mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-16 13:56:35 +00:00
Add entity and device selectors (#7735)
This commit is contained in:
parent
46f5589530
commit
f835810f0a
@ -42,6 +42,10 @@ interface Device {
|
|||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type HaDevicePickerDeviceFilterFunc = (
|
||||||
|
device: DeviceRegistryEntry
|
||||||
|
) => boolean;
|
||||||
|
|
||||||
const rowRenderer = (root: HTMLElement, _owner, model: { item: Device }) => {
|
const rowRenderer = (root: HTMLElement, _owner, model: { item: Device }) => {
|
||||||
if (!root.firstElementChild) {
|
if (!root.firstElementChild) {
|
||||||
root.innerHTML = `
|
root.innerHTML = `
|
||||||
@ -102,6 +106,8 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
|||||||
@property({ type: Array, attribute: "include-device-classes" })
|
@property({ type: Array, attribute: "include-device-classes" })
|
||||||
public includeDeviceClasses?: string[];
|
public includeDeviceClasses?: string[];
|
||||||
|
|
||||||
|
@property() public deviceFilter?: HaDevicePickerDeviceFilterFunc;
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
private _opened?: boolean;
|
private _opened?: boolean;
|
||||||
|
|
||||||
@ -112,7 +118,8 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
|||||||
entities: EntityRegistryEntry[],
|
entities: EntityRegistryEntry[],
|
||||||
includeDomains: this["includeDomains"],
|
includeDomains: this["includeDomains"],
|
||||||
excludeDomains: this["excludeDomains"],
|
excludeDomains: this["excludeDomains"],
|
||||||
includeDeviceClasses: this["includeDeviceClasses"]
|
includeDeviceClasses: this["includeDeviceClasses"],
|
||||||
|
deviceFilter: this["deviceFilter"]
|
||||||
): Device[] => {
|
): Device[] => {
|
||||||
if (!devices.length) {
|
if (!devices.length) {
|
||||||
return [];
|
return [];
|
||||||
@ -180,6 +187,14 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deviceFilter) {
|
||||||
|
inputDevices = inputDevices.filter(
|
||||||
|
(device) =>
|
||||||
|
// We always want to include the device of the current value
|
||||||
|
device.id === this.value || deviceFilter!(device)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const outputDevices = inputDevices.map((device) => {
|
const outputDevices = inputDevices.map((device) => {
|
||||||
return {
|
return {
|
||||||
id: device.id,
|
id: device.id,
|
||||||
@ -224,7 +239,8 @@ export class HaDevicePicker extends SubscribeMixin(LitElement) {
|
|||||||
this.entities,
|
this.entities,
|
||||||
this.includeDomains,
|
this.includeDomains,
|
||||||
this.excludeDomains,
|
this.excludeDomains,
|
||||||
this.includeDeviceClasses
|
this.includeDeviceClasses,
|
||||||
|
this.deviceFilter
|
||||||
);
|
);
|
||||||
return html`
|
return html`
|
||||||
<vaadin-combo-box-light
|
<vaadin-combo-box-light
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
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 { compare } from "../common/string/compare";
|
import { compare } from "../common/string/compare";
|
||||||
import { Blueprints, fetchBlueprints } from "../data/blueprint";
|
import { Blueprint, Blueprints, fetchBlueprints } from "../data/blueprint";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
@customElement("ha-blueprint-picker")
|
@customElement("ha-blueprint-picker")
|
||||||
@ -34,10 +34,12 @@ class HaBluePrintPicker extends LitElement {
|
|||||||
if (!blueprints) {
|
if (!blueprints) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const result = Object.entries(blueprints).map(([path, blueprint]) => ({
|
const result = Object.entries(blueprints)
|
||||||
...blueprint.metadata,
|
.filter(([_path, blueprint]) => !("error" in blueprint))
|
||||||
path,
|
.map(([path, blueprint]) => ({
|
||||||
}));
|
...(blueprint as Blueprint).metadata,
|
||||||
|
path,
|
||||||
|
}));
|
||||||
return result.sort((a, b) => compare(a.name, b.name));
|
return result.sort((a, b) => compare(a.name, b.name));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
81
src/components/ha-selector/ha-selector-device.ts
Normal file
81
src/components/ha-selector/ha-selector-device.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
} from "lit-element";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
import "../device/ha-device-picker";
|
||||||
|
import { DeviceRegistryEntry } from "../../data/device_registry";
|
||||||
|
import { ConfigEntry, getConfigEntries } from "../../data/config_entries";
|
||||||
|
import { DeviceSelector } from "../../data/selector";
|
||||||
|
|
||||||
|
@customElement("ha-selector-device")
|
||||||
|
export class HaDeviceSelector extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public selector!: DeviceSelector;
|
||||||
|
|
||||||
|
@property() public value?: any;
|
||||||
|
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
@internalProperty() public _configEntries?: ConfigEntry[];
|
||||||
|
|
||||||
|
protected updated(changedProperties) {
|
||||||
|
if (changedProperties.has("selector")) {
|
||||||
|
const oldSelector = changedProperties.get("selector");
|
||||||
|
if (oldSelector !== this.selector && this.selector.device.integration) {
|
||||||
|
this._loadConfigEntries();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
return html`<ha-device-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${this.value}
|
||||||
|
.label=${this.label}
|
||||||
|
.deviceFilter=${(device) => this._filterDevices(device)}
|
||||||
|
allow-custom-entity
|
||||||
|
></ha-device-picker>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _filterDevices(device: DeviceRegistryEntry): boolean {
|
||||||
|
if (
|
||||||
|
this.selector.device.manufacturer &&
|
||||||
|
device.manufacturer !== this.selector.device.manufacturer
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.selector.device.model &&
|
||||||
|
device.model !== this.selector.device.model
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (this.selector.device.integration) {
|
||||||
|
if (
|
||||||
|
!this._configEntries?.some((entry) =>
|
||||||
|
device.config_entries.includes(entry.entry_id)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _loadConfigEntries() {
|
||||||
|
this._configEntries = (await getConfigEntries(this.hass)).filter(
|
||||||
|
(entry) => entry.domain === this.selector.device.integration
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-selector-device": HaDeviceSelector;
|
||||||
|
}
|
||||||
|
}
|
75
src/components/ha-selector/ha-selector-entity.ts
Normal file
75
src/components/ha-selector/ha-selector-entity.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import {
|
||||||
|
customElement,
|
||||||
|
html,
|
||||||
|
internalProperty,
|
||||||
|
LitElement,
|
||||||
|
property,
|
||||||
|
} from "lit-element";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
import "../entity/ha-entity-picker";
|
||||||
|
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
|
import { computeStateDomain } from "../../common/entity/compute_state_domain";
|
||||||
|
import { subscribeEntityRegistry } from "../../data/entity_registry";
|
||||||
|
import { SubscribeMixin } from "../../mixins/subscribe-mixin";
|
||||||
|
import { EntitySelector } from "../../data/selector";
|
||||||
|
|
||||||
|
@customElement("ha-selector-entity")
|
||||||
|
export class HaEntitySelector extends SubscribeMixin(LitElement) {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public selector!: EntitySelector;
|
||||||
|
|
||||||
|
@internalProperty() private _entities?: Record<string, string>;
|
||||||
|
|
||||||
|
@property() public value?: any;
|
||||||
|
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
return html`<ha-entity-picker
|
||||||
|
.hass=${this.hass}
|
||||||
|
.value=${this.value}
|
||||||
|
.label=${this.label}
|
||||||
|
.entityFilter=${(entity) => this._filterEntities(entity)}
|
||||||
|
allow-custom-entity
|
||||||
|
></ha-entity-picker>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
public hassSubscribe(): UnsubscribeFunc[] {
|
||||||
|
return [
|
||||||
|
subscribeEntityRegistry(this.hass.connection!, (entities) => {
|
||||||
|
const entityLookup = {};
|
||||||
|
for (const confEnt of entities) {
|
||||||
|
if (!confEnt.platform) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entityLookup[confEnt.entity_id] = confEnt.platform;
|
||||||
|
}
|
||||||
|
this._entities = entityLookup;
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private _filterEntities(entity: HassEntity): boolean {
|
||||||
|
if (this.selector.entity.domain) {
|
||||||
|
if (computeStateDomain(entity) !== this.selector.entity.domain) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.selector.entity.integration) {
|
||||||
|
if (
|
||||||
|
!this._entities ||
|
||||||
|
this._entities[entity.entity_id] !== this.selector.entity.integration
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-selector-entity": HaEntitySelector;
|
||||||
|
}
|
||||||
|
}
|
48
src/components/ha-selector/ha-selector.ts
Normal file
48
src/components/ha-selector/ha-selector.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { customElement, html, LitElement, property } from "lit-element";
|
||||||
|
import { dynamicElement } from "../../common/dom/dynamic-element-directive";
|
||||||
|
import { HomeAssistant } from "../../types";
|
||||||
|
|
||||||
|
import "./ha-selector-entity";
|
||||||
|
import "./ha-selector-device";
|
||||||
|
import { Selector } from "../../data/selector";
|
||||||
|
|
||||||
|
@customElement("ha-selector")
|
||||||
|
export class HaSelector extends LitElement {
|
||||||
|
@property() public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@property() public selector!: Selector;
|
||||||
|
|
||||||
|
@property() public value?: any;
|
||||||
|
|
||||||
|
@property() public label?: string;
|
||||||
|
|
||||||
|
public focus() {
|
||||||
|
const input = this.shadowRoot!.getElementById("selector");
|
||||||
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(input as HTMLElement).focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _type() {
|
||||||
|
return Object.keys(this.selector)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
return html`
|
||||||
|
${dynamicElement(`ha-selector-${this._type}`, {
|
||||||
|
hass: this.hass,
|
||||||
|
selector: this.selector,
|
||||||
|
value: this.value,
|
||||||
|
label: this.label,
|
||||||
|
id: "selector",
|
||||||
|
})}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-selector": HaSelector;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
|
import { Selector } from "./selector";
|
||||||
|
|
||||||
export type Blueprints = Record<string, Blueprint>;
|
export type Blueprints = Record<string, BlueprintOrError>;
|
||||||
|
|
||||||
|
export type BlueprintOrError = Blueprint | { error: string };
|
||||||
export interface Blueprint {
|
export interface Blueprint {
|
||||||
metadata: BlueprintMetaData;
|
metadata: BlueprintMetaData;
|
||||||
}
|
}
|
||||||
@ -9,10 +11,14 @@ export interface Blueprint {
|
|||||||
export interface BlueprintMetaData {
|
export interface BlueprintMetaData {
|
||||||
domain: string;
|
domain: string;
|
||||||
name: string;
|
name: string;
|
||||||
input: BlueprintInput;
|
input: Record<string, BlueprintInput | null>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BlueprintInput = Record<string, any>;
|
export interface BlueprintInput {
|
||||||
|
name?: string;
|
||||||
|
description?: string;
|
||||||
|
selector?: Selector;
|
||||||
|
}
|
||||||
|
|
||||||
export interface BlueprintImportResult {
|
export interface BlueprintImportResult {
|
||||||
url: string;
|
url: string;
|
||||||
|
@ -94,7 +94,7 @@ export const removeEntityRegistryEntry = (
|
|||||||
entity_id: entityId,
|
entity_id: entityId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchEntityRegistry = (conn) =>
|
export const fetchEntityRegistry = (conn) =>
|
||||||
conn.sendMessagePromise({
|
conn.sendMessagePromise({
|
||||||
type: "config/entity_registry/list",
|
type: "config/entity_registry/list",
|
||||||
});
|
});
|
||||||
|
16
src/data/selector.ts
Normal file
16
src/data/selector.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export type Selector = EntitySelector | DeviceSelector;
|
||||||
|
|
||||||
|
export interface EntitySelector {
|
||||||
|
entity: {
|
||||||
|
integration?: string;
|
||||||
|
domain?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeviceSelector {
|
||||||
|
device: {
|
||||||
|
integration?: string;
|
||||||
|
manufacturer?: string;
|
||||||
|
model?: string;
|
||||||
|
};
|
||||||
|
}
|
@ -26,12 +26,13 @@ import { haStyle } from "../../../resources/styles";
|
|||||||
import { HassEntity } from "home-assistant-js-websocket";
|
import { HassEntity } from "home-assistant-js-websocket";
|
||||||
import { navigate } from "../../../common/navigate";
|
import { navigate } from "../../../common/navigate";
|
||||||
import {
|
import {
|
||||||
Blueprint,
|
BlueprintOrError,
|
||||||
Blueprints,
|
Blueprints,
|
||||||
fetchBlueprints,
|
fetchBlueprints,
|
||||||
} from "../../../data/blueprint";
|
} from "../../../data/blueprint";
|
||||||
import "../../../components/ha-blueprint-picker";
|
import "../../../components/ha-blueprint-picker";
|
||||||
import "../../../components/ha-circular-progress";
|
import "../../../components/ha-circular-progress";
|
||||||
|
import "../../../components/ha-selector/ha-selector";
|
||||||
|
|
||||||
@customElement("blueprint-automation-editor")
|
@customElement("blueprint-automation-editor")
|
||||||
export class HaBlueprintAutomationEditor extends LitElement {
|
export class HaBlueprintAutomationEditor extends LitElement {
|
||||||
@ -52,7 +53,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
this._getBlueprints();
|
this._getBlueprints();
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _blueprint(): Blueprint | undefined {
|
private get _blueprint(): BlueprintOrError | undefined {
|
||||||
if (!this._blueprints) {
|
if (!this._blueprints) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -149,9 +150,14 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
)}
|
)}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
${this.config.use_blueprint.path
|
${this.config.use_blueprint.path
|
||||||
? blueprint?.metadata?.input &&
|
? blueprint && "error" in blueprint
|
||||||
Object.keys(blueprint.metadata.input).length
|
? html`<p class="warning">
|
||||||
|
There is an error in this Blueprint: ${blueprint.error}
|
||||||
|
</p>`
|
||||||
|
: blueprint?.metadata?.input &&
|
||||||
|
Object.keys(blueprint.metadata.input).length
|
||||||
? html`<h3>
|
? html`<h3>
|
||||||
${this.hass.localize(
|
${this.hass.localize(
|
||||||
"ui.panel.config.automation.editor.blueprint.inputs"
|
"ui.panel.config.automation.editor.blueprint.inputs"
|
||||||
@ -161,13 +167,23 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
([key, value]) =>
|
([key, value]) =>
|
||||||
html`<div>
|
html`<div>
|
||||||
${value?.description}
|
${value?.description}
|
||||||
<paper-input
|
${value?.selector
|
||||||
.key=${key}
|
? html`<ha-selector
|
||||||
.label=${value?.name || key}
|
.hass=${this.hass}
|
||||||
.value=${this.config.use_blueprint.input &&
|
.selector=${value.selector}
|
||||||
this.config.use_blueprint.input[key]}
|
.key=${key}
|
||||||
@value-changed=${this._inputChanged}
|
.label=${value?.name || key}
|
||||||
></paper-input>
|
.value=${this.config.use_blueprint.input &&
|
||||||
|
this.config.use_blueprint.input[key]}
|
||||||
|
@value-changed=${this._inputChanged}
|
||||||
|
></ha-selector>`
|
||||||
|
: html`<paper-input
|
||||||
|
.key=${key}
|
||||||
|
.label=${value?.name || key}
|
||||||
|
.value=${this.config.use_blueprint.input &&
|
||||||
|
this.config.use_blueprint.input[key]}
|
||||||
|
@value-changed=${this._inputChanged}
|
||||||
|
></paper-input>`}
|
||||||
</div>`
|
</div>`
|
||||||
)}`
|
)}`
|
||||||
: this.hass.localize(
|
: this.hass.localize(
|
||||||
@ -206,7 +222,7 @@ export class HaBlueprintAutomationEditor extends LitElement {
|
|||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
const target = ev.target as any;
|
const target = ev.target as any;
|
||||||
const key = target.key;
|
const key = target.key;
|
||||||
const value = target.value;
|
const value = ev.detail.value;
|
||||||
if (
|
if (
|
||||||
(this.config.use_blueprint.input &&
|
(this.config.use_blueprint.input &&
|
||||||
this.config.use_blueprint.input[key] === value) ||
|
this.config.use_blueprint.input[key] === value) ||
|
||||||
|
@ -34,6 +34,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
|||||||
|
|
||||||
interface BlueprintMetaDataPath extends BlueprintMetaData {
|
interface BlueprintMetaDataPath extends BlueprintMetaData {
|
||||||
path: string;
|
path: string;
|
||||||
|
error: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const createNewFunctions = {
|
const createNewFunctions = {
|
||||||
@ -61,10 +62,20 @@ class HaBlueprintOverview extends LitElement {
|
|||||||
@property() public blueprints!: Blueprints;
|
@property() public blueprints!: Blueprints;
|
||||||
|
|
||||||
private _processedBlueprints = memoizeOne((blueprints: Blueprints) => {
|
private _processedBlueprints = memoizeOne((blueprints: Blueprints) => {
|
||||||
const result = Object.entries(blueprints).map(([path, blueprint]) => ({
|
const result = Object.entries(blueprints).map(([path, blueprint]) => {
|
||||||
...blueprint.metadata,
|
if ("error" in blueprint) {
|
||||||
path,
|
return {
|
||||||
}));
|
name: blueprint.error,
|
||||||
|
error: true,
|
||||||
|
path,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...blueprint.metadata,
|
||||||
|
error: false,
|
||||||
|
path,
|
||||||
|
};
|
||||||
|
});
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -98,20 +109,26 @@ class HaBlueprintOverview extends LitElement {
|
|||||||
columns.create = {
|
columns.create = {
|
||||||
title: "",
|
title: "",
|
||||||
type: "icon-button",
|
type: "icon-button",
|
||||||
template: (_, blueprint) => html`<mwc-icon-button
|
template: (_, blueprint: any) =>
|
||||||
.blueprint=${blueprint}
|
blueprint.error
|
||||||
@click=${(ev) => this._createNew(ev)}
|
? ""
|
||||||
><ha-svg-icon .path=${mdiPlus}></ha-svg-icon
|
: html`<mwc-icon-button
|
||||||
></mwc-icon-button>`,
|
.blueprint=${blueprint}
|
||||||
|
@click=${(ev) => this._createNew(ev)}
|
||||||
|
><ha-svg-icon .path=${mdiPlus}></ha-svg-icon
|
||||||
|
></mwc-icon-button>`,
|
||||||
};
|
};
|
||||||
columns.delete = {
|
columns.delete = {
|
||||||
title: "",
|
title: "",
|
||||||
type: "icon-button",
|
type: "icon-button",
|
||||||
template: (_, blueprint) => html`<mwc-icon-button
|
template: (_, blueprint: any) =>
|
||||||
.blueprint=${blueprint}
|
blueprint.error
|
||||||
@click=${(ev) => this._delete(ev)}
|
? ""
|
||||||
><ha-svg-icon .path=${mdiDelete}></ha-svg-icon
|
: html`<mwc-icon-button
|
||||||
></mwc-icon-button>`,
|
.blueprint=${blueprint}
|
||||||
|
@click=${(ev) => this._delete(ev)}
|
||||||
|
><ha-svg-icon .path=${mdiDelete}></ha-svg-icon
|
||||||
|
></mwc-icon-button>`,
|
||||||
};
|
};
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user