From 1cac1c01a444e3d7e682c62b4fbdb48d65440bdd Mon Sep 17 00:00:00 2001 From: Paul Bottein Date: Tue, 14 Nov 2023 17:54:24 +0100 Subject: [PATCH] Add new dashboard dialog --- .../config/dashboard/dialog-new-dashboard.ts | 143 ++++++++++++++++++ .../dashboard/show-dialog-new-dashboard.ts | 19 +++ .../ha-config-lovelace-dashboards.ts | 33 ++-- src/translations/en.json | 7 + 4 files changed, 192 insertions(+), 10 deletions(-) create mode 100644 src/panels/config/dashboard/dialog-new-dashboard.ts create mode 100644 src/panels/config/dashboard/show-dialog-new-dashboard.ts diff --git a/src/panels/config/dashboard/dialog-new-dashboard.ts b/src/panels/config/dashboard/dialog-new-dashboard.ts new file mode 100644 index 000000000000..89a74d0a50e5 --- /dev/null +++ b/src/panels/config/dashboard/dialog-new-dashboard.ts @@ -0,0 +1,143 @@ +import "@material/mwc-list/mwc-list"; +import { mdiPencilOutline, mdiShape } from "@mdi/js"; +import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { fireEvent } from "../../../common/dom/fire_event"; +import { createCloseHeading } from "../../../components/ha-dialog"; +import "../../../components/ha-icon-next"; +import "../../../components/ha-list-item"; +import { HassDialog } from "../../../dialogs/make-dialog-manager"; +import { haStyle, haStyleDialog } from "../../../resources/styles"; +import type { HomeAssistant } from "../../../types"; +import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event"; +import { NewDashboardDialogParams } from "./show-dialog-new-dashboard"; +import { LovelaceRawConfig } from "../../../data/lovelace/config/types"; + +const EMPTY_CONFIG: LovelaceRawConfig = { views: [{ title: "Home" }] }; + +@customElement("ha-dialog-new-dashboard") +class DialogNewDashboard extends LitElement implements HassDialog { + @property({ attribute: false }) public hass!: HomeAssistant; + + @state() private _opened = false; + + @state() private _params?: NewDashboardDialogParams; + + public showDialog(params: NewDashboardDialogParams): void { + this._opened = true; + this._params = params; + } + + public closeDialog(): void { + if (this._opened) { + fireEvent(this, "dialog-closed", { dialog: this.localName }); + } + this._opened = false; + this._params = undefined; + } + + protected render() { + if (!this._opened) { + return nothing; + } + + return html` + + + + + ${this.hass.localize( + `ui.panel.config.lovelace.dashboards.dialog_new.create_empty` + )} + + ${this.hass.localize( + `ui.panel.config.lovelace.dashboards.dialog_new.create_empty_description` + )} + + + +
  • + + + ${this.hass.localize( + `ui.panel.config.lovelace.dashboards.dialog_new.default` + )} + ${this.hass.localize( + `ui.panel.config.lovelace.dashboards.dialog_new.default_description` + )} + + +
    +
    + `; + } + + private async _selected(ev) { + if (!shouldHandleRequestSelectedEvent(ev)) { + return; + } + const config = (ev.currentTarget! as any).config; + this._params?.selectConfig(config); + this.closeDialog(); + } + + static get styles(): CSSResultGroup { + return [ + haStyle, + haStyleDialog, + css` + ha-dialog { + --dialog-content-padding: 0; + --mdc-dialog-max-height: 60vh; + } + @media all and (min-width: 550px) { + ha-dialog { + --mdc-dialog-min-width: 500px; + } + } + ha-icon-next { + width: 24px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-dialog-new-dashboard": DialogNewDashboard; + } +} diff --git a/src/panels/config/dashboard/show-dialog-new-dashboard.ts b/src/panels/config/dashboard/show-dialog-new-dashboard.ts new file mode 100644 index 000000000000..7011b9e7e3da --- /dev/null +++ b/src/panels/config/dashboard/show-dialog-new-dashboard.ts @@ -0,0 +1,19 @@ +import { fireEvent } from "../../../common/dom/fire_event"; +import { LovelaceConfig } from "../../../data/lovelace/config/types"; + +export interface NewDashboardDialogParams { + selectConfig: (config: LovelaceConfig | undefined) => any; +} + +export const loadNewDashboardDialog = () => import("./dialog-new-dashboard"); + +export const showNewDashboardDialog = ( + element: HTMLElement, + newDashboardDialogParams: NewDashboardDialogParams +): void => { + fireEvent(element, "show-dialog", { + dialogTag: "ha-dialog-new-dashboard", + dialogImport: loadNewDashboardDialog, + dialogParams: newDashboardDialogParams, + }); +}; diff --git a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts index fc661d48e9c3..f246a48a1ba5 100644 --- a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts +++ b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts @@ -1,3 +1,4 @@ +import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; import { mdiCheck, mdiCheckCircleOutline, @@ -5,8 +6,7 @@ import { mdiOpenInNew, mdiPlus, } from "@mdi/js"; -import "@lrnwebcomponents/simple-tooltip/simple-tooltip"; -import { html, LitElement, nothing, PropertyValues } from "lit"; +import { LitElement, PropertyValues, html, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import { ifDefined } from "lit/directives/if-defined"; import memoize from "memoize-one"; @@ -22,21 +22,26 @@ import "../../../../components/ha-fab"; import "../../../../components/ha-icon"; import "../../../../components/ha-icon-button"; import "../../../../components/ha-svg-icon"; +import { LovelacePanelConfig } from "../../../../data/lovelace"; import { + LovelaceConfig, + saveConfig, +} from "../../../../data/lovelace/config/types"; +import { + LovelaceDashboard, + LovelaceDashboardCreateParams, createDashboard, deleteDashboard, fetchDashboards, - LovelaceDashboard, - LovelaceDashboardCreateParams, updateDashboard, } from "../../../../data/lovelace/dashboard"; import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box"; import "../../../../layouts/hass-loading-screen"; import "../../../../layouts/hass-tabs-subpage-data-table"; import { HomeAssistant, Route } from "../../../../types"; +import { showNewDashboardDialog } from "../../dashboard/show-dialog-new-dashboard"; import { lovelaceTabs } from "../ha-config-lovelace"; import { showDashboardDetailDialog } from "./show-dialog-lovelace-dashboard-detail"; -import { LovelacePanelConfig } from "../../../../data/lovelace"; type DataTableItem = Pick< LovelaceDashboard, @@ -329,16 +334,21 @@ export class HaConfigLovelaceDashboards extends LitElement { return; } const dashboard = this._dashboards.find((res) => res.url_path === urlPath); - this._openDialog(dashboard, urlPath); + this._openDetailDialog(dashboard, urlPath); } - private _addDashboard() { - this._openDialog(); + private async _addDashboard() { + showNewDashboardDialog(this, { + selectConfig: (config) => { + this._openDetailDialog(undefined, undefined, config); + }, + }); } - private async _openDialog( + private async _openDetailDialog( dashboard?: LovelaceDashboard, - urlPath?: string + urlPath?: string, + defaultConfig?: LovelaceConfig ): Promise { showDashboardDetailDialog(this, { dashboard, @@ -353,6 +363,9 @@ export class HaConfigLovelaceDashboards extends LitElement { this.hass.locale.language ) ); + if (defaultConfig) { + await saveConfig(this.hass!, created.url_path, defaultConfig); + } }, updateDashboard: async (values) => { const updated = await updateDashboard( diff --git a/src/translations/en.json b/src/translations/en.json index 953ab5e368eb..d6bfe8ea2350 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2100,6 +2100,13 @@ "yaml": "YAML file", "storage": "UI controlled" }, + "dialog_new": { + "header": "Add dashboard", + "create_empty": "New dashboard from scratch", + "create_empty_description": "Start with an empty dashboard from scratch", + "default": "Overview dashboard", + "default_description": "Display all the devices of your home" + }, "picker": { "headers": { "icon": "Icon",