|
@@ -880,6 +880,10 @@ function renderRolesTable() {
|
|
|
}
|
|
}
|
|
|
empty?.classList.add('hidden');
|
|
empty?.classList.add('hidden');
|
|
|
|
|
|
|
|
|
|
+ const sig = roles.map(r => `${r.id}:${r.name}:${r.color}:${r.description}:${(r.interfaces||[]).join(',')}`).join(';');
|
|
|
|
|
+ if (tbody.dataset.sig === sig) return;
|
|
|
|
|
+ tbody.dataset.sig = sig;
|
|
|
|
|
+
|
|
|
tbody.innerHTML = roles.map(r => {
|
|
tbody.innerHTML = roles.map(r => {
|
|
|
const colorKey = (r.color || 'blue').toLowerCase();
|
|
const colorKey = (r.color || 'blue').toLowerCase();
|
|
|
const theme = ROLE_COLORS[colorKey] || ROLE_COLORS.blue;
|
|
const theme = ROLE_COLORS[colorKey] || ROLE_COLORS.blue;
|
|
@@ -1037,13 +1041,19 @@ function populateRoleSelects(selectedRole = '') {
|
|
|
|
|
|
|
|
if (ifaceSelect) {
|
|
if (ifaceSelect) {
|
|
|
const currentVal = selectedRole || ifaceSelect.value || 'LAN';
|
|
const currentVal = selectedRole || ifaceSelect.value || 'LAN';
|
|
|
- ifaceSelect.innerHTML = optionsHtml;
|
|
|
|
|
|
|
+ if (ifaceSelect.dataset.optionsSig !== optionsHtml) {
|
|
|
|
|
+ ifaceSelect.innerHTML = optionsHtml;
|
|
|
|
|
+ ifaceSelect.dataset.optionsSig = optionsHtml;
|
|
|
|
|
+ }
|
|
|
if (currentVal) ifaceSelect.value = currentVal;
|
|
if (currentVal) ifaceSelect.value = currentVal;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (vlanSelect) {
|
|
if (vlanSelect) {
|
|
|
- const currentVal = vlanSelect.value || 'LAN';
|
|
|
|
|
- vlanSelect.innerHTML = optionsHtml;
|
|
|
|
|
|
|
+ const currentVal = selectedRole || vlanSelect.value || 'LAN';
|
|
|
|
|
+ if (vlanSelect.dataset.optionsSig !== optionsHtml) {
|
|
|
|
|
+ vlanSelect.innerHTML = optionsHtml;
|
|
|
|
|
+ vlanSelect.dataset.optionsSig = optionsHtml;
|
|
|
|
|
+ }
|
|
|
if (currentVal) vlanSelect.value = currentVal;
|
|
if (currentVal) vlanSelect.value = currentVal;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1101,7 +1111,7 @@ function renderInterfacesList() {
|
|
|
|
|
|
|
|
const sig = `${state.ifaceFilter}|${query}|` + filteredParents.map(p => {
|
|
const sig = `${state.ifaceFilter}|${query}|` + filteredParents.map(p => {
|
|
|
const cVlans = allVlans.filter(v => v.parent_name === p.name || v.name.startsWith(p.name + '.'));
|
|
const cVlans = allVlans.filter(v => v.parent_name === p.name || v.name.startsWith(p.name + '.'));
|
|
|
- return `${p.name}:${p.state}:${(p.ipv4||[]).join(',')}:${p.mtu}:${cVlans.length}:${state.expandedParents.has(p.name)}`;
|
|
|
|
|
|
|
+ return `${p.name}:${p.state}:${p.role||'LAN'}:${(p.ipv4||[]).join(',')}:${p.mtu}:${cVlans.length}:${state.expandedParents.has(p.name)}`;
|
|
|
}).join(';');
|
|
}).join(';');
|
|
|
|
|
|
|
|
if (tbody.dataset.sig === sig) {
|
|
if (tbody.dataset.sig === sig) {
|