mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-31 13:07:49 +00:00
Add undo/redo action for dashboard edition
This commit is contained in:
parent
ed92958735
commit
497484d419
@ -324,6 +324,8 @@ export class LovelacePanel extends LitElement {
|
|||||||
urlPath: this.urlPath,
|
urlPath: this.urlPath,
|
||||||
editMode: this.lovelace ? this.lovelace.editMode : false,
|
editMode: this.lovelace ? this.lovelace.editMode : false,
|
||||||
locale: this.hass!.locale,
|
locale: this.hass!.locale,
|
||||||
|
configHistory: this.lovelace ? this.lovelace.configHistory : [config],
|
||||||
|
configHistoryIndex: this.lovelace ? this.lovelace.configHistoryIndex : 0,
|
||||||
enableFullEditMode: () => {
|
enableFullEditMode: () => {
|
||||||
if (!editorLoaded) {
|
if (!editorLoaded) {
|
||||||
editorLoaded = true;
|
editorLoaded = true;
|
||||||
@ -358,6 +360,8 @@ export class LovelacePanel extends LitElement {
|
|||||||
config: previousConfig,
|
config: previousConfig,
|
||||||
rawConfig: previousRawConfig,
|
rawConfig: previousRawConfig,
|
||||||
mode: previousMode,
|
mode: previousMode,
|
||||||
|
configHistory: previousConfigHistory,
|
||||||
|
configHistoryIndex: previousConfigHistoryIndex,
|
||||||
} = this.lovelace!;
|
} = this.lovelace!;
|
||||||
newConfig = this._checkLovelaceConfig(newConfig);
|
newConfig = this._checkLovelaceConfig(newConfig);
|
||||||
let conf: LovelaceConfig;
|
let conf: LovelaceConfig;
|
||||||
@ -372,11 +376,22 @@ export class LovelacePanel extends LitElement {
|
|||||||
conf = newConfig;
|
conf = newConfig;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
const newConfigHistory = [...previousConfigHistory];
|
||||||
|
let newConfigHistoryIndex = previousConfigHistoryIndex;
|
||||||
|
|
||||||
|
if (previousConfigHistoryIndex !== 0) {
|
||||||
|
newConfigHistory.splice(0, previousConfigHistoryIndex);
|
||||||
|
newConfigHistoryIndex = 0;
|
||||||
|
}
|
||||||
|
newConfigHistory.unshift(newConfig);
|
||||||
|
|
||||||
// Optimistic update
|
// Optimistic update
|
||||||
this._updateLovelace({
|
this._updateLovelace({
|
||||||
config: conf,
|
config: conf,
|
||||||
rawConfig: newConfig,
|
rawConfig: newConfig,
|
||||||
mode: "storage",
|
mode: "storage",
|
||||||
|
configHistory: newConfigHistory,
|
||||||
|
configHistoryIndex: newConfigHistoryIndex,
|
||||||
});
|
});
|
||||||
this._ignoreNextUpdateEvent = true;
|
this._ignoreNextUpdateEvent = true;
|
||||||
await saveConfig(this.hass!, urlPath, newConfig);
|
await saveConfig(this.hass!, urlPath, newConfig);
|
||||||
@ -388,6 +403,7 @@ export class LovelacePanel extends LitElement {
|
|||||||
config: previousConfig,
|
config: previousConfig,
|
||||||
rawConfig: previousRawConfig,
|
rawConfig: previousRawConfig,
|
||||||
mode: previousMode,
|
mode: previousMode,
|
||||||
|
configHistory: previousConfigHistory,
|
||||||
});
|
});
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
@ -427,6 +443,57 @@ export class LovelacePanel extends LitElement {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
restoreConfigFromHistory: async (
|
||||||
|
configHistoryIndex: number
|
||||||
|
): Promise<void> => {
|
||||||
|
const {
|
||||||
|
configHistory,
|
||||||
|
configHistoryIndex: previousConfigHistoryIndex,
|
||||||
|
config: previousConfig,
|
||||||
|
rawConfig: previousRawConfig,
|
||||||
|
} = this.lovelace!;
|
||||||
|
|
||||||
|
if (
|
||||||
|
previousConfigHistoryIndex === configHistoryIndex ||
|
||||||
|
configHistoryIndex < 0 ||
|
||||||
|
configHistoryIndex >= configHistory.length
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let conf: LovelaceConfig;
|
||||||
|
const newConfig = configHistory[configHistoryIndex];
|
||||||
|
|
||||||
|
if (newConfig.strategy) {
|
||||||
|
conf = await generateLovelaceDashboardStrategy({
|
||||||
|
config: newConfig,
|
||||||
|
hass: this.hass!,
|
||||||
|
narrow: this.narrow,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
conf = newConfig;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Optimistic update
|
||||||
|
this._updateLovelace({
|
||||||
|
config: conf,
|
||||||
|
rawConfig: newConfig,
|
||||||
|
configHistoryIndex: configHistoryIndex,
|
||||||
|
});
|
||||||
|
this._ignoreNextUpdateEvent = true;
|
||||||
|
await saveConfig(this.hass!, urlPath, newConfig);
|
||||||
|
} catch (err: any) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
console.error(err);
|
||||||
|
// Rollback the optimistic update
|
||||||
|
this._updateLovelace({
|
||||||
|
config: previousConfig,
|
||||||
|
rawConfig: previousRawConfig,
|
||||||
|
configHistoryIndex: previousConfigHistoryIndex,
|
||||||
|
});
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,10 @@ import {
|
|||||||
mdiMagnify,
|
mdiMagnify,
|
||||||
mdiPencil,
|
mdiPencil,
|
||||||
mdiPlus,
|
mdiPlus,
|
||||||
|
mdiRedo,
|
||||||
mdiRefresh,
|
mdiRefresh,
|
||||||
mdiShape,
|
mdiShape,
|
||||||
|
mdiUndo,
|
||||||
mdiViewDashboard,
|
mdiViewDashboard,
|
||||||
} from "@mdi/js";
|
} from "@mdi/js";
|
||||||
import "@polymer/paper-tabs/paper-tab";
|
import "@polymer/paper-tabs/paper-tab";
|
||||||
@ -106,12 +108,31 @@ class HUIRoot extends LitElement {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _undo() {
|
||||||
|
if (this.lovelace) {
|
||||||
|
this.lovelace.restoreConfigFromHistory(
|
||||||
|
this.lovelace.configHistoryIndex + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _redo() {
|
||||||
|
if (this.lovelace) {
|
||||||
|
this.lovelace.restoreConfigFromHistory(
|
||||||
|
this.lovelace.configHistoryIndex - 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const views = this.lovelace?.config.views ?? [];
|
const views = this.lovelace?.config.views ?? [];
|
||||||
|
|
||||||
const curViewConfig =
|
const curViewConfig =
|
||||||
typeof this._curView === "number" ? views[this._curView] : undefined;
|
typeof this._curView === "number" ? views[this._curView] : undefined;
|
||||||
|
|
||||||
|
const historyTotal = this.lovelace?.configHistory.length ?? 0 - 1;
|
||||||
|
const historyIndex = this.lovelace?.configHistoryIndex ?? 0;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<div
|
<div
|
||||||
class=${classMap({
|
class=${classMap({
|
||||||
@ -144,6 +165,18 @@ class HUIRoot extends LitElement {
|
|||||||
)}
|
)}
|
||||||
@click=${this._editModeDisable}
|
@click=${this._editModeDisable}
|
||||||
></mwc-button>
|
></mwc-button>
|
||||||
|
<ha-icon-button
|
||||||
|
label="Undo"
|
||||||
|
.path=${mdiUndo}
|
||||||
|
.disabled=${historyIndex + 1 >= historyTotal}
|
||||||
|
@click=${this._undo}
|
||||||
|
></ha-icon-button>
|
||||||
|
<ha-icon-button
|
||||||
|
label="Redo"
|
||||||
|
.path=${mdiRedo}
|
||||||
|
.disabled=${historyIndex === 0}
|
||||||
|
@click=${this._redo}
|
||||||
|
></ha-icon-button>
|
||||||
<a
|
<a
|
||||||
href=${documentationUrl(this.hass, "/dashboards/")}
|
href=${documentationUrl(this.hass, "/dashboards/")}
|
||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
|
@ -32,6 +32,9 @@ export interface Lovelace {
|
|||||||
setEditMode: (editMode: boolean) => void;
|
setEditMode: (editMode: boolean) => void;
|
||||||
saveConfig: (newConfig: LovelaceConfig) => Promise<void>;
|
saveConfig: (newConfig: LovelaceConfig) => Promise<void>;
|
||||||
deleteConfig: () => Promise<void>;
|
deleteConfig: () => Promise<void>;
|
||||||
|
configHistory: LovelaceConfig[];
|
||||||
|
configHistoryIndex: number;
|
||||||
|
restoreConfigFromHistory: (index: number) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LovelaceBadge extends HTMLElement {
|
export interface LovelaceBadge extends HTMLElement {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user