Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add category and labels to automation/script save and rename dialog #23240

Merged
Merged
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
Loading