From a5ca36c93f678129fe83ee5982019ac35f18e8ba Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Wed, 30 Jul 2025 19:45:10 +0200 Subject: [PATCH] Add weekdays to time trigger (#25908) * Add weekdays to time trigger * Update src/translations/en.json Co-authored-by: Norbert Rittel * Localization changes --------- Co-authored-by: Norbert Rittel Co-authored-by: Simon Lamon <32477463+silamon@users.noreply.github.com> --- src/data/automation.ts | 1 + src/data/automation_i18n.ts | 15 ++++ .../types/ha-automation-trigger-time.ts | 77 +++++++++++++++---- src/translations/en.json | 12 ++- 4 files changed, 89 insertions(+), 16 deletions(-) diff --git a/src/data/automation.ts b/src/data/automation.ts index 1e57fde2ff..7bb4369c61 100644 --- a/src/data/automation.ts +++ b/src/data/automation.ts @@ -169,6 +169,7 @@ export interface TagTrigger extends BaseTrigger { export interface TimeTrigger extends BaseTrigger { trigger: "time"; at: string | { entity_id: string; offset?: string }; + weekday?: string | string[]; } export interface TemplateTrigger extends BaseTrigger { diff --git a/src/data/automation_i18n.ts b/src/data/automation_i18n.ts index 89a52c1002..36bc47fa7f 100644 --- a/src/data/automation_i18n.ts +++ b/src/data/automation_i18n.ts @@ -400,8 +400,23 @@ const tryDescribeTrigger = ( return `${entityStr}${offsetStr}`; }); + // Handle weekday information if present + let weekdays: string[] = []; + if (trigger.weekday) { + const weekdayArray = ensureArray(trigger.weekday); + if (weekdayArray.length > 0) { + weekdays = weekdayArray.map((day) => + hass.localize( + `ui.panel.config.automation.editor.triggers.type.time.weekdays.${day}` as any + ) + ); + } + } + return hass.localize(`${triggerTranslationBaseKey}.time.description.full`, { time: formatListWithOrs(hass.locale, result), + hasWeekdays: weekdays.length > 0 ? "true" : "false", + weekdays: formatListWithOrs(hass.locale, weekdays), }); } diff --git a/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts b/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts index 9154b1e86f..484d927102 100644 --- a/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts +++ b/src/panels/config/automation/trigger/types/ha-automation-trigger-time.ts @@ -2,11 +2,13 @@ import type { PropertyValues } from "lit"; import { html, LitElement, nothing } from "lit"; import { customElement, property, state } from "lit/decorators"; import memoizeOne from "memoize-one"; +import { firstWeekdayIndex } from "../../../../../common/datetime/first_weekday"; import { fireEvent } from "../../../../../common/dom/fire_event"; import type { LocalizeFunc } from "../../../../../common/translations/localize"; import "../../../../../components/ha-form/ha-form"; import type { SchemaUnion } from "../../../../../components/ha-form/types"; import type { TimeTrigger } from "../../../../../data/automation"; +import type { FrontendLocaleData } from "../../../../../data/translation"; import type { HomeAssistant } from "../../../../../types"; import type { TriggerElement } from "../ha-automation-trigger-row"; import { computeDomain } from "../../../../../common/entity/compute_domain"; @@ -14,6 +16,7 @@ import { computeDomain } from "../../../../../common/entity/compute_domain"; const MODE_TIME = "time"; const MODE_ENTITY = "entity"; const VALID_DOMAINS = ["sensor", "input_datetime"]; +const DAYS = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"] as const; @customElement("ha-automation-trigger-time") export class HaTimeTrigger extends LitElement implements TriggerElement { @@ -35,9 +38,14 @@ export class HaTimeTrigger extends LitElement implements TriggerElement { private _schema = memoizeOne( ( localize: LocalizeFunc, + locale: FrontendLocaleData, inputMode: typeof MODE_TIME | typeof MODE_ENTITY - ) => - [ + ) => { + const dayIndex = firstWeekdayIndex(locale); + const sortedDays = DAYS.slice(dayIndex, DAYS.length).concat( + DAYS.slice(0, dayIndex) + ); + return [ { name: "mode", type: "select", @@ -73,7 +81,21 @@ export class HaTimeTrigger extends LitElement implements TriggerElement { }, { name: "offset", selector: { text: {} } }, ] as const)), - ] as const + { + type: "multi_select", + name: "weekday", + options: sortedDays.map( + (day) => + [ + day, + localize( + `ui.panel.config.automation.editor.triggers.type.time.weekdays.${day}` + ), + ] as const + ), + }, + ] as const; + } ); public willUpdate(changedProperties: PropertyValues) { @@ -95,12 +117,14 @@ export class HaTimeTrigger extends LitElement implements TriggerElement { inputMode: undefined | typeof MODE_ENTITY | typeof MODE_TIME, at: | string - | { entity_id: string | undefined; offset?: string | undefined } + | { entity_id: string | undefined; offset?: string | undefined }, + weekday: string | string[] | undefined ): { mode: typeof MODE_TIME | typeof MODE_ENTITY; entity: string | undefined; time: string | undefined; offset: string | undefined; + weekday: string | string[] | undefined; } => { const entity = typeof at === "object" @@ -116,6 +140,7 @@ export class HaTimeTrigger extends LitElement implements TriggerElement { entity, time, offset, + weekday, }; } ); @@ -127,8 +152,12 @@ export class HaTimeTrigger extends LitElement implements TriggerElement { return nothing; } - const data = this._data(this._inputMode, at); - const schema = this._schema(this.hass.localize, data.mode); + const data = this._data(this._inputMode, at, this.trigger.weekday); + const schema = this._schema( + this.hass.localize, + this.hass.locale, + data.mode + ); return html` 0) { + triggerUpdate.weekday = weekday; + } else { + delete triggerUpdate.weekday; + } + fireEvent(this, "value-changed", { - value: { - ...this.trigger, - at: newValue.offset - ? { - entity_id: newValue.entity, - offset: newValue.offset, - } - : newValue.entity || newValue.time, - }, + value: triggerUpdate, }); } @@ -173,6 +216,10 @@ export class HaTimeTrigger extends LitElement implements TriggerElement { return this.hass.localize( `ui.panel.config.automation.editor.triggers.type.time.at` ); + case "weekday": + return this.hass.localize( + `ui.panel.config.automation.editor.triggers.type.time.weekday` + ); } return this.hass.localize( `ui.panel.config.automation.editor.triggers.type.time.${schema.name}` diff --git a/src/translations/en.json b/src/translations/en.json index 918ac1989f..3e10edd42f 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -4017,9 +4017,19 @@ "entity": "Entity with timestamp", "offset_by": "offset by {offset}", "mode": "Mode", + "weekday": "Weekdays", + "weekdays": { + "mon": "[%key:ui::weekdays::monday%]", + "tue": "[%key:ui::weekdays::tuesday%]", + "wed": "[%key:ui::weekdays::wednesday%]", + "thu": "[%key:ui::weekdays::thursday%]", + "fri": "[%key:ui::weekdays::friday%]", + "sat": "[%key:ui::weekdays::saturday%]", + "sun": "[%key:ui::weekdays::sunday%]" + }, "description": { "picker": "At a specific time, or on a specific date.", - "full": "When the time is equal to {time}" + "full": "When the time is equal to {time}{hasWeekdays, select, \n true { on {weekdays}} \n other {}\n}" } }, "time_pattern": {