Development
This commit is contained in:
parent
e2d33e04d5
commit
7825b9cd1a
2 changed files with 59 additions and 21 deletions
|
|
@ -1128,15 +1128,17 @@ def _render_field(item, tokens):
|
|||
if input_type == 'number':
|
||||
min_attr = f' min="{item["min"]}"' if 'min' in item else ''
|
||||
max_attr = f' max="{item["max"]}"' if 'max' in item else ''
|
||||
dyn_hint_html = '<p class="form-hint field-dyn-hint" style="display:none"></p>'
|
||||
inp = (f'<input type="number" name="{name}" value="{e(value)}"{min_attr}{max_attr}'
|
||||
f' class="form-input{extra_cls}"{readonly}/>')
|
||||
f' class="form-input{extra_cls}"{readonly}'
|
||||
f' data-validate="positive_int" />')
|
||||
if item.get('layout') == 'inline':
|
||||
return (f'<div class="form-group" style="display:flex;align-items:center;gap:0.75em">'
|
||||
f'<label class="form-label" style="margin:0;white-space:nowrap">{label}</label>'
|
||||
f'<div style="width:6rem">{inp}</div>'
|
||||
f'<div style="width:6rem">{inp}{dyn_hint_html}</div>'
|
||||
f'{hint_html}</div>')
|
||||
return (f'<div class="form-group"><label class="form-label">{label}</label>'
|
||||
f'{inp}{hint_html}</div>')
|
||||
f'{inp}{dyn_hint_html}{hint_html}</div>')
|
||||
|
||||
if input_type == 'textarea':
|
||||
rows = item.get('rows', 4)
|
||||
|
|
@ -1878,6 +1880,17 @@ function classifyTime24h(s) {
|
|||
return 'complete';
|
||||
}
|
||||
|
||||
function classifyPositiveInt(s, el) {
|
||||
if (el && el.validity && el.validity.badInput) return 'invalid_char';
|
||||
if (!s && s !== '0') return 'empty';
|
||||
if (/[^0-9]/.test(s)) return 'invalid_char';
|
||||
var n = parseInt(s, 10);
|
||||
var min = (el && el.min !== '') ? parseInt(el.min, 10) : 0;
|
||||
var max = (el && el.max !== '') ? parseInt(el.max, 10) : null;
|
||||
if (n < min || (max !== null && n > max)) return 'out_of_range';
|
||||
return 'complete';
|
||||
}
|
||||
|
||||
function classifySubnet(s) {
|
||||
if (!s) return 'empty';
|
||||
if (/[^0-9.]/.test(s)) return 'invalid_char';
|
||||
|
|
@ -2078,8 +2091,10 @@ document.addEventListener('click', function(e) {
|
|||
|
||||
if (inputType === 'checkbox') {
|
||||
var checked = (val === true || val === 'true' || val === 1 || val === '1');
|
||||
td.innerHTML = '<input type="checkbox" name="' + field + '"' +
|
||||
(checked ? ' checked' : '') + ' class="inline-edit-checkbox"/>';
|
||||
var cbLabel = fDef.checkbox_label ? ' <span class="form-checkbox-label">' + esc(fDef.checkbox_label) + '</span>' : '';
|
||||
td.innerHTML = '<label class="inline-edit-checkbox-wrap">' +
|
||||
'<input type="checkbox" name="' + field + '"' +
|
||||
(checked ? ' checked' : '') + ' class="inline-edit-checkbox"/>' + cbLabel + '</label>';
|
||||
} else if (inputType === 'checkbox_multi') {
|
||||
var opts = fDef.options || [];
|
||||
var checked = [];
|
||||
|
|
@ -2106,7 +2121,9 @@ document.addEventListener('click', function(e) {
|
|||
var minAttr = fDef.min !== undefined ? ' min="' + esc(String(fDef.min)) + '"' : '';
|
||||
var maxAttr = fDef.max !== undefined ? ' max="' + esc(String(fDef.max)) + '"' : '';
|
||||
td.innerHTML = '<input type="number" name="' + field + '" value="' + esc(String(val)) +
|
||||
'"' + minAttr + maxAttr + ' class="form-input inline-edit-input"/>';
|
||||
'"' + minAttr + maxAttr + ' class="form-input inline-edit-input" data-validate="positive_int"/>' +
|
||||
'<p class="form-hint field-dyn-hint" style="display:none"></p>';
|
||||
if (typeof validateEl === 'function') validateEl(td.querySelector('input'));
|
||||
} else if (inputType === 'textarea') {
|
||||
var textVal;
|
||||
try { var arr = JSON.parse(val); textVal = Array.isArray(arr) ? arr.join('\n') : String(val||''); }
|
||||
|
|
@ -2254,21 +2271,30 @@ var validateEl;
|
|||
invalid_struct: 'Invalid domain format' },
|
||||
networkname: { invalid_char: 'Letters, digits, hyphens and underscores only',
|
||||
invalid_struct: 'No leading, trailing or consecutive special characters' },
|
||||
time_24h: { invalid_char: 'Digits and colon only', invalid_struct: 'Must be HH:MM in 24-hour format (e.g. 02:30)' }
|
||||
time_24h: { invalid_char: 'Digits and colon only', invalid_struct: 'Must be HH:MM in 24-hour format (e.g. 02:30)' },
|
||||
positive_int: { invalid_char: 'Digits only',
|
||||
out_of_range: function(el) {
|
||||
var mn = (el && el.min !== '') ? el.min : null;
|
||||
var mx = (el && el.max !== '') ? el.max : null;
|
||||
if (mn !== null && mx !== null) return 'Must be between ' + mn + ' and ' + mx;
|
||||
if (mn !== null) return 'Must be ≥ ' + mn;
|
||||
if (mx !== null) return 'Must be ≤ ' + mx;
|
||||
return 'Out of range';
|
||||
}}
|
||||
};
|
||||
var _classifiers = { ip: classifyIp, ipv4: classifyIpv4, ipv6: classifyIpv6, mac: classifyMac,
|
||||
subnet: classifySubnet, url: classifyUrl,
|
||||
port: classifyPort, ipv4cidr: classifyIpv4Cidr,
|
||||
endpoint: classifyEndpoint,
|
||||
dashname: classifyDashname, domainname: classifyDomainname, networkname: classifyNetworkname,
|
||||
time_24h: classifyTime24h };
|
||||
time_24h: classifyTime24h, positive_int: classifyPositiveInt };
|
||||
|
||||
validateEl = function(el) {
|
||||
var list = el.closest('.editable-list[data-validate]');
|
||||
var vtype = el.dataset.validate || (list ? list.dataset.validate : '');
|
||||
var classify = _classifiers[vtype];
|
||||
if (!classify) return;
|
||||
var cls = classify(el.value);
|
||||
var cls = classify(el.value, el);
|
||||
if (list) {
|
||||
el.classList.remove('field-invalid', 'field-warning');
|
||||
if (cls === 'incomplete') el.classList.add('field-warning');
|
||||
|
|
@ -2280,7 +2306,8 @@ var validateEl;
|
|||
} else if (cls === 'incomplete') {
|
||||
setFieldHint(el, el._postValidate ? el._postValidate(cls) : '', 'warning');
|
||||
} else {
|
||||
setFieldHint(el, msgs[cls] || 'Invalid', 'error');
|
||||
var msgVal = msgs[cls];
|
||||
setFieldHint(el, typeof msgVal === 'function' ? msgVal(el) : (msgVal || 'Invalid'), 'error');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -974,7 +974,8 @@
|
|||
},
|
||||
{
|
||||
"col": "enabled",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -1100,7 +1101,8 @@
|
|||
},
|
||||
{
|
||||
"col": "enabled",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -1519,15 +1521,18 @@
|
|||
},
|
||||
{
|
||||
"col": "radius_default",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
},
|
||||
{
|
||||
"col": "mdns_reflection",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
},
|
||||
{
|
||||
"col": "dnsmasq_log_queries",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Record"
|
||||
},
|
||||
{
|
||||
"col": "use_blocklists",
|
||||
|
|
@ -1754,7 +1759,8 @@
|
|||
},
|
||||
{
|
||||
"col": "enabled",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -1920,7 +1926,8 @@
|
|||
},
|
||||
{
|
||||
"col": "enabled",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -2128,11 +2135,13 @@
|
|||
},
|
||||
{
|
||||
"col": "radius_client",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
},
|
||||
{
|
||||
"col": "enabled",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -2326,11 +2335,13 @@
|
|||
},
|
||||
{
|
||||
"col": "split_tunnel",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
},
|
||||
{
|
||||
"col": "enabled",
|
||||
"input_type": "checkbox"
|
||||
"input_type": "checkbox",
|
||||
"checkbox_label": "Enabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue