Automation editor tweaks (#19225)

* Automation editor tweaks

* fix styling
This commit is contained in:
Bram Kragten 2024-01-02 13:36:06 +01:00 committed by GitHub
parent c650e23432
commit 52fcf64cfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 108 additions and 42 deletions

View File

@ -46,7 +46,6 @@ export const CONDITION_GROUPS: AutomationElementGroup = {
icon: mdiDotsHorizontal, icon: mdiDotsHorizontal,
members: { members: {
template: {}, template: {},
trigger: {},
}, },
}, },
} as const; } as const;

View File

@ -1,7 +1,14 @@
import "@material/mwc-list/mwc-list"; import "@material/mwc-list/mwc-list";
import { mdiClose, mdiContentPaste, mdiPlus } from "@mdi/js"; import { mdiClose, mdiContentPaste, mdiPlus } from "@mdi/js";
import Fuse, { IFuseOptions } from "fuse.js"; import Fuse, { IFuseOptions } from "fuse.js";
import { CSSResultGroup, LitElement, css, html, nothing } from "lit"; import {
CSSResultGroup,
LitElement,
PropertyValues,
css,
html,
nothing,
} from "lit";
import { customElement, property, query, state } from "lit/decorators"; import { customElement, property, query, state } from "lit/decorators";
import { ifDefined } from "lit/directives/if-defined"; import { ifDefined } from "lit/directives/if-defined";
import { repeat } from "lit/directives/repeat"; import { repeat } from "lit/directives/repeat";
@ -42,6 +49,8 @@ import {
AddAutomationElementDialogParams, AddAutomationElementDialogParams,
PASTE_VALUE, PASTE_VALUE,
} from "./show-add-automation-element-dialog"; } from "./show-add-automation-element-dialog";
import { computeDomain } from "../../../common/entity/compute_domain";
import { deepEqual } from "../../../common/util/deep-equal";
const TYPES = { const TYPES = {
trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS }, trigger: { groups: TRIGGER_GROUPS, icons: TRIGGER_ICONS },
@ -93,13 +102,15 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
@state() private _manifests?: DomainManifestLookup; @state() private _manifests?: DomainManifestLookup;
@state() private _domains?: Set<string>;
@query("ha-dialog") private _dialog?: HaDialog; @query("ha-dialog") private _dialog?: HaDialog;
private _fullScreen = false; private _fullScreen = false;
private _width?: number; @state() private _width?: number;
private _height?: number; @state() private _height?: number;
public showDialog(params): void { public showDialog(params): void {
this._params = params; this._params = params;
@ -124,6 +135,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
this._prev = undefined; this._prev = undefined;
this._filter = ""; this._filter = "";
this._manifests = undefined; this._manifests = undefined;
this._domains = undefined;
} }
private _convertToItem = ( private _convertToItem = (
@ -152,6 +164,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
private _getFilteredItems = memoizeOne( private _getFilteredItems = memoizeOne(
( (
type: AddAutomationElementDialogParams["type"], type: AddAutomationElementDialogParams["type"],
root: AddAutomationElementDialogParams["root"],
group: string | undefined, group: string | undefined,
filter: string, filter: string,
localize: LocalizeFunc, localize: LocalizeFunc,
@ -164,6 +177,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
: TYPES[type].groups[group].members! : TYPES[type].groups[group].members!
: TYPES[type].groups; : TYPES[type].groups;
if (type === "condition" && group === "other" && !root) {
groups.trigger = {};
}
const flattenGroups = (grp: AutomationElementGroup) => const flattenGroups = (grp: AutomationElementGroup) =>
Object.entries(grp).map(([key, options]) => Object.entries(grp).map(([key, options]) =>
options.members options.members
@ -191,7 +208,9 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
private _getGroupItems = memoizeOne( private _getGroupItems = memoizeOne(
( (
type: AddAutomationElementDialogParams["type"], type: AddAutomationElementDialogParams["type"],
root: AddAutomationElementDialogParams["root"],
group: string | undefined, group: string | undefined,
domains: Set<string> | undefined,
localize: LocalizeFunc, localize: LocalizeFunc,
services: HomeAssistant["services"], services: HomeAssistant["services"],
manifests?: DomainManifestLookup manifests?: DomainManifestLookup
@ -208,6 +227,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
? TYPES[type].groups[group].members! ? TYPES[type].groups[group].members!
: TYPES[type].groups; : TYPES[type].groups;
if (type === "condition" && group === "other" && !root) {
groups.trigger = {};
}
const result = Object.entries(groups).map(([key, options]) => const result = Object.entries(groups).map(([key, options]) =>
this._convertToItem(key, options, type, localize) this._convertToItem(key, options, type, localize)
); );
@ -215,15 +238,33 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
if (type === "action") { if (type === "action") {
if (!this._group) { if (!this._group) {
result.unshift( result.unshift(
...this._serviceGroups(localize, services, manifests, undefined) ...this._serviceGroups(
localize,
services,
manifests,
domains,
undefined
)
); );
} else if (this._group === "helpers") { } else if (this._group === "helpers") {
result.unshift( result.unshift(
...this._serviceGroups(localize, services, manifests, "helper") ...this._serviceGroups(
localize,
services,
manifests,
domains,
"helper"
)
); );
} else if (this._group === "other") { } else if (this._group === "other") {
result.unshift( result.unshift(
...this._serviceGroups(localize, services, manifests, "other") ...this._serviceGroups(
localize,
services,
manifests,
domains,
"other"
)
); );
} }
} }
@ -243,42 +284,44 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
} }
); );
private _serviceGroups = memoizeOne( private _serviceGroups = (
( localize: LocalizeFunc,
localize: LocalizeFunc, services: HomeAssistant["services"],
services: HomeAssistant["services"], manifests: DomainManifestLookup | undefined,
manifests: DomainManifestLookup | undefined, domains: Set<string> | undefined,
type: "helper" | "other" | undefined type: "helper" | "other" | undefined
): ListItem[] => { ): ListItem[] => {
if (!services || !manifests) { if (!services || !manifests) {
return []; return [];
}
const result: ListItem[] = [];
Object.keys(services).forEach((domain) => {
const manifest = manifests[domain];
if (
(type === undefined &&
manifest?.integration_type === "entity" &&
!ENTITY_DOMAINS_OTHER.has(domain)) ||
(type === "helper" && manifest?.integration_type === "helper") ||
(type === "other" &&
(ENTITY_DOMAINS_OTHER.has(domain) ||
!["helper", "entity"].includes(manifest?.integration_type || "")))
) {
result.push({
group: true,
icon: domainIcon(domain),
key: `${SERVICE_PREFIX}${domain}`,
name: domainToName(localize, domain, manifest),
description: "",
});
}
});
return result.sort((a, b) =>
stringCompare(a.name, b.name, this.hass.locale.language)
);
} }
); const result: ListItem[] = [];
Object.keys(services).forEach((domain) => {
const manifest = manifests[domain];
const domainUsed = !domains ? true : domains.has(domain);
if (
(type === undefined &&
manifest?.integration_type === "entity" &&
domainUsed &&
!ENTITY_DOMAINS_OTHER.has(domain)) ||
(type === "helper" && manifest?.integration_type === "helper") ||
(type === "other" &&
(ENTITY_DOMAINS_OTHER.has(domain) ||
(!domainUsed && manifest?.integration_type === "entity") ||
!["helper", "entity"].includes(manifest?.integration_type || "")))
) {
result.push({
group: true,
icon: domainIcon(domain),
key: `${SERVICE_PREFIX}${domain}`,
name: domainToName(localize, domain, manifest),
description: "",
});
}
});
return result.sort((a, b) =>
stringCompare(a.name, b.name, this.hass.locale.language)
);
};
private _services = memoizeOne( private _services = memoizeOne(
( (
@ -368,6 +411,19 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
this._height = boundingRect?.height; this._height = boundingRect?.height;
} }
protected willUpdate(changedProperties: PropertyValues): void {
if (
this._params?.type === "action" &&
changedProperties.has("hass") &&
changedProperties.get("hass")?.states !== this.hass.states
) {
const domains = new Set(Object.keys(this.hass.states).map(computeDomain));
if (!deepEqual(domains, this._domains)) {
this._domains = domains;
}
}
}
protected render() { protected render() {
if (!this._params) { if (!this._params) {
return nothing; return nothing;
@ -376,6 +432,7 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
const items = this._filter const items = this._filter
? this._getFilteredItems( ? this._getFilteredItems(
this._params.type, this._params.type,
this._params.root,
this._group, this._group,
this._filter, this._filter,
this.hass.localize, this.hass.localize,
@ -384,7 +441,9 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
) )
: this._getGroupItems( : this._getGroupItems(
this._params.type, this._params.type,
this._params.root,
this._group, this._group,
this._domains,
this.hass.localize, this.hass.localize,
this.hass.services, this.hass.services,
this._manifests this._manifests
@ -562,6 +621,10 @@ class DialogAddAutomationElement extends LitElement implements HassDialog {
ha-icon-next { ha-icon-next {
width: 24px; width: 24px;
} }
mwc-list {
max-height: 468px;
max-width: 100vw;
}
search-input { search-input {
display: block; display: block;
margin: 0 16px; margin: 0 16px;

View File

@ -203,6 +203,7 @@ export default class HaAutomationCondition extends LitElement {
showAddAutomationElementDialog(this, { showAddAutomationElementDialog(this, {
type: "condition", type: "condition",
add: this._addCondition, add: this._addCondition,
root: !this.nested,
clipboardItem: this._clipboard?.condition?.condition, clipboardItem: this._clipboard?.condition?.condition,
}); });
} }

View File

@ -168,6 +168,7 @@ export class HaDeviceCondition extends LitElement {
} }
ha-form { ha-form {
display: block;
margin-top: 24px; margin-top: 24px;
} }
`; `;

View File

@ -6,6 +6,7 @@ export interface AddAutomationElementDialogParams {
type: "trigger" | "condition" | "action"; type: "trigger" | "condition" | "action";
add: (key: string) => void; add: (key: string) => void;
clipboardItem: string | undefined; clipboardItem: string | undefined;
root?: boolean;
group?: string; group?: string;
} }
const loadDialog = () => import("./add-automation-element-dialog"); const loadDialog = () => import("./add-automation-element-dialog");

View File

@ -174,6 +174,7 @@ export class HaDeviceTrigger extends LitElement {
} }
ha-form { ha-form {
display: block;
margin-top: 24px; margin-top: 24px;
} }
`; `;