mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-14 12:56:37 +00:00
Move view to another dashboard (#23245)
* Add move view to dashboard * Remove unneeded return in error flow * Update src/panels/lovelace/editor/select-dashboard/hui-dialog-select-dashboard.ts Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com> * Update src/panels/lovelace/editor/select-dashboard/hui-dialog-select-dashboard.ts Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com> * Use ha-list-item for button-menu --------- Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
This commit is contained in:
parent
f688780677
commit
e4fc21c991
@ -179,12 +179,21 @@ export const moveCard = (
|
|||||||
export const addView = (
|
export const addView = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: LovelaceConfig,
|
config: LovelaceConfig,
|
||||||
viewConfig: LovelaceViewConfig
|
viewConfig: LovelaceViewConfig,
|
||||||
|
tolerantPath = false
|
||||||
): LovelaceConfig => {
|
): LovelaceConfig => {
|
||||||
if (viewConfig.path && config.views.some((v) => v.path === viewConfig.path)) {
|
if (viewConfig.path && config.views.some((v) => v.path === viewConfig.path)) {
|
||||||
|
if (!tolerantPath) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
hass.localize("ui.panel.lovelace.editor.edit_view.error_same_url")
|
hass.localize("ui.panel.lovelace.editor.edit_view.error_same_url")
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// add a suffix to the path
|
||||||
|
viewConfig = {
|
||||||
|
...viewConfig,
|
||||||
|
path: `${viewConfig.path}-2`,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...config,
|
...config,
|
||||||
@ -240,6 +249,20 @@ export const deleteView = (
|
|||||||
views: config.views.filter((_origView, index) => index !== viewIndex),
|
views: config.views.filter((_origView, index) => index !== viewIndex),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const moveViewToDashboard = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
fromConfig: LovelaceConfig,
|
||||||
|
toConfig: LovelaceConfig,
|
||||||
|
viewIndex: number
|
||||||
|
): [LovelaceConfig, LovelaceConfig] => {
|
||||||
|
const view = fromConfig.views[viewIndex];
|
||||||
|
|
||||||
|
return [
|
||||||
|
deleteView(fromConfig, viewIndex),
|
||||||
|
addView(hass, toConfig, view, true),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
export const addSection = (
|
export const addSection = (
|
||||||
config: LovelaceConfig,
|
config: LovelaceConfig,
|
||||||
viewIndex: number,
|
viewIndex: number,
|
||||||
|
@ -0,0 +1,193 @@
|
|||||||
|
import { mdiClose } from "@mdi/js";
|
||||||
|
import type { CSSResultGroup } from "lit";
|
||||||
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, query, state } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import "../../../../components/ha-md-dialog";
|
||||||
|
import "../../../../components/ha-dialog-header";
|
||||||
|
import "../../../../components/ha-icon-button";
|
||||||
|
import "../../../../components/ha-md-select";
|
||||||
|
import "../../../../components/ha-md-select-option";
|
||||||
|
import "../../../../components/ha-button";
|
||||||
|
import "../../../../components/ha-circular-progress";
|
||||||
|
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
||||||
|
import type { LovelaceDashboard } from "../../../../data/lovelace/dashboard";
|
||||||
|
import { fetchDashboards } from "../../../../data/lovelace/dashboard";
|
||||||
|
import { haStyleDialog } from "../../../../resources/styles";
|
||||||
|
import type { HomeAssistant } from "../../../../types";
|
||||||
|
import type { SelectDashboardDialogParams } from "./show-select-dashboard-dialog";
|
||||||
|
import type { HaMdDialog } from "../../../../components/ha-md-dialog";
|
||||||
|
|
||||||
|
@customElement("hui-dialog-select-dashboard")
|
||||||
|
export class HuiDialogSelectDashboard extends LitElement {
|
||||||
|
public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _params?: SelectDashboardDialogParams;
|
||||||
|
|
||||||
|
@state() private _dashboards?: LovelaceDashboard[];
|
||||||
|
|
||||||
|
@state() private _fromUrlPath?: string | null;
|
||||||
|
|
||||||
|
@state() private _toUrlPath?: string | null;
|
||||||
|
|
||||||
|
@state() private _config?: LovelaceConfig;
|
||||||
|
|
||||||
|
@state() private _saving = false;
|
||||||
|
|
||||||
|
@query("ha-md-dialog") private _dialog?: HaMdDialog;
|
||||||
|
|
||||||
|
public showDialog(params: SelectDashboardDialogParams): void {
|
||||||
|
this._config = params.lovelaceConfig;
|
||||||
|
this._fromUrlPath = params.urlPath;
|
||||||
|
this._params = params;
|
||||||
|
this._getDashboards();
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeDialog(): void {
|
||||||
|
this._saving = false;
|
||||||
|
this._dashboards = undefined;
|
||||||
|
this._toUrlPath = undefined;
|
||||||
|
this._dialog?.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _dialogClosed(): void {
|
||||||
|
this._params = undefined;
|
||||||
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this._params) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dialogTitle =
|
||||||
|
this._params.header ||
|
||||||
|
this.hass.localize("ui.panel.lovelace.editor.select_dashboard.header");
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-md-dialog
|
||||||
|
open
|
||||||
|
@closed=${this._dialogClosed}
|
||||||
|
.ariaLabel=${dialogTitle}
|
||||||
|
.disableCancelAction=${this._saving}
|
||||||
|
>
|
||||||
|
<ha-dialog-header slot="headline">
|
||||||
|
<ha-icon-button
|
||||||
|
slot="navigationIcon"
|
||||||
|
.label=${this.hass.localize("ui.dialogs.generic.close")}
|
||||||
|
.path=${mdiClose}
|
||||||
|
@click=${this.closeDialog}
|
||||||
|
.disabled=${this._saving}
|
||||||
|
></ha-icon-button>
|
||||||
|
<span slot="title" .title=${dialogTitle}>${dialogTitle}</span>
|
||||||
|
</ha-dialog-header>
|
||||||
|
<div slot="content">
|
||||||
|
${this._dashboards && !this._saving
|
||||||
|
? html`
|
||||||
|
<ha-md-select
|
||||||
|
.label=${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.select_view.dashboard_label"
|
||||||
|
)}
|
||||||
|
@change=${this._dashboardChanged}
|
||||||
|
.value=${this._toUrlPath || ""}
|
||||||
|
>
|
||||||
|
${this._dashboards.map(
|
||||||
|
(dashboard) => html`
|
||||||
|
<ha-md-select-option
|
||||||
|
.disabled=${dashboard.mode !== "storage" ||
|
||||||
|
dashboard.url_path === this._fromUrlPath ||
|
||||||
|
(dashboard.url_path === "lovelace" &&
|
||||||
|
this._fromUrlPath === null)}
|
||||||
|
.value=${dashboard.url_path}
|
||||||
|
>${dashboard.title}</ha-md-select-option
|
||||||
|
>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</ha-md-select>
|
||||||
|
`
|
||||||
|
: html`<div class="loading">
|
||||||
|
<ha-circular-progress
|
||||||
|
indeterminate
|
||||||
|
size="medium"
|
||||||
|
></ha-circular-progress>
|
||||||
|
</div>`}
|
||||||
|
</div>
|
||||||
|
<div slot="actions">
|
||||||
|
<ha-button @click=${this.closeDialog} .disabled=${this._saving}>
|
||||||
|
${this.hass!.localize("ui.common.cancel")}
|
||||||
|
</ha-button>
|
||||||
|
<ha-button
|
||||||
|
@click=${this._selectDashboard}
|
||||||
|
.disabled=${!this._config ||
|
||||||
|
this._fromUrlPath === this._toUrlPath ||
|
||||||
|
this._saving}
|
||||||
|
>
|
||||||
|
${this._params.actionLabel || this.hass!.localize("ui.common.move")}
|
||||||
|
</ha-button>
|
||||||
|
</div>
|
||||||
|
</ha-md-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _getDashboards() {
|
||||||
|
this._dashboards = [
|
||||||
|
{
|
||||||
|
id: "lovelace",
|
||||||
|
url_path: "lovelace",
|
||||||
|
require_admin: false,
|
||||||
|
show_in_sidebar: true,
|
||||||
|
title: this.hass.localize("ui.common.default"),
|
||||||
|
mode: this.hass.panels.lovelace?.config?.mode,
|
||||||
|
},
|
||||||
|
...(this._params!.dashboards || (await fetchDashboards(this.hass))),
|
||||||
|
].filter(
|
||||||
|
(dashboard) => this.hass.user!.is_admin || !dashboard.require_admin
|
||||||
|
);
|
||||||
|
|
||||||
|
const currentPath = this._fromUrlPath || this.hass.defaultPanel;
|
||||||
|
for (const dashboard of this._dashboards!) {
|
||||||
|
if (dashboard.url_path !== currentPath) {
|
||||||
|
this._toUrlPath = dashboard.url_path;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _dashboardChanged(ev) {
|
||||||
|
const urlPath: string = ev.target.value;
|
||||||
|
if (urlPath === this._toUrlPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._toUrlPath = urlPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _selectDashboard() {
|
||||||
|
this._saving = true;
|
||||||
|
if (this._toUrlPath! === "lovelace") {
|
||||||
|
this._toUrlPath = null;
|
||||||
|
}
|
||||||
|
this._params!.dashboardSelectedCallback(this._toUrlPath!);
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return [
|
||||||
|
haStyleDialog,
|
||||||
|
css`
|
||||||
|
ha-md-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.loading {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-dialog-select-dashboard": HuiDialogSelectDashboard;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
||||||
|
import type { LovelaceDashboard } from "../../../../data/lovelace/dashboard";
|
||||||
|
|
||||||
|
export interface SelectDashboardDialogParams {
|
||||||
|
lovelaceConfig: LovelaceConfig;
|
||||||
|
dashboards?: LovelaceDashboard[];
|
||||||
|
urlPath?: string | null;
|
||||||
|
header?: string;
|
||||||
|
actionLabel?: string;
|
||||||
|
dashboardSelectedCallback: (urlPath: string | null) => any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const showSelectDashboardDialog = (
|
||||||
|
element: HTMLElement,
|
||||||
|
selectViewDialogParams: SelectDashboardDialogParams
|
||||||
|
): void => {
|
||||||
|
fireEvent(element, "show-dialog", {
|
||||||
|
dialogTag: "hui-dialog-select-dashboard",
|
||||||
|
dialogImport: () => import("./hui-dialog-select-dashboard"),
|
||||||
|
dialogParams: selectViewDialogParams,
|
||||||
|
});
|
||||||
|
};
|
@ -1,8 +1,12 @@
|
|||||||
import "@material/mwc-button";
|
|
||||||
import type { ActionDetail } from "@material/mwc-list";
|
import type { ActionDetail } from "@material/mwc-list";
|
||||||
import "@material/mwc-tab-bar/mwc-tab-bar";
|
import "@material/mwc-tab-bar/mwc-tab-bar";
|
||||||
import "@material/mwc-tab/mwc-tab";
|
import "@material/mwc-tab/mwc-tab";
|
||||||
import { mdiClose, mdiDotsVertical, mdiPlaylistEdit } from "@mdi/js";
|
import {
|
||||||
|
mdiClose,
|
||||||
|
mdiDotsVertical,
|
||||||
|
mdiFileMoveOutline,
|
||||||
|
mdiPlaylistEdit,
|
||||||
|
} from "@mdi/js";
|
||||||
import type { CSSResultGroup, PropertyValues } from "lit";
|
import type { CSSResultGroup, PropertyValues } from "lit";
|
||||||
import { LitElement, css, html, nothing } from "lit";
|
import { LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property, query, state } from "lit/decorators";
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
@ -31,12 +35,25 @@ import "../../components/hui-entity-editor";
|
|||||||
import { SECTIONS_VIEW_LAYOUT } from "../../views/const";
|
import { SECTIONS_VIEW_LAYOUT } from "../../views/const";
|
||||||
import { generateDefaultSection } from "../../views/default-section";
|
import { generateDefaultSection } from "../../views/default-section";
|
||||||
import { getViewType } from "../../views/get-view-type";
|
import { getViewType } from "../../views/get-view-type";
|
||||||
import { addView, deleteView, replaceView } from "../config-util";
|
import {
|
||||||
|
addView,
|
||||||
|
deleteView,
|
||||||
|
moveViewToDashboard,
|
||||||
|
replaceView,
|
||||||
|
} from "../config-util";
|
||||||
import type { ViewEditEvent, ViewVisibilityChangeEvent } from "../types";
|
import type { ViewEditEvent, ViewVisibilityChangeEvent } from "../types";
|
||||||
import "./hui-view-background-editor";
|
import "./hui-view-background-editor";
|
||||||
import "./hui-view-editor";
|
import "./hui-view-editor";
|
||||||
import "./hui-view-visibility-editor";
|
import "./hui-view-visibility-editor";
|
||||||
import type { EditViewDialogParams } from "./show-edit-view-dialog";
|
import type { EditViewDialogParams } from "./show-edit-view-dialog";
|
||||||
|
import { showSelectDashboardDialog } from "../select-dashboard/show-select-dashboard-dialog";
|
||||||
|
import {
|
||||||
|
fetchConfig,
|
||||||
|
isStrategyDashboard,
|
||||||
|
saveConfig,
|
||||||
|
type LovelaceConfig,
|
||||||
|
} from "../../../../data/lovelace/config/types";
|
||||||
|
import type { Lovelace } from "../../types";
|
||||||
|
|
||||||
const TABS = ["tab-settings", "tab-background", "tab-visibility"] as const;
|
const TABS = ["tab-settings", "tab-background", "tab-visibility"] as const;
|
||||||
|
|
||||||
@ -46,6 +63,8 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
|
|
||||||
@state() private _params?: EditViewDialogParams;
|
@state() private _params?: EditViewDialogParams;
|
||||||
|
|
||||||
|
@state() private _lovelace?: Lovelace;
|
||||||
|
|
||||||
@state() private _config?: LovelaceViewConfig;
|
@state() private _config?: LovelaceViewConfig;
|
||||||
|
|
||||||
@state() private _saving = false;
|
@state() private _saving = false;
|
||||||
@ -83,7 +102,10 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
this._dirty = false;
|
this._dirty = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const view = this._params.lovelace!.config.views[this._params.viewIndex];
|
|
||||||
|
this._lovelace = this._params.lovelace;
|
||||||
|
|
||||||
|
const view = this._lovelace.config.views[this._params.viewIndex];
|
||||||
// Todo : add better support for strategy views
|
// Todo : add better support for strategy views
|
||||||
if (isStrategyView(view)) {
|
if (isStrategyView(view)) {
|
||||||
const { strategy, ...viewConfig } = view;
|
const { strategy, ...viewConfig } = view;
|
||||||
@ -212,6 +234,15 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
.path=${mdiPlaylistEdit}
|
.path=${mdiPlaylistEdit}
|
||||||
></ha-svg-icon>
|
></ha-svg-icon>
|
||||||
</ha-list-item>
|
</ha-list-item>
|
||||||
|
<ha-list-item graphic="icon">
|
||||||
|
${this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.edit_view.move_to_dashboard"
|
||||||
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiFileMoveOutline}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</ha-list-item>
|
||||||
</ha-button-menu>
|
</ha-button-menu>
|
||||||
${convertToSection
|
${convertToSection
|
||||||
? html`
|
? html`
|
||||||
@ -300,9 +331,102 @@ export class HuiDialogEditView extends LitElement {
|
|||||||
case 0:
|
case 0:
|
||||||
this._yamlMode = !this._yamlMode;
|
this._yamlMode = !this._yamlMode;
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
|
this._openSelectDashboard();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _openSelectDashboard(): void {
|
||||||
|
showSelectDashboardDialog(this, {
|
||||||
|
lovelaceConfig: this._lovelace!.config,
|
||||||
|
dashboardSelectedCallback: this._moveViewToDashboard,
|
||||||
|
urlPath: this._lovelace!.urlPath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _moveViewToDashboard = async (urlPath: string | null) => {
|
||||||
|
let errorMessage;
|
||||||
|
let toConfig;
|
||||||
|
let undoAction;
|
||||||
|
|
||||||
|
try {
|
||||||
|
toConfig = (await fetchConfig(
|
||||||
|
this.hass!.connection,
|
||||||
|
urlPath,
|
||||||
|
false
|
||||||
|
)) as LovelaceConfig;
|
||||||
|
} catch (err: any) {
|
||||||
|
errorMessage = this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.select_dashboard.get_config_failed"
|
||||||
|
);
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toConfig && isStrategyDashboard(toConfig)) {
|
||||||
|
errorMessage = this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.select_dashboard.cannot_move_to_strategy"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!errorMessage) {
|
||||||
|
const [newFromConfig, newToConfig] = moveViewToDashboard(
|
||||||
|
this.hass!,
|
||||||
|
this._lovelace!.config,
|
||||||
|
toConfig,
|
||||||
|
this._params!.viewIndex!
|
||||||
|
);
|
||||||
|
|
||||||
|
const oldFromConfig = this._lovelace!.config;
|
||||||
|
const oldToConfig = toConfig;
|
||||||
|
|
||||||
|
undoAction = async () => {
|
||||||
|
await saveConfig(this.hass!, urlPath, oldToConfig);
|
||||||
|
await this._lovelace!.saveConfig(oldFromConfig);
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this._lovelace!.saveConfig(newFromConfig);
|
||||||
|
await saveConfig(this.hass!, urlPath, newToConfig);
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(err);
|
||||||
|
try {
|
||||||
|
await undoAction();
|
||||||
|
errorMessage = this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.select_dashboard.move_failed"
|
||||||
|
);
|
||||||
|
} catch (revertError) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error(revertError);
|
||||||
|
errorMessage = this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.select_dashboard.revert_failed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorMessage) {
|
||||||
|
showAlertDialog(this, {
|
||||||
|
text: errorMessage,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._lovelace!.showToast({
|
||||||
|
message: this.hass!.localize(
|
||||||
|
"ui.panel.lovelace.editor.select_dashboard.success"
|
||||||
|
),
|
||||||
|
duration: 4000,
|
||||||
|
action: {
|
||||||
|
action: undoAction,
|
||||||
|
text: this.hass!.localize("ui.common.undo"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.closeDialog();
|
||||||
|
navigate(`/${window.location.pathname.split("/")[1]}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private async _convertToSection() {
|
private async _convertToSection() {
|
||||||
if (!this._params || !this._config) {
|
if (!this._params || !this._config) {
|
||||||
return;
|
return;
|
||||||
|
@ -5929,7 +5929,8 @@
|
|||||||
"edit_ui": "Edit in visual editor",
|
"edit_ui": "Edit in visual editor",
|
||||||
"edit_yaml": "Edit in YAML",
|
"edit_yaml": "Edit in YAML",
|
||||||
"saving_failed": "Saving failed",
|
"saving_failed": "Saving failed",
|
||||||
"error_same_url": "You cannot save a view with the same URL as a different existing view."
|
"error_same_url": "You cannot save a view with the same URL as a different existing view.",
|
||||||
|
"move_to_dashboard": "Move to dashboard"
|
||||||
},
|
},
|
||||||
"edit_badges": {
|
"edit_badges": {
|
||||||
"view_no_badges": "Badges are not be supported by the current view type."
|
"view_no_badges": "Badges are not be supported by the current view type."
|
||||||
@ -6022,6 +6023,14 @@
|
|||||||
"no_views": "No views in this dashboard.",
|
"no_views": "No views in this dashboard.",
|
||||||
"strategy_type": "strategy"
|
"strategy_type": "strategy"
|
||||||
},
|
},
|
||||||
|
"select_dashboard": {
|
||||||
|
"header": "Choose a dasboard",
|
||||||
|
"cannot_move_to_strategy": "The view cannot be moved because the selected dashboard is auto generated.",
|
||||||
|
"get_config_failed": "Failed to load selected dashboard config.",
|
||||||
|
"move_failed": "Failed to move the view to the new dashboard, please try again.",
|
||||||
|
"revert_failed": "Failed to move the view to the new dashboard, your dashboards are in an unknown state. Please reload the page and check if everything is in place.",
|
||||||
|
"success": "View moved successfully"
|
||||||
|
},
|
||||||
"section": {
|
"section": {
|
||||||
"add_badge": "Add badge",
|
"add_badge": "Add badge",
|
||||||
"add_card": "[%key:ui::panel::lovelace::editor::edit_card::add%]",
|
"add_card": "[%key:ui::panel::lovelace::editor::edit_card::add%]",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user