From 3357d7fd830fad3d88f165650b16f6c2d8a0c24f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 15 Mar 2022 13:13:38 -0700 Subject: [PATCH 1/2] Add support for menu data entry flow option --- src/data/data_entry_flow.ts | 21 +++-- .../config-flow/dialog-data-entry-flow.ts | 11 ++- .../config-flow/show-dialog-config-flow.ts | 15 ++++ .../show-dialog-data-entry-flow.ts | 9 +++ .../config-flow/show-dialog-options-flow.ts | 15 ++++ src/dialogs/config-flow/step-flow-menu.ts | 80 +++++++++++++++++++ 6 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 src/dialogs/config-flow/step-flow-menu.ts diff --git a/src/data/data_entry_flow.ts b/src/data/data_entry_flow.ts index d617b3702098..14821f8b77e0 100644 --- a/src/data/data_entry_flow.ts +++ b/src/data/data_entry_flow.ts @@ -28,7 +28,7 @@ export interface DataEntryFlowStepForm { step_id: string; data_schema: HaFormSchema[]; errors: Record; - description_placeholders: Record; + description_placeholders?: Record; last_step: boolean | null; } @@ -49,7 +49,7 @@ export interface DataEntryFlowStepCreateEntry { title: string; result?: ConfigEntry; description: string; - description_placeholders: Record; + description_placeholders?: Record; } export interface DataEntryFlowStepAbort { @@ -57,7 +57,7 @@ export interface DataEntryFlowStepAbort { flow_id: string; handler: string; reason: string; - description_placeholders: Record; + description_placeholders?: Record; } export interface DataEntryFlowStepProgress { @@ -66,7 +66,17 @@ export interface DataEntryFlowStepProgress { handler: string; step_id: string; progress_action: string; - description_placeholders: Record; + description_placeholders?: Record; +} + +export interface DataEntryFlowStepMenu { + type: "menu"; + flow_id: string; + handler: string; + step_id: string; + /** If array, use value to lookup translations in strings.json */ + menu_options: string[] | Record; + description_placeholders?: Record; } export type DataEntryFlowStep = @@ -74,7 +84,8 @@ export type DataEntryFlowStep = | DataEntryFlowStepExternal | DataEntryFlowStepCreateEntry | DataEntryFlowStepAbort - | DataEntryFlowStepProgress; + | DataEntryFlowStepProgress + | DataEntryFlowStepMenu; export const subscribeDataEntryFlowProgressed = ( conn: Connection, diff --git a/src/dialogs/config-flow/dialog-data-entry-flow.ts b/src/dialogs/config-flow/dialog-data-entry-flow.ts index 6fbab75c745b..c35216021e52 100644 --- a/src/dialogs/config-flow/dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/dialog-data-entry-flow.ts @@ -46,6 +46,7 @@ import "./step-flow-loading"; import "./step-flow-pick-flow"; import "./step-flow-pick-handler"; import "./step-flow-progress"; +import "./step-flow-menu"; let instance = 0; @@ -292,6 +293,14 @@ class DataEntryFlowDialog extends LitElement { .hass=${this.hass} > ` + : this._step.type === "menu" + ? html` + + ` : this._devices === undefined || this._areas === undefined ? // When it's a create entry result, we will fetch device & area registry html` @@ -421,7 +430,7 @@ class DataEntryFlowDialog extends LitElement { title: this.hass.localize( "ui.panel.config.integrations.config_flow.error" ), - text: err.message || err.body, + text: err?.body?.message, }); return; } finally { diff --git a/src/dialogs/config-flow/show-dialog-config-flow.ts b/src/dialogs/config-flow/show-dialog-config-flow.ts index e516dfc4fe13..42337b40ff66 100644 --- a/src/dialogs/config-flow/show-dialog-config-flow.ts +++ b/src/dialogs/config-flow/show-dialog-config-flow.ts @@ -181,6 +181,21 @@ export const showConfigFlowDialog = ( : ""; }, + renderMenuHeader(hass, step) { + return ( + hass.localize( + `component.${step.handler}.config.step.${step.step_id}.title` + ) || hass.localize(`component.${step.handler}.title`) + ); + }, + + renderMenuOption(hass, step, option) { + return hass.localize( + `component.${step.handler}.config.step.${step.step_id}.menu_options.${option}`, + step.description_placeholders + ); + }, + renderLoadingDescription(hass, reason, handler, step) { if (!["loading_flow", "loading_step"].includes(reason)) { return ""; diff --git a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts index b0217ec0576a..be54d0983928 100644 --- a/src/dialogs/config-flow/show-dialog-data-entry-flow.ts +++ b/src/dialogs/config-flow/show-dialog-data-entry-flow.ts @@ -7,6 +7,7 @@ import { DataEntryFlowStepCreateEntry, DataEntryFlowStepExternal, DataEntryFlowStepForm, + DataEntryFlowStepMenu, DataEntryFlowStepProgress, } from "../../data/data_entry_flow"; import { HomeAssistant } from "../../types"; @@ -80,6 +81,14 @@ export interface FlowConfig { step: DataEntryFlowStepProgress ): TemplateResult | ""; + renderMenuHeader(hass: HomeAssistant, step: DataEntryFlowStepMenu): string; + + renderMenuOption( + hass: HomeAssistant, + step: DataEntryFlowStepMenu, + option: string + ): string; + renderLoadingDescription( hass: HomeAssistant, loadingReason: LoadingReason, diff --git a/src/dialogs/config-flow/show-dialog-options-flow.ts b/src/dialogs/config-flow/show-dialog-options-flow.ts index 7c7fde94dca8..451e601ed440 100644 --- a/src/dialogs/config-flow/show-dialog-options-flow.ts +++ b/src/dialogs/config-flow/show-dialog-options-flow.ts @@ -134,6 +134,21 @@ export const showOptionsFlowDialog = ( : ""; }, + renderMenuHeader(hass, step) { + return ( + hass.localize( + `component.${step.handler}.option.step.${step.step_id}.title` + ) || hass.localize(`component.${step.handler}.title`) + ); + }, + + renderMenuOption(hass, step, option) { + return hass.localize( + `component.${step.handler}.options.step.${step.step_id}.menu_options.${option}`, + step.description_placeholders + ); + }, + renderLoadingDescription(hass, reason) { return ( hass.localize(`component.${configEntry.domain}.options.loading`) || diff --git a/src/dialogs/config-flow/step-flow-menu.ts b/src/dialogs/config-flow/step-flow-menu.ts new file mode 100644 index 000000000000..85d534b32824 --- /dev/null +++ b/src/dialogs/config-flow/step-flow-menu.ts @@ -0,0 +1,80 @@ +import "@material/mwc-list/mwc-list-item"; +import { css, html, LitElement, TemplateResult } from "lit"; +import { customElement, property } from "lit/decorators"; +import { DataEntryFlowStepMenu } from "../../data/data_entry_flow"; +import { HomeAssistant } from "../../types"; +import { FlowConfig } from "./show-dialog-data-entry-flow"; +import "../../components/ha-icon-next"; +import { configFlowContentStyles } from "./styles"; +import { fireEvent } from "../../common/dom/fire_event"; + +@customElement("step-flow-menu") +class StepFlowMenu extends LitElement { + @property({ attribute: false }) public flowConfig!: FlowConfig; + + @property({ attribute: false }) public hass!: HomeAssistant; + + @property({ attribute: false }) public step!: DataEntryFlowStepMenu; + + protected render(): TemplateResult { + let options: string[]; + let translations: Record; + + if (Array.isArray(this.step.menu_options)) { + options = this.step.menu_options; + translations = {}; + for (const option of options) { + translations[option] = this.flowConfig.renderMenuOption( + this.hass, + this.step, + option + ); + } + } else { + options = Object.keys(this.step.menu_options); + translations = this.step.menu_options; + } + + return html` +

${this.flowConfig.renderMenuHeader(this.hass, this.step)}

+
+ ${options.map( + (option) => html` + + ${translations[option]} + + + ` + )} +
+ `; + } + + private _handleStep(ev) { + fireEvent(this, "flow-update", { + stepPromise: this.flowConfig.handleFlowStep( + this.hass, + this.step.flow_id, + { + next_step_id: ev.currentTarget.step, + } + ), + }); + } + + static styles = [ + configFlowContentStyles, + css` + .options { + margin-top: 20px; + margin-bottom: 8px; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + "step-flow-menu": StepFlowMenu; + } +} From 84dde605255513f209bd1506809ed2eb8c668dd0 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Tue, 15 Mar 2022 13:44:32 -0700 Subject: [PATCH 2/2] Import type --- src/dialogs/config-flow/step-flow-menu.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dialogs/config-flow/step-flow-menu.ts b/src/dialogs/config-flow/step-flow-menu.ts index 85d534b32824..a49baed97f23 100644 --- a/src/dialogs/config-flow/step-flow-menu.ts +++ b/src/dialogs/config-flow/step-flow-menu.ts @@ -1,9 +1,9 @@ import "@material/mwc-list/mwc-list-item"; import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators"; -import { DataEntryFlowStepMenu } from "../../data/data_entry_flow"; -import { HomeAssistant } from "../../types"; -import { FlowConfig } from "./show-dialog-data-entry-flow"; +import type { DataEntryFlowStepMenu } from "../../data/data_entry_flow"; +import type { HomeAssistant } from "../../types"; +import type { FlowConfig } from "./show-dialog-data-entry-flow"; import "../../components/ha-icon-next"; import { configFlowContentStyles } from "./styles"; import { fireEvent } from "../../common/dom/fire_event";