mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 17:26:42 +00:00
Add Area Multiple Selector option (#12138)
This commit is contained in:
parent
d30e8ee9d8
commit
b080bca9ce
@ -1,20 +1,20 @@
|
|||||||
/* eslint-disable lit/no-template-arrow */
|
/* eslint-disable lit/no-template-arrow */
|
||||||
import "@material/mwc-button";
|
import "@material/mwc-button";
|
||||||
import { LitElement, TemplateResult, css, html } from "lit";
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
import { customElement, state } from "lit/decorators";
|
import { customElement, state } from "lit/decorators";
|
||||||
|
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
||||||
|
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
||||||
|
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
||||||
|
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
||||||
import "../../../../src/components/ha-selector/ha-selector";
|
import "../../../../src/components/ha-selector/ha-selector";
|
||||||
import "../../../../src/components/ha-settings-row";
|
import "../../../../src/components/ha-settings-row";
|
||||||
|
import { BlueprintInput } from "../../../../src/data/blueprint";
|
||||||
|
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
||||||
|
import { getEntity } from "../../../../src/fake_data/entity";
|
||||||
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
import { provideHass } from "../../../../src/fake_data/provide_hass";
|
||||||
|
import { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin";
|
||||||
import type { HomeAssistant } from "../../../../src/types";
|
import type { HomeAssistant } from "../../../../src/types";
|
||||||
import "../../components/demo-black-white-row";
|
import "../../components/demo-black-white-row";
|
||||||
import { BlueprintInput } from "../../../../src/data/blueprint";
|
|
||||||
import { mockEntityRegistry } from "../../../../demo/src/stubs/entity_registry";
|
|
||||||
import { mockDeviceRegistry } from "../../../../demo/src/stubs/device_registry";
|
|
||||||
import { mockAreaRegistry } from "../../../../demo/src/stubs/area_registry";
|
|
||||||
import { mockHassioSupervisor } from "../../../../demo/src/stubs/hassio_supervisor";
|
|
||||||
import { getEntity } from "../../../../src/fake_data/entity";
|
|
||||||
import { ProvideHassElement } from "../../../../src/mixins/provide-hass-lit-mixin";
|
|
||||||
import { showDialog } from "../../../../src/dialogs/make-dialog-manager";
|
|
||||||
|
|
||||||
const ENTITIES = [
|
const ENTITIES = [
|
||||||
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
getEntity("alarm_control_panel", "alarm", "disarmed", {
|
||||||
@ -202,6 +202,7 @@ const SCHEMAS: {
|
|||||||
input: {
|
input: {
|
||||||
entity: { name: "Entity", selector: { entity: { multiple: true } } },
|
entity: { name: "Entity", selector: { entity: { multiple: true } } },
|
||||||
device: { name: "Device", selector: { device: { multiple: true } } },
|
device: { name: "Device", selector: { device: { multiple: true } } },
|
||||||
|
area: { name: "Area", selector: { area: { multiple: true } } },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
160
src/components/ha-areas-picker.ts
Normal file
160
src/components/ha-areas-picker.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import { css, html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import type { EntityRegistryEntry } from "../data/entity_registry";
|
||||||
|
import { SubscribeMixin } from "../mixins/subscribe-mixin";
|
||||||
|
import type { HomeAssistant } from "../types";
|
||||||
|
import type { HaDevicePickerDeviceFilterFunc } from "./device/ha-device-picker";
|
||||||
|
import "./ha-area-picker";
|
||||||
|
|
||||||
|
@customElement("ha-areas-picker")
|
||||||
|
export class HaAreasPicker extends SubscribeMixin(LitElement) {
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@property() public value?: string[];
|
||||||
|
|
||||||
|
@property() public placeholder?: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean, attribute: "no-add" })
|
||||||
|
public noAdd?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show only areas with entities from specific domains.
|
||||||
|
* @type {Array}
|
||||||
|
* @attr include-domains
|
||||||
|
*/
|
||||||
|
@property({ type: Array, attribute: "include-domains" })
|
||||||
|
public includeDomains?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show no areas with entities of these domains.
|
||||||
|
* @type {Array}
|
||||||
|
* @attr exclude-domains
|
||||||
|
*/
|
||||||
|
@property({ type: Array, attribute: "exclude-domains" })
|
||||||
|
public excludeDomains?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show only areas with entities of these device classes.
|
||||||
|
* @type {Array}
|
||||||
|
* @attr include-device-classes
|
||||||
|
*/
|
||||||
|
@property({ type: Array, attribute: "include-device-classes" })
|
||||||
|
public includeDeviceClasses?: string[];
|
||||||
|
|
||||||
|
@property() public deviceFilter?: HaDevicePickerDeviceFilterFunc;
|
||||||
|
|
||||||
|
@property() public entityFilter?: (entity: EntityRegistryEntry) => boolean;
|
||||||
|
|
||||||
|
@property({ attribute: "picked-area-label" })
|
||||||
|
public pickedAreaLabel?: string;
|
||||||
|
|
||||||
|
@property({ attribute: "pick-area-label" })
|
||||||
|
public pickAreaLabel?: string;
|
||||||
|
|
||||||
|
@property({ type: Boolean }) public disabled?: boolean;
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (!this.hass) {
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentAreas = this._currentAreas;
|
||||||
|
return html`
|
||||||
|
${currentAreas.map(
|
||||||
|
(area) => html`
|
||||||
|
<div>
|
||||||
|
<ha-area-picker
|
||||||
|
.curValue=${area}
|
||||||
|
.noAdd=${this.noAdd}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${area}
|
||||||
|
.label=${this.pickedAreaLabel}
|
||||||
|
.includeDomains=${this.includeDomains}
|
||||||
|
.excludeDomains=${this.excludeDomains}
|
||||||
|
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||||
|
.deviceFilter=${this.deviceFilter}
|
||||||
|
.entityFilter=${this.entityFilter}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
@value-changed=${this._areaChanged}
|
||||||
|
></ha-area-picker>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
)}
|
||||||
|
<div>
|
||||||
|
<ha-area-picker
|
||||||
|
.noAdd=${this.noAdd}
|
||||||
|
.hass=${this.hass}
|
||||||
|
.label=${this.pickAreaLabel}
|
||||||
|
.includeDomains=${this.includeDomains}
|
||||||
|
.excludeDomains=${this.excludeDomains}
|
||||||
|
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||||
|
.deviceFilter=${this.deviceFilter}
|
||||||
|
.entityFilter=${this.entityFilter}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
.placeholder=${this.placeholder}
|
||||||
|
@value-changed=${this._addArea}
|
||||||
|
></ha-area-picker>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _currentAreas(): string[] {
|
||||||
|
return this.value || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _updateAreas(areas) {
|
||||||
|
this.value = areas;
|
||||||
|
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: areas,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _areaChanged(ev: CustomEvent) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
const curValue = (ev.currentTarget as any).curValue;
|
||||||
|
const newValue = ev.detail.value;
|
||||||
|
if (newValue === curValue) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const currentAreas = this._currentAreas;
|
||||||
|
if (!newValue || currentAreas.includes(newValue)) {
|
||||||
|
this._updateAreas(currentAreas.filter((ent) => ent !== curValue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._updateAreas(
|
||||||
|
currentAreas.map((ent) => (ent === curValue ? newValue : ent))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _addArea(ev: CustomEvent) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
|
||||||
|
const toAdd = ev.detail.value;
|
||||||
|
if (!toAdd) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(ev.currentTarget as any).value = "";
|
||||||
|
const currentAreas = this._currentAreas;
|
||||||
|
if (currentAreas.includes(toAdd)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateAreas([...currentAreas, toAdd]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static override styles = css`
|
||||||
|
div {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-areas-picker": HaAreasPicker;
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@ import { EntityRegistryEntry } from "../../data/entity_registry";
|
|||||||
import { AreaSelector } from "../../data/selector";
|
import { AreaSelector } from "../../data/selector";
|
||||||
import { HomeAssistant } from "../../types";
|
import { HomeAssistant } from "../../types";
|
||||||
import "../ha-area-picker";
|
import "../ha-area-picker";
|
||||||
|
import "../ha-areas-picker";
|
||||||
|
|
||||||
@customElement("ha-selector-area")
|
@customElement("ha-selector-area")
|
||||||
export class HaAreaSelector extends LitElement {
|
export class HaAreaSelector extends LitElement {
|
||||||
@ -38,7 +39,9 @@ export class HaAreaSelector extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html`<ha-area-picker
|
if (!this.selector.area.multiple) {
|
||||||
|
return html`
|
||||||
|
<ha-area-picker
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this.value}
|
.value=${this.value}
|
||||||
.label=${this.label}
|
.label=${this.label}
|
||||||
@ -52,7 +55,27 @@ export class HaAreaSelector extends LitElement {
|
|||||||
? [this.selector.area.entity.domain]
|
? [this.selector.area.entity.domain]
|
||||||
: undefined}
|
: undefined}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
></ha-area-picker>`;
|
></ha-area-picker>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-areas-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${this.value}
|
||||||
|
.pickAreaLabel=${this.label}
|
||||||
|
no-add
|
||||||
|
.deviceFilter=${this._filterDevices}
|
||||||
|
.entityFilter=${this._filterEntities}
|
||||||
|
.includeDeviceClasses=${this.selector.area.entity?.device_class
|
||||||
|
? [this.selector.area.entity.device_class]
|
||||||
|
: undefined}
|
||||||
|
.includeDomains=${this.selector.area.entity?.domain
|
||||||
|
? [this.selector.area.entity.domain]
|
||||||
|
: undefined}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
></ha-areas-picker>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _filterEntities = (entity: EntityRegistryEntry): boolean => {
|
private _filterEntities = (entity: EntityRegistryEntry): boolean => {
|
||||||
|
@ -46,6 +46,7 @@ export interface AreaSelector {
|
|||||||
manufacturer?: DeviceSelector["device"]["manufacturer"];
|
manufacturer?: DeviceSelector["device"]["manufacturer"];
|
||||||
model?: DeviceSelector["device"]["model"];
|
model?: DeviceSelector["device"]["model"];
|
||||||
};
|
};
|
||||||
|
multiple?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user