Add subview option to dashboard views (#13822)

This commit is contained in:
Paul Bottein 2022-09-27 15:37:48 +02:00 committed by GitHub
parent 51874329d1
commit c79955e76a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 21 deletions

View File

@ -93,6 +93,8 @@ export interface LovelaceViewConfig {
panel?: boolean;
background?: string;
visible?: boolean | ShowViewConfig[];
subview?: boolean;
back_path?: string;
}
export interface LovelaceViewElement extends HTMLElement {

View File

@ -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}
></ha-form>
`;
}
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<ReturnType<typeof this._schema>>
) => {
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<ReturnType<typeof this._schema>>
) => {
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 {

View File

@ -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`
<ha-app-layout
class=${classMap({
@ -229,11 +234,21 @@ class HUIRoot extends LitElement {
`
: html`
<app-toolbar>
${curViewConfig?.subview
? html`
<ha-icon-button-arrow-prev
@click=${this._goBack}
></ha-icon-button-arrow-prev>
`
: html`
<ha-menu-button
.hass=${this.hass}
.narrow=${this.narrow}
></ha-menu-button>
${this.lovelace!.config.views.length > 1
`}
${curViewConfig?.subview
? html`<div main-title>${curViewConfig.title}</div>`
: views.filter((view) => !view.subview).length > 1
? html`
<ha-tabs
scrollable
@ -241,18 +256,20 @@ class HUIRoot extends LitElement {
@iron-activate=${this._handleViewSelected}
dir=${computeRTLDirection(this.hass!)}
>
${this.lovelace!.config.views.map(
${views.map(
(view) => html`
<paper-tab
aria-label=${ifDefined(view.title)}
class=${classMap({
"hide-tab": Boolean(
view.visible !== undefined &&
view.subview ||
(view.visible !== undefined &&
((Array.isArray(view.visible) &&
!view.visible.some(
(e) => e.user === this.hass!.user!.id
(e) =>
e.user === this.hass!.user!.id
)) ||
view.visible === false)
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`
<paper-tab
aria-label=${ifDefined(view.title)}
@ -505,6 +522,9 @@ class HUIRoot extends LitElement {
${view.icon
? html`
<ha-icon
class=${classMap({
"child-view-icon": Boolean(view.subview),
})}
title=${ifDefined(view.title)}
.icon=${view.icon}
></ha-icon>
@ -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}
></ha-icon-button-arrow-next>
`
: ""}
@ -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<RequestSelectedDetail>): 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;
}
`,
];
}

View File

@ -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."