Reorderable card-feature modes (#20647)

* Reorderable card-feature modes

* unused var in getStubConfig
This commit is contained in:
karwosts 2024-04-29 08:48:01 -07:00 committed by GitHub
parent 1a797b3415
commit a78608bfb4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 150 additions and 155 deletions

View File

@ -0,0 +1,7 @@
export const filterModes = (
supportedModes: string[] | undefined,
selectedModes: string[] | undefined
): string[] =>
(selectedModes || []).length
? selectedModes!.filter((mode) => (supportedModes || []).includes(mode))
: supportedModes || [];

View File

@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { ClimateFanModesCardFeatureConfig } from "./types"; import { ClimateFanModesCardFeatureConfig } from "./types";
import { filterModes } from "./common/filter-modes";
export const supportsClimateFanModesCardFeature = (stateObj: HassEntity) => { export const supportsClimateFanModesCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id); const domain = computeDomain(stateObj.entity_id);
@ -40,14 +41,11 @@ class HuiClimateFanModesCardFeature
@query("ha-control-select-menu", true) @query("ha-control-select-menu", true)
private _haSelect?: HaControlSelectMenu; private _haSelect?: HaControlSelectMenu;
static getStubConfig( static getStubConfig(): ClimateFanModesCardFeatureConfig {
_,
stateObj?: HassEntity
): ClimateFanModesCardFeatureConfig {
return { return {
type: "climate-fan-modes", type: "climate-fan-modes",
style: "dropdown", style: "dropdown",
fan_modes: stateObj?.attributes.fan_modes || [], fan_modes: [],
}; };
} }
@ -122,25 +120,24 @@ class HuiClimateFanModesCardFeature
const stateObj = this.stateObj; const stateObj = this.stateObj;
const modes = stateObj.attributes.fan_modes || []; const options = filterModes(
stateObj.attributes.fan_modes,
const options = modes this._config!.fan_modes
.filter((mode) => (this._config!.fan_modes || []).includes(mode)) ).map<ControlSelectOption>((mode) => ({
.map<ControlSelectOption>((mode) => ({ value: mode,
value: mode, label: this.hass!.formatEntityAttributeValue(
label: this.hass!.formatEntityAttributeValue( this.stateObj!,
this.stateObj!, "fan_mode",
"fan_mode", mode
mode ),
), icon: html`<ha-attribute-icon
icon: html`<ha-attribute-icon slot="graphic"
slot="graphic" .hass=${this.hass}
.hass=${this.hass} .stateObj=${stateObj}
.stateObj=${stateObj} attribute="fan_mode"
attribute="fan_mode" .attributeValue=${mode}
.attributeValue=${mode} ></ha-attribute-icon>`,
></ha-attribute-icon>`, }));
}));
if (this._config.style === "icons") { if (this._config.style === "icons") {
return html` return html`

View File

@ -20,6 +20,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { ClimateHvacModesCardFeatureConfig } from "./types"; import { ClimateHvacModesCardFeatureConfig } from "./types";
import { filterModes } from "./common/filter-modes";
export const supportsClimateHvacModesCardFeature = (stateObj: HassEntity) => { export const supportsClimateHvacModesCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id); const domain = computeDomain(stateObj.entity_id);
@ -42,13 +43,10 @@ class HuiClimateHvacModesCardFeature
@query("ha-control-select-menu", true) @query("ha-control-select-menu", true)
private _haSelect?: HaControlSelectMenu; private _haSelect?: HaControlSelectMenu;
static getStubConfig( static getStubConfig(): ClimateHvacModesCardFeatureConfig {
_,
stateObj?: HassEntity
): ClimateHvacModesCardFeatureConfig {
return { return {
type: "climate-hvac-modes", type: "climate-hvac-modes",
hvac_modes: stateObj?.attributes.hvac_modes || [], hvac_modes: [],
}; };
} }
@ -122,21 +120,21 @@ class HuiClimateHvacModesCardFeature
const color = stateColorCss(this.stateObj); const color = stateColorCss(this.stateObj);
const modes = this._config.hvac_modes || []; const options = filterModes(
[...(this.stateObj?.attributes.hvac_modes || [])].sort(
const options = modes compareClimateHvacModes
.filter((mode) => this.stateObj?.attributes.hvac_modes.includes(mode)) ),
.sort(compareClimateHvacModes) this._config.hvac_modes
.map<ControlSelectOption>((mode) => ({ ).map<ControlSelectOption>((mode) => ({
value: mode, value: mode,
label: this.hass!.formatEntityState(this.stateObj!, mode), label: this.hass!.formatEntityState(this.stateObj!, mode),
icon: html` icon: html`
<ha-svg-icon <ha-svg-icon
slot="graphic" slot="graphic"
.path=${climateHvacModeIcon(mode)} .path=${climateHvacModeIcon(mode)}
></ha-svg-icon> ></ha-svg-icon>
`, `,
})); }));
if (this._config.style === "dropdown") { if (this._config.style === "dropdown") {
return html` return html`

View File

@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { ClimatePresetModesCardFeatureConfig } from "./types"; import { ClimatePresetModesCardFeatureConfig } from "./types";
import { filterModes } from "./common/filter-modes";
export const supportsClimatePresetModesCardFeature = (stateObj: HassEntity) => { export const supportsClimatePresetModesCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id); const domain = computeDomain(stateObj.entity_id);
@ -40,14 +41,11 @@ class HuiClimatePresetModesCardFeature
@query("ha-control-select-menu", true) @query("ha-control-select-menu", true)
private _haSelect?: HaControlSelectMenu; private _haSelect?: HaControlSelectMenu;
static getStubConfig( static getStubConfig(): ClimatePresetModesCardFeatureConfig {
_,
stateObj?: HassEntity
): ClimatePresetModesCardFeatureConfig {
return { return {
type: "climate-preset-modes", type: "climate-preset-modes",
style: "dropdown", style: "dropdown",
preset_modes: stateObj?.attributes.preset_modes || [], preset_modes: [],
}; };
} }
@ -124,25 +122,24 @@ class HuiClimatePresetModesCardFeature
const stateObj = this.stateObj; const stateObj = this.stateObj;
const modes = stateObj.attributes.preset_modes || []; const options = filterModes(
stateObj.attributes.preset_modes,
const options = modes this._config!.preset_modes
.filter((mode) => (this._config!.preset_modes || []).includes(mode)) ).map<ControlSelectOption>((mode) => ({
.map<ControlSelectOption>((mode) => ({ value: mode,
value: mode, label: this.hass!.formatEntityAttributeValue(
label: this.hass!.formatEntityAttributeValue( this.stateObj!,
this.stateObj!, "preset_mode",
"preset_mode", mode
mode ),
), icon: html`<ha-attribute-icon
icon: html`<ha-attribute-icon slot="graphic"
slot="graphic" .hass=${this.hass}
.hass=${this.hass} .stateObj=${stateObj}
.stateObj=${stateObj} attribute="preset_mode"
attribute="preset_mode" .attributeValue=${mode}
.attributeValue=${mode} ></ha-attribute-icon>`,
></ha-attribute-icon>`, }));
}));
if (this._config.style === "icons") { if (this._config.style === "icons") {
return html` return html`

View File

@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { ClimateSwingModesCardFeatureConfig } from "./types"; import { ClimateSwingModesCardFeatureConfig } from "./types";
import { filterModes } from "./common/filter-modes";
export const supportsClimateSwingModesCardFeature = (stateObj: HassEntity) => { export const supportsClimateSwingModesCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id); const domain = computeDomain(stateObj.entity_id);
@ -40,14 +41,11 @@ class HuiClimateSwingModesCardFeature
@query("ha-control-select-menu", true) @query("ha-control-select-menu", true)
private _haSelect?: HaControlSelectMenu; private _haSelect?: HaControlSelectMenu;
static getStubConfig( static getStubConfig(): ClimateSwingModesCardFeatureConfig {
_,
stateObj?: HassEntity
): ClimateSwingModesCardFeatureConfig {
return { return {
type: "climate-swing-modes", type: "climate-swing-modes",
style: "dropdown", style: "dropdown",
swing_modes: stateObj?.attributes.swing_modes || [], swing_modes: [],
}; };
} }
@ -124,25 +122,24 @@ class HuiClimateSwingModesCardFeature
const stateObj = this.stateObj; const stateObj = this.stateObj;
const modes = stateObj.attributes.swing_modes || []; const options = filterModes(
stateObj.attributes.swing_modes,
const options = modes this._config!.swing_modes
.filter((mode) => (this._config!.swing_modes || []).includes(mode)) ).map<ControlSelectOption>((mode) => ({
.map<ControlSelectOption>((mode) => ({ value: mode,
value: mode, label: this.hass!.formatEntityAttributeValue(
label: this.hass!.formatEntityAttributeValue( this.stateObj!,
this.stateObj!, "swing_mode",
"swing_mode", mode
mode ),
), icon: html`<ha-attribute-icon
icon: html`<ha-attribute-icon slot="graphic"
slot="graphic" .hass=${this.hass}
.hass=${this.hass} .stateObj=${stateObj}
.stateObj=${stateObj} attribute="swing_mode"
attribute="swing_mode" .attributeValue=${mode}
.attributeValue=${mode} ></ha-attribute-icon>`,
></ha-attribute-icon>`, }));
}));
if (this._config.style === "icons") { if (this._config.style === "icons") {
return html` return html`

View File

@ -15,6 +15,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { FanPresetModesCardFeatureConfig } from "./types"; import { FanPresetModesCardFeatureConfig } from "./types";
import { filterModes } from "./common/filter-modes";
export const supportsFanPresetModesCardFeature = (stateObj: HassEntity) => { export const supportsFanPresetModesCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id); const domain = computeDomain(stateObj.entity_id);
@ -39,14 +40,11 @@ class HuiFanPresetModesCardFeature
@query("ha-control-select-menu", true) @query("ha-control-select-menu", true)
private _haSelect?: HaControlSelectMenu; private _haSelect?: HaControlSelectMenu;
static getStubConfig( static getStubConfig(): FanPresetModesCardFeatureConfig {
_,
stateObj?: HassEntity
): FanPresetModesCardFeatureConfig {
return { return {
type: "fan-preset-modes", type: "fan-preset-modes",
style: "dropdown", style: "dropdown",
preset_modes: stateObj?.attributes.preset_modes || [], preset_modes: [],
}; };
} }
@ -121,25 +119,24 @@ class HuiFanPresetModesCardFeature
const stateObj = this.stateObj; const stateObj = this.stateObj;
const modes = stateObj.attributes.preset_modes || []; const options = filterModes(
stateObj.attributes.preset_modes,
const options = modes this._config!.preset_modes
.filter((mode) => (this._config!.preset_modes || []).includes(mode)) ).map<ControlSelectOption>((mode) => ({
.map<ControlSelectOption>((mode) => ({ value: mode,
value: mode, label: this.hass!.formatEntityAttributeValue(
label: this.hass!.formatEntityAttributeValue( this.stateObj!,
this.stateObj!, "preset_mode",
"preset_mode", mode
mode ),
), icon: html`<ha-attribute-icon
icon: html`<ha-attribute-icon slot="graphic"
slot="graphic" .hass=${this.hass}
.hass=${this.hass} .stateObj=${stateObj}
.stateObj=${stateObj} attribute="preset_mode"
attribute="preset_mode" .attributeValue=${mode}
.attributeValue=${mode} ></ha-attribute-icon>`,
></ha-attribute-icon>`, }));
}));
if (this._config.style === "icons") { if (this._config.style === "icons") {
return html` return html`

View File

@ -18,6 +18,7 @@ import {
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { HumidifierModesCardFeatureConfig } from "./types"; import { HumidifierModesCardFeatureConfig } from "./types";
import { filterModes } from "./common/filter-modes";
export const supportsHumidifierModesCardFeature = (stateObj: HassEntity) => { export const supportsHumidifierModesCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id); const domain = computeDomain(stateObj.entity_id);
@ -43,14 +44,11 @@ class HuiHumidifierModesCardFeature
@query("ha-control-select-menu", true) @query("ha-control-select-menu", true)
private _haSelect?: HaControlSelectMenu; private _haSelect?: HaControlSelectMenu;
static getStubConfig( static getStubConfig(): HumidifierModesCardFeatureConfig {
_,
stateObj?: HassEntity
): HumidifierModesCardFeatureConfig {
return { return {
type: "humidifier-modes", type: "humidifier-modes",
style: "dropdown", style: "dropdown",
modes: stateObj?.attributes.available_modes || [], modes: [],
}; };
} }
@ -125,25 +123,24 @@ class HuiHumidifierModesCardFeature
const stateObj = this.stateObj; const stateObj = this.stateObj;
const modes = stateObj.attributes.available_modes || []; const options = filterModes(
stateObj.attributes.available_modes,
const options = modes this._config!.modes
.filter((mode) => (this._config!.modes || []).includes(mode)) ).map<ControlSelectOption>((mode) => ({
.map<ControlSelectOption>((mode) => ({ value: mode,
value: mode, label: this.hass!.formatEntityAttributeValue(
label: this.hass!.formatEntityAttributeValue( this.stateObj!,
this.stateObj!, "mode",
"mode", mode
mode ),
), icon: html`<ha-attribute-icon
icon: html`<ha-attribute-icon slot="graphic"
slot="graphic" .hass=${this.hass}
.hass=${this.hass} .stateObj=${stateObj}
.stateObj=${stateObj} attribute="mode"
attribute="mode" .attributeValue=${mode}
.attributeValue=${mode} ></ha-attribute-icon>`,
></ha-attribute-icon>`, }));
}));
if (this._config.style === "icons") { if (this._config.style === "icons") {
return html` return html`

View File

@ -19,6 +19,7 @@ import {
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { WaterHeaterOperationModesCardFeatureConfig } from "./types"; import { WaterHeaterOperationModesCardFeatureConfig } from "./types";
import { filterModes } from "./common/filter-modes";
export const supportsWaterHeaterOperationModesCardFeature = ( export const supportsWaterHeaterOperationModesCardFeature = (
stateObj: HassEntity stateObj: HassEntity
@ -40,13 +41,10 @@ class HuiWaterHeaterOperationModeCardFeature
@state() _currentOperationMode?: OperationMode; @state() _currentOperationMode?: OperationMode;
static getStubConfig( static getStubConfig(): WaterHeaterOperationModesCardFeatureConfig {
_,
stateObj?: HassEntity
): WaterHeaterOperationModesCardFeatureConfig {
return { return {
type: "water-heater-operation-modes", 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 color = stateColorCss(this.stateObj);
const modes = this._config.operation_modes || []; const options = filterModes(
[...(this.stateObj?.attributes.operation_list || [])].sort(
const options = modes compareWaterHeaterOperationMode
.filter((mode) => this.stateObj?.attributes.operation_list.includes(mode)) ),
.sort(compareWaterHeaterOperationMode) this._config.operation_modes
.map<ControlSelectOption>((mode) => ({ ).map<ControlSelectOption>((mode) => ({
value: mode, value: mode,
label: this.hass!.formatEntityState(this.stateObj!, mode), label: this.hass!.formatEntityState(this.stateObj!, mode),
path: computeOperationModeIcon(mode), path: computeOperationModeIcon(mode as OperationMode),
})); }));
return html` return html`
<div class="container"> <div class="container">

View File

@ -59,6 +59,7 @@ export class HuiClimateFanModesCardFeatureEditor
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
reorder: true,
mode: "list", mode: "list",
options: options:
stateObj?.attributes.fan_modes?.map((mode) => ({ stateObj?.attributes.fan_modes?.map((mode) => ({

View File

@ -57,6 +57,7 @@ export class HuiClimateHvacModesCardFeatureEditor
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
reorder: true,
mode: "list", mode: "list",
options: HVAC_MODES.filter((mode) => options: HVAC_MODES.filter((mode) =>
stateObj?.attributes.hvac_modes?.includes(mode) stateObj?.attributes.hvac_modes?.includes(mode)

View File

@ -59,6 +59,7 @@ export class HuiClimatePresetModesCardFeatureEditor
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
reorder: true,
mode: "list", mode: "list",
options: options:
stateObj?.attributes.preset_modes?.map((mode) => ({ stateObj?.attributes.preset_modes?.map((mode) => ({

View File

@ -59,6 +59,7 @@ export class HuiClimateSwingModesCardFeatureEditor
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
reorder: true,
mode: "list", mode: "list",
options: options:
stateObj?.attributes.swing_modes?.map((mode) => ({ stateObj?.attributes.swing_modes?.map((mode) => ({

View File

@ -59,6 +59,7 @@ export class HuiFanPresetModesCardFeatureEditor
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
reorder: true,
mode: "list", mode: "list",
options: options:
stateObj?.attributes.preset_modes?.map((mode) => ({ stateObj?.attributes.preset_modes?.map((mode) => ({

View File

@ -59,6 +59,7 @@ export class HuiHumidifierModesCardFeatureEditor
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
reorder: true,
mode: "list", mode: "list",
options: options:
stateObj?.attributes.available_modes?.map((mode) => ({ stateObj?.attributes.available_modes?.map((mode) => ({

View File

@ -37,6 +37,7 @@ export class HuiWaterHeaterOperationModesCardFeatureEditor
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
reorder: true,
mode: "list", mode: "list",
options: OPERATION_MODES.filter((mode) => options: OPERATION_MODES.filter((mode) =>
stateObj?.attributes.operation_list?.includes(mode) stateObj?.attributes.operation_list?.includes(mode)