Add undo/redo action for dashboard edition

This commit is contained in:
Paul Bottein 2023-08-23 21:31:25 +02:00
parent ed92958735
commit 497484d419
No known key found for this signature in database
3 changed files with 103 additions and 0 deletions

View File

@ -324,6 +324,8 @@ export class LovelacePanel extends LitElement {
urlPath: this.urlPath,
editMode: this.lovelace ? this.lovelace.editMode : false,
locale: this.hass!.locale,
configHistory: this.lovelace ? this.lovelace.configHistory : [config],
configHistoryIndex: this.lovelace ? this.lovelace.configHistoryIndex : 0,
enableFullEditMode: () => {
if (!editorLoaded) {
editorLoaded = true;
@ -358,6 +360,8 @@ export class LovelacePanel extends LitElement {
config: previousConfig,
rawConfig: previousRawConfig,
mode: previousMode,
configHistory: previousConfigHistory,
configHistoryIndex: previousConfigHistoryIndex,
} = this.lovelace!;
newConfig = this._checkLovelaceConfig(newConfig);
let conf: LovelaceConfig;
@ -372,11 +376,22 @@ export class LovelacePanel extends LitElement {
conf = newConfig;
}
try {
const newConfigHistory = [...previousConfigHistory];
let newConfigHistoryIndex = previousConfigHistoryIndex;
if (previousConfigHistoryIndex !== 0) {
newConfigHistory.splice(0, previousConfigHistoryIndex);
newConfigHistoryIndex = 0;
}
newConfigHistory.unshift(newConfig);
// Optimistic update
this._updateLovelace({
config: conf,
rawConfig: newConfig,
mode: "storage",
configHistory: newConfigHistory,
configHistoryIndex: newConfigHistoryIndex,
});
this._ignoreNextUpdateEvent = true;
await saveConfig(this.hass!, urlPath, newConfig);
@ -388,6 +403,7 @@ export class LovelacePanel extends LitElement {
config: previousConfig,
rawConfig: previousRawConfig,
mode: previousMode,
configHistory: previousConfigHistory,
});
throw err;
}
@ -427,6 +443,57 @@ export class LovelacePanel extends LitElement {
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;
}
},
};
}

View File

@ -12,8 +12,10 @@ import {
mdiMagnify,
mdiPencil,
mdiPlus,
mdiRedo,
mdiRefresh,
mdiShape,
mdiUndo,
mdiViewDashboard,
} from "@mdi/js";
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 {
const views = this.lovelace?.config.views ?? [];
const curViewConfig =
typeof this._curView === "number" ? views[this._curView] : undefined;
const historyTotal = this.lovelace?.configHistory.length ?? 0 - 1;
const historyIndex = this.lovelace?.configHistoryIndex ?? 0;
return html`
<div
class=${classMap({
@ -144,6 +165,18 @@ class HUIRoot extends LitElement {
)}
@click=${this._editModeDisable}
></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
href=${documentationUrl(this.hass, "/dashboards/")}
rel="noreferrer"

View File

@ -32,6 +32,9 @@ export interface Lovelace {
setEditMode: (editMode: boolean) => void;
saveConfig: (newConfig: LovelaceConfig) => Promise<void>;
deleteConfig: () => Promise<void>;
configHistory: LovelaceConfig[];
configHistoryIndex: number;
restoreConfigFromHistory: (index: number) => Promise<void>;
}
export interface LovelaceBadge extends HTMLElement {