Merge remote-tracking branch 'origin/master' into RED-1546

This commit is contained in:
Dan Percic 2021-07-23 13:27:20 +03:00
commit 0762dd3f62
66 changed files with 574 additions and 506 deletions

View File

@ -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'

View File

@ -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());
}
}

View File

@ -48,5 +48,3 @@
</div>
</div>
</section>
<redaction-full-page-loading-indicator [displayed]="!viewReady"></redaction-full-page-loading-indicator>

View File

@ -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<void> {
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();
}
}
}

View File

@ -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() {

View File

@ -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;
}

View File

@ -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],

View File

@ -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') }
]
};

View File

@ -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

View File

@ -72,24 +72,28 @@
<p class="download-includes">{{ 'download-includes' | translate }}</p>
<div class="d-flex">
<!-- only in edit mode-->
<redaction-select
*ngIf="dossierTemplate?.dossierTemplateId"
[label]="
'report-type.label'
| translate
: {
length: this.dossierTemplateForm.controls['reportTypes'].value.length
length: dossierTemplateForm.controls['reportTemplateIds'].value.length
}
"
[options]="reportTypes"
[optionTemplate]="reportTemplateOptionTemplate"
[options]="availableReportTypes"
[valueMapper]="reportTemplateValueMapper"
class="mr-16"
formControlName="reportTypes"
formControlName="reportTemplateIds"
></redaction-select>
<redaction-select
[label]="
'download-type.label'
| translate
: {
length: this.dossierTemplateForm.controls['downloadFileTypes'].value.length
length: dossierTemplateForm.controls['downloadFileTypes'].value.length
}
"
[options]="downloadTypes"
@ -107,3 +111,7 @@
<redaction-circle-button class="dialog-close" icon="red:close" mat-dialog-close></redaction-circle-button>
</section>
<ng-template #reportTemplateOptionTemplate let-option="option">
{{ option.fileName }}
</ng-template>

View File

@ -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<AddEditDossierTemplateDialogComponent>,
@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;

View File

@ -22,7 +22,7 @@ export class ActiveFieldsListingComponent extends BaseListingComponent<Field> 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);

View File

@ -32,6 +32,8 @@ export interface Field {
providers: [FilterService, SearchService, ScreenStateService, SortingService]
})
export class FileAttributesCsvImportDialogComponent extends BaseListingComponent<Field> {
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,

View File

@ -97,5 +97,3 @@
</div>
</div>
</section>
<redaction-full-page-loading-indicator [displayed]="processing"></redaction-full-page-loading-indicator>

View File

@ -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 = [];
}
);

View File

