Skip to content

Commit

Permalink
Add category and labels to automation/script save and rename dialog (#…
Browse files Browse the repository at this point in the history
…23240)

Co-authored-by: Bram Kragten <[email protected]>
  • Loading branch information
jpbede and bramkragten authored Dec 22, 2024
1 parent 523c38a commit 5cd6f22
Show file tree
Hide file tree
Showing 8 changed files with 355 additions and 74 deletions.
6 changes: 2 additions & 4 deletions src/common/util/debounce.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
// leading edge and on the trailing.

export const debounce = <T extends any[]>(
func: (...args: T) => void,
Expand All @@ -14,9 +14,7 @@ export const debounce = <T extends any[]>(
const debouncedFunc = (...args: T): void => {
const later = () => {
timeout = undefined;
if (!immediate) {
func(...args);
}
func(...args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
Expand Down
3 changes: 3 additions & 0 deletions src/components/ha-fab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ export class HaFab extends FabBase {
margin-inline-end: 12px;
direction: var(--direction);
}
:disabled {
opacity: var(--light-disabled-opacity);
}
`,
// safari workaround - must be explicit
mainWindow.document.dir === "rtl"
Expand Down
2 changes: 1 addition & 1 deletion src/mixins/prevent-unsaved-mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const PreventUnsavedMixin = <T extends Constructor<LitElement>>(
window.removeEventListener("beforeunload", this._handleUnload);
}

public willUpdate(changedProperties: PropertyValues): void {
protected willUpdate(changedProperties: PropertyValues): void {
super.willUpdate(changedProperties);

if (this.isDirty) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@ import "@material/mwc-button";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { mdiClose, mdiPlus } from "@mdi/js";
import { fireEvent } from "../../../../common/dom/fire_event";
import "../../../../components/ha-alert";
import { createCloseHeading } from "../../../../components/ha-dialog";
import "../../../../components/ha-domain-icon";
import "../../../../components/ha-icon-picker";
import "../../../../components/ha-textarea";
import "../../../../components/ha-textfield";
import "../../../../components/ha-labels-picker";
import "../../category/ha-category-picker";
import "../../../../components/ha-expansion-panel";
import "../../../../components/chips/ha-chip-set";
import "../../../../components/chips/ha-assist-chip";

import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
import { haStyle, haStyleDialog } from "../../../../resources/styles";
import type { HomeAssistant } from "../../../../types";
import type {
AutomationRenameDialogParams,
EntityRegistryUpdate,
ScriptRenameDialogParams,
} from "./show-dialog-automation-rename";

Expand All @@ -26,6 +32,10 @@ class DialogAutomationRename extends LitElement implements HassDialog {

@state() private _error?: string;

@state() private _visibleOptionals: string[] = [];

@state() private _entryUpdates!: EntityRegistryUpdate;

private _params!: AutomationRenameDialogParams | ScriptRenameDialogParams;

private _newName?: string;
Expand All @@ -46,6 +56,17 @@ class DialogAutomationRename extends LitElement implements HassDialog {
`ui.panel.config.${this._params.domain}.editor.default_name`
);
this._newDescription = params.config.description || "";
this._entryUpdates = params.entityRegistryUpdate || {
labels: params.entityRegistryEntry?.labels || [],
category: params.entityRegistryEntry?.categories[params.domain] || "",
};

this._visibleOptionals = [
this._newDescription ? "description" : "",
this._newIcon ? "icon" : "",
this._entryUpdates.category ? "category" : "",
this._entryUpdates.labels.length > 0 ? "labels" : "",
];
}

public closeDialog(): void {
Expand All @@ -55,6 +76,19 @@ class DialogAutomationRename extends LitElement implements HassDialog {
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
this._opened = false;
this._visibleOptionals = [];
}

protected _renderOptionalChip(id: string, label: string) {
if (this._visibleOptionals.includes(id)) {
return nothing;
}

return html`
<ha-assist-chip id=${id} @click=${this._addOptional} label=${label}>
<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon>
</ha-assist-chip>
`;
}

protected render() {
Expand All @@ -66,15 +100,27 @@ class DialogAutomationRename extends LitElement implements HassDialog {
open
scrimClickAction
@closed=${this.closeDialog}
.heading=${createCloseHeading(
this.hass,
this.hass.localize(
this._params.config.alias
? "ui.panel.config.automation.editor.rename"
: "ui.panel.config.automation.editor.save"
)
.heading=${this.hass.localize(
this._params.config.alias
? "ui.panel.config.automation.editor.rename"
: "ui.panel.config.automation.editor.save"
)}
>
<ha-dialog-header slot="heading">
<ha-icon-button
slot="navigationIcon"
dialogAction="cancel"
.label=${this.hass.localize("ui.common.close")}
.path=${mdiClose}
></ha-icon-button>
<span slot="title"
>${this.hass.localize(
this._params.config.alias
? "ui.panel.config.automation.editor.rename"
: "ui.panel.config.automation.editor.save"
)}</span
>
</ha-dialog-header>
${this._error
? html`<ha-alert alert-type="error"
>${this.hass.localize(
Expand All @@ -96,7 +142,8 @@ class DialogAutomationRename extends LitElement implements HassDialog {
@input=${this._valueChanged}
></ha-textfield>
${this._params.domain === "script"
${this._params.domain === "script" &&
this._visibleOptionals.includes("icon")
? html`
<ha-icon-picker
.hass=${this.hass}
Expand All @@ -115,33 +162,97 @@ class DialogAutomationRename extends LitElement implements HassDialog {
</ha-icon-picker>
`
: nothing}
<ha-textarea
.label=${this.hass.localize(
"ui.panel.config.automation.editor.description.label"
${this._visibleOptionals.includes("description")
? html` <ha-textarea
.label=${this.hass.localize(
"ui.panel.config.automation.editor.description.label"
)}
.placeholder=${this.hass.localize(
"ui.panel.config.automation.editor.description.placeholder"
)}
name="description"
autogrow
.value=${this._newDescription}
@input=${this._valueChanged}
></ha-textarea>`
: nothing}
${this._visibleOptionals.includes("category")
? html` <ha-category-picker
id="category"
.hass=${this.hass}
.scope=${this._params.domain}
.value=${this._entryUpdates.category}
@value-changed=${this._registryEntryChanged}
></ha-category-picker>`
: nothing}
${this._visibleOptionals.includes("labels")
? html` <ha-labels-picker
id="labels"
.hass=${this.hass}
.value=${this._entryUpdates.labels}
@value-changed=${this._registryEntryChanged}
></ha-labels-picker>`
: nothing}
<ha-chip-set>
${this._renderOptionalChip(
"description",
this.hass.localize(
"ui.panel.config.automation.editor.dialog.add_description"
)
)}
.placeholder=${this.hass.localize(
"ui.panel.config.automation.editor.description.placeholder"
${this._params.domain === "script"
? this._renderOptionalChip(
"icon",
this.hass.localize(
"ui.panel.config.automation.editor.dialog.add_icon"
)
)
: nothing}
${this._renderOptionalChip(
"category",
this.hass.localize(
"ui.panel.config.automation.editor.dialog.add_category"
)
)}
name="description"
autogrow
.value=${this._newDescription}
@input=${this._valueChanged}
></ha-textarea>
<mwc-button @click=${this.closeDialog} slot="secondaryAction">
${this.hass.localize("ui.dialogs.generic.cancel")}
</mwc-button>
<mwc-button @click=${this._save} slot="primaryAction">
${this.hass.localize(
this._params.config.alias
? "ui.panel.config.automation.editor.rename"
: "ui.panel.config.automation.editor.save"
${this._renderOptionalChip(
"labels",
this.hass.localize(
"ui.panel.config.automation.editor.dialog.add_labels"
)
)}
</mwc-button>
</ha-chip-set>
<div slot="primaryAction">
<mwc-button @click=${this.closeDialog}>
${this.hass.localize("ui.dialogs.generic.cancel")}
</mwc-button>
<mwc-button @click=${this._save}>
${this.hass.localize(
this._params.config.alias
? "ui.panel.config.automation.editor.rename"
: "ui.panel.config.automation.editor.save"
)}
</mwc-button>
</div>
</ha-dialog>
`;
}

private _addOptional(ev) {
ev.stopPropagation();
const option: string = ev.target.id;
this._visibleOptionals = [...this._visibleOptionals, option];
}

private _registryEntryChanged(ev) {
ev.stopPropagation();
const id: string = ev.target.id;
const value = ev.detail.value;

this._entryUpdates = { ...this._entryUpdates, [id]: value };
}

private _iconChanged(ev: CustomEvent) {
ev.stopPropagation();
this._newIcon = ev.detail.value || undefined;
Expand All @@ -162,19 +273,26 @@ class DialogAutomationRename extends LitElement implements HassDialog {
this._error = "Name is required";
return;
}

if (this._params.domain === "script") {
this._params.updateConfig({
...this._params.config,
alias: this._newName,
description: this._newDescription,
icon: this._newIcon,
});
this._params.updateConfig(
{
...this._params.config,
alias: this._newName,
description: this._newDescription,
icon: this._newIcon,
},
this._entryUpdates
);
} else {
this._params.updateConfig({
...this._params.config,
alias: this._newName,
description: this._newDescription,
});
this._params.updateConfig(
{
...this._params.config,
alias: this._newName,
description: this._newDescription,
},
this._entryUpdates
);
}

this.closeDialog();
Expand All @@ -185,12 +303,21 @@ class DialogAutomationRename extends LitElement implements HassDialog {
haStyle,
haStyleDialog,
css`
ha-dialog {
--dialog-content-padding: 0 24px 24px 24px;
}
ha-textfield,
ha-textarea,
ha-icon-picker {
ha-icon-picker,
ha-category-picker,
ha-labels-picker,
ha-chip-set {
display: block;
}
ha-icon-picker {
ha-icon-picker,
ha-category-picker,
ha-labels-picker,
ha-chip-set {
margin-top: 16px;
}
ha-alert {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
import { fireEvent } from "../../../../common/dom/fire_event";
import type { AutomationConfig } from "../../../../data/automation";
import type { ScriptConfig } from "../../../../data/script";
import type { EntityRegistryEntry } from "../../../../data/entity_registry";

export const loadAutomationRenameDialog = () =>
import("./dialog-automation-rename");

export interface AutomationRenameDialogParams {
interface BaseRenameDialogParams {
entityRegistryUpdate?: EntityRegistryUpdate;
entityRegistryEntry?: EntityRegistryEntry;
onClose: () => void;
}

export interface EntityRegistryUpdate {
labels: string[];
category: string;
}

export interface AutomationRenameDialogParams extends BaseRenameDialogParams {
config: AutomationConfig;
domain: "automation";
updateConfig: (config: AutomationConfig) => void;
onClose: () => void;
updateConfig: (
config: AutomationConfig,
entityRegistryUpdate: EntityRegistryUpdate
) => void;
}

export interface ScriptRenameDialogParams {
export interface ScriptRenameDialogParams extends BaseRenameDialogParams {
config: ScriptConfig;
domain: "script";
updateConfig: (config: ScriptConfig) => void;
onClose: () => void;
updateConfig: (
config: ScriptConfig,
entityRegistryUpdate: EntityRegistryUpdate
) => void;
}

export const showAutomationRenameDialog = (
Expand Down
Loading

0 comments on commit 5cd6f22

Please sign in to comment.