Add dialog to save config (#2100)

* Add dialog to save config

* Change types

* Helper funcs for register dialog

* Clean up

* Migrate config after save

* Clean up

* Unused imports

* Comments

* Missed half...

* cardConfig cant be undefined
This commit is contained in:
Bram Kragten 2018-11-25 20:09:32 +01:00 committed by Paulus Schoutsen
parent b939ae6ab4
commit 69df6179bb
8 changed files with 241 additions and 42 deletions

View File

@ -1,5 +1,21 @@
import { HomeAssistant } from "../../../types";
import { LovelaceCardConfig } from "../types";
import { LovelaceConfig, LovelaceCardConfig } from "../types";
export const migrateConfig = (hass: HomeAssistant): Promise<void> =>
hass.callWS({
type: "lovelace/config/migrate",
});
export const saveConfig = (
hass: HomeAssistant,
config: LovelaceConfig | string,
configFormat: "json" | "yaml"
): Promise<void> =>
hass.callWS({
type: "lovelace/config/save",
config,
format: configFormat,
});
export const getCardConfig = (
hass: HomeAssistant,
@ -22,8 +38,3 @@ export const updateCardConfig = (
card_config: config,
format: configFormat,
});
export const migrateConfig = (hass: HomeAssistant): Promise<void> =>
hass.callWS({
type: "lovelace/config/migrate",
});

View File

@ -1,6 +1,10 @@
import "@polymer/paper-button/paper-button";
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
import { fireEvent } from "../../../common/dom/fire_event";
import {
showEditCardDialog,
registerEditCardDialog,
} from "../editor/hui-dialog-edit-card";
import { HomeAssistant } from "../../../types";
import { LovelaceCardConfig } from "../types";
@ -18,11 +22,7 @@ export class HuiCardOptions extends LitElement {
super.connectedCallback();
if (!registeredDialog) {
registeredDialog = true;
fireEvent(this, "register-dialog", {
dialogShowEvent: "show-edit-card",
dialogTag: "hui-dialog-edit-card",
dialogImport: () => import("../editor/hui-dialog-edit-card"),
});
registerEditCardDialog(this);
}
}
@ -48,9 +48,8 @@ export class HuiCardOptions extends LitElement {
`;
}
private _editCard() {
fireEvent(this, "show-edit-card", {
hass: this.hass,
cardConfig: this.cardConfig,
showEditCardDialog(this, {
cardConfig: this.cardConfig!,
reloadLovelace: () => fireEvent(this, "config-refresh"),
});
}

View File

@ -3,48 +3,66 @@ import { TemplateResult } from "lit-html";
import { HomeAssistant } from "../../../types";
import { LovelaceCardConfig } from "../types";
import { fireEvent } from "../../../common/dom/fire_event";
import "./hui-edit-card";
import "./hui-migrate-config";
const dialogShowEvent = "show-edit-card";
const dialogTag = "hui-dialog-edit-config";
export interface EditCardDialogParams {
cardConfig: LovelaceCardConfig;
reloadLovelace: () => void;
}
export const registerEditCardDialog = (element: HTMLElement) =>
fireEvent(element, "register-dialog", {
dialogShowEvent,
dialogTag,
dialogImport: () => import("./hui-dialog-edit-card"),
});
export const showEditCardDialog = (
element: HTMLElement,
editCardDialogParams: EditCardDialogParams
) => fireEvent(element, dialogShowEvent, editCardDialogParams);
export class HuiDialogEditCard extends LitElement {
protected _hass?: HomeAssistant;
private _cardConfig?: LovelaceCardConfig;
private _reloadLovelace?: () => void;
protected hass?: HomeAssistant;
private _params?: EditCardDialogParams;
static get properties(): PropertyDeclarations {
return {
_hass: {},
hass: {},
_cardConfig: {},
};
}
public async showDialog({ hass, cardConfig, reloadLovelace }): Promise<void> {
this._hass = hass;
this._cardConfig = cardConfig;
this._reloadLovelace = reloadLovelace;
public async showDialog(params: EditCardDialogParams): Promise<void> {
this._params = params;
await this.updateComplete;
(this.shadowRoot!.children[0] as any).showDialog();
}
protected render(): TemplateResult {
if (!this._params) {
return html``;
}
if (!this._params.cardConfig.id) {
return html`
<hui-migrate-config
.hass="${this.hass}"
@reload-lovelace="${this._params.reloadLovelace}"
></hui-migrate-config>
`;
}
return html`
${
this._cardConfig!.id
? html`
<hui-edit-card
.cardConfig="${this._cardConfig}"
.hass="${this._hass}"
@reload-lovelace="${this._reloadLovelace}"
.cardConfig="${this._params.cardConfig}"
.hass="${this.hass}"
@reload-lovelace="${this._params.reloadLovelace}"
>
</hui-edit-card>
`
: html`
<hui-migrate-config
.hass="${this._hass}"
@reload-lovelace="${this._reloadLovelace}"
></hui-migrate-config>
`
}
`;
}
}
@ -55,4 +73,4 @@ declare global {
}
}
customElements.define("hui-dialog-edit-card", HuiDialogEditCard);
customElements.define(dialogTag, HuiDialogEditCard);

View File

@ -0,0 +1,150 @@
import { html, LitElement, PropertyDeclarations } from "@polymer/lit-element";
import { TemplateResult } from "lit-html";
import "@polymer/paper-spinner/paper-spinner";
import "@polymer/paper-dialog/paper-dialog";
// This is not a duplicate import, one is for types, one is for element.
// tslint:disable-next-line
import { PaperDialogElement } from "@polymer/paper-dialog/paper-dialog";
import "@polymer/paper-button/paper-button";
import { HomeAssistant } from "../../../types";
import { LovelaceConfig } from "../types";
import { saveConfig, migrateConfig } from "../common/data";
import { fireEvent } from "../../../common/dom/fire_event";
import { hassLocalizeLitMixin } from "../../../mixins/lit-localize-mixin";
const dialogShowEvent = "show-save-config";
const dialogTag = "hui-dialog-save-config";
export interface SaveDialogParams {
config: LovelaceConfig;
reloadLovelace: () => void;
}
export const registerSaveDialog = (element: HTMLElement) =>
fireEvent(element, "register-dialog", {
dialogShowEvent,
dialogTag,
dialogImport: () => import("./hui-dialog-save-config"),
});
export const showSaveDialog = (
element: HTMLElement,
saveDialogParams: SaveDialogParams
) => fireEvent(element, dialogShowEvent, saveDialogParams);
export class HuiSaveConfig extends hassLocalizeLitMixin(LitElement) {
protected hass?: HomeAssistant;
private _params?: SaveDialogParams;
private _saving: boolean;
static get properties(): PropertyDeclarations {
return {
hass: {},
_params: {},
_saving: {},
};
}
protected constructor() {
super();
this._saving = false;
}
public async showDialog(params: SaveDialogParams): Promise<void> {
this._params = params;
await this.updateComplete;
this._dialog.open();
}
private get _dialog(): PaperDialogElement {
return this.shadowRoot!.querySelector("paper-dialog")!;
}
protected render(): TemplateResult {
return html`
${this.renderStyle()}
<paper-dialog with-backdrop>
<h2>${this.localize("ui.panel.lovelace.editor.save_config.header")}</h2>
<paper-dialog-scrollable>
<p>${this.localize("ui.panel.lovelace.editor.save_config.para")}</p>
<p>
${this.localize("ui.panel.lovelace.editor.save_config.para_sure")}
</p>
</paper-dialog-scrollable>
<div class="paper-dialog-buttons">
<paper-button @click="${this._closeDialog}"
>${
this.localize("ui.panel.lovelace.editor.save_config.cancel")
}</paper-button
>
<paper-button
?disabled="${this._saving}"
@click="${this._saveConfig}"
>
<paper-spinner
?active="${this._saving}"
alt="Saving"
></paper-spinner>
${
this.localize("ui.panel.lovelace.editor.save_config.save")
}</paper-button
>
</div>
</paper-dialog>
`;
}
private renderStyle(): TemplateResult {
return html`
<style>
paper-dialog {
width: 650px;
}
paper-spinner {
display: none;
}
paper-spinner[active] {
display: block;
}
paper-button paper-spinner {
width: 14px;
height: 14px;
margin-right: 20px;
}
</style>
`;
}
private _closeDialog(): void {
this._dialog.close();
}
private async _saveConfig(): Promise<void> {
if (!this.hass || !this._params) {
return;
}
this._saving = true;
delete this._params.config._frontendAuto;
try {
await saveConfig(this.hass, this._params.config, "json");
await migrateConfig(this.hass);
this._saving = false;
this._closeDialog();
this._params.reloadLovelace!();
} catch (err) {
alert(`Saving failed: ${err.message}`);
this._saving = false;
}
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-dialog-save-config": HuiSaveConfig;
}
}
customElements.define(dialogTag, HuiSaveConfig);

View File

@ -2,11 +2,14 @@ import { html } from "@polymer/polymer/lib/utils/html-tag";
import { PolymerElement } from "@polymer/polymer/polymer-element";
import "@polymer/paper-button/paper-button";
import { registerSaveDialog } from "./editor/hui-dialog-save-config";
import "../../layouts/hass-loading-screen";
import "../../layouts/hass-error-screen";
import "./hui-root";
import localizeMixin from "../../mixins/localize-mixin";
let registeredDialog = false;
class Lovelace extends localizeMixin(PolymerElement) {
static get template() {
return html`
@ -125,6 +128,10 @@ class Lovelace extends localizeMixin(PolymerElement) {
_config: generateLovelaceConfig(this.hass, this.localize),
_state: "loaded",
});
if (!registeredDialog) {
registeredDialog = true;
registerSaveDialog(this);
}
} else {
this.setProperties({
_state: "error",

View File

@ -29,8 +29,8 @@ import "./components/notifications/hui-notifications-button";
import "./hui-unused-entities";
import "./hui-view";
import debounce from "../../common/util/debounce";
import createCardElement from "./common/create-card-element";
import { showSaveDialog } from "./editor/hui-dialog-save-config";
// CSS and JS should only be imported once. Modules and HTML are safe.
const CSS_CACHE = {};
@ -275,7 +275,13 @@ class HUIRoot extends NavigateMixin(EventsMixin(PolymerElement)) {
_editModeEnable() {
if (this.config._frontendAuto) {
alert("Unable to edit automatic generated UI yet.");
showSaveDialog(this, {
config: this.config,
reloadLovelace: () => {
this.fire("config-refresh");
this._editMode = true;
},
});
return;
}
this._editMode = true;

View File

@ -13,6 +13,7 @@ export interface LovelaceViewConfig {
id?: string;
icon?: string;
}
export interface LovelaceConfig {
_frontendAuto: boolean;
title?: string;

View File

@ -772,6 +772,13 @@
"save": "Save",
"toggle_editor": "Toggle Editor"
},
"save_config": {
"header": "Take control of your Lovelace UI",
"para": "By default Home Assistant will maintain your user interface, updating it when new entities or Lovelace components become available. If you take control we will no longer make changes automatically for you.",
"para_sure": "Are you sure you want to take control of your user interface?",
"cancel": "Never mind",
"save": "Take control"
},
"migrate": {
"header": "Configuration Incompatible",
"para_no_id": "This element doesn't have an ID. Please add an ID to this element in 'ui-lovelace.yaml'.",