mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 09:46:36 +00:00
Use unique id for script (#13817)
Co-authored-by: Bram Kragten <mail@bramkragten.nl>
This commit is contained in:
parent
3959a7475c
commit
fc86a66c33
@ -15,7 +15,6 @@ import {
|
||||
Describe,
|
||||
boolean,
|
||||
} from "superstruct";
|
||||
import { computeObjectId } from "../common/entity/compute_object_id";
|
||||
import { navigate } from "../common/navigate";
|
||||
import { HomeAssistant } from "../types";
|
||||
import {
|
||||
@ -278,9 +277,9 @@ export type ActionType = keyof ActionTypes;
|
||||
|
||||
export const triggerScript = (
|
||||
hass: HomeAssistant,
|
||||
entityId: string,
|
||||
scriptId: string,
|
||||
variables?: Record<string, unknown>
|
||||
) => hass.callService("script", computeObjectId(entityId), variables);
|
||||
) => hass.callService("script", scriptId, variables);
|
||||
|
||||
export const canRun = (state: ScriptEntity) => {
|
||||
if (state.state === "off") {
|
||||
|
@ -88,8 +88,8 @@ class HaConfigScript extends HassRouterPage {
|
||||
this._currentPage !== "dashboard"
|
||||
) {
|
||||
pageEl.creatingNew = undefined;
|
||||
const scriptEntityId = this.routeTail.path.substr(1);
|
||||
pageEl.scriptEntityId = scriptEntityId === "new" ? null : scriptEntityId;
|
||||
const scriptId = this.routeTail.path.substr(1);
|
||||
pageEl.scriptId = scriptId === "new" ? null : scriptId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import { property, query, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeObjectId } from "../../../common/entity/compute_object_id";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { slugify } from "../../../common/string/slugify";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
@ -68,7 +67,7 @@ import type { HaManualScriptEditor } from "./manual-script-editor";
|
||||
export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public scriptEntityId: string | null = null;
|
||||
@property() public scriptId: string | null = null;
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@ -162,7 +161,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
}
|
||||
|
||||
const schema = this._schema(
|
||||
!!this.scriptEntityId,
|
||||
!!this.scriptId,
|
||||
"use_blueprint" in this._config,
|
||||
this._config.mode
|
||||
);
|
||||
@ -183,7 +182,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
.backCallback=${this._backTapped}
|
||||
.header=${!this._config?.alias ? "" : this._config.alias}
|
||||
>
|
||||
${this.scriptEntityId && !this.narrow
|
||||
${this.scriptId && !this.narrow
|
||||
? html`
|
||||
<mwc-button @click=${this._showTrace} slot="toolbar-icon">
|
||||
${this.hass.localize(
|
||||
@ -201,7 +200,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
|
||||
<mwc-list-item
|
||||
graphic="icon"
|
||||
.disabled=${!this.scriptEntityId}
|
||||
.disabled=${!this.scriptId}
|
||||
@click=${this._showInfo}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.script.editor.show_info")}
|
||||
@ -213,16 +212,16 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
|
||||
<mwc-list-item
|
||||
graphic="icon"
|
||||
.disabled=${!this.scriptEntityId}
|
||||
.disabled=${!this.scriptId}
|
||||
@click=${this._runScript}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.script.picker.run_script")}
|
||||
<ha-svg-icon slot="graphic" .path=${mdiPlay}></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
|
||||
${this.scriptEntityId && this.narrow
|
||||
${this.scriptId && this.narrow
|
||||
? html`
|
||||
<a href="/config/script/trace/${this.scriptEntityId}">
|
||||
<a href="/config/script/trace/${this.scriptId}">
|
||||
<mwc-list-item graphic="icon">
|
||||
${this.hass.localize(
|
||||
"ui.panel.config.script.editor.show_trace"
|
||||
@ -295,7 +294,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
<li divider role="separator"></li>
|
||||
|
||||
<mwc-list-item
|
||||
.disabled=${!this.scriptEntityId}
|
||||
.disabled=${!this.scriptId}
|
||||
.label=${this.hass.localize(
|
||||
"ui.panel.config.script.picker.duplicate"
|
||||
)}
|
||||
@ -310,17 +309,17 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
</mwc-list-item>
|
||||
|
||||
<mwc-list-item
|
||||
.disabled=${!this.scriptEntityId}
|
||||
.disabled=${!this.scriptId}
|
||||
aria-label=${this.hass.localize(
|
||||
"ui.panel.config.script.picker.delete"
|
||||
)}
|
||||
class=${classMap({ warning: Boolean(this.scriptEntityId) })}
|
||||
class=${classMap({ warning: Boolean(this.scriptId) })}
|
||||
graphic="icon"
|
||||
@click=${this._deleteConfirm}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.script.picker.delete")}
|
||||
<ha-svg-icon
|
||||
class=${classMap({ warning: Boolean(this.scriptEntityId) })}
|
||||
class=${classMap({ warning: Boolean(this.scriptId) })}
|
||||
slot="graphic"
|
||||
.path=${mdiDelete}
|
||||
>
|
||||
@ -430,15 +429,15 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
super.updated(changedProps);
|
||||
|
||||
const oldScript = changedProps.get("scriptEntityId");
|
||||
const oldScript = changedProps.get("scriptId");
|
||||
if (
|
||||
changedProps.has("scriptEntityId") &&
|
||||
this.scriptEntityId &&
|
||||
changedProps.has("scriptId") &&
|
||||
this.scriptId &&
|
||||
this.hass &&
|
||||
// Only refresh config if we picked a new script. If same ID, don't fetch it.
|
||||
(!oldScript || oldScript !== this.scriptEntityId)
|
||||
(!oldScript || oldScript !== this.scriptId)
|
||||
) {
|
||||
getScriptConfig(this.hass, computeObjectId(this.scriptEntityId)).then(
|
||||
getScriptConfig(this.hass, this.scriptId).then(
|
||||
(config) => {
|
||||
// Normalize data: ensure sequence is a list
|
||||
// Happens when people copy paste their scripts into the config
|
||||
@ -458,7 +457,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.script.editor.load_error_unknown",
|
||||
"err_no",
|
||||
resp.status_code
|
||||
resp.status_code || resp.code
|
||||
)
|
||||
);
|
||||
history.back();
|
||||
@ -466,11 +465,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
changedProps.has("scriptEntityId") &&
|
||||
!this.scriptEntityId &&
|
||||
this.hass
|
||||
) {
|
||||
if (changedProps.has("scriptId") && !this.scriptId && this.hass) {
|
||||
const initData = getScriptEditorInitData();
|
||||
this._dirty = !!initData;
|
||||
const baseConfig: Partial<ScriptConfig> = {
|
||||
@ -530,24 +525,30 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
};
|
||||
|
||||
private async _showInfo() {
|
||||
if (!this.scriptEntityId) {
|
||||
if (!this.scriptId) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "hass-more-info", { entityId: this.scriptEntityId });
|
||||
const entity = Object.values(this.hass.entities).find(
|
||||
(entry) => entry.unique_id === this.scriptId
|
||||
);
|
||||
if (!entity) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "hass-more-info", { entityId: entity.entity_id });
|
||||
}
|
||||
|
||||
private async _showTrace() {
|
||||
if (this.scriptEntityId) {
|
||||
if (this.scriptId) {
|
||||
const result = await this.confirmUnsavedChanged();
|
||||
if (result) {
|
||||
navigate(`/config/script/trace/${this.scriptEntityId}`);
|
||||
navigate(`/config/script/trace/${this.scriptId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async _runScript(ev: CustomEvent) {
|
||||
ev.stopPropagation();
|
||||
await triggerScript(this.hass, this.scriptEntityId as string);
|
||||
await triggerScript(this.hass, this.scriptId!);
|
||||
showToast(this, {
|
||||
message: this.hass.localize(
|
||||
"ui.notification_toast.triggered",
|
||||
@ -613,7 +614,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
max: isMaxMode(values.mode) ? values.max : undefined,
|
||||
};
|
||||
|
||||
if (!this.scriptEntityId) {
|
||||
if (!this.scriptId) {
|
||||
this.updateEntityId(values.id, values.alias);
|
||||
}
|
||||
|
||||
@ -720,10 +721,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
}
|
||||
|
||||
private async _delete() {
|
||||
await deleteScript(
|
||||
this.hass,
|
||||
computeObjectId(this.scriptEntityId as string)
|
||||
);
|
||||
await deleteScript(this.hass, this.scriptId!);
|
||||
history.back();
|
||||
}
|
||||
|
||||
@ -741,7 +739,7 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
}
|
||||
}
|
||||
|
||||
private _saveScript(): void {
|
||||
private async _saveScript(): Promise<void> {
|
||||
if (this._idError) {
|
||||
showToast(this, {
|
||||
message: this.hass.localize(
|
||||
@ -756,24 +754,27 @@ export class HaScriptEditor extends KeyboardShortcutMixin(LitElement) {
|
||||
});
|
||||
return;
|
||||
}
|
||||
const id = this.scriptEntityId
|
||||
? computeObjectId(this.scriptEntityId)
|
||||
: this._entityId || Date.now();
|
||||
this.hass!.callApi("POST", "config/script/config/" + id, this._config).then(
|
||||
() => {
|
||||
this._dirty = false;
|
||||
if (!this.scriptEntityId) {
|
||||
navigate(`/config/script/edit/${id}`, { replace: true });
|
||||
}
|
||||
},
|
||||
(errors) => {
|
||||
this._errors = errors.body.message || errors.error || errors.body;
|
||||
showToast(this, {
|
||||
message: errors.body.message || errors.error || errors.body,
|
||||
});
|
||||
throw errors;
|
||||
}
|
||||
);
|
||||
|
||||
const id = this.scriptId || this._entityId || Date.now();
|
||||
try {
|
||||
await this.hass!.callApi(
|
||||
"POST",
|
||||
"config/script/config/" + id,
|
||||
this._config
|
||||
);
|
||||
} catch (errors: any) {
|
||||
this._errors = errors.body.message || errors.error || errors.body;
|
||||
showToast(this, {
|
||||
message: errors.body.message || errors.error || errors.body,
|
||||
});
|
||||
throw errors;
|
||||
}
|
||||
|
||||
this._dirty = false;
|
||||
|
||||
if (!this.scriptId) {
|
||||
navigate(`/config/script/edit/${id}`, { replace: true });
|
||||
}
|
||||
}
|
||||
|
||||
protected handleKeyboardSave() {
|
||||
|
@ -13,7 +13,6 @@ import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { formatDateTime } from "../../../common/datetime/format_date_time";
|
||||
import { fireEvent, HASSDomEvent } from "../../../common/dom/fire_event";
|
||||
import { computeObjectId } from "../../../common/entity/compute_object_id";
|
||||
import { computeStateName } from "../../../common/entity/compute_state_name";
|
||||
import { navigate } from "../../../common/navigate";
|
||||
import { computeRTL } from "../../../common/util/compute_rtl";
|
||||
@ -252,11 +251,15 @@ class HaScriptPicker extends LitElement {
|
||||
}
|
||||
|
||||
private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
|
||||
navigate(`/config/script/edit/${ev.detail.id}`);
|
||||
const entry = this.hass.entities[ev.detail.id];
|
||||
if (entry) {
|
||||
navigate(`/config/script/edit/${entry.unique_id}`);
|
||||
}
|
||||
}
|
||||
|
||||
private _runScript = async (script: any) => {
|
||||
await triggerScript(this.hass, script.entity_id);
|
||||
const entry = this.hass.entities[script.entity_id];
|
||||
await triggerScript(this.hass, entry.unique_id);
|
||||
showToast(this, {
|
||||
message: this.hass.localize(
|
||||
"ui.notification_toast.triggered",
|
||||
@ -271,7 +274,10 @@ class HaScriptPicker extends LitElement {
|
||||
}
|
||||
|
||||
private _showTrace(script: any) {
|
||||
navigate(`/config/script/trace/${script.entity_id}`);
|
||||
const entry = this.hass.entities[script.entity_id];
|
||||
if (entry) {
|
||||
navigate(`/config/script/trace/${entry.unique_id}`);
|
||||
}
|
||||
}
|
||||
|
||||
private _showHelp() {
|
||||
@ -294,10 +300,8 @@ class HaScriptPicker extends LitElement {
|
||||
|
||||
private async _duplicate(script: any) {
|
||||
try {
|
||||
const config = await getScriptConfig(
|
||||
this.hass,
|
||||
computeObjectId(script.entity_id)
|
||||
);
|
||||
const entry = this.hass.entities[script.entity_id];
|
||||
const config = await getScriptConfig(this.hass, entry.unique_id);
|
||||
showScriptEditor({
|
||||
...config,
|
||||
alias: `${config?.alias} (${this.hass.localize(
|
||||
@ -338,7 +342,8 @@ class HaScriptPicker extends LitElement {
|
||||
|
||||
private async _delete(script: any) {
|
||||
try {
|
||||
await deleteScript(this.hass, computeObjectId(script.entity_id));
|
||||
const entry = this.hass.entities[script.entity_id];
|
||||
await deleteScript(this.hass, entry.unique_id);
|
||||
} catch (err: any) {
|
||||
await showAlertDialog(this, {
|
||||
text:
|
||||
|
@ -44,7 +44,7 @@ import { fireEvent } from "../../../common/dom/fire_event";
|
||||
export class HaScriptTrace extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@property() public scriptEntityId!: string;
|
||||
@property() public scriptId!: string;
|
||||
|
||||
@property({ attribute: false }) public scripts!: ScriptEntity[];
|
||||
|
||||
@ -54,6 +54,8 @@ export class HaScriptTrace extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@state() private _entityId?: string;
|
||||
|
||||
@state() private _traces?: ScriptTrace[];
|
||||
|
||||
@state() private _runId?: string;
|
||||
@ -74,15 +76,15 @@ export class HaScriptTrace extends LitElement {
|
||||
@query("hat-script-graph") private _graph?: HatScriptGraph;
|
||||
|
||||
protected render(): TemplateResult {
|
||||
const stateObj = this.scriptEntityId
|
||||
? this.hass.states[this.scriptEntityId]
|
||||
const stateObj = this._entityId
|
||||
? this.hass.states[this._entityId]
|
||||
: undefined;
|
||||
|
||||
const graph = this._graph;
|
||||
const trackedNodes = graph?.trackedNodes;
|
||||
const renderedNodes = graph?.renderedNodes;
|
||||
|
||||
const title = stateObj?.attributes.friendly_name || this.scriptEntityId;
|
||||
const title = stateObj?.attributes.friendly_name || this._entityId;
|
||||
|
||||
let devButtons: TemplateResult | string = "";
|
||||
if (__DEV__) {
|
||||
@ -95,11 +97,11 @@ export class HaScriptTrace extends LitElement {
|
||||
return html`
|
||||
${devButtons}
|
||||
<hass-subpage .hass=${this.hass} .narrow=${this.narrow} .header=${title}>
|
||||
${!this.narrow && this.scriptEntityId
|
||||
${!this.narrow && this.scriptId
|
||||
? html`
|
||||
<a
|
||||
class="trace-link"
|
||||
href="/config/script/edit/${this.scriptEntityId}"
|
||||
href="/config/script/edit/${this.scriptId}"
|
||||
slot="toolbar-icon"
|
||||
>
|
||||
<mwc-button>
|
||||
@ -120,7 +122,7 @@ export class HaScriptTrace extends LitElement {
|
||||
|
||||
<mwc-list-item
|
||||
graphic="icon"
|
||||
.disabled=${!this.scriptEntityId}
|
||||
.disabled=${!stateObj}
|
||||
@click=${this._showInfo}
|
||||
>
|
||||
${this.hass.localize("ui.panel.config.script.editor.show_info")}
|
||||
@ -130,11 +132,11 @@ export class HaScriptTrace extends LitElement {
|
||||
></ha-svg-icon>
|
||||
</mwc-list-item>
|
||||
|
||||
${this.narrow && this.scriptEntityId
|
||||
${this.narrow && this.scriptId
|
||||
? html`
|
||||
<a
|
||||
class="trace-link"
|
||||
href="/config/script/edit/${this.scriptEntityId}"
|
||||
href="/config/script/edit/${this.scriptId}"
|
||||
>
|
||||
<mwc-list-item graphic="icon">
|
||||
${this.hass.localize(
|
||||
@ -309,25 +311,33 @@ export class HaScriptTrace extends LitElement {
|
||||
protected firstUpdated(changedProps) {
|
||||
super.firstUpdated(changedProps);
|
||||
|
||||
if (!this.scriptEntityId) {
|
||||
if (!this.scriptId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams(location.search);
|
||||
this._loadTraces(params.get("run_id") || undefined);
|
||||
|
||||
this._entityId = Object.values(this.hass.entities).find(
|
||||
(entry) => entry.unique_id === this.scriptId
|
||||
)?.entity_id;
|
||||
}
|
||||
|
||||
public willUpdate(changedProps) {
|
||||
super.willUpdate(changedProps);
|
||||
|
||||
// Only reset if scriptEntityId has changed and we had one before.
|
||||
if (changedProps.get("scriptEntityId")) {
|
||||
// Only reset if scriptId has changed and we had one before.
|
||||
if (changedProps.get("scriptId")) {
|
||||
this._traces = undefined;
|
||||
this._runId = undefined;
|
||||
this._trace = undefined;
|
||||
this._logbookEntries = undefined;
|
||||
if (this.scriptEntityId) {
|
||||
if (this.scriptId) {
|
||||
this._loadTraces();
|
||||
|
||||
this._entityId = Object.values(this.hass.entities).find(
|
||||
(entry) => entry.unique_id === this.scriptId
|
||||
)?.entity_id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,11 +374,7 @@ export class HaScriptTrace extends LitElement {
|
||||
}
|
||||
|
||||
private async _loadTraces(runId?: string) {
|
||||
this._traces = await loadTraces(
|
||||
this.hass,
|
||||
"script",
|
||||
this.scriptEntityId.split(".")[1]
|
||||
);
|
||||
this._traces = await loadTraces(this.hass, "script", this.scriptId);
|
||||
// Newest will be on top.
|
||||
this._traces.reverse();
|
||||
|
||||
@ -410,7 +416,7 @@ export class HaScriptTrace extends LitElement {
|
||||
const trace = await loadTrace(
|
||||
this.hass,
|
||||
"script",
|
||||
this.scriptEntityId.split(".")[1],
|
||||
this.scriptId,
|
||||
this._runId!
|
||||
);
|
||||
this._logbookEntries = isComponentLoaded(this.hass, "logbook")
|
||||
@ -426,7 +432,7 @@ export class HaScriptTrace extends LitElement {
|
||||
|
||||
private _downloadTrace() {
|
||||
const aEl = document.createElement("a");
|
||||
aEl.download = `trace ${this.scriptEntityId} ${
|
||||
aEl.download = `trace ${this._entityId} ${
|
||||
this._trace!.timestamp.start
|
||||
}.json`;
|
||||
aEl.href = `data:application/json;charset=utf-8,${encodeURI(
|
||||
@ -476,10 +482,10 @@ export class HaScriptTrace extends LitElement {
|
||||
}
|
||||
|
||||
private async _showInfo() {
|
||||
if (!this.scriptEntityId) {
|
||||
if (!this._entityId) {
|
||||
return;
|
||||
}
|
||||
fireEvent(this, "hass-more-info", { entityId: this.scriptEntityId });
|
||||
fireEvent(this, "hass-more-info", { entityId: this._entityId });
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
|
@ -170,11 +170,7 @@ class HaLogbookRenderer extends LitElement {
|
||||
<div
|
||||
class="entry-container ${classMap({ clickable: hasTrace })}"
|
||||
.traceLink=${traceContext
|
||||
? `/config/${traceContext.domain}/trace/${
|
||||
traceContext.domain === "script"
|
||||
? `script.${traceContext.item_id}`
|
||||
: traceContext.item_id
|
||||
}?run_id=${traceContext.run_id}`
|
||||
? `/config/${traceContext.domain}/trace/${traceContext.item_id}?run_id=${traceContext.run_id}`
|
||||
: undefined}
|
||||
@click=${this._handleClick}
|
||||
>
|
||||
|
Loading…
x
Reference in New Issue
Block a user