fix(ops-ui): improve operations table actions and modal form handling for profiles and network targets
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-04-02 - 12.2.6 - fix(ops-ui)
|
||||
improve operations table actions and modal form handling for profiles and network targets
|
||||
|
||||
- adds section headings for the Security Profiles and Network Targets views
|
||||
- updates edit and delete actions to support in-row table actions in addition to context menus
|
||||
- makes create and edit dialogs query forms safely from modal content and adds early returns when forms are unavailable
|
||||
- enables the database configuration in the development watch server
|
||||
|
||||
## 2026-04-02 - 12.2.5 - fix(dcrouter)
|
||||
sync allowed tunnel edges when merged routes change
|
||||
|
||||
|
||||
@@ -49,8 +49,7 @@ const devRouter = new DcRouter({
|
||||
{ clientId: 'admin-desktop', serverDefinedClientTags: ['admin'], description: 'Admin workstation' },
|
||||
],
|
||||
},
|
||||
// Disable db/mongo for dev
|
||||
dbConfig: { enabled: false },
|
||||
dbConfig: { enabled: true },
|
||||
});
|
||||
|
||||
console.log('Starting DcRouter in development mode...');
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '12.2.5',
|
||||
version: '12.2.6',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@serve.zone/dcrouter',
|
||||
version: '12.2.5',
|
||||
version: '12.2.6',
|
||||
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
];
|
||||
|
||||
return html`
|
||||
<ops-sectionheading>Network Targets</ops-sectionheading>
|
||||
<div class="targetsContainer">
|
||||
<dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>
|
||||
<dees-table
|
||||
@@ -81,8 +82,8 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
name: 'Create Target',
|
||||
iconName: 'lucide:plus',
|
||||
type: ['header' as const],
|
||||
actionFunc: async (_: any, table: any) => {
|
||||
await this.showCreateTargetDialog(table);
|
||||
actionFunc: async () => {
|
||||
await this.showCreateTargetDialog();
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -96,16 +97,18 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
{
|
||||
name: 'Edit',
|
||||
iconName: 'lucide:pencil',
|
||||
type: ['contextmenu' as const],
|
||||
actionFunc: async (target: interfaces.data.INetworkTarget, table: any) => {
|
||||
await this.showEditTargetDialog(target, table);
|
||||
type: ['inRow', 'contextmenu'] as any,
|
||||
actionFunc: async (actionData: any) => {
|
||||
const target = actionData.item as interfaces.data.INetworkTarget;
|
||||
await this.showEditTargetDialog(target);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
iconName: 'lucide:trash2',
|
||||
type: ['contextmenu' as const],
|
||||
actionFunc: async (target: interfaces.data.INetworkTarget) => {
|
||||
type: ['inRow', 'contextmenu'] as any,
|
||||
actionFunc: async (actionData: any) => {
|
||||
const target = actionData.item as interfaces.data.INetworkTarget;
|
||||
await this.deleteTarget(target);
|
||||
},
|
||||
},
|
||||
@@ -115,7 +118,7 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private async showCreateTargetDialog(table: any) {
|
||||
private async showCreateTargetDialog() {
|
||||
const { DeesModal } = await import('@design.estate/dees-catalog');
|
||||
DeesModal.createAndShow({
|
||||
heading: 'Create Network Target',
|
||||
@@ -128,10 +131,12 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
{
|
||||
name: 'Create',
|
||||
action: async (modalArg: any) => {
|
||||
const form = modalArg.shadowRoot!.querySelector('dees-form');
|
||||
const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
|
||||
if (!form) return;
|
||||
const data = await form.collectFormData();
|
||||
|
||||
await appstate.profilesTargetsStatePart.dispatchAction(appstate.createTargetAction, {
|
||||
@@ -143,12 +148,11 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
private async showEditTargetDialog(target: interfaces.data.INetworkTarget, table: any) {
|
||||
private async showEditTargetDialog(target: interfaces.data.INetworkTarget) {
|
||||
const hostStr = Array.isArray(target.host) ? target.host.join(', ') : target.host;
|
||||
|
||||
const { DeesModal } = await import('@design.estate/dees-catalog');
|
||||
@@ -163,10 +167,12 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
{
|
||||
name: 'Save',
|
||||
action: async (modalArg: any) => {
|
||||
const form = modalArg.shadowRoot!.querySelector('dees-form');
|
||||
const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
|
||||
if (!form) return;
|
||||
const data = await form.collectFormData();
|
||||
|
||||
await appstate.profilesTargetsStatePart.dispatchAction(appstate.updateTargetAction, {
|
||||
@@ -179,7 +185,6 @@ export class OpsViewNetworkTargets extends DeesElement {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
];
|
||||
|
||||
return html`
|
||||
<ops-sectionheading>Security Profiles</ops-sectionheading>
|
||||
<div class="profilesContainer">
|
||||
<dees-statsgrid .tiles=${statsTiles}></dees-statsgrid>
|
||||
<dees-table
|
||||
@@ -89,8 +90,8 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
name: 'Create Profile',
|
||||
iconName: 'lucide:plus',
|
||||
type: ['header' as const],
|
||||
actionFunc: async (_: any, table: any) => {
|
||||
await this.showCreateProfileDialog(table);
|
||||
actionFunc: async () => {
|
||||
await this.showCreateProfileDialog();
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -104,16 +105,18 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
{
|
||||
name: 'Edit',
|
||||
iconName: 'lucide:pencil',
|
||||
type: ['contextmenu' as const],
|
||||
actionFunc: async (profile: interfaces.data.ISecurityProfile, table: any) => {
|
||||
await this.showEditProfileDialog(profile, table);
|
||||
type: ['inRow', 'contextmenu'] as any,
|
||||
actionFunc: async (actionData: any) => {
|
||||
const profile = actionData.item as interfaces.data.ISecurityProfile;
|
||||
await this.showEditProfileDialog(profile);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Delete',
|
||||
iconName: 'lucide:trash2',
|
||||
type: ['contextmenu' as const],
|
||||
actionFunc: async (profile: interfaces.data.ISecurityProfile) => {
|
||||
type: ['inRow', 'contextmenu'] as any,
|
||||
actionFunc: async (actionData: any) => {
|
||||
const profile = actionData.item as interfaces.data.ISecurityProfile;
|
||||
await this.deleteProfile(profile);
|
||||
},
|
||||
},
|
||||
@@ -123,7 +126,7 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
`;
|
||||
}
|
||||
|
||||
private async showCreateProfileDialog(table: any) {
|
||||
private async showCreateProfileDialog() {
|
||||
const { DeesModal } = await import('@design.estate/dees-catalog');
|
||||
DeesModal.createAndShow({
|
||||
heading: 'Create Security Profile',
|
||||
@@ -137,10 +140,12 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
{
|
||||
name: 'Create',
|
||||
action: async (modalArg: any) => {
|
||||
const form = modalArg.shadowRoot!.querySelector('dees-form');
|
||||
const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
|
||||
if (!form) return;
|
||||
const data = await form.collectFormData();
|
||||
const ipAllowList: string[] = Array.isArray(data.ipAllowList) ? data.ipAllowList : [];
|
||||
const ipBlockList: string[] = Array.isArray(data.ipBlockList) ? data.ipBlockList : [];
|
||||
@@ -158,12 +163,11 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
private async showEditProfileDialog(profile: interfaces.data.ISecurityProfile, table: any) {
|
||||
private async showEditProfileDialog(profile: interfaces.data.ISecurityProfile) {
|
||||
const { DeesModal } = await import('@design.estate/dees-catalog');
|
||||
DeesModal.createAndShow({
|
||||
heading: `Edit Profile: ${profile.name}`,
|
||||
@@ -177,10 +181,12 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
</dees-form>
|
||||
`,
|
||||
menuOptions: [
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
{
|
||||
name: 'Save',
|
||||
action: async (modalArg: any) => {
|
||||
const form = modalArg.shadowRoot!.querySelector('dees-form');
|
||||
const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form');
|
||||
if (!form) return;
|
||||
const data = await form.collectFormData();
|
||||
const ipAllowList: string[] = Array.isArray(data.ipAllowList) ? data.ipAllowList : [];
|
||||
const ipBlockList: string[] = Array.isArray(data.ipBlockList) ? data.ipBlockList : [];
|
||||
@@ -199,7 +205,6 @@ export class OpsViewSecurityProfiles extends DeesElement {
|
||||
modalArg.destroy();
|
||||
},
|
||||
},
|
||||
{ name: 'Cancel', action: async (modalArg: any) => modalArg.destroy() },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user