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..c43b9888bf16
--- /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 type { LovelaceConfig } from "../../../data/lovelace";
+import { shouldHandleRequestSelectedEvent } from "../../../common/mwc/handle-request-selected-event";
+import { NewDashboardDialogParams } from "./show-dialog-new-dashboard";
+
+const EMPTY_CONFIG: LovelaceConfig = { 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..a106a3caa1f2
--- /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";
+
+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 7ab29c4ae958..01b15fcd443e 100644
--- a/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts
+++ b/src/panels/config/lovelace/dashboards/ha-config-lovelace-dashboards.ts
@@ -26,9 +26,11 @@ import {
createDashboard,
deleteDashboard,
fetchDashboards,
+ LovelaceConfig,
LovelaceDashboard,
LovelaceDashboardCreateParams,
LovelacePanelConfig,
+ saveConfig,
updateDashboard,
} from "../../../../data/lovelace";
import { showConfirmationDialog } from "../../../../dialogs/generic/show-dialog-box";
@@ -37,6 +39,7 @@ import "../../../../layouts/hass-tabs-subpage-data-table";
import { HomeAssistant, Route } from "../../../../types";
import { lovelaceTabs } from "../ha-config-lovelace";
import { showDashboardDetailDialog } from "./show-dialog-lovelace-dashboard-detail";
+import { showNewDashboardDialog } from "../../dashboard/show-dialog-new-dashboard";
type DataTableItem = Pick<
LovelaceDashboard,
@@ -329,16 +332,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 +361,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 20e3ad35d3e3..37bd9297c0c4 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",