mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-23 09:16:38 +00:00
Show non-editable scripts in UI (#13917)
This commit is contained in:
parent
0b76183acd
commit
7ff138534f
@ -300,9 +300,15 @@ export const deleteScript = (hass: HomeAssistant, objectId: string) =>
|
||||
|
||||
let inititialScriptEditorData: Partial<ScriptConfig> | undefined;
|
||||
|
||||
export const getScriptConfig = (hass: HomeAssistant, objectId: string) =>
|
||||
export const fetchScriptFileConfig = (hass: HomeAssistant, objectId: string) =>
|
||||
hass.callApi<ScriptConfig>("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<ScriptConfig>) => {
|
||||
inititialScriptEditorData = data;
|
||||
navigate("/config/script/edit/new");
|
||||
|
@ -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`<ha-alert alert-type="warning">
|
||||
${this.hass.localize("ui.panel.config.script.editor.read_only")}
|
||||
<mwc-button slot="action" @click=${this._duplicate}>
|
||||
${this.hass.localize("ui.panel.config.script.editor.migrate")}
|
||||
</mwc-button>
|
||||
</ha-alert>`
|
||||
: ""}
|
||||
<ha-card
|
||||
outlined
|
||||
class="blueprint"
|
||||
@ -64,6 +74,7 @@ export class HaBlueprintScriptEditor extends LitElement {
|
||||
)}
|
||||
.blueprints=${this._blueprints}
|
||||
.value=${this.config.use_blueprint.path}
|
||||
.disabled=${this.disabled}
|
||||
@value-changed=${this._blueprintChanged}
|
||||
></ha-blueprint-picker>
|
||||
`
|
||||
@ -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`<ha-textfield
|
||||
.key=${key}
|
||||
required
|
||||
.disabled=${this.disabled}
|
||||
.value=${(this.config.use_blueprint.input &&
|
||||
this.config.use_blueprint.input[key]) ??
|
||||
value?.default}
|
||||
@ -170,6 +183,10 @@ export class HaBlueprintScriptEditor extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _duplicate() {
|
||||
fireEvent(this, "duplicate");
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
|
@ -42,6 +42,9 @@ class HaConfigScript extends HassRouterPage {
|
||||
edit: {
|
||||
tag: "ha-script-editor",
|
||||
},
|
||||
show: {
|
||||
tag: "ha-script-editor",
|
||||
},
|
||||
trace: {
|
||||
tag: "ha-script-trace",
|
||||
load: () => 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"
|
||||
|
@ -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) {
|
||||
<li divider role="separator"></li>
|
||||
|
||||
<mwc-list-item
|
||||
.disabled=${!this.scriptId}
|
||||
.disabled=${!this._readOnly && !this.scriptId}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.script.picker.duplicate"
|
||||
this._readOnly
|
||||
? "ui.panel.config.script.editor.migrate"
|
||||
: "ui.panel.config.script.editor.duplicate"
|
||||
)}
|
||||
graphic="icon"
|
||||
@click=${this._duplicate}
|
||||
>
|
||||
${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"
|
||||
)}
|
||||
<ha-svg-icon
|
||||
slot="graphic"
|
||||
.path=${mdiContentDuplicate}
|
||||
@ -309,7 +320,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
</mwc-list-item>
|
||||
|
||||
<mwc-list-item
|
||||
.disabled=${!this.scriptId}
|
||||
.disabled=${this._readOnly || !this.scriptId}
|
||||
aria-label=${this.hass.localize(
|
||||
"ui.panel.config.script.picker.delete"
|
||||
)}
|
||||
@ -354,6 +365,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
.schema=${schema}
|
||||
.data=${data}
|
||||
.hass=${this.hass}
|
||||
.disabled=${this._readOnly}
|
||||
.computeLabel=${this._computeLabelCallback}
|
||||
.computeHelper=${this._computeHelperCallback}
|
||||
@value-changed=${this._valueChanged}
|
||||
@ -369,6 +381,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}
|
||||
></blueprint-script-editor>
|
||||
`
|
||||
@ -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}
|
||||
></manual-script-editor>
|
||||
`}
|
||||
@ -387,6 +403,18 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
`
|
||||
: this._mode === "yaml"
|
||||
? html`
|
||||
${this._readOnly
|
||||
? html`<ha-alert alert-type="warning">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.script.editor.read_only"
|
||||
)}
|
||||
<mwc-button slot="action" @click=${this._duplicate}>
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.script.editor.migrate"
|
||||
)}
|
||||
</mwc-button>
|
||||
</ha-alert>`
|
||||
: ""}
|
||||
${this._errors
|
||||
? html`
|
||||
<ha-alert alert-type="error">${this._errors}</ha-alert>
|
||||
@ -395,6 +423,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
<ha-yaml-editor
|
||||
.hass=${this.hass}
|
||||
.defaultValue=${this._preprocessYaml()}
|
||||
.readOnly=${this._readOnly}
|
||||
@value-changed=${this._yamlChanged}
|
||||
></ha-yaml-editor>
|
||||
<ha-card outlined>
|
||||
@ -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"
|
||||
)})`,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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(
|
||||
|
@ -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`<ha-alert alert-type="warning">
|
||||
${this.hass.localize("ui.panel.config.script.editor.read_only")}
|
||||
<mwc-button slot="action" @click=${this._duplicate}>
|
||||
${this.hass.localize("ui.panel.config.script.editor.migrate")}
|
||||
</mwc-button>
|
||||
</ha-alert>`
|
||||
: ""}
|
||||
${this.reOrderMode
|
||||
? html`
|
||||
<ha-alert
|
||||
@ -72,6 +82,7 @@ export class HaManualScriptEditor extends LitElement {
|
||||
@value-changed=${this._sequenceChanged}
|
||||
.hass=${this.hass}
|
||||
.narrow=${this.narrow}
|
||||
.disabled=${this.disabled}
|
||||
.reOrderMode=${this.reOrderMode}
|
||||
></ha-automation-action>
|
||||
`;
|
||||
@ -88,6 +99,10 @@ export class HaManualScriptEditor extends LitElement {
|
||||
this.reOrderMode = !this.reOrderMode;
|
||||
}
|
||||
|
||||
private _duplicate() {
|
||||
fireEvent(this, "duplicate");
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
|
@ -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": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user