diff --git a/src/components/ha-area-filter.ts b/src/components/ha-area-filter.ts index 9640f60e5e..504b4bf9f4 100644 --- a/src/components/ha-area-filter.ts +++ b/src/components/ha-area-filter.ts @@ -1,12 +1,12 @@ -import { mdiSofa } from "@mdi/js"; +import { mdiTextureBox } from "@mdi/js"; import { CSSResultGroup, LitElement, TemplateResult, css, html } from "lit"; import { customElement, property } from "lit/decorators"; import { fireEvent } from "../common/dom/fire_event"; import { showAreaFilterDialog } from "../dialogs/area-filter/show-area-filter-dialog"; import { HomeAssistant } from "../types"; +import "./ha-icon-next"; import "./ha-svg-icon"; import "./ha-textfield"; -import "./ha-icon-next"; export type AreaFilterValue = { hidden?: string[]; @@ -51,7 +51,7 @@ export class HaAreaPicker extends LitElement { @keydown=${this._edit} .disabled=${this.disabled} > - + ${this.label} ${description} = (item) => @@ -49,9 +52,14 @@ const rowRenderer: ComboBoxLitRenderer = (item) => ? "--mdc-list-side-padding-left: 48px;" : ""} > - ${item.icon - ? html`` - : nothing} + ${item.type === "floor" + ? html`` + : item.icon + ? html`` + : html``} ${item.name} `; @@ -165,6 +173,7 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { name: this.hass.localize("ui.components.area-picker.no_areas"), icon: null, strings: [], + level: null, }, ]; } @@ -316,6 +325,7 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { name: this.hass.localize("ui.components.area-picker.no_match"), icon: null, strings: [], + level: null, }, ]; } @@ -350,6 +360,7 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { name: floor.name, icon: floor.icon, strings: [floor.floor_id, ...floor.aliases, floor.name], + level: floor.level, }); } output.push( @@ -360,6 +371,7 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { icon: area.icon, strings: [area.area_id, ...area.aliases, area.name], hasFloor: true, + level: null, })) ); }); @@ -373,6 +385,7 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { ), icon: null, strings: [], + level: null, }); } @@ -383,6 +396,7 @@ export class HaAreaFloorPicker extends SubscribeMixin(LitElement) { name: area.name, icon: area.icon, strings: [area.area_id, ...area.aliases, area.name], + level: null, })) ); diff --git a/src/components/ha-area-picker.ts b/src/components/ha-area-picker.ts index 3f6301060c..a7b404f29a 100644 --- a/src/components/ha-area-picker.ts +++ b/src/components/ha-area-picker.ts @@ -1,14 +1,15 @@ +import { mdiTextureBox } from "@mdi/js"; import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit"; import { HassEntity } from "home-assistant-js-websocket"; -import { html, LitElement, nothing, PropertyValues, TemplateResult } from "lit"; +import { LitElement, PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import memoizeOne from "memoize-one"; import { fireEvent } from "../common/dom/fire_event"; import { computeDomain } from "../common/entity/compute_domain"; import { - fuzzyFilterSort, ScorableTextItem, + fuzzyFilterSort, } from "../common/string/filter/sequence-matching"; import { AreaRegistryEntry, @@ -41,7 +42,7 @@ const rowRenderer: ComboBoxLitRenderer = (item) => > ${item.icon ? html`` - : nothing} + : html``} ${item.name} `; diff --git a/src/components/ha-filter-floor-areas.ts b/src/components/ha-filter-floor-areas.ts index a90fba10f0..2ee817c370 100644 --- a/src/components/ha-filter-floor-areas.ts +++ b/src/components/ha-filter-floor-areas.ts @@ -1,4 +1,5 @@ import "@material/mwc-menu/mwc-menu-surface"; +import { mdiTextureBox } from "@mdi/js"; import { UnsubscribeFunc } from "home-assistant-js-websocket"; import { css, CSSResultGroup, html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; @@ -15,6 +16,9 @@ import { SubscribeMixin } from "../mixins/subscribe-mixin"; import { haStyleScrollbar } from "../resources/styles"; import type { HomeAssistant } from "../types"; import "./ha-check-list-item"; +import "./ha-floor-icon"; +import "./ha-icon"; +import "./ha-svg-icon"; @customElement("ha-filter-floor-areas") export class HaFilterFloorAreas extends SubscribeMixin(LitElement) { @@ -70,12 +74,10 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) { graphic="icon" @request-selected=${this._handleItemClick} > - ${floor.icon - ? html`` - : nothing} + ${floor.name} ${repeat( @@ -108,7 +110,10 @@ export class HaFilterFloorAreas extends SubscribeMixin(LitElement) { > ${area.icon ? html`` - : nothing} + : html``} ${area.name} `; } diff --git a/src/components/ha-floor-icon.ts b/src/components/ha-floor-icon.ts new file mode 100644 index 0000000000..edb840a57c --- /dev/null +++ b/src/components/ha-floor-icon.ts @@ -0,0 +1,56 @@ +import { + mdiHome, + mdiHomeFloor0, + mdiHomeFloor1, + mdiHomeFloor2, + mdiHomeFloor3, + mdiHomeFloorNegative1, +} from "@mdi/js"; +import { LitElement, html } from "lit"; +import { customElement, property } from "lit/decorators"; +import { FloorRegistryEntry } from "../data/floor_registry"; +import "./ha-icon"; +import "./ha-svg-icon"; + +export const floorDefaultIconPath = ( + floor: Pick +) => { + switch (floor.level) { + case 0: + return mdiHomeFloor0; + case 1: + return mdiHomeFloor1; + case 2: + return mdiHomeFloor2; + case 3: + return mdiHomeFloor3; + case -1: + return mdiHomeFloorNegative1; + } + return mdiHome; +}; + +@customElement("ha-floor-icon") +export class HaFloorIcon extends LitElement { + @property({ attribute: false }) public floor!: Pick< + FloorRegistryEntry, + "icon" | "level" + >; + + @property() public icon?: string; + + protected render() { + if (this.floor.icon) { + return html``; + } + const defaultPath = floorDefaultIconPath(this.floor); + + return html``; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-floor-icon": HaFloorIcon; + } +} diff --git a/src/components/ha-floor-picker.ts b/src/components/ha-floor-picker.ts index b344057543..1c6be3bf28 100644 --- a/src/components/ha-floor-picker.ts +++ b/src/components/ha-floor-picker.ts @@ -1,14 +1,14 @@ import { ComboBoxLitRenderer } from "@vaadin/combo-box/lit"; import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket"; -import { html, LitElement, nothing, PropertyValues, TemplateResult } from "lit"; +import { LitElement, PropertyValues, TemplateResult, html } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import memoizeOne from "memoize-one"; import { fireEvent } from "../common/dom/fire_event"; import { computeDomain } from "../common/entity/compute_domain"; import { - fuzzyFilterSort, ScorableTextItem, + fuzzyFilterSort, } from "../common/string/filter/sequence-matching"; import { AreaRegistryEntry } from "../data/area_registry"; import { @@ -17,24 +17,24 @@ import { getDeviceEntityDisplayLookup, } from "../data/device_registry"; import { EntityRegistryDisplayEntry } from "../data/entity_registry"; +import { + FloorRegistryEntry, + createFloorRegistryEntry, + getFloorAreaLookup, + subscribeFloorRegistry, +} from "../data/floor_registry"; import { showAlertDialog, showPromptDialog, } from "../dialogs/generic/show-dialog-box"; +import { SubscribeMixin } from "../mixins/subscribe-mixin"; import { HomeAssistant, ValueChangedEvent } from "../types"; import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker"; import "./ha-combo-box"; import type { HaComboBox } from "./ha-combo-box"; +import "./ha-floor-icon"; import "./ha-icon-button"; import "./ha-list-item"; -import "./ha-svg-icon"; -import { SubscribeMixin } from "../mixins/subscribe-mixin"; -import { - createFloorRegistryEntry, - FloorRegistryEntry, - getFloorAreaLookup, - subscribeFloorRegistry, -} from "../data/floor_registry"; type ScorableFloorRegistryEntry = ScorableTextItem & FloorRegistryEntry; @@ -43,9 +43,7 @@ const rowRenderer: ComboBoxLitRenderer = (item) => graphic="icon" class=${classMap({ "add-new": item.floor_id === "add_new" })} > - ${item.icon - ? html`` - : nothing} + ${item.name} `; diff --git a/src/components/ha-icon-picker.ts b/src/components/ha-icon-picker.ts index 871adf5380..e148ff86bd 100644 --- a/src/components/ha-icon-picker.ts +++ b/src/components/ha-icon-picker.ts @@ -118,7 +118,7 @@ export class HaIconPicker extends LitElement { ` - : html``} + : html``} `; } diff --git a/src/components/ha-target-picker.ts b/src/components/ha-target-picker.ts index 608a4ba829..21d32d3ea3 100644 --- a/src/components/ha-target-picker.ts +++ b/src/components/ha-target-picker.ts @@ -6,10 +6,10 @@ import "@material/mwc-menu/mwc-menu-surface"; import { mdiClose, mdiDevices, - mdiFloorPlan, + mdiHome, mdiLabel, mdiPlus, - mdiSofa, + mdiTextureBox, mdiUnfoldMoreVertical, } from "@mdi/js"; import { ComboBoxLightOpenedChangedEvent } from "@vaadin/combo-box/vaadin-combo-box-light"; @@ -18,30 +18,23 @@ import { HassServiceTarget, UnsubscribeFunc, } from "home-assistant-js-websocket"; -import { css, CSSResultGroup, html, LitElement, nothing, unsafeCSS } from "lit"; +import { CSSResultGroup, LitElement, css, html, nothing, unsafeCSS } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { ensureArray } from "../common/array/ensure-array"; +import { computeCssColor } from "../common/color/compute-color"; +import { hex2rgb } from "../common/color/convert-color"; import { fireEvent } from "../common/dom/fire_event"; import { stopPropagation } from "../common/dom/stop_propagation"; import { computeDomain } from "../common/entity/compute_domain"; import { computeStateName } from "../common/entity/compute_state_name"; import { isValidEntityId } from "../common/entity/valid_entity_id"; +import { AreaRegistryEntry } from "../data/area_registry"; import { - computeDeviceName, DeviceRegistryEntry, + computeDeviceName, } from "../data/device_registry"; import { EntityRegistryDisplayEntry } from "../data/entity_registry"; -import { HomeAssistant } from "../types"; -import "./device/ha-device-picker"; -import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker"; -import "./entity/ha-entity-picker"; -import type { HaEntityPickerEntityFilterFunc } from "./entity/ha-entity-picker"; -import "./ha-area-floor-picker"; -import "./ha-icon-button"; -import "./ha-input-helper-text"; -import "./ha-svg-icon"; -import { SubscribeMixin } from "../mixins/subscribe-mixin"; import { FloorRegistryEntry, subscribeFloorRegistry, @@ -50,9 +43,17 @@ import { LabelRegistryEntry, subscribeLabelRegistry, } from "../data/label_registry"; -import { computeCssColor } from "../common/color/compute-color"; -import { AreaRegistryEntry } from "../data/area_registry"; -import { hex2rgb } from "../common/color/convert-color"; +import { SubscribeMixin } from "../mixins/subscribe-mixin"; +import { HomeAssistant } from "../types"; +import "./device/ha-device-picker"; +import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker"; +import "./entity/ha-entity-picker"; +import type { HaEntityPickerEntityFilterFunc } from "./entity/ha-entity-picker"; +import "./ha-area-floor-picker"; +import { floorDefaultIconPath } from "./ha-floor-icon"; +import "./ha-icon-button"; +import "./ha-input-helper-text"; +import "./ha-svg-icon"; @customElement("ha-target-picker") export class HaTargetPicker extends SubscribeMixin(LitElement) { @@ -138,7 +139,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) { floor?.name || floor_id, undefined, floor?.icon, - mdiFloorPlan + floor ? floorDefaultIconPath(floor) : mdiHome ); }) : ""} @@ -151,7 +152,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) { area?.name || area_id, undefined, area?.icon, - mdiSofa + mdiTextureBox ); }) : nothing} diff --git a/src/data/floor_registry.ts b/src/data/floor_registry.ts index 32de014100..c69e31cc51 100644 --- a/src/data/floor_registry.ts +++ b/src/data/floor_registry.ts @@ -1,16 +1,16 @@ import { Connection, createCollection } from "home-assistant-js-websocket"; import { Store } from "home-assistant-js-websocket/dist/store"; import { stringCompare } from "../common/string/compare"; +import { debounce } from "../common/util/debounce"; import { HomeAssistant } from "../types"; import { AreaRegistryEntry } from "./area_registry"; -import { debounce } from "../common/util/debounce"; export { subscribeAreaRegistry } from "./ws-area_registry"; export interface FloorRegistryEntry { floor_id: string; name: string; - level: number; + level: number | null; icon: string | null; aliases: string[]; } diff --git a/src/panels/config/areas/dialog-floor-registry-detail.ts b/src/panels/config/areas/dialog-floor-registry-detail.ts index eabd0c03b2..421c996b0c 100644 --- a/src/panels/config/areas/dialog-floor-registry-detail.ts +++ b/src/panels/config/areas/dialog-floor-registry-detail.ts @@ -6,10 +6,11 @@ import { fireEvent } from "../../../common/dom/fire_event"; import "../../../components/ha-alert"; import "../../../components/ha-aliases-editor"; import { createCloseHeading } from "../../../components/ha-dialog"; +import "../../../components/ha-icon-picker"; import "../../../components/ha-picture-upload"; import "../../../components/ha-settings-row"; +import "../../../components/ha-svg-icon"; import "../../../components/ha-textfield"; -import "../../../components/ha-icon-picker"; import { FloorRegistryEntryMutableParams } from "../../../data/floor_registry"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; @@ -56,6 +57,7 @@ class DialogFloorDetail extends LitElement { } const entry = this._params.entry; const nameInvalid = !this._isNameValid(); + return html` + > + ${!this._icon + ? html` + + ` + : nothing} +

${this.hass.localize( @@ -157,7 +168,7 @@ class DialogFloorDetail extends LitElement { private _levelChanged(ev) { this._error = undefined; - this._level = Number(ev.target.value); + this._level = ev.target.value === "" ? null : Number(ev.target.value); } private _iconChanged(ev) { diff --git a/src/panels/config/areas/ha-config-areas-dashboard.ts b/src/panels/config/areas/ha-config-areas-dashboard.ts index 02e96bc9c2..e322274d34 100644 --- a/src/panels/config/areas/ha-config-areas-dashboard.ts +++ b/src/panels/config/areas/ha-config-areas-dashboard.ts @@ -1,3 +1,4 @@ +import { ActionDetail } from "@material/mwc-list"; import { mdiDelete, mdiDotsVertical, @@ -17,9 +18,9 @@ import { import { customElement, property, state } from "lit/decorators"; import { styleMap } from "lit/directives/style-map"; import memoizeOne from "memoize-one"; -import { ActionDetail } from "@material/mwc-list"; import { formatListWithAnds } from "../../../common/string/format-list"; import "../../../components/ha-fab"; +import "../../../components/ha-floor-icon"; import "../../../components/ha-icon-button"; import "../../../components/ha-svg-icon"; import { @@ -39,6 +40,7 @@ import { showConfirmationDialog, } from "../../../dialogs/generic/show-dialog-box"; import "../../../layouts/hass-tabs-subpage"; +import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; import { HomeAssistant, Route } from "../../../types"; import "../ha-config-section"; import { configSections } from "../ha-panel-config"; @@ -47,7 +49,6 @@ import { showAreaRegistryDetailDialog, } from "./show-dialog-area-registry-detail"; import { showFloorRegistryDetailDialog } from "./show-dialog-floor-registry-detail"; -import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; @customElement("ha-config-areas-dashboard") export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { @@ -154,9 +155,7 @@ export class HaConfigAreasDashboard extends SubscribeMixin(LitElement) { html`

- ${floor.icon - ? html`` - : nothing} + ${floor.name}