Use feature flag

This commit is contained in:
Wendelin
2025-11-25 16:56:53 +01:00
parent 6c52b2252e
commit c74d59dfc6
2 changed files with 208 additions and 155 deletions

View File

@@ -93,6 +93,7 @@ import {
fetchIntegrationManifests,
} from "../../../data/integration";
import type { LabelRegistryEntry } from "../../../data/label_registry";
import { subscribeLabFeatures } from "../../../data/labs";
import {
TARGET_SEPARATOR,
getServicesForTarget,
@@ -109,6 +110,7 @@ import {
} from "../../../data/trigger";
import type { HassDialog } from "../../../dialogs/make-dialog-manager";
import { KeyboardShortcutMixin } from "../../../mixins/keyboard-shortcut-mixin";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import type { HomeAssistant } from "../../../types";
import { isMac } from "../../../util/is_mac";
import { showToast } from "../../../util/toast";
@@ -162,7 +164,7 @@ const DYNAMIC_KEYWORDS = ["dynamicGroups", "helpers", "other"];
@customElement("add-automation-element-dialog")
class DialogAddAutomationElement
extends KeyboardShortcutMixin(LitElement)
extends KeyboardShortcutMixin(SubscribeMixin(LitElement))
implements HassDialog
{
@property({ attribute: false }) public hass!: HomeAssistant;
@@ -200,6 +202,8 @@ class DialogAddAutomationElement
@state() private _loadItemsError = false;
@state() private _newTriggersAndConditions = false;
@state() private _conditionDescriptions: ConditionDescriptions = {};
@state()
@@ -241,6 +245,20 @@ class DialogAddAutomationElement
}
}
public hassSubscribe() {
return [
subscribeLabFeatures(this.hass!.connection, (features) => {
this._newTriggersAndConditions =
features.find(
(feature) =>
feature.domain === "automation" &&
feature.preview_feature === "new_triggers_conditions"
)?.enabled ?? false;
this._tab = this._newTriggersAndConditions ? "targets" : "groups";
}),
];
}
public showDialog(params): void {
this._params = params;
@@ -293,7 +311,7 @@ class DialogAddAutomationElement
this._selectedCollectionIndex = undefined;
this._selectedGroup = undefined;
this._selectedTarget = undefined;
this._tab = "targets";
this._tab = this._newTriggersAndConditions ? "targets" : "groups";
this._filter = "";
this._manifests = undefined;
this._domains = undefined;
@@ -389,10 +407,6 @@ class DialogAddAutomationElement
const automationElementType = this._params!.type;
const tabButtons = [
{
label: this.hass.localize(`ui.panel.config.automation.editor.targets`),
value: "targets",
},
{
label: this.hass.localize(
`ui.panel.config.automation.editor.${automationElementType}s.name`
@@ -401,6 +415,13 @@ class DialogAddAutomationElement
},
];
if (this._newTriggersAndConditions) {
tabButtons.unshift({
label: this.hass.localize(`ui.panel.config.automation.editor.targets`),
value: "targets",
});
}
if (this._params?.type !== "trigger") {
tabButtons.push({
label: this.hass.localize("ui.panel.config.automation.editor.blocks"),
@@ -442,6 +463,7 @@ class DialogAddAutomationElement
`
: nothing}
${!this._filter &&
tabButtons.length > 1 &&
(!this._narrow || (!this._selectedGroup && !this._selectedTarget))
? html`<ha-button-toggle-group
variant="neutral"
@@ -483,6 +505,7 @@ class DialogAddAutomationElement
this._manifests
)}
.convertToItem=${this._convertToItem}
.newTriggersAndConditions=${this._newTriggersAndConditions}
@search-element-picked=${this._searchItemSelected}
>
</ha-automation-add-search>`

View File

@@ -67,9 +67,7 @@ import type {
} from "../add-automation-element-dialog";
import type { AddAutomationElementDialogParams } from "../show-add-automation-element-dialog";
const SEARCH_SECTIONS = [
"item",
"block",
const TARGET_SEARCH_SECTIONS = [
"separator",
"entity",
"device",
@@ -97,6 +95,9 @@ export class HaAutomationAddSearch extends LitElement {
@property({ type: Boolean }) public narrow = false;
@property({ type: Boolean, attribute: "new-triggers-and-conditions" })
public newTriggersAndConditions = false;
@property({ attribute: false })
public convertToItem!: (
key: string,
@@ -174,6 +175,7 @@ export class HaAutomationAddSearch extends LitElement {
this.filter,
this.configEntryLookup,
this.items,
this.newTriggersAndConditions,
this._selectedSearchSection
);
@@ -188,21 +190,7 @@ export class HaAutomationAddSearch extends LitElement {
}
return html`
<ha-chip-set class="sections">
${SEARCH_SECTIONS.map((section) =>
section === "separator"
? html`<div class="separator"></div>`
: this.addElementType !== "trigger" || section !== "block"
? html`<ha-filter-chip
@click=${this._toggleSection}
.section-id=${section}
.selected=${this._selectedSearchSection === section}
.label=${this._getSearchSectionLabel(section)}
>
</ha-filter-chip>`
: nothing
)}
</ha-chip-set>
${this._renderSections()}
${emptySearchTranslation
? html`<div class="empty-search">
${this.hass.localize(emptySearchTranslation as LocalizeKeys, {
@@ -236,6 +224,37 @@ export class HaAutomationAddSearch extends LitElement {
`;
}
private _renderSections() {
if (this.addElementType === "trigger" && !this.newTriggersAndConditions) {
return nothing;
}
const searchSections: ("separator" | SearchSection)[] = ["item"];
if (this.addElementType !== "trigger") {
searchSections.push("block");
}
if (this.newTriggersAndConditions) {
searchSections.push(...TARGET_SEARCH_SECTIONS);
}
return html`
<ha-chip-set class="sections">
${searchSections.map((section) =>
section === "separator"
? html`<div class="separator"></div>`
: html`<ha-filter-chip
@click=${this._toggleSection}
.section-id=${section}
.selected=${this._selectedSearchSection === section}
.label=${this._getSearchSectionLabel(section)}
>
</ha-filter-chip>`
)}
</ha-chip-set>
`;
}
private _renderSearchResultRow = (
item:
| PickerComboBoxItem
@@ -446,6 +465,7 @@ export class HaAutomationAddSearch extends LitElement {
searchTerm: string,
configEntryLookup: Record<string, ConfigEntry>,
automationItems: AddAutomationElementListItem[],
newTriggersAndConditions: boolean,
selectedSection?: SearchSection
) => {
const resultItems: (
@@ -510,146 +530,152 @@ export class HaAutomationAddSearch extends LitElement {
resultItems.push(...blocks);
}
if (!selectedSection || selectedSection === "entity") {
let entityItems = this._getEntitiesMemoized(
this.hass,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
`entity${TARGET_SEPARATOR}`
);
if (searchTerm) {
entityItems = this._filterGroup(
"entity",
entityItems,
searchTerm,
if (newTriggersAndConditions) {
if (!selectedSection || selectedSection === "entity") {
let entityItems = this._getEntitiesMemoized(
this.hass,
undefined,
(item: EntityComboBoxItem) =>
item.stateObj?.entity_id === searchTerm
) as EntityComboBoxItem[];
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
`entity${TARGET_SEPARATOR}`
);
if (searchTerm) {
entityItems = this._filterGroup(
"entity",
entityItems,
searchTerm,
undefined,
(item: EntityComboBoxItem) =>
item.stateObj?.entity_id === searchTerm
) as EntityComboBoxItem[];
}
if (!selectedSection && entityItems.length) {
// show group title
resultItems.push(
localize("ui.components.target-picker.type.entities")
);
}
resultItems.push(...entityItems);
}
if (!selectedSection && entityItems.length) {
// show group title
if (!selectedSection || selectedSection === "device") {
let deviceItems = this._getDevicesMemoized(
this.hass,
configEntryLookup,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
`device${TARGET_SEPARATOR}`
);
if (searchTerm) {
deviceItems = this._filterGroup("device", deviceItems, searchTerm);
}
if (!selectedSection && deviceItems.length) {
// show group title
resultItems.push(
localize("ui.components.target-picker.type.devices")
);
}
resultItems.push(...deviceItems);
}
if (!selectedSection || selectedSection === "area") {
let areasAndFloors = this._getAreasAndFloorsMemoized(
this.hass.states,
this.hass.floors,
this.hass.areas,
this.hass.devices,
this.hass.entities,
memoizeOne((value: AreaFloorValue): string =>
[value.type, value.id].join(TARGET_SEPARATOR)
),
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined
);
if (searchTerm) {
areasAndFloors = this._filterGroup(
"area",
areasAndFloors,
searchTerm
) as FloorComboBoxItem[];
}
if (!selectedSection && areasAndFloors.length) {
// show group title
resultItems.push(
localize("ui.components.target-picker.type.areas")
);
}
resultItems.push(
localize("ui.components.target-picker.type.entities")
...areasAndFloors.map((item, index) => {
const nextItem = areasAndFloors[index + 1];
if (
!nextItem ||
(item.type === "area" && nextItem.type === "floor")
) {
return {
...item,
last: true,
};
}
return item;
})
);
}
resultItems.push(...entityItems);
}
if (!selectedSection || selectedSection === "device") {
let deviceItems = this._getDevicesMemoized(
this.hass,
configEntryLookup,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
`device${TARGET_SEPARATOR}`
);
if (searchTerm) {
deviceItems = this._filterGroup("device", deviceItems, searchTerm);
}
if (!selectedSection && deviceItems.length) {
// show group title
resultItems.push(
localize("ui.components.target-picker.type.devices")
if (!selectedSection || selectedSection === "label") {
let labels = this._getLabelsMemoized(
this.hass.states,
this.hass.areas,
this.hass.devices,
this.hass.entities,
this._labelRegistry,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
`label${TARGET_SEPARATOR}`
);
if (searchTerm) {
labels = this._filterGroup("label", labels, searchTerm);
}
if (!selectedSection && labels.length) {
// show group title
resultItems.push(
localize("ui.components.target-picker.type.labels")
);
}
resultItems.push(...labels);
}
resultItems.push(...deviceItems);
}
if (!selectedSection || selectedSection === "area") {
let areasAndFloors = this._getAreasAndFloorsMemoized(
this.hass.states,
this.hass.floors,
this.hass.areas,
this.hass.devices,
this.hass.entities,
memoizeOne((value: AreaFloorValue): string =>
[value.type, value.id].join(TARGET_SEPARATOR)
),
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined
);
if (searchTerm) {
areasAndFloors = this._filterGroup(
"area",
areasAndFloors,
searchTerm
) as FloorComboBoxItem[];
}
if (!selectedSection && areasAndFloors.length) {
// show group title
resultItems.push(localize("ui.components.target-picker.type.areas"));
}
resultItems.push(
...areasAndFloors.map((item, index) => {
const nextItem = areasAndFloors[index + 1];
if (
!nextItem ||
(item.type === "area" && nextItem.type === "floor")
) {
return {
...item,
last: true,
};
}
return item;
})
);
}
if (!selectedSection || selectedSection === "label") {
let labels = this._getLabelsMemoized(
this.hass.states,
this.hass.areas,
this.hass.devices,
this.hass.entities,
this._labelRegistry,
undefined,
undefined,
undefined,
undefined,
undefined,
undefined,
`label${TARGET_SEPARATOR}`
);
if (searchTerm) {
labels = this._filterGroup("label", labels, searchTerm);
}
if (!selectedSection && labels.length) {
// show group title
resultItems.push(localize("ui.components.target-picker.type.labels"));
}
resultItems.push(...labels);
}
return resultItems;
@@ -1034,6 +1060,10 @@ export class HaAutomationAddSearch extends LitElement {
background-color: var(--ha-color-fill-neutral-normal-hover);
}
}
ha-svg-icon.plus {
color: var(--primary-color);
}
`;
}