diff --git a/src/components/chart/state-history-chart-line.ts b/src/components/chart/state-history-chart-line.ts index 071d47b2d4..434b9e2b24 100644 --- a/src/components/chart/state-history-chart-line.ts +++ b/src/components/chart/state-history-chart-line.ts @@ -28,6 +28,13 @@ const safeParseFloat = (value) => { return isFinite(parsed) ? parsed : null; }; +const CLIMATE_MODE_CONFIGS = [ + { mode: "heat", action: "heating", cssVar: "--state-climate-heat-color" }, + { mode: "cool", action: "cooling", cssVar: "--state-climate-cool-color" }, + { mode: "dry", action: "drying", cssVar: "--state-climate-dry-color" }, + { mode: "fan_only", action: "fan", cssVar: "--state-climate-fan_only-color" }, +] as const; + @customElement("state-history-chart-line") export class StateHistoryChartLine extends LitElement { @property({ attribute: false }) public hass!: HomeAssistant; @@ -429,39 +436,18 @@ export class StateHistoryChartLine extends LitElement { (entityState) => entityState.attributes?.hvac_action ); - const isHeating = - domain === "climate" && hasHvacAction - ? (entityState: LineChartState) => - CLIMATE_HVAC_ACTION_TO_MODE[ - entityState.attributes?.hvac_action - ] === "heat" - : (entityState: LineChartState) => entityState.state === "heat"; - const isCooling = - domain === "climate" && hasHvacAction - ? (entityState: LineChartState) => - CLIMATE_HVAC_ACTION_TO_MODE[ - entityState.attributes?.hvac_action - ] === "cool" - : (entityState: LineChartState) => entityState.state === "cool"; - const isDrying = - domain === "climate" && hasHvacAction - ? (entityState: LineChartState) => - CLIMATE_HVAC_ACTION_TO_MODE[ - entityState.attributes?.hvac_action - ] === "dry" - : (entityState: LineChartState) => entityState.state === "dry"; - const isFanOnly = - domain === "climate" && hasHvacAction - ? (entityState: LineChartState) => - CLIMATE_HVAC_ACTION_TO_MODE[ - entityState.attributes?.hvac_action - ] === "fan_only" - : (entityState: LineChartState) => entityState.state === "fan_only"; - - const hasHeat = states.states.some(isHeating); - const hasCool = states.states.some(isCooling); - const hasDry = states.states.some(isDrying); - const hasFan = states.states.some(isFanOnly); + const activeModes = CLIMATE_MODE_CONFIGS.map( + ({ mode, action, cssVar }) => { + const isActive = + domain === "climate" && hasHvacAction + ? (entityState: LineChartState) => + CLIMATE_HVAC_ACTION_TO_MODE[ + entityState.attributes?.hvac_action + ] === mode + : (entityState: LineChartState) => entityState.state === mode; + return { action, cssVar, isActive }; + } + ).filter(({ isActive }) => states.states.some(isActive)); // We differentiate between thermostats that have a target temperature // range versus ones that have just a target temperature @@ -482,61 +468,19 @@ export class StateHistoryChartLine extends LitElement { "component.climate.entity_component._.state_attributes.current_temperature.name" ) ); - if (hasHeat) { + for (const { action, cssVar } of activeModes) { addDataSet( - states.entity_id + "-heating", + `${states.entity_id}-${action}`, this.showNames - ? this.hass.localize("ui.card.climate.heating", { name: name }) + ? this.hass.localize(`ui.card.climate.${action}`, { + name: name, + }) : this.hass.localize( - "component.climate.entity_component._.state_attributes.hvac_action.state.heating" + `component.climate.entity_component._.state_attributes.hvac_action.state.${action}` ), - computedStyles.getPropertyValue("--state-climate-heat-color"), + computedStyles.getPropertyValue(cssVar), true ); - // The "heating" series uses steppedArea to shade the area below the current - // temperature when the thermostat is calling for heat. - } - if (hasCool) { - addDataSet( - states.entity_id + "-cooling", - this.showNames - ? this.hass.localize("ui.card.climate.cooling", { name: name }) - : this.hass.localize( - "component.climate.entity_component._.state_attributes.hvac_action.state.cooling" - ), - computedStyles.getPropertyValue("--state-climate-cool-color"), - true - ); - // The "cooling" series uses steppedArea to shade the area below the current - // temperature when the thermostat is calling for heat. - } - if (hasDry) { - addDataSet( - states.entity_id + "-drying", - this.showNames - ? this.hass.localize("ui.card.climate.drying", { name: name }) - : this.hass.localize( - "component.climate.entity_component._.state_attributes.hvac_action.state.drying" - ), - computedStyles.getPropertyValue("--state-climate-dry-color"), - true - ); - // The "drying" series uses steppedArea to shade the area below the current - // temperature when the climate entity is in dry mode. - } - if (hasFan) { - addDataSet( - states.entity_id + "-fan", - this.showNames - ? this.hass.localize("ui.card.climate.fan", { name: name }) - : this.hass.localize( - "component.climate.entity_component._.state_attributes.hvac_action.state.fan" - ), - computedStyles.getPropertyValue("--state-climate-fan_only-color"), - true - ); - // The "fan" series uses steppedArea to shade the area below the current - // temperature when the climate entity is in fan_only mode. } if (hasTargetRange) { @@ -584,17 +528,8 @@ export class StateHistoryChartLine extends LitElement { entityState.attributes.current_temperature ); const series = [curTemp]; - if (hasHeat) { - series.push(isHeating(entityState) ? curTemp : null); - } - if (hasCool) { - series.push(isCooling(entityState) ? curTemp : null); - } - if (hasDry) { - series.push(isDrying(entityState) ? curTemp : null); - } - if (hasFan) { - series.push(isFanOnly(entityState) ? curTemp : null); + for (const { isActive } of activeModes) { + series.push(isActive(entityState) ? curTemp : null); } if (hasTargetRange) { const targetHigh = safeParseFloat(