mirror of
https://github.com/home-assistant/frontend.git
synced 2025-04-19 19:07:23 +00:00
Compare commits
13 Commits
dev
...
20250327.1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
118c25d25f | ||
![]() |
ae5427a75e | ||
![]() |
3b6e267fb5 | ||
![]() |
1770a51303 | ||
![]() |
534df3d378 | ||
![]() |
23229b3e3b | ||
![]() |
94ee99160b | ||
![]() |
b009d71e8f | ||
![]() |
2ab8209622 | ||
![]() |
ed2940edc3 | ||
![]() |
e2b9a06242 | ||
![]() |
a7acee0438 | ||
![]() |
1208af510c |
@ -309,7 +309,7 @@ export class HcMain extends HassElement {
|
||||
"../../../../src/panels/lovelace/strategies/get-strategy"
|
||||
);
|
||||
const config = await generateLovelaceDashboardStrategy(
|
||||
rawConfig.strategy,
|
||||
rawConfig,
|
||||
this.hass!
|
||||
);
|
||||
this._handleNewLovelaceConfig(config);
|
||||
@ -351,10 +351,7 @@ export class HcMain extends HassElement {
|
||||
"../../../../src/panels/lovelace/strategies/get-strategy"
|
||||
);
|
||||
this._handleNewLovelaceConfig(
|
||||
await generateLovelaceDashboardStrategy(
|
||||
DEFAULT_CONFIG.strategy,
|
||||
this.hass!
|
||||
)
|
||||
await generateLovelaceDashboardStrategy(DEFAULT_CONFIG, this.hass!)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "home-assistant-frontend"
|
||||
version = "20250326.0"
|
||||
version = "20250327.1"
|
||||
license = "Apache-2.0"
|
||||
license-files = ["LICENSE*"]
|
||||
description = "The Home Assistant frontend"
|
||||
|
@ -33,7 +33,14 @@ export const computeEntityEntryName = (
|
||||
const device = entry.device_id ? hass.devices[entry.device_id] : undefined;
|
||||
|
||||
if (!device) {
|
||||
return name;
|
||||
if (name) {
|
||||
return name;
|
||||
}
|
||||
const stateObj = hass.states[entry.entity_id] as HassEntity | undefined;
|
||||
if (stateObj) {
|
||||
return computeStateName(stateObj);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const deviceName = computeDeviceName(device);
|
||||
|
@ -1,7 +1,11 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import type { AreaRegistryEntry } from "../../data/area_registry";
|
||||
import type { DeviceRegistryEntry } from "../../data/device_registry";
|
||||
import type { EntityRegistryDisplayEntry } from "../../data/entity_registry";
|
||||
import type {
|
||||
EntityRegistryDisplayEntry,
|
||||
EntityRegistryEntry,
|
||||
ExtEntityRegistryEntry,
|
||||
} from "../../data/entity_registry";
|
||||
import type { FloorRegistryEntry } from "../../data/floor_registry";
|
||||
import type { HomeAssistant } from "../../types";
|
||||
|
||||
@ -19,6 +23,23 @@ export const getEntityContext = (
|
||||
| EntityRegistryDisplayEntry
|
||||
| undefined;
|
||||
|
||||
if (!entry) {
|
||||
return {
|
||||
device: null,
|
||||
area: null,
|
||||
floor: null,
|
||||
};
|
||||
}
|
||||
return getEntityEntryContext(entry, hass);
|
||||
};
|
||||
|
||||
export const getEntityEntryContext = (
|
||||
entry:
|
||||
| EntityRegistryDisplayEntry
|
||||
| EntityRegistryEntry
|
||||
| ExtEntityRegistryEntry,
|
||||
hass: HomeAssistant
|
||||
): EntityContext => {
|
||||
const deviceId = entry?.device_id;
|
||||
const device = deviceId ? hass.devices[deviceId] : null;
|
||||
const areaId = entry?.area_id || device?.area_id;
|
||||
|
@ -69,11 +69,14 @@ export class HaTemplateSelector extends LitElement {
|
||||
}
|
||||
|
||||
private _handleChange(ev) {
|
||||
const value = ev.target.value;
|
||||
let value = ev.target.value;
|
||||
if (this.value === value) {
|
||||
return;
|
||||
}
|
||||
this.warn = WARNING_STRINGS.find((str) => value.includes(str));
|
||||
if (value === "" && !this.required) {
|
||||
value = undefined;
|
||||
}
|
||||
fireEvent(this, "value-changed", { value });
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@ export class HaTileInfo extends LitElement {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
height: 36px;
|
||||
}
|
||||
span {
|
||||
text-overflow: ellipsis;
|
||||
|
@ -38,7 +38,7 @@ export interface Statistic {
|
||||
|
||||
export enum StatisticMeanType {
|
||||
NONE = 0,
|
||||
ARIMETHIC = 1,
|
||||
ARITHMETIC = 1,
|
||||
CIRCULAR = 2,
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,10 @@ import { stopPropagation } from "../../common/dom/stop_propagation";
|
||||
import { computeAreaName } from "../../common/entity/compute_area_name";
|
||||
import { computeDeviceName } from "../../common/entity/compute_device_name";
|
||||
import { computeDomain } from "../../common/entity/compute_domain";
|
||||
import { computeEntityName } from "../../common/entity/compute_entity_name";
|
||||
import { getEntityContext } from "../../common/entity/get_entity_context";
|
||||
import {
|
||||
computeEntityEntryName,
|
||||
computeEntityName,
|
||||
} from "../../common/entity/compute_entity_name";
|
||||
import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event";
|
||||
import { navigate } from "../../common/navigate";
|
||||
import "../../components/ha-button-menu";
|
||||
@ -56,6 +58,10 @@ import "./ha-more-info-history-and-logbook";
|
||||
import "./ha-more-info-info";
|
||||
import "./ha-more-info-settings";
|
||||
import "./more-info-content";
|
||||
import {
|
||||
getEntityContext,
|
||||
getEntityEntryContext,
|
||||
} from "../../common/entity/get_entity_context";
|
||||
|
||||
export interface MoreInfoDialogParams {
|
||||
entityId: string | null;
|
||||
@ -293,11 +299,18 @@ export class MoreInfoDialog extends LitElement {
|
||||
this._initialView !== DEFAULT_VIEW && !this._childView;
|
||||
const showCloseIcon = isDefaultView || isSpecificInitialView;
|
||||
|
||||
const context = stateObj ? getEntityContext(stateObj, this.hass) : null;
|
||||
const context = stateObj
|
||||
? getEntityContext(stateObj, this.hass)
|
||||
: this._entry
|
||||
? getEntityEntryContext(this._entry, this.hass)
|
||||
: undefined;
|
||||
|
||||
const entityName = stateObj
|
||||
? computeEntityName(stateObj, this.hass)
|
||||
: undefined;
|
||||
: this._entry
|
||||
? computeEntityEntryName(this._entry, this.hass)
|
||||
: entityId;
|
||||
|
||||
const deviceName = context?.device
|
||||
? computeDeviceName(context.device)
|
||||
: undefined;
|
||||
@ -306,7 +319,7 @@ export class MoreInfoDialog extends LitElement {
|
||||
const breadcrumb = [areaName, deviceName, entityName].filter(
|
||||
(v): v is string => Boolean(v)
|
||||
);
|
||||
const title = this._childView?.viewTitle || breadcrumb.pop();
|
||||
const title = this._childView?.viewTitle || breadcrumb.pop() || entityId;
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
|
@ -152,12 +152,14 @@ export class EnergyDeviceSettings extends LitElement {
|
||||
device_consumptions: this.preferences
|
||||
.device_consumption as DeviceConsumptionEnergyPreference[],
|
||||
saveCallback: async (newDevice) => {
|
||||
await this._savePreferences({
|
||||
const newPrefs = {
|
||||
...this.preferences,
|
||||
device_consumption: this.preferences.device_consumption.map((d) =>
|
||||
d === origDevice ? newDevice : d
|
||||
),
|
||||
});
|
||||
};
|
||||
this._sanitizeParents(newPrefs);
|
||||
await this._savePreferences(newPrefs);
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -177,6 +179,15 @@ export class EnergyDeviceSettings extends LitElement {
|
||||
});
|
||||
}
|
||||
|
||||
private _sanitizeParents(prefs: EnergyPreferences) {
|
||||
const statIds = prefs.device_consumption.map((d) => d.stat_consumption);
|
||||
prefs.device_consumption.forEach((d) => {
|
||||
if (d.included_in_stat && !statIds.includes(d.included_in_stat)) {
|
||||
delete d.included_in_stat;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async _deleteDevice(ev) {
|
||||
const deviceToDelete: DeviceConsumptionEnergyPreference =
|
||||
ev.currentTarget.device;
|
||||
@ -196,14 +207,7 @@ export class EnergyDeviceSettings extends LitElement {
|
||||
(device) => device !== deviceToDelete
|
||||
),
|
||||
};
|
||||
newPrefs.device_consumption.forEach((d, idx) => {
|
||||
if (d.included_in_stat === deviceToDelete.stat_consumption) {
|
||||
newPrefs.device_consumption[idx] = {
|
||||
...newPrefs.device_consumption[idx],
|
||||
};
|
||||
delete newPrefs.device_consumption[idx].included_in_stat;
|
||||
}
|
||||
});
|
||||
this._sanitizeParents(newPrefs);
|
||||
await this._savePreferences(newPrefs);
|
||||
} catch (err: any) {
|
||||
showAlertDialog(this, { title: `Failed to save config: ${err.message}` });
|
||||
|
@ -74,6 +74,7 @@ export class DialogEnergyDeviceSettings
|
||||
this._possibleParents = this._params.device_consumptions.filter(
|
||||
(d) =>
|
||||
d.stat_consumption !== this._device!.stat_consumption &&
|
||||
d.stat_consumption !== this._params?.device?.stat_consumption &&
|
||||
!children.includes(d.stat_consumption)
|
||||
);
|
||||
}
|
||||
@ -160,18 +161,26 @@ export class DialogEnergyDeviceSettings
|
||||
naturalMenuWidth
|
||||
clearable
|
||||
>
|
||||
${this._possibleParents.map(
|
||||
(stat) => html`
|
||||
<mwc-list-item .value=${stat.stat_consumption}
|
||||
>${stat.name ||
|
||||
getStatisticLabel(
|
||||
this.hass,
|
||||
stat.stat_consumption,
|
||||
this._params?.statsMetadata?.[stat.stat_consumption]
|
||||
)}</mwc-list-item
|
||||
>
|
||||
`
|
||||
)}
|
||||
${!this._possibleParents.length
|
||||
? html`
|
||||
<mwc-list-item disabled value="-"
|
||||
>${this.hass.localize(
|
||||
"ui.panel.config.energy.device_consumption.dialog.no_upstream_devices"
|
||||
)}</mwc-list-item
|
||||
>
|
||||
`
|
||||
: this._possibleParents.map(
|
||||
(stat) => html`
|
||||
<mwc-list-item .value=${stat.stat_consumption}
|
||||
>${stat.name ||
|
||||
getStatisticLabel(
|
||||
this.hass,
|
||||
stat.stat_consumption,
|
||||
this._params?.statsMetadata?.[stat.stat_consumption]
|
||||
)}</mwc-list-item
|
||||
>
|
||||
`
|
||||
)}
|
||||
</ha-select>
|
||||
|
||||
<mwc-button @click=${this.closeDialog} slot="secondaryAction">
|
||||
|
@ -187,7 +187,7 @@ export class LovelacePanel extends LitElement {
|
||||
|
||||
private async _regenerateConfig() {
|
||||
const conf = await generateLovelaceDashboardStrategy(
|
||||
DEFAULT_CONFIG.strategy,
|
||||
DEFAULT_CONFIG,
|
||||
this.hass!
|
||||
);
|
||||
this._setLovelaceConfig(conf, DEFAULT_CONFIG, "generated");
|
||||
@ -281,10 +281,7 @@ export class LovelacePanel extends LitElement {
|
||||
// We need these to generate a dashboard, wait for them
|
||||
return;
|
||||
}
|
||||
conf = await generateLovelaceDashboardStrategy(
|
||||
rawConf.strategy,
|
||||
this.hass!
|
||||
);
|
||||
conf = await generateLovelaceDashboardStrategy(rawConf, this.hass!);
|
||||
} else {
|
||||
conf = rawConf;
|
||||
}
|
||||
@ -301,7 +298,7 @@ export class LovelacePanel extends LitElement {
|
||||
return;
|
||||
}
|
||||
conf = await generateLovelaceDashboardStrategy(
|
||||
DEFAULT_CONFIG.strategy,
|
||||
DEFAULT_CONFIG,
|
||||
this.hass!
|
||||
);
|
||||
rawConf = DEFAULT_CONFIG;
|
||||
@ -378,10 +375,7 @@ export class LovelacePanel extends LitElement {
|
||||
let conf: LovelaceConfig;
|
||||
// If strategy defined, apply it here.
|
||||
if (isStrategyDashboard(newConfig)) {
|
||||
conf = await generateLovelaceDashboardStrategy(
|
||||
newConfig.strategy,
|
||||
this.hass!
|
||||
);
|
||||
conf = await generateLovelaceDashboardStrategy(newConfig, this.hass!);
|
||||
} else {
|
||||
conf = newConfig;
|
||||
}
|
||||
@ -415,7 +409,7 @@ export class LovelacePanel extends LitElement {
|
||||
try {
|
||||
// Optimistic update
|
||||
const generatedConf = await generateLovelaceDashboardStrategy(
|
||||
DEFAULT_CONFIG.strategy,
|
||||
DEFAULT_CONFIG,
|
||||
this.hass!
|
||||
);
|
||||
this._updateLovelace({
|
||||
|
@ -76,9 +76,9 @@ import { getLovelaceStrategy } from "./strategies/get-strategy";
|
||||
import { isLegacyStrategyConfig } from "./strategies/legacy-strategy";
|
||||
import type { Lovelace } from "./types";
|
||||
import "./views/hui-view";
|
||||
import "./views/hui-view-container";
|
||||
import type { HUIView } from "./views/hui-view";
|
||||
import "./views/hui-view-background";
|
||||
import "./views/hui-view-container";
|
||||
|
||||
@customElement("hui-root")
|
||||
class HUIRoot extends LitElement {
|
||||
@ -99,8 +99,6 @@ class HUIRoot extends LitElement {
|
||||
|
||||
private _viewCache?: Record<string, HUIView>;
|
||||
|
||||
private _viewScrollPositions: Record<string, number> = {};
|
||||
|
||||
private _debouncedConfigChanged: () => void;
|
||||
|
||||
private _conversation = memoizeOne((_components) =>
|
||||
@ -112,7 +110,7 @@ class HUIRoot extends LitElement {
|
||||
// The view can trigger a re-render when it knows that certain
|
||||
// web components have been loaded.
|
||||
this._debouncedConfigChanged = debounce(
|
||||
() => this._selectView(this._curView, true, false),
|
||||
() => this._selectView(this._curView, true),
|
||||
100,
|
||||
false
|
||||
);
|
||||
@ -527,22 +525,13 @@ class HUIRoot extends LitElement {
|
||||
window.addEventListener("scroll", this._handleWindowScroll, {
|
||||
passive: true,
|
||||
});
|
||||
window.addEventListener("popstate", this._handlePopState);
|
||||
}
|
||||
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
window.removeEventListener("scroll", this._handleWindowScroll);
|
||||
window.removeEventListener("popstate", this._handlePopState);
|
||||
}
|
||||
|
||||
private _restoreScroll = false;
|
||||
|
||||
private _handlePopState = () => {
|
||||
// If we navigated back, we want to restore the scroll position.
|
||||
this._restoreScroll = true;
|
||||
};
|
||||
|
||||
protected updated(changedProperties: PropertyValues): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
@ -583,6 +572,9 @@ class HUIRoot extends LitElement {
|
||||
}
|
||||
newSelectView = index;
|
||||
}
|
||||
|
||||
// Will allow to override history scroll restoration when using back button
|
||||
setTimeout(() => scrollTo({ behavior: "auto", top: 0 }), 1);
|
||||
}
|
||||
|
||||
if (changedProperties.has("lovelace")) {
|
||||
@ -621,10 +613,7 @@ class HUIRoot extends LitElement {
|
||||
newSelectView = this._curView;
|
||||
}
|
||||
// Will allow for ripples to start rendering
|
||||
afterNextRender(() => {
|
||||
this._selectView(newSelectView, force, this._restoreScroll);
|
||||
this._restoreScroll = false;
|
||||
});
|
||||
afterNextRender(() => this._selectView(newSelectView, force));
|
||||
}
|
||||
}
|
||||
|
||||
@ -932,26 +921,17 @@ class HUIRoot extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
private _selectView(
|
||||
viewIndex: HUIRoot["_curView"],
|
||||
force: boolean,
|
||||
restoreScroll: boolean
|
||||
): void {
|
||||
private _selectView(viewIndex: HUIRoot["_curView"], force: boolean): void {
|
||||
if (!force && this._curView === viewIndex) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._curView != null) {
|
||||
this._viewScrollPositions[this._curView] = window.scrollY;
|
||||
}
|
||||
|
||||
viewIndex = viewIndex === undefined ? 0 : viewIndex;
|
||||
|
||||
this._curView = viewIndex;
|
||||
|
||||
if (force) {
|
||||
this._viewCache = {};
|
||||
this._viewScrollPositions = {};
|
||||
}
|
||||
|
||||
// Recreate a new element to clear the applied themes.
|
||||
@ -983,15 +963,10 @@ class HUIRoot extends LitElement {
|
||||
|
||||
if (!force && this._viewCache![viewIndex]) {
|
||||
view = this._viewCache![viewIndex];
|
||||
const position = restoreScroll
|
||||
? this._viewScrollPositions[viewIndex] || 0
|
||||
: 0;
|
||||
setTimeout(() => scrollTo({ behavior: "auto", top: position }), 0);
|
||||
} else {
|
||||
view = document.createElement("hui-view");
|
||||
view.index = viewIndex;
|
||||
this._viewCache![viewIndex] = view;
|
||||
setTimeout(() => scrollTo({ behavior: "auto", top: 0 }), 0);
|
||||
}
|
||||
|
||||
view.lovelace = this.lovelace;
|
||||
|
@ -185,7 +185,7 @@ export class HuiSection extends ReactiveElement {
|
||||
if (isStrategySection(sectionConfig)) {
|
||||
isStrategy = true;
|
||||
sectionConfig = await generateLovelaceSectionStrategy(
|
||||
sectionConfig.strategy,
|
||||
sectionConfig,
|
||||
this.hass!
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ReactiveElement } from "lit";
|
||||
import { customElement } from "lit/decorators";
|
||||
import { clamp } from "../../../../common/number/clamp";
|
||||
import type { LovelaceBadgeConfig } from "../../../../data/lovelace/config/badge";
|
||||
import type { LovelaceCardConfig } from "../../../../data/lovelace/config/card";
|
||||
import type { LovelaceSectionRawConfig } from "../../../../data/lovelace/config/section";
|
||||
@ -144,7 +145,10 @@ export class AreaViewStrategy extends ReactiveElement {
|
||||
});
|
||||
}
|
||||
|
||||
// Take the full width if there is only one section to avoid misalignment between cards and header
|
||||
// Allow between 2 and 3 columns (the max should be set to define the width of the header)
|
||||
const maxColumns = clamp(sections.length, 2, 3);
|
||||
|
||||
// Take the full width if there is only one section to avoid narrow header on desktop
|
||||
if (sections.length === 1) {
|
||||
sections[0].column_span = 2;
|
||||
}
|
||||
@ -160,7 +164,7 @@ export class AreaViewStrategy extends ReactiveElement {
|
||||
content: `## ${area.name}`,
|
||||
},
|
||||
},
|
||||
max_columns: 2,
|
||||
max_columns: maxColumns,
|
||||
sections: sections,
|
||||
badges: badges,
|
||||
};
|
||||
|
@ -1,13 +1,14 @@
|
||||
import { STATE_NOT_RUNNING } from "home-assistant-js-websocket";
|
||||
import { ReactiveElement } from "lit";
|
||||
import { customElement } from "lit/decorators";
|
||||
import type { LovelaceConfig } from "../../../../data/lovelace/config/types";
|
||||
import type { LovelaceViewRawConfig } from "../../../../data/lovelace/config/view";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { LovelaceStrategyEditor } from "../types";
|
||||
import type {
|
||||
AreaViewStrategyConfig,
|
||||
EntitiesDisplay,
|
||||
} from "./area-view-strategy";
|
||||
import type { LovelaceStrategyEditor } from "../types";
|
||||
import type { AreasViewStrategyConfig } from "./areas-overview-view-strategy";
|
||||
import { computeAreaPath, getAreas } from "./helpers/areas-strategy-helper";
|
||||
|
||||
@ -30,6 +31,28 @@ export class AreasDashboardStrategy extends ReactiveElement {
|
||||
config: AreasDashboardStrategyConfig,
|
||||
hass: HomeAssistant
|
||||
): Promise<LovelaceConfig> {
|
||||
if (hass.config.state === STATE_NOT_RUNNING) {
|
||||
return {
|
||||
views: [
|
||||
{
|
||||
type: "sections",
|
||||
sections: [{ cards: [{ type: "starting" }] }],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
if (hass.config.recovery_mode) {
|
||||
return {
|
||||
views: [
|
||||
{
|
||||
type: "sections",
|
||||
sections: [{ cards: [{ type: "recovery-mode" }] }],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
const areas = getAreas(
|
||||
hass.areas,
|
||||
config.areas_display?.hidden,
|
||||
|
@ -95,7 +95,7 @@ export class AreasOverviewViewStrategy extends ReactiveElement {
|
||||
|
||||
return {
|
||||
type: "sections",
|
||||
max_columns: 2,
|
||||
max_columns: 3,
|
||||
sections: areaSections,
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,18 @@
|
||||
import type {
|
||||
LovelaceSectionConfig,
|
||||
LovelaceStrategySectionConfig,
|
||||
} from "../../../data/lovelace/config/section";
|
||||
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||
import type {
|
||||
LovelaceConfig,
|
||||
LovelaceDashboardStrategyConfig,
|
||||
LovelaceRawConfig,
|
||||
} from "../../../data/lovelace/config/types";
|
||||
import { isStrategyDashboard } from "../../../data/lovelace/config/types";
|
||||
import type { LovelaceStrategyConfig } from "../../../data/lovelace/config/strategy";
|
||||
import type { LovelaceViewConfig } from "../../../data/lovelace/config/view";
|
||||
import type {
|
||||
LovelaceStrategyViewConfig,
|
||||
LovelaceViewConfig,
|
||||
} from "../../../data/lovelace/config/view";
|
||||
import { isStrategyView } from "../../../data/lovelace/config/view";
|
||||
import type { AsyncReturnType, HomeAssistant } from "../../../types";
|
||||
import { cleanLegacyStrategyConfig, isLegacyStrategy } from "./legacy-strategy";
|
||||
@ -133,10 +141,11 @@ const generateStrategy = async <T extends LovelaceStrategyConfigType>(
|
||||
};
|
||||
|
||||
export const generateLovelaceDashboardStrategy = async (
|
||||
strategyConfig: LovelaceStrategyConfig,
|
||||
config: LovelaceDashboardStrategyConfig,
|
||||
hass: HomeAssistant
|
||||
): Promise<LovelaceConfig> =>
|
||||
generateStrategy(
|
||||
): Promise<LovelaceConfig> => {
|
||||
const { strategy, ...base } = config;
|
||||
const generated = await generateStrategy(
|
||||
"dashboard",
|
||||
(err) => ({
|
||||
views: [
|
||||
@ -151,15 +160,21 @@ export const generateLovelaceDashboardStrategy = async (
|
||||
},
|
||||
],
|
||||
}),
|
||||
strategyConfig,
|
||||
strategy,
|
||||
hass
|
||||
);
|
||||
return {
|
||||
...base,
|
||||
...generated,
|
||||
};
|
||||
};
|
||||
|
||||
export const generateLovelaceViewStrategy = async (
|
||||
strategyConfig: LovelaceStrategyConfig,
|
||||
config: LovelaceStrategyViewConfig,
|
||||
hass: HomeAssistant
|
||||
): Promise<LovelaceViewConfig> =>
|
||||
generateStrategy(
|
||||
): Promise<LovelaceViewConfig> => {
|
||||
const { strategy, ...base } = config;
|
||||
const generated = await generateStrategy(
|
||||
"view",
|
||||
(err) => ({
|
||||
cards: [
|
||||
@ -169,15 +184,21 @@ export const generateLovelaceViewStrategy = async (
|
||||
},
|
||||
],
|
||||
}),
|
||||
strategyConfig,
|
||||
strategy,
|
||||
hass
|
||||
);
|
||||
return {
|
||||
...base,
|
||||
...generated,
|
||||
};
|
||||
};
|
||||
|
||||
export const generateLovelaceSectionStrategy = async (
|
||||
strategyConfig: LovelaceStrategyConfig,
|
||||
config: LovelaceStrategySectionConfig,
|
||||
hass: HomeAssistant
|
||||
): Promise<LovelaceViewConfig> =>
|
||||
generateStrategy(
|
||||
): Promise<LovelaceSectionConfig> => {
|
||||
const { strategy, ...base } = config;
|
||||
const generated = await generateStrategy(
|
||||
"section",
|
||||
(err) => ({
|
||||
cards: [
|
||||
@ -187,9 +208,14 @@ export const generateLovelaceSectionStrategy = async (
|
||||
},
|
||||
],
|
||||
}),
|
||||
strategyConfig,
|
||||
strategy,
|
||||
hass
|
||||
);
|
||||
return {
|
||||
...base,
|
||||
...generated,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Find all references to strategies and replaces them with the generated output
|
||||
@ -199,20 +225,20 @@ export const expandLovelaceConfigStrategies = async (
|
||||
hass: HomeAssistant
|
||||
): Promise<LovelaceConfig> => {
|
||||
const newConfig = isStrategyDashboard(config)
|
||||
? await generateLovelaceDashboardStrategy(config.strategy, hass)
|
||||
? await generateLovelaceDashboardStrategy(config, hass)
|
||||
: { ...config };
|
||||
|
||||
newConfig.views = await Promise.all(
|
||||
newConfig.views.map(async (view) => {
|
||||
const newView = isStrategyView(view)
|
||||
? await generateLovelaceViewStrategy(view.strategy, hass)
|
||||
? await generateLovelaceViewStrategy(view, hass)
|
||||
: { ...view };
|
||||
|
||||
if (newView.sections) {
|
||||
newView.sections = await Promise.all(
|
||||
newView.sections.map(async (section) => {
|
||||
const newSection = isStrategyView(section)
|
||||
? await generateLovelaceSectionStrategy(section.strategy, hass)
|
||||
? await generateLovelaceSectionStrategy(section, hass)
|
||||
: { ...section };
|
||||
return newSection;
|
||||
})
|
||||
|
@ -233,10 +233,7 @@ export class HUIView extends ReactiveElement {
|
||||
|
||||
if (isStrategyView(viewConfig)) {
|
||||
isStrategy = true;
|
||||
viewConfig = await generateLovelaceViewStrategy(
|
||||
viewConfig.strategy,
|
||||
this.hass!
|
||||
);
|
||||
viewConfig = await generateLovelaceViewStrategy(viewConfig, this.hass!);
|
||||
}
|
||||
|
||||
viewConfig = {
|
||||
|
@ -2902,7 +2902,8 @@
|
||||
"device_consumption_energy": "Device energy consumption",
|
||||
"selected_stat_intro": "Select the energy sensor that measures the device's energy usage in either of {unit}.",
|
||||
"included_in_device": "Upstream device",
|
||||
"included_in_device_helper": "If this device is already counted by another device (such as a smart switch measured by a smart breaker), selecting the upstream device prevents duplicate energy tracking."
|
||||
"included_in_device_helper": "If this device is already counted by another device (such as a smart switch measured by a smart breaker), selecting the upstream device prevents duplicate energy tracking.",
|
||||
"no_upstream_devices": "No eligible upstream devices"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -8129,7 +8130,7 @@
|
||||
},
|
||||
"mean_type": {
|
||||
"0": "None",
|
||||
"1": "Arimethic",
|
||||
"1": "Arithmetic",
|
||||
"2": "Circular"
|
||||
},
|
||||
"fix_issue": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user