Allow to reorder alarm modes in card feature (#20684)

This commit is contained in:
Paul Bottein 2024-05-01 11:55:06 +02:00 committed by GitHub
parent f611f23f6f
commit 6febe8552e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 85 additions and 35 deletions

View File

@ -11,6 +11,7 @@ import {
HassEntityBase, HassEntityBase,
} from "home-assistant-js-websocket"; } from "home-assistant-js-websocket";
import { HomeAssistant } from "../types"; import { HomeAssistant } from "../types";
import { supportsFeature } from "../common/entity/supports-feature";
export const FORMAT_TEXT = "text"; export const FORMAT_TEXT = "text";
export const FORMAT_NUMBER = "number"; export const FORMAT_NUMBER = "number";
@ -96,3 +97,9 @@ export const ALARM_MODES: Record<AlarmMode, AlarmConfig> = {
path: mdiShieldOff, path: mdiShieldOff,
}, },
}; };
export const supportedAlarmModes = (stateObj: AlarmControlPanelEntity) =>
(Object.keys(ALARM_MODES) as AlarmMode[]).filter((mode) => {
const feature = ALARM_MODES[mode].feature;
return !feature || supportsFeature(stateObj, feature);
});

View File

@ -16,12 +16,14 @@ import {
AlarmControlPanelEntity, AlarmControlPanelEntity,
AlarmMode, AlarmMode,
ALARM_MODES, ALARM_MODES,
supportedAlarmModes,
} from "../../../data/alarm_control_panel"; } from "../../../data/alarm_control_panel";
import { UNAVAILABLE } from "../../../data/entity"; import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types"; import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types"; import { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
import { AlarmModesCardFeatureConfig } from "./types"; import { AlarmModesCardFeatureConfig } from "./types";
import { showEnterCodeDialog } from "../../../dialogs/enter-code/show-enter-code-dialog"; import { showEnterCodeDialog } from "../../../dialogs/enter-code/show-enter-code-dialog";
import { filterModes } from "./common/filter-modes";
export const supportsAlarmModesCardFeature = (stateObj: HassEntity) => { export const supportsAlarmModesCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id); const domain = computeDomain(stateObj.entity_id);
@ -164,9 +166,12 @@ class HuiAlarmModeCardFeature
const color = stateColorCss(this.stateObj); const color = stateColorCss(this.stateObj);
const modes = this._modes(this.stateObj, this._config.modes); const supportedModes = supportedAlarmModes(this.stateObj);
const options = modes.map<ControlSelectOption>((mode) => ({ const options = filterModes(
supportedModes,
this._config.modes
).map<ControlSelectOption>((mode) => ({
value: mode, value: mode,
label: this.hass!.localize(`ui.card.alarm_control_panel.modes.${mode}`), label: this.hass!.localize(`ui.card.alarm_control_panel.modes.${mode}`),
path: ALARM_MODES[mode].path, path: ALARM_MODES[mode].path,
@ -196,7 +201,7 @@ class HuiAlarmModeCardFeature
)} )}
style=${styleMap({ style=${styleMap({
"--control-select-color": color, "--control-select-color": color,
"--modes-count": modes.length.toString(), "--modes-count": options.length.toString(),
})} })}
.disabled=${this.stateObj!.state === UNAVAILABLE} .disabled=${this.stateObj!.state === UNAVAILABLE}
> >

View File

@ -3,17 +3,23 @@ import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import { supportsFeature } from "../../../../common/entity/supports-feature";
import type { LocalizeFunc } from "../../../../common/translations/localize"; import type { LocalizeFunc } from "../../../../common/translations/localize";
import type { SchemaUnion } from "../../../../components/ha-form/types"; import "../../../../components/ha-form/ha-form";
import { AlarmMode, ALARM_MODES } from "../../../../data/alarm_control_panel"; import type {
HaFormSchema,
SchemaUnion,
} from "../../../../components/ha-form/types";
import { supportedAlarmModes } from "../../../../data/alarm_control_panel";
import type { HomeAssistant } from "../../../../types"; import type { HomeAssistant } from "../../../../types";
import { import {
LovelaceCardFeatureContext,
AlarmModesCardFeatureConfig, AlarmModesCardFeatureConfig,
LovelaceCardFeatureContext,
} from "../../card-features/types"; } from "../../card-features/types";
import type { LovelaceCardFeatureEditor } from "../../types"; import type { LovelaceCardFeatureEditor } from "../../types";
import "../../../../components/ha-form/ha-form";
type AlarmModesCardFeatureData = AlarmModesCardFeatureConfig & {
customize_modes: boolean;
};
@customElement("hui-alarm-modes-card-feature-editor") @customElement("hui-alarm-modes-card-feature-editor")
export class HuiAlarmModesCardFeatureEditor export class HuiAlarmModesCardFeatureEditor
@ -31,31 +37,40 @@ export class HuiAlarmModesCardFeatureEditor
} }
private _schema = memoizeOne( private _schema = memoizeOne(
(localize: LocalizeFunc, stateObj?: HassEntity) => (
localize: LocalizeFunc,
stateObj: HassEntity | undefined,
customizeModes: boolean
) =>
[ [
{
name: "customize_modes",
selector: {
boolean: {},
},
},
...(customizeModes
? ([
{ {
name: "modes", name: "modes",
selector: { selector: {
select: { select: {
multiple: true, multiple: true,
mode: "list", reorder: true,
options: Object.keys(ALARM_MODES) options: stateObj
.filter((mode) => { ? supportedAlarmModes(stateObj).map((mode) => ({
const feature = ALARM_MODES[mode as AlarmMode].feature;
return (
stateObj && (!feature || supportsFeature(stateObj, feature))
);
})
.map((mode) => ({
value: mode, value: mode,
label: `${localize( label: `${localize(
`ui.panel.lovelace.editor.features.types.alarm-modes.modes_list.${mode}` `ui.panel.lovelace.editor.features.types.alarm-modes.modes_list.${mode}`
)}`, )}`,
})), }))
: [],
}, },
}, },
}, },
] as const ] as const satisfies readonly HaFormSchema[])
: []),
] as const satisfies readonly HaFormSchema[]
); );
protected render() { protected render() {
@ -63,16 +78,25 @@ export class HuiAlarmModesCardFeatureEditor
return nothing; return nothing;
} }
const data: AlarmModesCardFeatureData = {
...this._config,
customize_modes: this._config.modes !== undefined,
};
const stateObj = this.context?.entity_id const stateObj = this.context?.entity_id
? this.hass.states[this.context?.entity_id] ? this.hass.states[this.context?.entity_id]
: undefined; : undefined;
const schema = this._schema(this.hass.localize, stateObj); const schema = this._schema(
this.hass.localize,
stateObj,
data.customize_modes
);
return html` return html`
<ha-form <ha-form
.hass=${this.hass} .hass=${this.hass}
.data=${this._config} .data=${data}
.schema=${schema} .schema=${schema}
.computeLabel=${this._computeLabelCallback} .computeLabel=${this._computeLabelCallback}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
@ -81,7 +105,21 @@ export class HuiAlarmModesCardFeatureEditor
} }
private _valueChanged(ev: CustomEvent): void { private _valueChanged(ev: CustomEvent): void {
fireEvent(this, "config-changed", { config: ev.detail.value }); const { customize_modes, ...config } = ev.detail
.value as AlarmModesCardFeatureData;
const stateObj = this.context?.entity_id
? this.hass!.states[this.context?.entity_id]
: undefined;
if (customize_modes && !config.modes) {
config.modes = stateObj ? supportedAlarmModes(stateObj) : [];
}
if (!customize_modes && config.modes) {
delete config.modes;
}
fireEvent(this, "config-changed", { config: config });
} }
private _computeLabelCallback = ( private _computeLabelCallback = (
@ -89,13 +127,12 @@ export class HuiAlarmModesCardFeatureEditor
) => { ) => {
switch (schema.name) { switch (schema.name) {
case "modes": case "modes":
case "customize_modes":
return this.hass!.localize( return this.hass!.localize(
`ui.panel.lovelace.editor.features.types.alarm-modes.${schema.name}` `ui.panel.lovelace.editor.features.types.alarm-modes.${schema.name}`
); );
default: default:
return this.hass!.localize( return "";
`ui.panel.lovelace.editor.card.generic.${schema.name}`
);
} }
}; };
} }

View File

@ -5970,7 +5970,8 @@
"armed_vacation": "[%key:ui::card::alarm_control_panel::modes::armed_vacation%]", "armed_vacation": "[%key:ui::card::alarm_control_panel::modes::armed_vacation%]",
"armed_custom_bypass": "[%key:ui::card::alarm_control_panel::modes::armed_custom_bypass%]", "armed_custom_bypass": "[%key:ui::card::alarm_control_panel::modes::armed_custom_bypass%]",
"disarmed": "[%key:ui::card::alarm_control_panel::modes::disarmed%]" "disarmed": "[%key:ui::card::alarm_control_panel::modes::disarmed%]"
} },
"customize_modes": "Customize alarm modes"
}, },
"light-brightness": { "light-brightness": {
"label": "Light brightness" "label": "Light brightness"