diff --git a/src/data/lovelace.ts b/src/data/lovelace.ts index 28d1c4886f..432cb6167b 100644 --- a/src/data/lovelace.ts +++ b/src/data/lovelace.ts @@ -93,6 +93,8 @@ export interface LovelaceViewConfig { panel?: boolean; background?: string; visible?: boolean | ShowViewConfig[]; + subview?: boolean; + back_path?: string; } export interface LovelaceViewElement extends HTMLElement { diff --git a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts index 323e6dab96..e25345e36f 100644 --- a/src/panels/lovelace/editor/view-editor/hui-view-editor.ts +++ b/src/panels/lovelace/editor/view-editor/hui-view-editor.ts @@ -1,10 +1,10 @@ -import "../../../../components/ha-form/ha-form"; import { html, LitElement, TemplateResult } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; import { fireEvent } from "../../../../common/dom/fire_event"; import { slugify } from "../../../../common/string/slugify"; import type { LocalizeFunc } from "../../../../common/translations/localize"; +import "../../../../components/ha-form/ha-form"; import type { SchemaUnion } from "../../../../components/ha-form/types"; import type { LovelaceViewConfig } from "../../../../data/lovelace"; import type { HomeAssistant } from "../../../../types"; @@ -33,7 +33,7 @@ export class HuiViewEditor extends LitElement { private _suggestedPath = false; private _schema = memoizeOne( - (localize: LocalizeFunc) => + (localize: LocalizeFunc, subview: boolean, showAdvanced: boolean) => [ { name: "title", selector: { text: {} } }, { @@ -63,6 +63,20 @@ export class HuiViewEditor extends LitElement { }, }, }, + { + name: "subview", + selector: { + boolean: {}, + }, + }, + ...(subview && showAdvanced + ? [ + { + name: "back_path", + selector: { navigation: {} }, + }, + ] + : []), ] as const ); @@ -84,7 +98,12 @@ export class HuiViewEditor extends LitElement { return html``; } - const schema = this._schema(this.hass.localize); + const schema = this._schema( + this.hass.localize, + this._config.subview ?? false, + this.hass.userData?.showAdvanced ?? false + ); + const data = { theme: "Backend-selected", ...this._config, @@ -96,18 +115,22 @@ export class HuiViewEditor extends LitElement { .hass=${this.hass} .data=${data} .schema=${schema} - .computeLabel=${this._computeLabelCallback} + .computeLabel=${this._computeLabel} + .computeHelper=${this._computeHelper} @value-changed=${this._valueChanged} > `; } private _valueChanged(ev: CustomEvent): void { - const config = ev.detail.value; + const config = ev.detail.value as LovelaceViewConfig; if (config.type === "masonry") { delete config.type; } + if (!config.subview) { + delete config.back_path; + } if ( this.isNew && @@ -122,7 +145,7 @@ export class HuiViewEditor extends LitElement { fireEvent(this, "view-config-changed", { config }); } - private _computeLabelCallback = ( + private _computeLabel = ( schema: SchemaUnion> ) => { switch (schema.name) { @@ -130,12 +153,35 @@ export class HuiViewEditor extends LitElement { return this.hass!.localize("ui.panel.lovelace.editor.card.generic.url"); case "type": return this.hass.localize("ui.panel.lovelace.editor.edit_view.type"); + case "subview": + return this.hass.localize("ui.panel.lovelace.editor.edit_view.subview"); + case "back_path": + return this.hass.localize( + "ui.panel.lovelace.editor.edit_view.back_path" + ); default: return this.hass!.localize( `ui.panel.lovelace.editor.card.generic.${schema.name}` ); } }; + + private _computeHelper = ( + schema: SchemaUnion> + ) => { + switch (schema.name) { + case "subview": + return this.hass.localize( + "ui.panel.lovelace.editor.edit_view.subview_helper" + ); + case "back_path": + return this.hass.localize( + "ui.panel.lovelace.editor.edit_view.back_path_helper" + ); + default: + return undefined; + } + }; } declare global { diff --git a/src/panels/lovelace/hui-root.ts b/src/panels/lovelace/hui-root.ts index 3539e6f26f..05e5187259 100644 --- a/src/panels/lovelace/hui-root.ts +++ b/src/panels/lovelace/hui-root.ts @@ -112,6 +112,11 @@ class HUIRoot extends LitElement { } protected render(): TemplateResult { + const views = this.lovelace?.config.views ?? []; + + const curViewConfig = + typeof this._curView === "number" ? views[this._curView] : undefined; + return html` - - ${this.lovelace!.config.views.length > 1 + ${curViewConfig?.subview + ? html` + + ` + : html` + + `} + ${curViewConfig?.subview + ? html`
${curViewConfig.title}
` + : views.filter((view) => !view.subview).length > 1 ? html` - ${this.lovelace!.config.views.map( + ${views.map( (view) => html` e.user === this.hass!.user!.id - )) || - view.visible === false) + view.subview || + (view.visible !== undefined && + ((Array.isArray(view.visible) && + !view.visible.some( + (e) => + e.user === this.hass!.user!.id + )) || + view.visible === false)) ), })} > @@ -473,7 +490,7 @@ class HUIRoot extends LitElement { @iron-activate=${this._handleViewSelected} dir=${computeRTLDirection(this.hass!)} > - ${this.lovelace!.config.views.map( + ${views.map( (view) => html` @@ -528,7 +548,7 @@ class HUIRoot extends LitElement { class="edit-icon view" @click=${this._moveViewRight} ?disabled=${(this._curView! as number) + 1 === - this.lovelace!.config.views.length} + views.length} > ` : ""} @@ -720,6 +740,20 @@ class HUIRoot extends LitElement { }); } + private _goBack(): void { + const views = this.lovelace?.config.views ?? []; + const curViewConfig = + typeof this._curView === "number" ? views[this._curView] : undefined; + + if (curViewConfig?.back_path) { + navigate(curViewConfig.back_path); + } else if (history.length > 0) { + history.back(); + } else { + navigate(views[0].path!); + } + } + private _handleRawEditor(ev: CustomEvent): void { if (!shouldHandleRequestSelectedEvent(ev)) { return; @@ -1019,6 +1053,9 @@ class HUIRoot extends LitElement { --mdc-button-outline-color: var(--app-header-edit-text-color, #fff); --mdc-typography-button-font-size: 14px; } + .child-view-icon { + opacity: 0.5; + } `, ]; } diff --git a/src/translations/en.json b/src/translations/en.json index 2200bf2228..e73e58b2fa 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3749,7 +3749,11 @@ "masonry": "Masonry (default)", "sidebar": "Sidebar", "panel": "Panel (1 card)" - } + }, + "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." }, "edit_badges": { "view_no_badges": "Badges are not be supported by the current view type."