diff --git a/src/data/scene.ts b/src/data/scene.ts index 6b029412c4..f77972af6a 100644 --- a/src/data/scene.ts +++ b/src/data/scene.ts @@ -39,6 +39,7 @@ export interface SceneEntity extends HassEntityBase { } export interface SceneConfig { + id?: string; name: string; icon?: string; entities: SceneEntities; diff --git a/src/panels/config/scene/ha-scene-editor.ts b/src/panels/config/scene/ha-scene-editor.ts index 545a5d12b8..953535dbc8 100644 --- a/src/panels/config/scene/ha-scene-editor.ts +++ b/src/panels/config/scene/ha-scene-editor.ts @@ -1,4 +1,11 @@ -import { mdiContentSave } from "@mdi/js"; +import { ActionDetail } from "@material/mwc-list/mwc-list-foundation"; +import "@material/mwc-list/mwc-list-item"; +import { + mdiContentDuplicate, + mdiContentSave, + mdiDelete, + mdiDotsVertical, +} from "@mdi/js"; import "@polymer/paper-item/paper-icon-item"; import "@polymer/paper-item/paper-item"; import "@polymer/paper-item/paper-item-body"; @@ -48,6 +55,7 @@ import { SceneEntities, SceneEntity, SCENE_IGNORED_DOMAINS, + showSceneEditor, } from "../../../data/scene"; import { showAlertDialog, @@ -83,7 +91,7 @@ export class HaSceneEditor extends SubscribeMixin( @property() public route!: Route; - @property() public sceneId?: string; + @property() public sceneId: string | null = null; @property() public scenes!: SceneEntity[]; @@ -198,19 +206,52 @@ export class HaSceneEditor extends SubscribeMixin( .backCallback=${() => this._backTapped()} .tabs=${configSections.automation} > - ${!this.sceneId - ? "" - : html` - - `} + + + + + + ${this.hass.localize( + "ui.panel.config.scene.picker.duplicate_scene" + )} + + + + + ${this.hass.localize("ui.panel.config.scene.picker.delete_scene")} + + + + ${this._errors ? html`
${this._errors}
` : ""} ${this.narrow ? html` ${name} ` : ""}
) { + switch (ev.detail.index) { + case 0: + this._duplicate(); + break; + case 1: + this._deleteTapped(); + break; + } + } + private async _setScene() { const scene = this.scenes.find( (entity: SceneEntity) => entity.attributes.id === this.sceneId @@ -683,6 +735,31 @@ export class HaSceneEditor extends SubscribeMixin( history.back(); } + private async _duplicate() { + if (this._dirty) { + if ( + !(await showConfirmationDialog(this, { + text: this.hass!.localize( + "ui.panel.config.scene.editor.unsaved_confirm" + ), + confirmText: this.hass!.localize("ui.common.leave"), + dismissText: this.hass!.localize("ui.common.stay"), + })) + ) { + return; + } + // Wait for dialog to complete closing + await new Promise((resolve) => setTimeout(resolve, 0)); + } + showSceneEditor(this, { + ...this._config, + id: undefined, + name: `${this._config?.name} (${this.hass.localize( + "ui.panel.config.scene.picker.duplicate" + )})`, + }); + } + private _calculateStates(): SceneEntities { const output: SceneEntities = {}; this._entities.forEach((entityId) => { diff --git a/src/translations/en.json b/src/translations/en.json index 731eda21fa..00a5030c59 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -1680,6 +1680,8 @@ "show_info_scene": "Show info about scene", "delete_scene": "Delete scene", "delete_confirm": "Are you sure you want to delete this scene?", + "duplicate_scene": "Duplicate scene", + "duplicate": "Duplicate", "headers": { "name": "Name" }