mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-29 04:06:35 +00:00
Change edit mode + add edit lovelace (#2277)
* Change edit mode + add edit lovelace * Comments * Fix (yes it was used :-) * Raw edit header changed
This commit is contained in:
parent
d277571735
commit
8c61624a9c
@ -87,7 +87,7 @@ export class HuiCardOptions extends hassLocalizeLitMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
return html`
|
return html`
|
||||||
<paper-item @click="${this._moveCard}" .index="${index}"
|
<paper-item @click="${this._moveCard}" .index="${index}"
|
||||||
>${view.title}</paper-item
|
>${view.title || "Unnamed view"}</paper-item
|
||||||
>
|
>
|
||||||
`;
|
`;
|
||||||
})
|
})
|
||||||
|
@ -0,0 +1,152 @@
|
|||||||
|
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
||||||
|
import { TemplateResult } from "lit-html";
|
||||||
|
import "@polymer/paper-spinner/paper-spinner";
|
||||||
|
import "@polymer/paper-dialog/paper-dialog";
|
||||||
|
// This is not a duplicate import, one is for types, one is for element.
|
||||||
|
// tslint:disable-next-line
|
||||||
|
import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
|
||||||
|
import "@polymer/paper-button/paper-button";
|
||||||
|
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable";
|
||||||
|
import "./hui-lovelace-editor";
|
||||||
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
import { LovelaceConfig } from "../../../../data/lovelace";
|
||||||
|
import { hassLocalizeLitMixin } from "../../../../mixins/lit-localize-mixin";
|
||||||
|
import { Lovelace } from "../../types";
|
||||||
|
|
||||||
|
export class HuiDialogEditLovelace extends hassLocalizeLitMixin(LitElement) {
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
private _lovelace?: Lovelace;
|
||||||
|
private _config?: LovelaceConfig;
|
||||||
|
private _saving: boolean;
|
||||||
|
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return {
|
||||||
|
hass: {},
|
||||||
|
_lovelace: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
protected constructor() {
|
||||||
|
super();
|
||||||
|
this._saving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async showDialog(lovelace: Lovelace): Promise<void> {
|
||||||
|
this._lovelace = lovelace;
|
||||||
|
if (this._dialog == null) {
|
||||||
|
await this.updateComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { views, ...lovelaceConfig } = this._lovelace!.config;
|
||||||
|
this._config = lovelaceConfig as LovelaceConfig;
|
||||||
|
|
||||||
|
this._dialog.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _dialog(): PaperDialogElement {
|
||||||
|
return this.shadowRoot!.querySelector("paper-dialog")!;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
${this.renderStyle()}
|
||||||
|
<paper-dialog with-backdrop>
|
||||||
|
<h2>Edit Lovelace</h2>
|
||||||
|
<paper-dialog-scrollable>
|
||||||
|
<hui-lovelace-editor
|
||||||
|
.hass="${this.hass}"
|
||||||
|
.config="${this._config}"
|
||||||
|
@lovelace-config-changed="${this._ConfigChanged}"
|
||||||
|
></hui-lovelace-editor
|
||||||
|
></paper-dialog-scrollable>
|
||||||
|
<div class="paper-dialog-buttons">
|
||||||
|
<paper-button @click="${this._closeDialog}"
|
||||||
|
>${this.localize("ui.common.cancel")}</paper-button
|
||||||
|
>
|
||||||
|
<paper-button
|
||||||
|
?disabled="${!this._config || this._saving}"
|
||||||
|
@click="${this._save}"
|
||||||
|
>
|
||||||
|
<paper-spinner
|
||||||
|
?active="${this._saving}"
|
||||||
|
alt="Saving"
|
||||||
|
></paper-spinner>
|
||||||
|
${this.localize("ui.common.save")}</paper-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</paper-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _closeDialog(): void {
|
||||||
|
this._config = undefined;
|
||||||
|
this._dialog.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _save(): Promise<void> {
|
||||||
|
if (!this._config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!this._isConfigChanged()) {
|
||||||
|
this._closeDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._saving = true;
|
||||||
|
const lovelace = this._lovelace!;
|
||||||
|
|
||||||
|
const config: LovelaceConfig = {
|
||||||
|
...lovelace.config,
|
||||||
|
...this._config,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await lovelace.saveConfig(config);
|
||||||
|
this._closeDialog();
|
||||||
|
} catch (err) {
|
||||||
|
alert(`Saving failed: ${err.message}`);
|
||||||
|
} finally {
|
||||||
|
this._saving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _ConfigChanged(ev: CustomEvent): void {
|
||||||
|
if (ev.detail && ev.detail.config) {
|
||||||
|
this._config = ev.detail.config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _isConfigChanged(): boolean {
|
||||||
|
const { views, ...lovelaceConfig } = this._lovelace!.config;
|
||||||
|
return JSON.stringify(this._config) !== JSON.stringify(lovelaceConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderStyle(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
<style>
|
||||||
|
paper-dialog {
|
||||||
|
width: 650px;
|
||||||
|
}
|
||||||
|
paper-button paper-spinner {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
paper-spinner {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
paper-spinner[active] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-dialog-edit-lovelace": HuiDialogEditLovelace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("hui-dialog-edit-lovelace", HuiDialogEditLovelace);
|
@ -0,0 +1,80 @@
|
|||||||
|
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
|
||||||
|
import { TemplateResult } from "lit-html";
|
||||||
|
import "@polymer/paper-input/paper-input";
|
||||||
|
|
||||||
|
import { EditorTarget } from "../types";
|
||||||
|
import { hassLocalizeLitMixin } from "../../../../mixins/lit-localize-mixin";
|
||||||
|
import { HomeAssistant } from "../../../../types";
|
||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { configElementStyle } from "../config-elements/config-elements-style";
|
||||||
|
|
||||||
|
import { LovelaceConfig } from "../../../../data/lovelace";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"lovelace-config-changed": {
|
||||||
|
config: LovelaceConfig;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HuiLovelaceEditor extends hassLocalizeLitMixin(LitElement) {
|
||||||
|
static get properties(): PropertyDeclarations {
|
||||||
|
return { hass: {}, config: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
public hass?: HomeAssistant;
|
||||||
|
public config?: LovelaceConfig;
|
||||||
|
|
||||||
|
get _title(): string {
|
||||||
|
if (!this.config) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return this.config.title || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
return html`
|
||||||
|
${configElementStyle}
|
||||||
|
<div class="card-config">
|
||||||
|
<paper-input
|
||||||
|
label="Title"
|
||||||
|
.value="${this._title}"
|
||||||
|
.configValue="${"title"}"
|
||||||
|
@value-changed="${this._valueChanged}"
|
||||||
|
></paper-input>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: Event): void {
|
||||||
|
if (!this.config) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = ev.currentTarget! as EditorTarget;
|
||||||
|
|
||||||
|
if (this[`_${target.configValue}`] === target.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let newConfig;
|
||||||
|
|
||||||
|
if (target.configValue) {
|
||||||
|
newConfig = {
|
||||||
|
...this.config,
|
||||||
|
[target.configValue]: target.value,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fireEvent(this, "lovelace-config-changed", { config: newConfig });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-lovelace-editor": HuiLovelaceEditor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("hui-lovelace-editor", HuiLovelaceEditor);
|
@ -0,0 +1,32 @@
|
|||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { Lovelace } from "../../types";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// for fire event
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"show-edit-lovelace": Lovelace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let registeredDialog = false;
|
||||||
|
const dialogShowEvent = "show-edit-lovelace";
|
||||||
|
const dialogTag = "hui-dialog-edit-lovelace";
|
||||||
|
|
||||||
|
const registerEditLovelaceDialog = (element: HTMLElement) =>
|
||||||
|
fireEvent(element, "register-dialog", {
|
||||||
|
dialogShowEvent,
|
||||||
|
dialogTag,
|
||||||
|
dialogImport: () =>
|
||||||
|
import(/* webpackChunkName: "hui-dialog-edit-lovelace" */ "./hui-dialog-edit-lovelace"),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const showEditLovelaceDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
lovelace: Lovelace
|
||||||
|
) => {
|
||||||
|
if (!registeredDialog) {
|
||||||
|
registeredDialog = true;
|
||||||
|
registerEditLovelaceDialog(element);
|
||||||
|
}
|
||||||
|
fireEvent(element, dialogShowEvent, lovelace);
|
||||||
|
};
|
@ -90,7 +90,9 @@ class LovelaceFullConfigEditor extends hassLocalizeLitMixin(LitElement) {
|
|||||||
app-header-layout {
|
app-header-layout {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
app-toolbar {
|
||||||
|
background-color: #455a64;
|
||||||
|
}
|
||||||
paper-button {
|
paper-button {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ import "./hui-view";
|
|||||||
import { HUIView } from "./hui-view";
|
import { HUIView } from "./hui-view";
|
||||||
import createCardElement from "./common/create-card-element";
|
import createCardElement from "./common/create-card-element";
|
||||||
import { showEditViewDialog } from "./editor/view-editor/show-edit-view-dialog";
|
import { showEditViewDialog } from "./editor/view-editor/show-edit-view-dialog";
|
||||||
|
import { showEditLovelaceDialog } from "./editor/lovelace-editor/show-edit-lovelace-dialog";
|
||||||
import { Lovelace } from "./types";
|
import { Lovelace } from "./types";
|
||||||
import { afterNextRender } from "../../common/util/render-status";
|
import { afterNextRender } from "../../common/util/render-status";
|
||||||
|
|
||||||
@ -121,18 +122,51 @@ class HUIRoot extends hassLocalizeLitMixin(LitElement) {
|
|||||||
.narrow="${this.narrow}"
|
.narrow="${this.narrow}"
|
||||||
></hui-notification-drawer>
|
></hui-notification-drawer>
|
||||||
<ha-app-layout id="layout">
|
<ha-app-layout id="layout">
|
||||||
<app-header slot="header" effects="waterfall" fixed condenses>
|
<app-header slot="header" effects="waterfall" class="${classMap({
|
||||||
|
"edit-mode": this._editMode,
|
||||||
|
})}" fixed condenses>
|
||||||
${
|
${
|
||||||
this._editMode
|
this._editMode
|
||||||
? html`
|
? html`
|
||||||
<app-toolbar>
|
<app-toolbar class="edit-mode">
|
||||||
<paper-icon-button
|
<paper-icon-button
|
||||||
icon="hass:close"
|
icon="hass:close"
|
||||||
@click="${this._editModeDisable}"
|
@click="${this._editModeDisable}"
|
||||||
></paper-icon-button>
|
></paper-icon-button>
|
||||||
<div main-title>
|
<div main-title>
|
||||||
${this.localize("ui.panel.lovelace.editor.header")}
|
${
|
||||||
|
this.config.title ||
|
||||||
|
this.localize("ui.panel.lovelace.editor.header")
|
||||||
|
}
|
||||||
|
<paper-icon-button
|
||||||
|
icon="hass:pencil"
|
||||||
|
class="edit-icon"
|
||||||
|
@click="${this._editLovelace}"
|
||||||
|
></paper-icon-button>
|
||||||
</div>
|
</div>
|
||||||
|
<paper-icon-button
|
||||||
|
icon="hass:help-circle"
|
||||||
|
title="Help"
|
||||||
|
@click="${this._handleHelp}"
|
||||||
|
></paper-icon-button>
|
||||||
|
<paper-menu-button
|
||||||
|
no-animations
|
||||||
|
horizontal-align="right"
|
||||||
|
horizontal-offset="-5"
|
||||||
|
>
|
||||||
|
<paper-icon-button
|
||||||
|
icon="hass:dots-vertical"
|
||||||
|
slot="dropdown-trigger"
|
||||||
|
></paper-icon-button>
|
||||||
|
<paper-listbox
|
||||||
|
@iron-select="${this._deselect}"
|
||||||
|
slot="dropdown-content"
|
||||||
|
>
|
||||||
|
<paper-item @click="${this.lovelace!.enableFullEditMode}"
|
||||||
|
>Raw config editor</paper-item
|
||||||
|
>
|
||||||
|
</paper-listbox>
|
||||||
|
</paper-menu-button>
|
||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
`
|
`
|
||||||
: html`
|
: html`
|
||||||
@ -180,16 +214,6 @@ class HUIRoot extends hassLocalizeLitMixin(LitElement) {
|
|||||||
this.localize("ui.panel.lovelace.editor.configure_ui")
|
this.localize("ui.panel.lovelace.editor.configure_ui")
|
||||||
}</paper-item
|
}</paper-item
|
||||||
>
|
>
|
||||||
${
|
|
||||||
this._storageMode
|
|
||||||
? html`
|
|
||||||
<paper-item
|
|
||||||
@click="${this.lovelace!.enableFullEditMode}"
|
|
||||||
>Raw config editor</paper-item
|
|
||||||
>
|
|
||||||
`
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
<paper-item @click="${this._handleHelp}">Help</paper-item>
|
<paper-item @click="${this._handleHelp}">Help</paper-item>
|
||||||
</paper-listbox>
|
</paper-listbox>
|
||||||
</paper-menu-button>
|
</paper-menu-button>
|
||||||
@ -224,7 +248,7 @@ class HUIRoot extends hassLocalizeLitMixin(LitElement) {
|
|||||||
this._editMode
|
this._editMode
|
||||||
? html`
|
? html`
|
||||||
<ha-icon
|
<ha-icon
|
||||||
class="edit-view-icon"
|
class="edit-icon view"
|
||||||
@click="${this._editView}"
|
@click="${this._editView}"
|
||||||
icon="hass:pencil"
|
icon="hass:pencil"
|
||||||
></ha-icon>
|
></ha-icon>
|
||||||
@ -293,11 +317,20 @@ class HUIRoot extends hassLocalizeLitMixin(LitElement) {
|
|||||||
--paper-tabs-selection-bar-color: var(--text-primary-color, #fff);
|
--paper-tabs-selection-bar-color: var(--text-primary-color, #fff);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
paper-tab.iron-selected .edit-view-icon {
|
.edit-mode {
|
||||||
|
background-color: #455a64;
|
||||||
|
}
|
||||||
|
.edit-mode div[main-title] {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
paper-tab.iron-selected .edit-icon {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
.edit-view-icon {
|
.edit-icon {
|
||||||
|
color: var(--accent-color);
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
.edit-icon.view {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#add-view {
|
#add-view {
|
||||||
@ -412,10 +445,6 @@ class HUIRoot extends hassLocalizeLitMixin(LitElement) {
|
|||||||
return this.lovelace!.mode === "yaml";
|
return this.lovelace!.mode === "yaml";
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _storageMode(): boolean {
|
|
||||||
return this.lovelace!.mode === "storage";
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _editMode() {
|
private get _editMode() {
|
||||||
return this.lovelace!.editMode;
|
return this.lovelace!.editMode;
|
||||||
}
|
}
|
||||||
@ -478,6 +507,10 @@ class HUIRoot extends hassLocalizeLitMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _editLovelace() {
|
||||||
|
showEditLovelaceDialog(this, this.lovelace!);
|
||||||
|
}
|
||||||
|
|
||||||
private _editView() {
|
private _editView() {
|
||||||
showEditViewDialog(this, {
|
showEditViewDialog(this, {
|
||||||
lovelace: this.lovelace!,
|
lovelace: this.lovelace!,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user