mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-16 13:56:35 +00:00
Add support for options flows (#3491)
This commit is contained in:
parent
200e099035
commit
f458bdffe0
@ -94,3 +94,34 @@ export const localizeConfigFlowTitle = (
|
|||||||
});
|
});
|
||||||
return localize(`component.${flow.handler}.config.flow_title`, ...args);
|
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}`);
|
||||||
|
@ -76,7 +76,7 @@ class DataEntryFlowDialog extends LitElement {
|
|||||||
this._instance = instance++;
|
this._instance = instance++;
|
||||||
|
|
||||||
// Create a new config flow. Show picker
|
// Create a new config flow. Show picker
|
||||||
if (!params.continueFlowId) {
|
if (!params.continueFlowId && !params.startFlowHandler) {
|
||||||
if (!params.flowConfig.getFlowHandlers) {
|
if (!params.flowConfig.getFlowHandlers) {
|
||||||
throw new Error("No getFlowHandlers defined in flow config");
|
throw new Error("No getFlowHandlers defined in flow config");
|
||||||
}
|
}
|
||||||
@ -99,10 +99,9 @@ class DataEntryFlowDialog extends LitElement {
|
|||||||
|
|
||||||
this._loading = true;
|
this._loading = true;
|
||||||
const curInstance = this._instance;
|
const curInstance = this._instance;
|
||||||
const step = await params.flowConfig.fetchFlow(
|
const step = await (params.continueFlowId
|
||||||
this.hass,
|
? params.flowConfig.fetchFlow(this.hass, params.continueFlowId)
|
||||||
params.continueFlowId
|
: params.flowConfig.createFlow(this.hass, params.startFlowHandler!));
|
||||||
);
|
|
||||||
|
|
||||||
// Happens if second showDialog called
|
// Happens if second showDialog called
|
||||||
if (curInstance !== this._instance) {
|
if (curInstance !== this._instance) {
|
||||||
@ -274,9 +273,11 @@ class DataEntryFlowDialog extends LitElement {
|
|||||||
this._params.flowConfig.deleteFlow(this.hass, this._step.flow_id);
|
this._params.flowConfig.deleteFlow(this.hass, this._step.flow_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._params.dialogClosedCallback({
|
if (this._params.dialogClosedCallback) {
|
||||||
flowFinished,
|
this._params.dialogClosedCallback({
|
||||||
});
|
flowFinished,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this._step = undefined;
|
this._step = undefined;
|
||||||
this._params = undefined;
|
this._params = undefined;
|
||||||
|
@ -71,8 +71,9 @@ export interface FlowConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DataEntryFlowDialogParams {
|
export interface DataEntryFlowDialogParams {
|
||||||
|
startFlowHandler?: string;
|
||||||
continueFlowId?: string;
|
continueFlowId?: string;
|
||||||
dialogClosedCallback: (params: { flowFinished: boolean }) => void;
|
dialogClosedCallback?: (params: { flowFinished: boolean }) => void;
|
||||||
flowConfig: FlowConfig;
|
flowConfig: FlowConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
83
src/dialogs/config-flow/show-dialog-options-flow.ts
Normal file
83
src/dialogs/config-flow/show-dialog-options-flow.ts
Normal 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>
|
||||||
|
`;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
@ -11,6 +11,7 @@ import "./ha-ce-entities-card";
|
|||||||
import { EventsMixin } from "../../../mixins/events-mixin";
|
import { EventsMixin } from "../../../mixins/events-mixin";
|
||||||
import LocalizeMixin from "../../../mixins/localize-mixin";
|
import LocalizeMixin from "../../../mixins/localize-mixin";
|
||||||
import NavigateMixin from "../../../mixins/navigate-mixin";
|
import NavigateMixin from "../../../mixins/navigate-mixin";
|
||||||
|
import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog-options-flow";
|
||||||
|
|
||||||
class HaConfigEntryPage extends NavigateMixin(
|
class HaConfigEntryPage extends NavigateMixin(
|
||||||
EventsMixin(LocalizeMixin(PolymerElement))
|
EventsMixin(LocalizeMixin(PolymerElement))
|
||||||
@ -34,6 +35,13 @@ class HaConfigEntryPage extends NavigateMixin(
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<hass-subpage header="[[configEntry.title]]">
|
<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
|
<paper-icon-button
|
||||||
slot="toolbar-icon"
|
slot="toolbar-icon"
|
||||||
icon="hass:delete"
|
icon="hass:delete"
|
||||||
@ -141,6 +149,10 @@ class HaConfigEntryPage extends NavigateMixin(
|
|||||||
return configEntryDevices.length === 0 && noDeviceEntities.length === 0;
|
return configEntryDevices.length === 0 && noDeviceEntities.length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_showSettings() {
|
||||||
|
showOptionsFlowDialog(this, this.configEntry);
|
||||||
|
}
|
||||||
|
|
||||||
_removeEntry() {
|
_removeEntry() {
|
||||||
if (
|
if (
|
||||||
!confirm(
|
!confirm(
|
||||||
|
@ -530,6 +530,14 @@
|
|||||||
"save": "Save",
|
"save": "Save",
|
||||||
"name": "Name Override",
|
"name": "Name Override",
|
||||||
"entity_id": "Entity ID"
|
"entity_id": "Entity ID"
|
||||||
|
},
|
||||||
|
"options_flow": {
|
||||||
|
"form": {
|
||||||
|
"header": "Options"
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"description": "Options successfully saved."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"duration": {
|
"duration": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user