diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 3fa8395fb..3a7379112 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -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, TranslateCompiler, TranslateLoader, TranslateModule } from '@ngx-translate/core'; import { TranslateHttpLoader } from '@ngx-translate/http-loader'; @@ -31,6 +31,8 @@ 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 { TranslateMessageFormatCompiler } from 'ngx-translate-messageformat-compiler'; +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'); @@ -106,6 +108,12 @@ const components = [AppComponent, LogoComponent, AuthErrorComponent, ToastCompon 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' diff --git a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts index 2a0ff2dfc..fad82258c 100644 --- a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts +++ b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts @@ -28,7 +28,7 @@ export class DownloadsListScreenComponent implements OnInit { deleteItem(download: DownloadStatusWrapper) { this._downloadControllerService - .deleteDownload({ storageId: download.storageId }) + .deleteDownload({ storageIds: [download.storageId] }) .subscribe(() => this.fileDownloadService.getDownloadStatus().subscribe()); } } diff --git a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.html b/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.html index acd38e4a6..779d9a35d 100644 --- a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.html +++ b/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.html @@ -48,5 +48,3 @@ - - diff --git a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts b/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts index 79a60257a..6816cf6c2 100644 --- a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts +++ b/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts @@ -8,6 +8,7 @@ import { UserControllerService } from '@redaction/red-ui-http'; import { AppConfigKey, AppConfigService } from '@app-config/app-config.service'; import { DomSanitizer } from '@angular/platform-browser'; import { languagesTranslations } from '../../translations/languages-translations'; +import { LoadingService } from '@services/loading.service'; @Component({ selector: 'redaction-user-profile-screen', @@ -15,7 +16,6 @@ import { languagesTranslations } from '../../translations/languages-translations styleUrls: ['./user-profile-screen.component.scss'] }) export class UserProfileScreenComponent implements OnInit { - viewReady = false; formGroup: FormGroup; changePasswordUrl: any; translations = languagesTranslations; @@ -30,8 +30,10 @@ export class UserProfileScreenComponent implements OnInit { private readonly _userControllerService: UserControllerService, private readonly _languageService: LanguageService, private readonly _domSanitizer: DomSanitizer, - private readonly _translateService: TranslateService + private readonly _translateService: TranslateService, + private readonly _loadingService: LoadingService ) { + this._loadingService.start(); this.formGroup = this._formBuilder.group({ email: [undefined, [Validators.required, Validators.email]], firstName: [undefined], @@ -70,7 +72,7 @@ export class UserProfileScreenComponent implements OnInit { } async save(): Promise { - this.viewReady = false; + this._loadingService.start(); if (this.languageChanged) { await this._languageService.changeLanguage(this.formGroup.get('language').value); @@ -108,7 +110,7 @@ export class UserProfileScreenComponent implements OnInit { this.formGroup.patchValue(this._profileModel, { emitEvent: false }); } catch (e) { } finally { - this.viewReady = true; + this._loadingService.stop(); } } } diff --git a/apps/red-ui/src/app/models/file/dossier-template-model.wrapper.ts b/apps/red-ui/src/app/models/file/dossier-template-model.wrapper.ts index 8fcfada48..d1889902f 100644 --- a/apps/red-ui/src/app/models/file/dossier-template-model.wrapper.ts +++ b/apps/red-ui/src/app/models/file/dossier-template-model.wrapper.ts @@ -38,8 +38,8 @@ export class DossierTemplateModelWrapper { return this.dossierTemplateModel.name; } - get reportTypes() { - return this.dossierTemplateModel.reportTypes; + get reportTemplateIds() { + return this.dossierTemplateModel.reportTemplateIds; } get validFrom() { diff --git a/apps/red-ui/src/app/models/file/file-status.wrapper.ts b/apps/red-ui/src/app/models/file/file-status.wrapper.ts index 4fbb4c662..34cfff788 100644 --- a/apps/red-ui/src/app/models/file/file-status.wrapper.ts +++ b/apps/red-ui/src/app/models/file/file-status.wrapper.ts @@ -125,6 +125,10 @@ export class FileStatusWrapper { return this.fileStatus.numberOfPages; } + get numberOfExcludedPages() { + return this.fileStatus.excludedPages?.length || 0; + } + get uploader() { return this.fileStatus.uploader; } diff --git a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts index 4006ca91b..bbb30cec2 100644 --- a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts @@ -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], diff --git a/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts b/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts index 030bc6c5f..d51cba474 100644 --- a/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts +++ b/apps/red-ui/src/app/modules/admin/admin-side-nav/admin-side-nav.component.ts @@ -32,7 +32,7 @@ export class AdminSideNavComponent { { screen: 'license-info', label: _('license-information'), onlyAdmin: true }, { screen: 'audit', label: _('audit'), onlyAdmin: true }, { screen: 'users', label: _('user-management'), userManagerOnly: true }, - { screen: 'smtp-config', label: _('configurations'), onlyAdmin: true } + { screen: 'general-config', label: _('configurations'), onlyAdmin: true } ], dossierTemplates: [ { screen: 'dictionaries', label: _('dictionaries') }, @@ -41,7 +41,7 @@ export class AdminSideNavComponent { { screen: 'watermark', label: _('watermark') }, { screen: 'file-attributes', label: _('file-attributes') }, { screen: 'dossier-attributes', label: _('dossier-attributes') }, - { screen: 'reports', label: _('reports'), onlyDevMode: true } + { screen: 'reports', label: _('reports') } ] }; diff --git a/apps/red-ui/src/app/modules/admin/admin.module.ts b/apps/red-ui/src/app/modules/admin/admin.module.ts index e3faf2cc2..e3cdbee28 100644 --- a/apps/red-ui/src/app/modules/admin/admin.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin.module.ts @@ -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 diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.html index 8b5e73dd5..acf8f461f 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.html @@ -72,24 +72,28 @@

{{ 'download-includes' | translate }}

+ + + + {{ option.fileName }} + diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts index 82d40eac0..3cdb65db1 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts @@ -1,12 +1,17 @@ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, OnInit } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import * as moment from 'moment'; import { Moment } from 'moment'; -import { Dossier, DossierTemplateControllerService, DossierTemplateModel } from '@redaction/red-ui-http'; +import { + Dossier, + DossierTemplateControllerService, + DossierTemplateModel, + ReportTemplate, + ReportTemplateControllerService +} from '@redaction/red-ui-http'; import { applyIntervalConstraints } from '@utils/date-inputs-utils'; -import { reportTypesTranslations } from '../../../../translations/report-types-translations'; import { downloadTypesTranslations } from '../../../../translations/download-types-translations'; @Component({ @@ -14,7 +19,7 @@ import { downloadTypesTranslations } from '../../../../translations/download-typ templateUrl: './add-edit-dossier-template-dialog.component.html', styleUrls: ['./add-edit-dossier-template-dialog.component.scss'] }) -export class AddEditDossierTemplateDialogComponent { +export class AddEditDossierTemplateDialogComponent implements OnInit { dossierTemplateForm: FormGroup; hasValidFrom: boolean; hasValidTo: boolean; @@ -23,19 +28,18 @@ export class AddEditDossierTemplateDialogComponent { key: type, label: downloadTypesTranslations[type] })); - reportTypesEnum = Object.values(DossierTemplateModel.ReportTypesEnum); - reportTypes: { key: DossierTemplateModel.ReportTypesEnum; label: string }[] = this.reportTypesEnum.map(type => ({ - key: type, - label: reportTypesTranslations[type] - })); + availableReportTypes: ReportTemplate[] = []; private _previousValidFrom: Moment; private _previousValidTo: Moment; + reportTemplateValueMapper = (reportTemplate: ReportTemplate) => reportTemplate.templateId; + constructor( private readonly _appStateService: AppStateService, private readonly _formBuilder: FormBuilder, private readonly _dossierTemplateController: DossierTemplateControllerService, + private readonly _reportTemplateController: ReportTemplateControllerService, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public dossierTemplate: DossierTemplateModel ) { @@ -50,13 +54,8 @@ export class AddEditDossierTemplateDialogComponent { this.dossierTemplate?.validTo ? moment(this.dossierTemplate?.validTo) : null, this._requiredIfValidator(() => this.hasValidTo) ], - downloadFileTypes: [this.dossierTemplate ? this.dossierTemplate.downloadFileTypes : ['PREVIEW', 'REDACTED']], - reportTypes: [ - this.dossierTemplate - ? this.dossierTemplate.reportTypes - : ['WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE', 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE', 'EXCEL_MULTI_FILE'], - Validators.required - ] + downloadFileTypes: [this.dossierTemplate?.downloadFileTypes || ['PREVIEW', 'REDACTED']], + reportTemplateIds: [this.dossierTemplate?.reportTemplateIds || [], Validators.required] }); this.hasValidFrom = !!this.dossierTemplate?.validFrom; this.hasValidTo = !!this.dossierTemplate?.validTo; @@ -69,6 +68,11 @@ export class AddEditDossierTemplateDialogComponent { }); } + async ngOnInit() { + this.availableReportTypes = + (await this._reportTemplateController.getAvailableReportTemplates(this.dossierTemplate?.dossierTemplateId).toPromise()) || []; + } + get changed(): boolean { if (!this.dossierTemplate) return true; diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts index 953f2e87e..2e7c9cd95 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts @@ -22,7 +22,7 @@ export class ActiveFieldsListingComponent extends BaseListingComponent im translations = fileAttributeTypesTranslations; readonly typeOptions = [FileAttributeConfig.TypeEnum.TEXT, FileAttributeConfig.TypeEnum.NUMBER, FileAttributeConfig.TypeEnum.DATE]; - protected readonly _primaryKey = 'id'; + protected readonly _primaryKey = 'csvColumn'; constructor(protected readonly _injector: Injector) { super(_injector); diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts index a28bff412..d6fff4bec 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts @@ -32,6 +32,8 @@ export interface Field { providers: [FilterService, SearchService, ScreenStateService, SortingService] }) export class FileAttributesCsvImportDialogComponent extends BaseListingComponent { + protected readonly _primaryKey = 'csvColumn'; + csvFile: File; dossierTemplateId: string; parseResult: { data: any[]; errors: any[]; meta: any; fields: Field[] }; @@ -44,7 +46,6 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent keepPreview = false; columnSample = []; initialParseConfig: { delimiter?: string; encoding?: string } = {}; - protected readonly _primaryKey = 'id'; constructor( private readonly _appStateService: AppStateService, diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html index 40e1787dd..d5b568d83 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html @@ -97,5 +97,3 @@
- - diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts index 46558b69b..3d0d9cce9 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts @@ -18,7 +18,6 @@ import { LoadingService } from '@services/loading.service'; styleUrls: ['./dictionary-overview-screen.component.scss'] }) export class DictionaryOverviewScreenComponent extends ComponentHasChanges implements OnInit { - processing = false; entries: string[] = []; @ViewChild('dictionaryManager', { static: false }) @@ -109,29 +108,29 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple } saveEntries(entries: string[]) { - this.processing = true; + this._loadingService.start(); this._dictionarySaveService .saveEntries(entries, this.entries, this.dictionary.dossierTemplateId, this.dictionary.type, null) .subscribe( () => { - this.processing = false; + this._loadingService.stop(); this._loadEntries(); }, () => { - this.processing = false; + this._loadingService.stop(); } ); } private _loadEntries() { - this.processing = true; + this._loadingService.start(); this._dictionaryControllerService.getDictionaryForType(this.dictionary.dossierTemplateId, this.dictionary.type).subscribe( data => { - this.processing = false; + this._loadingService.stop(); this.entries = data.entries.sort((str1, str2) => str1.localeCompare(str2, undefined, { sensitivity: 'accent' })); }, () => { - this.processing = false; + this._loadingService.stop(); this.entries = []; } ); diff --git a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.html similarity index 51% rename from apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.html rename to apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.html index c73b070cf..05dae7061 100644 --- a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.html @@ -10,10 +10,10 @@
@@ -23,136 +23,151 @@
-
-
+
+
-
-
- - +
+
+
+
+ + +
+ +
+ + +
+
-
-
- -
+
+ +
+
-
-
+
+
-
+
- +
- +
- +
- + - +
- +
- +
- + - +
- +
- +
- +
-
@@ -162,5 +177,3 @@
- - diff --git a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.scss b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.scss similarity index 96% rename from apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.scss rename to apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.scss index 71129224b..581e22a78 100644 --- a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.scss +++ b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.scss @@ -21,6 +21,7 @@ height: 38px; border-radius: 4px; padding: 1px 11px; + margin-top: 20px; } .dialog { diff --git a/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.ts new file mode 100644 index 000000000..750e0741d --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-screen.component.ts @@ -0,0 +1,149 @@ +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'; +import { LoadingService } from '../../../../services/loading.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 { + 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, + private readonly _loadingService: LoadingService + ) { + 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.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(); + configFormValues.displayName = configFormValues.displayName || 'RedactManager'; + + await this._generalSettingsControllerService.updateGeneralConfigurations(configFormValues).toPromise(); + this._appConfigService.updateDisplayName(configFormValues.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('smtp-config-screen.test.success'); + } catch (e) { + this._toaster.error('smtp-config-screen.test.error'); + } finally { + this._loadingService.stop(); + } + } + + private async _loadData() { + this._loadingService.start(); + 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._loadingService.stop(); + } +} diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html index 95c117176..6952262fc 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html @@ -33,5 +33,3 @@
- - diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts index e8c8065ab..65ef95081 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts @@ -9,6 +9,7 @@ import { ActivatedRoute } from '@angular/router'; import { AppStateService } from '@state/app-state.service'; import { debounce } from '../../../../utils/debounce'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { LoadingService } from '../../../../services/loading.service'; import ICodeEditor = monaco.editor.ICodeEditor; import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration; import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions; @@ -25,7 +26,6 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit automaticLayout: true, readOnly: !this.permissionsService.isAdmin() }; - processing = true; initialLines: string[] = []; currentLines: string[] = []; @@ -42,7 +42,8 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit private readonly _appStateService: AppStateService, private readonly _toaster: Toaster, protected readonly _translateService: TranslateService, - private readonly _activatedRoute: ActivatedRoute + private readonly _activatedRoute: ActivatedRoute, + private readonly _loadingService: LoadingService ) { super(_translateService); _appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId); @@ -86,7 +87,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit } async save(): Promise { - this.processing = true; + this._loadingService.start(); await this._rulesControllerService .uploadRules({ rules: this._codeEditor.getModel().getValue(), @@ -99,7 +100,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit this._toaster.success(_('rules-screen.success.generic')); }, () => { - this.processing = false; + this._loadingService.stop(); this._toaster.error(_('rules-screen.error.generic')); } ); @@ -108,7 +109,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit revert(): void { this.currentLines = this.initialLines; this._decorations = this._codeEditor?.deltaDecorations(this._decorations, []) || []; - this.processing = false; + this._loadingService.stop(); } download(): void { @@ -146,6 +147,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit } private async _initialize() { + this._loadingService.start(); await this._rulesControllerService .downloadRules(this._appStateService.activeDossierTemplateId) .toPromise() @@ -154,7 +156,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit this.currentLines = this.initialLines = rules.rules.split('\n'); this.revert(); }, - () => (this.processing = false) + () => this._loadingService.stop() ); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts deleted file mode 100644 index d89fdc07b..000000000 --- a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts +++ /dev/null @@ -1,131 +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'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; - -@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; - } - } -} diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html index 5c96350ac..d9ef81f1f 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html @@ -125,5 +125,3 @@ - - diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts index 21dd63d9b..3a4d8fc61 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts @@ -12,6 +12,7 @@ import { ActivatedRoute } from '@angular/router'; import { BASE_HREF } from '../../../../tokens'; import { stampPDFPage } from '../../../../utils/page-stamper'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { LoadingService } from '../../../../services/loading.service'; export const DEFAULT_WATERMARK: WatermarkModelRes = { text: null, @@ -28,7 +29,6 @@ export const DEFAULT_WATERMARK: WatermarkModelRes = { styleUrls: ['./watermark-screen.component.scss'] }) export class WatermarkScreenComponent implements OnInit { - viewReady = false; configForm: FormGroup; private _instance: WebViewerInstance; private _watermark: WatermarkModelRes = {}; @@ -44,9 +44,11 @@ export class WatermarkScreenComponent implements OnInit { private readonly _http: HttpClient, private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _formBuilder: FormBuilder, - private readonly _activatedRoute: ActivatedRoute + private readonly _activatedRoute: ActivatedRoute, + private readonly _loadingService: LoadingService ) { appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId); + this._loadingService.start(); this._initForm(); } @@ -136,7 +138,7 @@ export class WatermarkScreenComponent implements OnInit { this._instance = instance; instance.docViewer.on('documentLoaded', async () => { - this.viewReady = true; + this._loadingService.stop(); await this._drawWatermark(); }); diff --git a/apps/red-ui/src/app/modules/app-config/app-config.service.ts b/apps/red-ui/src/app/modules/app-config/app-config.service.ts index a0c8c8036..5da8dece3 100644 --- a/apps/red-ui/src/app/modules/app-config/app-config.service.ts +++ b/apps/red-ui/src/app/modules/app-config/app-config.service.ts @@ -64,11 +64,19 @@ export class AppConfigService { 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; } diff --git a/apps/red-ui/src/app/modules/app-config/configuration.initializer.ts b/apps/red-ui/src/app/modules/app-config/configuration.initializer.ts new file mode 100644 index 000000000..9b91db957 --- /dev/null +++ b/apps/red-ui/src/app/modules/app-config/configuration.initializer.ts @@ -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(); +} diff --git a/apps/red-ui/src/app/modules/auth/auth.module.ts b/apps/red-ui/src/app/modules/auth/auth.module.ts index eead711f4..7ba78bc5d 100644 --- a/apps/red-ui/src/app/modules/auth/auth.module.ts +++ b/apps/red-ui/src/app/modules/auth/auth.module.ts @@ -6,6 +6,7 @@ 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) { return () => @@ -31,7 +32,10 @@ export function keycloakInitializer(keycloak: KeycloakService, appConfigService: }, enableBearerInterceptor: true }; - return keycloak.init(options).then(() => configureAutomaticRedirectToLoginScreen(keycloak)); + return keycloak + .init(options) + .then(() => configureAutomaticRedirectToLoginScreen(keycloak)) + .then(() => APP_BOOTSTRAPPED.next(true)); }); } diff --git a/apps/red-ui/src/app/modules/bootstrap/app-bootstrap.ts b/apps/red-ui/src/app/modules/bootstrap/app-bootstrap.ts new file mode 100644 index 000000000..3b3133a74 --- /dev/null +++ b/apps/red-ui/src/app/modules/bootstrap/app-bootstrap.ts @@ -0,0 +1,3 @@ +import { ReplaySubject } from 'rxjs'; + +export const APP_BOOTSTRAPPED = new ReplaySubject(); diff --git a/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts b/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts index 1bede8dac..6c69164d7 100644 --- a/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/bulk-actions/dossier-overview-bulk-actions.component.ts @@ -152,12 +152,11 @@ export class DossierOverviewBulkActionsComponent { setToUnderApproval() { // If more than 1 approver - show dialog and ask who to assign if (this._appStateService.activeDossier.approverIds.length > 1) { - this._loadingService.start(); - this._dialogService.openAssignFileToUserDialog( this.selectedFiles, 'approver', () => { + this._loadingService.start(); this.reload.emit(); this._loadingService.stop(); }, @@ -194,11 +193,10 @@ export class DossierOverviewBulkActionsComponent { } assign() { - this._loadingService.start(); - const mode = this.selectedFiles[0].isUnderApproval ? 'approver' : 'reviewer'; this._dialogService.openAssignFileToUserDialog(this.selectedFiles, mode, () => { + this._loadingService.start(); this.reload.emit(); this._loadingService.stop(); }); diff --git a/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html b/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html index 888a9b680..428a81c2f 100644 --- a/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/file-actions/file-actions.component.html @@ -1,6 +1,6 @@
- +
@@ -8,7 +8,7 @@ -
+
{{ 'file-preview.tabs.annotations.page-is' | translate }} - + . diff --git a/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts b/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts index a6b42f8bb..a0321fd54 100644 --- a/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts +++ b/apps/red-ui/src/app/modules/dossier/components/needs-work-badge/needs-work-badge.component.ts @@ -59,11 +59,6 @@ export class NeedsWorkBadgeComponent { } private _getDictionaryColor(type: string) { - let dossierTemplateId = null; - if (this.needsWorkInput instanceof DossierWrapper) { - dossierTemplateId = this.needsWorkInput.dossierTemplateId; - } - - return this._appStateService.getDictionaryColor(type, dossierTemplateId); + return this._appStateService.getDictionaryColor(type); } } diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.html b/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.html index 0acb92175..b1ff24e25 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.html +++ b/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.html @@ -62,10 +62,12 @@

