mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-26 18:56:39 +00:00
Make config flow previews more generic (#21382)
* Make config flow previews more generic
This commit is contained in:
parent
29aa57229c
commit
dbc2db2591
@ -1,10 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
HassEntityAttributeBase,
|
HassEntityAttributeBase,
|
||||||
HassEntityBase,
|
HassEntityBase,
|
||||||
UnsubscribeFunc,
|
|
||||||
} from "home-assistant-js-websocket";
|
} from "home-assistant-js-websocket";
|
||||||
import { computeDomain } from "../common/entity/compute_domain";
|
import { computeDomain } from "../common/entity/compute_domain";
|
||||||
import { HomeAssistant } from "../types";
|
|
||||||
|
|
||||||
interface GroupEntityAttributes extends HassEntityAttributeBase {
|
interface GroupEntityAttributes extends HassEntityAttributeBase {
|
||||||
entity_id: string[];
|
entity_id: string[];
|
||||||
@ -17,11 +15,6 @@ export interface GroupEntity extends HassEntityBase {
|
|||||||
attributes: GroupEntityAttributes;
|
attributes: GroupEntityAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupPreview {
|
|
||||||
state: string;
|
|
||||||
attributes: Record<string, any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const computeGroupDomain = (
|
export const computeGroupDomain = (
|
||||||
stateObj: GroupEntity
|
stateObj: GroupEntity
|
||||||
): string | undefined => {
|
): string | undefined => {
|
||||||
@ -31,17 +24,3 @@ export const computeGroupDomain = (
|
|||||||
];
|
];
|
||||||
return uniqueDomains.length === 1 ? uniqueDomains[0] : undefined;
|
return uniqueDomains.length === 1 ? uniqueDomains[0] : undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const subscribePreviewGroup = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
flow_id: string,
|
|
||||||
flow_type: "config_flow" | "options_flow",
|
|
||||||
user_input: Record<string, any>,
|
|
||||||
callback: (preview: GroupPreview) => void
|
|
||||||
): Promise<UnsubscribeFunc> =>
|
|
||||||
hass.connection.subscribeMessage(callback, {
|
|
||||||
type: "group/start_preview",
|
|
||||||
flow_id,
|
|
||||||
flow_type,
|
|
||||||
user_input,
|
|
||||||
});
|
|
||||||
|
@ -1,21 +1,27 @@
|
|||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
||||||
import { HomeAssistant } from "../types";
|
import { HomeAssistant } from "../types";
|
||||||
|
|
||||||
export interface ThresholdPreview {
|
const HAS_CUSTOM_PREVIEW = ["template"];
|
||||||
|
|
||||||
|
export interface GenericPreview {
|
||||||
state: string;
|
state: string;
|
||||||
attributes: Record<string, any>;
|
attributes: Record<string, any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const subscribePreviewThreshold = (
|
export const subscribePreviewGeneric = (
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
domain: string,
|
||||||
flow_id: string,
|
flow_id: string,
|
||||||
flow_type: "config_flow" | "options_flow",
|
flow_type: "config_flow" | "options_flow",
|
||||||
user_input: Record<string, any>,
|
user_input: Record<string, any>,
|
||||||
callback: (preview: ThresholdPreview) => void
|
callback: (preview: GenericPreview) => void
|
||||||
): Promise<UnsubscribeFunc> =>
|
): Promise<UnsubscribeFunc> =>
|
||||||
hass.connection.subscribeMessage(callback, {
|
hass.connection.subscribeMessage(callback, {
|
||||||
type: "threshold/start_preview",
|
type: `${domain}/start_preview`,
|
||||||
flow_id,
|
flow_id,
|
||||||
flow_type,
|
flow_type,
|
||||||
user_input,
|
user_input,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const previewModule = (domain: string): string =>
|
||||||
|
HAS_CUSTOM_PREVIEW.includes(domain) ? domain : "generic";
|
@ -1,21 +0,0 @@
|
|||||||
import { UnsubscribeFunc } from "home-assistant-js-websocket";
|
|
||||||
import { HomeAssistant } from "../types";
|
|
||||||
|
|
||||||
export interface TimeDatePreview {
|
|
||||||
state: string;
|
|
||||||
attributes: Record<string, any>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const subscribePreviewTimeDate = (
|
|
||||||
hass: HomeAssistant,
|
|
||||||
flow_id: string,
|
|
||||||
flow_type: "config_flow" | "options_flow",
|
|
||||||
user_input: Record<string, any>,
|
|
||||||
callback: (preview: TimeDatePreview) => void
|
|
||||||
): Promise<UnsubscribeFunc> =>
|
|
||||||
hass.connection.subscribeMessage(callback, {
|
|
||||||
type: "time_date/start_preview",
|
|
||||||
flow_id,
|
|
||||||
flow_type,
|
|
||||||
user_input,
|
|
||||||
});
|
|
@ -2,23 +2,22 @@ import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
|||||||
import { LitElement, html } from "lit";
|
import { LitElement, html } from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { FlowType } from "../../../data/data_entry_flow";
|
import { FlowType } from "../../../data/data_entry_flow";
|
||||||
import {
|
import { GenericPreview, subscribePreviewGeneric } from "../../../data/preview";
|
||||||
ThresholdPreview,
|
|
||||||
subscribePreviewThreshold,
|
|
||||||
} from "../../../data/threshold";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import "./entity-preview-row";
|
import "./entity-preview-row";
|
||||||
import { debounce } from "../../../common/util/debounce";
|
import { debounce } from "../../../common/util/debounce";
|
||||||
import { fireEvent } from "../../../common/dom/fire_event";
|
import { fireEvent } from "../../../common/dom/fire_event";
|
||||||
|
|
||||||
@customElement("flow-preview-threshold")
|
@customElement("flow-preview-generic")
|
||||||
class FlowPreviewThreshold extends LitElement {
|
class FlowPreviewGeneric extends LitElement {
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
@property() public flowType!: FlowType;
|
@property() public flowType!: FlowType;
|
||||||
|
|
||||||
public handler!: string;
|
public handler!: string;
|
||||||
|
|
||||||
|
@property() public domain!: string;
|
||||||
|
|
||||||
@property() public stepId!: string;
|
@property() public stepId!: string;
|
||||||
|
|
||||||
@property() public flowId!: string;
|
@property() public flowId!: string;
|
||||||
@ -55,7 +54,7 @@ class FlowPreviewThreshold extends LitElement {
|
|||||||
></entity-preview-row>`;
|
></entity-preview-row>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setPreview = (preview: ThresholdPreview) => {
|
private _setPreview = (preview: GenericPreview) => {
|
||||||
const now = new Date().toISOString();
|
const now = new Date().toISOString();
|
||||||
this._preview = {
|
this._preview = {
|
||||||
entity_id: `${this.stepId}.___flow_preview___`,
|
entity_id: `${this.stepId}.___flow_preview___`,
|
||||||
@ -79,14 +78,14 @@ class FlowPreviewThreshold extends LitElement {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this._unsub = subscribePreviewThreshold(
|
this._unsub = subscribePreviewGeneric(
|
||||||
this.hass,
|
this.hass,
|
||||||
|
this.domain,
|
||||||
this.flowId,
|
this.flowId,
|
||||||
this.flowType,
|
this.flowType,
|
||||||
this.stepData,
|
this.stepData,
|
||||||
this._setPreview
|
this._setPreview
|
||||||
);
|
);
|
||||||
await this._unsub;
|
|
||||||
fireEvent(this, "set-flow-errors", { errors: {} });
|
fireEvent(this, "set-flow-errors", { errors: {} });
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (typeof err.message === "string") {
|
if (typeof err.message === "string") {
|
||||||
@ -103,6 +102,6 @@ class FlowPreviewThreshold extends LitElement {
|
|||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface HTMLElementTagNameMap {
|
interface HTMLElementTagNameMap {
|
||||||
"flow-preview-threshold": FlowPreviewThreshold;
|
"flow-preview-generic": FlowPreviewGeneric;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,90 +0,0 @@
|
|||||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
|
||||||
import { LitElement, html } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import { FlowType } from "../../../data/data_entry_flow";
|
|
||||||
import { GroupPreview, subscribePreviewGroup } from "../../../data/group";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import "./entity-preview-row";
|
|
||||||
import { debounce } from "../../../common/util/debounce";
|
|
||||||
|
|
||||||
@customElement("flow-preview-group")
|
|
||||||
class FlowPreviewGroup extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property() public flowType!: FlowType;
|
|
||||||
|
|
||||||
public handler!: string;
|
|
||||||
|
|
||||||
@property() public stepId!: string;
|
|
||||||
|
|
||||||
@property() public flowId!: string;
|
|
||||||
|
|
||||||
@property({ attribute: false }) public stepData!: Record<string, any>;
|
|
||||||
|
|
||||||
@state() private _preview?: HassEntity;
|
|
||||||
|
|
||||||
private _unsub?: Promise<UnsubscribeFunc>;
|
|
||||||
|
|
||||||
disconnectedCallback(): void {
|
|
||||||
super.disconnectedCallback();
|
|
||||||
if (this._unsub) {
|
|
||||||
this._unsub.then((unsub) => unsub());
|
|
||||||
this._unsub = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
willUpdate(changedProps) {
|
|
||||||
if (changedProps.has("stepData")) {
|
|
||||||
this._debouncedSubscribePreview();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
return html`<entity-preview-row
|
|
||||||
.hass=${this.hass}
|
|
||||||
.stateObj=${this._preview}
|
|
||||||
></entity-preview-row>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _setPreview = (preview: GroupPreview) => {
|
|
||||||
const now = new Date().toISOString();
|
|
||||||
this._preview = {
|
|
||||||
entity_id: `${this.stepId}.___flow_preview___`,
|
|
||||||
last_changed: now,
|
|
||||||
last_updated: now,
|
|
||||||
context: { id: "", parent_id: null, user_id: null },
|
|
||||||
...preview,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
private _debouncedSubscribePreview = debounce(() => {
|
|
||||||
this._subscribePreview();
|
|
||||||
}, 250);
|
|
||||||
|
|
||||||
private async _subscribePreview() {
|
|
||||||
if (this._unsub) {
|
|
||||||
(await this._unsub)();
|
|
||||||
this._unsub = undefined;
|
|
||||||
}
|
|
||||||
if (this.flowType === "repair_flow") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
this._unsub = subscribePreviewGroup(
|
|
||||||
this.hass,
|
|
||||||
this.flowId,
|
|
||||||
this.flowType,
|
|
||||||
this.stepData,
|
|
||||||
this._setPreview
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
this._preview = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"flow-preview-group": FlowPreviewGroup;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
import { HassEntity, UnsubscribeFunc } from "home-assistant-js-websocket";
|
|
||||||
import { LitElement, html } from "lit";
|
|
||||||
import { customElement, property, state } from "lit/decorators";
|
|
||||||
import { FlowType } from "../../../data/data_entry_flow";
|
|
||||||
import {
|
|
||||||
TimeDatePreview,
|
|
||||||
subscribePreviewTimeDate,
|
|
||||||
} from "../../../data/time_date";
|
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import "./entity-preview-row";
|
|
||||||
import { debounce } from "../../../common/util/debounce";
|
|
||||||
|
|
||||||
@customElement("flow-preview-time_date")
|
|
||||||
class FlowPreviewTimeDate extends LitElement {
|
|
||||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
||||||
|
|
||||||
@property() public flowType!: FlowType;
|
|
||||||
|
|
||||||
public handler!: string;
|
|
||||||
|
|
||||||
@property() public stepId!: string;
|
|
||||||
|
|
||||||
@property() public flowId!: string;
|
|
||||||
|
|
||||||
@property() public stepData!: Record<string, any>;
|
|
||||||
|
|
||||||
@state() private _preview?: HassEntity;
|
|
||||||
|
|
||||||
private _unsub?: Promise<UnsubscribeFunc>;
|
|
||||||
|
|
||||||
disconnectedCallback(): void {
|
|
||||||
super.disconnectedCallback();
|
|
||||||
if (this._unsub) {
|
|
||||||
this._unsub.then((unsub) => unsub());
|
|
||||||
this._unsub = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
willUpdate(changedProps) {
|
|
||||||
if (changedProps.has("stepData")) {
|
|
||||||
this._debouncedSubscribePreview();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected render() {
|
|
||||||
return html`<entity-preview-row
|
|
||||||
.hass=${this.hass}
|
|
||||||
.stateObj=${this._preview}
|
|
||||||
></entity-preview-row>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
private _setPreview = (preview: TimeDatePreview) => {
|
|
||||||
const now = new Date().toISOString();
|
|
||||||
this._preview = {
|
|
||||||
entity_id: `${this.stepId}.___flow_preview___`,
|
|
||||||
last_changed: now,
|
|
||||||
last_updated: now,
|
|
||||||
context: { id: "", parent_id: null, user_id: null },
|
|
||||||
...preview,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
private _debouncedSubscribePreview = debounce(() => {
|
|
||||||
this._subscribePreview();
|
|
||||||
}, 250);
|
|
||||||
|
|
||||||
private async _subscribePreview() {
|
|
||||||
if (this._unsub) {
|
|
||||||
(await this._unsub)();
|
|
||||||
this._unsub = undefined;
|
|
||||||
}
|
|
||||||
if (this.flowType === "repair_flow") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
this._unsub = subscribePreviewTimeDate(
|
|
||||||
this.hass,
|
|
||||||
this.flowId,
|
|
||||||
this.flowType,
|
|
||||||
this.stepData,
|
|
||||||
this._setPreview
|
|
||||||
);
|
|
||||||
await this._unsub;
|
|
||||||
} catch (err) {
|
|
||||||
this._preview = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare global {
|
|
||||||
interface HTMLElementTagNameMap {
|
|
||||||
"flow-preview-time_date": FlowPreviewTimeDate;
|
|
||||||
}
|
|
||||||
}
|
|
@ -25,6 +25,7 @@ import type { HomeAssistant } from "../../types";
|
|||||||
import type { FlowConfig } from "./show-dialog-data-entry-flow";
|
import type { FlowConfig } from "./show-dialog-data-entry-flow";
|
||||||
import { configFlowContentStyles } from "./styles";
|
import { configFlowContentStyles } from "./styles";
|
||||||
import { haStyle } from "../../resources/styles";
|
import { haStyle } from "../../resources/styles";
|
||||||
|
import { previewModule } from "../../data/preview";
|
||||||
|
|
||||||
@customElement("step-flow-form")
|
@customElement("step-flow-form")
|
||||||
class StepFlowForm extends LitElement {
|
class StepFlowForm extends LitElement {
|
||||||
@ -76,8 +77,9 @@ class StepFlowForm extends LitElement {
|
|||||||
"ui.panel.config.integrations.config_flow.preview"
|
"ui.panel.config.integrations.config_flow.preview"
|
||||||
)}:
|
)}:
|
||||||
</h3>
|
</h3>
|
||||||
${dynamicElement(`flow-preview-${this.step.preview}`, {
|
${dynamicElement(`flow-preview-${previewModule(step.preview)}`, {
|
||||||
hass: this.hass,
|
hass: this.hass,
|
||||||
|
domain: step.preview,
|
||||||
flowType: this.flowConfig.flowType,
|
flowType: this.flowConfig.flowType,
|
||||||
handler: step.handler,
|
handler: step.handler,
|
||||||
stepId: step.step_id,
|
stepId: step.step_id,
|
||||||
@ -120,7 +122,7 @@ class StepFlowForm extends LitElement {
|
|||||||
protected willUpdate(changedProps: PropertyValues): void {
|
protected willUpdate(changedProps: PropertyValues): void {
|
||||||
super.willUpdate(changedProps);
|
super.willUpdate(changedProps);
|
||||||
if (changedProps.has("step") && this.step?.preview) {
|
if (changedProps.has("step") && this.step?.preview) {
|
||||||
import(`./previews/flow-preview-${this.step.preview}`);
|
import(`./previews/flow-preview-${previewModule(this.step.preview)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user