Datumfels Focus verbessert

This commit is contained in:
2026-04-27 17:39:44 +02:00
parent c633acf9be
commit e394b55cfd
+106 -10
View File
@@ -15,6 +15,15 @@ const DEFAULT_ENTITIES = {
};
class SternwarteCard extends HTMLElement {
constructor() {
super();
this._scheduleInputState = {
open: { draft: "", editing: false, pending: false },
close: { draft: "", editing: false, pending: false },
};
this._pendingRender = false;
}
connectedCallback() {
this._ensureClockTimer();
}
@@ -36,7 +45,7 @@ class SternwarteCard extends HTMLElement {
set hass(hass) {
this._hass = hass;
this._ensureClockTimer();
this.render();
this._requestRender();
}
getCardSize() {
@@ -58,10 +67,73 @@ class SternwarteCard extends HTMLElement {
_ensureClockTimer() {
if (this._clockTimer) return;
this._clockTimer = window.setInterval(() => {
if (this._hass) this.render();
if (this._hass) this._requestRender();
}, 30000);
}
_requestRender() {
if (this._isScheduleEditing()) {
this._pendingRender = true;
return;
}
this._pendingRender = false;
this.render();
}
_isScheduleEditing() {
return Object.values(this._scheduleInputState).some((field) => field.editing);
}
_scheduleFieldState(key) {
return this._scheduleInputState[key];
}
_scheduleInputValue(key, fallbackState) {
const field = this._scheduleFieldState(key);
if (field.draft) return field.draft;
return this._isoForInput(fallbackState);
}
_resetScheduleDrafts() {
for (const field of Object.values(this._scheduleInputState)) {
field.draft = "";
field.editing = false;
field.pending = false;
}
}
_beginScheduleEdit(key, fallbackState) {
const field = this._scheduleFieldState(key);
field.editing = true;
field.pending = false;
if (!field.draft) {
field.draft = this._isoForInput(fallbackState);
}
}
_updateScheduleDraft(key, value) {
const field = this._scheduleFieldState(key);
field.draft = value;
field.pending = false;
}
_endScheduleEdit(key, event) {
const field = this._scheduleFieldState(key);
field.editing = false;
if (!this._isScheduleEditing() && this._pendingRender) {
this._requestRender();
}
}
_bindScheduleInput(key, inputId, fallbackState) {
const input = this.shadowRoot.getElementById(inputId);
if (!input) return;
input.addEventListener("focus", () => this._beginScheduleEdit(key, fallbackState));
input.addEventListener("input", (event) => this._updateScheduleDraft(key, event.target.value));
input.addEventListener("change", (event) => this._updateScheduleDraft(key, event.target.value));
input.addEventListener("blur", (event) => this._endScheduleEdit(key, event));
}
_firstExistingEntityId(entityIds) {
for (const entityId of entityIds) {
if (entityId && this._state(entityId)) return entityId;
@@ -128,14 +200,22 @@ class SternwarteCard extends HTMLElement {
});
}
_setDateTime(entityId, inputId) {
_setDateTime(entityId, inputId, key) {
const input = this.shadowRoot.getElementById(inputId);
if (!input || !input.value) return;
const field = this._scheduleFieldState(key);
const value = field?.draft || input?.value || "";
if (!value) return;
if (!entityId) return;
field.pending = true;
field.editing = false;
field.draft = value;
this._hass.callService("datetime", "set_value", {
entity_id: entityId,
datetime: input.value,
datetime: value,
});
if (this._pendingRender) {
this._requestRender();
}
}
_isoForInput(state) {
@@ -527,6 +607,16 @@ class SternwarteCard extends HTMLElement {
const closeScheduleEntityId = this._scheduleCloseEntityId();
const openSchedule = this._state(openScheduleEntityId);
const closeSchedule = this._state(closeScheduleEntityId);
const openInputValue = this._scheduleInputValue("open", openSchedule);
const closeInputValue = this._scheduleInputValue("close", closeSchedule);
if (openInputValue === this._isoForInput(openSchedule)) {
this._scheduleFieldState("open").draft = "";
this._scheduleFieldState("open").pending = false;
}
if (closeInputValue === this._isoForInput(closeSchedule)) {
this._scheduleFieldState("close").draft = "";
this._scheduleFieldState("close").pending = false;
}
const roofPosition = this._roofPositionValue();
const windIndicator = this._windIndicatorState();
const rainOn = rain?.state === "on";
@@ -1040,11 +1130,11 @@ class SternwarteCard extends HTMLElement {
</div>
</div>
<div class="schedule-grid">
<input id="open-schedule-input" type="datetime-local" value="${this._isoForInput(openSchedule)}">
<input id="open-schedule-input" type="datetime-local" value="${openInputValue}">
<button type="button" class="secondary" id="open-schedule-btn">\u00d6ffnen setzen</button>
</div>
<div class="schedule-grid">
<input id="close-schedule-input" type="datetime-local" value="${this._isoForInput(closeSchedule)}">
<input id="close-schedule-input" type="datetime-local" value="${closeInputValue}">
<button type="button" class="secondary" id="close-schedule-btn">Schlie\u00dfen setzen</button>
</div>
<div class="inline-actions">
@@ -1062,9 +1152,15 @@ class SternwarteCard extends HTMLElement {
this._bindClick("power-on-btn", () => this._callEntity("switch", "turn_on", powerEntityId));
this._bindClick("power-off-btn", () => this._callEntity("switch", "turn_off", powerEntityId));
this._bindClick("nautical-btn", () => this._call("sternwarte", "set_nautical_schedule"));
this._bindClick("clear-schedule-btn", () => this._call("sternwarte", "clear_schedule"));
this._bindClick("open-schedule-btn", () => this._setDateTime(openScheduleEntityId, "open-schedule-input"));
this._bindClick("close-schedule-btn", () => this._setDateTime(closeScheduleEntityId, "close-schedule-input"));
this._bindClick("clear-schedule-btn", () => {
this._resetScheduleDrafts();
this._call("sternwarte", "clear_schedule");
this._requestRender();
});
this._bindClick("open-schedule-btn", () => this._setDateTime(openScheduleEntityId, "open-schedule-input", "open"));
this._bindClick("close-schedule-btn", () => this._setDateTime(closeScheduleEntityId, "close-schedule-input", "close"));
this._bindScheduleInput("open", "open-schedule-input", openSchedule);
this._bindScheduleInput("close", "close-schedule-input", closeSchedule);
}
}