Skip to content

Commit 8553ad0

Browse files
committed
Add undo/redo functionality to dashboard editor
1 parent 5f53e1e commit 8553ad0

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

src/mixins/undo-redo-mixin.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ export const UndoRedoMixin = <T extends Constructor<LitElement>, ConfigType>(
4747
return this._redoStack.length > 0;
4848
}
4949

50+
public clearUndoRedo(): void {
51+
this._undoStack = [];
52+
this._redoStack = [];
53+
}
54+
5055
protected get currentConfig(): ConfigType | undefined {
5156
return undefined;
5257
}

src/panels/lovelace/hui-root.ts

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ import {
1111
mdiMagnify,
1212
mdiPencil,
1313
mdiPlus,
14+
mdiRedo,
1415
mdiRefresh,
1516
mdiRobot,
1617
mdiShape,
1718
mdiSofa,
19+
mdiUndo,
1820
mdiViewDashboard,
1921
} from "@mdi/js";
2022
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
@@ -50,7 +52,10 @@ import "../../components/ha-tab-group-tab";
5052
import "../../components/ha-tooltip";
5153
import { createAreaRegistryEntry } from "../../data/area_registry";
5254
import type { LovelacePanelConfig } from "../../data/lovelace";
53-
import type { LovelaceConfig } from "../../data/lovelace/config/types";
55+
import type {
56+
LovelaceConfig,
57+
LovelaceRawConfig,
58+
} from "../../data/lovelace/config/types";
5459
import { isStrategyDashboard } from "../../data/lovelace/config/types";
5560
import type { LovelaceViewConfig } from "../../data/lovelace/config/view";
5661
import {
@@ -92,6 +97,7 @@ import "./views/hui-view";
9297
import type { HUIView } from "./views/hui-view";
9398
import "./views/hui-view-background";
9499
import "./views/hui-view-container";
100+
import { UndoRedoMixin } from "../../mixins/undo-redo-mixin";
95101

96102
interface ActionItem {
97103
icon: string;
@@ -114,7 +120,9 @@ interface SubActionItem {
114120
}
115121

116122
@customElement("hui-root")
117-
class HUIRoot extends LitElement {
123+
class HUIRoot extends UndoRedoMixin<typeof LitElement, LovelaceRawConfig>(
124+
LitElement
125+
) {
118126
@property({ attribute: false }) public panel?: PanelInfo<LovelacePanelConfig>;
119127

120128
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -130,6 +138,8 @@ class HUIRoot extends LitElement {
130138

131139
@state() private _curView?: number | "hass-unused-entities";
132140

141+
private _configChangedByUndo = false;
142+
133143
private _viewCache?: Record<string, HUIView>;
134144

135145
private _viewScrollPositions: Record<string, number> = {};
@@ -157,7 +167,29 @@ class HUIRoot extends LitElement {
157167
const result: TemplateResult[] = [];
158168
if (this._editMode) {
159169
result.push(
160-
html`<ha-button
170+
html`<ha-icon-button
171+
slot="toolbar-icon"
172+
.path=${mdiUndo}
173+
@click=${this.undo}
174+
.disabled=${!this.canUndo}
175+
id="button-undo"
176+
>
177+
</ha-icon-button>
178+
<ha-tooltip placement="bottom" for="button-undo">
179+
${this.hass.localize("ui.common.undo")}
180+
</ha-tooltip>
181+
<ha-icon-button
182+
slot="toolbar-icon"
183+
.path=${mdiRedo}
184+
@click=${this.redo}
185+
.disabled=${!this.canRedo}
186+
id="button-redo"
187+
>
188+
</ha-icon-button>
189+
<ha-tooltip placement="bottom" for="button-redo">
190+
${this.hass.localize("ui.common.redo")}
191+
</ha-tooltip>
192+
<ha-button
161193
appearance="filled"
162194
size="small"
163195
class="exit-edit-mode"
@@ -640,6 +672,24 @@ class HUIRoot extends LitElement {
640672
window.history.scrollRestoration = "auto";
641673
}
642674

675+
protected willUpdate(changedProperties: PropertyValues): void {
676+
if (changedProperties.has("lovelace")) {
677+
const oldLovelace = changedProperties.get("lovelace") as
678+
| Lovelace
679+
| undefined;
680+
681+
if (
682+
oldLovelace &&
683+
this.lovelace!.rawConfig !== oldLovelace!.rawConfig &&
684+
!this._configChangedByUndo
685+
) {
686+
this.pushToUndo(oldLovelace.rawConfig);
687+
} else {
688+
this._configChangedByUndo = false;
689+
}
690+
}
691+
}
692+
643693
protected updated(changedProperties: PropertyValues): void {
644694
super.updated(changedProperties);
645695

@@ -1024,6 +1074,7 @@ class HUIRoot extends LitElement {
10241074

10251075
private _editModeDisable(): void {
10261076
this.lovelace!.setEditMode(false);
1077+
this.clearUndoRedo();
10271078
}
10281079

10291080
private async _editDashboard() {
@@ -1202,6 +1253,15 @@ class HUIRoot extends LitElement {
12021253
showShortcutsDialog(this);
12031254
}
12041255

1256+
protected get currentConfig() {
1257+
return this.lovelace?.rawConfig;
1258+
}
1259+
1260+
protected applyUndoRedo(config: LovelaceRawConfig) {
1261+
this._configChangedByUndo = true;
1262+
this.lovelace!.saveConfig(config);
1263+
}
1264+
12051265
static get styles(): CSSResultGroup {
12061266
return [
12071267
haStyle,

0 commit comments

Comments
 (0)