From 6a3ac9116e1041b733f7e99b6104ae9bc4e87cdb Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Fri, 30 Sep 2022 17:29:29 +0200 Subject: [PATCH] Add yaml mode to view editor (#13926) --- .../view-editor/hui-dialog-edit-view.ts | 296 +++++++++++++----- src/translations/en.json | 4 +- 2 files changed, 214 insertions(+), 86 deletions(-) diff --git a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts index 6b54de03dd..a9e4e4f45c 100644 --- a/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts +++ b/src/panels/lovelace/editor/view-editor/hui-dialog-edit-view.ts @@ -1,13 +1,26 @@ import "@material/mwc-button"; +import { ActionDetail } from "@material/mwc-list"; +import { mdiCheck, mdiDotsVertical } from "@mdi/js"; import "@polymer/paper-tabs/paper-tab"; import "@polymer/paper-tabs/paper-tabs"; -import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; -import { customElement, property, state } from "lit/decorators"; +import { + css, + CSSResultGroup, + html, + LitElement, + PropertyValues, + TemplateResult, +} from "lit"; +import { customElement, property, query, state } from "lit/decorators"; +import { classMap } from "lit/directives/class-map"; import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event"; +import { stopPropagation } from "../../../../common/dom/stop_propagation"; import { navigate } from "../../../../common/navigate"; +import { deepEqual } from "../../../../common/util/deep-equal"; +import "../../../../components/ha-alert"; import "../../../../components/ha-circular-progress"; import "../../../../components/ha-dialog"; -import "../../../../components/ha-alert"; +import { HaYamlEditor } from "../../../../components/ha-yaml-editor"; import type { LovelaceBadgeConfig, LovelaceCardConfig, @@ -20,6 +33,11 @@ import { import { haStyleDialog } from "../../../../resources/styles"; import type { HomeAssistant } from "../../../../types"; import "../../components/hui-entity-editor"; +import { + DEFAULT_VIEW_LAYOUT, + PANEL_VIEW_LAYOUT, + VIEWS_NO_BADGE_SUPPORT, +} from "../../views/const"; import { addView, deleteView, replaceView } from "../config-util"; import "../hui-badge-preview"; import { processEditorEntities } from "../process-editor-entities"; @@ -31,12 +49,6 @@ import { import "./hui-view-editor"; import "./hui-view-visibility-editor"; import { EditViewDialogParams } from "./show-edit-view-dialog"; -import { - DEFAULT_VIEW_LAYOUT, - PANEL_VIEW_LAYOUT, - VIEWS_NO_BADGE_SUPPORT, -} from "../../views/const"; -import { deepEqual } from "../../../../common/util/deep-equal"; @customElement("hui-dialog-edit-view") export class HuiDialogEditView extends LitElement { @@ -56,6 +68,10 @@ export class HuiDialogEditView extends LitElement { @state() private _dirty = false; + @state() private _yamlMode = false; + + @query("ha-yaml-editor") private _editor?: HaYamlEditor; + private _curTabIndex = 0; get _type(): string { @@ -67,6 +83,16 @@ export class HuiDialogEditView extends LitElement { : this._config.type || DEFAULT_VIEW_LAYOUT; } + protected updated(changedProperties: PropertyValues) { + if (this._yamlMode && changedProperties.has("_yamlMode")) { + const viewConfig = { + ...this._config, + badges: this._badges, + }; + this._editor?.setValue(viewConfig); + } + } + public showDialog(params: EditViewDialogParams): void { this._params = params; @@ -89,6 +115,7 @@ export class HuiDialogEditView extends LitElement { this._params = undefined; this._config = {}; this._badges = []; + this._yamlMode = false; this._dirty = false; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -111,62 +138,74 @@ export class HuiDialogEditView extends LitElement { } let content; - switch (this._curTab) { - case "tab-settings": - content = html` - - `; - break; - case "tab-badges": - content = html` - ${this._badges?.length - ? html` - ${VIEWS_NO_BADGE_SUPPORT.includes(this._type) - ? html` - - ${this.hass!.localize( - "ui.panel.lovelace.editor.edit_badges.view_no_badges" - )} - - ` - : ""} -
- ${this._badges.map( - (badgeConfig) => html` - - ` - )} -
- ` - : ""} - - `; - break; - case "tab-visibility": - content = html` - - `; - break; - case "tab-cards": - content = html` Cards `; - break; + + if (this._yamlMode) { + content = html` + + `; + } else { + switch (this._curTab) { + case "tab-settings": + content = html` + + `; + break; + case "tab-badges": + content = html` + ${this._badges?.length + ? html` + ${VIEWS_NO_BADGE_SUPPORT.includes(this._type) + ? html` + + ${this.hass!.localize( + "ui.panel.lovelace.editor.edit_badges.view_no_badges" + )} + + ` + : ""} +
+ ${this._badges.map( + (badgeConfig) => html` + + ` + )} +
+ ` + : ""} + + `; + break; + case "tab-visibility": + content = html` + + `; + break; + case "tab-cards": + content = html` Cards `; + break; + } } + return html`

${this._viewConfigTitle}

- - ${this.hass!.localize( - "ui.panel.lovelace.editor.edit_view.tab_settings" - )} - ${this.hass!.localize( - "ui.panel.lovelace.editor.edit_view.tab_badges" - )} - ${this.hass!.localize( - "ui.panel.lovelace.editor.edit_view.tab_visibility" - )} - + + + ${this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.edit_ui" + )} + ${!this._yamlMode + ? html`` + : ``} + + + + ${this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.edit_yaml" + )} + ${this._yamlMode + ? html`` + : ``} + + + ${!this._yamlMode + ? html` + ${this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.tab_settings" + )} + ${this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.tab_badges" + )} + ${this.hass!.localize( + "ui.panel.lovelace.editor.edit_view.tab_visibility" + )} + ` + : ""}
${content} ${this._params.viewIndex !== undefined @@ -235,6 +318,19 @@ export class HuiDialogEditView extends LitElement { `; } + private async _handleAction(ev: CustomEvent) { + ev.stopPropagation(); + ev.preventDefault(); + switch (ev.detail.index) { + case 0: + this._yamlMode = false; + break; + case 1: + this._yamlMode = true; + break; + } + } + private async _delete(): Promise { if (!this._params) { return; @@ -348,6 +444,17 @@ export class HuiDialogEditView extends LitElement { this._dirty = true; } + private _viewYamlChanged(ev: CustomEvent) { + ev.stopPropagation(); + if (!ev.detail.isValid) { + return; + } + const { badges = [], ...config } = ev.detail.value; + this._config = config; + this._badges = badges; + this._dirty = true; + } + private _isConfigChanged(): boolean { return ( this._creatingView || @@ -366,6 +473,9 @@ export class HuiDialogEditView extends LitElement { return [ haStyleDialog, css` + ha-dialog.yaml-mode { + --dialog-content-padding: 0; + } h2 { display: block; color: var(--primary-text-color); @@ -421,6 +531,22 @@ export class HuiDialogEditView extends LitElement { ha-circular-progress[active] { display: block; } + ha-button-menu { + color: var(--secondary-text-color); + position: absolute; + right: 16px; + top: 14px; + inset-inline-end: 16px; + inset-inline-start: initial; + direction: var(--direction); + } + ha-button-menu, + ha-icon-button { + --mdc-theme-text-primary-on-background: var(--primary-text-color); + } + .selected_menu_item { + color: var(--primary-color); + } .hidden { display: none; } diff --git a/src/translations/en.json b/src/translations/en.json index 3aeb0dffa6..0814955467 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3805,7 +3805,9 @@ "subview": "Subview", "subview_helper": "Subviews don't appear in tabs and have a back button.", "back_path": "Back path (optional)", - "back_path_helper": "Only for subviews. If empty, clicking on back button will go to the previous page." + "back_path_helper": "Only for subviews. If empty, clicking on back button will go to the previous page.", + "edit_ui": "Edit in visual editor", + "edit_yaml": "Edit in YAML" }, "edit_badges": { "view_no_badges": "Badges are not be supported by the current view type."