feat(web-ui): standardize settings views for ACME and email security panels

This commit is contained in:
2026-04-12 20:43:57 +00:00
parent 60d095cd78
commit 196e5dfc1b
7 changed files with 71 additions and 162 deletions

View File

@@ -1,5 +1,12 @@
# Changelog # Changelog
## 2026-04-12 - 13.10.0 - feat(web-ui)
standardize settings views for ACME and email security panels
- replace custom ACME settings layouts with the reusable dees-settings component for configured and empty states
- update the email security view to present settings through dees-settings and open a modal-based read-only edit dialog
- bump @design.estate/dees-catalog to ^3.78.0 to support the updated UI components
## 2026-04-12 - 13.9.2 - fix(web-ui) ## 2026-04-12 - 13.9.2 - fix(web-ui)
improve form field descriptions and align certificate settings with tile components improve form field descriptions and align certificate settings with tile components

View File

@@ -35,7 +35,7 @@
"@api.global/typedserver": "^8.4.6", "@api.global/typedserver": "^8.4.6",
"@api.global/typedsocket": "^4.1.2", "@api.global/typedsocket": "^4.1.2",
"@apiclient.xyz/cloudflare": "^7.1.0", "@apiclient.xyz/cloudflare": "^7.1.0",
"@design.estate/dees-catalog": "^3.76.1", "@design.estate/dees-catalog": "^3.78.0",
"@design.estate/dees-element": "^2.2.4", "@design.estate/dees-element": "^2.2.4",
"@push.rocks/lik": "^6.4.0", "@push.rocks/lik": "^6.4.0",
"@push.rocks/projectinfo": "^5.1.0", "@push.rocks/projectinfo": "^5.1.0",

14
pnpm-lock.yaml generated
View File

@@ -24,8 +24,8 @@ importers:
specifier: ^7.1.0 specifier: ^7.1.0
version: 7.1.0 version: 7.1.0
'@design.estate/dees-catalog': '@design.estate/dees-catalog':
specifier: ^3.76.1 specifier: ^3.78.0
version: 3.76.1(@tiptap/pm@2.27.2) version: 3.78.0(@tiptap/pm@2.27.2)
'@design.estate/dees-element': '@design.estate/dees-element':
specifier: ^2.2.4 specifier: ^2.2.4
version: 2.2.4 version: 2.2.4
@@ -353,8 +353,8 @@ packages:
'@configvault.io/interfaces@1.0.17': '@configvault.io/interfaces@1.0.17':
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==} resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
'@design.estate/dees-catalog@3.76.1': '@design.estate/dees-catalog@3.78.0':
resolution: {integrity: sha512-DSnu1NHz0C9CI13e6HMUV6lFiAKzOoPccZUZu6wDrpTcGha1trvFftcRzsieJ0NrvNJ6qZrh1vGL6ZYhu5RO0A==} resolution: {integrity: sha512-doc9eYGsFV47Ui7k5FuLXpt3ytC/Q+g+yX+qGU/V4fZpc5KUXpL04/FRzO0AU1wF9Xl9GMmL39CcE2vKj88QAQ==}
'@design.estate/dees-comms@1.0.30': '@design.estate/dees-comms@1.0.30':
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==} resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
@@ -4318,7 +4318,7 @@ snapshots:
'@api.global/typedrequest-interfaces': 3.0.19 '@api.global/typedrequest-interfaces': 3.0.19
'@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.3) '@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.3)
'@cloudflare/workers-types': 4.20260405.1 '@cloudflare/workers-types': 4.20260405.1
'@design.estate/dees-catalog': 3.76.1(@tiptap/pm@2.27.2) '@design.estate/dees-catalog': 3.78.0(@tiptap/pm@2.27.2)
'@design.estate/dees-comms': 1.0.30 '@design.estate/dees-comms': 1.0.30
'@push.rocks/lik': 6.4.0 '@push.rocks/lik': 6.4.0
'@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartdelay': 3.0.5
@@ -4847,7 +4847,7 @@ snapshots:
dependencies: dependencies:
'@api.global/typedrequest-interfaces': 3.0.19 '@api.global/typedrequest-interfaces': 3.0.19
'@design.estate/dees-catalog@3.76.1(@tiptap/pm@2.27.2)': '@design.estate/dees-catalog@3.78.0(@tiptap/pm@2.27.2)':
dependencies: dependencies:
'@design.estate/dees-domtools': 2.5.4 '@design.estate/dees-domtools': 2.5.4
'@design.estate/dees-element': 2.2.4 '@design.estate/dees-element': 2.2.4
@@ -6915,7 +6915,7 @@ snapshots:
'@serve.zone/catalog@2.12.3(@tiptap/pm@2.27.2)': '@serve.zone/catalog@2.12.3(@tiptap/pm@2.27.2)':
dependencies: dependencies:
'@design.estate/dees-catalog': 3.76.1(@tiptap/pm@2.27.2) '@design.estate/dees-catalog': 3.78.0(@tiptap/pm@2.27.2)
'@design.estate/dees-domtools': 2.5.4 '@design.estate/dees-domtools': 2.5.4
'@design.estate/dees-element': 2.2.4 '@design.estate/dees-element': 2.2.4
'@design.estate/dees-wcctools': 3.8.0 '@design.estate/dees-wcctools': 3.8.0

