mirror of
https://github.com/home-assistant/frontend.git
synced 2026-04-02 08:33:31 +01:00
Move loadConfig to common mixin (#30171)
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import "@home-assistant/webawesome/dist/components/divider/divider";
|
||||
import { consume } from "@lit/context";
|
||||
import {
|
||||
mdiAppleKeyboardCommand,
|
||||
mdiCog,
|
||||
@@ -24,7 +23,7 @@ import {
|
||||
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { customElement, property, query } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { UndoRedoController } from "../../../common/controllers/undo-redo-controller";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
@@ -57,7 +56,6 @@ import {
|
||||
} from "../../../data/automation";
|
||||
import { substituteBlueprint } from "../../../data/blueprint";
|
||||
import { validateConfig } from "../../../data/config";
|
||||
import { fullEntitiesContext } from "../../../data/context";
|
||||
import { UNAVAILABLE } from "../../../data/entity/entity";
|
||||
import {
|
||||
type EntityRegistryEntry,
|
||||
@@ -80,6 +78,7 @@ import { showAutomationModeDialog } from "./automation-mode-dialog/show-dialog-a
|
||||
import { showAutomationSaveDialog } from "./automation-save-dialog/show-dialog-automation-save";
|
||||
import { showAutomationSaveTimeoutDialog } from "./automation-save-timeout-dialog/show-dialog-automation-save-timeout";
|
||||
import "./blueprint-automation-editor";
|
||||
import type { EditorDomainHooks } from "./ha-automation-script-editor-mixin";
|
||||
import {
|
||||
AutomationScriptEditorMixin,
|
||||
automationScriptEditorStyles,
|
||||
@@ -117,10 +116,6 @@ export class HaAutomationEditor extends AutomationScriptEditorMixin<AutomationCo
|
||||
|
||||
@property({ attribute: false }) public automations!: AutomationEntity[];
|
||||
|
||||
@state()
|
||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||
_entityRegistry!: EntityRegistryEntry[];
|
||||
|
||||
@query("manual-automation-editor")
|
||||
private _manualEditor?: HaManualAutomationEditor;
|
||||
|
||||
@@ -133,6 +128,13 @@ export class HaAutomationEditor extends AutomationScriptEditorMixin<AutomationCo
|
||||
|
||||
private _newAutomationId?: string;
|
||||
|
||||
protected domainHooks: EditorDomainHooks<AutomationConfig> = {
|
||||
domain: "automation",
|
||||
fetchFileConfig: fetchAutomationFileConfig,
|
||||
normalizeConfig: normalizeAutomationConfig,
|
||||
checkValidation: () => this._checkValidation(),
|
||||
};
|
||||
|
||||
private _undoRedoController = new UndoRedoController<AutomationConfig>(this, {
|
||||
apply: (config) => this._applyUndoRedo(config),
|
||||
currentConfig: () => this.config!,
|
||||
@@ -144,9 +146,9 @@ export class HaAutomationEditor extends AutomationScriptEditorMixin<AutomationCo
|
||||
if (
|
||||
this.entityRegCreated &&
|
||||
this._newAutomationId &&
|
||||
changedProps.has("_entityRegistry")
|
||||
changedProps.has("entityRegistry")
|
||||
) {
|
||||
const automation = this._entityRegistry.find(
|
||||
const automation = this.entityRegistry.find(
|
||||
(entity: EntityRegistryEntry) =>
|
||||
entity.platform === "automation" &&
|
||||
entity.unique_id === this._newAutomationId
|
||||
@@ -576,7 +578,7 @@ export class HaAutomationEditor extends AutomationScriptEditorMixin<AutomationCo
|
||||
oldAutomationId !== this.automationId
|
||||
) {
|
||||
this._setEntityId();
|
||||
this._loadConfig();
|
||||
this.loadConfig(this.automationId);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -663,49 +665,6 @@ export class HaAutomationEditor extends AutomationScriptEditorMixin<AutomationCo
|
||||
);
|
||||
}
|
||||
|
||||
private async _loadConfig() {
|
||||
try {
|
||||
const config = await fetchAutomationFileConfig(
|
||||
this.hass,
|
||||
this.automationId as string
|
||||
);
|
||||
this.dirty = false;
|
||||
this.readOnly = false;
|
||||
this.config = normalizeAutomationConfig(config);
|
||||
this._checkValidation();
|
||||
} catch (err: any) {
|
||||
if (err.status_code !== 404) {
|
||||
const alertText =
|
||||
err.body?.message || err.error || err.body || "Unknown error";
|
||||
await showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
"ui.panel.config.automation.editor.load_error_unknown",
|
||||
{ err_no: err.status_code ?? "unknown" }
|
||||
),
|
||||
text: html`<pre>${alertText}</pre>`,
|
||||
});
|
||||
goBack("/config");
|
||||
return;
|
||||
}
|
||||
const entity = this._entityRegistry.find(
|
||||
(ent) =>
|
||||
ent.platform === "automation" && ent.unique_id === this.automationId
|
||||
);
|
||||
if (entity) {
|
||||
navigate(`/config/automation/show/${entity.entity_id}`, {
|
||||
replace: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await showAlertDialog(this, {
|
||||
text: this.hass.localize(
|
||||
"ui.panel.config.automation.editor.load_error_not_editable"
|
||||
),
|
||||
});
|
||||
goBack("/config");
|
||||
}
|
||||
}
|
||||
|
||||
private _valueChanged(ev: ValueChangedEvent<AutomationConfig>) {
|
||||
ev.stopPropagation();
|
||||
|
||||
|
||||
@@ -3,11 +3,14 @@ import type { CSSResult, TemplateResult, LitElement } from "lit";
|
||||
import { css, html } from "lit";
|
||||
import { property, state } from "lit/decorators";
|
||||
import { transform } from "../../../common/decorators/transform";
|
||||
import { goBack } from "../../../common/navigate";
|
||||
import { goBack, navigate } from "../../../common/navigate";
|
||||
import { afterNextRender } from "../../../common/util/render-status";
|
||||
import { fullEntitiesContext } from "../../../data/context";
|
||||
import type { EntityRegistryEntry } from "../../../data/entity/entity_registry";
|
||||
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import {
|
||||
showAlertDialog,
|
||||
showConfirmationDialog,
|
||||
} from "../../../dialogs/generic/show-dialog-box";
|
||||
import { showMoreInfoDialog } from "../../../dialogs/more-info/show-ha-more-info-dialog";
|
||||
import type { Constructor, HomeAssistant, Route } from "../../../types";
|
||||
import type { EntityRegistryUpdate } from "./automation-save-dialog/show-dialog-automation-save";
|
||||
@@ -67,6 +70,13 @@ export const automationScriptEditorStyles: CSSResult = css`
|
||||
}
|
||||
`;
|
||||
|
||||
export interface EditorDomainHooks<TConfig> {
|
||||
fetchFileConfig(hass: HomeAssistant, id: string): Promise<TConfig>;
|
||||
normalizeConfig(raw: TConfig): TConfig;
|
||||
checkValidation(): Promise<void>;
|
||||
domain: "automation" | "script";
|
||||
}
|
||||
|
||||
export const AutomationScriptEditorMixin = <TConfig extends BaseEditorConfig>(
|
||||
superClass: Constructor<LitElement>
|
||||
) => {
|
||||
@@ -81,6 +91,10 @@ export const AutomationScriptEditorMixin = <TConfig extends BaseEditorConfig>(
|
||||
|
||||
@property({ attribute: false }) public entityId: string | null = null;
|
||||
|
||||
@state()
|
||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||
entityRegistry!: EntityRegistryEntry[];
|
||||
|
||||
@state() protected dirty = false;
|
||||
|
||||
@state() protected errors?: string;
|
||||
@@ -115,6 +129,8 @@ export const AutomationScriptEditorMixin = <TConfig extends BaseEditorConfig>(
|
||||
|
||||
protected entityRegistryUpdate?: EntityRegistryUpdate;
|
||||
|
||||
protected domainHooks!: EditorDomainHooks<TConfig>;
|
||||
|
||||
protected entityRegCreated?: (
|
||||
value: PromiseLike<EntityRegistryEntry> | EntityRegistryEntry
|
||||
) => void;
|
||||
@@ -194,6 +210,47 @@ export const AutomationScriptEditorMixin = <TConfig extends BaseEditorConfig>(
|
||||
protected confirmUnsavedChanged(): Promise<boolean> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
protected async loadConfig(id: string) {
|
||||
const hooks = this.domainHooks;
|
||||
const domain = hooks.domain;
|
||||
try {
|
||||
const config = await hooks.fetchFileConfig(this.hass, id);
|
||||
this.dirty = false;
|
||||
this.readOnly = false;
|
||||
this.config = hooks.normalizeConfig(config);
|
||||
hooks.checkValidation();
|
||||
} catch (err: any) {
|
||||
if (err.status_code !== 404) {
|
||||
const alertText =
|
||||
err.body?.message || err.body || err.error || "Unknown error";
|
||||
await showAlertDialog(this, {
|
||||
title: this.hass.localize(
|
||||
`ui.panel.config.${domain}.editor.load_error_unknown`,
|
||||
{ err_no: err.status_code ?? "unknown" }
|
||||
),
|
||||
text: html`<pre>${alertText}</pre>`,
|
||||
});
|
||||
goBack("/config");
|
||||
return;
|
||||
}
|
||||
const entity = this.entityRegistry.find(
|
||||
(ent) => ent.platform === domain && ent.unique_id === id
|
||||
);
|
||||
if (entity) {
|
||||
navigate(`/config/${domain}/show/${entity.entity_id}`, {
|
||||
replace: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await showAlertDialog(this, {
|
||||
text: this.hass.localize(
|
||||
`ui.panel.config.${domain}.editor.load_error_not_editable`
|
||||
),
|
||||
});
|
||||
goBack("/config");
|
||||
}
|
||||
}
|
||||
}
|
||||
return AutomationScriptEditorClass;
|
||||
};
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import { consume } from "@lit/context";
|
||||
import type { HassEntities } from "home-assistant-js-websocket";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { computeStateDomain } from "../../../common/entity/compute_state_domain";
|
||||
import { debounce } from "../../../common/util/debounce";
|
||||
import type { CloudStatus } from "../../../data/cloud";
|
||||
import { fullEntitiesContext } from "../../../data/context";
|
||||
import type { EntityRegistryEntry } from "../../../data/entity/entity_registry";
|
||||
import type { ScriptEntity } from "../../../data/script";
|
||||
import type { RouterOptions } from "../../../layouts/hass-router-page";
|
||||
import { HassRouterPage } from "../../../layouts/hass-router-page";
|
||||
@@ -36,10 +33,6 @@ class HaConfigScript extends HassRouterPage {
|
||||
|
||||
@property({ attribute: false }) public scripts: ScriptEntity[] = [];
|
||||
|
||||
@state()
|
||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||
_entityReg: EntityRegistryEntry[] = [];
|
||||
|
||||
protected routerOptions: RouterOptions = {
|
||||
defaultPage: "dashboard",
|
||||
routes: {
|
||||
@@ -86,7 +79,6 @@ class HaConfigScript extends HassRouterPage {
|
||||
pageEl.isWide = this.isWide;
|
||||
pageEl.route = this.routeTail;
|
||||
pageEl.showAdvanced = this.showAdvanced;
|
||||
pageEl.entityRegistry = this._entityReg;
|
||||
pageEl.cloudStatus = this.cloudStatus;
|
||||
|
||||
if (this.hass) {
|
||||
|
||||
@@ -71,6 +71,7 @@ import { showAutomationSaveDialog } from "../automation/automation-save-dialog/s
|
||||
import { showAutomationSaveTimeoutDialog } from "../automation/automation-save-timeout-dialog/show-dialog-automation-save-timeout";
|
||||
import { showAssignCategoryDialog } from "../category/show-dialog-assign-category";
|
||||
import "./blueprint-script-editor";
|
||||
import type { EditorDomainHooks } from "../automation/ha-automation-script-editor-mixin";
|
||||
import {
|
||||
AutomationScriptEditorMixin,
|
||||
automationScriptEditorStyles,
|
||||
@@ -87,13 +88,18 @@ export class HaScriptEditor extends SubscribeMixin(
|
||||
) {
|
||||
@property({ attribute: false }) public scriptId: string | null = null;
|
||||
|
||||
@property({ attribute: false }) public entityRegistry!: EntityRegistryEntry[];
|
||||
|
||||
@query("manual-script-editor")
|
||||
private _manualEditor?: HaManualScriptEditor;
|
||||
|
||||
private _newScriptId?: string;
|
||||
|
||||
protected domainHooks: EditorDomainHooks<ScriptConfig> = {
|
||||
domain: "script",
|
||||
fetchFileConfig: fetchScriptFileConfig,
|
||||
normalizeConfig: normalizeScriptConfig,
|
||||
checkValidation: () => this._checkValidation(),
|
||||
};
|
||||
|
||||
private _undoRedoController = new UndoRedoController<ScriptConfig>(this, {
|
||||
apply: (config) => this._applyUndoRedo(config),
|
||||
currentConfig: () => this.config!,
|
||||
@@ -480,6 +486,13 @@ export class HaScriptEditor extends SubscribeMixin(
|
||||
`;
|
||||
}
|
||||
|
||||
private _setEntityId() {
|
||||
const entity = this.entityRegistry.find(
|
||||
(ent) => ent.platform === "script" && ent.unique_id === this.scriptId
|
||||
);
|
||||
this.currentEntityId = entity?.entity_id;
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
super.updated(changedProps);
|
||||
|
||||
@@ -492,7 +505,8 @@ export class HaScriptEditor extends SubscribeMixin(
|
||||
// Only refresh config if we picked a new script. If same ID, don't fetch it.
|
||||
(!oldScript || oldScript !== this.scriptId)
|
||||
) {
|
||||
this._loadConfig();
|
||||
this._setEntityId();
|
||||
this.loadConfig(this.scriptId);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -500,11 +514,7 @@ export class HaScriptEditor extends SubscribeMixin(
|
||||
this.scriptId &&
|
||||
this.entityRegistry
|
||||
) {
|
||||
// find entity for when script entity id changed
|
||||
const entity = this.entityRegistry.find(
|
||||
(ent) => ent.platform === "script" && ent.unique_id === this.scriptId
|
||||
);
|
||||
this.currentEntityId = entity?.entity_id;
|
||||
this._setEntityId();
|
||||
}
|
||||
|
||||
if (changedProps.has("scriptId") && !this.scriptId && this.hass) {
|
||||
@@ -562,43 +572,6 @@ export class HaScriptEditor extends SubscribeMixin(
|
||||
);
|
||||
}
|
||||
|
||||
private async _loadConfig() {
|
||||
fetchScriptFileConfig(this.hass, this.scriptId!).then(
|
||||
(config) => {
|
||||
this.dirty = false;
|
||||
this.readOnly = false;
|
||||
this.config = normalizeScriptConfig(config);
|
||||
const entity = this.entityRegistry.find(
|
||||
(ent) => ent.platform === "script" && ent.unique_id === this.scriptId
|
||||
);
|
||||
this.currentEntityId = entity?.entity_id;
|
||||
this._checkValidation();
|
||||
},
|
||||
(resp) => {
|
||||
const entity = this.entityRegistry.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(
|
||||
"ui.panel.config.script.editor.load_error_not_editable"
|
||||
)
|
||||
: this.hass.localize(
|
||||
"ui.panel.config.script.editor.load_error_unknown",
|
||||
{ err_no: resp.status_code || resp.code }
|
||||
)
|
||||
);
|
||||
goBack("/config");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _valueChanged(ev) {
|
||||
if (this.config) {
|
||||
this._undoRedoController.commit(this.config);
|
||||
|
||||
@@ -146,8 +146,6 @@ class HaScriptPicker extends SubscribeMixin(LitElement) {
|
||||
|
||||
@property({ attribute: false }) public cloudStatus?: CloudStatus;
|
||||
|
||||
@property({ attribute: false }) public entityRegistry!: EntityRegistryEntry[];
|
||||
|
||||
@state() private _searchParms = new URLSearchParams(window.location.search);
|
||||
|
||||
@state() private _selected: string[] = [];
|
||||
@@ -933,7 +931,7 @@ ${rejected
|
||||
}
|
||||
|
||||
private _handleRowClicked(ev: HASSDomEvent<RowClickedEvent>) {
|
||||
const entry = this.entityRegistry.find((e) => e.entity_id === ev.detail.id);
|
||||
const entry = this._entityReg.find((e) => e.entity_id === ev.detail.id);
|
||||
if (entry) {
|
||||
navigate(`/config/script/edit/${entry.unique_id}`);
|
||||
} else {
|
||||
@@ -950,9 +948,7 @@ ${rejected
|
||||
}
|
||||
|
||||
private _runScript = async (script: any) => {
|
||||
const entry = this.entityRegistry.find(
|
||||
(e) => e.entity_id === script.entity_id
|
||||
);
|
||||
const entry = this._entityReg.find((e) => e.entity_id === script.entity_id);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
@@ -981,9 +977,7 @@ ${rejected
|
||||
}
|
||||
|
||||
private _showTrace(script: any) {
|
||||
const entry = this.entityRegistry.find(
|
||||
(e) => e.entity_id === script.entity_id
|
||||
);
|
||||
const entry = this._entityReg.find((e) => e.entity_id === script.entity_id);
|
||||
if (entry) {
|
||||
navigate(`/config/script/trace/${entry.unique_id}`);
|
||||
}
|
||||
@@ -1009,7 +1003,7 @@ ${rejected
|
||||
|
||||
private async _duplicate(script: any) {
|
||||
try {
|
||||
const entry = this.entityRegistry.find(
|
||||
const entry = this._entityReg.find(
|
||||
(e) => e.entity_id === script.entity_id
|
||||
);
|
||||
if (!entry) {
|
||||
@@ -1058,7 +1052,7 @@ ${rejected
|
||||
|
||||
private async _delete(script: any) {
|
||||
try {
|
||||
const entry = this.entityRegistry.find(
|
||||
const entry = this._entityReg.find(
|
||||
(e) => e.entity_id === script.entity_id
|
||||
);
|
||||
if (entry) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { repeat } from "lit/directives/repeat";
|
||||
import { consume } from "@lit/context";
|
||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
import { formatDateTimeWithSeconds } from "../../../common/datetime/format_date_time";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
@@ -44,6 +45,7 @@ import { haStyle } from "../../../resources/styles";
|
||||
import type { HomeAssistant, Route } from "../../../types";
|
||||
import { fileDownload } from "../../../util/file_download";
|
||||
import type { HaDropdownSelectEvent } from "../../../components/ha-dropdown";
|
||||
import { fullEntitiesContext } from "../../../data/context";
|
||||
|
||||
@customElement("ha-script-trace")
|
||||
export class HaScriptTrace extends LitElement {
|
||||
@@ -59,7 +61,9 @@ export class HaScriptTrace extends LitElement {
|
||||
|
||||
@property({ attribute: false }) public route!: Route;
|
||||
|
||||
@property({ attribute: false }) public entityRegistry!: EntityRegistryEntry[];
|
||||
@state()
|
||||
@consume({ context: fullEntitiesContext, subscribe: true })
|
||||
_entityRegistry!: EntityRegistryEntry[];
|
||||
|
||||
@state() private _entityId?: string;
|
||||
|
||||
@@ -346,7 +350,7 @@ export class HaScriptTrace extends LitElement {
|
||||
const params = new URLSearchParams(location.search);
|
||||
this._loadTraces(params.get("run_id") || undefined);
|
||||
|
||||
this._entityId = this.entityRegistry.find(
|
||||
this._entityId = this._entityRegistry.find(
|
||||
(entry) => entry.unique_id === this.scriptId
|
||||
)?.entity_id;
|
||||
}
|
||||
@@ -363,7 +367,7 @@ export class HaScriptTrace extends LitElement {
|
||||
if (this.scriptId) {
|
||||
this._loadTraces();
|
||||
|
||||
this._entityId = this.entityRegistry.find(
|
||||
this._entityId = this._entityRegistry.find(
|
||||
(entry) => entry.unique_id === this.scriptId
|
||||
)?.entity_id;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user