@ -10,10 +10,10 @@
<div class="actions">
<redaction-circle-button
*ngIf="permissionsService.isUser()"
[tooltip]="'common.close' | translate"
class="ml-6"
icon="red:close"
redactionNavigateLastDossiersScreen
tooltip="common.close"
tooltipPosition="below"
></redaction-circle-button>
</div>
@ -23,136 +23,151 @@
<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 class="heading-l" translate="general-config-screen.general.title"></div>
<div translate="general-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>
<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>
<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 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="smtp-config-screen.title"></div>
<div translate="smtp-config-screen.subtitle"></div>
<div class="heading-l" translate="general-config-screen.title"></div>
<div translate="general-config-screen.subtitle"></div>
</div>
<form (submit)="save()" [formGroup]="configForm">
<form (submit)="save()" [formGroup]="smtpForm">
<div class="dialog-content">
<div class="dialog-content-left">
<div class="red-input-group required">
<label translate="smtp-config-screen.form.host"></label>
<label translate="general-config-screen.form.host"></label>
<input
[placeholder]="'smtp-config-screen.form.host-placeholder' | translate"
formControlName="host"
name="host"
placeholder="{{ 'general-config-screen.form.host-placeholder' | translate }}"
type="text"
/>
</div>
<div class="red-input-group w-100">
<label translate="smtp-config-screen.form.port"></label>
<label translate="general-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>
<label translate="general-config-screen.form.from"></label>
<input
[placeholder]="'smtp-config-screen.form.from-placeholder' | translate"
formControlName="from"
name="from"
placeholder="{{ 'general-config-screen.form.from-placeholder' | translate }}"
type="email"
/>
</div>
<div class="red-input-group">
<label translate="smtp-config-screen.form.from-display-name"></label>
<label translate="general-config-screen.form.from-display-name"></label>
<input
[placeholder]="'smtp-config-screen.form.from-display-name-placeholder' | translate"
formControlName="fromDisplayName"
name="fromDisplayName"
placeholder="{{ 'general-config-screen.form.from-display-name-placeholder' | translate }}"
type="text"
/>
<span class="hint" translate="smtp-config-screen.form.from-display-name-hint"></span>
<span class="hint" translate="general-config-screen.form.from-display-name-hint"></span>
</div>
<div class="red-input-group">
<label translate="smtp-config-screen.form.reply-to"></label>
<label translate="general-config-screen.form.reply-to"></label>
<input
[placeholder]="'smtp-config-screen.form.reply-to-placeholder' | translate"
formControlName="replyTo"
name="replyTo"
placeholder="{{ 'general-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>
<label translate="general-config-screen.form.reply-to-display-name"></label>
<input
[placeholder]="'smtp-config-screen.form.reply-to-display-name-placeholder' | translate"
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="smtp-config-screen.form.envelope-from"></label>
<label translate="general-config-screen.form.envelope-from"></label>
<input
[placeholder]="'smtp-config-screen.form.envelope-from-placeholder' | translate"
formControlName="envelopeFrom"
name="envelopeFrom"
placeholder="{{ 'general-config-screen.form.envelope-from-placeholder' | translate }}"
type="text"
/>
<span class="hint" translate="smtp-config-screen.form.envelope-from-hint"></span>
<span class="hint" translate="general-config-screen.form.envelope-from-hint"></span>
</div>
</div>
<div>
<div class="red-input-group">
<label translate="smtp-config-screen.form.ssl"></label>
<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="smtp-config-screen.form.starttls"></label>
<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="smtp-config-screen.form.auth"></label>
<label translate="general-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"
*ngIf="smtpForm.get('auth').value"
class="link-action"
translate="smtp-config-screen.form.change-credentials"
translate="general-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
[disabled]="smtpForm.invalid || !smtpConfigurationChanged"
color="primary"
mat-flat-button
type="submit"
>
{{ 'general-config-screen.actions.save' | translate }}
</button>
<redaction-icon-button
(action)="testConnection()"
[disabled]="configForm.invalid"
[label]="'smtp-config-screen.actions.test-connection' | translate"
[disabled]="smtpForm.invalid"
[label]="'general-config-screen.actions.test-connection' | translate"
type="show-bg"
></redaction-icon-button>
</div>
@ -162,5 +177,3 @@
</div>
</div>
</section>
<redaction-full-page-loading-indicator [displayed]="!viewReady"></redaction-full-page-loading-indicator>

View File

@ -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();
}
}

View File

@ -33,5 +33,3 @@
</div>
</div>
</section>
<redaction-full-page-loading-indicator [displayed]="processing"></redaction-full-page-loading-indicator>

View File

@ -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<void> {
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()
);
}
}

View File

@ -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;
}
}
}

View File

@ -125,5 +125,3 @@
</div>
</div>
</section>
<redaction-full-page-loading-indicator [displayed]="!viewReady"></redaction-full-page-loading-indicator>

View File

@ -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();
});

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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));
});
}

View File

@ -0,0 +1,3 @@
import { ReplaySubject } from 'rxjs';
export const APP_BOOTSTRAPPED = new ReplaySubject<boolean>();

View File

@ -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();
});

View File

@ -1,6 +1,6 @@
<div *ngIf="screen === 'dossier-overview'" [class.active]="actionMenuOpen" class="action-buttons">
<ng-container *ngTemplateOutlet="actions"></ng-container>
<redaction-status-bar *ngIf="fileStatus.isWorkable" [config]="statusBarConfig"></redaction-status-bar>
<redaction-status-bar *ngIf="fileStatus?.isWorkable" [config]="statusBarConfig"></redaction-status-bar>
</div>
<ng-container *ngIf="screen === 'file-preview'">
@ -8,7 +8,7 @@
</ng-container>
<ng-template #actions>
<div class="file-actions">
<div class="file-actions" *ngIf="fileStatus">
<!-- delete-->
<redaction-circle-button
(action)="openDeleteFileDialog($event)"

View File

@ -138,7 +138,11 @@
>
<ng-container *ngIf="fileData?.fileStatus?.excludedPages?.includes(activeViewerPage)">
{{ 'file-preview.tabs.annotations.page-is' | translate }}
<a (click)="actionPerformed.emit('view-exclude-pages')" translate="file-preview.excluded-from-redaction">
<a
(click)="actionPerformed.emit('view-exclude-pages')"
class="with-underline"
translate="file-preview.excluded-from-redaction"
>
</a
>.
</ng-container>