{{ 'download-includes' | translate }}

+ + + {{ option.fileName }} + diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts index e722b7865..31561a8e1 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts @@ -1,10 +1,9 @@ import { Component } from '@angular/core'; import { MatDialogRef } from '@angular/material/dialog'; -import { Dossier, DossierTemplateModel } from '@redaction/red-ui-http'; +import { Dossier, DossierTemplateModel, ReportTemplate, ReportTemplateControllerService } from '@redaction/red-ui-http'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { AppStateService } from '@state/app-state.service'; import * as moment from 'moment'; -import { reportTypesTranslations } from '../../../../translations/report-types-translations'; import { downloadTypesTranslations } from '../../../../translations/download-types-translations'; @Component({ @@ -20,16 +19,14 @@ export class AddDossierDialogComponent { key: type, label: downloadTypesTranslations[type] })); - reportTypesEnum = Object.values(DossierTemplateModel.ReportTypesEnum); - reportTypes: { key: DossierTemplateModel.ReportTypesEnum; label: string }[] = this.reportTypesEnum.map(type => ({ - key: type, - label: reportTypesTranslations[type] - })); dossierTemplates: DossierTemplateModel[]; + availableReportTypes = []; + reportTemplateValueMapper = (reportTemplate: ReportTemplate) => reportTemplate.templateId; constructor( private readonly _appStateService: AppStateService, private readonly _formBuilder: FormBuilder, + private readonly _reportTemplateController: ReportTemplateControllerService, public dialogRef: MatDialogRef ) { this._filterInvalidDossierTemplates(); @@ -38,20 +35,22 @@ export class AddDossierDialogComponent { dossierName: [null, Validators.required], dossierTemplateId: [null, Validators.required], downloadFileTypes: [null], - reportTypes: [null], + reportTemplateIds: [null], description: [null], dueDate: [null], watermarkEnabled: [true] }, { validators: control => - control.value.reportTypes?.length > 0 || control.value.downloadFileTypes?.length > 0 ? null : { downloadPackage: true } + control.value.reportTemplateIds?.length > 0 || control.value.downloadFileTypes?.length > 0 + ? null + : { downloadPackage: true } } ); } - get reportTypesLength() { - return this.dossierForm.controls['reportTypes']?.value?.length || 0; + get reportTemplateIdsLength() { + return this.dossierForm.controls['reportTemplateIds']?.value?.length || 0; } get downloadFileTypesLength() { @@ -88,15 +87,27 @@ export class AddDossierDialogComponent { } } - dossierTemplateChanged(dossierTemplateId) { + async dossierTemplateChanged(dossierTemplateId) { // get current selected dossierTemplate const dossierTemplate = this.dossierTemplates.find(r => r.dossierTemplateId === dossierTemplateId); + if (dossierTemplate) { + this.availableReportTypes = + (await this._reportTemplateController.getAvailableReportTemplates(dossierTemplate.dossierTemplateId).toPromise()) || []; // update dropdown values this.dossierForm.patchValue( { downloadFileTypes: dossierTemplate.downloadFileTypes, - reportTypes: dossierTemplate.reportTypes + reportTemplateIds: dossierTemplate.reportTemplateIds + }, + { emitEvent: false } + ); + } else { + this.availableReportTypes = []; + this.dossierForm.patchValue( + { + downloadFileTypes: [], + reportTemplateIds: [] }, { emitEvent: false } ); @@ -118,7 +129,9 @@ export class AddDossierDialogComponent { dueDate: this.hasDueDate ? this.dossierForm.get('dueDate').value : undefined, dossierTemplateId: this.dossierForm.get('dossierTemplateId').value, downloadFileTypes: this.dossierForm.get('downloadFileTypes').value, - reportTypes: this.dossierForm.get('reportTypes').value, + reportTemplateIds: this.dossierForm.get('reportTemplateIds').value, + // TODO REMOVE THIS + reportTypes: [], watermarkEnabled: this.dossierForm.get('watermarkEnabled').value }; } diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.html b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.html index dc7b3d85a..95ddd0035 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.html +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.html @@ -1,9 +1,11 @@ - + + + + {{ option.fileName }} + diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts index 53b096a80..bbd2d8006 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component.ts @@ -1,10 +1,9 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { Dossier, DossierTemplateModel } from '@redaction/red-ui-http'; +import { Dossier, DossierTemplateModel, ReportTemplate, ReportTemplateControllerService } from '@redaction/red-ui-http'; import { FormBuilder, FormGroup } from '@angular/forms'; import { AppStateService } from '@state/app-state.service'; import { DossierWrapper } from '@state/model/dossier.wrapper'; import { EditDossierSectionInterface } from '../edit-dossier-section.interface'; -import { reportTypesTranslations } from '../../../../../translations/report-types-translations'; import { downloadTypesTranslations } from '../../../../../translations/download-types-translations'; @Component({ @@ -19,20 +18,22 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS key: type, label: downloadTypesTranslations[type] })); - reportTypesEnum = Object.values(DossierTemplateModel.ReportTypesEnum); - reportTypes: { key: DossierTemplateModel.ReportTypesEnum; label: string }[] = this.reportTypesEnum.map(type => ({ - key: type, - label: reportTypesTranslations[type] - })); dossierTemplates: DossierTemplateModel[]; + availableReportTypes: ReportTemplate[] = []; @Input() dossierWrapper: DossierWrapper; @Output() updateDossier = new EventEmitter(); - constructor(private readonly _appStateService: AppStateService, private readonly _formBuilder: FormBuilder) {} + reportTemplateValueMapper = (reportTemplate: ReportTemplate) => reportTemplate.templateId; + + constructor( + private readonly _appStateService: AppStateService, + private readonly _reportTemplateController: ReportTemplateControllerService, + private readonly _formBuilder: FormBuilder + ) {} get reportTypesLength() { - return this.dossierForm.controls['reportTypes']?.value?.length || 0; + return this.dossierForm.controls['reportTemplateIds']?.value?.length || 0; } get downloadFileTypesLength() { @@ -59,18 +60,23 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS } get disabled() { - return this.dossierForm.invalid; + return this.dossierForm?.invalid; } - ngOnInit() { + async ngOnInit() { + this.availableReportTypes = + (await this._reportTemplateController.getAvailableReportTemplates(this.dossierWrapper.dossierTemplateId).toPromise()) || []; + this.dossierForm = this._formBuilder.group( { - reportTypes: [this.dossierWrapper.dossier.reportTypes], + reportTemplateIds: [this.dossierWrapper.dossier.reportTemplateIds], downloadFileTypes: [this.dossierWrapper.dossier.downloadFileTypes] }, { validators: control => - control.value.reportTypes?.length > 0 || control.value.downloadFileTypes?.length > 0 ? null : { downloadPackage: true } + control.value.reportTemplateIds?.length > 0 || control.value.downloadFileTypes?.length > 0 + ? null + : { downloadPackage: true } } ); } @@ -79,7 +85,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS const dossier = { ...this.dossierWrapper.dossier, downloadFileTypes: this.dossierForm.get('downloadFileTypes').value, - reportTypes: this.dossierForm.get('reportTypes').value + reportTemplateIds: this.dossierForm.get('reportTemplateIds').value }; const updatedDossier = await this._appStateService.createOrUpdateDossier(dossier); this.updateDossier.emit(updatedDossier); @@ -88,7 +94,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS revert() { this.dossierForm.reset({ downloadFileTypes: this.dossierWrapper.dossier.downloadFileTypes, - reportTypes: this.dossierWrapper.dossier.reportTypes + reportTemplateIds: this.dossierWrapper.dossier.reportTemplateIds }); } } diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts index 6335b1d66..0875a1a88 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts @@ -21,7 +21,6 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSectionInterface { dossierForm: FormGroup; hasDueDate: boolean; - readonly reportTypesEnum = Object.values(DossierTemplateModel.ReportTypesEnum); dossierTemplates: DossierTemplateModel[]; @Input() dossierWrapper: DossierWrapper; diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html index 95d46d14b..8d62c4de0 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html @@ -137,8 +137,20 @@
-
-
+
+
+ + {{ fileStatus.numberOfPages }} +
+
+ + {{ fileStatus.numberOfExcludedPages }} +
+
{{ fileStatus.ocrTime | date: 'mediumDate' }}
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts index 586ea0844..acdc86325 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.ts @@ -101,32 +101,35 @@ export class DossierOverviewScreenComponent } async ngOnInit(): Promise { - this._fileDropOverlayService.initFileDropHandling(); - - this.calculateData(); - - this.addSubscription = timer(0, 7500).subscribe(async () => { - await this._appStateService.reloadActiveDossierFilesIfNecessary(); - this._loadEntitiesFromState(); - }); - - this.addSubscription = this._appStateService.fileChanged.subscribe(() => { - this.calculateData(); - }); - - this.addSubscription = this._router.events - .pipe(filter(event => event instanceof NavigationStart)) - .subscribe((event: NavigationStart) => { - if (!event.url.endsWith(this._appStateService.activeDossierId)) { - this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top'); - } - }); - this._loadingService.start(); - this.dossierAttributes = await this._dossierAttributesService.getValues(this.activeDossier); + try { + this._fileDropOverlayService.initFileDropHandling(); - this._loadingService.stop(); + this.calculateData(); + + this.addSubscription = timer(0, 7500).subscribe(async () => { + await this._appStateService.reloadActiveDossierFilesIfNecessary(); + this._loadEntitiesFromState(); + }); + + this.addSubscription = this._appStateService.fileChanged.subscribe(() => { + this.calculateData(); + }); + + this.addSubscription = this._router.events + .pipe(filter(event => event instanceof NavigationStart)) + .subscribe((event: NavigationStart) => { + if (!event.url.endsWith(this._appStateService.activeDossierId)) { + this._lastScrollPosition = this.scrollViewport.measureScrollOffset('top'); + } + }); + + this.dossierAttributes = await this._dossierAttributesService.getValues(this.activeDossier); + } catch (e) { + } finally { + this._loadingService.stop(); + } } ngOnDestroy(): void { diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html index c5f7a327e..c982ab609 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html @@ -29,7 +29,7 @@
-
+
@@ -89,7 +89,6 @@ @@ -149,7 +148,7 @@
@@ -187,8 +186,6 @@
- - { if (!document.fullscreenElement) { this.fullScreen = false; @@ -229,7 +229,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme ngOnDetach() { this.displayPDFViewer = false; - this.viewReady = false; super.ngOnDestroy(); } @@ -255,7 +254,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme } this._subscribeToFileUpdates(); - this.viewReady = true; + this._loadingService.stop(); } rebuildFilters(deletePreviousAnnotations: boolean = false) { @@ -403,7 +402,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme await this._stampExcludedPages(); this._cleanupAndRedrawManualAnnotations(); this._updateCanPerformActions(); - this.viewReady = true; + this._loadingService.stop(); // Go to initial page from query params const pageNumber = this._lastPage || this._activatedRoute.snapshot.queryParams.page; if (pageNumber) { @@ -549,7 +548,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme if (fileStatus.fileId === this.fileId) { await this._loadFileData(!this._reloadFileOnReanalysis); this._reloadFileOnReanalysis = false; - this.viewReady = true; + this._loadingService.stop(); this._updateCanPerformActions(); this._cleanupAndRedrawManualAnnotations(); } @@ -593,7 +592,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme /* Get the documentElement () to display the page in fullscreen */ private _cleanupAndRedrawManualAnnotations() { - this._fileDownloadService.loadActiveFileRedactionLogPreview().subscribe(redactionLogPreview => { + this._fileDownloadService.loadActiveFileRedactionLog().subscribe(redactionLogPreview => { this.fileData.redactionLog = redactionLogPreview; this._annotationDrawService.drawAnnotations( this._instance, @@ -609,7 +608,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme const currentPageAnnotationIds = currentPageAnnotations.map(a => a.id); this.fileData.fileStatus = await this.appStateService.reloadActiveFile(); - this._fileDownloadService.loadActiveFileRedactionLogPreview().subscribe(redactionLogPreview => { + this._fileDownloadService.loadActiveFileRedactionLog().subscribe(redactionLogPreview => { this.fileData.redactionLog = redactionLogPreview; this.rebuildFilters(); if (this.viewMode === 'STANDARD') { diff --git a/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts b/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts index 80f06622c..30d46ee8e 100644 --- a/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/file-action.service.ts @@ -24,7 +24,8 @@ export class FileActionService { } return this._reanalysisControllerService.reanalyzeFile( this._appStateService.activeDossier.dossier.dossierId, - fileStatusWrapper.fileId + fileStatusWrapper.fileId, + true ); } diff --git a/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts b/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts index d3f1bf249..f07debfe0 100644 --- a/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts +++ b/apps/red-ui/src/app/modules/dossier/services/pdf-viewer-data.service.ts @@ -23,8 +23,8 @@ export class PdfViewerDataService { private readonly _viewedPagesControllerService: ViewedPagesControllerService ) {} - loadActiveFileRedactionLogPreview() { - return this._redactionLogControllerService.getRedactionLogPreview( + loadActiveFileRedactionLog() { + return this._redactionLogControllerService.getRedactionLog( this._appStateService.activeDossierId, this._appStateService.activeFileId ); @@ -37,7 +37,7 @@ export class PdfViewerDataService { this._man.getManualRedaction(dossierId, fileId).subscribe(); const file$ = this.downloadOriginalFile(this._appStateService.activeFile); - const reactionLog$ = this._redactionLogControllerService.getRedactionLogPreview(dossierId, fileId).pipe(catchError(() => of({}))); + const reactionLog$ = this._redactionLogControllerService.getRedactionLog(dossierId, fileId).pipe(catchError(() => of({}))); const redactionChangeLog$ = this._redactionLogControllerService .getRedactionChangeLog(dossierId, fileId) .pipe(catchError(() => of({}))); diff --git a/apps/red-ui/src/app/modules/shared/components/select/select.component.html b/apps/red-ui/src/app/modules/shared/components/select/select.component.html index 3db1bbe33..1e85e12df 100644 --- a/apps/red-ui/src/app/modules/shared/components/select/select.component.html +++ b/apps/red-ui/src/app/modules/shared/components/select/select.component.html @@ -7,7 +7,20 @@
- - {{ option.label | translate }} + + + + + {{ option.label | translate }} + diff --git a/apps/red-ui/src/app/modules/shared/components/select/select.component.ts b/apps/red-ui/src/app/modules/shared/components/select/select.component.ts index bd46a7270..b00222232 100644 --- a/apps/red-ui/src/app/modules/shared/components/select/select.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/select/select.component.ts @@ -1,8 +1,6 @@ -import { AfterViewInit, ChangeDetectorRef, Component, Input, ViewChild } from '@angular/core'; +import { AfterViewInit, ChangeDetectorRef, Component, Input, TemplateRef, ViewChild } from '@angular/core'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; -import { MatChip, MatChipList } from '@angular/material/chips'; -import { map } from 'rxjs/operators'; -import { Dossier, DossierTemplateModel } from '@redaction/red-ui-http'; +import { MatChip, MatChipList, MatChipSelectionChange } from '@angular/material/chips'; @Component({ selector: 'redaction-select', @@ -17,31 +15,39 @@ import { Dossier, DossierTemplateModel } from '@redaction/red-ui-http'; ] }) export class SelectComponent implements AfterViewInit, ControlValueAccessor { + @Input() optionTemplate: TemplateRef; @Input() label: string; - @Input() options: { key: DossierTemplateModel.ReportTypesEnum | Dossier.DownloadFileTypesEnum; label: string }[]; + @Input() options: any[]; @Input() disabled = false; @Input() multiple = true; @ViewChild(MatChipList) chipList: MatChipList; - private _value: string[] = []; - private _onChange: (value: string[]) => void; + private _value: any[] = []; + private _onChange: (value: any[]) => void; + + @Input() valueMapper: (option: any) => any = option => option.key; constructor(private readonly _changeDetector: ChangeDetectorRef) {} ngAfterViewInit(): void { - this._selectChips(this._value); - this.chipList.chipSelectionChanges.pipe(map(event => event.source)).subscribe(chip => { + setTimeout(() => { + this._selectChips(this._value); + this._changeDetector.detectChanges(); + }); + } + + selectChange($event: MatChipSelectionChange) { + const chip = $event.source; + if ($event.isUserInput) { if (chip.selected) { this._value = [...this._value, chip.value]; } else { this._value = this._value.filter(o => o !== chip.value); } - this._propagateChange(this._value); - }); - - this._changeDetector.detectChanges(); + this._propagateChange([...new Set(this._value)]); + } } registerOnChange(fn: any): void { @@ -51,9 +57,12 @@ export class SelectComponent implements AfterViewInit, ControlValueAccessor { // eslint-disable-next-line @typescript-eslint/no-unused-vars registerOnTouched(fn: any): void {} - writeValue(value: string[]): void { - if (this.chipList && value) this._selectChips(value); - else if (value) this._value = value; + writeValue(value: any[]): void { + if (this.chipList && value) { + this._selectChips(value); + } else if (value) { + this._value = value; + } } setDisabledState?(isDisabled: boolean): void { @@ -61,28 +70,34 @@ export class SelectComponent implements AfterViewInit, ControlValueAccessor { } toggleSelection(chip: MatChip): void { - if (!this.disabled) chip.toggleSelected(); + if (!this.disabled) chip.toggleSelected(true); } selectAll($event) { $event.stopPropagation(); - this.chipList.chips.forEach(chip => chip.select()); + this.chipList.chips.forEach(chip => { + if (!chip.selected) { + chip.toggleSelected(true); + } + }); } - deselectAll($event) { - $event.stopPropagation(); - this.chipList.chips.forEach(chip => chip.deselect()); + deselectAll($event?) { + $event?.stopPropagation(); + this.chipList.chips.forEach(chip => { + if (chip.selected) { + chip.toggleSelected(true); + } + }); } - private _selectChips(value: string[]): void { - this.chipList.chips.forEach(chip => chip.deselect()); - + private _selectChips(value: any[]): void { + this.deselectAll(); const chipsToSelect = this.chipList.chips.filter(c => value.includes(c.value)); - - chipsToSelect.forEach(chip => chip.select()); + chipsToSelect.forEach(chip => chip.toggleSelected(true)); } - private _propagateChange(value: string[]): void { + private _propagateChange(value: any[]): void { if (this._onChange) this._onChange(value); } } diff --git a/apps/red-ui/src/app/services/sorting.service.ts b/apps/red-ui/src/app/services/sorting.service.ts index 0894e2776..9f54c91a5 100644 --- a/apps/red-ui/src/app/services/sorting.service.ts +++ b/apps/red-ui/src/app/services/sorting.service.ts @@ -13,7 +13,9 @@ export interface SortingOption { column: string; } -@Injectable() +@Injectable({ + providedIn: 'root' +}) export class SortingService { private _sortingOption: SortingOption; diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts index c1b8914c4..6ac7a0440 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -15,7 +15,7 @@ import { Event, NavigationEnd, ResolveStart, Router } from '@angular/router'; import { UserService } from '@services/user.service'; import { forkJoin, Observable, of } from 'rxjs'; import { catchError, tap } from 'rxjs/operators'; -import { humanize } from '@utils/functions'; +import { FALLBACK_COLOR, hexToRgb, humanize } from '@utils/functions'; import { FileStatusWrapper } from '@models/file/file-status.wrapper'; import { DossierWrapper } from './model/dossier.wrapper'; import { TypeValueWrapper } from '@models/file/type-value.wrapper'; @@ -175,7 +175,7 @@ export class AppStateService { dossierTemplateId = this.dossierTemplates[0]?.dossierTemplateId; } if (!dossierTemplateId) { - return undefined; + return '#cccccc'; } const color = this._dictionaryData[dossierTemplateId][type]?.hexColor; return color ?? this._dictionaryData[dossierTemplateId]['default'].hexColor; @@ -259,7 +259,7 @@ export class AppStateService { } async reanalyzeDossier({ dossierId }: DossierWrapper = this.activeDossier) { - await this._reanalysisControllerService.reanalyzeDossier(dossierId).toPromise(); + await this._reanalysisControllerService.reanalyzeDossier(dossierId, true).toPromise(); } activateDossier(dossierId: string): void { @@ -404,6 +404,18 @@ export class AppStateService { const colorsObs = this._dictionaryControllerService.getColors(dossierTemplateId).pipe( tap(colors => { + for (const key of Object.keys(colors)) { + const color = colors[key]; + try { + const rgbValue = hexToRgb(color); + if (!rgbValue) { + colors[key] = FALLBACK_COLOR; + } + } catch (e) { + colors[key] = FALLBACK_COLOR; + } + } + // declined dictionaryData['declined-suggestion'] = new TypeValueWrapper( { diff --git a/apps/red-ui/src/app/translations/annotation-types-translations.ts b/apps/red-ui/src/app/translations/annotation-types-translations.ts index 08c363279..b2c98e4bb 100644 --- a/apps/red-ui/src/app/translations/annotation-types-translations.ts +++ b/apps/red-ui/src/app/translations/annotation-types-translations.ts @@ -20,4 +20,4 @@ export const annotationTypesTranslations: { [key in AnnotationSuperType]: string 'suggestion-force-redaction': _('annotation-type.suggestion-force-redaction'), 'suggestion-remove': _('annotation-type.suggestion-remove'), 'suggestion-remove-dictionary': _('annotation-type.suggestion-remove-dictionary') -}; +} as const; diff --git a/apps/red-ui/src/app/translations/download-types-translations.ts b/apps/red-ui/src/app/translations/download-types-translations.ts index 9ebd5604c..ba6bdf18d 100644 --- a/apps/red-ui/src/app/translations/download-types-translations.ts +++ b/apps/red-ui/src/app/translations/download-types-translations.ts @@ -7,4 +7,4 @@ export const downloadTypesTranslations: { [key in Dossier.DownloadFileTypesEnum] REDACTED: _('download-type.redacted'), ANNOTATED: _('download-type.annotated'), FLATTEN: _('download-type.flatten') -}; +} as const; diff --git a/apps/red-ui/src/app/translations/languages-translations.ts b/apps/red-ui/src/app/translations/languages-translations.ts index 412f98128..3678c12e8 100644 --- a/apps/red-ui/src/app/translations/languages-translations.ts +++ b/apps/red-ui/src/app/translations/languages-translations.ts @@ -3,4 +3,4 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; export const languagesTranslations: { [key: string]: string } = { en: _('top-bar.navigation-items.my-account.children.language.en'), de: _('top-bar.navigation-items.my-account.children.language.de') -}; +} as const; diff --git a/apps/red-ui/src/app/translations/report-types-translations.ts b/apps/red-ui/src/app/translations/report-types-translations.ts deleted file mode 100644 index 954b37dba..000000000 --- a/apps/red-ui/src/app/translations/report-types-translations.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { DossierTemplateModel } from '@redaction/red-ui-http'; - -export const reportTypesTranslations: { [key in DossierTemplateModel.ReportTypesEnum]: string } = { - EXCEL_MULTI_FILE: _('report-type.excel-multi-file'), - EXCEL_SINGLE_FILE: _('report-type.excel-single-file'), - WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE: _('report-type.word-single-file-appendix-a1'), - WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE: _('report-type.word-single-file-appendix-a2') -}; diff --git a/apps/red-ui/src/app/translations/roles-translations.ts b/apps/red-ui/src/app/translations/roles-translations.ts index 1c3385af4..b3f70b83c 100644 --- a/apps/red-ui/src/app/translations/roles-translations.ts +++ b/apps/red-ui/src/app/translations/roles-translations.ts @@ -9,4 +9,4 @@ export const rolesTranslations: { [key in string]: string } = { RED_USER: _('roles.red-user'), RED_USER_ADMIN: _('roles.red-user-admin'), REGULAR: _('roles.regular') -}; +} as const; diff --git a/apps/red-ui/src/app/utils/functions.ts b/apps/red-ui/src/app/utils/functions.ts index e4f6d99b8..83f1a5ed5 100644 --- a/apps/red-ui/src/app/utils/functions.ts +++ b/apps/red-ui/src/app/utils/functions.ts @@ -1,3 +1,5 @@ +export const FALLBACK_COLOR = '#CCCCCC'; + export function groupBy(xs: any[], key: string) { return xs.reduce((rv, x) => { (rv[x[key]] = rv[x[key]] || []).push(x); diff --git a/apps/red-ui/src/assets/i18n/de.json b/apps/red-ui/src/assets/i18n/de.json index 4d4e45e33..cfd162f3f 100644 --- a/apps/red-ui/src/assets/i18n/de.json +++ b/apps/red-ui/src/assets/i18n/de.json @@ -1024,7 +1024,7 @@ }, "title": "Aktivieren Sie die Authentifizierung" }, - "smtp-config-screen": { + "general-config-screen": { "actions": { "save": "Konfigurationen speichern", "test-connection": "Testverbindung" diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index e45ef1e82..041dee3ba 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -1170,11 +1170,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", diff --git a/apps/red-ui/src/assets/styles/red-text-styles.scss b/apps/red-ui/src/assets/styles/red-text-styles.scss index 9e72c84fd..b80aa2226 100644 --- a/apps/red-ui/src/assets/styles/red-text-styles.scss +++ b/apps/red-ui/src/assets/styles/red-text-styles.scss @@ -9,6 +9,12 @@ a { color: lighten($primary, 10%); } + &.with-underline { + &:hover { + text-decoration: underline; + } + } + cursor: pointer; } diff --git a/bamboo-specs/src/main/java/buildjob/PlanSpec.java b/bamboo-specs/src/main/java/buildjob/PlanSpec.java index 8a29c1b59..bfe825371 100644 --- a/bamboo-specs/src/main/java/buildjob/PlanSpec.java +++ b/bamboo-specs/src/main/java/buildjob/PlanSpec.java @@ -67,6 +67,7 @@ public class PlanSpec { public Job creatGinCloudPlatformImagesJob(String project) { return new Job("Build Job: " + project, new BambooKey(project.toUpperCase().replaceAll("-", ""))) .tasks( + new CleanWorkingDirectoryTask().description("My clean working directory task"), // Checkout new VcsCheckoutTask().description("Checkout Default Repository") .checkoutItems(new CheckoutItem().defaultRepository()), @@ -96,6 +97,7 @@ public class PlanSpec { public Job createRelease() { return new Job("Create Release", new BambooKey("CRLS")) .tasks( + new CleanWorkingDirectoryTask().description("My clean working directory task"), new VcsCheckoutTask().description("Checkout Default Repository") .checkoutItems(new CheckoutItem().defaultRepository()).cleanCheckout(true), diff --git a/docker/red-ui/docker-entrypoint.sh b/docker/red-ui/docker-entrypoint.sh index 57c9ace31..0482741aa 100755 --- a/docker/red-ui/docker-entrypoint.sh +++ b/docker/red-ui/docker-entrypoint.sh @@ -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"'", diff --git a/libs/red-ui-http/src/lib/api/redactionLogController.service.ts b/libs/red-ui-http/src/lib/api/redactionLogController.service.ts index a5bccf3ad..26b7adc72 100644 --- a/libs/red-ui-http/src/lib/api/redactionLogController.service.ts +++ b/libs/red-ui-http/src/lib/api/redactionLogController.service.ts @@ -174,69 +174,6 @@ export class RedactionLogControllerService { ); } - /** - * Gets the redaction log preview - * None - * @param dossierId dossierId - * @param fileId fileId - * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. - * @param reportProgress flag to report request and response progress. - */ - public getRedactionLogPreview(dossierId: string, fileId: string, observe?: 'body', reportProgress?: boolean): Observable; - public getRedactionLogPreview( - dossierId: string, - fileId: string, - observe?: 'response', - reportProgress?: boolean - ): Observable>; - public getRedactionLogPreview( - dossierId: string, - fileId: string, - observe?: 'events', - reportProgress?: boolean - ): Observable>; - public getRedactionLogPreview( - dossierId: string, - fileId: string, - observe: any = 'body', - reportProgress: boolean = false - ): Observable { - if (dossierId === null || dossierId === undefined) { - throw new Error('Required parameter dossierId was null or undefined when calling getRedactionLogPreview.'); - } - - if (fileId === null || fileId === undefined) { - throw new Error('Required parameter fileId was null or undefined when calling getRedactionLogPreview.'); - } - - let headers = this.defaultHeaders; - - // authentication (RED-OAUTH) required - if (this.configuration.accessToken) { - const accessToken = - typeof this.configuration.accessToken === 'function' ? this.configuration.accessToken() : this.configuration.accessToken; - headers = headers.set('Authorization', 'Bearer ' + accessToken); - } - - // to determine the Accept header - const httpHeaderAccepts: string[] = ['application/json']; - const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts); - if (httpHeaderAcceptSelected !== undefined) { - headers = headers.set('Accept', httpHeaderAcceptSelected); - } - - return this.httpClient.request( - 'get', - `${this.basePath}/sectionGrid/${encodeURIComponent(String(dossierId))}/${encodeURIComponent(String(fileId))}/preview`, - { - withCredentials: this.configuration.withCredentials, - headers: headers, - observe: observe, - reportProgress: reportProgress - } - ); - } - /** * Gets the section grid for a fileId * None diff --git a/libs/red-ui-http/src/lib/model/dossier.ts b/libs/red-ui-http/src/lib/model/dossier.ts index 494e25386..e5f28bc68 100644 --- a/libs/red-ui-http/src/lib/model/dossier.ts +++ b/libs/red-ui-http/src/lib/model/dossier.ts @@ -23,7 +23,7 @@ export interface Dossier { memberIds?: Array; ownerId?: string; reportTemplateIds?: Array; - reportTypes?: Array; + reportTypes?: Array; softDeletedTime?: string; status?: Dossier.StatusEnum; watermarkEnabled?: boolean; @@ -38,19 +38,6 @@ export namespace Dossier { PREVIEW: 'PREVIEW' as DownloadFileTypesEnum, REDACTED: 'REDACTED' as DownloadFileTypesEnum }; - export type ReportTypesEnum = - | 'EXCEL_MULTI_FILE' - | 'EXCEL_SINGLE_FILE' - | 'WORD_SINGLE_FILE' - | 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' - | 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE'; - export const ReportTypesEnum = { - EXCELMULTIFILE: 'EXCEL_MULTI_FILE' as ReportTypesEnum, - EXCELSINGLEFILE: 'EXCEL_SINGLE_FILE' as ReportTypesEnum, - WORDSINGLEFILE: 'WORD_SINGLE_FILE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA1TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA2TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE' as ReportTypesEnum - }; export type StatusEnum = 'ACTIVE' | 'DELETED'; export const StatusEnum = { ACTIVE: 'ACTIVE' as StatusEnum, diff --git a/libs/red-ui-http/src/lib/model/dossierRequest.ts b/libs/red-ui-http/src/lib/model/dossierRequest.ts index e04bfe3f9..744fa20c5 100644 --- a/libs/red-ui-http/src/lib/model/dossierRequest.ts +++ b/libs/red-ui-http/src/lib/model/dossierRequest.ts @@ -57,7 +57,7 @@ export interface DossierRequest { /** * Report File Types for this dossiers submission package. */ - reportTypes?: Array; + reportTypes?: Array; /** * Whether a watermark will be applied to the redacted files or not. */ @@ -73,17 +73,4 @@ export namespace DossierRequest { PREVIEW: 'PREVIEW' as DownloadFileTypesEnum, REDACTED: 'REDACTED' as DownloadFileTypesEnum }; - export type ReportTypesEnum = - | 'EXCEL_MULTI_FILE' - | 'EXCEL_SINGLE_FILE' - | 'WORD_SINGLE_FILE' - | 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' - | 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE'; - export const ReportTypesEnum = { - EXCELMULTIFILE: 'EXCEL_MULTI_FILE' as ReportTypesEnum, - EXCELSINGLEFILE: 'EXCEL_SINGLE_FILE' as ReportTypesEnum, - WORDSINGLEFILE: 'WORD_SINGLE_FILE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA1TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA2TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE' as ReportTypesEnum - }; } diff --git a/libs/red-ui-http/src/lib/model/dossierTemplateModel.ts b/libs/red-ui-http/src/lib/model/dossierTemplateModel.ts index 4b3fcfdfb..77146e580 100644 --- a/libs/red-ui-http/src/lib/model/dossierTemplateModel.ts +++ b/libs/red-ui-http/src/lib/model/dossierTemplateModel.ts @@ -46,7 +46,7 @@ export interface DossierTemplateModel { /** * Report File Types for this dossierTemplate's dossiers submission package. */ - reportTypes?: Array; + reportTemplateIds?: string[]; /** * Validity of start this dossierTemplate. */ @@ -66,15 +66,4 @@ export namespace DossierTemplateModel { PREVIEW: 'PREVIEW' as DownloadFileTypesEnum, REDACTED: 'REDACTED' as DownloadFileTypesEnum }; - export type ReportTypesEnum = - | 'EXCEL_MULTI_FILE' - | 'EXCEL_SINGLE_FILE' - | 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' - | 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE'; - export const ReportTypesEnum = { - EXCELMULTIFILE: 'EXCEL_MULTI_FILE' as ReportTypesEnum, - EXCELSINGLEFILE: 'EXCEL_SINGLE_FILE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA1TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA2TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE' as ReportTypesEnum - }; } diff --git a/libs/red-ui-http/src/lib/model/downloadDetails.ts b/libs/red-ui-http/src/lib/model/downloadDetails.ts index 801cc4afc..4f5543a9f 100644 --- a/libs/red-ui-http/src/lib/model/downloadDetails.ts +++ b/libs/red-ui-http/src/lib/model/downloadDetails.ts @@ -14,7 +14,6 @@ export interface DownloadDetails { downloadFileTypes?: Array; fileIds?: Array; reportTemplateIds?: Array; - reportTypes?: Array; } export namespace DownloadDetails { @@ -26,17 +25,4 @@ export namespace DownloadDetails { PREVIEW: 'PREVIEW' as DownloadFileTypesEnum, REDACTED: 'REDACTED' as DownloadFileTypesEnum }; - export type ReportTypesEnum = - | 'EXCEL_MULTI_FILE' - | 'EXCEL_SINGLE_FILE' - | 'WORD_SINGLE_FILE' - | 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' - | 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE'; - export const ReportTypesEnum = { - EXCELMULTIFILE: 'EXCEL_MULTI_FILE' as ReportTypesEnum, - EXCELSINGLEFILE: 'EXCEL_SINGLE_FILE' as ReportTypesEnum, - WORDSINGLEFILE: 'WORD_SINGLE_FILE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA1TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE' as ReportTypesEnum, - WORDSINGLEFILEAPPENDIXA2TEMPLATE: 'WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE' as ReportTypesEnum - }; } diff --git a/libs/red-ui-http/src/lib/model/generalConfigurationModel.ts b/libs/red-ui-http/src/lib/model/generalConfigurationModel.ts index fdb3b9a7c..3b5b6d659 100644 --- a/libs/red-ui-http/src/lib/model/generalConfigurationModel.ts +++ b/libs/red-ui-http/src/lib/model/generalConfigurationModel.ts @@ -12,4 +12,5 @@ export interface GeneralConfigurationModel { forgotPasswordFunctionEnabled?: boolean; + displayName?: string; } diff --git a/libs/red-ui-http/src/lib/model/removeDownloadRequest.ts b/libs/red-ui-http/src/lib/model/removeDownloadRequest.ts index 11be360b1..87003df06 100644 --- a/libs/red-ui-http/src/lib/model/removeDownloadRequest.ts +++ b/libs/red-ui-http/src/lib/model/removeDownloadRequest.ts @@ -11,5 +11,5 @@ */ export interface RemoveDownloadRequest { - storageId?: string; + storageIds?: string[]; } diff --git a/package.json b/package.json index c4b8684a2..30b130935 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redaction", - "version": "2.129.0", + "version": "2.135.0", "private": true, "license": "MIT", "scripts": { diff --git a/paligo-theme.tar.gz b/paligo-theme.tar.gz index 253338b6d..07bdd8def 100644 Binary files a/paligo-theme.tar.gz and b/paligo-theme.tar.gz differ