Manage areas from floor dialog (#20347)
* manage areas from floor dialog * Finish * fix exclude
This commit is contained in:
parent
eb79a1e7d7
commit
034fd9b4df
|
@ -10,7 +10,10 @@ import {
|
|||
ScorableTextItem,
|
||||
fuzzyFilterSort,
|
||||
} from "../common/string/filter/sequence-matching";
|
||||
import { AreaRegistryEntry } from "../data/area_registry";
|
||||
import {
|
||||
AreaRegistryEntry,
|
||||
updateAreaRegistryEntry,
|
||||
} from "../data/area_registry";
|
||||
import {
|
||||
DeviceEntityDisplayLookup,
|
||||
DeviceRegistryEntry,
|
||||
|
@ -441,9 +444,14 @@ export class HaFloorPicker extends SubscribeMixin(LitElement) {
|
|||
|
||||
showFloorRegistryDetailDialog(this, {
|
||||
suggestedName: newValue === ADD_NEW_SUGGESTION_ID ? this._suggestion : "",
|
||||
createEntry: async (values) => {
|
||||
createEntry: async (values, addedAreas) => {
|
||||
try {
|
||||
const floor = await createFloorRegistryEntry(this.hass, values);
|
||||
addedAreas.forEach((areaId) => {
|
||||
updateAreaRegistryEntry(this.hass, areaId, {
|
||||
floor_id: floor.floor_id,
|
||||
});
|
||||
});
|
||||
const floors = [...this._floors!, floor];
|
||||
this.comboBox.filteredItems = this._getFloors(
|
||||
floors,
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import "@material/mwc-button";
|
||||
import "@material/mwc-list/mwc-list";
|
||||
import { mdiTextureBox } from "@mdi/js";
|
||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { property, state } from "lit/decorators";
|
||||
import { repeat } from "lit/directives/repeat";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import "../../../components/chips/ha-chip-set";
|
||||
import "../../../components/chips/ha-input-chip";
|
||||
import "../../../components/ha-alert";
|
||||
import "../../../components/ha-aliases-editor";
|
||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||
|
@ -11,10 +16,15 @@ import "../../../components/ha-picture-upload";
|
|||
import "../../../components/ha-settings-row";
|
||||
import "../../../components/ha-svg-icon";
|
||||
import "../../../components/ha-textfield";
|
||||
import { FloorRegistryEntryMutableParams } from "../../../data/floor_registry";
|
||||
import { haStyleDialog } from "../../../resources/styles";
|
||||
import {
|
||||
FloorRegistryEntry,
|
||||
FloorRegistryEntryMutableParams,
|
||||
} from "../../../data/floor_registry";
|
||||
import { haStyle, haStyleDialog } from "../../../resources/styles";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { FloorRegistryDetailDialogParams } from "./show-dialog-floor-registry-detail";
|
||||
import { showAreaRegistryDetailDialog } from "./show-dialog-area-registry-detail";
|
||||
import { updateAreaRegistryEntry } from "../../../data/area_registry";
|
||||
|
||||
class DialogFloorDetail extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
@ -33,9 +43,11 @@ class DialogFloorDetail extends LitElement {
|
|||
|
||||
@state() private _submitting?: boolean;
|
||||
|
||||
public async showDialog(
|
||||
params: FloorRegistryDetailDialogParams
|
||||
): Promise<void> {
|
||||
@state() private _addedAreas = new Set<string>();
|
||||
|
||||
@state() private _removedAreas = new Set<string>();
|
||||
|
||||
public showDialog(params: FloorRegistryDetailDialogParams): void {
|
||||
this._params = params;
|
||||
this._error = undefined;
|
||||
this._name = this._params.entry
|
||||
|
@ -44,16 +56,40 @@ class DialogFloorDetail extends LitElement {
|
|||
this._aliases = this._params.entry?.aliases || [];
|
||||
this._icon = this._params.entry?.icon || null;
|
||||
this._level = this._params.entry?.level ?? null;
|
||||
await this.updateComplete;
|
||||
this._addedAreas.clear();
|
||||
this._removedAreas.clear();
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this._error = "";
|
||||
this._params = undefined;
|
||||
this._addedAreas.clear();
|
||||
this._removedAreas.clear();
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
private _floorAreas = memoizeOne(
|
||||
(
|
||||
entry: FloorRegistryEntry | undefined,
|
||||
areas: HomeAssistant["areas"],
|
||||
added: Set<string>,
|
||||
removed: Set<string>
|
||||
) =>
|
||||
Object.values(areas).filter(
|
||||
(area) =>
|
||||
(area.floor_id === entry?.floor_id || added.has(area.area_id)) &&
|
||||
!removed.has(area.area_id)
|
||||
)
|
||||
);
|
||||
|
||||
protected render() {
|
||||
const areas = this._floorAreas(
|
||||
this._params?.entry,
|
||||
this.hass.areas,
|
||||
this._addedAreas,
|
||||
this._removedAreas
|
||||
);
|
||||
|
||||
if (!this._params) {
|
||||
return nothing;
|
||||
}
|
||||
|
@ -125,6 +161,52 @@ class DialogFloorDetail extends LitElement {
|
|||
: nothing}
|
||||
</ha-icon-picker>
|
||||
|
||||
<h3 class="header">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.floors.editor.areas_section"
|
||||
)}
|
||||
</h3>
|
||||
|
||||
<p class="description">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.floors.editor.areas_description"
|
||||
)}
|
||||
</p>
|
||||
${areas.length
|
||||
? html`<ha-chip-set>
|
||||
${repeat(
|
||||
areas,
|
||||
(area) => area.area_id,
|
||||
(area) =>
|
||||
html`<ha-input-chip
|
||||
.area=${area}
|
||||
@click=${this._openArea}
|
||||
@remove=${this._removeArea}
|
||||
.label=${area?.name}
|
||||
>
|
||||
${area.icon
|
||||
? html`<ha-icon
|
||||
slot="icon"
|
||||
.icon=${area.icon}
|
||||
></ha-icon>`
|
||||
: html`<ha-svg-icon
|
||||
slot="icon"
|
||||
.path=${mdiTextureBox}
|
||||
></ha-svg-icon>`}
|
||||
</ha-input-chip>`
|
||||
)}
|
||||
</ha-chip-set>`
|
||||
: nothing}
|
||||
<ha-area-picker
|
||||
no-add
|
||||
.hass=${this.hass}
|
||||
@value-changed=${this._addArea}
|
||||
.excludeAreas=${areas.map((a) => a.area_id)}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.floors.editor.add_area"
|
||||
)}
|
||||
></ha-area-picker>
|
||||
|
||||
<h3 class="header">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.floors.editor.aliases_section"
|
||||
|
@ -159,6 +241,41 @@ class DialogFloorDetail extends LitElement {
|
|||
`;
|
||||
}
|
||||
|
||||
private _openArea(ev) {
|
||||
const area = ev.target.area;
|
||||
showAreaRegistryDetailDialog(this, {
|
||||
entry: area,
|
||||
updateEntry: (values) =>
|
||||
updateAreaRegistryEntry(this.hass!, area.area_id, values),
|
||||
});
|
||||
}
|
||||
|
||||
private _removeArea(ev) {
|
||||
const areaId = ev.target.area.area_id;
|
||||
if (this._addedAreas.has(areaId)) {
|
||||
this._addedAreas.delete(areaId);
|
||||
this._addedAreas = new Set(this._addedAreas);
|
||||
return;
|
||||
}
|
||||
this._removedAreas.add(areaId);
|
||||
this._removedAreas = new Set(this._removedAreas);
|
||||
}
|
||||
|
||||
private _addArea(ev) {
|
||||
const areaId = ev.detail.value;
|
||||
if (!areaId) {
|
||||
return;
|
||||
}
|
||||
ev.target.value = "";
|
||||
if (this._removedAreas.has(areaId)) {
|
||||
this._removedAreas.delete(areaId);
|
||||
this._removedAreas = new Set(this._removedAreas);
|
||||
return;
|
||||
}
|
||||
this._addedAreas.add(areaId);
|
||||
this._addedAreas = new Set(this._addedAreas);
|
||||
}
|
||||
|
||||
private _isNameValid() {
|
||||
return this._name.trim() !== "";
|
||||
}
|
||||
|
@ -189,9 +306,13 @@ class DialogFloorDetail extends LitElement {
|
|||
aliases: this._aliases,
|
||||
};
|
||||
if (create) {
|
||||
await this._params!.createEntry!(values);
|
||||
await this._params!.createEntry!(values, this._addedAreas);
|
||||
} else {
|
||||
await this._params!.updateEntry!(values);
|
||||
await this._params!.updateEntry!(
|
||||
values,
|
||||
this._addedAreas,
|
||||
this._removedAreas
|
||||
);
|
||||
}
|
||||
this.closeDialog();
|
||||
} catch (err: any) {
|
||||
|
@ -209,6 +330,7 @@ class DialogFloorDetail extends LitElement {
|
|||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-textfield {
|
||||
|
@ -218,6 +340,9 @@ class DialogFloorDetail extends LitElement {
|
|||
ha-floor-icon {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
ha-chip-set {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
|
|
@ -414,10 +414,31 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) {
|
|||
private _openFloorDialog(entry?: FloorRegistryEntry) {
|
||||
showFloorRegistryDetailDialog(this, {
|
||||
entry,
|
||||
createEntry: async (values) =>
|
||||
createFloorRegistryEntry(this.hass!, values),
|
||||
updateEntry: async (values) =>
|
||||
updateFloorRegistryEntry(this.hass!, entry!.floor_id, values),
|
||||
createEntry: async (values, addedAreas) => {
|
||||
const floor = await createFloorRegistryEntry(this.hass!, values);
|
||||
addedAreas.forEach((areaId) => {
|
||||
updateAreaRegistryEntry(this.hass, areaId, {
|
||||
floor_id: floor.floor_id,
|
||||
});
|
||||
});
|
||||
},
|
||||
updateEntry: async (values, addedAreas, removedAreas) => {
|
||||
const floor = await updateFloorRegistryEntry(
|
||||
this.hass!,
|
||||
entry!.floor_id,
|
||||
values
|
||||
);
|
||||
addedAreas.forEach((areaId) => {
|
||||
updateAreaRegistryEntry(this.hass, areaId, {
|
||||
floor_id: floor.floor_id,
|
||||
});
|
||||
});
|
||||
removedAreas.forEach((areaId) => {
|
||||
updateAreaRegistryEntry(this.hass, areaId, {
|
||||
floor_id: null,
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,14 @@ import {
|
|||
export interface FloorRegistryDetailDialogParams {
|
||||
entry?: FloorRegistryEntry;
|
||||
suggestedName?: string;
|
||||
createEntry?: (values: FloorRegistryEntryMutableParams) => Promise<unknown>;
|
||||
createEntry?: (
|
||||
values: FloorRegistryEntryMutableParams,
|
||||
addedAreas: Set<string>
|
||||
) => Promise<unknown>;
|
||||
updateEntry?: (
|
||||
updates: Partial<FloorRegistryEntryMutableParams>
|
||||
updates: Partial<FloorRegistryEntryMutableParams>,
|
||||
addedAreas: Set<string>,
|
||||
removedAreas: Set<string>
|
||||
) => Promise<unknown>;
|
||||
}
|
||||
|
||||
|
|
|
@ -1927,7 +1927,10 @@
|
|||
"aliases_section": "Aliases",
|
||||
"no_aliases": "No configured aliases",
|
||||
"configured_aliases": "{count} configured {count, plural,\n one {alias}\n other {aliases}\n}",
|
||||
"aliases_description": "Aliases are alternative names used in voice assistants to refer to this floor."
|
||||
"aliases_description": "Aliases are alternative names used in voice assistants to refer to this floor.",
|
||||
"areas_section": "Areas",
|
||||
"areas_description": "Specify the areas that are on this floor.",
|
||||
"add_area": "Add area"
|
||||
}
|
||||
},
|
||||
"category": {
|
||||
|
|
Loading…
Reference in New Issue