Add yaml mode to view editor (#13926)

This commit is contained in:
Paul Bottein 2022-09-30 17:29:29 +02:00 committed by GitHub
parent 2a6ef9b955
commit 6a3ac9116e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 214 additions and 86 deletions

View File

@ -1,13 +1,26 @@
import "@material/mwc-button"; 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-tab";
import "@polymer/paper-tabs/paper-tabs"; import "@polymer/paper-tabs/paper-tabs";
import { css, CSSResultGroup, html, LitElement, TemplateResult } from "lit"; import {
import { customElement, property, state } from "lit/decorators"; 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 { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
import { stopPropagation } from "../../../../common/dom/stop_propagation";
import { navigate } from "../../../../common/navigate"; import { navigate } from "../../../../common/navigate";
import { deepEqual } from "../../../../common/util/deep-equal";
import "../../../../components/ha-alert";
import "../../../../components/ha-circular-progress"; import "../../../../components/ha-circular-progress";
import "../../../../components/ha-dialog"; import "../../../../components/ha-dialog";
import "../../../../components/ha-alert"; import { HaYamlEditor } from "../../../../components/ha-yaml-editor";
import type { import type {
LovelaceBadgeConfig, LovelaceBadgeConfig,
LovelaceCardConfig, LovelaceCardConfig,
@ -20,6 +33,11 @@ import {
import { haStyleDialog } from "../../../../resources/styles"; import { haStyleDialog } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import "../../components/hui-entity-editor"; 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 { addView, deleteView, replaceView } from "../config-util";
import "../hui-badge-preview"; import "../hui-badge-preview";
import { processEditorEntities } from "../process-editor-entities"; import { processEditorEntities } from "../process-editor-entities";
@ -31,12 +49,6 @@ import {
import "./hui-view-editor"; import "./hui-view-editor";
import "./hui-view-visibility-editor"; import "./hui-view-visibility-editor";
import { EditViewDialogParams } from "./show-edit-view-dialog"; 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") @customElement("hui-dialog-edit-view")
export class HuiDialogEditView extends LitElement { export class HuiDialogEditView extends LitElement {
@ -56,6 +68,10 @@ export class HuiDialogEditView extends LitElement {
@state() private _dirty = false; @state() private _dirty = false;
@state() private _yamlMode = false;
@query("ha-yaml-editor") private _editor?: HaYamlEditor;
private _curTabIndex = 0; private _curTabIndex = 0;
get _type(): string { get _type(): string {
@ -67,6 +83,16 @@ export class HuiDialogEditView extends LitElement {
: this._config.type || DEFAULT_VIEW_LAYOUT; : 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 { public showDialog(params: EditViewDialogParams): void {
this._params = params; this._params = params;
@ -89,6 +115,7 @@ export class HuiDialogEditView extends LitElement {
this._params = undefined; this._params = undefined;
this._config = {}; this._config = {};
this._badges = []; this._badges = [];
this._yamlMode = false;
this._dirty = false; this._dirty = false;
fireEvent(this, "dialog-closed", { dialog: this.localName }); fireEvent(this, "dialog-closed", { dialog: this.localName });
} }
@ -111,62 +138,74 @@ export class HuiDialogEditView extends LitElement {
} }
let content; let content;
switch (this._curTab) {
case "tab-settings": if (this._yamlMode) {
content = html` content = html`
<hui-view-editor <ha-yaml-editor
.isNew=${this._params.viewIndex === undefined} .hass=${this.hass}
.hass=${this.hass} dialogInitialFocus
.config=${this._config} @value-changed=${this._viewYamlChanged}
@view-config-changed=${this._viewConfigChanged} ></ha-yaml-editor>
></hui-view-editor> `;
`; } else {
break; switch (this._curTab) {
case "tab-badges": case "tab-settings":
content = html` content = html`
${this._badges?.length <hui-view-editor
? html` .isNew=${this._params.viewIndex === undefined}
${VIEWS_NO_BADGE_SUPPORT.includes(this._type) .hass=${this.hass}
? html` .config=${this._config}
<ha-alert alert-type="warning"> @view-config-changed=${this._viewConfigChanged}
${this.hass!.localize( ></hui-view-editor>
"ui.panel.lovelace.editor.edit_badges.view_no_badges" `;
)} break;
</ha-alert> case "tab-badges":
` content = html`
: ""} ${this._badges?.length
<div class="preview-badges"> ? html`
${this._badges.map( ${VIEWS_NO_BADGE_SUPPORT.includes(this._type)
(badgeConfig) => html` ? html`
<hui-badge-preview <ha-alert alert-type="warning">
.hass=${this.hass} ${this.hass!.localize(
.config=${badgeConfig} "ui.panel.lovelace.editor.edit_badges.view_no_badges"
></hui-badge-preview> )}
` </ha-alert>
)} `
</div> : ""}
` <div class="preview-badges">
: ""} ${this._badges.map(
<hui-entity-editor (badgeConfig) => html`
.hass=${this.hass} <hui-badge-preview
.entities=${this._badges} .hass=${this.hass}
@entities-changed=${this._badgesChanged} .config=${badgeConfig}
></hui-entity-editor> ></hui-badge-preview>
`; `
break; )}
case "tab-visibility": </div>
content = html` `
<hui-view-visibility-editor : ""}
.hass=${this.hass} <hui-entity-editor
.config=${this._config} .hass=${this.hass}
@view-visibility-changed=${this._viewVisibilityChanged} .entities=${this._badges}
></hui-view-visibility-editor> @entities-changed=${this._badgesChanged}
`; ></hui-entity-editor>
break; `;
case "tab-cards": break;
content = html` Cards `; case "tab-visibility":
break; content = html`
<hui-view-visibility-editor
.hass=${this.hass}
.config=${this._config}
@view-visibility-changed=${this._viewVisibilityChanged}
></hui-view-visibility-editor>
`;
break;
case "tab-cards":
content = html` Cards `;
break;
}
} }
return html` return html`
<ha-dialog <ha-dialog
open open
@ -174,31 +213,75 @@ export class HuiDialogEditView extends LitElement {
escapeKeyAction escapeKeyAction
@closed=${this.closeDialog} @closed=${this.closeDialog}
.heading=${this._viewConfigTitle} .heading=${this._viewConfigTitle}
class=${classMap({
"yaml-mode": this._yamlMode,
})}
> >
<div slot="heading"> <div slot="heading">
<h2>${this._viewConfigTitle}</h2> <h2>${this._viewConfigTitle}</h2>
<paper-tabs <ha-button-menu
scrollable slot="icons"
hide-scroll-buttons fixed
.selected=${this._curTabIndex} corner="BOTTOM_END"
@selected-item-changed=${this._handleTabSelected} menuCorner="END"
@action=${this._handleAction}
@closed=${stopPropagation}
> >
<paper-tab id="tab-settings" dialogInitialFocus <ha-icon-button
>${this.hass!.localize( slot="trigger"
"ui.panel.lovelace.editor.edit_view.tab_settings" .label=${this.hass!.localize("ui.common.menu")}
)}</paper-tab .path=${mdiDotsVertical}
> ></ha-icon-button>
<paper-tab id="tab-badges" <mwc-list-item graphic="icon">
>${this.hass!.localize( ${this.hass!.localize(
"ui.panel.lovelace.editor.edit_view.tab_badges" "ui.panel.lovelace.editor.edit_view.edit_ui"
)}</paper-tab )}
> ${!this._yamlMode
<paper-tab id="tab-visibility" ? html`<ha-svg-icon
>${this.hass!.localize( class="selected_menu_item"
"ui.panel.lovelace.editor.edit_view.tab_visibility" slot="graphic"
)}</paper-tab .path=${mdiCheck}
> ></ha-svg-icon>`
</paper-tabs> : ``}
</mwc-list-item>
<mwc-list-item graphic="icon">
${this.hass!.localize(
"ui.panel.lovelace.editor.edit_view.edit_yaml"
)}
${this._yamlMode
? html`<ha-svg-icon
class="selected_menu_item"
slot="graphic"
.path=${mdiCheck}
></ha-svg-icon>`
: ``}
</mwc-list-item>
</ha-button-menu>
${!this._yamlMode
? html`<paper-tabs
scrollable
hide-scroll-buttons
.selected=${this._curTabIndex}
@selected-item-changed=${this._handleTabSelected}
>
<paper-tab id="tab-settings" dialogInitialFocus
>${this.hass!.localize(
"ui.panel.lovelace.editor.edit_view.tab_settings"
)}</paper-tab
>
<paper-tab id="tab-badges"
>${this.hass!.localize(
"ui.panel.lovelace.editor.edit_view.tab_badges"
)}</paper-tab
>
<paper-tab id="tab-visibility"
>${this.hass!.localize(
"ui.panel.lovelace.editor.edit_view.tab_visibility"
)}</paper-tab
>
</paper-tabs>`
: ""}
</div> </div>
${content} ${content}
${this._params.viewIndex !== undefined ${this._params.viewIndex !== undefined
@ -235,6 +318,19 @@ export class HuiDialogEditView extends LitElement {
`; `;
} }
private async _handleAction(ev: CustomEvent<ActionDetail>) {
ev.stopPropagation();
ev.preventDefault();
switch (ev.detail.index) {
case 0:
this._yamlMode = false;
break;
case 1:
this._yamlMode = true;
break;
}
}
private async _delete(): Promise<void> { private async _delete(): Promise<void> {
if (!this._params) { if (!this._params) {
return; return;
@ -348,6 +444,17 @@ export class HuiDialogEditView extends LitElement {
this._dirty = true; 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 { private _isConfigChanged(): boolean {
return ( return (
this._creatingView || this._creatingView ||
@ -366,6 +473,9 @@ export class HuiDialogEditView extends LitElement {
return [ return [
haStyleDialog, haStyleDialog,
css` css`
ha-dialog.yaml-mode {
--dialog-content-padding: 0;
}
h2 { h2 {
display: block; display: block;
color: var(--primary-text-color); color: var(--primary-text-color);
@ -421,6 +531,22 @@ export class HuiDialogEditView extends LitElement {
ha-circular-progress[active] { ha-circular-progress[active] {
display: block; 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 { .hidden {
display: none; display: none;
} }

View File

@ -3805,7 +3805,9 @@
"subview": "Subview", "subview": "Subview",
"subview_helper": "Subviews don't appear in tabs and have a back button.", "subview_helper": "Subviews don't appear in tabs and have a back button.",
"back_path": "Back path (optional)", "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": { "edit_badges": {
"view_no_badges": "Badges are not be supported by the current view type." "view_no_badges": "Badges are not be supported by the current view type."