From a78608bfb4a3e7ea75bfbdbf2e8d826319c153f9 Mon Sep 17 00:00:00 2001 From: karwosts <32912880+karwosts@users.noreply.github.com> Date: Mon, 29 Apr 2024 08:48:01 -0700 Subject: [PATCH] Reorderable card-feature modes (#20647) * Reorderable card-feature modes * unused var in getStubConfig --- .../card-features/common/filter-modes.ts | 7 +++ .../hui-climate-fan-modes-card-feature.ts | 45 +++++++++---------- .../hui-climate-hvac-modes-card-feature.ts | 38 ++++++++-------- .../hui-climate-preset-modes-card-feature.ts | 45 +++++++++---------- .../hui-climate-swing-modes-card-feature.ts | 45 +++++++++---------- .../hui-fan-preset-modes-card-feature.ts | 45 +++++++++---------- .../hui-humidifier-modes-card-feature.ts | 45 +++++++++---------- ...ter-heater-operation-modes-card-feature.ts | 28 ++++++------ ...i-climate-fan-modes-card-feature-editor.ts | 1 + ...-climate-hvac-modes-card-feature-editor.ts | 1 + ...limate-preset-modes-card-feature-editor.ts | 1 + ...climate-swing-modes-card-feature-editor.ts | 1 + ...ui-fan-preset-modes-card-feature-editor.ts | 1 + ...ui-humidifier-modes-card-feature-editor.ts | 1 + ...ter-operation-modes-card-feature-editor.ts | 1 + 15 files changed, 150 insertions(+), 155 deletions(-) create mode 100644 src/panels/lovelace/card-features/common/filter-modes.ts diff --git a/src/panels/lovelace/card-features/common/filter-modes.ts b/src/panels/lovelace/card-features/common/filter-modes.ts new file mode 100644 index 0000000000..e3d1d50acd --- /dev/null +++ b/src/panels/lovelace/card-features/common/filter-modes.ts @@ -0,0 +1,7 @@ +export const filterModes = ( + supportedModes: string[] | undefined, + selectedModes: string[] | undefined +): string[] => + (selectedModes || []).length + ? selectedModes!.filter((mode) => (supportedModes || []).includes(mode)) + : supportedModes || []; diff --git a/src/panels/lovelace/card-features/hui-climate-fan-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-climate-fan-modes-card-feature.ts index 78de1e6a4d..70c81e98ae 100644 --- a/src/panels/lovelace/card-features/hui-climate-fan-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-climate-fan-modes-card-feature.ts @@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { ClimateFanModesCardFeatureConfig } from "./types"; +import { filterModes } from "./common/filter-modes"; export const supportsClimateFanModesCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -40,14 +41,11 @@ class HuiClimateFanModesCardFeature @query("ha-control-select-menu", true) private _haSelect?: HaControlSelectMenu; - static getStubConfig( - _, - stateObj?: HassEntity - ): ClimateFanModesCardFeatureConfig { + static getStubConfig(): ClimateFanModesCardFeatureConfig { return { type: "climate-fan-modes", style: "dropdown", - fan_modes: stateObj?.attributes.fan_modes || [], + fan_modes: [], }; } @@ -122,25 +120,24 @@ class HuiClimateFanModesCardFeature const stateObj = this.stateObj; - const modes = stateObj.attributes.fan_modes || []; - - const options = modes - .filter((mode) => (this._config!.fan_modes || []).includes(mode)) - .map((mode) => ({ - value: mode, - label: this.hass!.formatEntityAttributeValue( - this.stateObj!, - "fan_mode", - mode - ), - icon: html``, - })); + const options = filterModes( + stateObj.attributes.fan_modes, + this._config!.fan_modes + ).map((mode) => ({ + value: mode, + label: this.hass!.formatEntityAttributeValue( + this.stateObj!, + "fan_mode", + mode + ), + icon: html``, + })); if (this._config.style === "icons") { return html` diff --git a/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts index 2cd020cc22..949bf3b0c5 100644 --- a/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-climate-hvac-modes-card-feature.ts @@ -20,6 +20,7 @@ import { UNAVAILABLE } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { ClimateHvacModesCardFeatureConfig } from "./types"; +import { filterModes } from "./common/filter-modes"; export const supportsClimateHvacModesCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -42,13 +43,10 @@ class HuiClimateHvacModesCardFeature @query("ha-control-select-menu", true) private _haSelect?: HaControlSelectMenu; - static getStubConfig( - _, - stateObj?: HassEntity - ): ClimateHvacModesCardFeatureConfig { + static getStubConfig(): ClimateHvacModesCardFeatureConfig { return { type: "climate-hvac-modes", - hvac_modes: stateObj?.attributes.hvac_modes || [], + hvac_modes: [], }; } @@ -122,21 +120,21 @@ class HuiClimateHvacModesCardFeature const color = stateColorCss(this.stateObj); - const modes = this._config.hvac_modes || []; - - const options = modes - .filter((mode) => this.stateObj?.attributes.hvac_modes.includes(mode)) - .sort(compareClimateHvacModes) - .map((mode) => ({ - value: mode, - label: this.hass!.formatEntityState(this.stateObj!, mode), - icon: html` - - `, - })); + const options = filterModes( + [...(this.stateObj?.attributes.hvac_modes || [])].sort( + compareClimateHvacModes + ), + this._config.hvac_modes + ).map((mode) => ({ + value: mode, + label: this.hass!.formatEntityState(this.stateObj!, mode), + icon: html` + + `, + })); if (this._config.style === "dropdown") { return html` diff --git a/src/panels/lovelace/card-features/hui-climate-preset-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-climate-preset-modes-card-feature.ts index 410f8ce942..84e3d61acf 100644 --- a/src/panels/lovelace/card-features/hui-climate-preset-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-climate-preset-modes-card-feature.ts @@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { ClimatePresetModesCardFeatureConfig } from "./types"; +import { filterModes } from "./common/filter-modes"; export const supportsClimatePresetModesCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -40,14 +41,11 @@ class HuiClimatePresetModesCardFeature @query("ha-control-select-menu", true) private _haSelect?: HaControlSelectMenu; - static getStubConfig( - _, - stateObj?: HassEntity - ): ClimatePresetModesCardFeatureConfig { + static getStubConfig(): ClimatePresetModesCardFeatureConfig { return { type: "climate-preset-modes", style: "dropdown", - preset_modes: stateObj?.attributes.preset_modes || [], + preset_modes: [], }; } @@ -124,25 +122,24 @@ class HuiClimatePresetModesCardFeature const stateObj = this.stateObj; - const modes = stateObj.attributes.preset_modes || []; - - const options = modes - .filter((mode) => (this._config!.preset_modes || []).includes(mode)) - .map((mode) => ({ - value: mode, - label: this.hass!.formatEntityAttributeValue( - this.stateObj!, - "preset_mode", - mode - ), - icon: html``, - })); + const options = filterModes( + stateObj.attributes.preset_modes, + this._config!.preset_modes + ).map((mode) => ({ + value: mode, + label: this.hass!.formatEntityAttributeValue( + this.stateObj!, + "preset_mode", + mode + ), + icon: html``, + })); if (this._config.style === "icons") { return html` diff --git a/src/panels/lovelace/card-features/hui-climate-swing-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-climate-swing-modes-card-feature.ts index ec7dadaa84..6d5399f3e2 100644 --- a/src/panels/lovelace/card-features/hui-climate-swing-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-climate-swing-modes-card-feature.ts @@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { ClimateSwingModesCardFeatureConfig } from "./types"; +import { filterModes } from "./common/filter-modes"; export const supportsClimateSwingModesCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -40,14 +41,11 @@ class HuiClimateSwingModesCardFeature @query("ha-control-select-menu", true) private _haSelect?: HaControlSelectMenu; - static getStubConfig( - _, - stateObj?: HassEntity - ): ClimateSwingModesCardFeatureConfig { + static getStubConfig(): ClimateSwingModesCardFeatureConfig { return { type: "climate-swing-modes", style: "dropdown", - swing_modes: stateObj?.attributes.swing_modes || [], + swing_modes: [], }; } @@ -124,25 +122,24 @@ class HuiClimateSwingModesCardFeature const stateObj = this.stateObj; - const modes = stateObj.attributes.swing_modes || []; - - const options = modes - .filter((mode) => (this._config!.swing_modes || []).includes(mode)) - .map((mode) => ({ - value: mode, - label: this.hass!.formatEntityAttributeValue( - this.stateObj!, - "swing_mode", - mode - ), - icon: html``, - })); + const options = filterModes( + stateObj.attributes.swing_modes, + this._config!.swing_modes + ).map((mode) => ({ + value: mode, + label: this.hass!.formatEntityAttributeValue( + this.stateObj!, + "swing_mode", + mode + ), + icon: html``, + })); if (this._config.style === "icons") { return html` diff --git a/src/panels/lovelace/card-features/hui-fan-preset-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-fan-preset-modes-card-feature.ts index b4701dab84..42066f146b 100644 --- a/src/panels/lovelace/card-features/hui-fan-preset-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-fan-preset-modes-card-feature.ts @@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity"; import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { FanPresetModesCardFeatureConfig } from "./types"; +import { filterModes } from "./common/filter-modes"; export const supportsFanPresetModesCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -39,14 +40,11 @@ class HuiFanPresetModesCardFeature @query("ha-control-select-menu", true) private _haSelect?: HaControlSelectMenu; - static getStubConfig( - _, - stateObj?: HassEntity - ): FanPresetModesCardFeatureConfig { + static getStubConfig(): FanPresetModesCardFeatureConfig { return { type: "fan-preset-modes", style: "dropdown", - preset_modes: stateObj?.attributes.preset_modes || [], + preset_modes: [], }; } @@ -121,25 +119,24 @@ class HuiFanPresetModesCardFeature const stateObj = this.stateObj; - const modes = stateObj.attributes.preset_modes || []; - - const options = modes - .filter((mode) => (this._config!.preset_modes || []).includes(mode)) - .map((mode) => ({ - value: mode, - label: this.hass!.formatEntityAttributeValue( - this.stateObj!, - "preset_mode", - mode - ), - icon: html``, - })); + const options = filterModes( + stateObj.attributes.preset_modes, + this._config!.preset_modes + ).map((mode) => ({ + value: mode, + label: this.hass!.formatEntityAttributeValue( + this.stateObj!, + "preset_mode", + mode + ), + icon: html``, + })); if (this._config.style === "icons") { return html` diff --git a/src/panels/lovelace/card-features/hui-humidifier-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-humidifier-modes-card-feature.ts index 94a366712a..1f9c970194 100644 --- a/src/panels/lovelace/card-features/hui-humidifier-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-humidifier-modes-card-feature.ts @@ -18,6 +18,7 @@ import { import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { HumidifierModesCardFeatureConfig } from "./types"; +import { filterModes } from "./common/filter-modes"; export const supportsHumidifierModesCardFeature = (stateObj: HassEntity) => { const domain = computeDomain(stateObj.entity_id); @@ -43,14 +44,11 @@ class HuiHumidifierModesCardFeature @query("ha-control-select-menu", true) private _haSelect?: HaControlSelectMenu; - static getStubConfig( - _, - stateObj?: HassEntity - ): HumidifierModesCardFeatureConfig { + static getStubConfig(): HumidifierModesCardFeatureConfig { return { type: "humidifier-modes", style: "dropdown", - modes: stateObj?.attributes.available_modes || [], + modes: [], }; } @@ -125,25 +123,24 @@ class HuiHumidifierModesCardFeature const stateObj = this.stateObj; - const modes = stateObj.attributes.available_modes || []; - - const options = modes - .filter((mode) => (this._config!.modes || []).includes(mode)) - .map((mode) => ({ - value: mode, - label: this.hass!.formatEntityAttributeValue( - this.stateObj!, - "mode", - mode - ), - icon: html``, - })); + const options = filterModes( + stateObj.attributes.available_modes, + this._config!.modes + ).map((mode) => ({ + value: mode, + label: this.hass!.formatEntityAttributeValue( + this.stateObj!, + "mode", + mode + ), + icon: html``, + })); if (this._config.style === "icons") { return html` diff --git a/src/panels/lovelace/card-features/hui-water-heater-operation-modes-card-feature.ts b/src/panels/lovelace/card-features/hui-water-heater-operation-modes-card-feature.ts index 344a4ad7ba..3dbb611622 100644 --- a/src/panels/lovelace/card-features/hui-water-heater-operation-modes-card-feature.ts +++ b/src/panels/lovelace/card-features/hui-water-heater-operation-modes-card-feature.ts @@ -19,6 +19,7 @@ import { import { HomeAssistant } from "../../../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { WaterHeaterOperationModesCardFeatureConfig } from "./types"; +import { filterModes } from "./common/filter-modes"; export const supportsWaterHeaterOperationModesCardFeature = ( stateObj: HassEntity @@ -40,13 +41,10 @@ class HuiWaterHeaterOperationModeCardFeature @state() _currentOperationMode?: OperationMode; - static getStubConfig( - _, - stateObj?: HassEntity - ): WaterHeaterOperationModesCardFeatureConfig { + static getStubConfig(): WaterHeaterOperationModesCardFeatureConfig { return { type: "water-heater-operation-modes", - operation_modes: stateObj?.attributes.operation_list || [], + operation_modes: [], }; } @@ -107,16 +105,16 @@ class HuiWaterHeaterOperationModeCardFeature const color = stateColorCss(this.stateObj); - const modes = this._config.operation_modes || []; - - const options = modes - .filter((mode) => this.stateObj?.attributes.operation_list.includes(mode)) - .sort(compareWaterHeaterOperationMode) - .map((mode) => ({ - value: mode, - label: this.hass!.formatEntityState(this.stateObj!, mode), - path: computeOperationModeIcon(mode), - })); + const options = filterModes( + [...(this.stateObj?.attributes.operation_list || [])].sort( + compareWaterHeaterOperationMode + ), + this._config.operation_modes + ).map((mode) => ({ + value: mode, + label: this.hass!.formatEntityState(this.stateObj!, mode), + path: computeOperationModeIcon(mode as OperationMode), + })); return html`
diff --git a/src/panels/lovelace/editor/config-elements/hui-climate-fan-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-climate-fan-modes-card-feature-editor.ts index 3316c26b5c..dafd27ec12 100644 --- a/src/panels/lovelace/editor/config-elements/hui-climate-fan-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-climate-fan-modes-card-feature-editor.ts @@ -59,6 +59,7 @@ export class HuiClimateFanModesCardFeatureEditor selector: { select: { multiple: true, + reorder: true, mode: "list", options: stateObj?.attributes.fan_modes?.map((mode) => ({ diff --git a/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts index 228a43740d..1d6aa6774f 100644 --- a/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-climate-hvac-modes-card-feature-editor.ts @@ -57,6 +57,7 @@ export class HuiClimateHvacModesCardFeatureEditor selector: { select: { multiple: true, + reorder: true, mode: "list", options: HVAC_MODES.filter((mode) => stateObj?.attributes.hvac_modes?.includes(mode) diff --git a/src/panels/lovelace/editor/config-elements/hui-climate-preset-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-climate-preset-modes-card-feature-editor.ts index 52955c1627..db33052af1 100644 --- a/src/panels/lovelace/editor/config-elements/hui-climate-preset-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-climate-preset-modes-card-feature-editor.ts @@ -59,6 +59,7 @@ export class HuiClimatePresetModesCardFeatureEditor selector: { select: { multiple: true, + reorder: true, mode: "list", options: stateObj?.attributes.preset_modes?.map((mode) => ({ diff --git a/src/panels/lovelace/editor/config-elements/hui-climate-swing-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-climate-swing-modes-card-feature-editor.ts index 812c5c03cb..a490a86fc5 100644 --- a/src/panels/lovelace/editor/config-elements/hui-climate-swing-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-climate-swing-modes-card-feature-editor.ts @@ -59,6 +59,7 @@ export class HuiClimateSwingModesCardFeatureEditor selector: { select: { multiple: true, + reorder: true, mode: "list", options: stateObj?.attributes.swing_modes?.map((mode) => ({ diff --git a/src/panels/lovelace/editor/config-elements/hui-fan-preset-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-fan-preset-modes-card-feature-editor.ts index 35cfd7b8a6..5c4d688f67 100644 --- a/src/panels/lovelace/editor/config-elements/hui-fan-preset-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-fan-preset-modes-card-feature-editor.ts @@ -59,6 +59,7 @@ export class HuiFanPresetModesCardFeatureEditor selector: { select: { multiple: true, + reorder: true, mode: "list", options: stateObj?.attributes.preset_modes?.map((mode) => ({ diff --git a/src/panels/lovelace/editor/config-elements/hui-humidifier-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-humidifier-modes-card-feature-editor.ts index a462f19e49..33df27d2dc 100644 --- a/src/panels/lovelace/editor/config-elements/hui-humidifier-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-humidifier-modes-card-feature-editor.ts @@ -59,6 +59,7 @@ export class HuiHumidifierModesCardFeatureEditor selector: { select: { multiple: true, + reorder: true, mode: "list", options: stateObj?.attributes.available_modes?.map((mode) => ({ diff --git a/src/panels/lovelace/editor/config-elements/hui-water-heater-operation-modes-card-feature-editor.ts b/src/panels/lovelace/editor/config-elements/hui-water-heater-operation-modes-card-feature-editor.ts index 6e1a5f43ab..a5763b3401 100644 --- a/src/panels/lovelace/editor/config-elements/hui-water-heater-operation-modes-card-feature-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-water-heater-operation-modes-card-feature-editor.ts @@ -37,6 +37,7 @@ export class HuiWaterHeaterOperationModesCardFeatureEditor selector: { select: { multiple: true, + reorder: true, mode: "list", options: OPERATION_MODES.filter((mode) => stateObj?.attributes.operation_list?.includes(mode)