View File

@ -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);
}
}

View File

@ -62,10 +62,12 @@
<p class="download-includes">{{ 'download-includes' | translate }}</p>
<div class="d-flex">
<redaction-select
[label]="'report-type.label' | translate: { length: reportTypesLength }"
[options]="reportTypes"
[label]="'report-type.label' | translate: { length: reportTemplateIdsLength }"
[options]="availableReportTypes"
[optionTemplate]="reportTemplateOptionTemplate"
[valueMapper]="reportTemplateValueMapper"
class="mr-16"
formControlName="reportTypes"
formControlName="reportTemplateIds"
></redaction-select>
<redaction-select
[label]="'download-type.label' | translate: { length: downloadFileTypesLength }"
@ -92,3 +94,7 @@
<redaction-circle-button class="dialog-close" icon="red:close" mat-dialog-close></redaction-circle-button>
</section>
<ng-template #reportTemplateOptionTemplate let-option="option">
{{ option.fileName }}
</ng-template>

View File

@ -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<AddDossierDialogComponent>
) {
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
};
}

View File

@ -1,9 +1,11 @@
<form [formGroup]="dossierForm">
<form [formGroup]="dossierForm" *ngIf="dossierForm">
<redaction-select
[label]="'report-type.label' | translate: { length: reportTypesLength }"
[options]="reportTypes"
[options]="availableReportTypes"
[valueMapper]="reportTemplateValueMapper"
[optionTemplate]="reportTemplateOptionTemplate"
class="mr-16"
formControlName="reportTypes"
formControlName="reportTemplateIds"
></redaction-select>
<redaction-select
[label]="'download-type.label' | translate: { length: downloadFileTypesLength }"
@ -11,3 +13,7 @@
formControlName="downloadFileTypes"
></redaction-select>
</form>
<ng-template #reportTemplateOptionTemplate let-option="option">
{{ option.fileName }}
</ng-template>

View File

@ -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<any>();
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
});
}
}

View File

@ -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;

View File

@ -137,8 +137,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>

View File

@ -101,32 +101,35 @@ export class DossierOverviewScreenComponent
}
async ngOnInit(): Promise<void> {
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 {

View File

@ -29,7 +29,7 @@
</div>
</div>
<div *ngIf="viewReady" class="flex-1 actions-container">
<div class="flex-1 actions-container">
<ng-container *ngIf="!appStateService.activeFile.isExcluded">
<ng-container *ngIf="!appStateService.activeFile.isProcessing">
<redaction-status-bar [config]="statusBarConfig" [small]="true"></redaction-status-bar>
@ -89,7 +89,6 @@
<redaction-file-actions
(actionPerformed)="fileActionPerformed($event)"
*ngIf="viewReady"
[activeDocumentInfo]="viewDocumentInfo"
[activeExcludePages]="excludePages"
></redaction-file-actions>
@ -149,7 +148,7 @@
<div class="right-container">
<redaction-empty-state
*ngIf="viewReady && appStateService.activeFile.isExcluded && !viewDocumentInfo && !excludePages"
*ngIf="appStateService.activeFile.isExcluded && !viewDocumentInfo && !excludePages"
[horizontalPadding]="40"
[text]="'file-preview.tabs.is-excluded' | translate"
icon="red:needs-work"
@ -157,7 +156,7 @@
<redaction-document-info
(closeDocumentInfoView)="viewDocumentInfo = false"
*ngIf="viewReady && viewDocumentInfo"
*ngIf="viewDocumentInfo"
[file]="fileData.fileStatus.fileStatus"
></redaction-document-info>
@ -187,8 +186,6 @@
</div>
</section>
<redaction-full-page-loading-indicator [displayed]="!viewReady"></redaction-full-page-loading-indicator>
<ng-template #annotationActionsTemplate let-annotation="annotation">
<redaction-annotation-actions
(annotationsChanged)="annotationsChangedByReviewAction($event)"

View File

@ -55,7 +55,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme
fileData: FileDataModel;
annotationData: AnnotationData;
selectedAnnotations: AnnotationWrapper[];
viewReady = false;
primaryFilters: FilterModel[];
secondaryFilters: FilterModel[];
canPerformAnnotationActions: boolean;
@ -93,6 +92,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribeComponent impleme
private readonly _translateService: TranslateService
) {
super();
this._loadingService.start();
document.documentElement.addEventListener('fullscreenchange', () => {
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 (<html>) 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') {

View File

@ -24,7 +24,8 @@ export class FileActionService {
}
return this._reanalysisControllerService.reanalyzeFile(
this._appStateService.activeDossier.dossier.dossierId,
fileStatusWrapper.fileId
fileStatusWrapper.fileId,
true
);
}

View File

@ -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({})));

View File

@ -7,7 +7,20 @@
</div>
<mat-chip-list [disabled]="disabled" [multiple]="multiple" class="options flex-center" selectable>
<mat-chip #chip="matChip" (click)="toggleSelection(chip)" *ngFor="let option of options" [value]="option.key">
{{ option.label | translate }}
<mat-chip
#chip="matChip"
(click)="toggleSelection(chip)"
(selectionChange)="selectChange($event)"
*ngFor="let option of options"
[value]="valueMapper(option)"
>
<ng-container
[ngTemplateOutlet]="optionTemplate ?? defaultOptionTemplate"
[ngTemplateOutletContext]="{ option: option }"
></ng-container>
</mat-chip>
</mat-chip-list>
<ng-template #defaultOptionTemplate let-option="option">
{{ option.label | translate }}
</ng-template>

View File

@ -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<any>;
@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);
}
}

