feat(ops-view-routes): add priority support and list-based domain editing for routes

This commit is contained in:
2026-04-02 22:55:57 +00:00
parent 8f23600ec1
commit f62bc4a526
4 changed files with 27 additions and 15 deletions

View File

@@ -1,5 +1,11 @@
# Changelog # Changelog
## 2026-04-02 - 12.5.0 - feat(ops-view-routes)
add priority support and list-based domain editing for routes
- Adds a priority field to route create and edit forms so route matching order can be configured.
- Replaces comma-separated domain text input with a list-based domain editor and updates form handling to persist domains as arrays.
## 2026-04-02 - 12.4.0 - feat(routes) ## 2026-04-02 - 12.4.0 - feat(routes)
add route edit and delete actions to the ops routes view add route edit and delete actions to the ops routes view

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/dcrouter', name: '@serve.zone/dcrouter',
version: '12.4.0', version: '12.5.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.' description: 'A multifaceted routing service handling mail and SMS delivery functions.'
} }

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/dcrouter', name: '@serve.zone/dcrouter',
version: '12.4.0', version: '12.5.0',
description: 'A multifaceted routing service handling mail and SMS delivery functions.' description: 'A multifaceted routing service handling mail and SMS delivery functions.'
} }

View File

@@ -414,9 +414,9 @@ export class OpsViewRoutes extends DeesElement {
const currentPorts = Array.isArray(route.match.ports) const currentPorts = Array.isArray(route.match.ports)
? route.match.ports.map((p: any) => typeof p === 'number' ? String(p) : `${p.from}-${p.to}`).join(', ') ? route.match.ports.map((p: any) => typeof p === 'number' ? String(p) : `${p.from}-${p.to}`).join(', ')
: String(route.match.ports); : String(route.match.ports);
const currentDomains = route.match.domains const currentDomains: string[] = route.match.domains
? (Array.isArray(route.match.domains) ? route.match.domains.join(', ') : route.match.domains) ? (Array.isArray(route.match.domains) ? route.match.domains : [route.match.domains])
: ''; : [];
const firstTarget = route.action.targets?.[0]; const firstTarget = route.action.targets?.[0];
const currentTargetHost = firstTarget const currentTargetHost = firstTarget
? (Array.isArray(firstTarget.host) ? firstTarget.host[0] : firstTarget.host) ? (Array.isArray(firstTarget.host) ? firstTarget.host[0] : firstTarget.host)
@@ -429,7 +429,8 @@ export class OpsViewRoutes extends DeesElement {
<dees-form> <dees-form>
<dees-input-text .key=${'name'} .label=${'Route Name'} .value=${route.name || ''} .required=${true}></dees-input-text> <dees-input-text .key=${'name'} .label=${'Route Name'} .value=${route.name || ''} .required=${true}></dees-input-text>
<dees-input-text .key=${'ports'} .label=${'Ports (comma-separated)'} .value=${currentPorts} .required=${true}></dees-input-text> <dees-input-text .key=${'ports'} .label=${'Ports (comma-separated)'} .value=${currentPorts} .required=${true}></dees-input-text>
<dees-input-text .key=${'domains'} .label=${'Domains (comma-separated, optional)'} .value=${currentDomains}></dees-input-text> <dees-input-list .key=${'domains'} .label=${'Domains'} .placeholder=${'Add domain...'} .value=${currentDomains}></dees-input-list>
<dees-input-text .key=${'priority'} .label=${'Priority (higher = matched first)'} .value=${route.priority != null ? String(route.priority) : ''}></dees-input-text>
<dees-input-dropdown .key=${'securityProfileRef'} .label=${'Security Profile'} .options=${profileOptions} .selectedKey=${merged.metadata?.securityProfileRef || ''}></dees-input-dropdown> <dees-input-dropdown .key=${'securityProfileRef'} .label=${'Security Profile'} .options=${profileOptions} .selectedKey=${merged.metadata?.securityProfileRef || ''}></dees-input-dropdown>
<dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions} .selectedKey=${merged.metadata?.networkTargetRef || ''}></dees-input-dropdown> <dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions} .selectedKey=${merged.metadata?.networkTargetRef || ''}></dees-input-dropdown>
<dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${currentTargetHost}></dees-input-text> <dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${currentTargetHost}></dees-input-text>
@@ -452,15 +453,16 @@ export class OpsViewRoutes extends DeesElement {
if (!formData.name || !formData.ports) return; if (!formData.name || !formData.ports) return;
const ports = formData.ports.split(',').map((p: string) => parseInt(p.trim(), 10)).filter((p: number) => !isNaN(p)); const ports = formData.ports.split(',').map((p: string) => parseInt(p.trim(), 10)).filter((p: number) => !isNaN(p));
const domains = formData.domains const domains: string[] = Array.isArray(formData.domains)
? formData.domains.split(',').map((d: string) => d.trim()).filter(Boolean) ? formData.domains.filter(Boolean)
: undefined; : [];
const priority = formData.priority ? parseInt(formData.priority, 10) : undefined;
const updatedRoute: any = { const updatedRoute: any = {
name: formData.name, name: formData.name,
match: { match: {
ports, ports,
...(domains && domains.length > 0 ? { domains } : {}), ...(domains.length > 0 ? { domains } : {}),
}, },
action: { action: {
type: 'forward', type: 'forward',
@@ -471,6 +473,7 @@ export class OpsViewRoutes extends DeesElement {
}, },
], ],
}, },
...(priority != null && !isNaN(priority) ? { priority } : {}),
}; };
const metadata: any = {}; const metadata: any = {};
@@ -523,7 +526,8 @@ export class OpsViewRoutes extends DeesElement {
<dees-form> <dees-form>
<dees-input-text .key=${'name'} .label=${'Route Name'} .required=${true}></dees-input-text> <dees-input-text .key=${'name'} .label=${'Route Name'} .required=${true}></dees-input-text>
<dees-input-text .key=${'ports'} .label=${'Ports (comma-separated)'} .required=${true}></dees-input-text> <dees-input-text .key=${'ports'} .label=${'Ports (comma-separated)'} .required=${true}></dees-input-text>
<dees-input-text .key=${'domains'} .label=${'Domains (comma-separated, optional)'}></dees-input-text> <dees-input-list .key=${'domains'} .label=${'Domains'} .placeholder=${'Add domain...'}></dees-input-list>
<dees-input-text .key=${'priority'} .label=${'Priority (higher = matched first)'}></dees-input-text>
<dees-input-dropdown .key=${'securityProfileRef'} .label=${'Security Profile'} .options=${profileOptions} .selectedKey=${''}></dees-input-dropdown> <dees-input-dropdown .key=${'securityProfileRef'} .label=${'Security Profile'} .options=${profileOptions} .selectedKey=${''}></dees-input-dropdown>
<dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions} .selectedKey=${''}></dees-input-dropdown> <dees-input-dropdown .key=${'networkTargetRef'} .label=${'Network Target'} .options=${targetOptions} .selectedKey=${''}></dees-input-dropdown>
<dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${'localhost'}></dees-input-text> <dees-input-text .key=${'targetHost'} .label=${'Target Host (if no target selected)'} .value=${'localhost'}></dees-input-text>
@@ -546,15 +550,16 @@ export class OpsViewRoutes extends DeesElement {
if (!formData.name || !formData.ports) return; if (!formData.name || !formData.ports) return;
const ports = formData.ports.split(',').map((p: string) => parseInt(p.trim(), 10)).filter((p: number) => !isNaN(p)); const ports = formData.ports.split(',').map((p: string) => parseInt(p.trim(), 10)).filter((p: number) => !isNaN(p));
const domains = formData.domains const domains: string[] = Array.isArray(formData.domains)
? formData.domains.split(',').map((d: string) => d.trim()).filter(Boolean) ? formData.domains.filter(Boolean)
: undefined; : [];
const priority = formData.priority ? parseInt(formData.priority, 10) : undefined;
const route: any = { const route: any = {
name: formData.name, name: formData.name,
match: { match: {
ports, ports,
...(domains && domains.length > 0 ? { domains } : {}), ...(domains.length > 0 ? { domains } : {}),
}, },
action: { action: {
type: 'forward', type: 'forward',
@@ -565,6 +570,7 @@ export class OpsViewRoutes extends DeesElement {
}, },
], ],
}, },
...(priority != null && !isNaN(priority) ? { priority } : {}),
}; };
// Build metadata if profile/target selected // Build metadata if profile/target selected