mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-28 11:46:42 +00:00
Create helpers from automation editor (#19287)
* Create helpers from automation editor * support multiple createDomains * localization * fix lint * Move multi domain to entity picker * Update dialog-helper-detail.ts * Update ha-config-helpers.ts * optimize a little --------- Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
0118a5bf4c
commit
178feb7330
@ -18,6 +18,12 @@ import "../ha-icon-button";
|
|||||||
import "../ha-svg-icon";
|
import "../ha-svg-icon";
|
||||||
import "./state-badge";
|
import "./state-badge";
|
||||||
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
import { caseInsensitiveStringCompare } from "../../common/string/compare";
|
||||||
|
import { showHelperDetailDialog } from "../../panels/config/helpers/show-dialog-helper-detail";
|
||||||
|
import { domainToName } from "../../data/integration";
|
||||||
|
import {
|
||||||
|
isHelperDomain,
|
||||||
|
HelperDomain,
|
||||||
|
} from "../../panels/config/helpers/const";
|
||||||
|
|
||||||
interface HassEntityWithCachedName extends HassEntity, ScorableTextItem {
|
interface HassEntityWithCachedName extends HassEntity, ScorableTextItem {
|
||||||
friendly_name: string;
|
friendly_name: string;
|
||||||
@ -25,6 +31,8 @@ interface HassEntityWithCachedName extends HassEntity, ScorableTextItem {
|
|||||||
|
|
||||||
export type HaEntityPickerEntityFilterFunc = (entity: HassEntity) => boolean;
|
export type HaEntityPickerEntityFilterFunc = (entity: HassEntity) => boolean;
|
||||||
|
|
||||||
|
const CREATE_ID = "___create-new-entity___";
|
||||||
|
|
||||||
@customElement("ha-entity-picker")
|
@customElement("ha-entity-picker")
|
||||||
export class HaEntityPicker extends LitElement {
|
export class HaEntityPicker extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
@ -44,6 +52,8 @@ export class HaEntityPicker extends LitElement {
|
|||||||
|
|
||||||
@property() public helper?: string;
|
@property() public helper?: string;
|
||||||
|
|
||||||
|
@property({ type: Array }) public createDomains?: string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show entities from specific domains.
|
* Show entities from specific domains.
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
@ -130,7 +140,11 @@ export class HaEntityPicker extends LitElement {
|
|||||||
></state-badge>`
|
></state-badge>`
|
||||||
: ""}
|
: ""}
|
||||||
<span>${item.friendly_name}</span>
|
<span>${item.friendly_name}</span>
|
||||||
<span slot="secondary">${item.entity_id}</span>
|
<span slot="secondary"
|
||||||
|
>${item.entity_id.startsWith(CREATE_ID)
|
||||||
|
? this.hass.localize("ui.components.entity.entity-picker.new_entity")
|
||||||
|
: item.entity_id}</span
|
||||||
|
>
|
||||||
</ha-list-item>`;
|
</ha-list-item>`;
|
||||||
|
|
||||||
private _getStates = memoizeOne(
|
private _getStates = memoizeOne(
|
||||||
@ -143,7 +157,8 @@ export class HaEntityPicker extends LitElement {
|
|||||||
includeDeviceClasses: this["includeDeviceClasses"],
|
includeDeviceClasses: this["includeDeviceClasses"],
|
||||||
includeUnitOfMeasurement: this["includeUnitOfMeasurement"],
|
includeUnitOfMeasurement: this["includeUnitOfMeasurement"],
|
||||||
includeEntities: this["includeEntities"],
|
includeEntities: this["includeEntities"],
|
||||||
excludeEntities: this["excludeEntities"]
|
excludeEntities: this["excludeEntities"],
|
||||||
|
createDomains: this["createDomains"]
|
||||||
): HassEntityWithCachedName[] => {
|
): HassEntityWithCachedName[] => {
|
||||||
let states: HassEntityWithCachedName[] = [];
|
let states: HassEntityWithCachedName[] = [];
|
||||||
|
|
||||||
@ -152,6 +167,34 @@ export class HaEntityPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
let entityIds = Object.keys(hass.states);
|
let entityIds = Object.keys(hass.states);
|
||||||
|
|
||||||
|
const createItems = createDomains?.length
|
||||||
|
? createDomains.map((domain) => {
|
||||||
|
const newFriendlyName = hass.localize(
|
||||||
|
"ui.components.entity.entity-picker.create_helper",
|
||||||
|
{
|
||||||
|
domain: isHelperDomain(domain)
|
||||||
|
? hass.localize(
|
||||||
|
`ui.panel.config.helpers.types.${domain as HelperDomain}`
|
||||||
|
)
|
||||||
|
: domainToName(hass.localize, domain),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
entity_id: CREATE_ID + domain,
|
||||||
|
state: "on",
|
||||||
|
last_changed: "",
|
||||||
|
last_updated: "",
|
||||||
|
context: { id: "", user_id: null, parent_id: null },
|
||||||
|
friendly_name: newFriendlyName,
|
||||||
|
attributes: {
|
||||||
|
icon: "mdi:plus",
|
||||||
|
},
|
||||||
|
strings: [domain, newFriendlyName],
|
||||||
|
};
|
||||||
|
})
|
||||||
|
: [];
|
||||||
|
|
||||||
if (!entityIds.length) {
|
if (!entityIds.length) {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -171,6 +214,7 @@ export class HaEntityPicker extends LitElement {
|
|||||||
},
|
},
|
||||||
strings: [],
|
strings: [],
|
||||||
},
|
},
|
||||||
|
...createItems,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,9 +325,14 @@ export class HaEntityPicker extends LitElement {
|
|||||||
},
|
},
|
||||||
strings: [],
|
strings: [],
|
||||||
},
|
},
|
||||||
|
...createItems,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (createItems?.length) {
|
||||||
|
states.push(...createItems);
|
||||||
|
}
|
||||||
|
|
||||||
return states;
|
return states;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -310,13 +359,18 @@ export class HaEntityPicker extends LitElement {
|
|||||||
this.includeDeviceClasses,
|
this.includeDeviceClasses,
|
||||||
this.includeUnitOfMeasurement,
|
this.includeUnitOfMeasurement,
|
||||||
this.includeEntities,
|
this.includeEntities,
|
||||||
this.excludeEntities
|
this.excludeEntities,
|
||||||
|
this.createDomains
|
||||||
);
|
);
|
||||||
if (this._initedStates) {
|
if (this._initedStates) {
|
||||||
this.comboBox.filteredItems = this._states;
|
this.comboBox.filteredItems = this._states;
|
||||||
}
|
}
|
||||||
this._initedStates = true;
|
this._initedStates = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changedProps.has("createDomains") && this.createDomains?.length) {
|
||||||
|
this.hass.loadFragmentTranslation("config");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected render(): TemplateResult {
|
protected render(): TemplateResult {
|
||||||
@ -354,6 +408,18 @@ export class HaEntityPicker extends LitElement {
|
|||||||
private _valueChanged(ev: ValueChangedEvent<string>) {
|
private _valueChanged(ev: ValueChangedEvent<string>) {
|
||||||
ev.stopPropagation();
|
ev.stopPropagation();
|
||||||
const newValue = ev.detail.value;
|
const newValue = ev.detail.value;
|
||||||
|
|
||||||
|
if (newValue.startsWith(CREATE_ID)) {
|
||||||
|
const domain = newValue.substring(CREATE_ID.length);
|
||||||
|
showHelperDetailDialog(this, {
|
||||||
|
domain,
|
||||||
|
dialogClosedCallback: (item) => {
|
||||||
|
if (item.entityId) this._setValue(item.entityId);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (newValue !== this._value) {
|
if (newValue !== this._value) {
|
||||||
this._setValue(newValue);
|
this._setValue(newValue);
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ export class HaTargetSelector extends LitElement {
|
|||||||
.deviceFilter=${this._filterDevices}
|
.deviceFilter=${this._filterDevices}
|
||||||
.entityFilter=${this._filterEntities}
|
.entityFilter=${this._filterEntities}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
|
.createDomains=${this.selector.target?.create_domains}
|
||||||
></ha-target-picker>`;
|
></ha-target-picker>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@ import {
|
|||||||
expandFloorTarget,
|
expandFloorTarget,
|
||||||
expandLabelTarget,
|
expandLabelTarget,
|
||||||
Selector,
|
Selector,
|
||||||
|
TargetSelector,
|
||||||
} from "../data/selector";
|
} from "../data/selector";
|
||||||
import { HomeAssistant, ValueChangedEvent } from "../types";
|
import { HomeAssistant, ValueChangedEvent } from "../types";
|
||||||
import { documentationUrl } from "../util/documentation-url";
|
import { documentationUrl } from "../util/documentation-url";
|
||||||
@ -43,6 +44,7 @@ import "./ha-service-picker";
|
|||||||
import "./ha-settings-row";
|
import "./ha-settings-row";
|
||||||
import "./ha-yaml-editor";
|
import "./ha-yaml-editor";
|
||||||
import type { HaYamlEditor } from "./ha-yaml-editor";
|
import type { HaYamlEditor } from "./ha-yaml-editor";
|
||||||
|
import { isHelperDomain } from "../panels/config/helpers/const";
|
||||||
|
|
||||||
const attributeFilter = (values: any[], attribute: any) => {
|
const attributeFilter = (values: any[], attribute: any) => {
|
||||||
if (typeof attribute === "object") {
|
if (typeof attribute === "object") {
|
||||||
@ -363,6 +365,15 @@ export class HaServiceControl extends LitElement {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _targetSelector = memoizeOne(
|
||||||
|
(targetSelector: TargetSelector | null | undefined, domain?: string) => {
|
||||||
|
const create_domains = isHelperDomain(domain) ? [domain] : undefined;
|
||||||
|
return targetSelector
|
||||||
|
? { target: { ...targetSelector, create_domains } }
|
||||||
|
: { target: { create_domains } };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
const serviceData = this._getServiceInfo(
|
const serviceData = this._getServiceInfo(
|
||||||
this._value?.service,
|
this._value?.service,
|
||||||
@ -401,157 +412,152 @@ export class HaServiceControl extends LitElement {
|
|||||||
)) ||
|
)) ||
|
||||||
serviceData?.description;
|
serviceData?.description;
|
||||||
|
|
||||||
return html`
|
return html`${this.hidePicker
|
||||||
${this.hidePicker
|
? nothing
|
||||||
? nothing
|
: html`<ha-service-picker
|
||||||
: html`<ha-service-picker
|
.hass=${this.hass}
|
||||||
|
.value=${this._value?.service}
|
||||||
|
.disabled=${this.disabled}
|
||||||
|
@value-changed=${this._serviceChanged}
|
||||||
|
></ha-service-picker>`}
|
||||||
|
${this.hideDescription
|
||||||
|
? nothing
|
||||||
|
: html`
|
||||||
|
<div class="description">
|
||||||
|
${description ? html`<p>${description}</p>` : ""}
|
||||||
|
${this._manifest
|
||||||
|
? html` <a
|
||||||
|
href=${this._manifest.is_built_in
|
||||||
|
? documentationUrl(
|
||||||
|
this.hass,
|
||||||
|
`/integrations/${this._manifest.domain}`
|
||||||
|
)
|
||||||
|
: this._manifest.documentation}
|
||||||
|
title=${this.hass.localize(
|
||||||
|
"ui.components.service-control.integration_doc"
|
||||||
|
)}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
.path=${mdiHelpCircle}
|
||||||
|
class="help-icon"
|
||||||
|
></ha-icon-button>
|
||||||
|
</a>`
|
||||||
|
: nothing}
|
||||||
|
</div>
|
||||||
|
`}
|
||||||
|
${serviceData && "target" in serviceData
|
||||||
|
? html`<ha-settings-row .narrow=${this.narrow}>
|
||||||
|
${hasOptional
|
||||||
|
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
||||||
|
: ""}
|
||||||
|
<span slot="heading"
|
||||||
|
>${this.hass.localize("ui.components.service-control.target")}</span
|
||||||
|
>
|
||||||
|
<span slot="description"
|
||||||
|
>${this.hass.localize(
|
||||||
|
"ui.components.service-control.target_description"
|
||||||
|
)}</span
|
||||||
|
><ha-selector
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.value=${this._value?.service}
|
.selector=${this._targetSelector(
|
||||||
|
serviceData.target as TargetSelector,
|
||||||
|
domain
|
||||||
|
)}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@value-changed=${this._serviceChanged}
|
@value-changed=${this._targetChanged}
|
||||||
></ha-service-picker>`}
|
.value=${this._value?.target}
|
||||||
${this.hideDescription
|
></ha-selector
|
||||||
? nothing
|
></ha-settings-row>`
|
||||||
: html`
|
: entityId
|
||||||
<div class="description">
|
? html`<ha-entity-picker
|
||||||
${description ? html`<p>${description}</p>` : ""}
|
|
||||||
${this._manifest
|
|
||||||
? html` <a
|
|
||||||
href=${this._manifest.is_built_in
|
|
||||||
? documentationUrl(
|
|
||||||
this.hass,
|
|
||||||
`/integrations/${this._manifest.domain}`
|
|
||||||
)
|
|
||||||
: this._manifest.documentation}
|
|
||||||
title=${this.hass.localize(
|
|
||||||
"ui.components.service-control.integration_doc"
|
|
||||||
)}
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
<ha-icon-button
|
|
||||||
.path=${mdiHelpCircle}
|
|
||||||
class="help-icon"
|
|
||||||
></ha-icon-button>
|
|
||||||
</a>`
|
|
||||||
: nothing}
|
|
||||||
</div>
|
|
||||||
`}
|
|
||||||
${serviceData && "target" in serviceData
|
|
||||||
? html`<ha-settings-row .narrow=${this.narrow}>
|
|
||||||
${hasOptional
|
|
||||||
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
|
||||||
: ""}
|
|
||||||
<span slot="heading"
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.components.service-control.target"
|
|
||||||
)}</span
|
|
||||||
>
|
|
||||||
<span slot="description"
|
|
||||||
>${this.hass.localize(
|
|
||||||
"ui.components.service-control.target_description"
|
|
||||||
)}</span
|
|
||||||
><ha-selector
|
|
||||||
.hass=${this.hass}
|
|
||||||
.selector=${serviceData.target
|
|
||||||
? { target: serviceData.target }
|
|
||||||
: { target: {} }}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
@value-changed=${this._targetChanged}
|
|
||||||
.value=${this._value?.target}
|
|
||||||
></ha-selector
|
|
||||||
></ha-settings-row>`
|
|
||||||
: entityId
|
|
||||||
? html`<ha-entity-picker
|
|
||||||
.hass=${this.hass}
|
|
||||||
.disabled=${this.disabled}
|
|
||||||
.value=${this._value?.data?.entity_id}
|
|
||||||
.label=${this.hass.localize(
|
|
||||||
`component.${domain}.services.${serviceName}.fields.entity_id.description`
|
|
||||||
) || entityId.description}
|
|
||||||
@value-changed=${this._entityPicked}
|
|
||||||
allow-custom-entity
|
|
||||||
></ha-entity-picker>`
|
|
||||||
: ""}
|
|
||||||
${shouldRenderServiceDataYaml
|
|
||||||
? html`<ha-yaml-editor
|
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.label=${this.hass.localize("ui.components.service-control.data")}
|
.disabled=${this.disabled}
|
||||||
.name=${"data"}
|
.value=${this._value?.data?.entity_id}
|
||||||
.readOnly=${this.disabled}
|
.label=${this.hass.localize(
|
||||||
.defaultValue=${this._value?.data}
|
`component.${domain}.services.${serviceName}.fields.entity_id.description`
|
||||||
@value-changed=${this._dataChanged}
|
) || entityId.description}
|
||||||
></ha-yaml-editor>`
|
@value-changed=${this._entityPicked}
|
||||||
: filteredFields?.map((dataField) => {
|
allow-custom-entity
|
||||||
const selector = dataField?.selector ?? { text: undefined };
|
></ha-entity-picker>`
|
||||||
const type = Object.keys(selector)[0];
|
: ""}
|
||||||
const enhancedSelector = [
|
${shouldRenderServiceDataYaml
|
||||||
"action",
|
? html`<ha-yaml-editor
|
||||||
"condition",
|
.hass=${this.hass}
|
||||||
"trigger",
|
.label=${this.hass.localize("ui.components.service-control.data")}
|
||||||
].includes(type)
|
.name=${"data"}
|
||||||
? {
|
.readOnly=${this.disabled}
|
||||||
[type]: {
|
.defaultValue=${this._value?.data}
|
||||||
...selector[type],
|
@value-changed=${this._dataChanged}
|
||||||
path: [dataField.key],
|
></ha-yaml-editor>`
|
||||||
},
|
: filteredFields?.map((dataField) => {
|
||||||
}
|
const selector = dataField?.selector ?? { text: undefined };
|
||||||
: selector;
|
const type = Object.keys(selector)[0];
|
||||||
|
const enhancedSelector = ["action", "condition", "trigger"].includes(
|
||||||
|
type
|
||||||
|
)
|
||||||
|
? {
|
||||||
|
[type]: {
|
||||||
|
...selector[type],
|
||||||
|
path: [dataField.key],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: selector;
|
||||||
|
|
||||||
const showOptional = showOptionalToggle(dataField);
|
const showOptional = showOptionalToggle(dataField);
|
||||||
|
|
||||||
return dataField.selector &&
|
return dataField.selector &&
|
||||||
(!dataField.advanced ||
|
(!dataField.advanced ||
|
||||||
this.showAdvanced ||
|
this.showAdvanced ||
|
||||||
(this._value?.data &&
|
(this._value?.data &&
|
||||||
this._value.data[dataField.key] !== undefined))
|
this._value.data[dataField.key] !== undefined))
|
||||||
? html`<ha-settings-row .narrow=${this.narrow}>
|
? html`<ha-settings-row .narrow=${this.narrow}>
|
||||||
${!showOptional
|
${!showOptional
|
||||||
? hasOptional
|
? hasOptional
|
||||||
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
? html`<div slot="prefix" class="checkbox-spacer"></div>`
|
||||||
: ""
|
: ""
|
||||||
: html`<ha-checkbox
|
: html`<ha-checkbox
|
||||||
.key=${dataField.key}
|
.key=${dataField.key}
|
||||||
.checked=${this._checkedKeys.has(dataField.key) ||
|
.checked=${this._checkedKeys.has(dataField.key) ||
|
||||||
(this._value?.data &&
|
(this._value?.data &&
|
||||||
this._value.data[dataField.key] !== undefined)}
|
this._value.data[dataField.key] !== undefined)}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
@change=${this._checkboxChanged}
|
@change=${this._checkboxChanged}
|
||||||
slot="prefix"
|
slot="prefix"
|
||||||
></ha-checkbox>`}
|
></ha-checkbox>`}
|
||||||
<span slot="heading"
|
<span slot="heading"
|
||||||
>${this.hass.localize(
|
>${this.hass.localize(
|
||||||
`component.${domain}.services.${serviceName}.fields.${dataField.key}.name`
|
`component.${domain}.services.${serviceName}.fields.${dataField.key}.name`
|
||||||
) ||
|
) ||
|
||||||
dataField.name ||
|
dataField.name ||
|
||||||
dataField.key}</span
|
dataField.key}</span
|
||||||
>
|
>
|
||||||
<span slot="description"
|
<span slot="description"
|
||||||
>${this.hass.localize(
|
>${this.hass.localize(
|
||||||
`component.${domain}.services.${serviceName}.fields.${dataField.key}.description`
|
`component.${domain}.services.${serviceName}.fields.${dataField.key}.description`
|
||||||
) || dataField?.description}</span
|
) || dataField?.description}</span
|
||||||
>
|
>
|
||||||
<ha-selector
|
<ha-selector
|
||||||
.disabled=${this.disabled ||
|
.disabled=${this.disabled ||
|
||||||
(showOptional &&
|
(showOptional &&
|
||||||
!this._checkedKeys.has(dataField.key) &&
|
!this._checkedKeys.has(dataField.key) &&
|
||||||
(!this._value?.data ||
|
(!this._value?.data ||
|
||||||
this._value.data[dataField.key] === undefined))}
|
this._value.data[dataField.key] === undefined))}
|
||||||
.hass=${this.hass}
|
.hass=${this.hass}
|
||||||
.selector=${enhancedSelector}
|
.selector=${enhancedSelector}
|
||||||
.key=${dataField.key}
|
.key=${dataField.key}
|
||||||
@value-changed=${this._serviceDataChanged}
|
@value-changed=${this._serviceDataChanged}
|
||||||
.value=${this._value?.data
|
.value=${this._value?.data
|
||||||
? this._value.data[dataField.key]
|
? this._value.data[dataField.key]
|
||||||
: undefined}
|
: undefined}
|
||||||
.placeholder=${dataField.default}
|
.placeholder=${dataField.default}
|
||||||
.localizeValue=${this._localizeValueCallback}
|
.localizeValue=${this._localizeValueCallback}
|
||||||
@item-moved=${this._itemMoved}
|
@item-moved=${this._itemMoved}
|
||||||
></ha-selector>
|
></ha-selector>
|
||||||
</ha-settings-row>`
|
</ha-settings-row>`
|
||||||
: "";
|
: "";
|
||||||
})}
|
})} `;
|
||||||
`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _localizeValueCallback = (key: string) => {
|
private _localizeValueCallback = (key: string) => {
|
||||||
|
@ -65,6 +65,8 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
|
|
||||||
@property() public helper?: string;
|
@property() public helper?: string;
|
||||||
|
|
||||||
|
@property({ type: Array }) public createDomains?: string[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show only targets with entities from specific domains.
|
* Show only targets with entities from specific domains.
|
||||||
* @type {Array}
|
* @type {Array}
|
||||||
@ -468,6 +470,7 @@ export class HaTargetPicker extends SubscribeMixin(LitElement) {
|
|||||||
.includeDeviceClasses=${this.includeDeviceClasses}
|
.includeDeviceClasses=${this.includeDeviceClasses}
|
||||||
.includeDomains=${this.includeDomains}
|
.includeDomains=${this.includeDomains}
|
||||||
.excludeEntities=${ensureArray(this.value?.entity_id)}
|
.excludeEntities=${ensureArray(this.value?.entity_id)}
|
||||||
|
.createDomains=${this.createDomains}
|
||||||
@value-changed=${this._targetPicked}
|
@value-changed=${this._targetPicked}
|
||||||
@click=${this._preventDefault}
|
@click=${this._preventDefault}
|
||||||
allow-custom-entity
|
allow-custom-entity
|
||||||
|
@ -401,6 +401,7 @@ export interface TargetSelector {
|
|||||||
target: {
|
target: {
|
||||||
entity?: EntitySelectorFilter | readonly EntitySelectorFilter[];
|
entity?: EntitySelectorFilter | readonly EntitySelectorFilter[];
|
||||||
device?: DeviceSelectorFilter | readonly DeviceSelectorFilter[];
|
device?: DeviceSelectorFilter | readonly DeviceSelectorFilter[];
|
||||||
|
create_domains?: string[];
|
||||||
} | null;
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ import { showConfigFlowDialog } from "../../../dialogs/config-flow/show-dialog-c
|
|||||||
import { haStyleDialog } from "../../../resources/styles";
|
import { haStyleDialog } from "../../../resources/styles";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { brandsUrl } from "../../../util/brands-url";
|
import { brandsUrl } from "../../../util/brands-url";
|
||||||
import { Helper, HelperDomain } from "./const";
|
import { Helper, HelperDomain, isHelperDomain } from "./const";
|
||||||
import type { ShowDialogHelperDetailParams } from "./show-dialog-helper-detail";
|
import type { ShowDialogHelperDetailParams } from "./show-dialog-helper-detail";
|
||||||
|
|
||||||
type HelperCreators = {
|
type HelperCreators = {
|
||||||
@ -96,7 +96,7 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
|
|
||||||
@state() private _opened = false;
|
@state() private _opened = false;
|
||||||
|
|
||||||
@state() private _domain?: HelperDomain;
|
@state() private _domain?: string;
|
||||||
|
|
||||||
@state() private _error?: string;
|
@state() private _error?: string;
|
||||||
|
|
||||||
@ -114,8 +114,12 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
this._params = params;
|
this._params = params;
|
||||||
this._domain = params.domain;
|
this._domain = params.domain;
|
||||||
this._item = undefined;
|
this._item = undefined;
|
||||||
|
if (this._domain && this._domain in HELPERS) {
|
||||||
|
await HELPERS[this._domain].import();
|
||||||
|
}
|
||||||
this._opened = true;
|
this._opened = true;
|
||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
|
this.hass.loadFragmentTranslation("config");
|
||||||
Promise.all([
|
Promise.all([
|
||||||
getConfigFlowHandlers(this.hass, ["helper"]),
|
getConfigFlowHandlers(this.hass, ["helper"]),
|
||||||
// Ensure the titles are loaded before we render the flows.
|
// Ensure the titles are loaded before we render the flows.
|
||||||
@ -141,7 +145,7 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
if (this._domain) {
|
if (this._domain) {
|
||||||
content = html`
|
content = html`
|
||||||
<div class="form" @value-changed=${this._valueChanged}>
|
<div class="form" @value-changed=${this._valueChanged}>
|
||||||
${this._error ? html` <div class="error">${this._error}</div> ` : ""}
|
${this._error ? html`<div class="error">${this._error}</div>` : ""}
|
||||||
${dynamicElement(`ha-${this._domain}-form`, {
|
${dynamicElement(`ha-${this._domain}-form`, {
|
||||||
hass: this.hass,
|
hass: this.hass,
|
||||||
item: this._item,
|
item: this._item,
|
||||||
@ -155,13 +159,15 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
>
|
>
|
||||||
${this.hass!.localize("ui.panel.config.helpers.dialog.create")}
|
${this.hass!.localize("ui.panel.config.helpers.dialog.create")}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
<mwc-button
|
${this._params?.domain
|
||||||
slot="secondaryAction"
|
? nothing
|
||||||
@click=${this._goBack}
|
: html`<mwc-button
|
||||||
.disabled=${this._submitting}
|
slot="secondaryAction"
|
||||||
>
|
@click=${this._goBack}
|
||||||
${this.hass!.localize("ui.common.back")}
|
.disabled=${this._submitting}
|
||||||
</mwc-button>
|
>
|
||||||
|
${this.hass!.localize("ui.common.back")}
|
||||||
|
</mwc-button>`}
|
||||||
`;
|
`;
|
||||||
} else if (this._loading || this._helperFlows === undefined) {
|
} else if (this._loading || this._helperFlows === undefined) {
|
||||||
content = html`<ha-circular-progress
|
content = html`<ha-circular-progress
|
||||||
@ -253,9 +259,13 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
"ui.panel.config.helpers.dialog.create_platform",
|
"ui.panel.config.helpers.dialog.create_platform",
|
||||||
{
|
{
|
||||||
platform:
|
platform:
|
||||||
this.hass.localize(
|
(isHelperDomain(this._domain) &&
|
||||||
`ui.panel.config.helpers.types.${this._domain}`
|
this.hass.localize(
|
||||||
) || this._domain,
|
`ui.panel.config.helpers.types.${
|
||||||
|
this._domain as HelperDomain
|
||||||
|
}`
|
||||||
|
)) ||
|
||||||
|
this._domain,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
: this.hass.localize("ui.panel.config.helpers.dialog.create_helper")
|
: this.hass.localize("ui.panel.config.helpers.dialog.create_helper")
|
||||||
@ -277,7 +287,16 @@ export class DialogHelperDetail extends LitElement {
|
|||||||
this._submitting = true;
|
this._submitting = true;
|
||||||
this._error = "";
|
this._error = "";
|
||||||
try {
|
try {
|
||||||
await HELPERS[this._domain].create(this.hass, this._item);
|
const createdEntity = await HELPERS[this._domain].create(
|
||||||
|
this.hass,
|
||||||
|
this._item
|
||||||
|
);
|
||||||
|
if (this._params?.dialogClosedCallback && createdEntity.id) {
|
||||||
|
this._params.dialogClosedCallback({
|
||||||
|
flowFinished: true,
|
||||||
|
entityId: `${this._domain}.${createdEntity.id}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
this.closeDialog();
|
this.closeDialog();
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this._error = err.message || "Unknown error";
|
this._error = err.message || "Unknown error";
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
import { DataEntryFlowDialogParams } from "../../../dialogs/config-flow/show-dialog-data-entry-flow";
|
|
||||||
import { HelperDomain } from "./const";
|
|
||||||
|
|
||||||
export const loadHelperDetailDialog = () => import("./dialog-helper-detail");
|
export const loadHelperDetailDialog = () => import("./dialog-helper-detail");
|
||||||
|
|
||||||
export interface ShowDialogHelperDetailParams {
|
export interface ShowDialogHelperDetailParams {
|
||||||
domain?: HelperDomain;
|
domain?: string;
|
||||||
// Only used for config entries
|
dialogClosedCallback?: (params: {
|
||||||
dialogClosedCallback?: DataEntryFlowDialogParams["dialogClosedCallback"];
|
flowFinished: boolean;
|
||||||
|
entryId?: string;
|
||||||
|
entityId?: string;
|
||||||
|
}) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const showHelperDetailDialog = (
|
export const showHelperDetailDialog = (
|
||||||
|
@ -472,7 +472,9 @@
|
|||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
"no_entities": "You don't have any entities",
|
"no_entities": "You don't have any entities",
|
||||||
"no_match": "No matching entities found",
|
"no_match": "No matching entities found",
|
||||||
"show_entities": "Show entities"
|
"show_entities": "Show entities",
|
||||||
|
"new_entity": "Create a new entity",
|
||||||
|
"create_helper": "Create a new {domain, select, \n undefined {} \n other {{domain} }\n } helper."
|
||||||
},
|
},
|
||||||
"entity-attribute-picker": {
|
"entity-attribute-picker": {
|
||||||
"attribute": "Attribute",
|
"attribute": "Attribute",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user