mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-27 14:57:20 +00:00
Change the area of scenes in editor (#10731)
This commit is contained in:
parent
ac8f748656
commit
ceac9834b9
@ -18,10 +18,15 @@ export const SCENE_IGNORED_DOMAINS = [
|
||||
"zone",
|
||||
];
|
||||
|
||||
let inititialSceneEditorData: Partial<SceneConfig> | undefined;
|
||||
let inititialSceneEditorData:
|
||||
| { config?: Partial<SceneConfig>; areaId?: string }
|
||||
| undefined;
|
||||
|
||||
export const showSceneEditor = (data?: Partial<SceneConfig>) => {
|
||||
inititialSceneEditorData = data;
|
||||
export const showSceneEditor = (
|
||||
config?: Partial<SceneConfig>,
|
||||
areaId?: string
|
||||
) => {
|
||||
inititialSceneEditorData = { config, areaId };
|
||||
navigate("/config/scene/edit/new");
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@ import "../../../components/ha-card";
|
||||
import "../../../components/ha-fab";
|
||||
import "../../../components/ha-icon-button";
|
||||
import "../../../components/ha-icon-picker";
|
||||
import "../../../components/ha-area-picker";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import {
|
||||
computeDeviceName,
|
||||
@ -41,6 +42,7 @@ import {
|
||||
import {
|
||||
EntityRegistryEntry,
|
||||
subscribeEntityRegistry,
|
||||
updateEntityRegistryEntry,
|
||||
} from "../../../data/entity_registry";
|
||||
import {
|
||||
activateScene,
|
||||
@ -121,6 +123,22 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
|
||||
private _activateContextId?: string;
|
||||
|
||||
@state() private _saving = false;
|
||||
|
||||
// undefined means not set in this session
|
||||
// null means picked nothing.
|
||||
@state() private _updatedAreaId?: string | null;
|
||||
|
||||
// Callback to be called when scene is set.
|
||||
private _scenesSet?: () => void;
|
||||
|
||||
private _getRegistryAreaId = memoizeOne(
|
||||
(entries: EntityRegistryEntry[], entity_id: string) => {
|
||||
const entry = entries.find((ent) => ent.entity_id === entity_id);
|
||||
return entry ? entry.area_id : null;
|
||||
}
|
||||
);
|
||||
|
||||
private _getEntitiesDevices = memoizeOne(
|
||||
(
|
||||
entities: string[],
|
||||
@ -287,6 +305,16 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
@value-changed=${this._valueChanged}
|
||||
>
|
||||
</ha-icon-picker>
|
||||
<ha-area-picker
|
||||
.hass=${this.hass}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.scene.editor.area"
|
||||
)}
|
||||
.name=${"area"}
|
||||
.value=${this._sceneAreaIdWithUpdates || ""}
|
||||
@value-changed=${this._areaChanged}
|
||||
>
|
||||
</ha-area-picker>
|
||||
</div>
|
||||
</ha-card>
|
||||
</ha-config-section>
|
||||
@ -444,8 +472,9 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
slot="fab"
|
||||
.label=${this.hass.localize("ui.panel.config.scene.editor.save")}
|
||||
extended
|
||||
.disabled=${this._saving}
|
||||
@click=${this._saveScene}
|
||||
class=${classMap({ dirty: this._dirty })}
|
||||
class=${classMap({ dirty: this._dirty, saving: this._saving })}
|
||||
>
|
||||
<ha-svg-icon slot="icon" .path=${mdiContentSave}></ha-svg-icon>
|
||||
</ha-fab>
|
||||
@ -474,12 +503,15 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
this._config = {
|
||||
name: this.hass.localize("ui.panel.config.scene.editor.default_name"),
|
||||
entities: {},
|
||||
...initData,
|
||||
...initData?.config,
|
||||
};
|
||||
this._initEntities(this._config);
|
||||
if (initData) {
|
||||
this._dirty = true;
|
||||
if (initData?.areaId) {
|
||||
this._updatedAreaId = initData.areaId;
|
||||
}
|
||||
this._dirty =
|
||||
initData !== undefined &&
|
||||
(initData.areaId !== undefined || initData.config !== undefined);
|
||||
}
|
||||
|
||||
if (changedProps.has("_entityRegistryEntries")) {
|
||||
@ -514,6 +546,9 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
) {
|
||||
this._setScene();
|
||||
}
|
||||
if (this._scenesSet && changedProps.has("scenes")) {
|
||||
this._scenesSet();
|
||||
}
|
||||
}
|
||||
|
||||
private async _handleMenuAction(ev: CustomEvent<ActionDetail>) {
|
||||
@ -689,6 +724,21 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
this._dirty = true;
|
||||
}
|
||||
|
||||
private _areaChanged(ev: CustomEvent) {
|
||||
const newValue = ev.detail.value === "" ? null : ev.detail.value;
|
||||
|
||||
if (newValue === (this._sceneAreaIdWithUpdates || "")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (newValue === this._sceneAreaIdCurrent) {
|
||||
this._updatedAreaId = undefined;
|
||||
} else {
|
||||
this._updatedAreaId = newValue;
|
||||
this._dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
private _stateChanged(event: HassEvent) {
|
||||
if (
|
||||
event.context.id !== this._activateContextId &&
|
||||
@ -749,13 +799,16 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
// Wait for dialog to complete closing
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
}
|
||||
showSceneEditor({
|
||||
showSceneEditor(
|
||||
{
|
||||
...this._config,
|
||||
id: undefined,
|
||||
name: `${this._config?.name} (${this.hass.localize(
|
||||
"ui.panel.config.scene.picker.duplicate"
|
||||
)})`,
|
||||
});
|
||||
},
|
||||
this._sceneAreaIdCurrent || undefined
|
||||
);
|
||||
}
|
||||
|
||||
private _calculateStates(): SceneEntities {
|
||||
@ -792,7 +845,41 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
const id = !this.sceneId ? "" + Date.now() : this.sceneId!;
|
||||
this._config = { ...this._config!, entities: this._calculateStates() };
|
||||
try {
|
||||
this._saving = true;
|
||||
await saveScene(this.hass, id, this._config);
|
||||
|
||||
if (this._updatedAreaId !== undefined) {
|
||||
let scene =
|
||||
this._scene ||
|
||||
this.scenes.find(
|
||||
(entity: SceneEntity) => entity.attributes.id === id
|
||||
);
|
||||
|
||||
if (!scene) {
|
||||
try {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
setTimeout(reject, 3000);
|
||||
this._scenesSet = resolve;
|
||||
});
|
||||
scene = this.scenes.find(
|
||||
(entity: SceneEntity) => entity.attributes.id === id
|
||||
);
|
||||
} catch (err) {
|
||||
// We do nothing.
|
||||
} finally {
|
||||
this._scenesSet = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if (scene) {
|
||||
await updateEntityRegistryEntry(this.hass, scene.entity_id, {
|
||||
area_id: this._updatedAreaId,
|
||||
});
|
||||
}
|
||||
|
||||
this._updatedAreaId = undefined;
|
||||
}
|
||||
|
||||
this._dirty = false;
|
||||
|
||||
if (!this.sceneId) {
|
||||
@ -804,6 +891,8 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
message: err.body.message || err.message,
|
||||
});
|
||||
throw err;
|
||||
} finally {
|
||||
this._saving = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -811,6 +900,21 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
this._saveScene();
|
||||
}
|
||||
|
||||
private get _sceneAreaIdWithUpdates(): string | undefined | null {
|
||||
return this._updatedAreaId !== undefined
|
||||
? this._updatedAreaId
|
||||
: this._sceneAreaIdCurrent;
|
||||
}
|
||||
|
||||
private get _sceneAreaIdCurrent(): string | undefined | null {
|
||||
return this._scene
|
||||
? this._getRegistryAreaId(
|
||||
this._entityRegistryEntries,
|
||||
this._scene.entity_id
|
||||
)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
@ -877,6 +981,9 @@ export class HaSceneEditor extends SubscribeMixin(
|
||||
ha-fab.dirty {
|
||||
bottom: 0;
|
||||
}
|
||||
ha-fab.saving {
|
||||
opacity: var(--light-disabled-opacity);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
@ -1900,6 +1900,7 @@
|
||||
"unsaved_confirm": "You have unsaved changes. Are you sure you want to leave?",
|
||||
"name": "Name",
|
||||
"icon": "Icon",
|
||||
"area": "Area",
|
||||
"devices": {
|
||||
"header": "Devices",
|
||||
"introduction": "Add the devices that you want to be included in your scene. Set all the devices to the state you want for this scene.",
|
||||
|
Loading…
x
Reference in New Issue
Block a user