274 lines
7.7 KiB
TypeScript
274 lines
7.7 KiB
TypeScript
import deepFreeze from "deep-freeze";
|
|
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
|
import { customElement, property, query, state } from "lit/decorators";
|
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
|
import "../../../../components/ha-yaml-editor";
|
|
import type { HaYamlEditor } from "../../../../components/ha-yaml-editor";
|
|
import { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
|
import { LovelaceSectionConfig } from "../../../../data/lovelace/config/section";
|
|
import { isStrategyView } from "../../../../data/lovelace/config/view";
|
|
import { haStyleDialog } from "../../../../resources/styles";
|
|
import { HomeAssistant } from "../../../../types";
|
|
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
|
import { addCards, addSection } from "../config-util";
|
|
import {
|
|
LovelaceContainerPath,
|
|
parseLovelaceContainerPath,
|
|
} from "../lovelace-path";
|
|
import "./hui-card-preview";
|
|
import { showCreateCardDialog } from "./show-create-card-dialog";
|
|
import { SuggestCardDialogParams } from "./show-suggest-card-dialog";
|
|
import { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
|
|
|
@customElement("hui-dialog-suggest-card")
|
|
export class HuiDialogSuggestCard extends LitElement {
|
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
|
|
|
@state() private _params?: SuggestCardDialogParams;
|
|
|
|
@state() private _cardConfig?: LovelaceCardConfig[];
|
|
|
|
@state() private _sectionConfig?: LovelaceSectionConfig;
|
|
|
|
@state() private _saving = false;
|
|
|
|
@query("ha-yaml-editor") private _yamlEditor?: HaYamlEditor;
|
|
|
|
public showDialog(params: SuggestCardDialogParams): void {
|
|
this._params = params;
|
|
this._cardConfig = params.cardConfig;
|
|
this._sectionConfig = params.sectionConfig;
|
|
if (!Object.isFrozen(this._cardConfig)) {
|
|
this._cardConfig = deepFreeze(this._cardConfig);
|
|
}
|
|
if (!Object.isFrozen(this._sectionConfig)) {
|
|
this._sectionConfig = deepFreeze(this._sectionConfig);
|
|
}
|
|
if (this._yamlEditor) {
|
|
this._yamlEditor.setValue(this._cardConfig);
|
|
}
|
|
}
|
|
|
|
public closeDialog(): void {
|
|
this._params = undefined;
|
|
this._cardConfig = undefined;
|
|
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
|
}
|
|
|
|
private get _viewSupportsSection(): boolean {
|
|
if (!this._params?.lovelaceConfig || !this._params?.path) {
|
|
return false;
|
|
}
|
|
|
|
const { viewIndex } = parseLovelaceContainerPath(this._params.path);
|
|
const viewConfig = this._params!.lovelaceConfig.views[viewIndex];
|
|
|
|
return !isStrategyView(viewConfig) && viewConfig.type === "sections";
|
|
}
|
|
|
|
private _renderPreview() {
|
|
if (this._sectionConfig && this._viewSupportsSection) {
|
|
return html`
|
|
<div class="element-preview">
|
|
<hui-section
|
|
.hass=${this.hass}
|
|
.config=${this._sectionConfig}
|
|
></hui-section>
|
|
</div>
|
|
`;
|
|
}
|
|
if (this._cardConfig) {
|
|
return html`
|
|
<div class="element-preview">
|
|
${this._cardConfig.map(
|
|
(cardConfig) => html`
|
|
<hui-card-preview
|
|
.hass=${this.hass}
|
|
.config=${cardConfig}
|
|
></hui-card-preview>
|
|
`
|
|
)}
|
|
</div>
|
|
`;
|
|
}
|
|
return nothing;
|
|
}
|
|
|
|
protected render() {
|
|
if (!this._params) {
|
|
return nothing;
|
|
}
|
|
return html`
|
|
<ha-dialog
|
|
open
|
|
scrimClickAction
|
|
@closed=${this.closeDialog}
|
|
.heading=${this.hass!.localize(
|
|
"ui.panel.lovelace.editor.suggest_card.header"
|
|
)}
|
|
>
|
|
<div>
|
|
${this._renderPreview()}
|
|
${this._params.yaml && this._cardConfig
|
|
? html`
|
|
<div class="editor">
|
|
<ha-yaml-editor
|
|
.hass=${this.hass}
|
|
.defaultValue=${this._cardConfig}
|
|
></ha-yaml-editor>
|
|
</div>
|
|
`
|
|
: nothing}
|
|
</div>
|
|
<mwc-button
|
|
slot="secondaryAction"
|
|
@click=${this.closeDialog}
|
|
dialogInitialFocus
|
|
>
|
|
${this._params.yaml
|
|
? this.hass!.localize("ui.common.close")
|
|
: this.hass!.localize("ui.common.cancel")}
|
|
</mwc-button>
|
|
${!this._params.yaml
|
|
? html`
|
|
<mwc-button slot="primaryAction" @click=${this._pickCard}
|
|
>${this.hass!.localize(
|
|
"ui.panel.lovelace.editor.suggest_card.create_own"
|
|
)}</mwc-button
|
|
>
|
|
<mwc-button
|
|
slot="primaryAction"
|
|
.disabled=${this._saving}
|
|
@click=${this._save}
|
|
>
|
|
${this._saving
|
|
? html`
|
|
<ha-circular-progress
|
|
indeterminate
|
|
aria-label="Saving"
|
|
size="small"
|
|
></ha-circular-progress>
|
|
`
|
|
: this.hass!.localize(
|
|
"ui.panel.lovelace.editor.suggest_card.add"
|
|
)}
|
|
</mwc-button>
|
|
`
|
|
: ""}
|
|
</ha-dialog>
|
|
`;
|
|
}
|
|
|
|
static get styles(): CSSResultGroup {
|
|
return [
|
|
haStyleDialog,
|
|
css`
|
|
@media all and (max-width: 450px), all and (max-height: 500px) {
|
|
/* overrule the ha-style-dialog max-height on small screens */
|
|
ha-dialog {
|
|
max-height: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
@media all and (min-width: 850px) {
|
|
ha-dialog {
|
|
width: 845px;
|
|
}
|
|
}
|
|
ha-dialog {
|
|
max-width: 845px;
|
|
--dialog-z-index: 6;
|
|
}
|
|
.hidden {
|
|
display: none;
|
|
}
|
|
.element-preview {
|
|
position: relative;
|
|
}
|
|
hui-card-preview,
|
|
hui-section {
|
|
padding-top: 8px;
|
|
margin: 4px auto;
|
|
max-width: 390px;
|
|
display: block;
|
|
width: 100%;
|
|
}
|
|
.editor {
|
|
padding-top: 16px;
|
|
}
|
|
`,
|
|
];
|
|
}
|
|
|
|
private _pickCard(): void {
|
|
if (
|
|
!this._params?.lovelaceConfig ||
|
|
!this._params?.path ||
|
|
!this._params?.saveConfig
|
|
) {
|
|
return;
|
|
}
|
|
|
|
showCreateCardDialog(this, {
|
|
lovelaceConfig: this._params!.lovelaceConfig,
|
|
saveConfig: this._params!.saveConfig,
|
|
path: this._params!.path,
|
|
entities: this._params!.entities,
|
|
});
|
|
this.closeDialog();
|
|
}
|
|
|
|
private _computeNewConfig(
|
|
config: LovelaceConfig,
|
|
path: LovelaceContainerPath
|
|
): LovelaceConfig {
|
|
if (!this._viewSupportsSection) {
|
|
return addCards(config, path, this._cardConfig!);
|
|
}
|
|
|
|
const { viewIndex, sectionIndex } = parseLovelaceContainerPath(path);
|
|
|
|
// If container is a view, add a section
|
|
if (sectionIndex === undefined) {
|
|
const newSection = this._sectionConfig ?? {
|
|
type: "grid",
|
|
cards: this._cardConfig,
|
|
};
|
|
return addSection(config, viewIndex, newSection);
|
|
}
|
|
|
|
// Else add cards to section
|
|
const newCards = this._sectionConfig
|
|
? this._sectionConfig.cards || []
|
|
: this._cardConfig!;
|
|
return addCards(config, [viewIndex, sectionIndex], newCards);
|
|
}
|
|
|
|
private async _save(): Promise<void> {
|
|
if (
|
|
!this._params?.lovelaceConfig ||
|
|
!this._params?.path ||
|
|
!this._params?.saveConfig ||
|
|
!this._cardConfig
|
|
) {
|
|
return;
|
|
}
|
|
this._saving = true;
|
|
|
|
const newConfig = this._computeNewConfig(
|
|
this._params.lovelaceConfig,
|
|
this._params.path
|
|
);
|
|
await this._params!.saveConfig(newConfig);
|
|
this._saving = false;
|
|
showSaveSuccessToast(this, this.hass);
|
|
this.closeDialog();
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
"hui-dialog-suggest-card": HuiDialogSuggestCard;
|
|
}
|
|
}
|