291 files
This commit is contained in:
+89
-56
@@ -11,6 +11,12 @@
|
||||
* under another name starts unticked with that task's name; a summary says
|
||||
* per object how many tasks it has before and after. Typing another object
|
||||
* asks the server again (problem_sensors/preview).
|
||||
*
|
||||
* #211 (54 problem sensors of 18 devices, on a phone): the summary grew a
|
||||
* line per object and squeezed the list, the only part that could shrink,
|
||||
* to nothing. The dialog now sits in the shared modal frame: the title and
|
||||
* the buttons stay, everything between them scrolls as one, and the summary
|
||||
* folds to its totals once it names more than three objects.
|
||||
*/
|
||||
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
@@ -18,6 +24,7 @@ import { property, state } from "lit/decorators.js";
|
||||
|
||||
import { t, ensureLocale, langOf } from "../styles";
|
||||
import { runWs } from "../helpers/ws-run";
|
||||
import { focusModalShell, modalShellStyles, renderModalShell } from "../helpers/modal-shell";
|
||||
import { TRIGGER_FOR_MINUTES_RANGE } from "../helpers/setting-ranges";
|
||||
import { UserService } from "../user-service";
|
||||
import type { HAUser, HomeAssistant } from "../types";
|
||||
@@ -52,6 +59,16 @@ interface AdoptResponse {
|
||||
errors?: string[];
|
||||
}
|
||||
|
||||
/** One object of the summary: the tasks it gains (entry null = a new object). */
|
||||
interface SummaryGroup {
|
||||
name: string;
|
||||
entry: string | null;
|
||||
adding: number;
|
||||
}
|
||||
|
||||
/** Up to this many objects the summary opens with its lines shown. */
|
||||
const SUMMARY_LINES_OPEN = 3;
|
||||
|
||||
export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@@ -74,6 +91,9 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
// #136: minutes the problem must persist before the created task triggers
|
||||
// (one field applied to every selection). "0" = react to the first flicker.
|
||||
@state() private _forMinutes = "0";
|
||||
/** #211: the summary's lines shown; decided when the list arrives (folded
|
||||
* beyond three objects), then the user's. */
|
||||
@state() private _summaryOpen = true;
|
||||
|
||||
private _localeReady = false;
|
||||
private _userService: UserService | null = null;
|
||||
@@ -87,6 +107,7 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
this._localeReady = true;
|
||||
ensureLocale(this._lang).then(() => this.requestUpdate());
|
||||
}
|
||||
if (changed.has("_open") && this._open) focusModalShell(this.shadowRoot);
|
||||
}
|
||||
|
||||
public async open(): Promise<void> {
|
||||
@@ -125,6 +146,7 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
// What the target probably already watches starts unticked.
|
||||
this._selected = new Set(this._sensors.filter((s) => !s.covered_by).map((s) => s.entity_id));
|
||||
this._users = users;
|
||||
this._summaryOpen = this._summaryGroups().length <= SUMMARY_LINES_OPEN;
|
||||
}
|
||||
|
||||
/** The default object: the one linked to the device, else the one the
|
||||
@@ -169,9 +191,9 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
if (resp?.covered) this._covered = { ...this._covered, ...resp.covered };
|
||||
}
|
||||
|
||||
/** Per target object: tasks before → after (only ticked rows count). */
|
||||
private _summary(L: string) {
|
||||
const groups = new Map<string, { name: string; entry: string | null; adding: number }>();
|
||||
/** The objects the ticked rows go to, each with the tasks it gains. */
|
||||
private _summaryGroups(): SummaryGroup[] {
|
||||
const groups = new Map<string, SummaryGroup>();
|
||||
for (const s of this._sensors) {
|
||||
if (!this._selected.has(s.entity_id)) continue;
|
||||
const entry = this._existingEntryFor(s);
|
||||
@@ -181,11 +203,30 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
g.adding += 1;
|
||||
groups.set(key, g);
|
||||
}
|
||||
if (groups.size === 0) return nothing;
|
||||
return [...groups.values()];
|
||||
}
|
||||
|
||||
/** Per target object: tasks before → after (only ticked rows count), under
|
||||
* a line with the totals that stays when the lines are folded (#211). */
|
||||
private _summary(L: string) {
|
||||
const groups = this._summaryGroups();
|
||||
if (groups.length === 0) return nothing;
|
||||
const created = groups.filter((g) => !g.entry).length;
|
||||
const totals = t(created ? "adopt_summary_totals_new" : "adopt_summary_totals", L)
|
||||
.replace("{tasks}", String(groups.reduce((n, g) => n + g.adding, 0)))
|
||||
.replace("{objects}", String(groups.length))
|
||||
.replace("{new}", String(created));
|
||||
return html`
|
||||
<div class="summary">
|
||||
<div class="summary-title">${t("adopt_summary_title", L)}</div>
|
||||
${[...groups.values()].map((g) => {
|
||||
<details
|
||||
class="summary"
|
||||
.open=${this._summaryOpen}
|
||||
@toggle=${(e: Event) => { this._summaryOpen = (e.target as HTMLDetailsElement).open; }}
|
||||
>
|
||||
<summary>
|
||||
<span class="summary-title">${t("adopt_summary_title", L)}</span>
|
||||
<span class="summary-totals">${totals}</span>
|
||||
</summary>
|
||||
${groups.map((g) => {
|
||||
if (!g.entry) {
|
||||
return html`<div class="summary-line new">
|
||||
${t("setups_new_object_count", L).replace("{name}", g.name).replace("{count}", String(g.adding))}
|
||||
@@ -199,7 +240,7 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
.replace("{after}", String(before + g.adding))}
|
||||
</div>`;
|
||||
})}
|
||||
</div>
|
||||
</details>
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -269,13 +310,12 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
const allSelected =
|
||||
this._sensors.length > 0 && this._selected.size === this._sensors.length;
|
||||
|
||||
return html`
|
||||
<div class="overlay" @click=${this._close}>
|
||||
<div class="card" @click=${(e: Event) => e.stopPropagation()}>
|
||||
<div class="title">${t("adopt_problem_title", L)}</div>
|
||||
<div class="hint">${t("adopt_problem_hint", L)}</div>
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : nothing}
|
||||
return renderModalShell(() => this._close(), html`
|
||||
<div class="title">${t("adopt_problem_title", L)}</div>
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : nothing}
|
||||
|
||||
<div class="dialog-scroll">
|
||||
<div class="hint">${t("adopt_problem_hint", L)}</div>
|
||||
${this._loading
|
||||
? html`<div class="loading">…</div>`
|
||||
: this._sensors.length === 0
|
||||
@@ -392,47 +432,28 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
</label>
|
||||
`
|
||||
: nothing}
|
||||
|
||||
<div class="actions">
|
||||
<ha-button appearance="plain" @click=${this._close}>
|
||||
${t("cancel", L)}
|
||||
</ha-button>
|
||||
<ha-button
|
||||
@click=${this._adopt}
|
||||
.disabled=${this._selected.size === 0 || this._adopting}
|
||||
>
|
||||
${t("adopt_problem_adopt", L)}
|
||||
</ha-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
<div class="actions">
|
||||
<ha-button appearance="plain" @click=${this._close}>
|
||||
${t("cancel", L)}
|
||||
</ha-button>
|
||||
<ha-button
|
||||
@click=${this._adopt}
|
||||
.disabled=${this._selected.size === 0 || this._adopting}
|
||||
>
|
||||
${t("adopt_problem_adopt", L)}
|
||||
</ha-button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-background-color, #fff);
|
||||
color: var(--primary-text-color);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-width: min(360px, calc(100vw - 24px));
|
||||
max-width: 560px;
|
||||
width: 90vw;
|
||||
max-height: 80vh;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
||||
static styles = [modalShellStyles, css`
|
||||
:host {
|
||||
--ms-modal-max-width: 560px;
|
||||
--ms-modal-max-height: 90dvh;
|
||||
--ms-modal-gap: 12px;
|
||||
--ms-modal-z: 1000;
|
||||
}
|
||||
.title {
|
||||
font-size: 18px;
|
||||
@@ -452,6 +473,9 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
font-size: 14px;
|
||||
padding: 12px 0;
|
||||
}
|
||||
/* Stays at the top of the scrolling middle: the count while ticking.
|
||||
top: -1px + 1px more padding: on a 3x screen a fractional offset let a
|
||||
line of the text scrolled under it show above it. */
|
||||
.select-all {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -459,6 +483,11 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
font-size: 12px;
|
||||
color: var(--secondary-text-color);
|
||||
cursor: pointer;
|
||||
position: sticky;
|
||||
top: -1px;
|
||||
z-index: 1;
|
||||
padding: 5px 0 4px;
|
||||
background: var(--card-background-color, var(--ha-card-background, #1c1c1c));
|
||||
}
|
||||
.select-all input {
|
||||
cursor: pointer;
|
||||
@@ -467,8 +496,6 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
overflow-y: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
@@ -536,9 +563,15 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
border-top: 1px dashed var(--divider-color);
|
||||
padding-top: 6px;
|
||||
}
|
||||
.summary > summary {
|
||||
cursor: pointer;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.summary-title {
|
||||
font-weight: 500;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.summary-totals {
|
||||
color: var(--secondary-text-color);
|
||||
}
|
||||
.summary-line {
|
||||
color: var(--primary-color);
|
||||
@@ -594,7 +627,7 @@ export class MaintenanceAdoptProblemSensorsDialog extends LitElement {
|
||||
gap: 8px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
`;
|
||||
`];
|
||||
}
|
||||
|
||||
if (!customElements.get("maintenance-adopt-problem-sensors-dialog")) {
|
||||
|
||||
+54
-76
@@ -7,6 +7,9 @@
|
||||
*
|
||||
* Uses a native <input> for the name — <ha-textfield> is not registered in the
|
||||
* custom-panel context, so it renders without its field (the documented trap).
|
||||
*
|
||||
* In the shared modal frame (#211): the list of views scrolls, the name
|
||||
* field and the Close button stay.
|
||||
*/
|
||||
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
@@ -14,6 +17,7 @@ import { property, state } from "lit/decorators.js";
|
||||
|
||||
import { t, ensureLocale, langOf } from "../styles";
|
||||
import { runWs } from "../helpers/ws-run";
|
||||
import { focusModalShell, modalShellStyles, renderModalShell } from "../helpers/modal-shell";
|
||||
import type { HomeAssistant, SavedView, SavedViewFilters } from "../types";
|
||||
|
||||
interface ViewsResponse {
|
||||
@@ -41,6 +45,7 @@ export class MaintenanceSavedViewsDialog extends LitElement {
|
||||
this._localeReady = true;
|
||||
ensureLocale(this._lang).then(() => this.requestUpdate());
|
||||
}
|
||||
if (changed.has("_open") && this._open) focusModalShell(this.shadowRoot);
|
||||
}
|
||||
|
||||
public async open(currentFilters: SavedViewFilters, views: SavedView[]): Promise<void> {
|
||||
@@ -90,81 +95,58 @@ export class MaintenanceSavedViewsDialog extends LitElement {
|
||||
render() {
|
||||
if (!this._open) return html``;
|
||||
const L = this._lang;
|
||||
return html`
|
||||
<div class="overlay" @click=${this._close}>
|
||||
<div class="card" @click=${(e: Event) => e.stopPropagation()}>
|
||||
<div class="title">${t("views_dialog_title", L)}</div>
|
||||
<div class="hint">${t("views_dialog_hint", L)}</div>
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : nothing}
|
||||
return renderModalShell(() => this._close(), html`
|
||||
<div class="title">${t("views_dialog_title", L)}</div>
|
||||
<div class="hint">${t("views_dialog_hint", L)}</div>
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : nothing}
|
||||
|
||||
<div class="save-row">
|
||||
<input
|
||||
class="name-input"
|
||||
type="text"
|
||||
.value=${this._name}
|
||||
placeholder=${t("views_name_placeholder", L)}
|
||||
maxlength="60"
|
||||
@input=${(e: Event) => (this._name = (e.target as HTMLInputElement).value)}
|
||||
@keydown=${(e: KeyboardEvent) => {
|
||||
if (e.key === "Enter") this._save();
|
||||
}}
|
||||
/>
|
||||
<ha-button @click=${this._save} .disabled=${!this._name.trim() || this._busy}>
|
||||
${t("views_save_current", L)}
|
||||
</ha-button>
|
||||
</div>
|
||||
|
||||
${this._views.length === 0
|
||||
? html`<div class="empty">${t("views_none_yet", L)}</div>`
|
||||
: html`
|
||||
<div class="list">
|
||||
${this._views.map(
|
||||
(v) => html`
|
||||
<div class="row">
|
||||
<span class="row-name">${v.name}</span>
|
||||
<ha-icon-button
|
||||
.path=${"M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"}
|
||||
.label=${t("delete", L)}
|
||||
@click=${() => this._delete(v.id)}
|
||||
></ha-icon-button>
|
||||
</div>
|
||||
`,
|
||||
)}
|
||||
</div>
|
||||
`}
|
||||
|
||||
<div class="actions">
|
||||
<ha-button appearance="plain" @click=${this._close}>${t("close", L)}</ha-button>
|
||||
</div>
|
||||
<div class="save-row">
|
||||
<input
|
||||
class="name-input"
|
||||
type="text"
|
||||
.value=${this._name}
|
||||
placeholder=${t("views_name_placeholder", L)}
|
||||
maxlength="60"
|
||||
@input=${(e: Event) => (this._name = (e.target as HTMLInputElement).value)}
|
||||
@keydown=${(e: KeyboardEvent) => {
|
||||
if (e.key === "Enter") this._save();
|
||||
}}
|
||||
/>
|
||||
<ha-button @click=${this._save} .disabled=${!this._name.trim() || this._busy}>
|
||||
${t("views_save_current", L)}
|
||||
</ha-button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
${this._views.length === 0
|
||||
? html`<div class="empty">${t("views_none_yet", L)}</div>`
|
||||
: html`
|
||||
<div class="list dialog-scroll">
|
||||
${this._views.map(
|
||||
(v) => html`
|
||||
<div class="row">
|
||||
<span class="row-name">${v.name}</span>
|
||||
<ha-icon-button
|
||||
.path=${"M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"}
|
||||
.label=${t("delete", L)}
|
||||
@click=${() => this._delete(v.id)}
|
||||
></ha-icon-button>
|
||||
</div>
|
||||
`,
|
||||
)}
|
||||
</div>
|
||||
`}
|
||||
|
||||
<div class="actions">
|
||||
<ha-button appearance="plain" @click=${this._close}>${t("close", L)}</ha-button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-background-color, #fff);
|
||||
color: var(--primary-text-color);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-width: min(360px, calc(100vw - 24px));
|
||||
max-width: 480px;
|
||||
width: 90vw;
|
||||
max-height: 80vh;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
||||
static styles = [modalShellStyles, css`
|
||||
:host {
|
||||
--ms-modal-max-height: 90dvh;
|
||||
--ms-modal-gap: 12px;
|
||||
--ms-modal-z: 1000;
|
||||
}
|
||||
.title {
|
||||
font-size: 18px;
|
||||
@@ -198,11 +180,7 @@ export class MaintenanceSavedViewsDialog extends LitElement {
|
||||
padding: 8px 0;
|
||||
}
|
||||
.list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
overflow-y: auto;
|
||||
max-height: 50vh;
|
||||
}
|
||||
.row {
|
||||
display: flex;
|
||||
@@ -227,7 +205,7 @@ export class MaintenanceSavedViewsDialog extends LitElement {
|
||||
gap: 8px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
`;
|
||||
`];
|
||||
}
|
||||
|
||||
if (!customElements.get("maintenance-saved-views-dialog")) {
|
||||
|
||||
+28
-44
@@ -19,6 +19,9 @@
|
||||
* reset button completing it will press; tasks adopted before (or wired by
|
||||
* hand) are offered the same in their own section, with a before/after line
|
||||
* (integration_setups/reset_offers + wire_resets).
|
||||
*
|
||||
* #211: in the shared modal frame like the adopt dialog: the title and the
|
||||
* buttons stay, the offers and the devices scroll as one.
|
||||
*/
|
||||
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
@@ -26,6 +29,7 @@ import { property, state } from "lit/decorators.js";
|
||||
|
||||
import { t, ensureLocale, langOf } from "../styles";
|
||||
import { runWs } from "../helpers/ws-run";
|
||||
import { focusModalShell, modalShellStyles, renderModalShell } from "../helpers/modal-shell";
|
||||
import type { HomeAssistant } from "../types";
|
||||
|
||||
interface SetupTask {
|
||||
@@ -112,6 +116,7 @@ export class MaintenanceSuggestedSetupsDialog extends LitElement {
|
||||
this._localeReady = true;
|
||||
ensureLocale(this._lang).then(() => this.requestUpdate());
|
||||
}
|
||||
if (changed.has("_open") && this._open) focusModalShell(this.shadowRoot);
|
||||
}
|
||||
|
||||
/** Ticked by default: everything the target does not probably have yet. */
|
||||
@@ -336,13 +341,12 @@ export class MaintenanceSuggestedSetupsDialog extends LitElement {
|
||||
if (!this._open) return html``;
|
||||
const L = this._lang;
|
||||
|
||||
return html`
|
||||
<div class="overlay" @click=${this._close}>
|
||||
<div class="card" @click=${(e: Event) => e.stopPropagation()}>
|
||||
<div class="title">${t("setups_title", L)}</div>
|
||||
<div class="hint">${t("setups_hint", L)}</div>
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : nothing}
|
||||
return renderModalShell(() => this._close(), html`
|
||||
<div class="title">${t("setups_title", L)}</div>
|
||||
${this._error ? html`<div class="error">${this._error}</div>` : nothing}
|
||||
|
||||
<div class="dialog-scroll">
|
||||
<div class="hint">${t("setups_hint", L)}</div>
|
||||
${this._renderOffers(L)}
|
||||
${this._loading
|
||||
? html`<div class="loading">…</div>`
|
||||
@@ -428,50 +432,31 @@ export class MaintenanceSuggestedSetupsDialog extends LitElement {
|
||||
})}
|
||||
</div>
|
||||
`}
|
||||
|
||||
<div class="actions">
|
||||
<ha-button appearance="plain" @click=${this._close}>
|
||||
${t("cancel", L)}
|
||||
</ha-button>
|
||||
<ha-button @click=${this._adopt} .disabled=${!this._anythingTicked || this._adopting}>
|
||||
${t("setups_adopt", L)}
|
||||
</ha-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
<div class="actions">
|
||||
<ha-button appearance="plain" @click=${this._close}>
|
||||
${t("cancel", L)}
|
||||
</ha-button>
|
||||
<ha-button @click=${this._adopt} .disabled=${!this._anythingTicked || this._adopting}>
|
||||
${t("setups_adopt", L)}
|
||||
</ha-button>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
static styles = css`
|
||||
.overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-background-color, #fff);
|
||||
color: var(--primary-text-color);
|
||||
border-radius: 12px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
min-width: min(360px, calc(100vw - 24px));
|
||||
max-width: 560px;
|
||||
width: 90vw;
|
||||
max-height: 80vh;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
|
||||
static styles = [modalShellStyles, css`
|
||||
:host {
|
||||
--ms-modal-max-width: 560px;
|
||||
--ms-modal-max-height: 90dvh;
|
||||
--ms-modal-gap: 12px;
|
||||
--ms-modal-z: 1000;
|
||||
}
|
||||
.title { font-size: 18px; font-weight: 500; }
|
||||
.hint { color: var(--secondary-text-color); font-size: 13px; }
|
||||
.error { color: var(--error-color, #f44336); font-size: 13px; }
|
||||
.loading, .empty { color: var(--secondary-text-color); font-size: 14px; padding: 12px 0; }
|
||||
.list { display: flex; flex-direction: column; gap: 6px; overflow-y: auto; max-height: 55vh; }
|
||||
.list { display: flex; flex-direction: column; gap: 6px; }
|
||||
.row {
|
||||
display: flex; align-items: flex-start; gap: 10px; padding: 8px;
|
||||
border: 1px solid var(--divider-color); border-radius: 6px;
|
||||
@@ -497,7 +482,6 @@ export class MaintenanceSuggestedSetupsDialog extends LitElement {
|
||||
.offers {
|
||||
display: flex; flex-direction: column; gap: 6px; padding: 8px;
|
||||
border: 1px solid var(--primary-color); border-radius: 6px;
|
||||
overflow-y: auto; max-height: 40vh; flex-shrink: 0;
|
||||
}
|
||||
.offers-title { font-weight: 500; font-size: 14px; }
|
||||
.offer { display: flex; align-items: flex-start; gap: 6px; font-size: 13px; cursor: pointer; }
|
||||
@@ -520,7 +504,7 @@ export class MaintenanceSuggestedSetupsDialog extends LitElement {
|
||||
color: var(--primary-text-color);
|
||||
}
|
||||
.actions { display: flex; justify-content: flex-end; gap: 8px; padding-top: 8px; }
|
||||
`;
|
||||
`];
|
||||
}
|
||||
|
||||
if (!customElements.get("maintenance-suggested-setups-dialog")) {
|
||||
|
||||
@@ -3072,6 +3072,7 @@ export class MaintenanceTaskDialog extends LitElement {
|
||||
<option value="completion" ?selected=${this._intervalAnchor === "completion"}>${t("anchor_completion", L)}</option>
|
||||
<option value="planned" ?selected=${this._intervalAnchor === "planned"}>${t("anchor_planned", L)}</option>
|
||||
</select>
|
||||
<div class="field-help anchor-help">${t("interval_anchor_hint", L)}</div>
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Ukotvení intervalu",
|
||||
"anchor_completion": "Od data dokončení",
|
||||
"anchor_planned": "Od plánovaného data (bez posunu)",
|
||||
"interval_anchor_hint": "Od data dokončení: další termín se počítá ode dne, kdy je úkol označen jako hotový, takže dřívější nebo pozdější splnění posune plán. Od plánovaného data: plán si ponechá své termíny, například když je faktura zaplacena týdny před splatností.",
|
||||
"edit_object": "Upravit objekt",
|
||||
"name": "Název",
|
||||
"manufacturer_optional": "Výrobce (volitelné)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Dejte několika senzorům stejný název objektu a stanou se jedním objektem; zadejte název existujícího objektu a přidají se tam.",
|
||||
"adopt_summary_title": "Co převzetí změní",
|
||||
"adopt_summary_existing": "„{name}“: úkoly {before} → {after}",
|
||||
"adopt_summary_totals": "Úkoly: {tasks} · objekty: {objects}",
|
||||
"adopt_summary_totals_new": "Úkoly: {tasks} · objekty: {objects} (z toho nové: {new})",
|
||||
"adopt_problem_adopt": "Převzít vybrané",
|
||||
"adopt_problem_done": "Převzato {tasks} senzorů problémů",
|
||||
"adopt_problem_done_one": "Převzat 1 senzor problémů",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter byl aktualizován na verzi {version}. Restartujte Home Assistant, aby se aktualizace dokončila.",
|
||||
"restart_pending_error": "Nepodařilo se: Maintenance Supporter byl aktualizován na verzi {version}, ale Home Assistant od té doby nebyl restartován. Restartujte Home Assistant a zkuste to 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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Intervalanker",
|
||||
"anchor_completion": "Fra fuldførelsesdato",
|
||||
"anchor_planned": "Fra planlagt dato (ingen drift)",
|
||||
"interval_anchor_hint": "Fra fuldførelsesdato: næste forfaldsdato regnes fra den dag, opgaven markeres som udført, så tidlig eller sen udførelse flytter planen. Fra planlagt dato: planen beholder sine datoer, for eksempel når en regning betales uger før forfald.",
|
||||
"edit_object": "Rediger objekt",
|
||||
"name": "Navn",
|
||||
"manufacturer_optional": "Producent (valgfrit)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Giv flere sensorer samme objektnavn, så bliver de ét objekt; skriv et eksisterende objekts navn for at tilføje dem der.",
|
||||
"adopt_summary_title": "Hvad overtagelsen ændrer",
|
||||
"adopt_summary_existing": "\"{name}\": opgaver {before} → {after}",
|
||||
"adopt_summary_totals": "Opgaver: {tasks} · objekter: {objects}",
|
||||
"adopt_summary_totals_new": "Opgaver: {tasks} · objekter: {objects} (heraf nye: {new})",
|
||||
"adopt_problem_adopt": "Adopter valgte",
|
||||
"adopt_problem_done": "Adopterede {tasks} problemsensor(er)",
|
||||
"adopt_problem_done_one": "Adopterede 1 problemsensor",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter er blevet opdateret til {version}. Genstart Home Assistant for at fuldføre opdateringen.",
|
||||
"restart_pending_error": "Det lykkedes ikke: Maintenance Supporter er blevet opdateret til {version}, men Home Assistant er ikke blevet genstartet siden. Genstart Home Assistant, og prøv igen.",
|
||||
"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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Intervall-Anker",
|
||||
"anchor_completion": "Ab Erledigung",
|
||||
"anchor_planned": "Ab geplantem Datum (kein Drift)",
|
||||
"interval_anchor_hint": "Ab Erledigung: Die nächste Fälligkeit zählt ab dem Tag, an dem die Aufgabe erledigt wird; früher oder später erledigt verschiebt also den Plan. Ab geplantem Datum: Der Plan behält seine Termine, zum Beispiel wenn eine Rechnung Wochen vor der Fälligkeit bezahlt wird.",
|
||||
"edit_object": "Objekt bearbeiten",
|
||||
"name": "Name",
|
||||
"manufacturer_optional": "Hersteller (optional)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Gib mehreren Sensoren denselben Objektnamen, dann werden sie ein Objekt; der Name eines vorhandenen Objekts ordnet sie dort zu.",
|
||||
"adopt_summary_title": "Was die Übernahme ändert",
|
||||
"adopt_summary_existing": "„{name}“: Aufgaben {before} → {after}",
|
||||
"adopt_summary_totals": "Aufgaben: {tasks} · Objekte: {objects}",
|
||||
"adopt_summary_totals_new": "Aufgaben: {tasks} · Objekte: {objects} (davon neu: {new})",
|
||||
"adopt_problem_adopt": "Auswahl übernehmen",
|
||||
"adopt_problem_done": "{tasks} Problem-Sensor(en) übernommen",
|
||||
"adopt_problem_done_one": "1 Problem-Sensor übernommen",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter wurde auf {version} aktualisiert. Starte Home Assistant neu, um das Update abzuschließen.",
|
||||
"restart_pending_error": "Das hat nicht geklappt: Maintenance Supporter wurde auf {version} aktualisiert, Home Assistant aber seitdem nicht neu gestartet. Starte Home Assistant neu und versuche es dann noch einmal.",
|
||||
"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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Interval anchor",
|
||||
"anchor_completion": "From completion date",
|
||||
"anchor_planned": "From planned date (no drift)",
|
||||
"interval_anchor_hint": "From completion date: the next due date counts from the day the task is marked done, so doing it early or late moves the schedule. From planned date: the schedule keeps its dates, for example when a bill is paid weeks before it is due.",
|
||||
"edit_object": "Edit Object",
|
||||
"name": "Name",
|
||||
"manufacturer_optional": "Manufacturer (optional)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Give several sensors the same object name and they become one object; type an existing object's name to add them there.",
|
||||
"adopt_summary_title": "What adopting changes",
|
||||
"adopt_summary_existing": "\"{name}\": tasks {before} → {after}",
|
||||
"adopt_summary_totals": "Tasks: {tasks} · objects: {objects}",
|
||||
"adopt_summary_totals_new": "Tasks: {tasks} · objects: {objects} ({new} new)",
|
||||
"adopt_problem_adopt": "Adopt selected",
|
||||
"adopt_problem_done": "Adopted {tasks} problem sensor(s)",
|
||||
"adopt_problem_done_one": "Adopted 1 problem sensor",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter was updated to {version}. Restart Home Assistant to finish the update.",
|
||||
"restart_pending_error": "That did not work: Maintenance Supporter was updated to {version}, but Home Assistant has not been restarted since. Restart Home Assistant, then try again.",
|
||||
"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",
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Anclaje del intervalo",
|
||||
"anchor_completion": "Desde la fecha de finalización",
|
||||
"anchor_planned": "Desde la fecha planificada (sin desviación)",
|
||||
"interval_anchor_hint": "Desde la fecha de finalización: el próximo vencimiento se cuenta desde el día en que se marca la tarea como hecha, así que hacerla antes o después mueve el calendario. Desde la fecha planificada: el calendario mantiene sus fechas, por ejemplo cuando una factura se paga semanas antes de su vencimiento.",
|
||||
"edit_object": "Editar objeto",
|
||||
"name": "Nombre",
|
||||
"manufacturer_optional": "Fabricante (opcional)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Da a varios sensores el mismo nombre de objeto y se convierten en un solo objeto; escribe el nombre de un objeto existente para añadirlos allí.",
|
||||
"adopt_summary_title": "Qué cambia al adoptar",
|
||||
"adopt_summary_existing": "«{name}»: tareas {before} → {after}",
|
||||
"adopt_summary_totals": "Tareas: {tasks} · objetos: {objects}",
|
||||
"adopt_summary_totals_new": "Tareas: {tasks} · objetos: {objects} (nuevos: {new})",
|
||||
"adopt_problem_adopt": "Adoptar seleccionados",
|
||||
"adopt_problem_done": "{tasks} sensor(es) de problema adoptado(s)",
|
||||
"adopt_problem_done_one": "1 sensor de problema adoptado",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter se actualizó a la versión {version}. Reinicia Home Assistant para completar la actualización.",
|
||||
"restart_pending_error": "No ha funcionado: Maintenance Supporter se actualizó a la versión {version}, pero Home Assistant no se ha reiniciado desde entonces. Reinicia Home Assistant y vuelve a intentarlo.",
|
||||
"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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Välin ankkuri",
|
||||
"anchor_completion": "Suorituspäivästä",
|
||||
"anchor_planned": "Suunnitellusta päivästä (ei poikkeamaa)",
|
||||
"interval_anchor_hint": "Suorituspäivästä: seuraava eräpäivä lasketaan päivästä, jolloin tehtävä merkitään tehdyksi, joten aikainen tai myöhäinen suoritus siirtää aikataulua. Suunnitellusta päivästä: aikataulu pitää päivänsä, esimerkiksi kun lasku maksetaan viikkoja ennen eräpäivää.",
|
||||
"edit_object": "Muokkaa kohdetta",
|
||||
"name": "Nimi",
|
||||
"manufacturer_optional": "Valmistaja (valinnainen)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Anna useille antureille sama kohteen nimi, niin niistä tulee yksi kohde; kirjoita olemassa olevan kohteen nimi lisätäksesi ne sinne.",
|
||||
"adopt_summary_title": "Mitä käyttöönotto muuttaa",
|
||||
"adopt_summary_existing": "\"{name}\": tehtävät {before} → {after}",
|
||||
"adopt_summary_totals": "Tehtäviä: {tasks} · kohteita: {objects}",
|
||||
"adopt_summary_totals_new": "Tehtäviä: {tasks} · kohteita: {objects} (uusia: {new})",
|
||||
"adopt_problem_adopt": "Ota valitut käyttöön",
|
||||
"adopt_problem_done": "Otettiin käyttöön {tasks} ongelma-anturia",
|
||||
"adopt_problem_done_one": "Otettiin käyttöön 1 ongelma-anturi",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter on päivitetty versioon {version}. Käynnistä Home Assistant uudelleen viimeistelläksesi päivityksen.",
|
||||
"restart_pending_error": "Se ei onnistunut: Maintenance Supporter on päivitetty versioon {version}, mutta Home Assistantia ei ole sen jälkeen käynnistetty uudelleen. Käynnistä Home Assistant uudelleen ja yritä sitten 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",
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Ancrage de l'intervalle",
|
||||
"anchor_completion": "Depuis la date de réalisation",
|
||||
"anchor_planned": "Depuis la date prévue (sans dérive)",
|
||||
"interval_anchor_hint": "Depuis la date de réalisation : la prochaine échéance compte à partir du jour où la tâche est marquée comme faite, donc la faire en avance ou en retard décale le planning. Depuis la date prévue : le planning garde ses dates, par exemple quand une facture est payée des semaines avant son échéance.",
|
||||
"edit_object": "Modifier l'objet",
|
||||
"name": "Nom",
|
||||
"manufacturer_optional": "Fabricant (optionnel)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Donnez le même nom d'objet à plusieurs capteurs et ils forment un seul objet ; saisissez le nom d'un objet existant pour les y ajouter.",
|
||||
"adopt_summary_title": "Ce que l'adoption modifie",
|
||||
"adopt_summary_existing": "« {name} » : tâches {before} → {after}",
|
||||
"adopt_summary_totals": "Tâches : {tasks} · objets : {objects}",
|
||||
"adopt_summary_totals_new": "Tâches : {tasks} · objets : {objects} (dont nouveaux : {new})",
|
||||
"adopt_problem_adopt": "Adopter la sélection",
|
||||
"adopt_problem_done": "{tasks} capteur(s) de problème adopté(s)",
|
||||
"adopt_problem_done_one": "1 capteur de problème adopté",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter a été mis à jour vers la version {version}. Redémarrez Home Assistant pour terminer la mise à jour.",
|
||||
"restart_pending_error": "Cela n'a pas fonctionné : Maintenance Supporter a été mis à jour vers la version {version}, mais Home Assistant n'a pas été redémarré depuis. Redémarrez Home Assistant, puis réessayez.",
|
||||
"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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "अंतराल आधार",
|
||||
"anchor_completion": "पूर्ण तिथि से",
|
||||
"anchor_planned": "नियोजित तिथि से (कोई विचलन नहीं)",
|
||||
"interval_anchor_hint": "पूर्ण तिथि से: अगली देय तिथि उस दिन से गिनी जाती है जिस दिन कार्य पूरा चिह्नित किया जाता है, इसलिए पहले या देर से करने पर समय-सारणी खिसक जाती है। नियोजित तिथि से: समय-सारणी अपनी तिथियाँ बनाए रखती है, उदाहरण के लिए जब कोई बिल देय तिथि से हफ़्तों पहले चुकाया जाता है।",
|
||||
"edit_object": "वस्तु संपादित करें",
|
||||
"name": "नाम",
|
||||
"manufacturer_optional": "निर्माता (वैकल्पिक)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "कई सेंसरों को एक ही ऑब्जेक्ट नाम दें तो वे एक ऑब्जेक्ट बन जाते हैं; मौजूदा ऑब्जेक्ट का नाम लिखें तो वे वहीं जुड़ जाते हैं।",
|
||||
"adopt_summary_title": "अपनाने से क्या बदलेगा",
|
||||
"adopt_summary_existing": "\"{name}\": कार्य {before} → {after}",
|
||||
"adopt_summary_totals": "कार्य: {tasks} · ऑब्जेक्ट: {objects}",
|
||||
"adopt_summary_totals_new": "कार्य: {tasks} · ऑब्जेक्ट: {objects} (नए: {new})",
|
||||
"adopt_problem_adopt": "चयनित अपनाएँ",
|
||||
"adopt_problem_done": "{tasks} समस्या सेंसर अपनाए गए",
|
||||
"adopt_problem_done_one": "1 समस्या सेंसर अपनाया गया",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"battery_fleet_setup_done": "बैटरी फ्लीट सेट — एक कार्य सभी बैटरियों को ट्रैक करता है।",
|
||||
"update_banner": "सर्वर पर Maintenance Supporter का नया संस्करण है — पैनल अपडेट करने के लिए पुनः लोड करें।",
|
||||
"update_reload": "पुनः लोड करें",
|
||||
"restart_pending_banner": "Maintenance Supporter को {version} संस्करण में अपडेट किया गया है। अपडेट पूरा करने के लिए Home Assistant को पुनः आरंभ करें।",
|
||||
"restart_pending_error": "यह नहीं हो सका: Maintenance Supporter को {version} संस्करण में अपडेट किया गया है, लेकिन उसके बाद से Home Assistant को पुनः आरंभ नहीं किया गया है। Home Assistant को पुनः आरंभ करें, फिर दोबारा प्रयास करें।",
|
||||
"row_actions_banner": "कार्य पंक्तियों में पूर्ण और छोड़ें अब बटन हैं। पुराने आइकन पसंद हैं?",
|
||||
"row_actions_keep": "बटन रखें",
|
||||
"row_actions_back": "आइकन पर वापस जाएँ",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Intervallum horgonya",
|
||||
"anchor_completion": "Az elvégzés dátumától",
|
||||
"anchor_planned": "A tervezett dátumtól (nincs csúszás)",
|
||||
"interval_anchor_hint": "Az elvégzés dátumától: a következő határidő attól a naptól számít, amikor a feladatot elvégzettnek jelölik, így a korábbi vagy későbbi elvégzés eltolja az ütemezést. A tervezett dátumtól: az ütemezés megtartja a dátumait, például ha egy számlát hetekkel a határidő előtt fizetnek be.",
|
||||
"edit_object": "Objektum szerkesztése",
|
||||
"name": "Név",
|
||||
"manufacturer_optional": "Gyártó (opcionális)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Adja több érzékelőnek ugyanazt az objektumnevet, és egy objektummá válnak; meglévő objektum nevét beírva oda kerülnek.",
|
||||
"adopt_summary_title": "Mit változtat az átvétel",
|
||||
"adopt_summary_existing": "„{name}”: feladatok {before} → {after}",
|
||||
"adopt_summary_totals": "Feladatok: {tasks} · objektumok: {objects}",
|
||||
"adopt_summary_totals_new": "Feladatok: {tasks} · objektumok: {objects} (ebből új: {new})",
|
||||
"adopt_problem_adopt": "Kijelöltek átvétele",
|
||||
"adopt_problem_done": "{tasks} problémaérzékelő átvéve",
|
||||
"adopt_problem_done_one": "1 problémaérzékelő átvéve",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "A Maintenance Supporter frissült a(z) {version} verzióra. Indítsa újra a Home Assistantot a frissítés befejezéséhez.",
|
||||
"restart_pending_error": "Ez nem sikerült: a Maintenance Supporter frissült a(z) {version} verzióra, de a Home Assistant azóta nem indult újra. Indítsa újra a Home Assistantot, majd próbálja újra.",
|
||||
"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",
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Ancoraggio intervallo",
|
||||
"anchor_completion": "Dalla data di completamento",
|
||||
"anchor_planned": "Dalla data pianificata (nessuna deriva)",
|
||||
"interval_anchor_hint": "Dalla data di completamento: la prossima scadenza si conta dal giorno in cui l'attività viene segnata come fatta, quindi farla prima o dopo sposta la pianificazione. Dalla data pianificata: la pianificazione mantiene le sue date, per esempio quando una bolletta viene pagata settimane prima della scadenza.",
|
||||
"edit_object": "Modifica oggetto",
|
||||
"name": "Nome",
|
||||
"manufacturer_optional": "Produttore (opzionale)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Assegna lo stesso nome oggetto a più sensori e diventano un unico oggetto; digita il nome di un oggetto esistente per aggiungerli lì.",
|
||||
"adopt_summary_title": "Cosa cambia l'adozione",
|
||||
"adopt_summary_existing": "«{name}»: attività {before} → {after}",
|
||||
"adopt_summary_totals": "Attività: {tasks} · oggetti: {objects}",
|
||||
"adopt_summary_totals_new": "Attività: {tasks} · oggetti: {objects} (di cui nuovi: {new})",
|
||||
"adopt_problem_adopt": "Adotta selezionati",
|
||||
"adopt_problem_done": "{tasks} sensore/i di problema adottato/i",
|
||||
"adopt_problem_done_one": "1 sensore di problema adottato",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter è stato aggiornato alla versione {version}. Riavvia Home Assistant per completare l'aggiornamento.",
|
||||
"restart_pending_error": "Non è andato a buon fine: Maintenance Supporter è stato aggiornato alla versione {version}, ma da allora Home Assistant non è stato riavviato. Riavvia Home Assistant e riprova.",
|
||||
"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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "間隔の起点",
|
||||
"anchor_completion": "完了日から",
|
||||
"anchor_planned": "予定日から(ずれなし)",
|
||||
"interval_anchor_hint": "完了日から: 次の期限はタスクを完了にした日から数えるため、早く・遅く完了すると予定がずれます。予定日から: 予定は元の日付を保ちます。たとえば請求書を期限の数週間前に支払った場合です。",
|
||||
"edit_object": "対象を編集",
|
||||
"name": "名前",
|
||||
"manufacturer_optional": "メーカー(任意)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "複数のセンサーに同じオブジェクト名を付けると1つのオブジェクトになります。既存のオブジェクト名を入力すればそこに追加されます。",
|
||||
"adopt_summary_title": "取り込みで変わること",
|
||||
"adopt_summary_existing": "「{name}」: タスク {before} → {after}",
|
||||
"adopt_summary_totals": "タスク: {tasks} · オブジェクト: {objects}",
|
||||
"adopt_summary_totals_new": "タスク: {tasks} · オブジェクト: {objects}(うち新規: {new})",
|
||||
"adopt_problem_adopt": "選択を取り込む",
|
||||
"adopt_problem_done": "{tasks} 件の問題センサーを取り込みました",
|
||||
"adopt_problem_done_one": "1 件の問題センサーを取り込みました",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"battery_fleet_setup_done": "電池フリートを設定 — 1つのタスクで全電池を管理。",
|
||||
"update_banner": "サーバーに新しいバージョンの Maintenance Supporter があります — 再読み込みしてパネルを更新してください。",
|
||||
"update_reload": "再読み込み",
|
||||
"restart_pending_banner": "Maintenance Supporter はバージョン {version} に更新されました。更新を完了するには Home Assistant を再起動してください。",
|
||||
"restart_pending_error": "実行できませんでした: Maintenance Supporter はバージョン {version} に更新されましたが、その後 Home Assistant が再起動されていません。Home Assistant を再起動してから、もう一度お試しください。",
|
||||
"row_actions_banner": "タスク行の「完了」と「スキップ」がボタンになりました。以前のアイコンに戻しますか?",
|
||||
"row_actions_keep": "ボタンのままにする",
|
||||
"row_actions_back": "アイコンに戻す",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "주기 기준",
|
||||
"anchor_completion": "완료일 기준",
|
||||
"anchor_planned": "예정일 기준 (밀림 없음)",
|
||||
"interval_anchor_hint": "완료일 기준: 다음 예정일은 작업을 완료로 표시한 날부터 계산되므로, 일찍 또는 늦게 완료하면 일정이 바뀝니다. 예정일 기준: 일정이 원래 날짜를 유지합니다. 예를 들어 청구서를 기한보다 몇 주 일찍 납부한 경우입니다.",
|
||||
"edit_object": "객체 편집",
|
||||
"name": "이름",
|
||||
"manufacturer_optional": "제조사 (선택)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "여러 센서에 같은 개체 이름을 주면 하나의 개체가 됩니다. 기존 개체 이름을 입력하면 거기에 추가됩니다.",
|
||||
"adopt_summary_title": "가져오기로 바뀌는 점",
|
||||
"adopt_summary_existing": "\"{name}\": 작업 {before} → {after}",
|
||||
"adopt_summary_totals": "작업: {tasks} · 객체: {objects}",
|
||||
"adopt_summary_totals_new": "작업: {tasks} · 객체: {objects} (새 객체: {new})",
|
||||
"adopt_problem_adopt": "선택 항목 가져오기",
|
||||
"adopt_problem_done": "문제 센서 {tasks}개를 가져왔습니다",
|
||||
"adopt_problem_done_one": "문제 센서 1개를 가져왔습니다",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"battery_fleet_setup_done": "배터리 플릿이 설정되었습니다 — 하나의 작업이 모든 배터리를 추적합니다.",
|
||||
"update_banner": "서버에 Maintenance Supporter의 새 버전이 있습니다 — 패널을 업데이트하려면 새로 고침하세요.",
|
||||
"update_reload": "새로 고침",
|
||||
"restart_pending_banner": "Maintenance Supporter가 {version} 버전으로 업데이트되었습니다. 업데이트를 완료하려면 Home Assistant를 다시 시작하세요.",
|
||||
"restart_pending_error": "실패했습니다: Maintenance Supporter가 {version} 버전으로 업데이트되었지만 그 이후 Home Assistant가 다시 시작되지 않았습니다. Home Assistant를 다시 시작한 후 다시 시도하세요.",
|
||||
"row_actions_banner": "작업 행의 완료와 건너뛰기가 이제 버튼으로 표시됩니다. 이전 아이콘이 더 좋으신가요?",
|
||||
"row_actions_keep": "버튼 유지",
|
||||
"row_actions_back": "아이콘으로 되돌리기",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Intervallforankring",
|
||||
"anchor_completion": "Fra fullføringsdato",
|
||||
"anchor_planned": "Fra planlagt dato (ingen avdrift)",
|
||||
"interval_anchor_hint": "Fra fullføringsdato: neste forfallsdato regnes fra dagen oppgaven markeres som utført, så tidlig eller sen utførelse flytter planen. Fra planlagt dato: planen beholder datoene sine, for eksempel når en regning betales uker før forfall.",
|
||||
"edit_object": "Rediger objekt",
|
||||
"name": "Navn",
|
||||
"manufacturer_optional": "Produsent (valgfritt)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Gi flere sensorer samme objektnavn, så blir de ett objekt; skriv navnet på et eksisterende objekt for å legge dem der.",
|
||||
"adopt_summary_title": "Hva overtakelsen endrer",
|
||||
"adopt_summary_existing": "«{name}»: oppgaver {before} → {after}",
|
||||
"adopt_summary_totals": "Oppgaver: {tasks} · objekter: {objects}",
|
||||
"adopt_summary_totals_new": "Oppgaver: {tasks} · objekter: {objects} (herav nye: {new})",
|
||||
"adopt_problem_adopt": "Ta i bruk valgte",
|
||||
"adopt_problem_done": "Tok i bruk {tasks} problemsensor(er)",
|
||||
"adopt_problem_done_one": "Tok i bruk 1 problemsensor",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter er oppdatert til {version}. Start Home Assistant på nytt for å fullføre oppdateringen.",
|
||||
"restart_pending_error": "Det fungerte ikke: Maintenance Supporter er oppdatert til {version}, men Home Assistant er ikke startet på nytt siden. Start Home Assistant på nytt, og prøv igjen.",
|
||||
"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",
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Interval-anker",
|
||||
"anchor_completion": "Vanaf voltooiing",
|
||||
"anchor_planned": "Vanaf geplande datum (geen drift)",
|
||||
"interval_anchor_hint": "Vanaf voltooiing: de volgende vervaldatum telt vanaf de dag waarop de taak als gedaan wordt gemarkeerd, dus eerder of later uitvoeren verschuift de planning. Vanaf geplande datum: de planning houdt haar data, bijvoorbeeld wanneer een rekening weken voor de vervaldatum wordt betaald.",
|
||||
"edit_object": "Object bewerken",
|
||||
"name": "Naam",
|
||||
"manufacturer_optional": "Fabrikant (optioneel)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Geef meerdere sensoren dezelfde objectnaam en ze worden één object; typ de naam van een bestaand object om ze daar toe te voegen.",
|
||||
"adopt_summary_title": "Wat overnemen verandert",
|
||||
"adopt_summary_existing": "\"{name}\": taken {before} → {after}",
|
||||
"adopt_summary_totals": "Taken: {tasks} · objecten: {objects}",
|
||||
"adopt_summary_totals_new": "Taken: {tasks} · objecten: {objects} (waarvan nieuw: {new})",
|
||||
"adopt_problem_adopt": "Selectie overnemen",
|
||||
"adopt_problem_done": "{tasks} probleemsensor(en) overgenomen",
|
||||
"adopt_problem_done_one": "1 probleemsensor overgenomen",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter is bijgewerkt naar {version}. Start Home Assistant opnieuw op om de update te voltooien.",
|
||||
"restart_pending_error": "Dat is niet gelukt: Maintenance Supporter is bijgewerkt naar {version}, maar Home Assistant is sindsdien niet opnieuw opgestart. Start Home Assistant opnieuw op en probeer het dan nog eens.",
|
||||
"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",
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Punkt zaczepienia interwału",
|
||||
"anchor_completion": "Od daty wykonania",
|
||||
"anchor_planned": "Od daty planowanej (bez przesunięć)",
|
||||
"interval_anchor_hint": "Od daty wykonania: następny termin liczy się od dnia oznaczenia zadania jako wykonanego, więc wcześniejsze lub późniejsze wykonanie przesuwa harmonogram. Od daty planowanej: harmonogram zachowuje swoje daty, na przykład gdy rachunek zostaje opłacony kilka tygodni przed terminem.",
|
||||
"edit_object": "Edytuj obiekt",
|
||||
"name": "Nazwa",
|
||||
"manufacturer_optional": "Producent (opcjonalne)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Nadaj kilku czujnikom tę samą nazwę obiektu, a staną się jednym obiektem; wpisz nazwę istniejącego obiektu, aby je tam dodać.",
|
||||
"adopt_summary_title": "Co zmieni przejęcie",
|
||||
"adopt_summary_existing": "„{name}”: zadania {before} → {after}",
|
||||
"adopt_summary_totals": "Zadania: {tasks} · obiekty: {objects}",
|
||||
"adopt_summary_totals_new": "Zadania: {tasks} · obiekty: {objects} (w tym nowe: {new})",
|
||||
"adopt_problem_adopt": "Przejmij zaznaczone",
|
||||
"adopt_problem_done": "Przejęto {tasks} czujnik(ów) problemów",
|
||||
"adopt_problem_done_one": "Przejęto 1 czujnik problemów",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter został zaktualizowany do wersji {version}. Uruchom ponownie Home Assistant, aby dokończyć aktualizację.",
|
||||
"restart_pending_error": "Nie udało się: Maintenance Supporter został zaktualizowany do wersji {version}, ale od tego czasu Home Assistant nie został uruchomiony ponownie. Uruchom ponownie Home Assistant i spróbuj jeszcze raz.",
|
||||
"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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Âncora do intervalo",
|
||||
"anchor_completion": "A partir da data de conclusão",
|
||||
"anchor_planned": "A partir da data planejada (sem deriva)",
|
||||
"interval_anchor_hint": "A partir da data de conclusão: o próximo vencimento conta a partir do dia em que a tarefa é marcada como feita, então fazê-la antes ou depois desloca o cronograma. A partir da data planejada: o cronograma mantém suas datas, por exemplo quando uma conta é paga semanas antes do vencimento.",
|
||||
"edit_object": "Editar objeto",
|
||||
"name": "Nome",
|
||||
"manufacturer_optional": "Fabricante (opcional)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Dê a vários sensores o mesmo nome de objeto e eles viram um único objeto; digite o nome de um objeto existente para adicioná-los lá.",
|
||||
"adopt_summary_title": "O que a adoção muda",
|
||||
"adopt_summary_existing": "\"{name}\": tarefas {before} → {after}",
|
||||
"adopt_summary_totals": "Tarefas: {tasks} · objetos: {objects}",
|
||||
"adopt_summary_totals_new": "Tarefas: {tasks} · objetos: {objects} (novos: {new})",
|
||||
"adopt_problem_adopt": "Adotar selecionados",
|
||||
"adopt_problem_done": "{tasks} sensor(es) de problema adotado(s)",
|
||||
"adopt_problem_done_one": "1 sensor de problema adotado",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "O Maintenance Supporter foi atualizado para a versão {version}. Reinicie o Home Assistant para finalizar a atualização.",
|
||||
"restart_pending_error": "Não deu certo: o Maintenance Supporter foi atualizado para a versão {version}, mas o Home Assistant ainda não foi reiniciado. Reinicie o Home Assistant e tente de novo.",
|
||||
"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",
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Âncora do intervalo",
|
||||
"anchor_completion": "A partir da data de conclusão",
|
||||
"anchor_planned": "A partir da data planeada (sem desvio)",
|
||||
"interval_anchor_hint": "A partir da data de conclusão: o próximo vencimento conta a partir do dia em que a tarefa é marcada como feita, por isso fazê-la antes ou depois desloca o calendário. A partir da data planeada: o calendário mantém as suas datas, por exemplo quando uma fatura é paga semanas antes do vencimento.",
|
||||
"edit_object": "Editar objeto",
|
||||
"name": "Nome",
|
||||
"manufacturer_optional": "Fabricante (opcional)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Dê a vários sensores o mesmo nome de objeto e tornam-se um só objeto; escreva o nome de um objeto existente para os juntar lá.",
|
||||
"adopt_summary_title": "O que a adoção altera",
|
||||
"adopt_summary_existing": "«{name}»: tarefas {before} → {after}",
|
||||
"adopt_summary_totals": "Tarefas: {tasks} · objetos: {objects}",
|
||||
"adopt_summary_totals_new": "Tarefas: {tasks} · objetos: {objects} (novos: {new})",
|
||||
"adopt_problem_adopt": "Adotar selecionados",
|
||||
"adopt_problem_done": "{tasks} sensor(es) de problema adotado(s)",
|
||||
"adopt_problem_done_one": "1 sensor de problema adotado",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "O Maintenance Supporter foi atualizado para a versão {version}. Reinicie o Home Assistant para concluir a atualização.",
|
||||
"restart_pending_error": "Não foi possível: o Maintenance Supporter foi atualizado para a versão {version}, mas o Home Assistant ainda não foi reiniciado. Reinicie o Home Assistant e tente novamente.",
|
||||
"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",
|
||||
|
||||
@@ -249,6 +249,7 @@
|
||||
"interval_anchor": "Якорь интервала",
|
||||
"anchor_completion": "От даты выполнения",
|
||||
"anchor_planned": "От плановой даты (без смещения)",
|
||||
"interval_anchor_hint": "От даты выполнения: следующий срок отсчитывается от дня, когда задача отмечена выполненной, поэтому раннее или позднее выполнение сдвигает график. От плановой даты: график сохраняет свои даты, например когда счёт оплачен за несколько недель до срока.",
|
||||
"edit_object": "Изменить объект",
|
||||
"name": "Имя",
|
||||
"manufacturer_optional": "Производитель (опционально)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Дайте нескольким датчикам одно имя объекта — они станут одним объектом; введите имя существующего объекта, чтобы добавить их туда.",
|
||||
"adopt_summary_title": "Что изменит добавление",
|
||||
"adopt_summary_existing": "«{name}»: задачи {before} → {after}",
|
||||
"adopt_summary_totals": "Задачи: {tasks} · объекты: {objects}",
|
||||
"adopt_summary_totals_new": "Задачи: {tasks} · объекты: {objects} (из них новых: {new})",
|
||||
"adopt_problem_adopt": "Принять выбранные",
|
||||
"adopt_problem_done": "Принято сенсоров проблем: {tasks}",
|
||||
"adopt_problem_done_one": "Принят 1 сенсор проблем",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"battery_fleet_setup_done": "Парк батарей настроен — одна задача следит за всеми.",
|
||||
"update_banner": "На сервере более новая версия Maintenance Supporter — перезагрузите, чтобы обновить панель.",
|
||||
"update_reload": "Перезагрузить",
|
||||
"restart_pending_banner": "Maintenance Supporter обновлён до версии {version}. Перезапустите Home Assistant, чтобы завершить обновление.",
|
||||
"restart_pending_error": "Не получилось: Maintenance Supporter обновлён до версии {version}, но Home Assistant с тех пор не перезапускался. Перезапустите Home Assistant и попробуйте ещё раз.",
|
||||
"row_actions_banner": "«Выполнено» и «Пропустить» в строках задач теперь кнопки. Предпочитаете старые значки?",
|
||||
"row_actions_keep": "Оставить кнопки",
|
||||
"row_actions_back": "Вернуть значки",
|
||||
|
||||
@@ -250,6 +250,7 @@
|
||||
"interval_anchor": "Intervallankare",
|
||||
"anchor_completion": "Från slutförandedatum",
|
||||
"anchor_planned": "Från planerat datum (ingen drift)",
|
||||
"interval_anchor_hint": "Från slutförandedatum: nästa förfallodatum räknas från dagen då uppgiften markeras som utförd, så att göra den tidigt eller sent flyttar schemat. Från planerat datum: schemat behåller sina datum, till exempel när en räkning betalas veckor före förfallodagen.",
|
||||
"edit_object": "Redigera objekt",
|
||||
"name": "Namn",
|
||||
"manufacturer_optional": "Tillverkare (valfritt)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Ge flera sensorer samma objektnamn så blir de ett objekt; skriv ett befintligt objekts namn för att lägga dem där.",
|
||||
"adopt_summary_title": "Vad övertagandet ändrar",
|
||||
"adopt_summary_existing": "”{name}”: uppgifter {before} → {after}",
|
||||
"adopt_summary_totals": "Uppgifter: {tasks} · objekt: {objects}",
|
||||
"adopt_summary_totals_new": "Uppgifter: {tasks} · objekt: {objects} (varav nya: {new})",
|
||||
"adopt_problem_adopt": "Anta valda",
|
||||
"adopt_problem_done": "Antog {tasks} problemsensor(er)",
|
||||
"adopt_problem_done_one": "Antog 1 problemsensor",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter har uppdaterats till {version}. Starta om Home Assistant för att slutföra uppdateringen.",
|
||||
"restart_pending_error": "Det fungerade inte: Maintenance Supporter har uppdaterats till {version}, men Home Assistant har inte startats om sedan dess. Starta om Home Assistant och försök igen.",
|
||||
"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",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "Aralık referansı",
|
||||
"anchor_completion": "Tamamlama tarihinden",
|
||||
"anchor_planned": "Planlanan tarihten (kayma olmaz)",
|
||||
"interval_anchor_hint": "Tamamlama tarihinden: sonraki vade, görevin yapıldı olarak işaretlendiği günden itibaren sayılır; bu yüzden erken veya geç yapmak planı kaydırır. Planlanan tarihten: plan tarihlerini korur; örneğin bir fatura vadesinden haftalar önce ödendiğinde.",
|
||||
"edit_object": "Nesneyi Düzenle",
|
||||
"name": "Ad",
|
||||
"manufacturer_optional": "Üretici (isteğe bağlı)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Birden çok sensöre aynı nesne adını verin, tek nesne olurlar; mevcut bir nesnenin adını yazarsanız oraya eklenirler.",
|
||||
"adopt_summary_title": "Devralmanın değiştirecekleri",
|
||||
"adopt_summary_existing": "\"{name}\": görevler {before} → {after}",
|
||||
"adopt_summary_totals": "Görevler: {tasks} · nesneler: {objects}",
|
||||
"adopt_summary_totals_new": "Görevler: {tasks} · nesneler: {objects} (yeni: {new})",
|
||||
"adopt_problem_adopt": "Seçilenleri devral",
|
||||
"adopt_problem_done": "{tasks} sorun sensörü devralındı",
|
||||
"adopt_problem_done_one": "1 sorun sensörü devralındı",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"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",
|
||||
"restart_pending_banner": "Maintenance Supporter {version} sürümüne güncellendi. Güncellemeyi tamamlamak için Home Assistant'ı yeniden başlatın.",
|
||||
"restart_pending_error": "Bu işlem başarısız oldu: Maintenance Supporter {version} sürümüne güncellendi, ancak Home Assistant o zamandan beri yeniden başlatılmadı. Home Assistant'ı yeniden başlatın ve tekrar deneyin.",
|
||||
"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",
|
||||
|
||||
@@ -249,6 +249,7 @@
|
||||
"interval_anchor": "Прив'язка інтервалу",
|
||||
"anchor_completion": "Від дати виконання",
|
||||
"anchor_planned": "Від запланованої дати (без зміщення)",
|
||||
"interval_anchor_hint": "Від дати виконання: наступний термін відраховується від дня, коли завдання позначено виконаним, тож раннє чи пізнє виконання зсуває графік. Від запланованої дати: графік зберігає свої дати, наприклад коли рахунок сплачено за кілька тижнів до терміну.",
|
||||
"edit_object": "Редагувати об'єкт",
|
||||
"name": "Назва",
|
||||
"manufacturer_optional": "Виробник (необов'язково)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "Дайте кільком сенсорам однакову назву об'єкта — вони стануть одним об'єктом; введіть назву наявного об'єкта, щоб додати їх туди.",
|
||||
"adopt_summary_title": "Що змінить додавання",
|
||||
"adopt_summary_existing": "«{name}»: завдання {before} → {after}",
|
||||
"adopt_summary_totals": "Завдання: {tasks} · об'єкти: {objects}",
|
||||
"adopt_summary_totals_new": "Завдання: {tasks} · об'єкти: {objects} (з них нових: {new})",
|
||||
"adopt_problem_adopt": "Прийняти вибрані",
|
||||
"adopt_problem_done": "Прийнято сенсорів проблем: {tasks}",
|
||||
"adopt_problem_done_one": "Прийнято 1 сенсор проблем",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"battery_fleet_setup_done": "Парк батарей налаштовано — одне завдання стежить за всіма.",
|
||||
"update_banner": "На сервері новіша версія Maintenance Supporter — перезавантажте, щоб оновити панель.",
|
||||
"update_reload": "Перезавантажити",
|
||||
"restart_pending_banner": "Maintenance Supporter оновлено до версії {version}. Перезапустіть Home Assistant, щоб завершити оновлення.",
|
||||
"restart_pending_error": "Не вдалося: Maintenance Supporter оновлено до версії {version}, але Home Assistant відтоді не перезапускався. Перезапустіть Home Assistant і спробуйте ще раз.",
|
||||
"row_actions_banner": "«Виконано» та «Пропустити» в рядках завдань тепер кнопки. Бажаєте старі значки?",
|
||||
"row_actions_keep": "Залишити кнопки",
|
||||
"row_actions_back": "Повернути значки",
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
"interval_anchor": "计划锚点",
|
||||
"anchor_completion": "从完成日期起算",
|
||||
"anchor_planned": "从计划日期起算 (无偏差)",
|
||||
"interval_anchor_hint": "从完成日期起算:下一个到期日从任务标记为完成的那天开始计算,因此提前或推迟完成都会移动计划。从计划日期起算:计划保持原定日期,例如账单在到期前几周就已支付时。",
|
||||
"edit_object": "编辑维护项",
|
||||
"name": "名称",
|
||||
"manufacturer_optional": "制造商 (可选)",
|
||||
@@ -1121,6 +1122,8 @@
|
||||
"adopt_object_hint": "给多个传感器相同的对象名称,它们就会合并为一个对象;输入已有对象的名称即可加入该对象。",
|
||||
"adopt_summary_title": "采用后会发生的变化",
|
||||
"adopt_summary_existing": "“{name}”:任务 {before} → {after}",
|
||||
"adopt_summary_totals": "任务:{tasks} · 对象:{objects}",
|
||||
"adopt_summary_totals_new": "任务:{tasks} · 对象:{objects}(其中新建:{new})",
|
||||
"adopt_problem_adopt": "采用所选",
|
||||
"adopt_problem_done": "已采用 {tasks} 个问题传感器",
|
||||
"adopt_problem_done_one": "已采用 1 个问题传感器",
|
||||
@@ -1282,6 +1285,8 @@
|
||||
"battery_fleet_setup_done": "电池群已设置 — 一个任务跟踪所有电池。",
|
||||
"update_banner": "服务器上有更新版本的 Maintenance Supporter——请重新加载以更新面板。",
|
||||
"update_reload": "重新加载",
|
||||
"restart_pending_banner": "Maintenance Supporter 已更新到 {version} 版本。请重启 Home Assistant 以完成更新。",
|
||||
"restart_pending_error": "操作失败:Maintenance Supporter 已更新到 {version} 版本,但 Home Assistant 此后尚未重启。请重启 Home Assistant 后重试。",
|
||||
"row_actions_banner": "任务行中的“完成”和“跳过”现在是按钮。更喜欢旧的图标?",
|
||||
"row_actions_keep": "保留按钮",
|
||||
"row_actions_back": "改回图标",
|
||||
|
||||
@@ -5,7 +5,7 @@ import { isSafeLink } from "./helpers/url";
|
||||
import { queryTokens, scoreFields } from "./helpers/search-match";
|
||||
import { objectRef, parseRef, renderRefChip, taskRef, type HasRef } from "./helpers/reference";
|
||||
import { applySubscriptionEvent, type SubscriptionEvent } from "./helpers/subscription-merge";
|
||||
import { isStaleBundle } from "./helpers/bundle-version";
|
||||
import { isStaleBundle, pendingRestartVersion, type ServerVersion } from "./helpers/bundle-version";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { syncLocaleFromHass, sharedStyles, STATUS_COLORS, currencySymbolOf, t, ensureLocale, isLocaleLoaded, formatDate, formatDueDays, formatInterval, formatRecurrence, setProfilePrefs, langOf, formatCost, formatQty, syncCurrencyDecimals} from "./styles";
|
||||
import { OVERVIEW_TABS, type OverviewTab } from "./helpers/overview-tabs";
|
||||
@@ -313,7 +313,11 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
// and the fleet isn't set up yet.
|
||||
@state() private _batteryFleetSetupAvailable = false;
|
||||
@state() private _staleBundle = false;
|
||||
/** The version an update installed while Home Assistant still runs the
|
||||
* old code (helpers/update_state.py); null when both agree. */
|
||||
@state() private _restartPendingVersion: string | null = null;
|
||||
private _staleChecked = false;
|
||||
private _onReconnect = (): void => this._checkServerVersion();
|
||||
private _toastTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
private _dismissedSuggestions = new Set<string>();
|
||||
|
||||
@@ -408,7 +412,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
private _statsService: StatisticsService | null = null;
|
||||
private _userService: UserService | null = null;
|
||||
private _dataLoaded = false;
|
||||
private _lastConnection: unknown = null;
|
||||
private _lastConnection: HomeAssistant["connection"] | null = null;
|
||||
|
||||
private get _lang(): string {
|
||||
return langOf(this.hass);
|
||||
@@ -553,7 +557,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
}
|
||||
this._dataLoaded = false;
|
||||
this._initialLoadDone = false;
|
||||
this._lastConnection = null;
|
||||
this._watchConnection(null);
|
||||
this._deepLinkHandled = false;
|
||||
// `_presetsApplied` intentionally survives (see its declaration).
|
||||
// Pending timers must not fire into a detached element (bug audit
|
||||
@@ -582,13 +586,13 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
if (changedProps.has("hass") && this.hass) {
|
||||
if (!this._dataLoaded) {
|
||||
this._dataLoaded = true;
|
||||
this._lastConnection = this.hass.connection;
|
||||
this._watchConnection(this.hass.connection);
|
||||
// Seed initial history state so back button returns to overview
|
||||
history.replaceState({ msp_view: "overview", msp_entry: null, msp_task: null }, "");
|
||||
this._loadData();
|
||||
this._subscribe();
|
||||
} else if (this.hass.connection !== this._lastConnection) {
|
||||
this._lastConnection = this.hass.connection;
|
||||
this._watchConnection(this.hass.connection);
|
||||
if (this._unsub) {
|
||||
try { this._unsub(); } catch { /* ignore */ }
|
||||
this._unsub = null;
|
||||
@@ -743,6 +747,31 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
}
|
||||
}
|
||||
|
||||
/** Follow `conn`'s reconnects for the version check (and stop following
|
||||
* the previous connection). */
|
||||
private _watchConnection(conn: HomeAssistant["connection"] | null): void {
|
||||
this._lastConnection?.removeEventListener?.("ready", this._onReconnect);
|
||||
this._lastConnection = conn;
|
||||
conn?.addEventListener?.("ready", this._onReconnect);
|
||||
}
|
||||
|
||||
/** Stale-bundle handshake (roadmap guard 2): compare the version esbuild
|
||||
* stamped into this bundle with the backend's — a mismatch means the
|
||||
* browser/service worker is still serving an OLD cached frontend, and no
|
||||
* amount of HA restarts fixes that. Unless an update waits for its
|
||||
* restart: then that explains any difference, and only the restart helps. */
|
||||
private _checkServerVersion(): void {
|
||||
this.hass.connection
|
||||
.sendMessagePromise<ServerVersion>({ type: "maintenance_supporter/version" })
|
||||
.then((v) => {
|
||||
this._restartPendingVersion = pendingRestartVersion(v);
|
||||
this._staleBundle = !this._restartPendingVersion && isStaleBundle(v?.version);
|
||||
})
|
||||
.catch(() => {
|
||||
/* backend too old to answer — no banner */
|
||||
});
|
||||
}
|
||||
|
||||
private async _loadData(): Promise<void> {
|
||||
const [objResult, statsResult, budgetResult, groupsResult, settingsResult, viewsResult] = await Promise.all([
|
||||
this.hass.connection.sendMessagePromise({ type: "maintenance_supporter/objects", compact: true }).catch(() => null),
|
||||
@@ -780,20 +809,11 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
.catch(() => {
|
||||
this._batteryFleetSetupAvailable = false;
|
||||
});
|
||||
// Stale-bundle handshake (roadmap guard 2): compare the version esbuild
|
||||
// stamped into this bundle with the backend's — a mismatch means the
|
||||
// browser/service worker is still serving an OLD cached frontend, and no
|
||||
// amount of HA restarts fixes that. Checked once per panel lifetime.
|
||||
// Checked once per panel lifetime, and again after every reconnect (a
|
||||
// Home Assistant restart ends the "restart pending" state).
|
||||
if (!this._staleChecked) {
|
||||
this._staleChecked = true;
|
||||
this.hass.connection
|
||||
.sendMessagePromise<{ version: string }>({ type: "maintenance_supporter/version" })
|
||||
.then((v) => {
|
||||
this._staleBundle = isStaleBundle(v?.version);
|
||||
})
|
||||
.catch(() => {
|
||||
/* backend too old to answer — no banner */
|
||||
});
|
||||
this._checkServerVersion();
|
||||
}
|
||||
if (statsResult) this._stats = statsResult as StatisticsResponse;
|
||||
if (budgetResult) { this._budget = budgetResult as BudgetStatus; syncCurrencyDecimals(this._budget); }
|
||||
@@ -1272,6 +1292,7 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
labels: task.labels ?? [],
|
||||
area_id: obj.object.area_id ?? null,
|
||||
responsible_user_id: task.responsible_user_id ?? null,
|
||||
assignee_pool: task.assignee_pool ?? null,
|
||||
group_names: groupNames,
|
||||
});
|
||||
}
|
||||
@@ -1281,8 +1302,11 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
const byDue = (a: TaskRow, b: TaskRow) => byStatus(a, b) || byDays(a, b);
|
||||
const areaName = (r: TaskRow) =>
|
||||
r.area_id ? this.hass?.areas?.[r.area_id]?.name || "" : "";
|
||||
const userName = (r: TaskRow) =>
|
||||
r.responsible_user_id ? this._userService?.getUserName(r.responsible_user_id) || "" : "";
|
||||
// Whom the task is meant for, as the person filter reads it (D#110):
|
||||
// the responsible person, else everyone it is shared with.
|
||||
const userNames = (r: TaskRow) =>
|
||||
taskUserIds(r).map((id) => this._userService?.getUserName(id) || "").filter(Boolean);
|
||||
const userName = (r: TaskRow) => userNames(r).sort((a, b) => a.localeCompare(b)).join(", ");
|
||||
const groupName = (r: TaskRow) => r.group_names[0] || "";
|
||||
const sorts: Record<SortMode, (a: TaskRow, b: TaskRow) => number> = {
|
||||
due_date: byDue,
|
||||
@@ -3172,6 +3196,14 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
render() {
|
||||
return html`
|
||||
<div class="panel">
|
||||
${this._restartPendingVersion
|
||||
? html`
|
||||
<div class="update-banner restart-pending-banner" role="status">
|
||||
<ha-icon icon="mdi:restart"></ha-icon>
|
||||
<span>${t("restart_pending_banner", this._lang).replace("{version}", this._restartPendingVersion)}</span>
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
${this._staleBundle
|
||||
? html`
|
||||
<div class="update-banner" role="status">
|
||||
@@ -3906,8 +3938,10 @@ export class MaintenanceSupporterPanel extends LitElement {
|
||||
const a = row.area_id ? this.hass?.areas?.[row.area_id]?.name : null;
|
||||
keys = [a || noneLabel];
|
||||
} else if (this._groupByMode === "user") {
|
||||
const u = row.responsible_user_id ? this._userService?.getUserName(row.responsible_user_id) : null;
|
||||
keys = [u || noneLabel];
|
||||
// A shared task with nobody responsible is listed under each of its
|
||||
// people, as the person filter lists it (D#110).
|
||||
const names = taskUserIds(row).map((id) => this._userService?.getUserName(id)).filter((n): n is string => !!n);
|
||||
keys = names.length > 0 ? [...new Set(names)] : [noneLabel];
|
||||
} else if (this._groupByMode === "group") {
|
||||
keys = row.group_names.length > 0 ? row.group_names : [noneLabel];
|
||||
} else if (this._groupByMode === "object") {
|
||||
|
||||
@@ -633,6 +633,8 @@ export interface TaskRow {
|
||||
labels: string[];
|
||||
area_id: string | null;
|
||||
responsible_user_id: string | null;
|
||||
/** "Shared with": with nobody responsible, the task is meant for each (D#110). */
|
||||
assignee_pool?: string[] | null;
|
||||
group_names: string[];
|
||||
/** #189: titles of the calendar events behind next_due (calendar kind). */
|
||||
next_event_titles: string[];
|
||||
@@ -660,6 +662,10 @@ export interface HomeAssistant {
|
||||
subscribeMsg: Record<string, unknown>,
|
||||
options?: Record<string, unknown>
|
||||
): Promise<() => void>;
|
||||
/** "ready" fires after a reconnect (a Home Assistant restart). Optional:
|
||||
* test stubs leave it out. */
|
||||
addEventListener?(event: "ready", callback: () => void): void;
|
||||
removeEventListener?(event: "ready", callback: () => void): void;
|
||||
};
|
||||
callService(
|
||||
domain: string,
|
||||
|
||||
Reference in New Issue
Block a user