ha-frontend/src/panels/lovelace/card-features/hui-lock-open-door-card-fea...

159 lines
4.4 KiB
TypeScript

import { mdiCheck } from "@mdi/js";
import { HassEntity } from "home-assistant-js-websocket";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { computeDomain } from "../../../common/entity/compute_domain";
import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-control-button";
import "../../../components/ha-control-button-group";
import {
LockEntityFeature,
callProtectedLockService,
isAvailable,
} from "../../../data/lock";
import { HomeAssistant } from "../../../types";
import { LovelaceCardFeature } from "../types";
import { LockOpenDoorCardFeatureConfig } from "./types";
export const supportsLockOpenDoorCardFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id);
return domain === "lock" && supportsFeature(stateObj, LockEntityFeature.OPEN);
};
const CONFIRM_TIMEOUT_SECOND = 5;
const OPENED_TIMEOUT_SECOND = 3;
type ButtonState = "normal" | "confirm" | "success";
@customElement("hui-lock-open-door-card-feature")
class HuiLockOpenDoorCardFeature
extends LitElement
implements LovelaceCardFeature
{
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity;
@state() public _buttonState: ButtonState = "normal";
@state() private _config?: LockOpenDoorCardFeatureConfig;
private _buttonTimeout?: number;
static getStubConfig(): LockOpenDoorCardFeatureConfig {
return {
type: "lock-open-door",
};
}
public setConfig(config: LockOpenDoorCardFeatureConfig): void {
if (!config) {
throw new Error("Invalid configuration");
}
this._config = config;
}
private _setButtonState(buttonState: ButtonState, timeoutSecond?: number) {
clearTimeout(this._buttonTimeout);
this._buttonState = buttonState;
if (timeoutSecond) {
this._buttonTimeout = window.setTimeout(() => {
this._buttonState = "normal";
}, timeoutSecond * 1000);
}
}
private async _open() {
if (this._buttonState !== "confirm") {
this._setButtonState("confirm", CONFIRM_TIMEOUT_SECOND);
return;
}
if (!this.hass || !this.stateObj) {
return;
}
callProtectedLockService(this, this.hass, this.stateObj!, "open");
this._setButtonState("success", OPENED_TIMEOUT_SECOND);
}
protected render() {
if (
!this._config ||
!this.hass ||
!this.stateObj ||
!supportsLockOpenDoorCardFeature(this.stateObj)
) {
return nothing;
}
return html`
${this._buttonState === "success"
? html`
<div class="buttons">
<p class="open-success">
<ha-svg-icon path=${mdiCheck}></ha-svg-icon>
${this.hass.localize("ui.card.lock.open_door_success")}
</p>
</div>
`
: html`
<ha-control-button-group>
<ha-control-button
.disabled=${!isAvailable(this.stateObj)}
class="open-button ${this._buttonState}"
@click=${this._open}
>
${this._buttonState === "confirm"
? this.hass.localize("ui.card.lock.open_door_confirm")
: this.hass.localize("ui.card.lock.open_door")}
</ha-control-button>
</ha-control-button-group>
`}
`;
}
static get styles(): CSSResultGroup {
return css`
.buttons {
display: flex;
align-items: center;
justify-content: center;
margin-top: 0;
}
ha-control-button {
font-size: 14px;
}
ha-control-button-group {
margin: 0 12px 12px 12px;
--control-button-group-spacing: 12px;
}
.open-button {
width: 130px;
}
.open-button.confirm {
--control-button-background-color: var(--warning-color);
}
.open-success {
font-size: 14px;
line-height: 14px;
display: flex;
align-items: center;
flex-direction: row;
gap: 8px;
font-weight: 500;
color: var(--success-color);
}
ha-control-button-group + ha-attributes:not([empty]) {
margin-top: 16px;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-lock-open-door-card-feature": HuiLockOpenDoorCardFeature;
}
}