Change Data Entry Flow loading step description logic + cleanups (#9558)

* Change Data Entry Flow loading step description logic + cleanups

Fixes #6251

* Lint

* Address comment
This commit is contained in:
Bram Kragten
2021-07-15 21:07:25 +02:00
committed by GitHub
parent cc81239b9d
commit 1206e2d75f
12 changed files with 177 additions and 76 deletions

View File

@@ -10,7 +10,7 @@ import {
TemplateResult,
} from "lit";
import { customElement, state } from "lit/decorators";
import { fireEvent } from "../../common/dom/fire_event";
import { fireEvent, HASSDomEvent } from "../../common/dom/fire_event";
import { computeRTL } from "../../common/util/compute_rtl";
import "../../components/ha-circular-progress";
import "../../components/ha-dialog";
@@ -22,10 +22,10 @@ import {
subscribeAreaRegistry,
} from "../../data/area_registry";
import { fetchConfigFlowInProgress } from "../../data/config_flow";
import type {
import {
DataEntryFlowProgress,
DataEntryFlowProgressedEvent,
DataEntryFlowStep,
subscribeDataEntryFlowProgressed,
} from "../../data/data_entry_flow";
import {
DeviceRegistryEntry,
@@ -34,7 +34,10 @@ import {
import { haStyleDialog } from "../../resources/styles";
import type { HomeAssistant } from "../../types";
import { showAlertDialog } from "../generic/show-dialog-box";
import { DataEntryFlowDialogParams } from "./show-dialog-data-entry-flow";
import {
DataEntryFlowDialogParams,
LoadingReason,
} from "./show-dialog-data-entry-flow";
import "./step-flow-abort";
import "./step-flow-create-entry";
import "./step-flow-external";
@@ -46,13 +49,19 @@ import "./step-flow-progress";
let instance = 0;
interface FlowUpdateEvent {
step?: DataEntryFlowStep;
stepPromise?: Promise<DataEntryFlowStep>;
}
declare global {
// for fire event
interface HASSDomEvents {
"flow-update": {
step?: DataEntryFlowStep;
stepPromise?: Promise<DataEntryFlowStep>;
};
"flow-update": FlowUpdateEvent;
}
// for add event listener
interface HTMLElementEventMap {
"flow-update": HASSDomEvent<FlowUpdateEvent>;
}
}
@@ -62,7 +71,7 @@ class DataEntryFlowDialog extends LitElement {
@state() private _params?: DataEntryFlowDialogParams;
@state() private _loading = true;
@state() private _loading?: LoadingReason;
private _instance = instance;
@@ -86,6 +95,8 @@ class DataEntryFlowDialog extends LitElement {
private _unsubDevices?: UnsubscribeFunc;
private _unsubDataEntryFlowProgressed?: Promise<UnsubscribeFunc>;
public async showDialog(params: DataEntryFlowDialogParams): Promise<void> {
this._params = params;
this._instance = instance++;
@@ -96,7 +107,7 @@ class DataEntryFlowDialog extends LitElement {
}
if (params.continueFlowId) {
this._loading = true;
this._loading = "loading_flow";
const curInstance = this._instance;
let step: DataEntryFlowStep;
try {
@@ -124,7 +135,7 @@ class DataEntryFlowDialog extends LitElement {
}
this._processStep(step);
this._loading = false;
this._loading = undefined;
return;
}
@@ -136,14 +147,13 @@ class DataEntryFlowDialog extends LitElement {
// We only load the handlers once
if (this._handlers === undefined) {
this._loading = true;
this._loading = "loading_handlers";
try {
this._handlers = await params.flowConfig.getFlowHandlers(this.hass);
} finally {
this._loading = false;
this._loading = undefined;
}
}
await this.updateComplete;
}
public closeDialog() {
@@ -178,6 +188,12 @@ class DataEntryFlowDialog extends LitElement {
this._unsubDevices();
this._unsubDevices = undefined;
}
if (this._unsubDataEntryFlowProgressed) {
this._unsubDataEntryFlowProgressed.then((unsub) => {
unsub();
});
this._unsubDataEntryFlowProgressed = undefined;
}
fireEvent(this, "dialog-closed", { dialog: this.localName });
}
@@ -201,9 +217,11 @@ class DataEntryFlowDialog extends LitElement {
this._handler === undefined)
? html`
<step-flow-loading
.label=${this.hass.localize(
"ui.panel.config.integrations.config_flow.loading_first_time"
)}
.flowConfig=${this._params.flowConfig}
.hass=${this.hass}
.loadingReason=${this._loading || "loading_handlers"}
.handler=${this._handler}
.step=${this._step}
></step-flow-loading>
`
: this._step === undefined
@@ -269,7 +287,13 @@ class DataEntryFlowDialog extends LitElement {
`
: this._devices === undefined || this._areas === undefined
? // When it's a create entry result, we will fetch device & area registry
html` <step-flow-loading></step-flow-loading> `
html`
<step-flow-loading
.flowConfig=${this._params.flowConfig}
.hass=${this.hass}
loadingReason="loading_devices_areas"
></step-flow-loading>
`
: html`
<step-flow-create-entry
.flowConfig=${this._params.flowConfig}
@@ -287,31 +311,22 @@ class DataEntryFlowDialog extends LitElement {
protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);
this.hass.connection.subscribeEvents<DataEntryFlowProgressedEvent>(
async (ev) => {
if (ev.data.flow_id !== this._step?.flow_id) {
return;
}
const step = await this._params!.flowConfig.fetchFlow(
this.hass,
this._step?.flow_id
);
this._processStep(step);
},
"data_entry_flow_progressed"
);
this.addEventListener("flow-update", (ev) => {
const { step, stepPromise } = (ev as any).detail;
const { step, stepPromise } = ev.detail;
this._processStep(step || stepPromise);
});
}
protected updated(changedProps: PropertyValues) {
if (
changedProps.has("_step") &&
this._step &&
this._step.type === "create_entry"
) {
public willUpdate(changedProps: PropertyValues) {
super.willUpdate(changedProps);
if (!changedProps.has("_step") || !this._step) {
return;
}
if (["external", "progress"].includes(this._step.type)) {
// external and progress step will send update event from the backend, so we should subscribe to them
this._subscribeDataEntryFlowProgressed();
}
if (this._step.type === "create_entry") {
if (this._step.result && this._params!.flowConfig.loadDevicesAndAreas) {
this._fetchDevices(this._step.result.entry_id);
this._fetchAreas();
@@ -340,13 +355,16 @@ class DataEntryFlowDialog extends LitElement {
}
private async _checkFlowsInProgress(handler: string) {
this._loading = true;
this._loading = "loading_handlers";
this._handler = handler;
const flowsInProgress = (
await fetchConfigFlowInProgress(this.hass.connection)
).filter((flow) => flow.handler === handler);
if (!flowsInProgress.length) {
// No flows in progress, create a new flow
this._loading = "loading_flow";
let step: DataEntryFlowStep;
try {
step = await this._params!.flowConfig.createFlow(this.hass, handler);
@@ -362,14 +380,15 @@ class DataEntryFlowDialog extends LitElement {
),
});
return;
} finally {
this._handler = undefined;
}
this._processStep(step);
} else {
this._step = null;
this._handler = handler;
this._flowsInProgress = flowsInProgress;
}
this._loading = false;
this._loading = undefined;
}
private _handlerPicked(ev) {
@@ -380,11 +399,11 @@ class DataEntryFlowDialog extends LitElement {
step: DataEntryFlowStep | undefined | Promise<DataEntryFlowStep>
): Promise<void> {
if (step instanceof Promise) {
this._loading = true;
this._loading = "loading_step";
try {
this._step = await step;
} finally {
this._loading = false;
this._loading = undefined;
}
return;
}
@@ -398,6 +417,23 @@ class DataEntryFlowDialog extends LitElement {
this._step = step;
}
private _subscribeDataEntryFlowProgressed() {
if (this._unsubDataEntryFlowProgressed) {
return;
}
this._unsubDataEntryFlowProgressed = subscribeDataEntryFlowProgressed(
this.hass.connection,
async (ev) => {
if (ev.data.flow_id !== this._step?.flow_id) {
return;
}
this._processStep(
this._params!.flowConfig.fetchFlow(this.hass, this._step?.flow_id)
);
}
);
}
static get styles(): CSSResultGroup {
return [
haStyleDialog,