mirror of
				https://github.com/home-assistant/frontend.git
				synced 2025-11-04 00:19:47 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			20251001.2
			...
			dashboard-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					f3f2059634 | ||
| 
						 | 
					497484d419 | 
@@ -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;
 | 
			
		||||
@@ -343,7 +345,11 @@ export class LovelacePanel extends LitElement {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!editMode || this.lovelace!.mode !== "generated") {
 | 
			
		||||
          this._updateLovelace({ editMode });
 | 
			
		||||
          this._updateLovelace({
 | 
			
		||||
            editMode,
 | 
			
		||||
            configHistory: [this.lovelace!.config],
 | 
			
		||||
            configHistoryIndex: 0,
 | 
			
		||||
          });
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -358,6 +364,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 +380,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 +407,7 @@ export class LovelacePanel extends LitElement {
 | 
			
		||||
            config: previousConfig,
 | 
			
		||||
            rawConfig: previousRawConfig,
 | 
			
		||||
            mode: previousMode,
 | 
			
		||||
            configHistory: previousConfigHistory,
 | 
			
		||||
          });
 | 
			
		||||
          throw err;
 | 
			
		||||
        }
 | 
			
		||||
@@ -427,6 +447,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;
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user