View File

@ -13,7 +13,9 @@ export interface SortingOption {
column: string;
}
@Injectable()
@Injectable({
providedIn: 'root'
})
export class SortingService {
private _sortingOption: SortingOption;

View File

@ -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(
{

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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')
};

View File

@ -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;

View File

@ -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);

View File

@ -1024,7 +1024,7 @@
},
"title": "Aktivieren Sie die Authentifizierung"
},
"smtp-config-screen": {
"general-config-screen": {
"actions": {
"save": "Konfigurationen speichern",
"test-connection": "Testverbindung"

View File

@ -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",

View File

@ -9,6 +9,12 @@ a {
color: lighten($primary, 10%);
}
&.with-underline {
&:hover {
text-decoration: underline;
}
}
cursor: pointer;
}

View File

@ -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),

View File

@ -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"'",

View File

@ -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<RedactionLog>;
public getRedactionLogPreview(
dossierId: string,
fileId: string,
observe?: 'response',
reportProgress?: boolean
): Observable<HttpResponse<RedactionLog>>;
public getRedactionLogPreview(
dossierId: string,
fileId: string,
observe?: 'events',
reportProgress?: boolean
): Observable<HttpEvent<RedactionLog>>;
public getRedactionLogPreview(
dossierId: string,
fileId: string,
observe: any = 'body',
reportProgress: boolean = false
): Observable<any> {
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<RedactionLog>(
'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

View File

@ -23,7 +23,7 @@ export interface Dossier {
memberIds?: Array<string>;
ownerId?: string;
reportTemplateIds?: Array<string>;
reportTypes?: Array<Dossier.ReportTypesEnum>;
reportTypes?: Array<string>;
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,

View File

@ -57,7 +57,7 @@ export interface DossierRequest {
/**
* Report File Types for this dossiers submission package.
*/
reportTypes?: Array<DossierRequest.ReportTypesEnum>;
reportTypes?: Array<string>;
/**
* 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
};
}

View File

@ -46,7 +46,7 @@ export interface DossierTemplateModel {
/**
* Report File Types for this dossierTemplate's dossiers submission package.
*/
reportTypes?: Array<DossierTemplateModel.ReportTypesEnum>;
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
};
}

View File

@ -14,7 +14,6 @@ export interface DownloadDetails {
downloadFileTypes?: Array<DownloadDetails.DownloadFileTypesEnum>;
fileIds?: Array<string>;
reportTemplateIds?: Array<string>;
reportTypes?: Array<DownloadDetails.ReportTypesEnum>;
}
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
};
}

View File

@ -12,4 +12,5 @@
export interface GeneralConfigurationModel {
forgotPasswordFunctionEnabled?: boolean;
displayName?: string;
}

View File

@ -11,5 +11,5 @@
*/
export interface RemoveDownloadRequest {
storageId?: string;
storageIds?: string[];
}

View File

@ -1,6 +1,6 @@
{
"name": "redaction",
"version": "2.129.0",
"version": "2.135.0",
"private": true,
"license": "MIT",
"scripts": {

Binary file not shown.