Added Display Name General Config
This commit is contained in:
parent
334ef37a5c
commit
eb00732f2f
@ -1,11 +1,11 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserModule, Title } from '@angular/platform-browser';
|
||||
import { APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core';
|
||||
import { AppComponent } from './app.component';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http';
|
||||
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
|
||||
import { ApiModule } from '@redaction/red-ui-http';
|
||||
import { ApiModule, GeneralSettingsControllerService } from '@redaction/red-ui-http';
|
||||
import { ApiPathInterceptor } from '@utils/api-path-interceptor';
|
||||
import { MissingTranslationHandler, TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||
@ -30,6 +30,8 @@ import { BASE_HREF } from './tokens';
|
||||
import { MONACO_PATH, MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { GlobalErrorHandler } from '@utils/global-error-handler.service';
|
||||
import { REDMissingTranslationHandler } from '@utils/missing-translations-handler';
|
||||
import { configurationInitializer } from '@app-config/configuration.initializer';
|
||||
import { AppConfigService } from '@app-config/app-config.service';
|
||||
|
||||
export function httpLoaderFactory(httpClient: HttpClient) {
|
||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -47,14 +49,7 @@ function cleanupBaseUrl(baseUrl: string) {
|
||||
|
||||
const screens = [BaseScreenComponent, DownloadsListScreenComponent, UserProfileScreenComponent];
|
||||
|
||||
const components = [
|
||||
AppComponent,
|
||||
LogoComponent,
|
||||
AuthErrorComponent,
|
||||
ToastComponent,
|
||||
NotificationsComponent,
|
||||
...screens
|
||||
];
|
||||
const components = [AppComponent, LogoComponent, AuthErrorComponent, ToastComponent, NotificationsComponent, ...screens];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components],
|
||||
@ -108,6 +103,12 @@ const components = [
|
||||
useFactory: languageInitializer,
|
||||
deps: [LanguageService]
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
multi: true,
|
||||
useFactory: configurationInitializer,
|
||||
deps: [Title, AppConfigService, GeneralSettingsControllerService]
|
||||
},
|
||||
{
|
||||
provide: MONACO_PATH,
|
||||
useValue: 'https://unpkg.com/monaco-editor@0.24.0/min/vs'
|
||||
@ -126,11 +127,7 @@ export class AppModule {
|
||||
|
||||
private _configureKeyCloakRouteHandling() {
|
||||
this._route.queryParamMap.subscribe(queryParams => {
|
||||
if (
|
||||
queryParams.has('code') ||
|
||||
queryParams.has('state') ||
|
||||
queryParams.has('session_state')
|
||||
) {
|
||||
if (queryParams.has('code') || queryParams.has('state') || queryParams.has('session_state')) {
|
||||
this._router.navigate([], {
|
||||
queryParams: {
|
||||
state: null,
|
||||
|
||||
@ -14,9 +14,7 @@ export class FileStatusWrapper {
|
||||
this.searchField = fileStatus.filename;
|
||||
|
||||
if (fileAttributesConfig) {
|
||||
const primary = fileAttributesConfig.fileAttributeConfigs?.find(
|
||||
c => c.primaryAttribute
|
||||
);
|
||||
const primary = fileAttributesConfig.fileAttributeConfigs?.find(c => c.primaryAttribute);
|
||||
if (primary && fileStatus.fileAttributes?.attributeIdToValue) {
|
||||
this.primaryAttribute = fileStatus.fileAttributes?.attributeIdToValue[primary.id];
|
||||
this.searchField += ' ' + this.primaryAttribute;
|
||||
@ -120,15 +118,17 @@ export class FileStatusWrapper {
|
||||
}
|
||||
|
||||
get status() {
|
||||
return this.fileStatus.status === 'REPROCESS' || this.fileStatus.status === 'FULLREPROCESS'
|
||||
? 'PROCESSING'
|
||||
: this.fileStatus.status;
|
||||
return this.fileStatus.status === 'REPROCESS' || this.fileStatus.status === 'FULLREPROCESS' ? 'PROCESSING' : this.fileStatus.status;
|
||||
}
|
||||
|
||||
get numberOfPages() {
|
||||
return this.fileStatus.numberOfPages;
|
||||
}
|
||||
|
||||
get numberOfExcludedPages() {
|
||||
return this.fileStatus.excludedPages?.length || 0;
|
||||
}
|
||||
|
||||
get uploader() {
|
||||
return this.fileStatus.uploader;
|
||||
}
|
||||
|
||||
@ -16,10 +16,10 @@ import { LicenseInformationScreenComponent } from './screens/license-information
|
||||
import { DigitalSignatureScreenComponent } from './screens/digital-signature/digital-signature-screen.component';
|
||||
import { AuditScreenComponent } from './screens/audit/audit-screen.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SmtpConfigScreenComponent } from './screens/smtp-config/smtp-config-screen.component';
|
||||
import { ReportsScreenComponent } from './screens/reports/reports-screen.component';
|
||||
import { DossierAttributesListingScreenComponent } from './screens/dossier-attributes-listing/dossier-attributes-listing-screen.component';
|
||||
import { TrashScreenComponent } from './screens/trash/trash-screen.component';
|
||||
import { GeneralConfigScreenComponent } from './screens/general-config/general-config-screen.component';
|
||||
|
||||
const routes = [
|
||||
{ path: '', redirectTo: 'dossier-templates', pathMatch: 'full' },
|
||||
@ -154,8 +154,8 @@ const routes = [
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'smtp-config',
|
||||
component: SmtpConfigScreenComponent,
|
||||
path: 'general-config',
|
||||
component: GeneralConfigScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard],
|
||||
|
||||
@ -27,7 +27,7 @@ export class AdminSideNavComponent {
|
||||
{ screen: 'license-info', label: 'license-information', onlyAdmin: true },
|
||||
{ screen: 'audit', onlyAdmin: true },
|
||||
{ screen: 'users', label: 'user-management', userManagerOnly: true },
|
||||
{ screen: 'smtp-config', label: 'configurations', onlyAdmin: true }
|
||||
{ screen: 'general-config', label: 'configurations', onlyAdmin: true }
|
||||
],
|
||||
'dossier-templates': [
|
||||
{ screen: 'dictionaries' },
|
||||
|
||||
@ -24,7 +24,7 @@ import { EditColorDialogComponent } from './dialogs/edit-color-dialog/edit-color
|
||||
import { ComboChartComponent, ComboSeriesVerticalComponent } from './components/combo-chart';
|
||||
import { NgxChartsModule } from '@swimlane/ngx-charts';
|
||||
import { AdminDialogService } from './services/admin-dialog.service';
|
||||
import { SmtpConfigScreenComponent } from './screens/smtp-config/smtp-config-screen.component';
|
||||
import { GeneralConfigScreenComponent } from './screens/general-config/general-config-screen.component';
|
||||
import { SmtpAuthDialogComponent } from './dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||
import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
|
||||
@ -65,7 +65,7 @@ const screens = [
|
||||
LicenseInformationScreenComponent,
|
||||
UserListingScreenComponent,
|
||||
WatermarkScreenComponent,
|
||||
SmtpConfigScreenComponent,
|
||||
GeneralConfigScreenComponent,
|
||||
ReportsScreenComponent,
|
||||
DossierAttributesListingScreenComponent,
|
||||
TrashScreenComponent
|
||||
|
||||
@ -0,0 +1,181 @@
|
||||
<section class="settings">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<redaction-admin-side-nav type="settings"></redaction-admin-side-nav>
|
||||
|
||||
<div>
|
||||
<div class="page-header">
|
||||
<div class="breadcrumb" translate="configurations"></div>
|
||||
|
||||
<div class="actions">
|
||||
<redaction-circle-button
|
||||
*ngIf="permissionsService.isUser()"
|
||||
class="ml-6"
|
||||
icon="red:close"
|
||||
redactionNavigateLastDossiersScreen
|
||||
tooltip="common.close"
|
||||
tooltipPosition="below"
|
||||
></redaction-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="red-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="red-input-group">
|
||||
<label translate="general-config-screen.app-name.label"></label>
|
||||
<input
|
||||
formControlName="displayName"
|
||||
name="displayName"
|
||||
placeholder="{{ 'general-config-screen.app-name.placeholder' | translate }}"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="inline-input-group flex-align-items-center">
|
||||
<mat-slide-toggle formControlName="forgotPasswordFunctionEnabled" color="primary"></mat-slide-toggle>
|
||||
<span class="ml-8" translate="general-config-screen.general.form.forgot-password"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<button
|
||||
type="submit"
|
||||
[disabled]="configForm.invalid || !generalConfigurationChanged"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
>
|
||||
{{ 'general-config-screen.actions.save' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</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="red-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="red-input-group w-100">
|
||||
<label translate="general-config-screen.form.port"></label>
|
||||
<input formControlName="port" name="port" type="number" />
|
||||
</div>
|
||||
|
||||
<div class="red-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="red-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="red-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="red-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="red-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="red-input-group">
|
||||
<label translate="general-config-screen.form.ssl"></label>
|
||||
<mat-slide-toggle color="primary" formControlName="ssl"></mat-slide-toggle>
|
||||
</div>
|
||||
<div class="red-input-group">
|
||||
<label translate="general-config-screen.form.starttls"></label>
|
||||
<mat-slide-toggle color="primary" formControlName="starttls"></mat-slide-toggle>
|
||||
</div>
|
||||
<div class="red-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>
|
||||
|
||||
<redaction-icon-button
|
||||
(action)="testConnection()"
|
||||
[disabled]="smtpForm.invalid"
|
||||
text="general-config-screen.actions.test-connection"
|
||||
type="show-bg"
|
||||
></redaction-icon-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-full-page-loading-indicator [displayed]="!viewReady"></redaction-full-page-loading-indicator>
|
||||
@ -21,6 +21,7 @@
|
||||
height: 38px;
|
||||
border-radius: 4px;
|
||||
padding: 1px 11px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.dialog {
|
||||
@ -0,0 +1,150 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {PermissionsService} from '@services/permissions.service';
|
||||
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
|
||||
import {AdminDialogService} from '../../services/admin-dialog.service';
|
||||
import {
|
||||
GeneralConfigurationModel,
|
||||
GeneralSettingsControllerService,
|
||||
SmtpConfigurationControllerService,
|
||||
SMTPConfigurationModel
|
||||
} from '@redaction/red-ui-http';
|
||||
import {AppConfigService} from '../../../app-config/app-config.service';
|
||||
import {AutoUnsubscribeComponent} from "../../../shared/base/auto-unsubscribe.component";
|
||||
import {Toaster} from "../../../../services/toaster.service";
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-general-config-screen',
|
||||
templateUrl: './general-config-screen.component.html',
|
||||
styleUrls: ['./general-config-screen.component.scss']
|
||||
})
|
||||
export class GeneralConfigScreenComponent extends AutoUnsubscribeComponent implements OnInit {
|
||||
viewReady = false;
|
||||
configForm: FormGroup;
|
||||
smtpForm: FormGroup;
|
||||
|
||||
private _initialGeneralConfiguration: GeneralConfigurationModel;
|
||||
private _initialSMTPConfiguration: SMTPConfigurationModel;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _smtpConfigService: SmtpConfigurationControllerService,
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _generalSettingsControllerService: GeneralSettingsControllerService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.configForm = this._formBuilder.group({
|
||||
forgotPasswordFunctionEnabled: [false],
|
||||
displayName: [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.configForm.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.viewReady = false;
|
||||
await this._smtpConfigService.updateSMTPConfiguration(this.smtpForm.getRawValue()).toPromise();
|
||||
this._initialSMTPConfiguration = this.smtpForm.getRawValue();
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
async saveGeneralConfig() {
|
||||
this.viewReady = false;
|
||||
|
||||
const configFormValues = this.configForm.getRawValue();
|
||||
configFormValues.displayName = configFormValues.displayName || 'RedactManager';
|
||||
|
||||
await this._generalSettingsControllerService.updateGeneralConfigurations(configFormValues).toPromise();
|
||||
this._appConfigService.updateDisplayName(configFormValues.displayName);
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
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.viewReady = false;
|
||||
try {
|
||||
await this._smtpConfigService.testSMTPConfiguration(this.smtpForm.getRawValue()).toPromise();
|
||||
this._toaster.success('smtp-config-screen.test.success');
|
||||
} catch (e) {
|
||||
this._toaster.error('smtp-config-screen.test.error');
|
||||
} finally {
|
||||
this.viewReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
this._initialGeneralConfiguration = await this._generalSettingsControllerService.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.viewReady = true;
|
||||
}
|
||||
}
|
||||
@ -1,213 +0,0 @@
|
||||
<section class="settings">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<redaction-admin-side-nav type="settings"></redaction-admin-side-nav>
|
||||
|
||||
<div>
|
||||
<div class="page-header">
|
||||
<div class="breadcrumb" translate="configurations"></div>
|
||||
|
||||
<div class="actions">
|
||||
<redaction-circle-button
|
||||
*ngIf="permissionsService.isUser()"
|
||||
class="ml-6"
|
||||
icon="red:close"
|
||||
redactionNavigateLastDossiersScreen
|
||||
tooltip="common.close"
|
||||
tooltipPosition="below"
|
||||
></redaction-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="red-content-inner">
|
||||
<div class="content-container">
|
||||
<div class="dialog mb-8">
|
||||
<div class="dialog-header">
|
||||
<div class="heading-l" translate="smtp-config-screen.general.title"></div>
|
||||
<div translate="smtp-config-screen.general.subtitle"></div>
|
||||
</div>
|
||||
<div class="dialog-content">
|
||||
<div class="inline-input-group flex-align-items-center">
|
||||
<mat-slide-toggle
|
||||
[(ngModel)]="generalSettings.forgotPasswordFunctionEnabled"
|
||||
color="primary"
|
||||
></mat-slide-toggle>
|
||||
<span
|
||||
class="ml-8"
|
||||
translate="smtp-config-screen.general.form.forgot-password"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<button
|
||||
(click)="saveGeneralConfig()"
|
||||
[disabled]="!generalConfigChanged"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
type="submit"
|
||||
>
|
||||
{{ 'smtp-config-screen.actions.save' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog mt-16">
|
||||
<div class="dialog-header">
|
||||
<div class="heading-l" translate="smtp-config-screen.title"></div>
|
||||
<div translate="smtp-config-screen.subtitle"></div>
|
||||
</div>
|
||||
<form (submit)="save()" [formGroup]="configForm">
|
||||
<div class="dialog-content">
|
||||
<div class="dialog-content-left">
|
||||
<div class="red-input-group required">
|
||||
<label translate="smtp-config-screen.form.host"></label>
|
||||
<input
|
||||
formControlName="host"
|
||||
name="host"
|
||||
placeholder="{{
|
||||
'smtp-config-screen.form.host-placeholder' | translate
|
||||
}}"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group w-100">
|
||||
<label translate="smtp-config-screen.form.port"></label>
|
||||
<input formControlName="port" name="port" type="number" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required">
|
||||
<label translate="smtp-config-screen.form.from"></label>
|
||||
<input
|
||||
formControlName="from"
|
||||
name="from"
|
||||
placeholder="{{
|
||||
'smtp-config-screen.form.from-placeholder' | translate
|
||||
}}"
|
||||
type="email"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<label
|
||||
translate="smtp-config-screen.form.from-display-name"
|
||||
></label>
|
||||
<input
|
||||
formControlName="fromDisplayName"
|
||||
name="fromDisplayName"
|
||||
placeholder="{{
|
||||
'smtp-config-screen.form.from-display-name-placeholder'
|
||||
| translate
|
||||
}}"
|
||||
type="text"
|
||||
/>
|
||||
<span
|
||||
class="hint"
|
||||
translate="smtp-config-screen.form.from-display-name-hint"
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<label translate="smtp-config-screen.form.reply-to"></label>
|
||||
<input
|
||||
formControlName="replyTo"
|
||||
name="replyTo"
|
||||
placeholder="{{
|
||||
'smtp-config-screen.form.reply-to-placeholder'
|
||||
| translate
|
||||
}}"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<label
|
||||
translate="smtp-config-screen.form.reply-to-display-name"
|
||||
></label>
|
||||
<input
|
||||
formControlName="replyToDisplayName"
|
||||
name="replyToDisplayName"
|
||||
placeholder="{{
|
||||
'smtp-config-screen.form.reply-to-display-name-placeholder'
|
||||
| translate
|
||||
}}"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<label
|
||||
translate="smtp-config-screen.form.envelope-from"
|
||||
></label>
|
||||
<input
|
||||
formControlName="envelopeFrom"
|
||||
name="envelopeFrom"
|
||||
placeholder="{{
|
||||
'smtp-config-screen.form.envelope-from-placeholder'
|
||||
| translate
|
||||
}}"
|
||||
type="text"
|
||||
/>
|
||||
<span
|
||||
class="hint"
|
||||
translate="smtp-config-screen.form.envelope-from-hint"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="red-input-group">
|
||||
<label translate="smtp-config-screen.form.ssl"></label>
|
||||
<mat-slide-toggle
|
||||
color="primary"
|
||||
formControlName="ssl"
|
||||
></mat-slide-toggle>
|
||||
</div>
|
||||
<div class="red-input-group">
|
||||
<label translate="smtp-config-screen.form.starttls"></label>
|
||||
<mat-slide-toggle
|
||||
color="primary"
|
||||
formControlName="starttls"
|
||||
></mat-slide-toggle>
|
||||
</div>
|
||||
<div class="red-input-group">
|
||||
<label translate="smtp-config-screen.form.auth"></label>
|
||||
<mat-slide-toggle
|
||||
color="primary"
|
||||
formControlName="auth"
|
||||
></mat-slide-toggle>
|
||||
</div>
|
||||
<div
|
||||
(click)="openAuthConfigDialog(true)"
|
||||
*ngIf="configForm.get('auth').value"
|
||||
class="link-action"
|
||||
translate="smtp-config-screen.form.change-credentials"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<button
|
||||
[disabled]="configForm.invalid || !changed"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
type="submit"
|
||||
>
|
||||
{{ 'smtp-config-screen.actions.save' | translate }}
|
||||
</button>
|
||||
|
||||
<redaction-icon-button
|
||||
(action)="testConnection()"
|
||||
[disabled]="configForm.invalid"
|
||||
text="smtp-config-screen.actions.test-connection"
|
||||
type="show-bg"
|
||||
></redaction-icon-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-full-page-loading-indicator
|
||||
[displayed]="!viewReady"
|
||||
></redaction-full-page-loading-indicator>
|
||||
@ -1,130 +0,0 @@
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import {
|
||||
GeneralConfigurationModel,
|
||||
GeneralSettingsControllerService,
|
||||
SmtpConfigurationControllerService,
|
||||
SMTPConfigurationModel
|
||||
} from '@redaction/red-ui-http';
|
||||
import { Toaster } from '../../../../services/toaster.service';
|
||||
import { AutoUnsubscribeComponent } from '../../../shared/base/auto-unsubscribe.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-smtp-config-screen',
|
||||
templateUrl: './smtp-config-screen.component.html',
|
||||
styleUrls: ['./smtp-config-screen.component.scss']
|
||||
})
|
||||
export class SmtpConfigScreenComponent extends AutoUnsubscribeComponent implements OnInit, OnDestroy {
|
||||
viewReady = false;
|
||||
configForm: FormGroup;
|
||||
generalSettings: GeneralConfigurationModel = {
|
||||
forgotPasswordFunctionEnabled: false
|
||||
};
|
||||
|
||||
private _initialGeneralSettings: GeneralConfigurationModel;
|
||||
private _initialValue: SMTPConfigurationModel;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _smtpConfigService: SmtpConfigurationControllerService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _generalSettingsControllerService: GeneralSettingsControllerService
|
||||
) {
|
||||
super();
|
||||
this.configForm = _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.configForm.controls.auth.valueChanges.subscribe(auth => {
|
||||
if (auth) {
|
||||
this.openAuthConfigDialog();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
if (!this._initialValue) return true;
|
||||
|
||||
for (const key of Object.keys(this.configForm.getRawValue())) {
|
||||
if (this._initialValue[key] !== this.configForm.get(key).value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get generalConfigChanged(): boolean {
|
||||
if (!this._initialGeneralSettings) return false;
|
||||
|
||||
const toBool = key => this.generalSettings[key] !== this._initialGeneralSettings[key];
|
||||
const changes = Object.keys(this.generalSettings).map(toBool);
|
||||
return changes.filter(value => value).length > 0;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this._loadData();
|
||||
this.generalSettings = await this._generalSettingsControllerService.getGeneralConfigurations().toPromise();
|
||||
this._initialGeneralSettings = Object.assign({}, this.generalSettings);
|
||||
}
|
||||
|
||||
async save() {
|
||||
this.viewReady = false;
|
||||
await this._smtpConfigService.updateSMTPConfiguration(this.configForm.getRawValue()).toPromise();
|
||||
this._initialValue = this.configForm.getRawValue();
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
async saveGeneralConfig() {
|
||||
this.viewReady = false;
|
||||
await this._generalSettingsControllerService.updateGeneralConfigurations(this.generalSettings).toPromise();
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
openAuthConfigDialog(skipDisableOnCancel?: boolean) {
|
||||
this._dialogService.openDialog('smtpAuthConfig', null, this.configForm.getRawValue(), null, authConfig => {
|
||||
if (authConfig) {
|
||||
this.configForm.patchValue(authConfig);
|
||||
} else if (!skipDisableOnCancel) {
|
||||
this.configForm.patchValue({ auth: false }, { emitEvent: false });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async testConnection() {
|
||||
this.viewReady = false;
|
||||
try {
|
||||
await this._smtpConfigService.testSMTPConfiguration(this.configForm.getRawValue()).toPromise();
|
||||
this._toaster.success('smtp-config-screen.test.success');
|
||||
} catch (e) {
|
||||
this._toaster.error('smtp-config-screen.test.error');
|
||||
} finally {
|
||||
this.viewReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
this._initialValue = await this._smtpConfigService.getCurrentSMTPConfiguration().toPromise();
|
||||
this.configForm.patchValue(this._initialValue, { emitEvent: false });
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this.viewReady = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,35 +50,33 @@ export class AppConfigService {
|
||||
}
|
||||
|
||||
loadAppConfig(): Observable<any> {
|
||||
this._cacheApiService
|
||||
.getCachedValue(AppConfigKey.FRONTEND_APP_VERSION)
|
||||
.then(async lastVersion => {
|
||||
console.log(
|
||||
'[REDACTION] Last app version: ',
|
||||
lastVersion,
|
||||
' current version ',
|
||||
this.version
|
||||
);
|
||||
if (lastVersion !== this.version) {
|
||||
console.log('[REDACTION] Version-missmatch - wiping caches!');
|
||||
await wipeCaches();
|
||||
}
|
||||
await this._cacheApiService.cacheValue(
|
||||
AppConfigKey.FRONTEND_APP_VERSION,
|
||||
this.version
|
||||
);
|
||||
});
|
||||
this._cacheApiService.getCachedValue(AppConfigKey.FRONTEND_APP_VERSION).then(async lastVersion => {
|
||||
console.log('[REDACTION] Last app version: ', lastVersion, ' current version ', this.version);
|
||||
if (lastVersion !== this.version) {
|
||||
console.log('[REDACTION] Version-missmatch - wiping caches!');
|
||||
await wipeCaches();
|
||||
}
|
||||
await this._cacheApiService.cacheValue(AppConfigKey.FRONTEND_APP_VERSION, this.version);
|
||||
});
|
||||
|
||||
return this._httpClient.get<any>('/assets/config/config.json').pipe(
|
||||
tap(config => {
|
||||
console.log('[REDACTION] Started with config: ', config);
|
||||
this._config = config;
|
||||
this._config[AppConfigKey.FRONTEND_APP_VERSION] = this.version;
|
||||
this._titleService.setTitle(this.getConfig(AppConfigKey.APP_NAME, 'DDA-R'));
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
updateDisplayName(name: string) {
|
||||
this.setConfig(AppConfigKey.APP_NAME, name);
|
||||
this._titleService.setTitle(this.getConfig(AppConfigKey.APP_NAME, 'RedactManager'));
|
||||
}
|
||||
|
||||
setConfig(key: AppConfigKey, value: any) {
|
||||
this._config[key] = value;
|
||||
}
|
||||
|
||||
getConfig(key: AppConfigKey | string, defaultValue?: any) {
|
||||
return this._config[key] ? this._config[key] : defaultValue;
|
||||
}
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
import { GeneralSettingsControllerService } from '@redaction/red-ui-http';
|
||||
import { catchError, mergeMap, take, tap } from 'rxjs/operators';
|
||||
import { AppConfigService } from './app-config.service';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { APP_BOOTSTRAPPED } from '../bootstrap/app-bootstrap';
|
||||
import { of } from 'rxjs';
|
||||
|
||||
export function configurationInitializer(
|
||||
title: Title,
|
||||
appConfigService: AppConfigService,
|
||||
generalSettingsControllerService: GeneralSettingsControllerService
|
||||
) {
|
||||
return () =>
|
||||
APP_BOOTSTRAPPED.pipe(
|
||||
mergeMap(() =>
|
||||
generalSettingsControllerService.getGeneralConfigurations().pipe(
|
||||
tap(configuration => {
|
||||
appConfigService.updateDisplayName(configuration.displayName);
|
||||
})
|
||||
)
|
||||
),
|
||||
catchError(() => {
|
||||
title.setTitle('RedactManager');
|
||||
return of({});
|
||||
}),
|
||||
take(1)
|
||||
).toPromise();
|
||||
}
|
||||
@ -6,12 +6,9 @@ import { AppConfigModule } from '@app-config/app-config.module';
|
||||
import { KeycloakAngularModule, KeycloakOptions, KeycloakService } from 'keycloak-angular';
|
||||
import { AppConfigKey, AppConfigService } from '@app-config/app-config.service';
|
||||
import { BASE_HREF } from '../../tokens';
|
||||
import { APP_BOOTSTRAPPED } from '../bootstrap/app-bootstrap';
|
||||
|
||||
export function keycloakInitializer(
|
||||
keycloak: KeycloakService,
|
||||
appConfigService: AppConfigService,
|
||||
baseUrl
|
||||
) {
|
||||
export function keycloakInitializer(keycloak: KeycloakService, appConfigService: AppConfigService, baseUrl) {
|
||||
return () =>
|
||||
appConfigService
|
||||
.loadAppConfig()
|
||||
@ -30,15 +27,15 @@ export function keycloakInitializer(
|
||||
initOptions: {
|
||||
checkLoginIframe: false,
|
||||
onLoad: 'check-sso',
|
||||
silentCheckSsoRedirectUri:
|
||||
window.location.origin + baseUrl + '/assets/oauth/silent-refresh.html',
|
||||
silentCheckSsoRedirectUri: window.location.origin + baseUrl + '/assets/oauth/silent-refresh.html',
|
||||
flow: 'standard'
|
||||
},
|
||||
enableBearerInterceptor: true
|
||||
};
|
||||
return keycloak
|
||||
.init(options)
|
||||
.then(() => configureAutomaticRedirectToLoginScreen(keycloak));
|
||||
.then(() => configureAutomaticRedirectToLoginScreen(keycloak))
|
||||
.then(() => APP_BOOTSTRAPPED.next(true));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
3
apps/red-ui/src/app/modules/bootstrap/app-bootstrap.ts
Normal file
3
apps/red-ui/src/app/modules/bootstrap/app-bootstrap.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import { ReplaySubject } from 'rxjs';
|
||||
|
||||
export const APP_BOOTSTRAPPED = new ReplaySubject<boolean>();
|
||||
@ -106,7 +106,7 @@
|
||||
|
||||
<cdk-virtual-scroll-viewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let fileStatus of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
*cdkVirtualFor="let fileStatus of sortedDisplayedEntities$ | async ; trackBy: trackByPrimaryKey"
|
||||
[class.disabled]="fileStatus.isExcluded"
|
||||
[class.last-opened]="isLastOpenedFile(fileStatus)"
|
||||
[class.pointer]="permissionsService.canOpenFile(fileStatus)"
|
||||
@ -136,8 +136,20 @@
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="fileStatus.ocrTime" class="small-label stats-subtitle">
|
||||
<div [matTooltipPosition]="'above'" [matTooltip]="'dossier-overview.ocr-performed' | translate">
|
||||
<div class="small-label stats-subtitle">
|
||||
<div>
|
||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||
{{ fileStatus.numberOfPages }}
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:exclude-pages"></mat-icon>
|
||||
{{ fileStatus.numberOfExcludedPages }}
|
||||
</div>
|
||||
<div
|
||||
*ngIf="fileStatus.ocrTime"
|
||||
[matTooltipPosition]="'above'"
|
||||
[matTooltip]="'dossier-overview.ocr-performed' | translate"
|
||||
>
|
||||
<mat-icon svgIcon="red:ocr"></mat-icon>
|
||||
{{ fileStatus.ocrTime | date: 'mediumDate' }}
|
||||
</div>
|
||||
|
||||
@ -1024,7 +1024,7 @@
|
||||
},
|
||||
"title": "Aktivieren Sie die Authentifizierung"
|
||||
},
|
||||
"smtp-config-screen": {
|
||||
"general-config-screen": {
|
||||
"actions": {
|
||||
"save": "Konfigurationen speichern",
|
||||
"test-connection": "Testverbindung"
|
||||
|
||||
@ -1244,11 +1244,15 @@
|
||||
},
|
||||
"title": "Enable Authentication"
|
||||
},
|
||||
"smtp-config-screen": {
|
||||
"general-config-screen": {
|
||||
"actions": {
|
||||
"save": "Save Configurations",
|
||||
"test-connection": "Test Connection"
|
||||
},
|
||||
"app-name": {
|
||||
"label": "Application Name",
|
||||
"placeholder": "RedactManager"
|
||||
},
|
||||
"form": {
|
||||
"auth": "Enable Authentication",
|
||||
"change-credentials": "Change Credentials",
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
OAUTH_CLIENT_ID="${OAUTH_CLIENT_ID:-gin-client}"
|
||||
OAUTH_URL="${OAUTH_URL:-https://keycloak-dev.iqser.cloud/auth/realms/dev}"
|
||||
APP_NAME="${APP_NAME:-DDA-R}"
|
||||
API_URL="${API_URL:-}"
|
||||
OAUTH_IDP_HINT="${OAUTH_IDP_HINT:-}"
|
||||
ADMIN_CONTACT_NAME="${ADMIN_CONTACT_NAME:-}"
|
||||
@ -34,7 +33,6 @@ echo '{
|
||||
"LICENSE_PAGE_COUNT":'"$LICENSE_PAGE_COUNT"',
|
||||
"LICENSE_CUSTOMER":"'"$LICENSE_CUSTOMER"'",
|
||||
"LICENSE_EMAIL":"'"$LICENSE_EMAIL"'",
|
||||
"APP_NAME":"'"$APP_NAME"'",
|
||||
"AUTO_READ_TIME":'"$AUTO_READ_TIME"',
|
||||
"SELECTION_MODE":"'"$SELECTION_MODE"'",
|
||||
"MAX_FILE_SIZE_MB":"'"$MAX_FILE_SIZE_MB"'",
|
||||
|
||||
@ -12,4 +12,5 @@
|
||||
|
||||
export interface GeneralConfigurationModel {
|
||||
forgotPasswordFunctionEnabled?: boolean;
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user