diff --git a/src/data/timer.ts b/src/data/timer.ts index 8b54020a7d..a963d64ea3 100644 --- a/src/data/timer.ts +++ b/src/data/timer.ts @@ -2,6 +2,7 @@ import { HassEntityAttributeBase, HassEntityBase, } from "home-assistant-js-websocket"; +import { HomeAssistant } from "../types"; export type TimerEntity = HassEntityBase & { attributes: HassEntityAttributeBase & { @@ -9,3 +10,48 @@ export type TimerEntity = HassEntityBase & { remaining: string; }; }; + +export interface DurationDict { + hours?: number | string; + minutes?: number | string; + seconds?: number | string; +} + +export interface Timer { + id: string; + name: string; + icon?: string; + duration?: string | number | DurationDict; +} + +export interface TimerMutableParams { + name: string; + icon: string; + duration: string | number | DurationDict; +} + +export const fetchTimer = (hass: HomeAssistant) => + hass.callWS({ type: "timer/list" }); + +export const createTimer = (hass: HomeAssistant, values: TimerMutableParams) => + hass.callWS({ + type: "timer/create", + ...values, + }); + +export const updateTimer = ( + hass: HomeAssistant, + id: string, + updates: Partial +) => + hass.callWS({ + type: "timer/update", + timer_id: id, + ...updates, + }); + +export const deleteTimer = (hass: HomeAssistant, id: string) => + hass.callWS({ + type: "timer/delete", + timer_id: id, + }); diff --git a/src/panels/config/entities/const.ts b/src/panels/config/entities/const.ts index ca76edf359..1c5e4b4f59 100644 --- a/src/panels/config/entities/const.ts +++ b/src/panels/config/entities/const.ts @@ -6,4 +6,5 @@ export const PLATFORMS_WITH_SETTINGS_TAB = { input_boolean: "entity-settings-helper-tab", input_datetime: "entity-settings-helper-tab", counter: "entity-settings-helper-tab", + timer: "entity-settings-helper-tab", }; diff --git a/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts b/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts index 09c7e268e8..8f7ecfff2f 100644 --- a/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts +++ b/src/panels/config/entities/editor-tabs/settings/entity-settings-helper-tab.ts @@ -47,6 +47,11 @@ import { fetchCounter, updateCounter, } from "../../../../../data/counter"; +import { + deleteTimer, + fetchTimer, + updateTimer, +} from "../../../../../data/timer"; import { showConfirmationDialog } from "../../../../../dialogs/generic/show-dialog-box"; import type { HomeAssistant } from "../../../../../types"; import type { Helper } from "../../../helpers/const"; @@ -56,6 +61,7 @@ import "../../../helpers/forms/ha-input_number-form"; import "../../../helpers/forms/ha-input_select-form"; import "../../../helpers/forms/ha-input_text-form"; import "../../../helpers/forms/ha-counter-form"; +import "../../../helpers/forms/ha-timer-form"; import "../../entity-registry-basic-editor"; import type { HaEntityRegistryBasicEditor } from "../../entity-registry-basic-editor"; import { haStyle } from "../../../../../resources/styles"; @@ -91,6 +97,11 @@ const HELPERS = { update: updateCounter, delete: deleteCounter, }, + timer: { + fetch: fetchTimer, + update: updateTimer, + delete: deleteTimer, + }, }; @customElement("entity-settings-helper-tab") diff --git a/src/panels/config/helpers/const.ts b/src/panels/config/helpers/const.ts index 22ebcab1a6..5835f63c28 100644 --- a/src/panels/config/helpers/const.ts +++ b/src/panels/config/helpers/const.ts @@ -4,6 +4,7 @@ import { InputNumber } from "../../../data/input_number"; import { InputSelect } from "../../../data/input_select"; import { InputText } from "../../../data/input_text"; import { Counter } from "../../../data/counter"; +import { Timer } from "../../../data/timer"; export const HELPER_DOMAINS = [ "input_boolean", @@ -12,6 +13,7 @@ export const HELPER_DOMAINS = [ "input_datetime", "input_select", "counter", + "timer", ]; export type Helper = @@ -20,4 +22,5 @@ export type Helper = | InputNumber | InputSelect | InputDateTime - | Counter; + | Counter + | Timer; diff --git a/src/panels/config/helpers/dialog-helper-detail.ts b/src/panels/config/helpers/dialog-helper-detail.ts index 38fc564544..8a314af8d7 100644 --- a/src/panels/config/helpers/dialog-helper-detail.ts +++ b/src/panels/config/helpers/dialog-helper-detail.ts @@ -23,6 +23,7 @@ import { createInputNumber } from "../../../data/input_number"; import { createInputSelect } from "../../../data/input_select"; import { createInputText } from "../../../data/input_text"; import { createCounter } from "../../../data/counter"; +import { createTimer } from "../../../data/timer"; import { haStyleDialog } from "../../../resources/styles"; import { HomeAssistant } from "../../../types"; import { Helper } from "./const"; @@ -32,6 +33,7 @@ import "./forms/ha-input_number-form"; import "./forms/ha-input_select-form"; import "./forms/ha-input_text-form"; import "./forms/ha-counter-form"; +import "./forms/ha-timer-form"; const HELPERS = { input_boolean: createInputBoolean, @@ -40,6 +42,7 @@ const HELPERS = { input_datetime: createInputDateTime, input_select: createInputSelect, counter: createCounter, + timer: createTimer, }; @customElement("dialog-helper-detail") diff --git a/src/panels/config/helpers/forms/ha-timer-form.ts b/src/panels/config/helpers/forms/ha-timer-form.ts new file mode 100644 index 0000000000..9757b76b94 --- /dev/null +++ b/src/panels/config/helpers/forms/ha-timer-form.ts @@ -0,0 +1,130 @@ +import { + css, + CSSResult, + customElement, + html, + LitElement, + property, + internalProperty, + TemplateResult, +} from "lit-element"; +import { fireEvent } from "../../../../common/dom/fire_event"; +import "../../../../components/ha-icon-input"; +import { Timer, DurationDict } from "../../../../data/timer"; +import { haStyle } from "../../../../resources/styles"; +import { HomeAssistant } from "../../../../types"; + +@customElement("ha-timer-form") +class HaTimerForm extends LitElement { + @property({ attribute: false }) public hass!: HomeAssistant; + + @property() public new?: boolean; + + private _item?: Timer; + + @internalProperty() private _name!: string; + + @internalProperty() private _icon!: string; + + @internalProperty() private _duration!: string | number | DurationDict; + + set item(item: Timer) { + this._item = item; + if (item) { + this._name = item.name || ""; + this._icon = item.icon || ""; + this._duration = item.duration || ""; + } else { + this._name = ""; + this._icon = ""; + this._duration = "00:00:00"; + } + } + + public focus() { + this.updateComplete.then(() => + (this.shadowRoot?.querySelector( + "[dialogInitialFocus]" + ) as HTMLElement)?.focus() + ); + } + + protected render(): TemplateResult { + if (!this.hass) { + return html``; + } + const nameInvalid = !this._name || this._name.trim() === ""; + + return html` +
+ + + +
+ `; + } + + private _valueChanged(ev: CustomEvent) { + if (!this.new && !this._item) { + return; + } + ev.stopPropagation(); + const configValue = (ev.target as any).configValue; + const value = ev.detail.value; + if (this[`_${configValue}`] === value) { + return; + } + const newValue = { ...this._item }; + if (!value) { + delete newValue[configValue]; + } else { + newValue[configValue] = ev.detail.value; + } + fireEvent(this, "value-changed", { + value: newValue, + }); + } + + static get styles(): CSSResult[] { + return [ + haStyle, + css` + .form { + color: var(--primary-text-color); + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-timer-form": HaTimerForm; + } +} diff --git a/src/translations/en.json b/src/translations/en.json index 98a4f009fd..1885072109 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -608,6 +608,9 @@ "initial": "Initial value", "restore": "Restore the last known value when Home Assistant starts", "step": "Step size" + }, + "timer": { + "duration": "Duration" } }, "options_flow": { @@ -793,7 +796,8 @@ "input_select": "Dropdown", "input_boolean": "Toggle", "input_datetime": "Date and/or time", - "counter": "Counter" + "counter": "Counter", + "timer": "Timer" }, "picker": { "headers": {