mirror of
https://github.com/home-assistant/frontend.git
synced 2026-10-28 08:33:47 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cf50a001b |
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import { resolveTimeZone } from "../../../../common/datetime/resolve-time-zone";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type { FrontendLocaleData } from "../../../../data/translation";
|
||||
import type { ClockCardConfig, ClockCardDatePart } from "../types";
|
||||
|
||||
type ClockCardSeparatorPart = Extract<
|
||||
@@ -17,21 +17,22 @@ interface ClockCardDateConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the locale and time zone for a clock card from `hass` and the
|
||||
* card's configuration. Applies the optional `time_format` override to the
|
||||
* locale and falls back to the user's preferred time zone.
|
||||
* Resolves the locale and time zone for a clock card from the user's locale,
|
||||
* the server time zone and the card's configuration. Applies the optional
|
||||
* `time_format` override to the locale and falls back to the user's preferred
|
||||
* time zone.
|
||||
*/
|
||||
export const resolveClockCardLocale = (
|
||||
hass: HomeAssistant,
|
||||
userLocale: FrontendLocaleData,
|
||||
serverTimeZone: string,
|
||||
config: Pick<ClockCardConfig, "time_format" | "time_zone">
|
||||
): { locale: HomeAssistant["locale"]; timeZone: string } => {
|
||||
): { locale: FrontendLocaleData; timeZone: string } => {
|
||||
const locale = config.time_format
|
||||
? { ...hass.locale, time_format: config.time_format }
|
||||
: hass.locale;
|
||||
? { ...userLocale, time_format: config.time_format }
|
||||
: userLocale;
|
||||
|
||||
const timeZone =
|
||||
config.time_zone ||
|
||||
resolveTimeZone(locale.time_zone, hass.config?.time_zone);
|
||||
config.time_zone || resolveTimeZone(locale.time_zone, serverTimeZone);
|
||||
|
||||
return { locale, timeZone };
|
||||
};
|
||||
|
||||
@@ -5,7 +5,17 @@ import { classMap } from "lit/directives/class-map";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import memoizeOne from "memoize-one";
|
||||
import "../../../../components/ha-marquee-text";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import { consume } from "../../../../common/decorators/consume";
|
||||
import { transform } from "../../../../common/decorators/transform";
|
||||
import {
|
||||
configContext,
|
||||
internationalizationContext,
|
||||
} from "../../../../data/context";
|
||||
import type { FrontendLocaleData } from "../../../../data/translation";
|
||||
import type {
|
||||
HomeAssistantConfig,
|
||||
HomeAssistantInternationalization,
|
||||
} from "../../../../types";
|
||||
import type { ClockCardConfig } from "../types";
|
||||
import {
|
||||
formatClockCardDate,
|
||||
@@ -41,10 +51,22 @@ const MINUTE_TICKS = Array.from({ length: 60 }, (_, i) => i);
|
||||
|
||||
@customElement("hui-clock-card-analog")
|
||||
export class HuiClockCardAnalog extends LitElement {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public config?: ClockCardConfig;
|
||||
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
@transform<HomeAssistantInternationalization, FrontendLocaleData>({
|
||||
transformer: ({ locale }) => locale,
|
||||
})
|
||||
private _locale?: FrontendLocaleData;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, string>({
|
||||
transformer: ({ config }) => config.time_zone,
|
||||
})
|
||||
private _serverTimeZone?: string;
|
||||
|
||||
@state() private _dateTimeFormat?: Intl.DateTimeFormat;
|
||||
|
||||
@state() private _hourOffsetSec?: number;
|
||||
@@ -79,15 +101,12 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (changedProps.has("config") || changedProps.has("hass")) {
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (
|
||||
changedProps.has("config") ||
|
||||
!oldHass ||
|
||||
oldHass.locale !== this.hass?.locale
|
||||
) {
|
||||
this._initDate();
|
||||
}
|
||||
if (
|
||||
changedProps.has("config") ||
|
||||
changedProps.has("_locale") ||
|
||||
changedProps.has("_serverTimeZone")
|
||||
) {
|
||||
this._initDate();
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -120,18 +139,22 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
};
|
||||
|
||||
private _initDate() {
|
||||
if (!this.config || !this.hass) {
|
||||
if (!this.config || !this._locale || this._serverTimeZone === undefined) {
|
||||
this._stopDateTick();
|
||||
this._date = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const { timeZone } = resolveClockCardLocale(this.hass, this.config);
|
||||
const { locale, timeZone } = resolveClockCardLocale(
|
||||
this._locale,
|
||||
this._serverTimeZone,
|
||||
this.config
|
||||
);
|
||||
|
||||
this._language = this.hass.locale.language;
|
||||
this._language = locale.language;
|
||||
this._timeZone = timeZone;
|
||||
|
||||
this._dateTimeFormat = new Intl.DateTimeFormat(this.hass.locale.language, {
|
||||
this._dateTimeFormat = new Intl.DateTimeFormat(locale.language, {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
|
||||
@@ -3,8 +3,18 @@ import type { PropertyValues } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import "../../../../components/ha-marquee-text";
|
||||
import type { ClockCardConfig } from "../types";
|
||||
import type { HomeAssistant } from "../../../../types";
|
||||
import type {
|
||||
HomeAssistantConfig,
|
||||
HomeAssistantInternationalization,
|
||||
} from "../../../../types";
|
||||
import { useAmPm } from "../../../../common/datetime/use_am_pm";
|
||||
import { consume } from "../../../../common/decorators/consume";
|
||||
import { transform } from "../../../../common/decorators/transform";
|
||||
import {
|
||||
configContext,
|
||||
internationalizationContext,
|
||||
} from "../../../../data/context";
|
||||
import type { FrontendLocaleData } from "../../../../data/translation";
|
||||
import {
|
||||
formatClockCardDate,
|
||||
getClockCardDateConfig,
|
||||
@@ -16,10 +26,22 @@ const INTERVAL = 1000;
|
||||
|
||||
@customElement("hui-clock-card-digital")
|
||||
export class HuiClockCardDigital extends LitElement {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@property({ attribute: false }) public config?: ClockCardConfig;
|
||||
|
||||
@state()
|
||||
@consume({ context: internationalizationContext, subscribe: true })
|
||||
@transform<HomeAssistantInternationalization, FrontendLocaleData>({
|
||||
transformer: ({ locale }) => locale,
|
||||
})
|
||||
private _locale?: FrontendLocaleData;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, string>({
|
||||
transformer: ({ config }) => config.time_zone,
|
||||
})
|
||||
private _serverTimeZone?: string;
|
||||
|
||||
@state() private _dateTimeFormat?: Intl.DateTimeFormat;
|
||||
|
||||
@state() private _timeHour?: string;
|
||||
@@ -41,19 +63,23 @@ export class HuiClockCardDigital extends LitElement {
|
||||
private _language?: string;
|
||||
|
||||
private _initDate() {
|
||||
if (!this.config || !this.hass) {
|
||||
if (!this.config || !this._locale || this._serverTimeZone === undefined) {
|
||||
this._date = undefined;
|
||||
this._lastDateMinute = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
const { locale, timeZone } = resolveClockCardLocale(this.hass, this.config);
|
||||
const { locale, timeZone } = resolveClockCardLocale(
|
||||
this._locale,
|
||||
this._serverTimeZone,
|
||||
this.config
|
||||
);
|
||||
|
||||
const h12 = useAmPm(locale);
|
||||
this._language = this.hass.locale.language;
|
||||
this._language = locale.language;
|
||||
this._timeZone = timeZone;
|
||||
|
||||
this._dateTimeFormat = new Intl.DateTimeFormat(this.hass.locale.language, {
|
||||
this._dateTimeFormat = new Intl.DateTimeFormat(locale.language, {
|
||||
hour: h12 ? "numeric" : "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
@@ -66,16 +92,13 @@ export class HuiClockCardDigital extends LitElement {
|
||||
this._tick();
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues<this>) {
|
||||
if (changedProps.has("config") || changedProps.has("hass")) {
|
||||
const oldHass = changedProps.get("hass");
|
||||
if (
|
||||
changedProps.has("config") ||
|
||||
!oldHass ||
|
||||
oldHass.locale !== this.hass?.locale
|
||||
) {
|
||||
this._initDate();
|
||||
}
|
||||
protected updated(changedProps: PropertyValues) {
|
||||
if (
|
||||
changedProps.has("config") ||
|
||||
changedProps.has("_locale") ||
|
||||
changedProps.has("_serverTimeZone")
|
||||
) {
|
||||
this._initDate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import "../../../components/ha-alert";
|
||||
import "../../../components/ha-card";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type {
|
||||
LovelaceCard,
|
||||
LovelaceCardEditor,
|
||||
@@ -24,8 +23,6 @@ export class HuiClockCard extends LitElement implements LovelaceCard {
|
||||
};
|
||||
}
|
||||
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@state() private _config?: ClockCardConfig;
|
||||
|
||||
public setConfig(config: ClockCardConfig): void {
|
||||
@@ -122,13 +119,11 @@ export class HuiClockCard extends LitElement implements LovelaceCard {
|
||||
this._config.clock_style === "analog"
|
||||
? html`
|
||||
<hui-clock-card-analog
|
||||
.hass=${this.hass}
|
||||
.config=${this._config}
|
||||
></hui-clock-card-analog>
|
||||
`
|
||||
: html`
|
||||
<hui-clock-card-digital
|
||||
.hass=${this.hass}
|
||||
.config=${this._config}
|
||||
></hui-clock-card-digital>
|
||||
`
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../components/ha-button";
|
||||
import "../../../components/ha-icon";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
import type { LovelaceCard, LovelaceCardEditor } from "../types";
|
||||
import type { EmptyStateCardConfig } from "./types";
|
||||
|
||||
@@ -27,8 +26,6 @@ export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
|
||||
};
|
||||
}
|
||||
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@state() private _config?: EmptyStateCardConfig;
|
||||
|
||||
public getCardSize(): number {
|
||||
@@ -40,7 +37,7 @@ export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this.hass || !this._config) {
|
||||
if (!this._config) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
@@ -108,8 +105,11 @@ export class HuiEmptyStateCard extends LitElement implements LovelaceCard {
|
||||
private _handleButtonAction(ev: Event): void {
|
||||
const index = (ev.currentTarget as any).index;
|
||||
const button = this._config?.buttons?.[index];
|
||||
if (this.hass && button) {
|
||||
handleAction(this, this.hass, { tap_action: button.tap_action }, "tap");
|
||||
if (button) {
|
||||
fireEvent(this, "hass-action", {
|
||||
config: { tap_action: button.tap_action },
|
||||
action: "tap",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
import type { HassConfig, HassEntity } from "home-assistant-js-websocket";
|
||||
import type { PropertyValues, TemplateResult } from "lit";
|
||||
import { LitElement, css, html, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { consume } from "../../../common/decorators/consume";
|
||||
import {
|
||||
consumeEntityStates,
|
||||
consumeLocalize,
|
||||
} from "../../../common/decorators/consume-context-entry";
|
||||
import { transform } from "../../../common/decorators/transform";
|
||||
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
|
||||
import type { HASSDomCurrentTargetEvent } from "../../../common/dom/fire_event";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import type { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import "../../../components/entity/state-badge";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../components/ha-icon";
|
||||
import "../../../components/ha-relative-time";
|
||||
import {
|
||||
configContext,
|
||||
entitiesContext,
|
||||
formattersContext,
|
||||
uiContext,
|
||||
} from "../../../data/context";
|
||||
import { UNAVAILABLE, UNKNOWN } from "../../../data/entity/entity";
|
||||
import type { EntityRegistryDisplayEntry } from "../../../data/entity/entity_registry";
|
||||
import type { ActionHandlerEvent } from "../../../data/lovelace/action_handler";
|
||||
import type {
|
||||
CallServiceActionConfig,
|
||||
@@ -20,12 +36,16 @@ import {
|
||||
SENSOR_DEVICE_CLASS_UPTIME,
|
||||
SENSOR_TIMESTAMP_DEVICE_CLASSES,
|
||||
} from "../../../data/sensor";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { Themes } from "../../../data/ws-themes";
|
||||
import type {
|
||||
HomeAssistant,
|
||||
HomeAssistantConfig,
|
||||
HomeAssistantFormatters,
|
||||
HomeAssistantUI,
|
||||
} from "../../../types";
|
||||
import { actionHandler } from "../common/directives/action-handler-directive";
|
||||
import { findEntities } from "../common/find-entities";
|
||||
import { handleAction } from "../common/handle-action";
|
||||
import { hasAction, hasAnyAction } from "../common/has-action";
|
||||
import { hasConfigOrEntitiesChanged } from "../common/has-changed";
|
||||
import { applyDefaultColor } from "../common/entity-color-config";
|
||||
import { processConfigEntities } from "../common/process-config-entities";
|
||||
import "../components/hui-timestamp-display";
|
||||
@@ -63,10 +83,49 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
return { type: "glance", entities: foundEntities };
|
||||
}
|
||||
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@state() private _config?: GlanceCardConfig;
|
||||
|
||||
@state() private _entityIds?: string[];
|
||||
|
||||
@state()
|
||||
@consumeEntityStates({ entityIdPath: ["_entityIds"] })
|
||||
private _stateObjs?: Record<string, HassEntity>;
|
||||
|
||||
@state()
|
||||
@consume({ context: entitiesContext, subscribe: true })
|
||||
@transform<
|
||||
HomeAssistant["entities"],
|
||||
Record<string, EntityRegistryDisplayEntry>
|
||||
>({
|
||||
transformer: function (this: HuiGlanceCard, entities) {
|
||||
return this._selectEntityEntries(entities);
|
||||
},
|
||||
watch: ["_entityIds"],
|
||||
})
|
||||
private _entityEntries?: Record<string, EntityRegistryDisplayEntry>;
|
||||
|
||||
@state()
|
||||
@consumeLocalize()
|
||||
private _localize!: LocalizeFunc;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, HassConfig>({
|
||||
transformer: ({ config }) => config,
|
||||
})
|
||||
private _hassConfig!: HassConfig;
|
||||
|
||||
@state()
|
||||
@consume({ context: formattersContext, subscribe: true })
|
||||
private _formatters!: HomeAssistantFormatters;
|
||||
|
||||
@state()
|
||||
@consume({ context: uiContext, subscribe: true })
|
||||
@transform<HomeAssistantUI, Themes>({
|
||||
transformer: ({ themes }) => themes,
|
||||
})
|
||||
private _themes!: Themes;
|
||||
|
||||
private _configEntities?: GlanceConfigEntity[];
|
||||
|
||||
public getCardSize(): number {
|
||||
@@ -123,18 +182,11 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
this.style.setProperty("--glance-column-width", `${100 / columns}%`);
|
||||
|
||||
this._configEntities = entities;
|
||||
|
||||
if (this.hass) {
|
||||
this.requestUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues<this>): boolean {
|
||||
return hasConfigOrEntitiesChanged(this, changedProps);
|
||||
this._entityIds = entities.map((entityConf) => entityConf.entity);
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._config || !this.hass) {
|
||||
if (!this._config) {
|
||||
return nothing;
|
||||
}
|
||||
const { title } = this._config;
|
||||
@@ -152,21 +204,23 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
super.updated(changedProps);
|
||||
if (!this._config || !this.hass) {
|
||||
if (!this._config || !this._themes) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
if (!changedProps.has("_themes") && !changedProps.has("_config")) {
|
||||
return;
|
||||
}
|
||||
const oldThemes = changedProps.get("_themes") as Themes | undefined;
|
||||
const oldConfig = changedProps.get("_config") as
|
||||
GlanceCardConfig | undefined;
|
||||
|
||||
if (
|
||||
!oldHass ||
|
||||
!oldConfig ||
|
||||
oldHass.themes !== this.hass.themes ||
|
||||
oldConfig.theme !== this._config.theme
|
||||
(changedProps.has("_themes") &&
|
||||
(!oldThemes || oldThemes !== this._themes)) ||
|
||||
(changedProps.has("_config") &&
|
||||
(!oldConfig || oldConfig.theme !== this._config.theme))
|
||||
) {
|
||||
applyThemesOnElement(this, this.hass.themes, this._config.theme);
|
||||
applyThemesOnElement(this, this._themes, this._config.theme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,8 +296,36 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
`;
|
||||
|
||||
/** Reuses the previous record while every selected entry is unchanged. */
|
||||
private _selectEntityEntries(
|
||||
entities: HomeAssistant["entities"] | undefined
|
||||
): Record<string, EntityRegistryDisplayEntry> | undefined {
|
||||
if (!this._entityIds || !entities) {
|
||||
return undefined;
|
||||
}
|
||||
const next: Record<string, EntityRegistryDisplayEntry> = {};
|
||||
for (const id of this._entityIds) {
|
||||
const entry = entities[id];
|
||||
if (entry !== undefined) {
|
||||
next[id] = entry;
|
||||
}
|
||||
}
|
||||
const previous = this._entityEntries;
|
||||
if (!previous) {
|
||||
return next;
|
||||
}
|
||||
const nextKeys = Object.keys(next);
|
||||
if (
|
||||
Object.keys(previous).length === nextKeys.length &&
|
||||
nextKeys.every((key) => previous[key] === next[key])
|
||||
) {
|
||||
return previous;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
private _renderEntity(entityConf: GlanceConfigEntity): TemplateResult {
|
||||
const stateObj = this.hass!.states[entityConf.entity];
|
||||
const stateObj = this._stateObjs?.[entityConf.entity];
|
||||
|
||||
if (!stateObj) {
|
||||
return html`<div class="entity warning">
|
||||
@@ -251,7 +333,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
this._config!.show_name
|
||||
? html`
|
||||
<div class="name">
|
||||
${createEntityNotFoundWarning(this.hass!.localize, this.hass!.config)}
|
||||
${createEntityNotFoundWarning(this._localize, this._hassConfig)}
|
||||
</div>
|
||||
`
|
||||
: ""
|
||||
@@ -259,7 +341,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
${
|
||||
this._config!.show_icon
|
||||
? html` <hui-warning-element
|
||||
.label=${createEntityNotFoundWarning(this.hass!.localize, this.hass!.config)}
|
||||
.label=${createEntityNotFoundWarning(this._localize, this._hassConfig)}
|
||||
></hui-warning-element>`
|
||||
: ""
|
||||
}
|
||||
@@ -267,7 +349,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
const name = this.hass!.formatEntityName(stateObj, entityConf.name);
|
||||
const name = this._formatters.formatEntityName(stateObj, entityConf.name);
|
||||
const domain = computeDomain(entityConf.entity);
|
||||
|
||||
return html`
|
||||
@@ -334,7 +416,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
capitalize
|
||||
></ha-relative-time>
|
||||
`
|
||||
: this.hass!.formatEntityState(stateObj)
|
||||
: this._formatters.formatEntityState(stateObj)
|
||||
}
|
||||
</div>
|
||||
`
|
||||
@@ -351,7 +433,7 @@ export class HuiGlanceCard extends LitElement implements LovelaceCard {
|
||||
ActionHandlerEvent
|
||||
) {
|
||||
const { config } = ev.currentTarget;
|
||||
handleAction(this, this.hass!, config, ev.detail.action!);
|
||||
fireEvent(this, "hass-action", { config, action: ev.detail.action });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@ import { customElement, property, state } from "lit/decorators";
|
||||
import { classMap } from "lit/directives/class-map";
|
||||
import { ifDefined } from "lit/directives/if-defined";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { consumeLocalize } from "../../../common/decorators/consume-context-entry";
|
||||
import type { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import parseAspectRatio from "../../../common/util/parse-aspect-ratio";
|
||||
import "../../../components/ha-alert";
|
||||
import "../../../components/ha-card";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type {
|
||||
LovelaceCard,
|
||||
LovelaceCardEditor,
|
||||
@@ -34,10 +35,12 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
||||
@property({ attribute: false })
|
||||
public layout?: string;
|
||||
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@state() protected _config?: IframeCardConfig;
|
||||
|
||||
@state()
|
||||
@consumeLocalize()
|
||||
private _localize!: LocalizeFunc;
|
||||
|
||||
public getCardSize(): number {
|
||||
if (!this._config) {
|
||||
return 5;
|
||||
@@ -63,7 +66,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._config || !this.hass) {
|
||||
if (!this._config) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
@@ -85,7 +88,7 @@ export class HuiIframeCard extends LitElement implements LovelaceCard {
|
||||
if (location.protocol === "https:" && target_protocol !== "https:") {
|
||||
return html`
|
||||
<ha-alert alert-type="error">
|
||||
${this.hass!.localize(
|
||||
${this._localize(
|
||||
"ui.panel.lovelace.cards.iframe.error_secure_context",
|
||||
{
|
||||
target_protocol,
|
||||
|
||||
@@ -1,18 +1,33 @@
|
||||
import type { HassConfig } from "home-assistant-js-websocket";
|
||||
import { STATE_NOT_RUNNING } from "home-assistant-js-websocket";
|
||||
import type { PropertyValues } from "lit";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { consume } from "../../../common/decorators/consume";
|
||||
import { consumeLocalize } from "../../../common/decorators/consume-context-entry";
|
||||
import { transform } from "../../../common/decorators/transform";
|
||||
import { fireEvent } from "../../../common/dom/fire_event";
|
||||
import type { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import "../../../components/animation/ha-fade-in";
|
||||
import "../../../components/ha-card";
|
||||
import "../../../components/ha-spinner";
|
||||
import { configContext } from "../../../data/context";
|
||||
import type { LovelaceCardConfig } from "../../../data/lovelace/config/card";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { HomeAssistantConfig } from "../../../types";
|
||||
import type { LovelaceCard } from "../types";
|
||||
|
||||
@customElement("hui-starting-card")
|
||||
export class HuiStartingCard extends LitElement implements LovelaceCard {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
@state()
|
||||
@consumeLocalize()
|
||||
private _localize!: LocalizeFunc;
|
||||
|
||||
@state()
|
||||
@consume({ context: configContext, subscribe: true })
|
||||
@transform<HomeAssistantConfig, HassConfig>({
|
||||
transformer: ({ config }) => config,
|
||||
})
|
||||
private _hassConfig?: HassConfig;
|
||||
|
||||
public getCardSize(): number {
|
||||
return 2;
|
||||
@@ -21,28 +36,24 @@ export class HuiStartingCard extends LitElement implements LovelaceCard {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
public setConfig(_config: LovelaceCardConfig): void {}
|
||||
|
||||
protected updated(changedProperties: PropertyValues<this>) {
|
||||
protected updated(changedProperties: PropertyValues) {
|
||||
super.updated(changedProperties);
|
||||
if (!changedProperties.has("hass") || !this.hass!.config) {
|
||||
if (!changedProperties.has("_hassConfig") || !this._hassConfig) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hass!.config.state !== STATE_NOT_RUNNING) {
|
||||
if (this._hassConfig.state !== STATE_NOT_RUNNING) {
|
||||
fireEvent(this, "config-refresh");
|
||||
}
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this.hass) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class="content">
|
||||
<ha-fade-in .delay=${500}>
|
||||
<ha-spinner></ha-spinner>
|
||||
</ha-fade-in>
|
||||
${this.hass.localize("ui.panel.lovelace.cards.starting.description")}
|
||||
${this._localize("ui.panel.lovelace.cards.starting.description")}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
import type { HassEntity } from "home-assistant-js-websocket";
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
import { styleMap } from "lit/directives/style-map";
|
||||
import { computeCssColor } from "../../../common/color/compute-color";
|
||||
import { consume } from "../../../common/decorators/consume";
|
||||
import {
|
||||
consumeEntityStates,
|
||||
consumeLocalize,
|
||||
} from "../../../common/decorators/consume-context-entry";
|
||||
import type { LocalizeFunc } from "../../../common/translations/localize";
|
||||
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||
import { stateActive } from "../../../common/entity/state_active";
|
||||
import { stateColorCss } from "../../../common/entity/state_color";
|
||||
@@ -10,18 +16,28 @@ import "../../../components/ha-card";
|
||||
import "../../../components/tile/ha-tile-container";
|
||||
import "../../../components/tile/ha-tile-icon";
|
||||
import "../../../components/tile/ha-tile-info";
|
||||
import { apiContext } from "../../../data/context";
|
||||
import { forwardHaptic } from "../../../data/haptics";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
import type { HomeAssistantApi } from "../../../types";
|
||||
import type { LovelaceCard, LovelaceGridOptions } from "../types";
|
||||
import type { ToggleGroupCardConfig } from "./types";
|
||||
import { getToggleAction } from "../../../common/entity/get_toggle_action";
|
||||
|
||||
@customElement("hui-toggle-group-card")
|
||||
export class HuiToggleGroupCard extends LitElement implements LovelaceCard {
|
||||
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||
|
||||
@state() private _config?: ToggleGroupCardConfig;
|
||||
|
||||
@state()
|
||||
@consumeEntityStates({ entityIdPath: ["_config", "entities"] })
|
||||
private _stateObjs?: Record<string, HassEntity>;
|
||||
|
||||
@state()
|
||||
@consumeLocalize()
|
||||
private _localize!: LocalizeFunc;
|
||||
|
||||
@consume({ context: apiContext, subscribe: true })
|
||||
private _api!: HomeAssistantApi;
|
||||
|
||||
public setConfig(config: ToggleGroupCardConfig): void {
|
||||
if (!config.entities?.length) {
|
||||
throw new Error("Entities are required");
|
||||
@@ -52,17 +68,14 @@ export class HuiToggleGroupCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
private _getOnEntities(): HassEntity[] {
|
||||
if (!this.hass || !this._config) return [];
|
||||
return this._config.entities
|
||||
.map((entityId) => this.hass!.states[entityId])
|
||||
.filter(
|
||||
(stateObj): stateObj is HassEntity =>
|
||||
stateObj !== undefined && stateActive(stateObj)
|
||||
);
|
||||
if (!this._stateObjs) return [];
|
||||
return Object.values(this._stateObjs).filter((stateObj) =>
|
||||
stateActive(stateObj)
|
||||
);
|
||||
}
|
||||
|
||||
private _computeColor(): string | undefined {
|
||||
if (!this._config || !this.hass) return undefined;
|
||||
if (!this._config) return undefined;
|
||||
|
||||
const onEntities = this._getOnEntities();
|
||||
if (onEntities.length === 0) return undefined;
|
||||
@@ -75,17 +88,17 @@ export class HuiToggleGroupCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
private _computeLabel(): string {
|
||||
if (!this.hass || !this._config) return "";
|
||||
if (!this._config) return "";
|
||||
const onCount = this._getOnEntities().length;
|
||||
const total = this._config.entities.length;
|
||||
|
||||
if (onCount === 0) {
|
||||
return this.hass.localize("ui.card.toggle-group.all_off");
|
||||
return this._localize("ui.card.toggle-group.all_off");
|
||||
}
|
||||
if (onCount === total) {
|
||||
return this.hass.localize("ui.card.toggle-group.all_on");
|
||||
return this._localize("ui.card.toggle-group.all_on");
|
||||
}
|
||||
return this.hass.localize("ui.card.toggle-group.some_on", {
|
||||
return this._localize("ui.card.toggle-group.some_on", {
|
||||
on_count: onCount,
|
||||
total_count: total,
|
||||
});
|
||||
@@ -95,14 +108,14 @@ export class HuiToggleGroupCard extends LitElement implements LovelaceCard {
|
||||
const turnOn = this._getOnEntities().length === 0;
|
||||
const title = this._config!.title;
|
||||
if (title) {
|
||||
return this.hass!.localize(
|
||||
return this._localize(
|
||||
turnOn
|
||||
? "ui.card.toggle-group.turn_on_name"
|
||||
: "ui.card.toggle-group.turn_off_name",
|
||||
{ name: title }
|
||||
);
|
||||
}
|
||||
return this.hass!.localize(
|
||||
return this._localize(
|
||||
turnOn
|
||||
? "ui.card.toggle-group.turn_all_on"
|
||||
: "ui.card.toggle-group.turn_all_off"
|
||||
@@ -110,20 +123,20 @@ export class HuiToggleGroupCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
private _handleTap(): void {
|
||||
if (!this.hass || !this._config) return;
|
||||
if (!this._config) return;
|
||||
const onEntities = this._getOnEntities();
|
||||
const domain = computeDomain(this._config.entities[0]);
|
||||
|
||||
const service = getToggleAction(domain, onEntities.length === 0);
|
||||
|
||||
this.hass.callService(domain, service, {
|
||||
this._api.callService(domain, service, {
|
||||
entity_id: this._config.entities,
|
||||
});
|
||||
forwardHaptic(this, "light");
|
||||
}
|
||||
|
||||
protected render() {
|
||||
if (!this._config || !this.hass) {
|
||||
if (!this._config) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user