Compare commits

...

2 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
564a2e7301 Group device and entity automation items under Generic
Co-authored-by: timmo001 <28114703+timmo001@users.noreply.github.com>
2026-03-13 11:04:19 +00:00
copilot-swe-agent[bot]
054b98dfc5 Initial plan 2026-03-13 10:53:13 +00:00
4 changed files with 129 additions and 5 deletions

View File

@@ -123,6 +123,10 @@ import { showToast } from "../../../util/toast";
import "./add-automation-element/ha-automation-add-from-target";
import "./add-automation-element/ha-automation-add-items";
import "./add-automation-element/ha-automation-add-search";
import {
splitOutGenericAutomationCollections,
type AutomationDialogCollection,
} from "./split-out-generic-automation-collections";
import type { AddAutomationElementDialogParams } from "./show-add-automation-element-dialog";
import { PASTE_VALUE } from "./show-add-automation-element-dialog";
import { getTargetText } from "./target/get_target_text";
@@ -663,7 +667,7 @@ class DialogAddAutomationElement
<wa-divider></wa-divider>`
: nothing}
${collections.map(
(collection, index) => html`
(collection) => html`
${collection.titleKey && collection.groups.length
? html`<ha-section-title>
${this.hass.localize(collection.titleKey)}
@@ -677,7 +681,7 @@ class DialogAddAutomationElement
interactive
type="button"
.value=${item.key}
.index=${index}
.index=${collection.collectionIndex}
@click=${this._groupSelected}
class=${item.key === this._selectedGroup
? "selected"
@@ -956,12 +960,14 @@ class DialogAddAutomationElement
conditionDescriptions: ConditionDescriptions,
manifests?: DomainManifestLookup
): {
collectionIndex: number;
titleKey?: LocalizeKeys;
groups: AddAutomationElementListItem[];
}[] => {
const generatedCollections: any = [];
const generatedCollections: AutomationDialogCollection<AddAutomationElementListItem>[] =
[];
collections.forEach((collection) => {
collections.forEach((collection, collectionIndex) => {
let collectionGroups = Object.entries(collection.groups);
const groups: AddAutomationElementListItem[] = [];
@@ -1043,6 +1049,7 @@ class DialogAddAutomationElement
);
generatedCollections.push({
collectionIndex,
titleKey: collection.titleKey,
groups: groups.sort((a, b) => {
// make sure device is always on top
@@ -1056,7 +1063,13 @@ class DialogAddAutomationElement
}),
});
});
return generatedCollections;
return generatedCollections.flatMap((collection) =>
splitOutGenericAutomationCollections(
type,
collection,
this._newTriggersAndConditions
)
);
}
);

View File

@@ -0,0 +1,53 @@
import type { LocalizeKeys } from "../../../common/translations/localize";
interface CollectionGroupItem {
key: string;
}
export interface AutomationDialogCollection<T extends CollectionGroupItem> {
collectionIndex: number;
titleKey?: LocalizeKeys;
groups: T[];
}
const GENERIC_GROUPS = new Set(["device", "entity"]);
export const splitOutGenericAutomationCollections = <
T extends CollectionGroupItem,
>(
type: "trigger" | "condition" | "action",
collection: AutomationDialogCollection<T>,
newTriggersAndConditions: boolean
): AutomationDialogCollection<T>[] => {
if (
!newTriggersAndConditions ||
!["trigger", "condition"].includes(type) ||
!collection.groups.some((group) => GENERIC_GROUPS.has(group.key))
) {
return [collection];
}
const genericGroups = collection.groups.filter((group) =>
GENERIC_GROUPS.has(group.key)
);
const mainGroups = collection.groups.filter(
(group) => !GENERIC_GROUPS.has(group.key)
);
return [
...(mainGroups.length
? [
{
...collection,
groups: mainGroups,
},
]
: []),
{
collectionIndex: collection.collectionIndex,
titleKey: "ui.panel.config.automation.editor.generic" as LocalizeKeys,
groups: genericGroups,
},
];
};

View File

@@ -4835,6 +4835,7 @@
"none_entities": "No entities",
"template": "Template"
},
"generic": "Generic",
"triggers": {
"name": "Triggers",
"header": "When",

View File

@@ -0,0 +1,57 @@
import { assert, describe, it } from "vitest";
import { splitOutGenericAutomationCollections } from "../../../../src/panels/config/automation/split-out-generic-automation-collections";
describe("splitOutGenericAutomationCollections", () => {
it("splits device and entity into a Generic section for triggers", () => {
const result = splitOutGenericAutomationCollections(
"trigger",
{
collectionIndex: 0,
groups: [
{ key: "climate" },
{ key: "device" },
{ key: "entity" },
{ key: "time_location" },
],
},
true
);
assert.deepEqual(result, [
{
collectionIndex: 0,
groups: [{ key: "climate" }, { key: "time_location" }],
},
{
collectionIndex: 0,
titleKey: "ui.panel.config.automation.editor.generic",
groups: [{ key: "device" }, { key: "entity" }],
},
]);
});
it("does not split collections when the feature is disabled", () => {
const collection = {
collectionIndex: 0,
groups: [{ key: "device" }, { key: "entity" }],
};
assert.deepEqual(
splitOutGenericAutomationCollections("condition", collection, false),
[collection]
);
});
it("does not split action collections", () => {
const collection = {
collectionIndex: 1,
groups: [{ key: "device" }, { key: "entity" }],
};
assert.deepEqual(
splitOutGenericAutomationCollections("action", collection, true),
[collection]
);
});
});