124 files
This commit is contained in:
@@ -43,6 +43,19 @@ interface SettingsResponse {
|
||||
panel_title: string;
|
||||
/** Opt-in copy of the shipped Assist sentences into the config dir. */
|
||||
install_assist_sentences?: boolean;
|
||||
/** #146: household "low" floors (percent) for discovery + battery fleet. */
|
||||
default_consumable_threshold?: number;
|
||||
battery_low_percent?: number;
|
||||
/** Computed: what Battery Notes reports (null when not installed). */
|
||||
battery_notes?: {
|
||||
default: number;
|
||||
devices: number;
|
||||
overrides: { name: string; device_id: string | null; threshold: number }[];
|
||||
more: number;
|
||||
} | null;
|
||||
/** #145: how task rows show Complete / Skip. */
|
||||
row_action_style?: "buttons_compact" | "buttons" | "icons";
|
||||
row_action_notice_pending?: boolean;
|
||||
};
|
||||
notifications: {
|
||||
due_soon_enabled: boolean;
|
||||
@@ -241,6 +254,37 @@ export class MaintenanceSettingsView extends LitElement {
|
||||
this._vacWindowEnd = v.window_end;
|
||||
}
|
||||
|
||||
/** #146 follow-up: what Battery Notes currently reports, with the rule
|
||||
* spelled out — warn-toned when its default sits above our floor (then a
|
||||
* lowered floor would silently change nothing for noted batteries). */
|
||||
private _renderBatteryNotesHint(L: string) {
|
||||
const bn = this._settings?.general?.battery_notes;
|
||||
if (!bn || !bn.devices) return nothing;
|
||||
const floor = this._settings?.general?.battery_low_percent ?? 20;
|
||||
const warn = bn.default > floor;
|
||||
const summary = t("bn_summary", L)
|
||||
.replace("{name}", "Battery Notes")
|
||||
.replace("{pct}", String(bn.default))
|
||||
.replace("{n}", String(bn.devices));
|
||||
const rule = (warn ? t("bn_above_floor", L).replace("{name}", "Battery Notes") : t("bn_floor_decides", L))
|
||||
.replace("{floor}", String(floor));
|
||||
return html`
|
||||
<div class="bn-note${warn ? " warn" : ""}">
|
||||
<ha-icon icon="${warn ? "mdi:alert-outline" : "mdi:battery-heart-variant"}"></ha-icon>
|
||||
<span>
|
||||
<a class="bn-link" href="/config/integrations/integration/battery_notes">${summary.split(":")[0]}</a>${summary.slice(summary.indexOf(":"))}
|
||||
${bn.overrides.length
|
||||
? html` · ${t("bn_overrides", L).replace("{n}", String(bn.overrides.length + bn.more))}
|
||||
${bn.overrides.map((o, i) => html`${i ? " · " : " "}${o.device_id
|
||||
? html`<a class="bn-link" href="/config/devices/device/${o.device_id}">${o.name}</a>`
|
||||
: o.name} (${o.threshold} %)`)}
|
||||
${bn.more ? html` <span class="bn-more">${t("bn_more", L).replace("{n}", String(bn.more))}</span>` : nothing}`
|
||||
: nothing}
|
||||
<span class="bn-sub">${rule}</span>
|
||||
</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
private async _updateSetting(key: string, value: unknown): Promise<void> {
|
||||
try {
|
||||
const result = await this.hass.connection.sendMessagePromise({
|
||||
@@ -594,6 +638,32 @@ export class MaintenanceSettingsView extends LitElement {
|
||||
if (v >= 0 && v <= 365) this._updateSetting("default_warning_days", v);
|
||||
}} />
|
||||
</label>
|
||||
<label class="setting-row">
|
||||
<span class="setting-label">${t("settings_consumable_threshold", L)}</span>
|
||||
<input type="number" min="1" max="90" .value=${String(g.default_consumable_threshold ?? 10)}
|
||||
@change=${(e: Event) => {
|
||||
const v = parseInt((e.target as HTMLInputElement).value, 10);
|
||||
if (v >= 1 && v <= 90) this._updateSetting("default_consumable_threshold", v);
|
||||
}} />
|
||||
</label>
|
||||
<label class="setting-row">
|
||||
<span class="setting-label">${t("settings_battery_low_percent", L)}</span>
|
||||
<input type="number" min="1" max="90" .value=${String(g.battery_low_percent ?? 20)}
|
||||
@change=${(e: Event) => {
|
||||
const v = parseInt((e.target as HTMLInputElement).value, 10);
|
||||
if (v >= 1 && v <= 90) this._updateSetting("battery_low_percent", v);
|
||||
}} />
|
||||
</label>
|
||||
${this._renderBatteryNotesHint(L)}
|
||||
<div class="setting-hint">${t("settings_thresholds_hint", L)}</div>
|
||||
<label class="setting-row">
|
||||
<span class="setting-label">${t("settings_row_actions", L)}</span>
|
||||
<select .value=${live(g.row_action_style || "buttons_compact")}
|
||||
@change=${(e: Event) => this._updateSetting("row_action_style", (e.target as HTMLSelectElement).value)}>
|
||||
${(["buttons_compact", "buttons", "icons"] as const).map((v) => html`
|
||||
<option value=${v} ?selected=${(g.row_action_style || "buttons_compact") === v}>${t(`row_actions_${v}`, L)}</option>`)}
|
||||
</select>
|
||||
</label>
|
||||
<label class="setting-row">
|
||||
<span class="setting-label">${t("settings_currency", L)}</span>
|
||||
<select .value=${live(b.currency)} @change=${(e: Event) => this._updateSetting("budget_currency", (e.target as HTMLSelectElement).value)}>
|
||||
@@ -1667,6 +1737,21 @@ export class MaintenanceSettingsView extends LitElement {
|
||||
// --- Styles ---
|
||||
|
||||
static styles = css`
|
||||
.bn-note {
|
||||
display: flex; align-items: flex-start; gap: 10px;
|
||||
margin: 6px 0 10px; padding: 10px 12px; border-radius: 8px;
|
||||
background: rgba(3, 169, 244, 0.08);
|
||||
border: 1px solid rgba(3, 169, 244, 0.25);
|
||||
font-size: 13.5px; line-height: 1.45;
|
||||
}
|
||||
.bn-note ha-icon { --mdc-icon-size: 20px; flex: none; color: var(--primary-color); margin-top: 1px; }
|
||||
.bn-note.warn { background: rgba(255, 167, 38, 0.08); border-color: rgba(255, 167, 38, 0.35); }
|
||||
.bn-note.warn ha-icon { color: var(--warning-color, #ffa726); }
|
||||
.bn-link { color: var(--primary-color); text-decoration: none; }
|
||||
.bn-link:hover { text-decoration: underline; }
|
||||
.bn-more, .bn-sub { color: var(--secondary-text-color); }
|
||||
.bn-sub { display: block; font-size: 12.5px; margin-top: 2px; }
|
||||
|
||||
:host { display: block; }
|
||||
|
||||
.settings-loading {
|
||||
|
||||
+26
-23
@@ -596,40 +596,40 @@ export class MaintenanceTaskQuickActionsDialog extends LitElement {
|
||||
`
|
||||
: html`
|
||||
<div class="actions primary-row">
|
||||
<button class="btn primary" @click=${this._onComplete} ?disabled=${this._busy}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>
|
||||
<ha-button appearance="accent" variant="success" @click=${this._onComplete} .disabled=${this._busy}>
|
||||
<ha-icon slot="start" icon="mdi:check"></ha-icon>
|
||||
${t("complete", L) || "Complete"}
|
||||
</button>
|
||||
<button class="btn" @click=${() => { this._showSkip = true; }} ?disabled=${this._busy}>
|
||||
<ha-icon icon="mdi:skip-next"></ha-icon>
|
||||
</ha-button>
|
||||
<ha-button appearance="plain" variant="neutral" @click=${() => { this._showSkip = true; }} .disabled=${this._busy}>
|
||||
<ha-icon slot="start" icon="mdi:skip-next"></ha-icon>
|
||||
${t("skip", L) || "Skip"}
|
||||
</button>
|
||||
<button class="btn" @click=${() => { this._showReset = true; }} ?disabled=${this._busy}>
|
||||
<ha-icon icon="mdi:restart"></ha-icon>
|
||||
</ha-button>
|
||||
<ha-button appearance="plain" variant="neutral" @click=${() => { this._showReset = true; }} .disabled=${this._busy}>
|
||||
<ha-icon slot="start" icon="mdi:restart"></ha-icon>
|
||||
${t("reset", L) || "Reset"}
|
||||
</button>
|
||||
</ha-button>
|
||||
</div>
|
||||
${isAdmin
|
||||
? html`
|
||||
<div class="actions secondary-row">
|
||||
<button class="btn ghost" @click=${this._onEdit} ?disabled=${this._busy}>
|
||||
<ha-icon icon="mdi:pencil"></ha-icon>
|
||||
<ha-button size="small" appearance="outlined" variant="neutral" @click=${this._onEdit} .disabled=${this._busy}>
|
||||
<ha-icon slot="start" icon="mdi:pencil"></ha-icon>
|
||||
${t("edit", L) || "Edit"}
|
||||
</button>
|
||||
<button class="btn ghost" @click=${this._onQr} ?disabled=${this._busy}>
|
||||
<ha-icon icon="mdi:qrcode"></ha-icon>
|
||||
</ha-button>
|
||||
<ha-button size="small" appearance="outlined" variant="neutral" @click=${this._onQr} .disabled=${this._busy}>
|
||||
<ha-icon slot="start" icon="mdi:qrcode"></ha-icon>
|
||||
${t("qr_code", L) || "QR"}
|
||||
</button>
|
||||
<button class="btn ghost"
|
||||
</ha-button>
|
||||
<ha-button size="small" appearance="outlined" variant="neutral"
|
||||
@click=${task.archived ? this._onUnarchive : this._onArchive}
|
||||
?disabled=${this._busy}>
|
||||
<ha-icon icon="${task.archived ? 'mdi:archive-arrow-up-outline' : 'mdi:archive-outline'}"></ha-icon>
|
||||
.disabled=${this._busy}>
|
||||
<ha-icon slot="start" icon="${task.archived ? 'mdi:archive-arrow-up-outline' : 'mdi:archive-outline'}"></ha-icon>
|
||||
${task.archived ? (t("unarchive", L) || "Unarchive") : (t("archive", L) || "Archive")}
|
||||
</button>
|
||||
<button class="btn ghost danger" @click=${this._onDelete} ?disabled=${this._busy}>
|
||||
<ha-icon icon="mdi:delete"></ha-icon>
|
||||
</ha-button>
|
||||
<ha-button size="small" appearance="outlined" variant="danger" class="danger" @click=${this._onDelete} .disabled=${this._busy}>
|
||||
<ha-icon slot="start" icon="mdi:delete"></ha-icon>
|
||||
${t("delete", L) || "Delete"}
|
||||
</button>
|
||||
</ha-button>
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
@@ -704,6 +704,7 @@ export class MaintenanceTaskQuickActionsDialog extends LitElement {
|
||||
.actions { display: flex; gap: 8px; }
|
||||
.actions.primary-row { gap: 6px; }
|
||||
.actions.primary-row .btn { flex: 1; }
|
||||
.actions.primary-row ha-button { 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
|
||||
@@ -712,9 +713,11 @@ export class MaintenanceTaskQuickActionsDialog extends LitElement {
|
||||
padding-top: 8px; border-top: 1px solid var(--divider-color);
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.actions.secondary-row .btn.danger {
|
||||
.actions.secondary-row .btn.danger,
|
||||
.actions.secondary-row ha-button.danger {
|
||||
margin-left: auto;
|
||||
}
|
||||
.actions.secondary-row ha-button { --ha-button-font-size: 13px; }
|
||||
.btn {
|
||||
padding: 8px 12px; font-size: 14px;
|
||||
border-radius: 6px; cursor: pointer;
|
||||
|
||||
@@ -122,6 +122,8 @@ interface SettingsCache {
|
||||
checklists: boolean; schedule_time: boolean; completion_actions: boolean;
|
||||
};
|
||||
defaultWarningDays: number;
|
||||
/** #145: global "Task row actions" style (buttons_compact | buttons | icons). */
|
||||
rowActionStyle: string;
|
||||
}
|
||||
|
||||
const FALLBACK_SETTINGS: SettingsCache = {
|
||||
@@ -131,8 +133,21 @@ const FALLBACK_SETTINGS: SettingsCache = {
|
||||
checklists: false, schedule_time: false, completion_actions: false,
|
||||
},
|
||||
defaultWarningDays: 7,
|
||||
rowActionStyle: "buttons_compact",
|
||||
};
|
||||
|
||||
/** The household's row-action style for surfaces outside the panel (the
|
||||
* Lovelace card follows it unless its own `action_style` is set). */
|
||||
export function getRowActionStyle(hass: HomeAssistant): Promise<string> {
|
||||
return fetchSettingsOnce(hass).then((s) => s.rowActionStyle);
|
||||
}
|
||||
|
||||
/** Test hook: the settings cache is module-wide (one fetch per page), which
|
||||
* makes component tests with DIFFERENT settings share the first answer. */
|
||||
export function __resetSettingsCacheForTests(): void {
|
||||
_cachedSettings = null;
|
||||
}
|
||||
|
||||
let _cachedSettings: Promise<SettingsCache> | null = null;
|
||||
|
||||
function fetchSettingsOnce(hass: HomeAssistant): Promise<SettingsCache> {
|
||||
@@ -140,11 +155,12 @@ function fetchSettingsOnce(hass: HomeAssistant): Promise<SettingsCache> {
|
||||
_cachedSettings = hass.connection
|
||||
.sendMessagePromise<{
|
||||
features?: SettingsCache["features"];
|
||||
general?: { default_warning_days?: number };
|
||||
general?: { default_warning_days?: number; row_action_style?: string };
|
||||
}>({ type: "maintenance_supporter/settings" })
|
||||
.then((r) => ({
|
||||
features: r.features ?? FALLBACK_SETTINGS.features,
|
||||
defaultWarningDays: r.general?.default_warning_days ?? 7,
|
||||
rowActionStyle: r.general?.row_action_style ?? FALLBACK_SETTINGS.rowActionStyle,
|
||||
}))
|
||||
.catch(() => FALLBACK_SETTINGS);
|
||||
return _cachedSettings;
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Název",
|
||||
"card_show_header": "Zobrazit záhlaví se statistikami",
|
||||
"card_show_actions": "Zobrazit tlačítka akcí",
|
||||
"card_action_style": "Styl tlačítka Dokončit",
|
||||
"card_compact": "Kompaktní režim",
|
||||
"card_max_items": "Max položek (0 = vše)",
|
||||
"card_filter_status": "Filtrovat podle stavu",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Vícestupňové procedury pro dokončení úkolu",
|
||||
"settings_general": "Obecné",
|
||||
"settings_default_warning": "Výchozí dny upozornění",
|
||||
"settings_consumable_threshold": "Práh „spotřební materiál nízký“ (%)",
|
||||
"settings_battery_low_percent": "Práh „baterie slabá“ (%)",
|
||||
"settings_thresholds_hint": "Výchozí hodnoty pro nová Navrhovaná nastavení (zbývající procenta) a pro baterie flotily bez vlastního prahu Battery Notes. Stávající úkoly si ponechají svou hodnotu.",
|
||||
"bn_summary": "{name}: {pct} % pro {n} baterií",
|
||||
"bn_floor_decides": "Tvůj práh {floor} % rozhoduje pro všechny; u každé baterie platí vyšší z obou prahů.",
|
||||
"bn_above_floor": "To je nad tvým prahem {floor} %, takže o všech poznamenaných bateriích rozhoduje {name}.",
|
||||
"bn_overrides": "{n} zařízení s vlastním prahem:",
|
||||
"bn_more": "+ {n} dalších",
|
||||
"settings_row_actions": "Akce v řádcích úkolů",
|
||||
"row_actions_buttons_compact": "Tlačítka (na telefonu jen ikony)",
|
||||
"row_actions_buttons": "Tlačítka s textem",
|
||||
"row_actions_icons": "Ikony (klasické)",
|
||||
"row_actions_follow": "Podle nastavení domácnosti",
|
||||
"settings_panel_enabled": "Boční panel",
|
||||
"settings_panel_title": "Název panelu",
|
||||
"settings_notifications": "Oznámení",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Flotila baterií nastavena — jeden úkol sleduje všechny.",
|
||||
"update_banner": "Na serveru je novější verze Maintenance Supporter — načtěte znovu pro aktualizaci panelu.",
|
||||
"update_reload": "Načíst znovu",
|
||||
"row_actions_banner": "Dokončit a Přeskočit jsou v řádcích úkolů nyní tlačítka. Dáváte přednost starým ikonám?",
|
||||
"row_actions_keep": "Ponechat tlačítka",
|
||||
"row_actions_back": "Zpět na ikony",
|
||||
"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ů",
|
||||
"dismiss": "Skrýt",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Titel",
|
||||
"card_show_header": "Vis overskrift med statistik",
|
||||
"card_show_actions": "Vis handlingsknapper",
|
||||
"card_action_style": "Stil for Fuldfør-knappen",
|
||||
"card_compact": "Kompakt tilstand",
|
||||
"card_max_items": "Maks. elementer (0 = alle)",
|
||||
"card_filter_status": "Filtrer efter status",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Procedurer i flere trin til fuldførelse af opgaver",
|
||||
"settings_general": "Generelt",
|
||||
"settings_default_warning": "Standard advarselsdage",
|
||||
"settings_consumable_threshold": "Tærskel „forbrugsvare lav“ (%)",
|
||||
"settings_battery_low_percent": "Tærskel „batteri lavt“ (%)",
|
||||
"settings_thresholds_hint": "Standardværdier for nye Foreslåede opsætninger (resterende procent) og for flådebatterier uden egen Battery Notes-tærskel. Eksisterende opgaver beholder deres værdi.",
|
||||
"bn_summary": "{name}: {pct} % for {n} batterier",
|
||||
"bn_floor_decides": "Din tærskel på {floor} % afgør for alle; pr. batteri gælder den højeste af de to tærskler.",
|
||||
"bn_above_floor": "Det er over din tærskel på {floor} %, så {name} afgør for alle noterede batterier.",
|
||||
"bn_overrides": "{n} enheder med egen tærskel:",
|
||||
"bn_more": "+ {n} mere",
|
||||
"settings_row_actions": "Handlinger i opgaverækker",
|
||||
"row_actions_buttons_compact": "Knapper (kun ikoner på telefonen)",
|
||||
"row_actions_buttons": "Knapper med tekst",
|
||||
"row_actions_icons": "Ikoner (klassisk)",
|
||||
"row_actions_follow": "Følg husstandens indstilling",
|
||||
"settings_panel_enabled": "Sidepanel",
|
||||
"settings_panel_title": "Sidepanelets titel",
|
||||
"settings_notifications": "Notifikationer",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Batteriflåde opsat — én opgave følger alle batterier.",
|
||||
"update_banner": "En nyere version af Maintenance Supporter er på serveren — genindlæs for at opdatere panelet.",
|
||||
"update_reload": "Genindlæs",
|
||||
"row_actions_banner": "Fuldfør og Spring over er nu knapper i opgaverækkerne. Foretrækker du de gamle ikoner?",
|
||||
"row_actions_keep": "Behold knapper",
|
||||
"row_actions_back": "Tilbage til ikoner",
|
||||
"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",
|
||||
"dismiss": "Afvis",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Titel",
|
||||
"card_show_header": "Kopfzeile mit Statistiken anzeigen",
|
||||
"card_show_actions": "Aktionsbuttons anzeigen",
|
||||
"card_action_style": "Stil des Erledigt-Buttons",
|
||||
"card_compact": "Kompaktmodus",
|
||||
"card_max_items": "Max. Einträge (0 = alle)",
|
||||
"card_filter_status": "Nach Status filtern",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Mehrstufige Verfahren zur Aufgabenerlediung",
|
||||
"settings_general": "Allgemein",
|
||||
"settings_default_warning": "Standard-Warntage",
|
||||
"settings_consumable_threshold": "Schwelle „Verbrauchsmaterial niedrig“ (%)",
|
||||
"settings_battery_low_percent": "Schwelle „Batterie niedrig“ (%)",
|
||||
"settings_thresholds_hint": "Vorgaben für neue Vorgeschlagene Einrichtungen (Prozent-Restwert) und für Flotten-Batterien ohne eigene Battery-Notes-Schwelle. Bestehende Aufgaben behalten ihren Wert.",
|
||||
"bn_summary": "{name}: {pct} % für {n} Batterien",
|
||||
"bn_floor_decides": "Deine {floor}-%-Schwelle entscheidet für alle; pro Batterie zählt die höhere der beiden Schwellen.",
|
||||
"bn_above_floor": "Das liegt über deiner {floor}-%-Schwelle — für alle notierten Batterien entscheidet {name}.",
|
||||
"bn_overrides": "{n} Geräte mit eigener Schwelle:",
|
||||
"bn_more": "+ {n} weitere",
|
||||
"settings_row_actions": "Aktionen in Aufgabenzeilen",
|
||||
"row_actions_buttons_compact": "Buttons (auf dem Handy nur Symbole)",
|
||||
"row_actions_buttons": "Buttons mit Text",
|
||||
"row_actions_icons": "Symbole (klassisch)",
|
||||
"row_actions_follow": "Wie in den Einstellungen",
|
||||
"settings_panel_enabled": "Seitenleisten-Panel",
|
||||
"settings_panel_title": "Panel-Titel",
|
||||
"settings_notifications": "Benachrichtigungen",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Batterie-Flotte eingerichtet — ein Task überwacht alle Batterien.",
|
||||
"update_banner": "Auf dem Server läuft eine neuere Version von Maintenance Supporter — neu laden, um das Panel zu aktualisieren.",
|
||||
"update_reload": "Neu laden",
|
||||
"row_actions_banner": "Erledigt und Überspringen sind in den Aufgabenzeilen jetzt Buttons. Lieber die alten Symbole?",
|
||||
"row_actions_keep": "Buttons behalten",
|
||||
"row_actions_back": "Zurück zu Symbolen",
|
||||
"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",
|
||||
"dismiss": "Ausblenden",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Title",
|
||||
"card_show_header": "Show header with statistics",
|
||||
"card_show_actions": "Show action buttons",
|
||||
"card_action_style": "Complete button style",
|
||||
"card_compact": "Compact mode",
|
||||
"card_max_items": "Max items (0 = all)",
|
||||
"card_filter_status": "Filter by status",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Multi-step procedures for task completion",
|
||||
"settings_general": "General",
|
||||
"settings_default_warning": "Default warning days",
|
||||
"settings_consumable_threshold": "Consumable low threshold (%)",
|
||||
"settings_battery_low_percent": "Battery low threshold (%)",
|
||||
"settings_thresholds_hint": "Defaults for new Suggested setups (percent-remaining consumables) and for fleet batteries without their own Battery Notes threshold. Existing tasks keep their value.",
|
||||
"bn_summary": "{name}: {pct} % for {n} batteries",
|
||||
"bn_floor_decides": "Your {floor} % floor decides for all of them; the higher of the two thresholds counts per battery.",
|
||||
"bn_above_floor": "That is above your {floor} % floor, so {name} decides for all noted batteries.",
|
||||
"bn_overrides": "{n} devices with their own threshold:",
|
||||
"bn_more": "+ {n} more",
|
||||
"settings_row_actions": "Task row actions",
|
||||
"row_actions_buttons_compact": "Buttons (icons only on phones)",
|
||||
"row_actions_buttons": "Buttons with text",
|
||||
"row_actions_icons": "Icons (classic)",
|
||||
"row_actions_follow": "Follow the household setting",
|
||||
"settings_panel_enabled": "Sidebar panel",
|
||||
"settings_panel_title": "Sidebar panel title",
|
||||
"settings_notifications": "Notifications",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Battery fleet set up — one task tracks all your batteries.",
|
||||
"update_banner": "A newer version of Maintenance Supporter is on the server — reload to update the panel.",
|
||||
"update_reload": "Reload",
|
||||
"row_actions_banner": "Complete and Skip in task rows are now buttons. Prefer the old icons?",
|
||||
"row_actions_keep": "Keep buttons",
|
||||
"row_actions_back": "Back to icons",
|
||||
"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",
|
||||
"dismiss": "Dismiss",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Título",
|
||||
"card_show_header": "Mostrar encabezado con estadísticas",
|
||||
"card_show_actions": "Mostrar botones de acción",
|
||||
"card_action_style": "Estilo del botón Completar",
|
||||
"card_compact": "Modo compacto",
|
||||
"card_max_items": "Máx. elementos (0 = todos)",
|
||||
"card_filter_status": "Filtrar por estado",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Procedimientos de varios pasos para completar tareas",
|
||||
"settings_general": "General",
|
||||
"settings_default_warning": "Días de aviso predeterminados",
|
||||
"settings_consumable_threshold": "Umbral „consumible bajo“ (%)",
|
||||
"settings_battery_low_percent": "Umbral „pila baja“ (%)",
|
||||
"settings_thresholds_hint": "Valores predeterminados para nuevas Configuraciones sugeridas (porcentaje restante) y para pilas de la flota sin umbral propio de Battery Notes. Las tareas existentes conservan su valor.",
|
||||
"bn_summary": "{name}: {pct} % para {n} pilas",
|
||||
"bn_floor_decides": "Tu umbral del {floor} % decide para todas; por pila cuenta el mayor de los dos umbrales.",
|
||||
"bn_above_floor": "Está por encima de tu umbral del {floor} %, así que {name} decide para todas las pilas anotadas.",
|
||||
"bn_overrides": "{n} dispositivos con umbral propio:",
|
||||
"bn_more": "+ {n} más",
|
||||
"settings_row_actions": "Acciones en las filas de tareas",
|
||||
"row_actions_buttons_compact": "Botones (solo iconos en el móvil)",
|
||||
"row_actions_buttons": "Botones con texto",
|
||||
"row_actions_icons": "Iconos (clásico)",
|
||||
"row_actions_follow": "Seguir el ajuste del hogar",
|
||||
"settings_panel_enabled": "Panel lateral",
|
||||
"settings_panel_title": "Título del panel lateral",
|
||||
"settings_notifications": "Notificaciones",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Flota de baterías configurada — una tarea controla todas.",
|
||||
"update_banner": "Hay una versión más reciente de Maintenance Supporter en el servidor — recarga para actualizar el panel.",
|
||||
"update_reload": "Recargar",
|
||||
"row_actions_banner": "Completar y Omitir ahora son botones en las filas de tareas. ¿Prefieres los iconos antiguos?",
|
||||
"row_actions_keep": "Mantener botones",
|
||||
"row_actions_back": "Volver a los iconos",
|
||||
"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",
|
||||
"dismiss": "Descartar",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Otsikko",
|
||||
"card_show_header": "Näytä otsikko tilastoineen",
|
||||
"card_show_actions": "Näytä toimintopainikkeet",
|
||||
"card_action_style": "Valmis-painikkeen tyyli",
|
||||
"card_compact": "Tiivis tila",
|
||||
"card_max_items": "Enimmäismäärä (0 = kaikki)",
|
||||
"card_filter_status": "Suodata tilan mukaan",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Monivaiheiset menettelyt tehtävän suorittamiseen",
|
||||
"settings_general": "Yleiset",
|
||||
"settings_default_warning": "Oletusvaroituspäivät",
|
||||
"settings_consumable_threshold": "Kynnys „kulutustarvike vähissä“ (%)",
|
||||
"settings_battery_low_percent": "Kynnys „paristo vähissä“ (%)",
|
||||
"settings_thresholds_hint": "Oletukset uusille Ehdotetuille asetuksille (jäljellä oleva prosentti) ja paristokannan paristoille ilman omaa Battery Notes -kynnystä. Olemassa olevat tehtävät säilyttävät arvonsa.",
|
||||
"bn_summary": "{name}: {pct} % {n} paristolle",
|
||||
"bn_floor_decides": "Sinun {floor} %:n kynnyksesi ratkaisee kaikille; paristoa kohden pätee korkeampi kahdesta kynnyksestä.",
|
||||
"bn_above_floor": "Se on sinun {floor} %:n kynnyksesi yläpuolella, joten {name} ratkaisee kaikille kirjatuille paristoille.",
|
||||
"bn_overrides": "{n} laitetta, joilla on oma kynnys:",
|
||||
"bn_more": "+ {n} lisää",
|
||||
"settings_row_actions": "Tehtävärivien toiminnot",
|
||||
"row_actions_buttons_compact": "Painikkeet (puhelimessa vain kuvakkeet)",
|
||||
"row_actions_buttons": "Painikkeet tekstillä",
|
||||
"row_actions_icons": "Kuvakkeet (perinteinen)",
|
||||
"row_actions_follow": "Kotitalouden asetuksen mukaan",
|
||||
"settings_panel_enabled": "Sivupalkin paneeli",
|
||||
"settings_panel_title": "Sivupalkin paneelin otsikko",
|
||||
"settings_notifications": "Ilmoitukset",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Paristokanta määritetty — yksi tehtävä seuraa kaikkia.",
|
||||
"update_banner": "Palvelimella on uudempi Maintenance Supporter -versio — lataa uudelleen päivittääksesi paneelin.",
|
||||
"update_reload": "Lataa uudelleen",
|
||||
"row_actions_banner": "Valmis ja Ohita ovat tehtäväriveillä nyt painikkeita. Haluatko mieluummin vanhat kuvakkeet?",
|
||||
"row_actions_keep": "Pidä painikkeet",
|
||||
"row_actions_back": "Takaisin kuvakkeisiin",
|
||||
"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",
|
||||
"dismiss": "Hylkää",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Titre",
|
||||
"card_show_header": "Afficher l'en-tête avec statistiques",
|
||||
"card_show_actions": "Afficher les boutons d'action",
|
||||
"card_action_style": "Style du bouton Terminer",
|
||||
"card_compact": "Mode compact",
|
||||
"card_max_items": "Nombre max (0 = tous)",
|
||||
"card_filter_status": "Filtrer par statut",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Procédures multi-étapes pour la réalisation des tâches",
|
||||
"settings_general": "Général",
|
||||
"settings_default_warning": "Jours d'avertissement par défaut",
|
||||
"settings_consumable_threshold": "Seuil « consommable bas » (%)",
|
||||
"settings_battery_low_percent": "Seuil « pile faible » (%)",
|
||||
"settings_thresholds_hint": "Valeurs par défaut pour les nouvelles Configurations suggérées (pourcentage restant) et pour les piles de la flotte sans seuil Battery Notes propre. Les tâches existantes gardent leur valeur.",
|
||||
"bn_summary": "{name} : {pct} % pour {n} piles",
|
||||
"bn_floor_decides": "Votre seuil de {floor} % décide pour toutes ; par pile, c'est le plus élevé des deux seuils qui compte.",
|
||||
"bn_above_floor": "C'est au-dessus de votre seuil de {floor} % : {name} décide donc pour toutes les piles notées.",
|
||||
"bn_overrides": "{n} appareils avec leur propre seuil :",
|
||||
"bn_more": "+ {n} autres",
|
||||
"settings_row_actions": "Actions des lignes de tâches",
|
||||
"row_actions_buttons_compact": "Boutons (icônes seules sur téléphone)",
|
||||
"row_actions_buttons": "Boutons avec texte",
|
||||
"row_actions_icons": "Icônes (classique)",
|
||||
"row_actions_follow": "Suivre le réglage du foyer",
|
||||
"settings_panel_enabled": "Panneau latéral",
|
||||
"settings_panel_title": "Titre du panneau latéral",
|
||||
"settings_notifications": "Notifications",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Parc de piles configuré — une tâche suit toutes vos piles.",
|
||||
"update_banner": "Une version plus récente de Maintenance Supporter est sur le serveur — rechargez pour mettre à jour le panneau.",
|
||||
"update_reload": "Recharger",
|
||||
"row_actions_banner": "Terminer et Ignorer sont désormais des boutons dans les lignes de tâches. Vous préférez les anciennes icônes ?",
|
||||
"row_actions_keep": "Garder les boutons",
|
||||
"row_actions_back": "Revenir aux icônes",
|
||||
"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",
|
||||
"dismiss": "Ignorer",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "शीर्षक",
|
||||
"card_show_header": "सांख्यिकी के साथ हेडर दिखाएँ",
|
||||
"card_show_actions": "क्रिया बटन दिखाएँ",
|
||||
"card_action_style": "पूर्ण बटन की शैली",
|
||||
"card_compact": "संक्षिप्त मोड",
|
||||
"card_max_items": "अधिकतम आइटम (0 = सभी)",
|
||||
"card_filter_status": "स्थिति के अनुसार फ़िल्टर करें",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "कार्य पूर्णता के लिए बहु-चरणीय प्रक्रियाएँ",
|
||||
"settings_general": "सामान्य",
|
||||
"settings_default_warning": "डिफ़ॉल्ट चेतावनी दिन",
|
||||
"settings_consumable_threshold": "उपभोग्य „कम“ सीमा (%)",
|
||||
"settings_battery_low_percent": "बैटरी „कम“ सीमा (%)",
|
||||
"settings_thresholds_hint": "नए सुझाए गए सेटअप (शेष प्रतिशत) और अपनी Battery Notes सीमा न रखने वाली बेड़े की बैटरियों के लिए डिफ़ॉल्ट। मौजूदा कार्य अपना मान रखते हैं।",
|
||||
"bn_summary": "{name}: {n} बैटरियों के लिए {pct} %",
|
||||
"bn_floor_decides": "आपकी {floor} % सीमा सभी के लिए निर्णायक है; प्रत्येक बैटरी के लिए दोनों में से ऊँची सीमा मान्य है।",
|
||||
"bn_above_floor": "यह आपकी {floor} % सीमा से ऊपर है, इसलिए सभी नोट की गई बैटरियों के लिए {name} निर्णायक है।",
|
||||
"bn_overrides": "{n} डिवाइस अपनी सीमा के साथ:",
|
||||
"bn_more": "+ {n} और",
|
||||
"settings_row_actions": "कार्य पंक्ति क्रियाएँ",
|
||||
"row_actions_buttons_compact": "बटन (फ़ोन पर केवल आइकन)",
|
||||
"row_actions_buttons": "टेक्स्ट वाले बटन",
|
||||
"row_actions_icons": "आइकन (क्लासिक)",
|
||||
"row_actions_follow": "घर की सेटिंग के अनुसार",
|
||||
"settings_panel_enabled": "साइडबार पैनल",
|
||||
"settings_panel_title": "साइडबार पैनल शीर्षक",
|
||||
"settings_notifications": "सूचनाएँ",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "बैटरी फ्लीट सेट — एक कार्य सभी बैटरियों को ट्रैक करता है।",
|
||||
"update_banner": "सर्वर पर Maintenance Supporter का नया संस्करण है — पैनल अपडेट करने के लिए पुनः लोड करें।",
|
||||
"update_reload": "पुनः लोड करें",
|
||||
"row_actions_banner": "कार्य पंक्तियों में पूर्ण और छोड़ें अब बटन हैं। पुराने आइकन पसंद हैं?",
|
||||
"row_actions_keep": "बटन रखें",
|
||||
"row_actions_back": "आइकन पर वापस जाएँ",
|
||||
"battery_fleet_forecast_overdue": "अनुमानित तिथि बीत गई — बैटरी अब भी अच्छी स्थिति बता रही है। यदि आपने इसे बदला है, तो बदलाव दर्ज करें; अन्यथा पूर्वानुमान गलत था।",
|
||||
"cost_from_parts": "पुर्ज़ों से ≈ {amount} लें",
|
||||
"dismiss": "हटाएँ",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Cím",
|
||||
"card_show_header": "Fejléc megjelenítése statisztikákkal",
|
||||
"card_show_actions": "Műveletgombok megjelenítése",
|
||||
"card_action_style": "A Kész gomb stílusa",
|
||||
"card_compact": "Kompakt mód",
|
||||
"card_max_items": "Max. elemszám (0 = mind)",
|
||||
"card_filter_status": "Szűrés állapot szerint",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Többlépéses eljárások a feladatok elvégzéséhez",
|
||||
"settings_general": "Általános",
|
||||
"settings_default_warning": "Alapértelmezett figyelmeztetési napok",
|
||||
"settings_consumable_threshold": "„Fogyóeszköz alacsony” küszöb (%)",
|
||||
"settings_battery_low_percent": "„Alacsony akkumulátor” küszöb (%)",
|
||||
"settings_thresholds_hint": "Alapértékek az új Javasolt beállításokhoz (százalékos maradék) és a saját Battery Notes-küszöb nélküli flottaelemekhez. A meglévő feladatok megtartják az értéküket.",
|
||||
"bn_summary": "{name}: {pct} % {n} elemhez",
|
||||
"bn_floor_decides": "A te {floor} %-os küszöböd dönt mindegyiknél; elemenként a két küszöb közül a magasabb számít.",
|
||||
"bn_above_floor": "Ez a te {floor} %-os küszöböd felett van, így minden feljegyzett elemnél a {name} dönt.",
|
||||
"bn_overrides": "{n} eszköz saját küszöbbel:",
|
||||
"bn_more": "+ még {n}",
|
||||
"settings_row_actions": "Műveletek a feladatsorokban",
|
||||
"row_actions_buttons_compact": "Gombok (telefonon csak ikonok)",
|
||||
"row_actions_buttons": "Gombok szöveggel",
|
||||
"row_actions_icons": "Ikonok (klasszikus)",
|
||||
"row_actions_follow": "A háztartás beállítása szerint",
|
||||
"settings_panel_enabled": "Oldalsáv-panel",
|
||||
"settings_panel_title": "Oldalsáv-panel címe",
|
||||
"settings_notifications": "Értesítések",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Elemflotta beállítva — egyetlen feladat követi az összes elemet.",
|
||||
"update_banner": "A Maintenance Supporter újabb verziója érhető el a szerveren — töltse újra az oldalt a panel frissítéséhez.",
|
||||
"update_reload": "Újratöltés",
|
||||
"row_actions_banner": "A Kész és a Kihagyás a feladatsorokban mostantól gombok. Inkább a régi ikonokat szeretné?",
|
||||
"row_actions_keep": "Gombok megtartása",
|
||||
"row_actions_back": "Vissza az ikonokhoz",
|
||||
"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",
|
||||
"dismiss": "Elrejtés",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Titolo",
|
||||
"card_show_header": "Mostra intestazione con statistiche",
|
||||
"card_show_actions": "Mostra pulsanti azione",
|
||||
"card_action_style": "Stile del pulsante Completa",
|
||||
"card_compact": "Modalità compatta",
|
||||
"card_max_items": "Max elementi (0 = tutti)",
|
||||
"card_filter_status": "Filtra per stato",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Procedure multi-fase per il completamento delle attività",
|
||||
"settings_general": "Generale",
|
||||
"settings_default_warning": "Giorni di avviso predefiniti",
|
||||
"settings_consumable_threshold": "Soglia „consumabile basso“ (%)",
|
||||
"settings_battery_low_percent": "Soglia „batteria scarica“ (%)",
|
||||
"settings_thresholds_hint": "Valori predefiniti per le nuove Configurazioni suggerite (percentuale residua) e per le batterie della flotta senza soglia Battery Notes propria. Le attività esistenti mantengono il loro valore.",
|
||||
"bn_summary": "{name}: {pct} % per {n} batterie",
|
||||
"bn_floor_decides": "La tua soglia del {floor} % decide per tutte; per ogni batteria conta la più alta delle due soglie.",
|
||||
"bn_above_floor": "È sopra la tua soglia del {floor} %, quindi {name} decide per tutte le batterie annotate.",
|
||||
"bn_overrides": "{n} dispositivi con soglia propria:",
|
||||
"bn_more": "+ altri {n}",
|
||||
"settings_row_actions": "Azioni nelle righe delle attività",
|
||||
"row_actions_buttons_compact": "Pulsanti (solo icone sul telefono)",
|
||||
"row_actions_buttons": "Pulsanti con testo",
|
||||
"row_actions_icons": "Icone (classico)",
|
||||
"row_actions_follow": "Segui l'impostazione della casa",
|
||||
"settings_panel_enabled": "Pannello laterale",
|
||||
"settings_panel_title": "Titolo pannello laterale",
|
||||
"settings_notifications": "Notifiche",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Parco batterie configurato — un'attività monitora tutte.",
|
||||
"update_banner": "Sul server è presente una versione più recente di Maintenance Supporter — ricarica per aggiornare il pannello.",
|
||||
"update_reload": "Ricarica",
|
||||
"row_actions_banner": "Completa e Salta nelle righe delle attività ora sono pulsanti. Preferisci le vecchie icone?",
|
||||
"row_actions_keep": "Mantieni i pulsanti",
|
||||
"row_actions_back": "Torna alle icone",
|
||||
"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",
|
||||
"dismiss": "Ignora",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "タイトル",
|
||||
"card_show_header": "統計付きヘッダーを表示",
|
||||
"card_show_actions": "操作ボタンを表示",
|
||||
"card_action_style": "完了ボタンのスタイル",
|
||||
"card_compact": "コンパクトモード",
|
||||
"card_max_items": "最大表示件数(0=すべて)",
|
||||
"card_filter_status": "状態で絞り込み",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "タスク完了のための複数手順の手続き",
|
||||
"settings_general": "一般",
|
||||
"settings_default_warning": "既定の警告日数",
|
||||
"settings_consumable_threshold": "消耗品「残量少」しきい値(%)",
|
||||
"settings_battery_low_percent": "電池「残量少」しきい値(%)",
|
||||
"settings_thresholds_hint": "新しい「推奨セットアップ」(残量パーセント)と、独自の Battery Notes しきい値を持たないバッテリー一覧の電池に適用される既定値です。既存のタスクは値を保持します。",
|
||||
"bn_summary": "{name}:{n} 個の電池に {pct} %",
|
||||
"bn_floor_decides": "あなたの {floor} % のしきい値がすべてに適用されます。電池ごとに高い方のしきい値が有効です。",
|
||||
"bn_above_floor": "これはあなたの {floor} % のしきい値を上回るため、記録済みのすべての電池は {name} が決定します。",
|
||||
"bn_overrides": "独自のしきい値を持つデバイス {n} 台:",
|
||||
"bn_more": "+ 他 {n} 件",
|
||||
"settings_row_actions": "タスク行の操作",
|
||||
"row_actions_buttons_compact": "ボタン(スマートフォンではアイコンのみ)",
|
||||
"row_actions_buttons": "テキスト付きボタン",
|
||||
"row_actions_icons": "アイコン(従来)",
|
||||
"row_actions_follow": "全体設定に従う",
|
||||
"settings_panel_enabled": "サイドバーパネル",
|
||||
"settings_panel_title": "サイドバーパネルのタイトル",
|
||||
"settings_notifications": "通知",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "電池フリートを設定 — 1つのタスクで全電池を管理。",
|
||||
"update_banner": "サーバーに新しいバージョンの Maintenance Supporter があります — 再読み込みしてパネルを更新してください。",
|
||||
"update_reload": "再読み込み",
|
||||
"row_actions_banner": "タスク行の「完了」と「スキップ」がボタンになりました。以前のアイコンに戻しますか?",
|
||||
"row_actions_keep": "ボタンのままにする",
|
||||
"row_actions_back": "アイコンに戻す",
|
||||
"battery_fleet_forecast_overdue": "予測日を過ぎましたが、電池はまだ正常と報告しています。交換済みなら交換を記録してください。そうでなければ予測が外れています。",
|
||||
"cost_from_parts": "部品から ≈ {amount} を適用",
|
||||
"dismiss": "閉じる",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "제목",
|
||||
"card_show_header": "통계 헤더 표시",
|
||||
"card_show_actions": "동작 버튼 표시",
|
||||
"card_action_style": "완료 버튼 스타일",
|
||||
"card_compact": "컴팩트 모드",
|
||||
"card_max_items": "최대 항목 수 (0 = 전체)",
|
||||
"card_filter_status": "상태로 필터",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "작업 완료를 위한 다단계 절차",
|
||||
"settings_general": "일반",
|
||||
"settings_default_warning": "기본 경고 일수",
|
||||
"settings_consumable_threshold": "소모품 „부족“ 임계값 (%)",
|
||||
"settings_battery_low_percent": "배터리 „부족“ 임계값 (%)",
|
||||
"settings_thresholds_hint": "새 추천 설정(남은 비율)과 자체 Battery Notes 임계값이 없는 배터리 목록 배터리의 기본값입니다. 기존 작업은 값을 유지합니다.",
|
||||
"bn_summary": "{name}: 배터리 {n}개에 {pct} %",
|
||||
"bn_floor_decides": "당신의 {floor} % 임계값이 모두에 적용됩니다. 배터리마다 두 임계값 중 높은 쪽이 적용됩니다.",
|
||||
"bn_above_floor": "이는 당신의 {floor} % 임계값보다 높으므로, 기록된 모든 배터리는 {name}이(가) 결정합니다.",
|
||||
"bn_overrides": "자체 임계값이 있는 기기 {n}개:",
|
||||
"bn_more": "+ {n}개 더",
|
||||
"settings_row_actions": "작업 행 동작",
|
||||
"row_actions_buttons_compact": "버튼 (휴대폰에서는 아이콘만)",
|
||||
"row_actions_buttons": "텍스트가 있는 버튼",
|
||||
"row_actions_icons": "아이콘 (기본)",
|
||||
"row_actions_follow": "가정 설정을 따름",
|
||||
"settings_panel_enabled": "사이드바 패널",
|
||||
"settings_panel_title": "사이드바 패널 제목",
|
||||
"settings_notifications": "알림",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "배터리 플릿이 설정되었습니다 — 하나의 작업이 모든 배터리를 추적합니다.",
|
||||
"update_banner": "서버에 Maintenance Supporter의 새 버전이 있습니다 — 패널을 업데이트하려면 새로 고침하세요.",
|
||||
"update_reload": "새로 고침",
|
||||
"row_actions_banner": "작업 행의 완료와 건너뛰기가 이제 버튼으로 표시됩니다. 이전 아이콘이 더 좋으신가요?",
|
||||
"row_actions_keep": "버튼 유지",
|
||||
"row_actions_back": "아이콘으로 되돌리기",
|
||||
"battery_fleet_forecast_overdue": "예측 날짜가 지났지만 배터리는 여전히 정상으로 보고됩니다. 교체했다면 교체를 기록하세요. 아니라면 예측이 빗나간 것입니다.",
|
||||
"cost_from_parts": "부품에서 ≈ {amount} 적용",
|
||||
"dismiss": "닫기",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Tittel",
|
||||
"card_show_header": "Vis topptekst med statistikk",
|
||||
"card_show_actions": "Vis handlingsknapper",
|
||||
"card_action_style": "Stil på Fullfør-knappen",
|
||||
"card_compact": "Kompakt modus",
|
||||
"card_max_items": "Maks elementer (0 = alle)",
|
||||
"card_filter_status": "Filtrer etter status",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Flertrinnsprosedyrer for fullføring av oppgaver",
|
||||
"settings_general": "Generelt",
|
||||
"settings_default_warning": "Standard varslingsdager",
|
||||
"settings_consumable_threshold": "Terskel „forbruksvare lav“ (%)",
|
||||
"settings_battery_low_percent": "Terskel „batteri lavt“ (%)",
|
||||
"settings_thresholds_hint": "Standardverdier for nye Foreslåtte oppsett (gjenværende prosent) og for flåtebatterier uten egen Battery Notes-terskel. Eksisterende oppgaver beholder verdien sin.",
|
||||
"bn_summary": "{name}: {pct} % for {n} batterier",
|
||||
"bn_floor_decides": "Din terskel på {floor} % avgjør for alle; per batteri gjelder den høyeste av de to tersklene.",
|
||||
"bn_above_floor": "Det er over din terskel på {floor} %, så {name} avgjør for alle noterte batterier.",
|
||||
"bn_overrides": "{n} enheter med egen terskel:",
|
||||
"bn_more": "+ {n} til",
|
||||
"settings_row_actions": "Handlinger i oppgaverader",
|
||||
"row_actions_buttons_compact": "Knapper (bare ikoner på mobil)",
|
||||
"row_actions_buttons": "Knapper med tekst",
|
||||
"row_actions_icons": "Ikoner (klassisk)",
|
||||
"row_actions_follow": "Følg husstandens innstilling",
|
||||
"settings_panel_enabled": "Sidepanel",
|
||||
"settings_panel_title": "Tittel på sidepanel",
|
||||
"settings_notifications": "Varsler",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Batteriflåte satt opp — én oppgave følger alle batteriene.",
|
||||
"update_banner": "En nyere versjon av Maintenance Supporter er på serveren — last inn på nytt for å oppdatere panelet.",
|
||||
"update_reload": "Last inn på nytt",
|
||||
"row_actions_banner": "Fullfør og Hopp over er nå knapper i oppgaveradene. Foretrekker du de gamle ikonene?",
|
||||
"row_actions_keep": "Behold knapper",
|
||||
"row_actions_back": "Tilbake til ikoner",
|
||||
"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",
|
||||
"dismiss": "Avvis",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Titel",
|
||||
"card_show_header": "Koptekst met statistieken tonen",
|
||||
"card_show_actions": "Actieknoppen tonen",
|
||||
"card_action_style": "Stijl van de Voltooien-knop",
|
||||
"card_compact": "Compacte modus",
|
||||
"card_max_items": "Max items (0 = alle)",
|
||||
"card_filter_status": "Filteren op status",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Meerstaps procedures voor taakvoltooiing",
|
||||
"settings_general": "Algemeen",
|
||||
"settings_default_warning": "Standaard waarschuwingsdagen",
|
||||
"settings_consumable_threshold": "Drempel „verbruiksartikel laag“ (%)",
|
||||
"settings_battery_low_percent": "Drempel „batterij laag“ (%)",
|
||||
"settings_thresholds_hint": "Standaardwaarden voor nieuwe Voorgestelde installaties (resterend percentage) en voor vlootbatterijen zonder eigen Battery Notes-drempel. Bestaande taken behouden hun waarde.",
|
||||
"bn_summary": "{name}: {pct} % voor {n} batterijen",
|
||||
"bn_floor_decides": "Jouw drempel van {floor} % beslist voor allemaal; per batterij telt de hoogste van de twee drempels.",
|
||||
"bn_above_floor": "Dat ligt boven jouw drempel van {floor} %, dus {name} beslist voor alle genoteerde batterijen.",
|
||||
"bn_overrides": "{n} apparaten met een eigen drempel:",
|
||||
"bn_more": "+ {n} meer",
|
||||
"settings_row_actions": "Acties in taakrijen",
|
||||
"row_actions_buttons_compact": "Knoppen (op telefoons alleen pictogrammen)",
|
||||
"row_actions_buttons": "Knoppen met tekst",
|
||||
"row_actions_icons": "Pictogrammen (klassiek)",
|
||||
"row_actions_follow": "Volg de instelling van het huishouden",
|
||||
"settings_panel_enabled": "Zijbalkpaneel",
|
||||
"settings_panel_title": "Titel zijbalkpaneel",
|
||||
"settings_notifications": "Meldingen",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Batterijvloot ingesteld — één taak volgt al je batterijen.",
|
||||
"update_banner": "Er staat een nieuwere versie van Maintenance Supporter op de server — herlaad om het paneel bij te werken.",
|
||||
"update_reload": "Herladen",
|
||||
"row_actions_banner": "Voltooien en Overslaan zijn in taakrijen nu knoppen. Liever de oude pictogrammen?",
|
||||
"row_actions_keep": "Knoppen houden",
|
||||
"row_actions_back": "Terug naar pictogrammen",
|
||||
"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",
|
||||
"dismiss": "Verbergen",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Tytuł",
|
||||
"card_show_header": "Pokaż nagłówek ze statystykami",
|
||||
"card_show_actions": "Pokaż przyciski akcji",
|
||||
"card_action_style": "Styl przycisku Ukończ",
|
||||
"card_compact": "Tryb kompaktowy",
|
||||
"card_max_items": "Maks. elementów (0 = wszystkie)",
|
||||
"card_filter_status": "Filtruj wg statusu",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Wieloetapowe procedury wykonania zadania",
|
||||
"settings_general": "Ogólne",
|
||||
"settings_default_warning": "Domyślne dni ostrzeżenia",
|
||||
"settings_consumable_threshold": "Próg „materiał eksploatacyjny niski” (%)",
|
||||
"settings_battery_low_percent": "Próg „bateria słaba” (%)",
|
||||
"settings_thresholds_hint": "Wartości domyślne dla nowych Sugerowanych konfiguracji (procent pozostały) i dla baterii floty bez własnego progu Battery Notes. Istniejące zadania zachowują swoją wartość.",
|
||||
"bn_summary": "{name}: {pct} % dla {n} baterii",
|
||||
"bn_floor_decides": "Twój próg {floor} % decyduje dla wszystkich; dla każdej baterii liczy się wyższy z dwóch progów.",
|
||||
"bn_above_floor": "To powyżej twojego progu {floor} %, więc o wszystkich odnotowanych bateriach decyduje {name}.",
|
||||
"bn_overrides": "{n} urządzeń z własnym progiem:",
|
||||
"bn_more": "+ {n} więcej",
|
||||
"settings_row_actions": "Akcje w wierszach zadań",
|
||||
"row_actions_buttons_compact": "Przyciski (na telefonie tylko ikony)",
|
||||
"row_actions_buttons": "Przyciski z tekstem",
|
||||
"row_actions_icons": "Ikony (klasyczne)",
|
||||
"row_actions_follow": "Zgodnie z ustawieniem domu",
|
||||
"settings_panel_enabled": "Panel boczny",
|
||||
"settings_panel_title": "Tytuł panelu bocznego",
|
||||
"settings_notifications": "Powiadomienia",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Flota baterii skonfigurowana — jedno zadanie śledzi wszystkie.",
|
||||
"update_banner": "Na serwerze jest nowsza wersja Maintenance Supporter — załaduj ponownie, aby zaktualizować panel.",
|
||||
"update_reload": "Załaduj ponownie",
|
||||
"row_actions_banner": "Ukończ i Pomiń w wierszach zadań są teraz przyciskami. Wolisz stare ikony?",
|
||||
"row_actions_keep": "Zachowaj przyciski",
|
||||
"row_actions_back": "Wróć do ikon",
|
||||
"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",
|
||||
"dismiss": "Odrzuć",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Título",
|
||||
"card_show_header": "Mostrar cabeçalho com estatísticas",
|
||||
"card_show_actions": "Mostrar botões de ação",
|
||||
"card_action_style": "Estilo do botão Concluir",
|
||||
"card_compact": "Modo compacto",
|
||||
"card_max_items": "Máx. de itens (0 = todos)",
|
||||
"card_filter_status": "Filtrar por status",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Procedimentos em várias etapas para concluir tarefas",
|
||||
"settings_general": "Geral",
|
||||
"settings_default_warning": "Dias de aviso padrão",
|
||||
"settings_consumable_threshold": "Limite „consumível baixo“ (%)",
|
||||
"settings_battery_low_percent": "Limite „pilha fraca“ (%)",
|
||||
"settings_thresholds_hint": "Padrões para novas Configurações sugeridas (porcentagem restante) e para pilhas da frota sem limite próprio do Battery Notes. As tarefas existentes mantêm seu valor.",
|
||||
"bn_summary": "{name}: {pct} % para {n} pilhas",
|
||||
"bn_floor_decides": "Seu limite de {floor} % decide para todas; por pilha vale o maior dos dois limites.",
|
||||
"bn_above_floor": "Está acima do seu limite de {floor} %, então o {name} decide para todas as pilhas anotadas.",
|
||||
"bn_overrides": "{n} dispositivos com limite próprio:",
|
||||
"bn_more": "+ {n} mais",
|
||||
"settings_row_actions": "Ações nas linhas de tarefas",
|
||||
"row_actions_buttons_compact": "Botões (só ícones no celular)",
|
||||
"row_actions_buttons": "Botões com texto",
|
||||
"row_actions_icons": "Ícones (clássico)",
|
||||
"row_actions_follow": "Seguir a configuração da casa",
|
||||
"settings_panel_enabled": "Painel na barra lateral",
|
||||
"settings_panel_title": "Título do painel na barra lateral",
|
||||
"settings_notifications": "Notificações",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Frota de baterias configurada — uma única tarefa acompanha todas as suas baterias.",
|
||||
"update_banner": "Há uma versão mais nova do Maintenance Supporter no servidor — recarregue para atualizar o painel.",
|
||||
"update_reload": "Recarregar",
|
||||
"row_actions_banner": "Concluir e Pular agora são botões nas linhas de tarefas. Prefere os ícones antigos?",
|
||||
"row_actions_keep": "Manter botões",
|
||||
"row_actions_back": "Voltar aos ícones",
|
||||
"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",
|
||||
"dismiss": "Dispensar",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Título",
|
||||
"card_show_header": "Mostrar cabeçalho com estatísticas",
|
||||
"card_show_actions": "Mostrar botões de ação",
|
||||
"card_action_style": "Estilo do botão Concluir",
|
||||
"card_compact": "Modo compacto",
|
||||
"card_max_items": "Máx. itens (0 = todos)",
|
||||
"card_filter_status": "Filtrar por estado",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Procedimentos com vários passos para conclusão de tarefas",
|
||||
"settings_general": "Geral",
|
||||
"settings_default_warning": "Dias de aviso predefinidos",
|
||||
"settings_consumable_threshold": "Limiar „consumível baixo“ (%)",
|
||||
"settings_battery_low_percent": "Limiar „pilha fraca“ (%)",
|
||||
"settings_thresholds_hint": "Predefinições para novas Configurações sugeridas (percentagem restante) e para pilhas da frota sem limiar Battery Notes próprio. As tarefas existentes mantêm o seu valor.",
|
||||
"bn_summary": "{name}: {pct} % para {n} pilhas",
|
||||
"bn_floor_decides": "O teu limiar de {floor} % decide para todas; por pilha conta o mais alto dos dois limiares.",
|
||||
"bn_above_floor": "Está acima do teu limiar de {floor} %, por isso o {name} decide para todas as pilhas anotadas.",
|
||||
"bn_overrides": "{n} dispositivos com limiar próprio:",
|
||||
"bn_more": "+ {n} mais",
|
||||
"settings_row_actions": "Ações nas linhas de tarefas",
|
||||
"row_actions_buttons_compact": "Botões (só ícones no telemóvel)",
|
||||
"row_actions_buttons": "Botões com texto",
|
||||
"row_actions_icons": "Ícones (clássico)",
|
||||
"row_actions_follow": "Seguir a definição da casa",
|
||||
"settings_panel_enabled": "Painel lateral",
|
||||
"settings_panel_title": "Título do painel lateral",
|
||||
"settings_notifications": "Notificações",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Frota de baterias configurada — uma tarefa acompanha todas.",
|
||||
"update_banner": "Há uma versão mais recente do Maintenance Supporter no servidor — recarregue para atualizar o painel.",
|
||||
"update_reload": "Recarregar",
|
||||
"row_actions_banner": "Concluir e Ignorar são agora botões nas linhas de tarefas. Prefere os ícones antigos?",
|
||||
"row_actions_keep": "Manter botões",
|
||||
"row_actions_back": "Voltar aos ícones",
|
||||
"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",
|
||||
"dismiss": "Dispensar",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Заголовок",
|
||||
"card_show_header": "Показывать заголовок со статистикой",
|
||||
"card_show_actions": "Показывать кнопки действий",
|
||||
"card_action_style": "Стиль кнопки «Выполнено»",
|
||||
"card_compact": "Компактный режим",
|
||||
"card_max_items": "Макс. элементов (0 = все)",
|
||||
"card_filter_status": "Фильтровать по статусу",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Многошаговые процедуры для выполнения задачи",
|
||||
"settings_general": "Основные",
|
||||
"settings_default_warning": "Дни предупреждения по умолчанию",
|
||||
"settings_consumable_threshold": "Порог «расходник заканчивается» (%)",
|
||||
"settings_battery_low_percent": "Порог «батарея разряжена» (%)",
|
||||
"settings_thresholds_hint": "Значения по умолчанию для новых «Предлагаемых настроек» (остаток в процентах) и для батарей парка без собственного порога Battery Notes. Существующие задачи сохраняют своё значение.",
|
||||
"bn_summary": "{name}: {pct} % для {n} батарей",
|
||||
"bn_floor_decides": "Ваш порог {floor} % действует для всех; для каждой батареи учитывается больший из двух порогов.",
|
||||
"bn_above_floor": "Это выше вашего порога {floor} %, поэтому для всех отмеченных батарей решает {name}.",
|
||||
"bn_overrides": "{n} устройств с собственным порогом:",
|
||||
"bn_more": "+ ещё {n}",
|
||||
"settings_row_actions": "Действия в строках задач",
|
||||
"row_actions_buttons_compact": "Кнопки (на телефоне только значки)",
|
||||
"row_actions_buttons": "Кнопки с текстом",
|
||||
"row_actions_icons": "Значки (классический вид)",
|
||||
"row_actions_follow": "Как в настройках дома",
|
||||
"settings_panel_enabled": "Боковая панель",
|
||||
"settings_panel_title": "Заголовок панели",
|
||||
"settings_notifications": "Уведомления",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Парк батарей настроен — одна задача следит за всеми.",
|
||||
"update_banner": "На сервере более новая версия Maintenance Supporter — перезагрузите, чтобы обновить панель.",
|
||||
"update_reload": "Перезагрузить",
|
||||
"row_actions_banner": "«Выполнено» и «Пропустить» в строках задач теперь кнопки. Предпочитаете старые значки?",
|
||||
"row_actions_keep": "Оставить кнопки",
|
||||
"row_actions_back": "Вернуть значки",
|
||||
"battery_fleet_forecast_overdue": "Прогнозируемая дата прошла — батарея по-прежнему сообщает о хорошем состоянии. Если вы её заменили, зафиксируйте замену; иначе прогноз оказался неверным.",
|
||||
"cost_from_parts": "Взять ≈ {amount} из запчастей",
|
||||
"dismiss": "Скрыть",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Titel",
|
||||
"card_show_header": "Visa rubrik med statistik",
|
||||
"card_show_actions": "Visa åtgärdsknappar",
|
||||
"card_action_style": "Stil på Slutför-knappen",
|
||||
"card_compact": "Kompakt läge",
|
||||
"card_max_items": "Max objekt (0 = alla)",
|
||||
"card_filter_status": "Filtrera efter status",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Flerstegs procedurer för uppgiftens slutförande",
|
||||
"settings_general": "Allmänt",
|
||||
"settings_default_warning": "Standard varningsdagar",
|
||||
"settings_consumable_threshold": "Tröskel „förbrukningsartikel låg“ (%)",
|
||||
"settings_battery_low_percent": "Tröskel „batteri lågt“ (%)",
|
||||
"settings_thresholds_hint": "Standardvärden för nya Föreslagna inställningar (återstående procent) och för flottans batterier utan egen Battery Notes-tröskel. Befintliga uppgifter behåller sitt värde.",
|
||||
"bn_summary": "{name}: {pct} % för {n} batterier",
|
||||
"bn_floor_decides": "Din tröskel på {floor} % avgör för alla; per batteri gäller den högre av de två trösklarna.",
|
||||
"bn_above_floor": "Det är över din tröskel på {floor} %, så {name} avgör för alla noterade batterier.",
|
||||
"bn_overrides": "{n} enheter med egen tröskel:",
|
||||
"bn_more": "+ {n} till",
|
||||
"settings_row_actions": "Åtgärder i uppgiftsrader",
|
||||
"row_actions_buttons_compact": "Knappar (endast ikoner på mobilen)",
|
||||
"row_actions_buttons": "Knappar med text",
|
||||
"row_actions_icons": "Ikoner (klassiskt)",
|
||||
"row_actions_follow": "Följ hushållets inställning",
|
||||
"settings_panel_enabled": "Sidopanel",
|
||||
"settings_panel_title": "Sidopanelens titel",
|
||||
"settings_notifications": "Notifikationer",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Batteriflotta konfigurerad — en uppgift följer alla batterier.",
|
||||
"update_banner": "En nyare version av Maintenance Supporter finns på servern — ladda om för att uppdatera panelen.",
|
||||
"update_reload": "Ladda om",
|
||||
"row_actions_banner": "Slutför och Hoppa över är nu knappar i uppgiftsraderna. Föredrar du de gamla ikonerna?",
|
||||
"row_actions_keep": "Behåll knappar",
|
||||
"row_actions_back": "Tillbaka till ikoner",
|
||||
"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",
|
||||
"dismiss": "Avfärda",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "Başlık",
|
||||
"card_show_header": "İstatistikli başlığı göster",
|
||||
"card_show_actions": "Eylem düğmelerini göster",
|
||||
"card_action_style": "Tamamla düğmesi stili",
|
||||
"card_compact": "Kompakt mod",
|
||||
"card_max_items": "En fazla öğe (0 = tümü)",
|
||||
"card_filter_status": "Duruma göre filtrele",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "Görev tamamlama için çok adımlı prosedürler",
|
||||
"settings_general": "Genel",
|
||||
"settings_default_warning": "Varsayılan uyarı günleri",
|
||||
"settings_consumable_threshold": "„Sarf malzemesi düşük“ eşiği (%)",
|
||||
"settings_battery_low_percent": "„Pil zayıf“ eşiği (%)",
|
||||
"settings_thresholds_hint": "Yeni Önerilen kurulumlar (kalan yüzde) ve kendi Battery Notes eşiği olmayan filo pilleri için varsayılanlar. Mevcut görevler değerlerini korur.",
|
||||
"bn_summary": "{name}: {n} pil için % {pct}",
|
||||
"bn_floor_decides": "Senin % {floor} eşiğin hepsi için belirleyici; her pil için iki eşikten yüksek olanı geçerli.",
|
||||
"bn_above_floor": "Bu, senin % {floor} eşiğinin üzerinde; bu yüzden kayıtlı tüm piller için {name} belirleyici.",
|
||||
"bn_overrides": "Kendi eşiği olan {n} cihaz:",
|
||||
"bn_more": "+ {n} tane daha",
|
||||
"settings_row_actions": "Görev satırı eylemleri",
|
||||
"row_actions_buttons_compact": "Düğmeler (telefonda yalnızca simgeler)",
|
||||
"row_actions_buttons": "Metinli düğmeler",
|
||||
"row_actions_icons": "Simgeler (klasik)",
|
||||
"row_actions_follow": "Ev ayarını izle",
|
||||
"settings_panel_enabled": "Kenar çubuğu paneli",
|
||||
"settings_panel_title": "Kenar çubuğu paneli başlığı",
|
||||
"settings_notifications": "Bildirimler",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Pil filosu kuruldu — tek bir görev tüm pillerinizi takip ediyor.",
|
||||
"update_banner": "Sunucuda Maintenance Supporter'ın daha yeni bir sürümü var — paneli güncellemek için sayfayı yeniden yükleyin.",
|
||||
"update_reload": "Yeniden yükle",
|
||||
"row_actions_banner": "Görev satırlarındaki Tamamla ve Atla artık düğme. Eski simgeleri mi tercih edersiniz?",
|
||||
"row_actions_keep": "Düğmeleri koru",
|
||||
"row_actions_back": "Simgelere geri dön",
|
||||
"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",
|
||||
"dismiss": "Kapat",
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
"card_title": "Заголовок",
|
||||
"card_show_header": "Показувати заголовок зі статистикою",
|
||||
"card_show_actions": "Показувати кнопки дій",
|
||||
"card_action_style": "Стиль кнопки «Виконано»",
|
||||
"card_compact": "Компактний режим",
|
||||
"card_max_items": "Макс. елементів (0 = всі)",
|
||||
"card_filter_status": "Фільтрувати за статусом",
|
||||
@@ -448,6 +449,19 @@
|
||||
"feat_checklists_desc": "Багатокрокові процедури для виконання завдань",
|
||||
"settings_general": "Загальне",
|
||||
"settings_default_warning": "Днів попередження за замовчуванням",
|
||||
"settings_consumable_threshold": "Поріг «витратний матеріал закінчується» (%)",
|
||||
"settings_battery_low_percent": "Поріг «батарея розряджена» (%)",
|
||||
"settings_thresholds_hint": "Значення за замовчуванням для нових «Запропонованих налаштувань» (залишок у відсотках) і для батарей парку без власного порогу Battery Notes. Наявні завдання зберігають своє значення.",
|
||||
"bn_summary": "{name}: {pct} % для {n} батарей",
|
||||
"bn_floor_decides": "Ваш поріг {floor} % діє для всіх; для кожної батареї враховується більший із двох порогів.",
|
||||
"bn_above_floor": "Це вище за ваш поріг {floor} %, тому для всіх занотованих батарей вирішує {name}.",
|
||||
"bn_overrides": "{n} пристроїв із власним порогом:",
|
||||
"bn_more": "+ ще {n}",
|
||||
"settings_row_actions": "Дії в рядках завдань",
|
||||
"row_actions_buttons_compact": "Кнопки (на телефоні лише значки)",
|
||||
"row_actions_buttons": "Кнопки з текстом",
|
||||
"row_actions_icons": "Значки (класичний вигляд)",
|
||||
"row_actions_follow": "Як у налаштуваннях дому",
|
||||
"settings_panel_enabled": "Панель у бічному меню",
|
||||
"settings_panel_title": "Заголовок панелі",
|
||||
"settings_notifications": "Сповіщення",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "Парк батарей налаштовано — одне завдання стежить за всіма.",
|
||||
"update_banner": "На сервері новіша версія Maintenance Supporter — перезавантажте, щоб оновити панель.",
|
||||
"update_reload": "Перезавантажити",
|
||||
"row_actions_banner": "«Виконано» та «Пропустити» в рядках завдань тепер кнопки. Бажаєте старі значки?",
|
||||
"row_actions_keep": "Залишити кнопки",
|
||||
"row_actions_back": "Повернути значки",
|
||||
"battery_fleet_forecast_overdue": "Прогнозована дата минула — батарея й далі повідомляє про добрий стан. Якщо ви її замінили, зафіксуйте заміну; інакше прогноз не справдився.",
|
||||
"cost_from_parts": "Узяти ≈ {amount} із запчастин",
|
||||
"dismiss": "Приховати",
|
||||
|
||||
@@ -376,6 +376,7 @@
|
||||
"card_title": "标题",
|
||||
"card_show_header": "显示统计信息页眉",
|
||||
"card_show_actions": "显示操作按钮",
|
||||
"card_action_style": "“完成”按钮样式",
|
||||
"card_compact": "紧凑模式",
|
||||
"card_max_items": "最大显示项 (0 = 全部)",
|
||||
"card_filter_status": "按状态过滤",
|
||||
@@ -450,6 +451,19 @@
|
||||
"feat_checklists_desc": "为任务完成提供多步骤操作流程",
|
||||
"settings_general": "常规",
|
||||
"settings_default_warning": "默认预警天数",
|
||||
"settings_consumable_threshold": "耗材“不足”阈值(%)",
|
||||
"settings_battery_low_percent": "电池“电量低”阈值(%)",
|
||||
"settings_thresholds_hint": "用于新的“建议设置”(剩余百分比)以及没有自身 Battery Notes 阈值的电池组电池。现有任务保留其值。",
|
||||
"bn_summary": "{name}:{n} 块电池为 {pct}%",
|
||||
"bn_floor_decides": "你的 {floor}% 阈值对所有电池生效;每块电池取两个阈值中较高者。",
|
||||
"bn_above_floor": "这高于你的 {floor}% 阈值,因此所有已记录的电池由 {name} 决定。",
|
||||
"bn_overrides": "{n} 台设备有自己的阈值:",
|
||||
"bn_more": "+ 另外 {n} 个",
|
||||
"settings_row_actions": "任务行操作",
|
||||
"row_actions_buttons_compact": "按钮(手机上仅显示图标)",
|
||||
"row_actions_buttons": "带文字的按钮",
|
||||
"row_actions_icons": "图标(经典)",
|
||||
"row_actions_follow": "跟随全局设置",
|
||||
"settings_panel_enabled": "侧边栏面板",
|
||||
"settings_panel_title": "侧边栏面板标题",
|
||||
"settings_notifications": "通知",
|
||||
@@ -864,6 +878,9 @@
|
||||
"battery_fleet_setup_done": "电池群已设置 — 一个任务跟踪所有电池。",
|
||||
"update_banner": "服务器上有更新版本的 Maintenance Supporter——请重新加载以更新面板。",
|
||||
"update_reload": "重新加载",
|
||||
"row_actions_banner": "任务行中的“完成”和“跳过”现在是按钮。更喜欢旧的图标?",
|
||||
"row_actions_keep": "保留按钮",
|
||||
"row_actions_back": "改回图标",
|
||||
"battery_fleet_forecast_overdue": "预测日期已过——电池仍报告状态良好。如果您已更换电池,请记录更换;否则说明预测有误。",
|
||||
"cost_from_parts": "采用配件合计 ≈ {amount}",
|
||||
"dismiss": "忽略",
|
||||
|
||||
@@ -300,6 +300,21 @@ export class MaintenanceSupporterCardEditor extends LitElement {
|
||||
></ha-switch>
|
||||
</ha-formfield>
|
||||
|
||||
<label class="editor-select">
|
||||
<span>${t("card_action_style", L)}</span>
|
||||
<select
|
||||
.value=${this._config.action_style ?? ""}
|
||||
@change=${(e: Event) => {
|
||||
const v = (e.target as HTMLSelectElement).value;
|
||||
this._valueChanged("action_style", v === "" ? undefined : v);
|
||||
}}
|
||||
>
|
||||
<option value="" ?selected=${!this._config.action_style}>${t("row_actions_follow", L)}</option>
|
||||
<option value="buttons" ?selected=${this._config.action_style === "buttons"}>${t("row_actions_buttons", L)}</option>
|
||||
<option value="icons" ?selected=${this._config.action_style === "icons"}>${t("row_actions_icons", L)}</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<ha-formfield label="${t("responsible_user", L)}">
|
||||
<ha-switch
|
||||
.checked=${this._config.show_assignee !== false}
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
openCreateObjectDialog,
|
||||
openCreateTaskDialog,
|
||||
openTaskQuickActions,
|
||||
getRowActionStyle,
|
||||
} from "./dialog-mount";
|
||||
|
||||
interface CardDoc {
|
||||
@@ -48,6 +49,8 @@ interface FlatTask {
|
||||
export class MaintenanceSupporterCard extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@state() private _config: CardConfig = { type: "custom:maintenance-supporter-card" };
|
||||
/** #145: global "Task row actions" style, resolved once from the settings cache. */
|
||||
@state() private _globalRowStyle = "buttons_compact";
|
||||
@state() private _objects: MaintenanceObjectResponse[] = [];
|
||||
@state() private _stats: StatisticsResponse | null = null;
|
||||
@state() private _unsub: (() => void) | null = null;
|
||||
@@ -158,6 +161,8 @@ export class MaintenanceSupporterCard extends LitElement {
|
||||
}
|
||||
|
||||
private async _loadData(): Promise<void> {
|
||||
// #145: resolve the household's row-action style once (cached settings).
|
||||
void getRowActionStyle(this.hass).then((s) => { this._globalRowStyle = s; }).catch(() => undefined);
|
||||
try {
|
||||
const [objResult, statsResult] = await Promise.all([
|
||||
this.hass.connection.sendMessagePromise({ type: "maintenance_supporter/objects", compact: true }),
|
||||
@@ -400,6 +405,9 @@ export class MaintenanceSupporterCard extends LitElement {
|
||||
const L = this._lang;
|
||||
const title = this._config.title || t("maintenance", L);
|
||||
const showHeader = this._config.show_header !== false;
|
||||
// #145: the card's own action_style wins; otherwise follow the household
|
||||
// setting (any "buttons*" style → labelled HA button, "icons" → icon).
|
||||
const useButtons = (this._config.action_style ?? (this._globalRowStyle === "icons" ? "icons" : "buttons")) === "buttons";
|
||||
const showActions = this._config.show_actions !== false;
|
||||
const compact = this._config.compact || false;
|
||||
const tasks = this._flatTasks;
|
||||
@@ -507,7 +515,38 @@ export class MaintenanceSupporterCard extends LitElement {
|
||||
? "⚡"
|
||||
: "—"}
|
||||
</div>
|
||||
${showActions
|
||||
${showActions && useButtons
|
||||
? html`
|
||||
<ha-button
|
||||
size="small"
|
||||
appearance="accent"
|
||||
variant="success"
|
||||
class="complete-btn-text"
|
||||
title="${t("complete", L)}"
|
||||
@click=${(e: Event) => {
|
||||
e.stopPropagation();
|
||||
const dlg = this.shadowRoot!.querySelector<MaintenanceCompleteDialog>("maintenance-complete-dialog")!;
|
||||
fillAndOpenCompleteDialog(
|
||||
dlg,
|
||||
buildCompleteDialogArgs({
|
||||
entryId: entry_id,
|
||||
taskId: task.id,
|
||||
taskName: task.name,
|
||||
task,
|
||||
objects: this._objects,
|
||||
lang: L,
|
||||
checklist: task.checklist || [],
|
||||
adaptiveEnabled: !!task.adaptive_config?.enabled,
|
||||
currencySymbol: this._stats?.budget?.currency_symbol || "",
|
||||
}),
|
||||
L,
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ha-icon slot="start" icon="mdi:check"></ha-icon>${t("complete", L)}
|
||||
</ha-button>
|
||||
`
|
||||
: showActions
|
||||
? html`
|
||||
<mwc-icon-button
|
||||
class="complete-btn"
|
||||
@@ -688,6 +727,9 @@ export class MaintenanceSupporterCard extends LitElement {
|
||||
--mdc-icon-size: 18px;
|
||||
color: var(--primary-color);
|
||||
}
|
||||
/* DESIGN PROTOTYPE (#145): action_style: buttons — HA-native labelled button. */
|
||||
.complete-btn-text { --ha-button-font-size: 13px; flex: none; white-space: nowrap; }
|
||||
.complete-btn-text ha-icon { --mdc-icon-size: 18px; }
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** Maintenance Supporter Sidebar Panel. */
|
||||
|
||||
import { LitElement, html, nothing } from "lit";
|
||||
import { LitElement, html, nothing, type TemplateResult } from "lit";
|
||||
import { isSafeHttpUrl } from "./helpers/url";
|
||||
import { applySubscriptionEvent, type SubscriptionEvent } from "./helpers/subscription-merge";
|
||||
import { isStaleBundle } from "./helpers/bundle-version";
|
||||
@@ -120,6 +120,12 @@ type GroupByMode = "none" | "area" | "group" | "user";
|
||||
export class MaintenanceSupporterPanel extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@property({ type: Boolean, reflect: true }) public narrow = false;
|
||||
/** #145: the panel itself is tight (< 880 px) although the viewport is not
|
||||
* `narrow` — an iPad in portrait with HA's sidebar docked leaves ~768 px.
|
||||
* The wide row grid then cannot hold labelled action buttons, so the
|
||||
* compact (icon-only) form applies here too. Reflected for the CSS. */
|
||||
@property({ type: Boolean, reflect: true }) public tight = false;
|
||||
private _tightObserver: ResizeObserver | null = null;
|
||||
@property({ attribute: false }) public panel: Record<string, unknown> = {};
|
||||
|
||||
@state() private _objects: MaintenanceObjectResponse[] = [];
|
||||
@@ -170,6 +176,10 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
// value in the task-create dialog so the Settings → General → "Default
|
||||
// warning days" choice actually flows through to new tasks.
|
||||
@state() private _defaultWarningDays = 7;
|
||||
/** #145: global "Task row actions" style (buttons_compact | buttons | icons). */
|
||||
@state() private _rowActionStyle = "buttons_compact";
|
||||
/** #145: one-time "rows look different now" notice for existing installs. */
|
||||
@state() private _rowActionNotice = false;
|
||||
@state() private _actionLoading = false;
|
||||
@state() private _moreMenuOpen = false;
|
||||
@state() private _objMenuOpen = false;
|
||||
@@ -320,6 +330,19 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
else window.setTimeout(kick, 1500);
|
||||
window.addEventListener("popstate", this._popstateHandler);
|
||||
window.addEventListener("keydown", this._paletteKeydown);
|
||||
if (typeof ResizeObserver !== "undefined") {
|
||||
this._tightObserver = new ResizeObserver((entries) => {
|
||||
const w = entries[0]?.contentRect.width ?? 0;
|
||||
// 1000, not 880: between ~880 and ~1000 the wide grid technically
|
||||
// fits its column minimums, but the chips track shrinks below any
|
||||
// readable width — first the chips painted over the type column
|
||||
// (duty-rotation GIF, 2026-08-30), clipped they left ellipsis
|
||||
// fragments. Below ~1000 the narrow layout is the honest choice;
|
||||
// from there up the chips track keeps ≥150 px of slack.
|
||||
if (w > 0) this.tight = w < 1000;
|
||||
});
|
||||
this._tightObserver.observe(this);
|
||||
}
|
||||
window.addEventListener("resize", this._onVirtualScroll, { passive: true });
|
||||
// localStorage.getItem can THROW (Safari private mode / locked-down policies
|
||||
// where storage access raises rather than returning null) — an unguarded
|
||||
@@ -360,6 +383,8 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
super.disconnectedCallback();
|
||||
window.removeEventListener("popstate", this._popstateHandler);
|
||||
window.removeEventListener("keydown", this._paletteKeydown);
|
||||
this._tightObserver?.disconnect();
|
||||
this._tightObserver = null;
|
||||
window.removeEventListener("resize", this._onVirtualScroll);
|
||||
this.shadowRoot?.querySelector(".content")?.removeEventListener("scroll", this._onVirtualScroll);
|
||||
this._virtScrollAttached = false;
|
||||
@@ -517,7 +542,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
features: AdvancedFeatures;
|
||||
admin_panel_user_ids?: string[];
|
||||
operator_write_enabled?: boolean;
|
||||
general?: { default_warning_days?: number };
|
||||
general?: { default_warning_days?: number; row_action_style?: string; row_action_notice_pending?: boolean };
|
||||
objects_table_columns?: string[];
|
||||
};
|
||||
this._features = sr.features;
|
||||
@@ -527,6 +552,9 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
if (typeof dwd === "number" && dwd >= 0 && dwd <= 365) {
|
||||
this._defaultWarningDays = dwd;
|
||||
}
|
||||
const ras = sr.general?.row_action_style;
|
||||
this._rowActionStyle = ras === "icons" || ras === "buttons" ? ras : "buttons_compact";
|
||||
this._rowActionNotice = sr.general?.row_action_notice_pending === true;
|
||||
this._objectsTableColumns = sanitizeColumns(sr.objects_table_columns);
|
||||
}
|
||||
|
||||
@@ -1995,6 +2023,20 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
${this._rowActionNotice && !!this.hass?.user?.is_admin
|
||||
? html`
|
||||
<div class="update-banner row-actions-banner" role="status">
|
||||
<ha-icon icon="mdi:gesture-tap-button"></ha-icon>
|
||||
<span>${t("row_actions_banner", this._lang)}</span>
|
||||
<ha-button appearance="plain" @click=${() => this._dismissRowActionNotice(false)}>
|
||||
${t("row_actions_keep", this._lang)}
|
||||
</ha-button>
|
||||
<ha-button appearance="filled" @click=${() => this._dismissRowActionNotice(true)}>
|
||||
${t("row_actions_back", this._lang)}
|
||||
</ha-button>
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
${this.narrow || this._view !== "overview" ? this._renderHeader() : nothing}
|
||||
<div class="content">
|
||||
${this._view === "overview"
|
||||
@@ -2285,10 +2327,19 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
<div class="today-task">${row.task_name}</div>
|
||||
<div class="today-object">${row.object_name} · ${formatDueDays(row.days_until_due, L)}</div>
|
||||
</div>
|
||||
<mwc-icon-button class="btn-complete" title="${t("complete", L)}"
|
||||
@click=${(e: Event) => { e.stopPropagation(); this._openCompleteDialogForRow(row); }}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>
|
||||
</mwc-icon-button>
|
||||
${this._actionStyle() === "icons"
|
||||
? html`
|
||||
<mwc-icon-button class="btn-complete" title="${t("complete", L)}"
|
||||
@click=${(e: Event) => { e.stopPropagation(); this._openCompleteDialogForRow(row); }}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>
|
||||
</mwc-icon-button>`
|
||||
: html`
|
||||
<ha-button size="small" appearance="accent" variant="success" class="today-complete" title="${t("complete", L)}"
|
||||
@click=${(e: Event) => { e.stopPropagation(); this._openCompleteDialogForRow(row); }}>
|
||||
${this._actionStyle() === "buttons_compact" && (this.narrow || this.tight)
|
||||
? html`<ha-icon icon="mdi:check"></ha-icon>`
|
||||
: html`<ha-icon slot="start" icon="mdi:check"></ha-icon>${t("complete", L)}`}
|
||||
</ha-button>`}
|
||||
</div>
|
||||
`)}
|
||||
</div>
|
||||
@@ -3215,18 +3266,74 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
: nothing}
|
||||
${renderMiniSparkline(row, this._miniStatsData, this._lang)}
|
||||
</span>
|
||||
<span class="row-actions">
|
||||
<mwc-icon-button class="btn-complete" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); this._openCompleteDialogForRow(row); }}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-icon-button class="btn-skip" title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); this._promptSkipTask(row.entry_id, row.task_id); }}>
|
||||
<ha-icon icon="mdi:skip-next"></ha-icon>
|
||||
</mwc-icon-button>
|
||||
</span>
|
||||
${this._renderRowActions(L, () => this._openCompleteDialogForRow(row), () => this._promptSkipTask(row.entry_id, row.task_id))}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/** DESIGN PROTOTYPE (#145 wish 1): row actions as bare icons (current) or
|
||||
* as labelled colour-coded buttons. Switch: localStorage "msp-action-style"
|
||||
* = "buttons" — evaluation only, no settings plumbing yet. */
|
||||
private _actionStyle(): string {
|
||||
return this._rowActionStyle;
|
||||
}
|
||||
|
||||
/** The #145 banner's two ways out: keep the buttons (just dismiss) or go
|
||||
* back to icons (style + dismiss in one write). Admin-only, like every
|
||||
* global setting. */
|
||||
private async _dismissRowActionNotice(backToIcons: boolean): Promise<void> {
|
||||
const settings: Record<string, unknown> = { row_action_notice_pending: false };
|
||||
if (backToIcons) settings.row_action_style = "icons";
|
||||
try {
|
||||
await this.hass.connection.sendMessagePromise({ type: "maintenance_supporter/global/update", settings });
|
||||
this._rowActionNotice = false;
|
||||
if (backToIcons) this._rowActionStyle = "icons";
|
||||
} catch (err) {
|
||||
console.warn("[maintenance-supporter] row-action notice update failed", err);
|
||||
}
|
||||
}
|
||||
|
||||
/** #145: row actions as HA buttons — labelled (accent/success + plain, the
|
||||
* task-detail pairing) or, for "buttons_compact" on narrow screens,
|
||||
* icon-only — or the classic icon pair when the household chose "icons". */
|
||||
private _renderRowActions(L: string, onComplete: () => void, onSkip: () => void): TemplateResult {
|
||||
const style = this._actionStyle();
|
||||
if (style === "buttons" || style === "buttons_compact") {
|
||||
const iconOnly = style === "buttons_compact" && (this.narrow || this.tight);
|
||||
if (iconOnly) {
|
||||
// Compact narrow form: the primary action stays a solid ha-button
|
||||
// (icon only), the secondary one becomes HA's own icon button.
|
||||
return html`
|
||||
<span class="row-actions as-buttons compact">
|
||||
<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-button>
|
||||
<ha-icon-button .label=${t("skip", L)} title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}>
|
||||
<ha-icon icon="mdi:skip-next"></ha-icon>
|
||||
</ha-icon-button>
|
||||
</span>`;
|
||||
}
|
||||
return html`
|
||||
<span class="row-actions as-buttons">
|
||||
<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-button>
|
||||
<ha-button size="small" appearance="plain" variant="neutral" title="${t("skip", L)}" ?disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}>
|
||||
<ha-icon slot="start" icon="mdi:skip-next"></ha-icon>${t("skip", L)}
|
||||
</ha-button>
|
||||
</span>`;
|
||||
}
|
||||
return html`
|
||||
<span class="row-actions">
|
||||
<mwc-icon-button class="btn-complete" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); onComplete(); }}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-icon-button class="btn-skip" title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); onSkip(); }}>
|
||||
<ha-icon icon="mdi:skip-next"></ha-icon>
|
||||
</mwc-icon-button>
|
||||
</span>`;
|
||||
}
|
||||
|
||||
private _openCompleteDialogForRow(row: TaskRow): void {
|
||||
const obj = this._objects.find(o => o.entry_id === row.entry_id);
|
||||
const task = obj?.tasks.find(t => t.id === row.task_id);
|
||||
@@ -3367,14 +3474,11 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
: nothing}
|
||||
${renderMiniSparkline(task, this._miniStatsData, this._lang)}
|
||||
</span>
|
||||
<span class="row-actions">
|
||||
<mwc-icon-button class="btn-complete" title="${t("complete", L)}" @click=${(e: Event) => { e.stopPropagation(); this._openCompleteDialog(obj.entry_id, task.id, task.name, this._features.checklists ? task.checklist : undefined, this._features.adaptive && !!task.adaptive_config?.enabled); }}>
|
||||
<ha-icon icon="mdi:check"></ha-icon>
|
||||
</mwc-icon-button>
|
||||
<mwc-icon-button class="btn-skip" title="${t("skip", L)}" .disabled=${this._actionLoading} @click=${(e: Event) => { e.stopPropagation(); this._promptSkipTask(obj.entry_id, task.id); }}>
|
||||
<ha-icon icon="mdi:skip-next"></ha-icon>
|
||||
</mwc-icon-button>
|
||||
</span>
|
||||
${this._renderRowActions(
|
||||
L,
|
||||
() => 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),
|
||||
)}
|
||||
</div>
|
||||
`)}</div>`}
|
||||
|
||||
|
||||
@@ -287,6 +287,10 @@ export const panelStyles = css`
|
||||
.today-task { font-weight: 600; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.today-object { color: var(--secondary-text-color); font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
.today-row .btn-complete { color: var(--success-color, #4caf50); flex: none; }
|
||||
.today-row .today-complete { flex: none; --ha-button-font-size: 13px; white-space: nowrap; }
|
||||
.today-row .today-complete ha-icon { --mdc-icon-size: 18px; }
|
||||
:host([narrow]) .today-row .today-complete,
|
||||
:host([tight]) .today-row .today-complete { min-width: 0; --ha-button-height: 36px; }
|
||||
.today-empty {
|
||||
display: flex; flex-direction: column; align-items: center; gap: 10px;
|
||||
padding: 48px 16px; color: var(--secondary-text-color); text-align: center;
|
||||
@@ -376,6 +380,17 @@ export const panelStyles = css`
|
||||
color: var(--secondary-text-color);
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-end;
|
||||
/* The chips track is minmax(0, …): when the row gets squeezed the track
|
||||
may shrink below the chips' natural width — clip instead of painting
|
||||
over the neighbouring type column (duty-rotation GIF, 2026-08-30). */
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
/* …and all-or-nothing: below 60 px of track there is no readable chip,
|
||||
only fragments — hide them entirely via the container query below. */
|
||||
container-type: inline-size;
|
||||
}
|
||||
@container (max-width: 60px) {
|
||||
.sub-chip { display: none; }
|
||||
}
|
||||
/* Empty subline still occupies its grid slot so neighbouring columns line up */
|
||||
.task-sub-empty { min-height: 1px; }
|
||||
@@ -388,6 +403,11 @@ export const panelStyles = css`
|
||||
border-radius: 10px;
|
||||
background: var(--secondary-background-color, rgba(127, 127, 127, 0.1));
|
||||
line-height: 1.4;
|
||||
/* A single chip wider than the squeezed track truncates instead of
|
||||
bleeding into the next column. */
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.sub-chip ha-icon {
|
||||
--mdc-icon-size: 14px;
|
||||
@@ -407,6 +427,16 @@ export const panelStyles = css`
|
||||
--mdc-icon-size: 26px;
|
||||
}
|
||||
|
||||
/* DESIGN PROTOTYPE (#145 wish 1): labelled, colour-coded action buttons
|
||||
instead of bare icons. Complete = filled success pill, Skip = outlined
|
||||
neutral pill; both keep the icon as a leading glyph. */
|
||||
.row-actions.as-buttons { gap: 4px; }
|
||||
.row-actions.as-buttons ha-button {
|
||||
--ha-button-font-size: 13px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.row-actions.as-buttons ha-icon { --mdc-icon-size: 18px; }
|
||||
|
||||
/* Custom elements default to display:inline; the task-detail component
|
||||
renders light-DOM and must behave like the block it wraps. */
|
||||
maintenance-task-detail-view { display: block; }
|
||||
@@ -1440,7 +1470,7 @@ export const panelStyles = css`
|
||||
full bottom row. */
|
||||
display: grid;
|
||||
grid-column: auto;
|
||||
grid-template-columns: auto minmax(0, 1fr) 100px auto;
|
||||
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-rows: auto auto auto;
|
||||
column-gap: 8px;
|
||||
row-gap: 4px;
|
||||
@@ -1480,6 +1510,56 @@ export const panelStyles = css`
|
||||
grid-column: 4;
|
||||
grid-row: 2;
|
||||
}
|
||||
/* Prototype: on phones the two labelled pills stack, so the row keeps its
|
||||
deterministic column X-positions and neither label gets truncated. */
|
||||
/* Labelled buttons stack when the row cannot hold them side by side:
|
||||
narrow viewports AND a tight panel (iPad portrait with the sidebar
|
||||
docked — the viewport is not narrow but the panel is ~768 px). */
|
||||
:host([narrow]) .row-actions.as-buttons,
|
||||
:host([tight]) .row-actions.as-buttons {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 4px;
|
||||
}
|
||||
:host([narrow]) .row-actions.as-buttons ha-button,
|
||||
:host([tight]) .row-actions.as-buttons ha-button { --ha-button-font-size: 12px; }
|
||||
/* buttons_compact: the labelled buttons collapse to an icon-only ha-button
|
||||
plus ha-icon-button side by side — the colour carries the meaning, the
|
||||
row keeps the icon-era height. */
|
||||
:host([narrow]) .row-actions.as-buttons.compact,
|
||||
:host([tight]) .row-actions.as-buttons.compact { flex-direction: row; align-items: center; gap: 2px; }
|
||||
:host([narrow]) .row-actions.compact ha-button,
|
||||
:host([tight]) .row-actions.compact ha-button { --ha-button-height: 36px; min-width: 0; }
|
||||
:host([narrow]) .row-actions.compact ha-icon-button,
|
||||
:host([tight]) .row-actions.compact ha-icon-button { --mdc-icon-button-size: 40px; --mdc-icon-size: 22px; color: var(--secondary-text-color); }
|
||||
:host([narrow]) .row-actions.compact ha-icon,
|
||||
:host([tight]) .row-actions.compact ha-icon { --mdc-icon-size: 20px; }
|
||||
|
||||
/* A TIGHT panel that is not narrow (iPad portrait with HA's sidebar
|
||||
docked: 1024 px viewport, ~768 px panel) gets the narrow row layout too —
|
||||
the wide subgrid overflowed its last column at that width even before
|
||||
the buttons. Same rules as the :host([narrow]) block above / the
|
||||
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-row {
|
||||
display: grid;
|
||||
grid-column: auto;
|
||||
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-rows: auto auto auto;
|
||||
column-gap: 8px;
|
||||
row-gap: 4px;
|
||||
padding: 12px;
|
||||
min-width: 0;
|
||||
}
|
||||
: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-badges { grid-column: 1; grid-row: 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])) .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-empty { display: none; }
|
||||
:host([tight]:not([narrow])) .mini-sparkline { width: 50px; }
|
||||
:host([narrow]) .task-sub {
|
||||
grid-column: 1 / -1;
|
||||
grid-row: 3;
|
||||
@@ -1614,7 +1694,7 @@ export const panelStyles = css`
|
||||
/* Mirror the :host([narrow]) grid layout for narrow desktop windows */
|
||||
.task-row {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr) 100px auto;
|
||||
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-rows: auto auto auto;
|
||||
column-gap: 8px;
|
||||
row-gap: 4px;
|
||||
|
||||
@@ -373,6 +373,9 @@ export interface SavedView {
|
||||
export interface CardConfig {
|
||||
type: string;
|
||||
title?: string;
|
||||
/** #145: how the row's Complete action looks. Omit to follow the global
|
||||
* "Task row actions" setting (buttons unless the household chose icons). */
|
||||
action_style?: "icons" | "buttons";
|
||||
show_header?: boolean;
|
||||
max_items?: number;
|
||||
filter_status?: string[];
|
||||
|
||||
Reference in New Issue
Block a user