217 files
This commit is contained in:
@@ -56,6 +56,7 @@ interface SettingsResponse {
|
||||
battery_low_percent?: number;
|
||||
/** #180: a low battery counts as replaced only once its level is above this. */
|
||||
battery_recovered_percent?: number;
|
||||
battery_auto_record_recovery?: boolean;
|
||||
/** D#182: shopping-search URL with {q} ("" = automatic) + the automatic value in effect. */
|
||||
part_search_url_template?: string;
|
||||
part_search_url_default?: string;
|
||||
@@ -517,6 +518,28 @@ export class MaintenanceSettingsView extends LitElement {
|
||||
return runWs<T>(this, payload, { fallbackKey, busy, onError: (msg) => this._showToast(msg) });
|
||||
}
|
||||
|
||||
@state() private _compacting = false;
|
||||
|
||||
/** #170: renumber every object, task and completion sequentially — an
|
||||
* explicit, admin-only action behind a confirm (printed booklets keep the
|
||||
* old numbers, so this is never done silently). */
|
||||
private async _compactReferenceNumbers(): Promise<void> {
|
||||
const L = this._lang;
|
||||
if (this._compacting || !window.confirm(t("settings_compact_refs_confirm", L))) return;
|
||||
const res = await this._ws<{ objects: number; tasks: number; completions: number }>(
|
||||
{ type: "maintenance_supporter/reference_numbers/compact" },
|
||||
"action_error",
|
||||
(b) => { this._compacting = b; },
|
||||
);
|
||||
if (!res) return;
|
||||
this._showToast(
|
||||
t("settings_compact_refs_done", L)
|
||||
.replace("{objects}", String(res.objects))
|
||||
.replace("{tasks}", String(res.tasks))
|
||||
.replace("{completions}", String(res.completions)),
|
||||
);
|
||||
}
|
||||
|
||||
/** Bounded integer settings: an out-of-range entry used to be dropped
|
||||
* silently while the field kept showing it (bug review 2026-09-04). Now
|
||||
* it is named in a toast and the field snaps back to the stored value;
|
||||
@@ -870,6 +893,13 @@ export class MaintenanceSettingsView extends LitElement {
|
||||
${this._intSetting("battery_recovered_percent", g.battery_recovered_percent ?? 50)}
|
||||
</label>
|
||||
<div class="setting-hint">${t("settings_battery_recovered_percent_hint", L)}</div>
|
||||
<label class="setting-row">
|
||||
<span class="setting-label">${t("settings_battery_auto_record", L)}</span>
|
||||
<input type="checkbox" class="auto-record-recovery"
|
||||
.checked=${g.battery_auto_record_recovery === true}
|
||||
@change=${(e: Event) => this._updateSetting("battery_auto_record_recovery", (e.target as HTMLInputElement).checked)} />
|
||||
</label>
|
||||
<div class="setting-hint">${t("settings_battery_auto_record_hint", L)}</div>
|
||||
${this._renderBatteryNotesHint(L)}
|
||||
${this._renderBatteryLifetimes(L)}
|
||||
<div class="setting-hint">${t("settings_thresholds_hint", L)}</div>
|
||||
@@ -896,6 +926,15 @@ export class MaintenanceSettingsView extends LitElement {
|
||||
@change=${(e: Event) => this._updateSetting("ref_numbers_in_lists", (e.target as HTMLInputElement).checked)} />
|
||||
</label>
|
||||
<div class="setting-hint">${t("settings_ref_numbers_in_lists_hint", L)}</div>
|
||||
${this.hass?.user?.is_admin
|
||||
? html`<div class="setting-row">
|
||||
<span class="setting-label">${t("settings_compact_refs", L)}</span>
|
||||
<button class="btn compact-refs" ?disabled=${this._compacting} @click=${this._compactReferenceNumbers}>
|
||||
<ha-icon icon="mdi:sort-numeric-ascending"></ha-icon> ${t("settings_compact_refs", L)}
|
||||
</button>
|
||||
</div>
|
||||
<div class="setting-hint">${t("settings_compact_refs_hint", L)}</div>`
|
||||
: nothing}
|
||||
<label class="setting-row">
|
||||
<span class="setting-label">${t("settings_currency", L)}</span>
|
||||
<select .value=${live(b.currency)} @change=${(e: Event) => this._updateSetting("budget_currency", (e.target as HTMLSelectElement).value)}>
|
||||
|
||||
@@ -168,6 +168,9 @@ export class MaintenanceTaskDialog extends LitElement {
|
||||
@state() private _warning = "";
|
||||
@state() private _entryId = "";
|
||||
@state() private _taskId: string | null = null; // null = create
|
||||
/** #181: the battery fleet task takes its quantities from Battery Notes per
|
||||
* device — the parts picker is hidden for it (links there would be ignored). */
|
||||
@state() private _isFleetTask = false;
|
||||
// When openCreate is called without an entry_id and a list of objects is supplied,
|
||||
// the dialog renders an Object selector dropdown so the user can pick the parent.
|
||||
@state() private _objectChoices: Array<{ entry_id: string; name: string }> = [];
|
||||
@@ -350,6 +353,7 @@ export class MaintenanceTaskDialog extends LitElement {
|
||||
public async openCreate(entryId: string, objects?: Array<{ entry_id: string; object: { name: string } }>): Promise<void> {
|
||||
this._entryId = entryId;
|
||||
this._taskId = null;
|
||||
this._isFleetTask = false;
|
||||
this._error = "";
|
||||
this._warning = "";
|
||||
// If no entryId is preset but caller passed objects, expose them as a dropdown.
|
||||
@@ -379,6 +383,7 @@ export class MaintenanceTaskDialog extends LitElement {
|
||||
// edit mode — and picking another object re-pointed _entryId while
|
||||
// _taskId kept the old task (audit 2026-08-29).
|
||||
this._objectChoices = [];
|
||||
this._isFleetTask = task.battery_fleet_task === true;
|
||||
this._name = task.name;
|
||||
this._type = task.type;
|
||||
this._scheduleType = task.schedule_type;
|
||||
@@ -2675,7 +2680,9 @@ export class MaintenanceTaskDialog extends LitElement {
|
||||
${this._partsLoadFailed
|
||||
? html`<div class="field-help parts-load-failed">${t("parts_load_failed", L)}</div>`
|
||||
: nothing}
|
||||
${this.parts.length || this._foreignOwners.length
|
||||
${this._isFleetTask
|
||||
? html`<div class="field-help parts-fleet-hint">${t("task_parts_fleet_hint", L)}</div>`
|
||||
: this.parts.length || this._foreignOwners.length
|
||||
? html`
|
||||
<div class="field">
|
||||
<label>${t("consumes_parts_label", L)}</label>
|
||||
|
||||
Reference in New Issue
Block a user