fix(network-ui): enable flashing table updates for network activity, remote ingress, and VPN views
This commit is contained in:
@@ -1,5 +1,12 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-04-08 - 13.9.1 - fix(network-ui)
|
||||
enable flashing table updates for network activity, remote ingress, and VPN views
|
||||
|
||||
- adds stable row keys to dees-table instances so existing rows can be diffed correctly
|
||||
- enables flash highlighting for changed rows and cells across network activity, top IPs, backends, remote ingress edges, and VPN clients
|
||||
- updates network activity request data on every refresh so live metrics like duration and byte counts visibly refresh
|
||||
|
||||
## 2026-04-08 - 13.9.0 - feat(dns)
|
||||
add built-in dcrouter DNS provider support and rename manual domains to dcrouter-hosted/local
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '13.9.0',
|
||||
version: '13.9.1',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '13.9.0',
|
||||
version: '13.9.1',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
@@ -323,6 +323,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
<!-- Requests Table -->
|
||||
<dees-table
|
||||
.data=${this.networkRequests}
|
||||
.rowKey=${'id'}
|
||||
.highlightUpdates=${'flash'}
|
||||
.displayFunction=${(req: INetworkRequest) => ({
|
||||
Time: new Date(req.timestamp).toLocaleTimeString(),
|
||||
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
||||
@@ -595,6 +597,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
return html`
|
||||
<dees-table
|
||||
.data=${this.networkState.topIPs}
|
||||
.rowKey=${'ip'}
|
||||
.highlightUpdates=${'flash'}
|
||||
.displayFunction=${(ipData: { ip: string; count: number }) => {
|
||||
const bw = bandwidthByIP.get(ipData.ip);
|
||||
return {
|
||||
@@ -624,6 +628,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
return html`
|
||||
<dees-table
|
||||
.data=${backends}
|
||||
.rowKey=${'backend'}
|
||||
.highlightUpdates=${'flash'}
|
||||
.displayFunction=${(item: interfaces.data.IBackendInfo) => {
|
||||
const totalErrors = item.connectErrors + item.handshakeErrors + item.requestErrors;
|
||||
const protocolClass = item.protocol.toLowerCase().replace(/[^a-z0-9]/g, '');
|
||||
@@ -724,37 +730,24 @@ export class OpsViewNetworkActivity extends DeesElement {
|
||||
this.requestsPerSecHistory.shift();
|
||||
}
|
||||
|
||||
// Only update if connections changed significantly
|
||||
const newConnectionCount = this.networkState.connections.length;
|
||||
const oldConnectionCount = this.networkRequests.length;
|
||||
|
||||
// Check if we need to update the network requests array
|
||||
const shouldUpdate = newConnectionCount !== oldConnectionCount ||
|
||||
newConnectionCount === 0 ||
|
||||
(newConnectionCount > 0 && this.networkRequests.length === 0);
|
||||
|
||||
if (shouldUpdate) {
|
||||
// Convert connection data to network requests format
|
||||
if (newConnectionCount > 0) {
|
||||
this.networkRequests = this.networkState.connections.map((conn, index) => ({
|
||||
id: conn.id,
|
||||
timestamp: conn.startTime,
|
||||
method: 'GET', // Default method for proxy connections
|
||||
url: '/',
|
||||
hostname: conn.remoteAddress,
|
||||
port: conn.protocol === 'https' ? 443 : 80,
|
||||
protocol: conn.protocol === 'https' || conn.protocol === 'http' ? conn.protocol : 'tcp',
|
||||
statusCode: conn.state === 'connected' ? 200 : undefined,
|
||||
duration: Date.now() - conn.startTime,
|
||||
bytesIn: conn.bytesReceived,
|
||||
bytesOut: conn.bytesSent,
|
||||
remoteIp: conn.remoteAddress,
|
||||
route: 'proxy',
|
||||
}));
|
||||
} else {
|
||||
this.networkRequests = [];
|
||||
}
|
||||
}
|
||||
// Reassign unconditionally so dees-table's flash diff can compare per-cell
|
||||
// values against the previous snapshot. Row identity is preserved via
|
||||
// rowKey='id', so DOM nodes are reused across ticks.
|
||||
this.networkRequests = this.networkState.connections.map((conn) => ({
|
||||
id: conn.id,
|
||||
timestamp: conn.startTime,
|
||||
method: 'GET', // Default method for proxy connections
|
||||
url: '/',
|
||||
hostname: conn.remoteAddress,
|
||||
port: conn.protocol === 'https' ? 443 : 80,
|
||||
protocol: conn.protocol === 'https' || conn.protocol === 'http' ? conn.protocol : 'tcp',
|
||||
statusCode: conn.state === 'connected' ? 200 : undefined,
|
||||
duration: Date.now() - conn.startTime,
|
||||
bytesIn: conn.bytesReceived,
|
||||
bytesOut: conn.bytesSent,
|
||||
remoteIp: conn.remoteAddress,
|
||||
route: 'proxy',
|
||||
}));
|
||||
|
||||
// Load server-side throughput history into chart (once)
|
||||
if (!this.historyLoaded && this.networkState.throughputHistory && this.networkState.throughputHistory.length > 0) {
|
||||
|
||||
@@ -220,6 +220,8 @@ export class OpsViewRemoteIngress extends DeesElement {
|
||||
.heading1=${'Edge Nodes'}
|
||||
.heading2=${'Manage remote ingress edge registrations'}
|
||||
.data=${this.riState.edges}
|
||||
.rowKey=${'id'}
|
||||
.highlightUpdates=${'flash'}
|
||||
.showColumnFilters=${true}
|
||||
.displayFunction=${(edge: interfaces.data.IRemoteIngress) => ({
|
||||
name: edge.name,
|
||||
|
||||
@@ -305,6 +305,8 @@ export class OpsViewVpn extends DeesElement {
|
||||
.heading1=${'VPN Clients'}
|
||||
.heading2=${'Manage WireGuard and SmartVPN client registrations'}
|
||||
.data=${clients}
|
||||
.rowKey=${'clientId'}
|
||||
.highlightUpdates=${'flash'}
|
||||
.showColumnFilters=${true}
|
||||
.displayFunction=${(client: interfaces.data.IVpnClient) => {
|
||||
const conn = this.getConnectedInfo(client);
|
||||
|
||||
Reference in New Issue
Block a user