184 files

This commit is contained in:
Home Assistant Version Control committed 2026-09-02 11:49:09 +00:00
1 parent 7b47edbf8d
commit 0c64e47969
184 files changed
+9608 -11572

No files matched your search

@@ -3,7 +3,9 @@
from __future__ import annotations from __future__ import annotations
import logging import logging
from collections.abc import Awaitable, Callable
from dataclasses import dataclass from dataclasses import dataclass
from datetime import date as date_cls
from datetime import timedelta from datetime import timedelta
from typing import Any from typing import Any
@@ -18,7 +20,7 @@ from homeassistant.core import (
SupportsResponse, SupportsResponse,
callback, callback,
) )
from homeassistant.exceptions import ServiceValidationError from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
from homeassistant.helpers import ( from homeassistant.helpers import (
config_validation as cv, config_validation as cv,
) )
@@ -34,6 +36,7 @@ from homeassistant.helpers.event import (
) )
from homeassistant.helpers.start import async_at_started from homeassistant.helpers.start import async_at_started
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util import dt as dt_util
from .const import ( from .const import (
BATTERY_FLEET_OBJECT_FLAG, BATTERY_FLEET_OBJECT_FLAG,
@@ -131,7 +134,7 @@ type MaintenanceSupporterConfigEntry = ConfigEntry[MaintenanceSupporterData]
# --- Service Schemas --- # --- Service Schemas ---
SERVICE_COMPLETE_SCHEMA = vol.Schema( SERVICE_COMPLETE_SCHEMA = vol.Schema(
{ {
vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional("notes"): vol.All(cv.string, vol.Length(max=2000)), vol.Optional("notes"): vol.All(cv.string, vol.Length(max=2000)),
vol.Optional("cost"): vol.All(vol.Coerce(float), vol.Range(min=0, max=MAX_COST)), vol.Optional("cost"): vol.All(vol.Coerce(float), vol.Range(min=0, max=MAX_COST)),
vol.Optional("duration"): vol.All(vol.Coerce(int), vol.Range(min=0, max=MAX_DURATION_MINUTES)), vol.Optional("duration"): vol.All(vol.Coerce(int), vol.Range(min=0, max=MAX_DURATION_MINUTES)),
@@ -149,14 +152,14 @@ SERVICE_COMPLETE_SCHEMA = vol.Schema(
SERVICE_RESET_SCHEMA = vol.Schema( SERVICE_RESET_SCHEMA = vol.Schema(
{ {
vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional("date"): cv.date, vol.Optional("date"): cv.date,
} }
) )
SERVICE_SKIP_SCHEMA = vol.Schema( SERVICE_SKIP_SCHEMA = vol.Schema(
{ {
vol.Required(ATTR_ENTITY_ID): cv.entity_id, vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
vol.Optional("reason"): vol.All(cv.string, vol.Length(max=2000)), vol.Optional("reason"): vol.All(cv.string, vol.Length(max=2000)),
} }
) )
@@ -451,9 +454,8 @@ async def _async_setup_shared(hass: HomeAssistant) -> bool:
) )
return str(user_id) return str(user_id)
async def _handle_complete(call: ServiceCall) -> None: def _resolve_task_target(entity_id: str) -> tuple[MaintenanceCoordinator, str]:
"""Handle the complete service call.""" """entity_id -> (coordinator, task_id), with the classic errors."""
entity_id = call.data[ATTR_ENTITY_ID]
coordinator = _get_coordinator_for_entity(hass, entity_id) coordinator = _get_coordinator_for_entity(hass, entity_id)
if coordinator is None: if coordinator is None:
raise ServiceValidationError( raise ServiceValidationError(
@@ -468,68 +470,94 @@ async def _async_setup_shared(hass: HomeAssistant) -> bool:
translation_key="no_task_for_entity", translation_key="no_task_for_entity",
translation_placeholders={"entity_id": entity_id}, translation_placeholders={"entity_id": entity_id},
) )
return coordinator, task_id
async def _run_per_task(
action: Callable[[MaintenanceCoordinator, str], Awaitable[None]],
entity_ids: list[str],
label: str,
) -> None:
"""#158: one or many task sensors. A single entity keeps today's
exact error shape; a list runs sequentially best-effort — the
choke-point refusals (too_early, tag_scan_required,
completion_details_required, the skip lock, ...) hit per task, are
collected, and never block the other tasks. Partial success stands
and the summary error names what was refused."""
ids = list(dict.fromkeys(entity_ids))
if len(ids) == 1:
coordinator, task_id = _resolve_task_target(ids[0])
await action(coordinator, task_id)
return
done = 0
errors: list[str] = []
for eid in ids:
try:
coordinator, task_id = _resolve_task_target(eid)
await action(coordinator, task_id)
done += 1
except HomeAssistantError as err:
errors.append(f"{eid}: {err}")
if errors:
raise ServiceValidationError(
f"{label}: {done} of {len(ids)} succeeded; " + " | ".join(errors)
)
async def _handle_complete(call: ServiceCall) -> None:
"""Handle the complete service call (one or many task sensors, #158)."""
entity_ids = call.data[ATTR_ENTITY_ID]
if len(dict.fromkeys(entity_ids)) > 1:
# Per-task values must not fan out: a reading belongs to ONE
# meter, cost/duration would multiply into the budget and the
# averages, and one physical scan proves exactly one tag.
for field in ("reading_value", "cost", "duration", "via_tag_scan"):
if call.data.get(field) is not None:
raise ServiceValidationError(
f"'{field}' can only be used with a single entity_id"
)
# #128: explicit person beats the call context; the context covers the # #128: explicit person beats the call context; the context covers the
# common case for free (a dashboard tap propagates the tapping user). # common case for free (a dashboard tap propagates the tapping user).
if call.data.get("completed_by"): if call.data.get("completed_by"):
completed_by: str | None = _resolve_person_user_id(call.data["completed_by"]) completed_by: str | None = _resolve_person_user_id(call.data["completed_by"])
else: else:
completed_by = call.context.user_id if call.context else None completed_by = call.context.user_id if call.context else None
await coordinator.complete_maintenance(
task_id=task_id, async def _one(coordinator: MaintenanceCoordinator, task_id: str) -> None:
notes=call.data.get("notes"), await coordinator.complete_maintenance(
cost=call.data.get("cost"), task_id=task_id,
duration=call.data.get("duration"), notes=call.data.get("notes"),
reading_value=call.data.get("reading_value"), cost=call.data.get("cost"),
completed_by=completed_by, duration=call.data.get("duration"),
completed_at=call.data.get("completed_at"), reading_value=call.data.get("reading_value"),
# Proof of presence: an automation that reacted to the physical completed_by=completed_by,
# scan itself passes via_tag_scan to satisfy require_tag_scan. completed_at=call.data.get("completed_at"),
tag_verified=bool(call.data.get("via_tag_scan")), # Proof of presence: an automation that reacted to the physical
) # scan itself passes via_tag_scan to satisfy require_tag_scan.
tag_verified=bool(call.data.get("via_tag_scan")),
)
await _run_per_task(_one, entity_ids, "complete")
async def _handle_reset(call: ServiceCall) -> None: async def _handle_reset(call: ServiceCall) -> None:
"""Handle the reset service call.""" """Handle the reset service call (one or many task sensors, #158)."""
entity_id = call.data[ATTR_ENTITY_ID]
coordinator = _get_coordinator_for_entity(hass, entity_id) async def _one(coordinator: MaintenanceCoordinator, task_id: str) -> None:
if coordinator is None: await coordinator.reset_maintenance(
raise ServiceValidationError( task_id=task_id,
translation_domain=DOMAIN, date=call.data.get("date"),
translation_key="no_coordinator_for_entity",
translation_placeholders={"entity_id": entity_id},
) )
task_id = _get_task_id_for_entity(hass, entity_id)
if task_id is None: await _run_per_task(_one, call.data[ATTR_ENTITY_ID], "reset")
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="no_task_for_entity",
translation_placeholders={"entity_id": entity_id},
)
await coordinator.reset_maintenance(
task_id=task_id,
date=call.data.get("date"),
)
async def _handle_skip(call: ServiceCall) -> None: async def _handle_skip(call: ServiceCall) -> None:
"""Handle the skip service call.""" """Handle the skip service call (one or many task sensors, #158)."""
entity_id = call.data[ATTR_ENTITY_ID]
coordinator = _get_coordinator_for_entity(hass, entity_id) async def _one(coordinator: MaintenanceCoordinator, task_id: str) -> None:
if coordinator is None: await coordinator.skip_maintenance(
raise ServiceValidationError( task_id=task_id,
translation_domain=DOMAIN, reason=call.data.get("reason"),
translation_key="no_coordinator_for_entity",
translation_placeholders={"entity_id": entity_id},
) )
task_id = _get_task_id_for_entity(hass, entity_id)
if task_id is None: await _run_per_task(_one, call.data[ATTR_ENTITY_ID], "skip")
raise ServiceValidationError(
translation_domain=DOMAIN,
translation_key="no_task_for_entity",
translation_placeholders={"entity_id": entity_id},
)
await coordinator.skip_maintenance(
task_id=task_id,
reason=call.data.get("reason"),
)
async def _handle_export(call: ServiceCall) -> None: async def _handle_export(call: ServiceCall) -> None:
"""Handle the export_data service call.""" """Handle the export_data service call."""
@@ -689,6 +717,21 @@ async def _async_setup_shared(hass: HomeAssistant) -> bool:
continue continue
if wanted_status and status != wanted_status: if wanted_status and status != wanted_status:
continue continue
# #151: last completion + live trigger reading, so
# notification automations don't need extra lookups.
lp = task.get("last_performed")
days_since: int | None = None
if lp:
try:
days_since = (dt_util.now().date() - date_cls.fromisoformat(str(lp)[:10])).days
except ValueError:
days_since = None
tc = task.get("trigger_config") or {}
trigger_unit: str | None = None
if tc.get("entity_id"):
st = hass.states.get(tc["entity_id"])
if st:
trigger_unit = st.attributes.get("unit_of_measurement")
tasks.append( tasks.append(
{ {
"entry_id": ce.entry_id, "entry_id": ce.entry_id,
@@ -700,6 +743,10 @@ async def _async_setup_shared(hass: HomeAssistant) -> bool:
"days_until_due": task.get("_days_until_due"), "days_until_due": task.get("_days_until_due"),
"type": task.get("type"), "type": task.get("type"),
"priority": task.get("priority", "normal"), "priority": task.get("priority", "normal"),
"last_performed": lp,
"days_since_last_completed": days_since,
"trigger_current_value": task.get("_trigger_current_value"),
"trigger_unit": trigger_unit,
} }
) )
return {"tasks": tasks, "count": len(tasks)} return {"tasks": tasks, "count": len(tasks)}
@@ -1484,12 +1531,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: MaintenanceSupporterConf
except Exception: except Exception:
_LOGGER.exception("Battery-fleet part reconcile at start failed") _LOGGER.exception("Battery-fleet part reconcile at start failed")
return return
if result["added"] or result["pruned"]: if result["added"] or result["pruned"] or result["orphans_removed"]:
_LOGGER.info( _LOGGER.info(
"Battery-fleet parts reconciled at start: added %s, pruned legacy UNKNOWN: %s", "Battery-fleet parts reconciled at start: added %s, pruned legacy UNKNOWN: %s, orphaned stock sensors removed: %s",
result["added"] or "none", result["added"] or "none",
result["pruned"], result["pruned"],
result["orphans_removed"],
) )
if result.get("trigger_healed"):
# #156: the recovery flag only reaches the LIVE trigger
# after a reload — do it once; the next start finds it set.
_LOGGER.info("Battery-fleet trigger healed (auto_complete_on_recovery) — reloading %s", entry.title)
hass.async_create_task(hass.config_entries.async_reload(entry.entry_id))
entry.async_on_unload(async_at_started(hass, _fleet_parts_at_start)) entry.async_on_unload(async_at_started(hass, _fleet_parts_at_start))
@@ -11,6 +11,7 @@
"postpone_needs_when": "Řekni mi, o kolik ho mám odložit — třeba o pět dní.", "postpone_needs_when": "Řekni mi, o kolik ho mám odložit — třeba o pět dní.",
"postpone_past": "Tím by '{task}' spadl do minulosti.", "postpone_past": "Tím by '{task}' spadl do minulosti.",
"skipped": "Tento cyklus úkolu '{task}' u zařízení {object} je přeskočený. Další termín je {date}.", "skipped": "Tento cyklus úkolu '{task}' u zařízení {object} je přeskočený. Další termín je {date}.",
"skip_disabled": "Přeskakování je pro '{task}' vypnuto.",
"not_found": "Nenašel jsem úkol údržby, který by odpovídal '{name}'.", "not_found": "Nenašel jsem úkol údržby, který by odpovídal '{name}'.",
"ambiguous": "Tomu odpovídá víc úkolů: {candidates}. Upřesni to, prosím.", "ambiguous": "Tomu odpovídá víc úkolů: {candidates}. Upřesni to, prosím.",
"too_early": "Úkol '{task}' se dá dokončit až blíž k termínu.", "too_early": "Úkol '{task}' se dá dokončit až blíž k termínu.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Sig, hvor langt jeg skal udskyde den — for eksempel fem dage.", "postpone_needs_when": "Sig, hvor langt jeg skal udskyde den — for eksempel fem dage.",
"postpone_past": "Så ville '{task}' ligge i fortiden.", "postpone_past": "Så ville '{task}' ligge i fortiden.",
"skipped": "Jeg har sprunget denne omgang af '{task}' på {object} over. Næste omgang skal laves den {date}.", "skipped": "Jeg har sprunget denne omgang af '{task}' på {object} over. Næste omgang skal laves den {date}.",
"skip_disabled": "Spring over er slået fra for '{task}'.",
"not_found": "Jeg kunne ikke finde en vedligeholdelsesopgave, der passer på '{name}'.", "not_found": "Jeg kunne ikke finde en vedligeholdelsesopgave, der passer på '{name}'.",
"ambiguous": "Det passer på flere opgaver: {candidates}. Vær lige lidt mere præcis.", "ambiguous": "Det passer på flere opgaver: {candidates}. Vær lige lidt mere præcis.",
"too_early": "'{task}' kan først markeres som udført tættere på forfaldsdatoen.", "too_early": "'{task}' kan først markeres som udført tættere på forfaldsdatoen.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Sag mir, um wie lange ich verschieben soll — zum Beispiel um fünf Tage.", "postpone_needs_when": "Sag mir, um wie lange ich verschieben soll — zum Beispiel um fünf Tage.",
"postpone_past": "Damit läge '{task}' in der Vergangenheit.", "postpone_past": "Damit läge '{task}' in der Vergangenheit.",
"skipped": "Dieser Durchgang von '{task}' an {object} wurde übersprungen. Der nächste ist am {date} fällig.", "skipped": "Dieser Durchgang von '{task}' an {object} wurde übersprungen. Der nächste ist am {date} fällig.",
"skip_disabled": "Überspringen ist für '{task}' ausgeschaltet.",
"not_found": "Ich habe keine Wartungsaufgabe zu '{name}' gefunden.", "not_found": "Ich habe keine Wartungsaufgabe zu '{name}' gefunden.",
"ambiguous": "Das passt auf mehrere Aufgaben: {candidates}. Bitte formuliere genauer.", "ambiguous": "Das passt auf mehrere Aufgaben: {candidates}. Bitte formuliere genauer.",
"too_early": "'{task}' kann erst näher am Fälligkeitstermin erledigt werden.", "too_early": "'{task}' kann erst näher am Fälligkeitstermin erledigt werden.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Tell me how far to postpone it — for example, by five days.", "postpone_needs_when": "Tell me how far to postpone it — for example, by five days.",
"postpone_past": "That would put '{task}' in the past.", "postpone_past": "That would put '{task}' in the past.",
"skipped": "Skipped this cycle of '{task}' on {object}. The next one is due {date}.", "skipped": "Skipped this cycle of '{task}' on {object}. The next one is due {date}.",
"skip_disabled": "Skipping is turned off for '{task}'.",
"not_found": "I couldn't find a maintenance task matching '{name}'.", "not_found": "I couldn't find a maintenance task matching '{name}'.",
"ambiguous": "That matches several tasks: {candidates}. Please be more specific.", "ambiguous": "That matches several tasks: {candidates}. Please be more specific.",
"too_early": "'{task}' can only be completed closer to its due date.", "too_early": "'{task}' can only be completed closer to its due date.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Dime cuánto quieres aplazarlo — por ejemplo, cinco días.", "postpone_needs_when": "Dime cuánto quieres aplazarlo — por ejemplo, cinco días.",
"postpone_past": "Eso dejaría '{task}' en el pasado.", "postpone_past": "Eso dejaría '{task}' en el pasado.",
"skipped": "Me he saltado este ciclo de '{task}' en {object}. El siguiente toca el {date}.", "skipped": "Me he saltado este ciclo de '{task}' en {object}. El siguiente toca el {date}.",
"skip_disabled": "Omitir está desactivado para '{task}'.",
"not_found": "No he encontrado ninguna tarea de mantenimiento que coincida con '{name}'.", "not_found": "No he encontrado ninguna tarea de mantenimiento que coincida con '{name}'.",
"ambiguous": "Eso coincide con varias tareas: {candidates}. Concreta un poco más, por favor.", "ambiguous": "Eso coincide con varias tareas: {candidates}. Concreta un poco más, por favor.",
"too_early": "'{task}' solo se puede completar cuando se acerque su fecha prevista.", "too_early": "'{task}' solo se puede completar cuando se acerque su fecha prevista.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Kerro, kuinka paljon siirrän sitä — esimerkiksi viisi päivää.", "postpone_needs_when": "Kerro, kuinka paljon siirrän sitä — esimerkiksi viisi päivää.",
"postpone_past": "Silloin tehtävä '{task}' menisi menneisyyteen.", "postpone_past": "Silloin tehtävä '{task}' menisi menneisyyteen.",
"skipped": "Ohitin tehtävän '{task}' tämän kerran kohteessa {object}. Seuraava ajankohta: {date}.", "skipped": "Ohitin tehtävän '{task}' tämän kerran kohteessa {object}. Seuraava ajankohta: {date}.",
"skip_disabled": "Ohittaminen on poistettu käytöstä kohteelle '{task}'.",
"not_found": "En löytänyt huoltotehtävää, joka vastaisi hakua '{name}'.", "not_found": "En löytänyt huoltotehtävää, joka vastaisi hakua '{name}'.",
"ambiguous": "Tämä vastaa useaa tehtävää: {candidates}. Tarkenna vielä hieman.", "ambiguous": "Tämä vastaa useaa tehtävää: {candidates}. Tarkenna vielä hieman.",
"too_early": "Tehtävän '{task}' voi kuitata tehdyksi vasta lähempänä sen ajankohtaa.", "too_early": "Tehtävän '{task}' voi kuitata tehdyksi vasta lähempänä sen ajankohtaa.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Dis-moi de combien je dois le reporter — par exemple, de cinq jours.", "postpone_needs_when": "Dis-moi de combien je dois le reporter — par exemple, de cinq jours.",
"postpone_past": "Ça mettrait '{task}' dans le passé.", "postpone_past": "Ça mettrait '{task}' dans le passé.",
"skipped": "J'ai sauté ce cycle de '{task}' sur {object}. Le prochain est à faire le {date}.", "skipped": "J'ai sauté ce cycle de '{task}' sur {object}. Le prochain est à faire le {date}.",
"skip_disabled": "Ignorer est désactivé pour '{task}'.",
"not_found": "Je n'ai pas trouvé de tâche d'entretien qui corresponde à '{name}'.", "not_found": "Je n'ai pas trouvé de tâche d'entretien qui corresponde à '{name}'.",
"ambiguous": "Ça correspond à plusieurs tâches : {candidates}. Sois un peu plus précis, s'il te plaît.", "ambiguous": "Ça correspond à plusieurs tâches : {candidates}. Sois un peu plus précis, s'il te plaît.",
"too_early": "Tu ne pourras valider '{task}' que plus près de sa date d'échéance.", "too_early": "Tu ne pourras valider '{task}' que plus près de sa date d'échéance.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "बताइए कितना टालना है — जैसे पाँच दिन।", "postpone_needs_when": "बताइए कितना टालना है — जैसे पाँच दिन।",
"postpone_past": "इससे '{task}' की तारीख़ पिछली हो जाएगी।", "postpone_past": "इससे '{task}' की तारीख़ पिछली हो जाएगी।",
"skipped": "{object} पर '{task}' का यह चक्र छोड़ दिया है। अगली बार {date} को करना है।", "skipped": "{object} पर '{task}' का यह चक्र छोड़ दिया है। अगली बार {date} को करना है।",
"skip_disabled": "'{task}' के लिए छोड़ना बंद है।",
"not_found": "'{name}' से मिलता-जुलता कोई मेंटेनेंस काम नहीं मिला।", "not_found": "'{name}' से मिलता-जुलता कोई मेंटेनेंस काम नहीं मिला।",
"ambiguous": "इससे कई काम मेल खाते हैं: {candidates}। थोड़ा और साफ़ बताइए।", "ambiguous": "इससे कई काम मेल खाते हैं: {candidates}। थोड़ा और साफ़ बताइए।",
"too_early": "'{task}' को तय तारीख़ के क़रीब आने पर ही पूरा किया जा सकता है।", "too_early": "'{task}' को तय तारीख़ के क़रीब आने पर ही पूरा किया जा सकता है।",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Mondd meg, mennyivel halasszam el — például öt nappal.", "postpone_needs_when": "Mondd meg, mennyivel halasszam el — például öt nappal.",
"postpone_past": "'{task}': ezzel a feladat a múltba kerülne.", "postpone_past": "'{task}': ezzel a feladat a múltba kerülne.",
"skipped": "Kihagytam ezt a fordulót: '{task}' – {object}. A következő időpont: {date}.", "skipped": "Kihagytam ezt a fordulót: '{task}' – {object}. A következő időpont: {date}.",
"skip_disabled": "A kihagyás ki van kapcsolva ehhez: '{task}'.",
"not_found": "Nem találtam ehhez illő karbantartási feladatot: '{name}'.", "not_found": "Nem találtam ehhez illő karbantartási feladatot: '{name}'.",
"ambiguous": "Több feladatra is illik: {candidates}. Fogalmazz pontosabban.", "ambiguous": "Több feladatra is illik: {candidates}. Fogalmazz pontosabban.",
"too_early": "'{task}': ezt a feladatot csak az esedékesség közelében lehet elvégezni.", "too_early": "'{task}': ezt a feladatot csak az esedékesség közelében lehet elvégezni.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Dimmi di quanto rimandarla — per esempio, di cinque giorni.", "postpone_needs_when": "Dimmi di quanto rimandarla — per esempio, di cinque giorni.",
"postpone_past": "Così '{task}' finirebbe nel passato.", "postpone_past": "Così '{task}' finirebbe nel passato.",
"skipped": "Ho saltato questo ciclo di '{task}' su {object}. Il prossimo è previsto per il {date}.", "skipped": "Ho saltato questo ciclo di '{task}' su {object}. Il prossimo è previsto per il {date}.",
"skip_disabled": "Saltare è disattivato per '{task}'.",
"not_found": "Non ho trovato nessuna attività di manutenzione che corrisponda a '{name}'.", "not_found": "Non ho trovato nessuna attività di manutenzione che corrisponda a '{name}'.",
"ambiguous": "Corrisponde a più attività: {candidates}. Puoi essere un po' più preciso?", "ambiguous": "Corrisponde a più attività: {candidates}. Puoi essere un po' più preciso?",
"too_early": "Puoi completare '{task}' solo quando si avvicina la scadenza.", "too_early": "Puoi completare '{task}' solo quando si avvicina la scadenza.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "どのくらい先に延ばすか教えてください。たとえば「5日」のように言ってください。", "postpone_needs_when": "どのくらい先に延ばすか教えてください。たとえば「5日」のように言ってください。",
"postpone_past": "それだと「{task}」の日付が過去になってしまいます。", "postpone_past": "それだと「{task}」の日付が過去になってしまいます。",
"skipped": "{object}の「{task}」の今回分をスキップしました。次回は{date}が期限です。", "skipped": "{object}の「{task}」の今回分をスキップしました。次回は{date}が期限です。",
"skip_disabled": "'{task}'のスキップは無効になっています。",
"not_found": "「{name}」に一致するメンテナンスタスクは見つかりませんでした。", "not_found": "「{name}」に一致するメンテナンスタスクは見つかりませんでした。",
"ambiguous": "いくつかのタスクが当てはまります:{candidates}。もう少し詳しく言ってください。", "ambiguous": "いくつかのタスクが当てはまります:{candidates}。もう少し詳しく言ってください。",
"too_early": "「{task}」は期限が近づいてからでないと完了にできません。", "too_early": "「{task}」は期限が近づいてからでないと完了にできません。",
@@ -11,6 +11,7 @@
"postpone_needs_when": "얼마나 미룰지 알려주세요. 예를 들어 '닷새 뒤'처럼요.", "postpone_needs_when": "얼마나 미룰지 알려주세요. 예를 들어 '닷새 뒤'처럼요.",
"postpone_past": "그러면 '{task}' 날짜가 과거가 돼요.", "postpone_past": "그러면 '{task}' 날짜가 과거가 돼요.",
"skipped": "{object}의 '{task}', 이번 차례는 건너뛰었어요. 다음은 {date}에 예정돼 있어요.", "skipped": "{object}의 '{task}', 이번 차례는 건너뛰었어요. 다음은 {date}에 예정돼 있어요.",
"skip_disabled": "'{task}'의 건너뛰기가 꺼져 있습니다.",
"not_found": "'{name}'에 맞는 정비 작업을 찾지 못했어요.", "not_found": "'{name}'에 맞는 정비 작업을 찾지 못했어요.",
"ambiguous": "여러 작업이 해당돼요: {candidates}. 조금 더 구체적으로 말씀해 주세요.", "ambiguous": "여러 작업이 해당돼요: {candidates}. 조금 더 구체적으로 말씀해 주세요.",
"too_early": "'{task}' 작업은 예정일이 가까워져야 완료할 수 있어요.", "too_early": "'{task}' 작업은 예정일이 가까워져야 완료할 수 있어요.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Si hvor langt jeg skal utsette den — for eksempel fem dager.", "postpone_needs_when": "Si hvor langt jeg skal utsette den — for eksempel fem dager.",
"postpone_past": "Da ville '{task}' havne i fortiden.", "postpone_past": "Da ville '{task}' havne i fortiden.",
"skipped": "Jeg hoppet over denne runden av '{task}' på {object}. Neste runde skal gjøres {date}.", "skipped": "Jeg hoppet over denne runden av '{task}' på {object}. Neste runde skal gjøres {date}.",
"skip_disabled": "Hopp over er slått av for '{task}'.",
"not_found": "Jeg fant ingen vedlikeholdsoppgave som passer med '{name}'.", "not_found": "Jeg fant ingen vedlikeholdsoppgave som passer med '{name}'.",
"ambiguous": "Det passer med flere oppgaver: {candidates}. Vær litt mer presis.", "ambiguous": "Det passer med flere oppgaver: {candidates}. Vær litt mer presis.",
"too_early": "'{task}' kan først krysses av nærmere forfallsdatoen.", "too_early": "'{task}' kan først krysses av nærmere forfallsdatoen.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Zeg even hoe lang ik het moet uitstellen — bijvoorbeeld vijf dagen.", "postpone_needs_when": "Zeg even hoe lang ik het moet uitstellen — bijvoorbeeld vijf dagen.",
"postpone_past": "Dan zou '{task}' in het verleden liggen.", "postpone_past": "Dan zou '{task}' in het verleden liggen.",
"skipped": "Ik heb deze ronde van '{task}' bij {object} overgeslagen. De volgende staat op {date}.", "skipped": "Ik heb deze ronde van '{task}' bij {object} overgeslagen. De volgende staat op {date}.",
"skip_disabled": "Overslaan is uitgeschakeld voor '{task}'.",
"not_found": "Ik kon geen onderhoudstaak vinden die past bij '{name}'.", "not_found": "Ik kon geen onderhoudstaak vinden die past bij '{name}'.",
"ambiguous": "Dat past bij meerdere taken: {candidates}. Kun je het iets preciezer zeggen?", "ambiguous": "Dat past bij meerdere taken: {candidates}. Kun je het iets preciezer zeggen?",
"too_early": "'{task}' kun je pas afvinken als de datum dichterbij is.", "too_early": "'{task}' kun je pas afvinken als de datum dichterbij is.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Powiedz mi, o ile mam przełożyć — na przykład o pięć dni.", "postpone_needs_when": "Powiedz mi, o ile mam przełożyć — na przykład o pięć dni.",
"postpone_past": "Wtedy '{task}' wypadłoby w przeszłości.", "postpone_past": "Wtedy '{task}' wypadłoby w przeszłości.",
"skipped": "Ten cykl zadania '{task}' na urządzeniu {object} został pominięty. Następny termin to {date}.", "skipped": "Ten cykl zadania '{task}' na urządzeniu {object} został pominięty. Następny termin to {date}.",
"skip_disabled": "Pomijanie jest wyłączone dla '{task}'.",
"not_found": "Nie znalazłem zadania konserwacyjnego pasującego do '{name}'.", "not_found": "Nie znalazłem zadania konserwacyjnego pasującego do '{name}'.",
"ambiguous": "To pasuje do kilku zadań: {candidates}. Doprecyzuj, proszę.", "ambiguous": "To pasuje do kilku zadań: {candidates}. Doprecyzuj, proszę.",
"too_early": "Zadanie '{task}' można wykonać dopiero bliżej terminu.", "too_early": "Zadanie '{task}' można wykonać dopiero bliżej terminu.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Me diga por quanto tempo adiar — por exemplo, cinco dias.", "postpone_needs_when": "Me diga por quanto tempo adiar — por exemplo, cinco dias.",
"postpone_past": "Isso colocaria '{task}' no passado.", "postpone_past": "Isso colocaria '{task}' no passado.",
"skipped": "Pulei este ciclo de '{task}' em {object}. O próximo vence em {date}.", "skipped": "Pulei este ciclo de '{task}' em {object}. O próximo vence em {date}.",
"skip_disabled": "Pular está desativado para '{task}'.",
"not_found": "Não encontrei nenhuma tarefa de manutenção que corresponda a '{name}'.", "not_found": "Não encontrei nenhuma tarefa de manutenção que corresponda a '{name}'.",
"ambiguous": "Isso corresponde a várias tarefas: {candidates}. Seja mais específico, por favor.", "ambiguous": "Isso corresponde a várias tarefas: {candidates}. Seja mais específico, por favor.",
"too_early": "'{task}' só pode ser concluída mais perto da data de vencimento.", "too_early": "'{task}' só pode ser concluída mais perto da data de vencimento.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Diz-me quanto tempo queres adiar — por exemplo, cinco dias.", "postpone_needs_when": "Diz-me quanto tempo queres adiar — por exemplo, cinco dias.",
"postpone_past": "Assim '{task}' ficaria no passado.", "postpone_past": "Assim '{task}' ficaria no passado.",
"skipped": "Saltei este ciclo de '{task}' em {object}. O próximo está previsto para {date}.", "skipped": "Saltei este ciclo de '{task}' em {object}. O próximo está previsto para {date}.",
"skip_disabled": "Ignorar está desativado para '{task}'.",
"not_found": "Não encontrei nenhuma tarefa de manutenção que corresponda a '{name}'.", "not_found": "Não encontrei nenhuma tarefa de manutenção que corresponda a '{name}'.",
"ambiguous": "Isso corresponde a várias tarefas: {candidates}. Podes ser um pouco mais específico?", "ambiguous": "Isso corresponde a várias tarefas: {candidates}. Podes ser um pouco mais específico?",
"too_early": "Só podes concluir '{task}' mais perto da data prevista.", "too_early": "Só podes concluir '{task}' mais perto da data prevista.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Скажи, на сколько перенести — например, на пять дней.", "postpone_needs_when": "Скажи, на сколько перенести — например, на пять дней.",
"postpone_past": "Тогда '{task}' окажется в прошлом.", "postpone_past": "Тогда '{task}' окажется в прошлом.",
"skipped": "Этот цикл задачи '{task}' у устройства {object} пропущен. Следующий срок — {date}.", "skipped": "Этот цикл задачи '{task}' у устройства {object} пропущен. Следующий срок — {date}.",
"skip_disabled": "Пропуск отключён для '{task}'.",
"not_found": "Я не нашёл задачу обслуживания, подходящую под '{name}'.", "not_found": "Я не нашёл задачу обслуживания, подходящую под '{name}'.",
"ambiguous": "Под это подходит несколько задач: {candidates}. Уточни, пожалуйста.", "ambiguous": "Под это подходит несколько задач: {candidates}. Уточни, пожалуйста.",
"too_early": "Задачу '{task}' можно выполнить только ближе к сроку.", "too_early": "Задачу '{task}' можно выполнить только ближе к сроку.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Säg hur långt jag ska skjuta upp den — till exempel fem dagar.", "postpone_needs_when": "Säg hur långt jag ska skjuta upp den — till exempel fem dagar.",
"postpone_past": "Då skulle '{task}' hamna i det förflutna.", "postpone_past": "Då skulle '{task}' hamna i det förflutna.",
"skipped": "Jag har hoppat över den här omgången av '{task}' på {object}. Nästa omgång ska göras den {date}.", "skipped": "Jag har hoppat över den här omgången av '{task}' på {object}. Nästa omgång ska göras den {date}.",
"skip_disabled": "Hoppa över är avstängt för '{task}'.",
"not_found": "Jag hittade ingen underhållsuppgift som matchar '{name}'.", "not_found": "Jag hittade ingen underhållsuppgift som matchar '{name}'.",
"ambiguous": "Det matchar flera uppgifter: {candidates}. Var lite mer specifik.", "ambiguous": "Det matchar flera uppgifter: {candidates}. Var lite mer specifik.",
"too_early": "'{task}' går att bocka av först närmare förfallodatumet.", "too_early": "'{task}' går att bocka av först närmare förfallodatumet.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Ne kadar erteleyeceğimi söyle — örneğin beş gün.", "postpone_needs_when": "Ne kadar erteleyeceğimi söyle — örneğin beş gün.",
"postpone_past": "Bu durumda '{task}' görevi geçmişte kalır.", "postpone_past": "Bu durumda '{task}' görevi geçmişte kalır.",
"skipped": "{object} için '{task}' görevinin bu turu atlandı. Sıradaki {date} tarihinde.", "skipped": "{object} için '{task}' görevinin bu turu atlandı. Sıradaki {date} tarihinde.",
"skip_disabled": "'{task}' için atlama kapalı.",
"not_found": "'{name}' ile eşleşen bir bakım görevi bulamadım.", "not_found": "'{name}' ile eşleşen bir bakım görevi bulamadım.",
"ambiguous": "Birden fazla göreve uyuyor: {candidates}. Biraz daha açık söyler misin?", "ambiguous": "Birden fazla göreve uyuyor: {candidates}. Biraz daha açık söyler misin?",
"too_early": "'{task}' görevi ancak son tarihine yaklaşınca tamamlanabilir.", "too_early": "'{task}' görevi ancak son tarihine yaklaşınca tamamlanabilir.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "Скажи, на скільки перенести — наприклад, на п’ять днів.", "postpone_needs_when": "Скажи, на скільки перенести — наприклад, на п’ять днів.",
"postpone_past": "Тоді '{task}' опиниться в минулому.", "postpone_past": "Тоді '{task}' опиниться в минулому.",
"skipped": "Цей цикл завдання '{task}' на пристрої {object} пропущено. Наступний термін — {date}.", "skipped": "Цей цикл завдання '{task}' на пристрої {object} пропущено. Наступний термін — {date}.",
"skip_disabled": "Пропуск вимкнено для '{task}'.",
"not_found": "Я не знайшов завдання з обслуговування, яке відповідає '{name}'.", "not_found": "Я не знайшов завдання з обслуговування, яке відповідає '{name}'.",
"ambiguous": "Цьому відповідає кілька завдань: {candidates}. Уточни, будь ласка.", "ambiguous": "Цьому відповідає кілька завдань: {candidates}. Уточни, будь ласка.",
"too_early": "Завдання '{task}' можна виконати лише ближче до терміну.", "too_early": "Завдання '{task}' можна виконати лише ближче до терміну.",
@@ -11,6 +11,7 @@
"postpone_needs_when": "告诉我要推迟多久,比如推迟五天。", "postpone_needs_when": "告诉我要推迟多久,比如推迟五天。",
"postpone_past": "那样的话,“{task}”的日期就会落在过去了。", "postpone_past": "那样的话,“{task}”的日期就会落在过去了。",
"skipped": "已跳过{object}的“{task}”这一次。下一次在{date}到期。", "skipped": "已跳过{object}的“{task}”这一次。下一次在{date}到期。",
"skip_disabled": "已为'{task}'关闭跳过。",
"not_found": "我没有找到和“{name}”对得上的维护任务。", "not_found": "我没有找到和“{name}”对得上的维护任务。",
"ambiguous": "有好几项任务都对得上:{candidates}。请说得更具体一些。", "ambiguous": "有好几项任务都对得上:{candidates}。请说得更具体一些。",
"too_early": "“{task}”要等到接近到期日才能完成。", "too_early": "“{task}”要等到接近到期日才能完成。",
@@ -353,6 +353,14 @@ class TriggerConfigMixin:
if "trigger_baseline_value" in prev_tc if "trigger_baseline_value" in prev_tc
else {} else {}
), ),
# #149: the session cap is panel-managed (the flow grew no
# field) — carry it so an options-flow trigger edit doesn't
# silently drop it.
**(
{"trigger_runtime_max_session_seconds": prev_tc["trigger_runtime_max_session_seconds"]}
if "trigger_runtime_max_session_seconds" in prev_tc
else {}
),
} }
return await next_step() return await next_step()
@@ -1436,6 +1436,13 @@ class MaintenanceCoordinator(DataUpdateCoordinator[dict[str, Any]]):
_LOGGER.error("Task %s not found in entry %s", task_id, self.entry.title) _LOGGER.error("Task %s not found in entry %s", task_id, self.entry.title)
return return
# #150: the per-task skip lock is enforced HERE — the choke point
# every surface funnels through (WS, voice, vacation preview).
if merged[task_id].get("allow_skip") is False:
raise ServiceValidationError(
f"Skipping is disabled for task {merged[task_id].get('name', task_id)!r}"
)
task = MaintenanceTask.from_dict(merged[task_id]) task = MaintenanceTask.from_dict(merged[task_id])
# Skipping an already-overdue task means it lapsed → record it as MISSED # Skipping an already-overdue task means it lapsed → record it as MISSED
# (not a deliberate skip). An explicit as_missed=True always wins. # (not a deliberate skip). An explicit as_missed=True always wins.
@@ -100,6 +100,10 @@ def _inject_per_entity_state(config: dict[str, Any], entity_state: dict[str, Any
config["trigger_accumulated_seconds"] = entity_state["accumulated_seconds"] config["trigger_accumulated_seconds"] = entity_state["accumulated_seconds"]
if "on_since" in entity_state: if "on_since" in entity_state:
config["trigger_on_since"] = entity_state["on_since"] config["trigger_on_since"] = entity_state["on_since"]
# #149: what the current session already booked — the per-session cap
# must survive a restart, or a stuck sensor books the cap again.
if "session_booked_seconds" in entity_state:
config["trigger_session_booked_seconds"] = entity_state["session_booked_seconds"]
elif trigger_type == TriggerType.STATE_CHANGE: elif trigger_type == TriggerType.STATE_CHANGE:
if "change_count" in entity_state: if "change_count" in entity_state:
config["trigger_change_count"] = entity_state["change_count"] config["trigger_change_count"] = entity_state["change_count"]
@@ -59,6 +59,18 @@ class RuntimeTrigger(BaseTrigger):
self._target_hours: float = trigger_config.get("trigger_runtime_hours", 100.0) self._target_hours: float = trigger_config.get("trigger_runtime_hours", 100.0)
self._accumulated_seconds: float = trigger_config.get("trigger_accumulated_seconds", 0.0) self._accumulated_seconds: float = trigger_config.get("trigger_accumulated_seconds", 0.0)
# #149: optional per-session cap (seconds). A session that exceeds it
# contributes exactly the cap — protects against a sensor stuck ON
# (lost connection, restart while "running").
raw_cap = trigger_config.get("trigger_runtime_max_session_seconds")
self._max_session: float | None = (
float(raw_cap) if isinstance(raw_cap, (int, float)) and not isinstance(raw_cap, bool) and raw_cap > 0 else None
)
# Seconds the CURRENT session already booked. Persisted, because the
# 5-minute periodic persist resets the on_since window — the cap is
# per SESSION, not per window.
self._session_booked: float = float(trigger_config.get("trigger_session_booked_seconds", 0.0) or 0.0)
# Restore on_since timestamp for restart recovery. parse_persisted_utc # Restore on_since timestamp for restart recovery. parse_persisted_utc
# coerces a naive legacy payload to UTC — dt_util.parse_datetime kept # coerces a naive legacy payload to UTC — dt_util.parse_datetime kept
# it naive here, and `utcnow() - naive` raises TypeError in the # it naive here, and `utcnow() - naive` raises TypeError in the
@@ -107,6 +119,7 @@ class RuntimeTrigger(BaseTrigger):
now = dt_util.utcnow() now = dt_util.utcnow()
self._on_since_dt = now self._on_since_dt = now
self._on_since = now.isoformat() self._on_since = now.isoformat()
self._session_booked = 0.0
await self._persist_runtime() await self._persist_runtime()
_LOGGER.debug( _LOGGER.debug(
"Runtime trigger: entity %s is ON, started tracking from now", "Runtime trigger: entity %s is ON, started tracking from now",
@@ -119,6 +132,7 @@ class RuntimeTrigger(BaseTrigger):
self._accumulate_elapsed() self._accumulate_elapsed()
self._on_since_dt = None self._on_since_dt = None
self._on_since = None self._on_since = None
self._session_booked = 0.0
await self._persist_runtime() await self._persist_runtime()
# Register state change listener # Register state change listener
@@ -184,6 +198,7 @@ class RuntimeTrigger(BaseTrigger):
now = dt_util.utcnow() now = dt_util.utcnow()
self._on_since_dt = now self._on_since_dt = now
self._on_since = now.isoformat() self._on_since = now.isoformat()
self._session_booked = 0.0
self.hass.async_create_task(self._persist_runtime()) self.hass.async_create_task(self._persist_runtime())
elif not self._is_on(new_val) and self._on_since_dt is not None: elif not self._is_on(new_val) and self._on_since_dt is not None:
# Restored anchor but the device APPEARS off (deferred setup # Restored anchor but the device APPEARS off (deferred setup
@@ -195,6 +210,7 @@ class RuntimeTrigger(BaseTrigger):
self._accumulate_elapsed() self._accumulate_elapsed()
self._on_since_dt = None self._on_since_dt = None
self._on_since = None self._on_since = None
self._session_booked = 0.0
self.hass.async_create_task(self._persist_runtime()) self.hass.async_create_task(self._persist_runtime())
self._update_evaluation() self._update_evaluation()
return return
@@ -207,6 +223,7 @@ class RuntimeTrigger(BaseTrigger):
self._accumulate_elapsed() self._accumulate_elapsed()
self._on_since_dt = None self._on_since_dt = None
self._on_since = None self._on_since = None
self._session_booked = 0.0
self.hass.async_create_task(self._persist_runtime()) self.hass.async_create_task(self._persist_runtime())
if not self._logged_unavailable: if not self._logged_unavailable:
_LOGGER.warning( _LOGGER.warning(
@@ -234,6 +251,7 @@ class RuntimeTrigger(BaseTrigger):
self._accumulate_elapsed() self._accumulate_elapsed()
self._on_since_dt = None self._on_since_dt = None
self._on_since = None self._on_since = None
self._session_booked = 0.0
self.hass.async_create_task(self._persist_runtime()) self.hass.async_create_task(self._persist_runtime())
_LOGGER.debug( _LOGGER.debug(
"Runtime trigger: %s turned OFF (accumulated=%.2fh)", "Runtime trigger: %s turned OFF (accumulated=%.2fh)",
@@ -245,6 +263,7 @@ class RuntimeTrigger(BaseTrigger):
now = dt_util.utcnow() now = dt_util.utcnow()
self._on_since_dt = now self._on_since_dt = now
self._on_since = now.isoformat() self._on_since = now.isoformat()
self._session_booked = 0.0
self.hass.async_create_task(self._persist_runtime()) self.hass.async_create_task(self._persist_runtime())
_LOGGER.debug( _LOGGER.debug(
"Runtime trigger: %s turned ON (tracking started)", "Runtime trigger: %s turned ON (tracking started)",
@@ -258,6 +277,7 @@ class RuntimeTrigger(BaseTrigger):
self._accumulate_elapsed() self._accumulate_elapsed()
self._on_since_dt = None self._on_since_dt = None
self._on_since = None self._on_since = None
self._session_booked = 0.0
self.hass.async_create_task(self._persist_runtime()) self.hass.async_create_task(self._persist_runtime())
self._update_evaluation() self._update_evaluation()
@@ -279,12 +299,23 @@ class RuntimeTrigger(BaseTrigger):
return str(state.state) return str(state.state)
def _accumulate_elapsed(self, now: datetime | None = None) -> None: def _accumulate_elapsed(self, now: datetime | None = None) -> None:
"""Add elapsed time since _on_since to accumulated total.""" """Add elapsed time since _on_since to accumulated total.
With a per-session cap (#149) the whole session contributes at most
the cap: ``_session_booked`` remembers what this session booked across
the 5-minute persist windows, so a stuck-ON sensor cannot book capped
slices window after window.
"""
if self._on_since_dt is None: if self._on_since_dt is None:
return return
now = now or dt_util.utcnow() now = now or dt_util.utcnow()
elapsed = (now - self._on_since_dt).total_seconds() elapsed = (now - self._on_since_dt).total_seconds()
if elapsed <= 0:
return
if self._max_session is not None:
elapsed = min(elapsed, max(0.0, self._max_session - self._session_booked))
if elapsed > 0: if elapsed > 0:
self._session_booked += elapsed
self._accumulated_seconds += elapsed self._accumulated_seconds += elapsed
def _get_current_runtime_hours(self) -> float: def _get_current_runtime_hours(self) -> float:
@@ -293,6 +324,8 @@ class RuntimeTrigger(BaseTrigger):
if self._on_since_dt is not None: if self._on_since_dt is not None:
elapsed = (dt_util.utcnow() - self._on_since_dt).total_seconds() elapsed = (dt_util.utcnow() - self._on_since_dt).total_seconds()
if elapsed > 0: if elapsed > 0:
if self._max_session is not None:
elapsed = min(elapsed, max(0.0, self._max_session - self._session_booked))
total_seconds += elapsed total_seconds += elapsed
return total_seconds / 3600.0 return total_seconds / 3600.0
@@ -326,6 +359,7 @@ class RuntimeTrigger(BaseTrigger):
data: dict[str, Any] = { data: dict[str, Any] = {
"accumulated_seconds": self._accumulated_seconds, "accumulated_seconds": self._accumulated_seconds,
"on_since": self._on_since, "on_since": self._on_since,
"session_booked_seconds": self._session_booked,
} }
await self._coordinator.async_persist_trigger_runtime( await self._coordinator.async_persist_trigger_runtime(
self._task_id, self._task_id,
@@ -117,6 +117,8 @@ def _build_export_object(
"custom_icon": tdata.get("custom_icon"), "custom_icon": tdata.get("custom_icon"),
"nfc_tag_id": tdata.get("nfc_tag_id"), "nfc_tag_id": tdata.get("nfc_tag_id"),
"require_tag_scan": tdata.get("require_tag_scan"), "require_tag_scan": tdata.get("require_tag_scan"),
# #150: per-task skip lock.
"allow_skip": tdata.get("allow_skip"),
"responsible_user_id": tdata.get("responsible_user_id"), "responsible_user_id": tdata.get("responsible_user_id"),
"entity_slug": tdata.get("entity_slug"), "entity_slug": tdata.get("entity_slug"),
"adaptive_config": tdata.get("adaptive_config"), "adaptive_config": tdata.get("adaptive_config"),
@@ -227,6 +227,7 @@ export class MaintenanceTaskDialog extends LitElement {
@state() private _triggerToState = ""; @state() private _triggerToState = "";
@state() private _triggerTargetChanges = ""; @state() private _triggerTargetChanges = "";
@state() private _triggerRuntimeHours = ""; @state() private _triggerRuntimeHours = "";
@state() private _triggerRuntimeMaxSession = "";
// Comma-separated "running" states for the runtime trigger (#103) — // Comma-separated "running" states for the runtime trigger (#103) —
// empty = the backend default ["on"]. Must roundtrip on edit: adopted // empty = the backend default ["on"]. Must roundtrip on edit: adopted
// tasks ship e.g. ["mowing"], and dropping it on save silently stops // tasks ship e.g. ["mowing"], and dropping it on save silently stops
@@ -245,6 +246,7 @@ export class MaintenanceTaskDialog extends LitElement {
@state() private _lastPerformed = ""; @state() private _lastPerformed = "";
@state() private _nfcTagId = ""; @state() private _nfcTagId = "";
@state() private _requireTagScan = false; @state() private _requireTagScan = false;
@state() private _allowSkip = true;
// v2.20 (#83): unit for `reading`-type tasks ("kWh", "m³", ...) // v2.20 (#83): unit for `reading`-type tasks ("kWh", "m³", ...)
@state() private _readingUnit = ""; @state() private _readingUnit = "";
/** The picked links, keyed by `partLinkKey` — the (entry_id, part_id) pair, /** The picked links, keyed by `partLinkKey` — the (entry_id, part_id) pair,
@@ -400,6 +402,7 @@ export class MaintenanceTaskDialog extends LitElement {
this._lastPerformed = task.last_performed || ""; this._lastPerformed = task.last_performed || "";
this._nfcTagId = task.nfc_tag_id || ""; this._nfcTagId = task.nfc_tag_id || "";
this._requireTagScan = !!task.require_tag_scan; this._requireTagScan = !!task.require_tag_scan;
this._allowSkip = task.allow_skip !== false;
this._readingUnit = task.reading_unit || ""; this._readingUnit = task.reading_unit || "";
// Whole link, entry_id included — hydrating only part_id would turn every // Whole link, entry_id included — hydrating only part_id would turn every
// shared-pool link into an own-part link on the next save (#111). // shared-pool link into an own-part link on the next save (#111).
@@ -500,6 +503,7 @@ export class MaintenanceTaskDialog extends LitElement {
this._triggerToState = tc.trigger_to_state || ""; this._triggerToState = tc.trigger_to_state || "";
this._triggerTargetChanges = tc.trigger_target_changes?.toString() || ""; this._triggerTargetChanges = tc.trigger_target_changes?.toString() || "";
this._triggerRuntimeHours = tc.trigger_runtime_hours?.toString() || ""; this._triggerRuntimeHours = tc.trigger_runtime_hours?.toString() || "";
this._triggerRuntimeMaxSession = tc.trigger_runtime_max_session_seconds?.toString() || "";
this._triggerOnStates = (tc.trigger_on_states || []).join(", "); this._triggerOnStates = (tc.trigger_on_states || []).join(", ");
if (tc.type === "compound") { if (tc.type === "compound") {
this._compoundLogic = tc.compound_logic === "OR" ? "OR" : "AND"; this._compoundLogic = tc.compound_logic === "OR" ? "OR" : "AND";
@@ -551,6 +555,7 @@ export class MaintenanceTaskDialog extends LitElement {
this._lastPerformed = ""; this._lastPerformed = "";
this._nfcTagId = ""; this._nfcTagId = "";
this._requireTagScan = false; this._requireTagScan = false;
this._allowSkip = true;
this._readingUnit = ""; this._readingUnit = "";
this._consumesParts = {}; this._consumesParts = {};
this._responsibleUserId = null; this._responsibleUserId = null;
@@ -610,6 +615,7 @@ export class MaintenanceTaskDialog extends LitElement {
this._triggerToState = ""; this._triggerToState = "";
this._triggerTargetChanges = ""; this._triggerTargetChanges = "";
this._triggerRuntimeHours = ""; this._triggerRuntimeHours = "";
this._triggerRuntimeMaxSession = "";
this._triggerOnStates = ""; this._triggerOnStates = "";
this._compoundLogic = "AND"; this._compoundLogic = "AND";
this._compoundConditions = []; this._compoundConditions = [];
@@ -1253,6 +1259,7 @@ export class MaintenanceTaskDialog extends LitElement {
data.last_performed = this._lastPerformed || null; data.last_performed = this._lastPerformed || null;
data.nfc_tag_id = this._nfcTagId || null; data.nfc_tag_id = this._nfcTagId || null;
data.require_tag_scan = this._requireTagScan; data.require_tag_scan = this._requireTagScan;
data.allow_skip = this._allowSkip;
data.reading_unit = this._readingUnit.trim() || null; data.reading_unit = this._readingUnit.trim() || null;
// Task phases (#139): always sent — null clears a removed cycle. // Task phases (#139): always sent — null clears a removed cycle.
{ {
@@ -1366,6 +1373,8 @@ export class MaintenanceTaskDialog extends LitElement {
if (this._triggerForMinutes) { const v = parseInt(this._triggerForMinutes, 10); if (!isNaN(v)) triggerConfig.trigger_for_minutes = v; } if (this._triggerForMinutes) { const v = parseInt(this._triggerForMinutes, 10); if (!isNaN(v)) triggerConfig.trigger_for_minutes = v; }
} else if (this._triggerType === "runtime") { } else if (this._triggerType === "runtime") {
if (this._triggerRuntimeHours) { const v = parseFloat(this._triggerRuntimeHours); if (!isNaN(v)) triggerConfig.trigger_runtime_hours = v; } if (this._triggerRuntimeHours) { const v = parseFloat(this._triggerRuntimeHours); if (!isNaN(v)) triggerConfig.trigger_runtime_hours = v; }
// #149: per-session cap (seconds) against sensors stuck ON.
if (this._triggerRuntimeMaxSession) { const v = parseInt(this._triggerRuntimeMaxSession, 10); if (!isNaN(v) && v > 0) triggerConfig.trigger_runtime_max_session_seconds = v; }
const onStates = this._triggerOnStates.split(",").map((s) => s.trim()).filter(Boolean); const onStates = this._triggerOnStates.split(",").map((s) => s.trim()).filter(Boolean);
if (onStates.length > 0) triggerConfig.trigger_on_states = onStates; if (onStates.length > 0) triggerConfig.trigger_on_states = onStates;
} }
@@ -2480,6 +2489,14 @@ export class MaintenanceTaskDialog extends LitElement {
.value=${this._triggerRuntimeHours} .value=${this._triggerRuntimeHours}
@input=${(e: Event) => (this._triggerRuntimeHours = (e.target as HTMLInputElement).value)} @input=${(e: Event) => (this._triggerRuntimeHours = (e.target as HTMLInputElement).value)}
></ms-textfield> ></ms-textfield>
<ms-textfield
label="${t("runtime_max_session", L)}"
type="number"
step="1"
.value=${this._triggerRuntimeMaxSession}
@input=${(e: Event) => (this._triggerRuntimeMaxSession = (e.target as HTMLInputElement).value)}
></ms-textfield>
<div class="field-help">${t("runtime_max_session_help", L)}</div>
${this._renderOnStatesField({ ${this._renderOnStatesField({
value: this._triggerOnStates, value: this._triggerOnStates,
entityId: this._triggerEntityId, entityId: this._triggerEntityId,
@@ -2831,6 +2848,15 @@ export class MaintenanceTaskDialog extends LitElement {
<span>${t("require_tag_scan", L)}</span> <span>${t("require_tag_scan", L)}</span>
</label> </label>
${this._requireTagScan ? html`<div class="field-help">${t("require_tag_scan_help", L)}</div>` : nothing} ${this._requireTagScan ? html`<div class="field-help">${t("require_tag_scan_help", L)}</div>` : nothing}
<label class="req-option">
<input
type="checkbox"
.checked=${!this._allowSkip}
@change=${(e: Event) => (this._allowSkip = !(e.target as HTMLInputElement).checked)}
/>
<span>${t("disallow_skip", L)}</span>
</label>
${!this._allowSkip ? html`<div class="field-help">${t("disallow_skip_help", L)}</div>` : nothing}
<label class="toggle-row"> <label class="toggle-row">
<input <input
type="checkbox" type="checkbox"
@@ -600,11 +600,15 @@ export class MaintenanceTaskQuickActionsDialog extends LitElement {
<ha-icon slot="start" icon="mdi:check"></ha-icon> <ha-icon slot="start" icon="mdi:check"></ha-icon>
${t("complete", L) || "Complete"} ${t("complete", L) || "Complete"}
</ha-button> </ha-button>
<ha-button appearance="plain" variant="neutral" @click=${() => { this._showSkip = true; }} .disabled=${this._busy}> ${task.allow_skip !== false
<ha-icon slot="start" icon="mdi:skip-next"></ha-icon> ? html`
${t("skip", L) || "Skip"} <ha-button appearance="outlined" variant="neutral" @click=${() => { this._showSkip = true; }} .disabled=${this._busy}>
</ha-button> <ha-icon slot="start" icon="mdi:skip-next"></ha-icon>
<ha-button appearance="plain" variant="neutral" @click=${() => { this._showReset = true; }} .disabled=${this._busy}> ${t("skip", L) || "Skip"}
</ha-button>
`
: nothing}
<ha-button appearance="outlined" variant="neutral" @click=${() => { this._showReset = true; }} .disabled=${this._busy}>
<ha-icon slot="start" icon="mdi:restart"></ha-icon> <ha-icon slot="start" icon="mdi:restart"></ha-icon>
${t("reset", L) || "Reset"} ${t("reset", L) || "Reset"}
</ha-button> </ha-button>
@@ -528,6 +528,7 @@
"groupby_area": "Podle oblasti", "groupby_area": "Podle oblasti",
"groupby_group": "Podle skupiny", "groupby_group": "Podle skupiny",
"groupby_user": "Podle uživatele", "groupby_user": "Podle uživatele",
"groupby_object": "Podle objektu",
"filter_label": "Filtr", "filter_label": "Filtr",
"user_label": "Uživatel", "user_label": "Uživatel",
"photo_label": "Fotografie", "photo_label": "Fotografie",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Aktuálně platná počáteční hodnota: {value}", "baseline_current_effective": "Aktuálně platná počáteční hodnota: {value}",
"runtime_on_states": "Aktivní stavy", "runtime_on_states": "Aktivní stavy",
"runtime_on_states_help": "Stavy počítané jako doba běhu — výchozí: on. Např. mowing, cleaning, printing. Při zvoleném atributu se porovnávají jeho hodnoty.", "runtime_on_states_help": "Stavy počítané jako doba běhu — výchozí: on. Např. mowing, cleaning, printing. Při zvoleném atributu se porovnávají jeho hodnoty.",
"runtime_max_session": "Max. doba běhu relace (sekundy)",
"runtime_max_session_help": "Jeden běh se počítá nejvýše na tolik sekund — chrání před senzorem zaseknutým na ZAP (ztráta spojení, restart). Prázdné = bez limitu.",
"trend_approaching": "Blíží se k prahu",
"trend_easing": "Vzdaluje se od prahu",
"split_select_hint": "Vyberte úkol a zde se zobrazí podrobnosti",
"setups_target_new": "Vytvořit nový: {name}", "setups_target_new": "Vytvořit nový: {name}",
"schedule_preview_title": "Nejbližší termíny", "schedule_preview_title": "Nejbližší termíny",
"schedule_preview_ontime": "Za předpokladu včasného dokončení.", "schedule_preview_ontime": "Za předpokladu včasného dokončení.",
@@ -927,5 +933,7 @@
"history_add_past": "Přidat dřívější dokončení", "history_add_past": "Přidat dřívější dokončení",
"require_tag_scan": "Dokončit pouze naskenováním štítku", "require_tag_scan": "Dokončit pouze naskenováním štítku",
"require_tag_scan_help": "Důkaz přítomnosti: „Hotovo“ je všude blokováno, dokud nenaskenujete NFC štítek nebo QR kód na zařízení. Automatizace mohou službě complete předat 'via_tag_scan'.", "require_tag_scan_help": "Důkaz přítomnosti: „Hotovo“ je všude blokováno, dokud nenaskenujete NFC štítek nebo QR kód na zařízení. Automatizace mohou službě complete předat 'via_tag_scan'.",
"disallow_skip": "Nepovolit přeskočení",
"disallow_skip_help": "Akce Přeskočit zmizí ze všech ploch a server odmítne přeskočení i z automatizací a hlasu.",
"require_tag_scan_hint": "Tento úkol lze dokončit pouze naskenováním jeho NFC štítku nebo QR kódu na zařízení — uložení zde bude odmítnuto." "require_tag_scan_hint": "Tento úkol lze dokončit pouze naskenováním jeho NFC štítku nebo QR kódu na zařízení — uložení zde bude odmítnuto."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Efter område", "groupby_area": "Efter område",
"groupby_group": "Efter gruppe", "groupby_group": "Efter gruppe",
"groupby_user": "Efter bruger", "groupby_user": "Efter bruger",
"groupby_object": "Efter objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Bruger", "user_label": "Bruger",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Aktuelt gældende startværdi: {value}", "baseline_current_effective": "Aktuelt gældende startværdi: {value}",
"runtime_on_states": "Aktive tilstande", "runtime_on_states": "Aktive tilstande",
"runtime_on_states_help": "Tilstande der tæller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med en valgt attribut sammenlignes dens værdier i stedet.", "runtime_on_states_help": "Tilstande der tæller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med en valgt attribut sammenlignes dens værdier i stedet.",
"runtime_max_session": "Maks. sessionstid (sekunder)",
"runtime_max_session_help": "En enkelt kørsel tæller højst så mange sekunder — beskytter mod en sensor, der hænger på TÆNDT (tabt forbindelse, genstart). Tom = ingen grænse.",
"trend_approaching": "Nærmer sig tærsklen",
"trend_easing": "Bevæger sig væk fra tærsklen",
"split_select_hint": "Vælg en opgave for at se detaljerne her",
"setups_target_new": "Opret ny: {name}", "setups_target_new": "Opret ny: {name}",
"schedule_preview_title": "Kommende datoer", "schedule_preview_title": "Kommende datoer",
"schedule_preview_ontime": "Forudsat rettidig fuldførelse.", "schedule_preview_ontime": "Forudsat rettidig fuldførelse.",
@@ -927,5 +933,7 @@
"history_add_past": "Tilføj tidligere udførelse", "history_add_past": "Tilføj tidligere udførelse",
"require_tag_scan": "Kan kun udføres ved tag-scanning", "require_tag_scan": "Kan kun udføres ved tag-scanning",
"require_tag_scan_help": "Tilstedeværelsesbevis: „Udført“ er blokeret overalt, indtil NFC-tagget eller QR-koden på selve tingen er scannet. Automatiseringer kan give 'via_tag_scan' til complete-tjenesten.", "require_tag_scan_help": "Tilstedeværelsesbevis: „Udført“ er blokeret overalt, indtil NFC-tagget eller QR-koden på selve tingen er scannet. Automatiseringer kan give 'via_tag_scan' til complete-tjenesten.",
"disallow_skip": "Tillad ikke at springe over",
"disallow_skip_help": "Handlingen Spring over forsvinder fra alle flader, og serveren afviser også spring fra automatiseringer og stemme.",
"require_tag_scan_hint": "Denne opgave udføres kun ved at scanne dens NFC-tag eller QR-kode på selve tingen — at gemme her vil blive afvist." "require_tag_scan_hint": "Denne opgave udføres kun ved at scanne dens NFC-tag eller QR-kode på selve tingen — at gemme her vil blive afvist."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Nach Bereich", "groupby_area": "Nach Bereich",
"groupby_group": "Nach Gruppe", "groupby_group": "Nach Gruppe",
"groupby_user": "Nach Verantwortlichem", "groupby_user": "Nach Verantwortlichem",
"groupby_object": "Nach Objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Benutzer", "user_label": "Benutzer",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Aktuell wirksamer Startwert: {value}", "baseline_current_effective": "Aktuell wirksamer Startwert: {value}",
"runtime_on_states": "Aktive Zustände", "runtime_on_states": "Aktive Zustände",
"runtime_on_states_help": "Zustände, die als Laufzeit zählen — Standard: on. Z. B. mowing, cleaning, printing. Bei gewähltem Attribut werden dessen Werte verglichen.", "runtime_on_states_help": "Zustände, die als Laufzeit zählen — Standard: on. Z. B. mowing, cleaning, printing. Bei gewähltem Attribut werden dessen Werte verglichen.",
"runtime_max_session": "Maximale Sitzungslaufzeit (Sekunden)",
"runtime_max_session_help": "Ein einzelner Lauf zählt höchstens so viele Sekunden — schützt vor Sensoren, die auf AN hängen bleiben (Verbindungsabriss, Neustart). Leer = keine Begrenzung.",
"trend_approaching": "Läuft auf die Schwelle zu",
"trend_easing": "Entfernt sich von der Schwelle",
"split_select_hint": "Wähle eine Aufgabe, um hier die Details zu sehen",
"setups_target_new": "Neu anlegen: {name}", "setups_target_new": "Neu anlegen: {name}",
"schedule_preview_title": "Nächste Termine", "schedule_preview_title": "Nächste Termine",
"schedule_preview_ontime": "Bei pünktlichem Abschluss.", "schedule_preview_ontime": "Bei pünktlichem Abschluss.",
@@ -927,5 +933,7 @@
"history_add_past": "Vergangene Erledigung nachtragen", "history_add_past": "Vergangene Erledigung nachtragen",
"require_tag_scan": "Nur per Tag-Scan abschließbar", "require_tag_scan": "Nur per Tag-Scan abschließbar",
"require_tag_scan_help": "Anwesenheitsnachweis: „Erledigt“ ist überall blockiert, bis das NFC-Tag oder der QR-Code am Gerät gescannt wurde. Automationen können 'via_tag_scan' an den complete-Dienst übergeben.", "require_tag_scan_help": "Anwesenheitsnachweis: „Erledigt“ ist überall blockiert, bis das NFC-Tag oder der QR-Code am Gerät gescannt wurde. Automationen können 'via_tag_scan' an den complete-Dienst übergeben.",
"disallow_skip": "Überspringen nicht erlauben",
"disallow_skip_help": "Die Aktion Überspringen verschwindet von allen Oberflächen; auch Automationen und Sprachbefehle werden abgewiesen.",
"require_tag_scan_hint": "Diese Aufgabe kann nur per Scan des NFC-Tags oder QR-Codes am Gerät erledigt werden — Speichern hier wird abgelehnt." "require_tag_scan_hint": "Diese Aufgabe kann nur per Scan des NFC-Tags oder QR-Codes am Gerät erledigt werden — Speichern hier wird abgelehnt."
} }
@@ -536,6 +536,7 @@
"groupby_area": "By area", "groupby_area": "By area",
"groupby_group": "By group", "groupby_group": "By group",
"groupby_user": "By user", "groupby_user": "By user",
"groupby_object": "By object",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "User", "user_label": "User",
"photo_label": "Photo", "photo_label": "Photo",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Currently effective start value: {value}", "baseline_current_effective": "Currently effective start value: {value}",
"runtime_on_states": "Active states", "runtime_on_states": "Active states",
"runtime_on_states_help": "States that count as running — default: on. E.g. mowing, cleaning, printing. With an attribute selected, its values are matched instead.", "runtime_on_states_help": "States that count as running — default: on. E.g. mowing, cleaning, printing. With an attribute selected, its values are matched instead.",
"runtime_max_session": "Max session runtime (seconds)",
"runtime_max_session_help": "A single run counts at most this many seconds — protects against a sensor stuck ON (lost connection, restart). Empty = no cap.",
"trend_approaching": "Heading toward the threshold",
"trend_easing": "Easing away from the threshold",
"split_select_hint": "Select a task to see its details here",
"setups_target_new": "Create new: {name}", "setups_target_new": "Create new: {name}",
"schedule_preview_title": "Next dates", "schedule_preview_title": "Next dates",
"schedule_preview_ontime": "Assuming on-time completion.", "schedule_preview_ontime": "Assuming on-time completion.",
@@ -927,5 +933,7 @@
"history_add_past": "Add past completion", "history_add_past": "Add past completion",
"require_tag_scan": "Only complete by scanning the tag", "require_tag_scan": "Only complete by scanning the tag",
"require_tag_scan_help": "Proof of presence: Done is blocked on every surface until the NFC tag or QR code on the thing itself is scanned. Automations can pass 'via_tag_scan' to the complete service.", "require_tag_scan_help": "Proof of presence: Done is blocked on every surface until the NFC tag or QR code on the thing itself is scanned. Automations can pass 'via_tag_scan' to the complete service.",
"disallow_skip": "Don't allow skipping",
"disallow_skip_help": "The Skip action disappears from every surface, and the server refuses a skip from automations and voice too.",
"require_tag_scan_hint": "This task completes only by scanning its NFC tag or QR code on the thing itself — saving here will be refused." "require_tag_scan_hint": "This task completes only by scanning its NFC tag or QR code on the thing itself — saving here will be refused."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Por área", "groupby_area": "Por área",
"groupby_group": "Por grupo", "groupby_group": "Por grupo",
"groupby_user": "Por usuario", "groupby_user": "Por usuario",
"groupby_object": "Por objeto",
"filter_label": "Filtro", "filter_label": "Filtro",
"user_label": "Usuario", "user_label": "Usuario",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valor inicial vigente: {value}", "baseline_current_effective": "Valor inicial vigente: {value}",
"runtime_on_states": "Estados activos", "runtime_on_states": "Estados activos",
"runtime_on_states_help": "Estados que cuentan como en funcionamiento — predeterminado: on. P. ej. mowing, cleaning, printing. Con un atributo seleccionado se comparan sus valores.", "runtime_on_states_help": "Estados que cuentan como en funcionamiento — predeterminado: on. P. ej. mowing, cleaning, printing. Con un atributo seleccionado se comparan sus valores.",
"runtime_max_session": "Duración máxima por sesión (segundos)",
"runtime_max_session_help": "Una sola ejecución cuenta como máximo estos segundos — protege contra un sensor atascado en ON (conexión perdida, reinicio). Vacío = sin límite.",
"trend_approaching": "Se acerca al umbral",
"trend_easing": "Se aleja del umbral",
"split_select_hint": "Selecciona una tarea para ver sus detalles aquí",
"setups_target_new": "Crear nuevo: {name}", "setups_target_new": "Crear nuevo: {name}",
"schedule_preview_title": "Próximas fechas", "schedule_preview_title": "Próximas fechas",
"schedule_preview_ontime": "Suponiendo finalización puntual.", "schedule_preview_ontime": "Suponiendo finalización puntual.",
@@ -927,5 +933,7 @@
"history_add_past": "Añadir una finalización pasada", "history_add_past": "Añadir una finalización pasada",
"require_tag_scan": "Completar solo escaneando la etiqueta", "require_tag_scan": "Completar solo escaneando la etiqueta",
"require_tag_scan_help": "Prueba de presencia: «Hecho» queda bloqueado en todas partes hasta escanear la etiqueta NFC o el código QR del propio objeto. Las automatizaciones pueden pasar 'via_tag_scan' al servicio complete.", "require_tag_scan_help": "Prueba de presencia: «Hecho» queda bloqueado en todas partes hasta escanear la etiqueta NFC o el código QR del propio objeto. Las automatizaciones pueden pasar 'via_tag_scan' al servicio complete.",
"disallow_skip": "No permitir omitir",
"disallow_skip_help": "La acción Omitir desaparece de todas las superficies y el servidor también rechaza omisiones desde automatizaciones y voz.",
"require_tag_scan_hint": "Esta tarea solo se completa escaneando su etiqueta NFC o código QR en el propio objeto; guardar aquí será rechazado." "require_tag_scan_hint": "Esta tarea solo se completa escaneando su etiqueta NFC o código QR en el propio objeto; guardar aquí será rechazado."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Alueen mukaan", "groupby_area": "Alueen mukaan",
"groupby_group": "Ryhmän mukaan", "groupby_group": "Ryhmän mukaan",
"groupby_user": "Käyttäjän mukaan", "groupby_user": "Käyttäjän mukaan",
"groupby_object": "Kohteen mukaan",
"filter_label": "Suodata", "filter_label": "Suodata",
"user_label": "Käyttäjä", "user_label": "Käyttäjä",
"photo_label": "Valokuva", "photo_label": "Valokuva",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Nyt voimassa oleva aloitusarvo: {value}", "baseline_current_effective": "Nyt voimassa oleva aloitusarvo: {value}",
"runtime_on_states": "Aktiiviset tilat", "runtime_on_states": "Aktiiviset tilat",
"runtime_on_states_help": "Tilat, jotka lasketaan käyntiajaksi — oletus: on. Esim. mowing, cleaning, printing. Jos attribuutti on valittu, verrataan sen arvoja.", "runtime_on_states_help": "Tilat, jotka lasketaan käyntiajaksi — oletus: on. Esim. mowing, cleaning, printing. Jos attribuutti on valittu, verrataan sen arvoja.",
"runtime_max_session": "Istunnon enimmäiskesto (sekuntia)",
"runtime_max_session_help": "Yksi ajo lasketaan enintään näin moneksi sekunniksi — suojaa PÄÄLLÄ-tilaan jumittuneelta anturilta (katkennut yhteys, uudelleenkäynnistys). Tyhjä = ei rajaa.",
"trend_approaching": "Lähestyy raja-arvoa",
"trend_easing": "Loittonee raja-arvosta",
"split_select_hint": "Valitse tehtävä nähdäksesi sen tiedot tässä",
"setups_target_new": "Luo uusi: {name}", "setups_target_new": "Luo uusi: {name}",
"schedule_preview_title": "Seuraavat päivämäärät", "schedule_preview_title": "Seuraavat päivämäärät",
"schedule_preview_ontime": "Olettaen, että valmistuminen on ajallaan.", "schedule_preview_ontime": "Olettaen, että valmistuminen on ajallaan.",
@@ -927,5 +933,7 @@
"history_add_past": "Lisää aiempi suoritus", "history_add_past": "Lisää aiempi suoritus",
"require_tag_scan": "Suoritus vain tunnisteen skannauksella", "require_tag_scan": "Suoritus vain tunnisteen skannauksella",
"require_tag_scan_help": "Läsnäolotodistus: ”Valmis” on estetty kaikkialla, kunnes laitteen NFC-tunniste tai QR-koodi on skannattu. Automaatiot voivat välittää 'via_tag_scan' complete-palvelulle.", "require_tag_scan_help": "Läsnäolotodistus: ”Valmis” on estetty kaikkialla, kunnes laitteen NFC-tunniste tai QR-koodi on skannattu. Automaatiot voivat välittää 'via_tag_scan' complete-palvelulle.",
"disallow_skip": "Estä ohittaminen",
"disallow_skip_help": "Ohita-toiminto katoaa kaikista näkymistä, ja palvelin hylkää ohituksen myös automaatioista ja puheesta.",
"require_tag_scan_hint": "Tämä tehtävä valmistuu vain skannaamalla sen NFC-tunniste tai QR-koodi itse laitteesta — tallennus tässä estetään." "require_tag_scan_hint": "Tämä tehtävä valmistuu vain skannaamalla sen NFC-tunniste tai QR-koodi itse laitteesta — tallennus tässä estetään."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Par zone", "groupby_area": "Par zone",
"groupby_group": "Par groupe", "groupby_group": "Par groupe",
"groupby_user": "Par utilisateur", "groupby_user": "Par utilisateur",
"groupby_object": "Par objet",
"filter_label": "Filtre", "filter_label": "Filtre",
"user_label": "Utilisateur", "user_label": "Utilisateur",
"photo_label": "Photo", "photo_label": "Photo",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valeur de départ actuellement en vigueur : {value}", "baseline_current_effective": "Valeur de départ actuellement en vigueur : {value}",
"runtime_on_states": "États actifs", "runtime_on_states": "États actifs",
"runtime_on_states_help": "États comptés comme en fonctionnement — par défaut : on. P. ex. mowing, cleaning, printing. Si un attribut est sélectionné, ce sont ses valeurs qui sont comparées.", "runtime_on_states_help": "États comptés comme en fonctionnement — par défaut : on. P. ex. mowing, cleaning, printing. Si un attribut est sélectionné, ce sont ses valeurs qui sont comparées.",
"runtime_max_session": "Durée max. par session (secondes)",
"runtime_max_session_help": "Une seule exécution compte au plus ce nombre de secondes — protège contre un capteur bloqué sur ON (connexion perdue, redémarrage). Vide = pas de limite.",
"trend_approaching": "Se rapproche du seuil",
"trend_easing": "S'éloigne du seuil",
"split_select_hint": "Sélectionnez une tâche pour voir ses détails ici",
"setups_target_new": "Créer : {name}", "setups_target_new": "Créer : {name}",
"schedule_preview_title": "Prochaines échéances", "schedule_preview_title": "Prochaines échéances",
"schedule_preview_ontime": "En supposant un achèvement ponctuel.", "schedule_preview_ontime": "En supposant un achèvement ponctuel.",
@@ -927,5 +933,7 @@
"history_add_past": "Ajouter une réalisation passée", "history_add_past": "Ajouter une réalisation passée",
"require_tag_scan": "Terminer uniquement en scannant le tag", "require_tag_scan": "Terminer uniquement en scannant le tag",
"require_tag_scan_help": "Preuve de présence : « Terminé » est bloqué partout tant que le tag NFC ou le QR code sur l'objet n'a pas été scanné. Les automatisations peuvent passer 'via_tag_scan' au service complete.", "require_tag_scan_help": "Preuve de présence : « Terminé » est bloqué partout tant que le tag NFC ou le QR code sur l'objet n'a pas été scanné. Les automatisations peuvent passer 'via_tag_scan' au service complete.",
"disallow_skip": "Ne pas autoriser à ignorer",
"disallow_skip_help": "L'action Ignorer disparaît de toutes les surfaces et le serveur refuse aussi un saut via les automatisations et la voix.",
"require_tag_scan_hint": "Cette tâche ne se termine qu'en scannant son tag NFC ou son QR code sur l'objet — l'enregistrement ici sera refusé." "require_tag_scan_hint": "Cette tâche ne se termine qu'en scannant son tag NFC ou son QR code sur l'objet — l'enregistrement ici sera refusé."
} }
@@ -530,6 +530,7 @@
"groupby_area": "क्षेत्र के अनुसार", "groupby_area": "क्षेत्र के अनुसार",
"groupby_group": "समूह के अनुसार", "groupby_group": "समूह के अनुसार",
"groupby_user": "उपयोगकर्ता के अनुसार", "groupby_user": "उपयोगकर्ता के अनुसार",
"groupby_object": "वस्तु के अनुसार",
"filter_label": "फ़िल्टर", "filter_label": "फ़िल्टर",
"user_label": "उपयोगकर्ता", "user_label": "उपयोगकर्ता",
"photo_label": "फ़ोटो", "photo_label": "फ़ोटो",
@@ -834,6 +835,11 @@
"baseline_current_effective": "वर्तमान में प्रभावी प्रारंभिक मान: {value}", "baseline_current_effective": "वर्तमान में प्रभावी प्रारंभिक मान: {value}",
"runtime_on_states": "सक्रिय अवस्थाएँ", "runtime_on_states": "सक्रिय अवस्थाएँ",
"runtime_on_states_help": "वे अवस्थाएँ जो चालू समय में गिनी जाती हैं — डिफ़ॉल्ट: on। जैसे mowing, cleaning, printing। विशेषता चुनी होने पर उसकी मानों की तुलना होती है।", "runtime_on_states_help": "वे अवस्थाएँ जो चालू समय में गिनी जाती हैं — डिफ़ॉल्ट: on। जैसे mowing, cleaning, printing। विशेषता चुनी होने पर उसकी मानों की तुलना होती है।",
"runtime_max_session": "प्रति सत्र अधिकतम रनटाइम (सेकंड)",
"runtime_max_session_help": "एक रन अधिकतम इतने सेकंड गिना जाता है — ON पर अटके सेंसर (कनेक्शन टूटना, रीस्टार्ट) से बचाता है। खाली = कोई सीमा नहीं।",
"trend_approaching": "सीमा की ओर बढ़ रहा है",
"trend_easing": "सीमा से दूर जा रहा है",
"split_select_hint": "विवरण यहाँ देखने के लिए कोई कार्य चुनें",
"setups_target_new": "नया बनाएँ: {name}", "setups_target_new": "नया बनाएँ: {name}",
"schedule_preview_title": "अगली तिथियाँ", "schedule_preview_title": "अगली तिथियाँ",
"schedule_preview_ontime": "समय पर पूर्णता मानते हुए।", "schedule_preview_ontime": "समय पर पूर्णता मानते हुए।",
@@ -927,5 +933,7 @@
"history_add_past": "पिछली पूर्णता जोड़ें", "history_add_past": "पिछली पूर्णता जोड़ें",
"require_tag_scan": "केवल टैग स्कैन से पूर्ण करें", "require_tag_scan": "केवल टैग स्कैन से पूर्ण करें",
"require_tag_scan_help": "उपस्थिति प्रमाण: जब तक वस्तु पर लगा NFC टैग या QR कोड स्कैन न हो, हर जगह “पूर्ण” अवरुद्ध रहता है। ऑटोमेशन complete सेवा को 'via_tag_scan' दे सकते हैं।", "require_tag_scan_help": "उपस्थिति प्रमाण: जब तक वस्तु पर लगा NFC टैग या QR कोड स्कैन न हो, हर जगह “पूर्ण” अवरुद्ध रहता है। ऑटोमेशन complete सेवा को 'via_tag_scan' दे सकते हैं।",
"disallow_skip": "छोड़ने की अनुमति न दें",
"disallow_skip_help": "छोड़ें क्रिया सभी सतहों से हट जाती है, और सर्वर ऑटोमेशन व वॉयस से छोड़ने को भी अस्वीकार करता है।",
"require_tag_scan_hint": "यह कार्य केवल वस्तु पर लगे NFC टैग या QR कोड को स्कैन करके ही पूर्ण होता है — यहाँ सहेजना अस्वीकार होगा।" "require_tag_scan_hint": "यह कार्य केवल वस्तु पर लगे NFC टैग या QR कोड को स्कैन करके ही पूर्ण होता है — यहाँ सहेजना अस्वीकार होगा।"
} }
@@ -536,6 +536,7 @@
"groupby_area": "Terület szerint", "groupby_area": "Terület szerint",
"groupby_group": "Csoport szerint", "groupby_group": "Csoport szerint",
"groupby_user": "Felhasználó szerint", "groupby_user": "Felhasználó szerint",
"groupby_object": "Objektum szerint",
"filter_label": "Szűrő", "filter_label": "Szűrő",
"user_label": "Felhasználó", "user_label": "Felhasználó",
"photo_label": "Fénykép", "photo_label": "Fénykép",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Jelenleg érvényes kezdőérték: {value}", "baseline_current_effective": "Jelenleg érvényes kezdőérték: {value}",
"runtime_on_states": "Aktív állapotok", "runtime_on_states": "Aktív állapotok",
"runtime_on_states_help": "Működésként számító állapotok — alapértelmezés: on. Pl. mowing, cleaning, printing. Attribútum kiválasztásakor annak értékei számítanak.", "runtime_on_states_help": "Működésként számító állapotok — alapértelmezés: on. Pl. mowing, cleaning, printing. Attribútum kiválasztásakor annak értékei számítanak.",
"runtime_max_session": "Max. munkamenet-futásidő (másodperc)",
"runtime_max_session_help": "Egy futás legfeljebb ennyi másodpercet számít — véd a BE állapotban beragadt érzékelő ellen (kapcsolatvesztés, újraindítás). Üres = nincs korlát.",
"trend_approaching": "Közeledik a küszöbhöz",
"trend_easing": "Távolodik a küszöbtől",
"split_select_hint": "Válassz egy feladatot, és itt jelennek meg a részletei",
"setups_target_new": "Új létrehozása: {name}", "setups_target_new": "Új létrehozása: {name}",
"schedule_preview_title": "Következő dátumok", "schedule_preview_title": "Következő dátumok",
"schedule_preview_ontime": "Időben történő elvégzést feltételezve.", "schedule_preview_ontime": "Időben történő elvégzést feltételezve.",
@@ -927,5 +933,7 @@
"history_add_past": "Korábbi elvégzés rögzítése", "history_add_past": "Korábbi elvégzés rögzítése",
"require_tag_scan": "Csak címke beolvasásával fejezhető be", "require_tag_scan": "Csak címke beolvasásával fejezhető be",
"require_tag_scan_help": "Jelenlét-igazolás: a „Kész” mindenhol blokkolva van, amíg be nem olvasod az eszközön lévő NFC-címkét vagy QR-kódot. Az automatizálások 'via_tag_scan' értéket adhatnak át a complete szolgáltatásnak.", "require_tag_scan_help": "Jelenlét-igazolás: a „Kész” mindenhol blokkolva van, amíg be nem olvasod az eszközön lévő NFC-címkét vagy QR-kódot. Az automatizálások 'via_tag_scan' értéket adhatnak át a complete szolgáltatásnak.",
"disallow_skip": "Kihagyás tiltása",
"disallow_skip_help": "A Kihagyás művelet minden felületről eltűnik, és a szerver az automatizálásokból és hangból érkező kihagyást is elutasítja.",
"require_tag_scan_hint": "Ez a feladat csak az eszközön lévő NFC-címke vagy QR-kód beolvasásával fejezhető be — az itteni mentés el lesz utasítva." "require_tag_scan_hint": "Ez a feladat csak az eszközön lévő NFC-címke vagy QR-kód beolvasásával fejezhető be — az itteni mentés el lesz utasítva."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Per area", "groupby_area": "Per area",
"groupby_group": "Per gruppo", "groupby_group": "Per gruppo",
"groupby_user": "Per utente", "groupby_user": "Per utente",
"groupby_object": "Per oggetto",
"filter_label": "Filtro", "filter_label": "Filtro",
"user_label": "Utente", "user_label": "Utente",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valore iniziale attualmente in vigore: {value}", "baseline_current_effective": "Valore iniziale attualmente in vigore: {value}",
"runtime_on_states": "Stati attivi", "runtime_on_states": "Stati attivi",
"runtime_on_states_help": "Stati che contano come in funzione — predefinito: on. Ad es. mowing, cleaning, printing. Con un attributo selezionato vengono confrontati i suoi valori.", "runtime_on_states_help": "Stati che contano come in funzione — predefinito: on. Ad es. mowing, cleaning, printing. Con un attributo selezionato vengono confrontati i suoi valori.",
"runtime_max_session": "Durata massima per sessione (secondi)",
"runtime_max_session_help": "Una singola esecuzione conta al massimo questi secondi — protegge da un sensore bloccato su ON (connessione persa, riavvio). Vuoto = nessun limite.",
"trend_approaching": "Si avvicina alla soglia",
"trend_easing": "Si allontana dalla soglia",
"split_select_hint": "Seleziona un'attività per vederne i dettagli qui",
"setups_target_new": "Crea nuovo: {name}", "setups_target_new": "Crea nuovo: {name}",
"schedule_preview_title": "Prossime date", "schedule_preview_title": "Prossime date",
"schedule_preview_ontime": "Presumendo un completamento puntuale.", "schedule_preview_ontime": "Presumendo un completamento puntuale.",
@@ -927,5 +933,7 @@
"history_add_past": "Aggiungi un completamento passato", "history_add_past": "Aggiungi un completamento passato",
"require_tag_scan": "Completa solo scansionando il tag", "require_tag_scan": "Completa solo scansionando il tag",
"require_tag_scan_help": "Prova di presenza: «Fatto» è bloccato ovunque finché non viene scansionato il tag NFC o il codice QR sull'oggetto. Le automazioni possono passare 'via_tag_scan' al servizio complete.", "require_tag_scan_help": "Prova di presenza: «Fatto» è bloccato ovunque finché non viene scansionato il tag NFC o il codice QR sull'oggetto. Le automazioni possono passare 'via_tag_scan' al servizio complete.",
"disallow_skip": "Non consentire di saltare",
"disallow_skip_help": "L'azione Salta scompare da tutte le superfici e il server rifiuta anche i salti da automazioni e voce.",
"require_tag_scan_hint": "Questa attività si completa solo scansionando il suo tag NFC o codice QR sull'oggetto — il salvataggio qui verrà rifiutato." "require_tag_scan_hint": "Questa attività si completa solo scansionando il suo tag NFC o codice QR sull'oggetto — il salvataggio qui verrà rifiutato."
} }
@@ -530,6 +530,7 @@
"groupby_area": "エリア別", "groupby_area": "エリア別",
"groupby_group": "グループ別", "groupby_group": "グループ別",
"groupby_user": "ユーザー別", "groupby_user": "ユーザー別",
"groupby_object": "対象別",
"filter_label": "絞り込み", "filter_label": "絞り込み",
"user_label": "ユーザー", "user_label": "ユーザー",
"photo_label": "写真", "photo_label": "写真",
@@ -834,6 +835,11 @@
"baseline_current_effective": "現在有効な開始値:{value}", "baseline_current_effective": "現在有効な開始値:{value}",
"runtime_on_states": "稼働中とみなす状態", "runtime_on_states": "稼働中とみなす状態",
"runtime_on_states_help": "稼働時間として数える状態 — 既定値:on。例:mowing, cleaning, printing。属性を選択している場合はその値が比較されます。", "runtime_on_states_help": "稼働時間として数える状態 — 既定値:on。例:mowing, cleaning, printing。属性を選択している場合はその値が比較されます。",
"runtime_max_session": "1回の最大稼働時間(秒)",
"runtime_max_session_help": "1回の稼働は最大この秒数までカウント——ONのまま固まったセンサー(接続切れ・再起動)への保護です。空欄=制限なし。",
"trend_approaching": "しきい値に近づいています",
"trend_easing": "しきい値から遠ざかっています",
"split_select_hint": "タスクを選択すると、ここに詳細が表示されます",
"setups_target_new": "新規作成:{name}", "setups_target_new": "新規作成:{name}",
"schedule_preview_title": "次回の予定日", "schedule_preview_title": "次回の予定日",
"schedule_preview_ontime": "期日どおりに完了した場合。", "schedule_preview_ontime": "期日どおりに完了した場合。",
@@ -927,5 +933,7 @@
"history_add_past": "過去の完了を追加", "history_add_past": "過去の完了を追加",
"require_tag_scan": "タグのスキャンでのみ完了可能", "require_tag_scan": "タグのスキャンでのみ完了可能",
"require_tag_scan_help": "在席証明:対象物のNFCタグまたはQRコードをスキャンするまで、どの画面でも「完了」はブロックされます。オートメーションはcompleteサービスに 'via_tag_scan' を渡せます。", "require_tag_scan_help": "在席証明:対象物のNFCタグまたはQRコードをスキャンするまで、どの画面でも「完了」はブロックされます。オートメーションはcompleteサービスに 'via_tag_scan' を渡せます。",
"disallow_skip": "スキップを許可しない",
"disallow_skip_help": "スキップ操作はすべての画面から消え、オートメーションや音声からのスキップもサーバーが拒否します。",
"require_tag_scan_hint": "このタスクは対象物のNFCタグまたはQRコードをスキャンしないと完了できません。ここでの保存は拒否されます。" "require_tag_scan_hint": "このタスクは対象物のNFCタグまたはQRコードをスキャンしないと完了できません。ここでの保存は拒否されます。"
} }
@@ -536,6 +536,7 @@
"groupby_area": "구역별", "groupby_area": "구역별",
"groupby_group": "그룹별", "groupby_group": "그룹별",
"groupby_user": "사용자별", "groupby_user": "사용자별",
"groupby_object": "대상별",
"filter_label": "필터", "filter_label": "필터",
"user_label": "사용자", "user_label": "사용자",
"photo_label": "사진", "photo_label": "사진",
@@ -834,6 +835,11 @@
"baseline_current_effective": "현재 적용 중인 시작 값: {value}", "baseline_current_effective": "현재 적용 중인 시작 값: {value}",
"runtime_on_states": "활성 상태", "runtime_on_states": "활성 상태",
"runtime_on_states_help": "가동 중으로 계산할 상태입니다 — 기본값: on. 예: mowing, cleaning, printing. 속성을 선택한 경우 해당 속성 값과 비교합니다.", "runtime_on_states_help": "가동 중으로 계산할 상태입니다 — 기본값: on. 예: mowing, cleaning, printing. 속성을 선택한 경우 해당 속성 값과 비교합니다.",
"runtime_max_session": "세션당 최대 가동 시간(초)",
"runtime_max_session_help": "한 번의 가동은 최대 이 초까지만 집계됩니다 — ON에 멈춘 센서(연결 끊김, 재시작)로부터 보호합니다. 비워두면 제한 없음.",
"trend_approaching": "임계값에 가까워지는 중",
"trend_easing": "임계값에서 멀어지는 중",
"split_select_hint": "작업을 선택하면 여기에 세부 정보가 표시됩니다",
"setups_target_new": "새로 만들기: {name}", "setups_target_new": "새로 만들기: {name}",
"schedule_preview_title": "다음 예정일", "schedule_preview_title": "다음 예정일",
"schedule_preview_ontime": "제때 완료한다고 가정한 일정입니다.", "schedule_preview_ontime": "제때 완료한다고 가정한 일정입니다.",
@@ -927,5 +933,7 @@
"history_add_past": "지난 완료 추가", "history_add_past": "지난 완료 추가",
"require_tag_scan": "태그 스캔으로만 완료 가능", "require_tag_scan": "태그 스캔으로만 완료 가능",
"require_tag_scan_help": "현장 확인: 기기의 NFC 태그나 QR 코드를 스캔할 때까지 모든 화면에서 '완료'가 차단됩니다. 자동화는 complete 서비스에 'via_tag_scan'을 전달할 수 있습니다.", "require_tag_scan_help": "현장 확인: 기기의 NFC 태그나 QR 코드를 스캔할 때까지 모든 화면에서 '완료'가 차단됩니다. 자동화는 complete 서비스에 'via_tag_scan'을 전달할 수 있습니다.",
"disallow_skip": "건너뛰기 허용 안 함",
"disallow_skip_help": "건너뛰기 동작이 모든 화면에서 사라지며, 서버는 자동화와 음성의 건너뛰기도 거부합니다.",
"require_tag_scan_hint": "이 작업은 기기의 NFC 태그나 QR 코드를 스캔해야만 완료됩니다. 여기서 저장하면 거부됩니다." "require_tag_scan_hint": "이 작업은 기기의 NFC 태그나 QR 코드를 스캔해야만 완료됩니다. 여기서 저장하면 거부됩니다."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Etter område", "groupby_area": "Etter område",
"groupby_group": "Etter gruppe", "groupby_group": "Etter gruppe",
"groupby_user": "Etter bruker", "groupby_user": "Etter bruker",
"groupby_object": "Etter objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Bruker", "user_label": "Bruker",
"photo_label": "Bilde", "photo_label": "Bilde",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Gjeldende startverdi: {value}", "baseline_current_effective": "Gjeldende startverdi: {value}",
"runtime_on_states": "Aktive tilstander", "runtime_on_states": "Aktive tilstander",
"runtime_on_states_help": "Tilstander som teller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med et valgt attributt sammenlignes verdiene dets i stedet.", "runtime_on_states_help": "Tilstander som teller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med et valgt attributt sammenlignes verdiene dets i stedet.",
"runtime_max_session": "Maks økt-varighet (sekunder)",
"runtime_max_session_help": "En enkelt kjøring teller høyst så mange sekunder — beskytter mot en sensor som henger på PÅ (mistet forbindelse, omstart). Tom = ingen grense.",
"trend_approaching": "Nærmer seg terskelen",
"trend_easing": "Beveger seg bort fra terskelen",
"split_select_hint": "Velg en oppgave for å se detaljene her",
"setups_target_new": "Opprett ny: {name}", "setups_target_new": "Opprett ny: {name}",
"schedule_preview_title": "Kommende datoer", "schedule_preview_title": "Kommende datoer",
"schedule_preview_ontime": "Forutsatt fullføring i tide.", "schedule_preview_ontime": "Forutsatt fullføring i tide.",
@@ -927,5 +933,7 @@
"history_add_past": "Legg til tidligere fullføring", "history_add_past": "Legg til tidligere fullføring",
"require_tag_scan": "Kan bare fullføres ved tag-skanning", "require_tag_scan": "Kan bare fullføres ved tag-skanning",
"require_tag_scan_help": "Tilstedeværelsesbevis: «Fullført» er blokkert overalt til NFC-taggen eller QR-koden på selve tingen er skannet. Automatiseringer kan sende 'via_tag_scan' til complete-tjenesten.", "require_tag_scan_help": "Tilstedeværelsesbevis: «Fullført» er blokkert overalt til NFC-taggen eller QR-koden på selve tingen er skannet. Automatiseringer kan sende 'via_tag_scan' til complete-tjenesten.",
"disallow_skip": "Ikke tillat å hoppe over",
"disallow_skip_help": "Handlingen Hopp over forsvinner fra alle flater, og serveren avviser også hopp fra automatiseringer og tale.",
"require_tag_scan_hint": "Denne oppgaven fullføres bare ved å skanne NFC-taggen eller QR-koden på selve tingen — lagring her vil bli avvist." "require_tag_scan_hint": "Denne oppgaven fullføres bare ved å skanne NFC-taggen eller QR-koden på selve tingen — lagring her vil bli avvist."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Per gebied", "groupby_area": "Per gebied",
"groupby_group": "Per groep", "groupby_group": "Per groep",
"groupby_user": "Per gebruiker", "groupby_user": "Per gebruiker",
"groupby_object": "Per object",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Gebruiker", "user_label": "Gebruiker",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Momenteel geldende startwaarde: {value}", "baseline_current_effective": "Momenteel geldende startwaarde: {value}",
"runtime_on_states": "Actieve statussen", "runtime_on_states": "Actieve statussen",
"runtime_on_states_help": "Statussen die als draaitijd tellen — standaard: on. Bijv. mowing, cleaning, printing. Met een geselecteerd attribuut worden de waarden daarvan vergeleken.", "runtime_on_states_help": "Statussen die als draaitijd tellen — standaard: on. Bijv. mowing, cleaning, printing. Met een geselecteerd attribuut worden de waarden daarvan vergeleken.",
"runtime_max_session": "Maximale sessieduur (seconden)",
"runtime_max_session_help": "Eén run telt maximaal dit aantal seconden — beschermt tegen sensoren die op AAN blijven hangen (verbroken verbinding, herstart). Leeg = geen limiet.",
"trend_approaching": "Beweegt richting de drempel",
"trend_easing": "Beweegt weg van de drempel",
"split_select_hint": "Selecteer een taak om hier de details te zien",
"setups_target_new": "Nieuw aanmaken: {name}", "setups_target_new": "Nieuw aanmaken: {name}",
"schedule_preview_title": "Volgende data", "schedule_preview_title": "Volgende data",
"schedule_preview_ontime": "Uitgaande van tijdige afronding.", "schedule_preview_ontime": "Uitgaande van tijdige afronding.",
@@ -927,5 +933,7 @@
"history_add_past": "Eerdere afronding toevoegen", "history_add_past": "Eerdere afronding toevoegen",
"require_tag_scan": "Alleen af te ronden via tag-scan", "require_tag_scan": "Alleen af te ronden via tag-scan",
"require_tag_scan_help": "Aanwezigheidsbewijs: „Klaar” is overal geblokkeerd totdat de NFC-tag of QR-code op het apparaat zelf is gescand. Automatiseringen kunnen 'via_tag_scan' aan de complete-service meegeven.", "require_tag_scan_help": "Aanwezigheidsbewijs: „Klaar” is overal geblokkeerd totdat de NFC-tag of QR-code op het apparaat zelf is gescand. Automatiseringen kunnen 'via_tag_scan' aan de complete-service meegeven.",
"disallow_skip": "Overslaan niet toestaan",
"disallow_skip_help": "De actie Overslaan verdwijnt overal, en de server weigert ook een skip via automatiseringen en spraak.",
"require_tag_scan_hint": "Deze taak wordt alleen afgerond door de NFC-tag of QR-code op het apparaat te scannen — opslaan hier wordt geweigerd." "require_tag_scan_hint": "Deze taak wordt alleen afgerond door de NFC-tag of QR-code op het apparaat te scannen — opslaan hier wordt geweigerd."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Wg obszaru", "groupby_area": "Wg obszaru",
"groupby_group": "Wg grupy", "groupby_group": "Wg grupy",
"groupby_user": "Wg użytkownika", "groupby_user": "Wg użytkownika",
"groupby_object": "Według obiektu",
"filter_label": "Filtr", "filter_label": "Filtr",
"user_label": "Użytkownik", "user_label": "Użytkownik",
"photo_label": "Zdjęcie", "photo_label": "Zdjęcie",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Obecnie obowiązująca wartość początkowa: {value}", "baseline_current_effective": "Obecnie obowiązująca wartość początkowa: {value}",
"runtime_on_states": "Stany aktywne", "runtime_on_states": "Stany aktywne",
"runtime_on_states_help": "Stany liczone jako czas pracy — domyślnie: on. Np. mowing, cleaning, printing. Przy wybranym atrybucie porównywane są jego wartości.", "runtime_on_states_help": "Stany liczone jako czas pracy — domyślnie: on. Np. mowing, cleaning, printing. Przy wybranym atrybucie porównywane są jego wartości.",
"runtime_max_session": "Maks. czas sesji (sekundy)",
"runtime_max_session_help": "Pojedynczy przebieg liczy się najwyżej tyle sekund — chroni przed czujnikiem zawieszonym na WŁ. (utrata połączenia, restart). Puste = bez limitu.",
"trend_approaching": "Zbliża się do progu",
"trend_easing": "Oddala się od progu",
"split_select_hint": "Wybierz zadanie, aby zobaczyć tutaj szczegóły",
"setups_target_new": "Utwórz nowy: {name}", "setups_target_new": "Utwórz nowy: {name}",
"schedule_preview_title": "Najbliższe terminy", "schedule_preview_title": "Najbliższe terminy",
"schedule_preview_ontime": "Przy założeniu terminowego ukończenia.", "schedule_preview_ontime": "Przy założeniu terminowego ukończenia.",
@@ -927,5 +933,7 @@
"history_add_past": "Dodaj wcześniejsze ukończenie", "history_add_past": "Dodaj wcześniejsze ukończenie",
"require_tag_scan": "Ukończenie tylko przez skan tagu", "require_tag_scan": "Ukończenie tylko przez skan tagu",
"require_tag_scan_help": "Dowód obecności: „Gotowe” jest wszędzie zablokowane, dopóki nie zeskanujesz tagu NFC lub kodu QR na urządzeniu. Automatyzacje mogą przekazać 'via_tag_scan' do usługi complete.", "require_tag_scan_help": "Dowód obecności: „Gotowe” jest wszędzie zablokowane, dopóki nie zeskanujesz tagu NFC lub kodu QR na urządzeniu. Automatyzacje mogą przekazać 'via_tag_scan' do usługi complete.",
"disallow_skip": "Nie zezwalaj na pomijanie",
"disallow_skip_help": "Akcja Pomiń znika ze wszystkich widoków, a serwer odrzuca pominięcie także z automatyzacji i głosu.",
"require_tag_scan_hint": "To zadanie można ukończyć tylko skanując jego tag NFC lub kod QR na urządzeniu — zapis tutaj zostanie odrzucony." "require_tag_scan_hint": "To zadanie można ukończyć tylko skanując jego tag NFC lub kod QR na urządzeniu — zapis tutaj zostanie odrzucony."
} }
@@ -536,6 +536,7 @@
"groupby_area": "Por área", "groupby_area": "Por área",
"groupby_group": "Por grupo", "groupby_group": "Por grupo",
"groupby_user": "Por usuário", "groupby_user": "Por usuário",
"groupby_object": "Por objeto",
"filter_label": "Filtro", "filter_label": "Filtro",
"user_label": "Usuário", "user_label": "Usuário",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valor inicial efetivo atual: {value}", "baseline_current_effective": "Valor inicial efetivo atual: {value}",
"runtime_on_states": "Estados ativos", "runtime_on_states": "Estados ativos",
"runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. Ex.: mowing, cleaning, printing. Com um atributo selecionado, os valores dele são comparados.", "runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. Ex.: mowing, cleaning, printing. Com um atributo selecionado, os valores dele são comparados.",
"runtime_max_session": "Duração máxima por sessão (segundos)",
"runtime_max_session_help": "Uma única execução conta no máximo esses segundos — protege contra um sensor travado em ON (conexão perdida, reinício). Vazio = sem limite.",
"trend_approaching": "Aproximando-se do limite",
"trend_easing": "Afastando-se do limite",
"split_select_hint": "Selecione uma tarefa para ver os detalhes aqui",
"setups_target_new": "Criar novo: {name}", "setups_target_new": "Criar novo: {name}",
"schedule_preview_title": "Próximas datas", "schedule_preview_title": "Próximas datas",
"schedule_preview_ontime": "Supondo conclusão em dia.", "schedule_preview_ontime": "Supondo conclusão em dia.",
@@ -927,5 +933,7 @@
"history_add_past": "Adicionar conclusão passada", "history_add_past": "Adicionar conclusão passada",
"require_tag_scan": "Concluir apenas escaneando a etiqueta", "require_tag_scan": "Concluir apenas escaneando a etiqueta",
"require_tag_scan_help": "Prova de presença: “Concluído” fica bloqueado em toda parte até escanear a etiqueta NFC ou o código QR no próprio objeto. Automações podem passar 'via_tag_scan' ao serviço complete.", "require_tag_scan_help": "Prova de presença: “Concluído” fica bloqueado em toda parte até escanear a etiqueta NFC ou o código QR no próprio objeto. Automações podem passar 'via_tag_scan' ao serviço complete.",
"disallow_skip": "Não permitir pular",
"disallow_skip_help": "A ação Pular desaparece de todas as telas e o servidor também recusa pular via automações e voz.",
"require_tag_scan_hint": "Esta tarefa só é concluída escaneando sua etiqueta NFC ou código QR no próprio objeto — salvar aqui será recusado." "require_tag_scan_hint": "Esta tarefa só é concluída escaneando sua etiqueta NFC ou código QR no próprio objeto — salvar aqui será recusado."
} }
@@ -573,6 +573,7 @@
"groupby_area": "Por área", "groupby_area": "Por área",
"groupby_group": "Por grupo", "groupby_group": "Por grupo",
"groupby_user": "Por usuário", "groupby_user": "Por usuário",
"groupby_object": "Por objeto",
"unassigned": "Não atribuído", "unassigned": "Não atribuído",
"no_area": "Sem área", "no_area": "Sem área",
"has_overdue": "Tarefas em atraso", "has_overdue": "Tarefas em atraso",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valor inicial atualmente em vigor: {value}", "baseline_current_effective": "Valor inicial atualmente em vigor: {value}",
"runtime_on_states": "Estados ativos", "runtime_on_states": "Estados ativos",
"runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. P. ex. mowing, cleaning, printing. Com um atributo selecionado, são comparados os valores dele.", "runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. P. ex. mowing, cleaning, printing. Com um atributo selecionado, são comparados os valores dele.",
"runtime_max_session": "Duração máxima por sessão (segundos)",
"runtime_max_session_help": "Uma única execução conta no máximo estes segundos — protege contra um sensor preso em ON (ligação perdida, reinício). Vazio = sem limite.",
"trend_approaching": "A aproximar-se do limiar",
"trend_easing": "A afastar-se do limiar",
"split_select_hint": "Selecione uma tarefa para ver os detalhes aqui",
"setups_target_new": "Criar novo: {name}", "setups_target_new": "Criar novo: {name}",
"schedule_preview_title": "Próximas datas", "schedule_preview_title": "Próximas datas",
"schedule_preview_ontime": "Assumindo conclusão pontual.", "schedule_preview_ontime": "Assumindo conclusão pontual.",
@@ -927,5 +933,7 @@
"history_add_past": "Adicionar conclusão passada", "history_add_past": "Adicionar conclusão passada",
"require_tag_scan": "Concluir apenas lendo a etiqueta", "require_tag_scan": "Concluir apenas lendo a etiqueta",
"require_tag_scan_help": "Prova de presença: «Concluído» fica bloqueado em todo o lado até ler a etiqueta NFC ou o código QR no próprio objeto. As automações podem passar 'via_tag_scan' ao serviço complete.", "require_tag_scan_help": "Prova de presença: «Concluído» fica bloqueado em todo o lado até ler a etiqueta NFC ou o código QR no próprio objeto. As automações podem passar 'via_tag_scan' ao serviço complete.",
"disallow_skip": "Não permitir ignorar",
"disallow_skip_help": "A ação Ignorar desaparece de todas as superfícies e o servidor também recusa ignorar via automações e voz.",
"require_tag_scan_hint": "Esta tarefa só é concluída lendo a sua etiqueta NFC ou código QR no próprio objeto — guardar aqui será recusado." "require_tag_scan_hint": "Esta tarefa só é concluída lendo a sua etiqueta NFC ou código QR no próprio objeto — guardar aqui será recusado."
} }
@@ -528,6 +528,7 @@
"groupby_area": "По области", "groupby_area": "По области",
"groupby_group": "По группе", "groupby_group": "По группе",
"groupby_user": "По пользователю", "groupby_user": "По пользователю",
"groupby_object": "По объекту",
"filter_label": "Фильтр", "filter_label": "Фильтр",
"user_label": "Пользователь", "user_label": "Пользователь",
"photo_label": "Фото", "photo_label": "Фото",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Действующее начальное значение: {value}", "baseline_current_effective": "Действующее начальное значение: {value}",
"runtime_on_states": "Активные состояния", "runtime_on_states": "Активные состояния",
"runtime_on_states_help": "Состояния, засчитываемые как работа — по умолчанию: on. Напр. mowing, cleaning, printing. Если выбран атрибут, сравниваются его значения.", "runtime_on_states_help": "Состояния, засчитываемые как работа — по умолчанию: on. Напр. mowing, cleaning, printing. Если выбран атрибут, сравниваются его значения.",
"runtime_max_session": "Макс. время сеанса (секунды)",
"runtime_max_session_help": "Один запуск засчитывается не более чем на столько секунд — защита от датчика, зависшего во включённом состоянии (обрыв связи, перезапуск). Пусто = без ограничения.",
"trend_approaching": "Приближается к порогу",
"trend_easing": "Отдаляется от порога",
"split_select_hint": "Выберите задачу, чтобы увидеть здесь её детали",
"setups_target_new": "Создать новый: {name}", "setups_target_new": "Создать новый: {name}",
"schedule_preview_title": "Ближайшие даты", "schedule_preview_title": "Ближайшие даты",
"schedule_preview_ontime": "При условии своевременного выполнения.", "schedule_preview_ontime": "При условии своевременного выполнения.",
@@ -927,5 +933,7 @@
"history_add_past": "Добавить прошлое выполнение", "history_add_past": "Добавить прошлое выполнение",
"require_tag_scan": "Завершение только по скану метки", "require_tag_scan": "Завершение только по скану метки",
"require_tag_scan_help": "Подтверждение присутствия: «Готово» заблокировано везде, пока не отсканирована NFC-метка или QR-код на самом устройстве. Автоматизации могут передавать 'via_tag_scan' в службу complete.", "require_tag_scan_help": "Подтверждение присутствия: «Готово» заблокировано везде, пока не отсканирована NFC-метка или QR-код на самом устройстве. Автоматизации могут передавать 'via_tag_scan' в службу complete.",
"disallow_skip": "Запретить пропуск",
"disallow_skip_help": "Действие «Пропустить» исчезает со всех экранов, а сервер отклоняет пропуск из автоматизаций и голосовых команд.",
"require_tag_scan_hint": "Эта задача завершается только сканированием её NFC-метки или QR-кода на самом устройстве — сохранение здесь будет отклонено." "require_tag_scan_hint": "Эта задача завершается только сканированием её NFC-метки или QR-кода на самом устройстве — сохранение здесь будет отклонено."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Per område", "groupby_area": "Per område",
"groupby_group": "Per grupp", "groupby_group": "Per grupp",
"groupby_user": "Per användare", "groupby_user": "Per användare",
"groupby_object": "Efter objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Användare", "user_label": "Användare",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Nu gällande startvärde: {value}", "baseline_current_effective": "Nu gällande startvärde: {value}",
"runtime_on_states": "Aktiva tillstånd", "runtime_on_states": "Aktiva tillstånd",
"runtime_on_states_help": "Tillstånd som räknas som drifttid — standard: on. T.ex. mowing, cleaning, printing. Med ett valt attribut jämförs dess värden i stället.", "runtime_on_states_help": "Tillstånd som räknas som drifttid — standard: on. T.ex. mowing, cleaning, printing. Med ett valt attribut jämförs dess värden i stället.",
"runtime_max_session": "Max körtid per session (sekunder)",
"runtime_max_session_help": "En enskild körning räknas som högst så här många sekunder — skyddar mot en sensor som fastnat på PÅ (tappad anslutning, omstart). Tomt = ingen gräns.",
"trend_approaching": "Närmar sig tröskeln",
"trend_easing": "Rör sig bort från tröskeln",
"split_select_hint": "Välj en uppgift för att se detaljerna här",
"setups_target_new": "Skapa ny: {name}", "setups_target_new": "Skapa ny: {name}",
"schedule_preview_title": "Kommande datum", "schedule_preview_title": "Kommande datum",
"schedule_preview_ontime": "Förutsatt slutförande i tid.", "schedule_preview_ontime": "Förutsatt slutförande i tid.",
@@ -927,5 +933,7 @@
"history_add_past": "Lägg till tidigare slutförande", "history_add_past": "Lägg till tidigare slutförande",
"require_tag_scan": "Kan endast slutföras via tagg-skanning", "require_tag_scan": "Kan endast slutföras via tagg-skanning",
"require_tag_scan_help": "Närvarobevis: ”Klar” är blockerad överallt tills NFC-taggen eller QR-koden på själva saken har skannats. Automationer kan skicka 'via_tag_scan' till complete-tjänsten.", "require_tag_scan_help": "Närvarobevis: ”Klar” är blockerad överallt tills NFC-taggen eller QR-koden på själva saken har skannats. Automationer kan skicka 'via_tag_scan' till complete-tjänsten.",
"disallow_skip": "Tillåt inte att hoppa över",
"disallow_skip_help": "Åtgärden Hoppa över försvinner från alla ytor och servern nekar även hopp från automationer och röst.",
"require_tag_scan_hint": "Den här uppgiften slutförs endast genom att skanna dess NFC-tagg eller QR-kod på själva saken — att spara här kommer att nekas." "require_tag_scan_hint": "Den här uppgiften slutförs endast genom att skanna dess NFC-tagg eller QR-kod på själva saken — att spara här kommer att nekas."
} }
@@ -536,6 +536,7 @@
"groupby_area": "Alana göre", "groupby_area": "Alana göre",
"groupby_group": "Gruba göre", "groupby_group": "Gruba göre",
"groupby_user": "Kullanıcıya göre", "groupby_user": "Kullanıcıya göre",
"groupby_object": "Nesneye göre",
"filter_label": "Filtre", "filter_label": "Filtre",
"user_label": "Kullanıcı", "user_label": "Kullanıcı",
"photo_label": "Fotoğraf", "photo_label": "Fotoğraf",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Şu anda geçerli başlangıç değeri: {value}", "baseline_current_effective": "Şu anda geçerli başlangıç değeri: {value}",
"runtime_on_states": "Etkin durumlar", "runtime_on_states": "Etkin durumlar",
"runtime_on_states_help": "Çalışıyor sayılan durumlar — varsayılan: on. Örn. mowing, cleaning, printing. Bir öznitelik seçiliyse onun değerleri eşleştirilir.", "runtime_on_states_help": "Çalışıyor sayılan durumlar — varsayılan: on. Örn. mowing, cleaning, printing. Bir öznitelik seçiliyse onun değerleri eşleştirilir.",
"runtime_max_session": "Oturum başına azami çalışma süresi (saniye)",
"runtime_max_session_help": "Tek bir çalışma en fazla bu kadar saniye sayılır — AÇIK durumda takılı kalan sensöre (bağlantı kopması, yeniden başlatma) karşı korur. Boş = sınır yok.",
"trend_approaching": "Eşiğe yaklaşıyor",
"trend_easing": "Eşikten uzaklaşıyor",
"split_select_hint": "Ayrıntıları burada görmek için bir görev seçin",
"setups_target_new": "Yeni oluştur: {name}", "setups_target_new": "Yeni oluştur: {name}",
"schedule_preview_title": "Sonraki tarihler", "schedule_preview_title": "Sonraki tarihler",
"schedule_preview_ontime": "Zamanında tamamlama varsayılarak.", "schedule_preview_ontime": "Zamanında tamamlama varsayılarak.",
@@ -927,5 +933,7 @@
"history_add_past": "Geçmiş tamamlama ekle", "history_add_past": "Geçmiş tamamlama ekle",
"require_tag_scan": "Yalnızca etiket taranarak tamamlanır", "require_tag_scan": "Yalnızca etiket taranarak tamamlanır",
"require_tag_scan_help": "Yerinde olma kanıtı: Cihazın üzerindeki NFC etiketi veya QR kodu taranana kadar 'Tamamlandı' her yerde engellenir. Otomasyonlar complete servisine 'via_tag_scan' iletebilir.", "require_tag_scan_help": "Yerinde olma kanıtı: Cihazın üzerindeki NFC etiketi veya QR kodu taranana kadar 'Tamamlandı' her yerde engellenir. Otomasyonlar complete servisine 'via_tag_scan' iletebilir.",
"disallow_skip": "Atlamaya izin verme",
"disallow_skip_help": "Atla eylemi tüm yüzeylerden kaybolur; sunucu otomasyonlardan ve sesten gelen atlamayı da reddeder.",
"require_tag_scan_hint": "Bu görev yalnızca cihazın üzerindeki NFC etiketi veya QR kodu taranarak tamamlanır — buradan kaydetme reddedilecektir." "require_tag_scan_hint": "Bu görev yalnızca cihazın üzerindeki NFC etiketi veya QR kodu taranarak tamamlanır — buradan kaydetme reddedilecektir."
} }
@@ -528,6 +528,7 @@
"groupby_area": "За зоною", "groupby_area": "За зоною",
"groupby_group": "За групою", "groupby_group": "За групою",
"groupby_user": "За користувачем", "groupby_user": "За користувачем",
"groupby_object": "За об'єктом",
"filter_label": "Фільтр", "filter_label": "Фільтр",
"user_label": "Користувач", "user_label": "Користувач",
"photo_label": "Фото", "photo_label": "Фото",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Чинне початкове значення: {value}", "baseline_current_effective": "Чинне початкове значення: {value}",
"runtime_on_states": "Активні стани", "runtime_on_states": "Активні стани",
"runtime_on_states_help": "Стани, що зараховуються як робота — типово: on. Напр. mowing, cleaning, printing. Якщо вибрано атрибут, порівнюються його значення.", "runtime_on_states_help": "Стани, що зараховуються як робота — типово: on. Напр. mowing, cleaning, printing. Якщо вибрано атрибут, порівнюються його значення.",
"runtime_max_session": "Макс. час сеансу (секунди)",
"runtime_max_session_help": "Один запуск зараховується щонайбільше на стільки секунд — захист від датчика, що завис в увімкненому стані (втрата зв'язку, перезапуск). Порожньо = без обмеження.",
"trend_approaching": "Наближається до порога",
"trend_easing": "Віддаляється від порога",
"split_select_hint": "Виберіть завдання, щоб побачити тут його деталі",
"setups_target_new": "Створити новий: {name}", "setups_target_new": "Створити новий: {name}",
"schedule_preview_title": "Найближчі дати", "schedule_preview_title": "Найближчі дати",
"schedule_preview_ontime": "За умови вчасного виконання.", "schedule_preview_ontime": "За умови вчасного виконання.",
@@ -927,5 +933,7 @@
"history_add_past": "Додати минуле виконання", "history_add_past": "Додати минуле виконання",
"require_tag_scan": "Завершення лише скануванням мітки", "require_tag_scan": "Завершення лише скануванням мітки",
"require_tag_scan_help": "Підтвердження присутності: «Готово» заблоковано всюди, доки не відскановано NFC-мітку або QR-код на самому пристрої. Автоматизації можуть передати 'via_tag_scan' службі complete.", "require_tag_scan_help": "Підтвердження присутності: «Готово» заблоковано всюди, доки не відскановано NFC-мітку або QR-код на самому пристрої. Автоматизації можуть передати 'via_tag_scan' службі complete.",
"disallow_skip": "Заборонити пропуск",
"disallow_skip_help": "Дія «Пропустити» зникає з усіх поверхонь, а сервер відхиляє пропуск з автоматизацій і голосу.",
"require_tag_scan_hint": "Це завдання завершується лише скануванням його NFC-мітки або QR-коду на самому пристрої — збереження тут буде відхилено." "require_tag_scan_hint": "Це завдання завершується лише скануванням його NFC-мітки або QR-коду на самому пристрої — збереження тут буде відхилено."
} }
@@ -530,6 +530,7 @@
"groupby_area": "按区域分组", "groupby_area": "按区域分组",
"groupby_group": "按分组", "groupby_group": "按分组",
"groupby_user": "按负责人", "groupby_user": "按负责人",
"groupby_object": "按对象",
"filter_label": "过滤器", "filter_label": "过滤器",
"user_label": "用户", "user_label": "用户",
"photo_label": "照片", "photo_label": "照片",
@@ -834,6 +835,11 @@
"baseline_current_effective": "当前生效的起始读数:{value}", "baseline_current_effective": "当前生效的起始读数:{value}",
"runtime_on_states": "活动状态", "runtime_on_states": "活动状态",
"runtime_on_states_help": "计入运行时间的状态 — 默认:on。例如 mowing、cleaning、printing。选择了属性时将比较该属性的值。", "runtime_on_states_help": "计入运行时间的状态 — 默认:on。例如 mowing、cleaning、printing。选择了属性时将比较该属性的值。",
"runtime_max_session": "单次运行最长时间(秒)",
"runtime_max_session_help": "单次运行最多计入这么多秒——防止传感器卡在开启状态(连接丢失、重启)。留空 = 不限制。",
"trend_approaching": "正接近阈值",
"trend_easing": "正远离阈值",
"split_select_hint": "选择一个任务,在此查看详情",
"setups_target_new": "新建:{name}", "setups_target_new": "新建:{name}",
"schedule_preview_title": "下次日期", "schedule_preview_title": "下次日期",
"schedule_preview_ontime": "假设按时完成。", "schedule_preview_ontime": "假设按时完成。",
@@ -927,5 +933,7 @@
"history_add_past": "补录过去的完成记录", "history_add_past": "补录过去的完成记录",
"require_tag_scan": "仅可通过扫描标签完成", "require_tag_scan": "仅可通过扫描标签完成",
"require_tag_scan_help": "在场证明:在扫描设备上的 NFC 标签或二维码之前,所有界面的“完成”均被阻止。自动化可向 complete 服务传递 'via_tag_scan'。", "require_tag_scan_help": "在场证明:在扫描设备上的 NFC 标签或二维码之前,所有界面的“完成”均被阻止。自动化可向 complete 服务传递 'via_tag_scan'。",
"disallow_skip": "不允许跳过",
"disallow_skip_help": "跳过操作将从所有界面消失,服务器也会拒绝来自自动化和语音的跳过。",
"require_tag_scan_hint": "此任务只能通过扫描设备上的 NFC 标签或二维码来完成——在此保存将被拒绝。" "require_tag_scan_hint": "此任务只能通过扫描设备上的 NFC 标签或二维码来完成——在此保存将被拒绝。"
} }
@@ -75,7 +75,7 @@ import "./components/saved-views-dialog";
import type { MaintenanceSavedViewsDialog } from "./components/saved-views-dialog"; import type { MaintenanceSavedViewsDialog } from "./components/saved-views-dialog";
import { type SparklineContext } from "./renderers/sparkline"; import { type SparklineContext } from "./renderers/sparkline";
import { buildCalendarBuckets, isoDateLocal, type CalendarEvent } from "./helpers/calendar-bucket"; import { buildCalendarBuckets, isoDateLocal, type CalendarEvent } from "./helpers/calendar-bucket";
import { renderTriggerProgress, renderMiniSparkline } from "./renderers/progress"; import { renderTriggerProgress, renderMiniSparkline, computeTrend } from "./renderers/progress";
import { type HistoryContext } from "./renderers/history"; import { type HistoryContext } from "./renderers/history";
import { renderUserBadge, type TaskDetailContext } from "./renderers/task-detail"; import { renderUserBadge, type TaskDetailContext } from "./renderers/task-detail";
// The task-detail sub-view as a web component (light-DOM, panel styles apply). // The task-detail sub-view as a web component (light-DOM, panel styles apply).
@@ -112,7 +112,7 @@ interface PartsOverviewRow {
} }
type SortMode = "due_date" | "object" | "type" | "task_name" | "area" | "assigned_user" | "group"; type SortMode = "due_date" | "object" | "type" | "task_name" | "area" | "assigned_user" | "group";
type ObjectSortMode = "alphabetical" | "due_soonest" | "task_count"; type ObjectSortMode = "alphabetical" | "due_soonest" | "task_count";
type GroupByMode = "none" | "area" | "group" | "user"; type GroupByMode = "none" | "area" | "group" | "user" | "object";
// Chart dimension constants for mini sparklines (overview) // Chart dimension constants for mini sparklines (overview)
@@ -125,6 +125,10 @@ export class MaintenanceSupporterPanel extends LitElement {
* The wide row grid then cannot hold labelled action buttons, so the * The wide row grid then cannot hold labelled action buttons, so the
* compact (icon-only) form applies here too. Reflected for the CSS. */ * compact (icon-only) form applies here too. Reflected for the CSS. */
@property({ type: Boolean, reflect: true }) public tight = false; @property({ type: Boolean, reflect: true }) public tight = false;
/** ≥1500px panel width (2026-09-01): master-detail split — the dashboard
* keeps the task list on the left and docks the task detail on the right
* (a mail client's preview pane). Reflected for the CSS. */
@property({ type: Boolean, reflect: true }) public split = false;
private _tightObserver: ResizeObserver | null = null; private _tightObserver: ResizeObserver | null = null;
@property({ attribute: false }) public panel: Record<string, unknown> = {}; @property({ attribute: false }) public panel: Record<string, unknown> = {};
@@ -340,6 +344,7 @@ export class MaintenanceSupporterPanel extends LitElement {
// fragments. Below ~1000 the narrow layout is the honest choice; // fragments. Below ~1000 the narrow layout is the honest choice;
// from there up the chips track keeps ≥150 px of slack. // from there up the chips track keeps ≥150 px of slack.
if (w > 0) this.tight = w < 1000; if (w > 0) this.tight = w < 1000;
if (w > 0) this.split = w >= 1500;
}); });
this._tightObserver.observe(this); this._tightObserver.observe(this);
} }
@@ -358,7 +363,7 @@ export class MaintenanceSupporterPanel extends LitElement {
this._objectSortMode = savedObj as ObjectSortMode; this._objectSortMode = savedObj as ObjectSortMode;
} }
const savedGroup = lsGet(LS_KEYS.groupBy); const savedGroup = lsGet(LS_KEYS.groupBy);
if (savedGroup && ["none", "area", "group", "user"].includes(savedGroup)) { if (savedGroup && ["none", "area", "group", "user", "object"].includes(savedGroup)) {
this._groupByMode = savedGroup as GroupByMode; this._groupByMode = savedGroup as GroupByMode;
} }
const savedView = lsGet(LS_KEYS.objectView); const savedView = lsGet(LS_KEYS.objectView);
@@ -822,6 +827,7 @@ export class MaintenanceSupporterPanel extends LitElement {
entry_id: obj.entry_id, entry_id: obj.entry_id,
task_id: task.id, task_id: task.id,
object_name: obj.object.name, object_name: obj.object.name,
allow_skip: task.allow_skip !== false,
task_name: task.name, task_name: task.name,
type: task.type, type: task.type,
schedule_type: task.schedule_type, schedule_type: task.schedule_type,
@@ -1023,7 +1029,7 @@ export class MaintenanceSupporterPanel extends LitElement {
if (["due_date", "object", "type", "task_name", "area", "assigned_user", "group"].includes(f.sort_mode)) { if (["due_date", "object", "type", "task_name", "area", "assigned_user", "group"].includes(f.sort_mode)) {
this._sortMode = f.sort_mode as SortMode; this._sortMode = f.sort_mode as SortMode;
} }
if (["none", "area", "group", "user"].includes(f.group_by)) { if (["none", "area", "group", "user", "object"].includes(f.group_by)) {
this._groupByMode = f.group_by as GroupByMode; this._groupByMode = f.group_by as GroupByMode;
} }
// Persist sort/group like the manual controls do, so they stick after reload. // Persist sort/group like the manual controls do, so they stick after reload.
@@ -1077,7 +1083,28 @@ export class MaintenanceSupporterPanel extends LitElement {
this._scrollContentToTop(); this._scrollContentToTop();
} }
/** Master-detail split is active: wide panel, dashboard tab, no bulk. */
private _splitActive(): boolean {
return this.split && !this.narrow && !this.tight && this._view === "overview" && this._overviewTab === "dashboard" && !this._bulkMode;
}
private _showTask(entryId: string, taskId: string): void { private _showTask(entryId: string, taskId: string): void {
// Master-detail split (2026-09-01): same data prep, but no view switch
// and no history entry — the detail docks on the right like a mail
// client's preview pane. The detail's breadcrumb (showTaskView) still
// opens the full page.
if (this._splitActive()) {
this._selectedEntryId = entryId;
this._selectedTaskId = taskId;
this._activeTab = "overview";
this._historyFilter = null;
this._fetchFullHistory(entryId, taskId);
const task = this._getTask(entryId, taskId);
if (task?.trigger_config?.entity_id) {
this._fetchDetailStats(task.trigger_config.entity_id, this._isCounterEntity(task.trigger_config));
}
return;
}
this._pushPanelState("task", entryId, taskId); this._pushPanelState("task", entryId, taskId);
this._view = "task"; this._view = "task";
this._selectedEntryId = entryId; this._selectedEntryId = entryId;
@@ -2496,6 +2523,7 @@ export class MaintenanceSupporterPanel extends LitElement {
<option value="area" ?selected=${this._groupByMode === "area"}>${t("groupby_area", L)}</option> <option value="area" ?selected=${this._groupByMode === "area"}>${t("groupby_area", L)}</option>
${this._features.groups ? html`<option value="group" ?selected=${this._groupByMode === "group"}>${t("groupby_group", L)}</option>` : nothing} ${this._features.groups ? html`<option value="group" ?selected=${this._groupByMode === "group"}>${t("groupby_group", L)}</option>` : nothing}
<option value="user" ?selected=${this._groupByMode === "user"}>${t("groupby_user", L)}</option> <option value="user" ?selected=${this._groupByMode === "user"}>${t("groupby_user", L)}</option>
<option value="object" ?selected=${this._groupByMode === "object"}>${t("groupby_object", L)}</option>
</select> </select>
</label> </label>
${archivedCount > 0 ? html` ${archivedCount > 0 ? html`
@@ -2541,7 +2569,20 @@ export class MaintenanceSupporterPanel extends LitElement {
` `
: html` : html`
${this._bulkMode ? this._renderBulkBar(rows, L) : nothing} ${this._bulkMode ? this._renderBulkBar(rows, L) : nothing}
${this._groupByMode === "none" ${this._splitActive()
? html`
<div class="split-layout">
<div class="split-list">
${this._groupByMode === "none" ? this._renderTaskTable(rows) : this._renderGroupedTasks(rows, L)}
</div>
<div class="split-pane">
${this._selectedEntryId && this._selectedTaskId && this._getTask(this._selectedEntryId, this._selectedTaskId)
? this._renderTaskDetail()
: html`<div class="split-pane-empty"><ha-icon icon="mdi:cursor-default-click-outline"></ha-icon><p>${t("split_select_hint", L)}</p></div>`}
</div>
</div>
`
: this._groupByMode === "none"
? this._renderTaskTable(rows) ? this._renderTaskTable(rows)
: this._renderGroupedTasks(rows, L)} : this._renderGroupedTasks(rows, L)}
`} `}
@@ -2661,6 +2702,9 @@ export class MaintenanceSupporterPanel extends LitElement {
keys = [u || noneLabel]; keys = [u || noneLabel];
} else if (this._groupByMode === "group") { } else if (this._groupByMode === "group") {
keys = row.group_names.length > 0 ? row.group_names : [noneLabel]; keys = row.group_names.length > 0 ? row.group_names : [noneLabel];
} else if (this._groupByMode === "object") {
// #150(3): group the dashboard by the owning object/device.
keys = [row.object_name];
} }
for (const k of keys) { for (const k of keys) {
if (!groups.has(k)) groups.set(k, []); if (!groups.has(k)) groups.set(k, []);
@@ -2675,6 +2719,7 @@ export class MaintenanceSupporterPanel extends LitElement {
}); });
const icon = this._groupByMode === "area" ? "mdi:map-marker-outline" const icon = this._groupByMode === "area" ? "mdi:map-marker-outline"
: this._groupByMode === "group" ? "mdi:folder-outline" : this._groupByMode === "group" ? "mdi:folder-outline"
: this._groupByMode === "object" ? "mdi:cube-outline"
: "mdi:account-outline"; : "mdi:account-outline";
return html` return html`
${sorted.map(([key, taskRows]) => html` ${sorted.map(([key, taskRows]) => html`
@@ -3220,7 +3265,7 @@ export class MaintenanceSupporterPanel extends LitElement {
const bulkSelected = this._bulkMode && this._bulkSelected.has(this._bulkKey(row)); const bulkSelected = this._bulkMode && this._bulkSelected.has(this._bulkKey(row));
return html` return html`
<div class="task-row${!row.enabled ? ' task-disabled' : ''}${bulkSelected ? ' bulk-selected' : ''}"> <div class="task-row${!row.enabled ? ' task-disabled' : ''}${bulkSelected ? ' bulk-selected' : ''}${this._splitActive() && row.entry_id === this._selectedEntryId && row.task_id === this._selectedTaskId ? ' selected' : ''}">
${this._bulkMode ? html` ${this._bulkMode ? html`
<label class="cell bulk-check" @click=${(e: Event) => e.stopPropagation()}> <label class="cell bulk-check" @click=${(e: Event) => e.stopPropagation()}>
<input type="checkbox" .checked=${bulkSelected} @change=${() => this._toggleBulkRow(row)} /> <input type="checkbox" .checked=${bulkSelected} @change=${() => this._toggleBulkRow(row)} />
@@ -3260,13 +3305,13 @@ export class MaintenanceSupporterPanel extends LitElement {
? html`<div class="days-bar"><div class="days-bar-fill${daysOverflow ? " overflow" : ""}" style="width:${pct}%;background:${barColor}"></div></div>` ? html`<div class="days-bar"><div class="days-bar-fill${daysOverflow ? " overflow" : ""}" style="width:${pct}%;background:${barColor}"></div></div>`
: nothing} : nothing}
${row.trigger_config ${row.trigger_config
? renderTriggerProgress(row) ? renderTriggerProgress(row, { trend: computeTrend(row, this._miniStatsData), lang: L })
: !hasDaysBar && row.trigger_active : !hasDaysBar && row.trigger_active
? html`<span style="color:var(--maint-triggered-color);font-weight:600">⚡</span>` ? html`<span style="color:var(--maint-triggered-color);font-weight:600">⚡</span>`
: nothing} : nothing}
${renderMiniSparkline(row, this._miniStatsData, this._lang)} ${renderMiniSparkline(row, this._miniStatsData, this._lang)}
</span> </span>
${this._renderRowActions(L, () => this._openCompleteDialogForRow(row), () => this._promptSkipTask(row.entry_id, row.task_id))} ${this._renderRowActions(L, () => this._openCompleteDialogForRow(row), () => this._promptSkipTask(row.entry_id, row.task_id), row.allow_skip)}
</div> </div>
`; `;
} }
@@ -3296,7 +3341,7 @@ export class MaintenanceSupporterPanel extends LitElement {
/** #145: row actions as HA buttons — labelled (accent/success + plain, the /** #145: row actions as HA buttons — labelled (accent/success + plain, the
* task-detail pairing) or, for "buttons_compact" on narrow screens, * task-detail pairing) or, for "buttons_compact" on narrow screens,
* icon-only — or the classic icon pair when the household chose "icons". */ * icon-only — or the classic icon pair when the household chose "icons". */
private _renderRowActions(L: string, onComplete: () => void, onSkip: () => void): TemplateResult { private _renderRowActions(L: string, onComplete: () => void, onSkip: () => void, allowSkip = true): TemplateResult {
const style = this._actionStyle(); const style = this._actionStyle();
if (style === "buttons" || style === "buttons_compact") { if (style === "buttons" || style === "buttons_compact") {
const iconOnly = style === "buttons_compact" && (this.narrow || this.tight); const iconOnly = style === "buttons_compact" && (this.narrow || this.tight);
@@ -3308,9 +3353,10 @@ export class MaintenanceSupporterPanel extends LitElement {
<ha-button size="small" appearance="accent" variant="success" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); onComplete(); }}> <ha-button size="small" appearance="accent" variant="success" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); onComplete(); }}>
<ha-icon icon="mdi:check"></ha-icon> <ha-icon icon="mdi:check"></ha-icon>
</ha-button> </ha-button>
<ha-icon-button .label=${t("skip", L)} title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}> ${allowSkip ? html`
<ha-icon icon="mdi:skip-next"></ha-icon> <ha-icon-button .label=${t("skip", L)} title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}>
</ha-icon-button> <ha-icon icon="mdi:skip-next"></ha-icon>
</ha-icon-button>` : nothing}
</span>`; </span>`;
} }
return html` return html`
@@ -3318,9 +3364,10 @@ export class MaintenanceSupporterPanel extends LitElement {
<ha-button size="small" appearance="accent" variant="success" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); onComplete(); }}> <ha-button size="small" appearance="accent" variant="success" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); onComplete(); }}>
<ha-icon slot="start" icon="mdi:check"></ha-icon>${t("complete", L)} <ha-icon slot="start" icon="mdi:check"></ha-icon>${t("complete", L)}
</ha-button> </ha-button>
<ha-button size="small" appearance="plain" variant="neutral" title="${t("skip", L)}" ?disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}> ${allowSkip ? html`
<ha-icon slot="start" icon="mdi:skip-next"></ha-icon>${t("skip", L)} <ha-button size="small" appearance="outlined" variant="neutral" title="${t("skip", L)}" ?disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}>
</ha-button> <ha-icon slot="start" icon="mdi:skip-next"></ha-icon>${t("skip", L)}
</ha-button>` : nothing}
</span>`; </span>`;
} }
return html` return html`
@@ -3328,9 +3375,10 @@ export class MaintenanceSupporterPanel extends LitElement {
<mwc-icon-button class="btn-complete" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); onComplete(); }}> <mwc-icon-button class="btn-complete" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); onComplete(); }}>
<ha-icon icon="mdi:check"></ha-icon> <ha-icon icon="mdi:check"></ha-icon>
</mwc-icon-button> </mwc-icon-button>
<mwc-icon-button class="btn-skip" title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}> ${allowSkip ? html`
<ha-icon icon="mdi:skip-next"></ha-icon> <mwc-icon-button class="btn-skip" title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}>
</mwc-icon-button> <ha-icon icon="mdi:skip-next"></ha-icon>
</mwc-icon-button>` : nothing}
</span>`; </span>`;
} }
@@ -3470,7 +3518,7 @@ export class MaintenanceSupporterPanel extends LitElement {
<span class="due-cell" @click=${() => this._showTask(obj.entry_id, task.id)}> <span class="due-cell" @click=${() => this._showTask(obj.entry_id, task.id)}>
<span class="due-text">${formatDueDays(task.days_until_due, L)}</span> <span class="due-text">${formatDueDays(task.days_until_due, L)}</span>
${task.trigger_config ${task.trigger_config
? renderTriggerProgress(task) ? renderTriggerProgress(task, { trend: computeTrend(task, this._miniStatsData), lang: L })
: nothing} : nothing}
${renderMiniSparkline(task, this._miniStatsData, this._lang)} ${renderMiniSparkline(task, this._miniStatsData, this._lang)}
</span> </span>
@@ -3478,6 +3526,7 @@ export class MaintenanceSupporterPanel extends LitElement {
L, L,
() => this._openCompleteDialog(obj.entry_id, task.id, task.name, this._features.checklists ? task.checklist : undefined, this._features.adaptive && !!task.adaptive_config?.enabled), () => this._openCompleteDialog(obj.entry_id, task.id, task.name, this._features.checklists ? task.checklist : undefined, this._features.adaptive && !!task.adaptive_config?.enabled),
() => this._promptSkipTask(obj.entry_id, task.id), () => this._promptSkipTask(obj.entry_id, task.id),
task.allow_skip,
)} )}
</div> </div>
`)}</div>`} `)}</div>`}
@@ -18,7 +18,7 @@
"@web/dev-server-esbuild": "^2.0.0", "@web/dev-server-esbuild": "^2.0.0",
"@web/test-runner": "^1.0.0", "@web/test-runner": "^1.0.0",
"@web/test-runner-playwright": "^1.0.0", "@web/test-runner-playwright": "^1.0.0",
"esbuild": "^0.28.1", "esbuild": "^0.28.2",
"lit": "^3.3.3", "lit": "^3.3.3",
"react": "^19.2.8", "react": "^19.2.8",
"react-dom": "^19.2.8", "react-dom": "^19.2.8",
@@ -51,9 +51,9 @@
} }
}, },
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz",
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -68,9 +68,9 @@
} }
}, },
"node_modules/@esbuild/android-arm": { "node_modules/@esbuild/android-arm": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz",
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -85,9 +85,9 @@
} }
}, },
"node_modules/@esbuild/android-arm64": { "node_modules/@esbuild/android-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz",
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -102,9 +102,9 @@
} }
}, },
"node_modules/@esbuild/android-x64": { "node_modules/@esbuild/android-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz",
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -119,9 +119,9 @@
} }
}, },
"node_modules/@esbuild/darwin-arm64": { "node_modules/@esbuild/darwin-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz",
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -136,9 +136,9 @@
} }
}, },
"node_modules/@esbuild/darwin-x64": { "node_modules/@esbuild/darwin-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz",
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -153,9 +153,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-arm64": { "node_modules/@esbuild/freebsd-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz",
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -170,9 +170,9 @@
} }
}, },
"node_modules/@esbuild/freebsd-x64": { "node_modules/@esbuild/freebsd-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz",
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -187,9 +187,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm": { "node_modules/@esbuild/linux-arm": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz",
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==",
"cpu": [ "cpu": [
"arm" "arm"
], ],
@@ -204,9 +204,9 @@
} }
}, },
"node_modules/@esbuild/linux-arm64": { "node_modules/@esbuild/linux-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz",
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -221,9 +221,9 @@
} }
}, },
"node_modules/@esbuild/linux-ia32": { "node_modules/@esbuild/linux-ia32": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz",
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -238,9 +238,9 @@
} }
}, },
"node_modules/@esbuild/linux-loong64": { "node_modules/@esbuild/linux-loong64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz",
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==",
"cpu": [ "cpu": [
"loong64" "loong64"
], ],
@@ -255,9 +255,9 @@
} }
}, },
"node_modules/@esbuild/linux-mips64el": { "node_modules/@esbuild/linux-mips64el": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz",
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==",
"cpu": [ "cpu": [
"mips64el" "mips64el"
], ],
@@ -272,9 +272,9 @@
} }
}, },
"node_modules/@esbuild/linux-ppc64": { "node_modules/@esbuild/linux-ppc64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz",
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==",
"cpu": [ "cpu": [
"ppc64" "ppc64"
], ],
@@ -289,9 +289,9 @@
} }
}, },
"node_modules/@esbuild/linux-riscv64": { "node_modules/@esbuild/linux-riscv64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz",
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==",
"cpu": [ "cpu": [
"riscv64" "riscv64"
], ],
@@ -306,9 +306,9 @@
} }
}, },
"node_modules/@esbuild/linux-s390x": { "node_modules/@esbuild/linux-s390x": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz",
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==",
"cpu": [ "cpu": [
"s390x" "s390x"
], ],
@@ -323,9 +323,9 @@
} }
}, },
"node_modules/@esbuild/linux-x64": { "node_modules/@esbuild/linux-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz",
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -340,9 +340,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-arm64": { "node_modules/@esbuild/netbsd-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz",
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -357,9 +357,9 @@
} }
}, },
"node_modules/@esbuild/netbsd-x64": { "node_modules/@esbuild/netbsd-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz",
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -374,9 +374,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-arm64": { "node_modules/@esbuild/openbsd-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz",
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -391,9 +391,9 @@
} }
}, },
"node_modules/@esbuild/openbsd-x64": { "node_modules/@esbuild/openbsd-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz",
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -408,9 +408,9 @@
} }
}, },
"node_modules/@esbuild/openharmony-arm64": { "node_modules/@esbuild/openharmony-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz",
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -425,9 +425,9 @@
} }
}, },
"node_modules/@esbuild/sunos-x64": { "node_modules/@esbuild/sunos-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz",
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -442,9 +442,9 @@
} }
}, },
"node_modules/@esbuild/win32-arm64": { "node_modules/@esbuild/win32-arm64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz",
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -459,9 +459,9 @@
} }
}, },
"node_modules/@esbuild/win32-ia32": { "node_modules/@esbuild/win32-ia32": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz",
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -476,9 +476,9 @@
} }
}, },
"node_modules/@esbuild/win32-x64": { "node_modules/@esbuild/win32-x64": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz",
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -3204,9 +3204,9 @@
} }
}, },
"node_modules/esbuild": { "node_modules/esbuild": {
"version": "0.28.1", "version": "0.28.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz",
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==",
"dev": true, "dev": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT", "license": "MIT",
@@ -3217,32 +3217,32 @@
"node": ">=18" "node": ">=18"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/aix-ppc64": "0.28.1", "@esbuild/aix-ppc64": "0.28.2",
"@esbuild/android-arm": "0.28.1", "@esbuild/android-arm": "0.28.2",
"@esbuild/android-arm64": "0.28.1", "@esbuild/android-arm64": "0.28.2",
"@esbuild/android-x64": "0.28.1", "@esbuild/android-x64": "0.28.2",
"@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-arm64": "0.28.2",
"@esbuild/darwin-x64": "0.28.1", "@esbuild/darwin-x64": "0.28.2",
"@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.2",
"@esbuild/freebsd-x64": "0.28.1", "@esbuild/freebsd-x64": "0.28.2",
"@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm": "0.28.2",
"@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-arm64": "0.28.2",
"@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-ia32": "0.28.2",
"@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-loong64": "0.28.2",
"@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-mips64el": "0.28.2",
"@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-ppc64": "0.28.2",
"@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-riscv64": "0.28.2",
"@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-s390x": "0.28.2",
"@esbuild/linux-x64": "0.28.1", "@esbuild/linux-x64": "0.28.2",
"@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.2",
"@esbuild/netbsd-x64": "0.28.1", "@esbuild/netbsd-x64": "0.28.2",
"@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.2",
"@esbuild/openbsd-x64": "0.28.1", "@esbuild/openbsd-x64": "0.28.2",
"@esbuild/openharmony-arm64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.2",
"@esbuild/sunos-x64": "0.28.1", "@esbuild/sunos-x64": "0.28.2",
"@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-arm64": "0.28.2",
"@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-ia32": "0.28.2",
"@esbuild/win32-x64": "0.28.1" "@esbuild/win32-x64": "0.28.2"
} }
}, },
"node_modules/escalade": { "node_modules/escalade": {
@@ -4773,12 +4773,12 @@
} }
}, },
"node_modules/playwright": { "node_modules/playwright": {
"version": "1.62.0", "version": "1.62.1",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.0.tgz", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz",
"integrity": "sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw==", "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"playwright-core": "1.62.0" "playwright-core": "1.62.1"
}, },
"bin": { "bin": {
"playwright": "cli.js" "playwright": "cli.js"
@@ -4791,9 +4791,9 @@
} }
}, },
"node_modules/playwright-core": { "node_modules/playwright-core": {
"version": "1.62.0", "version": "1.62.1",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.0.tgz", "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz",
"integrity": "sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA==", "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==",
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
"playwright-core": "cli.js" "playwright-core": "cli.js"
@@ -15,7 +15,7 @@
"@web/dev-server-esbuild": "^2.0.0", "@web/dev-server-esbuild": "^2.0.0",
"@web/test-runner": "^1.0.0", "@web/test-runner": "^1.0.0",
"@web/test-runner-playwright": "^1.0.0", "@web/test-runner-playwright": "^1.0.0",
"esbuild": "^0.28.1", "esbuild": "^0.28.2",
"lit": "^3.3.3", "lit": "^3.3.3",
"react": "^19.2.8", "react": "^19.2.8",
"react-dom": "^19.2.8", "react-dom": "^19.2.8",
@@ -229,6 +229,51 @@ export const panelStyles = css`
} }
} }
.bulk-check { display: flex; align-items: center; justify-content: center; cursor: pointer; } .bulk-check { display: flex; align-items: center; justify-content: center; cursor: pointer; }
/* Master-detail split (>=1500px panel, 2026-09-01): list left, docked task
detail right - the width finally carries content instead of slack. Only
the dashboard tab uses it; below the threshold everything is unchanged. */
.split-layout {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(430px, 41%);
gap: 20px;
align-items: start;
}
.split-list { min-width: 0; }
/* Inside the split the list is ~60% wide — the type and chips columns are
redundant there (the docked detail names the type, assignee and labels),
and squeezed chips read as clutter. Drop both; the task name gets the
room and the list stays calm. */
.split-list .task-table { grid-template-columns: auto minmax(100px, 180px) minmax(120px, 1fr) 150px auto; }
.split-list .task-table.bulk { grid-template-columns: auto auto minmax(100px, 180px) minmax(120px, 1fr) 150px auto; }
.split-list .cell.type { display: none; }
.split-list .task-sub { display: none; }
.split-pane {
min-width: 0;
position: sticky;
top: 8px;
max-height: calc(100vh - 140px);
overflow-y: auto;
border: 1px solid var(--divider-color);
border-radius: 12px;
padding: 4px 16px 16px;
background: var(--card-background-color, #fff);
}
.split-pane-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 240px;
gap: 8px;
color: var(--secondary-text-color);
text-align: center;
}
.split-pane-empty ha-icon { --mdc-icon-size: 40px; opacity: 0.5; }
.task-row.selected {
background: rgba(var(--rgb-primary-color, 3, 169, 244), 0.1);
box-shadow: inset 3px 0 0 var(--primary-color);
}
.bulk-check input, .bulk-selectall input { width: 17px; height: 17px; cursor: pointer; accent-color: var(--primary-color); } .bulk-check input, .bulk-selectall input { width: 17px; height: 17px; cursor: pointer; accent-color: var(--primary-color); }
.task-row.bulk-selected { background: color-mix(in srgb, var(--primary-color) 12%, transparent); } .task-row.bulk-selected { background: color-mix(in srgb, var(--primary-color) 12%, transparent); }
.bulk-bar { .bulk-bar {
@@ -1457,7 +1502,16 @@ export const panelStyles = css`
width: 100%; width: 100%;
} }
:host([narrow]) .task-table { display: block; } /* Shared column tracks across rows (the wide layout's #66 lesson, applied
to narrow 2026-09-01): with per-row grids the auto badge/actions columns
sized independently, so the object-name column started at a different X
in every row — an "OK" pill vs "Due Soon" + priority chevron made the
list read jittery. The LIST owns the four tracks, rows subgrid them. */
:host([narrow]) .task-table {
display: grid;
grid-template-columns: auto minmax(76px, 1fr) 100px auto;
column-gap: 8px;
}
:host([narrow]) .task-row { :host([narrow]) .task-row {
/* Mobile: 4-column grid keeps due-cell + actions at deterministic /* Mobile: 4-column grid keeps due-cell + actions at deterministic
@@ -1469,10 +1523,9 @@ export const panelStyles = css`
Task-name spans the full top row (own row above), chips span the Task-name spans the full top row (own row above), chips span the
full bottom row. */ full bottom row. */
display: grid; display: grid;
grid-column: auto; grid-column: 1 / -1;
grid-template-columns: auto minmax(76px, 1fr) fit-content(100px) auto; /* name column keeps a word-sized floor, the due column hugs its content — at 400 px the object name used to be clipped mid-word (2026-08-30) */ grid-template-columns: subgrid;
grid-template-rows: auto auto auto; grid-template-rows: auto auto auto;
column-gap: 8px;
row-gap: 4px; row-gap: 4px;
padding: 12px; padding: 12px;
} }
@@ -1486,6 +1539,13 @@ export const panelStyles = css`
:host([narrow]) .cell-badges { :host([narrow]) .cell-badges {
grid-column: 1; grid-column: 1;
grid-row: 2; grid-row: 2;
/* Stack extra badges (priority chevron, NFC, disabled) under the status
pill: in the shared-track table the widest badge ROW sized column 1
for every row, and a pill+chevron combo pushed Complete/Skip off the
right edge at phone widths (2026-09-01). */
flex-direction: column;
align-items: flex-start;
gap: 4px;
} }
:host([narrow]) .cell.object-name { :host([narrow]) .cell.object-name {
grid-column: 2; grid-column: 2;
@@ -1540,26 +1600,30 @@ export const panelStyles = css`
the wide subgrid overflowed its last column at that width even before the wide subgrid overflowed its last column at that width even before
the buttons. Same rules as the :host([narrow]) block above / the the buttons. Same rules as the :host([narrow]) block above / the
max-width:768px media mirror below, keyed on the panel's own width. */ max-width:768px media mirror below, keyed on the panel's own width. */
:host([tight]:not([narrow])) .task-table { display: block; } :host([tight]:not([narrow])) .task-table {
display: grid;
grid-template-columns: auto minmax(76px, 1fr) 100px auto;
column-gap: 8px;
}
:host([tight]:not([narrow])) .task-row { :host([tight]:not([narrow])) .task-row {
display: grid; display: grid;
grid-column: auto; grid-column: 1 / -1;
grid-template-columns: auto minmax(76px, 1fr) fit-content(100px) auto; /* name column keeps a word-sized floor, the due column hugs its content — at 400 px the object name used to be clipped mid-word (2026-08-30) */ grid-template-columns: subgrid;
grid-template-rows: auto auto auto; grid-template-rows: auto auto auto;
column-gap: 8px;
row-gap: 4px; row-gap: 4px;
padding: 12px; padding: 12px;
min-width: 0; min-width: 0;
} }
:host([tight]:not([narrow])) .cell.type { display: none; } :host([tight]:not([narrow])) .cell.type { display: none; }
:host([tight]:not([narrow])) .cell.task-name { grid-column: 1 / -1; grid-row: 1; min-width: 0; } :host([tight]:not([narrow])) .cell.task-name { grid-column: 1 / -1; grid-row: 1; min-width: 0; }
:host([tight]:not([narrow])) .cell-badges { grid-column: 1; grid-row: 2; } :host([tight]:not([narrow])) .cell-badges { grid-column: 1; grid-row: 2; flex-direction: column; align-items: flex-start; gap: 4px; }
:host([tight]:not([narrow])) .cell.object-name { grid-column: 2; grid-row: 2; min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.2; } :host([tight]:not([narrow])) .cell.object-name { grid-column: 2; grid-row: 2; min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.2; }
:host([tight]:not([narrow])) .due-cell { grid-column: 3; grid-row: 2; align-items: flex-end; min-width: 0; } :host([tight]:not([narrow])) .due-cell { grid-column: 3; grid-row: 2; align-items: flex-end; min-width: 0; }
:host([tight]:not([narrow])) .row-actions { grid-column: 4; grid-row: 2; } :host([tight]:not([narrow])) .row-actions { grid-column: 4; grid-row: 2; }
:host([tight]:not([narrow])) .task-sub { grid-column: 1 / -1; grid-row: 3; font-size: 11px; gap: 6px; justify-content: flex-start; flex-wrap: wrap; } :host([tight]:not([narrow])) .task-sub { grid-column: 1 / -1; grid-row: 3; font-size: 11px; gap: 6px; justify-content: flex-start; flex-wrap: wrap; }
:host([tight]:not([narrow])) .task-sub-empty { display: none; } :host([tight]:not([narrow])) .task-sub-empty { display: none; }
:host([tight]:not([narrow])) .mini-sparkline { width: 50px; } :host([tight]:not([narrow])) .mini-sparkline { display: none; }
:host([tight]:not([narrow])) .trend-arrow { display: inline; }
:host([narrow]) .task-sub { :host([narrow]) .task-sub {
grid-column: 1 / -1; grid-column: 1 / -1;
grid-row: 3; grid-row: 3;
@@ -1569,7 +1633,22 @@ export const panelStyles = css`
flex-wrap: wrap; flex-wrap: wrap;
} }
:host([narrow]) .task-sub-empty { display: none; } :host([narrow]) .task-sub-empty { display: none; }
:host([narrow]) .mini-sparkline { width: 50px; } :host([narrow]) .mini-sparkline { display: none; }
:host([narrow]) .trend-arrow { display: inline; }
/* Phone band (≤429px): with SHARED tracks the widest badge sizes column 1
for every row, and the fixed 100px due column + both action buttons no
longer fit — Skip fell off the right edge. Tighter floors, slimmer row
padding and a smaller Skip icon-button. Bars stay uniform per
breakpoint (100px above, 84px here). */
@media (max-width: 429px) {
:host([narrow]) .task-table {
grid-template-columns: auto minmax(64px, 1fr) 84px auto;
column-gap: 6px;
}
:host([narrow]) .task-row { padding: 12px 8px; }
:host([narrow]) .row-actions.compact ha-icon-button { --mdc-icon-button-size: 32px; --mdc-icon-size: 20px; }
}
:host([narrow]) .detail-header { :host([narrow]) .detail-header {
flex-direction: column; flex-direction: column;
@@ -1691,24 +1770,31 @@ export const panelStyles = css`
.task-header-actions { width: 100%; justify-content: flex-start; flex-wrap: wrap; } .task-header-actions { width: 100%; justify-content: flex-start; flex-wrap: wrap; }
.filter-bar { flex-wrap: wrap; } .filter-bar { flex-wrap: wrap; }
.filter-bar select { flex: 1; min-width: 0; } .filter-bar select { flex: 1; min-width: 0; }
/* Mirror the :host([narrow]) grid layout for narrow desktop windows */ /* Mirror the :host([narrow]) grid layout for narrow desktop windows —
incl. the shared-track table so rows align (2026-09-01). */
.task-table {
display: grid;
grid-template-columns: auto minmax(76px, 1fr) 100px auto;
column-gap: 8px;
}
.task-row { .task-row {
display: grid; display: grid;
grid-template-columns: auto minmax(76px, 1fr) fit-content(100px) auto; /* name column keeps a word-sized floor, the due column hugs its content — at 400 px the object name used to be clipped mid-word (2026-08-30) */ grid-column: 1 / -1;
grid-template-columns: subgrid;
grid-template-rows: auto auto auto; grid-template-rows: auto auto auto;
column-gap: 8px;
row-gap: 4px; row-gap: 4px;
padding: 12px; padding: 12px;
} }
.cell.type { display: none; } .cell.type { display: none; }
.cell.task-name { grid-column: 1 / -1; grid-row: 1; min-width: 0; } .cell.task-name { grid-column: 1 / -1; grid-row: 1; min-width: 0; }
.cell-badges { grid-column: 1; grid-row: 2; } .cell-badges { grid-column: 1; grid-row: 2; flex-direction: column; align-items: flex-start; gap: 4px; }
.cell.object-name { grid-column: 2; grid-row: 2; min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.2; } .cell.object-name { grid-column: 2; grid-row: 2; min-width: 0; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; line-height: 1.2; }
.due-cell { grid-column: 3; grid-row: 2; align-items: flex-end; min-width: 0; } .due-cell { grid-column: 3; grid-row: 2; align-items: flex-end; min-width: 0; }
.row-actions { grid-column: 4; grid-row: 2; } .row-actions { grid-column: 4; grid-row: 2; }
.task-sub { grid-column: 1 / -1; grid-row: 3; font-size: 11px; gap: 6px; justify-content: flex-start; flex-wrap: wrap; } .task-sub { grid-column: 1 / -1; grid-row: 3; font-size: 11px; gap: 6px; justify-content: flex-start; flex-wrap: wrap; }
.task-sub-empty { display: none; } .task-sub-empty { display: none; }
.mini-sparkline { width: 50px; } .mini-sparkline { display: none; }
.trend-arrow { display: inline; }
.detail-header { flex-direction: column; align-items: flex-start; } .detail-header { flex-direction: column; align-items: flex-start; }
.info-grid { grid-template-columns: 1fr; } .info-grid { grid-template-columns: 1fr; }
.history-filters-new { flex-direction: column; } .history-filters-new { flex-direction: column; }
@@ -20,7 +20,59 @@ const MINI_SPARKLINE_W = 60;
const MINI_SPARKLINE_H = 20; const MINI_SPARKLINE_H = 20;
const MAX_MINI_POINTS = 30; const MAX_MINI_POINTS = 30;
export function renderTriggerProgress(row: TaskRow | MaintenanceTask) { export type TrendState = "approaching" | "stable" | "easing";
const TREND_GLYPHS: Record<TrendState, string> = { approaching: "\u2197", stable: "\u2192", easing: "\u2198" };
/** #150 follow-up: on narrow/tight rows the squeezed sparkline is unreadable
* — this reduces the same points to the one question the curve answered:
* is the value heading TOWARD the threshold, holding, or easing away?
* Direction is relative to the threshold (a dropping salt level and a
* rising runtime are both "approaching"). null = no arrow (no direction,
* compound, or fewer than two points). */
export function computeTrend(
row: TaskRow | MaintenanceTask,
miniStatsData: Map<string, StatisticsPoint[]>,
): TrendState | null {
const tc = row.trigger_config;
if (!tc?.entity_id) return null;
let toward: 1 | -1;
const type = tc.type || "threshold";
if (type === "threshold") {
if (tc.trigger_above != null) toward = 1;
else if (tc.trigger_below != null) toward = -1;
else return null; // discrete = / \u2260 levels have no gradient
} else if (type === "counter" || type === "runtime" || type === "state_change") {
toward = 1; // these accumulate toward their target
} else {
return null; // compound: conditions may point both ways
}
const statsPoints = miniStatsData.get(tc.entity_id) || [];
let points: { ts: number; val: number }[] =
statsPoints.length >= 2
? statsPoints.map((p) => ({ ts: p.ts, val: p.val }))
: (row.history || [])
.filter((h) => h.trigger_value != null)
.map((h) => ({ ts: new Date(h.timestamp).getTime(), val: h.trigger_value as number }));
if (row.trigger_current_value != null) points = [...points, { ts: Date.now(), val: row.trigger_current_value }];
if (points.length < 2) return null;
points.sort((a, b) => a.ts - b.ts);
const vals = points.map((p) => p.val);
const range = Math.max(...vals) - Math.min(...vals);
const delta = vals[vals.length - 1] - vals[0];
// Significance is judged against the JOURNEY to the threshold, not the
// series' own noise band: a sensor crawling 50.0 -> 50.15 under a
// 60-threshold is flat, even though that move spans most of its range.
const target =
type === "threshold" ? (tc.trigger_above ?? tc.trigger_below)
: type === "counter" ? tc.trigger_target_value
: type === "runtime" ? tc.trigger_runtime_hours
: tc.trigger_target_changes;
const base = typeof target === "number" ? Math.max(Math.abs(target - vals[0]), range) : range;
if (base === 0 || Math.abs(delta) < base * (typeof target === "number" ? 0.05 : 0.15)) return "stable";
return Math.sign(delta) === toward ? "approaching" : "easing";
}
export function renderTriggerProgress(row: TaskRow | MaintenanceTask, opts?: { trend?: TrendState | null; lang?: string }) {
const tc = row.trigger_config ?? null; const tc = row.trigger_config ?? null;
if (!tc) return nothing; if (!tc) return nothing;
@@ -109,7 +161,9 @@ export function renderTriggerProgress(row: TaskRow | MaintenanceTask) {
<div class="trigger-progress-bar"> <div class="trigger-progress-bar">
<div class="trigger-progress-fill${triggerOverflow ? " overflow" : ""}" style="width:${pct}%;background:${barColor}"></div> <div class="trigger-progress-fill${triggerOverflow ? " overflow" : ""}" style="width:${pct}%;background:${barColor}"></div>
</div> </div>
<span class="trigger-progress-label">${label}</span> <span class="trigger-progress-label">${label}${opts?.trend
? html` <i class="trend-arrow trend-${opts.trend}" title="${t(`trend_${opts.trend}`, opts.lang ?? "en")}" aria-label="${t(`trend_${opts.trend}`, opts.lang ?? "en")}">${TREND_GLYPHS[opts.trend]}</i>`
: nothing}</span>
</div> </div>
`; `;
} }
@@ -131,7 +131,9 @@ function renderTaskHeader(task: MaintenanceTask, ctx: TaskDetailContext) {
</div> </div>
<div class="task-header-actions"> <div class="task-header-actions">
<ha-button appearance="filled" @click=${() => ctx.openComplete(task)}>${t("complete", L)}</ha-button> <ha-button appearance="filled" @click=${() => ctx.openComplete(task)}>${t("complete", L)}</ha-button>
<ha-button appearance="plain" .disabled=${ctx.actionLoading} @click=${() => ctx.promptSkip()}>${t("skip", L)}</ha-button> ${task.allow_skip !== false
? html`<ha-button appearance="outlined" .disabled=${ctx.actionLoading} @click=${() => ctx.promptSkip()}>${t("skip", L)}</ha-button>`
: nothing}
<div class="more-menu-wrapper"> <div class="more-menu-wrapper">
<ha-icon-button .disabled=${ctx.actionLoading} .path=${"M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z"} @click=${() => ctx.toggleMoreMenu()}></ha-icon-button> <ha-icon-button .disabled=${ctx.actionLoading} .path=${"M12,16A2,2 0 0,1 14,18A2,2 0 0,1 12,20A2,2 0 0,1 10,18A2,2 0 0,1 12,16M12,10A2,2 0 0,1 14,12A2,2 0 0,1 12,14A2,2 0 0,1 10,12A2,2 0 0,1 12,10M12,4A2,2 0 0,1 14,6A2,2 0 0,1 12,8A2,2 0 0,1 10,6A2,2 0 0,1 12,4Z"} @click=${() => ctx.toggleMoreMenu()}></ha-icon-button>
${ctx.moreMenuOpen ? html` ${ctx.moreMenuOpen ? html`
@@ -908,8 +908,15 @@ export const sharedStyles = css`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 2px; gap: 2px;
/* #150 follow-up (2026-08-31, maisun's mobile screenshot): the box used
to carry min-width: 90px — in the narrow grid the due column is
fit-content(100px) and right-aligned, so on cells narrower than 90px
the box overhung LEFT across the object name. It now tracks the cell
with no floor, and the label ellipsizes inside. */
align-self: stretch;
max-width: 100%;
min-width: 0;
width: 100%; width: 100%;
min-width: 90px;
} }
.trigger-progress-bar { .trigger-progress-bar {
@@ -930,8 +937,25 @@ export const sharedStyles = css`
font-size: 12px; font-size: 12px;
color: var(--secondary-text-color); color: var(--secondary-text-color);
text-align: right; text-align: right;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
/* #150 follow-up: 3-state trend arrow — replaces the sparkline on
narrow/tight rows (panel-styles toggles visibility per regime). */
.trend-arrow {
display: none;
font-style: normal;
font-weight: 700;
margin-left: 2px;
}
.trend-approaching { color: var(--warning-color, #ff9800); }
.trend-stable { color: var(--secondary-text-color); }
.trend-easing { color: var(--success-color, #4caf50); }
/* Days progress bar (detail view) */ /* Days progress bar (detail view) */
.days-progress { .days-progress {
margin: 8px 0 16px; margin: 8px 0 16px;
@@ -974,6 +998,11 @@ export const sharedStyles = css`
/* Mini-sparkline in overview rows */ /* Mini-sparkline in overview rows */
.mini-sparkline { .mini-sparkline {
width: 60px; width: 60px;
/* Same class of bug as the trigger-progress floor (#150 follow-up): in
due cells narrower than the fixed width the right-aligned SVG used to
overhang LEFT (phone-360 sweep). preserveAspectRatio="none" lets it
just squeeze. */
max-width: 100%;
height: 20px; height: 20px;
display: block; display: block;
margin-top: 2px; margin-top: 2px;
@@ -68,6 +68,8 @@ export interface TriggerConfig {
trigger_to_state?: string | null; trigger_to_state?: string | null;
trigger_target_changes?: number; trigger_target_changes?: number;
trigger_runtime_hours?: number; trigger_runtime_hours?: number;
/** #149: a single session books at most this many seconds. */
trigger_runtime_max_session_seconds?: number;
/** States (or attribute values) that count as "running" — default ["on"]. */ /** States (or attribute values) that count as "running" — default ["on"]. */
trigger_on_states?: string[]; trigger_on_states?: string[];
compound_logic?: "AND" | "OR"; compound_logic?: "AND" | "OR";
@@ -173,6 +175,8 @@ export interface MaintenanceTask {
name: string; name: string;
type: string; // "cleaning" | "inspection" | "replacement" | "calibration" | "service" | "reading" | "custom" type: string; // "cleaning" | "inspection" | "replacement" | "calibration" | "service" | "reading" | "custom"
enabled: boolean; enabled: boolean;
/** #150: false = the skip lock — Skip hidden everywhere, server refuses. */
allow_skip?: boolean;
schedule_type: string; // "time_based" | "sensor_based" | "one_time" | "manual" | calendar kind schedule_type: string; // "time_based" | "sensor_based" | "one_time" | "manual" | calendar kind
interval_days?: number | null; interval_days?: number | null;
interval_unit?: string; // "days" | "weeks" | "months" | "years" interval_unit?: string; // "days" | "weeks" | "months" | "years"
@@ -509,6 +513,8 @@ export interface TaskRow {
archived: boolean; archived: boolean;
history: HistoryEntry[]; history: HistoryEntry[];
enabled: boolean; enabled: boolean;
/** #150: false = skip locked for this task. */
allow_skip: boolean;
nfc_tag_id: string | null; nfc_tag_id: string | null;
priority: string; priority: string;
labels: string[]; labels: string[];
@@ -528,6 +528,7 @@
"groupby_area": "Podle oblasti", "groupby_area": "Podle oblasti",
"groupby_group": "Podle skupiny", "groupby_group": "Podle skupiny",
"groupby_user": "Podle uživatele", "groupby_user": "Podle uživatele",
"groupby_object": "Podle objektu",
"filter_label": "Filtr", "filter_label": "Filtr",
"user_label": "Uživatel", "user_label": "Uživatel",
"photo_label": "Fotografie", "photo_label": "Fotografie",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Aktuálně platná počáteční hodnota: {value}", "baseline_current_effective": "Aktuálně platná počáteční hodnota: {value}",
"runtime_on_states": "Aktivní stavy", "runtime_on_states": "Aktivní stavy",
"runtime_on_states_help": "Stavy počítané jako doba běhu — výchozí: on. Např. mowing, cleaning, printing. Při zvoleném atributu se porovnávají jeho hodnoty.", "runtime_on_states_help": "Stavy počítané jako doba běhu — výchozí: on. Např. mowing, cleaning, printing. Při zvoleném atributu se porovnávají jeho hodnoty.",
"runtime_max_session": "Max. doba běhu relace (sekundy)",
"runtime_max_session_help": "Jeden běh se počítá nejvýše na tolik sekund — chrání před senzorem zaseknutým na ZAP (ztráta spojení, restart). Prázdné = bez limitu.",
"trend_approaching": "Blíží se k prahu",
"trend_easing": "Vzdaluje se od prahu",
"split_select_hint": "Vyberte úkol a zde se zobrazí podrobnosti",
"setups_target_new": "Vytvořit nový: {name}", "setups_target_new": "Vytvořit nový: {name}",
"schedule_preview_title": "Nejbližší termíny", "schedule_preview_title": "Nejbližší termíny",
"schedule_preview_ontime": "Za předpokladu včasného dokončení.", "schedule_preview_ontime": "Za předpokladu včasného dokončení.",
@@ -927,5 +933,7 @@
"history_add_past": "Přidat dřívější dokončení", "history_add_past": "Přidat dřívější dokončení",
"require_tag_scan": "Dokončit pouze naskenováním štítku", "require_tag_scan": "Dokončit pouze naskenováním štítku",
"require_tag_scan_help": "Důkaz přítomnosti: „Hotovo“ je všude blokováno, dokud nenaskenujete NFC štítek nebo QR kód na zařízení. Automatizace mohou službě complete předat 'via_tag_scan'.", "require_tag_scan_help": "Důkaz přítomnosti: „Hotovo“ je všude blokováno, dokud nenaskenujete NFC štítek nebo QR kód na zařízení. Automatizace mohou službě complete předat 'via_tag_scan'.",
"disallow_skip": "Nepovolit přeskočení",
"disallow_skip_help": "Akce Přeskočit zmizí ze všech ploch a server odmítne přeskočení i z automatizací a hlasu.",
"require_tag_scan_hint": "Tento úkol lze dokončit pouze naskenováním jeho NFC štítku nebo QR kódu na zařízení — uložení zde bude odmítnuto." "require_tag_scan_hint": "Tento úkol lze dokončit pouze naskenováním jeho NFC štítku nebo QR kódu na zařízení — uložení zde bude odmítnuto."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Efter område", "groupby_area": "Efter område",
"groupby_group": "Efter gruppe", "groupby_group": "Efter gruppe",
"groupby_user": "Efter bruger", "groupby_user": "Efter bruger",
"groupby_object": "Efter objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Bruger", "user_label": "Bruger",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Aktuelt gældende startværdi: {value}", "baseline_current_effective": "Aktuelt gældende startværdi: {value}",
"runtime_on_states": "Aktive tilstande", "runtime_on_states": "Aktive tilstande",
"runtime_on_states_help": "Tilstande der tæller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med en valgt attribut sammenlignes dens værdier i stedet.", "runtime_on_states_help": "Tilstande der tæller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med en valgt attribut sammenlignes dens værdier i stedet.",
"runtime_max_session": "Maks. sessionstid (sekunder)",
"runtime_max_session_help": "En enkelt kørsel tæller højst så mange sekunder — beskytter mod en sensor, der hænger på TÆNDT (tabt forbindelse, genstart). Tom = ingen grænse.",
"trend_approaching": "Nærmer sig tærsklen",
"trend_easing": "Bevæger sig væk fra tærsklen",
"split_select_hint": "Vælg en opgave for at se detaljerne her",
"setups_target_new": "Opret ny: {name}", "setups_target_new": "Opret ny: {name}",
"schedule_preview_title": "Kommende datoer", "schedule_preview_title": "Kommende datoer",
"schedule_preview_ontime": "Forudsat rettidig fuldførelse.", "schedule_preview_ontime": "Forudsat rettidig fuldførelse.",
@@ -927,5 +933,7 @@
"history_add_past": "Tilføj tidligere udførelse", "history_add_past": "Tilføj tidligere udførelse",
"require_tag_scan": "Kan kun udføres ved tag-scanning", "require_tag_scan": "Kan kun udføres ved tag-scanning",
"require_tag_scan_help": "Tilstedeværelsesbevis: „Udført“ er blokeret overalt, indtil NFC-tagget eller QR-koden på selve tingen er scannet. Automatiseringer kan give 'via_tag_scan' til complete-tjenesten.", "require_tag_scan_help": "Tilstedeværelsesbevis: „Udført“ er blokeret overalt, indtil NFC-tagget eller QR-koden på selve tingen er scannet. Automatiseringer kan give 'via_tag_scan' til complete-tjenesten.",
"disallow_skip": "Tillad ikke at springe over",
"disallow_skip_help": "Handlingen Spring over forsvinder fra alle flader, og serveren afviser også spring fra automatiseringer og stemme.",
"require_tag_scan_hint": "Denne opgave udføres kun ved at scanne dens NFC-tag eller QR-kode på selve tingen — at gemme her vil blive afvist." "require_tag_scan_hint": "Denne opgave udføres kun ved at scanne dens NFC-tag eller QR-kode på selve tingen — at gemme her vil blive afvist."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Nach Bereich", "groupby_area": "Nach Bereich",
"groupby_group": "Nach Gruppe", "groupby_group": "Nach Gruppe",
"groupby_user": "Nach Verantwortlichem", "groupby_user": "Nach Verantwortlichem",
"groupby_object": "Nach Objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Benutzer", "user_label": "Benutzer",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Aktuell wirksamer Startwert: {value}", "baseline_current_effective": "Aktuell wirksamer Startwert: {value}",
"runtime_on_states": "Aktive Zustände", "runtime_on_states": "Aktive Zustände",
"runtime_on_states_help": "Zustände, die als Laufzeit zählen — Standard: on. Z. B. mowing, cleaning, printing. Bei gewähltem Attribut werden dessen Werte verglichen.", "runtime_on_states_help": "Zustände, die als Laufzeit zählen — Standard: on. Z. B. mowing, cleaning, printing. Bei gewähltem Attribut werden dessen Werte verglichen.",
"runtime_max_session": "Maximale Sitzungslaufzeit (Sekunden)",
"runtime_max_session_help": "Ein einzelner Lauf zählt höchstens so viele Sekunden — schützt vor Sensoren, die auf AN hängen bleiben (Verbindungsabriss, Neustart). Leer = keine Begrenzung.",
"trend_approaching": "Läuft auf die Schwelle zu",
"trend_easing": "Entfernt sich von der Schwelle",
"split_select_hint": "Wähle eine Aufgabe, um hier die Details zu sehen",
"setups_target_new": "Neu anlegen: {name}", "setups_target_new": "Neu anlegen: {name}",
"schedule_preview_title": "Nächste Termine", "schedule_preview_title": "Nächste Termine",
"schedule_preview_ontime": "Bei pünktlichem Abschluss.", "schedule_preview_ontime": "Bei pünktlichem Abschluss.",
@@ -927,5 +933,7 @@
"history_add_past": "Vergangene Erledigung nachtragen", "history_add_past": "Vergangene Erledigung nachtragen",
"require_tag_scan": "Nur per Tag-Scan abschließbar", "require_tag_scan": "Nur per Tag-Scan abschließbar",
"require_tag_scan_help": "Anwesenheitsnachweis: „Erledigt“ ist überall blockiert, bis das NFC-Tag oder der QR-Code am Gerät gescannt wurde. Automationen können 'via_tag_scan' an den complete-Dienst übergeben.", "require_tag_scan_help": "Anwesenheitsnachweis: „Erledigt“ ist überall blockiert, bis das NFC-Tag oder der QR-Code am Gerät gescannt wurde. Automationen können 'via_tag_scan' an den complete-Dienst übergeben.",
"disallow_skip": "Überspringen nicht erlauben",
"disallow_skip_help": "Die Aktion Überspringen verschwindet von allen Oberflächen; auch Automationen und Sprachbefehle werden abgewiesen.",
"require_tag_scan_hint": "Diese Aufgabe kann nur per Scan des NFC-Tags oder QR-Codes am Gerät erledigt werden — Speichern hier wird abgelehnt." "require_tag_scan_hint": "Diese Aufgabe kann nur per Scan des NFC-Tags oder QR-Codes am Gerät erledigt werden — Speichern hier wird abgelehnt."
} }
@@ -536,6 +536,7 @@
"groupby_area": "By area", "groupby_area": "By area",
"groupby_group": "By group", "groupby_group": "By group",
"groupby_user": "By user", "groupby_user": "By user",
"groupby_object": "By object",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "User", "user_label": "User",
"photo_label": "Photo", "photo_label": "Photo",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Currently effective start value: {value}", "baseline_current_effective": "Currently effective start value: {value}",
"runtime_on_states": "Active states", "runtime_on_states": "Active states",
"runtime_on_states_help": "States that count as running — default: on. E.g. mowing, cleaning, printing. With an attribute selected, its values are matched instead.", "runtime_on_states_help": "States that count as running — default: on. E.g. mowing, cleaning, printing. With an attribute selected, its values are matched instead.",
"runtime_max_session": "Max session runtime (seconds)",
"runtime_max_session_help": "A single run counts at most this many seconds — protects against a sensor stuck ON (lost connection, restart). Empty = no cap.",
"trend_approaching": "Heading toward the threshold",
"trend_easing": "Easing away from the threshold",
"split_select_hint": "Select a task to see its details here",
"setups_target_new": "Create new: {name}", "setups_target_new": "Create new: {name}",
"schedule_preview_title": "Next dates", "schedule_preview_title": "Next dates",
"schedule_preview_ontime": "Assuming on-time completion.", "schedule_preview_ontime": "Assuming on-time completion.",
@@ -927,5 +933,7 @@
"history_add_past": "Add past completion", "history_add_past": "Add past completion",
"require_tag_scan": "Only complete by scanning the tag", "require_tag_scan": "Only complete by scanning the tag",
"require_tag_scan_help": "Proof of presence: Done is blocked on every surface until the NFC tag or QR code on the thing itself is scanned. Automations can pass 'via_tag_scan' to the complete service.", "require_tag_scan_help": "Proof of presence: Done is blocked on every surface until the NFC tag or QR code on the thing itself is scanned. Automations can pass 'via_tag_scan' to the complete service.",
"disallow_skip": "Don't allow skipping",
"disallow_skip_help": "The Skip action disappears from every surface, and the server refuses a skip from automations and voice too.",
"require_tag_scan_hint": "This task completes only by scanning its NFC tag or QR code on the thing itself — saving here will be refused." "require_tag_scan_hint": "This task completes only by scanning its NFC tag or QR code on the thing itself — saving here will be refused."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Por área", "groupby_area": "Por área",
"groupby_group": "Por grupo", "groupby_group": "Por grupo",
"groupby_user": "Por usuario", "groupby_user": "Por usuario",
"groupby_object": "Por objeto",
"filter_label": "Filtro", "filter_label": "Filtro",
"user_label": "Usuario", "user_label": "Usuario",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valor inicial vigente: {value}", "baseline_current_effective": "Valor inicial vigente: {value}",
"runtime_on_states": "Estados activos", "runtime_on_states": "Estados activos",
"runtime_on_states_help": "Estados que cuentan como en funcionamiento — predeterminado: on. P. ej. mowing, cleaning, printing. Con un atributo seleccionado se comparan sus valores.", "runtime_on_states_help": "Estados que cuentan como en funcionamiento — predeterminado: on. P. ej. mowing, cleaning, printing. Con un atributo seleccionado se comparan sus valores.",
"runtime_max_session": "Duración máxima por sesión (segundos)",
"runtime_max_session_help": "Una sola ejecución cuenta como máximo estos segundos — protege contra un sensor atascado en ON (conexión perdida, reinicio). Vacío = sin límite.",
"trend_approaching": "Se acerca al umbral",
"trend_easing": "Se aleja del umbral",
"split_select_hint": "Selecciona una tarea para ver sus detalles aquí",
"setups_target_new": "Crear nuevo: {name}", "setups_target_new": "Crear nuevo: {name}",
"schedule_preview_title": "Próximas fechas", "schedule_preview_title": "Próximas fechas",
"schedule_preview_ontime": "Suponiendo finalización puntual.", "schedule_preview_ontime": "Suponiendo finalización puntual.",
@@ -927,5 +933,7 @@
"history_add_past": "Añadir una finalización pasada", "history_add_past": "Añadir una finalización pasada",
"require_tag_scan": "Completar solo escaneando la etiqueta", "require_tag_scan": "Completar solo escaneando la etiqueta",
"require_tag_scan_help": "Prueba de presencia: «Hecho» queda bloqueado en todas partes hasta escanear la etiqueta NFC o el código QR del propio objeto. Las automatizaciones pueden pasar 'via_tag_scan' al servicio complete.", "require_tag_scan_help": "Prueba de presencia: «Hecho» queda bloqueado en todas partes hasta escanear la etiqueta NFC o el código QR del propio objeto. Las automatizaciones pueden pasar 'via_tag_scan' al servicio complete.",
"disallow_skip": "No permitir omitir",
"disallow_skip_help": "La acción Omitir desaparece de todas las superficies y el servidor también rechaza omisiones desde automatizaciones y voz.",
"require_tag_scan_hint": "Esta tarea solo se completa escaneando su etiqueta NFC o código QR en el propio objeto; guardar aquí será rechazado." "require_tag_scan_hint": "Esta tarea solo se completa escaneando su etiqueta NFC o código QR en el propio objeto; guardar aquí será rechazado."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Alueen mukaan", "groupby_area": "Alueen mukaan",
"groupby_group": "Ryhmän mukaan", "groupby_group": "Ryhmän mukaan",
"groupby_user": "Käyttäjän mukaan", "groupby_user": "Käyttäjän mukaan",
"groupby_object": "Kohteen mukaan",
"filter_label": "Suodata", "filter_label": "Suodata",
"user_label": "Käyttäjä", "user_label": "Käyttäjä",
"photo_label": "Valokuva", "photo_label": "Valokuva",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Nyt voimassa oleva aloitusarvo: {value}", "baseline_current_effective": "Nyt voimassa oleva aloitusarvo: {value}",
"runtime_on_states": "Aktiiviset tilat", "runtime_on_states": "Aktiiviset tilat",
"runtime_on_states_help": "Tilat, jotka lasketaan käyntiajaksi — oletus: on. Esim. mowing, cleaning, printing. Jos attribuutti on valittu, verrataan sen arvoja.", "runtime_on_states_help": "Tilat, jotka lasketaan käyntiajaksi — oletus: on. Esim. mowing, cleaning, printing. Jos attribuutti on valittu, verrataan sen arvoja.",
"runtime_max_session": "Istunnon enimmäiskesto (sekuntia)",
"runtime_max_session_help": "Yksi ajo lasketaan enintään näin moneksi sekunniksi — suojaa PÄÄLLÄ-tilaan jumittuneelta anturilta (katkennut yhteys, uudelleenkäynnistys). Tyhjä = ei rajaa.",
"trend_approaching": "Lähestyy raja-arvoa",
"trend_easing": "Loittonee raja-arvosta",
"split_select_hint": "Valitse tehtävä nähdäksesi sen tiedot tässä",
"setups_target_new": "Luo uusi: {name}", "setups_target_new": "Luo uusi: {name}",
"schedule_preview_title": "Seuraavat päivämäärät", "schedule_preview_title": "Seuraavat päivämäärät",
"schedule_preview_ontime": "Olettaen, että valmistuminen on ajallaan.", "schedule_preview_ontime": "Olettaen, että valmistuminen on ajallaan.",
@@ -927,5 +933,7 @@
"history_add_past": "Lisää aiempi suoritus", "history_add_past": "Lisää aiempi suoritus",
"require_tag_scan": "Suoritus vain tunnisteen skannauksella", "require_tag_scan": "Suoritus vain tunnisteen skannauksella",
"require_tag_scan_help": "Läsnäolotodistus: ”Valmis” on estetty kaikkialla, kunnes laitteen NFC-tunniste tai QR-koodi on skannattu. Automaatiot voivat välittää 'via_tag_scan' complete-palvelulle.", "require_tag_scan_help": "Läsnäolotodistus: ”Valmis” on estetty kaikkialla, kunnes laitteen NFC-tunniste tai QR-koodi on skannattu. Automaatiot voivat välittää 'via_tag_scan' complete-palvelulle.",
"disallow_skip": "Estä ohittaminen",
"disallow_skip_help": "Ohita-toiminto katoaa kaikista näkymistä, ja palvelin hylkää ohituksen myös automaatioista ja puheesta.",
"require_tag_scan_hint": "Tämä tehtävä valmistuu vain skannaamalla sen NFC-tunniste tai QR-koodi itse laitteesta — tallennus tässä estetään." "require_tag_scan_hint": "Tämä tehtävä valmistuu vain skannaamalla sen NFC-tunniste tai QR-koodi itse laitteesta — tallennus tässä estetään."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Par zone", "groupby_area": "Par zone",
"groupby_group": "Par groupe", "groupby_group": "Par groupe",
"groupby_user": "Par utilisateur", "groupby_user": "Par utilisateur",
"groupby_object": "Par objet",
"filter_label": "Filtre", "filter_label": "Filtre",
"user_label": "Utilisateur", "user_label": "Utilisateur",
"photo_label": "Photo", "photo_label": "Photo",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valeur de départ actuellement en vigueur : {value}", "baseline_current_effective": "Valeur de départ actuellement en vigueur : {value}",
"runtime_on_states": "États actifs", "runtime_on_states": "États actifs",
"runtime_on_states_help": "États comptés comme en fonctionnement — par défaut : on. P. ex. mowing, cleaning, printing. Si un attribut est sélectionné, ce sont ses valeurs qui sont comparées.", "runtime_on_states_help": "États comptés comme en fonctionnement — par défaut : on. P. ex. mowing, cleaning, printing. Si un attribut est sélectionné, ce sont ses valeurs qui sont comparées.",
"runtime_max_session": "Durée max. par session (secondes)",
"runtime_max_session_help": "Une seule exécution compte au plus ce nombre de secondes — protège contre un capteur bloqué sur ON (connexion perdue, redémarrage). Vide = pas de limite.",
"trend_approaching": "Se rapproche du seuil",
"trend_easing": "S'éloigne du seuil",
"split_select_hint": "Sélectionnez une tâche pour voir ses détails ici",
"setups_target_new": "Créer : {name}", "setups_target_new": "Créer : {name}",
"schedule_preview_title": "Prochaines échéances", "schedule_preview_title": "Prochaines échéances",
"schedule_preview_ontime": "En supposant un achèvement ponctuel.", "schedule_preview_ontime": "En supposant un achèvement ponctuel.",
@@ -927,5 +933,7 @@
"history_add_past": "Ajouter une réalisation passée", "history_add_past": "Ajouter une réalisation passée",
"require_tag_scan": "Terminer uniquement en scannant le tag", "require_tag_scan": "Terminer uniquement en scannant le tag",
"require_tag_scan_help": "Preuve de présence : « Terminé » est bloqué partout tant que le tag NFC ou le QR code sur l'objet n'a pas été scanné. Les automatisations peuvent passer 'via_tag_scan' au service complete.", "require_tag_scan_help": "Preuve de présence : « Terminé » est bloqué partout tant que le tag NFC ou le QR code sur l'objet n'a pas été scanné. Les automatisations peuvent passer 'via_tag_scan' au service complete.",
"disallow_skip": "Ne pas autoriser à ignorer",
"disallow_skip_help": "L'action Ignorer disparaît de toutes les surfaces et le serveur refuse aussi un saut via les automatisations et la voix.",
"require_tag_scan_hint": "Cette tâche ne se termine qu'en scannant son tag NFC ou son QR code sur l'objet — l'enregistrement ici sera refusé." "require_tag_scan_hint": "Cette tâche ne se termine qu'en scannant son tag NFC ou son QR code sur l'objet — l'enregistrement ici sera refusé."
} }
@@ -530,6 +530,7 @@
"groupby_area": "क्षेत्र के अनुसार", "groupby_area": "क्षेत्र के अनुसार",
"groupby_group": "समूह के अनुसार", "groupby_group": "समूह के अनुसार",
"groupby_user": "उपयोगकर्ता के अनुसार", "groupby_user": "उपयोगकर्ता के अनुसार",
"groupby_object": "वस्तु के अनुसार",
"filter_label": "फ़िल्टर", "filter_label": "फ़िल्टर",
"user_label": "उपयोगकर्ता", "user_label": "उपयोगकर्ता",
"photo_label": "फ़ोटो", "photo_label": "फ़ोटो",
@@ -834,6 +835,11 @@
"baseline_current_effective": "वर्तमान में प्रभावी प्रारंभिक मान: {value}", "baseline_current_effective": "वर्तमान में प्रभावी प्रारंभिक मान: {value}",
"runtime_on_states": "सक्रिय अवस्थाएँ", "runtime_on_states": "सक्रिय अवस्थाएँ",
"runtime_on_states_help": "वे अवस्थाएँ जो चालू समय में गिनी जाती हैं — डिफ़ॉल्ट: on। जैसे mowing, cleaning, printing। विशेषता चुनी होने पर उसकी मानों की तुलना होती है।", "runtime_on_states_help": "वे अवस्थाएँ जो चालू समय में गिनी जाती हैं — डिफ़ॉल्ट: on। जैसे mowing, cleaning, printing। विशेषता चुनी होने पर उसकी मानों की तुलना होती है।",
"runtime_max_session": "प्रति सत्र अधिकतम रनटाइम (सेकंड)",
"runtime_max_session_help": "एक रन अधिकतम इतने सेकंड गिना जाता है — ON पर अटके सेंसर (कनेक्शन टूटना, रीस्टार्ट) से बचाता है। खाली = कोई सीमा नहीं।",
"trend_approaching": "सीमा की ओर बढ़ रहा है",
"trend_easing": "सीमा से दूर जा रहा है",
"split_select_hint": "विवरण यहाँ देखने के लिए कोई कार्य चुनें",
"setups_target_new": "नया बनाएँ: {name}", "setups_target_new": "नया बनाएँ: {name}",
"schedule_preview_title": "अगली तिथियाँ", "schedule_preview_title": "अगली तिथियाँ",
"schedule_preview_ontime": "समय पर पूर्णता मानते हुए।", "schedule_preview_ontime": "समय पर पूर्णता मानते हुए।",
@@ -927,5 +933,7 @@
"history_add_past": "पिछली पूर्णता जोड़ें", "history_add_past": "पिछली पूर्णता जोड़ें",
"require_tag_scan": "केवल टैग स्कैन से पूर्ण करें", "require_tag_scan": "केवल टैग स्कैन से पूर्ण करें",
"require_tag_scan_help": "उपस्थिति प्रमाण: जब तक वस्तु पर लगा NFC टैग या QR कोड स्कैन न हो, हर जगह “पूर्ण” अवरुद्ध रहता है। ऑटोमेशन complete सेवा को 'via_tag_scan' दे सकते हैं।", "require_tag_scan_help": "उपस्थिति प्रमाण: जब तक वस्तु पर लगा NFC टैग या QR कोड स्कैन न हो, हर जगह “पूर्ण” अवरुद्ध रहता है। ऑटोमेशन complete सेवा को 'via_tag_scan' दे सकते हैं।",
"disallow_skip": "छोड़ने की अनुमति न दें",
"disallow_skip_help": "छोड़ें क्रिया सभी सतहों से हट जाती है, और सर्वर ऑटोमेशन व वॉयस से छोड़ने को भी अस्वीकार करता है।",
"require_tag_scan_hint": "यह कार्य केवल वस्तु पर लगे NFC टैग या QR कोड को स्कैन करके ही पूर्ण होता है — यहाँ सहेजना अस्वीकार होगा।" "require_tag_scan_hint": "यह कार्य केवल वस्तु पर लगे NFC टैग या QR कोड को स्कैन करके ही पूर्ण होता है — यहाँ सहेजना अस्वीकार होगा।"
} }
@@ -536,6 +536,7 @@
"groupby_area": "Terület szerint", "groupby_area": "Terület szerint",
"groupby_group": "Csoport szerint", "groupby_group": "Csoport szerint",
"groupby_user": "Felhasználó szerint", "groupby_user": "Felhasználó szerint",
"groupby_object": "Objektum szerint",
"filter_label": "Szűrő", "filter_label": "Szűrő",
"user_label": "Felhasználó", "user_label": "Felhasználó",
"photo_label": "Fénykép", "photo_label": "Fénykép",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Jelenleg érvényes kezdőérték: {value}", "baseline_current_effective": "Jelenleg érvényes kezdőérték: {value}",
"runtime_on_states": "Aktív állapotok", "runtime_on_states": "Aktív állapotok",
"runtime_on_states_help": "Működésként számító állapotok — alapértelmezés: on. Pl. mowing, cleaning, printing. Attribútum kiválasztásakor annak értékei számítanak.", "runtime_on_states_help": "Működésként számító állapotok — alapértelmezés: on. Pl. mowing, cleaning, printing. Attribútum kiválasztásakor annak értékei számítanak.",
"runtime_max_session": "Max. munkamenet-futásidő (másodperc)",
"runtime_max_session_help": "Egy futás legfeljebb ennyi másodpercet számít — véd a BE állapotban beragadt érzékelő ellen (kapcsolatvesztés, újraindítás). Üres = nincs korlát.",
"trend_approaching": "Közeledik a küszöbhöz",
"trend_easing": "Távolodik a küszöbtől",
"split_select_hint": "Válassz egy feladatot, és itt jelennek meg a részletei",
"setups_target_new": "Új létrehozása: {name}", "setups_target_new": "Új létrehozása: {name}",
"schedule_preview_title": "Következő dátumok", "schedule_preview_title": "Következő dátumok",
"schedule_preview_ontime": "Időben történő elvégzést feltételezve.", "schedule_preview_ontime": "Időben történő elvégzést feltételezve.",
@@ -927,5 +933,7 @@
"history_add_past": "Korábbi elvégzés rögzítése", "history_add_past": "Korábbi elvégzés rögzítése",
"require_tag_scan": "Csak címke beolvasásával fejezhető be", "require_tag_scan": "Csak címke beolvasásával fejezhető be",
"require_tag_scan_help": "Jelenlét-igazolás: a „Kész” mindenhol blokkolva van, amíg be nem olvasod az eszközön lévő NFC-címkét vagy QR-kódot. Az automatizálások 'via_tag_scan' értéket adhatnak át a complete szolgáltatásnak.", "require_tag_scan_help": "Jelenlét-igazolás: a „Kész” mindenhol blokkolva van, amíg be nem olvasod az eszközön lévő NFC-címkét vagy QR-kódot. Az automatizálások 'via_tag_scan' értéket adhatnak át a complete szolgáltatásnak.",
"disallow_skip": "Kihagyás tiltása",
"disallow_skip_help": "A Kihagyás művelet minden felületről eltűnik, és a szerver az automatizálásokból és hangból érkező kihagyást is elutasítja.",
"require_tag_scan_hint": "Ez a feladat csak az eszközön lévő NFC-címke vagy QR-kód beolvasásával fejezhető be — az itteni mentés el lesz utasítva." "require_tag_scan_hint": "Ez a feladat csak az eszközön lévő NFC-címke vagy QR-kód beolvasásával fejezhető be — az itteni mentés el lesz utasítva."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Per area", "groupby_area": "Per area",
"groupby_group": "Per gruppo", "groupby_group": "Per gruppo",
"groupby_user": "Per utente", "groupby_user": "Per utente",
"groupby_object": "Per oggetto",
"filter_label": "Filtro", "filter_label": "Filtro",
"user_label": "Utente", "user_label": "Utente",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valore iniziale attualmente in vigore: {value}", "baseline_current_effective": "Valore iniziale attualmente in vigore: {value}",
"runtime_on_states": "Stati attivi", "runtime_on_states": "Stati attivi",
"runtime_on_states_help": "Stati che contano come in funzione — predefinito: on. Ad es. mowing, cleaning, printing. Con un attributo selezionato vengono confrontati i suoi valori.", "runtime_on_states_help": "Stati che contano come in funzione — predefinito: on. Ad es. mowing, cleaning, printing. Con un attributo selezionato vengono confrontati i suoi valori.",
"runtime_max_session": "Durata massima per sessione (secondi)",
"runtime_max_session_help": "Una singola esecuzione conta al massimo questi secondi — protegge da un sensore bloccato su ON (connessione persa, riavvio). Vuoto = nessun limite.",
"trend_approaching": "Si avvicina alla soglia",
"trend_easing": "Si allontana dalla soglia",
"split_select_hint": "Seleziona un'attività per vederne i dettagli qui",
"setups_target_new": "Crea nuovo: {name}", "setups_target_new": "Crea nuovo: {name}",
"schedule_preview_title": "Prossime date", "schedule_preview_title": "Prossime date",
"schedule_preview_ontime": "Presumendo un completamento puntuale.", "schedule_preview_ontime": "Presumendo un completamento puntuale.",
@@ -927,5 +933,7 @@
"history_add_past": "Aggiungi un completamento passato", "history_add_past": "Aggiungi un completamento passato",
"require_tag_scan": "Completa solo scansionando il tag", "require_tag_scan": "Completa solo scansionando il tag",
"require_tag_scan_help": "Prova di presenza: «Fatto» è bloccato ovunque finché non viene scansionato il tag NFC o il codice QR sull'oggetto. Le automazioni possono passare 'via_tag_scan' al servizio complete.", "require_tag_scan_help": "Prova di presenza: «Fatto» è bloccato ovunque finché non viene scansionato il tag NFC o il codice QR sull'oggetto. Le automazioni possono passare 'via_tag_scan' al servizio complete.",
"disallow_skip": "Non consentire di saltare",
"disallow_skip_help": "L'azione Salta scompare da tutte le superfici e il server rifiuta anche i salti da automazioni e voce.",
"require_tag_scan_hint": "Questa attività si completa solo scansionando il suo tag NFC o codice QR sull'oggetto — il salvataggio qui verrà rifiutato." "require_tag_scan_hint": "Questa attività si completa solo scansionando il suo tag NFC o codice QR sull'oggetto — il salvataggio qui verrà rifiutato."
} }
@@ -530,6 +530,7 @@
"groupby_area": "エリア別", "groupby_area": "エリア別",
"groupby_group": "グループ別", "groupby_group": "グループ別",
"groupby_user": "ユーザー別", "groupby_user": "ユーザー別",
"groupby_object": "対象別",
"filter_label": "絞り込み", "filter_label": "絞り込み",
"user_label": "ユーザー", "user_label": "ユーザー",
"photo_label": "写真", "photo_label": "写真",
@@ -834,6 +835,11 @@
"baseline_current_effective": "現在有効な開始値:{value}", "baseline_current_effective": "現在有効な開始値:{value}",
"runtime_on_states": "稼働中とみなす状態", "runtime_on_states": "稼働中とみなす状態",
"runtime_on_states_help": "稼働時間として数える状態 — 既定値:on。例:mowing, cleaning, printing。属性を選択している場合はその値が比較されます。", "runtime_on_states_help": "稼働時間として数える状態 — 既定値:on。例:mowing, cleaning, printing。属性を選択している場合はその値が比較されます。",
"runtime_max_session": "1回の最大稼働時間(秒)",
"runtime_max_session_help": "1回の稼働は最大この秒数までカウント——ONのまま固まったセンサー(接続切れ・再起動)への保護です。空欄=制限なし。",
"trend_approaching": "しきい値に近づいています",
"trend_easing": "しきい値から遠ざかっています",
"split_select_hint": "タスクを選択すると、ここに詳細が表示されます",
"setups_target_new": "新規作成:{name}", "setups_target_new": "新規作成:{name}",
"schedule_preview_title": "次回の予定日", "schedule_preview_title": "次回の予定日",
"schedule_preview_ontime": "期日どおりに完了した場合。", "schedule_preview_ontime": "期日どおりに完了した場合。",
@@ -927,5 +933,7 @@
"history_add_past": "過去の完了を追加", "history_add_past": "過去の完了を追加",
"require_tag_scan": "タグのスキャンでのみ完了可能", "require_tag_scan": "タグのスキャンでのみ完了可能",
"require_tag_scan_help": "在席証明:対象物のNFCタグまたはQRコードをスキャンするまで、どの画面でも「完了」はブロックされます。オートメーションはcompleteサービスに 'via_tag_scan' を渡せます。", "require_tag_scan_help": "在席証明:対象物のNFCタグまたはQRコードをスキャンするまで、どの画面でも「完了」はブロックされます。オートメーションはcompleteサービスに 'via_tag_scan' を渡せます。",
"disallow_skip": "スキップを許可しない",
"disallow_skip_help": "スキップ操作はすべての画面から消え、オートメーションや音声からのスキップもサーバーが拒否します。",
"require_tag_scan_hint": "このタスクは対象物のNFCタグまたはQRコードをスキャンしないと完了できません。ここでの保存は拒否されます。" "require_tag_scan_hint": "このタスクは対象物のNFCタグまたはQRコードをスキャンしないと完了できません。ここでの保存は拒否されます。"
} }
@@ -536,6 +536,7 @@
"groupby_area": "구역별", "groupby_area": "구역별",
"groupby_group": "그룹별", "groupby_group": "그룹별",
"groupby_user": "사용자별", "groupby_user": "사용자별",
"groupby_object": "대상별",
"filter_label": "필터", "filter_label": "필터",
"user_label": "사용자", "user_label": "사용자",
"photo_label": "사진", "photo_label": "사진",
@@ -834,6 +835,11 @@
"baseline_current_effective": "현재 적용 중인 시작 값: {value}", "baseline_current_effective": "현재 적용 중인 시작 값: {value}",
"runtime_on_states": "활성 상태", "runtime_on_states": "활성 상태",
"runtime_on_states_help": "가동 중으로 계산할 상태입니다 — 기본값: on. 예: mowing, cleaning, printing. 속성을 선택한 경우 해당 속성 값과 비교합니다.", "runtime_on_states_help": "가동 중으로 계산할 상태입니다 — 기본값: on. 예: mowing, cleaning, printing. 속성을 선택한 경우 해당 속성 값과 비교합니다.",
"runtime_max_session": "세션당 최대 가동 시간(초)",
"runtime_max_session_help": "한 번의 가동은 최대 이 초까지만 집계됩니다 — ON에 멈춘 센서(연결 끊김, 재시작)로부터 보호합니다. 비워두면 제한 없음.",
"trend_approaching": "임계값에 가까워지는 중",
"trend_easing": "임계값에서 멀어지는 중",
"split_select_hint": "작업을 선택하면 여기에 세부 정보가 표시됩니다",
"setups_target_new": "새로 만들기: {name}", "setups_target_new": "새로 만들기: {name}",
"schedule_preview_title": "다음 예정일", "schedule_preview_title": "다음 예정일",
"schedule_preview_ontime": "제때 완료한다고 가정한 일정입니다.", "schedule_preview_ontime": "제때 완료한다고 가정한 일정입니다.",
@@ -927,5 +933,7 @@
"history_add_past": "지난 완료 추가", "history_add_past": "지난 완료 추가",
"require_tag_scan": "태그 스캔으로만 완료 가능", "require_tag_scan": "태그 스캔으로만 완료 가능",
"require_tag_scan_help": "현장 확인: 기기의 NFC 태그나 QR 코드를 스캔할 때까지 모든 화면에서 '완료'가 차단됩니다. 자동화는 complete 서비스에 'via_tag_scan'을 전달할 수 있습니다.", "require_tag_scan_help": "현장 확인: 기기의 NFC 태그나 QR 코드를 스캔할 때까지 모든 화면에서 '완료'가 차단됩니다. 자동화는 complete 서비스에 'via_tag_scan'을 전달할 수 있습니다.",
"disallow_skip": "건너뛰기 허용 안 함",
"disallow_skip_help": "건너뛰기 동작이 모든 화면에서 사라지며, 서버는 자동화와 음성의 건너뛰기도 거부합니다.",
"require_tag_scan_hint": "이 작업은 기기의 NFC 태그나 QR 코드를 스캔해야만 완료됩니다. 여기서 저장하면 거부됩니다." "require_tag_scan_hint": "이 작업은 기기의 NFC 태그나 QR 코드를 스캔해야만 완료됩니다. 여기서 저장하면 거부됩니다."
} }
@@ -530,6 +530,7 @@
"groupby_area": "Etter område", "groupby_area": "Etter område",
"groupby_group": "Etter gruppe", "groupby_group": "Etter gruppe",
"groupby_user": "Etter bruker", "groupby_user": "Etter bruker",
"groupby_object": "Etter objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Bruker", "user_label": "Bruker",
"photo_label": "Bilde", "photo_label": "Bilde",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Gjeldende startverdi: {value}", "baseline_current_effective": "Gjeldende startverdi: {value}",
"runtime_on_states": "Aktive tilstander", "runtime_on_states": "Aktive tilstander",
"runtime_on_states_help": "Tilstander som teller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med et valgt attributt sammenlignes verdiene dets i stedet.", "runtime_on_states_help": "Tilstander som teller som driftstid — standard: on. F.eks. mowing, cleaning, printing. Med et valgt attributt sammenlignes verdiene dets i stedet.",
"runtime_max_session": "Maks økt-varighet (sekunder)",
"runtime_max_session_help": "En enkelt kjøring teller høyst så mange sekunder — beskytter mot en sensor som henger på PÅ (mistet forbindelse, omstart). Tom = ingen grense.",
"trend_approaching": "Nærmer seg terskelen",
"trend_easing": "Beveger seg bort fra terskelen",
"split_select_hint": "Velg en oppgave for å se detaljene her",
"setups_target_new": "Opprett ny: {name}", "setups_target_new": "Opprett ny: {name}",
"schedule_preview_title": "Kommende datoer", "schedule_preview_title": "Kommende datoer",
"schedule_preview_ontime": "Forutsatt fullføring i tide.", "schedule_preview_ontime": "Forutsatt fullføring i tide.",
@@ -927,5 +933,7 @@
"history_add_past": "Legg til tidligere fullføring", "history_add_past": "Legg til tidligere fullføring",
"require_tag_scan": "Kan bare fullføres ved tag-skanning", "require_tag_scan": "Kan bare fullføres ved tag-skanning",
"require_tag_scan_help": "Tilstedeværelsesbevis: «Fullført» er blokkert overalt til NFC-taggen eller QR-koden på selve tingen er skannet. Automatiseringer kan sende 'via_tag_scan' til complete-tjenesten.", "require_tag_scan_help": "Tilstedeværelsesbevis: «Fullført» er blokkert overalt til NFC-taggen eller QR-koden på selve tingen er skannet. Automatiseringer kan sende 'via_tag_scan' til complete-tjenesten.",
"disallow_skip": "Ikke tillat å hoppe over",
"disallow_skip_help": "Handlingen Hopp over forsvinner fra alle flater, og serveren avviser også hopp fra automatiseringer og tale.",
"require_tag_scan_hint": "Denne oppgaven fullføres bare ved å skanne NFC-taggen eller QR-koden på selve tingen — lagring her vil bli avvist." "require_tag_scan_hint": "Denne oppgaven fullføres bare ved å skanne NFC-taggen eller QR-koden på selve tingen — lagring her vil bli avvist."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Per gebied", "groupby_area": "Per gebied",
"groupby_group": "Per groep", "groupby_group": "Per groep",
"groupby_user": "Per gebruiker", "groupby_user": "Per gebruiker",
"groupby_object": "Per object",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Gebruiker", "user_label": "Gebruiker",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Momenteel geldende startwaarde: {value}", "baseline_current_effective": "Momenteel geldende startwaarde: {value}",
"runtime_on_states": "Actieve statussen", "runtime_on_states": "Actieve statussen",
"runtime_on_states_help": "Statussen die als draaitijd tellen — standaard: on. Bijv. mowing, cleaning, printing. Met een geselecteerd attribuut worden de waarden daarvan vergeleken.", "runtime_on_states_help": "Statussen die als draaitijd tellen — standaard: on. Bijv. mowing, cleaning, printing. Met een geselecteerd attribuut worden de waarden daarvan vergeleken.",
"runtime_max_session": "Maximale sessieduur (seconden)",
"runtime_max_session_help": "Eén run telt maximaal dit aantal seconden — beschermt tegen sensoren die op AAN blijven hangen (verbroken verbinding, herstart). Leeg = geen limiet.",
"trend_approaching": "Beweegt richting de drempel",
"trend_easing": "Beweegt weg van de drempel",
"split_select_hint": "Selecteer een taak om hier de details te zien",
"setups_target_new": "Nieuw aanmaken: {name}", "setups_target_new": "Nieuw aanmaken: {name}",
"schedule_preview_title": "Volgende data", "schedule_preview_title": "Volgende data",
"schedule_preview_ontime": "Uitgaande van tijdige afronding.", "schedule_preview_ontime": "Uitgaande van tijdige afronding.",
@@ -927,5 +933,7 @@
"history_add_past": "Eerdere afronding toevoegen", "history_add_past": "Eerdere afronding toevoegen",
"require_tag_scan": "Alleen af te ronden via tag-scan", "require_tag_scan": "Alleen af te ronden via tag-scan",
"require_tag_scan_help": "Aanwezigheidsbewijs: „Klaar” is overal geblokkeerd totdat de NFC-tag of QR-code op het apparaat zelf is gescand. Automatiseringen kunnen 'via_tag_scan' aan de complete-service meegeven.", "require_tag_scan_help": "Aanwezigheidsbewijs: „Klaar” is overal geblokkeerd totdat de NFC-tag of QR-code op het apparaat zelf is gescand. Automatiseringen kunnen 'via_tag_scan' aan de complete-service meegeven.",
"disallow_skip": "Overslaan niet toestaan",
"disallow_skip_help": "De actie Overslaan verdwijnt overal, en de server weigert ook een skip via automatiseringen en spraak.",
"require_tag_scan_hint": "Deze taak wordt alleen afgerond door de NFC-tag of QR-code op het apparaat te scannen — opslaan hier wordt geweigerd." "require_tag_scan_hint": "Deze taak wordt alleen afgerond door de NFC-tag of QR-code op het apparaat te scannen — opslaan hier wordt geweigerd."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Wg obszaru", "groupby_area": "Wg obszaru",
"groupby_group": "Wg grupy", "groupby_group": "Wg grupy",
"groupby_user": "Wg użytkownika", "groupby_user": "Wg użytkownika",
"groupby_object": "Według obiektu",
"filter_label": "Filtr", "filter_label": "Filtr",
"user_label": "Użytkownik", "user_label": "Użytkownik",
"photo_label": "Zdjęcie", "photo_label": "Zdjęcie",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Obecnie obowiązująca wartość początkowa: {value}", "baseline_current_effective": "Obecnie obowiązująca wartość początkowa: {value}",
"runtime_on_states": "Stany aktywne", "runtime_on_states": "Stany aktywne",
"runtime_on_states_help": "Stany liczone jako czas pracy — domyślnie: on. Np. mowing, cleaning, printing. Przy wybranym atrybucie porównywane są jego wartości.", "runtime_on_states_help": "Stany liczone jako czas pracy — domyślnie: on. Np. mowing, cleaning, printing. Przy wybranym atrybucie porównywane są jego wartości.",
"runtime_max_session": "Maks. czas sesji (sekundy)",
"runtime_max_session_help": "Pojedynczy przebieg liczy się najwyżej tyle sekund — chroni przed czujnikiem zawieszonym na WŁ. (utrata połączenia, restart). Puste = bez limitu.",
"trend_approaching": "Zbliża się do progu",
"trend_easing": "Oddala się od progu",
"split_select_hint": "Wybierz zadanie, aby zobaczyć tutaj szczegóły",
"setups_target_new": "Utwórz nowy: {name}", "setups_target_new": "Utwórz nowy: {name}",
"schedule_preview_title": "Najbliższe terminy", "schedule_preview_title": "Najbliższe terminy",
"schedule_preview_ontime": "Przy założeniu terminowego ukończenia.", "schedule_preview_ontime": "Przy założeniu terminowego ukończenia.",
@@ -927,5 +933,7 @@
"history_add_past": "Dodaj wcześniejsze ukończenie", "history_add_past": "Dodaj wcześniejsze ukończenie",
"require_tag_scan": "Ukończenie tylko przez skan tagu", "require_tag_scan": "Ukończenie tylko przez skan tagu",
"require_tag_scan_help": "Dowód obecności: „Gotowe” jest wszędzie zablokowane, dopóki nie zeskanujesz tagu NFC lub kodu QR na urządzeniu. Automatyzacje mogą przekazać 'via_tag_scan' do usługi complete.", "require_tag_scan_help": "Dowód obecności: „Gotowe” jest wszędzie zablokowane, dopóki nie zeskanujesz tagu NFC lub kodu QR na urządzeniu. Automatyzacje mogą przekazać 'via_tag_scan' do usługi complete.",
"disallow_skip": "Nie zezwalaj na pomijanie",
"disallow_skip_help": "Akcja Pomiń znika ze wszystkich widoków, a serwer odrzuca pominięcie także z automatyzacji i głosu.",
"require_tag_scan_hint": "To zadanie można ukończyć tylko skanując jego tag NFC lub kod QR na urządzeniu — zapis tutaj zostanie odrzucony." "require_tag_scan_hint": "To zadanie można ukończyć tylko skanując jego tag NFC lub kod QR na urządzeniu — zapis tutaj zostanie odrzucony."
} }
@@ -536,6 +536,7 @@
"groupby_area": "Por área", "groupby_area": "Por área",
"groupby_group": "Por grupo", "groupby_group": "Por grupo",
"groupby_user": "Por usuário", "groupby_user": "Por usuário",
"groupby_object": "Por objeto",
"filter_label": "Filtro", "filter_label": "Filtro",
"user_label": "Usuário", "user_label": "Usuário",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valor inicial efetivo atual: {value}", "baseline_current_effective": "Valor inicial efetivo atual: {value}",
"runtime_on_states": "Estados ativos", "runtime_on_states": "Estados ativos",
"runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. Ex.: mowing, cleaning, printing. Com um atributo selecionado, os valores dele são comparados.", "runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. Ex.: mowing, cleaning, printing. Com um atributo selecionado, os valores dele são comparados.",
"runtime_max_session": "Duração máxima por sessão (segundos)",
"runtime_max_session_help": "Uma única execução conta no máximo esses segundos — protege contra um sensor travado em ON (conexão perdida, reinício). Vazio = sem limite.",
"trend_approaching": "Aproximando-se do limite",
"trend_easing": "Afastando-se do limite",
"split_select_hint": "Selecione uma tarefa para ver os detalhes aqui",
"setups_target_new": "Criar novo: {name}", "setups_target_new": "Criar novo: {name}",
"schedule_preview_title": "Próximas datas", "schedule_preview_title": "Próximas datas",
"schedule_preview_ontime": "Supondo conclusão em dia.", "schedule_preview_ontime": "Supondo conclusão em dia.",
@@ -927,5 +933,7 @@
"history_add_past": "Adicionar conclusão passada", "history_add_past": "Adicionar conclusão passada",
"require_tag_scan": "Concluir apenas escaneando a etiqueta", "require_tag_scan": "Concluir apenas escaneando a etiqueta",
"require_tag_scan_help": "Prova de presença: “Concluído” fica bloqueado em toda parte até escanear a etiqueta NFC ou o código QR no próprio objeto. Automações podem passar 'via_tag_scan' ao serviço complete.", "require_tag_scan_help": "Prova de presença: “Concluído” fica bloqueado em toda parte até escanear a etiqueta NFC ou o código QR no próprio objeto. Automações podem passar 'via_tag_scan' ao serviço complete.",
"disallow_skip": "Não permitir pular",
"disallow_skip_help": "A ação Pular desaparece de todas as telas e o servidor também recusa pular via automações e voz.",
"require_tag_scan_hint": "Esta tarefa só é concluída escaneando sua etiqueta NFC ou código QR no próprio objeto — salvar aqui será recusado." "require_tag_scan_hint": "Esta tarefa só é concluída escaneando sua etiqueta NFC ou código QR no próprio objeto — salvar aqui será recusado."
} }
@@ -573,6 +573,7 @@
"groupby_area": "Por área", "groupby_area": "Por área",
"groupby_group": "Por grupo", "groupby_group": "Por grupo",
"groupby_user": "Por usuário", "groupby_user": "Por usuário",
"groupby_object": "Por objeto",
"unassigned": "Não atribuído", "unassigned": "Não atribuído",
"no_area": "Sem área", "no_area": "Sem área",
"has_overdue": "Tarefas em atraso", "has_overdue": "Tarefas em atraso",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Valor inicial atualmente em vigor: {value}", "baseline_current_effective": "Valor inicial atualmente em vigor: {value}",
"runtime_on_states": "Estados ativos", "runtime_on_states": "Estados ativos",
"runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. P. ex. mowing, cleaning, printing. Com um atributo selecionado, são comparados os valores dele.", "runtime_on_states_help": "Estados que contam como em funcionamento — padrão: on. P. ex. mowing, cleaning, printing. Com um atributo selecionado, são comparados os valores dele.",
"runtime_max_session": "Duração máxima por sessão (segundos)",
"runtime_max_session_help": "Uma única execução conta no máximo estes segundos — protege contra um sensor preso em ON (ligação perdida, reinício). Vazio = sem limite.",
"trend_approaching": "A aproximar-se do limiar",
"trend_easing": "A afastar-se do limiar",
"split_select_hint": "Selecione uma tarefa para ver os detalhes aqui",
"setups_target_new": "Criar novo: {name}", "setups_target_new": "Criar novo: {name}",
"schedule_preview_title": "Próximas datas", "schedule_preview_title": "Próximas datas",
"schedule_preview_ontime": "Assumindo conclusão pontual.", "schedule_preview_ontime": "Assumindo conclusão pontual.",
@@ -927,5 +933,7 @@
"history_add_past": "Adicionar conclusão passada", "history_add_past": "Adicionar conclusão passada",
"require_tag_scan": "Concluir apenas lendo a etiqueta", "require_tag_scan": "Concluir apenas lendo a etiqueta",
"require_tag_scan_help": "Prova de presença: «Concluído» fica bloqueado em todo o lado até ler a etiqueta NFC ou o código QR no próprio objeto. As automações podem passar 'via_tag_scan' ao serviço complete.", "require_tag_scan_help": "Prova de presença: «Concluído» fica bloqueado em todo o lado até ler a etiqueta NFC ou o código QR no próprio objeto. As automações podem passar 'via_tag_scan' ao serviço complete.",
"disallow_skip": "Não permitir ignorar",
"disallow_skip_help": "A ação Ignorar desaparece de todas as superfícies e o servidor também recusa ignorar via automações e voz.",
"require_tag_scan_hint": "Esta tarefa só é concluída lendo a sua etiqueta NFC ou código QR no próprio objeto — guardar aqui será recusado." "require_tag_scan_hint": "Esta tarefa só é concluída lendo a sua etiqueta NFC ou código QR no próprio objeto — guardar aqui será recusado."
} }
@@ -528,6 +528,7 @@
"groupby_area": "По области", "groupby_area": "По области",
"groupby_group": "По группе", "groupby_group": "По группе",
"groupby_user": "По пользователю", "groupby_user": "По пользователю",
"groupby_object": "По объекту",
"filter_label": "Фильтр", "filter_label": "Фильтр",
"user_label": "Пользователь", "user_label": "Пользователь",
"photo_label": "Фото", "photo_label": "Фото",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Действующее начальное значение: {value}", "baseline_current_effective": "Действующее начальное значение: {value}",
"runtime_on_states": "Активные состояния", "runtime_on_states": "Активные состояния",
"runtime_on_states_help": "Состояния, засчитываемые как работа — по умолчанию: on. Напр. mowing, cleaning, printing. Если выбран атрибут, сравниваются его значения.", "runtime_on_states_help": "Состояния, засчитываемые как работа — по умолчанию: on. Напр. mowing, cleaning, printing. Если выбран атрибут, сравниваются его значения.",
"runtime_max_session": "Макс. время сеанса (секунды)",
"runtime_max_session_help": "Один запуск засчитывается не более чем на столько секунд — защита от датчика, зависшего во включённом состоянии (обрыв связи, перезапуск). Пусто = без ограничения.",
"trend_approaching": "Приближается к порогу",
"trend_easing": "Отдаляется от порога",
"split_select_hint": "Выберите задачу, чтобы увидеть здесь её детали",
"setups_target_new": "Создать новый: {name}", "setups_target_new": "Создать новый: {name}",
"schedule_preview_title": "Ближайшие даты", "schedule_preview_title": "Ближайшие даты",
"schedule_preview_ontime": "При условии своевременного выполнения.", "schedule_preview_ontime": "При условии своевременного выполнения.",
@@ -927,5 +933,7 @@
"history_add_past": "Добавить прошлое выполнение", "history_add_past": "Добавить прошлое выполнение",
"require_tag_scan": "Завершение только по скану метки", "require_tag_scan": "Завершение только по скану метки",
"require_tag_scan_help": "Подтверждение присутствия: «Готово» заблокировано везде, пока не отсканирована NFC-метка или QR-код на самом устройстве. Автоматизации могут передавать 'via_tag_scan' в службу complete.", "require_tag_scan_help": "Подтверждение присутствия: «Готово» заблокировано везде, пока не отсканирована NFC-метка или QR-код на самом устройстве. Автоматизации могут передавать 'via_tag_scan' в службу complete.",
"disallow_skip": "Запретить пропуск",
"disallow_skip_help": "Действие «Пропустить» исчезает со всех экранов, а сервер отклоняет пропуск из автоматизаций и голосовых команд.",
"require_tag_scan_hint": "Эта задача завершается только сканированием её NFC-метки или QR-кода на самом устройстве — сохранение здесь будет отклонено." "require_tag_scan_hint": "Эта задача завершается только сканированием её NFC-метки или QR-кода на самом устройстве — сохранение здесь будет отклонено."
} }
@@ -528,6 +528,7 @@
"groupby_area": "Per område", "groupby_area": "Per område",
"groupby_group": "Per grupp", "groupby_group": "Per grupp",
"groupby_user": "Per användare", "groupby_user": "Per användare",
"groupby_object": "Efter objekt",
"filter_label": "Filter", "filter_label": "Filter",
"user_label": "Användare", "user_label": "Användare",
"photo_label": "Foto", "photo_label": "Foto",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Nu gällande startvärde: {value}", "baseline_current_effective": "Nu gällande startvärde: {value}",
"runtime_on_states": "Aktiva tillstånd", "runtime_on_states": "Aktiva tillstånd",
"runtime_on_states_help": "Tillstånd som räknas som drifttid — standard: on. T.ex. mowing, cleaning, printing. Med ett valt attribut jämförs dess värden i stället.", "runtime_on_states_help": "Tillstånd som räknas som drifttid — standard: on. T.ex. mowing, cleaning, printing. Med ett valt attribut jämförs dess värden i stället.",
"runtime_max_session": "Max körtid per session (sekunder)",
"runtime_max_session_help": "En enskild körning räknas som högst så här många sekunder — skyddar mot en sensor som fastnat på PÅ (tappad anslutning, omstart). Tomt = ingen gräns.",
"trend_approaching": "Närmar sig tröskeln",
"trend_easing": "Rör sig bort från tröskeln",
"split_select_hint": "Välj en uppgift för att se detaljerna här",
"setups_target_new": "Skapa ny: {name}", "setups_target_new": "Skapa ny: {name}",
"schedule_preview_title": "Kommande datum", "schedule_preview_title": "Kommande datum",
"schedule_preview_ontime": "Förutsatt slutförande i tid.", "schedule_preview_ontime": "Förutsatt slutförande i tid.",
@@ -927,5 +933,7 @@
"history_add_past": "Lägg till tidigare slutförande", "history_add_past": "Lägg till tidigare slutförande",
"require_tag_scan": "Kan endast slutföras via tagg-skanning", "require_tag_scan": "Kan endast slutföras via tagg-skanning",
"require_tag_scan_help": "Närvarobevis: ”Klar” är blockerad överallt tills NFC-taggen eller QR-koden på själva saken har skannats. Automationer kan skicka 'via_tag_scan' till complete-tjänsten.", "require_tag_scan_help": "Närvarobevis: ”Klar” är blockerad överallt tills NFC-taggen eller QR-koden på själva saken har skannats. Automationer kan skicka 'via_tag_scan' till complete-tjänsten.",
"disallow_skip": "Tillåt inte att hoppa över",
"disallow_skip_help": "Åtgärden Hoppa över försvinner från alla ytor och servern nekar även hopp från automationer och röst.",
"require_tag_scan_hint": "Den här uppgiften slutförs endast genom att skanna dess NFC-tagg eller QR-kod på själva saken — att spara här kommer att nekas." "require_tag_scan_hint": "Den här uppgiften slutförs endast genom att skanna dess NFC-tagg eller QR-kod på själva saken — att spara här kommer att nekas."
} }
@@ -536,6 +536,7 @@
"groupby_area": "Alana göre", "groupby_area": "Alana göre",
"groupby_group": "Gruba göre", "groupby_group": "Gruba göre",
"groupby_user": "Kullanıcıya göre", "groupby_user": "Kullanıcıya göre",
"groupby_object": "Nesneye göre",
"filter_label": "Filtre", "filter_label": "Filtre",
"user_label": "Kullanıcı", "user_label": "Kullanıcı",
"photo_label": "Fotoğraf", "photo_label": "Fotoğraf",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Şu anda geçerli başlangıç değeri: {value}", "baseline_current_effective": "Şu anda geçerli başlangıç değeri: {value}",
"runtime_on_states": "Etkin durumlar", "runtime_on_states": "Etkin durumlar",
"runtime_on_states_help": "Çalışıyor sayılan durumlar — varsayılan: on. Örn. mowing, cleaning, printing. Bir öznitelik seçiliyse onun değerleri eşleştirilir.", "runtime_on_states_help": "Çalışıyor sayılan durumlar — varsayılan: on. Örn. mowing, cleaning, printing. Bir öznitelik seçiliyse onun değerleri eşleştirilir.",
"runtime_max_session": "Oturum başına azami çalışma süresi (saniye)",
"runtime_max_session_help": "Tek bir çalışma en fazla bu kadar saniye sayılır — AÇIK durumda takılı kalan sensöre (bağlantı kopması, yeniden başlatma) karşı korur. Boş = sınır yok.",
"trend_approaching": "Eşiğe yaklaşıyor",
"trend_easing": "Eşikten uzaklaşıyor",
"split_select_hint": "Ayrıntıları burada görmek için bir görev seçin",
"setups_target_new": "Yeni oluştur: {name}", "setups_target_new": "Yeni oluştur: {name}",
"schedule_preview_title": "Sonraki tarihler", "schedule_preview_title": "Sonraki tarihler",
"schedule_preview_ontime": "Zamanında tamamlama varsayılarak.", "schedule_preview_ontime": "Zamanında tamamlama varsayılarak.",
@@ -927,5 +933,7 @@
"history_add_past": "Geçmiş tamamlama ekle", "history_add_past": "Geçmiş tamamlama ekle",
"require_tag_scan": "Yalnızca etiket taranarak tamamlanır", "require_tag_scan": "Yalnızca etiket taranarak tamamlanır",
"require_tag_scan_help": "Yerinde olma kanıtı: Cihazın üzerindeki NFC etiketi veya QR kodu taranana kadar 'Tamamlandı' her yerde engellenir. Otomasyonlar complete servisine 'via_tag_scan' iletebilir.", "require_tag_scan_help": "Yerinde olma kanıtı: Cihazın üzerindeki NFC etiketi veya QR kodu taranana kadar 'Tamamlandı' her yerde engellenir. Otomasyonlar complete servisine 'via_tag_scan' iletebilir.",
"disallow_skip": "Atlamaya izin verme",
"disallow_skip_help": "Atla eylemi tüm yüzeylerden kaybolur; sunucu otomasyonlardan ve sesten gelen atlamayı da reddeder.",
"require_tag_scan_hint": "Bu görev yalnızca cihazın üzerindeki NFC etiketi veya QR kodu taranarak tamamlanır — buradan kaydetme reddedilecektir." "require_tag_scan_hint": "Bu görev yalnızca cihazın üzerindeki NFC etiketi veya QR kodu taranarak tamamlanır — buradan kaydetme reddedilecektir."
} }
@@ -528,6 +528,7 @@
"groupby_area": "За зоною", "groupby_area": "За зоною",
"groupby_group": "За групою", "groupby_group": "За групою",
"groupby_user": "За користувачем", "groupby_user": "За користувачем",
"groupby_object": "За об'єктом",
"filter_label": "Фільтр", "filter_label": "Фільтр",
"user_label": "Користувач", "user_label": "Користувач",
"photo_label": "Фото", "photo_label": "Фото",
@@ -834,6 +835,11 @@
"baseline_current_effective": "Чинне початкове значення: {value}", "baseline_current_effective": "Чинне початкове значення: {value}",
"runtime_on_states": "Активні стани", "runtime_on_states": "Активні стани",
"runtime_on_states_help": "Стани, що зараховуються як робота — типово: on. Напр. mowing, cleaning, printing. Якщо вибрано атрибут, порівнюються його значення.", "runtime_on_states_help": "Стани, що зараховуються як робота — типово: on. Напр. mowing, cleaning, printing. Якщо вибрано атрибут, порівнюються його значення.",
"runtime_max_session": "Макс. час сеансу (секунди)",
"runtime_max_session_help": "Один запуск зараховується щонайбільше на стільки секунд — захист від датчика, що завис в увімкненому стані (втрата зв'язку, перезапуск). Порожньо = без обмеження.",
"trend_approaching": "Наближається до порога",
"trend_easing": "Віддаляється від порога",
"split_select_hint": "Виберіть завдання, щоб побачити тут його деталі",
"setups_target_new": "Створити новий: {name}", "setups_target_new": "Створити новий: {name}",
"schedule_preview_title": "Найближчі дати", "schedule_preview_title": "Найближчі дати",
"schedule_preview_ontime": "За умови вчасного виконання.", "schedule_preview_ontime": "За умови вчасного виконання.",
@@ -927,5 +933,7 @@
"history_add_past": "Додати минуле виконання", "history_add_past": "Додати минуле виконання",
"require_tag_scan": "Завершення лише скануванням мітки", "require_tag_scan": "Завершення лише скануванням мітки",
"require_tag_scan_help": "Підтвердження присутності: «Готово» заблоковано всюди, доки не відскановано NFC-мітку або QR-код на самому пристрої. Автоматизації можуть передати 'via_tag_scan' службі complete.", "require_tag_scan_help": "Підтвердження присутності: «Готово» заблоковано всюди, доки не відскановано NFC-мітку або QR-код на самому пристрої. Автоматизації можуть передати 'via_tag_scan' службі complete.",
"disallow_skip": "Заборонити пропуск",
"disallow_skip_help": "Дія «Пропустити» зникає з усіх поверхонь, а сервер відхиляє пропуск з автоматизацій і голосу.",
"require_tag_scan_hint": "Це завдання завершується лише скануванням його NFC-мітки або QR-коду на самому пристрої — збереження тут буде відхилено." "require_tag_scan_hint": "Це завдання завершується лише скануванням його NFC-мітки або QR-коду на самому пристрої — збереження тут буде відхилено."
} }
@@ -530,6 +530,7 @@
"groupby_area": "按区域分组", "groupby_area": "按区域分组",
"groupby_group": "按分组", "groupby_group": "按分组",
"groupby_user": "按负责人", "groupby_user": "按负责人",
"groupby_object": "按对象",
"filter_label": "过滤器", "filter_label": "过滤器",
"user_label": "用户", "user_label": "用户",
"photo_label": "照片", "photo_label": "照片",
@@ -834,6 +835,11 @@
"baseline_current_effective": "当前生效的起始读数:{value}", "baseline_current_effective": "当前生效的起始读数:{value}",
"runtime_on_states": "活动状态", "runtime_on_states": "活动状态",
"runtime_on_states_help": "计入运行时间的状态 — 默认:on。例如 mowing、cleaning、printing。选择了属性时将比较该属性的值。", "runtime_on_states_help": "计入运行时间的状态 — 默认:on。例如 mowing、cleaning、printing。选择了属性时将比较该属性的值。",
"runtime_max_session": "单次运行最长时间(秒)",
"runtime_max_session_help": "单次运行最多计入这么多秒——防止传感器卡在开启状态(连接丢失、重启)。留空 = 不限制。",
"trend_approaching": "正接近阈值",
"trend_easing": "正远离阈值",
"split_select_hint": "选择一个任务,在此查看详情",
"setups_target_new": "新建:{name}", "setups_target_new": "新建:{name}",
"schedule_preview_title": "下次日期", "schedule_preview_title": "下次日期",
"schedule_preview_ontime": "假设按时完成。", "schedule_preview_ontime": "假设按时完成。",
@@ -927,5 +933,7 @@
"history_add_past": "补录过去的完成记录", "history_add_past": "补录过去的完成记录",
"require_tag_scan": "仅可通过扫描标签完成", "require_tag_scan": "仅可通过扫描标签完成",
"require_tag_scan_help": "在场证明:在扫描设备上的 NFC 标签或二维码之前,所有界面的“完成”均被阻止。自动化可向 complete 服务传递 'via_tag_scan'。", "require_tag_scan_help": "在场证明:在扫描设备上的 NFC 标签或二维码之前,所有界面的“完成”均被阻止。自动化可向 complete 服务传递 'via_tag_scan'。",
"disallow_skip": "不允许跳过",
"disallow_skip_help": "跳过操作将从所有界面消失,服务器也会拒绝来自自动化和语音的跳过。",
"require_tag_scan_hint": "此任务只能通过扫描设备上的 NFC 标签或二维码来完成——在此保存将被拒绝。" "require_tag_scan_hint": "此任务只能通过扫描设备上的 NFC 标签或二维码来完成——在此保存将被拒绝。"
} }
@@ -1,9 +1,9 @@
/*! maintenance_supporter frontend 2.70.0 */ /*! maintenance_supporter frontend 2.71.0 */
var Tt=Object.defineProperty;var cs=Object.getOwnPropertyDescriptor;var w=(r,s,e)=>()=>{if(e)throw e[0];try{return r&&(s=r(r=0)),s}catch(t){throw e=[t],t}};var ds=(r,s)=>{for(var e in s)Tt(r,e,{get:s[e],enumerable:!0})};var c=(r,s,e,t)=>{for(var i=t>1?void 0:t?cs(s,e):s,n=r.length-1,o;n>=0;n--)(o=r[n])&&(i=(t?o(s,e,i):o(i))||i);return t&&i&&Tt(s,e,i),i};var Me,Oe,Xe,Ct,xe,It,S,Pt,et,tt=w(()=>{Me=globalThis,Oe=Me.ShadowRoot&&(Me.ShadyCSS===void 0||Me.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Xe=Symbol(),Ct=new WeakMap,xe=class{constructor(s,e,t){if(this._$cssResult$=!0,t!==Xe)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=s,this.t=e}get styleSheet(){let s=this.o,e=this.t;if(Oe&&s===void 0){let t=e!==void 0&&e.length===1;t&&(s=Ct.get(e)),s===void 0&&((this.o=s=new CSSStyleSheet).replaceSync(this.cssText),t&&Ct.set(e,s))}return s}toString(){return this.cssText}},It=r=>new xe(typeof r=="string"?r:r+"",void 0,Xe),S=(r,...s)=>{let e=r.length===1?r[0]:s.reduce((t,i,n)=>t+(o=>{if(o._$cssResult$===!0)return o.cssText;if(typeof o=="number")return o;throw Error("Value passed to 'css' function must be a 'css' function result: "+o+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+r[n+1],r[0]);return new xe(e,r,Xe)},Pt=(r,s)=>{if(Oe)r.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of s){let t=document.createElement("style"),i=Me.litNonce;i!==void 0&&t.setAttribute("nonce",i),t.textContent=e.cssText,r.appendChild(t)}},et=Oe?r=>r:r=>r instanceof CSSStyleSheet?(s=>{let e="";for(let t of s.cssRules)e+=t.cssText;return It(e)})(r):r});var ps,us,hs,_s,gs,ms,ze,Lt,fs,vs,we,$e,Fe,qt,Y,ke=w(()=>{tt();tt();({is:ps,defineProperty:us,getOwnPropertyDescriptor:hs,getOwnPropertyNames:_s,getOwnPropertySymbols:gs,getPrototypeOf:ms}=Object),ze=globalThis,Lt=ze.trustedTypes,fs=Lt?Lt.emptyScript:"",vs=ze.reactiveElementPolyfillSupport,we=(r,s)=>r,$e={toAttribute(r,s){switch(s){case Boolean:r=r?fs:null;break;case Object:case Array:r=r==null?r:JSON.stringify(r)}return r},fromAttribute(r,s){let e=r;switch(s){case Boolean:e=r!==null;break;case Number:e=r===null?null:Number(r);break;case Object:case Array:try{e=JSON.parse(r)}catch{e=null}}return e}},Fe=(r,s)=>!ps(r,s),qt={attribute:!0,type:String,converter:$e,reflect:!1,useDefault:!1,hasChanged:Fe};Symbol.metadata??=Symbol("metadata"),ze.litPropertyMetadata??=new WeakMap;Y=class extends HTMLElement{static addInitializer(s){this._$Ei(),(this.l??=[]).push(s)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(s,e=qt){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(s)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(s,e),!e.noAccessor){let t=Symbol(),i=this.getPropertyDescriptor(s,t,e);i!==void 0&&us(this.prototype,s,i)}}static getPropertyDescriptor(s,e,t){let{get:i,set:n}=hs(this.prototype,s)??{get(){return this[e]},set(o){this[e]=o}};return{get:i,set(o){let p=i?.call(this);n?.call(this,o),this.requestUpdate(s,p,t)},configurable:!0,enumerable:!0}}static getPropertyOptions(s){return this.elementProperties.get(s)??qt}static _$Ei(){if(this.hasOwnProperty(we("elementProperties")))return;let s=ms(this);s.finalize(),s.l!==void 0&&(this.l=[...s.l]),this.elementProperties=new Map(s.elementProperties)}static finalize(){if(this.hasOwnProperty(we("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(we("properties"))){let e=this.properties,t=[..._s(e),...gs(e)];for(let i of t)this.createProperty(i,e[i])}let s=this[Symbol.metadata];if(s!==null){let e=litPropertyMetadata.get(s);if(e!==void 0)for(let[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(let[e,t]of this.elementProperties){let i=this._$Eu(e,t);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(s){let e=[];if(Array.isArray(s)){let t=new Set(s.flat(1/0).reverse());for(let i of t)e.unshift(et(i))}else s!==void 0&&e.push(et(s));return e}static _$Eu(s,e){let t=e.attribute;return t===!1?void 0:typeof t=="string"?t:typeof s=="string"?s.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(s=>this.enableUpdating=s),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(s=>s(this))}addController(s){(this._$EO??=new Set).add(s),this.renderRoot!==void 0&&this.isConnected&&s.hostConnected?.()}removeController(s){this._$EO?.delete(s)}_$E_(){let s=new Map,e=this.constructor.elementProperties;for(let t of e.keys())this.hasOwnProperty(t)&&(s.set(t,this[t]),delete this[t]);s.size>0&&(this._$Ep=s)}createRenderRoot(){let s=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Pt(s,this.constructor.elementStyles),s}connectedCallback(){this.renderRoot??=thiLine truncated var Tt=Object.defineProperty;var cs=Object.getOwnPropertyDescriptor;var w=(r,s,e)=>()=>{if(e)throw e[0];try{return r&&(s=r(r=0)),s}catch(t){throw e=[t],t}};var ds=(r,s)=>{for(var e in s)Tt(r,e,{get:s[e],enumerable:!0})};var c=(r,s,e,t)=>{for(var i=t>1?void 0:t?cs(s,e):s,n=r.length-1,o;n>=0;n--)(o=r[n])&&(i=(t?o(s,e,i):o(i))||i);return t&&i&&Tt(s,e,i),i};var Me,Oe,Xe,It,xe,Ct,S,Pt,et,tt=w(()=>{Me=globalThis,Oe=Me.ShadowRoot&&(Me.ShadyCSS===void 0||Me.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Xe=Symbol(),It=new WeakMap,xe=class{constructor(s,e,t){if(this._$cssResult$=!0,t!==Xe)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=s,this.t=e}get styleSheet(){let s=this.o,e=this.t;if(Oe&&s===void 0){let t=e!==void 0&&e.length===1;t&&(s=It.get(e)),s===void 0&&((this.o=s=new CSSStyleSheet).replaceSync(this.cssText),t&&It.set(e,s))}return s}toString(){return this.cssText}},Ct=r=>new xe(typeof r=="string"?r:r+"",void 0,Xe),S=(r,...s)=>{let e=r.length===1?r[0]:s.reduce((t,i,n)=>t+(o=>{if(o._$cssResult$===!0)return o.cssText;if(typeof o=="number")return o;throw Error("Value passed to 'css' function must be a 'css' function result: "+o+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+r[n+1],r[0]);return new xe(e,r,Xe)},Pt=(r,s)=>{if(Oe)r.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of s){let t=document.createElement("style"),i=Me.litNonce;i!==void 0&&t.setAttribute("nonce",i),t.textContent=e.cssText,r.appendChild(t)}},et=Oe?r=>r:r=>r instanceof CSSStyleSheet?(s=>{let e="";for(let t of s.cssRules)e+=t.cssText;return Ct(e)})(r):r});var ps,us,hs,_s,gs,ms,ze,Lt,fs,vs,we,$e,Fe,qt,Y,ke=w(()=>{tt();tt();({is:ps,defineProperty:us,getOwnPropertyDescriptor:hs,getOwnPropertyNames:_s,getOwnPropertySymbols:gs,getPrototypeOf:ms}=Object),ze=globalThis,Lt=ze.trustedTypes,fs=Lt?Lt.emptyScript:"",vs=ze.reactiveElementPolyfillSupport,we=(r,s)=>r,$e={toAttribute(r,s){switch(s){case Boolean:r=r?fs:null;break;case Object:case Array:r=r==null?r:JSON.stringify(r)}return r},fromAttribute(r,s){let e=r;switch(s){case Boolean:e=r!==null;break;case Number:e=r===null?null:Number(r);break;case Object:case Array:try{e=JSON.parse(r)}catch{e=null}}return e}},Fe=(r,s)=>!ps(r,s),qt={attribute:!0,type:String,converter:$e,reflect:!1,useDefault:!1,hasChanged:Fe};Symbol.metadata??=Symbol("metadata"),ze.litPropertyMetadata??=new WeakMap;Y=class extends HTMLElement{static addInitializer(s){this._$Ei(),(this.l??=[]).push(s)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(s,e=qt){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(s)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(s,e),!e.noAccessor){let t=Symbol(),i=this.getPropertyDescriptor(s,t,e);i!==void 0&&us(this.prototype,s,i)}}static getPropertyDescriptor(s,e,t){let{get:i,set:n}=hs(this.prototype,s)??{get(){return this[e]},set(o){this[e]=o}};return{get:i,set(o){let p=i?.call(this);n?.call(this,o),this.requestUpdate(s,p,t)},configurable:!0,enumerable:!0}}static getPropertyOptions(s){return this.elementProperties.get(s)??qt}static _$Ei(){if(this.hasOwnProperty(we("elementProperties")))return;let s=ms(this);s.finalize(),s.l!==void 0&&(this.l=[...s.l]),this.elementProperties=new Map(s.elementProperties)}static finalize(){if(this.hasOwnProperty(we("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(we("properties"))){let e=this.properties,t=[..._s(e),...gs(e)];for(let i of t)this.createProperty(i,e[i])}let s=this[Symbol.metadata];if(s!==null){let e=litPropertyMetadata.get(s);if(e!==void 0)for(let[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(let[e,t]of this.elementProperties){let i=this._$Eu(e,t);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(s){let e=[];if(Array.isArray(s)){let t=new Set(s.flat(1/0).reverse());for(let i of t)e.unshift(et(i))}else s!==void 0&&e.push(et(s));return e}static _$Eu(s,e){let t=e.attribute;return t===!1?void 0:typeof t=="string"?t:typeof s=="string"?s.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(s=>this.enableUpdating=s),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(s=>s(this))}addController(s){(this._$EO??=new Set).add(s),this.renderRoot!==void 0&&this.isConnected&&s.hostConnected?.()}removeController(s){this._$EO?.delete(s)}_$E_(){let s=new Map,e=this.constructor.elementProperties;for(let t of e.keys())this.hasOwnProperty(t)&&(s.set(t,this[t]),delete this[t]);s.size>0&&(this._$Ep=s)}createRenderRoot(){let s=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Pt(s,this.constructor.elementStyles),s}connectedCallback(){this.renderRoot??=thiLine truncated
\f\r]`,Ee=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,jt=/-->/g,Ht=/>/g,re=RegExp(`>|${it}(?:([^\\s"'>=/]+)(${it}*=${it}*(?:[^ \f\r]`,Ee=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Nt=/-->/g,Ht=/>/g,re=RegExp(`>|${it}(?:([^\\s"'>=/]+)(${it}*=${it}*(?:[^
\f\r"'\`<>=]|("|')|))|$)`,"g"),Dt=/'/g,Mt=/"/g,Ut=/^(?:script|style|textarea|title)$/i,dt=r=>(s,...e)=>({_$litType$:r,strings:s,values:e}),l=dt(1),_e=dt(2),Ar=dt(3),oe=Symbol.for("lit-noChange"),_=Symbol.for("lit-nothing"),Ot=new WeakMap,ae=ne.createTreeWalker(ne,129);xs=(r,s)=>{let e=r.length-1,t=[],i,n=s===2?"<svg>":s===3?"<math>":"",o=Ee;for(let p=0;p<e;p++){let d=r[p],u,m,f=-1,v=0;for(;v<d.length&&(o.lastIndex=v,m=o.exec(d),m!==null);)v=o.lastIndex,o===Ee?m[1]==="!--"?o=jt:m[1]!==void 0?o=Ht:m[2]!==void 0?(Ut.test(m[2])&&(i=RegExp("</"+m[2],"g")),o=re):m[3]!==void 0&&(o=re):o===re?m[0]===">"?(o=i??Ee,f=-1):m[1]===void 0?f=-2:(f=o.lastIndex-m[2].length,u=m[1],o=m[3]===void 0?re:m[3]==='"'?Mt:Dt):o===Mt||o===Dt?o=re:o===jt||o===Ht?o=Ee:(o=re,i=void 0);let y=o===re&&r[p+1].startsWith("/>")?" ":"";n+=o===Ee?d+ys:f>=0?(t.push(u),d.slice(0,f)+zt+d.slice(f)+ie+y):d+ie+(f===-2?p:y)}return[Bt(r,n+(r[e]||"<?>")+(s===2?"</svg>":s===3?"</math>":"")),t]},Te=class r{constructor({strings:s,_$litType$:e},t){let i;this.parts=[];let n=0,o=0,p=s.length-1,d=this.parts,[u,m]=xs(s,e);if(this.el=r.createElement(u,t),ae.currentNode=this.el.content,e===2||e===3){let f=this.el.content.firstChild;f.replaceWith(...f.childNodes)}for(;(i=ae.nextNode())!==null&&d.length<p;){if(i.nodeType===1){if(i.hasAttributes())for(let f of i.getAttributeNames())if(f.endsWith(zt)){let v=m[o++],y=i.getAttribute(f).split(ie),k=/([.?@])?(.*)/.exec(v);d.push({type:1,index:n,name:k[2],strings:y,ctor:k[1]==="."?rt:k[1]==="?"?at:k[1]==="@"?nt:he}),i.removeAttribute(f)}else f.startsWith(ie)&&(d.push({type:6,index:n}),i.removeAttribute(f));if(Ut.test(i.tagName)){let f=i.textContent.split(ie),v=f.length-1;if(v>0){i.textContent=Ue?Ue.emptyScript:"";for(let y=0;y<v;y++)i.append(f[y],Se()),ae.nextNode(),d.push({type:2,index:++n});i.append(f[v],Se())}}}else if(i.nodeType===8)if(i.data===Ft)d.push({type:2,index:n});else{let f=-1;for(;(f=i.data.indexOf(ie,f+1))!==-1;)d.push({type:7,index:n}),f+=ie.length-1}n++}}static createElement(s,e){let t=ne.createElement("template");return t.innerHTML=s,t}};st=class{constructor(s,e){this._$AV=[],this._$AN=void 0,this._$AD=s,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(s){let{el:{content:e},parts:t}=this._$AD,i=(s?.creationScope??ne).importNode(e,!0);ae.currentNode=i;let n=ae.nextNode(),o=0,p=0,d=t[0];for(;d!==void 0;){if(o===d.index){let u;d.type===2?u=new Ce(n,n.nextSibling,this,s):d.type===1?u=new d.ctor(n,d.name,d.strings,this,s):d.type===6&&(u=new ot(n,this,s)),this._$AV.push(u),d=t[++p]}o!==d?.index&&(n=ae.nextNode(),o++)}return ae.currentNode=ne,i}p(s){let e=0;for(let t of this._$AV)t!==void 0&&(t.strings!==void 0?(t._$AI(s,t,e),e+=t.strings.length-2):t._$AI(s[e])),e++}},Ce=class r{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(s,e,t,i){this.type=2,this._$AH=_,this._$AN=void 0,this._$AA=s,this._$AB=e,this._$AM=t,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let s=this._$AA.parentNode,e=this._$AM;return e!==void 0&&s?.nodeType===11&&(s=e.parentNode),s}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(s,e=this){s=ue(this,s,e),Ae(s)?s===_||s==null||s===""?(this._$AH!==_&&this._$AR(),this._$AH=_):s!==this._$AH&&s!==oe&&this._(s):s._$litType$!==void 0?this.$(s):s.nodeType!==void 0?this.T(s):bs(s)?this.k(s):this._(s)}O(s){return this._$AA.parentNode.insertBefore(s,this._$AB)}T(s){this._$AH!==s&&(this._$AR(),this._$AH=this.O(s))}_(s){this._$AH!==_&&Ae(this._$AH)?this._$AA.nextSibling.data=s:this.T(ne.createTextNode(s)),this._$AH=s}$(s){let{values:e,_$litType$:t}=s,i=typeof t=="number"?this._$AC(s):(t.el===void 0&&(t.el=Te.createElement(Bt(t.h,t.h[0]),this.options)),t);if(this._$AH?._$AD===i)this._$AH.p(e);else{let n=new st(i,this),o=n.u(this.options);n.p(e),this.T(o),this._$AH=n}}_$AC(s){let e=Ot.get(s.strings);return e===void 0&&Ot.set(s.strings,e=new Te(s)),e}k(s){ct(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,t,i=0;for(let n of s)i===e.length?e.push(t=new r(this.O(Se()),this.O(Se()),this,this.options)):t=e[i],t._$AI(n),i++;i<e.length&&(this._$AR(t&&t._$AB.nextSibling,i),e.length=i)}_$AR(s=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);s!==this._$AB;){let t=Rt(s).nextSibling;Rt(s).remove(),s=t}}setConnected(s){this._$AM===void 0&&(this._$Cv=s,this._$AP?.(s))}},he=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(s,e,t,i,n){this.type=1,this._$AH=_,this._$AN=void 0,this.element=s,this.name=e,this._$AM=i,this.options=n,t.length>2||t[0]!==""||t[1]!==""?(this._$AH=Array(t.length-1).fill(new String),this.strings=t):this._$AH=_}_$AI(s,e=this,t,i){let n=this.strings,o=!1;if(n===void 0)s=ue(this,s,e,0),o=!Ae(s)||s!==this._$AH&&s!==oe,o&&(this._$AH=s);else{let p=s,d,u;for(s=n[0],d=0;d<n.length-1;d++)u=ue(this,p[t+d],e,d),u===oe&&(u=this._$AH[d]),o||=!Ae(u)||u!==this._$AH[d],u===_?s=_:s!==_&&(s+=(u??"")+n[d+1]),this._$AH[d]=u}o&&!i&&this.j(s)}j(s){s===_?this.element.removeAttribute(this.naLine truncated \f\r"'\`<>=]|("|')|))|$)`,"g"),Dt=/'/g,Mt=/"/g,Ut=/^(?:script|style|textarea|title)$/i,dt=r=>(s,...e)=>({_$litType$:r,strings:s,values:e}),l=dt(1),_e=dt(2),Ar=dt(3),oe=Symbol.for("lit-noChange"),_=Symbol.for("lit-nothing"),Ot=new WeakMap,ae=ne.createTreeWalker(ne,129);xs=(r,s)=>{let e=r.length-1,t=[],i,n=s===2?"<svg>":s===3?"<math>":"",o=Ee;for(let p=0;p<e;p++){let d=r[p],u,m,f=-1,v=0;for(;v<d.length&&(o.lastIndex=v,m=o.exec(d),m!==null);)v=o.lastIndex,o===Ee?m[1]==="!--"?o=Nt:m[1]!==void 0?o=Ht:m[2]!==void 0?(Ut.test(m[2])&&(i=RegExp("</"+m[2],"g")),o=re):m[3]!==void 0&&(o=re):o===re?m[0]===">"?(o=i??Ee,f=-1):m[1]===void 0?f=-2:(f=o.lastIndex-m[2].length,u=m[1],o=m[3]===void 0?re:m[3]==='"'?Mt:Dt):o===Mt||o===Dt?o=re:o===Nt||o===Ht?o=Ee:(o=re,i=void 0);let y=o===re&&r[p+1].startsWith("/>")?" ":"";n+=o===Ee?d+ys:f>=0?(t.push(u),d.slice(0,f)+zt+d.slice(f)+ie+y):d+ie+(f===-2?p:y)}return[Bt(r,n+(r[e]||"<?>")+(s===2?"</svg>":s===3?"</math>":"")),t]},Te=class r{constructor({strings:s,_$litType$:e},t){let i;this.parts=[];let n=0,o=0,p=s.length-1,d=this.parts,[u,m]=xs(s,e);if(this.el=r.createElement(u,t),ae.currentNode=this.el.content,e===2||e===3){let f=this.el.content.firstChild;f.replaceWith(...f.childNodes)}for(;(i=ae.nextNode())!==null&&d.length<p;){if(i.nodeType===1){if(i.hasAttributes())for(let f of i.getAttributeNames())if(f.endsWith(zt)){let v=m[o++],y=i.getAttribute(f).split(ie),k=/([.?@])?(.*)/.exec(v);d.push({type:1,index:n,name:k[2],strings:y,ctor:k[1]==="."?rt:k[1]==="?"?at:k[1]==="@"?nt:he}),i.removeAttribute(f)}else f.startsWith(ie)&&(d.push({type:6,index:n}),i.removeAttribute(f));if(Ut.test(i.tagName)){let f=i.textContent.split(ie),v=f.length-1;if(v>0){i.textContent=Ue?Ue.emptyScript:"";for(let y=0;y<v;y++)i.append(f[y],Se()),ae.nextNode(),d.push({type:2,index:++n});i.append(f[v],Se())}}}else if(i.nodeType===8)if(i.data===Ft)d.push({type:2,index:n});else{let f=-1;for(;(f=i.data.indexOf(ie,f+1))!==-1;)d.push({type:7,index:n}),f+=ie.length-1}n++}}static createElement(s,e){let t=ne.createElement("template");return t.innerHTML=s,t}};st=class{constructor(s,e){this._$AV=[],this._$AN=void 0,this._$AD=s,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(s){let{el:{content:e},parts:t}=this._$AD,i=(s?.creationScope??ne).importNode(e,!0);ae.currentNode=i;let n=ae.nextNode(),o=0,p=0,d=t[0];for(;d!==void 0;){if(o===d.index){let u;d.type===2?u=new Ie(n,n.nextSibling,this,s):d.type===1?u=new d.ctor(n,d.name,d.strings,this,s):d.type===6&&(u=new ot(n,this,s)),this._$AV.push(u),d=t[++p]}o!==d?.index&&(n=ae.nextNode(),o++)}return ae.currentNode=ne,i}p(s){let e=0;for(let t of this._$AV)t!==void 0&&(t.strings!==void 0?(t._$AI(s,t,e),e+=t.strings.length-2):t._$AI(s[e])),e++}},Ie=class r{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(s,e,t,i){this.type=2,this._$AH=_,this._$AN=void 0,this._$AA=s,this._$AB=e,this._$AM=t,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let s=this._$AA.parentNode,e=this._$AM;return e!==void 0&&s?.nodeType===11&&(s=e.parentNode),s}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(s,e=this){s=ue(this,s,e),Ae(s)?s===_||s==null||s===""?(this._$AH!==_&&this._$AR(),this._$AH=_):s!==this._$AH&&s!==oe&&this._(s):s._$litType$!==void 0?this.$(s):s.nodeType!==void 0?this.T(s):bs(s)?this.k(s):this._(s)}O(s){return this._$AA.parentNode.insertBefore(s,this._$AB)}T(s){this._$AH!==s&&(this._$AR(),this._$AH=this.O(s))}_(s){this._$AH!==_&&Ae(this._$AH)?this._$AA.nextSibling.data=s:this.T(ne.createTextNode(s)),this._$AH=s}$(s){let{values:e,_$litType$:t}=s,i=typeof t=="number"?this._$AC(s):(t.el===void 0&&(t.el=Te.createElement(Bt(t.h,t.h[0]),this.options)),t);if(this._$AH?._$AD===i)this._$AH.p(e);else{let n=new st(i,this),o=n.u(this.options);n.p(e),this.T(o),this._$AH=n}}_$AC(s){let e=Ot.get(s.strings);return e===void 0&&Ot.set(s.strings,e=new Te(s)),e}k(s){ct(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,t,i=0;for(let n of s)i===e.length?e.push(t=new r(this.O(Se()),this.O(Se()),this,this.options)):t=e[i],t._$AI(n),i++;i<e.length&&(this._$AR(t&&t._$AB.nextSibling,i),e.length=i)}_$AR(s=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);s!==this._$AB;){let t=Rt(s).nextSibling;Rt(s).remove(),s=t}}setConnected(s){this._$AM===void 0&&(this._$Cv=s,this._$AP?.(s))}},he=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(s,e,t,i,n){this.type=1,this._$AH=_,this._$AN=void 0,this.element=s,this.name=e,this._$AM=i,this.options=n,t.length>2||t[0]!==""||t[1]!==""?(this._$AH=Array(t.length-1).fill(new String),this.strings=t):this._$AH=_}_$AI(s,e=this,t,i){let n=this.strings,o=!1;if(n===void 0)s=ue(this,s,e,0),o=!Ae(s)||s!==this._$AH&&s!==oe,o&&(this._$AH=s);else{let p=s,d,u;for(s=n[0],d=0;d<n.length-1;d++)u=ue(this,p[t+d],e,d),u===oe&&(u=this._$AH[d]),o||=!Ae(u)||u!==this._$AH[d],u===_?s=_:s!==_&&(s+=(u??"")+n[d+1]),this._$AH[d]=u}o&&!i&&this.j(s)}j(s){s===_?this.element.removeAttribute(this.naLine truncated
Replace seal Replace seal
Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"{field}: too long (max {n} characters)",err_too_short:"{field}: too short (min {n} characters)",err_value_too_high:"{field}: too large (max {n})",err_value_too_low:"{field}: too small (min {n})",err_required:"{field}: required",err_wrong_type:"{field}: wrong type (expected: {type})",err_invalid_choice:"{field}: not an allowed value",err_invalid_value:"{field}: invalid value",feat_schedule_time:"Time-of-day scheduling",feat_schedule_time_desc:"Tasks become overdue at a specific time of day instead of midnight.",schedule_time_optional:"Due at time (optional, HH:MM)",schedule_time_help:"Empty = midnight (default). HA timezone.",at_time:"at",notes_optional:"Notes (optional)",notes_markdown_hint:"Markdown is supported \u2014 **bold**, lists, [links](\u2026)",cost_optional:"Cost (optional)",duration_minutes:"Duration in minutes (optional)",completed_at_optional:"Completed at (optional, empty = now)",completed_at_future_error:"The completion date cannot be in the future.",days:"days",day:"day",today:"Today",d_overdue:"d overdue",no_tasks:"No maintenance tasks yet. Create an object to get started.",no_tasks_short:"No tasks",no_history:"No history entries yet.",show_all:"Show all",cost_duration_chart:"Cost & Duration",installed:"Installed",confirm_delete_object:"Delete this object and all its tasks?",confirm_delete_task:"Delete this task?",min:"Min",max:"Max",save:"Save",saving:"Saving\u2026",edit_task:"Edit Task",new_task:"New Maintenance Task",task_name:"Task name",maintenance_type:"Maintenance type",priority:"Priority",labels:"Labels",labels_placeholder:"e.g. safety, seasonal, tenant-visible",labels_help:"Comma-separated tags for filtering and reporting.",priority_low:"Low",priority_normal:"Normal",priority_high:"High",all_priorities:"All priorities",schedule_type:"Schedule type",interval_days:"Interval (days)",warning_days:"Warning days",earliest_completion_days:"Earliest completion (days before due)",earliest_completion_days_help:"Leave empty to allow completing any time. 0 = only on/after the due date.",last_performed_optional:"Last performed (optional)",interval_anchor:"Interval anchor",anchor_completion:"From completion date",anchor_planned:"From planned date (no drift)",edit_object:"Edit Object",name:"Name",manufacturer_optional:"Manufacturer (optional)",model_optional:"Model (optional)",serial_number_optional:"Serial number (optional)",serial_number_label:"S/N",documentation_url_label:"Manual",object_notes_label:"Notes",sort_due_date:"Due date",sort_object:"Object name",sort_type:"Type",sort_task_name:"Task name",all_objects:"All objects",all_parts:"All parts",tasks_lower:"tasks",no_tasks_yet:"No tasks yet",add_first_task:"Add first task",trigger_configuration:"Trigger Configuration",entity_id:"Entity ID",comma_separated:"comma-separated",entity_logic:"Entity logic",entity_logic_any:"Any entity triggers",entity_logic_all:"All entities must trigger",entities:"entities",attribute_optional:"Attribute (optional, blank = state)",use_entity_state:"Use entity state (no attribute)",trigger_above:"Trigger above",trigger_below:"Trigger below",trigger_equals:"Trigger when equal to (=)",trigger_not_equals:"Trigger when different from (\u2260)",for_at_least_minutes:"For at least (minutes)",safety_interval_days:"Safety interval (days, optional)",safety_interval:"Safety interval (optional)",trigger_combinator:"Combine trigger and interval",trigger_combinator_any:"Trigger or interval (whichever first)",trigger_combinator_all:"Trigger and interval (both required)",delta_mode:"Delta mode",from_state_optional:"From state (optional)",to_state_optional:"To state (optional)",documentation_url_optional:"Documentation URL (optional)",object_notes_optional:"Notes (optional)",nfc_tag_id_optional:"NFC Tag ID (optional)",nfc_tags_empty_help:"No NFC tags registered in Home Assistant yet.",nfc_tags_open_settings:"Open Tags settings",nfc_tags_refresh:"Refresh",environmental_entity_optional:"Environmental sensor (optional)",environmental_entity_helper:"e.g. sensor.outdoor_temperature \u2014 adjusts the interval based on environmental conditions",adaptive_prediction_enabled:"Enable sensor-driven predictions",adaptive_seasonal_enabled:"Enable seasonal awareness",adaptive_max_interval:"Maximum interval (days)",adaptive_min_interval:"Minimum interval (days)",adaptive_ewa_alpha:"Learning rate (alpha)",adaptive_enabled:"Enable adaptive scheduling",adaptive_section_title:"Adaptive Scheduling",environmental_attribute_optional:"Environmental attribute (optional)",nfc_tag_id:"NFC Tag ID",nfc_linked:"NFC tag linked",nfc_link_hint:"Click to link NFC tag",responsible_user:"Responsible User",shared_with:"Shared with (rotation)",shared_with_help:"Pick multiple people to share this task; the responsible person rotates on each completion.",rotation_strategy:"Rotation",rotation_none:"No rotation",rotation_round_robin:"Round-robin",rotation_least_completed:"Least completed",ro Line truncated Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"{field}: too long (max {n} characters)",err_too_short:"{field}: too short (min {n} characters)",err_value_too_high:"{field}: too large (max {n})",err_value_too_low:"{field}: too small (min {n})",err_required:"{field}: required",err_wrong_type:"{field}: wrong type (expected: {type})",err_invalid_choice:"{field}: not an allowed value",err_invalid_value:"{field}: invalid value",feat_schedule_time:"Time-of-day scheduling",feat_schedule_time_desc:"Tasks become overdue at a specific time of day instead of midnight.",schedule_time_optional:"Due at time (optional, HH:MM)",schedule_time_help:"Empty = midnight (default). HA timezone.",at_time:"at",notes_optional:"Notes (optional)",notes_markdown_hint:"Markdown is supported \u2014 **bold**, lists, [links](\u2026)",cost_optional:"Cost (optional)",duration_minutes:"Duration in minutes (optional)",completed_at_optional:"Completed at (optional, empty = now)",completed_at_future_error:"The completion date cannot be in the future.",days:"days",day:"day",today:"Today",d_overdue:"d overdue",no_tasks:"No maintenance tasks yet. Create an object to get started.",no_tasks_short:"No tasks",no_history:"No history entries yet.",show_all:"Show all",cost_duration_chart:"Cost & Duration",installed:"Installed",confirm_delete_object:"Delete this object and all its tasks?",confirm_delete_task:"Delete this task?",min:"Min",max:"Max",save:"Save",saving:"Saving\u2026",edit_task:"Edit Task",new_task:"New Maintenance Task",task_name:"Task name",maintenance_type:"Maintenance type",priority:"Priority",labels:"Labels",labels_placeholder:"e.g. safety, seasonal, tenant-visible",labels_help:"Comma-separated tags for filtering and reporting.",priority_low:"Low",priority_normal:"Normal",priority_high:"High",all_priorities:"All priorities",schedule_type:"Schedule type",interval_days:"Interval (days)",warning_days:"Warning days",earliest_completion_days:"Earliest completion (days before due)",earliest_completion_days_help:"Leave empty to allow completing any time. 0 = only on/after the due date.",last_performed_optional:"Last performed (optional)",interval_anchor:"Interval anchor",anchor_completion:"From completion date",anchor_planned:"From planned date (no drift)",edit_object:"Edit Object",name:"Name",manufacturer_optional:"Manufacturer (optional)",model_optional:"Model (optional)",serial_number_optional:"Serial number (optional)",serial_number_label:"S/N",documentation_url_label:"Manual",object_notes_label:"Notes",sort_due_date:"Due date",sort_object:"Object name",sort_type:"Type",sort_task_name:"Task name",all_objects:"All objects",all_parts:"All parts",tasks_lower:"tasks",no_tasks_yet:"No tasks yet",add_first_task:"Add first task",trigger_configuration:"Trigger Configuration",entity_id:"Entity ID",comma_separated:"comma-separated",entity_logic:"Entity logic",entity_logic_any:"Any entity triggers",entity_logic_all:"All entities must trigger",entities:"entities",attribute_optional:"Attribute (optional, blank = state)",use_entity_state:"Use entity state (no attribute)",trigger_above:"Trigger above",trigger_below:"Trigger below",trigger_equals:"Trigger when equal to (=)",trigger_not_equals:"Trigger when different from (\u2260)",for_at_least_minutes:"For at least (minutes)",safety_interval_days:"Safety interval (days, optional)",safety_interval:"Safety interval (optional)",trigger_combinator:"Combine trigger and interval",trigger_combinator_any:"Trigger or interval (whichever first)",trigger_combinator_all:"Trigger and interval (both required)",delta_mode:"Delta mode",from_state_optional:"From state (optional)",to_state_optional:"To state (optional)",documentation_url_optional:"Documentation URL (optional)",object_notes_optional:"Notes (optional)",nfc_tag_id_optional:"NFC Tag ID (optional)",nfc_tags_empty_help:"No NFC tags registered in Home Assistant yet.",nfc_tags_open_settings:"Open Tags settings",nfc_tags_refresh:"Refresh",environmental_entity_optional:"Environmental sensor (optional)",environmental_entity_helper:"e.g. sensor.outdoor_temperature \u2014 adjusts the interval based on environmental conditions",adaptive_prediction_enabled:"Enable sensor-driven predictions",adaptive_seasonal_enabled:"Enable seasonal awareness",adaptive_max_interval:"Maximum interval (days)",adaptive_min_interval:"Minimum interval (days)",adaptive_ewa_alpha:"Learning rate (alpha)",adaptive_enabled:"Enable adaptive scheduling",adaptive_section_title:"Adaptive Scheduling",environmental_attribute_optional:"Environmental attribute (optional)",nfc_tag_id:"NFC Tag ID",nfc_linked:"NFC tag linked",nfc_link_hint:"Click to link NFC tag",responsible_user:"Responsible User",shared_with:"Shared with (rotation)",shared_with_help:"Pick multiple people to share this task; the responsible person rotates on each completion.",rotation_strategy:"Rotation",rotation_none:"No rotation",rotation_round_robin:"Round-robin",rotation_least_completed:"Least completed",ro Line truncated
.field { display: flex; flex-direction: column; gap: 4px; } .field { display: flex; flex-direction: column; gap: 4px; }
.field-label { font-size: 12px; color: var(--secondary-text-color); } .field-label { font-size: 12px; color: var(--secondary-text-color); }
.field-input { .field-input {
@@ -531,8 +531,15 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 2px; gap: 2px;
/* #150 follow-up (2026-08-31, maisun's mobile screenshot): the box used
to carry min-width: 90px — in the narrow grid the due column is
fit-content(100px) and right-aligned, so on cells narrower than 90px
the box overhung LEFT across the object name. It now tracks the cell
with no floor, and the label ellipsizes inside. */
align-self: stretch;
max-width: 100%;
min-width: 0;
width: 100%; width: 100%;
min-width: 90px;
} }
.trigger-progress-bar { .trigger-progress-bar {
@@ -553,8 +560,25 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
font-size: 12px; font-size: 12px;
color: var(--secondary-text-color); color: var(--secondary-text-color);
text-align: right; text-align: right;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
/* #150 follow-up: 3-state trend arrow — replaces the sparkline on
narrow/tight rows (panel-styles toggles visibility per regime). */
.trend-arrow {
display: none;
font-style: normal;
font-weight: 700;
margin-left: 2px;
}
.trend-approaching { color: var(--warning-color, #ff9800); }
.trend-stable { color: var(--secondary-text-color); }
.trend-easing { color: var(--success-color, #4caf50); }
/* Days progress bar (detail view) */ /* Days progress bar (detail view) */
.days-progress { .days-progress {
margin: 8px 0 16px; margin: 8px 0 16px;
@@ -597,6 +621,11 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
/* Mini-sparkline in overview rows */ /* Mini-sparkline in overview rows */
.mini-sparkline { .mini-sparkline {
width: 60px; width: 60px;
/* Same class of bug as the trigger-progress floor (#150 follow-up): in
due cells narrower than the fixed width the right-aligned SVG used to
overhang LEFT (phone-360 sweep). preserveAspectRatio="none" lets it
just squeeze. */
max-width: 100%;
height: 20px; height: 20px;
display: block; display: block;
margin-top: 2px; margin-top: 2px;
@@ -1149,7 +1178,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
.stat-item .stat-label { font-size: 11px; white-space: normal; text-align: center; line-height: 1.2; } .stat-item .stat-label { font-size: 11px; white-space: normal; text-align: center; line-height: 1.2; }
.stat-value { font-size: 20px; } .stat-value { font-size: 20px; }
} }
`});function Os(r,s){let e=Ms[r];if(!e)return r;let t=a(e,s);return t&&t!==e?t:r}function zs(r){let e=r.match(/data\['([^']+)'\]/)?.[1],t;return(t=r.match(/length of value must be at most (\d+)/))?{field:e,rule:"too_long",param:t[1]}:(t=r.match(/length of value must be at least (\d+)/))?{field:e,rule:"too_short",param:t[1]}:(t=r.match(/value must be at most (\S+)/))?{field:e,rule:"value_too_high",param:t[1]}:(t=r.match(/value must be at least (\S+)/))?{field:e,rule:"value_too_low",param:t[1]}:/required key not provided/.test(r)?{field:e,rule:"required"}:(t=r.match(/expected (\w+)/))?{field:e,rule:"wrong_type",param:t[1]}:/value must be one of/.test(r)?{field:e,rule:"invalid_choice"}:/not a valid value/.test(r)?{field:e,rule:"invalid_value"}:{field:e,rule:"unknown"}}function j(r,s,e){if(e=e??a("action_error",s),typeof r=="string")return r;if(typeof r!="object"||r===null)return e;let t=r,i=t.message||t.error?.message||"";if(!i)return e;let n=zs(i),o=n.field?Os(n.field,s):"",p=d=>a(d,s).replace("{field}",o).replace("{n}",n.param??"");switch(n.rule){case"too_long":return p("err_too_long");case"too_short":return p("err_too_short");case"value_too_high":return p("err_value_too_high");case"value_too_low":return p("err_value_too_low");case"required":return p("err_required");case"wrong_type":return p("err_wrong_type").replace("{type}",n.param??"");case"invalid_choice":return p("err_invalid_choice");case"invalid_value":return p("err_invalid_value");default:return i||e}}var Ms,de=w(()=>{"use strict";N();Ms={entry_id:"object",name:"name",task_type:"maintenance_type",schedule_type:"schedule_type",interval_days:"interval_days",interval_anchor:"interval_anchor",warning_days:"warning_days",last_performed:"last_performed_optional",notes:"notes_optional",documentation_url:"documentation_url_optional",custom_icon:"custom_icon_optional",nfc_tag_id:"nfc_tag_id_optional",responsible_user_id:"responsible_user",entity_slug:"entity_slug",entity_id:"entity_id",area_id:"area_id_optional",manufacturer:"manufacturer_optional",model:"model_optional",serial_number:"serial_number_optional",installation_date:"installation_date_optional",warranty_expiry:"warranty_expiry_optional",checklist:"checklist_steps_optional",reason:"reason",feedback:"feedback",cost:"cost",duration:"duration",description:"description_optional",group_name:"name",group_description:"description_optional",environmental_entity:"environmental_entity_optional",environmental_attribute:"environmental_attribute_optional",trigger_above:"trigger_above",trigger_below:"trigger_below",trigger_equals:"trigger_equals",trigger_not_equals:"trigger_not_equals",trigger_for_minutes:"trigger_for_minutes"}});var L,gt=w(()=>{"use strict";P();W();L=class extends A{constructor(){super(...arguments);this.label="";this.value="";this.placeholder="";this.type="text";this.required=!1;this.disabled=!1;this.multiline=!1;this.rows=3}_onInput(e){let t=e.target.value;this.value=t,this.dispatchEvent(new CustomEvent("input",{bubbles:!0,composed:!0,detail:{value:t}}))}render(){return l` `});function Os(r,s){let e=Ms[r];if(!e)return r;let t=a(e,s);return t&&t!==e?t:r}function zs(r){let e=r.match(/data\['([^']+)'\]/)?.[1],t;return(t=r.match(/length of value must be at most (\d+)/))?{field:e,rule:"too_long",param:t[1]}:(t=r.match(/length of value must be at least (\d+)/))?{field:e,rule:"too_short",param:t[1]}:(t=r.match(/value must be at most (\S+)/))?{field:e,rule:"value_too_high",param:t[1]}:(t=r.match(/value must be at least (\S+)/))?{field:e,rule:"value_too_low",param:t[1]}:/required key not provided/.test(r)?{field:e,rule:"required"}:(t=r.match(/expected (\w+)/))?{field:e,rule:"wrong_type",param:t[1]}:/value must be one of/.test(r)?{field:e,rule:"invalid_choice"}:/not a valid value/.test(r)?{field:e,rule:"invalid_value"}:{field:e,rule:"unknown"}}function N(r,s,e){if(e=e??a("action_error",s),typeof r=="string")return r;if(typeof r!="object"||r===null)return e;let t=r,i=t.message||t.error?.message||"";if(!i)return e;let n=zs(i),o=n.field?Os(n.field,s):"",p=d=>a(d,s).replace("{field}",o).replace("{n}",n.param??"");switch(n.rule){case"too_long":return p("err_too_long");case"too_short":return p("err_too_short");case"value_too_high":return p("err_value_too_high");case"value_too_low":return p("err_value_too_low");case"required":return p("err_required");case"wrong_type":return p("err_wrong_type").replace("{type}",n.param??"");case"invalid_choice":return p("err_invalid_choice");case"invalid_value":return p("err_invalid_value");default:return i||e}}var Ms,de=w(()=>{"use strict";j();Ms={entry_id:"object",name:"name",task_type:"maintenance_type",schedule_type:"schedule_type",interval_days:"interval_days",interval_anchor:"interval_anchor",warning_days:"warning_days",last_performed:"last_performed_optional",notes:"notes_optional",documentation_url:"documentation_url_optional",custom_icon:"custom_icon_optional",nfc_tag_id:"nfc_tag_id_optional",responsible_user_id:"responsible_user",entity_slug:"entity_slug",entity_id:"entity_id",area_id:"area_id_optional",manufacturer:"manufacturer_optional",model:"model_optional",serial_number:"serial_number_optional",installation_date:"installation_date_optional",warranty_expiry:"warranty_expiry_optional",checklist:"checklist_steps_optional",reason:"reason",feedback:"feedback",cost:"cost",duration:"duration",description:"description_optional",group_name:"name",group_description:"description_optional",environmental_entity:"environmental_entity_optional",environmental_attribute:"environmental_attribute_optional",trigger_above:"trigger_above",trigger_below:"trigger_below",trigger_equals:"trigger_equals",trigger_not_equals:"trigger_not_equals",trigger_for_minutes:"trigger_for_minutes"}});var L,gt=w(()=>{"use strict";P();W();L=class extends A{constructor(){super(...arguments);this.label="";this.value="";this.placeholder="";this.type="text";this.required=!1;this.disabled=!1;this.multiline=!1;this.rows=3}_onInput(e){let t=e.target.value;this.value=t,this.dispatchEvent(new CustomEvent("input",{bubbles:!0,composed:!0,detail:{value:t}}))}render(){return l`
<label class="field"> <label class="field">
${this.label?l`<span class="label">${this.label}${this.required?l`<span class="req">*</span>`:_}</span>`:_} ${this.label?l`<span class="label">${this.label}${this.required?l`<span class="req">*</span>`:_}</span>`:_}
${this.multiline?l` ${this.multiline?l`
@@ -1226,7 +1255,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
color: var(--secondary-text-color); color: var(--secondary-text-color);
font-style: italic; font-style: italic;
} }
`,c([x()],L.prototype,"label",2),c([x()],L.prototype,"value",2),c([x()],L.prototype,"placeholder",2),c([x()],L.prototype,"type",2),c([x({type:Boolean})],L.prototype,"required",2),c([x({type:Boolean})],L.prototype,"disabled",2),c([x()],L.prototype,"step",2),c([x()],L.prototype,"min",2),c([x()],L.prototype,"max",2),c([x()],L.prototype,"pattern",2),c([x()],L.prototype,"helper",2),c([x({type:Boolean})],L.prototype,"multiline",2),c([x({type:Number})],L.prototype,"rows",2);customElements.get("ms-textfield")||customElements.define("ms-textfield",L)});var T,Ei=w(()=>{"use strict";P();W();N();de();gt();T=class extends A{constructor(){super(...arguments);this.objects=[];this._open=!1;this._loading=!1;this._error="";this._name="";this._manufacturer="";this._model="";this._serialNumber="";this._areaId="";this._installationDate="";this._warrantyExpiry="";this._documentationUrl="";this._notes="";this._haDeviceId="";this._parentEntryId="";this._entryId=null}get _lang(){return D(this.hass)}openCreate(){this._entryId=null,this._name="",this._manufacturer="",this._model="",this._serialNumber="",this._areaId="",this._installationDate="",this._warrantyExpiry="",this._documentationUrl="",this._notes="",this._haDeviceId="",this._parentEntryId="",this._error="",this._open=!0}openEdit(e,t){this._entryId=e,this._name=t.name||"",this._manufacturer=t.manufacturer||"",this._model=t.model||"",this._serialNumber=t.serial_number||"",this._areaId=t.area_id||"",this._installationDate=t.installation_date||"",this._warrantyExpiry=t.warranty_expiry||"",this._documentationUrl=t.documentation_url||"",this._notes=t.notes||"",this._haDeviceId=t.ha_device_id||"",this._parentEntryId=t.parent_entry_id||"",this._error="",this._open=!0}async _save(){if(!this._loading&&this._name.trim()){this._loading=!0,this._error="";try{this._entryId?await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/update",entry_id:this._entryId,name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}):await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/create",name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}),this._open=!1,this.dispatchEvent(new CustomEvent("object-saved"))}catch(e){this._error=j(e,this._lang,a("save_error",this._lang))}finally{this._loading=!1}}}_parentChoices(){return(this.objects||[]).filter(e=>e.entry_id!==this._entryId)}_close(){this._open=!1}render(){if(!this._open)return l``;let e=this._lang,t=this._entryId?a("edit_object",e):a("new_object",e);return l` `,c([x()],L.prototype,"label",2),c([x()],L.prototype,"value",2),c([x()],L.prototype,"placeholder",2),c([x()],L.prototype,"type",2),c([x({type:Boolean})],L.prototype,"required",2),c([x({type:Boolean})],L.prototype,"disabled",2),c([x()],L.prototype,"step",2),c([x()],L.prototype,"min",2),c([x()],L.prototype,"max",2),c([x()],L.prototype,"pattern",2),c([x()],L.prototype,"helper",2),c([x({type:Boolean})],L.prototype,"multiline",2),c([x({type:Number})],L.prototype,"rows",2);customElements.get("ms-textfield")||customElements.define("ms-textfield",L)});var T,Ei=w(()=>{"use strict";P();W();j();de();gt();T=class extends A{constructor(){super(...arguments);this.objects=[];this._open=!1;this._loading=!1;this._error="";this._name="";this._manufacturer="";this._model="";this._serialNumber="";this._areaId="";this._installationDate="";this._warrantyExpiry="";this._documentationUrl="";this._notes="";this._haDeviceId="";this._parentEntryId="";this._entryId=null}get _lang(){return D(this.hass)}openCreate(){this._entryId=null,this._name="",this._manufacturer="",this._model="",this._serialNumber="",this._areaId="",this._installationDate="",this._warrantyExpiry="",this._documentationUrl="",this._notes="",this._haDeviceId="",this._parentEntryId="",this._error="",this._open=!0}openEdit(e,t){this._entryId=e,this._name=t.name||"",this._manufacturer=t.manufacturer||"",this._model=t.model||"",this._serialNumber=t.serial_number||"",this._areaId=t.area_id||"",this._installationDate=t.installation_date||"",this._warrantyExpiry=t.warranty_expiry||"",this._documentationUrl=t.documentation_url||"",this._notes=t.notes||"",this._haDeviceId=t.ha_device_id||"",this._parentEntryId=t.parent_entry_id||"",this._error="",this._open=!0}async _save(){if(!this._loading&&this._name.trim()){this._loading=!0,this._error="";try{this._entryId?await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/update",entry_id:this._entryId,name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}):await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/create",name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}),this._open=!1,this.dispatchEvent(new CustomEvent("object-saved"))}catch(e){this._error=N(e,this._lang,a("save_error",this._lang))}finally{this._loading=!1}}}_parentChoices(){return(this.objects||[]).filter(e=>e.entry_id!==this._entryId)}_close(){this._open=!1}render(){if(!this._open)return l``;let e=this._lang,t=this._entryId?a("edit_object",e):a("new_object",e);return l`
<ha-dialog open @closed=${this._close}> <ha-dialog open @closed=${this._close}>
<div class="dialog-title">${t}</div> <div class="dialog-title">${t}</div>
<div class="content"> <div class="content">
@@ -1371,9 +1400,9 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
color: var(--error-color, #f44336); color: var(--error-color, #f44336);
font-size: 13px; font-size: 13px;
} }
`,c([x({attribute:!1})],T.prototype,"hass",2),c([x({attribute:!1})],T.prototype,"objects",2),c([h()],T.prototype,"_open",2),c([h()],T.prototype,"_loading",2),c([h()],T.prototype,"_error",2),c([h()],T.prototype,"_name",2),c([h()],T.prototype,"_manufacturer",2),c([h()],T.prototype,"_model",2),c([h()],T.prototype,"_serialNumber",2),c([h()],T.prototype,"_areaId",2),c([h()],T.prototype,"_installationDate",2),c([h()],T.prototype,"_warrantyExpiry",2),c([h()],T.prototype,"_documentationUrl",2),c([h()],T.prototype,"_notes",2),c([h()],T.prototype,"_haDeviceId",2),c([h()],T.prototype,"_parentEntryId",2),c([h()],T.prototype,"_entryId",2);customElements.get("maintenance-object-dialog")||customElements.define("maintenance-object-dialog",T)});var Qe,Si=w(()=>{"use strict";Qe=class{constructor(s){this.usersCache=null;this.cacheTimestamp=0;this.CACHE_TTL_MS=6e4;this.hass=s}updateHass(s){this.hass=s}async getUsers(s=!1){let e=Date.now();if(!s&&this.usersCache&&e-this.cacheTimestamp<this.CACHE_TTL_MS)return this.usersCache;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/users/list"});return this.usersCache=t.users,this.cacheTimestamp=e,this.usersCache}catch(t){return console.error("Failed to fetch users:",t),this.usersCache||[]}}async assignUser(s,e,t){await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/assign_user",entry_id:s,task_id:e,user_id:t})}async getTasksByUser(s){return(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/tasks/by_user",user_id:s})).tasks}getUserName(s){return!s||!this.usersCache?null:this.usersCache.find(t=>t.id===s)?.name||null}getUser(s){return!s||!this.usersCache?null:this.usersCache.find(e=>e.id===s)||null}getCurrentUserId(){return this.hass.user?.id||null}isCurrentUser(s){return s?s===this.getCurrentUserId():!1}clearCache(){this.usersCache=null,this.cacheTimestamp=0}}});function V(r){return`${r.entry_id??""}\0${r.part_id}`}function Ai(r,s,e,t){let i=!!r.entry_id&&r.entry_id!==s,n=i?r.entry_id:s,o=e.find(m=>m.entry_id===n),p=(o?.parts||[]).find(m=>m.id===r.part_id)||null,d=i&&o?.object?.name||"",u=p?.name||a("shared_part_unknown",t);return{part:p,foreign:i,ownerName:d,label:d?`${u} (${d})`:u}}function Ti(r,s,e,t){let{part:i,label:n}=Ai(r,s,e,t),o=i&&i.stock!==null&&i.stock!==void 0?` (${i.stock}${i.unit?" "+i.unit:""})`:"",p=i?.storage_location?` \u2014 ${i.storage_location}`:"";return`${r.quantity}\xD7 ${n}${o}${p}`}function Ci(r,s,e,t){let n=(e.find(p=>p.entry_id===s)?.parts||[]).map(p=>({...p})),o=new Set(n.map(p=>V({part_id:p.id})));for(let p of r?.consumes_parts||[]){if(!p.entry_id||p.entry_id===s)continue;let d=V(p);if(o.has(d))continue;o.add(d);let{part:u,ownerName:m}=Ai(p,s,e,t);n.push({id:p.part_id,name:u?.name||a("shared_part_unknown",t),unit:u?.unit,stock:u?.stock??null,storage_location:u?.storage_location,entry_id:p.entry_id,owner_name:m})}return n}var Je=w(()=>{"use strict";N()});var mt,Ii,Pi,Li=w(()=>{"use strict";mt=["sensor","binary_sensor","number","input_number","input_boolean","switch","climate","vacuum","cover","fan","light","water_heater","humidifier","media_player","weather","air_quality","valve","lawn_mower","lock"],Ii=["sensor"],Pi=["temperature","humidity","pressure"]});var ft,je,vt=w(()=>{"use strict";ft=["notes","cost","duration","photo","user"],je={notes:"notes_label",cost:"cost",duration:"duration",photo:"photo_label",user:"user_label"}});function Vs(){return{entityIds:"",type:"threshold",attribute:"",above:"",below:"",equals:"",notEquals:"",forMinutes:"0",targetValue:"",deltaMode:!1,fromState:"",toState:"",targetChanges:"",runtimeHours:"",onStates:"",carry:{}}}function Gs(r){return{entityIds:(r.entity_ids||(r.entity_id?[r.entity_id]:[])).join(", "),type:r.type||"threshold",attribute:r.attribute||"",above:r.trigger_above?.toString()??"",below:r.trigger_below?.toString()??"",equals:r.trigger_equals?.toString()??"",notEquals:r.trigger_not_equals?.toString()??"",forMinutes:r.trigger_for_minutes?.toString()??"0",targetValue:r.trigger_target_value?.toString()??"",deltaMode:r.trigger_delta_mode||!1,fromState:r.trigger_from_state||"",toState:r.trigger_to_state||"",targetChanges:r.trigger_target_changes?.toString()??"",runtimeHours:r.trigger_runtime_hours?.toString()??"",onStates:(r.trigger_on_states||[]).join(", "),carry:Object.fromEntries(Object.entries(r).filter(([e])=>!Ks.has(e)&&!e.startsWith("_")))}}function Ys(r){let s=r.entityIds.split(",").map(t=>t.trim()).filter(Boolean);if(s.length===0)return null;let e={...r.carry||{},entity_id:s[0],entity_ids:s,type:r.type};if(r.attribute&&(e.attribute=r.attribute),r.type==="threshold"){let t=parseFloat(r.above);isNaN(t)||(e.trigger_above=t);let i=parseFloat(r.below);isNaN(i)||(e.trigger_below=i);let n=parseFloat(r.equals);isNaN(n)||(e.trigger_equals=n);let o=parseFloat(r.notEquals);isNaN(o)||(e.trigger_not_equals=o);let p=parseInt(r.forMinutes,10);isNaN(p)||(e.trigger_for_minutes=p)}else if(r.type==="counter"){let t=parseFloat(r.targetValu Line truncated `,c([x({attribute:!1})],T.prototype,"hass",2),c([x({attribute:!1})],T.prototype,"objects",2),c([h()],T.prototype,"_open",2),c([h()],T.prototype,"_loading",2),c([h()],T.prototype,"_error",2),c([h()],T.prototype,"_name",2),c([h()],T.prototype,"_manufacturer",2),c([h()],T.prototype,"_model",2),c([h()],T.prototype,"_serialNumber",2),c([h()],T.prototype,"_areaId",2),c([h()],T.prototype,"_installationDate",2),c([h()],T.prototype,"_warrantyExpiry",2),c([h()],T.prototype,"_documentationUrl",2),c([h()],T.prototype,"_notes",2),c([h()],T.prototype,"_haDeviceId",2),c([h()],T.prototype,"_parentEntryId",2),c([h()],T.prototype,"_entryId",2);customElements.get("maintenance-object-dialog")||customElements.define("maintenance-object-dialog",T)});var Qe,Si=w(()=>{"use strict";Qe=class{constructor(s){this.usersCache=null;this.cacheTimestamp=0;this.CACHE_TTL_MS=6e4;this.hass=s}updateHass(s){this.hass=s}async getUsers(s=!1){let e=Date.now();if(!s&&this.usersCache&&e-this.cacheTimestamp<this.CACHE_TTL_MS)return this.usersCache;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/users/list"});return this.usersCache=t.users,this.cacheTimestamp=e,this.usersCache}catch(t){return console.error("Failed to fetch users:",t),this.usersCache||[]}}async assignUser(s,e,t){await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/assign_user",entry_id:s,task_id:e,user_id:t})}async getTasksByUser(s){return(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/tasks/by_user",user_id:s})).tasks}getUserName(s){return!s||!this.usersCache?null:this.usersCache.find(t=>t.id===s)?.name||null}getUser(s){return!s||!this.usersCache?null:this.usersCache.find(e=>e.id===s)||null}getCurrentUserId(){return this.hass.user?.id||null}isCurrentUser(s){return s?s===this.getCurrentUserId():!1}clearCache(){this.usersCache=null,this.cacheTimestamp=0}}});function V(r){return`${r.entry_id??""}\0${r.part_id}`}function Ai(r,s,e,t){let i=!!r.entry_id&&r.entry_id!==s,n=i?r.entry_id:s,o=e.find(m=>m.entry_id===n),p=(o?.parts||[]).find(m=>m.id===r.part_id)||null,d=i&&o?.object?.name||"",u=p?.name||a("shared_part_unknown",t);return{part:p,foreign:i,ownerName:d,label:d?`${u} (${d})`:u}}function Ti(r,s,e,t){let{part:i,label:n}=Ai(r,s,e,t),o=i&&i.stock!==null&&i.stock!==void 0?` (${i.stock}${i.unit?" "+i.unit:""})`:"",p=i?.storage_location?` \u2014 ${i.storage_location}`:"";return`${r.quantity}\xD7 ${n}${o}${p}`}function Ii(r,s,e,t){let n=(e.find(p=>p.entry_id===s)?.parts||[]).map(p=>({...p})),o=new Set(n.map(p=>V({part_id:p.id})));for(let p of r?.consumes_parts||[]){if(!p.entry_id||p.entry_id===s)continue;let d=V(p);if(o.has(d))continue;o.add(d);let{part:u,ownerName:m}=Ai(p,s,e,t);n.push({id:p.part_id,name:u?.name||a("shared_part_unknown",t),unit:u?.unit,stock:u?.stock??null,storage_location:u?.storage_location,entry_id:p.entry_id,owner_name:m})}return n}var Je=w(()=>{"use strict";j()});var mt,Ci,Pi,Li=w(()=>{"use strict";mt=["sensor","binary_sensor","number","input_number","input_boolean","switch","climate","vacuum","cover","fan","light","water_heater","humidifier","media_player","weather","air_quality","valve","lawn_mower","lock"],Ci=["sensor"],Pi=["temperature","humidity","pressure"]});var ft,Ne,vt=w(()=>{"use strict";ft=["notes","cost","duration","photo","user"],Ne={notes:"notes_label",cost:"cost",duration:"duration",photo:"photo_label",user:"user_label"}});function Vs(){return{entityIds:"",type:"threshold",attribute:"",above:"",below:"",equals:"",notEquals:"",forMinutes:"0",targetValue:"",deltaMode:!1,fromState:"",toState:"",targetChanges:"",runtimeHours:"",onStates:"",carry:{}}}function Gs(r){return{entityIds:(r.entity_ids||(r.entity_id?[r.entity_id]:[])).join(", "),type:r.type||"threshold",attribute:r.attribute||"",above:r.trigger_above?.toString()??"",below:r.trigger_below?.toString()??"",equals:r.trigger_equals?.toString()??"",notEquals:r.trigger_not_equals?.toString()??"",forMinutes:r.trigger_for_minutes?.toString()??"0",targetValue:r.trigger_target_value?.toString()??"",deltaMode:r.trigger_delta_mode||!1,fromState:r.trigger_from_state||"",toState:r.trigger_to_state||"",targetChanges:r.trigger_target_changes?.toString()??"",runtimeHours:r.trigger_runtime_hours?.toString()??"",onStates:(r.trigger_on_states||[]).join(", "),carry:Object.fromEntries(Object.entries(r).filter(([e])=>!Ks.has(e)&&!e.startsWith("_")))}}function Ys(r){let s=r.entityIds.split(",").map(t=>t.trim()).filter(Boolean);if(s.length===0)return null;let e={...r.carry||{},entity_id:s[0],entity_ids:s,type:r.type};if(r.attribute&&(e.attribute=r.attribute),r.type==="threshold"){let t=parseFloat(r.above);isNaN(t)||(e.trigger_above=t);let i=parseFloat(r.below);isNaN(i)||(e.trigger_below=i);let n=parseFloat(r.equals);isNaN(n)||(e.trigger_equals=n);let o=parseFloat(r.notEquals);isNaN(o)||(e.trigger_not_equals=o);let p=parseInt(r.forMinutes,10);isNaN(p)||(e.trigger_for_minutes=p)}else if(r.type==="counter"){let t=parseFloat(r.targetValu Line truncated
`),this._phaseDefs=Object.entries(t.phases||{}).map(([u,m])=>{let{name:f,checklist:v,consumes_parts:y,required_completion_fields:k,...E}=m,H=m.consumes_parts||[],M=H.findIndex(F=>!F.entry_id),q=M>=0?H[M]:void 0;return{id:u,name:m.name||u,checklistText:(m.checklist||[]).join(` `),this._phaseDefs=Object.entries(t.phases||{}).map(([u,m])=>{let{name:f,checklist:v,consumes_parts:y,required_completion_fields:k,...E}=m,H=m.consumes_parts||[],M=H.findIndex(F=>!F.entry_id),q=M>=0?H[M]:void 0;return{id:u,name:m.name||u,checklistText:(m.checklist||[]).join(`
`),partId:q?.part_id||"",partQty:q?.quantity!=null?String(q.quantity):"",reqOverride:m.required_completion_fields!==void 0,reqFields:[...m.required_completion_fields||[]],extraParts:H.filter((F,te)=>te!==M).map(F=>({...F})),carry:E}}),this._phaseSeq=[...t.phase_sequence||[]],this._requiredCompletion=[...t.required_completion_fields||[]],this._scheduleTime=t.schedule_time||"";let o=t.on_complete_action;if(o&&o.service){this._actionService=o.service;let u=o.target?.entity_id;this._actionTargetEntity=Array.isArray(u)?u[0]||"":u||"",this._actionData=o.data&&typeof o.data=="object"?{...o.data}:{},this._actionDataJsonFallback=""}else this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="";let p=t.quick_complete_defaults;this._qcNotes=p?.notes||"",this._qcCost=p?.cost!=null?String(p.cost):"",this._qcDuration=p?.duration!=null?String(p.duration):"",this._qcFeedback=p?.feedback||"";let d=t.adaptive_config||{};if(this._environmentalEntity=d.environmental_entity||"",this._environmentalAttribute=d.environmental_attribute||"",this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute,this._adaptiveEnabled=!!d.enabled,this._adaptiveAlpha=d.ewa_alpha?.toString()??J.alpha,this._adaptiveMin=d.min_interval_days?.toString()??J.min,this._adaptiveMax=d.max_interval_days?.toString()??J.max,this._adaptiveSeasonal=d.seasonal_enabled!==!1,this._adaptivePrediction=d.sensor_prediction_enabled!==!1,this._adaptiveInitial=this._adaptiveSnapshot(),t.trigger_config){let u=t.trigger_config;this._triggerEntityId=u.entity_id||u.entity_ids&&u.entity_ids[0]||"",this._triggerEntityIds=u.entity_ids||(u.entity_id?[u.entity_id]:[]),this._triggerEntityLogic=u.entity_logic||"any",this._triggerAttribute=u.attribute||"",this._triggerType=u.type||"threshold",this._triggerAbove=u.trigger_above?.toString()||"",this._triggerBelow=u.trigger_below?.toString()||"",this._triggerEquals=u.trigger_equals?.toString()||"",this._triggerNotEquals=u.trigger_not_equals?.toString()||"",this._triggerForMinutes=u.trigger_for_minutes?.toString()||"0",this._triggerCombinator=u.trigger_combinator==="all"?"all":"any",this._triggerTargetValue=u.trigger_target_value?.toString()||"",this._triggerDeltaMode=u.trigger_delta_mode||!1,this._triggerBaselineValue=u.trigger_baseline_value?.toString()||"",this._liveBaselineValue=t.trigger_baseline_value??null,this._autoCompleteOnRecovery=u.auto_complete_on_recovery||!1,this._triggerFromState=u.trigger_from_state||"",this._triggerToState=u.trigger_to_state||"",this._triggerTargetChanges=u.trigger_target_changes?.toString()||"",this._triggerRuntimeHours=u.trigger_runtime_hours?.toString()||"",this._triggerOnStates=(u.trigger_on_states||[]).join(", "),u.type==="compound"?(this._compoundLogic=u.compound_logic==="OR"?"OR":"AND",this._compoundConditions=(u.conditions||[]).map(Gs)):(this._compoundLogic="AND",this._compoundConditions=[])}else this._resetTriggerFields();this._triggerEntityId&&this._fetchEntityAttributes(this._triggerEntityId),await Promise.all([this._loadUsers(),this._loadTags(),this._loadParts(),this._loadForeignPools()]),this._open=!0}_resetFields(){this._name="",this._type="custom",this._scheduleType="time_based",this._intervalDays="30",this._intervalUnit="days",this._dueDate="",this._warningDays=String(this.defaultWarningDays),this._earliestCompletionDays="",this._intervalAnchor="completion",this._weekdays=[],this._nth="1",this._nthWeekday="5",this._domDay="1",this._domLastDay=!1,this._domBusiness=!1,this._calOffset="0",this._seasonMonths=[],this._endsMode="never",this._endsCount="",this._endsUntil="",this._notes="",this._documentationUrl="",this._customIcon="",this._priority="normal",this._labels="",this._enabled=!0,this._lastPerformed="",this._nfcTagId="",this._requireTagScan=!1,this._readingUnit="",this._consumesParts={},this._responsibleUserId=null,this._assigneePool=[],this._rotationStrategy="",this._checklistText="",this._phaseDefs=[],this._phaseSeq=[],this._requiredCompletion=[],this._scheduleTime="",this._environmentalEntity="",this._environmentalAttribute="",this._environmentalInitial="",this._environmentalAttributeInitial="",this._adaptiveEnabled=!1,this._adaptiveAlpha=J.alpha,this._adaptiveMin=J.min,this._adaptiveMax=J.max,this._adaptiveSeasonal=!0,this._adaptivePrediction=!0,this._adaptiveInitial=this._adaptiveSnapshot(),this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="",this._actionTesting=!1,this._actionTestResult="",this._qcNotes="",this._qcCost="",this._qcDuration="",this._qcFeedback="",this._resetTriggerFields()}_resetTriggerFields(){this._triggerEntityId="",this._triggerEntityIds=[],this._triggerEntityLogic="any",this._triggerAttribute="",this._suggestedAttributes=[],this._availableAttributes=[],this._entityDomain="",this._triggerType="threshold",this._triggerAbove="",this._triggerBelow="",this._triggerEquals="",this._triggerNotEquals="",this._trigger Line truncated `),partId:q?.part_id||"",partQty:q?.quantity!=null?String(q.quantity):"",reqOverride:m.required_completion_fields!==void 0,reqFields:[...m.required_completion_fields||[]],extraParts:H.filter((F,te)=>te!==M).map(F=>({...F})),carry:E}}),this._phaseSeq=[...t.phase_sequence||[]],this._requiredCompletion=[...t.required_completion_fields||[]],this._scheduleTime=t.schedule_time||"";let o=t.on_complete_action;if(o&&o.service){this._actionService=o.service;let u=o.target?.entity_id;this._actionTargetEntity=Array.isArray(u)?u[0]||"":u||"",this._actionData=o.data&&typeof o.data=="object"?{...o.data}:{},this._actionDataJsonFallback=""}else this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="";let p=t.quick_complete_defaults;this._qcNotes=p?.notes||"",this._qcCost=p?.cost!=null?String(p.cost):"",this._qcDuration=p?.duration!=null?String(p.duration):"",this._qcFeedback=p?.feedback||"";let d=t.adaptive_config||{};if(this._environmentalEntity=d.environmental_entity||"",this._environmentalAttribute=d.environmental_attribute||"",this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute,this._adaptiveEnabled=!!d.enabled,this._adaptiveAlpha=d.ewa_alpha?.toString()??J.alpha,this._adaptiveMin=d.min_interval_days?.toString()??J.min,this._adaptiveMax=d.max_interval_days?.toString()??J.max,this._adaptiveSeasonal=d.seasonal_enabled!==!1,this._adaptivePrediction=d.sensor_prediction_enabled!==!1,this._adaptiveInitial=this._adaptiveSnapshot(),t.trigger_config){let u=t.trigger_config;this._triggerEntityId=u.entity_id||u.entity_ids&&u.entity_ids[0]||"",this._triggerEntityIds=u.entity_ids||(u.entity_id?[u.entity_id]:[]),this._triggerEntityLogic=u.entity_logic||"any",this._triggerAttribute=u.attribute||"",this._triggerType=u.type||"threshold",this._triggerAbove=u.trigger_above?.toString()||"",this._triggerBelow=u.trigger_below?.toString()||"",this._triggerEquals=u.trigger_equals?.toString()||"",this._triggerNotEquals=u.trigger_not_equals?.toString()||"",this._triggerForMinutes=u.trigger_for_minutes?.toString()||"0",this._triggerCombinator=u.trigger_combinator==="all"?"all":"any",this._triggerTargetValue=u.trigger_target_value?.toString()||"",this._triggerDeltaMode=u.trigger_delta_mode||!1,this._triggerBaselineValue=u.trigger_baseline_value?.toString()||"",this._liveBaselineValue=t.trigger_baseline_value??null,this._autoCompleteOnRecovery=u.auto_complete_on_recovery||!1,this._triggerFromState=u.trigger_from_state||"",this._triggerToState=u.trigger_to_state||"",this._triggerTargetChanges=u.trigger_target_changes?.toString()||"",this._triggerRuntimeHours=u.trigger_runtime_hours?.toString()||"",this._triggerRuntimeMaxSession=u.trigger_runtime_max_session_seconds?.toString()||"",this._triggerOnStates=(u.trigger_on_states||[]).join(", "),u.type==="compound"?(this._compoundLogic=u.compound_logic==="OR"?"OR":"AND",this._compoundConditions=(u.conditions||[]).map(Gs)):(this._compoundLogic="AND",this._compoundConditions=[])}else this._resetTriggerFields();this._triggerEntityId&&this._fetchEntityAttributes(this._triggerEntityId),await Promise.all([this._loadUsers(),this._loadTags(),this._loadParts(),this._loadForeignPools()]),this._open=!0}_resetFields(){this._name="",this._type="custom",this._scheduleType="time_based",this._intervalDays="30",this._intervalUnit="days",this._dueDate="",this._warningDays=String(this.defaultWarningDays),this._earliestCompletionDays="",this._intervalAnchor="completion",this._weekdays=[],this._nth="1",this._nthWeekday="5",this._domDay="1",this._domLastDay=!1,this._domBusiness=!1,this._calOffset="0",this._seasonMonths=[],this._endsMode="never",this._endsCount="",this._endsUntil="",this._notes="",this._documentationUrl="",this._customIcon="",this._priority="normal",this._labels="",this._enabled=!0,this._lastPerformed="",this._nfcTagId="",this._requireTagScan=!1,this._allowSkip=!0,this._readingUnit="",this._consumesParts={},this._responsibleUserId=null,this._assigneePool=[],this._rotationStrategy="",this._checklistText="",this._phaseDefs=[],this._phaseSeq=[],this._requiredCompletion=[],this._scheduleTime="",this._environmentalEntity="",this._environmentalAttribute="",this._environmentalInitial="",this._environmentalAttributeInitial="",this._adaptiveEnabled=!1,this._adaptiveAlpha=J.alpha,this._adaptiveMin=J.min,this._adaptiveMax=J.max,this._adaptiveSeasonal=!0,this._adaptivePrediction=!0,this._adaptiveInitial=this._adaptiveSnapshot(),this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="",this._actionTesting=!1,this._actionTestResult="",this._qcNotes="",this._qcCost="",this._qcDuration="",this._qcFeedback="",this._resetTriggerFields()}_resetTriggerFields(){this._triggerEntityId="",this._triggerEntityIds=[],this._triggerEntityLogic="any",this._triggerAttribute="",this._suggestedAttributes=[],this._availableAttributes=[],this._entityDomain="",this._triggerType="threshold",th Line truncated
<details class="ca-section"> <details class="ca-section">
<summary>${a("on_complete_action_title",e)}</summary> <summary>${a("on_complete_action_title",e)}</summary>
<p class="field-help">${a("on_complete_action_desc",e)}</p> <p class="field-help">${a("on_complete_action_desc",e)}</p>
@@ -1524,7 +1553,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
.checked=${i.reqFields.includes(n)} .checked=${i.reqFields.includes(n)}
@change=${o=>{let p=o.target.checked,d=new Set(i.reqFields);p?d.add(n):d.delete(n),this._patchPhaseDef(i.id,{reqFields:[...d]})}} @change=${o=>{let p=o.target.checked,d=new Set(i.reqFields);p?d.add(n):d.delete(n),this._patchPhaseDef(i.id,{reqFields:[...d]})}}
/> />
<span>${a(je[n],e)}</span> <span>${a(Ne[n],e)}</span>
</label> </label>
`)} `)}
</div> </div>
@@ -1553,9 +1582,9 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
</select> </select>
</div> </div>
`:_} `:_}
`}async _save(){if(!this._loading&&this._name.trim()){if(this._adaptiveSnapshot()!==this._adaptiveInitial){let e=parseInt(this._adaptiveMin,10),t=parseInt(this._adaptiveMax,10);if(!isNaN(e)&&!isNaN(t)&&e>t){this._error=`${a("adaptive_min_interval",this._lang)} > ${a("adaptive_max_interval",this._lang)}`;return}}this._loading=!0,this._error="";try{let e={type:this._taskId?"maintenance_supporter/task/update":"maintenance_supporter/task/create",entry_id:this._entryId,name:this._name,task_type:this._type,schedule_type:this._scheduleType,warning_days:Number.isNaN(parseInt(this._warningDays,10))?this.defaultWarningDays:Math.max(0,parseInt(this._warningDays,10))},t=this._earliestCompletionDays.trim();e.earliest_completion_days=t===""?null:Math.max(0,parseInt(t,10)||0),this._taskId&&(e.task_id=this._taskId),this._scheduleType==="one_time"?(e.due_date=this._dueDate||null,e.interval_days=null):yt.includes(this._scheduleType)?(e.schedule={...this._buildSchedule(),...this._recurrenceExtras()},e.interval_days=null,this._taskId&&(e.due_date=null)):(this._taskId&&(e.due_date=null),this._scheduleType!=="manual"&&this._intervalDays?(e.interval_days=parseInt(this._intervalDays,10),e.interval_unit=this._intervalUnit,e.interval_anchor=this._intervalAnchor,this._scheduleType==="time_based"&&(e.schedule={kind:"interval",...this._recurrenceExtras()})):this._taskId&&(e.interval_days=null,e.interval_anchor="completion")),e.notes=this._notes||null,e.documentation_url=this._documentationUrl||null,e.custom_icon=this._customIcon||null,e.priority=this._priority,e.labels=this._labels.split(",").map(p=>p.trim()).filter(Boolean),e.enabled=this._enabled,e.last_performed=this._lastPerformed||null,e.nfc_tag_id=this._nfcTagId||null,e.require_tag_scan=this._requireTagScan,e.reading_unit=this._readingUnit.trim()||null;{let p={};for(let u of this._phaseDefs){if(!u.name.trim())continue;let m={...u.carry,name:u.name.trim()},f=u.checklistText.split(` `}async _save(){if(!this._loading&&this._name.trim()){if(this._adaptiveSnapshot()!==this._adaptiveInitial){let e=parseInt(this._adaptiveMin,10),t=parseInt(this._adaptiveMax,10);if(!isNaN(e)&&!isNaN(t)&&e>t){this._error=`${a("adaptive_min_interval",this._lang)} > ${a("adaptive_max_interval",this._lang)}`;return}}this._loading=!0,this._error="";try{let e={type:this._taskId?"maintenance_supporter/task/update":"maintenance_supporter/task/create",entry_id:this._entryId,name:this._name,task_type:this._type,schedule_type:this._scheduleType,warning_days:Number.isNaN(parseInt(this._warningDays,10))?this.defaultWarningDays:Math.max(0,parseInt(this._warningDays,10))},t=this._earliestCompletionDays.trim();e.earliest_completion_days=t===""?null:Math.max(0,parseInt(t,10)||0),this._taskId&&(e.task_id=this._taskId),this._scheduleType==="one_time"?(e.due_date=this._dueDate||null,e.interval_days=null):yt.includes(this._scheduleType)?(e.schedule={...this._buildSchedule(),...this._recurrenceExtras()},e.interval_days=null,this._taskId&&(e.due_date=null)):(this._taskId&&(e.due_date=null),this._scheduleType!=="manual"&&this._intervalDays?(e.interval_days=parseInt(this._intervalDays,10),e.interval_unit=this._intervalUnit,e.interval_anchor=this._intervalAnchor,this._scheduleType==="time_based"&&(e.schedule={kind:"interval",...this._recurrenceExtras()})):this._taskId&&(e.interval_days=null,e.interval_anchor="completion")),e.notes=this._notes||null,e.documentation_url=this._documentationUrl||null,e.custom_icon=this._customIcon||null,e.priority=this._priority,e.labels=this._labels.split(",").map(p=>p.trim()).filter(Boolean),e.enabled=this._enabled,e.last_performed=this._lastPerformed||null,e.nfc_tag_id=this._nfcTagId||null,e.require_tag_scan=this._requireTagScan,e.allow_skip=this._allowSkip,e.reading_unit=this._readingUnit.trim()||null;{let p={};for(let u of this._phaseDefs){if(!u.name.trim())continue;let m={...u.carry,name:u.name.trim()},f=u.checklistText.split(`
`).map(y=>y.trim()).filter(Boolean);f.length&&(m.checklist=f);let v=[];if(u.partId){let y=parseFloat(u.partQty);v.push({part_id:u.partId,quantity:Number.isFinite(y)&&y>0?y:1})}for(let y of u.extraParts)v.push(y.entry_id?{part_id:y.part_id,quantity:y.quantity,entry_id:y.entry_id}:{part_id:y.part_id,quantity:y.quantity});v.length&&(m.consumes_parts=v),u.reqOverride&&(m.required_completion_fields=[...u.reqFields]),p[u.id]=m}let d=this._phaseSeq.filter(u=>u in p);e.phases=Object.keys(p).length&&d.length?p:null,e.phase_sequence=e.phases?d:null}if((this.parts.length||this._foreignOwners.length)&&(e.consumes_parts=Object.values(this._consumesParts).map(p=>p.entry_id?{part_id:p.part_id,quantity:p.quantity,entry_id:p.entry_id}:{part_id:p.part_id,quantity:p.quantity})),e.responsible_user_id=this._responsibleUserId,e.assignee_pool=this._assigneePool,e.required_completion_fields=this._requiredCompletion,e.rotation_strategy=this._assigneePool.length>=2&&this._rotationStrategy?this._rotationStrategy:null,this._scheduleType==="sensor_based"&&this._triggerType==="compound"){let p=this._compoundConditions.map(Ys).filter(d=>d!==null);if(p.length>0){let d={type:"compound",compound_logic:this._compoundLogic,conditions:p};this._autoCompleteOnRecovery&&(d.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(d.trigger_combinator="all"),e.trigger_config=d}else this._taskId&&(e.trigger_config=null)}else if(this._scheduleType==="sensor_based"&&this._triggerEntityId){let p=this._triggerEntityIds.length>0?this._triggerEntityIds:[this._triggerEntityId],d={entity_id:p[0],entity_ids:p,type:this._triggerType};if(this._triggerAttribute&&(d.attribute=this._triggerAttribute),this._autoCompleteOnRecovery&&(d.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(d.trigger_combinator="all"),p.length>1&&(d.entity_logic=this._triggerEntityLogic),this._triggerType==="threshold"){if(this._triggerAbove){let u=parseFloat(this._triggerAbove);isNaN(u)||(d.trigger_above=u)}if(this._triggerBelow){let u=parseFloat(this._triggerBelow);isNaN(u)||(d.trigger_below=u)}if(this._triggerEquals){let u=parseFloat(this._triggerEquals);isNaN(u)||(d.trigger_equals=u)}if(this._triggerNotEquals){let u=parseFloat(this._triggerNotEquals);isNaN(u)||(d.trigger_not_equals=u)}if(this._triggerForMinutes){let u=parseInt(this._triggerForMinutes,10);isNaN(u)||(d.trigger_for_minutes=u)}}else if(this._triggerType==="counter"){if(this._triggerTargetValue){let u=parseFloat(this._triggerTargetValue);isNaN(u)||(d.trigger_target_value=u)}if(d.trigger_delta_mode=this._triggerDeltaMode,this._triggerDeltaMode&&this._triggerBaselineValue){let u=parseFloat(this._triggerBaselineValue);!isNaN(u)&&u>=0&&(d.trigger_baseline_value=u)}}else if(this._triggerType==="state_change"){if(this._triggerFromState&&(d.trigger_from_state=this._triggerFromState),this._triggerToState&&(d.trigger_to_state=this._triggerToState),this._triggerTargetChanges){let u=parseInt(this._triggerTargetChanges,10);isNaN(u)||(d.trigger_target_changes=u)}if(this._triggerForMinutes){let u=parseInt(this._triggerForMinutes,10);isNaN(u)||(d.trigger_for_minutes=u)}}else if(this._triggerType==="runtime"){if(this._triggerRuntimeHours){let m=parseFloat(this._triggerRuntimeHours);isNaN(m)||(d.trigger_runtime_hours=m)}let u=this._triggerOnStates.split(",").map(m=>m.trim()).filter(Boolean);u.length>0&&(d.trigger_on_states=u)}e.trigger_config=d}else this._taskId&&(e.trigger_config=null);if(this.scheduleTimeEnabled&&this._scheduleType==="time_based"){let p=this._scheduleTime.trim();e.schedule_time=/^([01]\d|2[0-3]):[0-5]\d$/.test(p)?p:null}if(this.checklistsEnabled){let p=this._checklistText.split(` `).map(y=>y.trim()).filter(Boolean);f.length&&(m.checklist=f);let v=[];if(u.partId){let y=parseFloat(u.partQty);v.push({part_id:u.partId,quantity:Number.isFinite(y)&&y>0?y:1})}for(let y of u.extraParts)v.push(y.entry_id?{part_id:y.part_id,quantity:y.quantity,entry_id:y.entry_id}:{part_id:y.part_id,quantity:y.quantity});v.length&&(m.consumes_parts=v),u.reqOverride&&(m.required_completion_fields=[...u.reqFields]),p[u.id]=m}let d=this._phaseSeq.filter(u=>u in p);e.phases=Object.keys(p).length&&d.length?p:null,e.phase_sequence=e.phases?d:null}if((this.parts.length||this._foreignOwners.length)&&(e.consumes_parts=Object.values(this._consumesParts).map(p=>p.entry_id?{part_id:p.part_id,quantity:p.quantity,entry_id:p.entry_id}:{part_id:p.part_id,quantity:p.quantity})),e.responsible_user_id=this._responsibleUserId,e.assignee_pool=this._assigneePool,e.required_completion_fields=this._requiredCompletion,e.rotation_strategy=this._assigneePool.length>=2&&this._rotationStrategy?this._rotationStrategy:null,this._scheduleType==="sensor_based"&&this._triggerType==="compound"){let p=this._compoundConditions.map(Ys).filter(d=>d!==null);if(p.length>0){let d={type:"compound",compound_logic:this._compoundLogic,conditions:p};this._autoCompleteOnRecovery&&(d.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(d.trigger_combinator="all"),e.trigger_config=d}else this._taskId&&(e.trigger_config=null)}else if(this._scheduleType==="sensor_based"&&this._triggerEntityId){let p=this._triggerEntityIds.length>0?this._triggerEntityIds:[this._triggerEntityId],d={entity_id:p[0],entity_ids:p,type:this._triggerType};if(this._triggerAttribute&&(d.attribute=this._triggerAttribute),this._autoCompleteOnRecovery&&(d.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(d.trigger_combinator="all"),p.length>1&&(d.entity_logic=this._triggerEntityLogic),this._triggerType==="threshold"){if(this._triggerAbove){let u=parseFloat(this._triggerAbove);isNaN(u)||(d.trigger_above=u)}if(this._triggerBelow){let u=parseFloat(this._triggerBelow);isNaN(u)||(d.trigger_below=u)}if(this._triggerEquals){let u=parseFloat(this._triggerEquals);isNaN(u)||(d.trigger_equals=u)}if(this._triggerNotEquals){let u=parseFloat(this._triggerNotEquals);isNaN(u)||(d.trigger_not_equals=u)}if(this._triggerForMinutes){let u=parseInt(this._triggerForMinutes,10);isNaN(u)||(d.trigger_for_minutes=u)}}else if(this._triggerType==="counter"){if(this._triggerTargetValue){let u=parseFloat(this._triggerTargetValue);isNaN(u)||(d.trigger_target_value=u)}if(d.trigger_delta_mode=this._triggerDeltaMode,this._triggerDeltaMode&&this._triggerBaselineValue){let u=parseFloat(this._triggerBaselineValue);!isNaN(u)&&u>=0&&(d.trigger_baseline_value=u)}}else if(this._triggerType==="state_change"){if(this._triggerFromState&&(d.trigger_from_state=this._triggerFromState),this._triggerToState&&(d.trigger_to_state=this._triggerToState),this._triggerTargetChanges){let u=parseInt(this._triggerTargetChanges,10);isNaN(u)||(d.trigger_target_changes=u)}if(this._triggerForMinutes){let u=parseInt(this._triggerForMinutes,10);isNaN(u)||(d.trigger_for_minutes=u)}}else if(this._triggerType==="runtime"){if(this._triggerRuntimeHours){let m=parseFloat(this._triggerRuntimeHours);isNaN(m)||(d.trigger_runtime_hours=m)}if(this._triggerRuntimeMaxSession){let m=parseInt(this._triggerRuntimeMaxSession,10);!isNaN(m)&&m>0&&(d.trigger_runtime_max_session_seconds=m)}let u=this._triggerOnStates.split(",").map(m=>m.trim()).filter(Boolean);u.length>0&&(d.trigger_on_states=u)}e.trigger_config=d}else this._taskId&&(e.trigger_config=null);if(this.scheduleTimeEnabled&&this._scheduleType==="time_based"){let p=this._scheduleTime.trim();e.schedule_time=/^([01]\d|2[0-3]):[0-5]\d$/.test(p)?p:null}if(this.checklistsEnabled){let p=this._checklistText.split(`
`).map(d=>d.trim()).filter(Boolean).slice(0,100);e.checklist=p.length?p:null}if(this.completionActionsEnabled){let p=this._actionService.trim();if(p&&/^[a-z][a-z0-9_]*\.[a-z0-9_]+$/.test(p)){let f={service:p},v=this._actionTargetEntity.trim();v&&(f.target={entity_id:v});let y=this._buildActionData();Object.keys(y).length>0&&(f.data=y),e.on_complete_action=f}else e.on_complete_action=null;let d={};this._qcNotes.trim()&&(d.notes=this._qcNotes.trim());let u=parseFloat(this._qcCost);!isNaN(u)&&u>=0&&(d.cost=u);let m=parseInt(this._qcDuration,10);!isNaN(m)&&m>=0&&(d.duration=m),this._qcFeedback&&(d.feedback=this._qcFeedback),e.quick_complete_defaults=Object.keys(d).length?d:null}let i=await this.hass.connection.sendMessagePromise(e),n=this._taskId||i?.task_id,o=this._environmentalEntity!==this._environmentalInitial||this._environmentalAttribute!==this._environmentalAttributeInitial;if(n&&this._scheduleType==="sensor_based"&&o)try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_environmental_entity",entry_id:this._entryId,task_id:n,environmental_entity:this._environmentalEntity||null,environmental_attribute:this._environmentalAttribute||null}),this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute}catch{}if(n&&this._adaptiveSnapshot()!==this._adaptiveInitial){let p=parseFloat(this._adaptiveAlpha),d=parseInt(this._adaptiveMin,10),u=parseInt(this._adaptiveMax,10);try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_adaptive",entry_id:this._entryId,task_id:n,enabled:this._adaptiveEnabled,...p>=.1&&p<=.9?{ewa_alpha:p}:{},...!isNaN(d)&&d>=1?{min_interval_days:d}:{},...!isNaN(u)&&u>=1?{max_interval_days:u}:{},seasonal_enabled:this._adaptiveSeasonal,sensor_prediction_enabled:this._adaptivePrediction}),this._adaptiveInitial=this._adaptiveSnapshot()}catch{}}this._open=!1,this.dispatchEvent(new CustomEvent("task-saved"))}catch(e){this._error=j(e,this._lang,a("save_error",this._lang))}finally{this._loading=!1}}}_close(){this._open=!1,this._pickerProbeTimer!==void 0&&(clearTimeout(this._pickerProbeTimer),this._pickerProbeTimer=void 0),this._pickerProbeStrikes=0}_renderTriggerFields(){if(this._scheduleType!=="sensor_based")return _;let e=this._lang,t=this._triggerType==="compound";return l` `).map(d=>d.trim()).filter(Boolean).slice(0,100);e.checklist=p.length?p:null}if(this.completionActionsEnabled){let p=this._actionService.trim();if(p&&/^[a-z][a-z0-9_]*\.[a-z0-9_]+$/.test(p)){let f={service:p},v=this._actionTargetEntity.trim();v&&(f.target={entity_id:v});let y=this._buildActionData();Object.keys(y).length>0&&(f.data=y),e.on_complete_action=f}else e.on_complete_action=null;let d={};this._qcNotes.trim()&&(d.notes=this._qcNotes.trim());let u=parseFloat(this._qcCost);!isNaN(u)&&u>=0&&(d.cost=u);let m=parseInt(this._qcDuration,10);!isNaN(m)&&m>=0&&(d.duration=m),this._qcFeedback&&(d.feedback=this._qcFeedback),e.quick_complete_defaults=Object.keys(d).length?d:null}let i=await this.hass.connection.sendMessagePromise(e),n=this._taskId||i?.task_id,o=this._environmentalEntity!==this._environmentalInitial||this._environmentalAttribute!==this._environmentalAttributeInitial;if(n&&this._scheduleType==="sensor_based"&&o)try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_environmental_entity",entry_id:this._entryId,task_id:n,environmental_entity:this._environmentalEntity||null,environmental_attribute:this._environmentalAttribute||null}),this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute}catch{}if(n&&this._adaptiveSnapshot()!==this._adaptiveInitial){let p=parseFloat(this._adaptiveAlpha),d=parseInt(this._adaptiveMin,10),u=parseInt(this._adaptiveMax,10);try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_adaptive",entry_id:this._entryId,task_id:n,enabled:this._adaptiveEnabled,...p>=.1&&p<=.9?{ewa_alpha:p}:{},...!isNaN(d)&&d>=1?{min_interval_days:d}:{},...!isNaN(u)&&u>=1?{max_interval_days:u}:{},seasonal_enabled:this._adaptiveSeasonal,sensor_prediction_enabled:this._adaptivePrediction}),this._adaptiveInitial=this._adaptiveSnapshot()}catch{}}this._open=!1,this.dispatchEvent(new CustomEvent("task-saved"))}catch(e){this._error=N(e,this._lang,a("save_error",this._lang))}finally{this._loading=!1}}}_close(){this._open=!1,this._pickerProbeTimer!==void 0&&(clearTimeout(this._pickerProbeTimer),this._pickerProbeTimer=void 0),this._pickerProbeStrikes=0}_renderTriggerFields(){if(this._scheduleType!=="sensor_based")return _;let e=this._lang,t=this._triggerType==="compound";return l`
<h3>${a("trigger_configuration",e)}</h3> <h3>${a("trigger_configuration",e)}</h3>
<div class="select-row"> <div class="select-row">
<label>${a("trigger_type",e)}</label> <label>${a("trigger_type",e)}</label>
@@ -2004,6 +2033,14 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
.value=${this._triggerRuntimeHours} .value=${this._triggerRuntimeHours}
@input=${t=>this._triggerRuntimeHours=t.target.value} @input=${t=>this._triggerRuntimeHours=t.target.value}
></ms-textfield> ></ms-textfield>
<ms-textfield
label="${a("runtime_max_session",e)}"
type="number"
step="1"
.value=${this._triggerRuntimeMaxSession}
@input=${t=>this._triggerRuntimeMaxSession=t.target.value}
></ms-textfield>
<div class="field-help">${a("runtime_max_session_help",e)}</div>
${this._renderOnStatesField({value:this._triggerOnStates,entityId:this._triggerEntityId,onInput:t=>this._triggerOnStates=t})} ${this._renderOnStatesField({value:this._triggerOnStates,entityId:this._triggerEntityId,onInput:t=>this._triggerOnStates=t})}
<div class="field-help">${a("runtime_on_states_help",e)}</div> <div class="field-help">${a("runtime_on_states_help",e)}</div>
`:_}render(){if(!this._open)return l``;let e=this._lang,t=this._taskId?a("edit_task",e):a("new_task",e);return l` `:_}render(){if(!this._open)return l``;let e=this._lang,t=this._taskId?a("edit_task",e):a("new_task",e);return l`
@@ -2166,7 +2203,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
.checked=${this._requiredCompletion.includes(i)} .checked=${this._requiredCompletion.includes(i)}
@change=${n=>this._toggleRequired(i,n.target.checked)} @change=${n=>this._toggleRequired(i,n.target.checked)}
/> />
<span>${a(je[i],e)}</span> <span>${a(Ne[i],e)}</span>
</label> </label>
`)} `)}
</div> </div>
@@ -2225,7 +2262,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
<ha-form <ha-form
class="entity-picker-form" class="entity-picker-form"
.hass=${this.hass} .hass=${this.hass}
.schema=${[{name:"environmental_entity",selector:{entity:{domain:Ii,device_class:Pi}}}]} .schema=${[{name:"environmental_entity",selector:{entity:{domain:Ci,device_class:Pi}}}]}
.data=${{environmental_entity:this._environmentalEntity}} .data=${{environmental_entity:this._environmentalEntity}}
.computeLabel=${()=>a("environmental_entity_optional",e)} .computeLabel=${()=>a("environmental_entity_optional",e)}
.computeHelper=${()=>a("environmental_entity_helper",e)} .computeHelper=${()=>a("environmental_entity_helper",e)}
@@ -2290,6 +2327,15 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
<span>${a("require_tag_scan",e)}</span> <span>${a("require_tag_scan",e)}</span>
</label> </label>
${this._requireTagScan?l`<div class="field-help">${a("require_tag_scan_help",e)}</div>`:_} ${this._requireTagScan?l`<div class="field-help">${a("require_tag_scan_help",e)}</div>`:_}
<label class="req-option">
<input
type="checkbox"
.checked=${!this._allowSkip}
@change=${i=>this._allowSkip=!i.target.checked}
/>
<span>${a("disallow_skip",e)}</span>
</label>
${this._allowSkip?_:l`<div class="field-help">${a("disallow_skip_help",e)}</div>`}
<label class="toggle-row"> <label class="toggle-row">
<input <input
type="checkbox" type="checkbox"
@@ -2686,7 +2732,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
} }
`,c([x({attribute:!1})],g.prototype,"hass",2),c([x({type:Boolean,attribute:"checklists-enabled"})],g.prototype,"checklistsEnabled",2),c([x({type:Boolean,attribute:"schedule-time-enabled"})],g.prototype,"scheduleTimeEnabled",2),c([x({type:Boolean,attribute:"completion-actions-enabled"})],g.prototype,"completionActionsEnabled",2),c([x({type:Number,attribute:"default-warning-days"})],g.prototype,"defaultWarningDays",2),c([h()],g.prototype,"parts",2),c([h()],g.prototype,"_foreignOwners",2),c([h()],g.prototype,"_open",2),c([h()],g.prototype,"_entityPickerFallback",2),c([h()],g.prototype,"_loading",2),c([h()],g.prototype,"_error",2),c([h()],g.prototype,"_entryId",2),c([h()],g.prototype,"_taskId",2),c([h()],g.prototype,"_objectChoices",2),c([h()],g.prototype,"_name",2),c([h()],g.prototype,"_type",2),c([h()],g.prototype,"_scheduleType",2),c([h()],g.prototype,"_intervalDays",2),c([h()],g.prototype,"_intervalUnit",2),c([h()],g.prototype,"_dueDate",2),c([h()],g.prototype,"_warningDays",2),c([h()],g.prototype,"_earliestCompletionDays",2),c([h()],g.prototype,"_intervalAnchor",2),c([h()],g.prototype,"_weekdays",2),c([h()],g.prototype,"_nth",2),c([h()],g.prototype,"_nthWeekday",2),c([h()],g.prototype,"_domDay",2),c([h()],g.prototype,"_domLastDay",2),c([h()],g.prototype,"_domBusiness",2),c([h()],g.prototype,"_calOffset",2),c([h()],g.prototype,"_seasonMonths",2),c([h()],g.prototype,"_endsMode",2),c([h()],g.prototype,"_endsCount",2),c([h()],g.prototype,"_endsUntil",2),c([h()],g.prototype,"_schedulePreview",2),c([h()],g.prototype,"_schedulePreviewEnded",2),c([h()],g.prototype,"_notes",2),c([h()],g.prototype,"_documentationUrl",2),c([h()],g.prototype,"_customIcon",2),c([h()],g.prototype,"_priority",2),c([h()],g.prototype,"_labels",2),c([h()],g.prototype,"_enabled",2),c([h()],g.prototype,"_triggerEntityId",2),c([h()],g.prototype,"_triggerEntityIds",2),c([h()],g.prototype,"_triggerEntityLogic",2),c([h()],g.prototype,"_triggerAttribute",2),c([h()],g.prototype,"_triggerType",2),c([h()],g.prototype,"_triggerAbove",2),c([h()],g.prototype,"_triggerBelow",2),c([h()],g.prototype,"_triggerEquals",2),c([h()],g.prototype,"_triggerNotEquals",2),c([h()],g.prototype,"_triggerForMinutes",2),c([h()],g.prototype,"_triggerCombinator",2),c([h()],g.prototype,"_triggerTargetValue",2),c([h()],g.prototype,"_triggerDeltaMode",2),c([h()],g.prototype,"_triggerBaselineValue",2),c([h()],g.prototype,"_liveBaselineValue",2),c([h()],g.prototype,"_autoCompleteOnRecovery",2),c([h()],g.prototype,"_triggerFromState",2),c([h()],g.prototype,"_triggerToState",2),c([h()],g.prototype,"_triggerTargetChanges",2),c([h()],g.prototype,"_triggerRuntimeHours",2),c([h()],g.prototype,"_triggerOnStates",2),c([h()],g.prototype,"_compoundLogic",2),c([h()],g.prototype,"_compoundConditions",2),c([h()],g.prototype,"_suggestedAttributes",2),c([h()],g.prototype,"_availableAttributes",2),c([h()],g.prototype,"_entityDomain",2),c([h()],g.prototype,"_lastPerformed",2),c([h()],g.prototype,"_nfcTagId",2),c([h()],g.prototype,"_requireTagScan",2),c([h()],g.prototype,"_readingUnit",2),c([h()],g.prototype,"_consumesParts",2),c([h()],g.prototype,"_partsLoadFailed",2),c([h()],g.prototype,"_availableTags",2),c([h()],g.prototype,"_responsibleUserId",2),c([h()],g.prototype,"_assigneePool",2),c([h()],g.prototype,"_rotationStrategy",2),c([h()],g.prototype,"_availableUsers",2),c([h()],g.prototype,"_checklistText",2),c([h()],g.prototype,"_phaseDefs",2),c([h()],g.prototype,"_phaseSeq",2),c([h()],g.prototype,"_requiredCompletion",2),c([h()],g.prototype,"_scheduleTime",2),c([h()],g.prototype,"_actionService",2),c([h()],g.prototype,"_actionTargetEntity",2),c([h()],g.prototype,"_actionData",2),c([h()],g.prototype,"_actionDataJsonFallback",2),c([h()],g.prototype,"_actionTesting",2),c([h()],g.prototype,"_actionTestResult",2),c([h()],g.prototype,"_actionTestError",2),c([h()],g.prototype,"_qcNotes",2),c([h()],g.prototype,"_qcCost",2),c([h()],g.prototype,"_qcDuration",2),c([h()],g.prototype,"_qcFeedback",2),c([h()],g.prototype,"_environmentalEntity",2),c([h()],g.prototype,"_environmentalAttribute",2),c([h()],g.prototype,"_adaptiveEnabled",2),c([h()],g.prototype,"_adaptiveAlpha",2),c([h()],g.prototype,"_adaptiveMin",2),c([h()],g.prototype,"_adaptiveMax",2),c([h()],g.prototype,"_adaptiveSeasonal",2),c([h()],g.prototype,"_adaptivePrediction",2),c([h()],g.prototype,"_conditionAttrOptions",2);bt=g;customElements.get("maintenance-task-dialog")||customElements.define("maintenance-task-dialog",bt)});var $,Ni=w(()=>{"use strict";P();W();N();de();Je();vt();$=class extends A{constructor(){super(...arguments);this.entryId="";this.taskId="";this.taskName="";this.lang="en";this.checklist=[];this.adaptiveEnabled=!1;this.taskType="";this.readingUnit="";this.restockDefault=null;this.restockUnitCost=null;this.currencySymbol="";this.parts=[];this.consumesParts=[];this.consumesInfo=[];this.requiredFields=[];this.phaseLabel="";this.requireTagScan=!1;this.viaTagScan=!1;this._open=!1;this._notes="";this._cost="";this._duration="";t Line truncated `,c([x({attribute:!1})],g.prototype,"hass",2),c([x({type:Boolean,attribute:"checklists-enabled"})],g.prototype,"checklistsEnabled",2),c([x({type:Boolean,attribute:"schedule-time-enabled"})],g.prototype,"scheduleTimeEnabled",2),c([x({type:Boolean,attribute:"completion-actions-enabled"})],g.prototype,"completionActionsEnabled",2),c([x({type:Number,attribute:"default-warning-days"})],g.prototype,"defaultWarningDays",2),c([h()],g.prototype,"parts",2),c([h()],g.prototype,"_foreignOwners",2),c([h()],g.prototype,"_open",2),c([h()],g.prototype,"_entityPickerFallback",2),c([h()],g.prototype,"_loading",2),c([h()],g.prototype,"_error",2),c([h()],g.prototype,"_entryId",2),c([h()],g.prototype,"_taskId",2),c([h()],g.prototype,"_objectChoices",2),c([h()],g.prototype,"_name",2),c([h()],g.prototype,"_type",2),c([h()],g.prototype,"_scheduleType",2),c([h()],g.prototype,"_intervalDays",2),c([h()],g.prototype,"_intervalUnit",2),c([h()],g.prototype,"_dueDate",2),c([h()],g.prototype,"_warningDays",2),c([h()],g.prototype,"_earliestCompletionDays",2),c([h()],g.prototype,"_intervalAnchor",2),c([h()],g.prototype,"_weekdays",2),c([h()],g.prototype,"_nth",2),c([h()],g.prototype,"_nthWeekday",2),c([h()],g.prototype,"_domDay",2),c([h()],g.prototype,"_domLastDay",2),c([h()],g.prototype,"_domBusiness",2),c([h()],g.prototype,"_calOffset",2),c([h()],g.prototype,"_seasonMonths",2),c([h()],g.prototype,"_endsMode",2),c([h()],g.prototype,"_endsCount",2),c([h()],g.prototype,"_endsUntil",2),c([h()],g.prototype,"_schedulePreview",2),c([h()],g.prototype,"_schedulePreviewEnded",2),c([h()],g.prototype,"_notes",2),c([h()],g.prototype,"_documentationUrl",2),c([h()],g.prototype,"_customIcon",2),c([h()],g.prototype,"_priority",2),c([h()],g.prototype,"_labels",2),c([h()],g.prototype,"_enabled",2),c([h()],g.prototype,"_triggerEntityId",2),c([h()],g.prototype,"_triggerEntityIds",2),c([h()],g.prototype,"_triggerEntityLogic",2),c([h()],g.prototype,"_triggerAttribute",2),c([h()],g.prototype,"_triggerType",2),c([h()],g.prototype,"_triggerAbove",2),c([h()],g.prototype,"_triggerBelow",2),c([h()],g.prototype,"_triggerEquals",2),c([h()],g.prototype,"_triggerNotEquals",2),c([h()],g.prototype,"_triggerForMinutes",2),c([h()],g.prototype,"_triggerCombinator",2),c([h()],g.prototype,"_triggerTargetValue",2),c([h()],g.prototype,"_triggerDeltaMode",2),c([h()],g.prototype,"_triggerBaselineValue",2),c([h()],g.prototype,"_liveBaselineValue",2),c([h()],g.prototype,"_autoCompleteOnRecovery",2),c([h()],g.prototype,"_triggerFromState",2),c([h()],g.prototype,"_triggerToState",2),c([h()],g.prototype,"_triggerTargetChanges",2),c([h()],g.prototype,"_triggerRuntimeHours",2),c([h()],g.prototype,"_triggerRuntimeMaxSession",2),c([h()],g.prototype,"_triggerOnStates",2),c([h()],g.prototype,"_compoundLogic",2),c([h()],g.prototype,"_compoundConditions",2),c([h()],g.prototype,"_suggestedAttributes",2),c([h()],g.prototype,"_availableAttributes",2),c([h()],g.prototype,"_entityDomain",2),c([h()],g.prototype,"_lastPerformed",2),c([h()],g.prototype,"_nfcTagId",2),c([h()],g.prototype,"_requireTagScan",2),c([h()],g.prototype,"_allowSkip",2),c([h()],g.prototype,"_readingUnit",2),c([h()],g.prototype,"_consumesParts",2),c([h()],g.prototype,"_partsLoadFailed",2),c([h()],g.prototype,"_availableTags",2),c([h()],g.prototype,"_responsibleUserId",2),c([h()],g.prototype,"_assigneePool",2),c([h()],g.prototype,"_rotationStrategy",2),c([h()],g.prototype,"_availableUsers",2),c([h()],g.prototype,"_checklistText",2),c([h()],g.prototype,"_phaseDefs",2),c([h()],g.prototype,"_phaseSeq",2),c([h()],g.prototype,"_requiredCompletion",2),c([h()],g.prototype,"_scheduleTime",2),c([h()],g.prototype,"_actionService",2),c([h()],g.prototype,"_actionTargetEntity",2),c([h()],g.prototype,"_actionData",2),c([h()],g.prototype,"_actionDataJsonFallback",2),c([h()],g.prototype,"_actionTesting",2),c([h()],g.prototype,"_actionTestResult",2),c([h()],g.prototype,"_actionTestError",2),c([h()],g.prototype,"_qcNotes",2),c([h()],g.prototype,"_qcCost",2),c([h()],g.prototype,"_qcDuration",2),c([h()],g.prototype,"_qcFeedback",2),c([h()],g.prototype,"_environmentalEntity",2),c([h()],g.prototype,"_environmentalAttribute",2),c([h()],g.prototype,"_adaptiveEnabled",2),c([h()],g.prototype,"_adaptiveAlpha",2),c([h()],g.prototype,"_adaptiveMin",2),c([h()],g.prototype,"_adaptiveMax",2),c([h()],g.prototype,"_adaptiveSeasonal",2),c([h()],g.prototype,"_adaptivePrediction",2),c([h()],g.prototype,"_conditionAttrOptions",2);bt=g;customElements.get("maintenance-task-dialog")||customElements.define("maintenance-task-dialog",bt)});var $,ji=w(()=>{"use strict";P();W();j();de();Je();vt();$=class extends A{constructor(){super(...arguments);this.entryId="";this.taskId="";this.taskName="";this.lang="en";this.checklist=[];this.adaptiveEnabled=!1;this.taskType="";this.readingUnit="";this.restockDefault=null;this.restockUnitCost=null;this.currencySymbol="";this.parts=[];this.consumesParts=[];this.consumesInfo=[];this.requiredFields=[];this.phaseLabel="";this.requireTagSc Line truncated
type="button" type="button"
class="cost-suggestion" class="cost-suggestion"
@click=${()=>this._cost=t.toFixed(2)} @click=${()=>this._cost=t.toFixed(2)}
@@ -2814,7 +2860,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
<ha-button <ha-button
@click=${this._complete} @click=${this._complete}
.disabled=${this._loading||this._missingRequired.length>0} .disabled=${this._loading||this._missingRequired.length>0}
title=${this._missingRequired.length?this._missingRequired.map(t=>a("err_required",e).replace("{field}",a(je[t]??t,e))).join(" \xB7 "):""} title=${this._missingRequired.length?this._missingRequired.map(t=>a("err_required",e).replace("{field}",a(Ne[t]??t,e))).join(" \xB7 "):""}
> >
${this._loading?a("completing",e):a("complete",e)} ${this._loading?a("completing",e):a("complete",e)}
</ha-button> </ha-button>
@@ -2999,7 +3045,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
color: var(--text-primary-color, #fff); color: var(--text-primary-color, #fff);
border-color: var(--primary-color); border-color: var(--primary-color);
} }
`],c([x({attribute:!1})],$.prototype,"hass",2),c([x()],$.prototype,"entryId",2),c([x()],$.prototype,"taskId",2),c([x()],$.prototype,"taskName",2),c([x()],$.prototype,"lang",2),c([x({type:Array})],$.prototype,"checklist",2),c([x({type:Boolean})],$.prototype,"adaptiveEnabled",2),c([x()],$.prototype,"taskType",2),c([x()],$.prototype,"readingUnit",2),c([x({attribute:!1})],$.prototype,"restockDefault",2),c([x({attribute:!1})],$.prototype,"restockUnitCost",2),c([x()],$.prototype,"currencySymbol",2),c([x({attribute:!1})],$.prototype,"parts",2),c([x({attribute:!1})],$.prototype,"consumesParts",2),c([x({type:Array})],$.prototype,"consumesInfo",2),c([x({type:Array})],$.prototype,"requiredFields",2),c([x()],$.prototype,"phaseLabel",2),c([x({type:Boolean})],$.prototype,"requireTagScan",2),c([x({type:Boolean})],$.prototype,"viaTagScan",2),c([h()],$.prototype,"_open",2),c([h()],$.prototype,"_notes",2),c([h()],$.prototype,"_cost",2),c([h()],$.prototype,"_duration",2),c([h()],$.prototype,"_loading",2),c([h()],$.prototype,"_error",2),c([h()],$.prototype,"_checklistState",2),c([h()],$.prototype,"_feedback",2),c([h()],$.prototype,"_photoDocId",2),c([h()],$.prototype,"_photoPreview",2),c([h()],$.prototype,"_photoUploading",2),c([h()],$.prototype,"_readingValue",2),c([h()],$.prototype,"_restockQty",2),c([h()],$.prototype,"_completedAt",2),c([h()],$.prototype,"_usedParts",2),c([x({attribute:!1})],$.prototype,"checklistPrefill",2);customElements.get("maintenance-complete-dialog")||customElements.define("maintenance-complete-dialog",$)});var U,ji=w(()=>{"use strict";P();W();N();de();U=class extends A{constructor(){super(...arguments);this._open=!1;this._saving=!1;this._error="";this._draft=null;this._originalSnapshot=null;this._partOptions=null;this._partQty={};this._partQtyOriginal=""}get _lang(){return D(this.hass)}openEdit(e){this._draft={...e},this._originalSnapshot={...e},this._error="",this._open=!0,this._partOptions=null,this._partQty={},this._partQtyOriginal="",this._loadPartOptions()}async _loadPartOptions(){let e=this._draft;if(e)try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/parts/overview"}),i=[];for(let o of t.parts||[]){let p=o.entry_id===e.entry_id,d=o.consumers.some(u=>u.entry_id===e.entry_id&&u.task_id===e.task_id);!p&&!d||i.push({part_id:o.part_id,name:o.name,entry_id:o.entry_id,foreign:!p,object_name:o.object_name})}for(let o of e.used_parts||[]){let p=o.entry_id||e.entry_id;i.some(d=>d.part_id===o.part_id&&d.entry_id===p)||i.push({part_id:o.part_id,name:o.name||o.part_id,entry_id:p,foreign:p!==e.entry_id,object_name:null})}let n={};for(let o of e.used_parts||[])n[`${o.entry_id||e.entry_id}:${o.part_id}`]=o.quantity??1;this._partOptions=i,this._partQty=n,this._partQtyOriginal=this._partSelectionKey()}catch{this._partOptions=[]}}_partSelectionKey(){return JSON.stringify(Object.entries(this._partQty).filter(([,e])=>e>0).sort(([e],[t])=>e.localeCompare(t)))}close(){this._open=!1,this._error="",this._draft=null,this._originalSnapshot=null}_set(e,t){this._draft&&(this._draft={...this._draft,[e]:t})}async _save(){if(!(!this._draft||!this._originalSnapshot)){this._saving=!0,this._error="";try{let e={type:"maintenance_supporter/task/history/update",entry_id:this._draft.entry_id,task_id:this._draft.task_id,original_timestamp:this._originalSnapshot.original_timestamp};if(this._draft.timestamp!==this._originalSnapshot.timestamp&&(e.timestamp=this._draft.timestamp),this._draft.notes!==this._originalSnapshot.notes&&(e.notes=this._draft.notes),this._draft.cost!==this._originalSnapshot.cost&&(e.cost=this._draft.cost),this._draft.duration!==this._originalSnapshot.duration&&(e.duration=this._draft.duration),this._draft.completed_by!==this._originalSnapshot.completed_by&&(e.completed_by=this._draft.completed_by),this._partOptions!==null&&this._partSelectionKey()!==this._partQtyOriginal&&(e.used_parts=(this._partOptions||[]).filter(i=>(this._partQty[`${i.entry_id}:${i.part_id}`]||0)>0).map(i=>({part_id:i.part_id,quantity:this._partQty[`${i.entry_id}:${i.part_id}`],...i.foreign?{entry_id:i.entry_id}:{}}))),Object.keys(e).filter(i=>!["type","entry_id","task_id","original_timestamp"].includes(i)).length===0){this.close();return}await this.hass.connection.sendMessagePromise(e),this.dispatchEvent(new CustomEvent("history-entry-saved",{detail:{entry_id:this._draft.entry_id,task_id:this._draft.task_id,new_timestamp:this._draft.timestamp},bubbles:!0,composed:!0})),this.close()}catch(e){this._error=j(e,this._lang)}finally{this._saving=!1}}}render(){if(!this._open||!this._draft)return _;let e=this._lang,t=this._draft;return l` `],c([x({attribute:!1})],$.prototype,"hass",2),c([x()],$.prototype,"entryId",2),c([x()],$.prototype,"taskId",2),c([x()],$.prototype,"taskName",2),c([x()],$.prototype,"lang",2),c([x({type:Array})],$.prototype,"checklist",2),c([x({type:Boolean})],$.prototype,"adaptiveEnabled",2),c([x()],$.prototype,"taskType",2),c([x()],$.prototype,"readingUnit",2),c([x({attribute:!1})],$.prototype,"restockDefault",2),c([x({attribute:!1})],$.prototype,"restockUnitCost",2),c([x()],$.prototype,"currencySymbol",2),c([x({attribute:!1})],$.prototype,"parts",2),c([x({attribute:!1})],$.prototype,"consumesParts",2),c([x({type:Array})],$.prototype,"consumesInfo",2),c([x({type:Array})],$.prototype,"requiredFields",2),c([x()],$.prototype,"phaseLabel",2),c([x({type:Boolean})],$.prototype,"requireTagScan",2),c([x({type:Boolean})],$.prototype,"viaTagScan",2),c([h()],$.prototype,"_open",2),c([h()],$.prototype,"_notes",2),c([h()],$.prototype,"_cost",2),c([h()],$.prototype,"_duration",2),c([h()],$.prototype,"_loading",2),c([h()],$.prototype,"_error",2),c([h()],$.prototype,"_checklistState",2),c([h()],$.prototype,"_feedback",2),c([h()],$.prototype,"_photoDocId",2),c([h()],$.prototype,"_photoPreview",2),c([h()],$.prototype,"_photoUploading",2),c([h()],$.prototype,"_readingValue",2),c([h()],$.prototype,"_restockQty",2),c([h()],$.prototype,"_completedAt",2),c([h()],$.prototype,"_usedParts",2),c([x({attribute:!1})],$.prototype,"checklistPrefill",2);customElements.get("maintenance-complete-dialog")||customElements.define("maintenance-complete-dialog",$)});var U,Ni=w(()=>{"use strict";P();W();j();de();U=class extends A{constructor(){super(...arguments);this._open=!1;this._saving=!1;this._error="";this._draft=null;this._originalSnapshot=null;this._partOptions=null;this._partQty={};this._partQtyOriginal=""}get _lang(){return D(this.hass)}openEdit(e){this._draft={...e},this._originalSnapshot={...e},this._error="",this._open=!0,this._partOptions=null,this._partQty={},this._partQtyOriginal="",this._loadPartOptions()}async _loadPartOptions(){let e=this._draft;if(e)try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/parts/overview"}),i=[];for(let o of t.parts||[]){let p=o.entry_id===e.entry_id,d=o.consumers.some(u=>u.entry_id===e.entry_id&&u.task_id===e.task_id);!p&&!d||i.push({part_id:o.part_id,name:o.name,entry_id:o.entry_id,foreign:!p,object_name:o.object_name})}for(let o of e.used_parts||[]){let p=o.entry_id||e.entry_id;i.some(d=>d.part_id===o.part_id&&d.entry_id===p)||i.push({part_id:o.part_id,name:o.name||o.part_id,entry_id:p,foreign:p!==e.entry_id,object_name:null})}let n={};for(let o of e.used_parts||[])n[`${o.entry_id||e.entry_id}:${o.part_id}`]=o.quantity??1;this._partOptions=i,this._partQty=n,this._partQtyOriginal=this._partSelectionKey()}catch{this._partOptions=[]}}_partSelectionKey(){return JSON.stringify(Object.entries(this._partQty).filter(([,e])=>e>0).sort(([e],[t])=>e.localeCompare(t)))}close(){this._open=!1,this._error="",this._draft=null,this._originalSnapshot=null}_set(e,t){this._draft&&(this._draft={...this._draft,[e]:t})}async _save(){if(!(!this._draft||!this._originalSnapshot)){this._saving=!0,this._error="";try{let e={type:"maintenance_supporter/task/history/update",entry_id:this._draft.entry_id,task_id:this._draft.task_id,original_timestamp:this._originalSnapshot.original_timestamp};if(this._draft.timestamp!==this._originalSnapshot.timestamp&&(e.timestamp=this._draft.timestamp),this._draft.notes!==this._originalSnapshot.notes&&(e.notes=this._draft.notes),this._draft.cost!==this._originalSnapshot.cost&&(e.cost=this._draft.cost),this._draft.duration!==this._originalSnapshot.duration&&(e.duration=this._draft.duration),this._draft.completed_by!==this._originalSnapshot.completed_by&&(e.completed_by=this._draft.completed_by),this._partOptions!==null&&this._partSelectionKey()!==this._partQtyOriginal&&(e.used_parts=(this._partOptions||[]).filter(i=>(this._partQty[`${i.entry_id}:${i.part_id}`]||0)>0).map(i=>({part_id:i.part_id,quantity:this._partQty[`${i.entry_id}:${i.part_id}`],...i.foreign?{entry_id:i.entry_id}:{}}))),Object.keys(e).filter(i=>!["type","entry_id","task_id","original_timestamp"].includes(i)).length===0){this.close();return}await this.hass.connection.sendMessagePromise(e),this.dispatchEvent(new CustomEvent("history-entry-saved",{detail:{entry_id:this._draft.entry_id,task_id:this._draft.task_id,new_timestamp:this._draft.timestamp},bubbles:!0,composed:!0})),this.close()}catch(e){this._error=N(e,this._lang)}finally{this._saving=!1}}}render(){if(!this._open||!this._draft)return _;let e=this._lang,t=this._draft;return l`
<div class="backdrop" @click=${this.close}></div> <div class="backdrop" @click=${this.close}></div>
<div class="dialog" role="dialog" aria-modal="true"> <div class="dialog" role="dialog" aria-modal="true">
<h2>${a("history_edit_title",e)||"Edit history entry"}</h2> <h2>${a("history_edit_title",e)||"Edit history entry"}</h2>
@@ -3137,7 +3183,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
.part-row-edit input[type="checkbox"] { width: auto; } .part-row-edit input[type="checkbox"] { width: auto; }
.part-label { flex: 1; color: var(--primary-text-color); } .part-label { flex: 1; color: var(--primary-text-color); }
.part-qty { width: 76px; } .part-qty { width: 76px; }
`,c([x({attribute:!1})],U.prototype,"hass",2),c([h()],U.prototype,"_open",2),c([h()],U.prototype,"_saving",2),c([h()],U.prototype,"_error",2),c([h()],U.prototype,"_draft",2),c([h()],U.prototype,"_partOptions",2),c([h()],U.prototype,"_partQty",2);customElements.get("maintenance-history-edit-dialog")||customElements.define("maintenance-history-edit-dialog",U)});function Hi(r,s,e){let t=new Blob([r],{type:e}),i=URL.createObjectURL(t),n=document.createElement("a");n.href=i,n.download=s,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(i),6e4)}var Di=w(()=>{"use strict"});function fe(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Mi(r){return!r.startsWith("data:image/svg+xml,")&&!r.startsWith("data:image/png;base64,")?"":fe(r)}function Zs(r){return r.replace(/[/\\:*?"<>|#%]+/g,"").replace(/\s+/g,"-").toLowerCase().substring(0,100)}var z,Oi=w(()=>{"use strict";P();W();N();Di();z=class extends A{constructor(){super(...arguments);this.lang="en";this._open=!1;this._loading=!1;this._error="";this._viewResult=null;this._completeResult=null;this._urlMode="companion";this._entryId="";this._taskId=null;this._objectName="";this._taskName="";this._generateSeq=0}openForObject(e,t){this._entryId=e,this._taskId=null,this._objectName=t,this._taskName="",this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}openForTask(e,t,i,n){this._entryId=e,this._taskId=t,this._objectName=i,this._taskName=n,this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}async _generate(){let e=++this._generateSeq;this._loading=!0,this._error="",this._viewResult=null,this._completeResult=null;try{let t={type:"maintenance_supporter/qr/generate",entry_id:this._entryId,url_mode:this._urlMode};this._taskId&&(t.task_id=this._taskId);let i=[this.hass.connection.sendMessagePromise({...t,action:"view"})];this._taskId&&i.push(this.hass.connection.sendMessagePromise({...t,action:"complete"}));let n=await Promise.all(i);if(e!==this._generateSeq)return;this._viewResult=n[0],n.length>1&&(this._completeResult=n[1])}catch(t){if(e!==this._generateSeq)return;let i=t?.code,n=t?.message;this._error=i==="no_url"||typeof n=="string"&&n.includes("No Home Assistant URL")?a("qr_error_no_url",this.lang):a("qr_error",this.lang)}finally{e===this._generateSeq&&(this._loading=!1)}}_setUrlMode(e){this._urlMode!==e&&(this._urlMode=e,this._generate())}_print(){if(!this._viewResult)return;let e=this._viewResult,t=e.label.task_name?`${e.label.object_name} \u2014 ${e.label.task_name}`:e.label.object_name,i=[e.label.manufacturer,e.label.model].filter(Boolean).join(" "),n=window.open("","_blank","width=600,height=500");if(!n)return;let o=this.lang||"en",p=fe(t),d=fe(i),u=!!this._completeResult,m=fe(a("qr_action_view",o)),f=fe(a("qr_action_complete",o));n.document.write(`<!DOCTYPE html><html><head><meta charset="utf-8"> `,c([x({attribute:!1})],U.prototype,"hass",2),c([h()],U.prototype,"_open",2),c([h()],U.prototype,"_saving",2),c([h()],U.prototype,"_error",2),c([h()],U.prototype,"_draft",2),c([h()],U.prototype,"_partOptions",2),c([h()],U.prototype,"_partQty",2);customElements.get("maintenance-history-edit-dialog")||customElements.define("maintenance-history-edit-dialog",U)});function Hi(r,s,e){let t=new Blob([r],{type:e}),i=URL.createObjectURL(t),n=document.createElement("a");n.href=i,n.download=s,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(i),6e4)}var Di=w(()=>{"use strict"});function fe(r){return r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function Mi(r){return!r.startsWith("data:image/svg+xml,")&&!r.startsWith("data:image/png;base64,")?"":fe(r)}function Zs(r){return r.replace(/[/\\:*?"<>|#%]+/g,"").replace(/\s+/g,"-").toLowerCase().substring(0,100)}var z,Oi=w(()=>{"use strict";P();W();j();Di();z=class extends A{constructor(){super(...arguments);this.lang="en";this._open=!1;this._loading=!1;this._error="";this._viewResult=null;this._completeResult=null;this._urlMode="companion";this._entryId="";this._taskId=null;this._objectName="";this._taskName="";this._generateSeq=0}openForObject(e,t){this._entryId=e,this._taskId=null,this._objectName=t,this._taskName="",this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}openForTask(e,t,i,n){this._entryId=e,this._taskId=t,this._objectName=i,this._taskName=n,this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}async _generate(){let e=++this._generateSeq;this._loading=!0,this._error="",this._viewResult=null,this._completeResult=null;try{let t={type:"maintenance_supporter/qr/generate",entry_id:this._entryId,url_mode:this._urlMode};this._taskId&&(t.task_id=this._taskId);let i=[this.hass.connection.sendMessagePromise({...t,action:"view"})];this._taskId&&i.push(this.hass.connection.sendMessagePromise({...t,action:"complete"}));let n=await Promise.all(i);if(e!==this._generateSeq)return;this._viewResult=n[0],n.length>1&&(this._completeResult=n[1])}catch(t){if(e!==this._generateSeq)return;let i=t?.code,n=t?.message;this._error=i==="no_url"||typeof n=="string"&&n.includes("No Home Assistant URL")?a("qr_error_no_url",this.lang):a("qr_error",this.lang)}finally{e===this._generateSeq&&(this._loading=!1)}}_setUrlMode(e){this._urlMode!==e&&(this._urlMode=e,this._generate())}_print(){if(!this._viewResult)return;let e=this._viewResult,t=e.label.task_name?`${e.label.object_name} \u2014 ${e.label.task_name}`:e.label.object_name,i=[e.label.manufacturer,e.label.model].filter(Boolean).join(" "),n=window.open("","_blank","width=600,height=500");if(!n)return;let o=this.lang||"en",p=fe(t),d=fe(i),u=!!this._completeResult,m=fe(a("qr_action_view",o)),f=fe(a("qr_action_complete",o));n.document.write(`<!DOCTYPE html><html><head><meta charset="utf-8">
<meta name="color-scheme" content="light"> <meta name="color-scheme" content="light">
<title>${p}</title> <title>${p}</title>
<style> <style>
@@ -3348,7 +3394,7 @@ ${d?`<div class="sub">${d}</div>`:""}
color: var(--text-primary-color, #fff); color: var(--text-primary-color, #fff);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.15);
} }
`,c([x({attribute:!1})],z.prototype,"hass",2),c([x()],z.prototype,"lang",2),c([h()],z.prototype,"_open",2),c([h()],z.prototype,"_loading",2),c([h()],z.prototype,"_error",2),c([h()],z.prototype,"_viewResult",2),c([h()],z.prototype,"_completeResult",2),c([h()],z.prototype,"_urlMode",2);customElements.get("maintenance-qr-dialog")||customElements.define("maintenance-qr-dialog",z)});function Xs(r,s){if(s<=0)return 0;let e=typeof r=="number"&&Number.isFinite(r)?Math.trunc(r):0;return e<0?0:e%s}function er(r){return!!(r?.phases&&r.phase_sequence&&r.phase_sequence.length>0)}function xt(r){if(!r||!er(r))return null;let s=r.phase_sequence,e=Xs(r.phase_cursor,s.length),t=s[e],i=r.phases?.[t];return i?{id:t,name:i.name,index:e,count:s.length,notes:i.notes,checklist:i.checklist!==void 0?i.checklist:r.checklist??[],consumesParts:i.consumes_parts!==void 0?i.consumes_parts:r.consumes_parts??[],requiredFields:i.required_completion_fields!==void 0?i.required_completion_fields:r.required_completion_fields??[]}:null}function He(r){let s=xt(r);return s?`${s.index+1}/${s.count} \xB7 ${s.name}`:""}var wt=w(()=>{"use strict"});function zi(r){let s=r.task??null,e=s?xt(s):null,t=e?e.consumesParts:s?.consumes_parts||[],i=!!s?.part_ref,n=r.objects.find(d=>d.entry_id===r.entryId)?.parts||[],o=i?n.find(d=>d.id===s.part_ref.part_id):void 0,p=r.checklistsEnabled??!0;return{entry_id:r.entryId,task_id:r.taskId,task_name:r.taskName,checklist:e?p?e.checklist:[]:r.checklist??[],adaptive_enabled:!!r.adaptiveEnabled,required_completion_fields:e?e.requiredFields:s?.required_completion_fields||[],task_type:s?.type||"",reading_unit:s?.reading_unit||"",parts:i?[]:Ci({consumes_parts:t},r.entryId,r.objects,r.lang),consumes_parts:i?[]:t,phase_label:e?He(s):"",require_tag_scan:!!s?.require_tag_scan,restock_default:i?o?.restock_quantity??1:null,restock_unit_cost:i?o?.cost??null:null,currency_symbol:r.currencySymbol??"",consumes_info:t.map(d=>Ti(d,r.entryId,r.objects,r.lang)),checklist_prefill:s?.checklist_progress||{},via_tag_scan:!!r.viaTagScan}}function Fi(r,s,e){r.entryId=s.entry_id,r.taskId=s.task_id,r.taskName=s.task_name,r.lang=e,r.checklist=s.checklist??[],r.adaptiveEnabled=!!s.adaptive_enabled,r.requiredFields=s.required_completion_fields??[],r.taskType=s.task_type??"",r.readingUnit=s.reading_unit??"",r.parts=s.parts??[],r.consumesParts=s.consumes_parts??[],r.phaseLabel=s.phase_label??"",r.requireTagScan=!!s.require_tag_scan,r.restockDefault=s.restock_default??null,r.restockUnitCost=s.restock_unit_cost??null,r.currencySymbol=s.currency_symbol??"",r.consumesInfo=s.consumes_info??[],r.checklistPrefill=s.checklist_prefill??{},r.viaTagScan=!!s.via_tag_scan,r.open({viaTagScan:!!s.via_tag_scan})}var $t=w(()=>{"use strict";Je();wt()});function Ui(r,s){let e=r.interval_analysis,t=e?.weibull_beta,i=e?.weibull_eta;if(t==null||i==null||i<=0)return _;let n=r.interval_days??0,o=r.suggested_interval??n;return l` `,c([x({attribute:!1})],z.prototype,"hass",2),c([x()],z.prototype,"lang",2),c([h()],z.prototype,"_open",2),c([h()],z.prototype,"_loading",2),c([h()],z.prototype,"_error",2),c([h()],z.prototype,"_viewResult",2),c([h()],z.prototype,"_completeResult",2),c([h()],z.prototype,"_urlMode",2);customElements.get("maintenance-qr-dialog")||customElements.define("maintenance-qr-dialog",z)});function Xs(r,s){if(s<=0)return 0;let e=typeof r=="number"&&Number.isFinite(r)?Math.trunc(r):0;return e<0?0:e%s}function er(r){return!!(r?.phases&&r.phase_sequence&&r.phase_sequence.length>0)}function xt(r){if(!r||!er(r))return null;let s=r.phase_sequence,e=Xs(r.phase_cursor,s.length),t=s[e],i=r.phases?.[t];return i?{id:t,name:i.name,index:e,count:s.length,notes:i.notes,checklist:i.checklist!==void 0?i.checklist:r.checklist??[],consumesParts:i.consumes_parts!==void 0?i.consumes_parts:r.consumes_parts??[],requiredFields:i.required_completion_fields!==void 0?i.required_completion_fields:r.required_completion_fields??[]}:null}function He(r){let s=xt(r);return s?`${s.index+1}/${s.count} \xB7 ${s.name}`:""}var wt=w(()=>{"use strict"});function zi(r){let s=r.task??null,e=s?xt(s):null,t=e?e.consumesParts:s?.consumes_parts||[],i=!!s?.part_ref,n=r.objects.find(d=>d.entry_id===r.entryId)?.parts||[],o=i?n.find(d=>d.id===s.part_ref.part_id):void 0,p=r.checklistsEnabled??!0;return{entry_id:r.entryId,task_id:r.taskId,task_name:r.taskName,checklist:e?p?e.checklist:[]:r.checklist??[],adaptive_enabled:!!r.adaptiveEnabled,required_completion_fields:e?e.requiredFields:s?.required_completion_fields||[],task_type:s?.type||"",reading_unit:s?.reading_unit||"",parts:i?[]:Ii({consumes_parts:t},r.entryId,r.objects,r.lang),consumes_parts:i?[]:t,phase_label:e?He(s):"",require_tag_scan:!!s?.require_tag_scan,restock_default:i?o?.restock_quantity??1:null,restock_unit_cost:i?o?.cost??null:null,currency_symbol:r.currencySymbol??"",consumes_info:t.map(d=>Ti(d,r.entryId,r.objects,r.lang)),checklist_prefill:s?.checklist_progress||{},via_tag_scan:!!r.viaTagScan}}function Fi(r,s,e){r.entryId=s.entry_id,r.taskId=s.task_id,r.taskName=s.task_name,r.lang=e,r.checklist=s.checklist??[],r.adaptiveEnabled=!!s.adaptive_enabled,r.requiredFields=s.required_completion_fields??[],r.taskType=s.task_type??"",r.readingUnit=s.reading_unit??"",r.parts=s.parts??[],r.consumesParts=s.consumes_parts??[],r.phaseLabel=s.phase_label??"",r.requireTagScan=!!s.require_tag_scan,r.restockDefault=s.restock_default??null,r.restockUnitCost=s.restock_unit_cost??null,r.currencySymbol=s.currency_symbol??"",r.consumesInfo=s.consumes_info??[],r.checklistPrefill=s.checklist_prefill??{},r.viaTagScan=!!s.via_tag_scan,r.open({viaTagScan:!!s.via_tag_scan})}var $t=w(()=>{"use strict";Je();wt()});function Ui(r,s){let e=r.interval_analysis,t=e?.weibull_beta,i=e?.weibull_eta;if(t==null||i==null||i<=0)return _;let n=r.interval_days??0,o=r.suggested_interval??n;return l`
<div class="weibull-section"> <div class="weibull-section">
<div class="weibull-title"> <div class="weibull-title">
<ha-svg-icon aria-hidden="true" path="M3,14L3.5,14.07L8.07,9.5C7.89,8.85 8.06,8.11 8.59,7.59C9.37,6.8 10.63,6.8 11.41,7.59C11.94,8.11 12.11,8.85 11.93,9.5L14.5,12.07L15,12C15.18,12 15.35,12 15.5,12.07L19.07,8.5C19,8.35 19,8.18 19,8A2,2 0 0,1 21,6A2,2 0 0,1 23,8A2,2 0 0,1 21,10C20.82,10 20.65,10 20.5,9.93L16.93,13.5C17,13.65 17,13.82 17,14A2,2 0 0,1 15,16A2,2 0 0,1 13,14L13.07,13.5L10.5,10.93C10.18,11 9.82,11 9.5,10.93L4.93,15.5L5,16A2,2 0 0,1 3,18A2,2 0 0,1 1,16A2,2 0 0,1 3,14Z"></ha-svg-icon> <ha-svg-icon aria-hidden="true" path="M3,14L3.5,14.07L8.07,9.5C7.89,8.85 8.06,8.11 8.59,7.59C9.37,6.8 10.63,6.8 11.41,7.59C11.94,8.11 12.11,8.85 11.93,9.5L14.5,12.07L15,12C15.18,12 15.35,12 15.5,12.07L19.07,8.5C19,8.35 19,8.18 19,8A2,2 0 0,1 21,6A2,2 0 0,1 23,8A2,2 0 0,1 21,10C20.82,10 20.65,10 20.5,9.93L16.93,13.5C17,13.65 17,13.82 17,14A2,2 0 0,1 15,16A2,2 0 0,1 13,14L13.07,13.5L10.5,10.93C10.18,11 9.82,11 9.5,10.93L4.93,15.5L5,16A2,2 0 0,1 3,18A2,2 0 0,1 1,16A2,2 0 0,1 3,14Z"></ha-svg-icon>
@@ -3364,14 +3410,14 @@ ${d?`<div class="sub">${d}</div>`:""}
<ha-svg-icon path="${t}"></ha-svg-icon> <ha-svg-icon path="${t}"></ha-svg-icon>
${a(i,s)} (\u03B2=${r.toFixed(2)}) ${a(i,s)} (\u03B2=${r.toFixed(2)})
</span> </span>
`}function ir(r,s,e,t,i){let y=Math.max(e,t,s,1)*1.3,k=50,E=[];for(let I=0;I<=k;I++){let R=I/k*y,se=1-Math.exp(-Math.pow(R/s,r)),ye=32+R/y*260,be=136-se*128;E.push([ye,be])}let H=E.map(([I,R])=>`${I.toFixed(1)},${R.toFixed(1)}`).join(" "),M="M32,136 "+E.map(([I,R])=>`L${I.toFixed(1)},${R.toFixed(1)}`).join(" ")+` L${E[k][0].toFixed(1)},136 Z`,q=32+e/y*260,F=1-Math.exp(-Math.pow(e/s,r)),te=136-F*128,b=((1-F)*100).toFixed(0),B=32+t/y*260,pe=[0,.25,.5,.75,1];return l` `}function ir(r,s,e,t,i){let y=Math.max(e,t,s,1)*1.3,k=50,E=[];for(let C=0;C<=k;C++){let R=C/k*y,se=1-Math.exp(-Math.pow(R/s,r)),ye=32+R/y*260,be=136-se*128;E.push([ye,be])}let H=E.map(([C,R])=>`${C.toFixed(1)},${R.toFixed(1)}`).join(" "),M="M32,136 "+E.map(([C,R])=>`L${C.toFixed(1)},${R.toFixed(1)}`).join(" ")+` L${E[k][0].toFixed(1)},136 Z`,q=32+e/y*260,F=1-Math.exp(-Math.pow(e/s,r)),te=136-F*128,b=((1-F)*100).toFixed(0),B=32+t/y*260,pe=[0,.25,.5,.75,1];return l`
<div class="weibull-chart"> <div class="weibull-chart">
<svg viewBox="0 0 ${300} ${160}" preserveAspectRatio="xMidYMid meet" role="img" aria-label="${a("chart_weibull",i)}"> <svg viewBox="0 0 ${300} ${160}" preserveAspectRatio="xMidYMid meet" role="img" aria-label="${a("chart_weibull",i)}">
${pe.map(I=>{let R=136-I*128;return _e` ${pe.map(C=>{let R=136-C*128;return _e`
<line x1="${32}" y1="${R.toFixed(1)}" x2="${292}" y2="${R.toFixed(1)}" <line x1="${32}" y1="${R.toFixed(1)}" x2="${292}" y2="${R.toFixed(1)}"
stroke="var(--divider-color)" stroke-width="0.5" stroke-dasharray="${I===.5?"4,3":_}" /> stroke="var(--divider-color)" stroke-width="0.5" stroke-dasharray="${C===.5?"4,3":_}" />
<text x="${28}" y="${(R+3).toFixed(1)}" fill="var(--secondary-text-color)" <text x="${28}" y="${(R+3).toFixed(1)}" fill="var(--secondary-text-color)"
font-size="8" text-anchor="end">${(I*100).toFixed(0)}%</text> font-size="8" text-anchor="end">${(C*100).toFixed(0)}%</text>
`})} `})}
<text x="${32}" y="${156}" fill="var(--secondary-text-color)" font-size="8" text-anchor="middle">0</text> <text x="${32}" y="${156}" fill="var(--secondary-text-color)" font-size="8" text-anchor="middle">0</text>
@@ -3435,7 +3481,7 @@ ${d?`<div class="sub">${d}</div>`:""}
<span class="confidence-text high">${a("confidence_aggressive",e)} (${i}${a("days",e).charAt(0)})</span> <span class="confidence-text high">${a("confidence_aggressive",e)} (${i}${a("days",e).charAt(0)})</span>
</div> </div>
</div> </div>
`}var Bi=w(()=>{"use strict";P();N()});function Wi(r,s,e){let t=r.degradation_trend!=null&&r.degradation_trend!=="insufficient_data",i=r.days_until_threshold!=null,n=r.environmental_factor!=null&&r.environmental_factor!==1;if(!t&&!i&&!n)return _;let o=r.degradation_trend==="rising"?"M16,6L18.29,8.29L13.41,13.17L9.41,9.17L2,16.59L3.41,18L9.41,12L13.41,16L19.71,9.71L22,12V6H16Z":r.degradation_trend==="falling"?"M16,18L18.29,15.71L13.41,10.83L9.41,14.83L2,7.41L3.41,6L9.41,12L13.41,8L19.71,14.29L22,12V18H16Z":"M22,12L18,8V11H3V13H18V16L22,12Z";return l` `}var Bi=w(()=>{"use strict";P();j()});function Wi(r,s,e){let t=r.degradation_trend!=null&&r.degradation_trend!=="insufficient_data",i=r.days_until_threshold!=null,n=r.environmental_factor!=null&&r.environmental_factor!==1;if(!t&&!i&&!n)return _;let o=r.degradation_trend==="rising"?"M16,6L18.29,8.29L13.41,13.17L9.41,9.17L2,16.59L3.41,18L9.41,12L13.41,16L19.71,9.71L22,12V6H16Z":r.degradation_trend==="falling"?"M16,18L18.29,15.71L13.41,10.83L9.41,14.83L2,7.41L3.41,6L9.41,12L13.41,8L19.71,14.29L22,12V18H16Z":"M22,12L18,8V11H3V13H18V16L22,12Z";return l`
<div class="prediction-section"> <div class="prediction-section">
${r.sensor_prediction_urgency?l` ${r.sensor_prediction_urgency?l`
<div class="prediction-urgency-banner"> <div class="prediction-urgency-banner">
@@ -3476,7 +3522,7 @@ ${d?`<div class="sub">${d}</div>`:""}
`:_} `:_}
</div> </div>
</div> </div>
`}var Vi=w(()=>{"use strict";P();N()});function Ki(r,s,e,t){let i=Math.max(r||1,s);return l` `}var Vi=w(()=>{"use strict";P();j()});function Ki(r,s,e,t){let i=Math.max(r||1,s);return l`
<div class="interval-comparison"> <div class="interval-comparison">
<div class="interval-bar"> <div class="interval-bar">
<div class="interval-label"> <div class="interval-label">
@@ -3494,7 +3540,7 @@ ${d?`<div class="sub">${d}</div>`:""}
style="width: ${Math.min(s/i*100,100)}%"></div> style="width: ${Math.min(s/i*100,100)}%"></div>
</div> </div>
</div> </div>
`}var Gi=w(()=>{"use strict";P();N()});function Qi(r,s,e){if(!e.seasonal||!r.seasonal_factor||r.seasonal_factor===1)return _;let t=Yi.map(p=>a(p,s)),i=new Date().getMonth(),n=r.seasonal_factors||r.interval_analysis?.seasonal_factors||null,o=n&&n.length===12?n:t.map((p,d)=>{let u=r.seasonal_factor||1,m=Math.sin((d-6)*Math.PI/6)*.3;return Math.max(.7,Math.min(1.3,u+m))});return l` `}var Gi=w(()=>{"use strict";P();j()});function Qi(r,s,e){if(!e.seasonal||!r.seasonal_factor||r.seasonal_factor===1)return _;let t=Yi.map(p=>a(p,s)),i=new Date().getMonth(),n=r.seasonal_factors||r.interval_analysis?.seasonal_factors||null,o=n&&n.length===12?n:t.map((p,d)=>{let u=r.seasonal_factor||1,m=Math.sin((d-6)*Math.PI/6)*.3;return Math.max(.7,Math.min(1.3,u+m))});return l`
<div class="seasonal-card-compact"> <div class="seasonal-card-compact">
<h4>${a("seasonal_awareness",s)}</h4> <h4>${a("seasonal_awareness",s)}</h4>
<div class="seasonal-mini-chart"> <div class="seasonal-mini-chart">
@@ -3531,7 +3577,7 @@ ${d?`<div class="sub">${d}</div>`:""}
${Yi.map((k,E)=>l`<span class="seasonal-label ${E===i?"active-month":""}">${a(k,s)}</span>`)} ${Yi.map((k,E)=>l`<span class="seasonal-label ${E===i?"active-month":""}">${a(k,s)}</span>`)}
</div> </div>
</div> </div>
`}var Yi,Zi=w(()=>{"use strict";P();N();Yi=["month_jan","month_feb","month_mar","month_apr","month_may","month_jun","month_jul","month_aug","month_sep","month_oct","month_nov","month_dec"]});var C,Xi=w(()=>{"use strict";P();W();N();de();ht();$t();wt();Bi();Vi();Gi();Zi();C=class extends A{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._taskId=null;this._task=null;this._objectName="";this._busy=!1;this._error="";this._showSkip=!1;this._showReset=!1;this._showDetails=!1;this._showAdaptive=!1;this._skipReason="";this._resetDate="";this._features={adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1};this._toast="";this._featuresLoaded=!1;this._currencySymbol=""}get _lang(){return D(this.hass)}async openFor(e,t){this._entryId=e,this._taskId=t,this._error="",this._showSkip=!1,this._showReset=!1,this._showAdaptive=!1,this._skipReason="",this._resetDate=le(new Date),this._open=!0,await Promise.all([this._loadTask(),this._loadFeatures()])}async _loadFeatures(){if(!this._featuresLoaded)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/settings"});e?.features&&(this._features={...this._features,...e.features}),this._currencySymbol=e?.budget?.currency_symbol||"",this._featuresLoaded=!0}catch{}}close(){this._open=!1,this._task=null,this._error=""}async _loadTask(){if(!(!this._entryId||!this._taskId))try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._objectName=e.object?.name||"";let t=(e.tasks||[]).find(i=>i.id===this._taskId);this._task=t??null}catch(e){this._error=j(e,this._lang)}}async _runWs(e){this._busy=!0,this._error="";try{return await this.hass.connection.sendMessagePromise(e),this._busy=!1,!0}catch(t){return this._error=j(t,this._lang),this._busy=!1,!1}}_notifyChanged(e){this.dispatchEvent(new CustomEvent("task-action-fired",{detail:{entry_id:this._entryId,task_id:this._taskId,action:e},bubbles:!0,composed:!0}))}_onComplete(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(async({openCompleteDialog:e})=>{let t=this._task,i=[];try{i=(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects",compact:!0})).objects||[]}catch{}e(zi({entryId:this._entryId,taskId:this._taskId,taskName:t.name,task:t,objects:i,lang:this._lang,checklist:t.checklist||[],adaptiveEnabled:!!t.adaptive_config?.enabled,currencySymbol:this._currencySymbol}))&&(this._notifyChanged("complete"),this.close())})}async _onSkipConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/skip",entry_id:this._entryId,task_id:this._taskId,reason:this._skipReason.trim()||null})&&(this._notifyChanged("skip"),this.close())}async _onResetConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/reset",entry_id:this._entryId,task_id:this._taskId,date:this._resetDate||void 0})&&(this._notifyChanged("reset"),this.close())}_onEdit(){!this._entryId||!this._taskId||Promise.resolve().then(()=>(K(),Z)).then(({openEditTaskDialog:e})=>{e(this._entryId,this._taskId),this.close()})}_onQr(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(({openQrDialog:e})=>{e({entry_id:this._entryId,task_id:this._taskId,task_name:this._task.name,object_name:this._objectName}),this.close()})}async _onDelete(){if(!this._entryId||!this._taskId)return;let e=a("delete_task_confirm",this._lang)||`Delete "${this._task?.name}"?`;if(!window.confirm(e))return;await this._runWs({type:"maintenance_supporter/task/delete",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("delete"),this.close())}async _onArchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/archive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("archive"),this.close())}async _onUnarchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/unarchive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("unarchive"),this.close())}_onOpenInPanel(){if(!this._entryId||!this._taskId)return;let e=`/maintenance-supporter?entry_id=${encodeURIComponent(this._entryId)}&task_id=${encodeURIComponent(this._taskId)}`;history.pushState(null,"",e),window.dispatchEvent(new CustomEvent("location-changed")),this.close()}async _applySuggestion(){if(!this._entryId||!this._taskId||!this._task?.suggested_interval)return;await this._runWs({type:"maintenance_supporter/task/apply_suggestion",entry_id:this._entryId,task_id:this._taskId,interval:this._task.suggested_interval})&&(this._toast=a("suggestion_applied",this._lang)||"Applied",this._notifyChanged("apply_suggestion"),await this._loadTask(),setTimeout(()=>{this._toast=""},2500))}async _reanalyzeInterval(){if(!(!this._entryId||!this._taskId)){this._busy=!0,this._error="";tr Line truncated `}var Yi,Zi=w(()=>{"use strict";P();j();Yi=["month_jan","month_feb","month_mar","month_apr","month_may","month_jun","month_jul","month_aug","month_sep","month_oct","month_nov","month_dec"]});var I,Xi=w(()=>{"use strict";P();W();j();de();ht();$t();wt();Bi();Vi();Gi();Zi();I=class extends A{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._taskId=null;this._task=null;this._objectName="";this._busy=!1;this._error="";this._showSkip=!1;this._showReset=!1;this._showDetails=!1;this._showAdaptive=!1;this._skipReason="";this._resetDate="";this._features={adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1};this._toast="";this._featuresLoaded=!1;this._currencySymbol=""}get _lang(){return D(this.hass)}async openFor(e,t){this._entryId=e,this._taskId=t,this._error="",this._showSkip=!1,this._showReset=!1,this._showAdaptive=!1,this._skipReason="",this._resetDate=le(new Date),this._open=!0,await Promise.all([this._loadTask(),this._loadFeatures()])}async _loadFeatures(){if(!this._featuresLoaded)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/settings"});e?.features&&(this._features={...this._features,...e.features}),this._currencySymbol=e?.budget?.currency_symbol||"",this._featuresLoaded=!0}catch{}}close(){this._open=!1,this._task=null,this._error=""}async _loadTask(){if(!(!this._entryId||!this._taskId))try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._objectName=e.object?.name||"";let t=(e.tasks||[]).find(i=>i.id===this._taskId);this._task=t??null}catch(e){this._error=N(e,this._lang)}}async _runWs(e){this._busy=!0,this._error="";try{return await this.hass.connection.sendMessagePromise(e),this._busy=!1,!0}catch(t){return this._error=N(t,this._lang),this._busy=!1,!1}}_notifyChanged(e){this.dispatchEvent(new CustomEvent("task-action-fired",{detail:{entry_id:this._entryId,task_id:this._taskId,action:e},bubbles:!0,composed:!0}))}_onComplete(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(async({openCompleteDialog:e})=>{let t=this._task,i=[];try{i=(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects",compact:!0})).objects||[]}catch{}e(zi({entryId:this._entryId,taskId:this._taskId,taskName:t.name,task:t,objects:i,lang:this._lang,checklist:t.checklist||[],adaptiveEnabled:!!t.adaptive_config?.enabled,currencySymbol:this._currencySymbol}))&&(this._notifyChanged("complete"),this.close())})}async _onSkipConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/skip",entry_id:this._entryId,task_id:this._taskId,reason:this._skipReason.trim()||null})&&(this._notifyChanged("skip"),this.close())}async _onResetConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/reset",entry_id:this._entryId,task_id:this._taskId,date:this._resetDate||void 0})&&(this._notifyChanged("reset"),this.close())}_onEdit(){!this._entryId||!this._taskId||Promise.resolve().then(()=>(K(),Z)).then(({openEditTaskDialog:e})=>{e(this._entryId,this._taskId),this.close()})}_onQr(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(({openQrDialog:e})=>{e({entry_id:this._entryId,task_id:this._taskId,task_name:this._task.name,object_name:this._objectName}),this.close()})}async _onDelete(){if(!this._entryId||!this._taskId)return;let e=a("delete_task_confirm",this._lang)||`Delete "${this._task?.name}"?`;if(!window.confirm(e))return;await this._runWs({type:"maintenance_supporter/task/delete",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("delete"),this.close())}async _onArchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/archive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("archive"),this.close())}async _onUnarchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/unarchive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("unarchive"),this.close())}_onOpenInPanel(){if(!this._entryId||!this._taskId)return;let e=`/maintenance-supporter?entry_id=${encodeURIComponent(this._entryId)}&task_id=${encodeURIComponent(this._taskId)}`;history.pushState(null,"",e),window.dispatchEvent(new CustomEvent("location-changed")),this.close()}async _applySuggestion(){if(!this._entryId||!this._taskId||!this._task?.suggested_interval)return;await this._runWs({type:"maintenance_supporter/task/apply_suggestion",entry_id:this._entryId,task_id:this._taskId,interval:this._task.suggested_interval})&&(this._toast=a("suggestion_applied",this._lang)||"Applied",this._notifyChanged("apply_suggestion"),await this._loadTask(),setTimeout(()=>{this._toast=""},2500))}async _reanalyzeInterval(){if(!(!this._entryId||!this._taskId)){this._busy=!0,this._error="";tr Line truncated
<div class="recommendation-card"> <div class="recommendation-card">
<h4>${a("suggested_interval",t)}</h4> <h4>${a("suggested_interval",t)}</h4>
${Ki(e.interval_days,e.suggested_interval,e.interval_confidence||"medium",t)} ${Ki(e.interval_days,e.suggested_interval,e.interval_confidence||"medium",t)}
@@ -3611,7 +3657,7 @@ ${d?`<div class="sub">${d}</div>`:""}
${t?l` ${t?l`
<div class="header"> <div class="header">
<div class="title"> <div class="title">
<span class="status-dot" style="background: ${Ie[t.status]||"#ccc"}"></span> <span class="status-dot" style="background: ${Ce[t.status]||"#ccc"}"></span>
<span class="task-name">${t.name}</span> <span class="task-name">${t.name}</span>
</div> </div>
<div class="object"> <div class="object">
@@ -3661,11 +3707,13 @@ ${d?`<div class="sub">${d}</div>`:""}
<ha-icon slot="start" icon="mdi:check"></ha-icon> <ha-icon slot="start" icon="mdi:check"></ha-icon>
${a("complete",e)||"Complete"} ${a("complete",e)||"Complete"}
</ha-button> </ha-button>
<ha-button appearance="plain" variant="neutral" @click=${()=>{this._showSkip=!0}} .disabled=${this._busy}> ${t.allow_skip!==!1?l`
<ha-icon slot="start" icon="mdi:skip-next"></ha-icon> <ha-button appearance="outlined" variant="neutral" @click=${()=>{this._showSkip=!0}} .disabled=${this._busy}>
${a("skip",e)||"Skip"} <ha-icon slot="start" icon="mdi:skip-next"></ha-icon>
</ha-button> ${a("skip",e)||"Skip"}
<ha-button appearance="plain" variant="neutral" @click=${()=>{this._showReset=!0}} .disabled=${this._busy}> </ha-button>
`:_}
<ha-button appearance="outlined" variant="neutral" @click=${()=>{this._showReset=!0}} .disabled=${this._busy}>
<ha-icon slot="start" icon="mdi:restart"></ha-icon> <ha-icon slot="start" icon="mdi:restart"></ha-icon>
${a("reset",e)||"Reset"} ${a("reset",e)||"Reset"}
</ha-button> </ha-button>
@@ -3713,7 +3761,7 @@ ${d?`<div class="sub">${d}</div>`:""}
`} `}
`:l`<div class="loading">${a("loading",e)||"Loading\u2026"}</div>`} `:l`<div class="loading">${a("loading",e)||"Loading\u2026"}</div>`}
</div> </div>
`}};C.styles=[Ye,S` `}};I.styles=[Ye,S`
:host { display: contents; } :host { display: contents; }
.backdrop { .backdrop {
position: fixed; inset: 0; z-index: 100; position: fixed; inset: 0; z-index: 100;
@@ -3896,7 +3944,7 @@ ${d?`<div class="sub">${d}</div>`:""}
.weibull-section, .seasonal-card-compact { max-width: 100%; } .weibull-section, .seasonal-card-compact { max-width: 100%; }
.weibull-chart svg { max-width: 100%; height: auto; } .weibull-chart svg { max-width: 100%; height: auto; }
.details-toggle { gap: 12px; flex-wrap: wrap; } .details-toggle { gap: 12px; flex-wrap: wrap; }
`],c([x({attribute:!1})],C.prototype,"hass",2),c([h()],C.prototype,"_open",2),c([h()],C.prototype,"_entryId",2),c([h()],C.prototype,"_taskId",2),c([h()],C.prototype,"_task",2),c([h()],C.prototype,"_objectName",2),c([h()],C.prototype,"_busy",2),c([h()],C.prototype,"_error",2),c([h()],C.prototype,"_showSkip",2),c([h()],C.prototype,"_showReset",2),c([h()],C.prototype,"_showDetails",2),c([h()],C.prototype,"_showAdaptive",2),c([h()],C.prototype,"_skipReason",2),c([h()],C.prototype,"_resetDate",2),c([h()],C.prototype,"_features",2),c([h()],C.prototype,"_toast",2);customElements.get("maintenance-task-quick-actions-dialog")||customElements.define("maintenance-task-quick-actions-dialog",C)});function es(r){return!!r&&/^https?:\/\//i.test(r)}var ts=w(()=>{"use strict"});function is(r){return r?customElements.get("ha-markdown")?l`<ha-markdown class="notes-md" .content=${r} breaks></ha-markdown>`:l`${r}`:_}var ss=w(()=>{"use strict";P()});var G,rs=w(()=>{"use strict";P();ts();ss();W();N();de();G=class extends A{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._data=null;this._busy=!1;this._error=""}get _lang(){return D(this.hass)}async openFor(e){this._entryId=e,this._error="",this._open=!0,await this._load()}close(){this._open=!1,this._data=null,this._error=""}async _load(){if(this._entryId)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._data=e}catch(e){this._error=j(e,this._lang)}}_onEditObject(){!this._entryId||!this._data||Promise.resolve().then(()=>(K(),Z)).then(({openEditObjectDialog:e})=>{e(this._entryId,this._data.object),this.close()})}_onAddTask(){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openCreateTaskDialog:e})=>{e(this._entryId),this.close()})}async _onDelete(){if(!this._entryId||!this._data)return;let e=a("delete_object_confirm",this._lang)||`Delete "${this._data.object.name}" and all its tasks?`;if(window.confirm(e)){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/delete",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-deleted",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=j(t,this._lang)}finally{this._busy=!1}}}async _onArchiveObject(){if(!this._entryId||!this._data)return;let e=!!this._data.object.archived;if(!e){let t=a("confirm_archive_object",this._lang)||"Archive this object and its tasks?";if(!window.confirm(t))return}this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:e?"maintenance_supporter/object/unarchive":"maintenance_supporter/object/archive",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-changed",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=j(t,this._lang)}finally{this._busy=!1}}_onTaskClick(e){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openTaskQuickActions:t})=>{t(this._entryId,e)})}render(){if(!this._open)return _;let e=this._lang,t=this._data,i=t?.object,n=t?.tasks||[],o=this.hass?.user?.is_admin??!0;return l` `],c([x({attribute:!1})],I.prototype,"hass",2),c([h()],I.prototype,"_open",2),c([h()],I.prototype,"_entryId",2),c([h()],I.prototype,"_taskId",2),c([h()],I.prototype,"_task",2),c([h()],I.prototype,"_objectName",2),c([h()],I.prototype,"_busy",2),c([h()],I.prototype,"_error",2),c([h()],I.prototype,"_showSkip",2),c([h()],I.prototype,"_showReset",2),c([h()],I.prototype,"_showDetails",2),c([h()],I.prototype,"_showAdaptive",2),c([h()],I.prototype,"_skipReason",2),c([h()],I.prototype,"_resetDate",2),c([h()],I.prototype,"_features",2),c([h()],I.prototype,"_toast",2);customElements.get("maintenance-task-quick-actions-dialog")||customElements.define("maintenance-task-quick-actions-dialog",I)});function es(r){return!!r&&/^https?:\/\//i.test(r)}var ts=w(()=>{"use strict"});function is(r){return r?customElements.get("ha-markdown")?l`<ha-markdown class="notes-md" .content=${r} breaks></ha-markdown>`:l`${r}`:_}var ss=w(()=>{"use strict";P()});var G,rs=w(()=>{"use strict";P();ts();ss();W();j();de();G=class extends A{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._data=null;this._busy=!1;this._error=""}get _lang(){return D(this.hass)}async openFor(e){this._entryId=e,this._error="",this._open=!0,await this._load()}close(){this._open=!1,this._data=null,this._error=""}async _load(){if(this._entryId)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._data=e}catch(e){this._error=N(e,this._lang)}}_onEditObject(){!this._entryId||!this._data||Promise.resolve().then(()=>(K(),Z)).then(({openEditObjectDialog:e})=>{e(this._entryId,this._data.object),this.close()})}_onAddTask(){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openCreateTaskDialog:e})=>{e(this._entryId),this.close()})}async _onDelete(){if(!this._entryId||!this._data)return;let e=a("delete_object_confirm",this._lang)||`Delete "${this._data.object.name}" and all its tasks?`;if(window.confirm(e)){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/delete",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-deleted",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=N(t,this._lang)}finally{this._busy=!1}}}async _onArchiveObject(){if(!this._entryId||!this._data)return;let e=!!this._data.object.archived;if(!e){let t=a("confirm_archive_object",this._lang)||"Archive this object and its tasks?";if(!window.confirm(t))return}this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:e?"maintenance_supporter/object/unarchive":"maintenance_supporter/object/archive",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-changed",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=N(t,this._lang)}finally{this._busy=!1}}_onTaskClick(e){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openTaskQuickActions:t})=>{t(this._entryId,e)})}render(){if(!this._open)return _;let e=this._lang,t=this._data,i=t?.object,n=t?.tasks||[],o=this.hass?.user?.is_admin??!0;return l`
<div class="backdrop" @click=${this.close}></div> <div class="backdrop" @click=${this.close}></div>
<div class="dialog" role="dialog" aria-modal="true"> <div class="dialog" role="dialog" aria-modal="true">
${t&&i?l` ${t&&i?l`
@@ -3916,7 +3964,7 @@ ${d?`<div class="sub">${d}</div>`:""}
<div class="task-list"> <div class="task-list">
${n.map(p=>l` ${n.map(p=>l`
<div class="task-row" @click=${()=>this._onTaskClick(p.id)}> <div class="task-row" @click=${()=>this._onTaskClick(p.id)}>
<span class="status-dot" style="background: ${Ie[p.status]||"#ccc"}"></span> <span class="status-dot" style="background: ${Ce[p.status]||"#ccc"}"></span>
<span class="task-name">${p.name}</span> <span class="task-name">${p.name}</span>
<span class="task-status">${a(p.status||"ok",e)}</span> <span class="task-status">${a(p.status||"ok",e)}</span>
</div> </div>
@@ -4023,7 +4071,7 @@ ${d?`<div class="sub">${d}</div>`:""}
.btn ha-icon { --mdc-icon-size: 16px; } .btn ha-icon { --mdc-icon-size: 16px; }
.loading { padding: 24px; text-align: center; color: var(--secondary-text-color); } .loading { padding: 24px; text-align: center; color: var(--secondary-text-color); }
.error { padding: 8px; border-radius: 6px; background: rgba(211,47,47,0.1); color: var(--error-color); font-size: 13px; } .error { padding: 8px; border-radius: 6px; background: rgba(211,47,47,0.1); color: var(--error-color); font-size: 13px; }
`,c([x({attribute:!1})],G.prototype,"hass",2),c([h()],G.prototype,"_open",2),c([h()],G.prototype,"_entryId",2),c([h()],G.prototype,"_data",2),c([h()],G.prototype,"_busy",2),c([h()],G.prototype,"_error",2);customElements.get("maintenance-object-quick-actions-dialog")||customElements.define("maintenance-object-quick-actions-dialog",G)});var Z={};ds(Z,{__resetSettingsCacheForTests:()=>hr,getRowActionStyle:()=>ur,openCompleteDialog:()=>vr,openCreateObjectDialog:()=>_r,openCreateTaskDialog:()=>mr,openEditObjectDialog:()=>gr,openEditTaskDialog:()=>fr,openHistoryEditDialog:()=>St,openObjectQuickActions:()=>br,openQrDialog:()=>yr,openTaskQuickActions:()=>At});function Ze(){return document.querySelector("home-assistant")?.hass}function pr(){return document.querySelector("home-assistant")?.shadowRoot??document.body}function X(r){let s=pr(),e=s.querySelector(r)??document.body.querySelector(r);return e?e.parentNode!==s&&s.appendChild(e):(e=document.createElement(r),s.appendChild(e)),e}function ee(r){let s=Ze();if(!s)return!1;r.hass=s;let e=D(s);return Re(e)||Ne(e).then(()=>{r.requestUpdate?.()}),!0}function ur(r){return Et(r).then(s=>s.rowActionStyle)}function hr(){De=null}function Et(r){return De||(De=r.connection.sendMessagePromise({type:"maintenance_supporter/settings"}).then(s=>({features:s.features??kt.features,defaultWarningDays:s.general?.default_warning_days??7,rowActionStyle:s.general?.row_action_style??kt.rowActionStyle})).catch(()=>kt),De)}function _r(){let r=X(as);return ee(r)?(r.openCreate(),!0):!1}function gr(r,s){let e=X(as);return ee(e)?(e.openEdit(r,s),!0):!1}function mr(r="",s){let e=X(ns);if(!ee(e))return!1;let t=Ze();return t?((async()=>{let i=await Et(t),n=e;n.checklistsEnabled=i.features.checklists,n.scheduleTimeEnabled=i.features.schedule_time,n.completionActionsEnabled=i.features.completion_actions,n.defaultWarningDays=i.defaultWarningDays,n.openCreate(r,s)})(),!0):!1}function fr(r,s){let e=X(ns);if(!ee(e))return!1;let t=Ze();return t?((async()=>{try{let[i,n]=await Promise.all([t.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:r}),Et(t)]),o=(i.tasks||[]).find(d=>d.id===s);if(!o){console.warn(`openEditTaskDialog: task ${s} not found in entry ${r}`);return}let p=e;p.checklistsEnabled=n.features.checklists,p.scheduleTimeEnabled=n.features.schedule_time,p.completionActionsEnabled=n.features.completion_actions,p.defaultWarningDays=n.defaultWarningDays,await p.openEdit(r,o)}catch(i){console.warn("openEditTaskDialog: failed to load task/features",i)}})(),!0):!1}function St(r){let s=X(nr);return ee(s)?(s.openEdit(r),!0):!1}function vr(r){let s=X(or);return ee(s)?(Fi(s,r,Ze()?.language||"en"),!0):!1}function yr(r){let s=X(lr);return ee(s)?(s.openForTask(r.entry_id,r.task_id,r.object_name,r.task_name),!0):!1}function At(r,s){let e=X(cr);return ee(e)?(e.openFor(r,s),!0):!1}function br(r){let s=X(dr);return ee(s)?(s.openFor(r),!0):!1}var as,ns,nr,or,lr,cr,dr,kt,De,K=w(()=>{"use strict";Ei();Ri();Ni();ji();Oi();Xi();rs();N();$t();as="maintenance-object-dialog",ns="maintenance-task-dialog",nr="maintenance-history-edit-dialog",or="maintenance-complete-dialog",lr="maintenance-qr-dialog",cr="maintenance-task-quick-actions-dialog",dr="maintenance-object-quick-actions-dialog";kt={features:{adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1},defaultWarningDays:7,rowActionStyle:"buttons_compact"};De=null});P();W();ht();P();var li=S` `,c([x({attribute:!1})],G.prototype,"hass",2),c([h()],G.prototype,"_open",2),c([h()],G.prototype,"_entryId",2),c([h()],G.prototype,"_data",2),c([h()],G.prototype,"_busy",2),c([h()],G.prototype,"_error",2);customElements.get("maintenance-object-quick-actions-dialog")||customElements.define("maintenance-object-quick-actions-dialog",G)});var Z={};ds(Z,{__resetSettingsCacheForTests:()=>hr,getRowActionStyle:()=>ur,openCompleteDialog:()=>vr,openCreateObjectDialog:()=>_r,openCreateTaskDialog:()=>mr,openEditObjectDialog:()=>gr,openEditTaskDialog:()=>fr,openHistoryEditDialog:()=>St,openObjectQuickActions:()=>br,openQrDialog:()=>yr,openTaskQuickActions:()=>At});function Ze(){return document.querySelector("home-assistant")?.hass}function pr(){return document.querySelector("home-assistant")?.shadowRoot??document.body}function X(r){let s=pr(),e=s.querySelector(r)??document.body.querySelector(r);return e?e.parentNode!==s&&s.appendChild(e):(e=document.createElement(r),s.appendChild(e)),e}function ee(r){let s=Ze();if(!s)return!1;r.hass=s;let e=D(s);return Re(e)||je(e).then(()=>{r.requestUpdate?.()}),!0}function ur(r){return Et(r).then(s=>s.rowActionStyle)}function hr(){De=null}function Et(r){return De||(De=r.connection.sendMessagePromise({type:"maintenance_supporter/settings"}).then(s=>({features:s.features??kt.features,defaultWarningDays:s.general?.default_warning_days??7,rowActionStyle:s.general?.row_action_style??kt.rowActionStyle})).catch(()=>kt),De)}function _r(){let r=X(as);return ee(r)?(r.openCreate(),!0):!1}function gr(r,s){let e=X(as);return ee(e)?(e.openEdit(r,s),!0):!1}function mr(r="",s){let e=X(ns);if(!ee(e))return!1;let t=Ze();return t?((async()=>{let i=await Et(t),n=e;n.checklistsEnabled=i.features.checklists,n.scheduleTimeEnabled=i.features.schedule_time,n.completionActionsEnabled=i.features.completion_actions,n.defaultWarningDays=i.defaultWarningDays,n.openCreate(r,s)})(),!0):!1}function fr(r,s){let e=X(ns);if(!ee(e))return!1;let t=Ze();return t?((async()=>{try{let[i,n]=await Promise.all([t.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:r}),Et(t)]),o=(i.tasks||[]).find(d=>d.id===s);if(!o){console.warn(`openEditTaskDialog: task ${s} not found in entry ${r}`);return}let p=e;p.checklistsEnabled=n.features.checklists,p.scheduleTimeEnabled=n.features.schedule_time,p.completionActionsEnabled=n.features.completion_actions,p.defaultWarningDays=n.defaultWarningDays,await p.openEdit(r,o)}catch(i){console.warn("openEditTaskDialog: failed to load task/features",i)}})(),!0):!1}function St(r){let s=X(nr);return ee(s)?(s.openEdit(r),!0):!1}function vr(r){let s=X(or);return ee(s)?(Fi(s,r,Ze()?.language||"en"),!0):!1}function yr(r){let s=X(lr);return ee(s)?(s.openForTask(r.entry_id,r.task_id,r.object_name,r.task_name),!0):!1}function At(r,s){let e=X(cr);return ee(e)?(e.openFor(r,s),!0):!1}function br(r){let s=X(dr);return ee(s)?(s.openFor(r),!0):!1}var as,ns,nr,or,lr,cr,dr,kt,De,K=w(()=>{"use strict";Ei();Ri();ji();Ni();Oi();Xi();rs();j();$t();as="maintenance-object-dialog",ns="maintenance-task-dialog",nr="maintenance-history-edit-dialog",or="maintenance-complete-dialog",lr="maintenance-qr-dialog",cr="maintenance-task-quick-actions-dialog",dr="maintenance-object-quick-actions-dialog";kt={features:{adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1},defaultWarningDays:7,rowActionStyle:"buttons_compact"};De=null});P();W();ht();P();var li=S`
.cal-controls { .cal-controls {
display: flex; display: flex;
gap: 12px; gap: 12px;
@@ -4220,7 +4268,7 @@ ${d?`<div class="sub">${d}</div>`:""}
.cal-pill-day { font-size: 17px; } .cal-pill-day { font-size: 17px; }
.cal-user-filter { margin-left: 0; width: 100%; } .cal-user-filter { margin-left: 0; width: 100%; }
} }
`;N();function ki(r){let s=window;s.customCards=s.customCards||[],s.customCards.some(e=>e.type===r.type)||s.customCards.push(r)}K();var O=class extends A{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-calendar-card"};this._objects=[];this._stats=null;this._windowDays=30;this._pastDays=0;this._userFilter="";this._objectFilter="";this._configuredObjects=[];this._unsub=null;this._dataLoaded=!1;this._lastConnection=null}static getConfigElement(){return document.createElement("maintenance-supporter-calendar-card-editor")}static getStubConfig(){return{type:"custom:maintenance-supporter-calendar-card",window_days:30,show_window_chips:!0,show_user_filter:!0}}setConfig(e){if(this._config={...e},e.past_days&&[30,90].includes(e.past_days)?this._pastDays=e.past_days:e.window_days&&[7,14,30,365].includes(e.window_days)&&(this._windowDays=e.window_days,this._pastDays=0),typeof e.user_filter=="string"&&(this._userFilter=e.user_filter),typeof e.object_filter=="string")this._objectFilter=e.object_filter,this._configuredObjects=[];else if(Array.isArray(e.object_filter)){let t=e.object_filter.filter(i=>typeof i=="string"&&i!=="");this._objectFilter=t.length===1?t[0]:"",this._configuredObjects=t.length>1?t:[]}}getCardSize(){return 6}get _lang(){return D(this.hass)}disconnectedCallback(){if(super.disconnectedCallback(),this._unsub){try{this._unsub()}catch{}this._unsub=null}this._dataLoaded=!1,this._lastConnection=null}updated(e){if(super.updated(e),mi(this,e),e.has("hass")&&this.hass){if(!this._dataLoaded)this._dataLoaded=!0,this._lastConnection=this.hass.connection,this._loadData(),this._subscribe();else if(this.hass.connection!==this._lastConnection){if(this._lastConnection=this.hass.connection,this._unsub){try{this._unsub()}catch{}this._unsub=null}this._subscribe(),this._loadData()}}}async _loadData(){try{let[e,t]=await Promise.all([this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects"}),this.hass.connection.sendMessagePromise({type:"maintenance_supporter/statistics"})]);this._objects=e.objects,this._stats=t}catch{}}async _subscribe(){try{let e=await this.hass.connection.subscribeMessage(t=>{let i=t;this._objects=i.objects},{type:"maintenance_supporter/subscribe"});if(!this.isConnected){e();return}this._unsub=e}catch{}}_onEventClick(e){if(e.history_timestamp){this._openHistoryEntry(e);return}At(e.entry_id,e.task_id)||this.dispatchEvent(new CustomEvent("ll-custom",{detail:{type:"maintenance-supporter:open-task",entry_id:e.entry_id,task_id:e.task_id},bubbles:!0,composed:!0}))}async _openHistoryEntry(e){try{let i=(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:e.entry_id})).tasks?.find(o=>o.id===e.task_id)?.history?.find(o=>o.timestamp===e.history_timestamp);if(!i||St({entry_id:e.entry_id,task_id:e.task_id,original_timestamp:e.history_timestamp,type:i.type||"completed",timestamp:i.timestamp||e.history_timestamp,notes:i.notes??null,cost:i.cost??null,duration:i.duration??null,completed_by:i.completed_by??null,used_parts:i.used_parts??null}))return}catch{}this.dispatchEvent(new CustomEvent("ll-custom",{detail:{type:"maintenance-supporter:edit-history",entry_id:e.entry_id,task_id:e.task_id,original_timestamp:e.history_timestamp},bubbles:!0,composed:!0}))}render(){if(!this.hass)return _;let e=this._lang,t=this._config.show_window_chips!==!1,i=this._config.show_user_filter!==!1,n=this._config.title,o=null;this._userFilter&&(o=this._userFilter==="current_user"?this.hass?.user?.id??null:this._userFilter);let p=b=>{let B=b.toLowerCase();return this._objects.find(I=>I.entry_id===b||I.object.name.toLowerCase()===B)?.entry_id??null},d=new Set(this._configuredObjects.map(p).filter(b=>b!==null)),u=d.size?this._objects.filter(b=>d.has(b.entry_id)):this._objects,m=this._config.show_object_filter!==!1&&u.length>1,f=this._objectFilter?p(this._objectFilter):null,v=f&&u.some(b=>b.entry_id===f)?u.filter(b=>b.entry_id===f):u,y=new Date;y.setHours(0,0,0,0);let k=this._pastDays>0,E=k?oi(v,y,this._pastDays,o):ni(v,y,this._windowDays,o),H=le(y),M=this._windowDays===365||k,q=M?E.filter(b=>b.events.length>0):E,F=b=>{let B=`cal-status-${b.status}`,pe=b.projected?"cal-event-projected":"",I=b.status==="overdue"&&b.days_until_due!=null?` (${bi(b.days_until_due,e)})`:"",R=b.projected&&b.interval_days?l`<span class="cal-event-recur">${b.interval_unit&&b.interval_unit!=="days"?`${b.interval_days} ${a("unit_"+b.interval_unit,e)}`:a("cal_every_n_days",e).replace("{n}",String(b.interval_days))}</span>`:_,se=b.schedule_type==="sensor_based",ye=se?l`<ha-icon class="cal-event-icon cal-source-sensor" `;j();function ki(r){let s=window;s.customCards=s.customCards||[],s.customCards.some(e=>e.type===r.type)||s.customCards.push(r)}K();var O=class extends A{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-calendar-card"};this._objects=[];this._stats=null;this._windowDays=30;this._pastDays=0;this._userFilter="";this._objectFilter="";this._configuredObjects=[];this._unsub=null;this._dataLoaded=!1;this._lastConnection=null}static getConfigElement(){return document.createElement("maintenance-supporter-calendar-card-editor")}static getStubConfig(){return{type:"custom:maintenance-supporter-calendar-card",window_days:30,show_window_chips:!0,show_user_filter:!0}}setConfig(e){if(this._config={...e},e.past_days&&[30,90].includes(e.past_days)?this._pastDays=e.past_days:e.window_days&&[7,14,30,365].includes(e.window_days)&&(this._windowDays=e.window_days,this._pastDays=0),typeof e.user_filter=="string"&&(this._userFilter=e.user_filter),typeof e.object_filter=="string")this._objectFilter=e.object_filter,this._configuredObjects=[];else if(Array.isArray(e.object_filter)){let t=e.object_filter.filter(i=>typeof i=="string"&&i!=="");this._objectFilter=t.length===1?t[0]:"",this._configuredObjects=t.length>1?t:[]}}getCardSize(){return 6}get _lang(){return D(this.hass)}disconnectedCallback(){if(super.disconnectedCallback(),this._unsub){try{this._unsub()}catch{}this._unsub=null}this._dataLoaded=!1,this._lastConnection=null}updated(e){if(super.updated(e),mi(this,e),e.has("hass")&&this.hass){if(!this._dataLoaded)this._dataLoaded=!0,this._lastConnection=this.hass.connection,this._loadData(),this._subscribe();else if(this.hass.connection!==this._lastConnection){if(this._lastConnection=this.hass.connection,this._unsub){try{this._unsub()}catch{}this._unsub=null}this._subscribe(),this._loadData()}}}async _loadData(){try{let[e,t]=await Promise.all([this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects"}),this.hass.connection.sendMessagePromise({type:"maintenance_supporter/statistics"})]);this._objects=e.objects,this._stats=t}catch{}}async _subscribe(){try{let e=await this.hass.connection.subscribeMessage(t=>{let i=t;this._objects=i.objects},{type:"maintenance_supporter/subscribe"});if(!this.isConnected){e();return}this._unsub=e}catch{}}_onEventClick(e){if(e.history_timestamp){this._openHistoryEntry(e);return}At(e.entry_id,e.task_id)||this.dispatchEvent(new CustomEvent("ll-custom",{detail:{type:"maintenance-supporter:open-task",entry_id:e.entry_id,task_id:e.task_id},bubbles:!0,composed:!0}))}async _openHistoryEntry(e){try{let i=(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:e.entry_id})).tasks?.find(o=>o.id===e.task_id)?.history?.find(o=>o.timestamp===e.history_timestamp);if(!i||St({entry_id:e.entry_id,task_id:e.task_id,original_timestamp:e.history_timestamp,type:i.type||"completed",timestamp:i.timestamp||e.history_timestamp,notes:i.notes??null,cost:i.cost??null,duration:i.duration??null,completed_by:i.completed_by??null,used_parts:i.used_parts??null}))return}catch{}this.dispatchEvent(new CustomEvent("ll-custom",{detail:{type:"maintenance-supporter:edit-history",entry_id:e.entry_id,task_id:e.task_id,original_timestamp:e.history_timestamp},bubbles:!0,composed:!0}))}render(){if(!this.hass)return _;let e=this._lang,t=this._config.show_window_chips!==!1,i=this._config.show_user_filter!==!1,n=this._config.title,o=null;this._userFilter&&(o=this._userFilter==="current_user"?this.hass?.user?.id??null:this._userFilter);let p=b=>{let B=b.toLowerCase();return this._objects.find(C=>C.entry_id===b||C.object.name.toLowerCase()===B)?.entry_id??null},d=new Set(this._configuredObjects.map(p).filter(b=>b!==null)),u=d.size?this._objects.filter(b=>d.has(b.entry_id)):this._objects,m=this._config.show_object_filter!==!1&&u.length>1,f=this._objectFilter?p(this._objectFilter):null,v=f&&u.some(b=>b.entry_id===f)?u.filter(b=>b.entry_id===f):u,y=new Date;y.setHours(0,0,0,0);let k=this._pastDays>0,E=k?oi(v,y,this._pastDays,o):ni(v,y,this._windowDays,o),H=le(y),M=this._windowDays===365||k,q=M?E.filter(b=>b.events.length>0):E,F=b=>{let B=`cal-status-${b.status}`,pe=b.projected?"cal-event-projected":"",C=b.status==="overdue"&&b.days_until_due!=null?` (${bi(b.days_until_due,e)})`:"",R=b.projected&&b.interval_days?l`<span class="cal-event-recur">${b.interval_unit&&b.interval_unit!=="days"?`${b.interval_days} ${a("unit_"+b.interval_unit,e)}`:a("cal_every_n_days",e).replace("{n}",String(b.interval_days))}</span>`:_,se=b.schedule_type==="sensor_based",ye=se?l`<ha-icon class="cal-event-icon cal-source-sensor"
title="${a("cal_source_sensor",e)}" icon="mdi:trending-up"></ha-icon>`:l`<ha-icon class="cal-event-icon cal-source-time" title="${a("cal_source_sensor",e)}" icon="mdi:trending-up"></ha-icon>`:l`<ha-icon class="cal-event-icon cal-source-time"
title="${b.adaptive_enabled?a("cal_source_time_adaptive",e):a("cal_source_time",e)}" title="${b.adaptive_enabled?a("cal_source_time_adaptive",e):a("cal_source_time",e)}"
icon="${b.adaptive_enabled?"mdi:clock-time-four-outline":"mdi:clock-outline"}"></ha-icon>`,be=se&&b.prediction_confidence&&b.status!=="triggered"&&!b.projected?l`<span class="cal-event-prediction cal-conf-${b.prediction_confidence}"> icon="${b.adaptive_enabled?"mdi:clock-time-four-outline":"mdi:clock-outline"}"></ha-icon>`,be=se&&b.prediction_confidence&&b.status!=="triggered"&&!b.projected?l`<span class="cal-event-prediction cal-conf-${b.prediction_confidence}">
@@ -4231,13 +4279,13 @@ ${d?`<div class="sub">${d}</div>`:""}
${ye} ${ye}
<span class="cal-status-pill ${B}">${ls}</span> <span class="cal-status-pill ${B}">${ls}</span>
<div class="cal-event-body"> <div class="cal-event-body">
<div class="cal-event-title">${b.object_name} · ${b.task_name}${I}</div> <div class="cal-event-title">${b.object_name} · ${b.task_name}${C}</div>
${be} ${be}
${R} ${R}
</div> </div>
${b.avg_cost!=null&&b.avg_cost>0?l`<span class="cal-event-cost">${b.avg_cost.toFixed(0)} ${os}</span>`:_} ${b.avg_cost!=null&&b.avg_cost>0?l`<span class="cal-event-cost">${b.avg_cost.toFixed(0)} ${os}</span>`:_}
</div> </div>
`},te=b=>{let[B,pe,I]=b.date.split("-").map(Number),R=new Date(B,pe-1,I),se=b.date===H,ye=R.toLocaleDateString(e,{weekday:"short"}),be=R.toLocaleDateString(e,{month:"long"});return l` `},te=b=>{let[B,pe,C]=b.date.split("-").map(Number),R=new Date(B,pe-1,C),se=b.date===H,ye=R.toLocaleDateString(e,{weekday:"short"}),be=R.toLocaleDateString(e,{month:"long"});return l`
<div class="cal-day-row"> <div class="cal-day-row">
<div class="cal-day-pill ${se?"cal-today":""}"> <div class="cal-day-pill ${se?"cal-today":""}">
<span class="cal-pill-weekday">${ye}</span> <span class="cal-pill-weekday">${ye}</span>
@@ -4299,7 +4347,7 @@ ${d?`<div class="sub">${d}</div>`:""}
`}};O.styles=[Ye,li,S` `}};O.styles=[Ye,li,S`
:host { display: block; } :host { display: block; }
ha-card { padding: 0; overflow: hidden; } ha-card { padding: 0; overflow: hidden; }
`],c([x({attribute:!1})],O.prototype,"hass",2),c([h()],O.prototype,"_config",2),c([h()],O.prototype,"_objects",2),c([h()],O.prototype,"_stats",2),c([h()],O.prototype,"_windowDays",2),c([h()],O.prototype,"_pastDays",2),c([h()],O.prototype,"_userFilter",2),c([h()],O.prototype,"_objectFilter",2),c([h()],O.prototype,"_unsub",2);var xr=[{value:7,key:"cal_editor_window_week"},{value:14,key:"cal_editor_window_fortnight"},{value:30,key:"cal_editor_window_month"},{value:365,key:"cal_editor_window_year"}],ve=class extends A{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-calendar-card"}}get _lang(){return D(this.hass)}setConfig(e){this._config={...e}}updated(){let e=this._lang;e&&!Re(e)&&Ne(e).then(()=>this.requestUpdate())}_valueChanged(e,t){let i={...this._config,[e]:t};e==="show_window_chips"&&t===!0&&delete i.show_window_chips,e==="show_user_filter"&&t===!0&&delete i.show_user_filter,e==="show_object_filter"&&t===!0&&delete i.show_object_filter,e==="title"&&(!t||typeof t=="string"&&t.trim()==="")&&delete i.title,e==="user_filter"&&t===""&&delete i.user_filter,this._config=i,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:i},bubbles:!0,composed:!0}))}render(){let e=this._lang,t=this._config.window_days??30,i=this._config.show_window_chips!==!1,n=this._config.show_user_filter!==!1,o=this._config.user_filter??"",p=this._config.title??"";return l` `],c([x({attribute:!1})],O.prototype,"hass",2),c([h()],O.prototype,"_config",2),c([h()],O.prototype,"_objects",2),c([h()],O.prototype,"_stats",2),c([h()],O.prototype,"_windowDays",2),c([h()],O.prototype,"_pastDays",2),c([h()],O.prototype,"_userFilter",2),c([h()],O.prototype,"_objectFilter",2),c([h()],O.prototype,"_unsub",2);var xr=[{value:7,key:"cal_editor_window_week"},{value:14,key:"cal_editor_window_fortnight"},{value:30,key:"cal_editor_window_month"},{value:365,key:"cal_editor_window_year"}],ve=class extends A{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-calendar-card"}}get _lang(){return D(this.hass)}setConfig(e){this._config={...e}}updated(){let e=this._lang;e&&!Re(e)&&je(e).then(()=>this.requestUpdate())}_valueChanged(e,t){let i={...this._config,[e]:t};e==="show_window_chips"&&t===!0&&delete i.show_window_chips,e==="show_user_filter"&&t===!0&&delete i.show_user_filter,e==="show_object_filter"&&t===!0&&delete i.show_object_filter,e==="title"&&(!t||typeof t=="string"&&t.trim()==="")&&delete i.title,e==="user_filter"&&t===""&&delete i.user_filter,this._config=i,this.dispatchEvent(new CustomEvent("config-changed",{detail:{config:i},bubbles:!0,composed:!0}))}render(){let e=this._lang,t=this._config.window_days??30,i=this._config.show_window_chips!==!1,n=this._config.show_user_filter!==!1,o=this._config.user_filter??"",p=this._config.title??"";return l`
<div class="editor"> <div class="editor">
<div class="row"> <div class="row">
<label for="title">${a("card_title",e)}</label> <label for="title">${a("card_title",e)}</label>
@@ -1,9 +1,9 @@
/*! maintenance_supporter frontend 2.70.0 */ /*! maintenance_supporter frontend 2.71.0 */
var Ht=Object.defineProperty;var ps=Object.getOwnPropertyDescriptor;var w=(a,s,e)=>()=>{if(e)throw e[0];try{return a&&(s=a(a=0)),s}catch(t){throw e=[t],t}};var hs=(a,s)=>{for(var e in s)Ht(a,e,{get:s[e],enumerable:!0})};var c=(a,s,e,t)=>{for(var i=t>1?void 0:t?ps(s,e):s,n=a.length-1,l;n>=0;n--)(l=a[n])&&(i=(t?l(s,e,i):l(i))||i);return t&&i&&Ht(s,e,i),i};var He,Oe,Xe,Ot,be,Dt,A,Mt,et,tt=w(()=>{He=globalThis,Oe=He.ShadowRoot&&(He.ShadyCSS===void 0||He.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Xe=Symbol(),Ot=new WeakMap,be=class{constructor(s,e,t){if(this._$cssResult$=!0,t!==Xe)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=s,this.t=e}get styleSheet(){let s=this.o,e=this.t;if(Oe&&s===void 0){let t=e!==void 0&&e.length===1;t&&(s=Ot.get(e)),s===void 0&&((this.o=s=new CSSStyleSheet).replaceSync(this.cssText),t&&Ot.set(e,s))}return s}toString(){return this.cssText}},Dt=a=>new be(typeof a=="string"?a:a+"",void 0,Xe),A=(a,...s)=>{let e=a.length===1?a[0]:s.reduce((t,i,n)=>t+(l=>{if(l._$cssResult$===!0)return l.cssText;if(typeof l=="number")return l;throw Error("Value passed to 'css' function must be a 'css' function result: "+l+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+a[n+1],a[0]);return new be(e,a,Xe)},Mt=(a,s)=>{if(Oe)a.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of s){let t=document.createElement("style"),i=He.litNonce;i!==void 0&&t.setAttribute("nonce",i),t.textContent=e.cssText,a.appendChild(t)}},et=Oe?a=>a:a=>a instanceof CSSStyleSheet?(s=>{let e="";for(let t of s.cssRules)e+=t.cssText;return Dt(e)})(a):a});var us,_s,gs,ms,fs,vs,De,zt,bs,ys,ye,xe,Me,Ft,Y,we=w(()=>{tt();tt();({is:us,defineProperty:_s,getOwnPropertyDescriptor:gs,getOwnPropertyNames:ms,getOwnPropertySymbols:fs,getPrototypeOf:vs}=Object),De=globalThis,zt=De.trustedTypes,bs=zt?zt.emptyScript:"",ys=De.reactiveElementPolyfillSupport,ye=(a,s)=>a,xe={toAttribute(a,s){switch(s){case Boolean:a=a?bs:null;break;case Object:case Array:a=a==null?a:JSON.stringify(a)}return a},fromAttribute(a,s){let e=a;switch(s){case Boolean:e=a!==null;break;case Number:e=a===null?null:Number(a);break;case Object:case Array:try{e=JSON.parse(a)}catch{e=null}}return e}},Me=(a,s)=>!us(a,s),Ft={attribute:!0,type:String,converter:xe,reflect:!1,useDefault:!1,hasChanged:Me};Symbol.metadata??=Symbol("metadata"),De.litPropertyMetadata??=new WeakMap;Y=class extends HTMLElement{static addInitializer(s){this._$Ei(),(this.l??=[]).push(s)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(s,e=Ft){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(s)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(s,e),!e.noAccessor){let t=Symbol(),i=this.getPropertyDescriptor(s,t,e);i!==void 0&&_s(this.prototype,s,i)}}static getPropertyDescriptor(s,e,t){let{get:i,set:n}=gs(this.prototype,s)??{get(){return this[e]},set(l){this[e]=l}};return{get:i,set(l){let d=i?.call(this);n?.call(this,l),this.requestUpdate(s,d,t)},configurable:!0,enumerable:!0}}static getPropertyOptions(s){return this.elementProperties.get(s)??Ft}static _$Ei(){if(this.hasOwnProperty(ye("elementProperties")))return;let s=vs(this);s.finalize(),s.l!==void 0&&(this.l=[...s.l]),this.elementProperties=new Map(s.elementProperties)}static finalize(){if(this.hasOwnProperty(ye("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(ye("properties"))){let e=this.properties,t=[...ms(e),...fs(e)];for(let i of t)this.createProperty(i,e[i])}let s=this[Symbol.metadata];if(s!==null){let e=litPropertyMetadata.get(s);if(e!==void 0)for(let[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(let[e,t]of this.elementProperties){let i=this._$Eu(e,t);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(s){let e=[];if(Array.isArray(s)){let t=new Set(s.flat(1/0).reverse());for(let i of t)e.unshift(et(i))}else s!==void 0&&e.push(et(s));return e}static _$Eu(s,e){let t=e.attribute;return t===!1?void 0:typeof t=="string"?t:typeof s=="string"?s.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(s=>this.enableUpdating=s),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(s=>s(this))}addController(s){(this._$EO??=new Set).add(s),this.renderRoot!==void 0&&this.isConnected&&s.hostConnected?.()}removeController(s){this._$EO?.delete(s)}_$E_(){let s=new Map,e=this.constructor.elementProperties;for(let t of e.keys())this.hasOwnProperty(t)&&(s.set(t,this[t]),delete this[t]);s.size>0&&(this._$Ep=s)}createRenderRoot(){let s=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Mt(s,this.constructor.elementStyles),s}connectedCallback(){this.renderRoot??=thiLine truncated var Ht=Object.defineProperty;var ps=Object.getOwnPropertyDescriptor;var w=(a,s,e)=>()=>{if(e)throw e[0];try{return a&&(s=a(a=0)),s}catch(t){throw e=[t],t}};var hs=(a,s)=>{for(var e in s)Ht(a,e,{get:s[e],enumerable:!0})};var c=(a,s,e,t)=>{for(var i=t>1?void 0:t?ps(s,e):s,n=a.length-1,l;n>=0;n--)(l=a[n])&&(i=(t?l(s,e,i):l(i))||i);return t&&i&&Ht(s,e,i),i};var He,Oe,Xe,Ot,be,Dt,T,Mt,et,tt=w(()=>{He=globalThis,Oe=He.ShadowRoot&&(He.ShadyCSS===void 0||He.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,Xe=Symbol(),Ot=new WeakMap,be=class{constructor(s,e,t){if(this._$cssResult$=!0,t!==Xe)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=s,this.t=e}get styleSheet(){let s=this.o,e=this.t;if(Oe&&s===void 0){let t=e!==void 0&&e.length===1;t&&(s=Ot.get(e)),s===void 0&&((this.o=s=new CSSStyleSheet).replaceSync(this.cssText),t&&Ot.set(e,s))}return s}toString(){return this.cssText}},Dt=a=>new be(typeof a=="string"?a:a+"",void 0,Xe),T=(a,...s)=>{let e=a.length===1?a[0]:s.reduce((t,i,n)=>t+(l=>{if(l._$cssResult$===!0)return l.cssText;if(typeof l=="number")return l;throw Error("Value passed to 'css' function must be a 'css' function result: "+l+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+a[n+1],a[0]);return new be(e,a,Xe)},Mt=(a,s)=>{if(Oe)a.adoptedStyleSheets=s.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of s){let t=document.createElement("style"),i=He.litNonce;i!==void 0&&t.setAttribute("nonce",i),t.textContent=e.cssText,a.appendChild(t)}},et=Oe?a=>a:a=>a instanceof CSSStyleSheet?(s=>{let e="";for(let t of s.cssRules)e+=t.cssText;return Dt(e)})(a):a});var us,_s,gs,ms,fs,vs,De,zt,bs,ys,ye,xe,Me,Ft,Y,we=w(()=>{tt();tt();({is:us,defineProperty:_s,getOwnPropertyDescriptor:gs,getOwnPropertyNames:ms,getOwnPropertySymbols:fs,getPrototypeOf:vs}=Object),De=globalThis,zt=De.trustedTypes,bs=zt?zt.emptyScript:"",ys=De.reactiveElementPolyfillSupport,ye=(a,s)=>a,xe={toAttribute(a,s){switch(s){case Boolean:a=a?bs:null;break;case Object:case Array:a=a==null?a:JSON.stringify(a)}return a},fromAttribute(a,s){let e=a;switch(s){case Boolean:e=a!==null;break;case Number:e=a===null?null:Number(a);break;case Object:case Array:try{e=JSON.parse(a)}catch{e=null}}return e}},Me=(a,s)=>!us(a,s),Ft={attribute:!0,type:String,converter:xe,reflect:!1,useDefault:!1,hasChanged:Me};Symbol.metadata??=Symbol("metadata"),De.litPropertyMetadata??=new WeakMap;Y=class extends HTMLElement{static addInitializer(s){this._$Ei(),(this.l??=[]).push(s)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(s,e=Ft){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(s)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(s,e),!e.noAccessor){let t=Symbol(),i=this.getPropertyDescriptor(s,t,e);i!==void 0&&_s(this.prototype,s,i)}}static getPropertyDescriptor(s,e,t){let{get:i,set:n}=gs(this.prototype,s)??{get(){return this[e]},set(l){this[e]=l}};return{get:i,set(l){let d=i?.call(this);n?.call(this,l),this.requestUpdate(s,d,t)},configurable:!0,enumerable:!0}}static getPropertyOptions(s){return this.elementProperties.get(s)??Ft}static _$Ei(){if(this.hasOwnProperty(ye("elementProperties")))return;let s=vs(this);s.finalize(),s.l!==void 0&&(this.l=[...s.l]),this.elementProperties=new Map(s.elementProperties)}static finalize(){if(this.hasOwnProperty(ye("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(ye("properties"))){let e=this.properties,t=[...ms(e),...fs(e)];for(let i of t)this.createProperty(i,e[i])}let s=this[Symbol.metadata];if(s!==null){let e=litPropertyMetadata.get(s);if(e!==void 0)for(let[t,i]of e)this.elementProperties.set(t,i)}this._$Eh=new Map;for(let[e,t]of this.elementProperties){let i=this._$Eu(e,t);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(s){let e=[];if(Array.isArray(s)){let t=new Set(s.flat(1/0).reverse());for(let i of t)e.unshift(et(i))}else s!==void 0&&e.push(et(s));return e}static _$Eu(s,e){let t=e.attribute;return t===!1?void 0:typeof t=="string"?t:typeof s=="string"?s.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(s=>this.enableUpdating=s),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(s=>s(this))}addController(s){(this._$EO??=new Set).add(s),this.renderRoot!==void 0&&this.isConnected&&s.hostConnected?.()}removeController(s){this._$EO?.delete(s)}_$E_(){let s=new Map,e=this.constructor.elementProperties;for(let t of e.keys())this.hasOwnProperty(t)&&(s.set(t,this[t]),delete this[t]);s.size>0&&(this._$Ep=s)}createRenderRoot(){let s=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return Mt(s,this.constructor.elementStyles),s}connectedCallback(){this.renderRoot??=thiLine truncated
\f\r]`,$e=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Vt=/-->/g,Wt=/>/g,re=RegExp(`>|${it}(?:([^\\s"'>=/]+)(${it}*=${it}*(?:[^ \f\r]`,$e=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,Vt=/-->/g,Wt=/>/g,re=RegExp(`>|${it}(?:([^\\s"'>=/]+)(${it}*=${it}*(?:[^
\f\r"'\`<>=]|("|')|))|$)`,"g"),Kt=/'/g,Gt=/"/g,Zt=/^(?:script|style|textarea|title)$/i,dt=a=>(s,...e)=>({_$litType$:a,strings:s,values:e}),o=dt(1),ue=dt(2),Cr=dt(3),oe=Symbol.for("lit-noChange"),h=Symbol.for("lit-nothing"),Yt=new WeakMap,ae=ne.createTreeWalker(ne,129);$s=(a,s)=>{let e=a.length-1,t=[],i,n=s===2?"<svg>":s===3?"<math>":"",l=$e;for(let d=0;d<e;d++){let p=a[d],_,f,b=-1,v=0;for(;v<p.length&&(l.lastIndex=v,f=l.exec(p),f!==null);)v=l.lastIndex,l===$e?f[1]==="!--"?l=Vt:f[1]!==void 0?l=Wt:f[2]!==void 0?(Zt.test(f[2])&&(i=RegExp("</"+f[2],"g")),l=re):f[3]!==void 0&&(l=re):l===re?f[0]===">"?(l=i??$e,b=-1):f[1]===void 0?b=-2:(b=l.lastIndex-f[2].length,_=f[1],l=f[3]===void 0?re:f[3]==='"'?Gt:Kt):l===Gt||l===Kt?l=re:l===Vt||l===Wt?l=$e:(l=re,i=void 0);let y=l===re&&a[d+1].startsWith("/>")?" ":"";n+=l===$e?p+xs:b>=0?(t.push(_),p.slice(0,b)+Qt+p.slice(b)+te+y):p+te+(b===-2?d:y)}return[Xt(a,n+(a[e]||"<?>")+(s===2?"</svg>":s===3?"</math>":"")),t]},Se=class a{constructor({strings:s,_$litType$:e},t){let i;this.parts=[];let n=0,l=0,d=s.length-1,p=this.parts,[_,f]=$s(s,e);if(this.el=a.createElement(_,t),ae.currentNode=this.el.content,e===2||e===3){let b=this.el.content.firstChild;b.replaceWith(...b.childNodes)}for(;(i=ae.nextNode())!==null&&p.length<d;){if(i.nodeType===1){if(i.hasAttributes())for(let b of i.getAttributeNames())if(b.endsWith(Qt)){let v=f[l++],y=i.getAttribute(b).split(te),m=/([.?@])?(.*)/.exec(v);p.push({type:1,index:n,name:m[2],strings:y,ctor:m[1]==="."?rt:m[1]==="?"?at:m[1]==="@"?nt:he}),i.removeAttribute(b)}else b.startsWith(te)&&(p.push({type:6,index:n}),i.removeAttribute(b));if(Zt.test(i.tagName)){let b=i.textContent.split(te),v=b.length-1;if(v>0){i.textContent=ze?ze.emptyScript:"";for(let y=0;y<v;y++)i.append(b[y],ke()),ae.nextNode(),p.push({type:2,index:++n});i.append(b[v],ke())}}}else if(i.nodeType===8)if(i.data===Jt)p.push({type:2,index:n});else{let b=-1;for(;(b=i.data.indexOf(te,b+1))!==-1;)p.push({type:7,index:n}),b+=te.length-1}n++}}static createElement(s,e){let t=ne.createElement("template");return t.innerHTML=s,t}};st=class{constructor(s,e){this._$AV=[],this._$AN=void 0,this._$AD=s,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(s){let{el:{content:e},parts:t}=this._$AD,i=(s?.creationScope??ne).importNode(e,!0);ae.currentNode=i;let n=ae.nextNode(),l=0,d=0,p=t[0];for(;p!==void 0;){if(l===p.index){let _;p.type===2?_=new Ae(n,n.nextSibling,this,s):p.type===1?_=new p.ctor(n,p.name,p.strings,this,s):p.type===6&&(_=new ot(n,this,s)),this._$AV.push(_),p=t[++d]}l!==p?.index&&(n=ae.nextNode(),l++)}return ae.currentNode=ne,i}p(s){let e=0;for(let t of this._$AV)t!==void 0&&(t.strings!==void 0?(t._$AI(s,t,e),e+=t.strings.length-2):t._$AI(s[e])),e++}},Ae=class a{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(s,e,t,i){this.type=2,this._$AH=h,this._$AN=void 0,this._$AA=s,this._$AB=e,this._$AM=t,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let s=this._$AA.parentNode,e=this._$AM;return e!==void 0&&s?.nodeType===11&&(s=e.parentNode),s}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(s,e=this){s=pe(this,s,e),Ee(s)?s===h||s==null||s===""?(this._$AH!==h&&this._$AR(),this._$AH=h):s!==this._$AH&&s!==oe&&this._(s):s._$litType$!==void 0?this.$(s):s.nodeType!==void 0?this.T(s):ws(s)?this.k(s):this._(s)}O(s){return this._$AA.parentNode.insertBefore(s,this._$AB)}T(s){this._$AH!==s&&(this._$AR(),this._$AH=this.O(s))}_(s){this._$AH!==h&&Ee(this._$AH)?this._$AA.nextSibling.data=s:this.T(ne.createTextNode(s)),this._$AH=s}$(s){let{values:e,_$litType$:t}=s,i=typeof t=="number"?this._$AC(s):(t.el===void 0&&(t.el=Se.createElement(Xt(t.h,t.h[0]),this.options)),t);if(this._$AH?._$AD===i)this._$AH.p(e);else{let n=new st(i,this),l=n.u(this.options);n.p(e),this.T(l),this._$AH=n}}_$AC(s){let e=Yt.get(s.strings);return e===void 0&&Yt.set(s.strings,e=new Se(s)),e}k(s){ct(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,t,i=0;for(let n of s)i===e.length?e.push(t=new a(this.O(ke()),this.O(ke()),this,this.options)):t=e[i],t._$AI(n),i++;i<e.length&&(this._$AR(t&&t._$AB.nextSibling,i),e.length=i)}_$AR(s=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);s!==this._$AB;){let t=Ut(s).nextSibling;Ut(s).remove(),s=t}}setConnected(s){this._$AM===void 0&&(this._$Cv=s,this._$AP?.(s))}},he=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(s,e,t,i,n){this.type=1,this._$AH=h,this._$AN=void 0,this.element=s,this.name=e,this._$AM=i,this.options=n,t.length>2||t[0]!==""||t[1]!==""?(this._$AH=Array(t.length-1).fill(new String),this.strings=t):this._$AH=h}_$AI(s,e=this,t,i){let n=this.strings,l=!1;if(n===void 0)s=pe(this,s,e,0),l=!Ee(s)||s!==this._$AH&&s!==oe,l&&(this._$AH=s);else{let d=s,p,_;for(s=n[0],p=0;p<n.length-1;p++)_=pe(this,d[t+p],e,p),_===oe&&(_=this._$AH[p]),l||=!Ee(_)||_!==this._$AH[p],_===h?s=h:s!==h&&(s+=(_??"")+n[p+1]),this._$AH[p]=_}l&&!i&&this.j(s)}j(s){s===h?this.element.removeAttribute(this.naLine truncated \f\r"'\`<>=]|("|')|))|$)`,"g"),Kt=/'/g,Gt=/"/g,Zt=/^(?:script|style|textarea|title)$/i,dt=a=>(s,...e)=>({_$litType$:a,strings:s,values:e}),o=dt(1),ue=dt(2),Cr=dt(3),oe=Symbol.for("lit-noChange"),h=Symbol.for("lit-nothing"),Yt=new WeakMap,ae=ne.createTreeWalker(ne,129);$s=(a,s)=>{let e=a.length-1,t=[],i,n=s===2?"<svg>":s===3?"<math>":"",l=$e;for(let d=0;d<e;d++){let p=a[d],_,f,b=-1,v=0;for(;v<p.length&&(l.lastIndex=v,f=l.exec(p),f!==null);)v=l.lastIndex,l===$e?f[1]==="!--"?l=Vt:f[1]!==void 0?l=Wt:f[2]!==void 0?(Zt.test(f[2])&&(i=RegExp("</"+f[2],"g")),l=re):f[3]!==void 0&&(l=re):l===re?f[0]===">"?(l=i??$e,b=-1):f[1]===void 0?b=-2:(b=l.lastIndex-f[2].length,_=f[1],l=f[3]===void 0?re:f[3]==='"'?Gt:Kt):l===Gt||l===Kt?l=re:l===Vt||l===Wt?l=$e:(l=re,i=void 0);let y=l===re&&a[d+1].startsWith("/>")?" ":"";n+=l===$e?p+xs:b>=0?(t.push(_),p.slice(0,b)+Qt+p.slice(b)+te+y):p+te+(b===-2?d:y)}return[Xt(a,n+(a[e]||"<?>")+(s===2?"</svg>":s===3?"</math>":"")),t]},Se=class a{constructor({strings:s,_$litType$:e},t){let i;this.parts=[];let n=0,l=0,d=s.length-1,p=this.parts,[_,f]=$s(s,e);if(this.el=a.createElement(_,t),ae.currentNode=this.el.content,e===2||e===3){let b=this.el.content.firstChild;b.replaceWith(...b.childNodes)}for(;(i=ae.nextNode())!==null&&p.length<d;){if(i.nodeType===1){if(i.hasAttributes())for(let b of i.getAttributeNames())if(b.endsWith(Qt)){let v=f[l++],y=i.getAttribute(b).split(te),m=/([.?@])?(.*)/.exec(v);p.push({type:1,index:n,name:m[2],strings:y,ctor:m[1]==="."?rt:m[1]==="?"?at:m[1]==="@"?nt:he}),i.removeAttribute(b)}else b.startsWith(te)&&(p.push({type:6,index:n}),i.removeAttribute(b));if(Zt.test(i.tagName)){let b=i.textContent.split(te),v=b.length-1;if(v>0){i.textContent=ze?ze.emptyScript:"";for(let y=0;y<v;y++)i.append(b[y],ke()),ae.nextNode(),p.push({type:2,index:++n});i.append(b[v],ke())}}}else if(i.nodeType===8)if(i.data===Jt)p.push({type:2,index:n});else{let b=-1;for(;(b=i.data.indexOf(te,b+1))!==-1;)p.push({type:7,index:n}),b+=te.length-1}n++}}static createElement(s,e){let t=ne.createElement("template");return t.innerHTML=s,t}};st=class{constructor(s,e){this._$AV=[],this._$AN=void 0,this._$AD=s,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(s){let{el:{content:e},parts:t}=this._$AD,i=(s?.creationScope??ne).importNode(e,!0);ae.currentNode=i;let n=ae.nextNode(),l=0,d=0,p=t[0];for(;p!==void 0;){if(l===p.index){let _;p.type===2?_=new Te(n,n.nextSibling,this,s):p.type===1?_=new p.ctor(n,p.name,p.strings,this,s):p.type===6&&(_=new ot(n,this,s)),this._$AV.push(_),p=t[++d]}l!==p?.index&&(n=ae.nextNode(),l++)}return ae.currentNode=ne,i}p(s){let e=0;for(let t of this._$AV)t!==void 0&&(t.strings!==void 0?(t._$AI(s,t,e),e+=t.strings.length-2):t._$AI(s[e])),e++}},Te=class a{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(s,e,t,i){this.type=2,this._$AH=h,this._$AN=void 0,this._$AA=s,this._$AB=e,this._$AM=t,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let s=this._$AA.parentNode,e=this._$AM;return e!==void 0&&s?.nodeType===11&&(s=e.parentNode),s}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(s,e=this){s=pe(this,s,e),Ee(s)?s===h||s==null||s===""?(this._$AH!==h&&this._$AR(),this._$AH=h):s!==this._$AH&&s!==oe&&this._(s):s._$litType$!==void 0?this.$(s):s.nodeType!==void 0?this.T(s):ws(s)?this.k(s):this._(s)}O(s){return this._$AA.parentNode.insertBefore(s,this._$AB)}T(s){this._$AH!==s&&(this._$AR(),this._$AH=this.O(s))}_(s){this._$AH!==h&&Ee(this._$AH)?this._$AA.nextSibling.data=s:this.T(ne.createTextNode(s)),this._$AH=s}$(s){let{values:e,_$litType$:t}=s,i=typeof t=="number"?this._$AC(s):(t.el===void 0&&(t.el=Se.createElement(Xt(t.h,t.h[0]),this.options)),t);if(this._$AH?._$AD===i)this._$AH.p(e);else{let n=new st(i,this),l=n.u(this.options);n.p(e),this.T(l),this._$AH=n}}_$AC(s){let e=Yt.get(s.strings);return e===void 0&&Yt.set(s.strings,e=new Se(s)),e}k(s){ct(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,t,i=0;for(let n of s)i===e.length?e.push(t=new a(this.O(ke()),this.O(ke()),this,this.options)):t=e[i],t._$AI(n),i++;i<e.length&&(this._$AR(t&&t._$AB.nextSibling,i),e.length=i)}_$AR(s=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);s!==this._$AB;){let t=Ut(s).nextSibling;Ut(s).remove(),s=t}}setConnected(s){this._$AM===void 0&&(this._$Cv=s,this._$AP?.(s))}},he=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(s,e,t,i,n){this.type=1,this._$AH=h,this._$AN=void 0,this.element=s,this.name=e,this._$AM=i,this.options=n,t.length>2||t[0]!==""||t[1]!==""?(this._$AH=Array(t.length-1).fill(new String),this.strings=t):this._$AH=h}_$AI(s,e=this,t,i){let n=this.strings,l=!1;if(n===void 0)s=pe(this,s,e,0),l=!Ee(s)||s!==this._$AH&&s!==oe,l&&(this._$AH=s);else{let d=s,p,_;for(s=n[0],p=0;p<n.length-1;p++)_=pe(this,d[t+p],e,p),_===oe&&(_=this._$AH[p]),l||=!Ee(_)||_!==this._$AH[p],_===h?s=h:s!==h&&(s+=(_??"")+n[p+1]),this._$AH[p]=_}l&&!i&&this.j(s)}j(s){s===h?this.element.removeAttribute(this.naLine truncated
Replace seal Replace seal
Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"{field}: too long (max {n} characters)",err_too_short:"{field}: too short (min {n} characters)",err_value_too_high:"{field}: too large (max {n})",err_value_too_low:"{field}: too small (min {n})",err_required:"{field}: required",err_wrong_type:"{field}: wrong type (expected: {type})",err_invalid_choice:"{field}: not an allowed value",err_invalid_value:"{field}: invalid value",feat_schedule_time:"Time-of-day scheduling",feat_schedule_time_desc:"Tasks become overdue at a specific time of day instead of midnight.",schedule_time_optional:"Due at time (optional, HH:MM)",schedule_time_help:"Empty = midnight (default). HA timezone.",at_time:"at",notes_optional:"Notes (optional)",notes_markdown_hint:"Markdown is supported \u2014 **bold**, lists, [links](\u2026)",cost_optional:"Cost (optional)",duration_minutes:"Duration in minutes (optional)",completed_at_optional:"Completed at (optional, empty = now)",completed_at_future_error:"The completion date cannot be in the future.",days:"days",day:"day",today:"Today",d_overdue:"d overdue",no_tasks:"No maintenance tasks yet. Create an object to get started.",no_tasks_short:"No tasks",no_history:"No history entries yet.",show_all:"Show all",cost_duration_chart:"Cost & Duration",installed:"Installed",confirm_delete_object:"Delete this object and all its tasks?",confirm_delete_task:"Delete this task?",min:"Min",max:"Max",save:"Save",saving:"Saving\u2026",edit_task:"Edit Task",new_task:"New Maintenance Task",task_name:"Task name",maintenance_type:"Maintenance type",priority:"Priority",labels:"Labels",labels_placeholder:"e.g. safety, seasonal, tenant-visible",labels_help:"Comma-separated tags for filtering and reporting.",priority_low:"Low",priority_normal:"Normal",priority_high:"High",all_priorities:"All priorities",schedule_type:"Schedule type",interval_days:"Interval (days)",warning_days:"Warning days",earliest_completion_days:"Earliest completion (days before due)",earliest_completion_days_help:"Leave empty to allow completing any time. 0 = only on/after the due date.",last_performed_optional:"Last performed (optional)",interval_anchor:"Interval anchor",anchor_completion:"From completion date",anchor_planned:"From planned date (no drift)",edit_object:"Edit Object",name:"Name",manufacturer_optional:"Manufacturer (optional)",model_optional:"Model (optional)",serial_number_optional:"Serial number (optional)",serial_number_label:"S/N",documentation_url_label:"Manual",object_notes_label:"Notes",sort_due_date:"Due date",sort_object:"Object name",sort_type:"Type",sort_task_name:"Task name",all_objects:"All objects",all_parts:"All parts",tasks_lower:"tasks",no_tasks_yet:"No tasks yet",add_first_task:"Add first task",trigger_configuration:"Trigger Configuration",entity_id:"Entity ID",comma_separated:"comma-separated",entity_logic:"Entity logic",entity_logic_any:"Any entity triggers",entity_logic_all:"All entities must trigger",entities:"entities",attribute_optional:"Attribute (optional, blank = state)",use_entity_state:"Use entity state (no attribute)",trigger_above:"Trigger above",trigger_below:"Trigger below",trigger_equals:"Trigger when equal to (=)",trigger_not_equals:"Trigger when different from (\u2260)",for_at_least_minutes:"For at least (minutes)",safety_interval_days:"Safety interval (days, optional)",safety_interval:"Safety interval (optional)",trigger_combinator:"Combine trigger and interval",trigger_combinator_any:"Trigger or interval (whichever first)",trigger_combinator_all:"Trigger and interval (both required)",delta_mode:"Delta mode",from_state_optional:"From state (optional)",to_state_optional:"To state (optional)",documentation_url_optional:"Documentation URL (optional)",object_notes_optional:"Notes (optional)",nfc_tag_id_optional:"NFC Tag ID (optional)",nfc_tags_empty_help:"No NFC tags registered in Home Assistant yet.",nfc_tags_open_settings:"Open Tags settings",nfc_tags_refresh:"Refresh",environmental_entity_optional:"Environmental sensor (optional)",environmental_entity_helper:"e.g. sensor.outdoor_temperature \u2014 adjusts the interval based on environmental conditions",adaptive_prediction_enabled:"Enable sensor-driven predictions",adaptive_seasonal_enabled:"Enable seasonal awareness",adaptive_max_interval:"Maximum interval (days)",adaptive_min_interval:"Minimum interval (days)",adaptive_ewa_alpha:"Learning rate (alpha)",adaptive_enabled:"Enable adaptive scheduling",adaptive_section_title:"Adaptive Scheduling",environmental_attribute_optional:"Environmental attribute (optional)",nfc_tag_id:"NFC Tag ID",nfc_linked:"NFC tag linked",nfc_link_hint:"Click to link NFC tag",responsible_user:"Responsible User",shared_with:"Shared with (rotation)",shared_with_help:"Pick multiple people to share this task; the responsible person rotates on each completion.",rotation_strategy:"Rotation",rotation_none:"No rotation",rotation_round_robin:"Round-robin",rotation_least_completed:"Least completed",ro Line truncated Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"{field}: too long (max {n} characters)",err_too_short:"{field}: too short (min {n} characters)",err_value_too_high:"{field}: too large (max {n})",err_value_too_low:"{field}: too small (min {n})",err_required:"{field}: required",err_wrong_type:"{field}: wrong type (expected: {type})",err_invalid_choice:"{field}: not an allowed value",err_invalid_value:"{field}: invalid value",feat_schedule_time:"Time-of-day scheduling",feat_schedule_time_desc:"Tasks become overdue at a specific time of day instead of midnight.",schedule_time_optional:"Due at time (optional, HH:MM)",schedule_time_help:"Empty = midnight (default). HA timezone.",at_time:"at",notes_optional:"Notes (optional)",notes_markdown_hint:"Markdown is supported \u2014 **bold**, lists, [links](\u2026)",cost_optional:"Cost (optional)",duration_minutes:"Duration in minutes (optional)",completed_at_optional:"Completed at (optional, empty = now)",completed_at_future_error:"The completion date cannot be in the future.",days:"days",day:"day",today:"Today",d_overdue:"d overdue",no_tasks:"No maintenance tasks yet. Create an object to get started.",no_tasks_short:"No tasks",no_history:"No history entries yet.",show_all:"Show all",cost_duration_chart:"Cost & Duration",installed:"Installed",confirm_delete_object:"Delete this object and all its tasks?",confirm_delete_task:"Delete this task?",min:"Min",max:"Max",save:"Save",saving:"Saving\u2026",edit_task:"Edit Task",new_task:"New Maintenance Task",task_name:"Task name",maintenance_type:"Maintenance type",priority:"Priority",labels:"Labels",labels_placeholder:"e.g. safety, seasonal, tenant-visible",labels_help:"Comma-separated tags for filtering and reporting.",priority_low:"Low",priority_normal:"Normal",priority_high:"High",all_priorities:"All priorities",schedule_type:"Schedule type",interval_days:"Interval (days)",warning_days:"Warning days",earliest_completion_days:"Earliest completion (days before due)",earliest_completion_days_help:"Leave empty to allow completing any time. 0 = only on/after the due date.",last_performed_optional:"Last performed (optional)",interval_anchor:"Interval anchor",anchor_completion:"From completion date",anchor_planned:"From planned date (no drift)",edit_object:"Edit Object",name:"Name",manufacturer_optional:"Manufacturer (optional)",model_optional:"Model (optional)",serial_number_optional:"Serial number (optional)",serial_number_label:"S/N",documentation_url_label:"Manual",object_notes_label:"Notes",sort_due_date:"Due date",sort_object:"Object name",sort_type:"Type",sort_task_name:"Task name",all_objects:"All objects",all_parts:"All parts",tasks_lower:"tasks",no_tasks_yet:"No tasks yet",add_first_task:"Add first task",trigger_configuration:"Trigger Configuration",entity_id:"Entity ID",comma_separated:"comma-separated",entity_logic:"Entity logic",entity_logic_any:"Any entity triggers",entity_logic_all:"All entities must trigger",entities:"entities",attribute_optional:"Attribute (optional, blank = state)",use_entity_state:"Use entity state (no attribute)",trigger_above:"Trigger above",trigger_below:"Trigger below",trigger_equals:"Trigger when equal to (=)",trigger_not_equals:"Trigger when different from (\u2260)",for_at_least_minutes:"For at least (minutes)",safety_interval_days:"Safety interval (days, optional)",safety_interval:"Safety interval (optional)",trigger_combinator:"Combine trigger and interval",trigger_combinator_any:"Trigger or interval (whichever first)",trigger_combinator_all:"Trigger and interval (both required)",delta_mode:"Delta mode",from_state_optional:"From state (optional)",to_state_optional:"To state (optional)",documentation_url_optional:"Documentation URL (optional)",object_notes_optional:"Notes (optional)",nfc_tag_id_optional:"NFC Tag ID (optional)",nfc_tags_empty_help:"No NFC tags registered in Home Assistant yet.",nfc_tags_open_settings:"Open Tags settings",nfc_tags_refresh:"Refresh",environmental_entity_optional:"Environmental sensor (optional)",environmental_entity_helper:"e.g. sensor.outdoor_temperature \u2014 adjusts the interval based on environmental conditions",adaptive_prediction_enabled:"Enable sensor-driven predictions",adaptive_seasonal_enabled:"Enable seasonal awareness",adaptive_max_interval:"Maximum interval (days)",adaptive_min_interval:"Minimum interval (days)",adaptive_ewa_alpha:"Learning rate (alpha)",adaptive_enabled:"Enable adaptive scheduling",adaptive_section_title:"Adaptive Scheduling",environmental_attribute_optional:"Environmental attribute (optional)",nfc_tag_id:"NFC Tag ID",nfc_linked:"NFC tag linked",nfc_link_hint:"Click to link NFC tag",responsible_user:"Responsible User",shared_with:"Shared with (rotation)",shared_with_help:"Pick multiple people to share this task; the responsible person rotates on each completion.",rotation_strategy:"Rotation",rotation_none:"No rotation",rotation_round_robin:"Round-robin",rotation_least_completed:"Least completed",ro Line truncated
.field { display: flex; flex-direction: column; gap: 4px; } .field { display: flex; flex-direction: column; gap: 4px; }
.field-label { font-size: 12px; color: var(--secondary-text-color); } .field-label { font-size: 12px; color: var(--secondary-text-color); }
.field-input { .field-input {
@@ -14,7 +14,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
font-family: inherit; width: 100%; box-sizing: border-box; font-family: inherit; width: 100%; box-sizing: border-box;
} }
.field-input:focus { outline: none; border-color: var(--primary-color); } .field-input:focus { outline: none; border-color: var(--primary-color); }
`,We=A` `,We=T`
:host { :host {
--maint-ok-color: var(--success-color, #4caf50); --maint-ok-color: var(--success-color, #4caf50);
--maint-due-soon-color: var(--warning-color, #ff9800); --maint-due-soon-color: var(--warning-color, #ff9800);
@@ -531,8 +531,15 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 2px; gap: 2px;
/* #150 follow-up (2026-08-31, maisun's mobile screenshot): the box used
to carry min-width: 90px — in the narrow grid the due column is
fit-content(100px) and right-aligned, so on cells narrower than 90px
the box overhung LEFT across the object name. It now tracks the cell
with no floor, and the label ellipsizes inside. */
align-self: stretch;
max-width: 100%;
min-width: 0;
width: 100%; width: 100%;
min-width: 90px;
} }
.trigger-progress-bar { .trigger-progress-bar {
@@ -553,8 +560,25 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
font-size: 12px; font-size: 12px;
color: var(--secondary-text-color); color: var(--secondary-text-color);
text-align: right; text-align: right;
max-width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
} }
/* #150 follow-up: 3-state trend arrow — replaces the sparkline on
narrow/tight rows (panel-styles toggles visibility per regime). */
.trend-arrow {
display: none;
font-style: normal;
font-weight: 700;
margin-left: 2px;
}
.trend-approaching { color: var(--warning-color, #ff9800); }
.trend-stable { color: var(--secondary-text-color); }
.trend-easing { color: var(--success-color, #4caf50); }
/* Days progress bar (detail view) */ /* Days progress bar (detail view) */
.days-progress { .days-progress {
margin: 8px 0 16px; margin: 8px 0 16px;
@@ -597,6 +621,11 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
/* Mini-sparkline in overview rows */ /* Mini-sparkline in overview rows */
.mini-sparkline { .mini-sparkline {
width: 60px; width: 60px;
/* Same class of bug as the trigger-progress floor (#150 follow-up): in
due cells narrower than the fixed width the right-aligned SVG used to
overhang LEFT (phone-360 sweep). preserveAspectRatio="none" lets it
just squeeze. */
max-width: 100%;
height: 20px; height: 20px;
display: block; display: block;
margin-top: 2px; margin-top: 2px;
@@ -1149,7 +1178,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
.stat-item .stat-label { font-size: 11px; white-space: normal; text-align: center; line-height: 1.2; } .stat-item .stat-label { font-size: 11px; white-space: normal; text-align: center; line-height: 1.2; }
.stat-value { font-size: 20px; } .stat-value { font-size: 20px; }
} }
`});function Ei(a,s,e){let t=new Blob([a],{type:e}),i=URL.createObjectURL(t),n=document.createElement("a");n.href=i,n.download=s,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(i),6e4)}var ft=w(()=>{"use strict"});function Ke(a){return!!a&&/^https?:\/\//i.test(a)}var vt=w(()=>{"use strict"});var me,bt=w(()=>{"use strict";me=class{constructor(s){this.usersCache=null;this.cacheTimestamp=0;this.CACHE_TTL_MS=6e4;this.hass=s}updateHass(s){this.hass=s}async getUsers(s=!1){let e=Date.now();if(!s&&this.usersCache&&e-this.cacheTimestamp<this.CACHE_TTL_MS)return this.usersCache;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/users/list"});return this.usersCache=t.users,this.cacheTimestamp=e,this.usersCache}catch(t){return console.error("Failed to fetch users:",t),this.usersCache||[]}}async assignUser(s,e,t){await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/assign_user",entry_id:s,task_id:e,user_id:t})}async getTasksByUser(s){return(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/tasks/by_user",user_id:s})).tasks}getUserName(s){return!s||!this.usersCache?null:this.usersCache.find(t=>t.id===s)?.name||null}getUser(s){return!s||!this.usersCache?null:this.usersCache.find(e=>e.id===s)||null}getCurrentUserId(){return this.hass.user?.id||null}isCurrentUser(s){return s?s===this.getCurrentUserId():!1}clearCache(){this.usersCache=null,this.cacheTimestamp=0}}});function Us(a,s){if(s<=0)return 0;let e=typeof a=="number"&&Number.isFinite(a)?Math.trunc(a):0;return e<0?0:e%s}function Bs(a){return!!(a?.phases&&a.phase_sequence&&a.phase_sequence.length>0)}function yt(a){if(!a||!Bs(a))return null;let s=a.phase_sequence,e=Us(a.phase_cursor,s.length),t=s[e],i=a.phases?.[t];return i?{id:t,name:i.name,index:e,count:s.length,notes:i.notes,checklist:i.checklist!==void 0?i.checklist:a.checklist??[],consumesParts:i.consumes_parts!==void 0?i.consumes_parts:a.consumes_parts??[],requiredFields:i.required_completion_fields!==void 0?i.required_completion_fields:a.required_completion_fields??[]}:null}function ie(a){let s=yt(a);return s?`${s.index+1}/${s.count} \xB7 ${s.name}`:""}var Ye=w(()=>{"use strict"});function V(a){return`${a.entry_id??""}\0${a.part_id}`}function Ai(a,s,e,t){let i=!!a.entry_id&&a.entry_id!==s,n=i?a.entry_id:s,l=e.find(f=>f.entry_id===n),d=(l?.parts||[]).find(f=>f.id===a.part_id)||null,p=i&&l?.object?.name||"",_=d?.name||r("shared_part_unknown",t);return{part:d,foreign:i,ownerName:p,label:p?`${_} (${p})`:_}}function Ti(a,s,e,t){let{part:i,label:n}=Ai(a,s,e,t),l=i&&i.stock!==null&&i.stock!==void 0?` (${i.stock}${i.unit?" "+i.unit:""})`:"",d=i?.storage_location?` \u2014 ${i.storage_location}`:"";return`${a.quantity}\xD7 ${n}${l}${d}`}function Ci(a,s,e,t){let n=(e.find(d=>d.entry_id===s)?.parts||[]).map(d=>({...d})),l=new Set(n.map(d=>V({part_id:d.id})));for(let d of a?.consumes_parts||[]){if(!d.entry_id||d.entry_id===s)continue;let p=V(d);if(l.has(p))continue;l.add(p);let{part:_,ownerName:f}=Ai(d,s,e,t);n.push({id:d.part_id,name:_?.name||r("shared_part_unknown",t),unit:_?.unit,stock:_?.stock??null,storage_location:_?.storage_location,entry_id:d.entry_id,owner_name:f})}return n}var Qe=w(()=>{"use strict";q()});function Re(a){let s=a.task??null,e=s?yt(s):null,t=e?e.consumesParts:s?.consumes_parts||[],i=!!s?.part_ref,n=a.objects.find(p=>p.entry_id===a.entryId)?.parts||[],l=i?n.find(p=>p.id===s.part_ref.part_id):void 0,d=a.checklistsEnabled??!0;return{entry_id:a.entryId,task_id:a.taskId,task_name:a.taskName,checklist:e?d?e.checklist:[]:a.checklist??[],adaptive_enabled:!!a.adaptiveEnabled,required_completion_fields:e?e.requiredFields:s?.required_completion_fields||[],task_type:s?.type||"",reading_unit:s?.reading_unit||"",parts:i?[]:Ci({consumes_parts:t},a.entryId,a.objects,a.lang),consumes_parts:i?[]:t,phase_label:e?ie(s):"",require_tag_scan:!!s?.require_tag_scan,restock_default:i?l?.restock_quantity??1:null,restock_unit_cost:i?l?.cost??null:null,currency_symbol:a.currencySymbol??"",consumes_info:t.map(p=>Ti(p,a.entryId,a.objects,a.lang)),checklist_prefill:s?.checklist_progress||{},via_tag_scan:!!a.viaTagScan}}function je(a,s,e){a.entryId=s.entry_id,a.taskId=s.task_id,a.taskName=s.task_name,a.lang=e,a.checklist=s.checklist??[],a.adaptiveEnabled=!!s.adaptive_enabled,a.requiredFields=s.required_completion_fields??[],a.taskType=s.task_type??"",a.readingUnit=s.reading_unit??"",a.parts=s.parts??[],a.consumesParts=s.consumes_parts??[],a.phaseLabel=s.phase_label??"",a.requireTagScan=!!s.require_tag_scan,a.restockDefault=s.restock_default??null,a.restockUnitCost=s.restock_unit_cost??null,a.currencySymbol=s.currency_symbol??"",a.consumesInfo=s.consumes_info??[],a.checklistPrefill=s.checklist_prefill??{},a.viaTagScan=!!s.via_tag_scan,a.open({viaTagScan:!!s.via_tag_scan})}var Je=w(()=>{"use strict";Qe();Ye()}); Line truncated `});function Ei(a,s,e){let t=new Blob([a],{type:e}),i=URL.createObjectURL(t),n=document.createElement("a");n.href=i,n.download=s,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(i),6e4)}var ft=w(()=>{"use strict"});function Ke(a){return!!a&&/^https?:\/\//i.test(a)}var vt=w(()=>{"use strict"});var me,bt=w(()=>{"use strict";me=class{constructor(s){this.usersCache=null;this.cacheTimestamp=0;this.CACHE_TTL_MS=6e4;this.hass=s}updateHass(s){this.hass=s}async getUsers(s=!1){let e=Date.now();if(!s&&this.usersCache&&e-this.cacheTimestamp<this.CACHE_TTL_MS)return this.usersCache;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/users/list"});return this.usersCache=t.users,this.cacheTimestamp=e,this.usersCache}catch(t){return console.error("Failed to fetch users:",t),this.usersCache||[]}}async assignUser(s,e,t){await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/assign_user",entry_id:s,task_id:e,user_id:t})}async getTasksByUser(s){return(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/tasks/by_user",user_id:s})).tasks}getUserName(s){return!s||!this.usersCache?null:this.usersCache.find(t=>t.id===s)?.name||null}getUser(s){return!s||!this.usersCache?null:this.usersCache.find(e=>e.id===s)||null}getCurrentUserId(){return this.hass.user?.id||null}isCurrentUser(s){return s?s===this.getCurrentUserId():!1}clearCache(){this.usersCache=null,this.cacheTimestamp=0}}});function Us(a,s){if(s<=0)return 0;let e=typeof a=="number"&&Number.isFinite(a)?Math.trunc(a):0;return e<0?0:e%s}function Bs(a){return!!(a?.phases&&a.phase_sequence&&a.phase_sequence.length>0)}function yt(a){if(!a||!Bs(a))return null;let s=a.phase_sequence,e=Us(a.phase_cursor,s.length),t=s[e],i=a.phases?.[t];return i?{id:t,name:i.name,index:e,count:s.length,notes:i.notes,checklist:i.checklist!==void 0?i.checklist:a.checklist??[],consumesParts:i.consumes_parts!==void 0?i.consumes_parts:a.consumes_parts??[],requiredFields:i.required_completion_fields!==void 0?i.required_completion_fields:a.required_completion_fields??[]}:null}function ie(a){let s=yt(a);return s?`${s.index+1}/${s.count} \xB7 ${s.name}`:""}var Ye=w(()=>{"use strict"});function V(a){return`${a.entry_id??""}\0${a.part_id}`}function Ti(a,s,e,t){let i=!!a.entry_id&&a.entry_id!==s,n=i?a.entry_id:s,l=e.find(f=>f.entry_id===n),d=(l?.parts||[]).find(f=>f.id===a.part_id)||null,p=i&&l?.object?.name||"",_=d?.name||r("shared_part_unknown",t);return{part:d,foreign:i,ownerName:p,label:p?`${_} (${p})`:_}}function Ai(a,s,e,t){let{part:i,label:n}=Ti(a,s,e,t),l=i&&i.stock!==null&&i.stock!==void 0?` (${i.stock}${i.unit?" "+i.unit:""})`:"",d=i?.storage_location?` \u2014 ${i.storage_location}`:"";return`${a.quantity}\xD7 ${n}${l}${d}`}function Ci(a,s,e,t){let n=(e.find(d=>d.entry_id===s)?.parts||[]).map(d=>({...d})),l=new Set(n.map(d=>V({part_id:d.id})));for(let d of a?.consumes_parts||[]){if(!d.entry_id||d.entry_id===s)continue;let p=V(d);if(l.has(p))continue;l.add(p);let{part:_,ownerName:f}=Ti(d,s,e,t);n.push({id:d.part_id,name:_?.name||r("shared_part_unknown",t),unit:_?.unit,stock:_?.stock??null,storage_location:_?.storage_location,entry_id:d.entry_id,owner_name:f})}return n}var Qe=w(()=>{"use strict";q()});function Re(a){let s=a.task??null,e=s?yt(s):null,t=e?e.consumesParts:s?.consumes_parts||[],i=!!s?.part_ref,n=a.objects.find(p=>p.entry_id===a.entryId)?.parts||[],l=i?n.find(p=>p.id===s.part_ref.part_id):void 0,d=a.checklistsEnabled??!0;return{entry_id:a.entryId,task_id:a.taskId,task_name:a.taskName,checklist:e?d?e.checklist:[]:a.checklist??[],adaptive_enabled:!!a.adaptiveEnabled,required_completion_fields:e?e.requiredFields:s?.required_completion_fields||[],task_type:s?.type||"",reading_unit:s?.reading_unit||"",parts:i?[]:Ci({consumes_parts:t},a.entryId,a.objects,a.lang),consumes_parts:i?[]:t,phase_label:e?ie(s):"",require_tag_scan:!!s?.require_tag_scan,restock_default:i?l?.restock_quantity??1:null,restock_unit_cost:i?l?.cost??null:null,currency_symbol:a.currencySymbol??"",consumes_info:t.map(p=>Ai(p,a.entryId,a.objects,a.lang)),checklist_prefill:s?.checklist_progress||{},via_tag_scan:!!a.viaTagScan}}function je(a,s,e){a.entryId=s.entry_id,a.taskId=s.task_id,a.taskName=s.task_name,a.lang=e,a.checklist=s.checklist??[],a.adaptiveEnabled=!!s.adaptive_enabled,a.requiredFields=s.required_completion_fields??[],a.taskType=s.task_type??"",a.readingUnit=s.reading_unit??"",a.parts=s.parts??[],a.consumesParts=s.consumes_parts??[],a.phaseLabel=s.phase_label??"",a.requireTagScan=!!s.require_tag_scan,a.restockDefault=s.restock_default??null,a.restockUnitCost=s.restock_unit_cost??null,a.currencySymbol=s.currency_symbol??"",a.consumesInfo=s.consumes_info??[],a.checklistPrefill=s.checklist_prefill??{},a.viaTagScan=!!s.via_tag_scan,a.open({viaTagScan:!!s.via_tag_scan})}var Je=w(()=>{"use strict";Qe();Ye()}); Line truncated
type="button" type="button"
class="cost-suggestion" class="cost-suggestion"
@click=${()=>this._cost=t.toFixed(2)} @click=${()=>this._cost=t.toFixed(2)}
@@ -1283,7 +1312,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
</ha-button> </ha-button>
</div> </div>
</ha-dialog> </ha-dialog>
`}};k.styles=[ki,A` `}};k.styles=[ki,T`
.req-mark { .req-mark {
color: var(--error-color, #f44336); color: var(--error-color, #f44336);
margin-left: 2px; margin-left: 2px;
@@ -1490,7 +1519,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
/>`} />`}
${this.helper?o`<span class="helper">${this.helper}</span>`:h} ${this.helper?o`<span class="helper">${this.helper}</span>`:h}
</label> </label>
`}};N.styles=A` `}};N.styles=T`
:host { display: block; } :host { display: block; }
.field { .field {
display: flex; display: flex;
@@ -1539,7 +1568,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
color: var(--secondary-text-color); color: var(--secondary-text-color);
font-style: italic; font-style: italic;
} }
`,c([x()],N.prototype,"label",2),c([x()],N.prototype,"value",2),c([x()],N.prototype,"placeholder",2),c([x()],N.prototype,"type",2),c([x({type:Boolean})],N.prototype,"required",2),c([x({type:Boolean})],N.prototype,"disabled",2),c([x()],N.prototype,"step",2),c([x()],N.prototype,"min",2),c([x()],N.prototype,"max",2),c([x()],N.prototype,"pattern",2),c([x()],N.prototype,"helper",2),c([x({type:Boolean})],N.prototype,"multiline",2),c([x({type:Number})],N.prototype,"rows",2);customElements.get("ms-textfield")||customElements.define("ms-textfield",N)});var I,Li=w(()=>{"use strict";R();D();q();se();St();I=class extends S{constructor(){super(...arguments);this.objects=[];this._open=!1;this._loading=!1;this._error="";this._name="";this._manufacturer="";this._model="";this._serialNumber="";this._areaId="";this._installationDate="";this._warrantyExpiry="";this._documentationUrl="";this._notes="";this._haDeviceId="";this._parentEntryId="";this._entryId=null}get _lang(){return j(this.hass)}openCreate(){this._entryId=null,this._name="",this._manufacturer="",this._model="",this._serialNumber="",this._areaId="",this._installationDate="",this._warrantyExpiry="",this._documentationUrl="",this._notes="",this._haDeviceId="",this._parentEntryId="",this._error="",this._open=!0}openEdit(e,t){this._entryId=e,this._name=t.name||"",this._manufacturer=t.manufacturer||"",this._model=t.model||"",this._serialNumber=t.serial_number||"",this._areaId=t.area_id||"",this._installationDate=t.installation_date||"",this._warrantyExpiry=t.warranty_expiry||"",this._documentationUrl=t.documentation_url||"",this._notes=t.notes||"",this._haDeviceId=t.ha_device_id||"",this._parentEntryId=t.parent_entry_id||"",this._error="",this._open=!0}async _save(){if(!this._loading&&this._name.trim()){this._loading=!0,this._error="";try{this._entryId?await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/update",entry_id:this._entryId,name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}):await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/create",name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}),this._open=!1,this.dispatchEvent(new CustomEvent("object-saved"))}catch(e){this._error=T(e,this._lang,r("save_error",this._lang))}finally{this._loading=!1}}}_parentChoices(){return(this.objects||[]).filter(e=>e.entry_id!==this._entryId)}_close(){this._open=!1}render(){if(!this._open)return o``;let e=this._lang,t=this._entryId?r("edit_object",e):r("new_object",e);return o` `,c([x()],N.prototype,"label",2),c([x()],N.prototype,"value",2),c([x()],N.prototype,"placeholder",2),c([x()],N.prototype,"type",2),c([x({type:Boolean})],N.prototype,"required",2),c([x({type:Boolean})],N.prototype,"disabled",2),c([x()],N.prototype,"step",2),c([x()],N.prototype,"min",2),c([x()],N.prototype,"max",2),c([x()],N.prototype,"pattern",2),c([x()],N.prototype,"helper",2),c([x({type:Boolean})],N.prototype,"multiline",2),c([x({type:Number})],N.prototype,"rows",2);customElements.get("ms-textfield")||customElements.define("ms-textfield",N)});var I,Li=w(()=>{"use strict";R();D();q();se();St();I=class extends S{constructor(){super(...arguments);this.objects=[];this._open=!1;this._loading=!1;this._error="";this._name="";this._manufacturer="";this._model="";this._serialNumber="";this._areaId="";this._installationDate="";this._warrantyExpiry="";this._documentationUrl="";this._notes="";this._haDeviceId="";this._parentEntryId="";this._entryId=null}get _lang(){return j(this.hass)}openCreate(){this._entryId=null,this._name="",this._manufacturer="",this._model="",this._serialNumber="",this._areaId="",this._installationDate="",this._warrantyExpiry="",this._documentationUrl="",this._notes="",this._haDeviceId="",this._parentEntryId="",this._error="",this._open=!0}openEdit(e,t){this._entryId=e,this._name=t.name||"",this._manufacturer=t.manufacturer||"",this._model=t.model||"",this._serialNumber=t.serial_number||"",this._areaId=t.area_id||"",this._installationDate=t.installation_date||"",this._warrantyExpiry=t.warranty_expiry||"",this._documentationUrl=t.documentation_url||"",this._notes=t.notes||"",this._haDeviceId=t.ha_device_id||"",this._parentEntryId=t.parent_entry_id||"",this._error="",this._open=!0}async _save(){if(!this._loading&&this._name.trim()){this._loading=!0,this._error="";try{this._entryId?await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/update",entry_id:this._entryId,name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}):await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/create",name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}),this._open=!1,this.dispatchEvent(new CustomEvent("object-saved"))}catch(e){this._error=A(e,this._lang,r("save_error",this._lang))}finally{this._loading=!1}}}_parentChoices(){return(this.objects||[]).filter(e=>e.entry_id!==this._entryId)}_close(){this._open=!1}render(){if(!this._open)return o``;let e=this._lang,t=this._entryId?r("edit_object",e):r("new_object",e);return o`
<ha-dialog open @closed=${this._close}> <ha-dialog open @closed=${this._close}>
<div class="dialog-title">${t}</div> <div class="dialog-title">${t}</div>
<div class="content"> <div class="content">
@@ -1634,7 +1663,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
</ha-button> </ha-button>
</div> </div>
</ha-dialog> </ha-dialog>
`}};I.styles=A` `}};I.styles=T`
.dialog-title { .dialog-title {
font-size: 18px; font-size: 18px;
font-weight: 500; font-weight: 500;
@@ -1684,9 +1713,9 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
color: var(--error-color, #f44336); color: var(--error-color, #f44336);
font-size: 13px; font-size: 13px;
} }
`,c([x({attribute:!1})],I.prototype,"hass",2),c([x({attribute:!1})],I.prototype,"objects",2),c([u()],I.prototype,"_open",2),c([u()],I.prototype,"_loading",2),c([u()],I.prototype,"_error",2),c([u()],I.prototype,"_name",2),c([u()],I.prototype,"_manufacturer",2),c([u()],I.prototype,"_model",2),c([u()],I.prototype,"_serialNumber",2),c([u()],I.prototype,"_areaId",2),c([u()],I.prototype,"_installationDate",2),c([u()],I.prototype,"_warrantyExpiry",2),c([u()],I.prototype,"_documentationUrl",2),c([u()],I.prototype,"_notes",2),c([u()],I.prototype,"_haDeviceId",2),c([u()],I.prototype,"_parentEntryId",2),c([u()],I.prototype,"_entryId",2);customElements.get("maintenance-object-dialog")||customElements.define("maintenance-object-dialog",I)});var At,Ri,ji,qi=w(()=>{"use strict";At=["sensor","binary_sensor","number","input_number","input_boolean","switch","climate","vacuum","cover","fan","light","water_heater","humidifier","media_player","weather","air_quality","valve","lawn_mower","lock"],Ri=["sensor"],ji=["temperature","humidity","pressure"]});function Xs(){return{entityIds:"",type:"threshold",attribute:"",above:"",below:"",equals:"",notEquals:"",forMinutes:"0",targetValue:"",deltaMode:!1,fromState:"",toState:"",targetChanges:"",runtimeHours:"",onStates:"",carry:{}}}function tr(a){return{entityIds:(a.entity_ids||(a.entity_id?[a.entity_id]:[])).join(", "),type:a.type||"threshold",attribute:a.attribute||"",above:a.trigger_above?.toString()??"",below:a.trigger_below?.toString()??"",equals:a.trigger_equals?.toString()??"",notEquals:a.trigger_not_equals?.toString()??"",forMinutes:a.trigger_for_minutes?.toString()??"0",targetValue:a.trigger_target_value?.toString()??"",deltaMode:a.trigger_delta_mode||!1,fromState:a.trigger_from_state||"",toState:a.trigger_to_state||"",targetChanges:a.trigger_target_changes?.toString()??"",runtimeHours:a.trigger_runtime_hours?.toString()??"",onStates:(a.trigger_on_states||[]).join(", "),carry:Object.fromEntries(Object.entries(a).filter(([e])=>!er.has(e)&&!e.startsWith("_")))}}function ir(a){let s=a.entityIds.split(",").map(t=>t.trim()).filter(Boolean);if(s.length===0)return null;let e={...a.carry||{},entity_id:s[0],entity_ids:s,type:a.type};if(a.attribute&&(e.attribute=a.attribute),a.type==="threshold"){let t=parseFloat(a.above);isNaN(t)||(e.trigger_above=t);let i=parseFloat(a.below);isNaN(i)||(e.trigger_below=i);let n=parseFloat(a.equals);isNaN(n)||(e.trigger_equals=n);let l=parseFloat(a.notEquals);isNaN(l)||(e.trigger_not_equals=l);let d=parseInt(a.forMinutes,10);isNaN(d)||(e.trigger_for_minutes=d)}else if(a.type==="counter"){let t=parseFloat(a.targetValue);isNaN(t)||(e.trigger_target_value=t),e.trigger_delta_mode=a.deltaMode}else if(a.type==="state_change"){a.fromState&&(e.trigger_from_state=a.fromState),a.toState&&(e.trigger_to_state=a.toState);let t=parseInt(a.targetChanges,10);isNaN(t)||(e.trigger_target_changes=t)}else if(a.type==="runtime"){let t=parseFloat(a.runtimeHours);isNaN(t)||(e.trigger_runtime_hours=t);let i=(a.onStates||"").split(",").map(n=>n.trim()).filter(Boolean);i.length>0&&(e.trigger_on_states=i)}return e}function sr(a){return Array.from({length:7},(s,e)=>Ie(e,a,"short"))}function rr(a){let s=new Intl.DateTimeFormat(a||"en",{month:"short"});return Array.from({length:12},(e,t)=>s.format(new Date(2021,t,1)))}var Ys,Qs,Js,Tt,Ni,Zs,J,er,g,Ct,Hi=w(()=>{"use strict";R();D();q();bt();Qe();qi();se();wt();St();Ys=["cleaning","inspection","replacement","calibration","service","reading","custom"],Qs=["low","normal","high"],Js=["time_based","weekdays","nth_weekday","day_of_month","sensor_based","one_time","manual"],Tt=["weekdays","nth_weekday","day_of_month"],Ni=["threshold","counter","state_change","runtime"],Zs=[...Ni,"compound"],J={alpha:"0.3",min:"7",max:"365"};er=new Set(["entity_id","entity_ids","type","attribute","trigger_above","trigger_below","trigger_equals","trigger_not_equals","trigger_for_minutes","trigger_target_value","trigger_delta_mode","trigger_from_state","trigger_to_state","trigger_target_changes","trigger_runtime_hours","trigger_on_states"]);g=class g extends S{constructor(){super(...arguments);this.checklistsEnabled=!1;this.scheduleTimeEnabled=!1;this.completionActionsEnabled=!1;this.defaultWarningDays=7;this.parts=[];this._foreignOwners=[];this._open=!1;this._entityPickerFallback=!1;this._pickerProbeStrikes=0;this._loading=!1;this._error="";this._entryId="";this._taskId=null;this._objectChoices=[];this._name="";this._type="custom";this._scheduleType="time_based";this._intervalDays="30";this._intervalUnit="days";this._dueDate="";this._warningDays="7";this._earliestCompletionDays="";this._intervalAnchor="completion";this._weekdays=[];this._nth="1";this._nthWeekday="5";this._domDay="1";this._domLastDay=!1;this._domBusiness=!1;this._calOffset="0";this._seasonMonths=[];this._endsMode="never";this._endsCount="";this._endsUntil="";this._schedulePreview=[];this._schedulePreviewEnded=!1;this._previewSeq=0;this._notes="";this._documentationUrl="";this._customIcon="";t Line truncated `,c([x({attribute:!1})],I.prototype,"hass",2),c([x({attribute:!1})],I.prototype,"objects",2),c([u()],I.prototype,"_open",2),c([u()],I.prototype,"_loading",2),c([u()],I.prototype,"_error",2),c([u()],I.prototype,"_name",2),c([u()],I.prototype,"_manufacturer",2),c([u()],I.prototype,"_model",2),c([u()],I.prototype,"_serialNumber",2),c([u()],I.prototype,"_areaId",2),c([u()],I.prototype,"_installationDate",2),c([u()],I.prototype,"_warrantyExpiry",2),c([u()],I.prototype,"_documentationUrl",2),c([u()],I.prototype,"_notes",2),c([u()],I.prototype,"_haDeviceId",2),c([u()],I.prototype,"_parentEntryId",2),c([u()],I.prototype,"_entryId",2);customElements.get("maintenance-object-dialog")||customElements.define("maintenance-object-dialog",I)});var Tt,Ri,ji,qi=w(()=>{"use strict";Tt=["sensor","binary_sensor","number","input_number","input_boolean","switch","climate","vacuum","cover","fan","light","water_heater","humidifier","media_player","weather","air_quality","valve","lawn_mower","lock"],Ri=["sensor"],ji=["temperature","humidity","pressure"]});function Xs(){return{entityIds:"",type:"threshold",attribute:"",above:"",below:"",equals:"",notEquals:"",forMinutes:"0",targetValue:"",deltaMode:!1,fromState:"",toState:"",targetChanges:"",runtimeHours:"",onStates:"",carry:{}}}function tr(a){return{entityIds:(a.entity_ids||(a.entity_id?[a.entity_id]:[])).join(", "),type:a.type||"threshold",attribute:a.attribute||"",above:a.trigger_above?.toString()??"",below:a.trigger_below?.toString()??"",equals:a.trigger_equals?.toString()??"",notEquals:a.trigger_not_equals?.toString()??"",forMinutes:a.trigger_for_minutes?.toString()??"0",targetValue:a.trigger_target_value?.toString()??"",deltaMode:a.trigger_delta_mode||!1,fromState:a.trigger_from_state||"",toState:a.trigger_to_state||"",targetChanges:a.trigger_target_changes?.toString()??"",runtimeHours:a.trigger_runtime_hours?.toString()??"",onStates:(a.trigger_on_states||[]).join(", "),carry:Object.fromEntries(Object.entries(a).filter(([e])=>!er.has(e)&&!e.startsWith("_")))}}function ir(a){let s=a.entityIds.split(",").map(t=>t.trim()).filter(Boolean);if(s.length===0)return null;let e={...a.carry||{},entity_id:s[0],entity_ids:s,type:a.type};if(a.attribute&&(e.attribute=a.attribute),a.type==="threshold"){let t=parseFloat(a.above);isNaN(t)||(e.trigger_above=t);let i=parseFloat(a.below);isNaN(i)||(e.trigger_below=i);let n=parseFloat(a.equals);isNaN(n)||(e.trigger_equals=n);let l=parseFloat(a.notEquals);isNaN(l)||(e.trigger_not_equals=l);let d=parseInt(a.forMinutes,10);isNaN(d)||(e.trigger_for_minutes=d)}else if(a.type==="counter"){let t=parseFloat(a.targetValue);isNaN(t)||(e.trigger_target_value=t),e.trigger_delta_mode=a.deltaMode}else if(a.type==="state_change"){a.fromState&&(e.trigger_from_state=a.fromState),a.toState&&(e.trigger_to_state=a.toState);let t=parseInt(a.targetChanges,10);isNaN(t)||(e.trigger_target_changes=t)}else if(a.type==="runtime"){let t=parseFloat(a.runtimeHours);isNaN(t)||(e.trigger_runtime_hours=t);let i=(a.onStates||"").split(",").map(n=>n.trim()).filter(Boolean);i.length>0&&(e.trigger_on_states=i)}return e}function sr(a){return Array.from({length:7},(s,e)=>Ie(e,a,"short"))}function rr(a){let s=new Intl.DateTimeFormat(a||"en",{month:"short"});return Array.from({length:12},(e,t)=>s.format(new Date(2021,t,1)))}var Ys,Qs,Js,At,Ni,Zs,J,er,g,Ct,Hi=w(()=>{"use strict";R();D();q();bt();Qe();qi();se();wt();St();Ys=["cleaning","inspection","replacement","calibration","service","reading","custom"],Qs=["low","normal","high"],Js=["time_based","weekdays","nth_weekday","day_of_month","sensor_based","one_time","manual"],At=["weekdays","nth_weekday","day_of_month"],Ni=["threshold","counter","state_change","runtime"],Zs=[...Ni,"compound"],J={alpha:"0.3",min:"7",max:"365"};er=new Set(["entity_id","entity_ids","type","attribute","trigger_above","trigger_below","trigger_equals","trigger_not_equals","trigger_for_minutes","trigger_target_value","trigger_delta_mode","trigger_from_state","trigger_to_state","trigger_target_changes","trigger_runtime_hours","trigger_on_states"]);g=class g extends S{constructor(){super(...arguments);this.checklistsEnabled=!1;this.scheduleTimeEnabled=!1;this.completionActionsEnabled=!1;this.defaultWarningDays=7;this.parts=[];this._foreignOwners=[];this._open=!1;this._entityPickerFallback=!1;this._pickerProbeStrikes=0;this._loading=!1;this._error="";this._entryId="";this._taskId=null;this._objectChoices=[];this._name="";this._type="custom";this._scheduleType="time_based";this._intervalDays="30";this._intervalUnit="days";this._dueDate="";this._warningDays="7";this._earliestCompletionDays="";this._intervalAnchor="completion";this._weekdays=[];this._nth="1";this._nthWeekday="5";this._domDay="1";this._domLastDay=!1;this._domBusiness=!1;this._calOffset="0";this._seasonMonths=[];this._endsMode="never";this._endsCount="";this._endsUntil="";this._schedulePreview=[];this._schedulePreviewEnded=!1;this._previewSeq=0;this._notes="";this._documentationUrl="";this._customIcon="";t Line truncated
`),this._phaseDefs=Object.entries(t.phases||{}).map(([_,f])=>{let{name:b,checklist:v,consumes_parts:y,required_completion_fields:m,...$}=f,H=f.consumes_parts||[],C=H.findIndex(P=>!P.entry_id),E=C>=0?H[C]:void 0;return{id:_,name:f.name||_,checklistText:(f.checklist||[]).join(` `),this._phaseDefs=Object.entries(t.phases||{}).map(([_,f])=>{let{name:b,checklist:v,consumes_parts:y,required_completion_fields:m,...$}=f,H=f.consumes_parts||[],C=H.findIndex(P=>!P.entry_id),E=C>=0?H[C]:void 0;return{id:_,name:f.name||_,checklistText:(f.checklist||[]).join(`
`),partId:E?.part_id||"",partQty:E?.quantity!=null?String(E.quantity):"",reqOverride:f.required_completion_fields!==void 0,reqFields:[...f.required_completion_fields||[]],extraParts:H.filter((P,de)=>de!==C).map(P=>({...P})),carry:$}}),this._phaseSeq=[...t.phase_sequence||[]],this._requiredCompletion=[...t.required_completion_fields||[]],this._scheduleTime=t.schedule_time||"";let l=t.on_complete_action;if(l&&l.service){this._actionService=l.service;let _=l.target?.entity_id;this._actionTargetEntity=Array.isArray(_)?_[0]||"":_||"",this._actionData=l.data&&typeof l.data=="object"?{...l.data}:{},this._actionDataJsonFallback=""}else this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="";let d=t.quick_complete_defaults;this._qcNotes=d?.notes||"",this._qcCost=d?.cost!=null?String(d.cost):"",this._qcDuration=d?.duration!=null?String(d.duration):"",this._qcFeedback=d?.feedback||"";let p=t.adaptive_config||{};if(this._environmentalEntity=p.environmental_entity||"",this._environmentalAttribute=p.environmental_attribute||"",this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute,this._adaptiveEnabled=!!p.enabled,this._adaptiveAlpha=p.ewa_alpha?.toString()??J.alpha,this._adaptiveMin=p.min_interval_days?.toString()??J.min,this._adaptiveMax=p.max_interval_days?.toString()??J.max,this._adaptiveSeasonal=p.seasonal_enabled!==!1,this._adaptivePrediction=p.sensor_prediction_enabled!==!1,this._adaptiveInitial=this._adaptiveSnapshot(),t.trigger_config){let _=t.trigger_config;this._triggerEntityId=_.entity_id||_.entity_ids&&_.entity_ids[0]||"",this._triggerEntityIds=_.entity_ids||(_.entity_id?[_.entity_id]:[]),this._triggerEntityLogic=_.entity_logic||"any",this._triggerAttribute=_.attribute||"",this._triggerType=_.type||"threshold",this._triggerAbove=_.trigger_above?.toString()||"",this._triggerBelow=_.trigger_below?.toString()||"",this._triggerEquals=_.trigger_equals?.toString()||"",this._triggerNotEquals=_.trigger_not_equals?.toString()||"",this._triggerForMinutes=_.trigger_for_minutes?.toString()||"0",this._triggerCombinator=_.trigger_combinator==="all"?"all":"any",this._triggerTargetValue=_.trigger_target_value?.toString()||"",this._triggerDeltaMode=_.trigger_delta_mode||!1,this._triggerBaselineValue=_.trigger_baseline_value?.toString()||"",this._liveBaselineValue=t.trigger_baseline_value??null,this._autoCompleteOnRecovery=_.auto_complete_on_recovery||!1,this._triggerFromState=_.trigger_from_state||"",this._triggerToState=_.trigger_to_state||"",this._triggerTargetChanges=_.trigger_target_changes?.toString()||"",this._triggerRuntimeHours=_.trigger_runtime_hours?.toString()||"",this._triggerOnStates=(_.trigger_on_states||[]).join(", "),_.type==="compound"?(this._compoundLogic=_.compound_logic==="OR"?"OR":"AND",this._compoundConditions=(_.conditions||[]).map(tr)):(this._compoundLogic="AND",this._compoundConditions=[])}else this._resetTriggerFields();this._triggerEntityId&&this._fetchEntityAttributes(this._triggerEntityId),await Promise.all([this._loadUsers(),this._loadTags(),this._loadParts(),this._loadForeignPools()]),this._open=!0}_resetFields(){this._name="",this._type="custom",this._scheduleType="time_based",this._intervalDays="30",this._intervalUnit="days",this._dueDate="",this._warningDays=String(this.defaultWarningDays),this._earliestCompletionDays="",this._intervalAnchor="completion",this._weekdays=[],this._nth="1",this._nthWeekday="5",this._domDay="1",this._domLastDay=!1,this._domBusiness=!1,this._calOffset="0",this._seasonMonths=[],this._endsMode="never",this._endsCount="",this._endsUntil="",this._notes="",this._documentationUrl="",this._customIcon="",this._priority="normal",this._labels="",this._enabled=!0,this._lastPerformed="",this._nfcTagId="",this._requireTagScan=!1,this._readingUnit="",this._consumesParts={},this._responsibleUserId=null,this._assigneePool=[],this._rotationStrategy="",this._checklistText="",this._phaseDefs=[],this._phaseSeq=[],this._requiredCompletion=[],this._scheduleTime="",this._environmentalEntity="",this._environmentalAttribute="",this._environmentalInitial="",this._environmentalAttributeInitial="",this._adaptiveEnabled=!1,this._adaptiveAlpha=J.alpha,this._adaptiveMin=J.min,this._adaptiveMax=J.max,this._adaptiveSeasonal=!0,this._adaptivePrediction=!0,this._adaptiveInitial=this._adaptiveSnapshot(),this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="",this._actionTesting=!1,this._actionTestResult="",this._qcNotes="",this._qcCost="",this._qcDuration="",this._qcFeedback="",this._resetTriggerFields()}_resetTriggerFields(){this._triggerEntityId="",this._triggerEntityIds=[],this._triggerEntityLogic="any",this._triggerAttribute="",this._suggestedAttributes=[],this._availableAttributes=[],this._entityDomain="",this._triggerType="threshold",this._triggerAbove="",this._triggerBelow="",this._triggerEquals="",this._triggerNotEquals="",this._trigger Line truncated `),partId:E?.part_id||"",partQty:E?.quantity!=null?String(E.quantity):"",reqOverride:f.required_completion_fields!==void 0,reqFields:[...f.required_completion_fields||[]],extraParts:H.filter((P,de)=>de!==C).map(P=>({...P})),carry:$}}),this._phaseSeq=[...t.phase_sequence||[]],this._requiredCompletion=[...t.required_completion_fields||[]],this._scheduleTime=t.schedule_time||"";let l=t.on_complete_action;if(l&&l.service){this._actionService=l.service;let _=l.target?.entity_id;this._actionTargetEntity=Array.isArray(_)?_[0]||"":_||"",this._actionData=l.data&&typeof l.data=="object"?{...l.data}:{},this._actionDataJsonFallback=""}else this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="";let d=t.quick_complete_defaults;this._qcNotes=d?.notes||"",this._qcCost=d?.cost!=null?String(d.cost):"",this._qcDuration=d?.duration!=null?String(d.duration):"",this._qcFeedback=d?.feedback||"";let p=t.adaptive_config||{};if(this._environmentalEntity=p.environmental_entity||"",this._environmentalAttribute=p.environmental_attribute||"",this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute,this._adaptiveEnabled=!!p.enabled,this._adaptiveAlpha=p.ewa_alpha?.toString()??J.alpha,this._adaptiveMin=p.min_interval_days?.toString()??J.min,this._adaptiveMax=p.max_interval_days?.toString()??J.max,this._adaptiveSeasonal=p.seasonal_enabled!==!1,this._adaptivePrediction=p.sensor_prediction_enabled!==!1,this._adaptiveInitial=this._adaptiveSnapshot(),t.trigger_config){let _=t.trigger_config;this._triggerEntityId=_.entity_id||_.entity_ids&&_.entity_ids[0]||"",this._triggerEntityIds=_.entity_ids||(_.entity_id?[_.entity_id]:[]),this._triggerEntityLogic=_.entity_logic||"any",this._triggerAttribute=_.attribute||"",this._triggerType=_.type||"threshold",this._triggerAbove=_.trigger_above?.toString()||"",this._triggerBelow=_.trigger_below?.toString()||"",this._triggerEquals=_.trigger_equals?.toString()||"",this._triggerNotEquals=_.trigger_not_equals?.toString()||"",this._triggerForMinutes=_.trigger_for_minutes?.toString()||"0",this._triggerCombinator=_.trigger_combinator==="all"?"all":"any",this._triggerTargetValue=_.trigger_target_value?.toString()||"",this._triggerDeltaMode=_.trigger_delta_mode||!1,this._triggerBaselineValue=_.trigger_baseline_value?.toString()||"",this._liveBaselineValue=t.trigger_baseline_value??null,this._autoCompleteOnRecovery=_.auto_complete_on_recovery||!1,this._triggerFromState=_.trigger_from_state||"",this._triggerToState=_.trigger_to_state||"",this._triggerTargetChanges=_.trigger_target_changes?.toString()||"",this._triggerRuntimeHours=_.trigger_runtime_hours?.toString()||"",this._triggerRuntimeMaxSession=_.trigger_runtime_max_session_seconds?.toString()||"",this._triggerOnStates=(_.trigger_on_states||[]).join(", "),_.type==="compound"?(this._compoundLogic=_.compound_logic==="OR"?"OR":"AND",this._compoundConditions=(_.conditions||[]).map(tr)):(this._compoundLogic="AND",this._compoundConditions=[])}else this._resetTriggerFields();this._triggerEntityId&&this._fetchEntityAttributes(this._triggerEntityId),await Promise.all([this._loadUsers(),this._loadTags(),this._loadParts(),this._loadForeignPools()]),this._open=!0}_resetFields(){this._name="",this._type="custom",this._scheduleType="time_based",this._intervalDays="30",this._intervalUnit="days",this._dueDate="",this._warningDays=String(this.defaultWarningDays),this._earliestCompletionDays="",this._intervalAnchor="completion",this._weekdays=[],this._nth="1",this._nthWeekday="5",this._domDay="1",this._domLastDay=!1,this._domBusiness=!1,this._calOffset="0",this._seasonMonths=[],this._endsMode="never",this._endsCount="",this._endsUntil="",this._notes="",this._documentationUrl="",this._customIcon="",this._priority="normal",this._labels="",this._enabled=!0,this._lastPerformed="",this._nfcTagId="",this._requireTagScan=!1,this._allowSkip=!0,this._readingUnit="",this._consumesParts={},this._responsibleUserId=null,this._assigneePool=[],this._rotationStrategy="",this._checklistText="",this._phaseDefs=[],this._phaseSeq=[],this._requiredCompletion=[],this._scheduleTime="",this._environmentalEntity="",this._environmentalAttribute="",this._environmentalInitial="",this._environmentalAttributeInitial="",this._adaptiveEnabled=!1,this._adaptiveAlpha=J.alpha,this._adaptiveMin=J.min,this._adaptiveMax=J.max,this._adaptiveSeasonal=!0,this._adaptivePrediction=!0,this._adaptiveInitial=this._adaptiveSnapshot(),this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="",this._actionTesting=!1,this._actionTestResult="",this._qcNotes="",this._qcCost="",this._qcDuration="",this._qcFeedback="",this._resetTriggerFields()}_resetTriggerFields(){this._triggerEntityId="",this._triggerEntityIds=[],this._triggerEntityLogic="any",this._triggerAttribute="",this._suggestedAttributes=[],this._availableAttributes=[],this._entityDomain="",this._triggerType="threshold",th Line truncated
<details class="ca-section"> <details class="ca-section">
<summary>${r("on_complete_action_title",e)}</summary> <summary>${r("on_complete_action_title",e)}</summary>
<p class="field-help">${r("on_complete_action_desc",e)}</p> <p class="field-help">${r("on_complete_action_desc",e)}</p>
@@ -1866,9 +1895,9 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
</select> </select>
</div> </div>
`:h} `:h}
`}async _save(){if(!this._loading&&this._name.trim()){if(this._adaptiveSnapshot()!==this._adaptiveInitial){let e=parseInt(this._adaptiveMin,10),t=parseInt(this._adaptiveMax,10);if(!isNaN(e)&&!isNaN(t)&&e>t){this._error=`${r("adaptive_min_interval",this._lang)} > ${r("adaptive_max_interval",this._lang)}`;return}}this._loading=!0,this._error="";try{let e={type:this._taskId?"maintenance_supporter/task/update":"maintenance_supporter/task/create",entry_id:this._entryId,name:this._name,task_type:this._type,schedule_type:this._scheduleType,warning_days:Number.isNaN(parseInt(this._warningDays,10))?this.defaultWarningDays:Math.max(0,parseInt(this._warningDays,10))},t=this._earliestCompletionDays.trim();e.earliest_completion_days=t===""?null:Math.max(0,parseInt(t,10)||0),this._taskId&&(e.task_id=this._taskId),this._scheduleType==="one_time"?(e.due_date=this._dueDate||null,e.interval_days=null):Tt.includes(this._scheduleType)?(e.schedule={...this._buildSchedule(),...this._recurrenceExtras()},e.interval_days=null,this._taskId&&(e.due_date=null)):(this._taskId&&(e.due_date=null),this._scheduleType!=="manual"&&this._intervalDays?(e.interval_days=parseInt(this._intervalDays,10),e.interval_unit=this._intervalUnit,e.interval_anchor=this._intervalAnchor,this._scheduleType==="time_based"&&(e.schedule={kind:"interval",...this._recurrenceExtras()})):this._taskId&&(e.interval_days=null,e.interval_anchor="completion")),e.notes=this._notes||null,e.documentation_url=this._documentationUrl||null,e.custom_icon=this._customIcon||null,e.priority=this._priority,e.labels=this._labels.split(",").map(d=>d.trim()).filter(Boolean),e.enabled=this._enabled,e.last_performed=this._lastPerformed||null,e.nfc_tag_id=this._nfcTagId||null,e.require_tag_scan=this._requireTagScan,e.reading_unit=this._readingUnit.trim()||null;{let d={};for(let _ of this._phaseDefs){if(!_.name.trim())continue;let f={..._.carry,name:_.name.trim()},b=_.checklistText.split(` `}async _save(){if(!this._loading&&this._name.trim()){if(this._adaptiveSnapshot()!==this._adaptiveInitial){let e=parseInt(this._adaptiveMin,10),t=parseInt(this._adaptiveMax,10);if(!isNaN(e)&&!isNaN(t)&&e>t){this._error=`${r("adaptive_min_interval",this._lang)} > ${r("adaptive_max_interval",this._lang)}`;return}}this._loading=!0,this._error="";try{let e={type:this._taskId?"maintenance_supporter/task/update":"maintenance_supporter/task/create",entry_id:this._entryId,name:this._name,task_type:this._type,schedule_type:this._scheduleType,warning_days:Number.isNaN(parseInt(this._warningDays,10))?this.defaultWarningDays:Math.max(0,parseInt(this._warningDays,10))},t=this._earliestCompletionDays.trim();e.earliest_completion_days=t===""?null:Math.max(0,parseInt(t,10)||0),this._taskId&&(e.task_id=this._taskId),this._scheduleType==="one_time"?(e.due_date=this._dueDate||null,e.interval_days=null):At.includes(this._scheduleType)?(e.schedule={...this._buildSchedule(),...this._recurrenceExtras()},e.interval_days=null,this._taskId&&(e.due_date=null)):(this._taskId&&(e.due_date=null),this._scheduleType!=="manual"&&this._intervalDays?(e.interval_days=parseInt(this._intervalDays,10),e.interval_unit=this._intervalUnit,e.interval_anchor=this._intervalAnchor,this._scheduleType==="time_based"&&(e.schedule={kind:"interval",...this._recurrenceExtras()})):this._taskId&&(e.interval_days=null,e.interval_anchor="completion")),e.notes=this._notes||null,e.documentation_url=this._documentationUrl||null,e.custom_icon=this._customIcon||null,e.priority=this._priority,e.labels=this._labels.split(",").map(d=>d.trim()).filter(Boolean),e.enabled=this._enabled,e.last_performed=this._lastPerformed||null,e.nfc_tag_id=this._nfcTagId||null,e.require_tag_scan=this._requireTagScan,e.allow_skip=this._allowSkip,e.reading_unit=this._readingUnit.trim()||null;{let d={};for(let _ of this._phaseDefs){if(!_.name.trim())continue;let f={..._.carry,name:_.name.trim()},b=_.checklistText.split(`
`).map(y=>y.trim()).filter(Boolean);b.length&&(f.checklist=b);let v=[];if(_.partId){let y=parseFloat(_.partQty);v.push({part_id:_.partId,quantity:Number.isFinite(y)&&y>0?y:1})}for(let y of _.extraParts)v.push(y.entry_id?{part_id:y.part_id,quantity:y.quantity,entry_id:y.entry_id}:{part_id:y.part_id,quantity:y.quantity});v.length&&(f.consumes_parts=v),_.reqOverride&&(f.required_completion_fields=[..._.reqFields]),d[_.id]=f}let p=this._phaseSeq.filter(_=>_ in d);e.phases=Object.keys(d).length&&p.length?d:null,e.phase_sequence=e.phases?p:null}if((this.parts.length||this._foreignOwners.length)&&(e.consumes_parts=Object.values(this._consumesParts).map(d=>d.entry_id?{part_id:d.part_id,quantity:d.quantity,entry_id:d.entry_id}:{part_id:d.part_id,quantity:d.quantity})),e.responsible_user_id=this._responsibleUserId,e.assignee_pool=this._assigneePool,e.required_completion_fields=this._requiredCompletion,e.rotation_strategy=this._assigneePool.length>=2&&this._rotationStrategy?this._rotationStrategy:null,this._scheduleType==="sensor_based"&&this._triggerType==="compound"){let d=this._compoundConditions.map(ir).filter(p=>p!==null);if(d.length>0){let p={type:"compound",compound_logic:this._compoundLogic,conditions:d};this._autoCompleteOnRecovery&&(p.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(p.trigger_combinator="all"),e.trigger_config=p}else this._taskId&&(e.trigger_config=null)}else if(this._scheduleType==="sensor_based"&&this._triggerEntityId){let d=this._triggerEntityIds.length>0?this._triggerEntityIds:[this._triggerEntityId],p={entity_id:d[0],entity_ids:d,type:this._triggerType};if(this._triggerAttribute&&(p.attribute=this._triggerAttribute),this._autoCompleteOnRecovery&&(p.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(p.trigger_combinator="all"),d.length>1&&(p.entity_logic=this._triggerEntityLogic),this._triggerType==="threshold"){if(this._triggerAbove){let _=parseFloat(this._triggerAbove);isNaN(_)||(p.trigger_above=_)}if(this._triggerBelow){let _=parseFloat(this._triggerBelow);isNaN(_)||(p.trigger_below=_)}if(this._triggerEquals){let _=parseFloat(this._triggerEquals);isNaN(_)||(p.trigger_equals=_)}if(this._triggerNotEquals){let _=parseFloat(this._triggerNotEquals);isNaN(_)||(p.trigger_not_equals=_)}if(this._triggerForMinutes){let _=parseInt(this._triggerForMinutes,10);isNaN(_)||(p.trigger_for_minutes=_)}}else if(this._triggerType==="counter"){if(this._triggerTargetValue){let _=parseFloat(this._triggerTargetValue);isNaN(_)||(p.trigger_target_value=_)}if(p.trigger_delta_mode=this._triggerDeltaMode,this._triggerDeltaMode&&this._triggerBaselineValue){let _=parseFloat(this._triggerBaselineValue);!isNaN(_)&&_>=0&&(p.trigger_baseline_value=_)}}else if(this._triggerType==="state_change"){if(this._triggerFromState&&(p.trigger_from_state=this._triggerFromState),this._triggerToState&&(p.trigger_to_state=this._triggerToState),this._triggerTargetChanges){let _=parseInt(this._triggerTargetChanges,10);isNaN(_)||(p.trigger_target_changes=_)}if(this._triggerForMinutes){let _=parseInt(this._triggerForMinutes,10);isNaN(_)||(p.trigger_for_minutes=_)}}else if(this._triggerType==="runtime"){if(this._triggerRuntimeHours){let f=parseFloat(this._triggerRuntimeHours);isNaN(f)||(p.trigger_runtime_hours=f)}let _=this._triggerOnStates.split(",").map(f=>f.trim()).filter(Boolean);_.length>0&&(p.trigger_on_states=_)}e.trigger_config=p}else this._taskId&&(e.trigger_config=null);if(this.scheduleTimeEnabled&&this._scheduleType==="time_based"){let d=this._scheduleTime.trim();e.schedule_time=/^([01]\d|2[0-3]):[0-5]\d$/.test(d)?d:null}if(this.checklistsEnabled){let d=this._checklistText.split(` `).map(y=>y.trim()).filter(Boolean);b.length&&(f.checklist=b);let v=[];if(_.partId){let y=parseFloat(_.partQty);v.push({part_id:_.partId,quantity:Number.isFinite(y)&&y>0?y:1})}for(let y of _.extraParts)v.push(y.entry_id?{part_id:y.part_id,quantity:y.quantity,entry_id:y.entry_id}:{part_id:y.part_id,quantity:y.quantity});v.length&&(f.consumes_parts=v),_.reqOverride&&(f.required_completion_fields=[..._.reqFields]),d[_.id]=f}let p=this._phaseSeq.filter(_=>_ in d);e.phases=Object.keys(d).length&&p.length?d:null,e.phase_sequence=e.phases?p:null}if((this.parts.length||this._foreignOwners.length)&&(e.consumes_parts=Object.values(this._consumesParts).map(d=>d.entry_id?{part_id:d.part_id,quantity:d.quantity,entry_id:d.entry_id}:{part_id:d.part_id,quantity:d.quantity})),e.responsible_user_id=this._responsibleUserId,e.assignee_pool=this._assigneePool,e.required_completion_fields=this._requiredCompletion,e.rotation_strategy=this._assigneePool.length>=2&&this._rotationStrategy?this._rotationStrategy:null,this._scheduleType==="sensor_based"&&this._triggerType==="compound"){let d=this._compoundConditions.map(ir).filter(p=>p!==null);if(d.length>0){let p={type:"compound",compound_logic:this._compoundLogic,conditions:d};this._autoCompleteOnRecovery&&(p.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(p.trigger_combinator="all"),e.trigger_config=p}else this._taskId&&(e.trigger_config=null)}else if(this._scheduleType==="sensor_based"&&this._triggerEntityId){let d=this._triggerEntityIds.length>0?this._triggerEntityIds:[this._triggerEntityId],p={entity_id:d[0],entity_ids:d,type:this._triggerType};if(this._triggerAttribute&&(p.attribute=this._triggerAttribute),this._autoCompleteOnRecovery&&(p.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(p.trigger_combinator="all"),d.length>1&&(p.entity_logic=this._triggerEntityLogic),this._triggerType==="threshold"){if(this._triggerAbove){let _=parseFloat(this._triggerAbove);isNaN(_)||(p.trigger_above=_)}if(this._triggerBelow){let _=parseFloat(this._triggerBelow);isNaN(_)||(p.trigger_below=_)}if(this._triggerEquals){let _=parseFloat(this._triggerEquals);isNaN(_)||(p.trigger_equals=_)}if(this._triggerNotEquals){let _=parseFloat(this._triggerNotEquals);isNaN(_)||(p.trigger_not_equals=_)}if(this._triggerForMinutes){let _=parseInt(this._triggerForMinutes,10);isNaN(_)||(p.trigger_for_minutes=_)}}else if(this._triggerType==="counter"){if(this._triggerTargetValue){let _=parseFloat(this._triggerTargetValue);isNaN(_)||(p.trigger_target_value=_)}if(p.trigger_delta_mode=this._triggerDeltaMode,this._triggerDeltaMode&&this._triggerBaselineValue){let _=parseFloat(this._triggerBaselineValue);!isNaN(_)&&_>=0&&(p.trigger_baseline_value=_)}}else if(this._triggerType==="state_change"){if(this._triggerFromState&&(p.trigger_from_state=this._triggerFromState),this._triggerToState&&(p.trigger_to_state=this._triggerToState),this._triggerTargetChanges){let _=parseInt(this._triggerTargetChanges,10);isNaN(_)||(p.trigger_target_changes=_)}if(this._triggerForMinutes){let _=parseInt(this._triggerForMinutes,10);isNaN(_)||(p.trigger_for_minutes=_)}}else if(this._triggerType==="runtime"){if(this._triggerRuntimeHours){let f=parseFloat(this._triggerRuntimeHours);isNaN(f)||(p.trigger_runtime_hours=f)}if(this._triggerRuntimeMaxSession){let f=parseInt(this._triggerRuntimeMaxSession,10);!isNaN(f)&&f>0&&(p.trigger_runtime_max_session_seconds=f)}let _=this._triggerOnStates.split(",").map(f=>f.trim()).filter(Boolean);_.length>0&&(p.trigger_on_states=_)}e.trigger_config=p}else this._taskId&&(e.trigger_config=null);if(this.scheduleTimeEnabled&&this._scheduleType==="time_based"){let d=this._scheduleTime.trim();e.schedule_time=/^([01]\d|2[0-3]):[0-5]\d$/.test(d)?d:null}if(this.checklistsEnabled){let d=this._checklistText.split(`
`).map(p=>p.trim()).filter(Boolean).slice(0,100);e.checklist=d.length?d:null}if(this.completionActionsEnabled){let d=this._actionService.trim();if(d&&/^[a-z][a-z0-9_]*\.[a-z0-9_]+$/.test(d)){let b={service:d},v=this._actionTargetEntity.trim();v&&(b.target={entity_id:v});let y=this._buildActionData();Object.keys(y).length>0&&(b.data=y),e.on_complete_action=b}else e.on_complete_action=null;let p={};this._qcNotes.trim()&&(p.notes=this._qcNotes.trim());let _=parseFloat(this._qcCost);!isNaN(_)&&_>=0&&(p.cost=_);let f=parseInt(this._qcDuration,10);!isNaN(f)&&f>=0&&(p.duration=f),this._qcFeedback&&(p.feedback=this._qcFeedback),e.quick_complete_defaults=Object.keys(p).length?p:null}let i=await this.hass.connection.sendMessagePromise(e),n=this._taskId||i?.task_id,l=this._environmentalEntity!==this._environmentalInitial||this._environmentalAttribute!==this._environmentalAttributeInitial;if(n&&this._scheduleType==="sensor_based"&&l)try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_environmental_entity",entry_id:this._entryId,task_id:n,environmental_entity:this._environmentalEntity||null,environmental_attribute:this._environmentalAttribute||null}),this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute}catch{}if(n&&this._adaptiveSnapshot()!==this._adaptiveInitial){let d=parseFloat(this._adaptiveAlpha),p=parseInt(this._adaptiveMin,10),_=parseInt(this._adaptiveMax,10);try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_adaptive",entry_id:this._entryId,task_id:n,enabled:this._adaptiveEnabled,...d>=.1&&d<=.9?{ewa_alpha:d}:{},...!isNaN(p)&&p>=1?{min_interval_days:p}:{},...!isNaN(_)&&_>=1?{max_interval_days:_}:{},seasonal_enabled:this._adaptiveSeasonal,sensor_prediction_enabled:this._adaptivePrediction}),this._adaptiveInitial=this._adaptiveSnapshot()}catch{}}this._open=!1,this.dispatchEvent(new CustomEvent("task-saved"))}catch(e){this._error=T(e,this._lang,r("save_error",this._lang))}finally{this._loading=!1}}}_close(){this._open=!1,this._pickerProbeTimer!==void 0&&(clearTimeout(this._pickerProbeTimer),this._pickerProbeTimer=void 0),this._pickerProbeStrikes=0}_renderTriggerFields(){if(this._scheduleType!=="sensor_based")return h;let e=this._lang,t=this._triggerType==="compound";return o` `).map(p=>p.trim()).filter(Boolean).slice(0,100);e.checklist=d.length?d:null}if(this.completionActionsEnabled){let d=this._actionService.trim();if(d&&/^[a-z][a-z0-9_]*\.[a-z0-9_]+$/.test(d)){let b={service:d},v=this._actionTargetEntity.trim();v&&(b.target={entity_id:v});let y=this._buildActionData();Object.keys(y).length>0&&(b.data=y),e.on_complete_action=b}else e.on_complete_action=null;let p={};this._qcNotes.trim()&&(p.notes=this._qcNotes.trim());let _=parseFloat(this._qcCost);!isNaN(_)&&_>=0&&(p.cost=_);let f=parseInt(this._qcDuration,10);!isNaN(f)&&f>=0&&(p.duration=f),this._qcFeedback&&(p.feedback=this._qcFeedback),e.quick_complete_defaults=Object.keys(p).length?p:null}let i=await this.hass.connection.sendMessagePromise(e),n=this._taskId||i?.task_id,l=this._environmentalEntity!==this._environmentalInitial||this._environmentalAttribute!==this._environmentalAttributeInitial;if(n&&this._scheduleType==="sensor_based"&&l)try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_environmental_entity",entry_id:this._entryId,task_id:n,environmental_entity:this._environmentalEntity||null,environmental_attribute:this._environmentalAttribute||null}),this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute}catch{}if(n&&this._adaptiveSnapshot()!==this._adaptiveInitial){let d=parseFloat(this._adaptiveAlpha),p=parseInt(this._adaptiveMin,10),_=parseInt(this._adaptiveMax,10);try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_adaptive",entry_id:this._entryId,task_id:n,enabled:this._adaptiveEnabled,...d>=.1&&d<=.9?{ewa_alpha:d}:{},...!isNaN(p)&&p>=1?{min_interval_days:p}:{},...!isNaN(_)&&_>=1?{max_interval_days:_}:{},seasonal_enabled:this._adaptiveSeasonal,sensor_prediction_enabled:this._adaptivePrediction}),this._adaptiveInitial=this._adaptiveSnapshot()}catch{}}this._open=!1,this.dispatchEvent(new CustomEvent("task-saved"))}catch(e){this._error=A(e,this._lang,r("save_error",this._lang))}finally{this._loading=!1}}}_close(){this._open=!1,this._pickerProbeTimer!==void 0&&(clearTimeout(this._pickerProbeTimer),this._pickerProbeTimer=void 0),this._pickerProbeStrikes=0}_renderTriggerFields(){if(this._scheduleType!=="sensor_based")return h;let e=this._lang,t=this._triggerType==="compound";return o`
<h3>${r("trigger_configuration",e)}</h3> <h3>${r("trigger_configuration",e)}</h3>
<div class="select-row"> <div class="select-row">
<label>${r("trigger_type",e)}</label> <label>${r("trigger_type",e)}</label>
@@ -1890,7 +1919,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
<ha-form <ha-form
class="entity-picker-form" class="entity-picker-form"
.hass=${this.hass} .hass=${this.hass}
.schema=${[{name:"trigger_entities",selector:{entity:{multiple:!0,domain:At}}}]} .schema=${[{name:"trigger_entities",selector:{entity:{multiple:!0,domain:Tt}}}]}
.data=${{trigger_entities:this._triggerEntityIds.length>0?this._triggerEntityIds:this._triggerEntityId?[this._triggerEntityId]:[]}} .data=${{trigger_entities:this._triggerEntityIds.length>0?this._triggerEntityIds:this._triggerEntityId?[this._triggerEntityId]:[]}}
.computeLabel=${()=>r("entity_id",e)} .computeLabel=${()=>r("entity_id",e)}
@value-changed=${i=>{let n=(i.detail.value.trigger_entities||[]).filter(Boolean);this._triggerEntityId=n[0]||"",this._triggerEntityIds=n,n[0]?this._fetchEntityAttributes(n[0]):this._fetchEntityAttributes("")}} @value-changed=${i=>{let n=(i.detail.value.trigger_entities||[]).filter(Boolean);this._triggerEntityId=n[0]||"",this._triggerEntityIds=n,n[0]?this._fetchEntityAttributes(n[0]):this._fetchEntityAttributes("")}}
@@ -1975,7 +2004,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
<ha-form <ha-form
class="entity-picker-form" class="entity-picker-form"
.hass=${this.hass} .hass=${this.hass}
.schema=${[{name:"condition_entities",selector:{entity:{multiple:!0,domain:At}}}]} .schema=${[{name:"condition_entities",selector:{entity:{multiple:!0,domain:Tt}}}]}
.data=${{condition_entities:e.entityIds.split(",").map(l=>l.trim()).filter(Boolean)}} .data=${{condition_entities:e.entityIds.split(",").map(l=>l.trim()).filter(Boolean)}}
.computeLabel=${()=>r("entity_id",i)} .computeLabel=${()=>r("entity_id",i)}
@value-changed=${l=>{let d=(l.detail.value.condition_entities||[]).filter(Boolean);this._patchCondition(t,{entityIds:d.join(", ")})}} @value-changed=${l=>{let d=(l.detail.value.condition_entities||[]).filter(Boolean);this._patchCondition(t,{entityIds:d.join(", ")})}}
@@ -2131,12 +2160,12 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
> >
${["days","weeks","months","years"].map(t=>o`<option value=${t} ?selected=${t===this._intervalUnit}>${r("unit_"+t,e)}</option>`)} ${["days","weeks","months","years"].map(t=>o`<option value=${t} ?selected=${t===this._intervalUnit}>${r("unit_"+t,e)}</option>`)}
</select> </select>
</div>`}_toggleWeekday(e){this._weekdays=this._weekdays.includes(e)?this._weekdays.filter(t=>t!==e):[...this._weekdays,e]}_previewScheduleDict(){if(this._scheduleType==="one_time")return this._dueDate?{kind:"one_time",due_date:this._dueDate}:null;if(Tt.includes(this._scheduleType))return{...this._buildSchedule(),...this._recurrenceExtras()};let e=parseInt(this._intervalDays,10);return this._scheduleType==="manual"||!e||e<=0?null:{kind:"interval",every:e,unit:this._intervalUnit,anchor:this._intervalAnchor,...this._recurrenceExtras()}}updated(e){super.updated?.(e),this._scheduleEntityPickerProbe();for(let t of e.keys())if(g._PREVIEW_RELEVANT.has(String(t))){this._schedulePreviewRefresh();return}}_scheduleEntityPickerProbe(){this._entityPickerFallback||this._pickerProbeTimer!==void 0||!this._open||this._scheduleType!=="sensor_based"||(this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),1500))}_probeEntityPickers(){if(this._pickerProbeTimer=void 0,this._entityPickerFallback||!this._open)return;let e=this.shadowRoot?.querySelector("ha-form.entity-picker-form"),t=(this.shadowRoot?.querySelector(".content")?.offsetHeight??0)>0;if(!e||!t){this._pickerProbeStrikes=0;return}let i=(p,_,f=0)=>{if(!(!p||f>10)){(p.tagName?.toLowerCase()??"")==="ha-entity-picker"&&_.push(p);for(let b of[p.shadowRoot,p])if(b)for(let v of Array.from(b.children??[]))i(v,_,f+1)}},n=[...this.shadowRoot?.querySelectorAll("ha-form.entity-picker-form")??[]],l=[];for(let p of n)i(p,l);let d=l.length===0||l.some(p=>p.offsetHeight===0);if(e.offsetHeight===0||d){if(this._pickerProbeStrikes+=1,this._pickerProbeStrikes>=2){this._entityPickerFallback=!0;return}this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),700)}else this._pickerProbeStrikes=0}_schedulePreviewRefresh(){this._previewTimer&&clearTimeout(this._previewTimer),this._previewTimer=setTimeout(()=>{this._fetchSchedulePreview()},300)}async _fetchSchedulePreview(){let e=this._open?this._previewScheduleDict():null;if(!e){this._schedulePreview=[],this._schedulePreviewEnded=!1;return}let t=++this._previewSeq;try{let i=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/schedule/preview",schedule:e,...this._lastPerformed?{last_performed:this._lastPerformed}:{}});if(t!==this._previewSeq)return;this._schedulePreview=i.occurrences||[],this._schedulePreviewEnded=!!i.series_ended}catch{}}_renderSchedulePreview(){if(this._schedulePreview.length===0)return h;let e=this._lang,t=this.scheduleTimeEnabled&&this._scheduleTime?` ${this._scheduleTime}`:"",i=this._schedulePreview.map((l,d)=>{let p=new Date(`${l}T12:00:00`).getDay();return`${Ie(p===0?6:p-1,e,"short")} ${Q(l,e)}${d===0?t:""}`}).join(" \xB7 "),n=this._scheduleType==="time_based"&&this._intervalAnchor==="completion"?o`<div class="field-help">${r("schedule_preview_ontime",e)}</div>`:h;return o` </div>`}_toggleWeekday(e){this._weekdays=this._weekdays.includes(e)?this._weekdays.filter(t=>t!==e):[...this._weekdays,e]}_previewScheduleDict(){if(this._scheduleType==="one_time")return this._dueDate?{kind:"one_time",due_date:this._dueDate}:null;if(At.includes(this._scheduleType))return{...this._buildSchedule(),...this._recurrenceExtras()};let e=parseInt(this._intervalDays,10);return this._scheduleType==="manual"||!e||e<=0?null:{kind:"interval",every:e,unit:this._intervalUnit,anchor:this._intervalAnchor,...this._recurrenceExtras()}}updated(e){super.updated?.(e),this._scheduleEntityPickerProbe();for(let t of e.keys())if(g._PREVIEW_RELEVANT.has(String(t))){this._schedulePreviewRefresh();return}}_scheduleEntityPickerProbe(){this._entityPickerFallback||this._pickerProbeTimer!==void 0||!this._open||this._scheduleType!=="sensor_based"||(this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),1500))}_probeEntityPickers(){if(this._pickerProbeTimer=void 0,this._entityPickerFallback||!this._open)return;let e=this.shadowRoot?.querySelector("ha-form.entity-picker-form"),t=(this.shadowRoot?.querySelector(".content")?.offsetHeight??0)>0;if(!e||!t){this._pickerProbeStrikes=0;return}let i=(p,_,f=0)=>{if(!(!p||f>10)){(p.tagName?.toLowerCase()??"")==="ha-entity-picker"&&_.push(p);for(let b of[p.shadowRoot,p])if(b)for(let v of Array.from(b.children??[]))i(v,_,f+1)}},n=[...this.shadowRoot?.querySelectorAll("ha-form.entity-picker-form")??[]],l=[];for(let p of n)i(p,l);let d=l.length===0||l.some(p=>p.offsetHeight===0);if(e.offsetHeight===0||d){if(this._pickerProbeStrikes+=1,this._pickerProbeStrikes>=2){this._entityPickerFallback=!0;return}this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),700)}else this._pickerProbeStrikes=0}_schedulePreviewRefresh(){this._previewTimer&&clearTimeout(this._previewTimer),this._previewTimer=setTimeout(()=>{this._fetchSchedulePreview()},300)}async _fetchSchedulePreview(){let e=this._open?this._previewScheduleDict():null;if(!e){this._schedulePreview=[],this._schedulePreviewEnded=!1;return}let t=++this._previewSeq;try{let i=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/schedule/preview",schedule:e,...this._lastPerformed?{last_performed:this._lastPerformed}:{}});if(t!==this._previewSeq)return;this._schedulePreview=i.occurrences||[],this._schedulePreviewEnded=!!i.series_ended}catch{}}_renderSchedulePreview(){if(this._schedulePreview.length===0)return h;let e=this._lang,t=this.scheduleTimeEnabled&&this._scheduleTime?` ${this._scheduleTime}`:"",i=this._schedulePreview.map((l,d)=>{let p=new Date(`${l}T12:00:00`).getDay();return`${Ie(p===0?6:p-1,e,"short")} ${Q(l,e)}${d===0?t:""}`}).join(" \xB7 "),n=this._scheduleType==="time_based"&&this._intervalAnchor==="completion"?o`<div class="field-help">${r("schedule_preview_ontime",e)}</div>`:h;return o`
<div class="trigger-live-hint schedule-preview"> <div class="trigger-live-hint schedule-preview">
${r("schedule_preview_title",e)}: ${i}${this._schedulePreviewEnded?o` <span class="field-help">${r("schedule_preview_ends",e)}</span>`:h} ${r("schedule_preview_title",e)}: ${i}${this._schedulePreviewEnded?o` <span class="field-help">${r("schedule_preview_ends",e)}</span>`:h}
${n} ${n}
</div> </div>
`}_buildSchedule(){let e=i=>{let n=parseInt(this._calOffset,10)||0;return n&&(i.offset=Math.max(-15,Math.min(n,15))),i};if(this._scheduleType==="weekdays")return e({kind:"weekdays",weekdays:[...this._weekdays].sort((i,n)=>i-n)});if(this._scheduleType==="nth_weekday")return e({kind:"nth_weekday",nth:parseInt(this._nth,10),weekday:parseInt(this._nthWeekday,10)});let t={kind:"day_of_month",day:this._domLastDay?-1:parseInt(this._domDay,10)||1};return this._domBusiness&&(t.business=!0),e(t)}_recurrenceExtras(){let e={};if(this._seasonMonths.length&&(e.season_months=[...this._seasonMonths].sort((t,i)=>t-i)),this._endsMode==="count"){let t=parseInt(this._endsCount,10);t>=1&&(e.ends={count:t})}else this._endsMode==="until"&&this._endsUntil&&(e.ends={until:this._endsUntil});return e}_toggleSeasonMonth(e){this._seasonMonths=this._seasonMonths.includes(e)?this._seasonMonths.filter(t=>t!==e):[...this._seasonMonths,e]}_renderRecurrenceExtras(){let e=this._lang;if(!(this._scheduleType==="time_based"||Tt.includes(this._scheduleType)))return h;let i=rr(e);return o` `}_buildSchedule(){let e=i=>{let n=parseInt(this._calOffset,10)||0;return n&&(i.offset=Math.max(-15,Math.min(n,15))),i};if(this._scheduleType==="weekdays")return e({kind:"weekdays",weekdays:[...this._weekdays].sort((i,n)=>i-n)});if(this._scheduleType==="nth_weekday")return e({kind:"nth_weekday",nth:parseInt(this._nth,10),weekday:parseInt(this._nthWeekday,10)});let t={kind:"day_of_month",day:this._domLastDay?-1:parseInt(this._domDay,10)||1};return this._domBusiness&&(t.business=!0),e(t)}_recurrenceExtras(){let e={};if(this._seasonMonths.length&&(e.season_months=[...this._seasonMonths].sort((t,i)=>t-i)),this._endsMode==="count"){let t=parseInt(this._endsCount,10);t>=1&&(e.ends={count:t})}else this._endsMode==="until"&&this._endsUntil&&(e.ends={until:this._endsUntil});return e}_toggleSeasonMonth(e){this._seasonMonths=this._seasonMonths.includes(e)?this._seasonMonths.filter(t=>t!==e):[...this._seasonMonths,e]}_renderRecurrenceExtras(){let e=this._lang;if(!(this._scheduleType==="time_based"||At.includes(this._scheduleType)))return h;let i=rr(e);return o`
<label class="field-label">${r("season_window_label",e)}</label> <label class="field-label">${r("season_window_label",e)}</label>
<div class="field-help">${r("season_window_hint",e)}</div> <div class="field-help">${r("season_window_hint",e)}</div>
<div class="weekday-chips season-chips"> <div class="weekday-chips season-chips">
@@ -2317,6 +2346,14 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
.value=${this._triggerRuntimeHours} .value=${this._triggerRuntimeHours}
@input=${t=>this._triggerRuntimeHours=t.target.value} @input=${t=>this._triggerRuntimeHours=t.target.value}
></ms-textfield> ></ms-textfield>
<ms-textfield
label="${r("runtime_max_session",e)}"
type="number"
step="1"
.value=${this._triggerRuntimeMaxSession}
@input=${t=>this._triggerRuntimeMaxSession=t.target.value}
></ms-textfield>
<div class="field-help">${r("runtime_max_session_help",e)}</div>
${this._renderOnStatesField({value:this._triggerOnStates,entityId:this._triggerEntityId,onInput:t=>this._triggerOnStates=t})} ${this._renderOnStatesField({value:this._triggerOnStates,entityId:this._triggerEntityId,onInput:t=>this._triggerOnStates=t})}
<div class="field-help">${r("runtime_on_states_help",e)}</div> <div class="field-help">${r("runtime_on_states_help",e)}</div>
`:h}render(){if(!this._open)return o``;let e=this._lang,t=this._taskId?r("edit_task",e):r("new_task",e);return o` `:h}render(){if(!this._open)return o``;let e=this._lang,t=this._taskId?r("edit_task",e):r("new_task",e);return o`
@@ -2603,6 +2640,15 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
<span>${r("require_tag_scan",e)}</span> <span>${r("require_tag_scan",e)}</span>
</label> </label>
${this._requireTagScan?o`<div class="field-help">${r("require_tag_scan_help",e)}</div>`:h} ${this._requireTagScan?o`<div class="field-help">${r("require_tag_scan_help",e)}</div>`:h}
<label class="req-option">
<input
type="checkbox"
.checked=${!this._allowSkip}
@change=${i=>this._allowSkip=!i.target.checked}
/>
<span>${r("disallow_skip",e)}</span>
</label>
${this._allowSkip?h:o`<div class="field-help">${r("disallow_skip_help",e)}</div>`}
<label class="toggle-row"> <label class="toggle-row">
<input <input
type="checkbox" type="checkbox"
@@ -2623,7 +2669,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
</ha-button> </ha-button>
</div> </div>
</ha-dialog> </ha-dialog>
`}};g._PREVIEW_RELEVANT=new Set(["_open","_scheduleType","_intervalDays","_intervalUnit","_intervalAnchor","_dueDate","_weekdays","_nth","_nthWeekday","_domDay","_domLastDay","_domBusiness","_calOffset","_seasonMonths","_endsMode","_endsCount","_endsUntil","_lastPerformed"]),g.styles=A` `}};g._PREVIEW_RELEVANT=new Set(["_open","_scheduleType","_intervalDays","_intervalUnit","_intervalAnchor","_dueDate","_weekdays","_nth","_nthWeekday","_domDay","_domLastDay","_domBusiness","_calOffset","_seasonMonths","_endsMode","_endsCount","_endsUntil","_lastPerformed"]),g.styles=T`
.dialog-title { .dialog-title {
font-size: 18px; font-size: 18px;
font-weight: 500; font-weight: 500;
@@ -2999,7 +3045,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
} }
`,c([x({attribute:!1})],g.prototype,"hass",2),c([x({type:Boolean,attribute:"checklists-enabled"})],g.prototype,"checklistsEnabled",2),c([x({type:Boolean,attribute:"schedule-time-enabled"})],g.prototype,"scheduleTimeEnabled",2),c([x({type:Boolean,attribute:"completion-actions-enabled"})],g.prototype,"completionActionsEnabled",2),c([x({type:Number,attribute:"default-warning-days"})],g.prototype,"defaultWarningDays",2),c([u()],g.prototype,"parts",2),c([u()],g.prototype,"_foreignOwners",2),c([u()],g.prototype,"_open",2),c([u()],g.prototype,"_entityPickerFallback",2),c([u()],g.prototype,"_loading",2),c([u()],g.prototype,"_error",2),c([u()],g.prototype,"_entryId",2),c([u()],g.prototype,"_taskId",2),c([u()],g.prototype,"_objectChoices",2),c([u()],g.prototype,"_name",2),c([u()],g.prototype,"_type",2),c([u()],g.prototype,"_scheduleType",2),c([u()],g.prototype,"_intervalDays",2),c([u()],g.prototype,"_intervalUnit",2),c([u()],g.prototype,"_dueDate",2),c([u()],g.prototype,"_warningDays",2),c([u()],g.prototype,"_earliestCompletionDays",2),c([u()],g.prototype,"_intervalAnchor",2),c([u()],g.prototype,"_weekdays",2),c([u()],g.prototype,"_nth",2),c([u()],g.prototype,"_nthWeekday",2),c([u()],g.prototype,"_domDay",2),c([u()],g.prototype,"_domLastDay",2),c([u()],g.prototype,"_domBusiness",2),c([u()],g.prototype,"_calOffset",2),c([u()],g.prototype,"_seasonMonths",2),c([u()],g.prototype,"_endsMode",2),c([u()],g.prototype,"_endsCount",2),c([u()],g.prototype,"_endsUntil",2),c([u()],g.prototype,"_schedulePreview",2),c([u()],g.prototype,"_schedulePreviewEnded",2),c([u()],g.prototype,"_notes",2),c([u()],g.prototype,"_documentationUrl",2),c([u()],g.prototype,"_customIcon",2),c([u()],g.prototype,"_priority",2),c([u()],g.prototype,"_labels",2),c([u()],g.prototype,"_enabled",2),c([u()],g.prototype,"_triggerEntityId",2),c([u()],g.prototype,"_triggerEntityIds",2),c([u()],g.prototype,"_triggerEntityLogic",2),c([u()],g.prototype,"_triggerAttribute",2),c([u()],g.prototype,"_triggerType",2),c([u()],g.prototype,"_triggerAbove",2),c([u()],g.prototype,"_triggerBelow",2),c([u()],g.prototype,"_triggerEquals",2),c([u()],g.prototype,"_triggerNotEquals",2),c([u()],g.prototype,"_triggerForMinutes",2),c([u()],g.prototype,"_triggerCombinator",2),c([u()],g.prototype,"_triggerTargetValue",2),c([u()],g.prototype,"_triggerDeltaMode",2),c([u()],g.prototype,"_triggerBaselineValue",2),c([u()],g.prototype,"_liveBaselineValue",2),c([u()],g.prototype,"_autoCompleteOnRecovery",2),c([u()],g.prototype,"_triggerFromState",2),c([u()],g.prototype,"_triggerToState",2),c([u()],g.prototype,"_triggerTargetChanges",2),c([u()],g.prototype,"_triggerRuntimeHours",2),c([u()],g.prototype,"_triggerOnStates",2),c([u()],g.prototype,"_compoundLogic",2),c([u()],g.prototype,"_compoundConditions",2),c([u()],g.prototype,"_suggestedAttributes",2),c([u()],g.prototype,"_availableAttributes",2),c([u()],g.prototype,"_entityDomain",2),c([u()],g.prototype,"_lastPerformed",2),c([u()],g.prototype,"_nfcTagId",2),c([u()],g.prototype,"_requireTagScan",2),c([u()],g.prototype,"_readingUnit",2),c([u()],g.prototype,"_consumesParts",2),c([u()],g.prototype,"_partsLoadFailed",2),c([u()],g.prototype,"_availableTags",2),c([u()],g.prototype,"_responsibleUserId",2),c([u()],g.prototype,"_assigneePool",2),c([u()],g.prototype,"_rotationStrategy",2),c([u()],g.prototype,"_availableUsers",2),c([u()],g.prototype,"_checklistText",2),c([u()],g.prototype,"_phaseDefs",2),c([u()],g.prototype,"_phaseSeq",2),c([u()],g.prototype,"_requiredCompletion",2),c([u()],g.prototype,"_scheduleTime",2),c([u()],g.prototype,"_actionService",2),c([u()],g.prototype,"_actionTargetEntity",2),c([u()],g.prototype,"_actionData",2),c([u()],g.prototype,"_actionDataJsonFallback",2),c([u()],g.prototype,"_actionTesting",2),c([u()],g.prototype,"_actionTestResult",2),c([u()],g.prototype,"_actionTestError",2),c([u()],g.prototype,"_qcNotes",2),c([u()],g.prototype,"_qcCost",2),c([u()],g.prototype,"_qcDuration",2),c([u()],g.prototype,"_qcFeedback",2),c([u()],g.prototype,"_environmentalEntity",2),c([u()],g.prototype,"_environmentalAttribute",2),c([u()],g.prototype,"_adaptiveEnabled",2),c([u()],g.prototype,"_adaptiveAlpha",2),c([u()],g.prototype,"_adaptiveMin",2),c([u()],g.prototype,"_adaptiveMax",2),c([u()],g.prototype,"_adaptiveSeasonal",2),c([u()],g.prototype,"_adaptivePrediction",2),c([u()],g.prototype,"_conditionAttrOptions",2);Ct=g;customElements.get("maintenance-task-dialog")||customElements.define("maintenance-task-dialog",Ct)});var U,Oi=w(()=>{"use strict";R();D();q();se();U=class extends S{constructor(){super(...arguments);this._open=!1;this._saving=!1;this._error="";this._draft=null;this._originalSnapshot=null;this._partOptions=null;this._partQty={};this._partQtyOriginal=""}get _lang(){return j(this.hass)}openEdit(e){this._draft={...e},this._originalSnapshot={...e},this._error="",this._open=!0,this._partOptions=null,this._partQty={},this._partQtyOriginal="",this._loadPartOptions()}async _loadPartOptions(){let e=this._draft;if(e)try{let t=await Line truncated `,c([x({attribute:!1})],g.prototype,"hass",2),c([x({type:Boolean,attribute:"checklists-enabled"})],g.prototype,"checklistsEnabled",2),c([x({type:Boolean,attribute:"schedule-time-enabled"})],g.prototype,"scheduleTimeEnabled",2),c([x({type:Boolean,attribute:"completion-actions-enabled"})],g.prototype,"completionActionsEnabled",2),c([x({type:Number,attribute:"default-warning-days"})],g.prototype,"defaultWarningDays",2),c([u()],g.prototype,"parts",2),c([u()],g.prototype,"_foreignOwners",2),c([u()],g.prototype,"_open",2),c([u()],g.prototype,"_entityPickerFallback",2),c([u()],g.prototype,"_loading",2),c([u()],g.prototype,"_error",2),c([u()],g.prototype,"_entryId",2),c([u()],g.prototype,"_taskId",2),c([u()],g.prototype,"_objectChoices",2),c([u()],g.prototype,"_name",2),c([u()],g.prototype,"_type",2),c([u()],g.prototype,"_scheduleType",2),c([u()],g.prototype,"_intervalDays",2),c([u()],g.prototype,"_intervalUnit",2),c([u()],g.prototype,"_dueDate",2),c([u()],g.prototype,"_warningDays",2),c([u()],g.prototype,"_earliestCompletionDays",2),c([u()],g.prototype,"_intervalAnchor",2),c([u()],g.prototype,"_weekdays",2),c([u()],g.prototype,"_nth",2),c([u()],g.prototype,"_nthWeekday",2),c([u()],g.prototype,"_domDay",2),c([u()],g.prototype,"_domLastDay",2),c([u()],g.prototype,"_domBusiness",2),c([u()],g.prototype,"_calOffset",2),c([u()],g.prototype,"_seasonMonths",2),c([u()],g.prototype,"_endsMode",2),c([u()],g.prototype,"_endsCount",2),c([u()],g.prototype,"_endsUntil",2),c([u()],g.prototype,"_schedulePreview",2),c([u()],g.prototype,"_schedulePreviewEnded",2),c([u()],g.prototype,"_notes",2),c([u()],g.prototype,"_documentationUrl",2),c([u()],g.prototype,"_customIcon",2),c([u()],g.prototype,"_priority",2),c([u()],g.prototype,"_labels",2),c([u()],g.prototype,"_enabled",2),c([u()],g.prototype,"_triggerEntityId",2),c([u()],g.prototype,"_triggerEntityIds",2),c([u()],g.prototype,"_triggerEntityLogic",2),c([u()],g.prototype,"_triggerAttribute",2),c([u()],g.prototype,"_triggerType",2),c([u()],g.prototype,"_triggerAbove",2),c([u()],g.prototype,"_triggerBelow",2),c([u()],g.prototype,"_triggerEquals",2),c([u()],g.prototype,"_triggerNotEquals",2),c([u()],g.prototype,"_triggerForMinutes",2),c([u()],g.prototype,"_triggerCombinator",2),c([u()],g.prototype,"_triggerTargetValue",2),c([u()],g.prototype,"_triggerDeltaMode",2),c([u()],g.prototype,"_triggerBaselineValue",2),c([u()],g.prototype,"_liveBaselineValue",2),c([u()],g.prototype,"_autoCompleteOnRecovery",2),c([u()],g.prototype,"_triggerFromState",2),c([u()],g.prototype,"_triggerToState",2),c([u()],g.prototype,"_triggerTargetChanges",2),c([u()],g.prototype,"_triggerRuntimeHours",2),c([u()],g.prototype,"_triggerRuntimeMaxSession",2),c([u()],g.prototype,"_triggerOnStates",2),c([u()],g.prototype,"_compoundLogic",2),c([u()],g.prototype,"_compoundConditions",2),c([u()],g.prototype,"_suggestedAttributes",2),c([u()],g.prototype,"_availableAttributes",2),c([u()],g.prototype,"_entityDomain",2),c([u()],g.prototype,"_lastPerformed",2),c([u()],g.prototype,"_nfcTagId",2),c([u()],g.prototype,"_requireTagScan",2),c([u()],g.prototype,"_allowSkip",2),c([u()],g.prototype,"_readingUnit",2),c([u()],g.prototype,"_consumesParts",2),c([u()],g.prototype,"_partsLoadFailed",2),c([u()],g.prototype,"_availableTags",2),c([u()],g.prototype,"_responsibleUserId",2),c([u()],g.prototype,"_assigneePool",2),c([u()],g.prototype,"_rotationStrategy",2),c([u()],g.prototype,"_availableUsers",2),c([u()],g.prototype,"_checklistText",2),c([u()],g.prototype,"_phaseDefs",2),c([u()],g.prototype,"_phaseSeq",2),c([u()],g.prototype,"_requiredCompletion",2),c([u()],g.prototype,"_scheduleTime",2),c([u()],g.prototype,"_actionService",2),c([u()],g.prototype,"_actionTargetEntity",2),c([u()],g.prototype,"_actionData",2),c([u()],g.prototype,"_actionDataJsonFallback",2),c([u()],g.prototype,"_actionTesting",2),c([u()],g.prototype,"_actionTestResult",2),c([u()],g.prototype,"_actionTestError",2),c([u()],g.prototype,"_qcNotes",2),c([u()],g.prototype,"_qcCost",2),c([u()],g.prototype,"_qcDuration",2),c([u()],g.prototype,"_qcFeedback",2),c([u()],g.prototype,"_environmentalEntity",2),c([u()],g.prototype,"_environmentalAttribute",2),c([u()],g.prototype,"_adaptiveEnabled",2),c([u()],g.prototype,"_adaptiveAlpha",2),c([u()],g.prototype,"_adaptiveMin",2),c([u()],g.prototype,"_adaptiveMax",2),c([u()],g.prototype,"_adaptiveSeasonal",2),c([u()],g.prototype,"_adaptivePrediction",2),c([u()],g.prototype,"_conditionAttrOptions",2);Ct=g;customElements.get("maintenance-task-dialog")||customElements.define("maintenance-task-dialog",Ct)});var U,Oi=w(()=>{"use strict";R();D();q();se();U=class extends S{constructor(){super(...arguments);this._open=!1;this._saving=!1;this._error="";this._draft=null;this._originalSnapshot=null;this._partOptions=null;this._partQty={};this._partQtyOriginal=""}get _lang(){return j(this.hass)}openEdit(e){this._draft={...e},this._originalSnapshot={...e},this._error="",this._open=!0,this._partOptions=null,this._partQty={},this._partQtyOriginal="", Line truncated
<div class="backdrop" @click=${this.close}></div> <div class="backdrop" @click=${this.close}></div>
<div class="dialog" role="dialog" aria-modal="true"> <div class="dialog" role="dialog" aria-modal="true">
<h2>${r("history_edit_title",e)||"Edit history entry"}</h2> <h2>${r("history_edit_title",e)||"Edit history entry"}</h2>
@@ -3061,7 +3107,7 @@ Test pressure`,checklist_help:"One step per line. Max 100 items.",err_too_long:"
</button> </button>
</div> </div>
</div> </div>
`}};U.styles=A` `}};U.styles=T`
:host { display: contents; } :host { display: contents; }
.backdrop { .backdrop {
position: fixed; inset: 0; position: fixed; inset: 0;
@@ -3230,7 +3276,7 @@ ${p?`<div class="sub">${p}</div>`:""}
</ha-button> </ha-button>
</div> </div>
</ha-dialog> </ha-dialog>
`}};z.styles=A` `}};z.styles=T`
.dialog-title { .dialog-title {
font-size: 18px; font-size: 18px;
font-weight: 500; font-weight: 500;
@@ -3531,7 +3577,7 @@ ${p?`<div class="sub">${p}</div>`:""}
${Qi.map((m,$)=>o`<span class="seasonal-label ${$===i?"active-month":""}">${r(m,s)}</span>`)} ${Qi.map((m,$)=>o`<span class="seasonal-label ${$===i?"active-month":""}">${r(m,s)}</span>`)}
</div> </div>
</div> </div>
`}var Qi,Xi=w(()=>{"use strict";R();q();Qi=["month_jan","month_feb","month_mar","month_apr","month_may","month_jun","month_jul","month_aug","month_sep","month_oct","month_nov","month_dec"]});var L,es=w(()=>{"use strict";R();D();q();se();Ui();Je();Ye();Vi();Ki();Yi();Xi();L=class extends S{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._taskId=null;this._task=null;this._objectName="";this._busy=!1;this._error="";this._showSkip=!1;this._showReset=!1;this._showDetails=!1;this._showAdaptive=!1;this._skipReason="";this._resetDate="";this._features={adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1};this._toast="";this._featuresLoaded=!1;this._currencySymbol=""}get _lang(){return j(this.hass)}async openFor(e,t){this._entryId=e,this._taskId=t,this._error="",this._showSkip=!1,this._showReset=!1,this._showAdaptive=!1,this._skipReason="",this._resetDate=Fi(new Date),this._open=!0,await Promise.all([this._loadTask(),this._loadFeatures()])}async _loadFeatures(){if(!this._featuresLoaded)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/settings"});e?.features&&(this._features={...this._features,...e.features}),this._currencySymbol=e?.budget?.currency_symbol||"",this._featuresLoaded=!0}catch{}}close(){this._open=!1,this._task=null,this._error=""}async _loadTask(){if(!(!this._entryId||!this._taskId))try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._objectName=e.object?.name||"";let t=(e.tasks||[]).find(i=>i.id===this._taskId);this._task=t??null}catch(e){this._error=T(e,this._lang)}}async _runWs(e){this._busy=!0,this._error="";try{return await this.hass.connection.sendMessagePromise(e),this._busy=!1,!0}catch(t){return this._error=T(t,this._lang),this._busy=!1,!1}}_notifyChanged(e){this.dispatchEvent(new CustomEvent("task-action-fired",{detail:{entry_id:this._entryId,task_id:this._taskId,action:e},bubbles:!0,composed:!0}))}_onComplete(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(async({openCompleteDialog:e})=>{let t=this._task,i=[];try{i=(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects",compact:!0})).objects||[]}catch{}e(Re({entryId:this._entryId,taskId:this._taskId,taskName:t.name,task:t,objects:i,lang:this._lang,checklist:t.checklist||[],adaptiveEnabled:!!t.adaptive_config?.enabled,currencySymbol:this._currencySymbol}))&&(this._notifyChanged("complete"),this.close())})}async _onSkipConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/skip",entry_id:this._entryId,task_id:this._taskId,reason:this._skipReason.trim()||null})&&(this._notifyChanged("skip"),this.close())}async _onResetConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/reset",entry_id:this._entryId,task_id:this._taskId,date:this._resetDate||void 0})&&(this._notifyChanged("reset"),this.close())}_onEdit(){!this._entryId||!this._taskId||Promise.resolve().then(()=>(K(),Z)).then(({openEditTaskDialog:e})=>{e(this._entryId,this._taskId),this.close()})}_onQr(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(({openQrDialog:e})=>{e({entry_id:this._entryId,task_id:this._taskId,task_name:this._task.name,object_name:this._objectName}),this.close()})}async _onDelete(){if(!this._entryId||!this._taskId)return;let e=r("delete_task_confirm",this._lang)||`Delete "${this._task?.name}"?`;if(!window.confirm(e))return;await this._runWs({type:"maintenance_supporter/task/delete",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("delete"),this.close())}async _onArchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/archive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("archive"),this.close())}async _onUnarchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/unarchive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("unarchive"),this.close())}_onOpenInPanel(){if(!this._entryId||!this._taskId)return;let e=`/maintenance-supporter?entry_id=${encodeURIComponent(this._entryId)}&task_id=${encodeURIComponent(this._taskId)}`;history.pushState(null,"",e),window.dispatchEvent(new CustomEvent("location-changed")),this.close()}async _applySuggestion(){if(!this._entryId||!this._taskId||!this._task?.suggested_interval)return;await this._runWs({type:"maintenance_supporter/task/apply_suggestion",entry_id:this._entryId,task_id:this._taskId,interval:this._task.suggested_interval})&&(this._toast=r("suggestion_applied",this._lang)||"Applied",this._notifyChanged("apply_suggestion"),await this._loadTask(),setTimeout(()=>{this._toast=""},2500))}async _reanalyzeInterval(){if(!(!this._entryId||!this._taskId)){this._busy=!0,this._error="";tr Line truncated `}var Qi,Xi=w(()=>{"use strict";R();q();Qi=["month_jan","month_feb","month_mar","month_apr","month_may","month_jun","month_jul","month_aug","month_sep","month_oct","month_nov","month_dec"]});var L,es=w(()=>{"use strict";R();D();q();se();Ui();Je();Ye();Vi();Ki();Yi();Xi();L=class extends S{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._taskId=null;this._task=null;this._objectName="";this._busy=!1;this._error="";this._showSkip=!1;this._showReset=!1;this._showDetails=!1;this._showAdaptive=!1;this._skipReason="";this._resetDate="";this._features={adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1};this._toast="";this._featuresLoaded=!1;this._currencySymbol=""}get _lang(){return j(this.hass)}async openFor(e,t){this._entryId=e,this._taskId=t,this._error="",this._showSkip=!1,this._showReset=!1,this._showAdaptive=!1,this._skipReason="",this._resetDate=Fi(new Date),this._open=!0,await Promise.all([this._loadTask(),this._loadFeatures()])}async _loadFeatures(){if(!this._featuresLoaded)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/settings"});e?.features&&(this._features={...this._features,...e.features}),this._currencySymbol=e?.budget?.currency_symbol||"",this._featuresLoaded=!0}catch{}}close(){this._open=!1,this._task=null,this._error=""}async _loadTask(){if(!(!this._entryId||!this._taskId))try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._objectName=e.object?.name||"";let t=(e.tasks||[]).find(i=>i.id===this._taskId);this._task=t??null}catch(e){this._error=A(e,this._lang)}}async _runWs(e){this._busy=!0,this._error="";try{return await this.hass.connection.sendMessagePromise(e),this._busy=!1,!0}catch(t){return this._error=A(t,this._lang),this._busy=!1,!1}}_notifyChanged(e){this.dispatchEvent(new CustomEvent("task-action-fired",{detail:{entry_id:this._entryId,task_id:this._taskId,action:e},bubbles:!0,composed:!0}))}_onComplete(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(async({openCompleteDialog:e})=>{let t=this._task,i=[];try{i=(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects",compact:!0})).objects||[]}catch{}e(Re({entryId:this._entryId,taskId:this._taskId,taskName:t.name,task:t,objects:i,lang:this._lang,checklist:t.checklist||[],adaptiveEnabled:!!t.adaptive_config?.enabled,currencySymbol:this._currencySymbol}))&&(this._notifyChanged("complete"),this.close())})}async _onSkipConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/skip",entry_id:this._entryId,task_id:this._taskId,reason:this._skipReason.trim()||null})&&(this._notifyChanged("skip"),this.close())}async _onResetConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/reset",entry_id:this._entryId,task_id:this._taskId,date:this._resetDate||void 0})&&(this._notifyChanged("reset"),this.close())}_onEdit(){!this._entryId||!this._taskId||Promise.resolve().then(()=>(K(),Z)).then(({openEditTaskDialog:e})=>{e(this._entryId,this._taskId),this.close()})}_onQr(){!this._entryId||!this._taskId||!this._task||Promise.resolve().then(()=>(K(),Z)).then(({openQrDialog:e})=>{e({entry_id:this._entryId,task_id:this._taskId,task_name:this._task.name,object_name:this._objectName}),this.close()})}async _onDelete(){if(!this._entryId||!this._taskId)return;let e=r("delete_task_confirm",this._lang)||`Delete "${this._task?.name}"?`;if(!window.confirm(e))return;await this._runWs({type:"maintenance_supporter/task/delete",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("delete"),this.close())}async _onArchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/archive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("archive"),this.close())}async _onUnarchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/unarchive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("unarchive"),this.close())}_onOpenInPanel(){if(!this._entryId||!this._taskId)return;let e=`/maintenance-supporter?entry_id=${encodeURIComponent(this._entryId)}&task_id=${encodeURIComponent(this._taskId)}`;history.pushState(null,"",e),window.dispatchEvent(new CustomEvent("location-changed")),this.close()}async _applySuggestion(){if(!this._entryId||!this._taskId||!this._task?.suggested_interval)return;await this._runWs({type:"maintenance_supporter/task/apply_suggestion",entry_id:this._entryId,task_id:this._taskId,interval:this._task.suggested_interval})&&(this._toast=r("suggestion_applied",this._lang)||"Applied",this._notifyChanged("apply_suggestion"),await this._loadTask(),setTimeout(()=>{this._toast=""},2500))}async _reanalyzeInterval(){if(!(!this._entryId||!this._taskId)){this._busy=!0,this._error="";tr Line truncated
<div class="recommendation-card"> <div class="recommendation-card">
<h4>${r("suggested_interval",t)}</h4> <h4>${r("suggested_interval",t)}</h4>
${Gi(e.interval_days,e.suggested_interval,e.interval_confidence||"medium",t)} ${Gi(e.interval_days,e.suggested_interval,e.interval_confidence||"medium",t)}
@@ -3661,11 +3707,13 @@ ${p?`<div class="sub">${p}</div>`:""}
<ha-icon slot="start" icon="mdi:check"></ha-icon> <ha-icon slot="start" icon="mdi:check"></ha-icon>
${r("complete",e)||"Complete"} ${r("complete",e)||"Complete"}
</ha-button> </ha-button>
<ha-button appearance="plain" variant="neutral" @click=${()=>{this._showSkip=!0}} .disabled=${this._busy}> ${t.allow_skip!==!1?o`
<ha-icon slot="start" icon="mdi:skip-next"></ha-icon> <ha-button appearance="outlined" variant="neutral" @click=${()=>{this._showSkip=!0}} .disabled=${this._busy}>
${r("skip",e)||"Skip"} <ha-icon slot="start" icon="mdi:skip-next"></ha-icon>
</ha-button> ${r("skip",e)||"Skip"}
<ha-button appearance="plain" variant="neutral" @click=${()=>{this._showReset=!0}} .disabled=${this._busy}> </ha-button>
`:h}
<ha-button appearance="outlined" variant="neutral" @click=${()=>{this._showReset=!0}} .disabled=${this._busy}>
<ha-icon slot="start" icon="mdi:restart"></ha-icon> <ha-icon slot="start" icon="mdi:restart"></ha-icon>
${r("reset",e)||"Reset"} ${r("reset",e)||"Reset"}
</ha-button> </ha-button>
@@ -3713,7 +3761,7 @@ ${p?`<div class="sub">${p}</div>`:""}
`} `}
`:o`<div class="loading">${r("loading",e)||"Loading\u2026"}</div>`} `:o`<div class="loading">${r("loading",e)||"Loading\u2026"}</div>`}
</div> </div>
`}};L.styles=[We,A` `}};L.styles=[We,T`
:host { display: contents; } :host { display: contents; }
.backdrop { .backdrop {
position: fixed; inset: 0; z-index: 100; position: fixed; inset: 0; z-index: 100;
@@ -3896,7 +3944,7 @@ ${p?`<div class="sub">${p}</div>`:""}
.weibull-section, .seasonal-card-compact { max-width: 100%; } .weibull-section, .seasonal-card-compact { max-width: 100%; }
.weibull-chart svg { max-width: 100%; height: auto; } .weibull-chart svg { max-width: 100%; height: auto; }
.details-toggle { gap: 12px; flex-wrap: wrap; } .details-toggle { gap: 12px; flex-wrap: wrap; }
`],c([x({attribute:!1})],L.prototype,"hass",2),c([u()],L.prototype,"_open",2),c([u()],L.prototype,"_entryId",2),c([u()],L.prototype,"_taskId",2),c([u()],L.prototype,"_task",2),c([u()],L.prototype,"_objectName",2),c([u()],L.prototype,"_busy",2),c([u()],L.prototype,"_error",2),c([u()],L.prototype,"_showSkip",2),c([u()],L.prototype,"_showReset",2),c([u()],L.prototype,"_showDetails",2),c([u()],L.prototype,"_showAdaptive",2),c([u()],L.prototype,"_skipReason",2),c([u()],L.prototype,"_resetDate",2),c([u()],L.prototype,"_features",2),c([u()],L.prototype,"_toast",2);customElements.get("maintenance-task-quick-actions-dialog")||customElements.define("maintenance-task-quick-actions-dialog",L)});function ts(a){return a?customElements.get("ha-markdown")?o`<ha-markdown class="notes-md" .content=${a} breaks></ha-markdown>`:o`${a}`:h}var is=w(()=>{"use strict";R()});var G,ss=w(()=>{"use strict";R();vt();is();D();q();se();G=class extends S{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._data=null;this._busy=!1;this._error=""}get _lang(){return j(this.hass)}async openFor(e){this._entryId=e,this._error="",this._open=!0,await this._load()}close(){this._open=!1,this._data=null,this._error=""}async _load(){if(this._entryId)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._data=e}catch(e){this._error=T(e,this._lang)}}_onEditObject(){!this._entryId||!this._data||Promise.resolve().then(()=>(K(),Z)).then(({openEditObjectDialog:e})=>{e(this._entryId,this._data.object),this.close()})}_onAddTask(){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openCreateTaskDialog:e})=>{e(this._entryId),this.close()})}async _onDelete(){if(!this._entryId||!this._data)return;let e=r("delete_object_confirm",this._lang)||`Delete "${this._data.object.name}" and all its tasks?`;if(window.confirm(e)){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/delete",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-deleted",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=T(t,this._lang)}finally{this._busy=!1}}}async _onArchiveObject(){if(!this._entryId||!this._data)return;let e=!!this._data.object.archived;if(!e){let t=r("confirm_archive_object",this._lang)||"Archive this object and its tasks?";if(!window.confirm(t))return}this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:e?"maintenance_supporter/object/unarchive":"maintenance_supporter/object/archive",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-changed",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=T(t,this._lang)}finally{this._busy=!1}}_onTaskClick(e){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openTaskQuickActions:t})=>{t(this._entryId,e)})}render(){if(!this._open)return h;let e=this._lang,t=this._data,i=t?.object,n=t?.tasks||[],l=this.hass?.user?.is_admin??!0;return o` `],c([x({attribute:!1})],L.prototype,"hass",2),c([u()],L.prototype,"_open",2),c([u()],L.prototype,"_entryId",2),c([u()],L.prototype,"_taskId",2),c([u()],L.prototype,"_task",2),c([u()],L.prototype,"_objectName",2),c([u()],L.prototype,"_busy",2),c([u()],L.prototype,"_error",2),c([u()],L.prototype,"_showSkip",2),c([u()],L.prototype,"_showReset",2),c([u()],L.prototype,"_showDetails",2),c([u()],L.prototype,"_showAdaptive",2),c([u()],L.prototype,"_skipReason",2),c([u()],L.prototype,"_resetDate",2),c([u()],L.prototype,"_features",2),c([u()],L.prototype,"_toast",2);customElements.get("maintenance-task-quick-actions-dialog")||customElements.define("maintenance-task-quick-actions-dialog",L)});function ts(a){return a?customElements.get("ha-markdown")?o`<ha-markdown class="notes-md" .content=${a} breaks></ha-markdown>`:o`${a}`:h}var is=w(()=>{"use strict";R()});var G,ss=w(()=>{"use strict";R();vt();is();D();q();se();G=class extends S{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._data=null;this._busy=!1;this._error=""}get _lang(){return j(this.hass)}async openFor(e){this._entryId=e,this._error="",this._open=!0,await this._load()}close(){this._open=!1,this._data=null,this._error=""}async _load(){if(this._entryId)try{let e=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._data=e}catch(e){this._error=A(e,this._lang)}}_onEditObject(){!this._entryId||!this._data||Promise.resolve().then(()=>(K(),Z)).then(({openEditObjectDialog:e})=>{e(this._entryId,this._data.object),this.close()})}_onAddTask(){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openCreateTaskDialog:e})=>{e(this._entryId),this.close()})}async _onDelete(){if(!this._entryId||!this._data)return;let e=r("delete_object_confirm",this._lang)||`Delete "${this._data.object.name}" and all its tasks?`;if(window.confirm(e)){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/delete",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-deleted",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=A(t,this._lang)}finally{this._busy=!1}}}async _onArchiveObject(){if(!this._entryId||!this._data)return;let e=!!this._data.object.archived;if(!e){let t=r("confirm_archive_object",this._lang)||"Archive this object and its tasks?";if(!window.confirm(t))return}this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:e?"maintenance_supporter/object/unarchive":"maintenance_supporter/object/archive",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-changed",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=A(t,this._lang)}finally{this._busy=!1}}_onTaskClick(e){this._entryId&&Promise.resolve().then(()=>(K(),Z)).then(({openTaskQuickActions:t})=>{t(this._entryId,e)})}render(){if(!this._open)return h;let e=this._lang,t=this._data,i=t?.object,n=t?.tasks||[],l=this.hass?.user?.is_admin??!0;return o`
<div class="backdrop" @click=${this.close}></div> <div class="backdrop" @click=${this.close}></div>
<div class="dialog" role="dialog" aria-modal="true"> <div class="dialog" role="dialog" aria-modal="true">
${t&&i?o` ${t&&i?o`
@@ -3963,7 +4011,7 @@ ${p?`<div class="sub">${p}</div>`:""}
</div> </div>
`)} `)}
</div> </div>
`}};G.styles=A` `}};G.styles=T`
:host { display: contents; } :host { display: contents; }
.backdrop { .backdrop {
position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,0.5); position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,0.5);
@@ -4023,7 +4071,7 @@ ${p?`<div class="sub">${p}</div>`:""}
.btn ha-icon { --mdc-icon-size: 16px; } .btn ha-icon { --mdc-icon-size: 16px; }
.loading { padding: 24px; text-align: center; color: var(--secondary-text-color); } .loading { padding: 24px; text-align: center; color: var(--secondary-text-color); }
.error { padding: 8px; border-radius: 6px; background: rgba(211,47,47,0.1); color: var(--error-color); font-size: 13px; } .error { padding: 8px; border-radius: 6px; background: rgba(211,47,47,0.1); color: var(--error-color); font-size: 13px; }
`,c([x({attribute:!1})],G.prototype,"hass",2),c([u()],G.prototype,"_open",2),c([u()],G.prototype,"_entryId",2),c([u()],G.prototype,"_data",2),c([u()],G.prototype,"_busy",2),c([u()],G.prototype,"_error",2);customElements.get("maintenance-object-quick-actions-dialog")||customElements.define("maintenance-object-quick-actions-dialog",G)});var Z={};hs(Z,{__resetSettingsCacheForTests:()=>fr,getRowActionStyle:()=>Pt,openCompleteDialog:()=>xr,openCreateObjectDialog:()=>Rt,openCreateTaskDialog:()=>jt,openEditObjectDialog:()=>vr,openEditTaskDialog:()=>br,openHistoryEditDialog:()=>yr,openObjectQuickActions:()=>$r,openQrDialog:()=>wr,openTaskQuickActions:()=>qt});function Ze(){return document.querySelector("home-assistant")?.hass}function mr(){return document.querySelector("home-assistant")?.shadowRoot??document.body}function X(a){let s=mr(),e=s.querySelector(a)??document.body.querySelector(a);return e?e.parentNode!==s&&s.appendChild(e):(e=document.createElement(a),s.appendChild(e)),e}function ee(a){let s=Ze();if(!s)return!1;a.hass=s;let e=j(s);return gt(e)||Le(e).then(()=>{a.requestUpdate?.()}),!0}function Pt(a){return Lt(a).then(s=>s.rowActionStyle)}function fr(){Ne=null}function Lt(a){return Ne||(Ne=a.connection.sendMessagePromise({type:"maintenance_supporter/settings"}).then(s=>({features:s.features??It.features,defaultWarningDays:s.general?.default_warning_days??7,rowActionStyle:s.general?.row_action_style??It.rowActionStyle})).catch(()=>It),Ne)}function Rt(){let a=X(rs);return ee(a)?(a.openCreate(),!0):!1}function vr(a,s){let e=X(rs);return ee(e)?(e.openEdit(a,s),!0):!1}function jt(a="",s){let e=X(as);if(!ee(e))return!1;let t=Ze();return t?((async()=>{let i=await Lt(t),n=e;n.checklistsEnabled=i.features.checklists,n.scheduleTimeEnabled=i.features.schedule_time,n.completionActionsEnabled=i.features.completion_actions,n.defaultWarningDays=i.defaultWarningDays,n.openCreate(a,s)})(),!0):!1}function br(a,s){let e=X(as);if(!ee(e))return!1;let t=Ze();return t?((async()=>{try{let[i,n]=await Promise.all([t.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:a}),Lt(t)]),l=(i.tasks||[]).find(p=>p.id===s);if(!l){console.warn(`openEditTaskDialog: task ${s} not found in entry ${a}`);return}let d=e;d.checklistsEnabled=n.features.checklists,d.scheduleTimeEnabled=n.features.schedule_time,d.completionActionsEnabled=n.features.completion_actions,d.defaultWarningDays=n.defaultWarningDays,await d.openEdit(a,l)}catch(i){console.warn("openEditTaskDialog: failed to load task/features",i)}})(),!0):!1}function yr(a){let s=X(pr);return ee(s)?(s.openEdit(a),!0):!1}function xr(a){let s=X(hr);return ee(s)?(je(s,a,Ze()?.language||"en"),!0):!1}function wr(a){let s=X(ur);return ee(s)?(s.openForTask(a.entry_id,a.task_id,a.object_name,a.task_name),!0):!1}function qt(a,s){let e=X(_r);return ee(e)?(e.openFor(a,s),!0):!1}function $r(a){let s=X(gr);return ee(s)?(s.openFor(a),!0):!1}var rs,as,pr,hr,ur,_r,gr,It,Ne,K=w(()=>{"use strict";Li();Hi();$t();Oi();Mi();es();ss();q();Je();rs="maintenance-object-dialog",as="maintenance-task-dialog",pr="maintenance-history-edit-dialog",hr="maintenance-complete-dialog",ur="maintenance-qr-dialog",_r="maintenance-task-quick-actions-dialog",gr="maintenance-object-quick-actions-dialog";It={features:{adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1},defaultWarningDays:7,rowActionStyle:"buttons_compact"};Ne=null});R();var Ss=["assignee_pool","required_completion_fields","checklist","labels","history"],As=["checklist_progress"],Ts=["tasks","parts"],Cs=["manual_docs","battery_fleet_excluded"];function ht(a,s,e=[]){for(let t of s)a[t]===void 0&&(a[t]=[]);for(let t of e)a[t]===void 0&&(a[t]={})}function Is(a){let s=a;ht(s,Ts),s.object&&typeof s.object=="object"&&ht(s.object,Cs);for(let e of s.tasks)ht(e,Ss,As);return a}function Te(a){for(let s of a)Is(s);return a}function Ps(a,s){if(s.objects)return s.objects;let e=s.delta||[],t=s.removed||[];if(!e.length&&!t.length)return null;let i=new Map(a.map(n=>[n.entry_id,n]));for(let n of e)i.set(n.entry_id,n);for(let n of t)i.delete(n);return[...i.values()]}function si(a,s){return s.objects&&Te(s.objects),s.delta&&Te(s.delta),Ps(a,s)}D();q();ft();async function zs(a,s,e=300){return(await a.connection.sendMessagePromise({type:"auth/sign_path",path:s,expires:e})).path}async function Fs(a,s,e=300){return zs(a,`/api/maintenance_supporter/document/${s}`,e)}async function Si(a,s,e=""){let t=window.open("about:blank","_blank");try{let i=await Fs(a,s);t&&(t.location.href=new URL(i+e,window.location.origin).href)}catch(i){throw t&&t.close(),i}}vt();function Ge(a){let s=window;s.customCards=s.customCards||[],s.customCards.some(e=>e.type===a.type)||s.customCards.push(a)}bt();Ye();Je();R();D();q();var Vs=["overdue","triggered","due_soon","ok"],W=class extends S{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-card"};this._objects=[];this._loadingObjects=!0; Line truncated `,c([x({attribute:!1})],G.prototype,"hass",2),c([u()],G.prototype,"_open",2),c([u()],G.prototype,"_entryId",2),c([u()],G.prototype,"_data",2),c([u()],G.prototype,"_busy",2),c([u()],G.prototype,"_error",2);customElements.get("maintenance-object-quick-actions-dialog")||customElements.define("maintenance-object-quick-actions-dialog",G)});var Z={};hs(Z,{__resetSettingsCacheForTests:()=>fr,getRowActionStyle:()=>Pt,openCompleteDialog:()=>xr,openCreateObjectDialog:()=>Rt,openCreateTaskDialog:()=>jt,openEditObjectDialog:()=>vr,openEditTaskDialog:()=>br,openHistoryEditDialog:()=>yr,openObjectQuickActions:()=>$r,openQrDialog:()=>wr,openTaskQuickActions:()=>qt});function Ze(){return document.querySelector("home-assistant")?.hass}function mr(){return document.querySelector("home-assistant")?.shadowRoot??document.body}function X(a){let s=mr(),e=s.querySelector(a)??document.body.querySelector(a);return e?e.parentNode!==s&&s.appendChild(e):(e=document.createElement(a),s.appendChild(e)),e}function ee(a){let s=Ze();if(!s)return!1;a.hass=s;let e=j(s);return gt(e)||Le(e).then(()=>{a.requestUpdate?.()}),!0}function Pt(a){return Lt(a).then(s=>s.rowActionStyle)}function fr(){Ne=null}function Lt(a){return Ne||(Ne=a.connection.sendMessagePromise({type:"maintenance_supporter/settings"}).then(s=>({features:s.features??It.features,defaultWarningDays:s.general?.default_warning_days??7,rowActionStyle:s.general?.row_action_style??It.rowActionStyle})).catch(()=>It),Ne)}function Rt(){let a=X(rs);return ee(a)?(a.openCreate(),!0):!1}function vr(a,s){let e=X(rs);return ee(e)?(e.openEdit(a,s),!0):!1}function jt(a="",s){let e=X(as);if(!ee(e))return!1;let t=Ze();return t?((async()=>{let i=await Lt(t),n=e;n.checklistsEnabled=i.features.checklists,n.scheduleTimeEnabled=i.features.schedule_time,n.completionActionsEnabled=i.features.completion_actions,n.defaultWarningDays=i.defaultWarningDays,n.openCreate(a,s)})(),!0):!1}function br(a,s){let e=X(as);if(!ee(e))return!1;let t=Ze();return t?((async()=>{try{let[i,n]=await Promise.all([t.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:a}),Lt(t)]),l=(i.tasks||[]).find(p=>p.id===s);if(!l){console.warn(`openEditTaskDialog: task ${s} not found in entry ${a}`);return}let d=e;d.checklistsEnabled=n.features.checklists,d.scheduleTimeEnabled=n.features.schedule_time,d.completionActionsEnabled=n.features.completion_actions,d.defaultWarningDays=n.defaultWarningDays,await d.openEdit(a,l)}catch(i){console.warn("openEditTaskDialog: failed to load task/features",i)}})(),!0):!1}function yr(a){let s=X(pr);return ee(s)?(s.openEdit(a),!0):!1}function xr(a){let s=X(hr);return ee(s)?(je(s,a,Ze()?.language||"en"),!0):!1}function wr(a){let s=X(ur);return ee(s)?(s.openForTask(a.entry_id,a.task_id,a.object_name,a.task_name),!0):!1}function qt(a,s){let e=X(_r);return ee(e)?(e.openFor(a,s),!0):!1}function $r(a){let s=X(gr);return ee(s)?(s.openFor(a),!0):!1}var rs,as,pr,hr,ur,_r,gr,It,Ne,K=w(()=>{"use strict";Li();Hi();$t();Oi();Mi();es();ss();q();Je();rs="maintenance-object-dialog",as="maintenance-task-dialog",pr="maintenance-history-edit-dialog",hr="maintenance-complete-dialog",ur="maintenance-qr-dialog",_r="maintenance-task-quick-actions-dialog",gr="maintenance-object-quick-actions-dialog";It={features:{adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1},defaultWarningDays:7,rowActionStyle:"buttons_compact"};Ne=null});R();var Ss=["assignee_pool","required_completion_fields","checklist","labels","history"],Ts=["checklist_progress"],As=["tasks","parts"],Cs=["manual_docs","battery_fleet_excluded"];function ht(a,s,e=[]){for(let t of s)a[t]===void 0&&(a[t]=[]);for(let t of e)a[t]===void 0&&(a[t]={})}function Is(a){let s=a;ht(s,As),s.object&&typeof s.object=="object"&&ht(s.object,Cs);for(let e of s.tasks)ht(e,Ss,Ts);return a}function Ae(a){for(let s of a)Is(s);return a}function Ps(a,s){if(s.objects)return s.objects;let e=s.delta||[],t=s.removed||[];if(!e.length&&!t.length)return null;let i=new Map(a.map(n=>[n.entry_id,n]));for(let n of e)i.set(n.entry_id,n);for(let n of t)i.delete(n);return[...i.values()]}function si(a,s){return s.objects&&Ae(s.objects),s.delta&&Ae(s.delta),Ps(a,s)}D();q();ft();async function zs(a,s,e=300){return(await a.connection.sendMessagePromise({type:"auth/sign_path",path:s,expires:e})).path}async function Fs(a,s,e=300){return zs(a,`/api/maintenance_supporter/document/${s}`,e)}async function Si(a,s,e=""){let t=window.open("about:blank","_blank");try{let i=await Fs(a,s);t&&(t.location.href=new URL(i+e,window.location.origin).href)}catch(i){throw t&&t.close(),i}}vt();function Ge(a){let s=window;s.customCards=s.customCards||[],s.customCards.some(e=>e.type===a.type)||s.customCards.push(a)}bt();Ye();Je();R();D();q();var Vs=["overdue","triggered","due_soon","ok"],W=class extends S{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-card"};this._objects=[];this._loadingObjects=!0; Line truncated
<div class="editor"> <div class="editor">
<ha-textfield <ha-textfield
label="${r("card_title",e)}" label="${r("card_title",e)}"
@@ -4203,7 +4251,7 @@ ${p?`<div class="sub">${p}</div>`:""}
></ha-textfield> ></ha-textfield>
${h} ${h}
</div> </div>
`}};W.styles=A` `}};W.styles=T`
.editor { .editor {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -4282,7 +4330,7 @@ ${p?`<div class="sub">${p}</div>`:""}
font-size: 14px; font-size: 14px;
max-width: 320px; max-width: 320px;
} }
`,c([x({attribute:!1})],W.prototype,"hass",2),c([u()],W.prototype,"_config",2),c([u()],W.prototype,"_objects",2),c([u()],W.prototype,"_loadingObjects",2),c([u()],W.prototype,"_loadError",2),c([u()],W.prototype,"_views",2);customElements.get("maintenance-supporter-card-editor")||customElements.define("maintenance-supporter-card-editor",W);$t();R();D();R();D();q();var kt={overviewTab:"msp-overview-tab",collapsedSections:"msp-collapsed-sections",chartRange:"msp-chart-range",chartHideOutliers:"msp-chart-hide-outliers",taskSort:"maintenance_supporter_sort",objectSort:"maintenance_supporter_object_sort",groupBy:"maintenance_supporter_groupby",objectView:"maintenance_supporter_object_view",objectsCache:"msp-objects-cache",gettingStartedDismissed:"msp-gs-dismissed",batteryRosterSort:"ms_bf_roster_sort"};function Ii(a){try{return localStorage.getItem(a)}catch{return null}}function Pi(a,s){try{localStorage.setItem(a,s)}catch{}}se();var O=class O extends S{constructor(){super(...arguments);this.flat=!1;this._ov=null;this._loading=!1;this._marking=!1;this._error="";this._history=null;this._rosterSort=O._storedSort();this._typeFilter=null;this._recorded=[];this._historyRequested=!1;this._localeReady=!1;this._markAll=async()=>{await this._mark(void 0)};this._repair=async()=>{if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/setup",language:this._lang}),await this._load()}catch(e){this._error=T(e,this._lang)}finally{this._marking=!1}}};this._loadHistory=async e=>{if(!(!e.target.open||this._historyRequested)){this._historyRequested=!0;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/overview_history"});this._history=t.series}catch{this._history=null}}}}get _lang(){return j(this.hass)}connectedCallback(){super.connectedCallback(),this.hass&&this._load()}updated(e){e.has("hass")&&this.hass&&!this._localeReady&&(this._localeReady=!0,Le(this._lang).then(()=>this.requestUpdate()),this._ov===null&&!this._loading&&this._load())}async _load(){this._loading=!0,this._error="";try{this._ov=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/overview"})}catch(e){this._error=T(e,this._lang)}finally{this._loading=!1}}async _mark(e){if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/mark_replaced",...e?{entity_ids:e}:{}}),await this._load()}catch(t){this._error=T(t,this._lang)}finally{this._marking=!1}}}async _setExcluded(e,t){if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/set_excluded",entity_id:e,excluded:t}),await this._load()}catch(i){this._error=T(i,this._lang)}finally{this._marking=!1}}}async _addBattery(e){let t=e.detail?.value;if(!(!t||this._marking)){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/set_included",entity_id:t,included:!0}),await this._load()}catch(i){this._error=T(i,this._lang)}finally{this._marking=!1}}}async _setTrackSelf(e){let t=e.target.checked;if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/set_track_self_charging",enabled:t}),await this._load()}catch(i){this._error=T(i,this._lang)}finally{this._marking=!1}}}_sparkline(e){let t=this._history?.[e.entity_id];if(!t||t.points.length<2)return h;let i=110,n=24,l=2,d=t.points[0][0],p=t.points[t.points.length-1][0],_=Date.now()/1e3,f=e.status!=="low"&&e.predicted_source==="trend"&&e.days_until!=null?_+e.days_until*86400:null,b=Math.max(p,f??p),v=C=>b===d?l:l+(C-d)/(b-d)*(i-2*l),y=C=>l+(1-Math.min(100,Math.max(0,C))/100)*(n-2*l),m=t.points.map(([C,E])=>`${v(C).toFixed(1)},${y(E).toFixed(1)}`).join(" "),$=t.points[t.points.length-1][1],H=y(t.threshold).toFixed(1);return o`<svg `,c([x({attribute:!1})],W.prototype,"hass",2),c([u()],W.prototype,"_config",2),c([u()],W.prototype,"_objects",2),c([u()],W.prototype,"_loadingObjects",2),c([u()],W.prototype,"_loadError",2),c([u()],W.prototype,"_views",2);customElements.get("maintenance-supporter-card-editor")||customElements.define("maintenance-supporter-card-editor",W);$t();R();D();R();D();q();var kt={overviewTab:"msp-overview-tab",collapsedSections:"msp-collapsed-sections",chartRange:"msp-chart-range",chartHideOutliers:"msp-chart-hide-outliers",taskSort:"maintenance_supporter_sort",objectSort:"maintenance_supporter_object_sort",groupBy:"maintenance_supporter_groupby",objectView:"maintenance_supporter_object_view",objectsCache:"msp-objects-cache",gettingStartedDismissed:"msp-gs-dismissed",batteryRosterSort:"ms_bf_roster_sort"};function Ii(a){try{return localStorage.getItem(a)}catch{return null}}function Pi(a,s){try{localStorage.setItem(a,s)}catch{}}se();var O=class O extends S{constructor(){super(...arguments);this.flat=!1;this._ov=null;this._loading=!1;this._marking=!1;this._error="";this._history=null;this._rosterSort=O._storedSort();this._typeFilter=null;this._recorded=[];this._historyRequested=!1;this._localeReady=!1;this._markAll=async()=>{await this._mark(void 0)};this._repair=async()=>{if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/setup",language:this._lang}),await this._load()}catch(e){this._error=A(e,this._lang)}finally{this._marking=!1}}};this._loadHistory=async e=>{if(!(!e.target.open||this._historyRequested)){this._historyRequested=!0;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/overview_history"});this._history=t.series}catch{this._history=null}}}}get _lang(){return j(this.hass)}connectedCallback(){super.connectedCallback(),this.hass&&this._load()}updated(e){e.has("hass")&&this.hass&&!this._localeReady&&(this._localeReady=!0,Le(this._lang).then(()=>this.requestUpdate()),this._ov===null&&!this._loading&&this._load())}async _load(){this._loading=!0,this._error="";try{this._ov=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/overview"})}catch(e){this._error=A(e,this._lang)}finally{this._loading=!1}}async _mark(e){if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/mark_replaced",...e?{entity_ids:e}:{}}),await this._load()}catch(t){this._error=A(t,this._lang)}finally{this._marking=!1}}}async _setExcluded(e,t){if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/set_excluded",entity_id:e,excluded:t}),await this._load()}catch(i){this._error=A(i,this._lang)}finally{this._marking=!1}}}async _addBattery(e){let t=e.detail?.value;if(!(!t||this._marking)){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/set_included",entity_id:t,included:!0}),await this._load()}catch(i){this._error=A(i,this._lang)}finally{this._marking=!1}}}async _setTrackSelf(e){let t=e.target.checked;if(!this._marking){this._marking=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/battery_fleet/set_track_self_charging",enabled:t}),await this._load()}catch(i){this._error=A(i,this._lang)}finally{this._marking=!1}}}_sparkline(e){let t=this._history?.[e.entity_id];if(!t||t.points.length<2)return h;let i=110,n=24,l=2,d=t.points[0][0],p=t.points[t.points.length-1][0],_=Date.now()/1e3,f=e.status!=="low"&&e.predicted_source==="trend"&&e.days_until!=null?_+e.days_until*86400:null,b=Math.max(p,f??p),v=C=>b===d?l:l+(C-d)/(b-d)*(i-2*l),y=C=>l+(1-Math.min(100,Math.max(0,C))/100)*(n-2*l),m=t.points.map(([C,E])=>`${v(C).toFixed(1)},${y(E).toFixed(1)}`).join(" "),$=t.points[t.points.length-1][1],H=y(t.threshold).toFixed(1);return o`<svg
class="bf-spark" class="bf-spark"
viewBox="0 0 ${i} ${n}" viewBox="0 0 ${i} ${n}"
role="img" role="img"
@@ -4304,7 +4352,7 @@ ${p?`<div class="sub">${p}</div>`:""}
@click=${()=>this._toggleTypeFilter(t)} @click=${()=>this._toggleTypeFilter(t)}
> >
${i}× ${t} ${i}× ${t}
</button>`)}_toggleTypeFilter(e){if(this._typeFilter=this._typeFilter===e?null:e,this._typeFilter!==null){let t=this.shadowRoot?.querySelector("details.bf-roster");t&&!t.open&&(t.open=!0)}}async _recordJump(e,t){if(!this._marking){this._marking=!0,this._error="";try{await this.hass.callService("battery_notes","set_battery_replaced",{device_id:t.device_id,datetime_replaced:new Date(t.at*1e3).toISOString()}),this._recorded=[...this._recorded,e],await this._load()}catch(i){this._error=T(i,this._lang)}finally{this._marking=!1}}}_levelBar(e){let t=e.level;if(t==null)return h;let i=e.low_threshold??20,n=t<=i?"bad":t<=i+20?"warn":"good";return o`<span class="bf-bar" aria-hidden="true" </button>`)}_toggleTypeFilter(e){if(this._typeFilter=this._typeFilter===e?null:e,this._typeFilter!==null){let t=this.shadowRoot?.querySelector("details.bf-roster");t&&!t.open&&(t.open=!0)}}async _recordJump(e,t){if(!this._marking){this._marking=!0,this._error="";try{await this.hass.callService("battery_notes","set_battery_replaced",{device_id:t.device_id,datetime_replaced:new Date(t.at*1e3).toISOString()}),this._recorded=[...this._recorded,e],await this._load()}catch(i){this._error=A(i,this._lang)}finally{this._marking=!1}}}_levelBar(e){let t=e.level;if(t==null)return h;let i=e.low_threshold??20,n=t<=i?"bad":t<=i+20?"warn":"good";return o`<span class="bf-bar" aria-hidden="true"
><span class="bf-bar-fill bf-bar-${n}" style="width: ${Math.min(100,Math.max(0,t))}%"></span ><span class="bf-bar-fill bf-bar-${n}" style="width: ${Math.min(100,Math.max(0,t))}%"></span
></span>`}render(){let e=this._lang;if(this._loading&&this._ov===null)return o`<div class="bf-card"><div class="bf-loading">…</div></div>`;let t=this._ov;if(!t)return this._error?o`<div class="bf-card"><div class="bf-error">${this._error}</div></div>`:h;let i=t.low.length;return o` ></span>`}render(){let e=this._lang;if(this._loading&&this._ov===null)return o`<div class="bf-card"><div class="bf-loading">…</div></div>`;let t=this._ov;if(!t)return this._error?o`<div class="bf-card"><div class="bf-error">${this._error}</div></div>`:h;let i=t.low.length;return o`
<div class="bf-card"> <div class="bf-card">
@@ -4469,7 +4517,7 @@ ${p?`<div class="sub">${p}</div>`:""}
`:h} `:h}
<div class="bf-total">${r("battery_fleet_total",e).replace("{n}",String(t.total))}</div> <div class="bf-total">${r("battery_fleet_total",e).replace("{n}",String(t.total))}</div>
</div> </div>
`}};O.styles=A` `}};O.styles=T`
.bf-card { .bf-card {
background: var(--card-background-color, #fff); background: var(--card-background-color, #fff);
border: 1px solid var(--divider-color); border: 1px solid var(--divider-color);
@@ -4863,14 +4911,14 @@ ${p?`<div class="sub">${p}</div>`:""}
<maintenance-battery-fleet-section flat .hass=${this.hass}></maintenance-battery-fleet-section> <maintenance-battery-fleet-section flat .hass=${this.hass}></maintenance-battery-fleet-section>
</div> </div>
</ha-card> </ha-card>
`:h}};fe.styles=A` `:h}};fe.styles=T`
ha-card { ha-card {
overflow: hidden; overflow: hidden;
} }
.content { .content {
padding: 12px 16px 14px; padding: 12px 16px 14px;
} }
`,c([x({attribute:!1})],fe.prototype,"hass",2),c([u()],fe.prototype,"_config",2);customElements.get("maintenance-battery-fleet-card")||customElements.define("maintenance-battery-fleet-card",fe);Ge({type:"maintenance-battery-fleet-card",name:"Battery Fleet",description:"All tracked batteries: what is low now, what runs out soon, and what to buy.",preview:!1});K();var M=class extends S{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-card"};this._globalRowStyle="buttons_compact";this._objects=[];this._stats=null;this._unsub=null;this._viewFilters=null;this._userNames={};this._userService=null;this._userNamesLoaded=!1;this._taskDocs={};this._docsLoadedFor=new Set;this._dataLoaded=!1;this._lastConnection=null;this._onCompleted=async()=>{await this._loadData()}}get _lang(){return j(this.hass)}static getConfigElement(){return document.createElement("maintenance-supporter-card-editor")}static getStubConfig(){return{type:"custom:maintenance-supporter-card",show_header:!0,show_actions:!0,filter_status:["overdue","triggered","due_soon"],max_items:10}}setConfig(e){let t=e.view_id!==this._config.view_id;this._config=e,t&&this._dataLoaded&&this.hass&&this._loadViewFilters()}getCardSize(){return 3}connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),this._unsub&&(this._unsub(),this._unsub=null),this._dataLoaded=!1,this._lastConnection=null}updated(e){if(super.updated(e),vi(this,e),this.hass&&!this._userNamesLoaded&&this._config.show_assignee!==!1&&this._objects.some(t=>t.tasks.some(i=>i.responsible_user_id))&&this._loadUserNames(),this.hass&&this._config.show_documents!==!1)for(let t of this._objects)this._docsLoadedFor.has(t.entry_id)||t.tasks.some(i=>(i.document_count??0)>0)&&this._loadDocuments(t.entry_id);if(e.has("hass")&&this.hass){if(!this._dataLoaded)this._dataLoaded=!0,this._lastConnection=this.hass.connection,this._loadData(),this._subscribe();else if(this.hass.connection!==this._lastConnection){if(this._lastConnection=this.hass.connection,this._unsub){try{this._unsub()}catch{}this._unsub=null}this._subscribe(),this._loadData()}}}async _loadData(){Pt(this.hass).then(e=>{this._globalRowStyle=e}).catch(()=>{});try{let[e,t]=await Promise.all([this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects",compact:!0}),this.hass.connection.sendMessagePromise({type:"maintenance_supporter/statistics"})]);this._objects=Te(e.objects),this._stats=t}catch{}await this._loadViewFilters()}_assigneeName(e){if(this._config.show_assignee===!1)return"";let t=e.responsible_user_id;return t&&this._userNames[t]||""}async _loadUserNames(){this._userNamesLoaded=!0,this._userService?this._userService.updateHass(this.hass):this._userService=new me(this.hass);try{let e=await this._userService.getUsers();this._userNames=Object.fromEntries(e.map(t=>[t.id,t.name]))}catch{}}async _loadDocuments(e){this._docsLoadedFor.add(e);try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/documents/list",entry_id:e}),i={};for(let n of t.documents||[])for(let l of n.task_ids||[])(i[l]||=[]).push({id:n.id,title:n.title,kind:n.kind,url:n.url});this._taskDocs={...this._taskDocs,[e]:i}}catch{}}_docsFor(e,t){if(this._config.show_documents===!1)return[];let n=[...this._taskDocs[e]?.[t.id]||[]];return t.documentation_url&&n.push({id:`url:${t.id}`,title:r("documentation_label",this._lang),kind:"weblink",url:t.documentation_url}),n}async _openDoc(e){if(e.kind==="weblink"&&e.url){Ke(e.url)&&window.open(e.url,"_blank","noopener");return}try{await Si(this.hass,e.id)}catch{}}async _loadViewFilters(){if(!this._config.view_id){this._viewFilters=null;return}try{let t=((await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/views/list"})).views||[]).find(i=>i.id===this._config.view_id);this._viewFilters=t?t.filters:null}catch{this._viewFilters=null}}async _subscribe(){try{let e=await this.hass.connection.subscribeMessage(t=>{let i=si(this._objects,t);i!==null&&(this._objects=i)},{type:"maintenance_supporter/subscribe",deltas:!0,compact:!0});if(!this.isConnected){e();return}this._unsub=e}catch{}}get _flatTasks(){let e=[],{filter_status:t,filter_objects:i,entity_ids:n,filter_due_min_days:l,filter_due_max_days:d,filter_labels:p,filter_priority:_,filter_areas:f,max_items:b}=this._config,v=n?.length?new Set(n):null,y=l!==void 0||d!==void 0,m=this._viewFilters,$=m?.user_id==="current_user"?this.hass.user?.id??null:m?.user_id??null;for(let C of this._objects)if(!(i?.length&&!i.includes(C.object.name))){if(f?.length){let E=C.object.area_id;if(!E||!f.includes(E))continue}for(let E of C.tasks)if(!E.is_done&&!(E.archived||C.object.archived)&&!(t?.length&&!t.includes(E.status))&&!(p?.length&&!(E.labels||[]).some(P=>p.includes(P)))&&!(_?.length&&!_.includes(E.priority||"normal"))&&!(v&&!(E.sensor_entity_id&&v.has(E.sensor_entity_id)||E.binary_sensor_entity_id&&v.has(E.binary_sensor_entity_id)))){if(y){let P=E.days_until_due;if(P==null||l Line truncated `,c([x({attribute:!1})],fe.prototype,"hass",2),c([u()],fe.prototype,"_config",2);customElements.get("maintenance-battery-fleet-card")||customElements.define("maintenance-battery-fleet-card",fe);Ge({type:"maintenance-battery-fleet-card",name:"Battery Fleet",description:"All tracked batteries: what is low now, what runs out soon, and what to buy.",preview:!1});K();var M=class extends S{constructor(){super(...arguments);this._config={type:"custom:maintenance-supporter-card"};this._globalRowStyle="buttons_compact";this._objects=[];this._stats=null;this._unsub=null;this._viewFilters=null;this._userNames={};this._userService=null;this._userNamesLoaded=!1;this._taskDocs={};this._docsLoadedFor=new Set;this._dataLoaded=!1;this._lastConnection=null;this._onCompleted=async()=>{await this._loadData()}}get _lang(){return j(this.hass)}static getConfigElement(){return document.createElement("maintenance-supporter-card-editor")}static getStubConfig(){return{type:"custom:maintenance-supporter-card",show_header:!0,show_actions:!0,filter_status:["overdue","triggered","due_soon"],max_items:10}}setConfig(e){let t=e.view_id!==this._config.view_id;this._config=e,t&&this._dataLoaded&&this.hass&&this._loadViewFilters()}getCardSize(){return 3}connectedCallback(){super.connectedCallback()}disconnectedCallback(){super.disconnectedCallback(),this._unsub&&(this._unsub(),this._unsub=null),this._dataLoaded=!1,this._lastConnection=null}updated(e){if(super.updated(e),vi(this,e),this.hass&&!this._userNamesLoaded&&this._config.show_assignee!==!1&&this._objects.some(t=>t.tasks.some(i=>i.responsible_user_id))&&this._loadUserNames(),this.hass&&this._config.show_documents!==!1)for(let t of this._objects)this._docsLoadedFor.has(t.entry_id)||t.tasks.some(i=>(i.document_count??0)>0)&&this._loadDocuments(t.entry_id);if(e.has("hass")&&this.hass){if(!this._dataLoaded)this._dataLoaded=!0,this._lastConnection=this.hass.connection,this._loadData(),this._subscribe();else if(this.hass.connection!==this._lastConnection){if(this._lastConnection=this.hass.connection,this._unsub){try{this._unsub()}catch{}this._unsub=null}this._subscribe(),this._loadData()}}}async _loadData(){Pt(this.hass).then(e=>{this._globalRowStyle=e}).catch(()=>{});try{let[e,t]=await Promise.all([this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects",compact:!0}),this.hass.connection.sendMessagePromise({type:"maintenance_supporter/statistics"})]);this._objects=Ae(e.objects),this._stats=t}catch{}await this._loadViewFilters()}_assigneeName(e){if(this._config.show_assignee===!1)return"";let t=e.responsible_user_id;return t&&this._userNames[t]||""}async _loadUserNames(){this._userNamesLoaded=!0,this._userService?this._userService.updateHass(this.hass):this._userService=new me(this.hass);try{let e=await this._userService.getUsers();this._userNames=Object.fromEntries(e.map(t=>[t.id,t.name]))}catch{}}async _loadDocuments(e){this._docsLoadedFor.add(e);try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/documents/list",entry_id:e}),i={};for(let n of t.documents||[])for(let l of n.task_ids||[])(i[l]||=[]).push({id:n.id,title:n.title,kind:n.kind,url:n.url});this._taskDocs={...this._taskDocs,[e]:i}}catch{}}_docsFor(e,t){if(this._config.show_documents===!1)return[];let n=[...this._taskDocs[e]?.[t.id]||[]];return t.documentation_url&&n.push({id:`url:${t.id}`,title:r("documentation_label",this._lang),kind:"weblink",url:t.documentation_url}),n}async _openDoc(e){if(e.kind==="weblink"&&e.url){Ke(e.url)&&window.open(e.url,"_blank","noopener");return}try{await Si(this.hass,e.id)}catch{}}async _loadViewFilters(){if(!this._config.view_id){this._viewFilters=null;return}try{let t=((await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/views/list"})).views||[]).find(i=>i.id===this._config.view_id);this._viewFilters=t?t.filters:null}catch{this._viewFilters=null}}async _subscribe(){try{let e=await this.hass.connection.subscribeMessage(t=>{let i=si(this._objects,t);i!==null&&(this._objects=i)},{type:"maintenance_supporter/subscribe",deltas:!0,compact:!0});if(!this.isConnected){e();return}this._unsub=e}catch{}}get _flatTasks(){let e=[],{filter_status:t,filter_objects:i,entity_ids:n,filter_due_min_days:l,filter_due_max_days:d,filter_labels:p,filter_priority:_,filter_areas:f,max_items:b}=this._config,v=n?.length?new Set(n):null,y=l!==void 0||d!==void 0,m=this._viewFilters,$=m?.user_id==="current_user"?this.hass.user?.id??null:m?.user_id??null;for(let C of this._objects)if(!(i?.length&&!i.includes(C.object.name))){if(f?.length){let E=C.object.area_id;if(!E||!f.includes(E))continue}for(let E of C.tasks)if(!E.is_done&&!(E.archived||C.object.archived)&&!(t?.length&&!t.includes(E.status))&&!(p?.length&&!(E.labels||[]).some(P=>p.includes(P)))&&!(_?.length&&!_.includes(E.priority||"normal"))&&!(v&&!(E.sensor_entity_id&&v.has(E.sensor_entity_id)||E.binary_sensor_entity_id&&v.has(E.binary_sensor_entity_id)))){if(y){let P=E.days_until_due;if(P==null||l Line truncated
<ha-card> <ha-card>
<div class="card-header"> <div class="card-header">
<h1>${t}</h1> <h1>${t}</h1>
@@ -4976,7 +5024,7 @@ ${p?`<div class="sub">${p}</div>`:""}
.hass=${this.hass} .hass=${this.hass}
@task-completed=${this._onCompleted} @task-completed=${this._onCompleted}
></maintenance-complete-dialog> ></maintenance-complete-dialog>
`}};M.styles=[We,A` `}};M.styles=[We,T`
ha-card { overflow: hidden; } ha-card { overflow: hidden; }
.card-header { .card-header {
File diff suppressed because it is too large. Load diff
@@ -1,2 +1,2 @@
/*! maintenance_supporter frontend 2.70.0 */ /*! maintenance_supporter frontend 2.71.0 */
var S="2.70.0";var l="maintenance-supporter",T=`ll-strategy-dashboard-${l}`,D="hui-maintenance-supporter-strategy-editor",C=`/maintenance_supporter_strategy/maintenance-dashboard-strategy.js?v=${S}`,m=null;function v(){return m||(m=import(C)),m}async function I(){let r=await v();if(!r.MaintenanceDashboardStrategy)throw new Error("[maintenance-supporter] strategy bundle loaded but did not export MaintenanceDashboardStrategy");return r.MaintenanceDashboardStrategy}var p=class extends HTMLElement{static getCreateSuggestions(c){return{title:"Maintenance Supporter",icon:"mdi:wrench-clock"}}static async getConfigElement(){return await v(),document.createElement(D)}static async generate(c,f){return(await I()).generate(c,f)}};function M(){try{customElements.define(T,p)}catch{}}M();var w=window;w.customStrategies=w.customStrategies||[];w.customStrategies.some(r=>r.type===l&&r.strategyType==="dashboard")||w.customStrategies.push({type:l,strategyType:"dashboard",name:"Maintenance Supporter",description:"Auto-generated dashboard. Group views by area, status, floor, or due date \u2014 picked from the strategy editor or YAML.",documentationURL:"https://github.com/iluebbe/maintenance_supporter#dashboard-strategy"});(()=>{let r=window;if(r.__msStrategyHealActive)return;r.__msStrategyHealActive=!0;let c=/^\/(auth|config|developer-tools|profile|hassio|history|logbook|map|media-browser|energy|todo|calendar)\b/,f=/Timeout waiting for strategy element ll-strategy-(dashboard-)?maintenance-supporter/i,g=`custom:${l}`;function R(a){let t=[document.documentElement],n=0;for(;t.length&&n<9e3;){let o=t.pop();if(n++,!o)continue;let e=o;if(e.nodeType===1&&e.tagName&&e.tagName.toLowerCase()===a)return e;e.shadowRoot&&t.push(e.shadowRoot);let i=o.children;if(i)for(let d of Array.from(i))t.push(d)}return null}function k(a){let t=a?.views;if(!Array.isArray(t)||!t.length)return null;let n=window.location.pathname.split("/").filter(Boolean).pop()||"",o=t.find(i=>i?.path===n);if(o)return o;let e=Number(n);return Number.isInteger(e)&&t[e]?t[e]:t[0]}function b(){try{let t=R("ha-panel-lovelace")?.lovelace;if(!t)return!1;let n=o=>o?.type;for(let o of[t.config,t.rawConfig]){if(!o)continue;if(n(o.strategy)===g)return!0;let e=k(o);if(e&&n(e.strategy)===g)return!0}return!1}catch{return!1}}function A(){let a=!1,t=0,n=!1,o=!1,e=[document.documentElement],i=0;for(;e.length&&i<9e3;){let d=e.pop();if(i++,!d)continue;let u=d;if(u.nodeType===1&&u.tagName){let s=u.tagName.toLowerCase();(s==="hui-view"||s==="hui-sections-view")&&(a=!0),(s==="ha-card"||s==="hui-card")&&t++,s==="hui-empty-state-card"&&(o=!0),s==="hui-error-card"&&f.test(u.textContent||"")&&(n=!0)}u.shadowRoot&&e.push(u.shadowRoot);let E=d.children;if(E)for(let s of Array.from(E))e.push(s)}return n?!0:o?!1:a&&t<3&&b()}let N="/maintenance_supporter_strategy_shim.js",y=0,_=0;function L(){let a=Date.now();a-_<5e3||y>=3||(_=a,y+=1,import(`${N}?heal=${a}`).catch(()=>{}).finally(()=>{let t=window.location.pathname+window.location.search;history.pushState(null,"","/lovelace"),window.dispatchEvent(new CustomEvent("location-changed")),window.setTimeout(()=>{history.pushState(null,"",t),window.dispatchEvent(new CustomEvent("location-changed"))},200)}))}function h(){if(c.test(window.location.pathname))return;let a=0,t=Date.now(),n=window.setInterval(()=>{a++;try{if(Date.now()-t<6e3)return;if(c.test(window.location.pathname)){window.clearInterval(n);return}A()?L():window.clearInterval(n),a>=30&&window.clearInterval(n)}catch{window.clearInterval(n)}},500)}try{document.readyState==="loading"?window.addEventListener("DOMContentLoaded",h):h(),window.addEventListener("location-changed",()=>{c.test(window.location.pathname)||h()})}catch{}})(); var S="2.71.0";var l="maintenance-supporter",T=`ll-strategy-dashboard-${l}`,D="hui-maintenance-supporter-strategy-editor",C=`/maintenance_supporter_strategy/maintenance-dashboard-strategy.js?v=${S}`,m=null;function v(){return m||(m=import(C)),m}async function I(){let r=await v();if(!r.MaintenanceDashboardStrategy)throw new Error("[maintenance-supporter] strategy bundle loaded but did not export MaintenanceDashboardStrategy");return r.MaintenanceDashboardStrategy}var p=class extends HTMLElement{static getCreateSuggestions(c){return{title:"Maintenance Supporter",icon:"mdi:wrench-clock"}}static async getConfigElement(){return await v(),document.createElement(D)}static async generate(c,f){return(await I()).generate(c,f)}};function M(){try{customElements.define(T,p)}catch{}}M();var w=window;w.customStrategies=w.customStrategies||[];w.customStrategies.some(r=>r.type===l&&r.strategyType==="dashboard")||w.customStrategies.push({type:l,strategyType:"dashboard",name:"Maintenance Supporter",description:"Auto-generated dashboard. Group views by area, status, floor, or due date \u2014 picked from the strategy editor or YAML.",documentationURL:"https://github.com/iluebbe/maintenance_supporter#dashboard-strategy"});(()=>{let r=window;if(r.__msStrategyHealActive)return;r.__msStrategyHealActive=!0;let c=/^\/(auth|config|developer-tools|profile|hassio|history|logbook|map|media-browser|energy|todo|calendar)\b/,f=/Timeout waiting for strategy element ll-strategy-(dashboard-)?maintenance-supporter/i,g=`custom:${l}`;function R(a){let t=[document.documentElement],n=0;for(;t.length&&n<9e3;){let o=t.pop();if(n++,!o)continue;let e=o;if(e.nodeType===1&&e.tagName&&e.tagName.toLowerCase()===a)return e;e.shadowRoot&&t.push(e.shadowRoot);let i=o.children;if(i)for(let d of Array.from(i))t.push(d)}return null}function k(a){let t=a?.views;if(!Array.isArray(t)||!t.length)return null;let n=window.location.pathname.split("/").filter(Boolean).pop()||"",o=t.find(i=>i?.path===n);if(o)return o;let e=Number(n);return Number.isInteger(e)&&t[e]?t[e]:t[0]}function b(){try{let t=R("ha-panel-lovelace")?.lovelace;if(!t)return!1;let n=o=>o?.type;for(let o of[t.config,t.rawConfig]){if(!o)continue;if(n(o.strategy)===g)return!0;let e=k(o);if(e&&n(e.strategy)===g)return!0}return!1}catch{return!1}}function A(){let a=!1,t=0,n=!1,o=!1,e=[document.documentElement],i=0;for(;e.length&&i<9e3;){let d=e.pop();if(i++,!d)continue;let u=d;if(u.nodeType===1&&u.tagName){let s=u.tagName.toLowerCase();(s==="hui-view"||s==="hui-sections-view")&&(a=!0),(s==="ha-card"||s==="hui-card")&&t++,s==="hui-empty-state-card"&&(o=!0),s==="hui-error-card"&&f.test(u.textContent||"")&&(n=!0)}u.shadowRoot&&e.push(u.shadowRoot);let E=d.children;if(E)for(let s of Array.from(E))e.push(s)}return n?!0:o?!1:a&&t<3&&b()}let N="/maintenance_supporter_strategy_shim.js",y=0,_=0;function L(){let a=Date.now();a-_<5e3||y>=3||(_=a,y+=1,import(`${N}?heal=${a}`).catch(()=>{}).finally(()=>{let t=window.location.pathname+window.location.search;history.pushState(null,"","/lovelace"),window.dispatchEvent(new CustomEvent("location-changed")),window.setTimeout(()=>{history.pushState(null,"",t),window.dispatchEvent(new CustomEvent("location-changed"))},200)}))}function h(){if(c.test(window.location.pathname))return;let a=0,t=Date.now(),n=window.setInterval(()=>{a++;try{if(Date.now()-t<6e3)return;if(c.test(window.location.pathname)){window.clearInterval(n);return}A()?L():window.clearInterval(n),a>=30&&window.clearInterval(n)}catch{window.clearInterval(n)}},500)}try{document.readyState==="loading"?window.addEventListener("DOMContentLoaded",h):h(),window.addEventListener("location-changed",()=>{c.test(window.location.pathname)||h()})}catch{}})();
@@ -1,5 +1,5 @@
/*! maintenance_supporter frontend 2.68.0 */ /*! maintenance_supporter frontend 2.71.0 */
import{a as f}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-MEZOPQBI.js";import{a as p}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PPH3NCFT.js";import{a as o,b as _,c as i,f as l,h,l as g,m as n,q as t,s as u,u as v}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YEY3J44W.js";var r=class extends h{constructor(){super(...arguments);this._open=!1;this._loading=!1;this._adopting=!1;this._error="";this._sensors=[];this._selected=new Set;this._users=[];this._responsible="";this._forMinutes="0";this._localeReady=!1;this._userService=null;this._toggle=s=>{let a=new Set(this._selected);a.has(s)?a.delete(s):a.add(s),this._selected=a};this._toggleAll=()=>{this._selected.size===this._sensors.length?this._selected=new Set:this._selected=new Set(this._sensors.map(s=>s.entity_id))};this._adopt=async()=>{if(!(this._selected.size===0||this._adopting)){this._adopting=!0,this._error="";try{let s=this._sensors.filter(e=>this._selected.has(e.entity_id)).map(e=>({entity_id:e.entity_id,name:e.name,entry_id:e.suggested_entry_id??void 0,object_name:e.suggested_object_name,device_id:e.device_id??void 0,part_id:e.suggested_part_id??void 0,responsible_user_id:this._responsible||void 0,for_minutes:parseInt(this._forMinutes,10)>0?parseInt(this._forMinutes,10):void 0})),a=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/problem_sensors/adopt",selections:s});this.dispatchEvent(new CustomEvent("problem-sensors-adopted",{bubbles:!0,composed:!0,detail:a})),this._open=!1}catch(s){this._error=p(s,this._lang)}finally{this._adopting=!1}}}}get _lang(){return u(this.hass)}updated(s){s.has("hass")&&this.hass&&!this._localeReady&&(this._localeReady=!0,v(this._lang).then(()=>this.requestUpdate()))}async open(){this._open=!0,this._loading=!0,this._error="",this._sensors=[],this._selected=new Set,this._responsible="",this._forMinutes="0";try{this._userService?this._userService.updateHass(this.hass):this._userService=new f(this.hass);let[s,a]=await Promise.all([this.hass.connection.sendMessagePromise({type:"maintenance_supporter/problem_sensors/discover"}),this._userService.getUsers().catch(()=>[])]);this._sensors=s.sensors||[],this._selected=new Set(this._sensors.map(e=>e.entity_id)),this._users=a}catch(s){this._error=p(s,this._lang)}finally{this._loading=!1}}_close(){this._open=!1}render(){if(!this._open)return i``;let s=this._lang,a=this._sensors.length>0&&this._selected.size===this._sensors.length;return i` import{a as f}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-JSPW4Q6Q.js";import{a as p}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-GJI3RTUI.js";import{a as o,b as _,c as i,f as l,h,l as g,m as n,q as t,s as u,u as v}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PBRIQQ2X.js";var r=class extends h{constructor(){super(...arguments);this._open=!1;this._loading=!1;this._adopting=!1;this._error="";this._sensors=[];this._selected=new Set;this._users=[];this._responsible="";this._forMinutes="0";this._localeReady=!1;this._userService=null;this._toggle=s=>{let a=new Set(this._selected);a.has(s)?a.delete(s):a.add(s),this._selected=a};this._toggleAll=()=>{this._selected.size===this._sensors.length?this._selected=new Set:this._selected=new Set(this._sensors.map(s=>s.entity_id))};this._adopt=async()=>{if(!(this._selected.size===0||this._adopting)){this._adopting=!0,this._error="";try{let s=this._sensors.filter(e=>this._selected.has(e.entity_id)).map(e=>({entity_id:e.entity_id,name:e.name,entry_id:e.suggested_entry_id??void 0,object_name:e.suggested_object_name,device_id:e.device_id??void 0,part_id:e.suggested_part_id??void 0,responsible_user_id:this._responsible||void 0,for_minutes:parseInt(this._forMinutes,10)>0?parseInt(this._forMinutes,10):void 0})),a=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/problem_sensors/adopt",selections:s});this.dispatchEvent(new CustomEvent("problem-sensors-adopted",{bubbles:!0,composed:!0,detail:a})),this._open=!1}catch(s){this._error=p(s,this._lang)}finally{this._adopting=!1}}}}get _lang(){return u(this.hass)}updated(s){s.has("hass")&&this.hass&&!this._localeReady&&(this._localeReady=!0,v(this._lang).then(()=>this.requestUpdate()))}async open(){this._open=!0,this._loading=!0,this._error="",this._sensors=[],this._selected=new Set,this._responsible="",this._forMinutes="0";try{this._userService?this._userService.updateHass(this.hass):this._userService=new f(this.hass);let[s,a]=await Promise.all([this.hass.connection.sendMessagePromise({type:"maintenance_supporter/problem_sensors/discover"}),this._userService.getUsers().catch(()=>[])]);this._sensors=s.sensors||[],this._selected=new Set(this._sensors.map(e=>e.entity_id)),this._users=a}catch(s){this._error=p(s,this._lang)}finally{this._loading=!1}}_close(){this._open=!1}render(){if(!this._open)return i``;let s=this._lang,a=this._sensors.length>0&&this._selected.size===this._sensors.length;return i`
<div class="overlay" @click=${this._close}> <div class="overlay" @click=${this._close}>
<div class="card" @click=${e=>e.stopPropagation()}> <div class="card" @click=${e=>e.stopPropagation()}>
<div class="title">${t("adopt_problem_title",s)}</div> <div class="title">${t("adopt_problem_title",s)}</div>
@@ -1,250 +0,0 @@
/*! maintenance_supporter frontend 2.70.0 */
import{a as f}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-J4OBOTUE.js";import{a as p}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-KKI2ZPWC.js";import{a as o,b as _,c as i,f as l,h,l as g,m as n,q as t,s as u,u as v}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-VSV22GFT.js";var r=class extends h{constructor(){super(...arguments);this._open=!1;this._loading=!1;this._adopting=!1;this._error="";this._sensors=[];this._selected=new Set;this._users=[];this._responsible="";this._forMinutes="0";this._localeReady=!1;this._userService=null;this._toggle=s=>{let a=new Set(this._selected);a.has(s)?a.delete(s):a.add(s),this._selected=a};this._toggleAll=()=>{this._selected.size===this._sensors.length?this._selected=new Set:this._selected=new Set(this._sensors.map(s=>s.entity_id))};this._adopt=async()=>{if(!(this._selected.size===0||this._adopting)){this._adopting=!0,this._error="";try{let s=this._sensors.filter(e=>this._selected.has(e.entity_id)).map(e=>({entity_id:e.entity_id,name:e.name,entry_id:e.suggested_entry_id??void 0,object_name:e.suggested_object_name,device_id:e.device_id??void 0,part_id:e.suggested_part_id??void 0,responsible_user_id:this._responsible||void 0,for_minutes:parseInt(this._forMinutes,10)>0?parseInt(this._forMinutes,10):void 0})),a=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/problem_sensors/adopt",selections:s});this.dispatchEvent(new CustomEvent("problem-sensors-adopted",{bubbles:!0,composed:!0,detail:a})),this._open=!1}catch(s){this._error=p(s,this._lang)}finally{this._adopting=!1}}}}get _lang(){return u(this.hass)}updated(s){s.has("hass")&&this.hass&&!this._localeReady&&(this._localeReady=!0,v(this._lang).then(()=>this.requestUpdate()))}async open(){this._open=!0,this._loading=!0,this._error="",this._sensors=[],this._selected=new Set,this._responsible="",this._forMinutes="0";try{this._userService?this._userService.updateHass(this.hass):this._userService=new f(this.hass);let[s,a]=await Promise.all([this.hass.connection.sendMessagePromise({type:"maintenance_supporter/problem_sensors/discover"}),this._userService.getUsers().catch(()=>[])]);this._sensors=s.sensors||[],this._selected=new Set(this._sensors.map(e=>e.entity_id)),this._users=a}catch(s){this._error=p(s,this._lang)}finally{this._loading=!1}}_close(){this._open=!1}render(){if(!this._open)return i``;let s=this._lang,a=this._sensors.length>0&&this._selected.size===this._sensors.length;return i`
<div class="overlay" @click=${this._close}>
<div class="card" @click=${e=>e.stopPropagation()}>
<div class="title">${t("adopt_problem_title",s)}</div>
<div class="hint">${t("adopt_problem_hint",s)}</div>
${this._error?i`<div class="error">${this._error}</div>`:l}
${this._loading?i`<div class="loading">…</div>`:this._sensors.length===0?i`<div class="empty">${t("adopt_problem_none",s)}</div>`:i`
<label class="select-all">
<input
type="checkbox"
.checked=${a}
@change=${this._toggleAll}
/>
<span>${t("selected",s)}: ${this._selected.size} / ${this._sensors.length}</span>
</label>
<div class="list">
${this._sensors.map(e=>{let m=this._selected.has(e.entity_id),d=e.state==="on",c=[e.device_name,e.area_name].filter(Boolean).join(" \xB7 ");return i`
<label class="row">
<input
type="checkbox"
.checked=${m}
@change=${()=>this._toggle(e.entity_id)}
/>
<div class="row-main">
<div class="row-top">
<span class="row-name">${e.name}</span>
<span class="chip ${d?"chip-active":"chip-ok"}">
${d?t("adopt_problem_active",s):t("adopt_problem_ok",s)}
</span>
</div>
${c?i`<div class="row-sub">${c}</div>`:l}
<div class="row-target">
→ ${e.suggested_object_name}${e.suggested_entry_id?l:i` <span class="new-tag">${t("adopt_problem_new_object",s)}</span>`}
</div>
${e.suggested_part_name?i`<div class="row-part">
<ha-icon icon="mdi:package-variant-closed"></ha-icon>
${t("adopt_problem_part",s).replace("{name}",e.suggested_part_name)}
</div>`:l}
</div>
</label>
`})}
</div>
`}
${!this._loading&&this._sensors.length>0?i`
<label class="responsible">
<span>${t("for_at_least_minutes",s)}</span>
<input
class="for-input"
type="number"
min="0"
max="1440"
.value=${this._forMinutes}
@input=${e=>this._forMinutes=e.target.value}
/>
</label>
<div class="for-hint">${t("adopt_for_minutes_hint",s)}</div>
`:l}
${!this._loading&&this._sensors.length>0&&this._users.length>0?i`
<label class="responsible">
<span>${t("adopt_problem_responsible",s)}</span>
<select
.value=${this._responsible}
@change=${e=>{this._responsible=e.target.value}}
>
<option value="" ?selected=${!this._responsible}>${t("no_user_assigned",s)}</option>
${this._users.map(e=>i`<option value=${e.id} ?selected=${e.id===this._responsible}>${e.name}</option>`)}
</select>
</label>
`:l}
<div class="actions">
<ha-button appearance="plain" @click=${this._close}>
${t("cancel",s)}
</ha-button>
<ha-button
@click=${this._adopt}
.disabled=${this._selected.size===0||this._adopting}
>
${t("adopt_problem_adopt",s)}
</ha-button>
</div>
</div>
</div>
`}};r.styles=_`
.overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.card {
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
border-radius: 12px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 12px;
min-width: min(360px, calc(100vw - 24px));
max-width: 560px;
width: 90vw;
max-height: 80vh;
overflow: hidden;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}
.title {
font-size: 18px;
font-weight: 500;
}
.hint {
color: var(--secondary-text-color);
font-size: 13px;
}
.error {
color: var(--error-color, #f44336);
font-size: 13px;
}
.loading,
.empty {
color: var(--secondary-text-color);
font-size: 14px;
padding: 12px 0;
}
.select-all {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--secondary-text-color);
cursor: pointer;
}
.select-all input {
cursor: pointer;
}
.list {
display: flex;
flex-direction: column;
gap: 6px;
overflow-y: auto;
max-height: 50vh;
}
.row {
display: flex;
align-items: flex-start;
gap: 10px;
padding: 8px;
border: 1px solid var(--divider-color);
border-radius: 6px;
cursor: pointer;
}
.row input {
margin-top: 2px;
cursor: pointer;
}
.row-main {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
flex: 1;
}
.row-top {
display: flex;
align-items: center;
gap: 8px;
}
.row-name {
font-weight: 500;
font-size: 13px;
}
.row-sub {
color: var(--secondary-text-color);
font-size: 12px;
}
.row-target {
color: var(--secondary-text-color);
font-size: 12px;
}
.row-part {
color: var(--secondary-text-color);
font-size: 12px;
display: flex;
align-items: center;
gap: 4px;
}
.row-part ha-icon {
--mdc-icon-size: 14px;
}
.new-tag {
font-style: italic;
}
.chip {
font-size: 11px;
padding: 1px 8px;
border-radius: 10px;
white-space: nowrap;
}
.chip-active {
background: var(--error-color, #f44336);
color: #fff;
}
.chip-ok {
background: var(--divider-color);
color: var(--secondary-text-color);
}
.responsible {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--secondary-text-color);
flex-wrap: wrap;
}
.for-input {
width: 70px;
background: var(--card-background-color);
color: var(--primary-text-color);
border: 1px solid var(--divider-color);
border-radius: 4px;
padding: 4px 6px;
}
.for-hint {
font-size: 11px;
color: var(--secondary-text-color);
margin: -4px 0 2px;
}
.responsible select {
flex: 1;
min-width: 140px;
padding: 4px 6px;
border-radius: 4px;
border: 1px solid var(--divider-color);
background: var(--card-background-color, #fff);
color: var(--primary-text-color);
font-size: 13px;
}
.actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding-top: 8px;
}
`,o([g({attribute:!1})],r.prototype,"hass",2),o([n()],r.prototype,"_open",2),o([n()],r.prototype,"_loading",2),o([n()],r.prototype,"_adopting",2),o([n()],r.prototype,"_error",2),o([n()],r.prototype,"_sensors",2),o([n()],r.prototype,"_selected",2),o([n()],r.prototype,"_users",2),o([n()],r.prototype,"_responsible",2),o([n()],r.prototype,"_forMinutes",2);customElements.get("maintenance-adopt-problem-sensors-dialog")||customElements.define("maintenance-adopt-problem-sensors-dialog",r);export{r as MaintenanceAdoptProblemSensorsDialog};
@@ -1,2 +0,0 @@
/*! maintenance_supporter frontend 2.70.0 */
function c(o,t,e){let l=new Blob([o],{type:e}),d=URL.createObjectURL(l),n=document.createElement("a");n.href=d,n.download=t,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(d),6e4)}function r(o,t){let e=document.createElement("a");e.href=o,e.download=t,e.target="_blank",e.rel="noopener",e.style.display="none",document.body.appendChild(e),e.dispatchEvent(new MouseEvent("click")),document.body.removeChild(e)}export{c as a,r as b};
@@ -1,14 +1,14 @@
/*! maintenance_supporter frontend 2.68.0 */ /*! maintenance_supporter frontend 2.71.0 */
import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-CPVQNQQQ.js";import{a as M}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-MEZOPQBI.js";import{a as R}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PPH3NCFT.js";import{a,b as L,c as o,f as p,h as N,l as $,m as l,q as s,s as H,v as F,z as S}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YEY3J44W.js";var C=["sensor","binary_sensor","number","input_number","input_boolean","switch","climate","vacuum","cover","fan","light","water_heater","humidifier","media_player","weather","air_quality","valve","lawn_mower","lock"],O=["sensor"],U=["temperature","humidity","pressure"];var z=["cleaning","inspection","replacement","calibration","service","reading","custom"],V=["low","normal","high"],W=["time_based","weekdays","nth_weekday","day_of_month","sensor_based","one_time","manual"],A=["weekdays","nth_weekday","day_of_month"],D=["threshold","counter","state_change","runtime"],K=[...D,"compound"],y={alpha:"0.3",min:"7",max:"365"};function Y(){return{entityIds:"",type:"threshold",attribute:"",above:"",below:"",equals:"",notEquals:"",forMinutes:"0",targetValue:"",deltaMode:!1,fromState:"",toState:"",targetChanges:"",runtimeHours:"",onStates:"",carry:{}}}var J=new Set(["entity_id","entity_ids","type","attribute","trigger_above","trigger_below","trigger_equals","trigger_not_equals","trigger_for_minutes","trigger_target_value","trigger_delta_mode","trigger_from_state","trigger_to_state","trigger_target_changes","trigger_runtime_hours","trigger_on_states"]);function G(u){return{entityIds:(u.entity_ids||(u.entity_id?[u.entity_id]:[])).join(", "),type:u.type||"threshold",attribute:u.attribute||"",above:u.trigger_above?.toString()??"",below:u.trigger_below?.toString()??"",equals:u.trigger_equals?.toString()??"",notEquals:u.trigger_not_equals?.toString()??"",forMinutes:u.trigger_for_minutes?.toString()??"0",targetValue:u.trigger_target_value?.toString()??"",deltaMode:u.trigger_delta_mode||!1,fromState:u.trigger_from_state||"",toState:u.trigger_to_state||"",targetChanges:u.trigger_target_changes?.toString()??"",runtimeHours:u.trigger_runtime_hours?.toString()??"",onStates:(u.trigger_on_states||[]).join(", "),carry:Object.fromEntries(Object.entries(u).filter(([e])=>!J.has(e)&&!e.startsWith("_")))}}function Q(u){let b=u.entityIds.split(",").map(i=>i.trim()).filter(Boolean);if(b.length===0)return null;let e={...u.carry||{},entity_id:b[0],entity_ids:b,type:u.type};if(u.attribute&&(e.attribute=u.attribute),u.type==="threshold"){let i=parseFloat(u.above);isNaN(i)||(e.trigger_above=i);let t=parseFloat(u.below);isNaN(t)||(e.trigger_below=t);let r=parseFloat(u.equals);isNaN(r)||(e.trigger_equals=r);let h=parseFloat(u.notEquals);isNaN(h)||(e.trigger_not_equals=h);let _=parseInt(u.forMinutes,10);isNaN(_)||(e.trigger_for_minutes=_)}else if(u.type==="counter"){let i=parseFloat(u.targetValue);isNaN(i)||(e.trigger_target_value=i),e.trigger_delta_mode=u.deltaMode}else if(u.type==="state_change"){u.fromState&&(e.trigger_from_state=u.fromState),u.toState&&(e.trigger_to_state=u.toState);let i=parseInt(u.targetChanges,10);isNaN(i)||(e.trigger_target_changes=i)}else if(u.type==="runtime"){let i=parseFloat(u.runtimeHours);isNaN(i)||(e.trigger_runtime_hours=i);let t=(u.onStates||"").split(",").map(r=>r.trim()).filter(Boolean);t.length>0&&(e.trigger_on_states=t)}return e}function X(u){return Array.from({length:7},(b,e)=>S(e,u,"short"))}function Z(u){let b=new Intl.DateTimeFormat(u||"en",{month:"short"});return Array.from({length:12},(e,i)=>b.format(new Date(2021,i,1)))}var n=class n extends N{constructor(){super(...arguments);this.checklistsEnabled=!1;this.scheduleTimeEnabled=!1;this.completionActionsEnabled=!1;this.defaultWarningDays=7;this.parts=[];this._foreignOwners=[];this._open=!1;this._entityPickerFallback=!1;this._pickerProbeStrikes=0;this._loading=!1;this._error="";this._entryId="";this._taskId=null;this._objectChoices=[];this._name="";this._type="custom";this._scheduleType="time_based";this._intervalDays="30";this._intervalUnit="days";this._dueDate="";this._warningDays="7";this._earliestCompletionDays="";this._intervalAnchor="completion";this._weekdays=[];this._nth="1";this._nthWeekday="5";this._domDay="1";this._domLastDay=!1;this._domBusiness=!1;this._calOffset="0";this._seasonMonths=[];this._endsMode="never";this._endsCount="";this._endsUntil="";this._schedulePreview=[];this._schedulePreviewEnded=!1;this._previewSeq=0;this._notes="";this._documentationUrl="";this._customIcon="";this._priority="normal";this._labels="";this._enabled=!0;this._triggerEntityId="";this._triggerEntityIds=[];this._triggerEntityLogic="any";this._triggerAttribute="";this._triggerType="threshold";this._triggerAbove="";this._triggerBelow="";this._triggerEquals="";this._triggerNotEquals="";this._triggerForMinutes="0";this._triggerCombinator="any";this._triggerTargetValue="";this._triggerDeltaMode=!1;this._triggerBaselineValue="";this._liveBaselineValue=null;Line truncated import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-WQQNFFGB.js";import{a as M}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-JSPW4Q6Q.js";import{a as R}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-GJI3RTUI.js";import{a,b as L,c as o,f as p,h as N,l as $,m as l,q as s,s as H,v as F,z as S}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PBRIQQ2X.js";var C=["sensor","binary_sensor","number","input_number","input_boolean","switch","climate","vacuum","cover","fan","light","water_heater","humidifier","media_player","weather","air_quality","valve","lawn_mower","lock"],O=["sensor"],U=["temperature","humidity","pressure"];var z=["cleaning","inspection","replacement","calibration","service","reading","custom"],V=["low","normal","high"],W=["time_based","weekdays","nth_weekday","day_of_month","sensor_based","one_time","manual"],A=["weekdays","nth_weekday","day_of_month"],D=["threshold","counter","state_change","runtime"],K=[...D,"compound"],y={alpha:"0.3",min:"7",max:"365"};function Y(){return{entityIds:"",type:"threshold",attribute:"",above:"",below:"",equals:"",notEquals:"",forMinutes:"0",targetValue:"",deltaMode:!1,fromState:"",toState:"",targetChanges:"",runtimeHours:"",onStates:"",carry:{}}}var J=new Set(["entity_id","entity_ids","type","attribute","trigger_above","trigger_below","trigger_equals","trigger_not_equals","trigger_for_minutes","trigger_target_value","trigger_delta_mode","trigger_from_state","trigger_to_state","trigger_target_changes","trigger_runtime_hours","trigger_on_states"]);function G(u){return{entityIds:(u.entity_ids||(u.entity_id?[u.entity_id]:[])).join(", "),type:u.type||"threshold",attribute:u.attribute||"",above:u.trigger_above?.toString()??"",below:u.trigger_below?.toString()??"",equals:u.trigger_equals?.toString()??"",notEquals:u.trigger_not_equals?.toString()??"",forMinutes:u.trigger_for_minutes?.toString()??"0",targetValue:u.trigger_target_value?.toString()??"",deltaMode:u.trigger_delta_mode||!1,fromState:u.trigger_from_state||"",toState:u.trigger_to_state||"",targetChanges:u.trigger_target_changes?.toString()??"",runtimeHours:u.trigger_runtime_hours?.toString()??"",onStates:(u.trigger_on_states||[]).join(", "),carry:Object.fromEntries(Object.entries(u).filter(([e])=>!J.has(e)&&!e.startsWith("_")))}}function Q(u){let b=u.entityIds.split(",").map(i=>i.trim()).filter(Boolean);if(b.length===0)return null;let e={...u.carry||{},entity_id:b[0],entity_ids:b,type:u.type};if(u.attribute&&(e.attribute=u.attribute),u.type==="threshold"){let i=parseFloat(u.above);isNaN(i)||(e.trigger_above=i);let t=parseFloat(u.below);isNaN(t)||(e.trigger_below=t);let r=parseFloat(u.equals);isNaN(r)||(e.trigger_equals=r);let h=parseFloat(u.notEquals);isNaN(h)||(e.trigger_not_equals=h);let c=parseInt(u.forMinutes,10);isNaN(c)||(e.trigger_for_minutes=c)}else if(u.type==="counter"){let i=parseFloat(u.targetValue);isNaN(i)||(e.trigger_target_value=i),e.trigger_delta_mode=u.deltaMode}else if(u.type==="state_change"){u.fromState&&(e.trigger_from_state=u.fromState),u.toState&&(e.trigger_to_state=u.toState);let i=parseInt(u.targetChanges,10);isNaN(i)||(e.trigger_target_changes=i)}else if(u.type==="runtime"){let i=parseFloat(u.runtimeHours);isNaN(i)||(e.trigger_runtime_hours=i);let t=(u.onStates||"").split(",").map(r=>r.trim()).filter(Boolean);t.length>0&&(e.trigger_on_states=t)}return e}function X(u){return Array.from({length:7},(b,e)=>S(e,u,"short"))}function Z(u){let b=new Intl.DateTimeFormat(u||"en",{month:"short"});return Array.from({length:12},(e,i)=>b.format(new Date(2021,i,1)))}var n=class n extends N{constructor(){super(...arguments);this.checklistsEnabled=!1;this.scheduleTimeEnabled=!1;this.completionActionsEnabled=!1;this.defaultWarningDays=7;this.parts=[];this._foreignOwners=[];this._open=!1;this._entityPickerFallback=!1;this._pickerProbeStrikes=0;this._loading=!1;this._error="";this._entryId="";this._taskId=null;this._objectChoices=[];this._name="";this._type="custom";this._scheduleType="time_based";this._intervalDays="30";this._intervalUnit="days";this._dueDate="";this._warningDays="7";this._earliestCompletionDays="";this._intervalAnchor="completion";this._weekdays=[];this._nth="1";this._nthWeekday="5";this._domDay="1";this._domLastDay=!1;this._domBusiness=!1;this._calOffset="0";this._seasonMonths=[];this._endsMode="never";this._endsCount="";this._endsUntil="";this._schedulePreview=[];this._schedulePreviewEnded=!1;this._previewSeq=0;this._notes="";this._documentationUrl="";this._customIcon="";this._priority="normal";this._labels="";this._enabled=!0;this._triggerEntityId="";this._triggerEntityIds=[];this._triggerEntityLogic="any";this._triggerAttribute="";this._triggerType="threshold";this._triggerAbove="";this._triggerBelow="";this._triggerEquals="";this._triggerNotEquals="";this._triggerForMinutes="0";this._triggerCombinator="any";this._triggerTargetValue="";this._triggerDeltaMode=!1;this._triggerBaselineValue="";this._liveBaselineValue=null;Line truncated
`),this._phaseDefs=Object.entries(i.phases||{}).map(([d,g])=>{let{name:v,checklist:m,consumes_parts:f,required_completion_fields:ee,...j}=g,x=g.consumes_parts||[],I=x.findIndex(E=>!E.entry_id),w=I>=0?x[I]:void 0;return{id:d,name:g.name||d,checklistText:(g.checklist||[]).join(` `),this._phaseDefs=Object.entries(i.phases||{}).map(([d,g])=>{let{name:v,checklist:m,consumes_parts:f,required_completion_fields:ee,...j}=g,x=g.consumes_parts||[],w=x.findIndex(E=>!E.entry_id),I=w>=0?x[w]:void 0;return{id:d,name:g.name||d,checklistText:(g.checklist||[]).join(`
`),partId:w?.part_id||"",partQty:w?.quantity!=null?String(w.quantity):"",reqOverride:g.required_completion_fields!==void 0,reqFields:[...g.required_completion_fields||[]],extraParts:x.filter((E,B)=>B!==I).map(E=>({...E})),carry:j}}),this._phaseSeq=[...i.phase_sequence||[]],this._requiredCompletion=[...i.required_completion_fields||[]],this._scheduleTime=i.schedule_time||"";let h=i.on_complete_action;if(h&&h.service){this._actionService=h.service;let d=h.target?.entity_id;this._actionTargetEntity=Array.isArray(d)?d[0]||"":d||"",this._actionData=h.data&&typeof h.data=="object"?{...h.data}:{},this._actionDataJsonFallback=""}else this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="";let _=i.quick_complete_defaults;this._qcNotes=_?.notes||"",this._qcCost=_?.cost!=null?String(_.cost):"",this._qcDuration=_?.duration!=null?String(_.duration):"",this._qcFeedback=_?.feedback||"";let c=i.adaptive_config||{};if(this._environmentalEntity=c.environmental_entity||"",this._environmentalAttribute=c.environmental_attribute||"",this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute,this._adaptiveEnabled=!!c.enabled,this._adaptiveAlpha=c.ewa_alpha?.toString()??y.alpha,this._adaptiveMin=c.min_interval_days?.toString()??y.min,this._adaptiveMax=c.max_interval_days?.toString()??y.max,this._adaptiveSeasonal=c.seasonal_enabled!==!1,this._adaptivePrediction=c.sensor_prediction_enabled!==!1,this._adaptiveInitial=this._adaptiveSnapshot(),i.trigger_config){let d=i.trigger_config;this._triggerEntityId=d.entity_id||d.entity_ids&&d.entity_ids[0]||"",this._triggerEntityIds=d.entity_ids||(d.entity_id?[d.entity_id]:[]),this._triggerEntityLogic=d.entity_logic||"any",this._triggerAttribute=d.attribute||"",this._triggerType=d.type||"threshold",this._triggerAbove=d.trigger_above?.toString()||"",this._triggerBelow=d.trigger_below?.toString()||"",this._triggerEquals=d.trigger_equals?.toString()||"",this._triggerNotEquals=d.trigger_not_equals?.toString()||"",this._triggerForMinutes=d.trigger_for_minutes?.toString()||"0",this._triggerCombinator=d.trigger_combinator==="all"?"all":"any",this._triggerTargetValue=d.trigger_target_value?.toString()||"",this._triggerDeltaMode=d.trigger_delta_mode||!1,this._triggerBaselineValue=d.trigger_baseline_value?.toString()||"",this._liveBaselineValue=i.trigger_baseline_value??null,this._autoCompleteOnRecovery=d.auto_complete_on_recovery||!1,this._triggerFromState=d.trigger_from_state||"",this._triggerToState=d.trigger_to_state||"",this._triggerTargetChanges=d.trigger_target_changes?.toString()||"",this._triggerRuntimeHours=d.trigger_runtime_hours?.toString()||"",this._triggerOnStates=(d.trigger_on_states||[]).join(", "),d.type==="compound"?(this._compoundLogic=d.compound_logic==="OR"?"OR":"AND",this._compoundConditions=(d.conditions||[]).map(G)):(this._compoundLogic="AND",this._compoundConditions=[])}else this._resetTriggerFields();this._triggerEntityId&&this._fetchEntityAttributes(this._triggerEntityId),await Promise.all([this._loadUsers(),this._loadTags(),this._loadParts(),this._loadForeignPools()]),this._open=!0}_resetFields(){this._name="",this._type="custom",this._scheduleType="time_based",this._intervalDays="30",this._intervalUnit="days",this._dueDate="",this._warningDays=String(this.defaultWarningDays),this._earliestCompletionDays="",this._intervalAnchor="completion",this._weekdays=[],this._nth="1",this._nthWeekday="5",this._domDay="1",this._domLastDay=!1,this._domBusiness=!1,this._calOffset="0",this._seasonMonths=[],this._endsMode="never",this._endsCount="",this._endsUntil="",this._notes="",this._documentationUrl="",this._customIcon="",this._priority="normal",this._labels="",this._enabled=!0,this._lastPerformed="",this._nfcTagId="",this._requireTagScan=!1,this._readingUnit="",this._consumesParts={},this._responsibleUserId=null,this._assigneePool=[],this._rotationStrategy="",this._checklistText="",this._phaseDefs=[],this._phaseSeq=[],this._requiredCompletion=[],this._scheduleTime="",this._environmentalEntity="",this._environmentalAttribute="",this._environmentalInitial="",this._environmentalAttributeInitial="",this._adaptiveEnabled=!1,this._adaptiveAlpha=y.alpha,this._adaptiveMin=y.min,this._adaptiveMax=y.max,this._adaptiveSeasonal=!0,this._adaptivePrediction=!0,this._adaptiveInitial=this._adaptiveSnapshot(),this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="",this._actionTesting=!1,this._actionTestResult="",this._qcNotes="",this._qcCost="",this._qcDuration="",this._qcFeedback="",this._resetTriggerFields()}_resetTriggerFields(){this._triggerEntityId="",this._triggerEntityIds=[],this._triggerEntityLogic="any",this._triggerAttribute="",this._suggestedAttributes=[],this._availableAttributes=[],this._entityDomain="",this._triggerType="threshold",this._triggerAbove="",this._triggerBelow="",this._triggerEquals="",this._triggerNotEquals="",this._triggerFor Line truncated `),partId:I?.part_id||"",partQty:I?.quantity!=null?String(I.quantity):"",reqOverride:g.required_completion_fields!==void 0,reqFields:[...g.required_completion_fields||[]],extraParts:x.filter((E,B)=>B!==w).map(E=>({...E})),carry:j}}),this._phaseSeq=[...i.phase_sequence||[]],this._requiredCompletion=[...i.required_completion_fields||[]],this._scheduleTime=i.schedule_time||"";let h=i.on_complete_action;if(h&&h.service){this._actionService=h.service;let d=h.target?.entity_id;this._actionTargetEntity=Array.isArray(d)?d[0]||"":d||"",this._actionData=h.data&&typeof h.data=="object"?{...h.data}:{},this._actionDataJsonFallback=""}else this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="";let c=i.quick_complete_defaults;this._qcNotes=c?.notes||"",this._qcCost=c?.cost!=null?String(c.cost):"",this._qcDuration=c?.duration!=null?String(c.duration):"",this._qcFeedback=c?.feedback||"";let _=i.adaptive_config||{};if(this._environmentalEntity=_.environmental_entity||"",this._environmentalAttribute=_.environmental_attribute||"",this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute,this._adaptiveEnabled=!!_.enabled,this._adaptiveAlpha=_.ewa_alpha?.toString()??y.alpha,this._adaptiveMin=_.min_interval_days?.toString()??y.min,this._adaptiveMax=_.max_interval_days?.toString()??y.max,this._adaptiveSeasonal=_.seasonal_enabled!==!1,this._adaptivePrediction=_.sensor_prediction_enabled!==!1,this._adaptiveInitial=this._adaptiveSnapshot(),i.trigger_config){let d=i.trigger_config;this._triggerEntityId=d.entity_id||d.entity_ids&&d.entity_ids[0]||"",this._triggerEntityIds=d.entity_ids||(d.entity_id?[d.entity_id]:[]),this._triggerEntityLogic=d.entity_logic||"any",this._triggerAttribute=d.attribute||"",this._triggerType=d.type||"threshold",this._triggerAbove=d.trigger_above?.toString()||"",this._triggerBelow=d.trigger_below?.toString()||"",this._triggerEquals=d.trigger_equals?.toString()||"",this._triggerNotEquals=d.trigger_not_equals?.toString()||"",this._triggerForMinutes=d.trigger_for_minutes?.toString()||"0",this._triggerCombinator=d.trigger_combinator==="all"?"all":"any",this._triggerTargetValue=d.trigger_target_value?.toString()||"",this._triggerDeltaMode=d.trigger_delta_mode||!1,this._triggerBaselineValue=d.trigger_baseline_value?.toString()||"",this._liveBaselineValue=i.trigger_baseline_value??null,this._autoCompleteOnRecovery=d.auto_complete_on_recovery||!1,this._triggerFromState=d.trigger_from_state||"",this._triggerToState=d.trigger_to_state||"",this._triggerTargetChanges=d.trigger_target_changes?.toString()||"",this._triggerRuntimeHours=d.trigger_runtime_hours?.toString()||"",this._triggerRuntimeMaxSession=d.trigger_runtime_max_session_seconds?.toString()||"",this._triggerOnStates=(d.trigger_on_states||[]).join(", "),d.type==="compound"?(this._compoundLogic=d.compound_logic==="OR"?"OR":"AND",this._compoundConditions=(d.conditions||[]).map(G)):(this._compoundLogic="AND",this._compoundConditions=[])}else this._resetTriggerFields();this._triggerEntityId&&this._fetchEntityAttributes(this._triggerEntityId),await Promise.all([this._loadUsers(),this._loadTags(),this._loadParts(),this._loadForeignPools()]),this._open=!0}_resetFields(){this._name="",this._type="custom",this._scheduleType="time_based",this._intervalDays="30",this._intervalUnit="days",this._dueDate="",this._warningDays=String(this.defaultWarningDays),this._earliestCompletionDays="",this._intervalAnchor="completion",this._weekdays=[],this._nth="1",this._nthWeekday="5",this._domDay="1",this._domLastDay=!1,this._domBusiness=!1,this._calOffset="0",this._seasonMonths=[],this._endsMode="never",this._endsCount="",this._endsUntil="",this._notes="",this._documentationUrl="",this._customIcon="",this._priority="normal",this._labels="",this._enabled=!0,this._lastPerformed="",this._nfcTagId="",this._requireTagScan=!1,this._allowSkip=!0,this._readingUnit="",this._consumesParts={},this._responsibleUserId=null,this._assigneePool=[],this._rotationStrategy="",this._checklistText="",this._phaseDefs=[],this._phaseSeq=[],this._requiredCompletion=[],this._scheduleTime="",this._environmentalEntity="",this._environmentalAttribute="",this._environmentalInitial="",this._environmentalAttributeInitial="",this._adaptiveEnabled=!1,this._adaptiveAlpha=y.alpha,this._adaptiveMin=y.min,this._adaptiveMax=y.max,this._adaptiveSeasonal=!0,this._adaptivePrediction=!0,this._adaptiveInitial=this._adaptiveSnapshot(),this._actionService="",this._actionTargetEntity="",this._actionData={},this._actionDataJsonFallback="",this._actionTesting=!1,this._actionTestResult="",this._qcNotes="",this._qcCost="",this._qcDuration="",this._qcFeedback="",this._resetTriggerFields()}_resetTriggerFields(){this._triggerEntityId="",this._triggerEntityIds=[],this._triggerEntityLogic="any",this._triggerAttribute="",this._suggestedAttributes=[],this._availableAttributes=[],this._entityDomain="",this._triggerType="threshold",this. Line truncated
<details class="ca-section"> <details class="ca-section">
<summary>${s("on_complete_action_title",e)}</summary> <summary>${s("on_complete_action_title",e)}</summary>
<p class="field-help">${s("on_complete_action_desc",e)}</p> <p class="field-help">${s("on_complete_action_desc",e)}</p>
<ha-service-picker <ha-service-picker
.hass=${this.hass} .hass=${this.hass}
.value=${this._actionService} .value=${this._actionService}
@value-changed=${t=>{this._actionService=t.detail.value||"";let r=this._serviceSchema();if(r){let h=new Set(r.map(_=>_.name));this._actionData=Object.fromEntries(Object.entries(this._actionData).filter(([_])=>h.has(_)))}}} @value-changed=${t=>{this._actionService=t.detail.value||"";let r=this._serviceSchema();if(r){let h=new Set(r.map(c=>c.name));this._actionData=Object.fromEntries(Object.entries(this._actionData).filter(([c])=>h.has(c)))}}}
></ha-service-picker> ></ha-service-picker>
<ha-form <ha-form
.hass=${this.hass} .hass=${this.hass}
@@ -83,7 +83,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
<input <input
type="checkbox" type="checkbox"
.checked=${r!==void 0} .checked=${r!==void 0}
@change=${_=>{let c={...this._consumesParts};_.target.checked?c[t]=c[t]||h:delete c[t],this._consumesParts=c}} @change=${c=>{let _={...this._consumesParts};c.target.checked?_[t]=_[t]||h:delete _[t],this._consumesParts=_}}
/> />
<span>${e.name}${e.unit?` (${e.unit})`:""}</span> <span>${e.name}${e.unit?` (${e.unit})`:""}</span>
</label> </label>
@@ -94,7 +94,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
max="999" max="999"
step="0.01" step="0.01"
.value=${String(r.quantity)} .value=${String(r.quantity)}
@input=${_=>{let c=parseFloat(_.target.value);this._consumesParts={...this._consumesParts,[t]:{...h,quantity:Number.isFinite(c)&&c>=.01?c:1}}}} @input=${c=>{let _=parseFloat(c.target.value);this._consumesParts={...this._consumesParts,[t]:{...h,quantity:Number.isFinite(_)&&_>=.01?_:1}}}}
/>`:p} />`:p}
</div> </div>
`}_toggleRequired(e,i){let t=new Set(this._requiredCompletion);i?t.add(e):t.delete(e),this._requiredCompletion=[...t]}_phaseSlug(e){let i=e.toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,24)||"phase",t=i,r=2;for(;this._phaseDefs.some(h=>h.id===t);)t=`${i}-${r++}`;return t}_addPhaseDef(){let e=this._phaseSlug(`phase-${this._phaseDefs.length+1}`);this._phaseDefs=[...this._phaseDefs,{id:e,name:"",checklistText:"",partId:"",partQty:"",reqOverride:!1,reqFields:[],extraParts:[],carry:{}}]}_removePhaseDef(e){this._phaseDefs=this._phaseDefs.filter(i=>i.id!==e),this._phaseSeq=this._phaseSeq.filter(i=>i!==e)}_patchPhaseDef(e,i){this._phaseDefs=this._phaseDefs.map(t=>t.id===e?{...t,...i}:t)}_renderPhasesEditor(e){let i=t=>this._phaseDefs.find(r=>r.id===t)?.name||t;return o` `}_toggleRequired(e,i){let t=new Set(this._requiredCompletion);i?t.add(e):t.delete(e),this._requiredCompletion=[...t]}_phaseSlug(e){let i=e.toLowerCase().replace(/[^a-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"").slice(0,24)||"phase",t=i,r=2;for(;this._phaseDefs.some(h=>h.id===t);)t=`${i}-${r++}`;return t}_addPhaseDef(){let e=this._phaseSlug(`phase-${this._phaseDefs.length+1}`);this._phaseDefs=[...this._phaseDefs,{id:e,name:"",checklistText:"",partId:"",partQty:"",reqOverride:!1,reqFields:[],extraParts:[],carry:{}}]}_removePhaseDef(e){this._phaseDefs=this._phaseDefs.filter(i=>i.id!==e),this._phaseSeq=this._phaseSeq.filter(i=>i!==e)}_patchPhaseDef(e,i){this._phaseDefs=this._phaseDefs.map(t=>t.id===e?{...t,...i}:t)}_renderPhasesEditor(e){let i=t=>this._phaseDefs.find(r=>r.id===t)?.name||t;return o`
@@ -150,7 +150,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
<input <input
type="checkbox" type="checkbox"
.checked=${t.reqFields.includes(r)} .checked=${t.reqFields.includes(r)}
@change=${h=>{let _=h.target.checked,c=new Set(t.reqFields);_?c.add(r):c.delete(r),this._patchPhaseDef(t.id,{reqFields:[...c]})}} @change=${h=>{let c=h.target.checked,_=new Set(t.reqFields);c?_.add(r):_.delete(r),this._patchPhaseDef(t.id,{reqFields:[..._]})}}
/> />
<span>${s(q[r],e)}</span> <span>${s(q[r],e)}</span>
</label> </label>
@@ -168,7 +168,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
${this._phaseSeq.map((t,r)=>o` ${this._phaseSeq.map((t,r)=>o`
<span class="phase-chip"> <span class="phase-chip">
${r+1}. ${i(t)} ${r+1}. ${i(t)}
<button class="phase-chip-x" @click=${()=>{this._phaseSeq=this._phaseSeq.filter((h,_)=>_!==r)}}>✕</button> <button class="phase-chip-x" @click=${()=>{this._phaseSeq=this._phaseSeq.filter((h,c)=>c!==r)}}>✕</button>
</span> </span>
`)} `)}
<select <select
@@ -181,9 +181,9 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
</select> </select>
</div> </div>
`:p} `:p}
`}async _save(){if(!this._loading&&this._name.trim()){if(this._adaptiveSnapshot()!==this._adaptiveInitial){let e=parseInt(this._adaptiveMin,10),i=parseInt(this._adaptiveMax,10);if(!isNaN(e)&&!isNaN(i)&&e>i){this._error=`${s("adaptive_min_interval",this._lang)} > ${s("adaptive_max_interval",this._lang)}`;return}}this._loading=!0,this._error="";try{let e={type:this._taskId?"maintenance_supporter/task/update":"maintenance_supporter/task/create",entry_id:this._entryId,name:this._name,task_type:this._type,schedule_type:this._scheduleType,warning_days:Number.isNaN(parseInt(this._warningDays,10))?this.defaultWarningDays:Math.max(0,parseInt(this._warningDays,10))},i=this._earliestCompletionDays.trim();e.earliest_completion_days=i===""?null:Math.max(0,parseInt(i,10)||0),this._taskId&&(e.task_id=this._taskId),this._scheduleType==="one_time"?(e.due_date=this._dueDate||null,e.interval_days=null):A.includes(this._scheduleType)?(e.schedule={...this._buildSchedule(),...this._recurrenceExtras()},e.interval_days=null,this._taskId&&(e.due_date=null)):(this._taskId&&(e.due_date=null),this._scheduleType!=="manual"&&this._intervalDays?(e.interval_days=parseInt(this._intervalDays,10),e.interval_unit=this._intervalUnit,e.interval_anchor=this._intervalAnchor,this._scheduleType==="time_based"&&(e.schedule={kind:"interval",...this._recurrenceExtras()})):this._taskId&&(e.interval_days=null,e.interval_anchor="completion")),e.notes=this._notes||null,e.documentation_url=this._documentationUrl||null,e.custom_icon=this._customIcon||null,e.priority=this._priority,e.labels=this._labels.split(",").map(_=>_.trim()).filter(Boolean),e.enabled=this._enabled,e.last_performed=this._lastPerformed||null,e.nfc_tag_id=this._nfcTagId||null,e.require_tag_scan=this._requireTagScan,e.reading_unit=this._readingUnit.trim()||null;{let _={};for(let d of this._phaseDefs){if(!d.name.trim())continue;let g={...d.carry,name:d.name.trim()},v=d.checklistText.split(` `}async _save(){if(!this._loading&&this._name.trim()){if(this._adaptiveSnapshot()!==this._adaptiveInitial){let e=parseInt(this._adaptiveMin,10),i=parseInt(this._adaptiveMax,10);if(!isNaN(e)&&!isNaN(i)&&e>i){this._error=`${s("adaptive_min_interval",this._lang)} > ${s("adaptive_max_interval",this._lang)}`;return}}this._loading=!0,this._error="";try{let e={type:this._taskId?"maintenance_supporter/task/update":"maintenance_supporter/task/create",entry_id:this._entryId,name:this._name,task_type:this._type,schedule_type:this._scheduleType,warning_days:Number.isNaN(parseInt(this._warningDays,10))?this.defaultWarningDays:Math.max(0,parseInt(this._warningDays,10))},i=this._earliestCompletionDays.trim();e.earliest_completion_days=i===""?null:Math.max(0,parseInt(i,10)||0),this._taskId&&(e.task_id=this._taskId),this._scheduleType==="one_time"?(e.due_date=this._dueDate||null,e.interval_days=null):A.includes(this._scheduleType)?(e.schedule={...this._buildSchedule(),...this._recurrenceExtras()},e.interval_days=null,this._taskId&&(e.due_date=null)):(this._taskId&&(e.due_date=null),this._scheduleType!=="manual"&&this._intervalDays?(e.interval_days=parseInt(this._intervalDays,10),e.interval_unit=this._intervalUnit,e.interval_anchor=this._intervalAnchor,this._scheduleType==="time_based"&&(e.schedule={kind:"interval",...this._recurrenceExtras()})):this._taskId&&(e.interval_days=null,e.interval_anchor="completion")),e.notes=this._notes||null,e.documentation_url=this._documentationUrl||null,e.custom_icon=this._customIcon||null,e.priority=this._priority,e.labels=this._labels.split(",").map(c=>c.trim()).filter(Boolean),e.enabled=this._enabled,e.last_performed=this._lastPerformed||null,e.nfc_tag_id=this._nfcTagId||null,e.require_tag_scan=this._requireTagScan,e.allow_skip=this._allowSkip,e.reading_unit=this._readingUnit.trim()||null;{let c={};for(let d of this._phaseDefs){if(!d.name.trim())continue;let g={...d.carry,name:d.name.trim()},v=d.checklistText.split(`
`).map(f=>f.trim()).filter(Boolean);v.length&&(g.checklist=v);let m=[];if(d.partId){let f=parseFloat(d.partQty);m.push({part_id:d.partId,quantity:Number.isFinite(f)&&f>0?f:1})}for(let f of d.extraParts)m.push(f.entry_id?{part_id:f.part_id,quantity:f.quantity,entry_id:f.entry_id}:{part_id:f.part_id,quantity:f.quantity});m.length&&(g.consumes_parts=m),d.reqOverride&&(g.required_completion_fields=[...d.reqFields]),_[d.id]=g}let c=this._phaseSeq.filter(d=>d in _);e.phases=Object.keys(_).length&&c.length?_:null,e.phase_sequence=e.phases?c:null}if((this.parts.length||this._foreignOwners.length)&&(e.consumes_parts=Object.values(this._consumesParts).map(_=>_.entry_id?{part_id:_.part_id,quantity:_.quantity,entry_id:_.entry_id}:{part_id:_.part_id,quantity:_.quantity})),e.responsible_user_id=this._responsibleUserId,e.assignee_pool=this._assigneePool,e.required_completion_fields=this._requiredCompletion,e.rotation_strategy=this._assigneePool.length>=2&&this._rotationStrategy?this._rotationStrategy:null,this._scheduleType==="sensor_based"&&this._triggerType==="compound"){let _=this._compoundConditions.map(Q).filter(c=>c!==null);if(_.length>0){let c={type:"compound",compound_logic:this._compoundLogic,conditions:_};this._autoCompleteOnRecovery&&(c.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(c.trigger_combinator="all"),e.trigger_config=c}else this._taskId&&(e.trigger_config=null)}else if(this._scheduleType==="sensor_based"&&this._triggerEntityId){let _=this._triggerEntityIds.length>0?this._triggerEntityIds:[this._triggerEntityId],c={entity_id:_[0],entity_ids:_,type:this._triggerType};if(this._triggerAttribute&&(c.attribute=this._triggerAttribute),this._autoCompleteOnRecovery&&(c.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(c.trigger_combinator="all"),_.length>1&&(c.entity_logic=this._triggerEntityLogic),this._triggerType==="threshold"){if(this._triggerAbove){let d=parseFloat(this._triggerAbove);isNaN(d)||(c.trigger_above=d)}if(this._triggerBelow){let d=parseFloat(this._triggerBelow);isNaN(d)||(c.trigger_below=d)}if(this._triggerEquals){let d=parseFloat(this._triggerEquals);isNaN(d)||(c.trigger_equals=d)}if(this._triggerNotEquals){let d=parseFloat(this._triggerNotEquals);isNaN(d)||(c.trigger_not_equals=d)}if(this._triggerForMinutes){let d=parseInt(this._triggerForMinutes,10);isNaN(d)||(c.trigger_for_minutes=d)}}else if(this._triggerType==="counter"){if(this._triggerTargetValue){let d=parseFloat(this._triggerTargetValue);isNaN(d)||(c.trigger_target_value=d)}if(c.trigger_delta_mode=this._triggerDeltaMode,this._triggerDeltaMode&&this._triggerBaselineValue){let d=parseFloat(this._triggerBaselineValue);!isNaN(d)&&d>=0&&(c.trigger_baseline_value=d)}}else if(this._triggerType==="state_change"){if(this._triggerFromState&&(c.trigger_from_state=this._triggerFromState),this._triggerToState&&(c.trigger_to_state=this._triggerToState),this._triggerTargetChanges){let d=parseInt(this._triggerTargetChanges,10);isNaN(d)||(c.trigger_target_changes=d)}if(this._triggerForMinutes){let d=parseInt(this._triggerForMinutes,10);isNaN(d)||(c.trigger_for_minutes=d)}}else if(this._triggerType==="runtime"){if(this._triggerRuntimeHours){let g=parseFloat(this._triggerRuntimeHours);isNaN(g)||(c.trigger_runtime_hours=g)}let d=this._triggerOnStates.split(",").map(g=>g.trim()).filter(Boolean);d.length>0&&(c.trigger_on_states=d)}e.trigger_config=c}else this._taskId&&(e.trigger_config=null);if(this.scheduleTimeEnabled&&this._scheduleType==="time_based"){let _=this._scheduleTime.trim();e.schedule_time=/^([01]\d|2[0-3]):[0-5]\d$/.test(_)?_:null}if(this.checklistsEnabled){let _=this._checklistText.split(` `).map(f=>f.trim()).filter(Boolean);v.length&&(g.checklist=v);let m=[];if(d.partId){let f=parseFloat(d.partQty);m.push({part_id:d.partId,quantity:Number.isFinite(f)&&f>0?f:1})}for(let f of d.extraParts)m.push(f.entry_id?{part_id:f.part_id,quantity:f.quantity,entry_id:f.entry_id}:{part_id:f.part_id,quantity:f.quantity});m.length&&(g.consumes_parts=m),d.reqOverride&&(g.required_completion_fields=[...d.reqFields]),c[d.id]=g}let _=this._phaseSeq.filter(d=>d in c);e.phases=Object.keys(c).length&&_.length?c:null,e.phase_sequence=e.phases?_:null}if((this.parts.length||this._foreignOwners.length)&&(e.consumes_parts=Object.values(this._consumesParts).map(c=>c.entry_id?{part_id:c.part_id,quantity:c.quantity,entry_id:c.entry_id}:{part_id:c.part_id,quantity:c.quantity})),e.responsible_user_id=this._responsibleUserId,e.assignee_pool=this._assigneePool,e.required_completion_fields=this._requiredCompletion,e.rotation_strategy=this._assigneePool.length>=2&&this._rotationStrategy?this._rotationStrategy:null,this._scheduleType==="sensor_based"&&this._triggerType==="compound"){let c=this._compoundConditions.map(Q).filter(_=>_!==null);if(c.length>0){let _={type:"compound",compound_logic:this._compoundLogic,conditions:c};this._autoCompleteOnRecovery&&(_.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(_.trigger_combinator="all"),e.trigger_config=_}else this._taskId&&(e.trigger_config=null)}else if(this._scheduleType==="sensor_based"&&this._triggerEntityId){let c=this._triggerEntityIds.length>0?this._triggerEntityIds:[this._triggerEntityId],_={entity_id:c[0],entity_ids:c,type:this._triggerType};if(this._triggerAttribute&&(_.attribute=this._triggerAttribute),this._autoCompleteOnRecovery&&(_.auto_complete_on_recovery=!0),this._triggerCombinator==="all"&&(_.trigger_combinator="all"),c.length>1&&(_.entity_logic=this._triggerEntityLogic),this._triggerType==="threshold"){if(this._triggerAbove){let d=parseFloat(this._triggerAbove);isNaN(d)||(_.trigger_above=d)}if(this._triggerBelow){let d=parseFloat(this._triggerBelow);isNaN(d)||(_.trigger_below=d)}if(this._triggerEquals){let d=parseFloat(this._triggerEquals);isNaN(d)||(_.trigger_equals=d)}if(this._triggerNotEquals){let d=parseFloat(this._triggerNotEquals);isNaN(d)||(_.trigger_not_equals=d)}if(this._triggerForMinutes){let d=parseInt(this._triggerForMinutes,10);isNaN(d)||(_.trigger_for_minutes=d)}}else if(this._triggerType==="counter"){if(this._triggerTargetValue){let d=parseFloat(this._triggerTargetValue);isNaN(d)||(_.trigger_target_value=d)}if(_.trigger_delta_mode=this._triggerDeltaMode,this._triggerDeltaMode&&this._triggerBaselineValue){let d=parseFloat(this._triggerBaselineValue);!isNaN(d)&&d>=0&&(_.trigger_baseline_value=d)}}else if(this._triggerType==="state_change"){if(this._triggerFromState&&(_.trigger_from_state=this._triggerFromState),this._triggerToState&&(_.trigger_to_state=this._triggerToState),this._triggerTargetChanges){let d=parseInt(this._triggerTargetChanges,10);isNaN(d)||(_.trigger_target_changes=d)}if(this._triggerForMinutes){let d=parseInt(this._triggerForMinutes,10);isNaN(d)||(_.trigger_for_minutes=d)}}else if(this._triggerType==="runtime"){if(this._triggerRuntimeHours){let g=parseFloat(this._triggerRuntimeHours);isNaN(g)||(_.trigger_runtime_hours=g)}if(this._triggerRuntimeMaxSession){let g=parseInt(this._triggerRuntimeMaxSession,10);!isNaN(g)&&g>0&&(_.trigger_runtime_max_session_seconds=g)}let d=this._triggerOnStates.split(",").map(g=>g.trim()).filter(Boolean);d.length>0&&(_.trigger_on_states=d)}e.trigger_config=_}else this._taskId&&(e.trigger_config=null);if(this.scheduleTimeEnabled&&this._scheduleType==="time_based"){let c=this._scheduleTime.trim();e.schedule_time=/^([01]\d|2[0-3]):[0-5]\d$/.test(c)?c:null}if(this.checklistsEnabled){let c=this._checklistText.split(`
`).map(c=>c.trim()).filter(Boolean).slice(0,100);e.checklist=_.length?_:null}if(this.completionActionsEnabled){let _=this._actionService.trim();if(_&&/^[a-z][a-z0-9_]*\.[a-z0-9_]+$/.test(_)){let v={service:_},m=this._actionTargetEntity.trim();m&&(v.target={entity_id:m});let f=this._buildActionData();Object.keys(f).length>0&&(v.data=f),e.on_complete_action=v}else e.on_complete_action=null;let c={};this._qcNotes.trim()&&(c.notes=this._qcNotes.trim());let d=parseFloat(this._qcCost);!isNaN(d)&&d>=0&&(c.cost=d);let g=parseInt(this._qcDuration,10);!isNaN(g)&&g>=0&&(c.duration=g),this._qcFeedback&&(c.feedback=this._qcFeedback),e.quick_complete_defaults=Object.keys(c).length?c:null}let t=await this.hass.connection.sendMessagePromise(e),r=this._taskId||t?.task_id,h=this._environmentalEntity!==this._environmentalInitial||this._environmentalAttribute!==this._environmentalAttributeInitial;if(r&&this._scheduleType==="sensor_based"&&h)try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_environmental_entity",entry_id:this._entryId,task_id:r,environmental_entity:this._environmentalEntity||null,environmental_attribute:this._environmentalAttribute||null}),this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute}catch{}if(r&&this._adaptiveSnapshot()!==this._adaptiveInitial){let _=parseFloat(this._adaptiveAlpha),c=parseInt(this._adaptiveMin,10),d=parseInt(this._adaptiveMax,10);try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_adaptive",entry_id:this._entryId,task_id:r,enabled:this._adaptiveEnabled,..._>=.1&&_<=.9?{ewa_alpha:_}:{},...!isNaN(c)&&c>=1?{min_interval_days:c}:{},...!isNaN(d)&&d>=1?{max_interval_days:d}:{},seasonal_enabled:this._adaptiveSeasonal,sensor_prediction_enabled:this._adaptivePrediction}),this._adaptiveInitial=this._adaptiveSnapshot()}catch{}}this._open=!1,this.dispatchEvent(new CustomEvent("task-saved"))}catch(e){this._error=R(e,this._lang,s("save_error",this._lang))}finally{this._loading=!1}}}_close(){this._open=!1,this._pickerProbeTimer!==void 0&&(clearTimeout(this._pickerProbeTimer),this._pickerProbeTimer=void 0),this._pickerProbeStrikes=0}_renderTriggerFields(){if(this._scheduleType!=="sensor_based")return p;let e=this._lang,i=this._triggerType==="compound";return o` `).map(_=>_.trim()).filter(Boolean).slice(0,100);e.checklist=c.length?c:null}if(this.completionActionsEnabled){let c=this._actionService.trim();if(c&&/^[a-z][a-z0-9_]*\.[a-z0-9_]+$/.test(c)){let v={service:c},m=this._actionTargetEntity.trim();m&&(v.target={entity_id:m});let f=this._buildActionData();Object.keys(f).length>0&&(v.data=f),e.on_complete_action=v}else e.on_complete_action=null;let _={};this._qcNotes.trim()&&(_.notes=this._qcNotes.trim());let d=parseFloat(this._qcCost);!isNaN(d)&&d>=0&&(_.cost=d);let g=parseInt(this._qcDuration,10);!isNaN(g)&&g>=0&&(_.duration=g),this._qcFeedback&&(_.feedback=this._qcFeedback),e.quick_complete_defaults=Object.keys(_).length?_:null}let t=await this.hass.connection.sendMessagePromise(e),r=this._taskId||t?.task_id,h=this._environmentalEntity!==this._environmentalInitial||this._environmentalAttribute!==this._environmentalAttributeInitial;if(r&&this._scheduleType==="sensor_based"&&h)try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_environmental_entity",entry_id:this._entryId,task_id:r,environmental_entity:this._environmentalEntity||null,environmental_attribute:this._environmentalAttribute||null}),this._environmentalInitial=this._environmentalEntity,this._environmentalAttributeInitial=this._environmentalAttribute}catch{}if(r&&this._adaptiveSnapshot()!==this._adaptiveInitial){let c=parseFloat(this._adaptiveAlpha),_=parseInt(this._adaptiveMin,10),d=parseInt(this._adaptiveMax,10);try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/set_adaptive",entry_id:this._entryId,task_id:r,enabled:this._adaptiveEnabled,...c>=.1&&c<=.9?{ewa_alpha:c}:{},...!isNaN(_)&&_>=1?{min_interval_days:_}:{},...!isNaN(d)&&d>=1?{max_interval_days:d}:{},seasonal_enabled:this._adaptiveSeasonal,sensor_prediction_enabled:this._adaptivePrediction}),this._adaptiveInitial=this._adaptiveSnapshot()}catch{}}this._open=!1,this.dispatchEvent(new CustomEvent("task-saved"))}catch(e){this._error=R(e,this._lang,s("save_error",this._lang))}finally{this._loading=!1}}}_close(){this._open=!1,this._pickerProbeTimer!==void 0&&(clearTimeout(this._pickerProbeTimer),this._pickerProbeTimer=void 0),this._pickerProbeStrikes=0}_renderTriggerFields(){if(this._scheduleType!=="sensor_based")return p;let e=this._lang,i=this._triggerType==="compound";return o`
<h3>${s("trigger_configuration",e)}</h3> <h3>${s("trigger_configuration",e)}</h3>
<div class="select-row"> <div class="select-row">
<label>${s("trigger_type",e)}</label> <label>${s("trigger_type",e)}</label>
@@ -199,7 +199,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
<ms-textfield <ms-textfield
label="${s("entity_id",e)} (${s("comma_separated",e)})" label="${s("entity_id",e)} (${s("comma_separated",e)})"
.value=${this._triggerEntityIds.length>0?this._triggerEntityIds.join(", "):this._triggerEntityId} .value=${this._triggerEntityIds.length>0?this._triggerEntityIds.join(", "):this._triggerEntityId}
@input=${t=>{let h=t.target.value.split(",").map(_=>_.trim()).filter(Boolean);this._triggerEntityId=h[0]||"",this._triggerEntityIds=h,h[0]&&this._fetchEntityAttributes(h[0])}} @input=${t=>{let h=t.target.value.split(",").map(c=>c.trim()).filter(Boolean);this._triggerEntityId=h[0]||"",this._triggerEntityIds=h,h[0]&&this._fetchEntityAttributes(h[0])}}
></ms-textfield> ></ms-textfield>
`:o` `:o`
<ha-form <ha-form
@@ -293,7 +293,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
.schema=${[{name:"condition_entities",selector:{entity:{multiple:!0,domain:C}}}]} .schema=${[{name:"condition_entities",selector:{entity:{multiple:!0,domain:C}}}]}
.data=${{condition_entities:e.entityIds.split(",").map(h=>h.trim()).filter(Boolean)}} .data=${{condition_entities:e.entityIds.split(",").map(h=>h.trim()).filter(Boolean)}}
.computeLabel=${()=>s("entity_id",t)} .computeLabel=${()=>s("entity_id",t)}
@value-changed=${h=>{let _=(h.detail.value.condition_entities||[]).filter(Boolean);this._patchCondition(i,{entityIds:_.join(", ")})}} @value-changed=${h=>{let c=(h.detail.value.condition_entities||[]).filter(Boolean);this._patchCondition(i,{entityIds:c.join(", ")})}}
></ha-form>`} ></ha-form>`}
${this._renderConditionAttribute(e,i)} ${this._renderConditionAttribute(e,i)}
<div class="select-row"> <div class="select-row">
@@ -446,7 +446,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
> >
${["days","weeks","months","years"].map(i=>o`<option value=${i} ?selected=${i===this._intervalUnit}>${s("unit_"+i,e)}</option>`)} ${["days","weeks","months","years"].map(i=>o`<option value=${i} ?selected=${i===this._intervalUnit}>${s("unit_"+i,e)}</option>`)}
</select> </select>
</div>`}_toggleWeekday(e){this._weekdays=this._weekdays.includes(e)?this._weekdays.filter(i=>i!==e):[...this._weekdays,e]}_previewScheduleDict(){if(this._scheduleType==="one_time")return this._dueDate?{kind:"one_time",due_date:this._dueDate}:null;if(A.includes(this._scheduleType))return{...this._buildSchedule(),...this._recurrenceExtras()};let e=parseInt(this._intervalDays,10);return this._scheduleType==="manual"||!e||e<=0?null:{kind:"interval",every:e,unit:this._intervalUnit,anchor:this._intervalAnchor,...this._recurrenceExtras()}}updated(e){super.updated?.(e),this._scheduleEntityPickerProbe();for(let i of e.keys())if(n._PREVIEW_RELEVANT.has(String(i))){this._schedulePreviewRefresh();return}}_scheduleEntityPickerProbe(){this._entityPickerFallback||this._pickerProbeTimer!==void 0||!this._open||this._scheduleType!=="sensor_based"||(this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),1500))}_probeEntityPickers(){if(this._pickerProbeTimer=void 0,this._entityPickerFallback||!this._open)return;let e=this.shadowRoot?.querySelector("ha-form.entity-picker-form"),i=(this.shadowRoot?.querySelector(".content")?.offsetHeight??0)>0;if(!e||!i){this._pickerProbeStrikes=0;return}let t=(c,d,g=0)=>{if(!(!c||g>10)){(c.tagName?.toLowerCase()??"")==="ha-entity-picker"&&d.push(c);for(let v of[c.shadowRoot,c])if(v)for(let m of Array.from(v.children??[]))t(m,d,g+1)}},r=[...this.shadowRoot?.querySelectorAll("ha-form.entity-picker-form")??[]],h=[];for(let c of r)t(c,h);let _=h.length===0||h.some(c=>c.offsetHeight===0);if(e.offsetHeight===0||_){if(this._pickerProbeStrikes+=1,this._pickerProbeStrikes>=2){this._entityPickerFallback=!0;return}this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),700)}else this._pickerProbeStrikes=0}_schedulePreviewRefresh(){this._previewTimer&&clearTimeout(this._previewTimer),this._previewTimer=setTimeout(()=>{this._fetchSchedulePreview()},300)}async _fetchSchedulePreview(){let e=this._open?this._previewScheduleDict():null;if(!e){this._schedulePreview=[],this._schedulePreviewEnded=!1;return}let i=++this._previewSeq;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/schedule/preview",schedule:e,...this._lastPerformed?{last_performed:this._lastPerformed}:{}});if(i!==this._previewSeq)return;this._schedulePreview=t.occurrences||[],this._schedulePreviewEnded=!!t.series_ended}catch{}}_renderSchedulePreview(){if(this._schedulePreview.length===0)return p;let e=this._lang,i=this.scheduleTimeEnabled&&this._scheduleTime?` ${this._scheduleTime}`:"",t=this._schedulePreview.map((h,_)=>{let c=new Date(`${h}T12:00:00`).getDay();return`${S(c===0?6:c-1,e,"short")} ${F(h,e)}${_===0?i:""}`}).join(" \xB7 "),r=this._scheduleType==="time_based"&&this._intervalAnchor==="completion"?o`<div class="field-help">${s("schedule_preview_ontime",e)}</div>`:p;return o` </div>`}_toggleWeekday(e){this._weekdays=this._weekdays.includes(e)?this._weekdays.filter(i=>i!==e):[...this._weekdays,e]}_previewScheduleDict(){if(this._scheduleType==="one_time")return this._dueDate?{kind:"one_time",due_date:this._dueDate}:null;if(A.includes(this._scheduleType))return{...this._buildSchedule(),...this._recurrenceExtras()};let e=parseInt(this._intervalDays,10);return this._scheduleType==="manual"||!e||e<=0?null:{kind:"interval",every:e,unit:this._intervalUnit,anchor:this._intervalAnchor,...this._recurrenceExtras()}}updated(e){super.updated?.(e),this._scheduleEntityPickerProbe();for(let i of e.keys())if(n._PREVIEW_RELEVANT.has(String(i))){this._schedulePreviewRefresh();return}}_scheduleEntityPickerProbe(){this._entityPickerFallback||this._pickerProbeTimer!==void 0||!this._open||this._scheduleType!=="sensor_based"||(this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),1500))}_probeEntityPickers(){if(this._pickerProbeTimer=void 0,this._entityPickerFallback||!this._open)return;let e=this.shadowRoot?.querySelector("ha-form.entity-picker-form"),i=(this.shadowRoot?.querySelector(".content")?.offsetHeight??0)>0;if(!e||!i){this._pickerProbeStrikes=0;return}let t=(_,d,g=0)=>{if(!(!_||g>10)){(_.tagName?.toLowerCase()??"")==="ha-entity-picker"&&d.push(_);for(let v of[_.shadowRoot,_])if(v)for(let m of Array.from(v.children??[]))t(m,d,g+1)}},r=[...this.shadowRoot?.querySelectorAll("ha-form.entity-picker-form")??[]],h=[];for(let _ of r)t(_,h);let c=h.length===0||h.some(_=>_.offsetHeight===0);if(e.offsetHeight===0||c){if(this._pickerProbeStrikes+=1,this._pickerProbeStrikes>=2){this._entityPickerFallback=!0;return}this._pickerProbeTimer=setTimeout(()=>this._probeEntityPickers(),700)}else this._pickerProbeStrikes=0}_schedulePreviewRefresh(){this._previewTimer&&clearTimeout(this._previewTimer),this._previewTimer=setTimeout(()=>{this._fetchSchedulePreview()},300)}async _fetchSchedulePreview(){let e=this._open?this._previewScheduleDict():null;if(!e){this._schedulePreview=[],this._schedulePreviewEnded=!1;return}let i=++this._previewSeq;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/schedule/preview",schedule:e,...this._lastPerformed?{last_performed:this._lastPerformed}:{}});if(i!==this._previewSeq)return;this._schedulePreview=t.occurrences||[],this._schedulePreviewEnded=!!t.series_ended}catch{}}_renderSchedulePreview(){if(this._schedulePreview.length===0)return p;let e=this._lang,i=this.scheduleTimeEnabled&&this._scheduleTime?` ${this._scheduleTime}`:"",t=this._schedulePreview.map((h,c)=>{let _=new Date(`${h}T12:00:00`).getDay();return`${S(_===0?6:_-1,e,"short")} ${F(h,e)}${c===0?i:""}`}).join(" \xB7 "),r=this._scheduleType==="time_based"&&this._intervalAnchor==="completion"?o`<div class="field-help">${s("schedule_preview_ontime",e)}</div>`:p;return o`
<div class="trigger-live-hint schedule-preview"> <div class="trigger-live-hint schedule-preview">
${s("schedule_preview_title",e)}: ${t}${this._schedulePreviewEnded?o` <span class="field-help">${s("schedule_preview_ends",e)}</span>`:p} ${s("schedule_preview_title",e)}: ${t}${this._schedulePreviewEnded?o` <span class="field-help">${s("schedule_preview_ends",e)}</span>`:p}
${r} ${r}
@@ -538,7 +538,7 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
max="15" max="15"
.value=${this._calOffset} .value=${this._calOffset}
@input=${i=>this._calOffset=i.target.value} @input=${i=>this._calOffset=i.target.value}
></ms-textfield>`}_renderTriggerLiveHint(){if(this._triggerType==="compound")return p;let e=this._triggerEntityId||this._triggerEntityIds[0];if(!e||!this.hass?.states)return p;let i=this.hass.states[e];if(!i)return p;let t=this._lang,r=i.attributes?.unit_of_measurement,h=typeof r=="string"&&r?` ${r}`:"",_=this._triggerAttribute?i.attributes?.[this._triggerAttribute]:i.state,c=typeof _=="number"?_:parseFloat(String(_)),d=_!=="unknown"&&_!=="unavailable"&&_!=null&&!isNaN(c),g=m=>Number.isInteger(m)?String(m):String(Math.round(m*10)/10),v=[];if(this._triggerType==="threshold"){let m=parseFloat(this._triggerAbove),f=parseFloat(this._triggerBelow);if(isNaN(m)&&isNaN(f))return p;d&&v.push(s("trigger_hint_now",t).replace("{value}",g(c)+h)),isNaN(m)||v.push(s("trigger_hint_above",t).replace("{target}",g(m)+h)),isNaN(f)||v.push(s("trigger_hint_below",t).replace("{target}",g(f)+h))}else if(this._triggerType==="counter"){let m=parseFloat(this._triggerTargetValue);if(isNaN(m))return p;this._triggerDeltaMode?this._taskId?v.push(s("trigger_hint_counter_delta_edit",t).replace("{target}",g(m)+h)):d?v.push(s("trigger_hint_counter_delta",t).replace("{value}",g(c)+h).replace("{due}",g(c+m)+h).replace("{target}",g(m)+h)):v.push(s("trigger_hint_counter_delta_edit",t).replace("{target}",g(m)+h)):(d&&v.push(s("trigger_hint_now",t).replace("{value}",g(c)+h)),v.push(s("trigger_hint_counter_abs",t).replace("{target}",g(m)+h)))}else if(this._triggerType==="runtime"){let m=parseFloat(this._triggerRuntimeHours);if(isNaN(m))return p;v.push(s("trigger_hint_runtime",t).replace("{hours}",g(m))),v.push(s("trigger_hint_state_now",t).replace("{value}",String(i.state)))}else if(this._triggerType==="state_change"){let m=parseInt(this._triggerTargetChanges,10)||1,f=this._triggerToState.trim();v.push((f?s("trigger_hint_state_change_to",t).replace("{state}",f):s("trigger_hint_state_change",t)).replace("{count}",String(m))),v.push(s("trigger_hint_state_now",t).replace("{value}",String(i.state)))}return v.length?o`<div class="trigger-live-hint">${v.join(" ")}</div>`:p}_renderTriggerTypeFields(){let e=this._lang;return this._triggerType==="threshold"?o` ></ms-textfield>`}_renderTriggerLiveHint(){if(this._triggerType==="compound")return p;let e=this._triggerEntityId||this._triggerEntityIds[0];if(!e||!this.hass?.states)return p;let i=this.hass.states[e];if(!i)return p;let t=this._lang,r=i.attributes?.unit_of_measurement,h=typeof r=="string"&&r?` ${r}`:"",c=this._triggerAttribute?i.attributes?.[this._triggerAttribute]:i.state,_=typeof c=="number"?c:parseFloat(String(c)),d=c!=="unknown"&&c!=="unavailable"&&c!=null&&!isNaN(_),g=m=>Number.isInteger(m)?String(m):String(Math.round(m*10)/10),v=[];if(this._triggerType==="threshold"){let m=parseFloat(this._triggerAbove),f=parseFloat(this._triggerBelow);if(isNaN(m)&&isNaN(f))return p;d&&v.push(s("trigger_hint_now",t).replace("{value}",g(_)+h)),isNaN(m)||v.push(s("trigger_hint_above",t).replace("{target}",g(m)+h)),isNaN(f)||v.push(s("trigger_hint_below",t).replace("{target}",g(f)+h))}else if(this._triggerType==="counter"){let m=parseFloat(this._triggerTargetValue);if(isNaN(m))return p;this._triggerDeltaMode?this._taskId?v.push(s("trigger_hint_counter_delta_edit",t).replace("{target}",g(m)+h)):d?v.push(s("trigger_hint_counter_delta",t).replace("{value}",g(_)+h).replace("{due}",g(_+m)+h).replace("{target}",g(m)+h)):v.push(s("trigger_hint_counter_delta_edit",t).replace("{target}",g(m)+h)):(d&&v.push(s("trigger_hint_now",t).replace("{value}",g(_)+h)),v.push(s("trigger_hint_counter_abs",t).replace("{target}",g(m)+h)))}else if(this._triggerType==="runtime"){let m=parseFloat(this._triggerRuntimeHours);if(isNaN(m))return p;v.push(s("trigger_hint_runtime",t).replace("{hours}",g(m))),v.push(s("trigger_hint_state_now",t).replace("{value}",String(i.state)))}else if(this._triggerType==="state_change"){let m=parseInt(this._triggerTargetChanges,10)||1,f=this._triggerToState.trim();v.push((f?s("trigger_hint_state_change_to",t).replace("{state}",f):s("trigger_hint_state_change",t)).replace("{count}",String(m))),v.push(s("trigger_hint_state_now",t).replace("{value}",String(i.state)))}return v.length?o`<div class="trigger-live-hint">${v.join(" ")}</div>`:p}_renderTriggerTypeFields(){let e=this._lang;return this._triggerType==="threshold"?o`
<ms-textfield <ms-textfield
label="${s("trigger_above",e)}" label="${s("trigger_above",e)}"
type="number" type="number"
@@ -632,6 +632,14 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
.value=${this._triggerRuntimeHours} .value=${this._triggerRuntimeHours}
@input=${i=>this._triggerRuntimeHours=i.target.value} @input=${i=>this._triggerRuntimeHours=i.target.value}
></ms-textfield> ></ms-textfield>
<ms-textfield
label="${s("runtime_max_session",e)}"
type="number"
step="1"
.value=${this._triggerRuntimeMaxSession}
@input=${i=>this._triggerRuntimeMaxSession=i.target.value}
></ms-textfield>
<div class="field-help">${s("runtime_max_session_help",e)}</div>
${this._renderOnStatesField({value:this._triggerOnStates,entityId:this._triggerEntityId,onInput:i=>this._triggerOnStates=i})} ${this._renderOnStatesField({value:this._triggerOnStates,entityId:this._triggerEntityId,onInput:i=>this._triggerOnStates=i})}
<div class="field-help">${s("runtime_on_states_help",e)}</div> <div class="field-help">${s("runtime_on_states_help",e)}</div>
`:p}render(){if(!this._open)return o``;let e=this._lang,i=this._taskId?s("edit_task",e):s("new_task",e);return o` `:p}render(){if(!this._open)return o``;let e=this._lang,i=this._taskId?s("edit_task",e):s("new_task",e);return o`
@@ -918,6 +926,15 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
<span>${s("require_tag_scan",e)}</span> <span>${s("require_tag_scan",e)}</span>
</label> </label>
${this._requireTagScan?o`<div class="field-help">${s("require_tag_scan_help",e)}</div>`:p} ${this._requireTagScan?o`<div class="field-help">${s("require_tag_scan_help",e)}</div>`:p}
<label class="req-option">
<input
type="checkbox"
.checked=${!this._allowSkip}
@change=${t=>this._allowSkip=!t.target.checked}
/>
<span>${s("disallow_skip",e)}</span>
</label>
${this._allowSkip?p:o`<div class="field-help">${s("disallow_skip_help",e)}</div>`}
<label class="toggle-row"> <label class="toggle-row">
<input <input
type="checkbox" type="checkbox"
@@ -1314,4 +1331,4 @@ import{a as T,d as k,e as q}from"/maintenance_supporter_panelfiles/panel-chunks/
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
} }
`,a([$({attribute:!1})],n.prototype,"hass",2),a([$({type:Boolean,attribute:"checklists-enabled"})],n.prototype,"checklistsEnabled",2),a([$({type:Boolean,attribute:"schedule-time-enabled"})],n.prototype,"scheduleTimeEnabled",2),a([$({type:Boolean,attribute:"completion-actions-enabled"})],n.prototype,"completionActionsEnabled",2),a([$({type:Number,attribute:"default-warning-days"})],n.prototype,"defaultWarningDays",2),a([l()],n.prototype,"parts",2),a([l()],n.prototype,"_foreignOwners",2),a([l()],n.prototype,"_open",2),a([l()],n.prototype,"_entityPickerFallback",2),a([l()],n.prototype,"_loading",2),a([l()],n.prototype,"_error",2),a([l()],n.prototype,"_entryId",2),a([l()],n.prototype,"_taskId",2),a([l()],n.prototype,"_objectChoices",2),a([l()],n.prototype,"_name",2),a([l()],n.prototype,"_type",2),a([l()],n.prototype,"_scheduleType",2),a([l()],n.prototype,"_intervalDays",2),a([l()],n.prototype,"_intervalUnit",2),a([l()],n.prototype,"_dueDate",2),a([l()],n.prototype,"_warningDays",2),a([l()],n.prototype,"_earliestCompletionDays",2),a([l()],n.prototype,"_intervalAnchor",2),a([l()],n.prototype,"_weekdays",2),a([l()],n.prototype,"_nth",2),a([l()],n.prototype,"_nthWeekday",2),a([l()],n.prototype,"_domDay",2),a([l()],n.prototype,"_domLastDay",2),a([l()],n.prototype,"_domBusiness",2),a([l()],n.prototype,"_calOffset",2),a([l()],n.prototype,"_seasonMonths",2),a([l()],n.prototype,"_endsMode",2),a([l()],n.prototype,"_endsCount",2),a([l()],n.prototype,"_endsUntil",2),a([l()],n.prototype,"_schedulePreview",2),a([l()],n.prototype,"_schedulePreviewEnded",2),a([l()],n.prototype,"_notes",2),a([l()],n.prototype,"_documentationUrl",2),a([l()],n.prototype,"_customIcon",2),a([l()],n.prototype,"_priority",2),a([l()],n.prototype,"_labels",2),a([l()],n.prototype,"_enabled",2),a([l()],n.prototype,"_triggerEntityId",2),a([l()],n.prototype,"_triggerEntityIds",2),a([l()],n.prototype,"_triggerEntityLogic",2),a([l()],n.prototype,"_triggerAttribute",2),a([l()],n.prototype,"_triggerType",2),a([l()],n.prototype,"_triggerAbove",2),a([l()],n.prototype,"_triggerBelow",2),a([l()],n.prototype,"_triggerEquals",2),a([l()],n.prototype,"_triggerNotEquals",2),a([l()],n.prototype,"_triggerForMinutes",2),a([l()],n.prototype,"_triggerCombinator",2),a([l()],n.prototype,"_triggerTargetValue",2),a([l()],n.prototype,"_triggerDeltaMode",2),a([l()],n.prototype,"_triggerBaselineValue",2),a([l()],n.prototype,"_liveBaselineValue",2),a([l()],n.prototype,"_autoCompleteOnRecovery",2),a([l()],n.prototype,"_triggerFromState",2),a([l()],n.prototype,"_triggerToState",2),a([l()],n.prototype,"_triggerTargetChanges",2),a([l()],n.prototype,"_triggerRuntimeHours",2),a([l()],n.prototype,"_triggerOnStates",2),a([l()],n.prototype,"_compoundLogic",2),a([l()],n.prototype,"_compoundConditions",2),a([l()],n.prototype,"_suggestedAttributes",2),a([l()],n.prototype,"_availableAttributes",2),a([l()],n.prototype,"_entityDomain",2),a([l()],n.prototype,"_lastPerformed",2),a([l()],n.prototype,"_nfcTagId",2),a([l()],n.prototype,"_requireTagScan",2),a([l()],n.prototype,"_readingUnit",2),a([l()],n.prototype,"_consumesParts",2),a([l()],n.prototype,"_partsLoadFailed",2),a([l()],n.prototype,"_availableTags",2),a([l()],n.prototype,"_responsibleUserId",2),a([l()],n.prototype,"_assigneePool",2),a([l()],n.prototype,"_rotationStrategy",2),a([l()],n.prototype,"_availableUsers",2),a([l()],n.prototype,"_checklistText",2),a([l()],n.prototype,"_phaseDefs",2),a([l()],n.prototype,"_phaseSeq",2),a([l()],n.prototype,"_requiredCompletion",2),a([l()],n.prototype,"_scheduleTime",2),a([l()],n.prototype,"_actionService",2),a([l()],n.prototype,"_actionTargetEntity",2),a([l()],n.prototype,"_actionData",2),a([l()],n.prototype,"_actionDataJsonFallback",2),a([l()],n.prototype,"_actionTesting",2),a([l()],n.prototype,"_actionTestResult",2),a([l()],n.prototype,"_actionTestError",2),a([l()],n.prototype,"_qcNotes",2),a([l()],n.prototype,"_qcCost",2),a([l()],n.prototype,"_qcDuration",2),a([l()],n.prototype,"_qcFeedback",2),a([l()],n.prototype,"_environmentalEntity",2),a([l()],n.prototype,"_environmentalAttribute",2),a([l()],n.prototype,"_adaptiveEnabled",2),a([l()],n.prototype,"_adaptiveAlpha",2),a([l()],n.prototype,"_adaptiveMin",2),a([l()],n.prototype,"_adaptiveMax",2),a([l()],n.prototype,"_adaptiveSeasonal",2),a([l()],n.prototype,"_adaptivePrediction",2),a([l()],n.prototype,"_conditionAttrOptions",2);var P=n;customElements.get("maintenance-task-dialog")||customElements.define("maintenance-task-dialog",P);export{P as a}; `,a([$({attribute:!1})],n.prototype,"hass",2),a([$({type:Boolean,attribute:"checklists-enabled"})],n.prototype,"checklistsEnabled",2),a([$({type:Boolean,attribute:"schedule-time-enabled"})],n.prototype,"scheduleTimeEnabled",2),a([$({type:Boolean,attribute:"completion-actions-enabled"})],n.prototype,"completionActionsEnabled",2),a([$({type:Number,attribute:"default-warning-days"})],n.prototype,"defaultWarningDays",2),a([l()],n.prototype,"parts",2),a([l()],n.prototype,"_foreignOwners",2),a([l()],n.prototype,"_open",2),a([l()],n.prototype,"_entityPickerFallback",2),a([l()],n.prototype,"_loading",2),a([l()],n.prototype,"_error",2),a([l()],n.prototype,"_entryId",2),a([l()],n.prototype,"_taskId",2),a([l()],n.prototype,"_objectChoices",2),a([l()],n.prototype,"_name",2),a([l()],n.prototype,"_type",2),a([l()],n.prototype,"_scheduleType",2),a([l()],n.prototype,"_intervalDays",2),a([l()],n.prototype,"_intervalUnit",2),a([l()],n.prototype,"_dueDate",2),a([l()],n.prototype,"_warningDays",2),a([l()],n.prototype,"_earliestCompletionDays",2),a([l()],n.prototype,"_intervalAnchor",2),a([l()],n.prototype,"_weekdays",2),a([l()],n.prototype,"_nth",2),a([l()],n.prototype,"_nthWeekday",2),a([l()],n.prototype,"_domDay",2),a([l()],n.prototype,"_domLastDay",2),a([l()],n.prototype,"_domBusiness",2),a([l()],n.prototype,"_calOffset",2),a([l()],n.prototype,"_seasonMonths",2),a([l()],n.prototype,"_endsMode",2),a([l()],n.prototype,"_endsCount",2),a([l()],n.prototype,"_endsUntil",2),a([l()],n.prototype,"_schedulePreview",2),a([l()],n.prototype,"_schedulePreviewEnded",2),a([l()],n.prototype,"_notes",2),a([l()],n.prototype,"_documentationUrl",2),a([l()],n.prototype,"_customIcon",2),a([l()],n.prototype,"_priority",2),a([l()],n.prototype,"_labels",2),a([l()],n.prototype,"_enabled",2),a([l()],n.prototype,"_triggerEntityId",2),a([l()],n.prototype,"_triggerEntityIds",2),a([l()],n.prototype,"_triggerEntityLogic",2),a([l()],n.prototype,"_triggerAttribute",2),a([l()],n.prototype,"_triggerType",2),a([l()],n.prototype,"_triggerAbove",2),a([l()],n.prototype,"_triggerBelow",2),a([l()],n.prototype,"_triggerEquals",2),a([l()],n.prototype,"_triggerNotEquals",2),a([l()],n.prototype,"_triggerForMinutes",2),a([l()],n.prototype,"_triggerCombinator",2),a([l()],n.prototype,"_triggerTargetValue",2),a([l()],n.prototype,"_triggerDeltaMode",2),a([l()],n.prototype,"_triggerBaselineValue",2),a([l()],n.prototype,"_liveBaselineValue",2),a([l()],n.prototype,"_autoCompleteOnRecovery",2),a([l()],n.prototype,"_triggerFromState",2),a([l()],n.prototype,"_triggerToState",2),a([l()],n.prototype,"_triggerTargetChanges",2),a([l()],n.prototype,"_triggerRuntimeHours",2),a([l()],n.prototype,"_triggerRuntimeMaxSession",2),a([l()],n.prototype,"_triggerOnStates",2),a([l()],n.prototype,"_compoundLogic",2),a([l()],n.prototype,"_compoundConditions",2),a([l()],n.prototype,"_suggestedAttributes",2),a([l()],n.prototype,"_availableAttributes",2),a([l()],n.prototype,"_entityDomain",2),a([l()],n.prototype,"_lastPerformed",2),a([l()],n.prototype,"_nfcTagId",2),a([l()],n.prototype,"_requireTagScan",2),a([l()],n.prototype,"_allowSkip",2),a([l()],n.prototype,"_readingUnit",2),a([l()],n.prototype,"_consumesParts",2),a([l()],n.prototype,"_partsLoadFailed",2),a([l()],n.prototype,"_availableTags",2),a([l()],n.prototype,"_responsibleUserId",2),a([l()],n.prototype,"_assigneePool",2),a([l()],n.prototype,"_rotationStrategy",2),a([l()],n.prototype,"_availableUsers",2),a([l()],n.prototype,"_checklistText",2),a([l()],n.prototype,"_phaseDefs",2),a([l()],n.prototype,"_phaseSeq",2),a([l()],n.prototype,"_requiredCompletion",2),a([l()],n.prototype,"_scheduleTime",2),a([l()],n.prototype,"_actionService",2),a([l()],n.prototype,"_actionTargetEntity",2),a([l()],n.prototype,"_actionData",2),a([l()],n.prototype,"_actionDataJsonFallback",2),a([l()],n.prototype,"_actionTesting",2),a([l()],n.prototype,"_actionTestResult",2),a([l()],n.prototype,"_actionTestError",2),a([l()],n.prototype,"_qcNotes",2),a([l()],n.prototype,"_qcCost",2),a([l()],n.prototype,"_qcDuration",2),a([l()],n.prototype,"_qcFeedback",2),a([l()],n.prototype,"_environmentalEntity",2),a([l()],n.prototype,"_environmentalAttribute",2),a([l()],n.prototype,"_adaptiveEnabled",2),a([l()],n.prototype,"_adaptiveAlpha",2),a([l()],n.prototype,"_adaptiveMin",2),a([l()],n.prototype,"_adaptiveMax",2),a([l()],n.prototype,"_adaptiveSeasonal",2),a([l()],n.prototype,"_adaptivePrediction",2),a([l()],n.prototype,"_conditionAttrOptions",2);var P=n;customElements.get("maintenance-task-dialog")||customElements.define("maintenance-task-dialog",P);export{P as a};
@@ -1,5 +1,5 @@
/*! maintenance_supporter frontend 2.68.0 */ /*! maintenance_supporter frontend 2.71.0 */
import{a as r,b as l,c as i,f as o,h as n,l as t}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YEY3J44W.js";var e=class extends n{constructor(){super(...arguments);this.label="";this.value="";this.placeholder="";this.type="text";this.required=!1;this.disabled=!1;this.multiline=!1;this.rows=3}_onInput(s){let a=s.target.value;this.value=a,this.dispatchEvent(new CustomEvent("input",{bubbles:!0,composed:!0,detail:{value:a}}))}render(){return i` import{a as r,b as l,c as i,f as o,h as n,l as t}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PBRIQQ2X.js";var e=class extends n{constructor(){super(...arguments);this.label="";this.value="";this.placeholder="";this.type="text";this.required=!1;this.disabled=!1;this.multiline=!1;this.rows=3}_onInput(s){let a=s.target.value;this.value=a,this.dispatchEvent(new CustomEvent("input",{bubbles:!0,composed:!0,detail:{value:a}}))}render(){return i`
<label class="field"> <label class="field">
${this.label?i`<span class="label">${this.label}${this.required?i`<span class="req">*</span>`:o}</span>`:o} ${this.label?i`<span class="label">${this.label}${this.required?i`<span class="req">*</span>`:o}</span>`:o}
${this.multiline?i` ${this.multiline?i`
@@ -1,2 +1,2 @@
/*! maintenance_supporter frontend 2.68.0 */ /*! maintenance_supporter frontend 2.71.0 */
function c(o,t,e){let l=new Blob([o],{type:e}),d=URL.createObjectURL(l),n=document.createElement("a");n.href=d,n.download=t,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(d),6e4)}function r(o,t){let e=document.createElement("a");e.href=o,e.download=t,e.target="_blank",e.rel="noopener",e.style.display="none",document.body.appendChild(e),e.dispatchEvent(new MouseEvent("click")),document.body.removeChild(e)}export{c as a,r as b}; function c(o,t,e){let l=new Blob([o],{type:e}),d=URL.createObjectURL(l),n=document.createElement("a");n.href=d,n.download=t,n.target="_blank",n.rel="noopener",n.style.display="none",document.body.appendChild(n),n.dispatchEvent(new MouseEvent("click")),document.body.removeChild(n),setTimeout(()=>URL.revokeObjectURL(d),6e4)}function r(o,t){let e=document.createElement("a");e.href=o,e.download=t,e.target="_blank",e.rel="noopener",e.style.display="none",document.body.appendChild(e),e.dispatchEvent(new MouseEvent("click")),document.body.removeChild(e)}export{c as a,r as b};
@@ -1,2 +0,0 @@
/*! maintenance_supporter frontend 2.68.0 */
import{q as _}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YEY3J44W.js";function u(e){return`${e.entry_id??""}\0${e.part_id}`}function l(e,r,s,c){let n=!!e.entry_id&&e.entry_id!==r,o=n?e.entry_id:r,a=s.find(p=>p.entry_id===o),t=(a?.parts||[]).find(p=>p.id===e.part_id)||null,d=n&&a?.object?.name||"",i=t?.name||_("shared_part_unknown",c);return{part:t,foreign:n,ownerName:d,label:d?`${i} (${d})`:i}}function P(e,r,s,c){let{part:n,label:o}=l(e,r,s,c),a=n&&n.stock!==null&&n.stock!==void 0?` (${n.stock}${n.unit?" "+n.unit:""})`:"",t=n?.storage_location?` \u2014 ${n.storage_location}`:"";return`${e.quantity}\xD7 ${o}${a}${t}`}function g(e,r,s,c){let o=(s.find(t=>t.entry_id===r)?.parts||[]).map(t=>({...t})),a=new Set(o.map(t=>u({part_id:t.id})));for(let t of e?.consumes_parts||[]){if(!t.entry_id||t.entry_id===r)continue;let d=u(t);if(a.has(d))continue;a.add(d);let{part:i,ownerName:p}=l(t,r,s,c);o.push({id:t.part_id,name:i?.name||_("shared_part_unknown",c),unit:i?.unit,stock:i?.stock??null,storage_location:i?.storage_location,entry_id:t.entry_id,owner_name:p})}return o}var f=["notes","cost","duration","photo","user"],m={notes:"notes_label",cost:"cost",duration:"duration",photo:"photo_label",user:"user_label"};export{u as a,P as b,g as c,f as d,m as e};
@@ -1,2 +1,2 @@
/*! maintenance_supporter frontend 2.70.0 */ /*! maintenance_supporter frontend 2.71.0 */
import{q as a}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-VSV22GFT.js";var s={entry_id:"object",name:"name",task_type:"maintenance_type",schedule_type:"schedule_type",interval_days:"interval_days",interval_anchor:"interval_anchor",warning_days:"warning_days",last_performed:"last_performed_optional",notes:"notes_optional",documentation_url:"documentation_url_optional",custom_icon:"custom_icon_optional",nfc_tag_id:"nfc_tag_id_optional",responsible_user_id:"responsible_user",entity_slug:"entity_slug",entity_id:"entity_id",area_id:"area_id_optional",manufacturer:"manufacturer_optional",model:"model_optional",serial_number:"serial_number_optional",installation_date:"installation_date_optional",warranty_expiry:"warranty_expiry_optional",checklist:"checklist_steps_optional",reason:"reason",feedback:"feedback",cost:"cost",duration:"duration",description:"description_optional",group_name:"name",group_description:"description_optional",environmental_entity:"environmental_entity_optional",environmental_attribute:"environmental_attribute_optional",trigger_above:"trigger_above",trigger_below:"trigger_below",trigger_equals:"trigger_equals",trigger_not_equals:"trigger_not_equals",trigger_for_minutes:"trigger_for_minutes"};function c(e,o){let r=s[e];if(!r)return e;let t=a(r,o);return t&&t!==r?t:e}function d(e){let r=e.match(/data\['([^']+)'\]/)?.[1],t;return(t=e.match(/length of value must be at most (\d+)/))?{field:r,rule:"too_long",param:t[1]}:(t=e.match(/length of value must be at least (\d+)/))?{field:r,rule:"too_short",param:t[1]}:(t=e.match(/value must be at most (\S+)/))?{field:r,rule:"value_too_high",param:t[1]}:(t=e.match(/value must be at least (\S+)/))?{field:r,rule:"value_too_low",param:t[1]}:/required key not provided/.test(e)?{field:r,rule:"required"}:(t=e.match(/expected (\w+)/))?{field:r,rule:"wrong_type",param:t[1]}:/value must be one of/.test(e)?{field:r,rule:"invalid_choice"}:/not a valid value/.test(e)?{field:r,rule:"invalid_value"}:{field:r,rule:"unknown"}}function g(e,o,r){if(r=r??a("action_error",o),typeof e=="string")return e;if(typeof e!="object"||e===null)return r;let t=e,_=t.message||t.error?.message||"";if(!_)return r;let i=d(_),l=i.field?c(i.field,o):"",n=u=>a(u,o).replace("{field}",l).replace("{n}",i.param??"");switch(i.rule){case"too_long":return n("err_too_long");case"too_short":return n("err_too_short");case"value_too_high":return n("err_value_too_high");case"value_too_low":return n("err_value_too_low");case"required":return n("err_required");case"wrong_type":return n("err_wrong_type").replace("{type}",i.param??"");case"invalid_choice":return n("err_invalid_choice");case"invalid_value":return n("err_invalid_value");default:return _||r}}export{g as a}; import{q as a}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PBRIQQ2X.js";var s={entry_id:"object",name:"name",task_type:"maintenance_type",schedule_type:"schedule_type",interval_days:"interval_days",interval_anchor:"interval_anchor",warning_days:"warning_days",last_performed:"last_performed_optional",notes:"notes_optional",documentation_url:"documentation_url_optional",custom_icon:"custom_icon_optional",nfc_tag_id:"nfc_tag_id_optional",responsible_user_id:"responsible_user",entity_slug:"entity_slug",entity_id:"entity_id",area_id:"area_id_optional",manufacturer:"manufacturer_optional",model:"model_optional",serial_number:"serial_number_optional",installation_date:"installation_date_optional",warranty_expiry:"warranty_expiry_optional",checklist:"checklist_steps_optional",reason:"reason",feedback:"feedback",cost:"cost",duration:"duration",description:"description_optional",group_name:"name",group_description:"description_optional",environmental_entity:"environmental_entity_optional",environmental_attribute:"environmental_attribute_optional",trigger_above:"trigger_above",trigger_below:"trigger_below",trigger_equals:"trigger_equals",trigger_not_equals:"trigger_not_equals",trigger_for_minutes:"trigger_for_minutes"};function c(e,o){let r=s[e];if(!r)return e;let t=a(r,o);return t&&t!==r?t:e}function d(e){let r=e.match(/data\['([^']+)'\]/)?.[1],t;return(t=e.match(/length of value must be at most (\d+)/))?{field:r,rule:"too_long",param:t[1]}:(t=e.match(/length of value must be at least (\d+)/))?{field:r,rule:"too_short",param:t[1]}:(t=e.match(/value must be at most (\S+)/))?{field:r,rule:"value_too_high",param:t[1]}:(t=e.match(/value must be at least (\S+)/))?{field:r,rule:"value_too_low",param:t[1]}:/required key not provided/.test(e)?{field:r,rule:"required"}:(t=e.match(/expected (\w+)/))?{field:r,rule:"wrong_type",param:t[1]}:/value must be one of/.test(e)?{field:r,rule:"invalid_choice"}:/not a valid value/.test(e)?{field:r,rule:"invalid_value"}:{field:r,rule:"unknown"}}function g(e,o,r){if(r=r??a("action_error",o),typeof e=="string")return e;if(typeof e!="object"||e===null)return r;let t=e,_=t.message||t.error?.message||"";if(!_)return r;let i=d(_),l=i.field?c(i.field,o):"",n=u=>a(u,o).replace("{field}",l).replace("{n}",i.param??"");switch(i.rule){case"too_long":return n("err_too_long");case"too_short":return n("err_too_short");case"value_too_high":return n("err_value_too_high");case"value_too_low":return n("err_value_too_low");case"required":return n("err_required");case"wrong_type":return n("err_wrong_type").replace("{type}",i.param??"");case"invalid_choice":return n("err_invalid_choice");case"invalid_value":return n("err_invalid_value");default:return _||r}}export{g as a};
@@ -1,5 +1,5 @@
/*! maintenance_supporter frontend 2.68.0 */ /*! maintenance_supporter frontend 2.71.0 */
import{a as _,e as k}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-CPVQNQQQ.js";import{a as m}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PPH3NCFT.js";import{C as g,a as s,b,c as o,f as d,h as v,l as n,m as l,q as r}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YEY3J44W.js";var i=class extends v{constructor(){super(...arguments);this.entryId="";this.taskId="";this.taskName="";this.lang="en";this.checklist=[];this.adaptiveEnabled=!1;this.taskType="";this.readingUnit="";this.restockDefault=null;this.restockUnitCost=null;this.currencySymbol="";this.parts=[];this.consumesParts=[];this.consumesInfo=[];this.requiredFields=[];this.phaseLabel="";this.requireTagScan=!1;this.viaTagScan=!1;this._open=!1;this._notes="";this._cost="";this._duration="";this._loading=!1;this._error="";this._checklistState={};this._feedback="needed";this._photoDocId="";this._photoPreview="";this._photoUploading=!1;this._readingValue="";this._restockQty="";this._completedAt="";this._usedParts={};this.checklistPrefill={}}open(e={}){this._open||(this._open=!0,this.viaTagScan=!!e.viaTagScan,this._notes="",this._cost="",this._duration="",this._error="",this._checklistState=Object.fromEntries(this.checklist.map((t,a)=>[String(a),!!this.checklistPrefill[t]]).filter(([,t])=>t)),this._feedback="needed",this._photoDocId="",this._photoPreview="",this._photoUploading=!1,this._readingValue="",this._restockQty=this.restockDefault!==null?String(this.restockDefault):"",this._completedAt="",this._usedParts=Object.fromEntries(this.consumesParts.map(t=>[_(t),{...t}])))}_toggleCheck(e){let t=String(e);this._checklistState={...this._checklistState,[t]:!this._checklistState[t]}}_setFeedback(e){this._feedback=e}async _onPhotoInput(e){let t=e.target,a=t.files?.[0];if(t.value="",!!a){this._photoUploading=!0,this._error="";try{let c=new FormData;c.append("entry_id",this.entryId),c.append("tags","photo"),c.append("file",a,a.name);let p=await fetch("/api/maintenance_supporter/document/upload",{method:"POST",headers:{Authorization:`Bearer ${this.hass.auth?.data?.access_token??""}`},body:c});if(!p.ok){this._error=p.status===413?r("doc_too_large",this.lang):r("doc_upload_failed",this.lang);return}let u=await p.json();u.id&&(this._photoDocId=u.id,this._photoPreview=URL.createObjectURL(a))}catch{this._error=r("doc_upload_failed",this.lang)}finally{this._photoUploading=!1}}}_removePhoto(){this._photoPreview&&URL.revokeObjectURL(this._photoPreview),this._photoDocId="",this._photoPreview=""}async _complete(){this._loading=!0,this._error="";try{let e={type:"maintenance_supporter/task/complete",entry_id:this.entryId,task_id:this.taskId};if(this._notes&&(e.notes=this._notes),this._cost){let t=parseFloat(this._cost);!isNaN(t)&&t>=0&&(e.cost=t)}if(this._duration){let t=parseInt(this._duration,10);!isNaN(t)&&t>=0&&(e.duration=t)}if(this.checklist.length>0&&(e.checklist_state=this._checklistState),this.adaptiveEnabled&&(e.feedback=this._feedback),this._photoDocId&&(e.photo_doc_id=this._photoDocId),this.viaTagScan&&(e.via_tag_scan=!0),this._completedAt){if(new Date(this._completedAt).getTime()>Date.now()){this._error=r("completed_at_future_error",this.lang),this._loading=!1;return}e.completed_at=this._completedAt.length===16?`${this._completedAt}:00`:this._completedAt}if(this._readingValue!==""){let t=parseFloat(this._readingValue);isNaN(t)||(e.reading_value=t)}if(this.restockDefault!==null&&this._restockQty!==""){let t=parseFloat(this._restockQty);!isNaN(t)&&t>=1&&(e.restock_quantity=t)}this.parts.length>0&&(e.used_parts=Object.values(this._usedParts).filter(t=>Number.isFinite(t.quantity)&&t.quantity>0).map(t=>t.entry_id?{part_id:t.part_id,quantity:t.quantity,entry_id:t.entry_id}:{part_id:t.part_id,quantity:t.quantity})),await this.hass.connection.sendMessagePromise(e),this._open=!1,this.dispatchEvent(new CustomEvent("task-completed"))}catch(e){this._error=m(e,this.lang,r("save_error",this.lang))}finally{this._loading=!1}}get _missingRequired(){let e={notes:this._notes.trim()!=="",cost:this._cost.trim()!=="",duration:this._duration.trim()!=="",photo:this._photoDocId!=="",user:!!this.hass?.user};return this.requiredFields.filter(t=>!e[t])}_req(e){return this.requiredFields.includes(e)?o`<span class="req-mark" aria-hidden="true">*</span>`:d}_partsCostSuggestion(){if(this.restockDefault!==null){let a=parseFloat(this._restockQty);return this.restockUnitCost==null||!Number.isFinite(a)||a<=0?null:Math.round(this.restockUnitCost*a*100)/100}if(!this.parts.length)return null;let e=0,t=!1;for(let a of Object.values(this._usedParts)){let c=this.parts.find(p=>_({part_id:p.id,entry_id:p.entry_id})===_(a));c?.cost!=null&&(e+=c.cost*(a.quantity||1),t=!0)}return t?Math.round(e*100)/100:null}_renderCostSuggestion(e){if(this._cost.trim()!=="")return d;let t=this._partsCostSuggestion();if(t==null||t<=0)return d;let a=`${t.toFixed(2)}${this.currencySymbol?` ${this.currencySymbol}`:""}`;return o`<button import{a as _,e as k}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-WQQNFFGB.js";import{a as m}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-GJI3RTUI.js";import{C as g,a as s,b,c as o,f as d,h as v,l as n,m as l,q as r}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PBRIQQ2X.js";var i=class extends v{constructor(){super(...arguments);this.entryId="";this.taskId="";this.taskName="";this.lang="en";this.checklist=[];this.adaptiveEnabled=!1;this.taskType="";this.readingUnit="";this.restockDefault=null;this.restockUnitCost=null;this.currencySymbol="";this.parts=[];this.consumesParts=[];this.consumesInfo=[];this.requiredFields=[];this.phaseLabel="";this.requireTagScan=!1;this.viaTagScan=!1;this._open=!1;this._notes="";this._cost="";this._duration="";this._loading=!1;this._error="";this._checklistState={};this._feedback="needed";this._photoDocId="";this._photoPreview="";this._photoUploading=!1;this._readingValue="";this._restockQty="";this._completedAt="";this._usedParts={};this.checklistPrefill={}}open(e={}){this._open||(this._open=!0,this.viaTagScan=!!e.viaTagScan,this._notes="",this._cost="",this._duration="",this._error="",this._checklistState=Object.fromEntries(this.checklist.map((t,a)=>[String(a),!!this.checklistPrefill[t]]).filter(([,t])=>t)),this._feedback="needed",this._photoDocId="",this._photoPreview="",this._photoUploading=!1,this._readingValue="",this._restockQty=this.restockDefault!==null?String(this.restockDefault):"",this._completedAt="",this._usedParts=Object.fromEntries(this.consumesParts.map(t=>[_(t),{...t}])))}_toggleCheck(e){let t=String(e);this._checklistState={...this._checklistState,[t]:!this._checklistState[t]}}_setFeedback(e){this._feedback=e}async _onPhotoInput(e){let t=e.target,a=t.files?.[0];if(t.value="",!!a){this._photoUploading=!0,this._error="";try{let c=new FormData;c.append("entry_id",this.entryId),c.append("tags","photo"),c.append("file",a,a.name);let p=await fetch("/api/maintenance_supporter/document/upload",{method:"POST",headers:{Authorization:`Bearer ${this.hass.auth?.data?.access_token??""}`},body:c});if(!p.ok){this._error=p.status===413?r("doc_too_large",this.lang):r("doc_upload_failed",this.lang);return}let u=await p.json();u.id&&(this._photoDocId=u.id,this._photoPreview=URL.createObjectURL(a))}catch{this._error=r("doc_upload_failed",this.lang)}finally{this._photoUploading=!1}}}_removePhoto(){this._photoPreview&&URL.revokeObjectURL(this._photoPreview),this._photoDocId="",this._photoPreview=""}async _complete(){this._loading=!0,this._error="";try{let e={type:"maintenance_supporter/task/complete",entry_id:this.entryId,task_id:this.taskId};if(this._notes&&(e.notes=this._notes),this._cost){let t=parseFloat(this._cost);!isNaN(t)&&t>=0&&(e.cost=t)}if(this._duration){let t=parseInt(this._duration,10);!isNaN(t)&&t>=0&&(e.duration=t)}if(this.checklist.length>0&&(e.checklist_state=this._checklistState),this.adaptiveEnabled&&(e.feedback=this._feedback),this._photoDocId&&(e.photo_doc_id=this._photoDocId),this.viaTagScan&&(e.via_tag_scan=!0),this._completedAt){if(new Date(this._completedAt).getTime()>Date.now()){this._error=r("completed_at_future_error",this.lang),this._loading=!1;return}e.completed_at=this._completedAt.length===16?`${this._completedAt}:00`:this._completedAt}if(this._readingValue!==""){let t=parseFloat(this._readingValue);isNaN(t)||(e.reading_value=t)}if(this.restockDefault!==null&&this._restockQty!==""){let t=parseFloat(this._restockQty);!isNaN(t)&&t>=1&&(e.restock_quantity=t)}this.parts.length>0&&(e.used_parts=Object.values(this._usedParts).filter(t=>Number.isFinite(t.quantity)&&t.quantity>0).map(t=>t.entry_id?{part_id:t.part_id,quantity:t.quantity,entry_id:t.entry_id}:{part_id:t.part_id,quantity:t.quantity})),await this.hass.connection.sendMessagePromise(e),this._open=!1,this.dispatchEvent(new CustomEvent("task-completed"))}catch(e){this._error=m(e,this.lang,r("save_error",this.lang))}finally{this._loading=!1}}get _missingRequired(){let e={notes:this._notes.trim()!=="",cost:this._cost.trim()!=="",duration:this._duration.trim()!=="",photo:this._photoDocId!=="",user:!!this.hass?.user};return this.requiredFields.filter(t=>!e[t])}_req(e){return this.requiredFields.includes(e)?o`<span class="req-mark" aria-hidden="true">*</span>`:d}_partsCostSuggestion(){if(this.restockDefault!==null){let a=parseFloat(this._restockQty);return this.restockUnitCost==null||!Number.isFinite(a)||a<=0?null:Math.round(this.restockUnitCost*a*100)/100}if(!this.parts.length)return null;let e=0,t=!1;for(let a of Object.values(this._usedParts)){let c=this.parts.find(p=>_({part_id:p.id,entry_id:p.entry_id})===_(a));c?.cost!=null&&(e+=c.cost*(a.quantity||1),t=!0)}return t?Math.round(e*100)/100:null}_renderCostSuggestion(e){if(this._cost.trim()!=="")return d;let t=this._partsCostSuggestion();if(t==null||t<=0)return d;let a=`${t.toFixed(2)}${this.currencySymbol?` ${this.currencySymbol}`:""}`;return o`<button
type="button" type="button"
class="cost-suggestion" class="cost-suggestion"
@click=${()=>this._cost=t.toFixed(2)} @click=${()=>this._cost=t.toFixed(2)}
@@ -1,2 +1,2 @@
/*! maintenance_supporter frontend 2.70.0 */ /*! maintenance_supporter frontend 2.71.0 */
var r=class{constructor(s){this.usersCache=null;this.cacheTimestamp=0;this.CACHE_TTL_MS=6e4;this.hass=s}updateHass(s){this.hass=s}async getUsers(s=!1){let e=Date.now();if(!s&&this.usersCache&&e-this.cacheTimestamp<this.CACHE_TTL_MS)return this.usersCache;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/users/list"});return this.usersCache=t.users,this.cacheTimestamp=e,this.usersCache}catch(t){return console.error("Failed to fetch users:",t),this.usersCache||[]}}async assignUser(s,e,t){await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/assign_user",entry_id:s,task_id:e,user_id:t})}async getTasksByUser(s){return(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/tasks/by_user",user_id:s})).tasks}getUserName(s){return!s||!this.usersCache?null:this.usersCache.find(t=>t.id===s)?.name||null}getUser(s){return!s||!this.usersCache?null:this.usersCache.find(e=>e.id===s)||null}getCurrentUserId(){return this.hass.user?.id||null}isCurrentUser(s){return s?s===this.getCurrentUserId():!1}clearCache(){this.usersCache=null,this.cacheTimestamp=0}};export{r as a}; var r=class{constructor(s){this.usersCache=null;this.cacheTimestamp=0;this.CACHE_TTL_MS=6e4;this.hass=s}updateHass(s){this.hass=s}async getUsers(s=!1){let e=Date.now();if(!s&&this.usersCache&&e-this.cacheTimestamp<this.CACHE_TTL_MS)return this.usersCache;try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/users/list"});return this.usersCache=t.users,this.cacheTimestamp=e,this.usersCache}catch(t){return console.error("Failed to fetch users:",t),this.usersCache||[]}}async assignUser(s,e,t){await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/assign_user",entry_id:s,task_id:e,user_id:t})}async getTasksByUser(s){return(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/tasks/by_user",user_id:s})).tasks}getUserName(s){return!s||!this.usersCache?null:this.usersCache.find(t=>t.id===s)?.name||null}getUser(s){return!s||!this.usersCache?null:this.usersCache.find(e=>e.id===s)||null}getCurrentUserId(){return this.hass.user?.id||null}isCurrentUser(s){return s?s===this.getCurrentUserId():!1}clearCache(){this.usersCache=null,this.cacheTimestamp=0}};export{r as a};
@@ -1,147 +0,0 @@
/*! maintenance_supporter frontend 2.70.0 */
import{a as u}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-KKI2ZPWC.js";import{a as r,b as _,c as l,f as o,h as p,l as d,m as s,q as i,s as h}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-VSV22GFT.js";var a=class extends p{constructor(){super(...arguments);this.objects=[];this._open=!1;this._loading=!1;this._error="";this._name="";this._manufacturer="";this._model="";this._serialNumber="";this._areaId="";this._installationDate="";this._warrantyExpiry="";this._documentationUrl="";this._notes="";this._haDeviceId="";this._parentEntryId="";this._entryId=null}get _lang(){return h(this.hass)}openCreate(){this._entryId=null,this._name="",this._manufacturer="",this._model="",this._serialNumber="",this._areaId="",this._installationDate="",this._warrantyExpiry="",this._documentationUrl="",this._notes="",this._haDeviceId="",this._parentEntryId="",this._error="",this._open=!0}openEdit(e,n){this._entryId=e,this._name=n.name||"",this._manufacturer=n.manufacturer||"",this._model=n.model||"",this._serialNumber=n.serial_number||"",this._areaId=n.area_id||"",this._installationDate=n.installation_date||"",this._warrantyExpiry=n.warranty_expiry||"",this._documentationUrl=n.documentation_url||"",this._notes=n.notes||"",this._haDeviceId=n.ha_device_id||"",this._parentEntryId=n.parent_entry_id||"",this._error="",this._open=!0}async _save(){if(!this._loading&&this._name.trim()){this._loading=!0,this._error="";try{this._entryId?await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/update",entry_id:this._entryId,name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}):await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/create",name:this._name,manufacturer:this._manufacturer||null,model:this._model||null,serial_number:this._serialNumber||null,area_id:this._areaId||null,installation_date:this._installationDate||null,warranty_expiry:this._warrantyExpiry||null,documentation_url:this._documentationUrl.trim()||null,notes:this._notes.trim()||null,ha_device_id:this._haDeviceId||null,parent_entry_id:this._parentEntryId||null}),this._open=!1,this.dispatchEvent(new CustomEvent("object-saved"))}catch(e){this._error=u(e,this._lang,i("save_error",this._lang))}finally{this._loading=!1}}}_parentChoices(){return(this.objects||[]).filter(e=>e.entry_id!==this._entryId)}_close(){this._open=!1}render(){if(!this._open)return l``;let e=this._lang,n=this._entryId?i("edit_object",e):i("new_object",e);return l`
<ha-dialog open @closed=${this._close}>
<div class="dialog-title">${n}</div>
<div class="content">
${this._error?l`<div class="error">${this._error}</div>`:o}
<ms-textfield
label="${i("name",e)}"
required
.value=${this._name}
@input=${t=>this._name=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("manufacturer_optional",e)}"
.value=${this._manufacturer}
@input=${t=>this._manufacturer=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("model_optional",e)}"
.value=${this._model}
@input=${t=>this._model=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("serial_number_optional",e)}"
.value=${this._serialNumber}
@input=${t=>this._serialNumber=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("documentation_url_optional",e)}"
type="url"
.value=${this._documentationUrl}
@input=${t=>this._documentationUrl=t.target.value}
></ms-textfield>
<ha-area-picker
.hass=${this.hass}
label="${i("area_id_optional",e)}"
.value=${this._areaId}
@value-changed=${t=>this._areaId=t.detail.value||""}
></ha-area-picker>
<ms-textfield
label="${i("installation_date_optional",e)}"
type="date"
.value=${this._installationDate}
@input=${t=>this._installationDate=t.target.value}
></ms-textfield>
<ms-textfield
label="${i("warranty_expiry_optional",e)}"
type="date"
.value=${this._warrantyExpiry}
@input=${t=>this._warrantyExpiry=t.target.value}
></ms-textfield>
<ha-form
.hass=${this.hass}
.data=${{device:this._haDeviceId||void 0}}
.schema=${[{name:"device",selector:{device:{}}}]}
.computeLabel=${()=>i("link_device_optional",e)}
@value-changed=${t=>this._haDeviceId=t.detail.value?.device||""}
></ha-form>
${this._parentChoices().length?l`<label class="textarea-field">
<span class="textarea-label">${i("parent_object_optional",e)}</span>
<select
class="parent-select"
.value=${this._parentEntryId}
@change=${t=>this._parentEntryId=t.target.value}
>
<option value="" ?selected=${!this._parentEntryId}>
${i("parent_none",e)}
</option>
${this._parentChoices().map(t=>l`<option
value=${t.entry_id}
?selected=${this._parentEntryId===t.entry_id}
>${t.object.name}</option>`)}
</select>
</label>`:o}
<label class="textarea-field">
<span class="textarea-label">${i("object_notes_optional",e)}</span>
<textarea
rows="3"
.value=${this._notes}
@input=${t=>this._notes=t.target.value}
></textarea>
<span class="md-hint">${i("notes_markdown_hint",e)}</span>
</label>
</div>
<div class="dialog-actions">
<ha-button appearance="plain" @click=${this._close}>
${i("cancel",this._lang)}
</ha-button>
<ha-button
@click=${this._save}
.disabled=${this._loading||!this._name.trim()}
>
${this._loading?i("saving",this._lang):i("save",this._lang)}
</ha-button>
</div>
</ha-dialog>
`}};a.styles=_`
.dialog-title {
font-size: 18px;
font-weight: 500;
padding-bottom: 12px;
}
.content {
display: flex;
flex-direction: column;
gap: 16px;
min-width: 300px;
}
.dialog-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
padding-top: 16px;
}
ms-textfield {
display: block;
}
.textarea-field {
display: flex; flex-direction: column; gap: 4px;
}
.textarea-label {
font-size: 12px; color: var(--secondary-text-color, #888); font-weight: 500;
}
.textarea-field textarea {
padding: 8px 10px; font-size: 14px; font-family: inherit;
background: var(--secondary-background-color, rgba(0,0,0,0.06));
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
resize: vertical;
}
.textarea-field textarea:focus {
outline: none; border-color: var(--primary-color);
}
.md-hint {
font-size: 11px; color: var(--secondary-text-color); font-style: italic;
}
.parent-select {
padding: 8px 10px; font-size: 14px; font-family: inherit;
background: var(--secondary-background-color, rgba(0,0,0,0.06));
color: var(--primary-text-color);
border: 1px solid var(--divider-color); border-radius: 6px;
}
.error {
color: var(--error-color, #f44336);
font-size: 13px;
}
`,r([d({attribute:!1})],a.prototype,"hass",2),r([d({attribute:!1})],a.prototype,"objects",2),r([s()],a.prototype,"_open",2),r([s()],a.prototype,"_loading",2),r([s()],a.prototype,"_error",2),r([s()],a.prototype,"_name",2),r([s()],a.prototype,"_manufacturer",2),r([s()],a.prototype,"_model",2),r([s()],a.prototype,"_serialNumber",2),r([s()],a.prototype,"_areaId",2),r([s()],a.prototype,"_installationDate",2),r([s()],a.prototype,"_warrantyExpiry",2),r([s()],a.prototype,"_documentationUrl",2),r([s()],a.prototype,"_notes",2),r([s()],a.prototype,"_haDeviceId",2),r([s()],a.prototype,"_parentEntryId",2),r([s()],a.prototype,"_entryId",2);customElements.get("maintenance-object-dialog")||customElements.define("maintenance-object-dialog",a);export{a};
@@ -1,2 +1,2 @@
/*! maintenance_supporter frontend 2.70.0 */ /*! maintenance_supporter frontend 2.71.0 */
import{b as i}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-3L2PFMVS.js";async function l(e,n,t=300){return(await e.connection.sendMessagePromise({type:"auth/sign_path",path:n,expires:t})).path}async function r(e,n,t=300){return l(e,`/api/maintenance_supporter/document/${n}`,t)}async function y(e,n,t=""){let a=window.open("about:blank","_blank");try{let o=await r(e,n);a&&(a.location.href=new URL(o+t,window.location.origin).href)}catch(o){throw a&&a.close(),o}}async function p(e,n,t){i(await r(e,n,30),t)}function d(e){let n=URL.createObjectURL(new Blob([e],{type:"text/html"}));window.open(n,"_blank"),setTimeout(()=>URL.revokeObjectURL(n),6e4)}var c=[{key:"name",labelKey:"name",required:!0},{key:"manufacturer",labelKey:"manufacturer"},{key:"model",labelKey:"model"},{key:"serial_number",labelKey:"serial_number_label"},{key:"installation_date",labelKey:"installed"},{key:"warranty_expiry",labelKey:"warranty"},{key:"area_id",labelKey:"area"},{key:"documentation_url",labelKey:"documentation_url_label"},{key:"notes",labelKey:"object_notes_label"},{key:"task_count",labelKey:"tasks"},{key:"actions",labelKey:"actions"}],u=c.map(e=>e.key),s=["name","manufacturer","model","serial_number","installation_date","warranty_expiry","area_id","task_count","actions"];function g(e){if(!Array.isArray(e))return[...s];let n=new Set,t=[];for(let a of e)typeof a=="string"&&u.includes(a)&&!n.has(a)&&(n.add(a),t.push(a));return t.length?(t.includes("name")||t.unshift("name"),t):[...s]}export{l as a,r as b,y as c,p as d,d as e,c as f,s as g,g as h}; import{b as i}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-BQCLT4RW.js";async function l(e,n,t=300){return(await e.connection.sendMessagePromise({type:"auth/sign_path",path:n,expires:t})).path}async function r(e,n,t=300){return l(e,`/api/maintenance_supporter/document/${n}`,t)}async function y(e,n,t=""){let a=window.open("about:blank","_blank");try{let o=await r(e,n);a&&(a.location.href=new URL(o+t,window.location.origin).href)}catch(o){throw a&&a.close(),o}}async function p(e,n,t){i(await r(e,n,30),t)}function d(e){let n=URL.createObjectURL(new Blob([e],{type:"text/html"}));window.open(n,"_blank"),setTimeout(()=>URL.revokeObjectURL(n),6e4)}var c=[{key:"name",labelKey:"name",required:!0},{key:"manufacturer",labelKey:"manufacturer"},{key:"model",labelKey:"model"},{key:"serial_number",labelKey:"serial_number_label"},{key:"installation_date",labelKey:"installed"},{key:"warranty_expiry",labelKey:"warranty"},{key:"area_id",labelKey:"area"},{key:"documentation_url",labelKey:"documentation_url_label"},{key:"notes",labelKey:"object_notes_label"},{key:"task_count",labelKey:"tasks"},{key:"actions",labelKey:"actions"}],u=c.map(e=>e.key),s=["name","manufacturer","model","serial_number","installation_date","warranty_expiry","area_id","task_count","actions"];function g(e){if(!Array.isArray(e))return[...s];let n=new Set,t=[];for(let a of e)typeof a=="string"&&u.includes(a)&&!n.has(a)&&(n.add(a),t.push(a));return t.length?(t.includes("name")||t.unshift("name"),t):[...s]}export{l as a,r as b,y as c,p as d,d as e,c as f,s as g,g as h};
@@ -1,5 +1,5 @@
/*! maintenance_supporter frontend 2.68.0 */ /*! maintenance_supporter frontend 2.71.0 */
import{a as x}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-LATOZBYW.js";import{a,b as v,c as n,f as p,h as b,l as h,m as c,q as t}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YEY3J44W.js";function d(l){return l.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function f(l){return!l.startsWith("data:image/svg+xml,")&&!l.startsWith("data:image/png;base64,")?"":d(l)}function q(l){return l.replace(/[/\\:*?"<>|#%]+/g,"").replace(/\s+/g,"-").toLowerCase().substring(0,100)}var o=class extends b{constructor(){super(...arguments);this.lang="en";this._open=!1;this._loading=!1;this._error="";this._viewResult=null;this._completeResult=null;this._urlMode="companion";this._entryId="";this._taskId=null;this._objectName="";this._taskName="";this._generateSeq=0}openForObject(e,i){this._entryId=e,this._taskId=null,this._objectName=i,this._taskName="",this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}openForTask(e,i,r,s){this._entryId=e,this._taskId=i,this._objectName=r,this._taskName=s,this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}async _generate(){let e=++this._generateSeq;this._loading=!0,this._error="",this._viewResult=null,this._completeResult=null;try{let i={type:"maintenance_supporter/qr/generate",entry_id:this._entryId,url_mode:this._urlMode};this._taskId&&(i.task_id=this._taskId);let r=[this.hass.connection.sendMessagePromise({...i,action:"view"})];this._taskId&&r.push(this.hass.connection.sendMessagePromise({...i,action:"complete"}));let s=await Promise.all(r);if(e!==this._generateSeq)return;this._viewResult=s[0],s.length>1&&(this._completeResult=s[1])}catch(i){if(e!==this._generateSeq)return;let r=i?.code,s=i?.message;this._error=r==="no_url"||typeof s=="string"&&s.includes("No Home Assistant URL")?t("qr_error_no_url",this.lang):t("qr_error",this.lang)}finally{e===this._generateSeq&&(this._loading=!1)}}_setUrlMode(e){this._urlMode!==e&&(this._urlMode=e,this._generate())}_print(){if(!this._viewResult)return;let e=this._viewResult,i=e.label.task_name?`${e.label.object_name} \u2014 ${e.label.task_name}`:e.label.object_name,r=[e.label.manufacturer,e.label.model].filter(Boolean).join(" "),s=window.open("","_blank","width=600,height=500");if(!s)return;let g=this.lang||"en",u=d(i),m=d(r),_=!!this._completeResult,w=d(t("qr_action_view",g)),$=d(t("qr_action_complete",g));s.document.write(`<!DOCTYPE html><html><head><meta charset="utf-8"> import{a as x}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-BQCLT4RW.js";import{a,b as v,c as n,f as p,h as b,l as h,m as c,q as t}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PBRIQQ2X.js";function d(l){return l.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function f(l){return!l.startsWith("data:image/svg+xml,")&&!l.startsWith("data:image/png;base64,")?"":d(l)}function q(l){return l.replace(/[/\\:*?"<>|#%]+/g,"").replace(/\s+/g,"-").toLowerCase().substring(0,100)}var o=class extends b{constructor(){super(...arguments);this.lang="en";this._open=!1;this._loading=!1;this._error="";this._viewResult=null;this._completeResult=null;this._urlMode="companion";this._entryId="";this._taskId=null;this._objectName="";this._taskName="";this._generateSeq=0}openForObject(e,i){this._entryId=e,this._taskId=null,this._objectName=i,this._taskName="",this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}openForTask(e,i,r,s){this._entryId=e,this._taskId=i,this._objectName=r,this._taskName=s,this._urlMode="companion",this._error="",this._viewResult=null,this._completeResult=null,this._open=!0,this._generate()}async _generate(){let e=++this._generateSeq;this._loading=!0,this._error="",this._viewResult=null,this._completeResult=null;try{let i={type:"maintenance_supporter/qr/generate",entry_id:this._entryId,url_mode:this._urlMode};this._taskId&&(i.task_id=this._taskId);let r=[this.hass.connection.sendMessagePromise({...i,action:"view"})];this._taskId&&r.push(this.hass.connection.sendMessagePromise({...i,action:"complete"}));let s=await Promise.all(r);if(e!==this._generateSeq)return;this._viewResult=s[0],s.length>1&&(this._completeResult=s[1])}catch(i){if(e!==this._generateSeq)return;let r=i?.code,s=i?.message;this._error=r==="no_url"||typeof s=="string"&&s.includes("No Home Assistant URL")?t("qr_error_no_url",this.lang):t("qr_error",this.lang)}finally{e===this._generateSeq&&(this._loading=!1)}}_setUrlMode(e){this._urlMode!==e&&(this._urlMode=e,this._generate())}_print(){if(!this._viewResult)return;let e=this._viewResult,i=e.label.task_name?`${e.label.object_name} \u2014 ${e.label.task_name}`:e.label.object_name,r=[e.label.manufacturer,e.label.model].filter(Boolean).join(" "),s=window.open("","_blank","width=600,height=500");if(!s)return;let g=this.lang||"en",u=d(i),m=d(r),_=!!this._completeResult,w=d(t("qr_action_view",g)),$=d(t("qr_action_complete",g));s.document.write(`<!DOCTYPE html><html><head><meta charset="utf-8">
<meta name="color-scheme" content="light"> <meta name="color-scheme" content="light">
<title>${u}</title> <title>${u}</title>
<style> <style>
@@ -1,812 +0,0 @@
/*! maintenance_supporter frontend 2.68.0 */
import{b as nt,c as st}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-CPVQNQQQ.js";import{a as A}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-PPH3NCFT.js";import{A as X,B as tt,D as et,a as m,b as E,c as o,d as S,f as d,h as H,l as j,m as y,n as N,q as a,s as I,t as Z,u as Y,v as O,w as Q,y as J}from"/maintenance_supporter_panelfiles/panel-chunks/chunk-YEY3J44W.js";var $=class extends H{constructor(){super(...arguments);this._open=!1;this._saving=!1;this._error="";this._draft=null;this._originalSnapshot=null;this._partOptions=null;this._partQty={};this._partQtyOriginal=""}get _lang(){return I(this.hass)}openEdit(t){this._draft={...t},this._originalSnapshot={...t},this._error="",this._open=!0,this._partOptions=null,this._partQty={},this._partQtyOriginal="",this._loadPartOptions()}async _loadPartOptions(){let t=this._draft;if(t)try{let n=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/parts/overview"}),i=[];for(let l of n.parts||[]){let c=l.entry_id===t.entry_id,p=l.consumers.some(u=>u.entry_id===t.entry_id&&u.task_id===t.task_id);!c&&!p||i.push({part_id:l.part_id,name:l.name,entry_id:l.entry_id,foreign:!c,object_name:l.object_name})}for(let l of t.used_parts||[]){let c=l.entry_id||t.entry_id;i.some(p=>p.part_id===l.part_id&&p.entry_id===c)||i.push({part_id:l.part_id,name:l.name||l.part_id,entry_id:c,foreign:c!==t.entry_id,object_name:null})}let r={};for(let l of t.used_parts||[])r[`${l.entry_id||t.entry_id}:${l.part_id}`]=l.quantity??1;this._partOptions=i,this._partQty=r,this._partQtyOriginal=this._partSelectionKey()}catch{this._partOptions=[]}}_partSelectionKey(){return JSON.stringify(Object.entries(this._partQty).filter(([,t])=>t>0).sort(([t],[n])=>t.localeCompare(n)))}close(){this._open=!1,this._error="",this._draft=null,this._originalSnapshot=null}_set(t,n){this._draft&&(this._draft={...this._draft,[t]:n})}async _save(){if(!(!this._draft||!this._originalSnapshot)){this._saving=!0,this._error="";try{let t={type:"maintenance_supporter/task/history/update",entry_id:this._draft.entry_id,task_id:this._draft.task_id,original_timestamp:this._originalSnapshot.original_timestamp};if(this._draft.timestamp!==this._originalSnapshot.timestamp&&(t.timestamp=this._draft.timestamp),this._draft.notes!==this._originalSnapshot.notes&&(t.notes=this._draft.notes),this._draft.cost!==this._originalSnapshot.cost&&(t.cost=this._draft.cost),this._draft.duration!==this._originalSnapshot.duration&&(t.duration=this._draft.duration),this._draft.completed_by!==this._originalSnapshot.completed_by&&(t.completed_by=this._draft.completed_by),this._partOptions!==null&&this._partSelectionKey()!==this._partQtyOriginal&&(t.used_parts=(this._partOptions||[]).filter(i=>(this._partQty[`${i.entry_id}:${i.part_id}`]||0)>0).map(i=>({part_id:i.part_id,quantity:this._partQty[`${i.entry_id}:${i.part_id}`],...i.foreign?{entry_id:i.entry_id}:{}}))),Object.keys(t).filter(i=>!["type","entry_id","task_id","original_timestamp"].includes(i)).length===0){this.close();return}await this.hass.connection.sendMessagePromise(t),this.dispatchEvent(new CustomEvent("history-entry-saved",{detail:{entry_id:this._draft.entry_id,task_id:this._draft.task_id,new_timestamp:this._draft.timestamp},bubbles:!0,composed:!0})),this.close()}catch(t){this._error=A(t,this._lang)}finally{this._saving=!1}}}render(){if(!this._open||!this._draft)return d;let t=this._lang,n=this._draft;return o`
<div class="backdrop" @click=${this.close}></div>
<div class="dialog" role="dialog" aria-modal="true">
<h2>${a("history_edit_title",t)||"Edit history entry"}</h2>
<div class="entry-type">
<ha-icon icon="mdi:tag-outline"></ha-icon>
<span>${a(n.type,t)||n.type}</span>
</div>
<label>
<span>${a("history_edit_timestamp",t)||"Timestamp"}</span>
<input type="datetime-local"
.value=${n.timestamp.length>=16?n.timestamp.slice(0,16):n.timestamp}
@change=${i=>{let r=i.target.value;this._set("timestamp",r.length===16?`${r}:00`:r)}} />
</label>
<label>
<span>${a("notes_label",t)}</span>
<textarea
rows="3"
@input=${i=>{let r=i.target.value;this._set("notes",r||null)}}
.value=${n.notes??""}></textarea>
</label>
<div class="row">
<label>
<span>${a("cost",t)||"Cost"}</span>
<input type="number" min="0" step="0.01"
.value=${n.cost!=null?String(n.cost):""}
@input=${i=>{let r=i.target.value;this._set("cost",r?Number(r):null)}} />
</label>
<label>
<span>${a("duration",t)||"Duration (min)"}</span>
<input type="number" min="0"
.value=${n.duration!=null?String(n.duration):""}
@input=${i=>{let r=i.target.value;this._set("duration",r?Number(r):null)}} />
</label>
</div>
${this._partOptions&&this._partOptions.length>0?o`
<div class="parts-block">
<span class="parts-title">${a("complete_parts_used",t)}</span>
${this._partOptions.map(i=>{let r=`${i.entry_id}:${i.part_id}`,l=this._partQty[r]||0;return o`
<label class="part-row-edit">
<input type="checkbox" .checked=${l>0}
@change=${c=>{let p=c.target.checked;this._partQty={...this._partQty,[r]:p?1:0}}} />
<span class="part-label">${i.name}${i.foreign&&i.object_name?` (${i.object_name})`:""}</span>
${l>0?o`
<input class="part-qty" type="number" min="0.01" max="999" step="0.01"
.value=${String(l)}
@input=${c=>{let p=parseFloat(c.target.value);!isNaN(p)&&p>0&&(this._partQty={...this._partQty,[r]:p})}} />
`:d}
</label>
`})}
</div>
`:d}
${this._error?o`<div class="error">${this._error}</div>`:d}
<div class="actions">
<button class="cancel" @click=${this.close} ?disabled=${this._saving}>
${a("cancel",t)||"Cancel"}
</button>
<button class="save" @click=${this._save} ?disabled=${this._saving}>
${this._saving?a("saving",t)||"Saving\u2026":a("save",t)||"Save"}
</button>
</div>
</div>
`}};$.styles=E`
:host { display: contents; }
.backdrop {
position: fixed; inset: 0;
background: rgba(0,0,0,0.5);
z-index: 100;
}
.dialog {
position: fixed; left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 95vw; max-width: 480px;
background: var(--card-background-color, var(--ha-card-background, #1c1c1c));
color: var(--primary-text-color);
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.4);
padding: 20px;
display: flex; flex-direction: column; gap: 12px;
z-index: 101;
max-height: 90vh; overflow: auto;
}
h2 { margin: 0; font-size: 18px; }
.entry-type {
display: flex; align-items: center; gap: 6px;
color: var(--secondary-text-color); font-size: 13px;
}
label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
label span { color: var(--secondary-text-color); }
.row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
input, textarea {
padding: 8px; font-size: 14px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color, #444);
border-radius: 6px;
width: 100%; box-sizing: border-box;
font-family: inherit;
}
.actions {
display: flex; gap: 8px; justify-content: flex-end;
margin-top: 8px;
}
button {
padding: 8px 16px; font-size: 14px;
border-radius: 6px; cursor: pointer;
border: none; font-weight: 500;
}
button.cancel {
background: transparent;
color: var(--primary-text-color);
border: 1px solid var(--divider-color);
}
button.save {
background: var(--primary-color);
color: var(--text-primary-color, white);
}
button[disabled] { opacity: 0.5; cursor: wait; }
.error {
color: var(--error-color, #d32f2f);
font-size: 13px; padding: 8px;
background: rgba(211,47,47,0.1);
border-radius: 6px;
}
/* #130: parts on the entry */
.parts-block {
display: flex; flex-direction: column; gap: 6px;
border: 1px solid var(--divider-color, #444);
border-radius: 6px; padding: 8px;
}
.parts-title { color: var(--secondary-text-color); font-size: 13px; }
.part-row-edit {
display: flex; flex-direction: row; align-items: center; gap: 8px;
font-size: 14px;
}
.part-row-edit input[type="checkbox"] { width: auto; }
.part-label { flex: 1; color: var(--primary-text-color); }
.part-qty { width: 76px; }
`,m([j({attribute:!1})],$.prototype,"hass",2),m([y()],$.prototype,"_open",2),m([y()],$.prototype,"_saving",2),m([y()],$.prototype,"_error",2),m([y()],$.prototype,"_draft",2),m([y()],$.prototype,"_partOptions",2),m([y()],$.prototype,"_partQty",2);customElements.get("maintenance-history-edit-dialog")||customElements.define("maintenance-history-edit-dialog",$);var At={days:1,weeks:7,months:30.4368,years:365.25};function U(e,s){return!e||e<=0?0:e*(At[s||"days"]??1)}function Yt(e,s,t){let n=U(e,t);if(n<=0||s==null)return{pct:0,overflow:!1};let i=(n-s)/n*100;return{pct:Math.max(0,Math.min(100,i)),overflow:i>100}}var it=5;function R(e){let s=e.getFullYear(),t=String(e.getMonth()+1).padStart(2,"0"),n=String(e.getDate()).padStart(2,"0");return`${s}-${t}-${n}`}function Lt(e,s){let t=[];for(let n=0;n<s;n++){let i=new Date(e);i.setDate(i.getDate()+n),i.setHours(0,0,0,0),t.push(R(i))}return t}function V(e,s){let[t,n,i]=e.split("-").map(Number),r=new Date(t,n-1,i);return r.setDate(r.getDate()+s),R(r)}function Mt(e){if(!e||e.length===0)return null;let s=e.map(t=>t.cost).filter(t=>typeof t=="number");return s.length===0?null:s.reduce((t,n)=>t+n,0)/s.length}function Dt(e){let{windowStart:s,windowEnd:t,task:n,entryId:i,objectName:r}=e,l=[],c=(_,g)=>({date:_,entry_id:i,task_id:n.id,task_name:n.name,object_name:r,status:g&&(n.status==="overdue"||n.status==="triggered")?"ok":n.status,days_until_due:g?null:n.days_until_due??null,projected:g,schedule_type:n.schedule_type,interval_days:n.interval_days??null,interval_unit:n.interval_unit??null,responsible_user_id:n.responsible_user_id??null,avg_cost:Mt(n.history),adaptive_enabled:!!n.adaptive_config?.enabled,prediction_confidence:n.threshold_prediction_confidence??null}),p=Math.max(1,Math.round(U(n.interval_days,n.interval_unit)));if(n.status==="overdue"||n.status==="triggered"){if(l.push(c(s,!1)),n.schedule_type==="time_based"&&n.interval_days&&n.interval_days>0){let _=V(s,p),g=1;for(;_<=t&&g<it;)l.push(c(_,!0)),g++,_=V(_,p)}return l}let u=n.next_due;if(typeof u!="string"||!u)return l;let h=u.slice(0,10);if(h>=s&&h<=t)l.push(c(h,!1));else if(h>t)return l;if(n.schedule_type==="time_based"&&n.interval_days&&n.interval_days>0){let _=V(h,p),g=l.length;for(;_<=t&&g<it;)_>=s&&(l.push(c(_,!0)),g++),_=V(_,p)}return l}var at={overdue:0,triggered:1,due_soon:2,ok:3};function Xt(e,s,t,n=null){let i=Lt(s,t),r=i[0],l=i[i.length-1],c=[];for(let u of e){let h=u.object?.name||"",_=u.entry_id,g=u.tasks||[];for(let f of g){if(n&&f.responsible_user_id!==n||f.enabled===!1)continue;let x=Dt({windowStart:r,windowEnd:l,task:f,entryId:_,objectName:h});c.push(...x)}}let p=new Map;for(let u of i)p.set(u,[]);for(let u of c){let h=p.get(u.date);h&&h.push(u)}for(let[,u]of p)u.sort((h,_)=>{let g=at[h.status]??99,f=at[_.status]??99;if(g!==f)return g-f;if(h.projected!==_.projected)return h.projected?1:-1;let x=h.object_name.localeCompare(_.object_name);return x!==0?x:h.task_name.localeCompare(_.task_name)});return i.map(u=>({date:u,events:p.get(u)??[]}))}var Tt={completed:"ok",reset:"ok",skipped:"due_soon",missed:"overdue",triggered:"triggered",trigger_replaced:"triggered",trigger_removed:"ok"};function Pt(e,s){let t=[];for(let n=s-1;n>=0;n--){let i=new Date(e);i.setDate(i.getDate()-n),i.setHours(0,0,0,0),t.push(R(i))}return t}function te(e,s,t,n=null){let i=Pt(s,t),r=i[0],l=i[i.length-1],c=new Map;for(let u of i)c.set(u,[]);for(let u of e){let h=u.object?.name||"",_=u.entry_id,g=u.tasks||[];for(let f of g){if(n&&f.responsible_user_id!==n)continue;let x=f.history||[];for(let v of x){if(typeof v?.timestamp!="string")continue;let M=v.timestamp.slice(0,10);if(M<r||M>l)continue;let C=c.get(M);if(!C)continue;let D=v.type??"completed";C.push({date:M,entry_id:_,task_id:f.id,task_name:f.name,object_name:h,status:Tt[D]??"ok",days_until_due:null,projected:!1,schedule_type:f.schedule_type,interval_days:f.interval_days??null,responsible_user_id:f.responsible_user_id??null,avg_cost:typeof v.cost=="number"?v.cost:null,adaptive_enabled:!!f.adaptive_config?.enabled,prediction_confidence:null,history_timestamp:v.timestamp,history_type:D,history_cost:typeof v.cost=="number"?v.cost:null,history_notes:typeof v.notes=="string"?v.notes:null,history_duration:typeof v.duration=="number"?v.duration:null})}}}let p={completed:0,reset:1,skipped:2,triggered:3,trigger_replaced:4};for(let[,u]of c)u.sort((h,_)=>{let g=p[h.history_type??""]??99,f=p[_.history_type??""]??99;if(g!==f)return g-f;let x=h.object_name.localeCompare(_.object_name);return x!==0?x:h.task_name.localeCompare(_.task_name)});return i.map(u=>({date:u,events:c.get(u)??[]}))}function It(e,s){if(s<=0)return 0;let t=typeof e=="number"&&Number.isFinite(e)?Math.trunc(e):0;return t<0?0:t%s}function Ct(e){return!!(e?.phases&&e.phase_sequence&&e.phase_sequence.length>0)}function K(e){if(!e||!Ct(e))return null;let s=e.phase_sequence,t=It(e.phase_cursor,s.length),n=s[t],i=e.phases?.[n];return i?{id:n,name:i.name,index:t,count:s.length,notes:i.notes,checklist:i.checklist!==void 0?i.che Line truncated
<div class="weibull-section">
<div class="weibull-title">
<ha-svg-icon aria-hidden="true" path="M3,14L3.5,14.07L8.07,9.5C7.89,8.85 8.06,8.11 8.59,7.59C9.37,6.8 10.63,6.8 11.41,7.59C11.94,8.11 12.11,8.85 11.93,9.5L14.5,12.07L15,12C15.18,12 15.35,12 15.5,12.07L19.07,8.5C19,8.35 19,8.18 19,8A2,2 0 0,1 21,6A2,2 0 0,1 23,8A2,2 0 0,1 21,10C20.82,10 20.65,10 20.5,9.93L16.93,13.5C17,13.65 17,13.82 17,14A2,2 0 0,1 15,16A2,2 0 0,1 13,14L13.07,13.5L10.5,10.93C10.18,11 9.82,11 9.5,10.93L4.93,15.5L5,16A2,2 0 0,1 3,18A2,2 0 0,1 1,16A2,2 0 0,1 3,14Z"></ha-svg-icon>
${a("weibull_reliability_curve",s)}
${Et(n,s)}
</div>
${St(n,i,r,l,s)}
${Ht(t,s)}
${t?.confidence_interval_low!=null?jt(t,e,s):d}
</div>
`}function Et(e,s){let t,n,i;return e<.8?(t="early_failures",n="M13,14H11V10H13M13,18H11V16H13M1,21H23L12,2L1,21Z",i="beta_early_failures"):e<=1.2?(t="random_failures",n="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M13,17H11V15H13V17M13,13H11V7H13V13Z",i="beta_random_failures"):e<=3.5?(t="wear_out",n="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4M12,6A6,6 0 0,1 18,12H12V6Z",i="beta_wear_out"):(t="highly_predictable",n="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.59,8.09L11,13.67L7.91,10.59L6.5,12L11,16.5Z",i="beta_highly_predictable"),o`
<span class="beta-badge ${t}">
<ha-svg-icon path="${n}"></ha-svg-icon>
${a(i,s)} (\u03B2=${e.toFixed(2)})
</span>
`}function St(e,s,t,n,i){let f=Math.max(t,n,s,1)*1.3,x=50,v=[];for(let k=0;k<=x;k++){let w=k/x*f,kt=1-Math.exp(-Math.pow(w/s,e)),$t=32+w/f*260,wt=136-kt*128;v.push([$t,wt])}let M=v.map(([k,w])=>`${k.toFixed(1)},${w.toFixed(1)}`).join(" "),C="M32,136 "+v.map(([k,w])=>`L${k.toFixed(1)},${w.toFixed(1)}`).join(" ")+` L${v[x][0].toFixed(1)},136 Z`,D=32+t/f*260,z=1-Math.exp(-Math.pow(t/s,e)),q=136-z*128,bt=((1-z)*100).toFixed(0),G=32+n/f*260,xt=[0,.25,.5,.75,1];return o`
<div class="weibull-chart">
<svg viewBox="0 0 ${300} ${160}" preserveAspectRatio="xMidYMid meet" role="img" aria-label="${a("chart_weibull",i)}">
${xt.map(k=>{let w=136-k*128;return S`
<line x1="${32}" y1="${w.toFixed(1)}" x2="${292}" y2="${w.toFixed(1)}"
stroke="var(--divider-color)" stroke-width="0.5" stroke-dasharray="${k===.5?"4,3":d}" />
<text x="${28}" y="${(w+3).toFixed(1)}" fill="var(--secondary-text-color)"
font-size="8" text-anchor="end">${(k*100).toFixed(0)}%</text>
`})}
<text x="${32}" y="${156}" fill="var(--secondary-text-color)" font-size="8" text-anchor="middle">0</text>
<text x="${324/2}" y="${156}" fill="var(--secondary-text-color)" font-size="8" text-anchor="middle">${Math.round(f/2)}</text>
<text x="${292}" y="${156}" fill="var(--secondary-text-color)" font-size="8" text-anchor="middle">${Math.round(f)}</text>
<path d="${C}" fill="var(--primary-color, #03a9f4)" opacity="0.08" />
<polyline points="${M}" fill="none"
stroke="var(--primary-color, #03a9f4)" stroke-width="2" />
${t>0?S`
<line x1="${D.toFixed(1)}" y1="${8}" x2="${D.toFixed(1)}" y2="${136 .toFixed(1)}"
stroke="var(--primary-color, #03a9f4)" stroke-width="1.5" stroke-dasharray="4,3" />
<circle cx="${D.toFixed(1)}" cy="${q.toFixed(1)}" r="3"
fill="var(--primary-color, #03a9f4)" />
<text x="${(D+4).toFixed(1)}" y="${(q-6).toFixed(1)}" fill="var(--primary-color, #03a9f4)"
font-size="9" font-weight="600">R=${bt}%</text>
`:d}
${n>0&&n!==t?S`
<line x1="${G.toFixed(1)}" y1="${8}" x2="${G.toFixed(1)}" y2="${136 .toFixed(1)}"
stroke="var(--success-color, #4caf50)" stroke-width="1.5" stroke-dasharray="4,3" />
`:d}
<line x1="${32}" y1="${8}" x2="${32}" y2="${136}"
stroke="var(--secondary-text-color)" stroke-width="1" />
<line x1="${32}" y1="${136}" x2="${292}" y2="${136}"
stroke="var(--secondary-text-color)" stroke-width="1" />
</svg>
</div>
<div class="chart-legend">
<span class="legend-item"><span class="legend-swatch" style="background:var(--primary-color, #03a9f4)"></span> ${a("weibull_failure_probability",i)}</span>
${t>0?o`<span class="legend-item"><span class="legend-swatch" style="background:var(--primary-color, #03a9f4); opacity:0.5"></span> ${a("current_interval_marker",i)}</span>`:d}
${n>0&&n!==t?o`<span class="legend-item"><span class="legend-swatch" style="background:var(--success-color, #4caf50)"></span> ${a("recommended_marker",i)}</span>`:d}
</div>
`}function Ht(e,s){return o`
<div class="weibull-info-row">
<div class="weibull-info-item">
<span>${a("characteristic_life",s)}</span>
<span class="weibull-info-value">${Math.round(e.weibull_eta)} ${a("days",s)}</span>
</div>
${e.weibull_r_squared!=null?o`
<div class="weibull-info-item">
<span>${a("weibull_r_squared",s)}</span>
<span class="weibull-info-value">${e.weibull_r_squared.toFixed(3)}</span>
</div>
`:d}
</div>
`}function jt(e,s,t){let n=e.confidence_interval_low,i=e.confidence_interval_high,r=s.suggested_interval??s.interval_days??0,l=s.interval_days??0,c=Math.max(0,n-5),u=i+5-c,h=(n-c)/u*100,_=(i-n)/u*100,g=(r-c)/u*100,f=l>0?(l-c)/u*100:-1;return o`
<div class="confidence-range">
<div class="confidence-range-title">
${a("confidence_interval",t)}: ${r} ${a("days",t)} (${n}\u2013${i})
</div>
<div class="confidence-bar">
<div class="confidence-fill" style="left:${h.toFixed(1)}%;width:${_.toFixed(1)}%"></div>
${f>=0?o`<div class="confidence-marker current" style="left:${f.toFixed(1)}%"></div>`:d}
<div class="confidence-marker recommended" style="left:${g.toFixed(1)}%"></div>
</div>
<div class="confidence-labels">
<span class="confidence-text low">${a("confidence_conservative",t)} (${n}${a("days",t).charAt(0)})</span>
<span class="confidence-text high">${a("confidence_aggressive",t)} (${i}${a("days",t).charAt(0)})</span>
</div>
</div>
`}function ct(e,s,t){let n=e.degradation_trend!=null&&e.degradation_trend!=="insufficient_data",i=e.days_until_threshold!=null,r=e.environmental_factor!=null&&e.environmental_factor!==1;if(!n&&!i&&!r)return d;let l=e.degradation_trend==="rising"?"M16,6L18.29,8.29L13.41,13.17L9.41,9.17L2,16.59L3.41,18L9.41,12L13.41,16L19.71,9.71L22,12V6H16Z":e.degradation_trend==="falling"?"M16,18L18.29,15.71L13.41,10.83L9.41,14.83L2,7.41L3.41,6L9.41,12L13.41,8L19.71,14.29L22,12V18H16Z":"M22,12L18,8V11H3V13H18V16L22,12Z";return o`
<div class="prediction-section">
${e.sensor_prediction_urgency?o`
<div class="prediction-urgency-banner">
<ha-svg-icon path="M1,21H23L12,2L1,21M12,18A1,1 0 0,1 11,17A1,1 0 0,1 12,16A1,1 0 0,1 13,17A1,1 0 0,1 12,18M13,15H11V10H13V15Z"></ha-svg-icon>
${a("sensor_prediction_urgency",s).replace("{days}",String(Math.round(e.days_until_threshold||0)))}
</div>
`:d}
<div class="prediction-title">
<ha-svg-icon path="M2,2V4H7V2H2M22,2V4H13V2H22M7,7V9H2V7H7M22,7V9H13V7H22M7,12V14H2V12H7M22,12V14H13V12H22M7,17V19H2V17H7M22,17V19H13V17H22M9,2V19L12,22L15,19V2H9M11,4H13V17.17L12,18.17L11,17.17V4Z"></ha-svg-icon>
${a("sensor_prediction",s)}
</div>
<div class="prediction-grid">
${n?o`
<div class="prediction-item">
<ha-svg-icon path="${l}"></ha-svg-icon>
<span class="prediction-label">${a("degradation_trend",s)}</span>
<span class="prediction-value ${e.degradation_trend}">${a("trend_"+e.degradation_trend,s)}</span>
${e.degradation_rate!=null?o`<span class="prediction-rate">${e.degradation_rate>0?"+":""}${Math.abs(e.degradation_rate)>=10?Math.round(e.degradation_rate).toLocaleString():e.degradation_rate.toFixed(1)} ${e.trigger_entity_info?.unit_of_measurement||""}/${a("day_short",s)}</span>`:d}
</div>
`:d}
${i?o`
<div class="prediction-item">
<ha-svg-icon path="M12,20A7,7 0 0,1 5,13A7,7 0 0,1 12,6A7,7 0 0,1 19,13A7,7 0 0,1 12,20M12,4A9,9 0 0,0 3,13A9,9 0 0,0 12,22A9,9 0 0,0 21,13A9,9 0 0,0 12,4M12.5,8H11V14L15.75,16.85L16.5,15.62L12.5,13.25V8M7.88,3.39L6.6,1.86L2,5.71L3.29,7.24L7.88,3.39M22,5.72L17.4,1.86L16.11,3.39L20.71,7.25L22,5.72Z"></ha-svg-icon>
<span class="prediction-label">${a("days_until_threshold",s)}</span>
<span class="prediction-value prediction-days${e.days_until_threshold===0?" exceeded":e.sensor_prediction_urgency?" urgent":""}">${e.days_until_threshold===0?a("threshold_exceeded",s):"~"+Math.round(e.days_until_threshold)+" "+a("days",s)}</span>
${e.threshold_prediction_date?o`<span class="prediction-date">${O(e.threshold_prediction_date,s)}</span>`:d}
${e.threshold_prediction_confidence?o`<span class="confidence-dot ${e.threshold_prediction_confidence}"></span>`:d}
${(e.prediction_cycles??0)>0?o`<span class="prediction-cycles">${a("prediction_cycles",s)}: ${e.prediction_cycles}</span>`:d}
</div>
`:d}
${r&&t.environmental?o`
<div class="prediction-item">
<ha-svg-icon path="M15,13V5A3,3 0 0,0 12,2A3,3 0 0,0 9,5V13A5,5 0 0,0 7,17A5,5 0 0,0 12,22A5,5 0 0,0 17,17A5,5 0 0,0 15,13M12,4A1,1 0 0,1 13,5V8H11V5A1,1 0 0,1 12,4Z"></ha-svg-icon>
<span class="prediction-label">${a("environmental_adjustment",s)}</span>
<span class="prediction-value">${e.environmental_factor.toFixed(2)}x</span>
${e.environmental_entity?o`<span class="prediction-entity entity-link" @click=${c=>tt(c,e.environmental_entity)}>${e.environmental_entity}</span>`:d}
</div>
`:d}
</div>
</div>
`}function dt(e,s,t,n){let i=Math.max(e||1,s);return o`
<div class="interval-comparison">
<div class="interval-bar">
<div class="interval-label">
${a("current",n)}: ${e??"\u2014"} ${e!=null?a("days",n):""}
</div>
<div class="interval-visual current"
style="width: ${e!=null?Math.min(e/i*100,100):0}%"></div>
</div>
<div class="interval-bar">
<div class="interval-label">
${a("recommended",n)}: ${s} ${a("days",n)}
<span class="confidence-badge ${t}">${a(`confidence_${t}`,n)}</span>
</div>
<div class="interval-visual suggested"
style="width: ${Math.min(s/i*100,100)}%"></div>
</div>
</div>
`}var pt=["month_jan","month_feb","month_mar","month_apr","month_may","month_jun","month_jul","month_aug","month_sep","month_oct","month_nov","month_dec"];function ut(e,s,t){if(!t.seasonal||!e.seasonal_factor||e.seasonal_factor===1)return d;let n=pt.map(c=>a(c,s)),i=new Date().getMonth(),r=e.seasonal_factors||e.interval_analysis?.seasonal_factors||null,l=r&&r.length===12?r:n.map((c,p)=>{let u=e.seasonal_factor||1,h=Math.sin((p-6)*Math.PI/6)*.3;return Math.max(.7,Math.min(1.3,u+h))});return o`
<div class="seasonal-card-compact">
<h4>${a("seasonal_awareness",s)}</h4>
<div class="seasonal-mini-chart">
${l.map((c,p)=>{let u=c*40,h=c<.9?"low":c>1.1?"high":"normal";return o`
<div class="seasonal-bar ${h} ${p===i?"current":""}"
style="height: ${u}px"
title="${n[p]}: ${c.toFixed(2)}x">
</div>
`})}
</div>
<div class="seasonal-legend">
<span class="legend-item"><span class="dot low"></span> ${a("shorter",s)||"K\xFCrzer"}</span>
<span class="legend-item"><span class="dot normal"></span> ${a("normal",s)||"Normal"}</span>
<span class="legend-item"><span class="dot high"></span> ${a("longer",s)||"L\xE4nger"}</span>
</div>
</div>
`}function ht(e,s){return Ot(e,s)}function Ot(e,s){let t=e.seasonal_factors??e.interval_analysis?.seasonal_factors;if(!t||t.length!==12)return d;let n=e.interval_analysis?.seasonal_reason,i=new Date().getMonth(),r=300,l=100,c=8,u=l-c-4,h=Math.max(...t,1.5),_=r/12,g=_*.65,f=c+u-1/h*u;return o`
<div class="seasonal-chart">
<div class="seasonal-chart-title">
<ha-svg-icon aria-hidden="true" path="M17.75 4.09L15.22 6.03L16.13 9.09L13.5 7.28L10.87 9.09L11.78 6.03L9.25 4.09L12.44 4L13.5 1L14.56 4L17.75 4.09M21.25 11L19.61 12.25L20.2 14.23L18.5 13.06L16.8 14.23L17.39 12.25L15.75 11L17.81 10.95L18.5 9L19.19 10.95L21.25 11M18.97 15.95C19.8 15.87 20.69 17.05 20.16 17.8C19.84 18.25 19.5 18.67 19.08 19.07C15.17 23 8.84 23 4.94 19.07C1.03 15.17 1.03 8.83 4.94 4.93C5.34 4.53 5.76 4.17 6.21 3.85C6.96 3.32 8.14 4.21 8.06 5.04C7.79 7.9 8.75 10.87 10.95 13.06C13.14 15.26 16.1 16.22 18.97 15.95Z"></ha-svg-icon>
${a("seasonal_chart_title",s)}
${n?o`<span class="source-tag">${n==="learned"?a("seasonal_learned",s):a("seasonal_manual",s)}</span>`:d}
</div>
<svg viewBox="0 0 ${r} ${l}" preserveAspectRatio="xMidYMid meet" role="img" aria-label="${a("chart_seasonal",s)}">
<line x1="0" y1="${f.toFixed(1)}" x2="${r}" y2="${f.toFixed(1)}"
stroke="var(--divider-color)" stroke-width="1" stroke-dasharray="4,3" />
${t.map((x,v)=>{let M=x/h*u,C=v*_+(_-g)/2,D=c+u-M,z=v===i,q=x<1?"var(--success-color, #4caf50)":x>1?"var(--warning-color, #ff9800)":"var(--secondary-text-color)";return S`
<rect x="${C.toFixed(1)}" y="${D.toFixed(1)}"
width="${g.toFixed(1)}" height="${M.toFixed(1)}"
fill="${q}" opacity="${z?1:.5}" rx="2" />
`})}
</svg>
<div class="seasonal-labels">
${pt.map((x,v)=>o`<span class="seasonal-label ${v===i?"active-month":""}">${a(x,s)}</span>`)}
</div>
</div>
`}var b=class extends H{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._taskId=null;this._task=null;this._objectName="";this._busy=!1;this._error="";this._showSkip=!1;this._showReset=!1;this._showDetails=!1;this._showAdaptive=!1;this._skipReason="";this._resetDate="";this._features={adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1};this._toast="";this._featuresLoaded=!1;this._currencySymbol=""}get _lang(){return I(this.hass)}async openFor(t,n){this._entryId=t,this._taskId=n,this._error="",this._showSkip=!1,this._showReset=!1,this._showAdaptive=!1,this._skipReason="",this._resetDate=R(new Date),this._open=!0,await Promise.all([this._loadTask(),this._loadFeatures()])}async _loadFeatures(){if(!this._featuresLoaded)try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/settings"});t?.features&&(this._features={...this._features,...t.features}),this._currencySymbol=t?.budget?.currency_symbol||"",this._featuresLoaded=!0}catch{}}close(){this._open=!1,this._task=null,this._error=""}async _loadTask(){if(!(!this._entryId||!this._taskId))try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._objectName=t.object?.name||"";let n=(t.tasks||[]).find(i=>i.id===this._taskId);this._task=n??null}catch(t){this._error=A(t,this._lang)}}async _runWs(t){this._busy=!0,this._error="";try{return await this.hass.connection.sendMessagePromise(t),this._busy=!1,!0}catch(n){return this._error=A(n,this._lang),this._busy=!1,!1}}_notifyChanged(t){this.dispatchEvent(new CustomEvent("task-action-fired",{detail:{entry_id:this._entryId,task_id:this._taskId,action:t},bubbles:!0,composed:!0}))}_onComplete(){!this._entryId||!this._taskId||!this._task||import("/maintenance_supporter_panelfiles/panel-chunks/dialog-mount-2CKELVLB.js").then(async({openCompleteDialog:t})=>{let n=this._task,i=[];try{i=(await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/objects",compact:!0})).objects||[]}catch{}t(rt({entryId:this._entryId,taskId:this._taskId,taskName:n.name,task:n,objects:i,lang:this._lang,checklist:n.checklist||[],adaptiveEnabled:!!n.adaptive_config?.enabled,currencySymbol:this._currencySymbol}))&&(this._notifyChanged("complete"),this.close())})}async _onSkipConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/skip",entry_id:this._entryId,task_id:this._taskId,reason:this._skipReason.trim()||null})&&(this._notifyChanged("skip"),this.close())}async _onResetConfirm(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/reset",entry_id:this._entryId,task_id:this._taskId,date:this._resetDate||void 0})&&(this._notifyChanged("reset"),this.close())}_onEdit(){!this._entryId||!this._taskId||import("/maintenance_supporter_panelfiles/panel-chunks/dialog-mount-2CKELVLB.js").then(({openEditTaskDialog:t})=>{t(this._entryId,this._taskId),this.close()})}_onQr(){!this._entryId||!this._taskId||!this._task||import("/maintenance_supporter_panelfiles/panel-chunks/dialog-mount-2CKELVLB.js").then(({openQrDialog:t})=>{t({entry_id:this._entryId,task_id:this._taskId,task_name:this._task.name,object_name:this._objectName}),this.close()})}async _onDelete(){if(!this._entryId||!this._taskId)return;let t=a("delete_task_confirm",this._lang)||`Delete "${this._task?.name}"?`;if(!window.confirm(t))return;await this._runWs({type:"maintenance_supporter/task/delete",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("delete"),this.close())}async _onArchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/archive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("archive"),this.close())}async _onUnarchive(){if(!this._entryId||!this._taskId)return;await this._runWs({type:"maintenance_supporter/task/unarchive",entry_id:this._entryId,task_id:this._taskId})&&(this._notifyChanged("unarchive"),this.close())}_onOpenInPanel(){if(!this._entryId||!this._taskId)return;let t=`/maintenance-supporter?entry_id=${encodeURIComponent(this._entryId)}&task_id=${encodeURIComponent(this._taskId)}`;history.pushState(null,"",t),window.dispatchEvent(new CustomEvent("location-changed")),this.close()}async _applySuggestion(){if(!this._entryId||!this._taskId||!this._task?.suggested_interval)return;await this._runWs({type:"maintenance_supporter/task/apply_suggestion",entry_id:this._entryId,task_id:this._taskId,interval:this._task.suggested_interval})&&(this._toast=a("suggestion_applied",this._lang)||"Applied",this._notifyChanged("apply_suggestion"),await this._loadTask(),setTimeout(()=>{this._toast=""},2500))}async _reanalyzeInterval(){if(!(!this._entryId||!this._taskId)){this._busy=!0,this._error="";try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/task/analyze_interval",entry_id:this._entryId, Line truncated
<div class="recommendation-card">
<h4>${a("suggested_interval",n)}</h4>
${dt(t.interval_days,t.suggested_interval,t.interval_confidence||"medium",n)}
<div class="recommendation-actions">
<button class="btn primary"
@click=${this._applySuggestion} ?disabled=${this._busy}>
<ha-icon icon="mdi:check"></ha-icon>
${a("apply_suggestion",n)}
</button>
<button class="btn"
@click=${this._reanalyzeInterval} ?disabled=${this._busy}>
<ha-icon icon="mdi:refresh"></ha-icon>
${a("reanalyze",n)}
</button>
</div>
</div>
`}_renderAdaptive(t){let n=this._lang,i=this._features.adaptive&&t.suggested_interval&&t.suggested_interval!==t.interval_days,r=t.degradation_trend!=null&&t.degradation_trend!=="insufficient_data"||t.days_until_threshold!=null||t.environmental_factor!=null&&t.environmental_factor!==1,l=this._features.adaptive&&t.interval_analysis?.weibull_beta!=null&&t.interval_analysis?.weibull_eta!=null,c=this._features.seasonal&&t.seasonal_factor&&t.seasonal_factor!==1;return!i&&!r&&!l&&!c?o`<div class="adaptive-empty">
${a("adaptive_no_data",n)||"Not enough completion history yet for adaptive analysis."}
</div>`:o`
<div class="adaptive-stack">
${this._toast?o`<div class="toast">${this._toast}</div>`:d}
${i?this._renderRecommendation(t):d}
${r?ct(t,n,this._features):d}
${l?lt(t,n):d}
${c?o`
${ut(t,n,this._features)}
${t.seasonal_factors?.length===12||t.interval_analysis?.seasonal_factors?.length===12?ht(t,n):d}
`:d}
</div>
`}_renderDetails(t){let n=this._lang,i=t.history||[],r=i.filter(p=>p.type==="completed"),l=r.reduce((p,u)=>p+(typeof u.cost=="number"?u.cost:0),0),c=(()=>{let p=r.map(u=>typeof u.duration=="number"?u.duration:null).filter(u=>u!=null);return p.length?Math.round(p.reduce((u,h)=>u+h,0)/p.length):null})();return o`
<div class="details">
<div class="stats-grid">
<div class="stat">
<span class="stat-label">${a("times_performed",n)||"Performed"}</span>
<span class="stat-value">${r.length}</span>
</div>
<div class="stat">
<span class="stat-label">${a("total_cost",n)||"Total cost"}</span>
<span class="stat-value">${l.toFixed(2)}</span>
</div>
<div class="stat">
<span class="stat-label">${a("avg_duration",n)||"Avg duration"}</span>
<span class="stat-value">${c!=null?`${c}m`:"\u2014"}</span>
</div>
</div>
<div class="history-header">
<strong>${a("history",n)||"History"}</strong>
<span class="history-count">${i.length}</span>
</div>
${i.length===0?o`<div class="history-empty">${a("history_empty",n)||"No history yet."}</div>`:o`
<div class="history-list">
${[...i].reverse().slice(0,20).map(p=>{let u=["completed","reset","skipped"].includes(p.type);return o`
<div class="history-entry">
<div class="history-line">
<span class="history-type type-${p.type}">${a(p.type,n)}</span>
<span class="history-date">${Q(p.timestamp,n)}</span>
${u?o`<button class="history-edit"
title="${a("history_edit_button",n)||"Edit"}"
@click=${()=>this._onEditHistoryEntry(p)}>
<ha-icon icon="mdi:pencil"></ha-icon>
</button>`:d}
</div>
${p.notes?o`<div class="history-notes">${p.notes}</div>`:d}
${p.cost!=null||p.duration!=null?o`<div class="history-meta">
${p.cost!=null?o`<span>💰 ${p.cost.toFixed(2)}</span>`:d}
${p.duration!=null?o`<span>⏱️ ${p.duration}m</span>`:d}
</div>`:d}
</div>
`})}
${i.length>20?o`<div class="history-more">… +${i.length-20} ${a("older_entries",n)||"older"}</div>`:d}
</div>
`}
</div>
`}render(){if(!this._open)return d;let t=this._lang,n=this._task,i=this.hass?.user?.is_admin??!0;return o`
<div class="backdrop" @click=${this.close}></div>
<div class="dialog" role="dialog" aria-modal="true">
${n?o`
<div class="header">
<div class="title">
<span class="status-dot" style="background: ${N[n.status]||"#ccc"}"></span>
<span class="task-name">${n.name}</span>
</div>
<div class="object">
<button class="link-inline" @click=${()=>{this._entryId&&import("/maintenance_supporter_panelfiles/panel-chunks/dialog-mount-2CKELVLB.js").then(({openObjectQuickActions:r})=>{r(this._entryId),this.close()})}}>${this._objectName}</button>
</div>
<div class="quick-info">
${n.next_due?o`<span><strong>${a("next_due",t)||"Next due"}:</strong> ${O(n.next_due,t)}</span>`:d}
${n.last_performed?o`<span><strong>${a("last_performed",t)||"Last"}:</strong> ${O(n.last_performed,t)}</span>`:d}
${n.schedule?.kind&&!["manual","one_time"].includes(n.schedule.kind)||n.interval_days!=null?o`<span><strong>${a("interval",t)||"Interval"}:</strong> ${X(n,t)}</span>`:d}
${F(n)?o`<span><strong>${a("phase_current",t)}:</strong> ${F(n)}</span>`:d}
</div>
</div>
${this._error?o`<div class="error">${this._error}</div>`:d}
${this._showSkip?o`
<div class="inline-form">
<label>${a("skip_reason",t)||"Skip reason (optional)"}</label>
<input type="text" .value=${this._skipReason}
@input=${r=>{this._skipReason=r.target.value}} />
<div class="inline-actions">
<button class="btn cancel" @click=${()=>{this._showSkip=!1}} ?disabled=${this._busy}>
${a("cancel",t)||"Cancel"}
</button>
<button class="btn primary" @click=${this._onSkipConfirm} ?disabled=${this._busy}>
${a("skip",t)||"Skip"}
</button>
</div>
</div>
`:this._showReset?o`
<div class="inline-form">
<label>${a("reset_to_date",t)||"Reset last_performed to"}</label>
<input type="date" .value=${this._resetDate}
@input=${r=>{this._resetDate=r.target.value}} />
<div class="inline-actions">
<button class="btn cancel" @click=${()=>{this._showReset=!1}} ?disabled=${this._busy}>
${a("cancel",t)||"Cancel"}
</button>
<button class="btn primary" @click=${this._onResetConfirm} ?disabled=${this._busy}>
${a("reset",t)||"Reset"}
</button>
</div>
</div>
`:o`
<div class="actions primary-row">
<button class="btn primary" @click=${this._onComplete} ?disabled=${this._busy}>
<ha-icon icon="mdi:check"></ha-icon>
${a("complete",t)||"Complete"}
</button>
<button class="btn" @click=${()=>{this._showSkip=!0}} ?disabled=${this._busy}>
<ha-icon icon="mdi:skip-next"></ha-icon>
${a("skip",t)||"Skip"}
</button>
<button class="btn" @click=${()=>{this._showReset=!0}} ?disabled=${this._busy}>
<ha-icon icon="mdi:restart"></ha-icon>
${a("reset",t)||"Reset"}
</button>
</div>
${i?o`
<div class="actions secondary-row">
<button class="btn ghost" @click=${this._onEdit} ?disabled=${this._busy}>
<ha-icon icon="mdi:pencil"></ha-icon>
${a("edit",t)||"Edit"}
</button>
<button class="btn ghost" @click=${this._onQr} ?disabled=${this._busy}>
<ha-icon icon="mdi:qrcode"></ha-icon>
${a("qr_code",t)||"QR"}
</button>
<button class="btn ghost"
@click=${n.archived?this._onUnarchive:this._onArchive}
?disabled=${this._busy}>
<ha-icon icon="${n.archived?"mdi:archive-arrow-up-outline":"mdi:archive-outline"}"></ha-icon>
${n.archived?a("unarchive",t)||"Unarchive":a("archive",t)||"Archive"}
</button>
<button class="btn ghost danger" @click=${this._onDelete} ?disabled=${this._busy}>
<ha-icon icon="mdi:delete"></ha-icon>
${a("delete",t)||"Delete"}
</button>
</div>
`:d}
<div class="details-toggle">
<button class="link" @click=${()=>{this._showDetails=!this._showDetails}}>
<ha-icon icon="${this._showDetails?"mdi:chevron-up":"mdi:chevron-down"}"></ha-icon>
${this._showDetails?a("hide_details",t)||"Hide details":a("show_details",t)||"Show history + stats"}
</button>
${this._features.adaptive||this._features.seasonal||this._features.environmental?o`<button class="link" @click=${()=>{this._showAdaptive=!this._showAdaptive}}>
<ha-icon icon="${this._showAdaptive?"mdi:chart-line":"mdi:chart-line-variant"}"></ha-icon>
${this._showAdaptive?a("hide_stats",t)||"Hide stats":a("show_stats",t)||"Show stats + graphs"}
</button>`:d}
</div>
${this._showDetails?this._renderDetails(n):d}
${this._showAdaptive?this._renderAdaptive(n):d}
<div class="footer">
<button class="link" @click=${this._onOpenInPanel}>
<ha-icon icon="mdi:open-in-new"></ha-icon>
${a("open_in_panel",t)||"Open in Maintenance panel"}
</button>
</div>
`}
`:o`<div class="loading">${a("loading",t)||"Loading\u2026"}</div>`}
</div>
`}};b.styles=[et,E`
:host { display: contents; }
.backdrop {
position: fixed; inset: 0; z-index: 100;
background: rgba(0,0,0,0.5);
}
.dialog {
position: fixed; left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 95vw; max-width: 460px;
max-height: 92vh; overflow: auto;
background: var(--card-background-color, var(--ha-card-background, #1c1c1c));
color: var(--primary-text-color);
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.4);
padding: 20px;
display: flex; flex-direction: column; gap: 14px;
z-index: 101;
}
.header { display: flex; flex-direction: column; gap: 6px; }
.title { display: flex; align-items: center; gap: 10px; }
.status-dot { width: 12px; height: 12px; border-radius: 50%; flex-shrink: 0; }
.task-name { font-size: 18px; font-weight: 600; }
.object { font-size: 13px; color: var(--secondary-text-color); }
.link-inline {
background: transparent; border: none; padding: 0; cursor: pointer;
color: var(--primary-color); font-size: inherit; font-family: inherit;
}
.link-inline:hover { text-decoration: underline; }
.quick-info {
display: flex; flex-wrap: wrap; gap: 12px;
font-size: 12px; color: var(--secondary-text-color);
padding-top: 4px; border-top: 1px solid var(--divider-color);
}
.quick-info strong { color: var(--primary-text-color); font-weight: 500; }
.actions { display: flex; gap: 8px; }
.actions.primary-row { gap: 6px; }
.actions.primary-row .btn { flex: 1; }
/* Edit + QR are admin-tools — left-align as a group; Delete is destructive
so it gets pushed to the far right with margin-left:auto for visual
separation. Earlier this row was flex-end which left a strange empty
gap on the left (user feedback). */
.actions.secondary-row {
padding-top: 8px; border-top: 1px solid var(--divider-color);
justify-content: flex-start;
}
.actions.secondary-row .btn.danger {
margin-left: auto;
}
.btn {
padding: 8px 12px; font-size: 14px;
border-radius: 6px; cursor: pointer;
border: 1px solid var(--divider-color);
background: var(--secondary-background-color, transparent);
color: var(--primary-text-color);
font-weight: 500;
display: inline-flex; align-items: center; gap: 6px;
transition: background 0.12s;
}
.btn:hover { background: var(--state-icon-color, rgba(255,255,255,0.06)); }
.btn[disabled] { opacity: 0.5; cursor: wait; }
.btn.primary {
background: var(--primary-color);
color: var(--text-primary-color, white);
border-color: var(--primary-color);
}
.btn.cancel { background: transparent; }
.btn.ghost { padding: 6px 10px; font-size: 13px; }
.btn.danger { color: var(--error-color); }
.btn ha-icon { --mdc-icon-size: 18px; }
.inline-form { display: flex; flex-direction: column; gap: 8px; }
.inline-form label { font-size: 13px; color: var(--secondary-text-color); }
.inline-form input {
padding: 8px; font-size: 14px;
background: var(--secondary-background-color, #2c2c2c);
color: var(--primary-text-color);
border: 1px solid var(--divider-color, #444);
border-radius: 6px;
}
.inline-actions { display: flex; gap: 8px; justify-content: flex-end; }
.footer { display: flex; justify-content: center; padding-top: 4px; }
.link {
background: transparent; border: none; cursor: pointer;
color: var(--primary-color); font-size: 13px;
display: inline-flex; align-items: center; gap: 4px;
}
.link:hover { text-decoration: underline; }
.link ha-icon { --mdc-icon-size: 14px; }
.loading { padding: 24px; text-align: center; color: var(--secondary-text-color); }
.error {
padding: 8px; border-radius: 6px;
background: rgba(211,47,47,0.1);
color: var(--error-color, #d32f2f); font-size: 13px;
}
/* Details (expandable Show details section) */
.details-toggle { display: flex; justify-content: center; margin-top: 4px; }
.details {
display: flex; flex-direction: column; gap: 12px;
border-top: 1px solid var(--divider-color);
padding-top: 12px;
}
.stats-grid {
display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px;
}
.stat {
display: flex; flex-direction: column; gap: 2px;
background: var(--secondary-background-color, rgba(255,255,255,0.04));
padding: 8px; border-radius: 6px;
align-items: center;
}
.stat-label { font-size: 11px; color: var(--secondary-text-color); text-transform: uppercase; letter-spacing: 0.5px; }
.stat-value { font-size: 16px; font-weight: 600; }
.history-header {
display: flex; align-items: baseline; gap: 8px;
font-size: 14px;
}
.history-count {
font-size: 12px; color: var(--secondary-text-color);
background: var(--secondary-background-color); padding: 2px 8px; border-radius: 999px;
}
.history-empty { color: var(--secondary-text-color); font-style: italic; font-size: 13px; }
.history-list { display: flex; flex-direction: column; gap: 8px; max-height: 280px; overflow: auto; }
.history-entry {
padding: 6px 8px; border-radius: 6px;
background: var(--secondary-background-color, rgba(255,255,255,0.03));
font-size: 13px;
}
.history-line {
display: flex; align-items: center; gap: 8px;
justify-content: space-between;
}
.history-type {
font-weight: 600; font-size: 11px;
padding: 2px 6px; border-radius: 4px;
text-transform: uppercase; letter-spacing: 0.5px;
}
.type-completed { background: rgba(46,125,50,0.2); color: #66bb6a; }
.type-skipped { background: rgba(158,158,158,0.2); color: var(--secondary-text-color); }
.type-reset { background: rgba(33,150,243,0.2); color: #64b5f6; }
.type-triggered { background: rgba(255,87,34,0.2); color: #ff8a65; }
.history-date { font-size: 11px; color: var(--secondary-text-color); flex: 1; text-align: right; }
.history-edit {
background: transparent; border: none; cursor: pointer;
padding: 4px; border-radius: 4px;
color: var(--secondary-text-color);
}
.history-edit:hover { background: var(--state-icon-color, rgba(255,255,255,0.06)); color: var(--primary-color); }
.history-edit ha-icon { --mdc-icon-size: 14px; }
.history-notes { margin-top: 4px; color: var(--primary-text-color); }
.history-meta { display: flex; gap: 12px; margin-top: 4px; color: var(--secondary-text-color); font-size: 11px; }
.history-more { padding: 8px; text-align: center; font-size: 12px; color: var(--secondary-text-color); font-style: italic; }
/* Adaptive section — wraps the panel renderers (which assume sharedStyles
are present) and adds dialog-specific layout. */
.adaptive-stack {
display: flex; flex-direction: column; gap: 12px;
border-top: 1px solid var(--divider-color);
padding-top: 12px;
}
.adaptive-empty {
padding: 16px; text-align: center;
color: var(--secondary-text-color);
font-style: italic; font-size: 13px;
border-top: 1px solid var(--divider-color);
}
.toast {
padding: 8px 12px; border-radius: 6px;
background: rgba(76, 175, 80, 0.15);
color: #4caf50; font-size: 13px; font-weight: 500;
}
/* The panel's recommendation-card uses ha-button. We use plain <button>
in this dialog's button styles. Re-style the action row to match. */
.recommendation-actions {
display: flex; gap: 8px; margin-top: 8px;
}
/* Constrain SVG charts so they fit the dialog width even on mobile. */
.weibull-section, .seasonal-card-compact { max-width: 100%; }
.weibull-chart svg { max-width: 100%; height: auto; }
.details-toggle { gap: 12px; flex-wrap: wrap; }
`],m([j({attribute:!1})],b.prototype,"hass",2),m([y()],b.prototype,"_open",2),m([y()],b.prototype,"_entryId",2),m([y()],b.prototype,"_taskId",2),m([y()],b.prototype,"_task",2),m([y()],b.prototype,"_objectName",2),m([y()],b.prototype,"_busy",2),m([y()],b.prototype,"_error",2),m([y()],b.prototype,"_showSkip",2),m([y()],b.prototype,"_showReset",2),m([y()],b.prototype,"_showDetails",2),m([y()],b.prototype,"_showAdaptive",2),m([y()],b.prototype,"_skipReason",2),m([y()],b.prototype,"_resetDate",2),m([y()],b.prototype,"_features",2),m([y()],b.prototype,"_toast",2);customElements.get("maintenance-task-quick-actions-dialog")||customElements.define("maintenance-task-quick-actions-dialog",b);function _t(e){return!!e&&/^https?:\/\//i.test(e)}function mt(e){return e?customElements.get("ha-markdown")?o`<ha-markdown class="notes-md" .content=${e} breaks></ha-markdown>`:o`${e}`:d}var L=class extends H{constructor(){super(...arguments);this._open=!1;this._entryId=null;this._data=null;this._busy=!1;this._error=""}get _lang(){return I(this.hass)}async openFor(t){this._entryId=t,this._error="",this._open=!0,await this._load()}close(){this._open=!1,this._data=null,this._error=""}async _load(){if(this._entryId)try{let t=await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:this._entryId});this._data=t}catch(t){this._error=A(t,this._lang)}}_onEditObject(){!this._entryId||!this._data||import("/maintenance_supporter_panelfiles/panel-chunks/dialog-mount-2CKELVLB.js").then(({openEditObjectDialog:t})=>{t(this._entryId,this._data.object),this.close()})}_onAddTask(){this._entryId&&import("/maintenance_supporter_panelfiles/panel-chunks/dialog-mount-2CKELVLB.js").then(({openCreateTaskDialog:t})=>{t(this._entryId),this.close()})}async _onDelete(){if(!this._entryId||!this._data)return;let t=a("delete_object_confirm",this._lang)||`Delete "${this._data.object.name}" and all its tasks?`;if(window.confirm(t)){this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:"maintenance_supporter/object/delete",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-deleted",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(n){this._error=A(n,this._lang)}finally{this._busy=!1}}}async _onArchiveObject(){if(!this._entryId||!this._data)return;let t=!!this._data.object.archived;if(!t){let n=a("confirm_archive_object",this._lang)||"Archive this object and its tasks?";if(!window.confirm(n))return}this._busy=!0,this._error="";try{await this.hass.connection.sendMessagePromise({type:t?"maintenance_supporter/object/unarchive":"maintenance_supporter/object/archive",entry_id:this._entryId}),this.dispatchEvent(new CustomEvent("object-changed",{detail:{entry_id:this._entryId},bubbles:!0,composed:!0})),this.close()}catch(n){this._error=A(n,this._lang)}finally{this._busy=!1}}_onTaskClick(t){this._entryId&&import("/maintenance_supporter_panelfiles/panel-chunks/dialog-mount-2CKELVLB.js").then(({openTaskQuickActions:n})=>{n(this._entryId,t)})}render(){if(!this._open)return d;let t=this._lang,n=this._data,i=n?.object,r=n?.tasks||[],l=this.hass?.user?.is_admin??!0;return o`
<div class="backdrop" @click=${this.close}></div>
<div class="dialog" role="dialog" aria-modal="true">
${n&&i?o`
<div class="header">
<div class="title">${i.name}</div>
${this._renderMetaRow(i)}
</div>
${this._error?o`<div class="error">${this._error}</div>`:d}
<div class="tasks-section">
<div class="section-header">
<strong>${a("tasks",t)||"Tasks"}</strong>
<span class="count">${r.length}</span>
</div>
${r.length===0?o`<div class="empty">${a("no_tasks",t)||"No tasks yet."}</div>`:o`
<div class="task-list">
${r.map(c=>o`
<div class="task-row" @click=${()=>this._onTaskClick(c.id)}>
<span class="status-dot" style="background: ${N[c.status]||"#ccc"}"></span>
<span class="task-name">${c.name}</span>
<span class="task-status">${a(c.status||"ok",t)}</span>
</div>
`)}
</div>
`}
</div>
${i.notes?o`
<div class="notes-section">
<strong>${a("object_notes_label",t)}</strong>
<div class="notes-body">${mt(i.notes)}</div>
</div>
`:d}
${l?o`
<div class="actions">
<button class="btn primary" @click=${this._onAddTask} ?disabled=${this._busy}>
<ha-icon icon="mdi:plus"></ha-icon>
${a("add_task",t)||"Add task"}
</button>
<button class="btn" @click=${this._onEditObject} ?disabled=${this._busy}>
<ha-icon icon="mdi:pencil"></ha-icon>
${a("edit",t)||"Edit"}
</button>
<button class="btn" @click=${this._onArchiveObject} ?disabled=${this._busy}>
<ha-icon icon="${i.archived?"mdi:archive-arrow-up-outline":"mdi:archive-outline"}"></ha-icon>
${i.archived?a("unarchive_object",t)||"Unarchive object":a("archive_object",t)||"Archive object"}
</button>
<button class="btn danger" @click=${this._onDelete} ?disabled=${this._busy}>
<ha-icon icon="mdi:delete"></ha-icon>
${a("delete",t)||"Delete"}
</button>
</div>
`:d}
`:o`<div class="loading">${a("loading",t)||"Loading\u2026"}</div>`}
</div>
`}_renderMetaRow(t){let n=this._lang,i=[];return t.area_id&&i.push([a("area",n),t.area_id]),t.manufacturer&&i.push([a("manufacturer",n),t.manufacturer]),t.model&&i.push([a("model",n),t.model]),t.serial_number&&i.push([a("serial_number_label",n),t.serial_number]),t.installation_date&&i.push([a("installed",n),t.installation_date]),t.warranty_expiry&&i.push([a("warranty",n),t.warranty_expiry]),t.documentation_url&&i.push([a("documentation_url_label",n),t.documentation_url]),i.length===0?d:o`
<div class="meta">
${i.map(([r,l])=>o`
<div class="meta-item">
<span class="meta-label">${r}</span>
<span class="meta-value">${_t(l)?o`<a href="${l}" target="_blank" rel="noopener noreferrer">${l}</a>`:l}</span>
</div>
`)}
</div>
`}};L.styles=E`
:host { display: contents; }
.backdrop {
position: fixed; inset: 0; z-index: 100; background: rgba(0,0,0,0.5);
}
.dialog {
position: fixed; left: 50%; top: 50%;
transform: translate(-50%, -50%);
width: 95vw; max-width: 480px;
max-height: 92vh; overflow: auto;
background: var(--card-background-color, var(--ha-card-background, #1c1c1c));
color: var(--primary-text-color);
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.4);
padding: 20px; z-index: 101;
display: flex; flex-direction: column; gap: 14px;
}
.header { display: flex; flex-direction: column; gap: 6px; }
.title { font-size: 20px; font-weight: 600; }
.meta { display: flex; flex-direction: column; gap: 4px; padding-top: 4px; border-top: 1px solid var(--divider-color); }
.meta-item { display: flex; gap: 8px; font-size: 12px; }
.meta-label { color: var(--secondary-text-color); min-width: 100px; }
.meta-value { color: var(--primary-text-color); flex: 1; word-break: break-word; }
.meta-value a { color: var(--primary-color); }
.tasks-section, .notes-section { display: flex; flex-direction: column; gap: 6px; }
.section-header { display: flex; align-items: baseline; gap: 8px; }
.count {
font-size: 11px; color: var(--secondary-text-color);
background: var(--secondary-background-color); padding: 2px 8px; border-radius: 999px;
}
.empty { color: var(--secondary-text-color); font-style: italic; font-size: 13px; padding: 8px 0; }
.task-list { display: flex; flex-direction: column; gap: 4px; max-height: 200px; overflow: auto; }
.task-row {
display: flex; align-items: center; gap: 10px;
padding: 8px; border-radius: 6px; cursor: pointer;
background: var(--secondary-background-color, rgba(255,255,255,0.03));
transition: background 0.12s;
}
.task-row:hover { background: var(--state-icon-color, rgba(255,255,255,0.06)); }
.status-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.task-name { flex: 1; font-size: 14px; }
.task-status { font-size: 11px; color: var(--secondary-text-color); text-transform: uppercase; }
.notes-body { white-space: pre-wrap; font-size: 13px; padding: 8px; background: var(--secondary-background-color); border-radius: 6px; }
.notes-body ha-markdown { white-space: normal; }
.actions { display: flex; gap: 8px; padding-top: 8px; border-top: 1px solid var(--divider-color); }
.actions .btn { flex: 1; }
.btn {
padding: 8px; font-size: 13px; border-radius: 6px; cursor: pointer;
border: 1px solid var(--divider-color);
background: var(--secondary-background-color, transparent);
color: var(--primary-text-color); font-weight: 500;
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.btn:hover { background: var(--state-icon-color, rgba(255,255,255,0.06)); }
.btn[disabled] { opacity: 0.5; cursor: wait; }
.btn.primary { background: var(--primary-color); color: var(--text-primary-color, white); border-color: var(--primary-color); }
.btn.danger { color: var(--error-color); }
.btn ha-icon { --mdc-icon-size: 16px; }
.loading { padding: 24px; text-align: center; color: var(--secondary-text-color); }
.error { padding: 8px; border-radius: 6px; background: rgba(211,47,47,0.1); color: var(--error-color); font-size: 13px; }
`,m([j({attribute:!1})],L.prototype,"hass",2),m([y()],L.prototype,"_open",2),m([y()],L.prototype,"_entryId",2),m([y()],L.prototype,"_data",2),m([y()],L.prototype,"_busy",2),m([y()],L.prototype,"_error",2);customElements.get("maintenance-object-quick-actions-dialog")||customElements.define("maintenance-object-quick-actions-dialog",L);var yt="maintenance-object-dialog",gt="maintenance-task-dialog",Rt="maintenance-history-edit-dialog",Ft="maintenance-complete-dialog",zt="maintenance-qr-dialog",qt="maintenance-task-quick-actions-dialog",Nt="maintenance-object-quick-actions-dialog";function B(){return document.querySelector("home-assistant")?.hass}function Vt(){return document.querySelector("home-assistant")?.shadowRoot??document.body}function T(e){let s=Vt(),t=s.querySelector(e)??document.body.querySelector(e);return t?t.parentNode!==s&&s.appendChild(t):(t=document.createElement(e),s.appendChild(t)),t}function P(e){let s=B();if(!s)return!1;e.hass=s;let t=I(s);return Z(t)||Y(t).then(()=>{e.requestUpdate?.()}),!0}var ft={features:{adaptive:!1,predictions:!1,seasonal:!1,environmental:!1,budget:!1,groups:!1,checklists:!1,schedule_time:!1,completion_actions:!1},defaultWarningDays:7},W=null;function vt(e){return W||(W=e.connection.sendMessagePromise({type:"maintenance_supporter/settings"}).then(s=>({features:s.features??ft.features,defaultWarningDays:s.general?.default_warning_days??7})).catch(()=>ft),W)}function Qe(){let e=T(yt);return P(e)?(e.openCreate(),!0):!1}function Je(e,s){let t=T(yt);return P(t)?(t.openEdit(e,s),!0):!1}function Xe(e="",s){let t=T(gt);if(!P(t))return!1;let n=B();return n?((async()=>{let i=await vt(n),r=t;r.checklistsEnabled=i.features.checklists,r.scheduleTimeEnabled=i.features.schedule_time,r.completionActionsEnabled=i.features.completion_actions,r.defaultWarningDays=i.defaultWarningDays,r.openCreate(e,s)})(),!0):!1}function tn(e,s){let t=T(gt);if(!P(t))return!1;let n=B();return n?((async()=>{try{let[i,r]=await Promise.all([n.connection.sendMessagePromise({type:"maintenance_supporter/object",entry_id:e}),vt(n)]),l=(i.tasks||[]).find(p=>p.id===s);if(!l){console.warn(`openEditTaskDialog: task ${s} not found in entry ${e}`);return}let c=t;c.checklistsEnabled=r.features.checklists,c.scheduleTimeEnabled=r.features.schedule_time,c.completionActionsEnabled=r.features.completion_actions,c.defaultWarningDays=r.defaultWarningDays,await c.openEdit(e,l)}catch(i){console.warn("openEditTaskDialog: failed to load task/features",i)}})(),!0):!1}function en(e){let s=T(Rt);return P(s)?(s.openEdit(e),!0):!1}function nn(e){let s=T(Ft);return P(s)?(ot(s,e,B()?.language||"en"),!0):!1}function sn(e){let s=T(zt);return P(s)?(s.openForTask(e.entry_id,e.task_id,e.object_name,e.task_name),!0):!1}function an(e,s){let t=T(qt);return P(t)?(t.openFor(e,s),!0):!1}function rn(e){let s=T(Nt);return P(s)?(s.openFor(e),!0):!1}export{_t as a,Yt as b,mt as c,It as d,Ct as e,K as f,rt as g,ot as h,R as i,Xt as j,te as k,lt as l,ct as m,dt as n,ut as o,ht as p,Qe as q,Je as r,Xe as s,tn as t,en as u,nn as v,sn as w,an as x,rn as y};
Loaded 100 of 184 files, more files were not shown because too many files have changed in this diff. Show more