parent
de370d6384
commit
1b44c7ce64
|
@ -0,0 +1,30 @@
|
|||
import { customElement } from "lit/decorators";
|
||||
import { LovelaceDashboardStrategyConfig } from "../../../../data/lovelace/config/types";
|
||||
import { getLovelaceStrategy } from "../../strategies/get-strategy";
|
||||
import { LovelaceStrategyEditor } from "../../strategies/types";
|
||||
import { HuiElementEditor } from "../hui-element-editor";
|
||||
|
||||
@customElement("hui-dashboard-strategy-element-editor")
|
||||
export class HuiDashboardStrategyElementEditor extends HuiElementEditor<LovelaceDashboardStrategyConfig> {
|
||||
protected async getConfigElement(): Promise<
|
||||
LovelaceStrategyEditor | undefined
|
||||
> {
|
||||
const elClass = await getLovelaceStrategy(
|
||||
"dashboard",
|
||||
this.configElementType!
|
||||
);
|
||||
|
||||
// Check if a GUI editor exists
|
||||
if (elClass && elClass.getConfigElement) {
|
||||
return elClass.getConfigElement();
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-dashboard-strategy-element-editor": HuiDashboardStrategyElementEditor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
import { html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import type {
|
||||
HaFormSchema,
|
||||
SchemaUnion,
|
||||
} from "../../../../components/ha-form/types";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { OriginalStatesDashboardStrategyConfig } from "../../strategies/original-states-dashboard-strategy";
|
||||
import { LovelaceStrategyEditor } from "../../strategies/types";
|
||||
|
||||
const SCHEMA = [
|
||||
{
|
||||
name: "no_area_group",
|
||||
selector: {
|
||||
boolean: {},
|
||||
},
|
||||
},
|
||||
] as const satisfies readonly HaFormSchema[];
|
||||
|
||||
@customElement("hui-original-states-dashboard-strategy-editor")
|
||||
export class HuiOriginalStatesDashboarStrategyEditor
|
||||
extends LitElement
|
||||
implements LovelaceStrategyEditor
|
||||
{
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@state()
|
||||
private _config?: OriginalStatesDashboardStrategyConfig;
|
||||
|
||||
public setConfig(config: OriginalStatesDashboardStrategyConfig): void {
|
||||
this._config = config;
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this.hass || !this._config) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const data = this._config;
|
||||
|
||||
return html`
|
||||
<ha-form
|
||||
.hass=${this.hass}
|
||||
.data=${data}
|
||||
.schema=${SCHEMA}
|
||||
.computeLabel=${this._computeLabelCallback}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>
|
||||
`;
|
||||
}
|
||||
|
||||
private _valueChanged(ev: CustomEvent): void {
|
||||
const config = ev.detail.value;
|
||||
fireEvent(this, "config-changed", { config });
|
||||
}
|
||||
|
||||
private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
|
||||
switch (schema.name) {
|
||||
case "no_area_group":
|
||||
return "Do not group by area";
|
||||
default:
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.generic.${schema.name}`
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-original-states-dashboard-strategy-editor": HuiOriginalStatesDashboarStrategyEditor;
|
||||
}
|
||||
}
|
|
@ -16,8 +16,9 @@ import "../../../components/ha-alert";
|
|||
import "../../../components/ha-circular-progress";
|
||||
import "../../../components/ha-code-editor";
|
||||
import type { HaCodeEditor } from "../../../components/ha-code-editor";
|
||||
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||
import type { LovelaceConfig } from "../../../data/lovelace/config/types";
|
||||
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||
import { LovelaceConfig } from "../../../data/lovelace/config/types";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { LovelaceRowConfig } from "../entity-rows/types";
|
||||
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||
|
@ -36,7 +37,8 @@ export interface ConfigChangedEvent {
|
|||
| LovelaceCardConfig
|
||||
| LovelaceRowConfig
|
||||
| LovelaceHeaderFooterConfig
|
||||
| LovelaceTileFeatureConfig;
|
||||
| LovelaceTileFeatureConfig
|
||||
| LovelaceStrategyConfig;
|
||||
error?: string;
|
||||
guiModeAvailable?: boolean;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ import {
|
|||
import "@polymer/paper-tabs/paper-tab";
|
||||
import "@polymer/paper-tabs/paper-tabs";
|
||||
import {
|
||||
css,
|
||||
CSSResultGroup,
|
||||
html,
|
||||
LitElement,
|
||||
PropertyValues,
|
||||
TemplateResult,
|
||||
css,
|
||||
html,
|
||||
} from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
|
@ -64,11 +64,15 @@ import { documentationUrl } from "../../util/documentation-url";
|
|||
import { swapView } from "./editor/config-util";
|
||||
import { showEditLovelaceDialog } from "./editor/lovelace-editor/show-edit-lovelace-dialog";
|
||||
import { showEditViewDialog } from "./editor/view-editor/show-edit-view-dialog";
|
||||
import { showDashboardStrategyEditorDialog } from "./strategies/device-registry-detail/show-dialog-dashboard-strategy-editor";
|
||||
import type { Lovelace } from "./types";
|
||||
import "./views/hui-view";
|
||||
import type { HUIView } from "./views/hui-view";
|
||||
import { LovelaceViewConfig } from "../../data/lovelace/config/view";
|
||||
import { LovelaceConfig } from "../../data/lovelace/config/types";
|
||||
import {
|
||||
LovelaceConfig,
|
||||
isStrategyDashboard,
|
||||
} from "../../data/lovelace/config/types";
|
||||
|
||||
@customElement("hui-root")
|
||||
class HUIRoot extends LitElement {
|
||||
|
@ -804,6 +808,13 @@ class HUIRoot extends LitElement {
|
|||
});
|
||||
return;
|
||||
}
|
||||
if (isStrategyDashboard(this.lovelace!.rawConfig)) {
|
||||
showDashboardStrategyEditorDialog(this, {
|
||||
config: this.lovelace!.rawConfig,
|
||||
saveConfig: this.lovelace!.saveConfig,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.lovelace!.setEditMode(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, query, state } from "lit/decorators";
|
||||
import { fireEvent, HASSDomEvent } from "../../../../common/dom/fire_event";
|
||||
import "../../../../components/ha-button";
|
||||
import { createCloseHeading } from "../../../../components/ha-dialog";
|
||||
import { LovelaceStrategyConfig } from "../../../../data/lovelace/config/strategy";
|
||||
import { haStyle, haStyleDialog } from "../../../../resources/styles";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { showSaveSuccessToast } from "../../../../util/toast-saved-success";
|
||||
import "../../editor/dashboard-strategy-editor/hui-dashboard-strategy-element-editor";
|
||||
import type { HuiDashboardStrategyElementEditor } from "../../editor/dashboard-strategy-editor/hui-dashboard-strategy-element-editor";
|
||||
import { ConfigChangedEvent } from "../../editor/hui-element-editor";
|
||||
import { GUIModeChangedEvent } from "../../editor/types";
|
||||
import { cleanLegacyStrategyConfig } from "../legacy-strategy";
|
||||
import type { DashboardStrategyEditorDialogParams } from "./show-dialog-dashboard-strategy-editor";
|
||||
|
||||
@customElement("dialog-dashboard-strategy-editor")
|
||||
class DialogDashboardStrategyEditor extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _params?: DashboardStrategyEditorDialogParams;
|
||||
|
||||
@state() private _strategyConfig?: LovelaceStrategyConfig;
|
||||
|
||||
@state() private _GUImode = true;
|
||||
|
||||
@state() private _guiModeAvailable? = true;
|
||||
|
||||
@query("hui-dashboard-strategy-element-editor")
|
||||
private _strategyEditorEl?: HuiDashboardStrategyElementEditor;
|
||||
|
||||
public async showDialog(
|
||||
params: DashboardStrategyEditorDialogParams
|
||||
): Promise<void> {
|
||||
this._params = params;
|
||||
this._strategyConfig = params.config.strategy;
|
||||
await this.updateComplete;
|
||||
}
|
||||
|
||||
public closeDialog(): void {
|
||||
this._params = undefined;
|
||||
this._strategyConfig = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
private _handleConfigChanged(ev: HASSDomEvent<ConfigChangedEvent>) {
|
||||
ev.stopPropagation();
|
||||
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
||||
this._strategyConfig = ev.detail.config as LovelaceStrategyConfig;
|
||||
}
|
||||
|
||||
private _handleGUIModeChanged(ev: HASSDomEvent<GUIModeChangedEvent>): void {
|
||||
ev.stopPropagation();
|
||||
this._GUImode = ev.detail.guiMode;
|
||||
this._guiModeAvailable = ev.detail.guiModeAvailable;
|
||||
}
|
||||
|
||||
private _toggleMode(): void {
|
||||
this._strategyEditorEl?.toggleMode();
|
||||
}
|
||||
|
||||
private _opened() {
|
||||
this._strategyEditorEl?.focusYamlEditor();
|
||||
}
|
||||
|
||||
private async _save(): Promise<void> {
|
||||
await this._params!.saveConfig({
|
||||
...this._params!.config,
|
||||
strategy: this._strategyConfig!,
|
||||
});
|
||||
showSaveSuccessToast(this, this.hass);
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._params || !this._strategyConfig) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const config = cleanLegacyStrategyConfig(this._strategyConfig);
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
open
|
||||
@closed=${this.closeDialog}
|
||||
.heading=${createCloseHeading(this.hass, "Edit dashboard")}
|
||||
@opened=${this._opened}
|
||||
>
|
||||
<hui-dashboard-strategy-element-editor
|
||||
.hass=${this.hass}
|
||||
.lovelace=${this._params.config}
|
||||
.value=${config}
|
||||
@config-changed=${this._handleConfigChanged}
|
||||
@GUImode-changed=${this._handleGUIModeChanged}
|
||||
dialogInitialFocus
|
||||
></hui-dashboard-strategy-element-editor>
|
||||
${this._strategyConfig !== undefined
|
||||
? html`
|
||||
<ha-button
|
||||
slot="secondaryAction"
|
||||
@click=${this._toggleMode}
|
||||
.disabled=${!this._guiModeAvailable}
|
||||
class="gui-mode-button"
|
||||
>
|
||||
${this.hass!.localize(
|
||||
!this._strategyEditorEl || this._GUImode
|
||||
? "ui.panel.lovelace.editor.edit_card.show_code_editor"
|
||||
: "ui.panel.lovelace.editor.edit_card.show_visual_editor"
|
||||
)}
|
||||
</ha-button>
|
||||
<ha-button @click=${this._save} slot="primaryAction">
|
||||
${this.hass!.localize("ui.common.save")}
|
||||
</ha-button>
|
||||
`
|
||||
: nothing}
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return [haStyle, haStyleDialog, css``];
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"dialog-dashboard-strategy-editor": DialogDashboardStrategyEditor;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { LovelaceDashboardStrategyConfig } from "../../../../data/lovelace/config/types";
|
||||
|
||||
export interface DashboardStrategyEditorDialogParams {
|
||||
config: LovelaceDashboardStrategyConfig;
|
||||
saveConfig: (config: LovelaceDashboardStrategyConfig) => void;
|
||||
}
|
||||
|
||||
export const loadDashboardStrategyEditorDialog = () =>
|
||||
import("./dialog-dashboard-strategy-editor");
|
||||
|
||||
export const showDashboardStrategyEditorDialog = (
|
||||
element: HTMLElement,
|
||||
params: DashboardStrategyEditorDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "dialog-dashboard-strategy-editor",
|
||||
dialogImport: loadDashboardStrategyEditorDialog,
|
||||
dialogParams: params,
|
||||
});
|
||||
};
|
|
@ -9,7 +9,7 @@ import {
|
|||
isStrategyView,
|
||||
} from "../../../data/lovelace/config/view";
|
||||
import { AsyncReturnType, HomeAssistant } from "../../../types";
|
||||
import { isLegacyStrategy } from "./legacy-strategy";
|
||||
import { cleanLegacyStrategyConfig, isLegacyStrategy } from "./legacy-strategy";
|
||||
import {
|
||||
LovelaceDashboardStrategy,
|
||||
LovelaceStrategy,
|
||||
|
@ -40,7 +40,7 @@ type StrategyConfig<T extends LovelaceStrategyConfigType> = AsyncReturnType<
|
|||
Strategies[T]["generate"]
|
||||
>;
|
||||
|
||||
const getLovelaceStrategy = async <T extends LovelaceStrategyConfigType>(
|
||||
export const getLovelaceStrategy = async <T extends LovelaceStrategyConfigType>(
|
||||
configType: T,
|
||||
strategyType: string
|
||||
): Promise<LovelaceStrategy> => {
|
||||
|
@ -109,12 +109,7 @@ const generateStrategy = async <T extends LovelaceStrategyConfigType>(
|
|||
}
|
||||
}
|
||||
|
||||
const config = {
|
||||
...strategyConfig,
|
||||
...strategyConfig.options,
|
||||
};
|
||||
|
||||
delete config.options;
|
||||
const config = cleanLegacyStrategyConfig(strategyConfig);
|
||||
|
||||
return await strategy.generate(config, hass);
|
||||
} catch (err: any) {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||
import {
|
||||
LovelaceConfig,
|
||||
LovelaceRawConfig,
|
||||
|
@ -27,3 +28,16 @@ export interface LovelaceViewStrategy {
|
|||
hass: HomeAssistant;
|
||||
}): Promise<LovelaceViewConfig>;
|
||||
}
|
||||
|
||||
export const cleanLegacyStrategyConfig = (config: LovelaceStrategyConfig) => {
|
||||
if (!(Object.keys(config).length === 2 && "options" in config)) {
|
||||
return config;
|
||||
}
|
||||
const cleanedConfig = {
|
||||
...config,
|
||||
...config.options,
|
||||
};
|
||||
|
||||
delete cleanedConfig.options;
|
||||
return cleanedConfig;
|
||||
};
|
||||
|
|
|
@ -1,22 +1,39 @@
|
|||
import { ReactiveElement } from "lit";
|
||||
import { customElement } from "lit/decorators";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||
import { LovelaceConfig } from "../../../data/lovelace/config/types";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceStrategyEditor } from "./types";
|
||||
|
||||
export type OriginalStatesDashboardStrategyConfig = LovelaceStrategyConfig & {
|
||||
no_area_group?: boolean;
|
||||
};
|
||||
|
||||
@customElement("original-states-dashboard-strategy")
|
||||
export class OriginalStatesDashboardStrategy extends ReactiveElement {
|
||||
static async generate(
|
||||
_config: LovelaceStrategyConfig,
|
||||
config: OriginalStatesDashboardStrategyConfig,
|
||||
hass: HomeAssistant
|
||||
): Promise<LovelaceConfig> {
|
||||
return {
|
||||
title: hass.config.location_name,
|
||||
views: [
|
||||
{
|
||||
strategy: { type: "original-states" },
|
||||
strategy: {
|
||||
type: "original-states",
|
||||
no_area_group: config.no_area_group,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
public static async getConfigElement(): Promise<LovelaceStrategyEditor> {
|
||||
await import(
|
||||
"../editor/dashboard-strategy-editor/hui-original-states-dashboard-strategy-editor"
|
||||
);
|
||||
return document.createElement(
|
||||
"hui-original-states-dashboard-strategy-editor"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,18 @@ import { ReactiveElement } from "lit";
|
|||
import { customElement } from "lit/decorators";
|
||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||
import { getEnergyPreferences } from "../../../data/energy";
|
||||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { generateDefaultViewConfig } from "../common/generate-lovelace-config";
|
||||
|
||||
export type OriginalStatesViewStrategyConfig = {
|
||||
no_area_group?: boolean;
|
||||
};
|
||||
|
||||
@customElement("original-states-view-strategy")
|
||||
export class OriginalStatesViewStrategy extends ReactiveElement {
|
||||
static async generate(
|
||||
_config: LovelaceStrategyConfig,
|
||||
config: OriginalStatesViewStrategyConfig,
|
||||
hass: HomeAssistant
|
||||
): Promise<LovelaceViewConfig> {
|
||||
if (hass.config.state === STATE_NOT_RUNNING) {
|
||||
|
@ -37,7 +40,7 @@ export class OriginalStatesViewStrategy extends ReactiveElement {
|
|||
// User can override default view. If they didn't, we will add one
|
||||
// that contains all entities.
|
||||
const view = generateDefaultViewConfig(
|
||||
hass.areas,
|
||||
config.no_area_group ? {} : hass.areas,
|
||||
hass.devices,
|
||||
hass.entities,
|
||||
hass.states,
|
||||
|
|
|
@ -2,9 +2,11 @@ import { LovelaceConfig } from "../../../data/lovelace/config/types";
|
|||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||
import { HomeAssistant } from "../../../types";
|
||||
import { LovelaceGenericElementEditor } from "../types";
|
||||
|
||||
export type LovelaceStrategy<T = any> = {
|
||||
generate(config: LovelaceStrategyConfig, hass: HomeAssistant): Promise<T>;
|
||||
getConfigElement?: () => LovelaceStrategyEditor;
|
||||
};
|
||||
|
||||
export interface LovelaceDashboardStrategy
|
||||
|
@ -12,3 +14,7 @@ export interface LovelaceDashboardStrategy
|
|||
|
||||
export interface LovelaceViewStrategy
|
||||
extends LovelaceStrategy<LovelaceViewConfig> {}
|
||||
|
||||
export interface LovelaceStrategyEditor extends LovelaceGenericElementEditor {
|
||||
setConfig(config: LovelaceStrategyConfig): void;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue