This commit is contained in:
Mateusz Gruszczyński
2026-08-25 18:54:35 +02:00
parent a8b80bdba9
commit 3ee93b7225
18 changed files with 560 additions and 93 deletions
+5 -2
View File
@@ -635,7 +635,7 @@ function deviceCard(device, detailed = false) {
<div class="mode-row">${modes.map(mode => `<button class="${device.mode === mode ? 'active' : ''}" data-action="mode" data-value="${mode}" data-device="${esc(device.id)}">${esc(modeLabel(mode))}</button>`).join('')}</div>
<div class="fan-row">${fans.map(fan => `<button class="${Number(device.fan_speed) === fan ? 'active' : ''}" data-action="fan" data-value="${fan}" data-device="${esc(device.id)}">${esc(fanLabel(fan))}</button>`).join('')}</div>
<div class="device-toggles">
<button class="${device.swing_vertical ? 'active' : ''}" data-action="toggle" data-field="swing_vertical" data-device="${esc(device.id)}">${esc(tr('devices.swing'))}</button>
<button class="${device.swing_vertical ? 'active' : ''}" data-action="toggle" data-field="swing_vertical" data-device="${esc(device.id)}">${esc(tr('devices.swing'))}</button>
${device.supports_quiet === false ? '' : `<button class="${device.quiet ? 'active' : ''}" data-action="toggle" data-field="quiet" data-device="${esc(device.id)}">${esc(tr('devices.quiet'))}</button>`}
${device.supports_turbo === false ? '' : `<button class="${device.turbo ? 'active' : ''}" data-action="toggle" data-field="turbo" data-device="${esc(device.id)}">${esc(tr('devices.turbo'))}</button>`}
</div>
@@ -684,7 +684,10 @@ function zoneCard(zone, detailed = true) {
const target = Number(zone.effective_setpoint ?? zone.setpoint);
const manual = zone.manual_preset || 'auto';
const mode = zone.inherit_house_mode ? 'house' : zone.mode;
const override = zone.manual_override_until ? `${tr('zones.overrideUntil')} ${new Date(zone.manual_override_until).toLocaleTimeString(locale(), {hour:'2-digit',minute:'2-digit'})}` : tr('zones.scheduleControl');
const hasManualOverride = zone.manual_preset != null || zone.manual_setpoint != null;
const override = zone.manual_override_until
? `${tr('zones.overrideUntil')} ${new Date(zone.manual_override_until).toLocaleTimeString(locale(), {hour:'2-digit',minute:'2-digit'})}`
: (hasManualOverride ? tr('zones.manualNoBoundary') : tr('zones.scheduleControl'));
const enabledControl = detailed
? `<span class="badge ${zone.enabled ? 'active' : ''}">${esc(state)}</span>`
: `<button type="button" class="zone-enable-toggle ${zone.enabled ? 'active' : ''}" data-action="zone-enabled" data-id="${esc(zone.id)}" data-value="${zone.enabled ? 'false' : 'true'}" aria-label="${esc(tr(zone.enabled ? 'zones.disable' : 'zones.enable'))}"><span>${zone.enabled ? '✓' : '○'}</span>${esc(state)}</button>`;
+1
View File
@@ -376,6 +376,7 @@
<label><span data-i18n="common.device">Device</span><select name="device_id" required></select></label>
<div class="copy-settings-row"><select id="copyZoneSource"><option value="" data-i18n="zones.copyFrom">Copy thermostat settings from…</option></select><button type="button" class="secondary" id="copyZoneSettings" data-i18n="zones.copySettings">Copy settings</button></div>
<div class="two"><label><span data-i18n="zones.modePolicy">Mode policy</span><select name="mode_policy"><option value="house" data-i18n="zones.followHouse">Follow house mode</option><option value="cool" data-i18n="mode.cool">Cooling only</option><option value="heat" data-i18n="mode.heat">Heating only</option></select></label><label><span data-i18n="common.targetC">Manual target °C</span><input type="text" inputmode="decimal" step="0.5" min="8" max="30" name="setpoint" value="23"></label></div>
<p class="field-note" data-i18n="zones.modePolicyHint">If this zone should inherit the mode selected globally in the app, leave “Follow house mode” unchanged. Cooling only / Heating only forces a fixed mode for this zone.</p>
<details class="profile-editor"><summary data-i18n="zones.profileTemperatures">Comfort / sleep / away temperatures</summary>
<div class="profile-grid"><strong data-i18n="mode.cool">Cooling</strong><label><span data-i18n="preset.comfort">Comfort</span><input type="text" inputmode="decimal" step="0.5" name="cool_comfort_setpoint" value="23"></label><label><span data-i18n="preset.sleep">Sleep</span><input type="text" inputmode="decimal" step="0.5" name="cool_sleep_setpoint" value="24.5"></label><label><span data-i18n="preset.away">Away</span><input type="text" inputmode="decimal" step="0.5" name="cool_away_setpoint" value="27"></label></div>
<div class="profile-grid"><strong data-i18n="mode.heat">Heating</strong><label><span data-i18n="preset.comfort">Comfort</span><input type="text" inputmode="decimal" step="0.5" name="heat_comfort_setpoint" value="21"></label><label><span data-i18n="preset.sleep">Sleep</span><input type="text" inputmode="decimal" step="0.5" name="heat_sleep_setpoint" value="19"></label><label><span data-i18n="preset.away">Away</span><input type="text" inputmode="decimal" step="0.5" name="heat_away_setpoint" value="17"></label></div>
+32 -1
View File
@@ -616,7 +616,7 @@ html[data-theme='light'] .simulation-metrics > div, html[data-theme='light'] .si
/* v0.5.4: settings headers no longer use decorative icons. */
.settings-block-head { gap:0; }
.device-capability-panel { display:grid; gap:8px; padding:12px 0 2px; border-top:1px solid var(--line); }
.device-capability-panel { display:grid; gap:8px; padding:12px 0 2px; }
.device-capability-panel > small { color:var(--muted); font-size:11px; text-transform:uppercase; letter-spacing:.08em; }
.device-capability-buttons { display:flex; flex-wrap:wrap; gap:7px; }
.device-capability-buttons button { min-height:34px; padding:7px 11px; border:1px solid var(--line); border-radius:11px; background:var(--surface-muted); color:var(--text); }
@@ -841,3 +841,34 @@ body.simulation-standalone [data-view="simulation"] { min-height:calc(100vh - 36
#controlPlan.automation-plan-grid { grid-template-columns:repeat(auto-fit,minmax(min(100%,180px),1fr)); }
}
[data-view="dashboard"] .dashboard-summary-card { margin-bottom:10px; }
/* 0.7.0: desktop fit and cleaner unit controls. */
#zoneList .zone-thermostat .card-footer { align-items:flex-start; }
#zoneList .zone-thermostat .card-footer > small {
flex:1 1 auto;
min-width:0;
overflow:visible;
text-overflow:clip;
white-space:normal;
line-height:1.35;
}
#zoneList .zone-thermostat .card-menu { flex:0 0 auto; }
@media (min-width: 701px) {
#dashboardDevices .mode-row {
grid-template-columns:repeat(5,minmax(0,1fr));
gap:4px;
}
#dashboardDevices .fan-row {
grid-template-columns:repeat(4,minmax(0,1fr));
gap:4px;
}
#dashboardDevices .mode-row button,
#dashboardDevices .fan-row button {
min-height:26px;
padding:4px 3px;
font-size:9px;
line-height:1.05;
white-space:nowrap;
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'gree-controller-v069-dashboard-fit';
const CACHE = 'gree-controller-v070-schedule-audit-ui';
const SCOPE = new URL(self.registration.scope).pathname.replace(/\/$/, '');
const path = value => `${SCOPE}${value.startsWith('/') ? value : `/${value}`}` || '/';
const ASSETS = [path('/'), path('/styles.css'), path('/app.js'), path('/theme-init.js'), path('/favicon.svg'), path('/manifest.webmanifest'), path('/lang/index.json'), path('/lang/en.json')];