From 59155c2e34ab94b55805b10de45feeeb16bb4712 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Fri, 6 Mar 2026 00:06:18 -0700 Subject: [PATCH] remove non option from smtp for better package compat --- .../lib/actions/input/inputSpecConstants.ts | 6 +- .../shared/src/i18n/dictionaries/de.ts | 1 - .../shared/src/i18n/dictionaries/en.ts | 1 - .../shared/src/i18n/dictionaries/es.ts | 1 - .../shared/src/i18n/dictionaries/fr.ts | 1 - .../shared/src/i18n/dictionaries/pl.ts | 1 - .../smtp.component.ts} | 73 ++++++++++++++----- .../portal/routes/system/system.routes.ts | 2 +- 8 files changed, 58 insertions(+), 28 deletions(-) rename web/projects/ui/src/app/routes/portal/routes/system/routes/{email/email.component.ts => smtp/smtp.component.ts} (77%) diff --git a/sdk/base/lib/actions/input/inputSpecConstants.ts b/sdk/base/lib/actions/input/inputSpecConstants.ts index 28d3c4f84..54c7afd7d 100644 --- a/sdk/base/lib/actions/input/inputSpecConstants.ts +++ b/sdk/base/lib/actions/input/inputSpecConstants.ts @@ -84,10 +84,6 @@ export const customSmtp = smtpFields() * Each variant has SMTP fields pre-filled with the provider's recommended settings. */ export const smtpProviderVariants = Variants.of({ - none: { - name: 'None', - spec: InputSpec.of({}), - }, gmail: { name: 'Gmail', spec: smtpFields({ @@ -140,7 +136,7 @@ export const smtpProviderVariants = Variants.of({ export const systemSmtpSpec = InputSpec.of({ provider: Value.union({ name: 'Provider', - default: 'none', + default: 'gmail', variants: smtpProviderVariants, }), }) diff --git a/web/projects/shared/src/i18n/dictionaries/de.ts b/web/projects/shared/src/i18n/dictionaries/de.ts index b4f265cb5..95f7152bb 100644 --- a/web/projects/shared/src/i18n/dictionaries/de.ts +++ b/web/projects/shared/src/i18n/dictionaries/de.ts @@ -360,7 +360,6 @@ export default { 377: 'StartOS-Sicherungen erkannt', 378: 'Keine StartOS-Sicherungen erkannt', 379: 'StartOS-Version', - 381: 'SMTP-Zugangsdaten', 382: 'Test-E-Mail senden', 383: 'Senden', 384: 'E-Mail wird gesendet', diff --git a/web/projects/shared/src/i18n/dictionaries/en.ts b/web/projects/shared/src/i18n/dictionaries/en.ts index 1b110f7cc..e7856c8fc 100644 --- a/web/projects/shared/src/i18n/dictionaries/en.ts +++ b/web/projects/shared/src/i18n/dictionaries/en.ts @@ -359,7 +359,6 @@ export const ENGLISH: Record = { 'StartOS backups detected': 377, 'No StartOS backups detected': 378, 'StartOS Version': 379, - 'SMTP Credentials': 381, 'Send test email': 382, 'Send': 383, 'Sending email': 384, diff --git a/web/projects/shared/src/i18n/dictionaries/es.ts b/web/projects/shared/src/i18n/dictionaries/es.ts index bd6c3944a..11cf98218 100644 --- a/web/projects/shared/src/i18n/dictionaries/es.ts +++ b/web/projects/shared/src/i18n/dictionaries/es.ts @@ -360,7 +360,6 @@ export default { 377: 'Copias de seguridad de StartOS detectadas', 378: 'No se detectaron copias de seguridad de StartOS', 379: 'Versión de StartOS', - 381: 'Credenciales SMTP', 382: 'Enviar correo de prueba', 383: 'Enviar', 384: 'Enviando correo', diff --git a/web/projects/shared/src/i18n/dictionaries/fr.ts b/web/projects/shared/src/i18n/dictionaries/fr.ts index b5c72b984..678f5961b 100644 --- a/web/projects/shared/src/i18n/dictionaries/fr.ts +++ b/web/projects/shared/src/i18n/dictionaries/fr.ts @@ -360,7 +360,6 @@ export default { 377: 'Sauvegardes StartOS détectées', 378: 'Aucune sauvegarde StartOS détectée', 379: 'Version de StartOS', - 381: 'Identifiants SMTP', 382: 'Envoyer un email de test', 383: 'Envoyer', 384: 'Envoi de l’email', diff --git a/web/projects/shared/src/i18n/dictionaries/pl.ts b/web/projects/shared/src/i18n/dictionaries/pl.ts index 78df10d9d..b26484268 100644 --- a/web/projects/shared/src/i18n/dictionaries/pl.ts +++ b/web/projects/shared/src/i18n/dictionaries/pl.ts @@ -360,7 +360,6 @@ export default { 377: 'Wykryto kopie zapasowe StartOS', 378: 'Nie wykryto kopii zapasowych StartOS', 379: 'Wersja StartOS', - 381: 'Dane logowania SMTP', 382: 'Wyślij e-mail testowy', 383: 'Wyślij', 384: 'Wysyłanie e-maila', diff --git a/web/projects/ui/src/app/routes/portal/routes/system/routes/email/email.component.ts b/web/projects/ui/src/app/routes/portal/routes/system/routes/smtp/smtp.component.ts similarity index 77% rename from web/projects/ui/src/app/routes/portal/routes/system/routes/email/email.component.ts rename to web/projects/ui/src/app/routes/portal/routes/system/routes/smtp/smtp.component.ts index 3cf1b0ca0..ed037a25b 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/routes/email/email.component.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/routes/smtp/smtp.component.ts @@ -10,7 +10,7 @@ import { i18nPipe, LoadingService, } from '@start9labs/shared' -import { inputSpec, utils } from '@start9labs/start-sdk' +import { inputSpec, ISB, utils } from '@start9labs/start-sdk' import { TuiButton, TuiError, TuiTextfield, TuiTitle } from '@taiga-ui/core' import { TuiHeader } from '@taiga-ui/layout' import { PatchDB } from 'patch-db-client' @@ -43,14 +43,14 @@ function detectProviderKey(host: string | undefined): string { {{ 'Back' | i18n }} - {{ 'SMTP' | i18n }} + SMTP @if (form$ | async; as data) {

