v0.9.3
This commit is contained in:
+3
-3
@@ -44,10 +44,10 @@ function renderHouseClimate() {
|
||||
const zonePresets = (app.zones || []).map(zone => zone.manual_preset || 'auto');
|
||||
const preset = zonePresets.length && zonePresets.every(value => value === zonePresets[0]) ? zonePresets[0] : null;
|
||||
const outdoor = app.outdoorTemperature == null ? tr('common.unavailable') : fmtTemp(app.outdoorTemperature);
|
||||
const powerEnabled = app.settings.house_power_enabled !== false;
|
||||
const powerOn = $('#housePowerOn'), powerOff = $('#housePowerOff');
|
||||
if (powerOn) { powerOn.classList.toggle('active', powerEnabled); powerOn.setAttribute('aria-pressed', String(powerEnabled)); }
|
||||
if (powerOff) { powerOff.classList.toggle('active', !powerEnabled); powerOff.setAttribute('aria-pressed', String(!powerEnabled)); }
|
||||
// Global power buttons are one-shot actions, not a persistent ON/OFF mode.
|
||||
if (powerOn) { powerOn.classList.remove('active'); powerOn.removeAttribute('aria-pressed'); }
|
||||
if (powerOff) { powerOff.classList.remove('active'); powerOff.removeAttribute('aria-pressed'); }
|
||||
node.innerHTML = `<div class="house-climate-head"><div><span class="eyebrow">${esc(tr('house.seasonMode'))}</span><h3>${esc(tr('house.smartThermostat'))}</h3><p>${esc(tr('house.setpointStrategy'))}</p></div><div class="outside-pill"><small>${esc(tr('house.outdoor'))}</small><strong>${esc(outdoor)}</strong></div></div>
|
||||
<div class="house-mode-row">
|
||||
<button class="${mode==='cool'?'active':''}" data-action="house-mode" data-value="cool" aria-pressed="${mode==='cool'}">${esc(tr('mode.cool'))}</button>
|
||||
|
||||
+5
-4
@@ -96,7 +96,7 @@ function groupControlStyle(group) {
|
||||
}
|
||||
|
||||
function groupControlForZone(zone) {
|
||||
if(app.settings?.house_power_enabled === false || zone?.device_manual_override || zone?.local_thermostat_power != null) return null;
|
||||
if(zone?.device_manual_override || zone?.local_thermostat_power != null) return null;
|
||||
const source=String(zone?.control_source || '');
|
||||
if(!source.startsWith('group:')) return null;
|
||||
const groupId=source.slice(6);
|
||||
@@ -115,6 +115,7 @@ function compressorPendingDescription(zone) {
|
||||
const targetValue = Number(target);
|
||||
if(kind==='mode_change') return tr('zones.queuedModeChange', {mode:modeLabel(mode), temperature:Number.isFinite(targetValue)?targetValue.toFixed(1):'—'});
|
||||
if(kind==='power_on') return tr('zones.queuedPowerOn', {mode:modeLabel(mode), temperature:Number.isFinite(targetValue)?targetValue.toFixed(1):'—'});
|
||||
if(kind==='global_power_on') return tr('zones.queuedGlobalPowerOn');
|
||||
return tr('zones.queuedAction');
|
||||
}
|
||||
|
||||
@@ -158,7 +159,9 @@ function renderCompressorQueueModal() {
|
||||
const device = app.devices.find(item => item.id === zone.device_id);
|
||||
const until = zone.compressor_pending_until || zone.lockout_until;
|
||||
const group = groupControlForZone(zone);
|
||||
const source = group ? `${zoneControlOwnerLabel(zone)}: ${group.name}` : zoneControlOwnerLabel(zone);
|
||||
const source = zone.compressor_pending_action === 'global_power_on'
|
||||
? tr('zones.queueSourceGlobal')
|
||||
: (group ? `${zoneControlOwnerLabel(zone)}: ${group.name}` : zoneControlOwnerLabel(zone));
|
||||
const exact = until ? dateTime(until) : tr('zones.afterProtection');
|
||||
return `<article class="compressor-queue-item">
|
||||
<div class="compressor-queue-index">${index + 1}</div>
|
||||
@@ -361,7 +364,6 @@ function groupCard(group, detailed = false) {
|
||||
const memberNames = state.zones.map(zone => zone.name);
|
||||
const memberText = memberNames.length ? memberNames.join(' · ') : tr('groups.noMembers');
|
||||
const powerEnabled = group.power_enabled !== false;
|
||||
const masterOff = app.settings?.house_power_enabled === false;
|
||||
const modeLabelForGroup = value => value === 'house' ? tr('groups.followHouse') : (value === 'mixed' ? tr('groups.mixed') : modeLabel(value));
|
||||
const presetLabelForGroup = value => value === 'mixed' ? tr('groups.mixed') : zonePresetLabel(value);
|
||||
const fallbackTarget = Number(state.zones[0]?.manual_setpoint ?? state.zones[0]?.effective_setpoint ?? state.zones[0]?.setpoint ?? 23);
|
||||
@@ -383,7 +385,6 @@ function groupCard(group, detailed = false) {
|
||||
<div class="group-control-block"><small>${esc(tr('groups.mode'))}</small><div class="mode-row group-mode-row">${['house','heat','cool'].map(mode => `<button class="${state.mode === mode ? 'active' : ''}" data-action="group-mode" data-id="${esc(group.id)}" data-value="${mode}"${climateControlsDisabled}>${esc(mode === 'house' ? tr('groups.followHouse') : modeLabel(mode))}</button>`).join('')}</div></div>
|
||||
<div class="group-control-block"><small>${esc(tr('groups.profile'))}</small><div class="preset-row group-preset-row">${['auto','comfort','sleep','away'].map(preset => `<button class="${state.preset === preset ? 'active' : ''}" data-action="group-preset" data-id="${esc(group.id)}" data-value="${preset}"${climateControlsDisabled}>${esc(zonePresetLabel(preset))}</button>`).join('')}<button class="${state.preset === 'custom' ? 'active' : (customDraft?.open === true ? 'editing' : '')}" data-action="group-custom-open" data-id="${esc(group.id)}" title="${esc(tr('groups.customOpenHint'))}"${climateControlsDisabled}>${esc(tr('preset.custom'))}</button></div>
|
||||
<div class="group-custom-temperature" data-group-custom-editor="${esc(group.id)}" ${customEditorVisible ? '' : 'hidden'}><label><span>${esc(tr('groups.customTemperature'))}</span><div class="group-custom-temperature-row"><input type="text" inputmode="decimal" min="8" max="30" step="0.1" value="${customTarget.toFixed(1)}" data-group-custom-temperature="${esc(group.id)}" aria-label="${esc(tr('groups.customTemperature'))}" title="${esc(tr('groups.customTemperatureHint'))}"><span>°C</span><button type="button" class="primary" data-action="group-custom-temperature" data-id="${esc(group.id)}" title="${esc(tr('groups.applyCustomTemperatureHint'))}">${esc(tr('actions.apply'))}</button><button type="button" class="secondary" data-action="group-custom-cancel" data-id="${esc(group.id)}">${esc(tr('actions.cancel'))}</button></div></label>${customDraftPending ? `<small class="group-custom-draft-note">${esc(tr('groups.customDraftPending'))}</small>` : ''}</div></div>
|
||||
${masterOff ? `<p class="field-note warning-note">${esc(tr('groups.masterOff'))}</p>` : ''}
|
||||
${detailed ? `<div class="card-footer"><small>${esc(tr('groups.memberCount', {count: state.zones.length}))}</small><div class="card-menu"><button data-action="edit-group" data-id="${esc(group.id)}">${esc(tr('actions.edit'))}</button><button class="danger" data-action="delete-group" data-id="${esc(group.id)}">${esc(tr('actions.delete'))}</button></div></div>` : ''}
|
||||
</article>`;
|
||||
}
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ document.addEventListener('click', async event => {
|
||||
}
|
||||
if (action === 'house-power') {
|
||||
const power = button.dataset.value === 'true';
|
||||
if (!power && app.settings?.house_power_enabled !== false && !confirm(tr('house.powerOffConfirm'))) return;
|
||||
if (!power && !confirm(tr('house.powerOffConfirm'))) return;
|
||||
try {
|
||||
button.disabled = true;
|
||||
const result = await enqueueClimateControlTask(async () => {
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ function connectWebSocket() {
|
||||
if (!haDirty) renderHomeAssistantSettings();
|
||||
renderHouseClimate(); renderSimulationModeBanner(); renderSystemInfo(); renderDebugOverlay(); if(app.settings?.debug?.overlay_enabled) loadDebugBacklog(); scheduleControlPlanLoad();
|
||||
}
|
||||
else if (message.event === 'house.power_changed') { app.settings=app.settings||{}; app.settings.house_power_enabled=data.house_power_enabled !== false; renderHouseClimate(); renderGroups(); scheduleControlPlanLoad(); }
|
||||
else if (message.event === 'house.power_changed') { renderHouseClimate(); renderGroups(); scheduleControlPlanLoad(); }
|
||||
else if (message.event === 'debug.settings') { app.settings = app.settings || {}; app.settings.debug = data; if (!isFormDirty($('#settingsForm'))) renderSettings(); renderDebugOverlay(); if(data.overlay_enabled) loadDebugBacklog(); }
|
||||
else if (message.event === 'outdoor.updated') { app.outdoorTemperature=Number.isFinite(Number(data.temperature))?Number(data.temperature):null; renderHouseClimate(); scheduleControlPlanLoad(); }
|
||||
else if (message.event === 'gree.frame_received') {
|
||||
|
||||
Reference in New Issue
Block a user