mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-25 18:26:35 +00:00
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,
|
ScorableTextItem,
|
||||||
fuzzyFilterSort,
|
fuzzyFilterSort,
|
||||||
} from "../common/string/filter/sequence-matching";
|
} from "../common/string/filter/sequence-matching";
|
||||||
import { AreaRegistryEntry } from "../data/area_registry";
|
import {
|
||||||
|
AreaRegistryEntry,
|
||||||
|
updateAreaRegistryEntry,
|
||||||
|
} from "../data/area_registry";
|
||||||
import {
|
import {
|
||||||
DeviceEntityDisplayLookup,
|
DeviceEntityDisplayLookup,
|
||||||
DeviceRegistryEntry,
|
DeviceRegistryEntry,
|
||||||
@ -441,9 +444,14 @@ export class HaFloorPicker extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
showFloorRegistryDetailDialog(this, {
|
showFloorRegistryDetailDialog(this, {
|
||||||
suggestedName: newValue === ADD_NEW_SUGGESTION_ID ? this._suggestion : "",
|
suggestedName: newValue === ADD_NEW_SUGGESTION_ID ? this._suggestion : "",
|
||||||
createEntry: async (values) => {
|
createEntry: async (values, addedAreas) => {
|
||||||
try {
|
try {
|
||||||
const floor = await createFloorRegistryEntry(this.hass, values);
|
const floor = await createFloorRegistryEntry(this.hass, values);
|
||||||
|
addedAreas.forEach((areaId) => {
|
||||||
|
updateAreaRegistryEntry(this.hass, areaId, {
|
||||||
|
floor_id: floor.floor_id,
|
||||||
|
});
|
||||||
|
});
|
||||||
const floors = [...this._floors!, floor];
|
const floors = [...this._floors!, floor];
|
||||||
this.comboBox.filteredItems = this._getFloors(
|
this.comboBox.filteredItems = this._getFloors(
|
||||||
floors,
|
floors,
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import "@material/mwc-list/mwc-list";
|
import "@material/mwc-list/mwc-list";
|
||||||
|
import { mdiTextureBox } from "@mdi/js";
|
||||||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||||
import { property, state } from "lit/decorators";
|
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 { 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-alert";
|
||||||
import "../../../components/ha-aliases-editor";
|
import "../../../components/ha-aliases-editor";
|
||||||
import { createCloseHeading } from "../../../components/ha-dialog";
|
import { createCloseHeading } from "../../../components/ha-dialog";
|
||||||
@ -11,10 +16,15 @@ import "../../../components/ha-picture-upload";
|
|||||||
import "../../../components/ha-settings-row";
|
import "../../../components/ha-settings-row";
|
||||||
import "../../../components/ha-svg-icon";
|
import "../../../components/ha-svg-icon";
|
||||||
import "../../../components/ha-textfield";
|
import "../../../components/ha-textfield";
|
||||||
import { FloorRegistryEntryMutableParams } from "../../../data/floor_registry";
|
import {
|
||||||
import { haStyleDialog } from "../../../resources/styles";
|
FloorRegistryEntry,
|
||||||
|
FloorRegistryEntryMutableParams,
|
||||||
|
} from "../../../data/floor_registry";
|
||||||
|
import { haStyle, haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { FloorRegistryDetailDialogParams } from "./show-dialog-floor-registry-detail";
|
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 {
|
class DialogFloorDetail extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@ -33,9 +43,11 @@ class DialogFloorDetail extends LitElement {
|
|||||||
|
|
||||||
@state() private _submitting?: boolean;
|
@state() private _submitting?: boolean;
|
||||||
|
|
||||||
public async showDialog(
|
@state() private _addedAreas = new Set<string>();
|
||||||
params: FloorRegistryDetailDialogParams
|
|
||||||
): Promise<void> {
|
@state() private _removedAreas = new Set<string>();
|
||||||
|
|
||||||
|
public showDialog(params: FloorRegistryDetailDialogParams): void {
|
||||||
this._params = params;
|
this._params = params;
|
||||||
this._error = undefined;
|
this._error = undefined;
|
||||||
this._name = this._params.entry
|
this._name = this._params.entry
|
||||||
@ -44,16 +56,40 @@ class DialogFloorDetail extends LitElement {
|
|||||||
this._aliases = this._params.entry?.aliases || [];
|
this._aliases = this._params.entry?.aliases || [];
|
||||||
this._icon = this._params.entry?.icon || null;
|
this._icon = this._params.entry?.icon || null;
|
||||||
this._level = this._params.entry?.level ?? null;
|
this._level = this._params.entry?.level ?? null;
|
||||||
await this.updateComplete;
|
this._addedAreas.clear();
|
||||||
|
this._removedAreas.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeDialog(): void {
|
public closeDialog(): void {
|
||||||
this._error = "";
|
this._error = "";
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
|
this._addedAreas.clear();
|
||||||
|
this._removedAreas.clear();
|
||||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
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() {
|
protected render() {
|
||||||
|
const areas = this._floorAreas(
|
||||||
|
this._params?.entry,
|
||||||
|
this.hass.areas,
|
||||||
|
this._addedAreas,
|
||||||
|
this._removedAreas
|
||||||
|
);
|
||||||
|
|
||||||
if (!this._params) {
|
if (!this._params) {
|
||||||
return nothing;
|
return nothing;
|
||||||
}
|
}
|
||||||
@ -125,6 +161,52 @@ class DialogFloorDetail extends LitElement {
|
|||||||
: nothing}
|
: nothing}
|
||||||
</ha-icon-picker>
|
</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">
|
<h3 class="header">
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.floors.editor.aliases_section"
|
"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() {
|
private _isNameValid() {
|
||||||
return this._name.trim() !== "";
|
return this._name.trim() !== "";
|
||||||
}
|
}
|
||||||
@ -189,9 +306,13 @@ class DialogFloorDetail extends LitElement {
|
|||||||
aliases: this._aliases,
|
aliases: this._aliases,
|
||||||
};
|
};
|
||||||
if (create) {
|
if (create) {
|
||||||
await this._params!.createEntry!(values);
|
await this._params!.createEntry!(values, this._addedAreas);
|
||||||
} else {
|
} else {
|
||||||
await this._params!.updateEntry!(values);
|
await this._params!.updateEntry!(
|
||||||
|
values,
|
||||||
|
this._addedAreas,
|
||||||
|
this._removedAreas
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
@ -209,6 +330,7 @@ class DialogFloorDetail extends LitElement {
|
|||||||
|
|
||||||
static get styles(): CSSResultGroup {
|
static get styles(): CSSResultGroup {
|
||||||
return [
|
return [
|
||||||
|
haStyle,
|
||||||
haStyleDialog,
|
haStyleDialog,
|
||||||
css`
|
css`
|
||||||
ha-textfield {
|
ha-textfield {
|
||||||
@ -218,6 +340,9 @@ class DialogFloorDetail extends LitElement {
|
|||||||
ha-floor-icon {
|
ha-floor-icon {
|
||||||
color: var(--secondary-text-color);
|
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) {
|
private _openFloorDialog(entry?: FloorRegistryEntry) {
|
||||||
showFloorRegistryDetailDialog(this, {
|
showFloorRegistryDetailDialog(this, {
|
||||||
entry,
|
entry,
|
||||||
createEntry: async (values) =>
|
createEntry: async (values, addedAreas) => {
|
||||||
createFloorRegistryEntry(this.hass!, values),
|
const floor = await createFloorRegistryEntry(this.hass!, values);
|
||||||
updateEntry: async (values) =>
|
addedAreas.forEach((areaId) => {
|
||||||
updateFloorRegistryEntry(this.hass!, entry!.floor_id, values),
|
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 {
|
export interface FloorRegistryDetailDialogParams {
|
||||||
entry?: FloorRegistryEntry;
|
entry?: FloorRegistryEntry;
|
||||||
suggestedName?: string;
|
suggestedName?: string;
|
||||||
createEntry?: (values: FloorRegistryEntryMutableParams) => Promise<unknown>;
|
createEntry?: (
|
||||||
|
values: FloorRegistryEntryMutableParams,
|
||||||
|
addedAreas: Set<string>
|
||||||
|
) => Promise<unknown>;
|
||||||
updateEntry?: (
|
updateEntry?: (
|
||||||
updates: Partial<FloorRegistryEntryMutableParams>
|
updates: Partial<FloorRegistryEntryMutableParams>,
|
||||||
|
addedAreas: Set<string>,
|
||||||
|
removedAreas: Set<string>
|
||||||
) => Promise<unknown>;
|
) => Promise<unknown>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1927,7 +1927,10 @@
|
|||||||
"aliases_section": "Aliases",
|
"aliases_section": "Aliases",
|
||||||
"no_aliases": "No configured aliases",
|
"no_aliases": "No configured aliases",
|
||||||
"configured_aliases": "{count} configured {count, plural,\n one {alias}\n other {aliases}\n}",
|
"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": {
|
"category": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user