general-config and smtp forms in separate components

This commit is contained in:
Edi Cziszter 2021-11-20 21:28:24 +02:00
parent 5061877036
commit 66d9083bfa
16 changed files with 373 additions and 332 deletions

View File

@ -46,6 +46,8 @@ import { LicenseReportService } from './services/licence-report.service';
import { RulesService } from './services/rules.service';
import { SmtpConfigService } from './services/smtp-config.service';
import { UploadDictionaryDialogComponent } from './dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component';
import { GeneralConfigFormComponent } from './screens/general-config/general-config-form/general-config-form.component';
import { SmtpFormComponent } from './screens/general-config/smtp-form/smtp-form.component';
const dialogs = [
AddEditDossierTemplateDialogComponent,
@ -96,7 +98,7 @@ const components = [
];
@NgModule({
declarations: [...components],
declarations: [...components, GeneralConfigFormComponent, SmtpFormComponent],
providers: [AdminDialogService, AuditService, DigitalSignatureService, LicenseReportService, RulesService, SmtpConfigService],
imports: [CommonModule, SharedModule, AdminRoutingModule, NgxChartsModule, ColorPickerModule, MonacoEditorModule],
})

View File

@ -8,12 +8,18 @@ import { defaultColorsTranslations } from '../../translations/default-colors-tra
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { DictionaryService } from '@shared/services/dictionary.service';
interface IEditColorData {
colors: IColors;
colorKey: DefaultColorType;
dossierTemplateId: string;
}
@Component({
templateUrl: './edit-color-dialog.component.html',
styleUrls: ['./edit-color-dialog.component.scss'],
})
export class EditColorDialogComponent extends BaseDialogComponent {
form: FormGroup;
readonly form: FormGroup;
translations = defaultColorsTranslations;
private readonly _initialColor: string;
private readonly _dossierTemplateId: string;
@ -25,7 +31,7 @@ export class EditColorDialogComponent extends BaseDialogComponent {
private readonly _translateService: TranslateService,
private readonly _dialogRef: MatDialogRef<EditColorDialogComponent>,
@Inject(MAT_DIALOG_DATA)
readonly data: { colors: IColors; colorKey: DefaultColorType; dossierTemplateId: string },
readonly data: IEditColorData,
) {
super();
this._dossierTemplateId = data.dossierTemplateId;

View File

@ -9,6 +9,12 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FileAttributeConfig, FileAttributeConfigTypes, IField, IFileAttributesConfig } from '@red/domain';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
interface IFileAttributesCSVImportData {
readonly csv: File;
readonly dossierTemplateId: string;
readonly existingConfiguration: IFileAttributesConfig;
}
@Component({
templateUrl: './file-attributes-csv-import-dialog.component.html',
styleUrls: ['./file-attributes-csv-import-dialog.component.scss'],
@ -36,12 +42,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<IFi
private readonly _formBuilder: FormBuilder,
readonly dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent>,
private readonly _fileAttributesService: FileAttributesService,
@Inject(MAT_DIALOG_DATA)
readonly data: {
readonly csv: File;
readonly dossierTemplateId: string;
readonly existingConfiguration: IFileAttributesConfig;
},
@Inject(MAT_DIALOG_DATA) readonly data: IFileAttributesCSVImportData,
) {
super(_injector);
this.form = this._getForm();

View File

@ -10,16 +10,14 @@ import { ISmtpConfiguration } from '@red/domain';
styleUrls: ['./smtp-auth-dialog.component.scss'],
})
export class SmtpAuthDialogComponent {
form: FormGroup;
readonly form: FormGroup = this._getForm();
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _userService: UserService,
public dialogRef: MatDialogRef<SmtpAuthDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: ISmtpConfiguration,
) {
this.form = this._getForm();
}
) {}
private _getForm(): FormGroup {
return this._formBuilder.group({

View File

@ -41,7 +41,7 @@
class="mr-0"
></redaction-pagination>
<div class="separator">·</div>
<form [formGroup]="filterForm">
<form [formGroup]="form">
<div class="iqser-input-group w-150 mr-20">
<mat-form-field class="no-label">
<mat-select formControlName="category">
@ -56,12 +56,12 @@
<mat-select formControlName="userId">
<mat-select-trigger>
<redaction-initials-avatar
*ngIf="filterForm.get('userId').value !== ALL_USERS"
[user]="filterForm.get('userId').value"
*ngIf="form.get('userId').value !== ALL_USERS"
[user]="form.get('userId').value"
[withName]="true"
size="small"
></redaction-initials-avatar>
<div *ngIf="filterForm.get('userId').value === ALL_USERS" [translate]="ALL_USERS"></div>
<div *ngIf="form.get('userId').value === ALL_USERS" [translate]="ALL_USERS"></div>
</mat-select-trigger>
<mat-option *ngFor="let userId of userIds" [value]="userId">
<redaction-initials-avatar

View File

@ -22,7 +22,7 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnD
readonly ALL_USERS = _('audit-screen.all-users');
readonly translations = auditCategoriesTranslations;
readonly currentUser = this._userService.currentUser;
filterForm: FormGroup;
readonly form: FormGroup = this._getForm();
categories: string[] = [];
userIds: Set<string>;
logs: IAuditResponse;
@ -44,18 +44,21 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnD
private readonly _auditService: AuditService,
) {
super(_injector);
this.filterForm = this._formBuilder.group({
this.addSubscription = this.form.valueChanges.subscribe(async value => {
if (!this._updateDateFilters(value)) {
await this._fetchData();
}
});
}
private _getForm(): FormGroup {
return this._formBuilder.group({
category: [this.ALL_CATEGORIES],
userId: [this.ALL_USERS],
from: [],
to: [],
});
this.addSubscription = this.filterForm.valueChanges.subscribe(async value => {
if (!this._updateDateFilters(value)) {
await this._fetchData();
}
});
}
get totalPages(): number {
@ -74,22 +77,22 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnD
}
private _updateDateFilters(value): boolean {
if (applyIntervalConstraints(value, this._previousFrom, this._previousTo, this.filterForm, 'from', 'to')) {
if (applyIntervalConstraints(value, this._previousFrom, this._previousTo, this.form, 'from', 'to')) {
return true;
}
this._previousFrom = this.filterForm.get('from').value;
this._previousTo = this.filterForm.get('to').value;
this._previousFrom = this.form.get('from').value;
this._previousTo = this.form.get('to').value;
return false;
}
private async _fetchData(page?: number) {
this._loadingService.start();
const promises = [];
const category = this.filterForm.get('category').value;
const userId = this.filterForm.get('userId').value;
const from = this.filterForm.get('from').value;
let to = this.filterForm.get('to').value;
const category = this.form.get('category').value;
const userId = this.form.get('userId').value;
const from = this.form.get('from').value;
let to = this.form.get('to').value;
if (to) {
to = to.clone().add(1, 'd');
}

View File

@ -13,7 +13,7 @@
<div class="content-inner">
<div class="content-container">
<div class="content-container-content">
<form *ngIf="digitalSignatureForm" [formGroup]="digitalSignatureForm" autocomplete="off">
<form *ngIf="form" [formGroup]="form" autocomplete="off">
<input #fileInput (change)="fileChanged($event, fileInput)" class="file-upload-input" hidden type="file" />
<iqser-empty-state
@ -76,7 +76,7 @@
<div [class.hidden]="!hasDigitalSignatureSet" class="changes-box">
<iqser-icon-button
(action)="saveDigitalSignature()"
[disabled]="digitalSignatureForm.invalid"
[disabled]="form.invalid"
[label]="'digital-signature-screen.action.save' | translate"
[type]="iconButtonTypes.primary"
icon="iqser:check"

View File

@ -19,7 +19,7 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements
readonly currentUser = this._userService.currentUser;
digitalSignature: IDigitalSignature;
digitalSignatureForm: FormGroup;
form: FormGroup;
digitalSignatureExists = false;
@ -36,12 +36,12 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements
}
get hasDigitalSignatureSet() {
return this.digitalSignatureExists || !!this.digitalSignatureForm.get('base64EncodedPrivateKey').value;
return this.digitalSignatureExists || !!this.form.get('base64EncodedPrivateKey').value;
}
saveDigitalSignature() {
const digitalSignature = {
...this.digitalSignatureForm.getRawValue(),
...this.form.getRawValue(),
};
//adjusted for chrome auto-complete / password manager
digitalSignature.password = digitalSignature.keySecret;
@ -81,8 +81,8 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements
fileReader.onload = () => {
const dataUrl = <string>fileReader.result;
const actualBase64Value = dataUrl.substring(lastIndexOfEnd(dataUrl, ';base64,'));
this.digitalSignatureForm.get('base64EncodedPrivateKey').setValue(actualBase64Value);
this.digitalSignatureForm.get('certificateName').setValue(file.name);
this.form.get('base64EncodedPrivateKey').setValue(actualBase64Value);
this.form.get('certificateName').setValue(file.name);
input.value = null;
};
fileReader.readAsDataURL(file);
@ -103,13 +103,13 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements
},
)
.add(() => {
this._initForm();
this.form = this._getForm();
this._loadingService.stop();
});
}
private _initForm() {
this.digitalSignatureForm = this._formBuilder.group({
private _getForm(): FormGroup {
return this._formBuilder.group({
certificateName: [this.digitalSignature.certificateName, Validators.required],
contactInfo: this.digitalSignature.contactInfo,
location: this.digitalSignature.location,

View File

@ -0,0 +1,29 @@
<div class="dialog-header">
<div class="heading-l" translate="general-config-screen.general.title"></div>
<div translate="general-config-screen.general.subtitle"></div>
</div>
<form (submit)="saveGeneralConfig()" [formGroup]="form">
<div class="dialog-content">
<div class="dialog-content-left">
<div class="iqser-input-group">
<label translate="general-config-screen.app-name.label"></label>
<input
formControlName="auxiliaryName"
name="auxiliaryName"
placeholder="{{ 'general-config-screen.app-name.placeholder' | translate }}"
type="text"
/>
</div>
<div class="inline-input-group flex-align-items-center">
<mat-slide-toggle color="primary" formControlName="forgotPasswordFunctionEnabled"></mat-slide-toggle>
<span class="ml-8" translate="general-config-screen.general.form.forgot-password"></span>
</div>
</div>
</div>
<div class="dialog-actions">
<button [disabled]="form.invalid || !generalConfigurationChanged" color="primary" mat-flat-button type="submit">
{{ 'general-config-screen.actions.save' | translate }}
</button>
</div>
</form>

View File

@ -0,0 +1,71 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { AutoUnsubscribe, LoadingService } from '@iqser/common-ui';
import { GeneralSettingsService } from '@services/general-settings.service';
import { IGeneralConfiguration } from '@red/domain';
import { ConfigService } from '@services/config.service';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'redaction-general-config-form',
templateUrl: './general-config-form.component.html',
styleUrls: ['./general-config-form.component.scss'],
})
export class GeneralConfigFormComponent extends AutoUnsubscribe implements OnInit, OnDestroy {
private _initialConfiguration: IGeneralConfiguration;
readonly form: FormGroup = this._getForm();
constructor(
private readonly _loadingService: LoadingService,
private readonly _generalSettingsService: GeneralSettingsService,
private readonly _configService: ConfigService,
private readonly _formBuilder: FormBuilder,
) {
super();
}
private _getForm(): FormGroup {
return this._formBuilder.group({
forgotPasswordFunctionEnabled: [false],
auxiliaryName: [undefined],
});
}
async ngOnInit(): Promise<void> {
await this._loadData();
}
async saveGeneralConfig() {
this._loadingService.start();
const configFormValues = this.form.getRawValue();
await this._generalSettingsService.updateGeneralConfigurations(configFormValues).toPromise();
this._initialConfiguration = await this._generalSettingsService.getGeneralConfigurations().toPromise();
this._configService.updateDisplayName(this._initialConfiguration.displayName);
this._loadingService.stop();
}
get generalConfigurationChanged(): boolean {
if (!this._initialConfiguration) {
return true;
}
for (const key of Object.keys(this.form.getRawValue())) {
if (this._initialConfiguration[key] !== this.form.get(key).value) {
return true;
}
}
return false;
}
private async _loadData() {
this._loadingService.start();
try {
this._initialConfiguration = await this._generalSettingsService.getGeneralConfigurations().toPromise();
this.form.patchValue(this._initialConfiguration, { emitEvent: false });
} catch (e) {}
this._loadingService.stop();
}
}

View File

@ -22,156 +22,10 @@
<div class="content-inner">
<div class="content-container">
<div class="dialog mb-8">
<div class="dialog-header">
<div class="heading-l" translate="general-config-screen.general.title"></div>
<div translate="general-config-screen.general.subtitle"></div>
</div>
<form (submit)="saveGeneralConfig()" [formGroup]="configForm">
<div class="dialog-content">
<div class="dialog-content-left">
<div class="iqser-input-group">
<label translate="general-config-screen.app-name.label"></label>
<input
formControlName="auxiliaryName"
name="auxiliaryName"
placeholder="{{ 'general-config-screen.app-name.placeholder' | translate }}"
type="text"
/>
</div>
<div class="inline-input-group flex-align-items-center">
<mat-slide-toggle color="primary" formControlName="forgotPasswordFunctionEnabled"></mat-slide-toggle>
<span class="ml-8" translate="general-config-screen.general.form.forgot-password"></span>
</div>
</div>
</div>
<div class="dialog-actions">
<button
[disabled]="configForm.invalid || !generalConfigurationChanged"
color="primary"
mat-flat-button
type="submit"
>
{{ 'general-config-screen.actions.save' | translate }}
</button>
</div>
</form>
<redaction-general-config-form></redaction-general-config-form>
</div>
<div class="dialog mt-16">
<div class="dialog-header">
<div class="heading-l" translate="general-config-screen.title"></div>
<div translate="general-config-screen.subtitle"></div>
</div>
<form (submit)="save()" [formGroup]="smtpForm">
<div class="dialog-content">
<div class="dialog-content-left">
<div class="iqser-input-group required">
<label translate="general-config-screen.form.host"></label>
<input
formControlName="host"
name="host"
placeholder="{{ 'general-config-screen.form.host-placeholder' | translate }}"
type="text"
/>
</div>
<div class="iqser-input-group w-100">
<label translate="general-config-screen.form.port"></label>
<input formControlName="port" name="port" type="number" />
</div>
<div class="iqser-input-group required">
<label translate="general-config-screen.form.from"></label>
<input
formControlName="from"
name="from"
placeholder="{{ 'general-config-screen.form.from-placeholder' | translate }}"
type="email"
/>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.from-display-name"></label>
<input
formControlName="fromDisplayName"
name="fromDisplayName"
placeholder="{{ 'general-config-screen.form.from-display-name-placeholder' | translate }}"
type="text"
/>
<span class="hint" translate="general-config-screen.form.from-display-name-hint"></span>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.reply-to"></label>
<input
formControlName="replyTo"
name="replyTo"
placeholder="{{ 'general-config-screen.form.reply-to-placeholder' | translate }}"
type="text"
/>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.reply-to-display-name"></label>
<input
formControlName="replyToDisplayName"
name="replyToDisplayName"
placeholder="{{ 'general-config-screen.form.reply-to-display-name-placeholder' | translate }}"
type="text"
/>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.envelope-from"></label>
<input
formControlName="envelopeFrom"
name="envelopeFrom"
placeholder="{{ 'general-config-screen.form.envelope-from-placeholder' | translate }}"
type="text"
/>
<span class="hint" translate="general-config-screen.form.envelope-from-hint"></span>
</div>
</div>
<div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.ssl"></label>
<mat-slide-toggle color="primary" formControlName="ssl"></mat-slide-toggle>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.starttls"></label>
<mat-slide-toggle color="primary" formControlName="starttls"></mat-slide-toggle>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.auth"></label>
<mat-slide-toggle color="primary" formControlName="auth"></mat-slide-toggle>
</div>
<div
(click)="openAuthConfigDialog(true)"
*ngIf="smtpForm.get('auth').value"
class="link-action"
translate="general-config-screen.form.change-credentials"
></div>
</div>
</div>
<div class="dialog-actions">
<button
[disabled]="smtpForm.invalid || !smtpConfigurationChanged"
color="primary"
mat-flat-button
type="submit"
>
{{ 'general-config-screen.actions.save' | translate }}
</button>
<iqser-icon-button
(action)="testConnection()"
[disabled]="smtpForm.invalid"
[label]="'general-config-screen.actions.test-connection' | translate"
[type]="iconButtonTypes.dark"
></iqser-icon-button>
</div>
</form>
<redaction-smtp-form></redaction-smtp-form>
</div>
</div>
</div>

View File

@ -1,152 +1,13 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { IGeneralConfiguration, ISmtpConfiguration } from '@red/domain';
import { ConfigService } from '@services/config.service';
import { AutoUnsubscribe, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { Component } from '@angular/core';
import { UserService } from '@services/user.service';
import { GeneralSettingsService } from '@services/general-settings.service';
import { SmtpConfigService } from '../../services/smtp-config.service';
@Component({
selector: 'redaction-general-config-screen',
templateUrl: './general-config-screen.component.html',
styleUrls: ['./general-config-screen.component.scss'],
})
export class GeneralConfigScreenComponent extends AutoUnsubscribe implements OnInit, OnDestroy {
readonly iconButtonTypes = IconButtonTypes;
export class GeneralConfigScreenComponent {
readonly currentUser = this._userService.currentUser;
readonly configForm: FormGroup;
readonly smtpForm: FormGroup;
private _initialGeneralConfiguration: IGeneralConfiguration;
private _initialSMTPConfiguration: ISmtpConfiguration;
constructor(
private readonly _toaster: Toaster,
private readonly _userService: UserService,
private readonly _formBuilder: FormBuilder,
private readonly _loadingService: LoadingService,
private readonly _dialogService: AdminDialogService,
private readonly _configService: ConfigService,
private readonly _smtpConfigService: SmtpConfigService,
private readonly _generalSettingsService: GeneralSettingsService,
) {
super();
this.configForm = this._formBuilder.group({
forgotPasswordFunctionEnabled: [false],
auxiliaryName: [undefined],
});
this.smtpForm = this._formBuilder.group({
host: [undefined, Validators.required],
port: [25],
from: [undefined, [Validators.required, Validators.email]],
fromDisplayName: [undefined],
replyTo: [undefined],
replyToDisplayName: [undefined],
envelopeFrom: [undefined],
ssl: [false],
starttls: [false],
auth: [false],
user: [undefined],
password: [undefined],
});
this.addSubscription = this.smtpForm.controls.auth.valueChanges.subscribe(auth => {
if (auth) {
this.openAuthConfigDialog();
}
});
}
get smtpConfigurationChanged(): boolean {
if (!this._initialSMTPConfiguration) {
return true;
}
for (const key of Object.keys(this.smtpForm.getRawValue())) {
if (this._initialSMTPConfiguration[key] !== this.smtpForm.get(key).value) {
return true;
}
}
return false;
}
get generalConfigurationChanged(): boolean {
if (!this._initialGeneralConfiguration) {
return true;
}
for (const key of Object.keys(this.configForm.getRawValue())) {
if (this._initialGeneralConfiguration[key] !== this.configForm.get(key).value) {
return true;
}
}
return false;
}
async ngOnInit() {
await this._loadData();
}
async save() {
this._loadingService.start();
await this._smtpConfigService.updateSMTPConfiguration(this.smtpForm.getRawValue()).toPromise();
this._initialSMTPConfiguration = this.smtpForm.getRawValue();
this._loadingService.stop();
}
async saveGeneralConfig() {
this._loadingService.start();
const configFormValues = this.configForm.getRawValue();
await this._generalSettingsService.updateGeneralConfigurations(configFormValues).toPromise();
this._initialGeneralConfiguration = await this._generalSettingsService.getGeneralConfigurations().toPromise();
this._configService.updateDisplayName(this._initialGeneralConfiguration.displayName);
this._loadingService.stop();
}
openAuthConfigDialog(skipDisableOnCancel?: boolean) {
this._dialogService.openDialog('smtpAuthConfig', null, this.smtpForm.getRawValue(), null, authConfig => {
if (authConfig) {
this.smtpForm.patchValue(authConfig);
} else if (!skipDisableOnCancel) {
this.smtpForm.patchValue({ auth: false }, { emitEvent: false });
}
});
}
async testConnection() {
this._loadingService.start();
try {
await this._smtpConfigService.testSMTPConfiguration(this.smtpForm.getRawValue()).toPromise();
this._toaster.success(_('general-config-screen.test.success'));
} catch (e) {
this._toaster.error(_('general-config-screen.test.error'));
} finally {
this._loadingService.stop();
}
}
private async _loadData() {
this._loadingService.start();
try {
this._initialGeneralConfiguration = await this._generalSettingsService.getGeneralConfigurations().toPromise();
this.configForm.patchValue(this._initialGeneralConfiguration, { emitEvent: false });
} catch (e) {}
try {
this._initialSMTPConfiguration = await this._smtpConfigService.getCurrentSMTPConfiguration().toPromise();
this.smtpForm.patchValue(this._initialSMTPConfiguration, { emitEvent: false });
} catch (e) {}
this._loadingService.stop();
}
constructor(private readonly _userService: UserService) {}
}

View File

@ -0,0 +1,108 @@
<div class="dialog-header">
<div class="heading-l" translate="general-config-screen.title"></div>
<div translate="general-config-screen.subtitle"></div>
</div>
<form (submit)="save()" [formGroup]="form">
<div class="dialog-content">
<div class="dialog-content-left">
<div class="iqser-input-group required">
<label translate="general-config-screen.form.host"></label>
<input
formControlName="host"
name="host"
placeholder="{{ 'general-config-screen.form.host-placeholder' | translate }}"
type="text"
/>
</div>
<div class="iqser-input-group w-100">
<label translate="general-config-screen.form.port"></label>
<input formControlName="port" name="port" type="number" />
</div>
<div class="iqser-input-group required">
<label translate="general-config-screen.form.from"></label>
<input
formControlName="from"
name="from"
placeholder="{{ 'general-config-screen.form.from-placeholder' | translate }}"
type="email"
/>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.from-display-name"></label>
<input
formControlName="fromDisplayName"
name="fromDisplayName"
placeholder="{{ 'general-config-screen.form.from-display-name-placeholder' | translate }}"
type="text"
/>
<span class="hint" translate="general-config-screen.form.from-display-name-hint"></span>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.reply-to"></label>
<input
formControlName="replyTo"
name="replyTo"
placeholder="{{ 'general-config-screen.form.reply-to-placeholder' | translate }}"
type="text"
/>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.reply-to-display-name"></label>
<input
formControlName="replyToDisplayName"
name="replyToDisplayName"
placeholder="{{ 'general-config-screen.form.reply-to-display-name-placeholder' | translate }}"
type="text"
/>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.envelope-from"></label>
<input
formControlName="envelopeFrom"
name="envelopeFrom"
placeholder="{{ 'general-config-screen.form.envelope-from-placeholder' | translate }}"
type="text"
/>
<span class="hint" translate="general-config-screen.form.envelope-from-hint"></span>
</div>
</div>
<div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.ssl"></label>
<mat-slide-toggle color="primary" formControlName="ssl"></mat-slide-toggle>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.starttls"></label>
<mat-slide-toggle color="primary" formControlName="starttls"></mat-slide-toggle>
</div>
<div class="iqser-input-group">
<label translate="general-config-screen.form.auth"></label>
<mat-slide-toggle color="primary" formControlName="auth"></mat-slide-toggle>
</div>
<div
(click)="openAuthConfigDialog(true)"
*ngIf="form.get('auth').value"
class="link-action"
translate="general-config-screen.form.change-credentials"
></div>
</div>
</div>
<div class="dialog-actions">
<button [disabled]="form.invalid || !smtpConfigurationChanged" color="primary" mat-flat-button type="submit">
{{ 'general-config-screen.actions.save' | translate }}
</button>
<iqser-icon-button
(action)="testConnection()"
[disabled]="form.invalid"
[label]="'general-config-screen.actions.test-connection' | translate"
[type]="iconButtonTypes.dark"
></iqser-icon-button>
</div>
</form>

View File

@ -0,0 +1,108 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ISmtpConfiguration } from '@red/domain';
import { AutoUnsubscribe, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { AdminDialogService } from '../../../services/admin-dialog.service';
import { SmtpConfigService } from '../../../services/smtp-config.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@Component({
selector: 'redaction-smtp-form',
templateUrl: './smtp-form.component.html',
styleUrls: ['./smtp-form.component.scss'],
})
export class SmtpFormComponent extends AutoUnsubscribe implements OnInit, OnDestroy {
readonly iconButtonTypes = IconButtonTypes;
private _initialConfiguration: ISmtpConfiguration;
readonly form: FormGroup = this._getForm();
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _dialogService: AdminDialogService,
private readonly _smtpConfigService: SmtpConfigService,
private readonly _loadingService: LoadingService,
private readonly _toaster: Toaster,
) {
super();
this.addSubscription = this.form.controls.auth.valueChanges.subscribe(auth => {
if (auth) {
this.openAuthConfigDialog();
}
});
}
async ngOnInit(): Promise<void> {
await this._loadData();
}
private _getForm(): FormGroup {
return this._formBuilder.group({
host: [undefined, Validators.required],
port: [25],
from: [undefined, [Validators.required, Validators.email]],
fromDisplayName: [undefined],
replyTo: [undefined],
replyToDisplayName: [undefined],
envelopeFrom: [undefined],
ssl: [false],
starttls: [false],
auth: [false],
user: [undefined],
password: [undefined],
});
}
openAuthConfigDialog(skipDisableOnCancel?: boolean) {
this._dialogService.openDialog('smtpAuthConfig', null, this.form.getRawValue(), null, authConfig => {
if (authConfig) {
this.form.patchValue(authConfig);
} else if (!skipDisableOnCancel) {
this.form.patchValue({ auth: false }, { emitEvent: false });
}
});
}
async save() {
this._loadingService.start();
await this._smtpConfigService.updateSMTPConfiguration(this.form.getRawValue()).toPromise();
this._initialConfiguration = this.form.getRawValue();
this._loadingService.stop();
}
get smtpConfigurationChanged(): boolean {
if (!this._initialConfiguration) {
return true;
}
for (const key of Object.keys(this.form.getRawValue())) {
if (this._initialConfiguration[key] !== this.form.get(key).value) {
return true;
}
}
return false;
}
async testConnection() {
this._loadingService.start();
try {
await this._smtpConfigService.testSMTPConfiguration(this.form.getRawValue()).toPromise();
this._toaster.success(_('general-config-screen.test.success'));
} catch (e) {
this._toaster.error(_('general-config-screen.test.error'));
} finally {
this._loadingService.stop();
}
}
private async _loadData() {
this._loadingService.start();
try {
this._initialConfiguration = await this._smtpConfigService.getCurrentSMTPConfiguration().toPromise();
this.form.patchValue(this._initialConfiguration, { emitEvent: false });
} catch (e) {}
this._loadingService.stop();
}
}