mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Allow to re-order floors in areas dashboard (#26002)
* Allow to re-order floors in areas dashboard * Move drag handle to right * Improve typings * Only show drag handle if there is at least 2 floors
This commit is contained in:
parent
8cc762d839
commit
0fbd430594
@ -1,14 +1,15 @@
|
|||||||
import { mdiTextureBox } from "@mdi/js";
|
import { mdiDrag, mdiTextureBox } from "@mdi/js";
|
||||||
import type { TemplateResult } from "lit";
|
import type { TemplateResult } from "lit";
|
||||||
import { LitElement, css, html, nothing } from "lit";
|
import { LitElement, css, html, nothing } from "lit";
|
||||||
import { customElement, property } from "lit/decorators";
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { repeat } from "lit/directives/repeat";
|
||||||
import memoizeOne from "memoize-one";
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../common/dom/fire_event";
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
import { computeFloorName } from "../common/entity/compute_floor_name";
|
import { computeFloorName } from "../common/entity/compute_floor_name";
|
||||||
import { getAreaContext } from "../common/entity/context/get_area_context";
|
import { getAreaContext } from "../common/entity/context/get_area_context";
|
||||||
import { stringCompare } from "../common/string/compare";
|
|
||||||
import { areaCompare } from "../data/area_registry";
|
import { areaCompare } from "../data/area_registry";
|
||||||
import type { FloorRegistryEntry } from "../data/floor_registry";
|
import type { FloorRegistryEntry } from "../data/floor_registry";
|
||||||
|
import { getFloors } from "../panels/lovelace/strategies/areas/helpers/areas-strategy-helper";
|
||||||
import type { HomeAssistant } from "../types";
|
import type { HomeAssistant } from "../types";
|
||||||
import "./ha-expansion-panel";
|
import "./ha-expansion-panel";
|
||||||
import "./ha-floor-icon";
|
import "./ha-floor-icon";
|
||||||
@ -17,9 +18,14 @@ import type { DisplayItem, DisplayValue } from "./ha-items-display-editor";
|
|||||||
import "./ha-svg-icon";
|
import "./ha-svg-icon";
|
||||||
import "./ha-textfield";
|
import "./ha-textfield";
|
||||||
|
|
||||||
export interface AreasDisplayValue {
|
export interface AreasFloorsDisplayValue {
|
||||||
|
areas_display?: {
|
||||||
hidden?: string[];
|
hidden?: string[];
|
||||||
order?: string[];
|
order?: string[];
|
||||||
|
};
|
||||||
|
floors_display?: {
|
||||||
|
order?: string[];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const UNASSIGNED_FLOOR = "__unassigned__";
|
const UNASSIGNED_FLOOR = "__unassigned__";
|
||||||
@ -30,12 +36,10 @@ export class HaAreasFloorsDisplayEditor extends LitElement {
|
|||||||
|
|
||||||
@property() public label?: string;
|
@property() public label?: string;
|
||||||
|
|
||||||
@property({ attribute: false }) public value?: AreasDisplayValue;
|
@property({ attribute: false }) public value?: AreasFloorsDisplayValue;
|
||||||
|
|
||||||
@property() public helper?: string;
|
@property() public helper?: string;
|
||||||
|
|
||||||
@property({ type: Boolean }) public expanded = false;
|
|
||||||
|
|
||||||
@property({ type: Boolean }) public disabled = false;
|
@property({ type: Boolean }) public disabled = false;
|
||||||
|
|
||||||
@property({ type: Boolean }) public required = false;
|
@property({ type: Boolean }) public required = false;
|
||||||
@ -44,55 +48,78 @@ export class HaAreasFloorsDisplayEditor extends LitElement {
|
|||||||
public showNavigationButton = false;
|
public showNavigationButton = false;
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
const groupedItems = this._groupedItems(this.hass.areas, this.hass.floors);
|
const groupedAreasItems = this._groupedAreasItems(
|
||||||
|
this.hass.areas,
|
||||||
|
this.hass.floors
|
||||||
|
);
|
||||||
|
|
||||||
const filteredFloors = this._sortedFloors(this.hass.floors).filter(
|
const filteredFloors = this._sortedFloors(
|
||||||
|
this.hass.floors,
|
||||||
|
this.value?.floors_display?.order
|
||||||
|
).filter(
|
||||||
(floor) =>
|
(floor) =>
|
||||||
// Only include floors that have areas assigned to them
|
// Only include floors that have areas assigned to them
|
||||||
groupedItems[floor.floor_id]?.length > 0
|
groupedAreasItems[floor.floor_id]?.length > 0
|
||||||
);
|
);
|
||||||
|
|
||||||
const value: DisplayValue = {
|
const value: DisplayValue = {
|
||||||
order: this.value?.order ?? [],
|
order: this.value?.areas_display?.order ?? [],
|
||||||
hidden: this.value?.hidden ?? [],
|
hidden: this.value?.areas_display?.hidden ?? [],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const canReorderFloors =
|
||||||
|
filteredFloors.filter((floor) => floor.floor_id !== UNASSIGNED_FLOOR)
|
||||||
|
.length > 1;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
|
${this.label ? html`<label>${this.label}</label>` : nothing}
|
||||||
|
<ha-sortable
|
||||||
|
draggable-selector=".draggable"
|
||||||
|
handle-selector=".handle"
|
||||||
|
@item-moved=${this._floorMoved}
|
||||||
|
.disabled=${this.disabled || !canReorderFloors}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
${repeat(
|
||||||
|
filteredFloors,
|
||||||
|
(floor) => floor.floor_id,
|
||||||
|
(floor: FloorRegistryEntry) => html`
|
||||||
<ha-expansion-panel
|
<ha-expansion-panel
|
||||||
outlined
|
outlined
|
||||||
.header=${this.label}
|
.header=${computeFloorName(floor)}
|
||||||
.expanded=${this.expanded}
|
left-chevron
|
||||||
|
class=${floor.floor_id === UNASSIGNED_FLOOR ? "" : "draggable"}
|
||||||
>
|
>
|
||||||
<ha-svg-icon slot="leading-icon" .path=${mdiTextureBox}></ha-svg-icon>
|
<ha-floor-icon
|
||||||
${filteredFloors.map((floor, _, array) => {
|
slot="leading-icon"
|
||||||
const noFloors =
|
.floor=${floor}
|
||||||
array.length === 1 && floor.floor_id === UNASSIGNED_FLOOR;
|
></ha-floor-icon>
|
||||||
return html`
|
${floor.floor_id === UNASSIGNED_FLOOR || !canReorderFloors
|
||||||
<div class="floor">
|
|
||||||
${noFloors
|
|
||||||
? nothing
|
? nothing
|
||||||
: html`<div class="header">
|
: html`
|
||||||
<ha-floor-icon .floor=${floor}></ha-floor-icon>
|
<ha-svg-icon
|
||||||
<p>${computeFloorName(floor)}</p>
|
class="handle"
|
||||||
</div>`}
|
slot="icons"
|
||||||
<div class="areas">
|
.path=${mdiDrag}
|
||||||
|
></ha-svg-icon>
|
||||||
|
`}
|
||||||
<ha-items-display-editor
|
<ha-items-display-editor
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.items=${groupedItems[floor.floor_id] || []}
|
.items=${groupedAreasItems[floor.floor_id]}
|
||||||
.value=${value}
|
.value=${value}
|
||||||
.floorId=${floor.floor_id ?? UNASSIGNED_FLOOR}
|
.floorId=${floor.floor_id}
|
||||||
@value-changed=${this._areaDisplayChanged}
|
@value-changed=${this._areaDisplayChanged}
|
||||||
.showNavigationButton=${this.showNavigationButton}
|
.showNavigationButton=${this.showNavigationButton}
|
||||||
></ha-items-display-editor>
|
></ha-items-display-editor>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
})}
|
|
||||||
</ha-expansion-panel>
|
</ha-expansion-panel>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ha-sortable>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _groupedItems = memoizeOne(
|
private _groupedAreasItems = memoizeOne(
|
||||||
(
|
(
|
||||||
hassAreas: HomeAssistant["areas"],
|
hassAreas: HomeAssistant["areas"],
|
||||||
// update items if floors change
|
// update items if floors change
|
||||||
@ -116,7 +143,6 @@ export class HaAreasFloorsDisplayEditor extends LitElement {
|
|||||||
label: area.name,
|
label: area.name,
|
||||||
icon: area.icon ?? undefined,
|
icon: area.icon ?? undefined,
|
||||||
iconPath: mdiTextureBox,
|
iconPath: mdiTextureBox,
|
||||||
description: floor?.name,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
@ -128,18 +154,17 @@ export class HaAreasFloorsDisplayEditor extends LitElement {
|
|||||||
);
|
);
|
||||||
|
|
||||||
private _sortedFloors = memoizeOne(
|
private _sortedFloors = memoizeOne(
|
||||||
(hassFloors: HomeAssistant["floors"]): FloorRegistryEntry[] => {
|
(
|
||||||
const floors = Object.values(hassFloors).sort((floorA, floorB) => {
|
hassFloors: HomeAssistant["floors"],
|
||||||
if (floorA.level !== floorB.level) {
|
order: string[] | undefined
|
||||||
return (floorA.level ?? 0) - (floorB.level ?? 0);
|
): FloorRegistryEntry[] => {
|
||||||
}
|
const floors = getFloors(hassFloors, order);
|
||||||
return stringCompare(floorA.name, floorB.name);
|
const noFloors = floors.length === 0;
|
||||||
});
|
|
||||||
floors.push({
|
floors.push({
|
||||||
floor_id: UNASSIGNED_FLOOR,
|
floor_id: UNASSIGNED_FLOOR,
|
||||||
name: this.hass.localize(
|
name: noFloors
|
||||||
"ui.panel.lovelace.strategy.areas.others_areas"
|
? this.hass.localize("ui.panel.lovelace.strategy.areas.areas")
|
||||||
),
|
: this.hass.localize("ui.panel.lovelace.strategy.areas.other_areas"),
|
||||||
icon: null,
|
icon: null,
|
||||||
level: null,
|
level: null,
|
||||||
aliases: [],
|
aliases: [],
|
||||||
@ -150,17 +175,43 @@ export class HaAreasFloorsDisplayEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
private async _areaDisplayChanged(ev) {
|
private _floorMoved(ev: CustomEvent<HASSDomEvents["item-moved"]>) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
const value = ev.detail.value as DisplayValue;
|
const newIndex = ev.detail.newIndex;
|
||||||
const currentFloorId = ev.currentTarget.floorId;
|
const oldIndex = ev.detail.oldIndex;
|
||||||
|
const floorIds = this._sortedFloors(
|
||||||
|
this.hass.floors,
|
||||||
|
this.value?.floors_display?.order
|
||||||
|
).map((floor) => floor.floor_id);
|
||||||
|
const newOrder = [...floorIds];
|
||||||
|
const movedFloorId = newOrder.splice(oldIndex, 1)[0];
|
||||||
|
newOrder.splice(newIndex, 0, movedFloorId);
|
||||||
|
const newValue: AreasFloorsDisplayValue = {
|
||||||
|
areas_display: this.value?.areas_display,
|
||||||
|
floors_display: {
|
||||||
|
order: newOrder,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if (newValue.floors_display?.order?.length === 0) {
|
||||||
|
delete newValue.floors_display.order;
|
||||||
|
}
|
||||||
|
fireEvent(this, "value-changed", { value: newValue });
|
||||||
|
}
|
||||||
|
|
||||||
const floorIds = this._sortedFloors(this.hass.floors).map(
|
private async _areaDisplayChanged(ev: CustomEvent<{ value: DisplayValue }>) {
|
||||||
(floor) => floor.floor_id
|
ev.stopPropagation();
|
||||||
);
|
const value = ev.detail.value;
|
||||||
|
const currentFloorId = (ev.currentTarget as any).floorId;
|
||||||
|
|
||||||
const oldHidden = this.value?.hidden ?? [];
|
const floorIds = this._sortedFloors(
|
||||||
const oldOrder = this.value?.order ?? [];
|
this.hass.floors,
|
||||||
|
this.value?.floors_display?.order
|
||||||
|
).map((floor) => floor.floor_id);
|
||||||
|
|
||||||
|
const oldAreaDisplay = this.value?.areas_display ?? {};
|
||||||
|
|
||||||
|
const oldHidden = oldAreaDisplay?.hidden ?? [];
|
||||||
|
const oldOrder = oldAreaDisplay?.order ?? [];
|
||||||
|
|
||||||
const newHidden: string[] = [];
|
const newHidden: string[] = [];
|
||||||
const newOrder: string[] = [];
|
const newOrder: string[] = [];
|
||||||
@ -187,37 +238,27 @@ export class HaAreasFloorsDisplayEditor extends LitElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newValue: AreasDisplayValue = {
|
const newValue: AreasFloorsDisplayValue = {
|
||||||
|
areas_display: {
|
||||||
hidden: newHidden,
|
hidden: newHidden,
|
||||||
order: newOrder,
|
order: newOrder,
|
||||||
|
},
|
||||||
|
floors_display: this.value?.floors_display,
|
||||||
};
|
};
|
||||||
if (newValue.hidden?.length === 0) {
|
if (newValue.areas_display?.hidden?.length === 0) {
|
||||||
delete newValue.hidden;
|
delete newValue.areas_display.hidden;
|
||||||
}
|
}
|
||||||
if (newValue.order?.length === 0) {
|
if (newValue.areas_display?.order?.length === 0) {
|
||||||
delete newValue.order;
|
delete newValue.areas_display.order;
|
||||||
}
|
}
|
||||||
this.value = newValue;
|
if (newValue.floors_display?.order?.length === 0) {
|
||||||
|
delete newValue.floors_display.order;
|
||||||
|
}
|
||||||
|
|
||||||
fireEvent(this, "value-changed", { value: newValue });
|
fireEvent(this, "value-changed", { value: newValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
static styles = css`
|
static styles = css`
|
||||||
.floor .header p {
|
|
||||||
margin: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.floor .header {
|
|
||||||
margin: 16px 0 8px 0;
|
|
||||||
padding: 0 8px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
ha-expansion-panel {
|
ha-expansion-panel {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
--expansion-panel-summary-padding: 0 16px;
|
--expansion-panel-summary-padding: 0 16px;
|
||||||
@ -225,6 +266,11 @@ export class HaAreasFloorsDisplayEditor extends LitElement {
|
|||||||
ha-expansion-panel [slot="leading-icon"] {
|
ha-expansion-panel [slot="leading-icon"] {
|
||||||
margin-inline-end: 16px;
|
margin-inline-end: 16px;
|
||||||
}
|
}
|
||||||
|
label {
|
||||||
|
display: block;
|
||||||
|
font-weight: var(--ha-font-weight-bold);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,22 +122,6 @@ export class HaItemDisplayEditor extends LitElement {
|
|||||||
${description
|
${description
|
||||||
? html`<span slot="supporting-text">${description}</span>`
|
? html`<span slot="supporting-text">${description}</span>`
|
||||||
: nothing}
|
: nothing}
|
||||||
${isVisible && !disableSorting
|
|
||||||
? html`
|
|
||||||
<ha-svg-icon
|
|
||||||
tabindex=${ifDefined(
|
|
||||||
this.showNavigationButton ? "0" : undefined
|
|
||||||
)}
|
|
||||||
.idx=${idx}
|
|
||||||
@keydown=${this.showNavigationButton
|
|
||||||
? this._dragHandleKeydown
|
|
||||||
: undefined}
|
|
||||||
class="handle"
|
|
||||||
.path=${mdiDrag}
|
|
||||||
slot="start"
|
|
||||||
></ha-svg-icon>
|
|
||||||
`
|
|
||||||
: html`<ha-svg-icon slot="start"></ha-svg-icon>`}
|
|
||||||
${!showIcon
|
${!showIcon
|
||||||
? nothing
|
? nothing
|
||||||
: icon
|
: icon
|
||||||
@ -162,6 +146,9 @@ export class HaItemDisplayEditor extends LitElement {
|
|||||||
<span slot="end"> ${this.actionsRenderer(item)} </span>
|
<span slot="end"> ${this.actionsRenderer(item)} </span>
|
||||||
`
|
`
|
||||||
: nothing}
|
: nothing}
|
||||||
|
${this.showNavigationButton
|
||||||
|
? html`<ha-icon-next slot="end"></ha-icon-next>`
|
||||||
|
: nothing}
|
||||||
<ha-icon-button
|
<ha-icon-button
|
||||||
.path=${isVisible ? mdiEye : mdiEyeOff}
|
.path=${isVisible ? mdiEye : mdiEyeOff}
|
||||||
slot="end"
|
slot="end"
|
||||||
@ -174,9 +161,22 @@ export class HaItemDisplayEditor extends LitElement {
|
|||||||
.value=${value}
|
.value=${value}
|
||||||
@click=${this._toggle}
|
@click=${this._toggle}
|
||||||
></ha-icon-button>
|
></ha-icon-button>
|
||||||
${this.showNavigationButton
|
${isVisible && !disableSorting
|
||||||
? html` <ha-icon-next slot="end"></ha-icon-next> `
|
? html`
|
||||||
: nothing}
|
<ha-svg-icon
|
||||||
|
tabindex=${ifDefined(
|
||||||
|
this.showNavigationButton ? "0" : undefined
|
||||||
|
)}
|
||||||
|
.idx=${idx}
|
||||||
|
@keydown=${this.showNavigationButton
|
||||||
|
? this._dragHandleKeydown
|
||||||
|
: undefined}
|
||||||
|
class="handle"
|
||||||
|
.path=${mdiDrag}
|
||||||
|
slot="end"
|
||||||
|
></ha-svg-icon>
|
||||||
|
`
|
||||||
|
: html`<ha-svg-icon slot="end"></ha-svg-icon>`}
|
||||||
</ha-md-list-item>
|
</ha-md-list-item>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,9 @@ export interface AreasDashboardStrategyConfig {
|
|||||||
hidden?: string[];
|
hidden?: string[];
|
||||||
order?: string[];
|
order?: string[];
|
||||||
};
|
};
|
||||||
|
floors_display?: {
|
||||||
|
order?: string[];
|
||||||
|
};
|
||||||
areas_options?: Record<string, AreaOptions>;
|
areas_options?: Record<string, AreaOptions>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,6 +87,7 @@ export class AreasDashboardStrategy extends ReactiveElement {
|
|||||||
type: "areas-overview",
|
type: "areas-overview",
|
||||||
areas_display: config.areas_display,
|
areas_display: config.areas_display,
|
||||||
areas_options: config.areas_options,
|
areas_options: config.areas_options,
|
||||||
|
floors_display: config.floors_display,
|
||||||
} satisfies AreasViewStrategyConfig,
|
} satisfies AreasViewStrategyConfig,
|
||||||
},
|
},
|
||||||
...areaViews,
|
...areaViews,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ReactiveElement } from "lit";
|
import { ReactiveElement } from "lit";
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import { stringCompare } from "../../../../common/string/compare";
|
|
||||||
import { floorDefaultIcon } from "../../../../components/ha-floor-icon";
|
import { floorDefaultIcon } from "../../../../components/ha-floor-icon";
|
||||||
import type { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
import type { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
||||||
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
import type { LovelaceViewConfig } from "../../../../data/lovelace/config/view";
|
||||||
@ -9,7 +8,11 @@ import { getAreaControlEntities } from "../../card-features/hui-area-controls-ca
|
|||||||
import { AREA_CONTROLS, type AreaControl } from "../../card-features/types";
|
import { AREA_CONTROLS, type AreaControl } from "../../card-features/types";
|
||||||
import type { AreaCardConfig, HeadingCardConfig } from "../../cards/types";
|
import type { AreaCardConfig, HeadingCardConfig } from "../../cards/types";
|
||||||
import type { EntitiesDisplay } from "./area-view-strategy";
|
import type { EntitiesDisplay } from "./area-view-strategy";
|
||||||
import { computeAreaPath, getAreas } from "./helpers/areas-strategy-helper";
|
import {
|
||||||
|
computeAreaPath,
|
||||||
|
getAreas,
|
||||||
|
getFloors,
|
||||||
|
} from "./helpers/areas-strategy-helper";
|
||||||
|
|
||||||
const UNASSIGNED_FLOOR = "__unassigned__";
|
const UNASSIGNED_FLOOR = "__unassigned__";
|
||||||
|
|
||||||
@ -23,6 +26,9 @@ export interface AreasViewStrategyConfig {
|
|||||||
hidden?: string[];
|
hidden?: string[];
|
||||||
order?: string[];
|
order?: string[];
|
||||||
};
|
};
|
||||||
|
floors_display?: {
|
||||||
|
order?: string[];
|
||||||
|
};
|
||||||
areas_options?: Record<string, AreaOptions>;
|
areas_options?: Record<string, AreaOptions>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,19 +44,13 @@ export class AreasOverviewViewStrategy extends ReactiveElement {
|
|||||||
config.areas_display?.order
|
config.areas_display?.order
|
||||||
);
|
);
|
||||||
|
|
||||||
const floors = Object.values(hass.floors);
|
const floors = getFloors(hass.floors, config.floors_display?.order);
|
||||||
floors.sort((floorA, floorB) => {
|
|
||||||
if (floorA.level !== floorB.level) {
|
|
||||||
return (floorA.level ?? 0) - (floorB.level ?? 0);
|
|
||||||
}
|
|
||||||
return stringCompare(floorA.name, floorB.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
const floorSections = [
|
const floorSections = [
|
||||||
...floors,
|
...floors,
|
||||||
{
|
{
|
||||||
floor_id: UNASSIGNED_FLOOR,
|
floor_id: UNASSIGNED_FLOOR,
|
||||||
name: hass.localize("ui.panel.lovelace.strategy.areas.others_areas"),
|
name: hass.localize("ui.panel.lovelace.strategy.areas.other_areas"),
|
||||||
level: null,
|
level: null,
|
||||||
icon: null,
|
icon: null,
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { mdiThermometerWater } from "@mdi/js";
|
import { mdiThermometerWater } from "@mdi/js";
|
||||||
import { css, html, LitElement, nothing } from "lit";
|
import { css, html, LitElement, nothing } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
import { fireEvent } from "../../../../../common/dom/fire_event";
|
import { fireEvent } from "../../../../../common/dom/fire_event";
|
||||||
import "../../../../../components/ha-areas-display-editor";
|
import "../../../../../components/ha-areas-display-editor";
|
||||||
import type { AreasDisplayValue } from "../../../../../components/ha-areas-display-editor";
|
import type { AreasDisplayValue } from "../../../../../components/ha-areas-display-editor";
|
||||||
import "../../../../../components/ha-areas-floors-display-editor";
|
import "../../../../../components/ha-areas-floors-display-editor";
|
||||||
|
import type { AreasFloorsDisplayValue } from "../../../../../components/ha-areas-floors-display-editor";
|
||||||
import "../../../../../components/ha-entities-display-editor";
|
import "../../../../../components/ha-entities-display-editor";
|
||||||
import "../../../../../components/ha-icon";
|
import "../../../../../components/ha-icon";
|
||||||
import "../../../../../components/ha-icon-button";
|
import "../../../../../components/ha-icon-button";
|
||||||
@ -126,7 +128,7 @@ export class HuiAreasDashboardStrategyEditor
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = this._config.areas_display;
|
const value = this._areasFloorsDisplayValue(this._config);
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<ha-areas-floors-display-editor
|
<ha-areas-floors-display-editor
|
||||||
@ -135,7 +137,7 @@ export class HuiAreasDashboardStrategyEditor
|
|||||||
.label=${this.hass.localize(
|
.label=${this.hass.localize(
|
||||||
"ui.panel.lovelace.editor.strategy.areas.areas_display"
|
"ui.panel.lovelace.editor.strategy.areas.areas_display"
|
||||||
)}
|
)}
|
||||||
@value-changed=${this._areasDisplayChanged}
|
@value-changed=${this._areasFloorsDisplayChanged}
|
||||||
expanded
|
expanded
|
||||||
show-navigation-button
|
show-navigation-button
|
||||||
@item-display-navigate-clicked=${this._handleAreaNavigate}
|
@item-display-navigate-clicked=${this._handleAreaNavigate}
|
||||||
@ -149,6 +151,13 @@ export class HuiAreasDashboardStrategyEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _areasFloorsDisplayValue = memoizeOne(
|
||||||
|
(config: AreasDashboardStrategyConfig): AreasFloorsDisplayValue => ({
|
||||||
|
areas_display: config.areas_display,
|
||||||
|
floors_display: config.floors_display,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
private _editArea(ev: Event): void {
|
private _editArea(ev: Event): void {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
const area = (ev.currentTarget! as any).area as AreaRegistryEntry;
|
const area = (ev.currentTarget! as any).area as AreaRegistryEntry;
|
||||||
@ -163,11 +172,11 @@ export class HuiAreasDashboardStrategyEditor
|
|||||||
this._area = ev.detail.value;
|
this._area = ev.detail.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _areasDisplayChanged(ev: CustomEvent): void {
|
private _areasFloorsDisplayChanged(ev: CustomEvent): void {
|
||||||
const value = ev.detail.value as AreasDisplayValue;
|
const value = ev.detail.value as AreasFloorsDisplayValue;
|
||||||
const newConfig: AreasDashboardStrategyConfig = {
|
const newConfig: AreasDashboardStrategyConfig = {
|
||||||
...this._config!,
|
...this._config!,
|
||||||
areas_display: value,
|
...value,
|
||||||
};
|
};
|
||||||
|
|
||||||
fireEvent(this, "config-changed", { config: newConfig });
|
fireEvent(this, "config-changed", { config: newConfig });
|
||||||
|
@ -3,9 +3,13 @@ import { computeStateName } from "../../../../../common/entity/compute_state_nam
|
|||||||
import type { EntityFilterFunc } from "../../../../../common/entity/entity_filter";
|
import type { EntityFilterFunc } from "../../../../../common/entity/entity_filter";
|
||||||
import { generateEntityFilter } from "../../../../../common/entity/entity_filter";
|
import { generateEntityFilter } from "../../../../../common/entity/entity_filter";
|
||||||
import { stripPrefixFromEntityName } from "../../../../../common/entity/strip_prefix_from_entity_name";
|
import { stripPrefixFromEntityName } from "../../../../../common/entity/strip_prefix_from_entity_name";
|
||||||
import { orderCompare } from "../../../../../common/string/compare";
|
import {
|
||||||
|
orderCompare,
|
||||||
|
stringCompare,
|
||||||
|
} from "../../../../../common/string/compare";
|
||||||
import type { AreaRegistryEntry } from "../../../../../data/area_registry";
|
import type { AreaRegistryEntry } from "../../../../../data/area_registry";
|
||||||
import { areaCompare } from "../../../../../data/area_registry";
|
import { areaCompare } from "../../../../../data/area_registry";
|
||||||
|
import type { FloorRegistryEntry } from "../../../../../data/floor_registry";
|
||||||
import type { LovelaceCardConfig } from "../../../../../data/lovelace/config/card";
|
import type { LovelaceCardConfig } from "../../../../../data/lovelace/config/card";
|
||||||
import type { HomeAssistant } from "../../../../../types";
|
import type { HomeAssistant } from "../../../../../types";
|
||||||
import { supportsAlarmModesCardFeature } from "../../../card-features/hui-alarm-modes-card-feature";
|
import { supportsAlarmModesCardFeature } from "../../../card-features/hui-alarm-modes-card-feature";
|
||||||
@ -290,4 +294,23 @@ export const getAreas = (
|
|||||||
return sortedAreas;
|
return sortedAreas;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getFloors = (
|
||||||
|
entries: HomeAssistant["floors"],
|
||||||
|
floorsOrder?: string[]
|
||||||
|
): FloorRegistryEntry[] => {
|
||||||
|
const floors = Object.values(entries);
|
||||||
|
const compare = orderCompare(floorsOrder || []);
|
||||||
|
|
||||||
|
return floors.sort((floorA, floorB) => {
|
||||||
|
const order = compare(floorA.floor_id, floorB.floor_id);
|
||||||
|
if (order !== 0) {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
if (floorA.level !== floorB.level) {
|
||||||
|
return (floorA.level ?? 0) - (floorB.level ?? 0);
|
||||||
|
}
|
||||||
|
return stringCompare(floorA.name, floorB.name);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const computeAreaPath = (areaId: string): string => `areas-${areaId}`;
|
export const computeAreaPath = (areaId: string): string => `areas-${areaId}`;
|
||||||
|
@ -6686,7 +6686,7 @@
|
|||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
"others": "Others"
|
"others": "Others"
|
||||||
},
|
},
|
||||||
"others_areas": "Other areas",
|
"other_areas": "Other areas",
|
||||||
"areas": "Areas"
|
"areas": "Areas"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user