126 files
This commit is contained in:
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Načíst znovu",
|
||||
"battery_fleet_forecast_overdue": "Předpovězené datum uplynulo — baterie stále hlásí dobrý stav. Pokud jste ji vyměnili, zaznamenejte výměnu; jinak byla předpověď mylná.",
|
||||
"cost_from_parts": "Použít ≈ {amount} z dílů",
|
||||
"new_menu": "Nový",
|
||||
"dismiss": "Skrýt",
|
||||
"gs_label": "Začínáme — tyto tipy zmizí, jak vaše nastavení poroste",
|
||||
"gs_setups_chip": "Navrhovaná nastavení: nalezeno {n} zařízení s předpřipravenými spouštěči",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Genindlæs",
|
||||
"battery_fleet_forecast_overdue": "Forudsagt dato er overskredet — batteriet melder stadig god tilstand. Hvis du har skiftet det, registrér udskiftningen; ellers ramte prognosen forbi.",
|
||||
"cost_from_parts": "Brug ≈ {amount} fra dele",
|
||||
"new_menu": "Ny",
|
||||
"dismiss": "Afvis",
|
||||
"gs_label": "Kom godt i gang — disse tips forsvinder, efterhånden som opsætningen vokser",
|
||||
"gs_setups_chip": "Foreslåede opsætninger fandt {n} enheder med forudindstillede udløsere",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Neu laden",
|
||||
"battery_fleet_forecast_overdue": "Prognosedatum überschritten — die Batterie meldet sich weiterhin gesund. Falls du sie gewechselt hast, trage den Wechsel nach; andernfalls lag die Prognose daneben.",
|
||||
"cost_from_parts": "≈ {amount} aus Teilen übernehmen",
|
||||
"new_menu": "Neu",
|
||||
"dismiss": "Ausblenden",
|
||||
"gs_label": "Erste Schritte — diese Hinweise verschwinden, wenn dein Setup wächst",
|
||||
"gs_setups_chip": "Vorgeschlagene Setups: {n} Geräte mit vorverdrahteten Auslösern gefunden",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Reload",
|
||||
"battery_fleet_forecast_overdue": "Predicted date passed — the battery still reports healthy. If you swapped it, record the replacement; otherwise the forecast was off.",
|
||||
"cost_from_parts": "Use ≈ {amount} from parts",
|
||||
"new_menu": "New",
|
||||
"dismiss": "Dismiss",
|
||||
"gs_label": "Getting started — these hints retire as your setup grows",
|
||||
"gs_setups_chip": "Suggested setups found {n} devices with pre-wired triggers",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Recargar",
|
||||
"battery_fleet_forecast_overdue": "Fecha prevista superada: la batería sigue informando buen estado. Si la cambiaste, registra el reemplazo; si no, la previsión falló.",
|
||||
"cost_from_parts": "Usar ≈ {amount} de las piezas",
|
||||
"new_menu": "Nuevo",
|
||||
"dismiss": "Descartar",
|
||||
"gs_label": "Primeros pasos: estas sugerencias desaparecen a medida que crece tu configuración",
|
||||
"gs_setups_chip": "Configuraciones sugeridas: {n} dispositivos con disparadores preconfigurados",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Lataa uudelleen",
|
||||
"battery_fleet_forecast_overdue": "Ennustettu päivä on ohitettu — akku ilmoittaa yhä hyvästä kunnosta. Jos vaihdoit sen, kirjaa vaihto; muuten ennuste oli pielessä.",
|
||||
"cost_from_parts": "Käytä ≈ {amount} osista",
|
||||
"new_menu": "Uusi",
|
||||
"dismiss": "Hylkää",
|
||||
"gs_label": "Aloitus — nämä vihjeet poistuvat asennuksen kasvaessa",
|
||||
"gs_setups_chip": "Ehdotetut asetukset löysivät {n} laitetta valmiilla laukaisimilla",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Recharger",
|
||||
"battery_fleet_forecast_overdue": "Date prévue dépassée — la batterie se signale toujours en bon état. Si vous l'avez remplacée, enregistrez le remplacement ; sinon la prévision était erronée.",
|
||||
"cost_from_parts": "Reprendre ≈ {amount} des pièces",
|
||||
"new_menu": "Nouveau",
|
||||
"dismiss": "Ignorer",
|
||||
"gs_label": "Premiers pas — ces conseils disparaissent à mesure que votre configuration grandit",
|
||||
"gs_setups_chip": "Configurations suggérées : {n} appareils avec déclencheurs pré-câblés trouvés",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "पुनः लोड करें",
|
||||
"battery_fleet_forecast_overdue": "अनुमानित तिथि बीत गई — बैटरी अब भी अच्छी स्थिति बता रही है। यदि आपने इसे बदला है, तो बदलाव दर्ज करें; अन्यथा पूर्वानुमान गलत था।",
|
||||
"cost_from_parts": "पुर्ज़ों से ≈ {amount} लें",
|
||||
"new_menu": "नया",
|
||||
"dismiss": "हटाएँ",
|
||||
"gs_label": "शुरुआत — सेटअप बढ़ने पर ये संकेत हट जाते हैं",
|
||||
"gs_setups_chip": "सुझाए गए सेटअप: पूर्व-निर्धारित ट्रिगर वाले {n} उपकरण मिले",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Újratöltés",
|
||||
"battery_fleet_forecast_overdue": "Az előrejelzett dátum elmúlt — az elem továbbra is jó állapotot jelez. Ha kicserélted, rögzítsd a cserét; különben az előrejelzés tévedett.",
|
||||
"cost_from_parts": "≈ {amount} átvétele az alkatrészekből",
|
||||
"new_menu": "Új",
|
||||
"dismiss": "Elrejtés",
|
||||
"gs_label": "Első lépések — a tippek eltűnnek, ahogy a beállítás bővül",
|
||||
"gs_setups_chip": "Javasolt beállítások: {n} eszköz előre bekötött triggerekkel",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Ricarica",
|
||||
"battery_fleet_forecast_overdue": "Data prevista superata — la batteria risulta ancora in buono stato. Se l'hai sostituita, registra la sostituzione; altrimenti la previsione era errata.",
|
||||
"cost_from_parts": "Usa ≈ {amount} dai ricambi",
|
||||
"new_menu": "Nuovo",
|
||||
"dismiss": "Ignora",
|
||||
"gs_label": "Primi passi — questi suggerimenti scompaiono man mano che la configurazione cresce",
|
||||
"gs_setups_chip": "Configurazioni suggerite: trovati {n} dispositivi con trigger preconfigurati",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "再読み込み",
|
||||
"battery_fleet_forecast_overdue": "予測日を過ぎましたが、電池はまだ正常と報告しています。交換済みなら交換を記録してください。そうでなければ予測が外れています。",
|
||||
"cost_from_parts": "部品から ≈ {amount} を適用",
|
||||
"new_menu": "新規",
|
||||
"dismiss": "閉じる",
|
||||
"gs_label": "はじめに — セットアップが進むとこれらのヒントは消えます",
|
||||
"gs_setups_chip": "推奨セットアップ:トリガー設定済みのデバイスを{n}台検出",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "새로 고침",
|
||||
"battery_fleet_forecast_overdue": "예측 날짜가 지났지만 배터리는 여전히 정상으로 보고됩니다. 교체했다면 교체를 기록하세요. 아니라면 예측이 빗나간 것입니다.",
|
||||
"cost_from_parts": "부품에서 ≈ {amount} 적용",
|
||||
"new_menu": "새로 만들기",
|
||||
"dismiss": "닫기",
|
||||
"gs_label": "시작하기 — 설정이 늘어나면 이 힌트는 사라집니다",
|
||||
"gs_setups_chip": "추천 설정: 트리거가 준비된 기기 {n}대 발견",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Last inn på nytt",
|
||||
"battery_fleet_forecast_overdue": "Forutsagt dato er passert — batteriet melder fortsatt god tilstand. Hvis du byttet det, registrer byttet; ellers bommet prognosen.",
|
||||
"cost_from_parts": "Bruk ≈ {amount} fra deler",
|
||||
"new_menu": "Ny",
|
||||
"dismiss": "Avvis",
|
||||
"gs_label": "Kom i gang — tipsene forsvinner etter hvert som oppsettet vokser",
|
||||
"gs_setups_chip": "Foreslåtte oppsett fant {n} enheter med ferdigkoblede utløsere",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Herladen",
|
||||
"battery_fleet_forecast_overdue": "Voorspelde datum verstreken — de batterij meldt zich nog steeds gezond. Heb je hem vervangen, registreer dan de vervanging; anders zat de voorspelling ernaast.",
|
||||
"cost_from_parts": "≈ {amount} uit onderdelen overnemen",
|
||||
"new_menu": "Nieuw",
|
||||
"dismiss": "Verbergen",
|
||||
"gs_label": "Aan de slag — deze tips verdwijnen naarmate je installatie groeit",
|
||||
"gs_setups_chip": "Voorgestelde setups: {n} apparaten met vooraf ingestelde triggers gevonden",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Załaduj ponownie",
|
||||
"battery_fleet_forecast_overdue": "Przewidywana data minęła — bateria nadal zgłasza dobry stan. Jeśli ją wymieniono, zapisz wymianę; w przeciwnym razie prognoza była błędna.",
|
||||
"cost_from_parts": "Użyj ≈ {amount} z części",
|
||||
"new_menu": "Nowy",
|
||||
"dismiss": "Odrzuć",
|
||||
"gs_label": "Pierwsze kroki — te wskazówki znikają wraz z rozwojem konfiguracji",
|
||||
"gs_setups_chip": "Sugerowane konfiguracje: znaleziono {n} urządzeń z gotowymi wyzwalaczami",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Recarregar",
|
||||
"battery_fleet_forecast_overdue": "Data prevista ultrapassada — a bateria ainda reporta bom estado. Se você a trocou, registre a troca; caso contrário, a previsão errou.",
|
||||
"cost_from_parts": "Usar ≈ {amount} das peças",
|
||||
"new_menu": "Novo",
|
||||
"dismiss": "Dispensar",
|
||||
"gs_label": "Primeiros passos — estas dicas somem conforme a configuração cresce",
|
||||
"gs_setups_chip": "Configurações sugeridas: {n} dispositivos com gatilhos pré-configurados",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Recarregar",
|
||||
"battery_fleet_forecast_overdue": "Data prevista ultrapassada — a bateria continua a reportar bom estado. Se a substituiu, registe a substituição; caso contrário, a previsão falhou.",
|
||||
"cost_from_parts": "Usar ≈ {amount} das peças",
|
||||
"new_menu": "Novo",
|
||||
"dismiss": "Dispensar",
|
||||
"gs_label": "Primeiros passos — estas dicas desaparecem à medida que a configuração cresce",
|
||||
"gs_setups_chip": "Configurações sugeridas: {n} dispositivos com gatilhos pré-configurados",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Перезагрузить",
|
||||
"battery_fleet_forecast_overdue": "Прогнозируемая дата прошла — батарея по-прежнему сообщает о хорошем состоянии. Если вы её заменили, зафиксируйте замену; иначе прогноз оказался неверным.",
|
||||
"cost_from_parts": "Взять ≈ {amount} из запчастей",
|
||||
"new_menu": "Создать",
|
||||
"dismiss": "Скрыть",
|
||||
"gs_label": "Первые шаги — эти подсказки исчезнут по мере роста настройки",
|
||||
"gs_setups_chip": "Рекомендуемые настройки: найдено {n} устройств с готовыми триггерами",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Ladda om",
|
||||
"battery_fleet_forecast_overdue": "Förutsagt datum har passerat — batteriet rapporterar fortfarande god status. Om du bytte det, registrera bytet; annars slog prognosen fel.",
|
||||
"cost_from_parts": "Använd ≈ {amount} från delar",
|
||||
"new_menu": "Ny",
|
||||
"dismiss": "Avfärda",
|
||||
"gs_label": "Kom igång — tipsen försvinner när din installation växer",
|
||||
"gs_setups_chip": "Föreslagna uppsättningar hittade {n} enheter med förkopplade utlösare",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Yeniden yükle",
|
||||
"battery_fleet_forecast_overdue": "Öngörülen tarih geçti — pil hâlâ sağlıklı görünüyor. Değiştirdiyseniz değişimi kaydedin; aksi halde tahmin yanılmış demektir.",
|
||||
"cost_from_parts": "Parçalardan ≈ {amount} kullan",
|
||||
"new_menu": "Yeni",
|
||||
"dismiss": "Kapat",
|
||||
"gs_label": "Başlarken — kurulumunuz büyüdükçe bu ipuçları kaybolur",
|
||||
"gs_setups_chip": "Önerilen kurulumlar {n} cihaz buldu (hazır tetikleyicilerle)",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "Перезавантажити",
|
||||
"battery_fleet_forecast_overdue": "Прогнозована дата минула — батарея й далі повідомляє про добрий стан. Якщо ви її замінили, зафіксуйте заміну; інакше прогноз не справдився.",
|
||||
"cost_from_parts": "Узяти ≈ {amount} із запчастин",
|
||||
"new_menu": "Створити",
|
||||
"dismiss": "Приховати",
|
||||
"gs_label": "Перші кроки — ці підказки зникнуть у міру зростання налаштування",
|
||||
"gs_setups_chip": "Рекомендовані налаштування: знайдено {n} пристроїв із готовими тригерами",
|
||||
|
||||
@@ -836,7 +836,6 @@
|
||||
"update_reload": "重新加载",
|
||||
"battery_fleet_forecast_overdue": "预测日期已过——电池仍报告状态良好。如果您已更换电池,请记录更换;否则说明预测有误。",
|
||||
"cost_from_parts": "采用配件合计 ≈ {amount}",
|
||||
"new_menu": "新建",
|
||||
"dismiss": "忽略",
|
||||
"gs_label": "入门提示——随着配置的完善,这些提示会自动消失",
|
||||
"gs_setups_chip": "推荐配置发现 {n} 台设备(含预设触发器)",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/** Maintenance Supporter Lovelace Card. */
|
||||
|
||||
import { LitElement, html, css, nothing } from "lit";
|
||||
import { mergeSubscriptionEvent, type SubscriptionEvent } from "./helpers/subscription-merge";
|
||||
import { applySubscriptionEvent, type SubscriptionEvent } from "./helpers/subscription-merge";
|
||||
import { hydrateObjects } from "./helpers/hydrate-objects";
|
||||
import { property, state } from "lit/decorators.js";
|
||||
import { sharedStyles, STATUS_COLORS, t, ensureLocale, isLocaleLoaded, setDateTimePrefs, formatDueDays } from "./styles";
|
||||
@@ -276,11 +276,10 @@ export class MaintenanceSupporterCard extends LitElement {
|
||||
try {
|
||||
const unsub = await this.hass.connection.subscribeMessage(
|
||||
(msg: unknown) => {
|
||||
const ev = msg as SubscriptionEvent<MaintenanceObjectResponse>;
|
||||
// Compact payloads: hydrate before merging (helpers/hydrate-objects).
|
||||
if (ev.objects) hydrateObjects(ev.objects);
|
||||
if (ev.delta) hydrateObjects(ev.delta);
|
||||
const next = mergeSubscriptionEvent(this._objects, ev);
|
||||
const next = applySubscriptionEvent(
|
||||
this._objects,
|
||||
msg as SubscriptionEvent<MaintenanceObjectResponse>,
|
||||
);
|
||||
if (next !== null) this._objects = next;
|
||||
},
|
||||
// deltas: only changed entries arrive — see helpers/subscription-merge.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { LitElement, html, nothing } from "lit";
|
||||
import { isSafeHttpUrl } from "./helpers/url";
|
||||
import { mergeSubscriptionEvent, type SubscriptionEvent } from "./helpers/subscription-merge";
|
||||
import { applySubscriptionEvent, type SubscriptionEvent } from "./helpers/subscription-merge";
|
||||
import { isStaleBundle } from "./helpers/bundle-version";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { sharedStyles, STATUS_COLORS, STATUS_ICONS, DEFAULT_CURRENCY_SYMBOL, t, ensureLocale, isLocaleLoaded, formatDate, formatDueDays, formatInterval, formatRecurrence, setDateTimePrefs } from "./styles";
|
||||
@@ -657,11 +657,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
const unsub = await this.hass.connection.subscribeMessage(
|
||||
(msg: unknown) => {
|
||||
const ev = msg as SubscriptionEvent<MaintenanceObjectResponse>;
|
||||
// Compact payloads: hydrate incoming entries before merging so
|
||||
// everything downstream keeps seeing the full shape.
|
||||
if (ev.objects) hydrateObjects(ev.objects);
|
||||
if (ev.delta) hydrateObjects(ev.delta);
|
||||
const next = mergeSubscriptionEvent(this._objects, ev);
|
||||
const next = applySubscriptionEvent(this._objects, ev);
|
||||
if (next !== null) {
|
||||
this._objects = next;
|
||||
// Full snapshots are rare (subscribe start) — keep the skeleton
|
||||
@@ -3284,7 +3280,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
<div class="new-menu-wrapper">
|
||||
<ha-button appearance="filled" class="new-menu-button"
|
||||
@click=${(e: Event) => { e.stopPropagation(); this._toggleNewMenu(); }}>
|
||||
<ha-icon icon="mdi:plus"></ha-icon> ${t("new_menu", L)}
|
||||
<ha-icon icon="mdi:plus"></ha-icon> ${t("add", L)}
|
||||
<ha-icon icon="mdi:menu-down"></ha-icon>
|
||||
</ha-button>
|
||||
${this._newMenuOpen ? html`
|
||||
@@ -3316,16 +3312,25 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private _toggleNewMenu(): void {
|
||||
this._newMenuOpen = !this._newMenuOpen;
|
||||
if (this._newMenuOpen) {
|
||||
/** Shared popup mechanic (DRY audit 2026-08: this closer was copy-pasted
|
||||
* three times): flip the flag, and while open arm a one-shot document
|
||||
* click that closes it again. The setTimeout defers past the click that
|
||||
* opened the menu. */
|
||||
private _togglePopup(get: () => boolean, set: (v: boolean) => void): void {
|
||||
const open = !get();
|
||||
set(open);
|
||||
if (open) {
|
||||
setTimeout(() => {
|
||||
const handler = () => { this._newMenuOpen = false; document.removeEventListener("click", handler); };
|
||||
const handler = () => { set(false); document.removeEventListener("click", handler); };
|
||||
document.addEventListener("click", handler);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private _toggleNewMenu(): void {
|
||||
this._togglePopup(() => this._newMenuOpen, (v) => { this._newMenuOpen = v; });
|
||||
}
|
||||
|
||||
private _closeNewMenu(): void {
|
||||
this._newMenuOpen = false;
|
||||
}
|
||||
@@ -3421,13 +3426,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
}
|
||||
|
||||
private _toggleObjMenu(): void {
|
||||
this._objMenuOpen = !this._objMenuOpen;
|
||||
if (this._objMenuOpen) {
|
||||
setTimeout(() => {
|
||||
const handler = () => { this._objMenuOpen = false; document.removeEventListener("click", handler); };
|
||||
document.addEventListener("click", handler);
|
||||
}, 0);
|
||||
}
|
||||
this._togglePopup(() => this._objMenuOpen, (v) => { this._objMenuOpen = v; });
|
||||
}
|
||||
|
||||
private _closeObjMenu(): void {
|
||||
@@ -3435,12 +3434,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
}
|
||||
|
||||
private _toggleMoreMenu(): void {
|
||||
this._moreMenuOpen = !this._moreMenuOpen;
|
||||
if (this._moreMenuOpen) {
|
||||
// Close menu on next outside click
|
||||
const handler = () => { this._moreMenuOpen = false; document.removeEventListener("click", handler); };
|
||||
setTimeout(() => document.addEventListener("click", handler, { once: true }), 0);
|
||||
}
|
||||
this._togglePopup(() => this._moreMenuOpen, (v) => { this._moreMenuOpen = v; });
|
||||
}
|
||||
|
||||
private _closeMoreMenu(): void {
|
||||
|
||||
Reference in New Issue
Block a user