393 files

This commit is contained in:
Home Assistant Version Control committed 2026-09-27 17:16:54 +00:00
1 parent b05b7a897e
commit 39d97ac2db
404 files changed
+54006 -11034

No files matched your search

@@ -23,8 +23,10 @@ import { renderRecommendationBars } from "./recommendation";
import { renderSeasonalCardCompact, renderSeasonalCardExpanded } from "./seasonal";
import { renderCostDurationCard } from "./charts";
import { renderDaysProgress } from "./progress";
import { renderHistoryEntry, renderHistoryFilters, renderHistoryList, type HistoryContext } from "./history";
import { newestFirst, renderHistoryEntry, renderHistoryFilters, renderHistoryList, type HistoryContext } from "./history";
import { renderStatusBadge } from "./status";
import { clampPhaseCursor, effectivePhase, hasPhases } from "../helpers/phases";
import { renderEventTitles } from "../helpers/event-titles";
import "../components/task-documents";
export interface TaskDetailContext {
@@ -118,19 +120,14 @@ function renderTaskHeader(task: MaintenanceTask, ctx: TaskDetailContext) {
const L = ctx.lang;
const isOperator = ctx.isOperator;
// Determine status chip — use the backend-computed status. A completed
// one-time task is shown as archived ("done") rather than its raw "ok".
const statusClass = task.archived ? "archived" : (task.is_done ? "done" : (task.status === "due_soon" ? "warning" : (task.status || "ok")));
const statusText = task.archived ? t("archived", L) : (task.is_done ? t("completed", L) : t(task.status || "ok", L));
return html`
<div class="task-header">
<div class="task-header-title">
<span class="task-name-breadcrumb" @click=${() => ctx.showTaskView()}>${task.name}</span>
<span class="task-name-breadcrumb" @click=${() => ctx.showTaskView()}>${task.name}${renderEventTitles(task.next_event_titles)}</span>
${renderRefChip(ctx.taskRef ?? null, t("ref_number", L))}
<span class="breadcrumb-separator">·</span>
<span class="object-name-breadcrumb" @click=${() => ctx.showObject()}>${ctx.objectName}</span>
<span class="status-chip ${statusClass}">${statusText}</span>
${renderStatusBadge(task, L, "chip")}
${task.due_override ? html`<span class="postponed-badge" title="${t("postponed_to", L)}">
<ha-icon icon="mdi:calendar-arrow-right"></ha-icon>${formatDate(task.due_override, L)}
</span>` : nothing}
@@ -167,9 +164,14 @@ function renderTaskHeader(task: MaintenanceTask, ctx: TaskDetailContext) {
${!isOperator ? html`
<div class="popup-menu-item" @click=${() => ctx.duplicateTask()}>${t("duplicate", L)}</div>
<div class="popup-menu-item" @click=${() => ctx.moveTask()}>${t("move_task", L)}</div>
<div class="popup-menu-item" @click=${() => { ctx.closeMoreMenu(); ctx.promptReset(); }}>${t("reset", L)}</div>
<div class="popup-menu-item" @click=${() => { ctx.closeMoreMenu(); ctx.promptPostpone(); }}>${t("postpone", L)}…</div>
<div class="popup-menu-item" @click=${() => { ctx.closeMoreMenu(); ctx.snoozeTask(); }}>${t("snooze", L)}</div>
` : nothing}
<!-- Reset / Postpone / Snooze are household actions (read tier,
helpers/permissions HOUSEHOLD_ACTIONS): offered to everyone,
like Complete / Skip and the Lovelace quick-actions Reset. -->
<div class="popup-menu-item" @click=${() => { ctx.closeMoreMenu(); ctx.promptReset(); }}>${t("reset", L)}</div>
<div class="popup-menu-item" @click=${() => { ctx.closeMoreMenu(); ctx.promptPostpone(); }}>${t("postpone", L)}…</div>
<div class="popup-menu-item" @click=${() => { ctx.closeMoreMenu(); ctx.snoozeTask(); }}>${t("snooze", L)}</div>
${!isOperator ? html`
<div class="popup-menu-item" @click=${() => { ctx.closeMoreMenu(); ctx.toggleArchive(!!task.archived); }}>${task.archived ? t("unarchive", L) : t("archive", L)}</div>
<div class="popup-menu-divider"></div>
<div class="popup-menu-item danger" @click=${() => { ctx.closeMoreMenu(); ctx.deleteTask(); }}>${t("delete", L)}</div>
@@ -401,10 +403,12 @@ function renderRecommendationCard(task: MaintenanceTask, ctx: TaskDetailContext)
task.interval_confidence || "medium", L,
)}
<div class="recommendation-actions">
<ha-button appearance="filled"
@click=${() => ctx.applySuggestion(suggested)}>
${t("apply_suggestion", L)}
</ha-button>
${ctx.isOperator
? nothing /* task/apply_suggestion is write tier — the server refuses a read-only member */
: html`<ha-button appearance="filled" class="apply-suggestion"
@click=${() => ctx.applySuggestion(suggested)}>
${t("apply_suggestion", L)}
</ha-button>`}
<ha-button appearance="plain"
@click=${() => ctx.reanalyze()}>
${t("reanalyze", L)}
@@ -420,7 +424,9 @@ function renderRecommendationCard(task: MaintenanceTask, ctx: TaskDetailContext)
function renderRecentActivities(task: MaintenanceTask, ctx: TaskDetailContext) {
const L = ctx.lang;
const recent = task.history.slice(-3).reverse();
// By timestamp, not array order: a backdated completion (#133) is appended
// last but belongs further down (bug audit 2026-09-26).
const recent = newestFirst(task.history).slice(0, 3);
if (recent.length === 0) {
return nothing;