v0.6.2
This commit is contained in:
+63
-6
@@ -632,7 +632,14 @@ function fillSelects() {
|
||||
if (zoneSelect) { const currentZone = zoneSelect.value; zoneSelect.innerHTML = zoneOptions; if ([...zoneSelect.options].some(o => o.value === currentZone)) zoneSelect.value = currentZone; }
|
||||
const presetZone = $('#schedulePresetZone');
|
||||
if (presetZone) { const currentZone = presetZone.value; presetZone.innerHTML = zoneOptions; if ([...presetZone.options].some(o => o.value === currentZone)) presetZone.value = currentZone; }
|
||||
const copyZone=$('#copyZoneSource'); if(copyZone){ const current=copyZone.value; copyZone.innerHTML='<option value="">Copy thermostat settings from…</option>'+app.zones.map(z=>`<option value="${esc(z.id)}">${esc(z.name)}</option>`).join(''); if([...copyZone.options].some(o=>o.value===current))copyZone.value=current; }
|
||||
const copyZone=$('#copyZoneSource');
|
||||
if(copyZone){
|
||||
const current=copyZone.value;
|
||||
const editingZoneId=$('#zoneForm')?.dataset.editingZoneId || '';
|
||||
const sources=app.zones.filter(zone=>zone.id!==editingZoneId);
|
||||
copyZone.innerHTML=`<option value="">${esc(tr('zones.copyFrom'))}</option>`+sources.map(z=>`<option value="${esc(z.id)}">${esc(z.name)}</option>`).join('');
|
||||
copyZone.value=[...copyZone.options].some(option=>option.value===current)?current:'';
|
||||
}
|
||||
}
|
||||
|
||||
function renderAccessTokens() {
|
||||
@@ -928,8 +935,12 @@ function updateSchedulePresetField() {
|
||||
|
||||
function populateZone(id) {
|
||||
const item = app.zones.find(v => v.id === id); if (!item) return;
|
||||
const form = $('#zoneForm'); form.reset(); fillSelects();
|
||||
Object.entries(item).forEach(([key,value]) => { if (form.elements[key] && value != null && typeof value !== 'object') form.elements[key].value = value; });
|
||||
const form = $('#zoneForm');
|
||||
form.reset();
|
||||
form.dataset.editingZoneId = item.id;
|
||||
form.elements.id.value = item.id;
|
||||
fillSelects();
|
||||
Object.entries(item).forEach(([key,value]) => { if (key !== 'id' && form.elements[key] && value != null && typeof value !== 'object') form.elements[key].value = value; });
|
||||
form.mode_policy.value = item.inherit_house_mode ? 'house' : (item.mode || 'cool');
|
||||
if (Number(item.profile_version || 0) === 0) {
|
||||
if ((item.mode || 'cool') === 'heat') form.heat_comfort_setpoint.value = Number(item.setpoint ?? 21);
|
||||
@@ -1360,7 +1371,17 @@ document.addEventListener('click', async event => {
|
||||
return;
|
||||
}
|
||||
if (button.dataset.go) { $('#moreDialog').close(); showView(button.dataset.go); return; }
|
||||
if (button.dataset.open) { const form = document.getElementById(button.dataset.open.replace('Dialog','Form')); if (form) form.reset(); if (button.dataset.open === 'zoneDialog') updateZoneSensorFields(); if (button.dataset.open === 'scheduleDialog') updateSchedulePresetField(); openDialog(button.dataset.open); return; }
|
||||
if (button.dataset.open) {
|
||||
const form = document.getElementById(button.dataset.open.replace('Dialog','Form'));
|
||||
if (form) form.reset();
|
||||
if (button.dataset.open === 'zoneDialog') {
|
||||
if (form) { form.dataset.editingZoneId = ''; if (form.elements.id) form.elements.id.value = ''; }
|
||||
updateZoneSensorFields();
|
||||
}
|
||||
if (button.dataset.open === 'scheduleDialog') updateSchedulePresetField();
|
||||
openDialog(button.dataset.open);
|
||||
return;
|
||||
}
|
||||
if (button.hasAttribute('data-close')) { button.closest('dialog')?.close(); return; }
|
||||
if (button.dataset.historyTab) { showHistoryTab(button.dataset.historyTab); return; }
|
||||
if (button.dataset.historyAction) { await handleHistoryAction(button); return; }
|
||||
@@ -1434,7 +1455,43 @@ $('#scheduleForm [name=preset]').addEventListener('change', updateSchedulePreset
|
||||
|
||||
$('#testNotifications')?.addEventListener('click', async () => { const f=$('#settingsForm'); const saved=app.settings?.notifications||{}; const body={enabled:true,mode:f.notifications_mode.value,provider:f.notifications_provider.value,pushover_app_token:f.pushover_app_token.value.trim(),pushover_user_key:f.pushover_user_key.value.trim(),slack_webhook_url:f.slack_webhook_url.value.trim(),discord_webhook_url:f.discord_webhook_url.value.trim(),cooldown_seconds:Number(f.notification_cooldown_seconds.value||300),communication_failure_threshold:Number(f.notification_failure_threshold.value||3),target_timeout_minutes:Number(f.notification_target_timeout.value||60)}; try{await api('/api/integrations/notifications/test',{method:'POST',body});toast('Test notification sent');}catch(e){toast(e.message,true);} });
|
||||
|
||||
$('#copyZoneSettings')?.addEventListener('click',()=>{ const source=app.zones.find(z=>z.id===$('#copyZoneSource')?.value); if(!source)return; const f=$('#zoneForm'); ['setpoint','cool_comfort_setpoint','cool_sleep_setpoint','cool_away_setpoint','heat_comfort_setpoint','heat_sleep_setpoint','heat_away_setpoint','hysteresis','min_on_seconds','min_off_seconds','min_adjust_seconds','standby_offset_c','external_sensor_weight_percent','max_sensor_difference'].forEach(name=>{ if(!f[name])return; const value=name==='external_sensor_weight_percent'?(source.external_sensor_weight*100):source[name]; if(value!==undefined&&value!==null)f[name].value=String(value); }); f.smart_fan.checked=source.smart_fan!==false; if(f.mode_policy) f.mode_policy.value=source.inherit_house_mode===false?(source.mode||'cool'):'house'; toast('Thermostat settings copied'); });
|
||||
$('#copyZoneSettings')?.addEventListener('click',()=>{
|
||||
const f=$('#zoneForm');
|
||||
const source=app.zones.find(zone=>zone.id===$('#copyZoneSource')?.value);
|
||||
if(!source)return;
|
||||
const targetId=f.dataset.editingZoneId || '';
|
||||
if(targetId && source.id===targetId){ toast(tr('zones.copyDifferent'),true); return; }
|
||||
|
||||
// Identity and sensor assignment belong to the destination profile and must never
|
||||
// be changed by copying thermostat tuning from another profile.
|
||||
const protectedValues={
|
||||
id:f.elements.id.value,
|
||||
name:f.elements.name.value,
|
||||
device_id:f.elements.device_id.value,
|
||||
sensor_source:f.elements.sensor_source.value,
|
||||
ha_entity_id:f.elements.ha_entity_id.value,
|
||||
enabled:f.elements.enabled.checked,
|
||||
};
|
||||
const copyFields=['setpoint','cool_comfort_setpoint','cool_sleep_setpoint','cool_away_setpoint','heat_comfort_setpoint','heat_sleep_setpoint','heat_away_setpoint','hysteresis','min_on_seconds','min_off_seconds','min_adjust_seconds','standby_offset_c','external_sensor_weight_percent','max_sensor_difference'];
|
||||
copyFields.forEach(name=>{
|
||||
const input=f.elements[name];
|
||||
if(!input)return;
|
||||
const value=name==='external_sensor_weight_percent'?(source.external_sensor_weight*100):source[name];
|
||||
if(value!==undefined&&value!==null)input.value=String(value);
|
||||
});
|
||||
f.elements.smart_fan.checked=source.smart_fan!==false;
|
||||
if(f.elements.mode_policy) f.elements.mode_policy.value=source.inherit_house_mode===false?(source.mode||'cool'):'house';
|
||||
|
||||
f.elements.id.value=protectedValues.id;
|
||||
f.elements.name.value=protectedValues.name;
|
||||
f.elements.device_id.value=protectedValues.device_id;
|
||||
f.elements.sensor_source.value=protectedValues.sensor_source;
|
||||
f.elements.ha_entity_id.value=protectedValues.ha_entity_id;
|
||||
f.elements.enabled.checked=protectedValues.enabled;
|
||||
f.dataset.editingZoneId=targetId;
|
||||
updateZoneSensorFields();
|
||||
toast(tr('zones.copiedFrom',{name:source.name}));
|
||||
});
|
||||
|
||||
$('#applyAutomationPreset')?.addEventListener('click',()=>{ const f=$('#automationForm'), p=$('#automationPreset')?.value; if(!p)return; const first=app.devices[0]?.id||''; const presets={hot:{name:'High temperature cooling',trigger_kind:'temperature_above',threshold:'28',action_power:'true',action_mode:'cool',action_target_temperature:'23',cooldown_seconds:'900'},cold:{name:'Low temperature heating',trigger_kind:'temperature_below',threshold:'17',action_power:'true',action_mode:'heat',action_target_temperature:'21',cooldown_seconds:'900'},morning:{name:'Morning comfort',trigger_kind:'time',at_time:'07:00',action_power:'true',action_mode:'auto',action_target_temperature:'22',cooldown_seconds:'3600'},nightoff:{name:'Night power off',trigger_kind:'time',at_time:'23:30',action_power:'false',action_mode:'',action_target_temperature:'',cooldown_seconds:'3600'}}; const x=presets[p]; Object.entries(x).forEach(([k,v])=>{if(f[k])f[k].value=v}); if(!f.trigger_device_id.value)f.trigger_device_id.value=first; if(!f.action_device_id.value)f.action_device_id.value=first; });
|
||||
|
||||
@@ -1482,7 +1539,7 @@ $('#deviceForm').addEventListener('submit', async event => {
|
||||
|
||||
$('#zoneForm').addEventListener('submit', async event => {
|
||||
event.preventDefault(); const form=event.currentTarget, raw=Object.fromEntries(new FormData(form));
|
||||
const id=raw.id; const body={
|
||||
const id=form.dataset.editingZoneId || raw.id; const body={
|
||||
name:raw.name,device_id:raw.device_id,enabled:form.enabled.checked,
|
||||
mode:raw.mode_policy==='house'?'cool':raw.mode_policy,inherit_house_mode:raw.mode_policy==='house',setpoint:parseDecimal(raw.setpoint),
|
||||
cool_comfort_setpoint:parseDecimal(raw.cool_comfort_setpoint),cool_sleep_setpoint:parseDecimal(raw.cool_sleep_setpoint),cool_away_setpoint:parseDecimal(raw.cool_away_setpoint),
|
||||
|
||||
+1
-1
@@ -613,7 +613,7 @@ html[data-theme='light'] .simulation-metrics > div, html[data-theme='light'] .si
|
||||
.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); }
|
||||
.device-capability-buttons button.active { border-color:var(--accent); color:var(--accent); }
|
||||
|
||||
/* v0.6.1: compact, centered unit-feature controls */
|
||||
/* v0.6.2: compact, centered unit-feature controls */
|
||||
.device-capability-panel { justify-items:center; text-align:center; padding:11px 0 3px; }
|
||||
.device-capability-panel > small { text-align:center; }
|
||||
.device-capability-buttons { justify-content:center; align-items:center; gap:6px; max-width:100%; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'gree-controller-v061';
|
||||
const CACHE = 'gree-controller-v062';
|
||||
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')];
|
||||
|
||||
Reference in New Issue
Block a user