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..3131d30bfaa7 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": "Default dashboard",
+ "default_description": "Display your devices grouped by area"
+ },
"picker": {
"headers": {
"icon": "Icon",