mirror of
https://github.com/home-assistant/frontend.git
synced 2025-11-10 03:19:44 +00:00
Improve automation save dialog when leaving editor dirty (#23589)
* Improve automation save dialog when leaving editor dirty * Make CI happy
This commit is contained in:
committed by
GitHub
parent
27d683f6e8
commit
09102d34d6
@@ -0,0 +1,391 @@
|
||||
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 "../../../../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 "../../../../components/ha-area-picker";
|
||||
|
||||
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
||||
import { haStyle, haStyleDialog } from "../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type {
|
||||
EntityRegistryUpdate,
|
||||
SaveDialogParams,
|
||||
} from "./show-dialog-automation-save";
|
||||
|
||||
@customElement("ha-dialog-automation-save")
|
||||
class DialogAutomationSave extends LitElement implements HassDialog {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _opened = false;
|
||||
|
||||
@state() private _error?: string;
|
||||
|
||||
@state() private _visibleOptionals: string[] = [];
|
||||
|
||||
@state() private _entryUpdates!: EntityRegistryUpdate;
|
||||
|
||||
private _params!: SaveDialogParams;
|
||||
|
||||
private _newName?: string;
|
||||
|
||||
private _newIcon?: string;
|
||||
|
||||
private _newDescription?: string;
|
||||
|
||||
public showDialog(params: SaveDialogParams): void {
|
||||
this._opened = true;
|
||||
this._params = params;
|
||||
this._newIcon = "icon" in params.config ? params.config.icon : undefined;
|
||||
this._newName =
|
||||
params.config.alias ||
|
||||
this.hass.localize(
|
||||
`ui.panel.config.${this._params.domain}.editor.default_name`
|
||||
);
|
||||
this._newDescription = params.config.description || "";
|
||||
this._entryUpdates = params.entityRegistryUpdate || {
|
||||
area: params.entityRegistryEntry?.area_id || "",
|
||||
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" : "",
|
||||
this._entryUpdates.area ? "area" : "",
|
||||
];
|
||||
}
|
||||
|
||||
public closeDialog() {
|
||||
this._params.onClose();
|
||||
|
||||
if (this._opened) {
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
this._opened = false;
|
||||
this._visibleOptionals = [];
|
||||
return true;
|
||||
}
|
||||
|
||||
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 _renderDiscard() {
|
||||
if (!this._params.onDiscard) {
|
||||
return nothing;
|
||||
}
|
||||
return html`
|
||||
<ha-button
|
||||
@click=${this._handleDiscard}
|
||||
slot="secondaryAction"
|
||||
class="destructive"
|
||||
>
|
||||
${this.hass.localize("ui.common.dont_save")}
|
||||
</ha-button>
|
||||
`;
|
||||
}
|
||||
|
||||
protected _renderInputs() {
|
||||
if (this._params.hideInputs) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`
|
||||
<ha-textfield
|
||||
dialogInitialFocus
|
||||
.value=${this._newName}
|
||||
.placeholder=${this.hass.localize(
|
||||
`ui.panel.config.${this._params.domain}.editor.default_name`
|
||||
)}
|
||||
.label=${this.hass.localize("ui.panel.config.automation.editor.alias")}
|
||||
required
|
||||
type="string"
|
||||
@input=${this._valueChanged}
|
||||
></ha-textfield>
|
||||
|
||||
${this._params.domain === "script" &&
|
||||
this._visibleOptionals.includes("icon")
|
||||
? html`
|
||||
<ha-icon-picker
|
||||
.hass=${this.hass}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.icon"
|
||||
)}
|
||||
.value=${this._newIcon}
|
||||
@value-changed=${this._iconChanged}
|
||||
>
|
||||
<ha-domain-icon
|
||||
slot="fallback"
|
||||
domain=${this._params.domain}
|
||||
.hass=${this.hass}
|
||||
>
|
||||
</ha-domain-icon>
|
||||
</ha-icon-picker>
|
||||
`
|
||||
: nothing}
|
||||
${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}
|
||||
${this._visibleOptionals.includes("area")
|
||||
? html` <ha-area-picker
|
||||
id="area"
|
||||
.hass=${this.hass}
|
||||
.value=${this._entryUpdates.area}
|
||||
@value-changed=${this._registryEntryChanged}
|
||||
></ha-area-picker>`
|
||||
: nothing}
|
||||
|
||||
<ha-chip-set>
|
||||
${this._renderOptionalChip(
|
||||
"description",
|
||||
this.hass.localize(
|
||||
"ui.panel.config.automation.editor.dialog.add_description"
|
||||
)
|
||||
)}
|
||||
${this._params.domain === "script"
|
||||
? this._renderOptionalChip(
|
||||
"icon",
|
||||
this.hass.localize(
|
||||
"ui.panel.config.automation.editor.dialog.add_icon"
|
||||
)
|
||||
)
|
||||
: nothing}
|
||||
${this._renderOptionalChip(
|
||||
"area",
|
||||
this.hass.localize(
|
||||
"ui.panel.config.automation.editor.dialog.add_area"
|
||||
)
|
||||
)}
|
||||
${this._renderOptionalChip(
|
||||
"category",
|
||||
this.hass.localize(
|
||||
"ui.panel.config.automation.editor.dialog.add_category"
|
||||
)
|
||||
)}
|
||||
${this._renderOptionalChip(
|
||||
"labels",
|
||||
this.hass.localize(
|
||||
"ui.panel.config.automation.editor.dialog.add_labels"
|
||||
)
|
||||
)}
|
||||
</ha-chip-set>
|
||||
`;
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._opened) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const title = this.hass.localize(
|
||||
this._params.config.alias
|
||||
? "ui.panel.config.automation.editor.rename"
|
||||
: "ui.panel.config.automation.editor.save"
|
||||
);
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
scrimClickAction
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${title}
|
||||
>
|
||||
<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._params.title || title}</span>
|
||||
</ha-dialog-header>
|
||||
${this._error
|
||||
? html`<ha-alert alert-type="error"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.automation.editor.missing_name"
|
||||
)}</ha-alert
|
||||
>`
|
||||
: ""}
|
||||
${this._params.description
|
||||
? html`<p>${this._params.description}</p>`
|
||||
: nothing}
|
||||
${this._renderInputs()} ${this._renderDiscard()}
|
||||
|
||||
<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 && !this._params.onDiscard
|
||||
? "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;
|
||||
}
|
||||
|
||||
private _valueChanged(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
const target = ev.target as any;
|
||||
if (target.name === "description") {
|
||||
this._newDescription = target.value;
|
||||
} else {
|
||||
this._newName = target.value;
|
||||
}
|
||||
}
|
||||
|
||||
private _handleDiscard() {
|
||||
this._params.onDiscard?.();
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
private async _save(): Promise<void> {
|
||||
if (!this._newName) {
|
||||
this._error = "Name is required";
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._params.domain === "script") {
|
||||
await this._params.updateConfig(
|
||||
{
|
||||
...this._params.config,
|
||||
alias: this._newName,
|
||||
description: this._newDescription,
|
||||
icon: this._newIcon,
|
||||
},
|
||||
this._entryUpdates
|
||||
);
|
||||
} else {
|
||||
await this._params.updateConfig(
|
||||
{
|
||||
...this._params.config,
|
||||
alias: this._newName,
|
||||
description: this._newDescription,
|
||||
},
|
||||
this._entryUpdates
|
||||
);
|
||||
}
|
||||
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-dialog {
|
||||
--dialog-content-padding: 0 24px 24px 24px;
|
||||
}
|
||||
|
||||
@media all and (min-width: 500px) {
|
||||
ha-dialog {
|
||||
--mdc-dialog-min-width: min(500px, 95vw);
|
||||
--mdc-dialog-max-width: min(500px, 95vw);
|
||||
}
|
||||
}
|
||||
|
||||
ha-textfield,
|
||||
ha-textarea,
|
||||
ha-icon-picker,
|
||||
ha-category-picker,
|
||||
ha-labels-picker,
|
||||
ha-area-picker {
|
||||
display: block;
|
||||
}
|
||||
ha-icon-picker,
|
||||
ha-category-picker,
|
||||
ha-labels-picker,
|
||||
ha-area-picker,
|
||||
ha-chip-set {
|
||||
margin-top: 16px;
|
||||
}
|
||||
ha-alert {
|
||||
display: block;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.destructive {
|
||||
--mdc-theme-primary: var(--error-color);
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ha-dialog-automation-save": DialogAutomationSave;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user