App Updates

This commit is contained in:
2026-07-21 11:19:17 -04:00
parent 87ffe648a5
commit 0ed1687503
180 changed files with 943 additions and 118 deletions
@@ -0,0 +1,52 @@
/** #106 follow-up: reproduce with the EXACT _build_task_summary shape. */
import { expect, fixture, html } from "@open-wc/testing";
import "../components/task-dialog.js";
import type { MaintenanceTaskDialog } from "../components/task-dialog";
import { createMockHass } from "./_test-utils.js";
it("fleet-shaped task (nested manual schedule + plural-only threshold) keeps its trigger", async () => {
const { hass, sent } = createMockHass({
states: { "sensor.maintenance_supporter_batteries_to_replace": { state: "8" } },
handlers: { "maintenance_supporter/task/update": () => ({ success: true }) },
});
const el = await fixture<MaintenanceTaskDialog>(html`
<maintenance-task-dialog .hass=${hass}></maintenance-task-dialog>
`);
await el.updateComplete;
await el.openEdit("entry_x", {
id: "t1",
name: "Replace low batteries",
type: "inspection",
enabled: true,
schedule_type: "sensor_based",
interval_days: null,
interval_unit: "days",
due_date: null,
interval_anchor: "completion",
schedule: { kind: "manual" },
warning_days: 7,
battery_fleet_task: true,
trigger_config: {
type: "threshold",
entity_ids: ["sensor.maintenance_supporter_batteries_to_replace"],
trigger_above: 0,
entity_logic: "any",
auto_complete_on_recovery: true,
},
trigger_entity_info: {
entity_id: "sensor.maintenance_supporter_batteries_to_replace",
friendly_name: "Batteries to replace",
unit_of_measurement: null,
},
} as any);
await el.updateComplete;
// the user's edit: rename + warning days
(el as any)._name = "Remplacer les piles";
(el as any)._warningDays = "1";
await (el as any)._save();
const update = sent.find((m: any) => m.type === "maintenance_supporter/task/update") as any;
expect(update, "update sent").to.exist;
expect(update.trigger_config, "trigger_config must survive").to.exist;
expect(update.trigger_config.type).to.equal("threshold");
expect(update.trigger_config.trigger_above).to.equal(0);
});
@@ -84,6 +84,7 @@ export class MaintenanceBatteryFleetSection extends LitElement {
try {
await this.hass.connection.sendMessagePromise({
type: "maintenance_supporter/battery_fleet/setup",
language: this._lang,
});
await this._load();
} catch (e) {
@@ -1045,6 +1045,7 @@ export class MaintenanceSupporterPanel extends LitElement {
try {
const res = await this.hass.connection.sendMessagePromise<{ entry_id: string; task_id?: string }>({
type: "maintenance_supporter/battery_fleet/setup",
language: this.hass.language || "en",
});
this._batteryFleetSetupAvailable = false;
await this._loadData();
@@ -1235,6 +1235,10 @@ export const panelStyles = css`
:host([narrow]) .task-header-actions {
width: 100%;
justify-content: flex-start;
/* Longer labels (de "Überspringen", fr "Archiver", …) overflow a phone
viewport in a nowrap row — the ⋮ menu then needs a horizontal scroll
to reach. Wrap instead; language-independent. */
flex-wrap: wrap;
}
:host([narrow]) .filter-bar {
@@ -1433,7 +1437,7 @@ export const panelStyles = css`
.two-column-layout { grid-template-columns: 1fr; }
.tab { padding: 12px 16px; font-size: 14px; }
.task-header { flex-direction: column; align-items: flex-start; }
.task-header-actions { width: 100%; justify-content: flex-start; }
.task-header-actions { width: 100%; justify-content: flex-start; flex-wrap: wrap; }
.filter-bar { flex-wrap: wrap; }
.filter-bar select { flex: 1; min-width: 0; }
/* Mirror the :host([narrow]) grid layout for narrow desktop windows */