185 files

This commit is contained in:
Home Assistant Version Control
2026-08-19 11:38:13 +00:00
parent 5f9330abd7
commit a718af6423
185 changed files with 16868 additions and 3088 deletions
@@ -101,6 +101,41 @@ describe("complete-dialog", () => {
expect("feedback" in msg).to.be.false;
expect("checklist_state" in msg).to.be.false;
expect("photo_doc_id" in msg).to.be.false;
expect("completed_at" in msg).to.be.false;
});
it("sends completed_at with seconds re-added when a backdate is picked (#133)", async () => {
const { el, sent } = await mount();
const dt = el.shadowRoot!.querySelector<HTMLInputElement>('input[type="datetime-local"]')!;
expect(dt, "backdate field rendered").to.exist;
dt.value = "2026-01-10T14:30";
dt.dispatchEvent(new Event("change"));
await el.updateComplete;
clickComplete(el);
await new Promise((r) => setTimeout(r, 10));
const msg = sent.find((m) => m.type === "maintenance_supporter/task/complete")!;
expect(msg).to.exist;
expect(msg.completed_at).to.equal("2026-01-10T14:30:00");
});
it("rejects a future completed_at client-side without a WS roundtrip (#133)", async () => {
const { el, sent } = await mount();
const future = new Date(Date.now() + 48 * 3600 * 1000);
const pad = (n: number) => String(n).padStart(2, "0");
const v = `${future.getFullYear()}-${pad(future.getMonth() + 1)}-${pad(future.getDate())}T12:00`;
const dt = el.shadowRoot!.querySelector<HTMLInputElement>('input[type="datetime-local"]')!;
dt.value = v;
dt.dispatchEvent(new Event("change"));
await el.updateComplete;
clickComplete(el);
await new Promise((r) => setTimeout(r, 10));
expect(sent.find((m) => m.type === "maintenance_supporter/task/complete")).to.equal(undefined);
await el.updateComplete;
expect(el.shadowRoot!.textContent).to.include("future");
});
it("attaches an uploaded photo as photo_doc_id", async () => {
@@ -63,6 +63,31 @@ describe("task-dialog trigger_config roundtrip closure (#103 class)", () => {
});
});
it("threshold: =/≠ limits and the all-combinator survive", async () => {
const tc = await saveRoundtrip({
type: "threshold",
entity_id: "sensor.a",
trigger_equals: 3,
trigger_not_equals: 1,
trigger_combinator: "all",
});
expect(tc).to.deep.include({
type: "threshold",
trigger_equals: 3,
trigger_not_equals: 1,
trigger_combinator: "all",
});
});
it("combinator defaults to any and is then omitted from the payload", async () => {
const tc = await saveRoundtrip({
type: "threshold",
entity_id: "sensor.a",
trigger_above: 80,
});
expect(tc.trigger_combinator, "any must not be persisted").to.equal(undefined);
});
it("threshold stored with ONLY plural entity_ids survives an edit (#106)", async () => {
// The Battery Fleet task's trigger has no singular entity_id; the save
// path gates on _triggerEntityId, so before the hydration fallback an
@@ -179,4 +204,34 @@ describe("task-dialog trigger_config roundtrip closure (#103 class)", () => {
entity_logic: "any",
});
});
it("compound: condition =/≠ limits and task-level combinator survive", async () => {
const tc = await saveRoundtrip({
type: "compound",
compound_logic: "AND",
trigger_combinator: "all",
conditions: [
{
type: "threshold",
entity_id: "sensor.a",
entity_ids: ["sensor.a"],
trigger_equals: 3,
trigger_not_equals: 1,
},
{
type: "threshold",
entity_id: "sensor.b",
entity_ids: ["sensor.b"],
trigger_above: 80,
},
],
});
expect(tc.trigger_combinator).to.equal("all");
const conds = tc.conditions as Array<Record<string, unknown>>;
expect(conds[0]).to.deep.include({
type: "threshold",
trigger_equals: 3,
trigger_not_equals: 1,
});
});
});
@@ -53,6 +53,8 @@ export class MaintenanceCompleteDialog extends LitElement {
@state() private _photoUploading = false;
@state() private _readingValue = "";
@state() private _restockQty = "";
/** #133: optional backdated completion moment (datetime-local value; "" = now). */
@state() private _completedAt = "";
/** Keyed by `partLinkKey` — the (entry_id, part_id) pair — because two
* objects can carry the same part id, so part_id alone would merge pools. */
@state() private _usedParts: Record<string, TaskPartLink> = {};
@@ -81,6 +83,7 @@ export class MaintenanceCompleteDialog extends LitElement {
this._photoUploading = false;
this._readingValue = "";
this._restockQty = this.restockDefault !== null ? String(this.restockDefault) : "";
this._completedAt = "";
// #99: prefill "parts used" with the task's fixed links — the user can
// untick or adjust before completing. The whole link is kept, entry_id
// included, so a shared pool survives the edit (#111).
@@ -167,6 +170,18 @@ export class MaintenanceCompleteDialog extends LitElement {
if (this._photoDocId) {
data.photo_doc_id = this._photoDocId;
}
if (this._completedAt) {
// Client-side guard mirrors the backend rule — a picked future moment
// fails fast with a localized message instead of a WS roundtrip.
if (new Date(this._completedAt).getTime() > Date.now()) {
this._error = t("completed_at_future_error", this.lang);
this._loading = false;
return;
}
// Re-add seconds if the datetime-local input drops them (same
// normalisation as the history-edit dialog).
data.completed_at = this._completedAt.length === 16 ? `${this._completedAt}:00` : this._completedAt;
}
if (this._readingValue !== "") {
const rv = parseFloat(this._readingValue);
if (!isNaN(rv)) data.reading_value = rv;
@@ -371,6 +386,13 @@ export class MaintenanceCompleteDialog extends LitElement {
.value=${this._duration}
@input=${(e: Event) => (this._duration = (e.target as HTMLInputElement).value)} />
</label>
<label class="field">
<span class="field-label">${t("completed_at_optional", L)}</span>
<input type="datetime-local" class="field-input"
max=${new Date(Date.now() - new Date().getTimezoneOffset() * 60000).toISOString().slice(0, 16)}
.value=${this._completedAt}
@change=${(e: Event) => (this._completedAt = (e.target as HTMLInputElement).value)} />
</label>
<div class="field">
<span class="field-label">${t("completion_photo_optional", L)}${this._req("photo")}</span>
${this._photoPreview
@@ -35,6 +35,8 @@ interface CompoundConditionDraft {
attribute: string; // "" = use the entity state
above: string;
below: string;
equals: string;
notEquals: string;
forMinutes: string;
targetValue: string;
deltaMode: boolean;
@@ -50,7 +52,8 @@ interface CompoundConditionDraft {
function emptyCondition(): CompoundConditionDraft {
return {
entityIds: "", type: "threshold", attribute: "", above: "", below: "", forMinutes: "0",
entityIds: "", type: "threshold", attribute: "", above: "", below: "",
equals: "", notEquals: "", forMinutes: "0",
targetValue: "", deltaMode: false, fromState: "", toState: "",
targetChanges: "", runtimeHours: "", onStates: "", carry: {},
};
@@ -60,7 +63,7 @@ function emptyCondition(): CompoundConditionDraft {
* travels through `carry` untouched. */
const MANAGED_CONDITION_KEYS = new Set([
"entity_id", "entity_ids", "type", "attribute",
"trigger_above", "trigger_below", "trigger_for_minutes",
"trigger_above", "trigger_below", "trigger_equals", "trigger_not_equals", "trigger_for_minutes",
"trigger_target_value", "trigger_delta_mode",
"trigger_from_state", "trigger_to_state", "trigger_target_changes",
"trigger_runtime_hours", "trigger_on_states",
@@ -75,6 +78,8 @@ function conditionToDraft(c: TriggerConfig): CompoundConditionDraft {
attribute: c.attribute || "",
above: c.trigger_above?.toString() ?? "",
below: c.trigger_below?.toString() ?? "",
equals: c.trigger_equals?.toString() ?? "",
notEquals: c.trigger_not_equals?.toString() ?? "",
forMinutes: c.trigger_for_minutes?.toString() ?? "0",
targetValue: c.trigger_target_value?.toString() ?? "",
deltaMode: c.trigger_delta_mode || false,
@@ -99,6 +104,8 @@ function draftToCondition(d: CompoundConditionDraft): TriggerConfig | null {
if (d.type === "threshold") {
const a = parseFloat(d.above); if (!isNaN(a)) c.trigger_above = a;
const b = parseFloat(d.below); if (!isNaN(b)) c.trigger_below = b;
const eq = parseFloat(d.equals); if (!isNaN(eq)) c.trigger_equals = eq;
const ne = parseFloat(d.notEquals); if (!isNaN(ne)) c.trigger_not_equals = ne;
const f = parseInt(d.forMinutes, 10); if (!isNaN(f)) c.trigger_for_minutes = f;
} else if (d.type === "counter") {
const v = parseFloat(d.targetValue); if (!isNaN(v)) c.trigger_target_value = v;
@@ -202,7 +209,11 @@ export class MaintenanceTaskDialog extends LitElement {
@state() private _triggerType = "threshold";
@state() private _triggerAbove = "";
@state() private _triggerBelow = "";
@state() private _triggerEquals = "";
@state() private _triggerNotEquals = "";
@state() private _triggerForMinutes = "0";
/** Trigger vs. safety interval: "any" = whichever first (default), "all" = both required. */
@state() private _triggerCombinator: "any" | "all" = "any";
@state() private _triggerTargetValue = "";
@state() private _triggerDeltaMode = false;
@state() private _triggerBaselineValue = "";
@@ -426,7 +437,10 @@ export class MaintenanceTaskDialog extends LitElement {
this._triggerType = tc.type || "threshold";
this._triggerAbove = tc.trigger_above?.toString() || "";
this._triggerBelow = tc.trigger_below?.toString() || "";
this._triggerEquals = tc.trigger_equals?.toString() || "";
this._triggerNotEquals = tc.trigger_not_equals?.toString() || "";
this._triggerForMinutes = tc.trigger_for_minutes?.toString() || "0";
this._triggerCombinator = tc.trigger_combinator === "all" ? "all" : "any";
this._triggerTargetValue = tc.trigger_target_value?.toString() || "";
this._triggerDeltaMode = tc.trigger_delta_mode || false;
this._triggerBaselineValue = tc.trigger_baseline_value?.toString() || "";
@@ -530,7 +544,10 @@ export class MaintenanceTaskDialog extends LitElement {
this._triggerType = "threshold";
this._triggerAbove = "";
this._triggerBelow = "";
this._triggerEquals = "";
this._triggerNotEquals = "";
this._triggerForMinutes = "0";
this._triggerCombinator = "any";
this._triggerTargetValue = "";
this._triggerDeltaMode = false;
this._triggerBaselineValue = "";
@@ -1089,6 +1106,7 @@ export class MaintenanceTaskDialog extends LitElement {
conditions,
};
if (this._autoCompleteOnRecovery) triggerConfig.auto_complete_on_recovery = true;
if (this._triggerCombinator === "all") triggerConfig.trigger_combinator = "all";
data.trigger_config = triggerConfig;
} else if (this._taskId) {
data.trigger_config = null;
@@ -1104,6 +1122,7 @@ export class MaintenanceTaskDialog extends LitElement {
};
if (this._triggerAttribute) triggerConfig.attribute = this._triggerAttribute;
if (this._autoCompleteOnRecovery) triggerConfig.auto_complete_on_recovery = true;
if (this._triggerCombinator === "all") triggerConfig.trigger_combinator = "all";
// Multi-entity: store entity_logic for all trigger types
if (entityIds.length > 1) {
@@ -1113,6 +1132,8 @@ export class MaintenanceTaskDialog extends LitElement {
if (this._triggerType === "threshold") {
if (this._triggerAbove) { const v = parseFloat(this._triggerAbove); if (!isNaN(v)) triggerConfig.trigger_above = v; }
if (this._triggerBelow) { const v = parseFloat(this._triggerBelow); if (!isNaN(v)) triggerConfig.trigger_below = v; }
if (this._triggerEquals) { const v = parseFloat(this._triggerEquals); if (!isNaN(v)) triggerConfig.trigger_equals = v; }
if (this._triggerNotEquals) { const v = parseFloat(this._triggerNotEquals); if (!isNaN(v)) triggerConfig.trigger_not_equals = v; }
if (this._triggerForMinutes) { const v = parseInt(this._triggerForMinutes, 10); if (!isNaN(v)) triggerConfig.trigger_for_minutes = v; }
} else if (this._triggerType === "counter") {
if (this._triggerTargetValue) { const v = parseFloat(this._triggerTargetValue); if (!isNaN(v)) triggerConfig.trigger_target_value = v; }
@@ -1342,6 +1363,19 @@ export class MaintenanceTaskDialog extends LitElement {
@input=${(e: Event) => (this._intervalDays = (e.target as HTMLInputElement).value)}
></ms-textfield>
${this._intervalDays ? this._renderUnitSelect() : nothing}
${this._intervalDays
? html`
<div class="select-row">
<label>${t("trigger_combinator", L)}</label>
<select
@change=${(e: Event) => (this._triggerCombinator = (e.target as HTMLSelectElement).value as "any" | "all")}
>
<option value="any" ?selected=${this._triggerCombinator === "any"}>${t("trigger_combinator_any", L)}</option>
<option value="all" ?selected=${this._triggerCombinator === "all"}>${t("trigger_combinator_all", L)}</option>
</select>
</div>
`
: nothing}
`;
}
@@ -1636,6 +1670,10 @@ export class MaintenanceTaskDialog extends LitElement {
@input=${(e: Event) => this._patchCondition(i, { above: (e.target as HTMLInputElement).value })}></ms-textfield>
<ms-textfield label="${t("trigger_below", L)}" type="number" .value=${c.below}
@input=${(e: Event) => this._patchCondition(i, { below: (e.target as HTMLInputElement).value })}></ms-textfield>
<ms-textfield label="${t("trigger_equals", L)}" type="number" .value=${c.equals}
@input=${(e: Event) => this._patchCondition(i, { equals: (e.target as HTMLInputElement).value })}></ms-textfield>
<ms-textfield label="${t("trigger_not_equals", L)}" type="number" .value=${c.notEquals}
@input=${(e: Event) => this._patchCondition(i, { notEquals: (e.target as HTMLInputElement).value })}></ms-textfield>
<ms-textfield label="${t("for_minutes", L)}" type="number" .value=${c.forMinutes}
@input=${(e: Event) => this._patchCondition(i, { forMinutes: (e.target as HTMLInputElement).value })}></ms-textfield>
`;
@@ -2122,6 +2160,20 @@ export class MaintenanceTaskDialog extends LitElement {
.value=${this._triggerBelow}
@input=${(e: Event) => (this._triggerBelow = (e.target as HTMLInputElement).value)}
></ms-textfield>
<ms-textfield
label="${t("trigger_equals", L)}"
type="number"
step="any"
.value=${this._triggerEquals}
@input=${(e: Event) => (this._triggerEquals = (e.target as HTMLInputElement).value)}
></ms-textfield>
<ms-textfield
label="${t("trigger_not_equals", L)}"
type="number"
step="any"
.value=${this._triggerNotEquals}
@input=${(e: Event) => (this._triggerNotEquals = (e.target as HTMLInputElement).value)}
></ms-textfield>
<ms-textfield
label="${t("for_at_least_minutes", L)}"
type="number"
@@ -128,6 +128,8 @@
"notes_optional": "Poznámky (volitelné)",
"cost_optional": "Náklady (volitelné)",
"duration_minutes": "Doba trvání v minutách (volitelné)",
"completed_at_optional": "Dokončeno dne (volitelné, prázdné = nyní)",
"completed_at_future_error": "Datum dokončení nesmí být v budoucnosti.",
"days": "dní",
"day": "den",
"today": "Dnes",
@@ -192,9 +194,14 @@
"use_entity_state": "Použít stav entity (bez atributu)",
"trigger_above": "Spustit nad",
"trigger_below": "Spustit pod",
"trigger_equals": "Spustit při rovnosti (=)",
"trigger_not_equals": "Spustit při odlišnosti od (≠)",
"for_at_least_minutes": "Po dobu alespoň (minut)",
"safety_interval_days": "Bezpečnostní interval (dny, volitelný)",
"safety_interval": "Bezpečnostní interval (volitelný)",
"trigger_combinator": "Kombinovat spouštěč a interval",
"trigger_combinator_any": "Spouštěč nebo interval (co dřív)",
"trigger_combinator_all": "Spouštěč a interval (obojí vyžadováno)",
"delta_mode": "Režim delta",
"from_state_optional": "Ze stavu (volitelné)",
"to_state_optional": "Do stavu (volitelné)",
@@ -850,5 +857,17 @@
"gs_label": "Začínáme — tyto tipy zmizí, jak vaše nastavení poroste",
"gs_setups_chip": "Navrhovaná nastavení: nalezeno {n} zařízení s předpřipravenými spouštěči",
"gs_adopt_chip": "{n} problémových senzorů se může stát údržbovými úkoly",
"gs_fleet_chip": "Jedno kliknutí nastaví flotilu baterií"
"gs_fleet_chip": "Jedno kliknutí nastaví flotilu baterií",
"cal_editor_window": "Výchozí okno",
"cal_editor_window_week": "Týden (7 dní)",
"cal_editor_window_fortnight": "Dva týdny (14 dní)",
"cal_editor_window_month": "Měsíc (30 dní, výchozí)",
"cal_editor_window_year": "Rok (365 dní, prázdné dny skryty)",
"cal_editor_show_chips": "Zobrazit přepínače okna v kartě",
"cal_editor_chips_hint": "Skryjte přepínače, pokud je karta ve strategickém pohledu, který už slouží jako výběr okna.",
"cal_editor_show_user_filter": "Zobrazit filtr uživatele",
"cal_editor_default_user": "Výchozí filtr uživatele",
"cal_editor_my_tasks": "Moje úkoly (aktuální uživatel)",
"cal_editor_show_object_filter": "Zobrazit filtr objektu",
"cal_editor_object_hint": "Předvyberte objekt přes YAML: object_filter: \"<název>\" — nebo seznam názvů pro omezení karty na více objektů."
}
@@ -129,6 +129,8 @@
"notes_optional": "Noter (valgfrit)",
"cost_optional": "Omkostning (valgfrit)",
"duration_minutes": "Varighed i minutter (valgfrit)",
"completed_at_optional": "Udført den (valgfrit, tomt = nu)",
"completed_at_future_error": "Udførelsesdatoen må ikke ligge i fremtiden.",
"days": "dage",
"day": "dag",
"today": "I dag",
@@ -193,9 +195,14 @@
"use_entity_state": "Brug enhedstilstand (ingen attribut)",
"trigger_above": "Udløs over",
"trigger_below": "Udløs under",
"trigger_equals": "Udløs ved lig med (=)",
"trigger_not_equals": "Udløs ved forskellig fra (≠)",
"for_at_least_minutes": "I mindst (minutter)",
"safety_interval_days": "Sikkerhedsinterval (dage, valgfrit)",
"safety_interval": "Sikkerhedsinterval (valgfrit)",
"trigger_combinator": "Kombinér trigger og interval",
"trigger_combinator_any": "Trigger eller interval (først opfyldt)",
"trigger_combinator_all": "Trigger og interval (begge kræves)",
"delta_mode": "Delta-tilstand",
"from_state_optional": "Fra tilstand (valgfrit)",
"to_state_optional": "Til tilstand (valgfrit)",
@@ -850,5 +857,17 @@
"gs_label": "Kom godt i gang — disse tips forsvinder, efterhånden som opsætningen vokser",
"gs_setups_chip": "Foreslåede opsætninger fandt {n} enheder med forudindstillede udløsere",
"gs_adopt_chip": "{n} problemsensorer kan blive vedligeholdelsesopgaver",
"gs_fleet_chip": "Ét klik opsætter batteriflåden"
"gs_fleet_chip": "Ét klik opsætter batteriflåden",
"cal_editor_window": "Standardvindue",
"cal_editor_window_week": "Uge (7 dage)",
"cal_editor_window_fortnight": "To uger (14 dage)",
"cal_editor_window_month": "Måned (30 dage, standard)",
"cal_editor_window_year": "År (365 dage, tomme dage skjult)",
"cal_editor_show_chips": "Vis vinduechips i kortet",
"cal_editor_chips_hint": "Skjul chips, når kortet er indlejret i en strategivisning, der allerede fungerer som vinduesvælger.",
"cal_editor_show_user_filter": "Vis brugerfilter",
"cal_editor_default_user": "Standard brugerfilter",
"cal_editor_my_tasks": "Mine opgaver (aktuel bruger)",
"cal_editor_show_object_filter": "Vis objektfilter",
"cal_editor_object_hint": "Forvælg et objekt via YAML: object_filter: \"<navn>\" — eller en liste af navne for at begrænse kortet til flere objekter."
}
@@ -129,6 +129,8 @@
"notes_optional": "Notizen (optional)",
"cost_optional": "Kosten (optional)",
"duration_minutes": "Dauer in Minuten (optional)",
"completed_at_optional": "Erledigt am (optional, leer = jetzt)",
"completed_at_future_error": "Das Erledigungsdatum darf nicht in der Zukunft liegen.",
"days": "Tage",
"day": "Tag",
"today": "Heute",
@@ -193,9 +195,14 @@
"use_entity_state": "Entitäts-Zustand verwenden (kein Attribut)",
"trigger_above": "Auslösen wenn über",
"trigger_below": "Auslösen wenn unter",
"trigger_equals": "Auslösen bei genau (=)",
"trigger_not_equals": "Auslösen bei abweichend von (≠)",
"for_at_least_minutes": "Für mindestens (Minuten)",
"safety_interval_days": "Sicherheitsintervall (Tage, optional)",
"safety_interval": "Sicherheitsintervall (optional)",
"trigger_combinator": "Trigger und Intervall kombinieren",
"trigger_combinator_any": "Trigger oder Intervall (zuerst erfüllt)",
"trigger_combinator_all": "Trigger und Intervall (beides erforderlich)",
"delta_mode": "Delta-Modus",
"from_state_optional": "Von Zustand (optional)",
"to_state_optional": "Zu Zustand (optional)",
@@ -850,5 +857,17 @@
"gs_label": "Erste Schritte — diese Hinweise verschwinden, wenn dein Setup wächst",
"gs_setups_chip": "Vorgeschlagene Setups: {n} Geräte mit vorverdrahteten Auslösern gefunden",
"gs_adopt_chip": "{n} Problem-Sensoren können zu Wartungsaufgaben werden",
"gs_fleet_chip": "Ein Klick richtet die Batterieflotte ein"
"gs_fleet_chip": "Ein Klick richtet die Batterieflotte ein",
"cal_editor_window": "Standard-Zeitfenster",
"cal_editor_window_week": "Woche (7 Tage)",
"cal_editor_window_fortnight": "Zwei Wochen (14 Tage)",
"cal_editor_window_month": "Monat (30 Tage, Standard)",
"cal_editor_window_year": "Jahr (365 Tage, leere Tage ausgeblendet)",
"cal_editor_show_chips": "Zeitfenster-Chips in der Karte anzeigen",
"cal_editor_chips_hint": "Chips ausblenden, wenn die Karte in einer Strategie-Ansicht steckt, die bereits als Zeitfenster-Auswahl dient.",
"cal_editor_show_user_filter": "Benutzerfilter-Dropdown anzeigen",
"cal_editor_default_user": "Standard-Benutzerfilter",
"cal_editor_my_tasks": "Meine Aufgaben (aktueller Benutzer)",
"cal_editor_show_object_filter": "Objektfilter-Dropdown anzeigen",
"cal_editor_object_hint": "Ein Objekt per YAML vorauswählen: object_filter: \"<Objektname>\" — oder eine Namensliste, um die Karte auf mehrere Objekte zu beschränken."
}
@@ -129,6 +129,8 @@
"notes_optional": "Notes (optional)",
"cost_optional": "Cost (optional)",
"duration_minutes": "Duration in minutes (optional)",
"completed_at_optional": "Completed at (optional, empty = now)",
"completed_at_future_error": "The completion date cannot be in the future.",
"days": "days",
"day": "day",
"today": "Today",
@@ -193,9 +195,14 @@
"use_entity_state": "Use entity state (no attribute)",
"trigger_above": "Trigger above",
"trigger_below": "Trigger below",
"trigger_equals": "Trigger when equal to (=)",
"trigger_not_equals": "Trigger when different from (≠)",
"for_at_least_minutes": "For at least (minutes)",
"safety_interval_days": "Safety interval (days, optional)",
"safety_interval": "Safety interval (optional)",
"trigger_combinator": "Combine trigger and interval",
"trigger_combinator_any": "Trigger or interval (whichever first)",
"trigger_combinator_all": "Trigger and interval (both required)",
"delta_mode": "Delta mode",
"from_state_optional": "From state (optional)",
"to_state_optional": "To state (optional)",
@@ -850,5 +857,17 @@
"gs_label": "Getting started — these hints retire as your setup grows",
"gs_setups_chip": "Suggested setups found {n} devices with pre-wired triggers",
"gs_adopt_chip": "{n} problem sensors can become maintenance tasks",
"gs_fleet_chip": "One click sets up the battery fleet"
"gs_fleet_chip": "One click sets up the battery fleet",
"cal_editor_window": "Default window",
"cal_editor_window_week": "Week (7 days)",
"cal_editor_window_fortnight": "Fortnight (14 days)",
"cal_editor_window_month": "Month (30 days, default)",
"cal_editor_window_year": "Year (365 days, empty days collapsed)",
"cal_editor_show_chips": "Show window chips inside the card",
"cal_editor_chips_hint": "Hide the chips when the card is embedded in a strategy view that already serves as the window selector.",
"cal_editor_show_user_filter": "Show user filter dropdown",
"cal_editor_default_user": "Default user filter",
"cal_editor_my_tasks": "My tasks (current user)",
"cal_editor_show_object_filter": "Show object filter dropdown",
"cal_editor_object_hint": "Pre-select one object via YAML: object_filter: \"<object name>\" — or a list of names to restrict the card to several objects."
}
@@ -128,6 +128,8 @@
"notes_optional": "Notas (opcional)",
"cost_optional": "Coste (opcional)",
"duration_minutes": "Duración en minutos (opcional)",
"completed_at_optional": "Completado el (opcional, vacío = ahora)",
"completed_at_future_error": "La fecha de finalización no puede estar en el futuro.",
"days": "días",
"day": "día",
"today": "Hoy",
@@ -192,9 +194,14 @@
"use_entity_state": "Usar estado de la entidad (sin atributo)",
"trigger_above": "Activar por encima de",
"trigger_below": "Activar por debajo de",
"trigger_equals": "Activar cuando sea igual a (=)",
"trigger_not_equals": "Activar cuando sea distinto de (≠)",
"for_at_least_minutes": "Durante al menos (minutos)",
"safety_interval_days": "Intervalo de seguridad (días, opcional)",
"safety_interval": "Intervalo de seguridad (opcional)",
"trigger_combinator": "Combinar disparador e intervalo",
"trigger_combinator_any": "Disparador o intervalo (el primero)",
"trigger_combinator_all": "Disparador e intervalo (ambos requeridos)",
"delta_mode": "Modo delta",
"from_state_optional": "Desde estado (opcional)",
"to_state_optional": "Hasta estado (opcional)",
@@ -850,5 +857,17 @@
"gs_label": "Primeros pasos: estas sugerencias desaparecen a medida que crece tu configuración",
"gs_setups_chip": "Configuraciones sugeridas: {n} dispositivos con disparadores preconfigurados",
"gs_adopt_chip": "{n} sensores de problemas pueden convertirse en tareas de mantenimiento",
"gs_fleet_chip": "Un clic configura la flota de baterías"
"gs_fleet_chip": "Un clic configura la flota de baterías",
"cal_editor_window": "Ventana predeterminada",
"cal_editor_window_week": "Semana (7 días)",
"cal_editor_window_fortnight": "Quincena (14 días)",
"cal_editor_window_month": "Mes (30 días, predeterminado)",
"cal_editor_window_year": "Año (365 días, días vacíos ocultos)",
"cal_editor_show_chips": "Mostrar chips de ventana en la tarjeta",
"cal_editor_chips_hint": "Oculta los chips cuando la tarjeta está en una vista de estrategia que ya sirve como selector de ventana.",
"cal_editor_show_user_filter": "Mostrar filtro de usuario",
"cal_editor_default_user": "Filtro de usuario predeterminado",
"cal_editor_my_tasks": "Mis tareas (usuario actual)",
"cal_editor_show_object_filter": "Mostrar filtro de objeto",
"cal_editor_object_hint": "Preselecciona un objeto por YAML: object_filter: \"<nombre>\" — o una lista de nombres para limitar la tarjeta a varios objetos."
}
@@ -129,6 +129,8 @@
"notes_optional": "Muistiinpanot (valinnainen)",
"cost_optional": "Kustannus (valinnainen)",
"duration_minutes": "Kesto minuutteina (valinnainen)",
"completed_at_optional": "Suoritettu (valinnainen, tyhjä = nyt)",
"completed_at_future_error": "Suorituspäivä ei voi olla tulevaisuudessa.",
"days": "päivää",
"day": "päivä",
"today": "Tänään",
@@ -193,9 +195,14 @@
"use_entity_state": "Käytä entiteetin tilaa (ei attribuuttia)",
"trigger_above": "Laukaise yli",
"trigger_below": "Laukaise alle",
"trigger_equals": "Laukaise kun yhtä suuri kuin (=)",
"trigger_not_equals": "Laukaise kun eri kuin (≠)",
"for_at_least_minutes": "Vähintään (minuuttia)",
"safety_interval_days": "Turvaväli (päivää, valinnainen)",
"safety_interval": "Turvaväli (valinnainen)",
"trigger_combinator": "Yhdistä laukaisin ja väli",
"trigger_combinator_any": "Laukaisin tai väli (ensin täyttyvä)",
"trigger_combinator_all": "Laukaisin ja väli (molemmat vaaditaan)",
"delta_mode": "Delta-tila",
"from_state_optional": "Lähtötilasta (valinnainen)",
"to_state_optional": "Kohdetilaan (valinnainen)",
@@ -850,5 +857,17 @@
"gs_label": "Aloitus — nämä vihjeet poistuvat asennuksen kasvaessa",
"gs_setups_chip": "Ehdotetut asetukset löysivät {n} laitetta valmiilla laukaisimilla",
"gs_adopt_chip": "{n} ongelma-anturia voi muuttua huoltotehtäviksi",
"gs_fleet_chip": "Yksi napsautus määrittää akkukannan"
"gs_fleet_chip": "Yksi napsautus määrittää akkukannan",
"cal_editor_window": "Oletusikkuna",
"cal_editor_window_week": "Viikko (7 päivää)",
"cal_editor_window_fortnight": "Kaksi viikkoa (14 päivää)",
"cal_editor_window_month": "Kuukausi (30 päivää, oletus)",
"cal_editor_window_year": "Vuosi (365 päivää, tyhjät päivät piilotettu)",
"cal_editor_show_chips": "Näytä ikkunavalinnat kortissa",
"cal_editor_chips_hint": "Piilota valinnat, kun kortti on strategianäkymässä, joka jo toimii ikkunan valitsimena.",
"cal_editor_show_user_filter": "Näytä käyttäjäsuodatin",
"cal_editor_default_user": "Oletuskäyttäjäsuodatin",
"cal_editor_my_tasks": "Omat tehtävät (nykyinen käyttäjä)",
"cal_editor_show_object_filter": "Näytä kohdesuodatin",
"cal_editor_object_hint": "Esivalitse kohde YAML:lla: object_filter: \"<nimi>\" — tai nimilista rajataksesi kortin useisiin kohteisiin."
}
@@ -128,6 +128,8 @@
"notes_optional": "Notes (optionnel)",
"cost_optional": "Coût (optionnel)",
"duration_minutes": "Durée en minutes (optionnel)",
"completed_at_optional": "Effectué le (optionnel, vide = maintenant)",
"completed_at_future_error": "La date d'achèvement ne peut pas être dans le futur.",
"days": "jours",
"day": "jour",
"today": "Aujourd'hui",
@@ -192,9 +194,14 @@
"use_entity_state": "Utiliser l'état de l'entité (pas d'attribut)",
"trigger_above": "Déclencher au-dessus de",
"trigger_below": "Déclencher en dessous de",
"trigger_equals": "Déclencher si égal à (=)",
"trigger_not_equals": "Déclencher si différent de (≠)",
"for_at_least_minutes": "Pendant au moins (minutes)",
"safety_interval_days": "Intervalle de sécurité (jours, optionnel)",
"safety_interval": "Intervalle de sécurité (optionnel)",
"trigger_combinator": "Combiner déclencheur et intervalle",
"trigger_combinator_any": "Déclencheur ou intervalle (premier atteint)",
"trigger_combinator_all": "Déclencheur et intervalle (les deux requis)",
"delta_mode": "Mode delta",
"from_state_optional": "État source (optionnel)",
"to_state_optional": "État cible (optionnel)",
@@ -850,5 +857,17 @@
"gs_label": "Premiers pas — ces conseils disparaissent à mesure que votre configuration grandit",
"gs_setups_chip": "Configurations suggérées : {n} appareils avec déclencheurs pré-câblés trouvés",
"gs_adopt_chip": "{n} capteurs de problème peuvent devenir des tâches de maintenance",
"gs_fleet_chip": "Un clic configure le parc de piles"
"gs_fleet_chip": "Un clic configure le parc de piles",
"cal_editor_window": "Fenêtre par défaut",
"cal_editor_window_week": "Semaine (7 jours)",
"cal_editor_window_fortnight": "Quinzaine (14 jours)",
"cal_editor_window_month": "Mois (30 jours, défaut)",
"cal_editor_window_year": "Année (365 jours, jours vides masqués)",
"cal_editor_show_chips": "Afficher les puces de fenêtre dans la carte",
"cal_editor_chips_hint": "Masquez les puces lorsque la carte est intégrée dans une vue stratégie qui sert déjà de sélecteur de fenêtre.",
"cal_editor_show_user_filter": "Afficher le filtre utilisateur",
"cal_editor_default_user": "Filtre utilisateur par défaut",
"cal_editor_my_tasks": "Mes tâches (utilisateur actuel)",
"cal_editor_show_object_filter": "Afficher le filtre d'objet",
"cal_editor_object_hint": "Présélectionnez un objet via YAML : object_filter : \"<nom>\" — ou une liste de noms pour limiter la carte à plusieurs objets."
}
@@ -129,6 +129,8 @@
"notes_optional": "टिप्पणियाँ (वैकल्पिक)",
"cost_optional": "लागत (वैकल्पिक)",
"duration_minutes": "मिनटों में अवधि (वैकल्पिक)",
"completed_at_optional": "पूर्ण होने का समय (वैकल्पिक, खाली = अभी)",
"completed_at_future_error": "पूर्णता की तारीख भविष्य में नहीं हो सकती।",
"days": "दिन",
"day": "दिन",
"today": "आज",
@@ -193,9 +195,14 @@
"use_entity_state": "एंटिटी स्थिति का उपयोग करें (कोई विशेषता नहीं)",
"trigger_above": "इससे ऊपर ट्रिगर करें",
"trigger_below": "इससे नीचे ट्रिगर करें",
"trigger_equals": "बराबर होने पर ट्रिगर करें (=)",
"trigger_not_equals": "भिन्न होने पर ट्रिगर करें (≠)",
"for_at_least_minutes": "कम से कम (मिनट)",
"safety_interval_days": "सुरक्षा अंतराल (दिन, वैकल्पिक)",
"safety_interval": "सुरक्षा अंतराल (वैकल्पिक)",
"trigger_combinator": "ट्रिगर और अंतराल संयोजित करें",
"trigger_combinator_any": "ट्रिगर या अंतराल (जो पहले हो)",
"trigger_combinator_all": "ट्रिगर और अंतराल (दोनों आवश्यक)",
"delta_mode": "डेल्टा मोड",
"from_state_optional": "किस स्थिति से (वैकल्पिक)",
"to_state_optional": "किस स्थिति तक (वैकल्पिक)",
@@ -850,5 +857,17 @@
"gs_label": "शुरुआत — सेटअप बढ़ने पर ये संकेत हट जाते हैं",
"gs_setups_chip": "सुझाए गए सेटअप: पूर्व-निर्धारित ट्रिगर वाले {n} उपकरण मिले",
"gs_adopt_chip": "{n} समस्या सेंसर रखरखाव कार्य बन सकते हैं",
"gs_fleet_chip": "एक क्लिक में बैटरी बेड़ा सेट करें"
"gs_fleet_chip": "एक क्लिक में बैटरी बेड़ा सेट करें",
"cal_editor_window": "डिफ़ॉल्ट विंडो",
"cal_editor_window_week": "सप्ताह (7 दिन)",
"cal_editor_window_fortnight": "पखवाड़ा (14 दिन)",
"cal_editor_window_month": "महीना (30 दिन, डिफ़ॉल्ट)",
"cal_editor_window_year": "वर्ष (365 दिन, खाली दिन छिपे)",
"cal_editor_show_chips": "कार्ड में विंडो चिप्स दिखाएँ",
"cal_editor_chips_hint": "जब कार्ड ऐसी स्ट्रैटेजी व्यू में हो जो पहले से विंडो चयनक है, तो चिप्स छिपाएँ।",
"cal_editor_show_user_filter": "उपयोगकर्ता फ़िल्टर दिखाएँ",
"cal_editor_default_user": "डिफ़ॉल्ट उपयोगकर्ता फ़िल्टर",
"cal_editor_my_tasks": "मेरे कार्य (वर्तमान उपयोगकर्ता)",
"cal_editor_show_object_filter": "ऑब्जेक्ट फ़िल्टर दिखाएँ",
"cal_editor_object_hint": "YAML से एक ऑब्जेक्ट पहले से चुनें: object_filter: \"<नाम>\" — या कार्ड को कई ऑब्जेक्ट तक सीमित करने हेतु नामों की सूची।"
}
@@ -129,6 +129,8 @@
"notes_optional": "Megjegyzések (opcionális)",
"cost_optional": "Költség (opcionális)",
"duration_minutes": "Időtartam percben (opcionális)",
"completed_at_optional": "Elvégezve ekkor (opcionális, üres = most)",
"completed_at_future_error": "Az elvégzés dátuma nem lehet a jövőben.",
"days": "nap",
"day": "nap",
"today": "Ma",
@@ -193,9 +195,14 @@
"use_entity_state": "Entitás állapotának használata (attribútum nélkül)",
"trigger_above": "Kiváltás e fölött",
"trigger_below": "Kiváltás ez alatt",
"trigger_equals": "Aktiválás ha egyenlő (=)",
"trigger_not_equals": "Aktiválás ha eltér ettől (≠)",
"for_at_least_minutes": "Legalább ennyi ideig (perc)",
"safety_interval_days": "Biztonsági intervallum (nap, opcionális)",
"safety_interval": "Biztonsági intervallum (opcionális)",
"trigger_combinator": "Trigger és időköz kombinálása",
"trigger_combinator_any": "Trigger vagy időköz (amelyik előbb)",
"trigger_combinator_all": "Trigger és időköz (mindkettő szükséges)",
"delta_mode": "Delta mód",
"from_state_optional": "Kezdő állapot (opcionális)",
"to_state_optional": "Célállapot (opcionális)",
@@ -850,5 +857,17 @@
"gs_label": "Első lépések — a tippek eltűnnek, ahogy a beállítás bővül",
"gs_setups_chip": "Javasolt beállítások: {n} eszköz előre bekötött triggerekkel",
"gs_adopt_chip": "{n} problémaérzékelő karbantartási feladattá válhat",
"gs_fleet_chip": "Egy kattintás beállítja az elemflottát"
"gs_fleet_chip": "Egy kattintás beállítja az elemflottát",
"cal_editor_window": "Alapértelmezett időablak",
"cal_editor_window_week": "Hét (7 nap)",
"cal_editor_window_fortnight": "Két hét (14 nap)",
"cal_editor_window_month": "Hónap (30 nap, alapértelmezett)",
"cal_editor_window_year": "Év (365 nap, üres napok elrejtve)",
"cal_editor_show_chips": "Időablak-választók megjelenítése a kártyán",
"cal_editor_chips_hint": "Rejtsd el a választókat, ha a kártya olyan stratégianézetben van, amely már időablak-választóként szolgál.",
"cal_editor_show_user_filter": "Felhasználószűrő megjelenítése",
"cal_editor_default_user": "Alapértelmezett felhasználószűrő",
"cal_editor_my_tasks": "Saját feladatok (aktuális felhasználó)",
"cal_editor_show_object_filter": "Objektumszűrő megjelenítése",
"cal_editor_object_hint": "Előválasztás YAML-lel: object_filter: \"<név>\" — vagy névlista, hogy a kártya több objektumra korlátozódjon."
}
@@ -128,6 +128,8 @@
"notes_optional": "Note (opzionale)",
"cost_optional": "Costo (opzionale)",
"duration_minutes": "Durata in minuti (opzionale)",
"completed_at_optional": "Completato il (opzionale, vuoto = adesso)",
"completed_at_future_error": "La data di completamento non può essere nel futuro.",
"days": "giorni",
"day": "giorno",
"today": "Oggi",
@@ -192,9 +194,14 @@
"use_entity_state": "Usa stato dell'entità (nessun attributo)",
"trigger_above": "Attivare sopra",
"trigger_below": "Attivare sotto",
"trigger_equals": "Attiva quando uguale a (=)",
"trigger_not_equals": "Attiva quando diverso da (≠)",
"for_at_least_minutes": "Per almeno (minuti)",
"safety_interval_days": "Intervallo di sicurezza (giorni, opzionale)",
"safety_interval": "Intervallo di sicurezza (opzionale)",
"trigger_combinator": "Combina trigger e intervallo",
"trigger_combinator_any": "Trigger o intervallo (il primo)",
"trigger_combinator_all": "Trigger e intervallo (entrambi richiesti)",
"delta_mode": "Modalità delta",
"from_state_optional": "Dallo stato (opzionale)",
"to_state_optional": "Allo stato (opzionale)",
@@ -850,5 +857,17 @@
"gs_label": "Primi passi — questi suggerimenti scompaiono man mano che la configurazione cresce",
"gs_setups_chip": "Configurazioni suggerite: trovati {n} dispositivi con trigger preconfigurati",
"gs_adopt_chip": "{n} sensori di problemi possono diventare attività di manutenzione",
"gs_fleet_chip": "Un clic configura la flotta di batterie"
"gs_fleet_chip": "Un clic configura la flotta di batterie",
"cal_editor_window": "Finestra predefinita",
"cal_editor_window_week": "Settimana (7 giorni)",
"cal_editor_window_fortnight": "Due settimane (14 giorni)",
"cal_editor_window_month": "Mese (30 giorni, predefinito)",
"cal_editor_window_year": "Anno (365 giorni, giorni vuoti nascosti)",
"cal_editor_show_chips": "Mostra i chip della finestra nella scheda",
"cal_editor_chips_hint": "Nascondi i chip quando la scheda è in una vista strategia che funge già da selettore di finestra.",
"cal_editor_show_user_filter": "Mostra il filtro utente",
"cal_editor_default_user": "Filtro utente predefinito",
"cal_editor_my_tasks": "Le mie attività (utente attuale)",
"cal_editor_show_object_filter": "Mostra il filtro oggetto",
"cal_editor_object_hint": "Preseleziona un oggetto via YAML: object_filter: \"<nome>\" — o un elenco di nomi per limitare la scheda a più oggetti."
}
@@ -129,6 +129,8 @@
"notes_optional": "メモ(任意)",
"cost_optional": "費用(任意)",
"duration_minutes": "所要時間(分、任意)",
"completed_at_optional": "完了日時(任意・空欄 = 現在)",
"completed_at_future_error": "完了日時に未来は指定できません。",
"days": "日",
"day": "日",
"today": "今日",
@@ -193,9 +195,14 @@
"use_entity_state": "エンティティの状態を使用(属性なし)",
"trigger_above": "この値を超えたらトリガー",
"trigger_below": "この値を下回ったらトリガー",
"trigger_equals": "値が一致したらトリガー(=)",
"trigger_not_equals": "値が異なればトリガー(≠)",
"for_at_least_minutes": "最低継続時間(分)",
"safety_interval_days": "安全間隔(日、任意)",
"safety_interval": "安全間隔(任意)",
"trigger_combinator": "トリガーと間隔の組み合わせ",
"trigger_combinator_any": "トリガーまたは間隔(先に満たした方)",
"trigger_combinator_all": "トリガーと間隔(両方必須)",
"delta_mode": "差分モード",
"from_state_optional": "変化前の状態(任意)",
"to_state_optional": "変化後の状態(任意)",
@@ -850,5 +857,17 @@
"gs_label": "はじめに — セットアップが進むとこれらのヒントは消えます",
"gs_setups_chip": "推奨セットアップ:トリガー設定済みのデバイスを{n}台検出",
"gs_adopt_chip": "{n}個の問題センサーをメンテナンスタスクにできます",
"gs_fleet_chip": "ワンクリックで電池フリートを設定"
"gs_fleet_chip": "ワンクリックで電池フリートを設定",
"cal_editor_window": "既定の期間",
"cal_editor_window_week": "1週間(7日)",
"cal_editor_window_fortnight": "2週間(14日)",
"cal_editor_window_month": "1か月(30日・既定)",
"cal_editor_window_year": "1年(365日・空の日は省略)",
"cal_editor_show_chips": "カード内に期間チップを表示",
"cal_editor_chips_hint": "ストラテジービューが期間選択を担う場合はチップを非表示にします。",
"cal_editor_show_user_filter": "ユーザーフィルターを表示",
"cal_editor_default_user": "既定のユーザーフィルター",
"cal_editor_my_tasks": "自分のタスク(現在のユーザー)",
"cal_editor_show_object_filter": "オブジェクトフィルターを表示",
"cal_editor_object_hint": "YAML でオブジェクトを事前選択:object_filter: \"<名前>\" — 複数指定はカードを複数オブジェクトに限定します。"
}
@@ -129,6 +129,8 @@
"notes_optional": "메모 (선택)",
"cost_optional": "비용 (선택)",
"duration_minutes": "소요 시간(분, 선택)",
"completed_at_optional": "완료 시각 (선택, 비우면 지금)",
"completed_at_future_error": "완료 날짜는 미래일 수 없습니다.",
"days": "일",
"day": "일",
"today": "오늘",
@@ -193,9 +195,14 @@
"use_entity_state": "엔티티 상태 사용 (속성 없음)",
"trigger_above": "초과 시 트리거",
"trigger_below": "미만 시 트리거",
"trigger_equals": "값이 같으면 트리거 (=)",
"trigger_not_equals": "값이 다르면 트리거 (≠)",
"for_at_least_minutes": "최소 지속 시간 (분)",
"safety_interval_days": "안전 주기 (일, 선택)",
"safety_interval": "안전 주기 (선택)",
"trigger_combinator": "트리거와 간격 결합",
"trigger_combinator_any": "트리거 또는 간격 (먼저 충족)",
"trigger_combinator_all": "트리거와 간격 (둘 다 필요)",
"delta_mode": "델타 모드",
"from_state_optional": "변경 전 상태 (선택)",
"to_state_optional": "변경 후 상태 (선택)",
@@ -850,5 +857,17 @@
"gs_label": "시작하기 — 설정이 늘어나면 이 힌트는 사라집니다",
"gs_setups_chip": "추천 설정: 트리거가 준비된 기기 {n}대 발견",
"gs_adopt_chip": "문제 센서 {n}개를 유지보수 작업으로 만들 수 있습니다",
"gs_fleet_chip": "클릭 한 번으로 배터리 플릿 설정"
"gs_fleet_chip": "클릭 한 번으로 배터리 플릿 설정",
"cal_editor_window": "기본 기간",
"cal_editor_window_week": "1주 (7일)",
"cal_editor_window_fortnight": "2주 (14일)",
"cal_editor_window_month": "1개월 (30일, 기본)",
"cal_editor_window_year": "1년 (365일, 빈 날은 접힘)",
"cal_editor_show_chips": "카드 안에 기간 칩 표시",
"cal_editor_chips_hint": "전략 뷰가 이미 기간 선택기 역할을 하면 칩을 숨기세요.",
"cal_editor_show_user_filter": "사용자 필터 표시",
"cal_editor_default_user": "기본 사용자 필터",
"cal_editor_my_tasks": "내 작업 (현재 사용자)",
"cal_editor_show_object_filter": "객체 필터 표시",
"cal_editor_object_hint": "YAML로 객체를 미리 선택: object_filter: \"<이름>\" — 이름 목록으로 카드를 여러 객체로 제한할 수 있습니다."
}
@@ -129,6 +129,8 @@
"notes_optional": "Notater (valgfritt)",
"cost_optional": "Kostnad (valgfritt)",
"duration_minutes": "Varighet i minutter (valgfritt)",
"completed_at_optional": "Utført den (valgfritt, tomt = nå)",
"completed_at_future_error": "Fullføringsdatoen kan ikke ligge i fremtiden.",
"days": "dager",
"day": "dag",
"today": "I dag",
@@ -193,9 +195,14 @@
"use_entity_state": "Bruk entitetstilstand (ingen attributt)",
"trigger_above": "Utløs over",
"trigger_below": "Utløs under",
"trigger_equals": "Utløs ved lik (=)",
"trigger_not_equals": "Utløs ved forskjellig fra (≠)",
"for_at_least_minutes": "I minst (minutter)",
"safety_interval_days": "Sikkerhetsintervall (dager, valgfritt)",
"safety_interval": "Sikkerhetsintervall (valgfritt)",
"trigger_combinator": "Kombiner utløser og intervall",
"trigger_combinator_any": "Utløser eller intervall (først oppfylt)",
"trigger_combinator_all": "Utløser og intervall (begge kreves)",
"delta_mode": "Deltamodus",
"from_state_optional": "Fra tilstand (valgfritt)",
"to_state_optional": "Til tilstand (valgfritt)",
@@ -850,5 +857,17 @@
"gs_label": "Kom i gang — tipsene forsvinner etter hvert som oppsettet vokser",
"gs_setups_chip": "Foreslåtte oppsett fant {n} enheter med ferdigkoblede utløsere",
"gs_adopt_chip": "{n} problemsensorer kan bli vedlikeholdsoppgaver",
"gs_fleet_chip": "Ett klikk setter opp batteriflåten"
"gs_fleet_chip": "Ett klikk setter opp batteriflåten",
"cal_editor_window": "Standardvindu",
"cal_editor_window_week": "Uke (7 dager)",
"cal_editor_window_fortnight": "To uker (14 dager)",
"cal_editor_window_month": "Måned (30 dager, standard)",
"cal_editor_window_year": "År (365 dager, tomme dager skjult)",
"cal_editor_show_chips": "Vis vindus-chips i kortet",
"cal_editor_chips_hint": "Skjul chipsene når kortet er innebygd i en strategivisning som allerede fungerer som vindusvelger.",
"cal_editor_show_user_filter": "Vis brukerfilter",
"cal_editor_default_user": "Standard brukerfilter",
"cal_editor_my_tasks": "Mine oppgaver (gjeldende bruker)",
"cal_editor_show_object_filter": "Vis objektfilter",
"cal_editor_object_hint": "Forhåndsvelg et objekt via YAML: object_filter: \"<navn>\" — eller en liste med navn for å begrense kortet til flere objekter."
}
@@ -128,6 +128,8 @@
"notes_optional": "Notities (optioneel)",
"cost_optional": "Kosten (optioneel)",
"duration_minutes": "Duur in minuten (optioneel)",
"completed_at_optional": "Voltooid op (optioneel, leeg = nu)",
"completed_at_future_error": "De voltooiingsdatum mag niet in de toekomst liggen.",
"days": "dagen",
"day": "dag",
"today": "Vandaag",
@@ -192,9 +194,14 @@
"use_entity_state": "Entiteitsstatus gebruiken (geen attribuut)",
"trigger_above": "Activeren als boven",
"trigger_below": "Activeren als onder",
"trigger_equals": "Activeren bij gelijk aan (=)",
"trigger_not_equals": "Activeren bij afwijkend van (≠)",
"for_at_least_minutes": "Voor minstens (minuten)",
"safety_interval_days": "Veiligheidsinterval (dagen, optioneel)",
"safety_interval": "Veiligheidsinterval (optioneel)",
"trigger_combinator": "Trigger en interval combineren",
"trigger_combinator_any": "Trigger of interval (eerst vervuld)",
"trigger_combinator_all": "Trigger en interval (beide vereist)",
"delta_mode": "Deltamodus",
"from_state_optional": "Van status (optioneel)",
"to_state_optional": "Naar status (optioneel)",
@@ -850,5 +857,17 @@
"gs_label": "Aan de slag — deze tips verdwijnen naarmate je installatie groeit",
"gs_setups_chip": "Voorgestelde setups: {n} apparaten met vooraf ingestelde triggers gevonden",
"gs_adopt_chip": "{n} probleemsensoren kunnen onderhoudstaken worden",
"gs_fleet_chip": "Eén klik stelt het batterijpark in"
"gs_fleet_chip": "Eén klik stelt het batterijpark in",
"cal_editor_window": "Standaardvenster",
"cal_editor_window_week": "Week (7 dagen)",
"cal_editor_window_fortnight": "Twee weken (14 dagen)",
"cal_editor_window_month": "Maand (30 dagen, standaard)",
"cal_editor_window_year": "Jaar (365 dagen, lege dagen verborgen)",
"cal_editor_show_chips": "Vensterchips in de kaart tonen",
"cal_editor_chips_hint": "Verberg de chips wanneer de kaart in een strategieweergave staat die al als vensterkeuze dient.",
"cal_editor_show_user_filter": "Gebruikersfilter tonen",
"cal_editor_default_user": "Standaard gebruikersfilter",
"cal_editor_my_tasks": "Mijn taken (huidige gebruiker)",
"cal_editor_show_object_filter": "Objectfilter tonen",
"cal_editor_object_hint": "Selecteer een object vooraf via YAML: object_filter: \"<naam>\" — of een lijst met namen om de kaart tot meerdere objecten te beperken."
}
@@ -128,6 +128,8 @@
"notes_optional": "Notatki (opcjonalne)",
"cost_optional": "Koszt (opcjonalne)",
"duration_minutes": "Czas trwania w minutach (opcjonalne)",
"completed_at_optional": "Wykonano dnia (opcjonalne, puste = teraz)",
"completed_at_future_error": "Data wykonania nie może być w przyszłości.",
"days": "dni",
"day": "dzień",
"today": "Dzisiaj",
@@ -192,9 +194,14 @@
"use_entity_state": "Użyj stanu encji (bez atrybutu)",
"trigger_above": "Wyzwól powyżej",
"trigger_below": "Wyzwól poniżej",
"trigger_equals": "Wyzwól przy równym (=)",
"trigger_not_equals": "Wyzwól przy różnym od (≠)",
"for_at_least_minutes": "Przez co najmniej (minuty)",
"safety_interval_days": "Interwał bezpieczeństwa (dni, opcjonalny)",
"safety_interval": "Interwał bezpieczeństwa (opcjonalny)",
"trigger_combinator": "Połącz wyzwalacz i interwał",
"trigger_combinator_any": "Wyzwalacz lub interwał (co pierwsze)",
"trigger_combinator_all": "Wyzwalacz i interwał (oba wymagane)",
"delta_mode": "Tryb delta",
"from_state_optional": "Ze stanu (opcjonalne)",
"to_state_optional": "Do stanu (opcjonalne)",
@@ -850,5 +857,17 @@
"gs_label": "Pierwsze kroki — te wskazówki znikają wraz z rozwojem konfiguracji",
"gs_setups_chip": "Sugerowane konfiguracje: znaleziono {n} urządzeń z gotowymi wyzwalaczami",
"gs_adopt_chip": "{n} czujników problemów może stać się zadaniami konserwacji",
"gs_fleet_chip": "Jedno kliknięcie konfiguruje flotę baterii"
"gs_fleet_chip": "Jedno kliknięcie konfiguruje flotę baterii",
"cal_editor_window": "Okno domyślne",
"cal_editor_window_week": "Tydzień (7 dni)",
"cal_editor_window_fortnight": "Dwa tygodnie (14 dni)",
"cal_editor_window_month": "Miesiąc (30 dni, domyślnie)",
"cal_editor_window_year": "Rok (365 dni, puste dni ukryte)",
"cal_editor_show_chips": "Pokaż przełączniki okna na karcie",
"cal_editor_chips_hint": "Ukryj przełączniki, gdy karta jest osadzona w widoku strategii, który już pełni rolę wyboru okna.",
"cal_editor_show_user_filter": "Pokaż filtr użytkownika",
"cal_editor_default_user": "Domyślny filtr użytkownika",
"cal_editor_my_tasks": "Moje zadania (bieżący użytkownik)",
"cal_editor_show_object_filter": "Pokaż filtr obiektu",
"cal_editor_object_hint": "Wybierz obiekt w YAML: object_filter: \"<nazwa>\" — lub listę nazw, aby ograniczyć kartę do kilku obiektów."
}
@@ -129,6 +129,8 @@
"notes_optional": "Observações (opcional)",
"cost_optional": "Custo (opcional)",
"duration_minutes": "Duração em minutos (opcional)",
"completed_at_optional": "Concluído em (opcional, vazio = agora)",
"completed_at_future_error": "A data de conclusão não pode estar no futuro.",
"days": "dias",
"day": "dia",
"today": "Hoje",
@@ -193,9 +195,14 @@
"use_entity_state": "Usar o estado da entidade (sem atributo)",
"trigger_above": "Acionar acima de",
"trigger_below": "Acionar abaixo de",
"trigger_equals": "Acionar quando igual a (=)",
"trigger_not_equals": "Acionar quando diferente de (≠)",
"for_at_least_minutes": "Por pelo menos (minutos)",
"safety_interval_days": "Intervalo de segurança (dias, opcional)",
"safety_interval": "Intervalo de segurança (opcional)",
"trigger_combinator": "Combinar gatilho e intervalo",
"trigger_combinator_any": "Gatilho ou intervalo (o primeiro)",
"trigger_combinator_all": "Gatilho e intervalo (ambos exigidos)",
"delta_mode": "Modo delta",
"from_state_optional": "Do estado (opcional)",
"to_state_optional": "Para o estado (opcional)",
@@ -850,5 +857,17 @@
"gs_label": "Primeiros passos — estas dicas somem conforme a configuração cresce",
"gs_setups_chip": "Configurações sugeridas: {n} dispositivos com gatilhos pré-configurados",
"gs_adopt_chip": "{n} sensores de problema podem virar tarefas de manutenção",
"gs_fleet_chip": "Um clique configura a frota de pilhas"
"gs_fleet_chip": "Um clique configura a frota de pilhas",
"cal_editor_window": "Janela padrão",
"cal_editor_window_week": "Semana (7 dias)",
"cal_editor_window_fortnight": "Quinzena (14 dias)",
"cal_editor_window_month": "Mês (30 dias, padrão)",
"cal_editor_window_year": "Ano (365 dias, dias vazios ocultos)",
"cal_editor_show_chips": "Mostrar chips de janela no cartão",
"cal_editor_chips_hint": "Oculte os chips quando o cartão estiver em uma visão de estratégia que já serve como seletor de janela.",
"cal_editor_show_user_filter": "Mostrar filtro de usuário",
"cal_editor_default_user": "Filtro de usuário padrão",
"cal_editor_my_tasks": "Minhas tarefas (usuário atual)",
"cal_editor_show_object_filter": "Mostrar filtro de objeto",
"cal_editor_object_hint": "Pré-selecione um objeto via YAML: object_filter: \"<nome>\" — ou uma lista de nomes para limitar o cartão a vários objetos."
}
@@ -128,6 +128,8 @@
"notes_optional": "Notas (opcional)",
"cost_optional": "Custo (opcional)",
"duration_minutes": "Duração em minutos (opcional)",
"completed_at_optional": "Concluído em (opcional, vazio = agora)",
"completed_at_future_error": "A data de conclusão não pode estar no futuro.",
"days": "dias",
"day": "dia",
"today": "Hoje",
@@ -192,9 +194,14 @@
"use_entity_state": "Usar estado da entidade (sem atributo)",
"trigger_above": "Acionar acima de",
"trigger_below": "Acionar abaixo de",
"trigger_equals": "Acionar quando igual a (=)",
"trigger_not_equals": "Acionar quando diferente de (≠)",
"for_at_least_minutes": "Durante pelo menos (minutos)",
"safety_interval_days": "Intervalo de segurança (dias, opcional)",
"safety_interval": "Intervalo de segurança (opcional)",
"trigger_combinator": "Combinar acionador e intervalo",
"trigger_combinator_any": "Acionador ou intervalo (o primeiro)",
"trigger_combinator_all": "Acionador e intervalo (ambos exigidos)",
"delta_mode": "Modo delta",
"from_state_optional": "Do estado (opcional)",
"to_state_optional": "Para o estado (opcional)",
@@ -850,5 +857,17 @@
"gs_label": "Primeiros passos — estas dicas desaparecem à medida que a configuração cresce",
"gs_setups_chip": "Configurações sugeridas: {n} dispositivos com gatilhos pré-configurados",
"gs_adopt_chip": "{n} sensores de problema podem tornar-se tarefas de manutenção",
"gs_fleet_chip": "Um clique configura a frota de pilhas"
"gs_fleet_chip": "Um clique configura a frota de pilhas",
"cal_editor_window": "Janela predefinida",
"cal_editor_window_week": "Semana (7 dias)",
"cal_editor_window_fortnight": "Quinzena (14 dias)",
"cal_editor_window_month": "Mês (30 dias, predefinido)",
"cal_editor_window_year": "Ano (365 dias, dias vazios ocultos)",
"cal_editor_show_chips": "Mostrar chips de janela no cartão",
"cal_editor_chips_hint": "Oculte os chips quando o cartão está numa vista de estratégia que já serve de seletor de janela.",
"cal_editor_show_user_filter": "Mostrar filtro de utilizador",
"cal_editor_default_user": "Filtro de utilizador predefinido",
"cal_editor_my_tasks": "As minhas tarefas (utilizador atual)",
"cal_editor_show_object_filter": "Mostrar filtro de objeto",
"cal_editor_object_hint": "Pré-selecione um objeto via YAML: object_filter: \"<nome>\" — ou uma lista de nomes para limitar o cartão a vários objetos."
}
@@ -128,6 +128,8 @@
"notes_optional": "Примечания (опционально)",
"cost_optional": "Стоимость (опционально)",
"duration_minutes": "Длительность в минутах (опционально)",
"completed_at_optional": "Выполнено (необязательно, пусто = сейчас)",
"completed_at_future_error": "Дата выполнения не может быть в будущем.",
"days": "дней",
"day": "день",
"today": "Сегодня",
@@ -192,9 +194,14 @@
"use_entity_state": "Использовать состояние сущности (без атрибута)",
"trigger_above": "Срабатывать выше",
"trigger_below": "Срабатывать ниже",
"trigger_equals": "Срабатывать при равенстве (=)",
"trigger_not_equals": "Срабатывать при отличии от (≠)",
"for_at_least_minutes": "Не менее (минут)",
"safety_interval_days": "Интервал безопасности (дни, опционально)",
"safety_interval": "Интервал безопасности (опционально)",
"trigger_combinator": "Совместить триггер и интервал",
"trigger_combinator_any": "Триггер или интервал (что раньше)",
"trigger_combinator_all": "Триггер и интервал (оба условия)",
"delta_mode": "Режим дельты",
"from_state_optional": "Из состояния (опционально)",
"to_state_optional": "В состояние (опционально)",
@@ -850,5 +857,17 @@
"gs_label": "Первые шаги — эти подсказки исчезнут по мере роста настройки",
"gs_setups_chip": "Рекомендуемые настройки: найдено {n} устройств с готовыми триггерами",
"gs_adopt_chip": "{n} датчиков проблем могут стать задачами обслуживания",
"gs_fleet_chip": "Один клик настроит парк батарей"
"gs_fleet_chip": "Один клик настроит парк батарей",
"cal_editor_window": "Окно по умолчанию",
"cal_editor_window_week": "Неделя (7 дней)",
"cal_editor_window_fortnight": "Две недели (14 дней)",
"cal_editor_window_month": "Месяц (30 дней, по умолчанию)",
"cal_editor_window_year": "Год (365 дней, пустые дни скрыты)",
"cal_editor_show_chips": "Показывать чипы окна в карточке",
"cal_editor_chips_hint": "Скройте чипы, если карточка встроена в стратегию, которая уже служит выбором окна.",
"cal_editor_show_user_filter": "Показывать фильтр пользователя",
"cal_editor_default_user": "Фильтр пользователя по умолчанию",
"cal_editor_my_tasks": "Мои задачи (текущий пользователь)",
"cal_editor_show_object_filter": "Показывать фильтр объекта",
"cal_editor_object_hint": "Предварительный выбор объекта через YAML: object_filter: \"<имя>\" — или список имён, чтобы ограничить карточку несколькими объектами."
}
@@ -128,6 +128,8 @@
"notes_optional": "Anteckningar (valfritt)",
"cost_optional": "Kostnad (valfritt)",
"duration_minutes": "Varaktighet i minuter (valfritt)",
"completed_at_optional": "Utförd den (valfritt, tomt = nu)",
"completed_at_future_error": "Slutförandedatumet får inte ligga i framtiden.",
"days": "dagar",
"day": "dag",
"today": "Idag",
@@ -192,9 +194,14 @@
"use_entity_state": "Använd entitetstillstånd (inget attribut)",
"trigger_above": "Utlös över",
"trigger_below": "Utlös under",
"trigger_equals": "Utlös vid lika med (=)",
"trigger_not_equals": "Utlös vid skilt från (≠)",
"for_at_least_minutes": "Under minst (minuter)",
"safety_interval_days": "Säkerhetsintervall (dagar, valfritt)",
"safety_interval": "Säkerhetsintervall (valfritt)",
"trigger_combinator": "Kombinera utlösare och intervall",
"trigger_combinator_any": "Utlösare eller intervall (först uppfylld)",
"trigger_combinator_all": "Utlösare och intervall (båda krävs)",
"delta_mode": "Delta-läge",
"from_state_optional": "Från tillstånd (valfritt)",
"to_state_optional": "Till tillstånd (valfritt)",
@@ -850,5 +857,17 @@
"gs_label": "Kom igång — tipsen försvinner när din installation växer",
"gs_setups_chip": "Föreslagna uppsättningar hittade {n} enheter med förkopplade utlösare",
"gs_adopt_chip": "{n} problemsensorer kan bli underhållsuppgifter",
"gs_fleet_chip": "Ett klick konfigurerar batteriflottan"
"gs_fleet_chip": "Ett klick konfigurerar batteriflottan",
"cal_editor_window": "Standardfönster",
"cal_editor_window_week": "Vecka (7 dagar)",
"cal_editor_window_fortnight": "Två veckor (14 dagar)",
"cal_editor_window_month": "Månad (30 dagar, standard)",
"cal_editor_window_year": "År (365 dagar, tomma dagar dolda)",
"cal_editor_show_chips": "Visa fönsterchips i kortet",
"cal_editor_chips_hint": "Dölj chipsen när kortet är inbäddat i en strategivy som redan fungerar som fönsterväljare.",
"cal_editor_show_user_filter": "Visa användarfilter",
"cal_editor_default_user": "Standardanvändarfilter",
"cal_editor_my_tasks": "Mina uppgifter (aktuell användare)",
"cal_editor_show_object_filter": "Visa objektfilter",
"cal_editor_object_hint": "Förvälj ett objekt via YAML: object_filter: \"<namn>\" — eller en lista med namn för att begränsa kortet till flera objekt."
}
@@ -129,6 +129,8 @@
"notes_optional": "Notlar (isteğe bağlı)",
"cost_optional": "Maliyet (isteğe bağlı)",
"duration_minutes": "Dakika cinsinden süre (isteğe bağlı)",
"completed_at_optional": "Tamamlanma zamanı (isteğe bağlı, boş = şimdi)",
"completed_at_future_error": "Tamamlanma tarihi gelecekte olamaz.",
"days": "gün",
"day": "gün",
"today": "Bugün",
@@ -193,9 +195,14 @@
"use_entity_state": "Varlık durumunu kullan (öznitelik yok)",
"trigger_above": "Üstünde tetikle",
"trigger_below": "Altında tetikle",
"trigger_equals": "Şuna eşitse tetikle (=)",
"trigger_not_equals": "Şundan farklıysa tetikle (≠)",
"for_at_least_minutes": "En az (dakika)",
"safety_interval_days": "Güvenlik aralığı (gün, isteğe bağlı)",
"safety_interval": "Güvenlik aralığı (isteğe bağlı)",
"trigger_combinator": "Tetikleyici ve aralığı birleştir",
"trigger_combinator_any": "Tetikleyici veya aralık (ilk gerçekleşen)",
"trigger_combinator_all": "Tetikleyici ve aralık (her ikisi gerekli)",
"delta_mode": "Fark modu",
"from_state_optional": "Başlangıç durumu (isteğe bağlı)",
"to_state_optional": "Hedef durum (isteğe bağlı)",
@@ -850,5 +857,17 @@
"gs_label": "Başlarken — kurulumunuz büyüdükçe bu ipuçları kaybolur",
"gs_setups_chip": "Önerilen kurulumlar {n} cihaz buldu (hazır tetikleyicilerle)",
"gs_adopt_chip": "{n} sorun sensörü bakım görevine dönüşebilir",
"gs_fleet_chip": "Tek tıkla pil filosunu kurun"
"gs_fleet_chip": "Tek tıkla pil filosunu kurun",
"cal_editor_window": "Varsayılan pencere",
"cal_editor_window_week": "Hafta (7 gün)",
"cal_editor_window_fortnight": "İki hafta (14 gün)",
"cal_editor_window_month": "Ay (30 gün, varsayılan)",
"cal_editor_window_year": "Yıl (365 gün, boş günler gizli)",
"cal_editor_show_chips": "Pencere seçeneklerini kartta göster",
"cal_editor_chips_hint": "Kart, zaten pencere seçici görevi gören bir strateji görünümüne gömülüyse seçenekleri gizleyin.",
"cal_editor_show_user_filter": "Kullanıcı filtresini göster",
"cal_editor_default_user": "Varsayılan kullanıcı filtresi",
"cal_editor_my_tasks": "Görevlerim (geçerli kullanıcı)",
"cal_editor_show_object_filter": "Nesne filtresini göster",
"cal_editor_object_hint": "YAML ile bir nesne önceden seçin: object_filter: \"<ad>\" — veya kartı birden çok nesneyle sınırlamak için ad listesi."
}
@@ -128,6 +128,8 @@
"notes_optional": "Примітки (необов'язково)",
"cost_optional": "Вартість (необов'язково)",
"duration_minutes": "Тривалість у хвилинах (необов'язково)",
"completed_at_optional": "Виконано (необов'язково, порожньо = зараз)",
"completed_at_future_error": "Дата виконання не може бути в майбутньому.",
"days": "днів",
"day": "день",
"today": "Сьогодні",
@@ -192,9 +194,14 @@
"use_entity_state": "Використовувати стан об'єкта (без атрибута)",
"trigger_above": "Спрацювати, коли вище",
"trigger_below": "Спрацювати, коли нижче",
"trigger_equals": "Спрацьовувати при рівності (=)",
"trigger_not_equals": "Спрацьовувати при відмінності від (≠)",
"for_at_least_minutes": "Протягом не менше (хвилин)",
"safety_interval_days": "Страховий інтервал (дні, необов'язково)",
"safety_interval": "Страховий інтервал (необов'язково)",
"trigger_combinator": "Поєднати тригер та інтервал",
"trigger_combinator_any": "Тригер або інтервал (що раніше)",
"trigger_combinator_all": "Тригер та інтервал (обидва потрібні)",
"delta_mode": "Режим дельти",
"from_state_optional": "З стану (необов'язково)",
"to_state_optional": "До стану (необов'язково)",
@@ -850,5 +857,17 @@
"gs_label": "Перші кроки — ці підказки зникнуть у міру зростання налаштування",
"gs_setups_chip": "Рекомендовані налаштування: знайдено {n} пристроїв із готовими тригерами",
"gs_adopt_chip": "{n} датчиків проблем можуть стати завданнями обслуговування",
"gs_fleet_chip": "Один клік налаштує парк батарей"
"gs_fleet_chip": "Один клік налаштує парк батарей",
"cal_editor_window": "Вікно за замовчуванням",
"cal_editor_window_week": "Тиждень (7 днів)",
"cal_editor_window_fortnight": "Два тижні (14 днів)",
"cal_editor_window_month": "Місяць (30 днів, типово)",
"cal_editor_window_year": "Рік (365 днів, порожні дні приховано)",
"cal_editor_show_chips": "Показувати чипи вікна в картці",
"cal_editor_chips_hint": "Приховайте чипи, якщо картка вбудована в стратегію, що вже слугує вибором вікна.",
"cal_editor_show_user_filter": "Показувати фільтр користувача",
"cal_editor_default_user": "Типовий фільтр користувача",
"cal_editor_my_tasks": "Мої завдання (поточний користувач)",
"cal_editor_show_object_filter": "Показувати фільтр об'єкта",
"cal_editor_object_hint": "Попередній вибір об'єкта через YAML: object_filter: \"<назва>\" — або список назв, щоб обмежити картку кількома об'єктами."
}
@@ -129,6 +129,8 @@
"notes_optional": "备注 (可选)",
"cost_optional": "成本 (可选)",
"duration_minutes": "耗时 (分钟, 可选)",
"completed_at_optional": "完成时间(可选,留空 = 现在)",
"completed_at_future_error": "完成日期不能是未来时间。",
"days": "天",
"day": "天",
"today": "今天",
@@ -193,9 +195,14 @@
"use_entity_state": "使用实体状态 (不使用属性)",
"trigger_above": "高于此值触发",
"trigger_below": "低于此值触发",
"trigger_equals": "等于时触发(=)",
"trigger_not_equals": "不等于时触发(≠)",
"for_at_least_minutes": "持续至少 (分钟)",
"safety_interval_days": "安全间隔 (天, 可选)",
"safety_interval": "安全间隔 (可选)",
"trigger_combinator": "组合触发器与间隔",
"trigger_combinator_any": "触发器或间隔(先到者)",
"trigger_combinator_all": "触发器与间隔(两者皆需)",
"delta_mode": "增量模式",
"from_state_optional": "起始状态 (可选)",
"to_state_optional": "目标状态 (可选)",
@@ -850,5 +857,17 @@
"gs_label": "入门提示——随着配置的完善,这些提示会自动消失",
"gs_setups_chip": "推荐配置发现 {n} 台设备(含预设触发器)",
"gs_adopt_chip": "{n} 个问题传感器可转换为维护任务",
"gs_fleet_chip": "一键设置电池车队"
"gs_fleet_chip": "一键设置电池车队",
"cal_editor_window": "默认时间窗",
"cal_editor_window_week": "一周(7天)",
"cal_editor_window_fortnight": "两周(14天)",
"cal_editor_window_month": "一个月(30天,默认)",
"cal_editor_window_year": "一年(365天,空白日折叠)",
"cal_editor_show_chips": "在卡片内显示时间窗标签",
"cal_editor_chips_hint": "当卡片嵌入已充当时间窗选择器的策略视图时,请隐藏标签。",
"cal_editor_show_user_filter": "显示用户筛选",
"cal_editor_default_user": "默认用户筛选",
"cal_editor_my_tasks": "我的任务(当前用户)",
"cal_editor_show_object_filter": "显示对象筛选",
"cal_editor_object_hint": "通过 YAML 预选对象:object_filter: \"<对象名>\" — 或名称列表,将卡片限定为多个对象。"
}
@@ -5,11 +5,12 @@
* (clock vs trending-up), prediction-confidence pill, projected recurrences
* at 55% opacity, today-pill highlight, empty-day collapsing in the year view.
*
* Click on an event fires an ``ll-custom`` event with payload
* ``{type: "maintenance-supporter:open-task", entry_id, task_id}``. The
* dashboard-strategy bundle's document-level handler picks that up and
* either opens the task dialog in-place (preferred) or deep-links into the
* panel as a fallback.
* Click on an event opens the task quick-actions dialog (future events) or
* the history-edit dialog (past events) DIRECTLY via the shared dialog-mount
* — so clicks work on any dashboard, with or without the strategy bundle.
* When the dialog helper cannot mount, an ``ll-custom`` event
* (``{type: "maintenance-supporter:open-task", entry_id, task_id}``) is
* dispatched as the fallback for the strategy bundle's document listener.
*
* Card config:
*
@@ -36,6 +37,7 @@ import {
import { calendarStyles } from "./calendar-styles";
import { sharedStyles, DEFAULT_CURRENCY_SYMBOL, t, ensureLocale, isLocaleLoaded, setDateTimePrefs, formatDueDays, langOf } from "./styles";
import { registerCustomCard } from "./helpers/register-card";
import { openHistoryEditDialog, openTaskQuickActions } from "./dialog-mount";
import type {
HomeAssistant,
MaintenanceObjectResponse,
@@ -200,23 +202,17 @@ export class MaintenanceCalendarCard extends LitElement {
private _onEventClick(ev: CalendarEvent): void {
// Past events carry a history_timestamp — those open the history-edit
// dialog instead of the task editor. Future / next_due events open
// the task editor as usual.
// dialog instead of the task editor. Future / next_due events open the
// task quick-actions. Dialogs open DIRECTLY via the shared dialog-mount
// (same fix the task card got): the ll-custom event this used to
// dispatch is only handled by the strategy bundle's document listener,
// so on a plain dashboard the clicks silently did nothing. ll-custom
// stays as the fallback when the dialog helper cannot mount.
if (ev.history_timestamp) {
this.dispatchEvent(
new CustomEvent("ll-custom", {
detail: {
type: "maintenance-supporter:edit-history",
entry_id: ev.entry_id,
task_id: ev.task_id,
original_timestamp: ev.history_timestamp,
},
bubbles: true,
composed: true,
}),
);
void this._openHistoryEntry(ev);
return;
}
if (openTaskQuickActions(ev.entry_id, ev.task_id)) return;
this.dispatchEvent(
new CustomEvent("ll-custom", {
detail: {
@@ -230,6 +226,48 @@ export class MaintenanceCalendarCard extends LitElement {
);
}
/** Fetch the recorded entry and open the history-edit dialog directly
* (mirrors the strategy shim's ll-custom "edit-history" path). */
private async _openHistoryEntry(ev: CalendarEvent): Promise<void> {
try {
const resp = await this.hass.connection.sendMessagePromise<{
tasks?: Array<{ id: string; history?: Array<Record<string, unknown>> }>;
}>({ type: "maintenance_supporter/object", entry_id: ev.entry_id });
const entry = resp.tasks
?.find((tk) => tk.id === ev.task_id)
?.history?.find((h) => h.timestamp === ev.history_timestamp);
if (!entry) return;
const opened = openHistoryEditDialog({
entry_id: ev.entry_id,
task_id: ev.task_id,
original_timestamp: ev.history_timestamp!,
type: (entry.type as string) || "completed",
timestamp: (entry.timestamp as string) || ev.history_timestamp!,
notes: (entry.notes as string | null) ?? null,
cost: (entry.cost as number | null) ?? null,
duration: (entry.duration as number | null) ?? null,
completed_by: (entry.completed_by as string | null) ?? null,
used_parts:
(entry.used_parts as Array<{ part_id: string; name?: string; quantity: number; entry_id?: string }> | null) ?? null,
});
if (opened) return;
} catch {
/* fall through to the ll-custom fallback below */
}
this.dispatchEvent(
new CustomEvent("ll-custom", {
detail: {
type: "maintenance-supporter:edit-history",
entry_id: ev.entry_id,
task_id: ev.task_id,
original_timestamp: ev.history_timestamp,
},
bubbles: true,
composed: true,
}),
);
}
render() {
if (!this.hass) return nothing;
@@ -456,11 +494,11 @@ export class MaintenanceCalendarCard extends LitElement {
// and user-filter on/off. Same pattern as MaintenanceSupporterCardEditor —
// LitElement with setConfig + dispatched config-changed.
const WINDOW_DAY_OPTIONS: Array<{ value: WindowDays; label: string }> = [
{ value: 7, label: "Week (7 days)" },
{ value: 14, label: "Fortnight (14 days)" },
{ value: 30, label: "Month (30 days, default)" },
{ value: 365, label: "Year (365 days, empty days collapsed)" },
const WINDOW_DAY_KEYS: Array<{ value: WindowDays; key: string }> = [
{ value: 7, key: "cal_editor_window_week" },
{ value: 14, key: "cal_editor_window_fortnight" },
{ value: 30, key: "cal_editor_window_month" },
{ value: 365, key: "cal_editor_window_year" },
];
class MaintenanceCalendarCardEditor extends LitElement {
@@ -469,10 +507,21 @@ class MaintenanceCalendarCardEditor extends LitElement {
type: "custom:maintenance-supporter-calendar-card",
};
private get _lang(): string {
return langOf(this.hass);
}
setConfig(config: CalendarCardConfig): void {
this._config = { ...config };
}
/** The editor renders before the locale JSON is fetched — re-render once
* it lands so the labels localize (same pattern as the card itself). */
updated(): void {
const lang = this._lang;
if (lang && !isLocaleLoaded(lang)) void ensureLocale(lang).then(() => this.requestUpdate());
}
private _valueChanged(key: keyof CalendarCardConfig, value: unknown): void {
const newConfig = { ...this._config, [key]: value } as CalendarCardConfig;
// Drop default-equivalent values so saved YAML stays minimal
@@ -502,6 +551,7 @@ class MaintenanceCalendarCardEditor extends LitElement {
}
render() {
const L = this._lang;
const currentWindow = this._config.window_days ?? 30;
const showChips = this._config.show_window_chips !== false;
const showUserFilter = this._config.show_user_filter !== false;
@@ -510,7 +560,7 @@ class MaintenanceCalendarCardEditor extends LitElement {
return html`
<div class="editor">
<div class="row">
<label for="title">Title (optional)</label>
<label for="title">${t("card_title", L)}</label>
<input
id="title"
type="text"
@@ -520,7 +570,7 @@ class MaintenanceCalendarCardEditor extends LitElement {
/>
</div>
<div class="row">
<label for="window">Default window</label>
<label for="window">${t("cal_editor_window", L)}</label>
<select
id="window"
@change=${(e: Event) =>
@@ -529,14 +579,14 @@ class MaintenanceCalendarCardEditor extends LitElement {
Number((e.target as HTMLSelectElement).value) as WindowDays,
)}
>
${WINDOW_DAY_OPTIONS.map(
${WINDOW_DAY_KEYS.map(
(o) =>
html`<option value="${o.value}" ?selected=${o.value === currentWindow}>${o.label}</option>`,
html`<option value="${o.value}" ?selected=${o.value === currentWindow}>${t(o.key, L)}</option>`,
)}
</select>
</div>
<div class="row toggle">
<label for="chips">Show window chips inside the card</label>
<label for="chips">${t("cal_editor_show_chips", L)}</label>
<input
id="chips"
type="checkbox"
@@ -548,12 +598,9 @@ class MaintenanceCalendarCardEditor extends LitElement {
)}
/>
</div>
<div class="hint">
Hide the chips when the card is embedded in a strategy view that
already serves as the window selector.
</div>
<div class="hint">${t("cal_editor_chips_hint", L)}</div>
<div class="row toggle">
<label for="userf">Show user filter dropdown</label>
<label for="userf">${t("cal_editor_show_user_filter", L)}</label>
<input
id="userf"
type="checkbox"
@@ -566,7 +613,7 @@ class MaintenanceCalendarCardEditor extends LitElement {
/>
</div>
<div class="row">
<label for="userv">Default user filter</label>
<label for="userv">${t("cal_editor_default_user", L)}</label>
<select
id="userv"
@change=${(e: Event) =>
@@ -575,14 +622,14 @@ class MaintenanceCalendarCardEditor extends LitElement {
(e.target as HTMLSelectElement).value,
)}
>
<option value="" ?selected=${userFilter === ""}>All users</option>
<option value="" ?selected=${userFilter === ""}>${t("all_users", L)}</option>
<option value="current_user" ?selected=${userFilter === "current_user"}>
My tasks (current user)
${t("cal_editor_my_tasks", L)}
</option>
</select>
</div>
<div class="row toggle">
<label for="objf">Show object filter dropdown</label>
<label for="objf">${t("cal_editor_show_object_filter", L)}</label>
<input
id="objf"
type="checkbox"
@@ -594,10 +641,7 @@ class MaintenanceCalendarCardEditor extends LitElement {
)}
/>
</div>
<div class="hint">
Pre-select one object via YAML: object_filter: "&lt;object name&gt;" — or a
list of names to restrict the card to several objects.
</div>
<div class="hint">${t("cal_editor_object_hint", L)}</div>
</div>
`;
}
@@ -50,6 +50,12 @@ export function renderTriggerProgress(row: TaskRow | MaintenanceTask) {
const range = high - below || 1;
pct = Math.min(100, Math.max(0, ((high - val) / range) * 100));
label = `${val.toFixed(1)} / ${below} ${unit}`;
} else if (tc.trigger_equals != null || tc.trigger_not_equals != null) {
// Discrete = / ≠ levels have no meaningful gradient — binary bar,
// same treatment as compound.
const target = tc.trigger_equals != null ? `= ${tc.trigger_equals}` : `≠ ${tc.trigger_not_equals}`;
label = `${val.toFixed(1)} (${target}${unit ? ` ${unit}` : ""})`;
pct = row.trigger_active ? 100 : 0;
} else {
return nothing;
}
@@ -98,6 +98,8 @@ export function renderTriggerSection(task: MaintenanceTask, ctx: SparklineContex
${triggerType === "threshold" ? html`
${tc.trigger_above != null ? html`<span class="trigger-limit-item"><span class="dot warn" aria-hidden="true"></span> ${t("threshold_above", L)}: ${tc.trigger_above} ${unit}</span>` : nothing}
${tc.trigger_below != null ? html`<span class="trigger-limit-item"><span class="dot warn" aria-hidden="true"></span> ${t("threshold_below", L)}: ${tc.trigger_below} ${unit}</span>` : nothing}
${tc.trigger_equals != null ? html`<span class="trigger-limit-item"><span class="dot warn" aria-hidden="true"></span> = ${tc.trigger_equals} ${unit}</span>` : nothing}
${tc.trigger_not_equals != null ? html`<span class="trigger-limit-item"><span class="dot warn" aria-hidden="true"></span> ≠ ${tc.trigger_not_equals} ${unit}</span>` : nothing}
${tc.trigger_for_minutes ? html`<span class="trigger-limit-item"><span class="dot range" aria-hidden="true"></span> ${t("for_minutes", L)}: ${tc.trigger_for_minutes}</span>` : nothing}
` : nothing}
${triggerType === "state_change" ? html`
@@ -56,6 +56,10 @@ export interface TriggerConfig {
type?: string; // "threshold" | "counter" | "state_change" | "runtime"
trigger_above?: number | null;
trigger_below?: number | null;
trigger_equals?: number | null;
trigger_not_equals?: number | null;
/** "any" (default) = trigger or safety interval, whichever first; "all" = both required. */
trigger_combinator?: string;
trigger_for_minutes?: number;
trigger_target_value?: number;
trigger_delta_mode?: boolean;
@@ -48,6 +48,8 @@ const FIELD_LABEL_KEYS: Record<string, string> = {
environmental_attribute: "environmental_attribute_optional",
trigger_above: "trigger_above",
trigger_below: "trigger_below",
trigger_equals: "trigger_equals",
trigger_not_equals: "trigger_not_equals",
trigger_for_minutes: "trigger_for_minutes",
};