View File

@@ -3,6 +3,6 @@
*/ */
export const commitinfo = { export const commitinfo = {
name: '@serve.zone/dcrouter', name: '@serve.zone/dcrouter',
version: '13.9.2', version: '13.10.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: '13.9.2', version: '13.10.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

@@ -54,51 +54,6 @@ export class OpsViewCertificates extends DeesElement {
gap: 24px; gap: 24px;
} }
.acmeTileHeader {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 8px 12px;
}
.acmeTileHeading {
font-size: 14px;
font-weight: 600;
}
.acmeEmptyContent {
padding: 16px;
font-size: 13px;
line-height: 1.5;
color: ${cssManager.bdTheme('#78350f', '#fde68a')};
}
.acmeGrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px 24px;
padding: 16px;
}
.acmeField {
display: flex;
flex-direction: column;
gap: 2px;
}
.acmeLabel {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.03em;
color: ${cssManager.bdTheme('#6b7280', '#9ca3af')};
}
.acmeValue {
font-size: 13px;
color: ${cssManager.bdTheme('#111827', '#f3f4f6')};
}
.statusBadge { .statusBadge {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -227,60 +182,26 @@ export class OpsViewCertificates extends DeesElement {
if (!config) { if (!config) {
return html` return html`
<dees-tile .heading=${'ACME Settings'}> <dees-settings
<div slot="header" class="acmeTileHeader"> .heading=${'ACME Settings'}
<span class="acmeTileHeading">ACME Settings</span> .description=${'No ACME configuration yet. Click Configure to set up automated TLS certificate issuance via Let\'s Encrypt. You\'ll also need at least one DNS provider under Domains > Providers.'}
<dees-button .actions=${[{ name: 'Configure', action: () => this.showEditAcmeDialog() }]}
@click=${() => this.showEditAcmeDialog()} ></dees-settings>
.type=${'highlighted'}
>Configure</dees-button>
</div>
<div class="acmeEmptyContent">
No ACME configuration yet. Click <strong>Configure</strong> to set up automated TLS
certificate issuance via Let's Encrypt. You'll also need at least one DNS provider
under <strong>Domains &gt; Providers</strong>.
</div>
</dees-tile>
`; `;
} }
return html` return html`
<dees-tile> <dees-settings
<div slot="header" class="acmeTileHeader"> .heading=${'ACME Settings'}
<span class="acmeTileHeading">ACME Settings</span> .settingsFields=${[
<dees-button @click=${() => this.showEditAcmeDialog()}>Edit</dees-button> { key: 'email', label: 'Account email', value: config.accountEmail || '(not set)' },
</div> { key: 'status', label: 'Status', value: config.enabled ? 'enabled' : 'disabled' },
<div class="acmeGrid"> { key: 'mode', label: 'Mode', value: config.useProduction ? 'production' : 'staging' },
<div class="acmeField"> { key: 'autoRenew', label: 'Auto-renew', value: config.autoRenew ? 'on' : 'off' },
<span class="acmeLabel">Account email</span> { key: 'threshold', label: 'Renewal threshold', value: `${config.renewThresholdDays} days` },
<span class="acmeValue">${config.accountEmail || '(not set)'}</span> ]}
</div> .actions=${[{ name: 'Edit', action: () => this.showEditAcmeDialog() }]}
<div class="acmeField"> ></dees-settings>
<span class="acmeLabel">Status</span>
<span class="acmeValue">
<span class="statusBadge ${config.enabled ? 'valid' : 'unknown'}">
${config.enabled ? 'enabled' : 'disabled'}
</span>
</span>
</div>
<div class="acmeField">
<span class="acmeLabel">Mode</span>
<span class="acmeValue">
<span class="statusBadge ${config.useProduction ? 'valid' : 'provisioning'}">
${config.useProduction ? 'production' : 'staging'}
</span>
</span>
</div>
<div class="acmeField">
<span class="acmeLabel">Auto-renew</span>
<span class="acmeValue">${config.autoRenew ? 'on' : 'off'}</span>
</div>
<div class="acmeField">
<span class="acmeLabel">Renewal threshold</span>
<span class="acmeValue">${config.renewThresholdDays} days</span>
</div>
</div>
</dees-tile>
`; `;
} }

View File

@@ -37,25 +37,10 @@ export class OpsViewEmailSecurity extends DeesElement {
cssManager.defaultStyles, cssManager.defaultStyles,
viewHostCss, viewHostCss,
css` css`
h2 { .securityContainer {
margin: 32px 0 16px 0; display: flex;
font-size: 24px; flex-direction: column;
font-weight: 600; gap: 24px;
color: ${cssManager.bdTheme('#333', '#ccc')};
}
dees-statsgrid {
margin-bottom: 32px;
}
.securityCard {
background: ${cssManager.bdTheme('#fff', '#222')};
border: 1px solid ${cssManager.bdTheme('#e9ecef', '#333')};
border-radius: 8px;
padding: 24px;
position: relative;
overflow: hidden;
}
.actionButton {
margin-top: 16px;
} }
`, `,
]; ];
@@ -113,48 +98,44 @@ export class OpsViewEmailSecurity extends DeesElement {
return html` return html`
<dees-heading level="3">Email Security</dees-heading> <dees-heading level="3">Email Security</dees-heading>
<dees-statsgrid <div class="securityContainer">
.tiles=${tiles} <dees-statsgrid
.minTileWidth=${200} .tiles=${tiles}
></dees-statsgrid> .minTileWidth=${200}
></dees-statsgrid>
<h2>Email Security Configuration</h2> <dees-settings
<div class="securityCard"> .heading=${'Security Configuration'}
<dees-form> .settingsFields=${[
<dees-input-checkbox { key: 'spf', label: 'SPF checking', value: 'enabled' },
.key=${'enableSPF'} { key: 'dkim', label: 'DKIM validation', value: 'enabled' },
.label=${'Enable SPF checking'} { key: 'dmarc', label: 'DMARC policy', value: 'enabled' },
.value=${true} { key: 'spam', label: 'Spam filtering', value: 'enabled' },
></dees-input-checkbox> ]}
<dees-input-checkbox .actions=${[{ name: 'Edit', action: () => this.showEditSecurityDialog() }]}
.key=${'enableDKIM'} ></dees-settings>
.label=${'Enable DKIM validation'}
.value=${true}
></dees-input-checkbox>
<dees-input-checkbox
.key=${'enableDMARC'}
.label=${'Enable DMARC policy enforcement'}
.value=${true}
></dees-input-checkbox>
<dees-input-checkbox
.key=${'enableSpamFilter'}
.label=${'Enable spam filtering'}
.value=${true}
></dees-input-checkbox>
</dees-form>
<dees-button
class="actionButton"
type="highlighted"
@click=${() => this.saveEmailSecuritySettings()}
>
Save Settings
</dees-button>
</div> </div>
`; `;
} }
private async saveEmailSecuritySettings() { private async showEditSecurityDialog() {
// Config is read-only from the UI for now const { DeesModal } = await import('@design.estate/dees-catalog');
alert('Email security settings are read-only. Update the dcrouter configuration file to change these settings.'); DeesModal.createAndShow({
heading: 'Edit Security Configuration',
content: html`
<dees-form>
<dees-input-checkbox .key=${'enableSPF'} .label=${'SPF checking'} .value=${true}></dees-input-checkbox>
<dees-input-checkbox .key=${'enableDKIM'} .label=${'DKIM validation'} .value=${true}></dees-input-checkbox>
<dees-input-checkbox .key=${'enableDMARC'} .label=${'DMARC policy enforcement'} .value=${true}></dees-input-checkbox>
<dees-input-checkbox .key=${'enableSpamFilter'} .label=${'Spam filtering'} .value=${true}></dees-input-checkbox>
</dees-form>
<p style="margin-top: 12px; font-size: 12px; opacity: 0.7;">
These settings are read-only for now. Update the dcrouter configuration to change them.
</p>
`,
menuOptions: [
{ name: 'Close', action: async (modalArg: any) => modalArg.destroy() },
],
});
} }
} }