mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-21 08:16:36 +00:00
Add configuration to default dashboard (#18658)
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com>
This commit is contained in:
parent
0735705dd3
commit
270d463d02
@ -328,7 +328,7 @@ export class HaAreaPicker extends LitElement {
|
|||||||
item-value-path="area_id"
|
item-value-path="area_id"
|
||||||
item-id-path="area_id"
|
item-id-path="area_id"
|
||||||
item-label-path="name"
|
item-label-path="name"
|
||||||
.value=${this.value}
|
.value=${this._value}
|
||||||
.disabled=${this.disabled}
|
.disabled=${this.disabled}
|
||||||
.required=${this.required}
|
.required=${this.required}
|
||||||
.label=${this.label === undefined && this.hass
|
.label=${this.label === undefined && this.hass
|
||||||
@ -347,18 +347,19 @@ export class HaAreaPicker extends LitElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _filterChanged(ev: CustomEvent): void {
|
private _filterChanged(ev: CustomEvent): void {
|
||||||
const filter = ev.detail.value;
|
const target = ev.target as HaComboBox;
|
||||||
if (!filter) {
|
const filterString = ev.detail.value;
|
||||||
|
if (!filterString) {
|
||||||
this.comboBox.filteredItems = this.comboBox.items;
|
this.comboBox.filteredItems = this.comboBox.items;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredItems = fuzzyFilterSort<ScorableAreaRegistryEntry>(
|
const filteredItems = fuzzyFilterSort<ScorableAreaRegistryEntry>(
|
||||||
filter,
|
filterString,
|
||||||
this.comboBox?.items || []
|
target.items || []
|
||||||
);
|
);
|
||||||
if (!this.noAdd && filteredItems?.length === 0) {
|
if (!this.noAdd && filteredItems?.length === 0) {
|
||||||
this._suggestion = filter;
|
this._suggestion = filterString;
|
||||||
this.comboBox.filteredItems = [
|
this.comboBox.filteredItems = [
|
||||||
{
|
{
|
||||||
area_id: "add_new_suggestion",
|
area_id: "add_new_suggestion",
|
||||||
|
@ -102,6 +102,7 @@ export class HaAreasPicker extends SubscribeMixin(LitElement) {
|
|||||||
.placeholder=${this.placeholder}
|
.placeholder=${this.placeholder}
|
||||||
.required=${this.required && !currentAreas.length}
|
.required=${this.required && !currentAreas.length}
|
||||||
@value-changed=${this._addArea}
|
@value-changed=${this._addArea}
|
||||||
|
.excludeAreas=${currentAreas}
|
||||||
></ha-area-picker>
|
></ha-area-picker>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -446,7 +446,12 @@ export const generateDefaultViewConfig = (
|
|||||||
entityEntries: HomeAssistant["entities"],
|
entityEntries: HomeAssistant["entities"],
|
||||||
entities: HassEntities,
|
entities: HassEntities,
|
||||||
localize: LocalizeFunc,
|
localize: LocalizeFunc,
|
||||||
energyPrefs?: EnergyPreferences
|
energyPrefs?: EnergyPreferences,
|
||||||
|
areasPrefs?: {
|
||||||
|
hidden?: string[];
|
||||||
|
},
|
||||||
|
hideEntitiesWithoutAreas?: boolean,
|
||||||
|
hideEnergy?: boolean
|
||||||
): LovelaceViewConfig => {
|
): LovelaceViewConfig => {
|
||||||
const states = computeDefaultViewStates(entities, entityEntries);
|
const states = computeDefaultViewStates(entities, entityEntries);
|
||||||
const path = "default_view";
|
const path = "default_view";
|
||||||
@ -469,6 +474,17 @@ export const generateDefaultViewConfig = (
|
|||||||
states
|
states
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (areasPrefs?.hidden) {
|
||||||
|
for (const area of areasPrefs.hidden) {
|
||||||
|
splittedByAreaDevice.areasWithEntities[area] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hideEntitiesWithoutAreas) {
|
||||||
|
splittedByAreaDevice.devicesWithEntities = {};
|
||||||
|
splittedByAreaDevice.otherEntities = {};
|
||||||
|
}
|
||||||
|
|
||||||
const splittedByGroups = splitByGroups(splittedByAreaDevice.otherEntities);
|
const splittedByGroups = splitByGroups(splittedByAreaDevice.otherEntities);
|
||||||
splittedByGroups.groups.sort(
|
splittedByGroups.groups.sort(
|
||||||
(gr1, gr2) => groupOrders[gr1.entity_id] - groupOrders[gr2.entity_id]
|
(gr1, gr2) => groupOrders[gr1.entity_id] - groupOrders[gr2.entity_id]
|
||||||
@ -553,7 +569,7 @@ export const generateDefaultViewConfig = (
|
|||||||
|
|
||||||
let energyCard: LovelaceCardConfig | undefined;
|
let energyCard: LovelaceCardConfig | undefined;
|
||||||
|
|
||||||
if (energyPrefs) {
|
if (energyPrefs && !hideEnergy) {
|
||||||
// Distribution card requires the grid to be configured
|
// Distribution card requires the grid to be configured
|
||||||
const grid = energyPrefs.energy_sources.find(
|
const grid = energyPrefs.energy_sources.find(
|
||||||
(source) => source.type === "grid"
|
(source) => source.type === "grid"
|
||||||
|
@ -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,132 @@
|
|||||||
|
import { html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import memoizeOne from "memoize-one";
|
||||||
|
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: "hidden_areas",
|
||||||
|
selector: {
|
||||||
|
area: {
|
||||||
|
multiple: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "",
|
||||||
|
type: "grid",
|
||||||
|
schema: [
|
||||||
|
{
|
||||||
|
name: "hide_entities_without_area",
|
||||||
|
selector: {
|
||||||
|
boolean: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hide_energy",
|
||||||
|
selector: {
|
||||||
|
boolean: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
] as const satisfies readonly HaFormSchema[];
|
||||||
|
|
||||||
|
type FormData = {
|
||||||
|
hidden_areas: string[];
|
||||||
|
hide_energy?: boolean;
|
||||||
|
hide_entities_without_area?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _configToFormData = memoizeOne(
|
||||||
|
(config: OriginalStatesDashboardStrategyConfig): FormData => {
|
||||||
|
const { areas, ...rest } = config;
|
||||||
|
return {
|
||||||
|
...rest,
|
||||||
|
hidden_areas: areas?.hidden || [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
private _formDataToConfig = memoizeOne(
|
||||||
|
(data: FormData): OriginalStatesDashboardStrategyConfig => {
|
||||||
|
const { hidden_areas, ...rest } = data;
|
||||||
|
const areas =
|
||||||
|
hidden_areas.length > 0
|
||||||
|
? {
|
||||||
|
hidden: hidden_areas,
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
return {
|
||||||
|
type: "original-states",
|
||||||
|
...rest,
|
||||||
|
areas,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this.hass || !this._config) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = this._configToFormData(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 data = ev.detail.value as FormData;
|
||||||
|
const config = this._formDataToConfig(data);
|
||||||
|
fireEvent(this, "config-changed", { config });
|
||||||
|
}
|
||||||
|
|
||||||
|
private _computeLabelCallback = (schema: SchemaUnion<typeof SCHEMA>) => {
|
||||||
|
switch (schema.name) {
|
||||||
|
case "hidden_areas":
|
||||||
|
case "hide_energy":
|
||||||
|
case "hide_entities_without_area":
|
||||||
|
return this.hass?.localize(
|
||||||
|
`ui.panel.lovelace.editor.strategy.original-states.${schema.name}`
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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-circular-progress";
|
||||||
import "../../../components/ha-code-editor";
|
import "../../../components/ha-code-editor";
|
||||||
import type { HaCodeEditor } from "../../../components/ha-code-editor";
|
import type { HaCodeEditor } from "../../../components/ha-code-editor";
|
||||||
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
import { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||||
import type { LovelaceConfig } from "../../../data/lovelace/config/types";
|
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||||
|
import { LovelaceConfig } from "../../../data/lovelace/config/types";
|
||||||
import type { HomeAssistant } from "../../../types";
|
import type { HomeAssistant } from "../../../types";
|
||||||
import type { LovelaceRowConfig } from "../entity-rows/types";
|
import type { LovelaceRowConfig } from "../entity-rows/types";
|
||||||
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
import { LovelaceHeaderFooterConfig } from "../header-footer/types";
|
||||||
@ -36,7 +37,8 @@ export interface ConfigChangedEvent {
|
|||||||
| LovelaceCardConfig
|
| LovelaceCardConfig
|
||||||
| LovelaceRowConfig
|
| LovelaceRowConfig
|
||||||
| LovelaceHeaderFooterConfig
|
| LovelaceHeaderFooterConfig
|
||||||
| LovelaceTileFeatureConfig;
|
| LovelaceTileFeatureConfig
|
||||||
|
| LovelaceStrategyConfig;
|
||||||
error?: string;
|
error?: string;
|
||||||
guiModeAvailable?: boolean;
|
guiModeAvailable?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,12 @@ import {
|
|||||||
import "@polymer/paper-tabs/paper-tab";
|
import "@polymer/paper-tabs/paper-tab";
|
||||||
import "@polymer/paper-tabs/paper-tabs";
|
import "@polymer/paper-tabs/paper-tabs";
|
||||||
import {
|
import {
|
||||||
css,
|
|
||||||
CSSResultGroup,
|
CSSResultGroup,
|
||||||
html,
|
|
||||||
LitElement,
|
LitElement,
|
||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
|
css,
|
||||||
|
html,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
import { customElement, property, state } from "lit/decorators";
|
import { customElement, property, state } from "lit/decorators";
|
||||||
import { classMap } from "lit/directives/class-map";
|
import { classMap } from "lit/directives/class-map";
|
||||||
@ -64,11 +64,17 @@ import { documentationUrl } from "../../util/documentation-url";
|
|||||||
import { swapView } from "./editor/config-util";
|
import { swapView } from "./editor/config-util";
|
||||||
import { showEditLovelaceDialog } from "./editor/lovelace-editor/show-edit-lovelace-dialog";
|
import { showEditLovelaceDialog } from "./editor/lovelace-editor/show-edit-lovelace-dialog";
|
||||||
import { showEditViewDialog } from "./editor/view-editor/show-edit-view-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 type { Lovelace } from "./types";
|
||||||
import "./views/hui-view";
|
import "./views/hui-view";
|
||||||
import type { HUIView } from "./views/hui-view";
|
import type { HUIView } from "./views/hui-view";
|
||||||
import { LovelaceViewConfig } from "../../data/lovelace/config/view";
|
import { LovelaceViewConfig } from "../../data/lovelace/config/view";
|
||||||
import { LovelaceConfig } from "../../data/lovelace/config/types";
|
import {
|
||||||
|
LovelaceConfig,
|
||||||
|
isStrategyDashboard,
|
||||||
|
} from "../../data/lovelace/config/types";
|
||||||
|
import { showSaveDialog } from "./editor/show-save-config-dialog";
|
||||||
|
import { isLegacyStrategyConfig } from "./strategies/legacy-strategy";
|
||||||
|
|
||||||
@customElement("hui-root")
|
@customElement("hui-root")
|
||||||
class HUIRoot extends LitElement {
|
class HUIRoot extends LitElement {
|
||||||
@ -813,6 +819,26 @@ class HUIRoot extends LitElement {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
isStrategyDashboard(this.lovelace!.rawConfig) &&
|
||||||
|
!isLegacyStrategyConfig(this.lovelace!.rawConfig.strategy)
|
||||||
|
) {
|
||||||
|
showDashboardStrategyEditorDialog(this, {
|
||||||
|
config: this.lovelace!.rawConfig,
|
||||||
|
saveConfig: this.lovelace!.saveConfig,
|
||||||
|
takeControl: () => {
|
||||||
|
showSaveDialog(this, {
|
||||||
|
lovelace: this.lovelace!,
|
||||||
|
mode: "storage",
|
||||||
|
narrow: this.narrow!,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
showRawConfigEditor: () => {
|
||||||
|
this.lovelace!.enableFullEditMode();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
this.lovelace!.setEditMode(true);
|
this.lovelace!.setEditMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,202 @@
|
|||||||
|
import {
|
||||||
|
mdiAccountHardHat,
|
||||||
|
mdiClose,
|
||||||
|
mdiCodeBraces,
|
||||||
|
mdiDotsVertical,
|
||||||
|
} from "@mdi/js";
|
||||||
|
import { CSSResultGroup, LitElement, css, html, nothing } from "lit";
|
||||||
|
import { customElement, property, query, state } from "lit/decorators";
|
||||||
|
import { HASSDomEvent, fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { stopPropagation } from "../../../../common/dom/stop_propagation";
|
||||||
|
import "../../../../components/ha-button";
|
||||||
|
import "../../../../components/ha-button-menu";
|
||||||
|
import "../../../../components/ha-dialog";
|
||||||
|
import "../../../../components/ha-dialog-header";
|
||||||
|
import "../../../../components/ha-icon-button";
|
||||||
|
import { LovelaceStrategyConfig } from "../../../../data/lovelace/config/strategy";
|
||||||
|
import { 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);
|
||||||
|
|
||||||
|
const title = this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.strategy-editor.header"
|
||||||
|
);
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-dialog
|
||||||
|
open
|
||||||
|
@closed=${this.closeDialog}
|
||||||
|
scrimClickAction
|
||||||
|
escapeKeyAction
|
||||||
|
@opened=${this._opened}
|
||||||
|
.heading=${title || "-"}
|
||||||
|
>
|
||||||
|
<ha-dialog-header slot="heading">
|
||||||
|
<ha-icon-button
|
||||||
|
slot="navigationIcon"
|
||||||
|
dialogAction="cancel"
|
||||||
|
.label=${this.hass.localize("ui.common.close")}
|
||||||
|
.path=${mdiClose}
|
||||||
|
></ha-icon-button>
|
||||||
|
<span slot="title" .title=${title}>${title}</span>
|
||||||
|
<ha-button-menu
|
||||||
|
corner="BOTTOM_END"
|
||||||
|
menuCorner="END"
|
||||||
|
slot="actionItems"
|
||||||
|
@closed=${stopPropagation}
|
||||||
|
fixed
|
||||||
|
>
|
||||||
|
<ha-icon-button
|
||||||
|
slot="trigger"
|
||||||
|
.label=${this.hass.localize("ui.common.menu")}
|
||||||
|
.path=${mdiDotsVertical}
|
||||||
|
></ha-icon-button>
|
||||||
|
<ha-list-item
|
||||||
|
graphic="icon"
|
||||||
|
@request-selected=${this._showRawConfigEditor}
|
||||||
|
>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.strategy-editor.raw_configuration_editor"
|
||||||
|
)}
|
||||||
|
<ha-svg-icon slot="graphic" .path=${mdiCodeBraces}></ha-svg-icon>
|
||||||
|
</ha-list-item>
|
||||||
|
<ha-list-item graphic="icon" @request-selected=${this._takeControl}>
|
||||||
|
${this.hass.localize(
|
||||||
|
"ui.panel.lovelace.editor.strategy-editor.take_control"
|
||||||
|
)}
|
||||||
|
<ha-svg-icon
|
||||||
|
slot="graphic"
|
||||||
|
.path=${mdiAccountHardHat}
|
||||||
|
></ha-svg-icon>
|
||||||
|
</ha-list-item>
|
||||||
|
</ha-button-menu>
|
||||||
|
</ha-dialog-header>
|
||||||
|
<div class="content">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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.strategy-editor.show_code_editor"
|
||||||
|
: "ui.panel.lovelace.editor.strategy-editor.show_visual_editor"
|
||||||
|
)}
|
||||||
|
</ha-button>
|
||||||
|
<ha-button @click=${this._save} slot="primaryAction">
|
||||||
|
${this.hass!.localize("ui.common.save")}
|
||||||
|
</ha-button>
|
||||||
|
</ha-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _takeControl() {
|
||||||
|
this._params!.takeControl();
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _showRawConfigEditor() {
|
||||||
|
this._params!.showRawConfigEditor();
|
||||||
|
this.closeDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get styles(): CSSResultGroup {
|
||||||
|
return [
|
||||||
|
haStyleDialog,
|
||||||
|
css`
|
||||||
|
ha-dialog {
|
||||||
|
--mdc-dialog-max-width: 800px;
|
||||||
|
--dialog-content-padding: 0 24px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"dialog-dashboard-strategy-editor": DialogDashboardStrategyEditor;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||||
|
import { LovelaceDashboardStrategyConfig } from "../../../../data/lovelace/config/types";
|
||||||
|
|
||||||
|
export interface DashboardStrategyEditorDialogParams {
|
||||||
|
config: LovelaceDashboardStrategyConfig;
|
||||||
|
saveConfig: (config: LovelaceDashboardStrategyConfig) => void;
|
||||||
|
takeControl: () => void;
|
||||||
|
showRawConfigEditor: () => 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,
|
isStrategyView,
|
||||||
} from "../../../data/lovelace/config/view";
|
} from "../../../data/lovelace/config/view";
|
||||||
import { AsyncReturnType, HomeAssistant } from "../../../types";
|
import { AsyncReturnType, HomeAssistant } from "../../../types";
|
||||||
import { isLegacyStrategy } from "./legacy-strategy";
|
import { cleanLegacyStrategyConfig, isLegacyStrategy } from "./legacy-strategy";
|
||||||
import {
|
import {
|
||||||
LovelaceDashboardStrategy,
|
LovelaceDashboardStrategy,
|
||||||
LovelaceStrategy,
|
LovelaceStrategy,
|
||||||
@ -40,7 +40,7 @@ type StrategyConfig<T extends LovelaceStrategyConfigType> = AsyncReturnType<
|
|||||||
Strategies[T]["generate"]
|
Strategies[T]["generate"]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const getLovelaceStrategy = async <T extends LovelaceStrategyConfigType>(
|
export const getLovelaceStrategy = async <T extends LovelaceStrategyConfigType>(
|
||||||
configType: T,
|
configType: T,
|
||||||
strategyType: string
|
strategyType: string
|
||||||
): Promise<LovelaceStrategy> => {
|
): Promise<LovelaceStrategy> => {
|
||||||
@ -109,12 +109,7 @@ const generateStrategy = async <T extends LovelaceStrategyConfigType>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = {
|
const config = cleanLegacyStrategyConfig(strategyConfig);
|
||||||
...strategyConfig,
|
|
||||||
...strategyConfig.options,
|
|
||||||
};
|
|
||||||
|
|
||||||
delete config.options;
|
|
||||||
|
|
||||||
return await strategy.generate(config, hass);
|
return await strategy.generate(config, hass);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||||
import {
|
import {
|
||||||
LovelaceConfig,
|
LovelaceConfig,
|
||||||
LovelaceRawConfig,
|
LovelaceRawConfig,
|
||||||
@ -27,3 +28,22 @@ export interface LovelaceViewStrategy {
|
|||||||
hass: HomeAssistant;
|
hass: HomeAssistant;
|
||||||
}): Promise<LovelaceViewConfig>;
|
}): Promise<LovelaceViewConfig>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We assume that if a strategy config has only "type" and "options" parameters, it's a legacy strategy config
|
||||||
|
export const isLegacyStrategyConfig = (config: LovelaceStrategyConfig) =>
|
||||||
|
Object.keys(config).length === 2 &&
|
||||||
|
"options" in config &&
|
||||||
|
typeof config.options === "object";
|
||||||
|
|
||||||
|
export const cleanLegacyStrategyConfig = (config: LovelaceStrategyConfig) => {
|
||||||
|
if (!isLegacyStrategyConfig(config)) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
const cleanedConfig = {
|
||||||
|
...config,
|
||||||
|
...config.options,
|
||||||
|
};
|
||||||
|
|
||||||
|
delete cleanedConfig.options;
|
||||||
|
return cleanedConfig;
|
||||||
|
};
|
||||||
|
@ -1,22 +1,35 @@
|
|||||||
import { ReactiveElement } from "lit";
|
import { ReactiveElement } from "lit";
|
||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import { HomeAssistant } from "../../../types";
|
|
||||||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
|
||||||
import { LovelaceConfig } from "../../../data/lovelace/config/types";
|
import { LovelaceConfig } from "../../../data/lovelace/config/types";
|
||||||
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { OriginalStatesViewStrategyConfig } from "./original-states-view-strategy";
|
||||||
|
import { LovelaceStrategyEditor } from "./types";
|
||||||
|
|
||||||
|
export type OriginalStatesDashboardStrategyConfig =
|
||||||
|
OriginalStatesViewStrategyConfig;
|
||||||
|
|
||||||
@customElement("original-states-dashboard-strategy")
|
@customElement("original-states-dashboard-strategy")
|
||||||
export class OriginalStatesDashboardStrategy extends ReactiveElement {
|
export class OriginalStatesDashboardStrategy extends ReactiveElement {
|
||||||
static async generate(
|
static async generate(
|
||||||
_config: LovelaceStrategyConfig,
|
config: OriginalStatesDashboardStrategyConfig,
|
||||||
hass: HomeAssistant
|
hass: HomeAssistant
|
||||||
): Promise<LovelaceConfig> {
|
): Promise<LovelaceConfig> {
|
||||||
return {
|
return {
|
||||||
title: hass.config.location_name,
|
title: hass.config.location_name,
|
||||||
views: [
|
views: [
|
||||||
{
|
{
|
||||||
strategy: { type: "original-states" },
|
strategy: config,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,23 @@ import { ReactiveElement } from "lit";
|
|||||||
import { customElement } from "lit/decorators";
|
import { customElement } from "lit/decorators";
|
||||||
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
|
||||||
import { getEnergyPreferences } from "../../../data/energy";
|
import { getEnergyPreferences } from "../../../data/energy";
|
||||||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
|
||||||
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
import { generateDefaultViewConfig } from "../common/generate-lovelace-config";
|
import { generateDefaultViewConfig } from "../common/generate-lovelace-config";
|
||||||
|
|
||||||
|
export type OriginalStatesViewStrategyConfig = {
|
||||||
|
type: "original-states";
|
||||||
|
areas?: {
|
||||||
|
hidden?: string[];
|
||||||
|
};
|
||||||
|
hide_entities_without_area?: boolean;
|
||||||
|
hide_energy?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
@customElement("original-states-view-strategy")
|
@customElement("original-states-view-strategy")
|
||||||
export class OriginalStatesViewStrategy extends ReactiveElement {
|
export class OriginalStatesViewStrategy extends ReactiveElement {
|
||||||
static async generate(
|
static async generate(
|
||||||
_config: LovelaceStrategyConfig,
|
config: OriginalStatesViewStrategyConfig,
|
||||||
hass: HomeAssistant
|
hass: HomeAssistant
|
||||||
): Promise<LovelaceViewConfig> {
|
): Promise<LovelaceViewConfig> {
|
||||||
if (hass.config.state === STATE_NOT_RUNNING) {
|
if (hass.config.state === STATE_NOT_RUNNING) {
|
||||||
@ -42,7 +50,10 @@ export class OriginalStatesViewStrategy extends ReactiveElement {
|
|||||||
hass.entities,
|
hass.entities,
|
||||||
hass.states,
|
hass.states,
|
||||||
localize,
|
localize,
|
||||||
energyPrefs
|
energyPrefs,
|
||||||
|
config.areas,
|
||||||
|
config.hide_entities_without_area,
|
||||||
|
config.hide_energy
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add map of geo locations to default view if loaded
|
// Add map of geo locations to default view if loaded
|
||||||
|
@ -2,9 +2,11 @@ import { LovelaceConfig } from "../../../data/lovelace/config/types";
|
|||||||
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
import { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||||
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
import { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||||
import { HomeAssistant } from "../../../types";
|
import { HomeAssistant } from "../../../types";
|
||||||
|
import { LovelaceGenericElementEditor } from "../types";
|
||||||
|
|
||||||
export type LovelaceStrategy<T = any> = {
|
export type LovelaceStrategy<T = any> = {
|
||||||
generate(config: LovelaceStrategyConfig, hass: HomeAssistant): Promise<T>;
|
generate(config: LovelaceStrategyConfig, hass: HomeAssistant): Promise<T>;
|
||||||
|
getConfigElement?: () => LovelaceStrategyEditor;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface LovelaceDashboardStrategy
|
export interface LovelaceDashboardStrategy
|
||||||
@ -12,3 +14,7 @@ export interface LovelaceDashboardStrategy
|
|||||||
|
|
||||||
export interface LovelaceViewStrategy
|
export interface LovelaceViewStrategy
|
||||||
extends LovelaceStrategy<LovelaceViewConfig> {}
|
extends LovelaceStrategy<LovelaceViewConfig> {}
|
||||||
|
|
||||||
|
export interface LovelaceStrategyEditor extends LovelaceGenericElementEditor {
|
||||||
|
setConfig(config: LovelaceStrategyConfig): void;
|
||||||
|
}
|
||||||
|
@ -4870,6 +4870,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"strategy-editor": {
|
||||||
|
"header": "Edit dashboard",
|
||||||
|
"take_control": "Take control",
|
||||||
|
"raw_configuration_editor": "[%key:ui::panel::lovelace::editor::menu::raw_editor%]",
|
||||||
|
"show_code_editor": "[%key:ui::panel::lovelace::editor::edit_card::show_code_editor%]",
|
||||||
|
"show_visual_editor": "[%key:ui::panel::lovelace::editor::edit_card::show_visual_editor%]"
|
||||||
|
},
|
||||||
"card": {
|
"card": {
|
||||||
"alarm-panel": {
|
"alarm-panel": {
|
||||||
"name": "Alarm panel",
|
"name": "Alarm panel",
|
||||||
@ -5264,6 +5271,13 @@
|
|||||||
"twice_daily": "Twice daily"
|
"twice_daily": "Twice daily"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"strategy": {
|
||||||
|
"original-states": {
|
||||||
|
"hidden_areas": "Hidden Areas",
|
||||||
|
"hide_entities_without_area": "Hide entities without area",
|
||||||
|
"hide_energy": "Hide energy"
|
||||||
|
}
|
||||||
|
},
|
||||||
"view": {
|
"view": {
|
||||||
"panel_mode": {
|
"panel_mode": {
|
||||||
"warning_multiple_cards": "This view contains more than one card, but a panel view can only show 1 card."
|
"warning_multiple_cards": "This view contains more than one card, but a panel view can only show 1 card."
|
||||||
|
Loading…
x
Reference in New Issue
Block a user