ha-frontend/src/panels/lovelace/editor/card-editor/hui-dialog-edit-card.ts

285 lines
7.4 KiB
TypeScript
Raw Normal View History

import {
css,
html,
LitElement,
TemplateResult,
CSSResultArray,
customElement,
property,
} from "lit-element";
2018-11-02 16:00:25 +01:00
import { HomeAssistant } from "../../../../types";
import { HASSDomEvent } from "../../../../common/dom/fire_event";
import { LovelaceCardConfig } from "../../../../data/lovelace";
import "./hui-card-editor";
// tslint:disable-next-line
import { HuiCardEditor } from "./hui-card-editor";
import "./hui-card-preview";
import "./hui-card-picker";
import { EditCardDialogParams } from "./show-edit-card-dialog";
import { addCard, replaceCard } from "../config-util";
2018-11-02 16:00:25 +01:00
import "../../../../components/dialog/ha-paper-dialog";
import { haStyleDialog } from "../../../../resources/styles";
declare global {
// for fire event
interface HASSDomEvents {
"reload-lovelace": undefined;
}
// for add event listener
interface HTMLElementEventMap {
"reload-lovelace": HASSDomEvent<undefined>;
}
}
@customElement("hui-dialog-edit-card")
2018-11-02 16:00:25 +01:00
export class HuiDialogEditCard extends LitElement {
@property() protected hass?: HomeAssistant;
2018-11-02 16:00:25 +01:00
@property() private _params?: EditCardDialogParams;
@property() private _cardConfig?: LovelaceCardConfig;
2018-11-02 16:00:25 +01:00
@property() private _saving: boolean = false;
@property() private _error?: string;
public async showDialog(params: EditCardDialogParams): Promise<void> {
this._params = params;
const [view, card] = params.path;
this._cardConfig =
card !== undefined
? params.lovelace.config.views[view].cards![card]
: undefined;
2018-11-02 16:00:25 +01:00
}
private get _cardEditorEl(): HuiCardEditor | null {
return this.shadowRoot!.querySelector("hui-card-editor");
}
protected render(): TemplateResult | void {
if (!this._params) {
return html``;
}
2018-11-02 16:00:25 +01:00
return html`
<ha-paper-dialog with-backdrop opened modal>
<h2>
${this.hass!.localize("ui.panel.lovelace.editor.edit_card.header")}
</h2>
<paper-dialog-scrollable>
${this._cardConfig === undefined
? html`
<hui-card-picker
.hass="${this.hass}"
@config-changed="${this._handleCardPicked}"
></hui-card-picker>
`
: html`
<div class="content">
<div class="element-editor">
<hui-card-editor
.hass="${this.hass}"
.value="${this._cardConfig}"
@config-changed="${this._handleConfigChanged}"
></hui-card-editor>
</div>
<div class="element-preview">
<hui-card-preview
.hass="${this.hass}"
.config="${this._cardConfig}"
class=${this._error ? "blur" : ""}
></hui-card-preview>
${this._error
? html`
<paper-spinner
active
alt="Can't update card"
></paper-spinner>
`
: ``}
</div>
</div>
`}
</paper-dialog-scrollable>
<div class="paper-dialog-buttons">
<mwc-button @click="${this._close}">
${this.hass!.localize("ui.common.cancel")}
</mwc-button>
<mwc-button
?disabled="${!this._canSave || this._saving}"
@click="${this._save}"
>
${this._saving
? html`
<paper-spinner active alt="Saving"></paper-spinner>
`
: this.hass!.localize("ui.common.save")}
</mwc-button>
</div>
</ha-paper-dialog>
2018-11-02 16:00:25 +01:00
`;
}
static get styles(): CSSResultArray {
return [
haStyleDialog,
css`
:host {
--code-mirror-max-height: calc(100vh - 176px);
}
@media all and (max-width: 450px), all and (max-height: 500px) {
/* overrule the ha-style-dialog max-height on small screens */
ha-paper-dialog {
max-height: 100%;
height: 100%;
}
}
@media all and (min-width: 660px) {
ha-paper-dialog {
width: 845px;
}
}
ha-paper-dialog {
max-width: 845px;
}
.center {
margin-left: auto;
margin-right: auto;
}
.content {
display: flex;
flex-direction: column;
margin: 0 -10px;
}
.content hui-card-preview {
margin: 4px auto;
max-width: 390px;
}
.content .element-editor {
margin: 0 10px;
}
@media (min-width: 1200px) {
ha-paper-dialog {
max-width: none;
width: 1000px;
}
.content {
flex-direction: row;
}
.content > * {
flex-basis: 0;
flex-grow: 1;
flex-shrink: 1;
min-width: 0;
}
.content hui-card-preview {
padding: 8px 0;
margin: auto 10px;
max-width: 500px;
}
}
mwc-button paper-spinner {
width: 14px;
height: 14px;
margin-right: 20px;
}
.hidden {
display: none;
}
.element-editor {
margin-bottom: 8px;
}
.blur {
filter: blur(2px) grayscale(100%);
}
.element-preview {
position: relative;
}
.element-preview paper-spinner {
top: 50%;
left: 50%;
position: absolute;
z-index: 10;
}
hui-card-preview {
padding-top: 8px;
margin-bottom: 4px;
display: block;
width: 100%;
}
`,
];
}
private _handleCardPicked(ev) {
this._cardConfig = ev.detail.config;
if (this._params!.entities && this._params!.entities.length > 0) {
if (Object.keys(this._cardConfig!).includes("entities")) {
this._cardConfig!.entities = this._params!.entities;
} else if (Object.keys(this._cardConfig!).includes("entity")) {
this._cardConfig!.entity = this._params!.entities[0];
}
}
this._error = ev.detail.error;
}
private _handleConfigChanged(ev) {
this._cardConfig = ev.detail.config;
this._error = ev.detail.error;
}
private _close(): void {
this._params = undefined;
this._cardConfig = undefined;
this._error = undefined;
}
private get _canSave(): boolean {
if (this._saving) {
return false;
}
if (this._cardConfig === undefined) {
return false;
}
if (this._cardEditorEl && this._cardEditorEl.hasError) {
return false;
}
return true;
}
private async _save(): Promise<void> {
const lovelace = this._params!.lovelace;
this._saving = true;
await lovelace.saveConfig(
this._params!.path.length === 1
? addCard(
lovelace.config,
this._params!.path as [number],
this._cardConfig!
)
: replaceCard(
lovelace.config,
this._params!.path as [number, number],
this._cardConfig!
)
);
this._saving = false;
this._close();
}
2018-11-02 16:00:25 +01:00
}
declare global {
interface HTMLElementTagNameMap {
"hui-dialog-edit-card": HuiDialogEditCard;
2018-11-02 16:00:25 +01:00
}
}