mirror of
https://github.com/home-assistant/frontend.git
synced 2025-08-01 13:37:47 +00:00
Add new card feature: button (#26165)
Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com> Co-authored-by: Wendelin <12148533+wendevlin@users.noreply.github.com>
This commit is contained in:
parent
b355556c07
commit
6dbfc2f4ed
98
src/panels/lovelace/card-features/hui-button-card-feature.ts
Normal file
98
src/panels/lovelace/card-features/hui-button-card-feature.ts
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { html, LitElement, nothing } from "lit";
|
||||||
|
import type { HassEntity } from "home-assistant-js-websocket";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import { computeDomain } from "../../../common/entity/compute_domain";
|
||||||
|
import "../../../components/ha-control-button";
|
||||||
|
import "../../../components/ha-control-button-group";
|
||||||
|
import type { HomeAssistant } from "../../../types";
|
||||||
|
import type { LovelaceCardFeature } from "../types";
|
||||||
|
import { cardFeatureStyles } from "./common/card-feature-styles";
|
||||||
|
import type {
|
||||||
|
LovelaceCardFeatureContext,
|
||||||
|
ButtonCardFeatureConfig,
|
||||||
|
} from "./types";
|
||||||
|
|
||||||
|
export const supportsButtonCardFeature = (
|
||||||
|
hass: HomeAssistant,
|
||||||
|
context: LovelaceCardFeatureContext
|
||||||
|
) => {
|
||||||
|
const stateObj = context.entity_id
|
||||||
|
? hass.states[context.entity_id]
|
||||||
|
: undefined;
|
||||||
|
if (!stateObj) return false;
|
||||||
|
const domain = computeDomain(stateObj.entity_id);
|
||||||
|
return ["button", "script"].includes(domain);
|
||||||
|
};
|
||||||
|
|
||||||
|
@customElement("hui-button-card-feature")
|
||||||
|
class HuiButtonCardFeature extends LitElement implements LovelaceCardFeature {
|
||||||
|
@property({ attribute: false }) public hass?: HomeAssistant;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public context?: LovelaceCardFeatureContext;
|
||||||
|
|
||||||
|
@state() private _config?: ButtonCardFeatureConfig;
|
||||||
|
|
||||||
|
private get _stateObj() {
|
||||||
|
if (!this.hass || !this.context || !this.context.entity_id) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return this.hass.states[this.context.entity_id!] as HassEntity | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _pressButton() {
|
||||||
|
if (!this.hass || !this._stateObj) return;
|
||||||
|
|
||||||
|
const domain = computeDomain(this._stateObj.entity_id);
|
||||||
|
const service = domain === "button" ? "press" : "turn_on";
|
||||||
|
|
||||||
|
this.hass.callService(domain, service, {
|
||||||
|
entity_id: this._stateObj.entity_id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static getStubConfig(): ButtonCardFeatureConfig {
|
||||||
|
return {
|
||||||
|
type: "button",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public setConfig(config: ButtonCardFeatureConfig): void {
|
||||||
|
if (!config) {
|
||||||
|
throw new Error("Invalid configuration");
|
||||||
|
}
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (
|
||||||
|
!this._config ||
|
||||||
|
!this.hass ||
|
||||||
|
!this.context ||
|
||||||
|
!this._stateObj ||
|
||||||
|
!supportsButtonCardFeature(this.hass, this.context)
|
||||||
|
) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-control-button-group>
|
||||||
|
<ha-control-button
|
||||||
|
.disabled=${["unavailable", "unknown"].includes(this._stateObj.state)}
|
||||||
|
class="press-button"
|
||||||
|
@click=${this._pressButton}
|
||||||
|
>
|
||||||
|
${this._config.action_name ??
|
||||||
|
this.hass.localize("ui.card.button.press")}
|
||||||
|
</ha-control-button>
|
||||||
|
</ha-control-button-group>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static styles = cardFeatureStyles;
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-button-card-feature": HuiButtonCardFeature;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,11 @@ import type { AlarmMode } from "../../../data/alarm_control_panel";
|
|||||||
import type { HvacMode } from "../../../data/climate";
|
import type { HvacMode } from "../../../data/climate";
|
||||||
import type { OperationMode } from "../../../data/water_heater";
|
import type { OperationMode } from "../../../data/water_heater";
|
||||||
|
|
||||||
|
export interface ButtonCardFeatureConfig {
|
||||||
|
type: "button";
|
||||||
|
action_name?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CoverOpenCloseCardFeatureConfig {
|
export interface CoverOpenCloseCardFeatureConfig {
|
||||||
type: "cover-open-close";
|
type: "cover-open-close";
|
||||||
}
|
}
|
||||||
@ -185,6 +190,7 @@ export type LovelaceCardFeaturePosition = "bottom" | "inline";
|
|||||||
|
|
||||||
export type LovelaceCardFeatureConfig =
|
export type LovelaceCardFeatureConfig =
|
||||||
| AlarmModesCardFeatureConfig
|
| AlarmModesCardFeatureConfig
|
||||||
|
| ButtonCardFeatureConfig
|
||||||
| ClimateFanModesCardFeatureConfig
|
| ClimateFanModesCardFeatureConfig
|
||||||
| ClimateSwingModesCardFeatureConfig
|
| ClimateSwingModesCardFeatureConfig
|
||||||
| ClimateSwingHorizontalModesCardFeatureConfig
|
| ClimateSwingHorizontalModesCardFeatureConfig
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import "../card-features/hui-alarm-modes-card-feature";
|
import "../card-features/hui-alarm-modes-card-feature";
|
||||||
|
import "../card-features/hui-button-card-feature";
|
||||||
import "../card-features/hui-climate-fan-modes-card-feature";
|
import "../card-features/hui-climate-fan-modes-card-feature";
|
||||||
import "../card-features/hui-climate-hvac-modes-card-feature";
|
import "../card-features/hui-climate-hvac-modes-card-feature";
|
||||||
import "../card-features/hui-climate-preset-modes-card-feature";
|
import "../card-features/hui-climate-preset-modes-card-feature";
|
||||||
@ -37,6 +38,7 @@ import {
|
|||||||
|
|
||||||
const TYPES = new Set<LovelaceCardFeatureConfig["type"]>([
|
const TYPES = new Set<LovelaceCardFeatureConfig["type"]>([
|
||||||
"alarm-modes",
|
"alarm-modes",
|
||||||
|
"button",
|
||||||
"area-controls",
|
"area-controls",
|
||||||
"climate-fan-modes",
|
"climate-fan-modes",
|
||||||
"climate-swing-modes",
|
"climate-swing-modes",
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
import { html, LitElement, nothing } from "lit";
|
||||||
|
import { customElement, property, state } from "lit/decorators";
|
||||||
|
import type { HomeAssistant } from "../../../../types";
|
||||||
|
import type { ButtonCardFeatureConfig } from "../../card-features/types";
|
||||||
|
import type { LovelaceCardFeatureEditor } from "../../types";
|
||||||
|
import "../../../../components/ha-form/ha-form";
|
||||||
|
import type { HaFormSchema } from "../../../../components/ha-form/types";
|
||||||
|
|
||||||
|
@customElement("hui-button-card-feature-editor")
|
||||||
|
export class HuiButtonCardFeatureEditor
|
||||||
|
extends LitElement
|
||||||
|
implements LovelaceCardFeatureEditor
|
||||||
|
{
|
||||||
|
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||||
|
|
||||||
|
@state() private _config?: ButtonCardFeatureConfig;
|
||||||
|
|
||||||
|
public setConfig(config: ButtonCardFeatureConfig): void {
|
||||||
|
this._config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _schema: HaFormSchema[] = [
|
||||||
|
{
|
||||||
|
name: "action_name",
|
||||||
|
selector: {
|
||||||
|
text: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
protected render() {
|
||||||
|
if (!this.hass || !this._config) {
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<ha-form
|
||||||
|
.hass=${this.hass}
|
||||||
|
.data=${this._config}
|
||||||
|
.schema=${this._schema}
|
||||||
|
@value-changed=${this._valueChanged}
|
||||||
|
></ha-form>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: CustomEvent) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent("config-changed", {
|
||||||
|
detail: { config: ev.detail.value },
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"hui-button-card-feature-editor": HuiButtonCardFeatureEditor;
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ import {
|
|||||||
import type { HomeAssistant } from "../../../../types";
|
import type { HomeAssistant } from "../../../../types";
|
||||||
import { supportsAlarmModesCardFeature } from "../../card-features/hui-alarm-modes-card-feature";
|
import { supportsAlarmModesCardFeature } from "../../card-features/hui-alarm-modes-card-feature";
|
||||||
import { supportsAreaControlsCardFeature } from "../../card-features/hui-area-controls-card-feature";
|
import { supportsAreaControlsCardFeature } from "../../card-features/hui-area-controls-card-feature";
|
||||||
|
import { supportsButtonCardFeature } from "../../card-features/hui-button-card-feature";
|
||||||
import { supportsClimateFanModesCardFeature } from "../../card-features/hui-climate-fan-modes-card-feature";
|
import { supportsClimateFanModesCardFeature } from "../../card-features/hui-climate-fan-modes-card-feature";
|
||||||
import { supportsClimateHvacModesCardFeature } from "../../card-features/hui-climate-hvac-modes-card-feature";
|
import { supportsClimateHvacModesCardFeature } from "../../card-features/hui-climate-hvac-modes-card-feature";
|
||||||
import { supportsClimatePresetModesCardFeature } from "../../card-features/hui-climate-preset-modes-card-feature";
|
import { supportsClimatePresetModesCardFeature } from "../../card-features/hui-climate-preset-modes-card-feature";
|
||||||
@ -63,6 +64,7 @@ type SupportsFeature = (
|
|||||||
const UI_FEATURE_TYPES = [
|
const UI_FEATURE_TYPES = [
|
||||||
"alarm-modes",
|
"alarm-modes",
|
||||||
"area-controls",
|
"area-controls",
|
||||||
|
"button",
|
||||||
"climate-fan-modes",
|
"climate-fan-modes",
|
||||||
"climate-hvac-modes",
|
"climate-hvac-modes",
|
||||||
"climate-preset-modes",
|
"climate-preset-modes",
|
||||||
@ -98,6 +100,7 @@ type UiFeatureTypes = (typeof UI_FEATURE_TYPES)[number];
|
|||||||
const EDITABLES_FEATURE_TYPES = new Set<UiFeatureTypes>([
|
const EDITABLES_FEATURE_TYPES = new Set<UiFeatureTypes>([
|
||||||
"alarm-modes",
|
"alarm-modes",
|
||||||
"area-controls",
|
"area-controls",
|
||||||
|
"button",
|
||||||
"climate-fan-modes",
|
"climate-fan-modes",
|
||||||
"climate-hvac-modes",
|
"climate-hvac-modes",
|
||||||
"climate-preset-modes",
|
"climate-preset-modes",
|
||||||
@ -120,6 +123,7 @@ const SUPPORTS_FEATURE_TYPES: Record<
|
|||||||
> = {
|
> = {
|
||||||
"alarm-modes": supportsAlarmModesCardFeature,
|
"alarm-modes": supportsAlarmModesCardFeature,
|
||||||
"area-controls": supportsAreaControlsCardFeature,
|
"area-controls": supportsAreaControlsCardFeature,
|
||||||
|
button: supportsButtonCardFeature,
|
||||||
"climate-fan-modes": supportsClimateFanModesCardFeature,
|
"climate-fan-modes": supportsClimateFanModesCardFeature,
|
||||||
"climate-swing-modes": supportsClimateSwingModesCardFeature,
|
"climate-swing-modes": supportsClimateSwingModesCardFeature,
|
||||||
"climate-swing-horizontal-modes":
|
"climate-swing-horizontal-modes":
|
||||||
|
Loading…
x
Reference in New Issue
Block a user