v0.9.5
This commit is contained in:
+25
-25
@@ -75,7 +75,7 @@ function validationMessageFor(field) {
|
||||
if (field.validity?.valueMissing) return tr('validation.required');
|
||||
if (field.validity?.typeMismatch) return field.type === 'url' ? tr('validation.url') : tr('validation.invalid');
|
||||
if (field.validity?.rangeUnderflow || field.validity?.rangeOverflow) {
|
||||
return tr('validation.range', {min:field.min || '—', max:field.max || '—'});
|
||||
return tr('validation.range', { min: field.min || '—', max: field.max || '—' });
|
||||
}
|
||||
if (field.validity?.badInput || field.validity?.stepMismatch || field.validity?.patternMismatch) return tr('validation.invalid');
|
||||
return field.validity?.valid === false ? tr('validation.invalid') : '';
|
||||
@@ -95,7 +95,7 @@ function validateDecimalField(form, name, min, max) {
|
||||
if (!field || field.disabled) return true;
|
||||
const value = parseDecimal(field.value);
|
||||
if (!Number.isFinite(value) || value < min || value > max) {
|
||||
showFieldError(field, tr('validation.range', {min, max}));
|
||||
showFieldError(field, tr('validation.range', { min, max }));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -114,7 +114,7 @@ function validateForm(form) {
|
||||
if (form.id === 'homeAssistantForm') {
|
||||
const url = form.elements.ha_url;
|
||||
if (url?.value && !httpUrlValid(url.value)) { showFieldError(url, tr('validation.url')); valid = false; }
|
||||
['ha_entity_id','ha_outdoor_entity_id'].forEach(name => {
|
||||
['ha_entity_id', 'ha_outdoor_entity_id'].forEach(name => {
|
||||
const field = form.elements[name];
|
||||
if (field?.value && !entityIdValid(field.value)) { showFieldError(field, tr('validation.entityId')); valid = false; }
|
||||
});
|
||||
@@ -134,14 +134,14 @@ function validateForm(form) {
|
||||
valid = false;
|
||||
}
|
||||
const zoneDecimalFields = [
|
||||
['cool_comfort_setpoint',8,30],['cool_sleep_setpoint',8,30],['cool_away_setpoint',8,30],
|
||||
['heat_comfort_setpoint',8,30],['heat_sleep_setpoint',8,30],['heat_away_setpoint',8,30],
|
||||
['max_sensor_difference',0.1,20],['standby_offset_c',0.5,8],
|
||||
['cool_comfort_setpoint', 8, 30], ['cool_sleep_setpoint', 8, 30], ['cool_away_setpoint', 8, 30],
|
||||
['heat_comfort_setpoint', 8, 30], ['heat_sleep_setpoint', 8, 30], ['heat_away_setpoint', 8, 30],
|
||||
['max_sensor_difference', 0.1, 20], ['standby_offset_c', 0.5, 8],
|
||||
...(form.elements.separate_hysteresis?.checked
|
||||
? [['cool_hysteresis',0.1,5],['heat_hysteresis',0.1,5]]
|
||||
: [['hysteresis',0.1,5]])
|
||||
? [['cool_hysteresis', 0.1, 5], ['heat_hysteresis', 0.1, 5]]
|
||||
: [['hysteresis', 0.1, 5]])
|
||||
];
|
||||
zoneDecimalFields.forEach(([name,min,max]) => { if (!validateDecimalField(form,name,min,max)) valid = false; });
|
||||
zoneDecimalFields.forEach(([name, min, max]) => { if (!validateDecimalField(form, name, min, max)) valid = false; });
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
@@ -149,8 +149,8 @@ function validateForm(form) {
|
||||
const first = $('[aria-invalid="true"]', form);
|
||||
const pane = first?.closest?.('[data-settings-pane]');
|
||||
if (pane?.dataset.settingsPane) setSettingsTab(pane.dataset.settingsPane);
|
||||
first?.focus({preventScroll:true});
|
||||
first?.scrollIntoView({behavior:'smooth', block:'center'});
|
||||
first?.focus({ preventScroll: true });
|
||||
first?.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
@@ -160,12 +160,12 @@ function apiErrorField(form, message) {
|
||||
const candidates = [];
|
||||
if (text.includes('influx')) candidates.push('influx_url');
|
||||
if (text.includes('home assistant') || text.includes('ha ')) candidates.push('ha_url');
|
||||
if (text.includes('entity')) candidates.push('ha_entity_id','ha_outdoor_entity_id');
|
||||
if (text.includes('device')) candidates.push('device_id','action_device_id','trigger_device_id');
|
||||
if (text.includes('temperature') || text.includes('setpoint')) candidates.push('target_temperature','cool_comfort_setpoint','action_target_temperature');
|
||||
if (text.includes('name')) candidates.push('name','controller_id');
|
||||
if (text.includes('token')) candidates.push('ha_token','influx_token','pushover_app_token');
|
||||
if (text.includes('url')) candidates.push('ha_url','influx_url','slack_webhook_url','discord_webhook_url');
|
||||
if (text.includes('entity')) candidates.push('ha_entity_id', 'ha_outdoor_entity_id');
|
||||
if (text.includes('device')) candidates.push('device_id', 'action_device_id', 'trigger_device_id');
|
||||
if (text.includes('temperature') || text.includes('setpoint')) candidates.push('target_temperature', 'cool_comfort_setpoint', 'action_target_temperature');
|
||||
if (text.includes('name')) candidates.push('name', 'controller_id');
|
||||
if (text.includes('token')) candidates.push('ha_token', 'influx_token', 'pushover_app_token');
|
||||
if (text.includes('url')) candidates.push('ha_url', 'influx_url', 'slack_webhook_url', 'discord_webhook_url');
|
||||
return candidates.map(name => form?.elements?.[name]).find(Boolean) || null;
|
||||
}
|
||||
|
||||
@@ -178,8 +178,8 @@ function presentFormError(form, error) {
|
||||
if (field) {
|
||||
const pane = field.closest?.('[data-settings-pane]');
|
||||
if (pane?.dataset.settingsPane) setSettingsTab(pane.dataset.settingsPane);
|
||||
field.focus({preventScroll:true});
|
||||
field.scrollIntoView({behavior:'smooth', block:'center'});
|
||||
field.focus({ preventScroll: true });
|
||||
field.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||||
}
|
||||
toast(message, true);
|
||||
}
|
||||
@@ -207,18 +207,18 @@ function setFormBusy(form, busy, busyKey = 'actions.saving') {
|
||||
}
|
||||
}
|
||||
|
||||
async function runFormTask(form, task, {busyKey='actions.saving', validate=true}={}) {
|
||||
if (!form || form.dataset.submitting === 'true') return {ok:false, duplicate:true};
|
||||
if (validate && !validateForm(form)) return {ok:false, validation:true};
|
||||
async function runFormTask(form, task, { busyKey = 'actions.saving', validate = true } = {}) {
|
||||
if (!form || form.dataset.submitting === 'true') return { ok: false, duplicate: true };
|
||||
if (validate && !validateForm(form)) return { ok: false, validation: true };
|
||||
clearFormErrors(form);
|
||||
setFormBusy(form, true, busyKey);
|
||||
try {
|
||||
const value = await task();
|
||||
markFormClean(form);
|
||||
return {ok:true, value};
|
||||
return { ok: true, value };
|
||||
} catch (error) {
|
||||
presentFormError(form, error);
|
||||
return {ok:false, error};
|
||||
return { ok: false, error };
|
||||
} finally {
|
||||
setFormBusy(form, false);
|
||||
}
|
||||
@@ -229,7 +229,7 @@ function restoreTrackedForm(form) {
|
||||
if (form.id === 'settingsForm') renderSettings();
|
||||
else if (form.id === 'nightModeForm') renderNightSettings();
|
||||
else if (form.id === 'homeAssistantForm') {
|
||||
app.sensorAliases = {...(app.settings?.home_assistant?.sensor_aliases || {})};
|
||||
app.sensorAliases = { ...(app.settings?.home_assistant?.sensor_aliases || {}) };
|
||||
renderHomeAssistantSettings();
|
||||
} else markFormClean(form);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user