From 7ff138534faef3e0ac91e5906515450d02042155 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Thu, 29 Sep 2022 18:11:48 +0200 Subject: [PATCH] Show non-editable scripts in UI (#13917) --- src/data/script.ts | 8 +- .../config/script/blueprint-script-editor.ts | 17 ++++ src/panels/config/script/ha-config-script.ts | 13 +++ src/panels/config/script/ha-script-editor.ts | 87 ++++++++++++++++--- src/panels/config/script/ha-script-picker.ts | 6 +- .../config/script/manual-script-editor.ts | 15 ++++ src/translations/en.json | 3 + 7 files changed, 135 insertions(+), 14 deletions(-) diff --git a/src/data/script.ts b/src/data/script.ts index ec13344714..06e31c017c 100644 --- a/src/data/script.ts +++ b/src/data/script.ts @@ -300,9 +300,15 @@ export const deleteScript = (hass: HomeAssistant, objectId: string) => let inititialScriptEditorData: Partial | undefined; -export const getScriptConfig = (hass: HomeAssistant, objectId: string) => +export const fetchScriptFileConfig = (hass: HomeAssistant, objectId: string) => hass.callApi("GET", `config/script/config/${objectId}`); +export const getScriptStateConfig = (hass: HomeAssistant, entity_id: string) => + hass.callWS<{ config: ScriptConfig }>({ + type: "script/config", + entity_id, + }); + export const showScriptEditor = (data?: Partial) => { inititialScriptEditorData = data; navigate("/config/script/edit/new"); diff --git a/src/panels/config/script/blueprint-script-editor.ts b/src/panels/config/script/blueprint-script-editor.ts index fac3a7873e..3e4f3e8ec8 100644 --- a/src/panels/config/script/blueprint-script-editor.ts +++ b/src/panels/config/script/blueprint-script-editor.ts @@ -27,6 +27,8 @@ export class HaBlueprintScriptEditor extends LitElement { @property({ reflect: true, type: Boolean }) public narrow!: boolean; + @property({ type: Boolean }) public disabled = false; + @property({ attribute: false }) public config!: BlueprintScriptConfig; @state() private _blueprints?: Blueprints; @@ -46,6 +48,14 @@ export class HaBlueprintScriptEditor extends LitElement { protected render() { const blueprint = this._blueprint; return html` + ${this.disabled + ? html` + ${this.hass.localize("ui.panel.config.script.editor.read_only")} + + ${this.hass.localize("ui.panel.config.script.editor.migrate")} + + ` + : ""} ` @@ -97,6 +108,7 @@ export class HaBlueprintScriptEditor extends LitElement { .hass=${this.hass} .selector=${value.selector} .key=${key} + .disabled=${this.disabled} .value=${(this.config.use_blueprint.input && this.config.use_blueprint.input[key]) ?? value?.default} @@ -105,6 +117,7 @@ export class HaBlueprintScriptEditor extends LitElement { : html` import("./ha-script-trace"), @@ -84,6 +87,16 @@ class HaConfigScript extends HassRouterPage { } } + if ( + (!changedProps || changedProps.has("route")) && + this._currentPage === "show" + ) { + pageEl.creatingNew = undefined; + const scriptId = this.routeTail.path.substr(1); + pageEl.entityId = scriptId === "new" ? null : scriptId; + return; + } + if ( (!changedProps || changedProps.has("route")) && this._currentPage !== "dashboard" diff --git a/src/panels/config/script/ha-script-editor.ts b/src/panels/config/script/ha-script-editor.ts index 34eb30b46d..dd81e9dd8f 100644 --- a/src/panels/config/script/ha-script-editor.ts +++ b/src/panels/config/script/ha-script-editor.ts @@ -42,7 +42,8 @@ import "../../../components/ha-yaml-editor"; import type { HaYamlEditor } from "../../../components/ha-yaml-editor"; import { deleteScript, - getScriptConfig, + getScriptStateConfig, + fetchScriptFileConfig, getScriptEditorInitData, isMaxMode, MODES, @@ -69,6 +70,8 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { @property() public scriptId: string | null = null; + @property() public entityId: string | null = null; + @property({ attribute: false }) public route!: Route; @property({ type: Boolean }) public isWide = false; @@ -87,6 +90,8 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { @state() private _mode: "gui" | "yaml" = "gui"; + @state() private _readOnly = false; + @query("ha-yaml-editor", true) private _yamlEditor?: HaYamlEditor; @query("manual-script-editor") @@ -241,7 +246,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { "ui.panel.config.automation.editor.re_order" )} graphic="icon" - .disabled=${this._mode !== "gui"} + .disabled=${this._readOnly || this._mode !== "gui"} @click=${this._toggleReOrderMode} > ${this.hass.localize( @@ -294,14 +299,20 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
  • - ${this.hass.localize("ui.panel.config.script.picker.duplicate")} + ${this.hass.localize( + this._readOnly + ? "ui.panel.config.script.editor.migrate" + : "ui.panel.config.script.editor.duplicate" + )} ` @@ -378,6 +392,8 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { .narrow=${this.narrow} .isWide=${this.isWide} .config=${this._config} + .disabled=${this._readOnly} + @duplicate=${this._duplicate} @value-changed=${this._configChanged} > `} @@ -387,6 +403,18 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { ` : this._mode === "yaml" ? html` + ${this._readOnly + ? html` + ${this.hass.localize( + "ui.panel.config.script.editor.read_only" + )} + + ${this.hass.localize( + "ui.panel.config.script.editor.migrate" + )} + + ` + : ""} ${this._errors ? html` ${this._errors} @@ -395,6 +423,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { @@ -433,11 +462,12 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { if ( changedProps.has("scriptId") && this.scriptId && + !this.entityId && this.hass && // Only refresh config if we picked a new script. If same ID, don't fetch it. (!oldScript || oldScript !== this.scriptId) ) { - getScriptConfig(this.hass, this.scriptId).then( + fetchScriptFileConfig(this.hass, this.scriptId).then( (config) => { // Normalize data: ensure sequence is a list // Happens when people copy paste their scripts into the config @@ -446,9 +476,20 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { config.sequence = [value]; } this._dirty = false; + this._readOnly = false; this._config = config; }, (resp) => { + const entity = Object.values(this.hass.entities).find( + (ent) => + ent.platform === "script" && ent.unique_id === this.scriptId + ); + if (entity) { + navigate(`/config/script/show/${entity.entity_id}`, { + replace: true, + }); + return; + } alert( resp.status_code === 404 ? this.hass.localize( @@ -478,6 +519,20 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { ...baseConfig, ...initData, } as ScriptConfig; + this._readOnly = false; + } + + if (changedProps.has("entityId") && this.entityId) { + getScriptStateConfig(this.hass, this.entityId).then((c) => { + this._config = c.config; + }); + const regEntry = this.hass.entities[this.entityId]; + if (regEntry?.unique_id) { + this.scriptId = regEntry.unique_id; + } + this._entityId = this.entityId; + this._dirty = false; + this._readOnly = true; } } @@ -603,6 +658,9 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { private _valueChanged(ev: CustomEvent) { ev.stopPropagation(); + if (this._readOnly) { + return; + } this._errors = undefined; const values = ev.detail.value as any; @@ -693,13 +751,20 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) { }; private async _duplicate() { - const result = await this.confirmUnsavedChanged(); + const result = this._readOnly + ? await showConfirmationDialog(this, { + title: "Migrate script?", + text: "You can migrate this script, so it can be edited from the UI. After it is migrated and you have saved it, you will have to manually delete your old script from your configuration. Do you want to migrate this script?", + }) + : await this.confirmUnsavedChanged(); if (result) { showScriptEditor({ ...this._config, - alias: `${this._config?.alias} (${this.hass.localize( - "ui.panel.config.script.picker.duplicate" - )})`, + alias: this._readOnly + ? this._config?.alias + : `${this._config?.alias} (${this.hass.localize( + "ui.panel.config.script.picker.duplicate" + )})`, }); } } diff --git a/src/panels/config/script/ha-script-picker.ts b/src/panels/config/script/ha-script-picker.ts index ef55423c10..c9e8dbfd85 100644 --- a/src/panels/config/script/ha-script-picker.ts +++ b/src/panels/config/script/ha-script-picker.ts @@ -27,7 +27,7 @@ import "../../../components/ha-icon-overflow-menu"; import "../../../components/ha-svg-icon"; import { deleteScript, - getScriptConfig, + fetchScriptFileConfig, showScriptEditor, triggerScript, } from "../../../data/script"; @@ -254,6 +254,8 @@ class HaScriptPicker extends LitElement { const entry = this.hass.entities[ev.detail.id]; if (entry) { navigate(`/config/script/edit/${entry.unique_id}`); + } else { + navigate(`/config/script/show/${ev.detail.id}`); } } @@ -301,7 +303,7 @@ class HaScriptPicker extends LitElement { private async _duplicate(script: any) { try { const entry = this.hass.entities[script.entity_id]; - const config = await getScriptConfig(this.hass, entry.unique_id); + const config = await fetchScriptFileConfig(this.hass, entry.unique_id); showScriptEditor({ ...config, alias: `${config?.alias} (${this.hass.localize( diff --git a/src/panels/config/script/manual-script-editor.ts b/src/panels/config/script/manual-script-editor.ts index 413abf862e..172c93ed22 100644 --- a/src/panels/config/script/manual-script-editor.ts +++ b/src/panels/config/script/manual-script-editor.ts @@ -20,6 +20,8 @@ export class HaManualScriptEditor extends LitElement { @property({ type: Boolean }) public narrow!: boolean; + @property({ type: Boolean }) public disabled = false; + @property({ attribute: false }) public config!: ScriptConfig; @property({ type: Boolean, reflect: true, attribute: "re-order-mode" }) @@ -27,6 +29,14 @@ export class HaManualScriptEditor extends LitElement { protected render() { return html` + ${this.disabled + ? html` + ${this.hass.localize("ui.panel.config.script.editor.read_only")} + + ${this.hass.localize("ui.panel.config.script.editor.migrate")} + + ` + : ""} ${this.reOrderMode ? html` `; @@ -88,6 +99,10 @@ export class HaManualScriptEditor extends LitElement { this.reOrderMode = !this.reOrderMode; } + private _duplicate() { + fireEvent(this, "duplicate"); + } + static get styles(): CSSResultGroup { return [ haStyle, diff --git a/src/translations/en.json b/src/translations/en.json index be41292a20..3aeb0dffa6 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2323,6 +2323,9 @@ "introduction": "Use scripts to run a sequence of actions.", "show_trace": "[%key:ui::panel::config::automation::editor::show_trace%]", "show_info": "[%key:ui::panel::config::automation::editor::show_info%]", + "read_only": "This script can not be edited from the UI, because it is not stored in the ''scripts.yaml'' file.", + "migrate": "Migrate", + "duplicate": "Duplicate", "header": "Script: {name}", "default_name": "New Script", "modes": {