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"
}