Skip to content

Commit

Permalink
Add area filter selector for default dashboard (#18779)
Browse files Browse the repository at this point in the history
Co-authored-by: Bram Kragten <[email protected]>
  • Loading branch information
piitaya and bramkragten authored Nov 28, 2023
1 parent 9b20e1c commit 7727f34
Show file tree
Hide file tree
Showing 11 changed files with 444 additions and 60 deletions.
96 changes: 96 additions & 0 deletions src/components/ha-area-filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { mdiChevronRight, mdiSofa } 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-svg-icon";
import "./ha-textfield";

export type AreaFilterValue = {
hidden?: string[];
order?: string[];
};

@customElement("ha-area-filter")
export class HaAreaPicker extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;

@property() public label?: string;

@property({ attribute: false }) public value?: AreaFilterValue;

@property() public helper?: string;

@property({ type: Boolean }) public disabled = false;

@property({ type: Boolean }) public required = false;

protected render(): TemplateResult {
const allAreasCount = Object.keys(this.hass.areas).length;
const hiddenAreasCount = this.value?.hidden?.length ?? 0;

const description =
hiddenAreasCount === 0
? this.hass.localize("ui.components.area-filter.all_areas")
: allAreasCount === hiddenAreasCount
? this.hass.localize("ui.components.area-filter.no_areas")
: this.hass.localize("ui.components.area-filter.area_count", {
count: allAreasCount - hiddenAreasCount,
});

return html`
<ha-list-item
tabindex="0"
role="button"
hasMeta
twoline
graphic="icon"
@click=${this._edit}
@keydown=${this._edit}
.disabled=${this.disabled}
>
<ha-svg-icon slot="graphic" .path=${mdiSofa}></ha-svg-icon>
<span>${this.label}</span>
<span slot="secondary">${description}</span>
<ha-svg-icon
slot="meta"
.label=${this.hass.localize("ui.common.edit")}
.path=${mdiChevronRight}
></ha-svg-icon>
</ha-list-item>
`;
}

private async _edit(ev) {
if (ev.defaultPrevented) {
return;
}
if (ev.type === "keydown" && ev.key !== "Enter" && ev.key !== " ") {
return;
}
ev.preventDefault();
ev.stopPropagation();
const value = await showAreaFilterDialog(this, {
title: this.label,
initialValue: this.value,
});
if (!value) return;
fireEvent(this, "value-changed", { value });
}

static get styles(): CSSResultGroup {
return css`
ha-list-item {
--mdc-list-side-padding-left: 8px;
--mdc-list-side-padding-right: 8px;
}
`;
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-area-filter": HaAreaPicker;
}
}
41 changes: 41 additions & 0 deletions src/components/ha-selector/ha-selector-area-filter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { LitElement, html } from "lit";
import { customElement, property } from "lit/decorators";
import type { AreaFilterSelector } from "../../data/selector";
import { HomeAssistant } from "../../types";
import "../ha-area-filter";

@customElement("ha-selector-area_filter")
export class HaAreaFilterSelector extends LitElement {
@property() public hass!: HomeAssistant;

@property() public selector!: AreaFilterSelector;

@property() public value?: any;

@property() public label?: string;

@property() public helper?: string;

@property({ type: Boolean }) public disabled = false;

@property({ type: Boolean }) public required = true;

protected render() {
return html`
<ha-area-filter
.hass=${this.hass}
.value=${this.value}
.label=${this.label}
.helper=${this.helper}
.disabled=${this.disabled}
.required=${this.required}
></ha-area-filter>
`;
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-selector-area_filter": HaAreaFilterSelector;
}
}
1 change: 1 addition & 0 deletions src/components/ha-selector/ha-selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const LOAD_ELEMENTS = {
action: () => import("./ha-selector-action"),
addon: () => import("./ha-selector-addon"),
area: () => import("./ha-selector-area"),
area_filter: () => import("./ha-selector-area-filter"),
attribute: () => import("./ha-selector-attribute"),
assist_pipeline: () => import("./ha-selector-assist-pipeline"),
boolean: () => import("./ha-selector-boolean"),
Expand Down
19 changes: 19 additions & 0 deletions src/data/area_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,22 @@ export const getAreaDeviceLookup = (
}
return areaDeviceLookup;
};

export const areaCompare =
(entries?: HomeAssistant["areas"], order?: string[]) =>
(a: string, b: string) => {
const indexA = order ? order.indexOf(a) : -1;
const indexB = order ? order.indexOf(b) : 1;
if (indexA === -1 && indexB === -1) {
const nameA = entries?.[a].name ?? a;
const nameB = entries?.[b].name ?? b;
return stringCompare(nameA, nameB);
}
if (indexA === -1) {
return 1;
}
if (indexB === -1) {
return -1;
}
return indexA - indexB;
};
6 changes: 6 additions & 0 deletions src/data/selector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type Selector =
| ActionSelector
| AddonSelector
| AreaSelector
| AreaFilterSelector
| AttributeSelector
| BooleanSelector
| ColorRGBSelector
Expand Down Expand Up @@ -77,6 +78,11 @@ export interface AreaSelector {
} | null;
}

export interface AreaFilterSelector {
// eslint-disable-next-line @typescript-eslint/ban-types
area_filter: {} | null;
}

export interface AttributeSelector {
attribute: {
entity_id?: string;
Expand Down
Loading

0 comments on commit 7727f34

Please sign in to comment.