- {{ 'SMTP Credentials' | i18n }} + SMTP
+ @if (!data.form.pristine) { + + }
- @if (data.form.value.provider?.selection !== 'none') { + @if (data.form.value.smtp?.selection === 'enabled') {

@@ -163,35 +173,57 @@ export default class SystemEmailComponent { return !!value && !this.emailRegex.test(value) } + private readonly smtpSpec = ISB.InputSpec.of({ + smtp: ISB.Value.union({ + name: this.i18n.transform('SMTP'), + default: 'disabled', + variants: ISB.Variants.of({ + disabled: { + name: this.i18n.transform('Disabled'), + spec: ISB.InputSpec.of({}), + }, + enabled: { + name: this.i18n.transform('Enabled'), + spec: inputSpec.constants.systemSmtpSpec, + }, + }), + }), + }) + readonly form$ = this.patch.watch$('serverInfo', 'smtp').pipe( switchMap(async value => { - const spec = await configBuilderToSpec(inputSpec.constants.systemSmtpSpec) + const spec = await configBuilderToSpec(this.smtpSpec) const formData = value ? { - provider: { - selection: detectProviderKey(value.host), + smtp: { + selection: 'enabled' as const, value: { - host: value.host, - security: { - selection: value.security, - value: { port: String(value.port) }, + provider: { + selection: detectProviderKey(value.host), + value: { + host: value.host, + security: { + selection: value.security, + value: { port: String(value.port) }, + }, + from: value.from, + username: value.username, + password: value.password, + }, }, - from: value.from, - username: value.username, - password: value.password, }, }, } : undefined const form = this.formService.createForm(spec, formData) - return { form, spec } + return { form, spec, formData } }), ) private getSmtpValue(formValue: Record) { - const { security, ...rest } = formValue['provider'].value + const { security, ...rest } = formValue['smtp'].value.provider.value return { ...rest, security: security.selection, @@ -203,7 +235,7 @@ export default class SystemEmailComponent { const loader = this.loader.open('Saving').subscribe() try { - if (formValue['provider'].selection === 'none') { + if (formValue['smtp'].selection === 'disabled') { await this.api.clearSmtp({}) } else { await this.api.setSmtp(this.getSmtpValue(formValue)) @@ -215,6 +247,13 @@ export default class SystemEmailComponent { } } + cancel(data: { + form: ReturnType + formData: Record | undefined + }) { + data.form.reset(data.formData) + } + async sendTestEmail(formValue: Record) { const smtpValue = this.getSmtpValue(formValue) const address = this.testEmailControl.value! diff --git a/web/projects/ui/src/app/routes/portal/routes/system/system.routes.ts b/web/projects/ui/src/app/routes/portal/routes/system/system.routes.ts index 8ed0703e5..689366dbf 100644 --- a/web/projects/ui/src/app/routes/portal/routes/system/system.routes.ts +++ b/web/projects/ui/src/app/routes/portal/routes/system/system.routes.ts @@ -28,7 +28,7 @@ export default [ { path: 'email', title: titleResolver, - loadComponent: () => import('./routes/email/email.component'), + loadComponent: () => import('./routes/smtp/smtp.component'), }, { path: 'backup',