feat (ui): netwerk map functionaliteit verder uitgebreid en polish
This commit is contained in:
@@ -48,6 +48,7 @@
|
||||
connectedOnly: false,
|
||||
hideDefaults: true,
|
||||
sharedOnly: false,
|
||||
showModes: true,
|
||||
sort: 'name_asc',
|
||||
},
|
||||
};
|
||||
@@ -126,6 +127,18 @@
|
||||
return { totalNetworks, usedNetworks, unusedNetworks, connectedContainers, sharedNetns };
|
||||
}
|
||||
|
||||
function buildMapStatus(label, nodesCount, linksCount) {
|
||||
const f = state.filters || {};
|
||||
const flags = [];
|
||||
if (f.connectedOnly) flags.push('connected');
|
||||
if (f.hideDefaults) flags.push('hide-defaults');
|
||||
if (f.sharedOnly) flags.push('shared');
|
||||
if (f.showModes === false) flags.push('modes-off');
|
||||
|
||||
const flagTxt = flags.length ? ` | ${flags.join(', ')}` : '';
|
||||
return `${label} | ${nodesCount} nodes, ${linksCount} links${flagTxt}`;
|
||||
}
|
||||
|
||||
function renderNetworksSummary() {
|
||||
const host = document.getElementById('networksSummary');
|
||||
if (!host) return;
|
||||
@@ -345,6 +358,7 @@
|
||||
const connectedOnly = !!state.filters.connectedOnly;
|
||||
const hideDefaults = !!state.filters.hideDefaults;
|
||||
const sharedOnly = !!state.filters.sharedOnly;
|
||||
const showModes = state.filters.showModes !== false;
|
||||
|
||||
const byMeta = state.usage?.byContainerMeta || {};
|
||||
|
||||
@@ -353,6 +367,9 @@
|
||||
if (hideDefaults) {
|
||||
out = out.filter(n => !isDefaultNetworkName(n.name));
|
||||
}
|
||||
if (!showModes) {
|
||||
out = out.filter(n => String(n.meta?.driver || '') !== 'mode');
|
||||
}
|
||||
|
||||
if (connectedOnly) {
|
||||
out = out.filter(n => n.containerCount > 0);
|
||||
@@ -696,8 +713,8 @@
|
||||
|
||||
// simulation
|
||||
const sim = d3.forceSimulation(model.nodes)
|
||||
.force('link', d3.forceLink(model.links).id(d => d.id).distance(45))
|
||||
.force('charge', d3.forceManyBody().strength(-40))
|
||||
.force('link', d3.forceLink(model.links).id(d => d.id).distance(80))
|
||||
.force('charge', d3.forceManyBody().strength(-30))
|
||||
.force('center', d3.forceCenter(w / 2, h / 2).strength(0.15))
|
||||
.force('collide', d3.forceCollide().radius(d => d.type === 'network' ? 18 : 16))
|
||||
.on('tick', () => {
|
||||
@@ -731,7 +748,7 @@
|
||||
showDetailPanel(networkName);
|
||||
|
||||
const s = document.getElementById('networksMapStatus');
|
||||
if (s) s.textContent = `Detail: ${networkName}`;
|
||||
if (s) s.textContent = buildMapStatus(`Detail: ${networkName}`, model.nodes.length, model.links.length);
|
||||
}
|
||||
|
||||
function showDetailPanel(networkName) {
|
||||
@@ -792,7 +809,7 @@
|
||||
hideDetailPanel();
|
||||
|
||||
const s = document.getElementById('networksMapStatus');
|
||||
if (s) s.textContent = `Kaart: ${model.meta.nodes} nodes, ${model.meta.links} links`;
|
||||
if (s) s.textContent = buildMapStatus('Global', model.nodes.length, model.links.length);
|
||||
}
|
||||
|
||||
function renderNetworks() {
|
||||
@@ -927,6 +944,10 @@
|
||||
resetBtn.dataset.bound = '1';
|
||||
resetBtn.addEventListener('click', () => {
|
||||
if (!graphCtx) return;
|
||||
|
||||
// wis highlight/dim
|
||||
graphCtx.g.selectAll('.graphNode').classed('graphDim', false);
|
||||
graphCtx.g.selectAll('.graphLink').classed('graphDim', false).classed('graphActive', false);
|
||||
|
||||
// reset zoom
|
||||
graphCtx.svg
|
||||
@@ -990,7 +1011,13 @@
|
||||
});
|
||||
|
||||
const s = document.getElementById('networksMapStatus');
|
||||
if (s) s.textContent = `Container: ${id.slice(0, 12)}…`;
|
||||
if (s) {
|
||||
const label = (state.mapMode === 'detail' && state.selectedNetwork)
|
||||
? `Detail: ${state.selectedNetwork}`
|
||||
: 'Global';
|
||||
|
||||
s.textContent = buildMapStatus(label, graphCtx.model.nodes.length, graphCtx.model.links.length) + ` | container: ${id.slice(0, 12)}…`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -999,13 +1026,24 @@
|
||||
const fHideDefaults = document.getElementById('networksFilterHideDefaults');
|
||||
const fShared = document.getElementById('networksFilterShared');
|
||||
const sort = document.getElementById('networksSort');
|
||||
const mapShowModes = document.getElementById('networksMapShowModes');
|
||||
const mapConnectedOnly = document.getElementById('networksMapConnectedOnly');
|
||||
|
||||
function rerender() {
|
||||
renderNetworks();
|
||||
|
||||
if (state.view === 'map') {
|
||||
|
||||
// als we in detail zitten → detail opnieuw renderen
|
||||
if (state.mapMode === 'detail' && state.selectedNetwork) {
|
||||
openNetworkDetail(state.selectedNetwork);
|
||||
return;
|
||||
}
|
||||
|
||||
// anders global map
|
||||
const model = buildGlobalGraphModel();
|
||||
const s = document.getElementById('networksMapStatus');
|
||||
if (s) s.textContent = `Kaart: ${model.meta.nodes} nodes, ${model.meta.links} links`;
|
||||
if (s) s.textContent = buildMapStatus('Global', model.nodes.length, model.links.length);
|
||||
renderGraph(model);
|
||||
}
|
||||
}
|
||||
@@ -1051,8 +1089,36 @@
|
||||
});
|
||||
}
|
||||
|
||||
if (mapConnectedOnly && !mapConnectedOnly.dataset.bound) {
|
||||
mapConnectedOnly.dataset.bound = '1';
|
||||
mapConnectedOnly.checked = !!state.filters.connectedOnly;
|
||||
|
||||
mapConnectedOnly.addEventListener('change', () => {
|
||||
state.filters.connectedOnly = !!mapConnectedOnly.checked;
|
||||
|
||||
// sync ook de tabel checkbox (zodat alles hetzelfde blijft)
|
||||
const tableChk = document.getElementById('networksFilterConnected');
|
||||
if (tableChk) tableChk.checked = !!state.filters.connectedOnly;
|
||||
|
||||
rerender();
|
||||
});
|
||||
}
|
||||
|
||||
if (mapShowModes && !mapShowModes.dataset.bound) {
|
||||
mapShowModes.dataset.bound = '1';
|
||||
mapShowModes.checked = state.filters.showModes !== false;
|
||||
mapShowModes.addEventListener('change', () => {
|
||||
state.filters.showModes = !!mapShowModes.checked;
|
||||
rerender();
|
||||
});
|
||||
}
|
||||
|
||||
renderNetworksSummary();
|
||||
setNetworksView(state.view);
|
||||
// sync kaart-checkbox bij init
|
||||
if (mapConnectedOnly) {
|
||||
mapConnectedOnly.checked = !!state.filters.connectedOnly;
|
||||
}
|
||||
}
|
||||
|
||||
// Expose minimal API
|
||||
@@ -1066,7 +1132,7 @@
|
||||
console.table(model.nodes.slice(0, 12));
|
||||
console.table(model.links.slice(0, 12));
|
||||
return model;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Bind when script loads (DOM is already mostly there because script is at end of body)
|
||||
|
||||
Reference in New Issue
Block a user