Add support for options flows (#3491)

This commit is contained in:
Paulus Schoutsen 2019-08-15 13:34:26 -07:00 committed by GitHub
parent 200e099035
commit f458bdffe0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 9 deletions

View File

@ -94,3 +94,34 @@ export const localizeConfigFlowTitle = (
});
return localize(`component.${flow.handler}.config.flow_title`, ...args);
};
// Options flow
export const createOptionsFlow = (hass: HomeAssistant, handler: string) =>
hass.callApi<DataEntryFlowStep>(
"POST",
"config/config_entries/options/flow",
{
handler,
}
);
export const fetchOptionsFlow = (hass: HomeAssistant, flowId: string) =>
hass.callApi<DataEntryFlowStep>(
"GET",
`config/config_entries/options/flow/${flowId}`
);
export const handleOptionsFlowStep = (
hass: HomeAssistant,
flowId: string,
data: { [key: string]: any }
) =>
hass.callApi<DataEntryFlowStep>(
"POST",
`config/config_entries/options/flow/${flowId}`,
data
);
export const deleteOptionsFlow = (hass: HomeAssistant, flowId: string) =>
hass.callApi("DELETE", `config/config_entries/options/flow/${flowId}`);

View File

@ -76,7 +76,7 @@ class DataEntryFlowDialog extends LitElement {
this._instance = instance++;
// Create a new config flow. Show picker
if (!params.continueFlowId) {
if (!params.continueFlowId && !params.startFlowHandler) {
if (!params.flowConfig.getFlowHandlers) {
throw new Error("No getFlowHandlers defined in flow config");
}
@ -99,10 +99,9 @@ class DataEntryFlowDialog extends LitElement {
this._loading = true;
const curInstance = this._instance;
const step = await params.flowConfig.fetchFlow(
this.hass,
params.continueFlowId
);
const step = await (params.continueFlowId
? params.flowConfig.fetchFlow(this.hass, params.continueFlowId)
: params.flowConfig.createFlow(this.hass, params.startFlowHandler!));
// Happens if second showDialog called
if (curInstance !== this._instance) {
@ -274,9 +273,11 @@ class DataEntryFlowDialog extends LitElement {
this._params.flowConfig.deleteFlow(this.hass, this._step.flow_id);
}
this._params.dialogClosedCallback({
flowFinished,
});
if (this._params.dialogClosedCallback) {
this._params.dialogClosedCallback({
flowFinished,
});
}
this._step = undefined;
this._params = undefined;

View File

@ -71,8 +71,9 @@ export interface FlowConfig {
}
export interface DataEntryFlowDialogParams {
startFlowHandler?: string;
continueFlowId?: string;
dialogClosedCallback: (params: { flowFinished: boolean }) => void;
dialogClosedCallback?: (params: { flowFinished: boolean }) => void;
flowConfig: FlowConfig;
}

View File

@ -0,0 +1,83 @@
import {
fetchOptionsFlow,
handleOptionsFlowStep,
deleteOptionsFlow,
createOptionsFlow,
ConfigEntry,
} from "../../data/config_entries";
import { html } from "lit-element";
import { localizeKey } from "../../common/translations/localize";
import {
showFlowDialog,
loadDataEntryFlowDialog,
} from "./show-dialog-data-entry-flow";
export const loadOptionsFlowDialog = loadDataEntryFlowDialog;
export const showOptionsFlowDialog = (
element: HTMLElement,
configEntry: ConfigEntry
): void =>
showFlowDialog(
element,
{
startFlowHandler: configEntry.entry_id,
},
{
loadDevicesAndAreas: false,
createFlow: createOptionsFlow,
fetchFlow: fetchOptionsFlow,
handleFlowStep: handleOptionsFlowStep,
deleteFlow: deleteOptionsFlow,
renderAbortDescription(hass, step) {
const description = localizeKey(
hass.localize,
`component.${configEntry.domain}.options.abort.${step.reason}`,
step.description_placeholders
);
return description
? html`
<ha-markdown .content=${description}></ha-markdown>
`
: "";
},
renderShowFormStepHeader(hass, _step) {
return hass.localize(`ui.dialogs.options_flow.form.header`);
},
renderShowFormStepDescription(_hass, _step) {
return "";
},
renderShowFormStepFieldLabel(hass, step, field) {
return hass.localize(
`component.${configEntry.domain}.options.step.${step.step_id}.data.${
field.name
}`
);
},
renderShowFormStepFieldError(hass, _step, error) {
return hass.localize(
`component.${configEntry.domain}.options.error.${error}`
);
},
renderExternalStepHeader(_hass, _step) {
return "";
},
renderExternalStepDescription(_hass, _step) {
return "";
},
renderCreateEntryDescription(hass, _step) {
return html`
<p>${hass.localize(`ui.dialogs.options_flow.success.description`)}</p>
`;
},
}
);

View File

@ -11,6 +11,7 @@ import "./ha-ce-entities-card";
import { EventsMixin } from "../../../mixins/events-mixin";
import LocalizeMixin from "../../../mixins/localize-mixin";
import NavigateMixin from "../../../mixins/navigate-mixin";
import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
class HaConfigEntryPage extends NavigateMixin(
EventsMixin(LocalizeMixin(PolymerElement))
@ -34,6 +35,13 @@ class HaConfigEntryPage extends NavigateMixin(
}
</style>
<hass-subpage header="[[configEntry.title]]">
<template is="dom-if" if="[[configEntry.supports_options]]">
<paper-icon-button
slot="toolbar-icon"
icon="hass:settings"
on-click="_showSettings"
></paper-icon-button>
</template>
<paper-icon-button
slot="toolbar-icon"
icon="hass:delete"
@ -141,6 +149,10 @@ class HaConfigEntryPage extends NavigateMixin(
return configEntryDevices.length === 0 && noDeviceEntities.length === 0;
}
_showSettings() {
showOptionsFlowDialog(this, this.configEntry);
}
_removeEntry() {
if (
!confirm(

View File

@ -530,6 +530,14 @@
"save": "Save",
"name": "Name Override",
"entity_id": "Entity ID"
},
"options_flow": {
"form": {
"header": "Options"
},
"success": {
"description": "Options successfully saved."
}
}
},
"duration": {