feat(ops-ui): add column filters to operations tables across admin views
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-04-08 - 13.2.0 - feat(ops-ui)
|
||||||
|
add column filters to operations tables across admin views
|
||||||
|
|
||||||
|
- Enable table column filters for API tokens, certificates, network requests, top IPs, backends, network targets, remote ingress edges, security views, source profiles, target profiles, and VPN clients.
|
||||||
|
- Improves filtering and exploration of operational data throughout the admin interface without changing backend behavior.
|
||||||
|
|
||||||
## 2026-04-08 - 13.1.3 - fix(certificate-handler)
|
## 2026-04-08 - 13.1.3 - fix(certificate-handler)
|
||||||
preserve wildcard coverage during forced certificate renewals and propagate renewed certs to sibling domains
|
preserve wildcard coverage during forced certificate renewals and propagate renewed certs to sibling domains
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '13.1.3',
|
version: '13.2.0',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@serve.zone/dcrouter',
|
name: '@serve.zone/dcrouter',
|
||||||
version: '13.1.3',
|
version: '13.2.0',
|
||||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ export class OpsViewApiTokens extends DeesElement {
|
|||||||
.data=${apiTokens}
|
.data=${apiTokens}
|
||||||
.dataName=${'token'}
|
.dataName=${'token'}
|
||||||
.searchable=${true}
|
.searchable=${true}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(token: interfaces.data.IApiTokenInfo) => ({
|
.displayFunction=${(token: interfaces.data.IApiTokenInfo) => ({
|
||||||
name: token.name,
|
name: token.name,
|
||||||
scopes: this.renderScopePills(token.scopes),
|
scopes: this.renderScopePills(token.scopes),
|
||||||
|
|||||||
@@ -228,6 +228,7 @@ export class OpsViewCertificates extends DeesElement {
|
|||||||
return html`
|
return html`
|
||||||
<dees-table
|
<dees-table
|
||||||
.data=${this.certState.certificates}
|
.data=${this.certState.certificates}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(cert: interfaces.requests.ICertificateInfo) => ({
|
.displayFunction=${(cert: interfaces.requests.ICertificateInfo) => ({
|
||||||
Domain: cert.domain,
|
Domain: cert.domain,
|
||||||
Routes: this.renderRoutePills(cert.routeNames),
|
Routes: this.renderRoutePills(cert.routeNames),
|
||||||
|
|||||||
@@ -323,6 +323,7 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
<!-- Requests Table -->
|
<!-- Requests Table -->
|
||||||
<dees-table
|
<dees-table
|
||||||
.data=${this.networkRequests}
|
.data=${this.networkRequests}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(req: INetworkRequest) => ({
|
.displayFunction=${(req: INetworkRequest) => ({
|
||||||
Time: new Date(req.timestamp).toLocaleTimeString(),
|
Time: new Date(req.timestamp).toLocaleTimeString(),
|
||||||
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
||||||
@@ -603,6 +604,7 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
return html`
|
return html`
|
||||||
<dees-table
|
<dees-table
|
||||||
.data=${this.networkState.topIPs}
|
.data=${this.networkState.topIPs}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(ipData: { ip: string; count: number }) => {
|
.displayFunction=${(ipData: { ip: string; count: number }) => {
|
||||||
const bw = bandwidthByIP.get(ipData.ip);
|
const bw = bandwidthByIP.get(ipData.ip);
|
||||||
return {
|
return {
|
||||||
@@ -630,6 +632,7 @@ export class OpsViewNetwork extends DeesElement {
|
|||||||
return html`
|
return html`
|
||||||
<dees-table
|
<dees-table
|
||||||
.data=${backends}
|
.data=${backends}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(item: interfaces.data.IBackendInfo) => {
|
.displayFunction=${(item: interfaces.data.IBackendInfo) => {
|
||||||
const totalErrors = item.connectErrors + item.handshakeErrors + item.requestErrors;
|
const totalErrors = item.connectErrors + item.handshakeErrors + item.requestErrors;
|
||||||
const protocolClass = item.protocol.toLowerCase().replace(/[^a-z0-9]/g, '');
|
const protocolClass = item.protocol.toLowerCase().replace(/[^a-z0-9]/g, '');
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export class OpsViewNetworkTargets extends DeesElement {
|
|||||||
.heading1=${'Network Targets'}
|
.heading1=${'Network Targets'}
|
||||||
.heading2=${'Reusable host:port destinations for routes'}
|
.heading2=${'Reusable host:port destinations for routes'}
|
||||||
.data=${targets}
|
.data=${targets}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(target: interfaces.data.INetworkTarget) => ({
|
.displayFunction=${(target: interfaces.data.INetworkTarget) => ({
|
||||||
Name: target.name,
|
Name: target.name,
|
||||||
Host: Array.isArray(target.host) ? target.host.join(', ') : target.host,
|
Host: Array.isArray(target.host) ? target.host.join(', ') : target.host,
|
||||||
|
|||||||
@@ -220,6 +220,7 @@ export class OpsViewRemoteIngress extends DeesElement {
|
|||||||
.heading1=${'Edge Nodes'}
|
.heading1=${'Edge Nodes'}
|
||||||
.heading2=${'Manage remote ingress edge registrations'}
|
.heading2=${'Manage remote ingress edge registrations'}
|
||||||
.data=${this.riState.edges}
|
.data=${this.riState.edges}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(edge: interfaces.data.IRemoteIngress) => ({
|
.displayFunction=${(edge: interfaces.data.IRemoteIngress) => ({
|
||||||
name: edge.name,
|
name: edge.name,
|
||||||
status: this.getEdgeStatusHtml(edge),
|
status: this.getEdgeStatusHtml(edge),
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
.heading1=${'Security Events'}
|
.heading1=${'Security Events'}
|
||||||
.heading2=${'Last 24 hours'}
|
.heading2=${'Last 24 hours'}
|
||||||
.data=${this.getSecurityEvents(metrics)}
|
.data=${this.getSecurityEvents(metrics)}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(item) => ({
|
.displayFunction=${(item) => ({
|
||||||
'Time': new Date(item.timestamp).toLocaleTimeString(),
|
'Time': new Date(item.timestamp).toLocaleTimeString(),
|
||||||
'Event': item.event,
|
'Event': item.event,
|
||||||
@@ -241,6 +242,7 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
.heading1=${'Blocked IP Addresses'}
|
.heading1=${'Blocked IP Addresses'}
|
||||||
.heading2=${'IPs blocked due to suspicious activity'}
|
.heading2=${'IPs blocked due to suspicious activity'}
|
||||||
.data=${blockedIPs.map((ip) => ({ ip }))}
|
.data=${blockedIPs.map((ip) => ({ ip }))}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(item) => ({
|
.displayFunction=${(item) => ({
|
||||||
'IP Address': item.ip,
|
'IP Address': item.ip,
|
||||||
'Reason': 'Suspicious activity',
|
'Reason': 'Suspicious activity',
|
||||||
@@ -314,6 +316,7 @@ export class OpsViewSecurity extends DeesElement {
|
|||||||
.heading1=${'Login History'}
|
.heading1=${'Login History'}
|
||||||
.heading2=${'Recent authentication attempts'}
|
.heading2=${'Recent authentication attempts'}
|
||||||
.data=${loginHistory}
|
.data=${loginHistory}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(item) => ({
|
.displayFunction=${(item) => ({
|
||||||
'Time': new Date(item.timestamp).toLocaleString(),
|
'Time': new Date(item.timestamp).toLocaleString(),
|
||||||
'Username': item.username,
|
'Username': item.username,
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export class OpsViewSourceProfiles extends DeesElement {
|
|||||||
.heading1=${'Source Profiles'}
|
.heading1=${'Source Profiles'}
|
||||||
.heading2=${'Reusable source configurations for routes'}
|
.heading2=${'Reusable source configurations for routes'}
|
||||||
.data=${profiles}
|
.data=${profiles}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(profile: interfaces.data.ISourceProfile) => ({
|
.displayFunction=${(profile: interfaces.data.ISourceProfile) => ({
|
||||||
Name: profile.name,
|
Name: profile.name,
|
||||||
Description: profile.description || '-',
|
Description: profile.description || '-',
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export class OpsViewTargetProfiles extends DeesElement {
|
|||||||
.heading1=${'Target Profiles'}
|
.heading1=${'Target Profiles'}
|
||||||
.heading2=${'Define what resources VPN clients can access'}
|
.heading2=${'Define what resources VPN clients can access'}
|
||||||
.data=${profiles}
|
.data=${profiles}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(profile: interfaces.data.ITargetProfile) => ({
|
.displayFunction=${(profile: interfaces.data.ITargetProfile) => ({
|
||||||
Name: profile.name,
|
Name: profile.name,
|
||||||
Description: profile.description || '-',
|
Description: profile.description || '-',
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ export class OpsViewVpn extends DeesElement {
|
|||||||
.heading1=${'VPN Clients'}
|
.heading1=${'VPN Clients'}
|
||||||
.heading2=${'Manage WireGuard and SmartVPN client registrations'}
|
.heading2=${'Manage WireGuard and SmartVPN client registrations'}
|
||||||
.data=${clients}
|
.data=${clients}
|
||||||
|
.showColumnFilters=${true}
|
||||||
.displayFunction=${(client: interfaces.data.IVpnClient) => {
|
.displayFunction=${(client: interfaces.data.IVpnClient) => {
|
||||||
const conn = this.getConnectedInfo(client);
|
const conn = this.getConnectedInfo(client);
|
||||||
let statusHtml;
|
let statusHtml;
|
||||||
|
|||||||
Reference in New Issue
Block a user