209 files
This commit is contained in:
@@ -65,6 +65,8 @@
|
||||
"interval": "Interval",
|
||||
"warning": "Upozornění",
|
||||
"last_performed": "Naposledy provedeno",
|
||||
"last_done_days_ago": "hotovo před {n} d",
|
||||
"last_done_today": "hotovo dnes",
|
||||
"next_due": "Další termín",
|
||||
"days_until_due": "Dnů do termínu",
|
||||
"avg_duration": "Prům. trvání",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Interval",
|
||||
"warning": "Advarsel",
|
||||
"last_performed": "Senest udført",
|
||||
"last_done_days_ago": "udført for {n} d siden",
|
||||
"last_done_today": "udført i dag",
|
||||
"next_due": "Næste forfald",
|
||||
"days_until_due": "Dage til forfald",
|
||||
"avg_duration": "Gns. varighed",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Intervall",
|
||||
"warning": "Vorwarnung",
|
||||
"last_performed": "Zuletzt durchgeführt",
|
||||
"last_done_days_ago": "vor {n} T erledigt",
|
||||
"last_done_today": "heute erledigt",
|
||||
"next_due": "Nächste Fälligkeit",
|
||||
"days_until_due": "Tage bis fällig",
|
||||
"avg_duration": "Ø Dauer",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Interval",
|
||||
"warning": "Warning",
|
||||
"last_performed": "Last performed",
|
||||
"last_done_days_ago": "done {n} d ago",
|
||||
"last_done_today": "done today",
|
||||
"next_due": "Next due",
|
||||
"days_until_due": "Days until due",
|
||||
"avg_duration": "Avg duration",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Intervalo",
|
||||
"warning": "Aviso",
|
||||
"last_performed": "Última ejecución",
|
||||
"last_done_days_ago": "hecho hace {n} d",
|
||||
"last_done_today": "hecho hoy",
|
||||
"next_due": "Próximo vencimiento",
|
||||
"days_until_due": "Días hasta vencimiento",
|
||||
"avg_duration": "Ø Duración",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Väli",
|
||||
"warning": "Varoitus",
|
||||
"last_performed": "Viimeksi suoritettu",
|
||||
"last_done_days_ago": "tehty {n} pv sitten",
|
||||
"last_done_today": "tehty tänään",
|
||||
"next_due": "Seuraava eräpäivä",
|
||||
"days_until_due": "Päiviä eräpäivään",
|
||||
"avg_duration": "Keskim. kesto",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Intervalle",
|
||||
"warning": "Avertissement",
|
||||
"last_performed": "Dernière exécution",
|
||||
"last_done_days_ago": "fait il y a {n} j",
|
||||
"last_done_today": "fait aujourd’hui",
|
||||
"next_due": "Prochaine échéance",
|
||||
"days_until_due": "Jours restants",
|
||||
"avg_duration": "Ø Durée",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "अंतराल",
|
||||
"warning": "चेतावनी",
|
||||
"last_performed": "अंतिम बार किया गया",
|
||||
"last_done_days_ago": "{n} दिन पहले किया",
|
||||
"last_done_today": "आज किया",
|
||||
"next_due": "अगली देय",
|
||||
"days_until_due": "देय तक दिन",
|
||||
"avg_duration": "औसत अवधि",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Intervallum",
|
||||
"warning": "Figyelmeztetés",
|
||||
"last_performed": "Utoljára elvégezve",
|
||||
"last_done_days_ago": "{n} napja elvégezve",
|
||||
"last_done_today": "ma elvégezve",
|
||||
"next_due": "Következő esedékesség",
|
||||
"days_until_due": "Napok az esedékességig",
|
||||
"avg_duration": "Átl. időtartam",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Intervallo",
|
||||
"warning": "Avviso",
|
||||
"last_performed": "Ultima esecuzione",
|
||||
"last_done_days_ago": "fatto {n} g fa",
|
||||
"last_done_today": "fatto oggi",
|
||||
"next_due": "Prossima scadenza",
|
||||
"days_until_due": "Giorni alla scadenza",
|
||||
"avg_duration": "Ø Durata",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "間隔",
|
||||
"warning": "警告",
|
||||
"last_performed": "最終実施",
|
||||
"last_done_days_ago": "{n}日前に実施",
|
||||
"last_done_today": "今日実施",
|
||||
"next_due": "次回期限",
|
||||
"days_until_due": "期限までの日数",
|
||||
"avg_duration": "平均所要時間",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "주기",
|
||||
"warning": "경고",
|
||||
"last_performed": "마지막 수행일",
|
||||
"last_done_days_ago": "{n}일 전 완료",
|
||||
"last_done_today": "오늘 완료",
|
||||
"next_due": "다음 예정일",
|
||||
"days_until_due": "남은 일수",
|
||||
"avg_duration": "평균 소요 시간",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Intervall",
|
||||
"warning": "Advarsel",
|
||||
"last_performed": "Sist utført",
|
||||
"last_done_days_ago": "utført for {n} d siden",
|
||||
"last_done_today": "utført i dag",
|
||||
"next_due": "Neste forfall",
|
||||
"days_until_due": "Dager til forfall",
|
||||
"avg_duration": "Gj.snittlig varighet",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Interval",
|
||||
"warning": "Waarschuwing",
|
||||
"last_performed": "Laatst uitgevoerd",
|
||||
"last_done_days_ago": "{n} d geleden gedaan",
|
||||
"last_done_today": "vandaag gedaan",
|
||||
"next_due": "Volgende keer",
|
||||
"days_until_due": "Dagen tot vervaldatum",
|
||||
"avg_duration": "Ø Duur",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Interwał",
|
||||
"warning": "Ostrzeżenie",
|
||||
"last_performed": "Ostatnio wykonane",
|
||||
"last_done_days_ago": "wykonano {n} d temu",
|
||||
"last_done_today": "wykonano dziś",
|
||||
"next_due": "Następny termin",
|
||||
"days_until_due": "Dni do terminu",
|
||||
"avg_duration": "Śr. czas trwania",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Intervalo",
|
||||
"warning": "Aviso",
|
||||
"last_performed": "Última execução",
|
||||
"last_done_days_ago": "feito há {n} d",
|
||||
"last_done_today": "feito hoje",
|
||||
"next_due": "Próximo vencimento",
|
||||
"days_until_due": "Dias até o vencimento",
|
||||
"avg_duration": "Duração média",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Intervalo",
|
||||
"warning": "Aviso",
|
||||
"last_performed": "Última execução",
|
||||
"last_done_days_ago": "feito há {n} d",
|
||||
"last_done_today": "feito hoje",
|
||||
"next_due": "Próximo vencimento",
|
||||
"days_until_due": "Dias até vencimento",
|
||||
"avg_duration": "Ø Duração",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Интервал",
|
||||
"warning": "Предупреждение",
|
||||
"last_performed": "Последнее выполнение",
|
||||
"last_done_days_ago": "выполнено {n} дн. назад",
|
||||
"last_done_today": "выполнено сегодня",
|
||||
"next_due": "Следующий срок",
|
||||
"days_until_due": "Дней до срока",
|
||||
"avg_duration": "Ср. длительность",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Intervall",
|
||||
"warning": "Varning",
|
||||
"last_performed": "Senast utförd",
|
||||
"last_done_days_ago": "klar för {n} d sedan",
|
||||
"last_done_today": "klar i dag",
|
||||
"next_due": "Nästa förfallodatum",
|
||||
"days_until_due": "Dagar till förfallodatum",
|
||||
"avg_duration": "Snittlig varaktighet",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "Aralık",
|
||||
"warning": "Uyarı",
|
||||
"last_performed": "Son yapılma",
|
||||
"last_done_days_ago": "{n} g önce yapıldı",
|
||||
"last_done_today": "bugün yapıldı",
|
||||
"next_due": "Sonraki vade",
|
||||
"days_until_due": "Vadeye kalan gün",
|
||||
"avg_duration": "Ort. süre",
|
||||
|
||||
@@ -65,6 +65,8 @@
|
||||
"interval": "Інтервал",
|
||||
"warning": "Попередження",
|
||||
"last_performed": "Останнє виконання",
|
||||
"last_done_days_ago": "виконано {n} д тому",
|
||||
"last_done_today": "виконано сьогодні",
|
||||
"next_due": "Наступний термін",
|
||||
"days_until_due": "Днів до терміну",
|
||||
"avg_duration": "Сер. тривалість",
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"interval": "间隔",
|
||||
"warning": "预警",
|
||||
"last_performed": "上次执行",
|
||||
"last_done_days_ago": "{n} 天前完成",
|
||||
"last_done_today": "今天完成",
|
||||
"next_due": "下次到期",
|
||||
"days_until_due": "距离到期天数",
|
||||
"avg_duration": "平均耗时",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { LitElement, html, css, nothing } from "lit";
|
||||
import { applySubscriptionEvent, type SubscriptionEvent } from "./helpers/subscription-merge";
|
||||
import { hydrateObjects } from "./helpers/hydrate-objects";
|
||||
import { property, state } from "lit/decorators.js";
|
||||
import { syncLocaleFromHass, sharedStyles, STATUS_COLORS, t, ensureLocale, isLocaleLoaded, setProfilePrefs, formatDueDays, langOf, currencySymbolOf, syncCurrencyDecimals} from "./styles";
|
||||
import { syncLocaleFromHass, sharedStyles, STATUS_COLORS, t, ensureLocale, isLocaleLoaded, setProfilePrefs, formatDueDays, formatLastDone, formatDate, langOf, currencySymbolOf, syncCurrencyDecimals} from "./styles";
|
||||
import { openSignedDocument } from "./helpers/document-url";
|
||||
import { isPhotoDocument } from "./helpers/document-categories";
|
||||
import { isSafeHttpUrl } from "./helpers/url";
|
||||
@@ -207,6 +207,15 @@ export class MaintenanceSupporterCard extends LitElement {
|
||||
this._firstLoadDone = true;
|
||||
}
|
||||
|
||||
/** A task without a due date (manual, sensor-only, paused): when it was
|
||||
* last done, "done 23 d ago" (D#203) — a dash only when never done. */
|
||||
private _lastDone(task: MaintenanceTask, L: string) {
|
||||
const done = formatLastDone(task.last_performed, L);
|
||||
return done
|
||||
? html`<span class="last-done" title="${t("last_performed", L)}: ${formatDate(task.last_performed, L)}">${done}</span>`
|
||||
: "—";
|
||||
}
|
||||
|
||||
/** Display name of the task's responsible user, or "" when the badge must
|
||||
* stay hidden (feature off, nobody assigned, or the name not resolved).
|
||||
* With a rotation this is whoever is up next — the pointer the engine
|
||||
@@ -603,7 +612,7 @@ export class MaintenanceSupporterCard extends LitElement {
|
||||
: formatDueDays(task.days_until_due, L)
|
||||
: task.trigger_active
|
||||
? "⚡"
|
||||
: "—"}
|
||||
: this._lastDone(task, L)}
|
||||
</div>
|
||||
${showActions && useButtons
|
||||
? html`
|
||||
|
||||
@@ -116,7 +116,7 @@ import type { MaintenanceSavedViewsDialog } from "./components/saved-views-dialo
|
||||
import { type SparklineContext } from "./renderers/sparkline";
|
||||
import { buildCalendarBuckets, type CalendarEvent } from "./helpers/calendar-bucket";
|
||||
import { haToday } from "./helpers/ha-time";
|
||||
import { renderTriggerProgress, renderMiniSparkline, computeTrend } from "./renderers/progress";
|
||||
import { renderTriggerProgress, renderMiniSparkline, computeTrend, renderDueText } from "./renderers/progress";
|
||||
import { type HistoryContext } from "./renderers/history";
|
||||
import { renderUserBadge, type TaskDetailContext } from "./renderers/task-detail";
|
||||
import { renderPersonChip, type PersonDisplay } from "./helpers/person";
|
||||
@@ -1248,6 +1248,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
status: task.status,
|
||||
days_until_due: task.days_until_due ?? null,
|
||||
next_due: task.next_due ?? null,
|
||||
last_performed: task.last_performed ?? null,
|
||||
next_event_titles: task.next_event_titles ?? [],
|
||||
trigger_active: task.trigger_active,
|
||||
trigger_current_value: task.trigger_current_value ?? null,
|
||||
@@ -4615,7 +4616,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
</span>
|
||||
<span class="cell type">${t(row.type, L)}</span>
|
||||
<span class="due-cell" @click=${() => this._showTask(row.entry_id, row.task_id)}>
|
||||
<span class="due-text">${formatDueDays(row.days_until_due, L)}</span>
|
||||
${renderDueText(row.days_until_due, row.last_performed, L)}
|
||||
${hasDaysBar
|
||||
? html`<div class="days-bar"><div class="days-bar-fill${daysOverflow ? " overflow" : ""}" style="width:${pct}%;background:${barColor}"></div></div>`
|
||||
: nothing}
|
||||
@@ -4845,7 +4846,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
<span class="task-sub${task.responsible_user_id ? '' : ' task-sub-empty'}">${renderUserBadge(task, (id) => this._userService?.getUserName(id) ?? null, (id) => this._userService?.getPerson(id) ?? null)}</span>
|
||||
<span class="cell type">${t(task.type, L)}</span>
|
||||
<span class="due-cell" @click=${() => this._showTask(obj.entry_id, task.id)}>
|
||||
<span class="due-text">${formatDueDays(task.days_until_due, L)}</span>
|
||||
${renderDueText(task.days_until_due, task.last_performed, L)}
|
||||
${task.trigger_config
|
||||
? renderTriggerProgress(task, { trend: computeTrend(task, this._miniStatsData), lang: L })
|
||||
: nothing}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
import { html, nothing } from "lit";
|
||||
import { t, formatDate, formatDueDays, formatNumber } from "../styles";
|
||||
import { t, formatDate, formatDueDays, formatLastDone, formatNumber } from "../styles";
|
||||
import { px } from "./chart-utils";
|
||||
import { daysProgress } from "../helpers/interval";
|
||||
import { stampMs } from "../helpers/ha-time";
|
||||
@@ -296,6 +296,24 @@ export function renderMiniSparkline(
|
||||
`;
|
||||
}
|
||||
|
||||
/** The due column's text: days until due, or, for a task without a due date
|
||||
* (manual, sensor-only, paused), when it was last done (D#203) — muted, so
|
||||
* it never reads as a status. A bare dash only for a task never done. */
|
||||
export function renderDueText(
|
||||
days: number | null | undefined,
|
||||
lastPerformed: string | null | undefined,
|
||||
lang: string,
|
||||
cls = "due-text",
|
||||
) {
|
||||
if (days == null) {
|
||||
const done = formatLastDone(lastPerformed, lang);
|
||||
if (done) {
|
||||
return html`<span class="${cls} last-done" title="${t("last_performed", lang)}: ${formatDate(lastPerformed, lang)}">${done}</span>`;
|
||||
}
|
||||
}
|
||||
return html`<span class="${cls}">${formatDueDays(days, lang)}</span>`;
|
||||
}
|
||||
|
||||
/** A detailed days-progress bar (last performed → next due) for the detail view. */
|
||||
export function renderDaysProgress(task: MaintenanceTask, lang: string) {
|
||||
const L = lang;
|
||||
|
||||
@@ -33,7 +33,7 @@ export { STATUS_COLORS, STATUS_ICONS } from "./status-constants";
|
||||
// `from "./styles"` import keeps working.
|
||||
import { ensureLocale, isLocaleLoaded, normLang, seedEnglish, t, type Translations } from "./helpers/locale-core";
|
||||
import { primeBackendErrors } from "./helpers/backend-errors";
|
||||
import { displayTimeZone, haTimeZone, minuteIn, stampMs, ymdIn } from "./helpers/ha-time";
|
||||
import { daysBetweenIso, displayTimeZone, haTimeZone, haToday, minuteIn, stampDate, stampMs, ymdIn } from "./helpers/ha-time";
|
||||
export { ensureLocale, isLocaleLoaded, seedEnglish, setLocale, t } from "./helpers/locale-core";
|
||||
seedEnglish(EN as Translations);
|
||||
|
||||
@@ -316,6 +316,18 @@ export function formatDueDays(days: number | null | undefined, lang?: string): s
|
||||
return `${days} ${days === 1 ? t("day", l) : t("days", l)}`;
|
||||
}
|
||||
|
||||
/** "done 23 d ago" / "done today" on HA's calendar — what the due column
|
||||
* shows for a task without a due date (manual, sensor-only, paused) instead
|
||||
* of a bare dash (D#203). null when the task was never done. */
|
||||
export function formatLastDone(lastPerformed: string | null | undefined, lang?: string): string | null {
|
||||
const day = stampDate(lastPerformed);
|
||||
if (!day) return null;
|
||||
const days = daysBetweenIso(day, haToday());
|
||||
if (!Number.isFinite(days)) return null;
|
||||
if (days <= 0) return t("last_done_today", lang || "en");
|
||||
return t("last_done_days_ago", lang || "en").replace("{n}", String(days));
|
||||
}
|
||||
|
||||
/** Localized interval label, e.g. "3 Months" / "7 Days" (issue #59 — was
|
||||
* hard-coded to days). Uses the unit_* keys from the schedule dialog. */
|
||||
export function formatInterval(
|
||||
@@ -1045,6 +1057,9 @@ export const sharedStyles = css`
|
||||
}
|
||||
|
||||
.due-text { font-size: 13px; }
|
||||
/* D#203: a task without a due date shows when it was last done — muted,
|
||||
so it never reads as a status. */
|
||||
.due-text.last-done { color: var(--secondary-text-color); }
|
||||
|
||||
.days-bar {
|
||||
width: 100%;
|
||||
|
||||
@@ -599,6 +599,8 @@ export interface TaskRow {
|
||||
status: string;
|
||||
days_until_due: number | null;
|
||||
next_due: string | null;
|
||||
/** D#203: shown as "done N d ago" when the task has no due date. */
|
||||
last_performed?: string | null;
|
||||
trigger_active: boolean;
|
||||
trigger_current_value: number | null;
|
||||
trigger_current_delta: number | null;
|
||||
|
||||
Reference in New Issue
Block a user