Edit dossier attributes WIP

This commit is contained in:
Adina Țeudan 2021-07-14 16:32:37 +03:00
parent e3beeae0e3
commit efa4e76f62
48 changed files with 527 additions and 871 deletions

View File

@ -4,7 +4,7 @@ import { AppStateService } from '@state/app-state.service';
import { Router } from '@angular/router';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { DossierTemplateControllerService } from '@redaction/red-ui-http';
import { LoadingService } from '../../../../services/loading.service';
import { LoadingService } from '@services/loading.service';
@Component({
selector: 'redaction-dossier-template-actions',
@ -33,22 +33,15 @@ export class DossierTemplateActionsComponent {
}
openEditDossierTemplateDialog($event: any) {
this._dialogService.openDialog(
'addEditDossierTemplate',
$event,
this.dossierTemplate,
() => {
this.loadDossierTemplatesData?.emit();
}
);
this._dialogService.openDialog('addEditDossierTemplate', $event, this.dossierTemplate, () => {
this.loadDossierTemplatesData?.emit();
});
}
openDeleteDossierTemplateDialog($event?: MouseEvent) {
this._dialogService.openDialog('confirm', $event, null, async () => {
this._loadingService.start();
await this._dossierTemplateControllerService
.deleteDossierTemplates([this.dossierTemplateId])
.toPromise();
await this._dossierTemplateControllerService.deleteDossierTemplates([this.dossierTemplateId]).toPromise();
await this._appStateService.loadAllDossierTemplates();
await this._appStateService.loadDictionaryData();
await this._router.navigate(['main', 'admin']);

View File

@ -5,7 +5,7 @@ import { DictionaryControllerService, TypeValue } from '@redaction/red-ui-http';
import { Observable } from 'rxjs';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { TypeValueWrapper } from '../../../../models/file/type-value.wrapper';
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
import { humanize } from '../../../../utils/functions';
@Component({
@ -78,11 +78,7 @@ export class AddEditDictionaryDialogComponent {
if (this.dictionary) {
// edit mode
observable = this._dictionaryControllerService.updateType(
typeValue,
this._dossierTemplateId,
typeValue.type
);
observable = this._dictionaryControllerService.updateType(typeValue, this._dossierTemplateId, typeValue.type);
} else {
// create mode
typeValue.dossierTemplateId = this._dossierTemplateId;
@ -104,11 +100,7 @@ export class AddEditDictionaryDialogComponent {
}
private _notifyError(message: string) {
this._notificationService.showToastNotification(
this._translateService.instant(message),
null,
NotificationType.ERROR
);
this._notificationService.showToastNotification(this._translateService.instant(message), null, NotificationType.ERROR);
}
private _formToObject(): TypeValue {

View File

@ -1,11 +1,11 @@
import { Component, Inject } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DossierAttributeConfig, DossierAttributesControllerService, FileAttributeConfig } from '@redaction/red-ui-http';
import { AppStateService } from '../../../../state/app-state.service';
import { AppStateService } from '@state/app-state.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { LoadingService } from '../../../../services/loading.service';
import { ErrorMessageService } from '../../../../services/error-message.service';
import { NotificationService, NotificationType } from '../../../../services/notification.service';
import { LoadingService } from '@services/loading.service';
import { ErrorMessageService } from '@services/error-message.service';
import { NotificationService, NotificationType } from '@services/notification.service';
import { HttpErrorResponse } from '@angular/common/http';
@Component({

View File

@ -1,8 +1,8 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { User, UserControllerService } from '@redaction/red-ui-http';
import { UserService } from '../../../../../services/user.service';
import { LoadingService } from '../../../../../services/loading.service';
import { UserService } from '@services/user.service';
import { LoadingService } from '@services/loading.service';
@Component({
selector: 'redaction-reset-password',

View File

@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { User, UserControllerService } from '@redaction/red-ui-http';
import { AdminDialogService } from '../../../services/admin-dialog.service';
import { LoadingService } from '../../../../../services/loading.service';
import { LoadingService } from '@services/loading.service';
@Component({
selector: 'redaction-user-details',
@ -64,10 +64,7 @@ export class UserDetailsComponent implements OnInit {
disabled:
this.user &&
Object.keys(this._ROLE_REQUIREMENTS).reduce(
(value, key) =>
value ||
(role === this._ROLE_REQUIREMENTS[key] &&
this.user.roles.indexOf(key) !== -1),
(value, key) => value || (role === this._ROLE_REQUIREMENTS[key] && this.user.roles.indexOf(key) !== -1),
false
)
}
@ -79,7 +76,10 @@ export class UserDetailsComponent implements OnInit {
firstName: [this.user?.firstName, Validators.required],
lastName: [this.user?.lastName, Validators.required],
email: [
{ value: this.user?.email, disabled: !!this.user },
{
value: this.user?.email,
disabled: !!this.user
},
[Validators.required, Validators.email]
],
...rolesControls

View File

@ -2,7 +2,7 @@ import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { User, UserControllerService } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { LoadingService } from '../../../../services/loading.service';
import { LoadingService } from '@services/loading.service';
@Component({
selector: 'redaction-confirm-delete-users-dialog',
@ -45,9 +45,7 @@ export class ConfirmDeleteUsersDialogComponent {
async deleteUser() {
if (this.valid) {
this._loadingService.start();
await this._userControllerService
.deleteUsers(this.users.map(u => u.userId))
.toPromise();
await this._userControllerService.deleteUsers(this.users.map(u => u.userId)).toPromise();
this.dialogRef.close(true);
} else {
this.showToast = true;

View File

@ -1,19 +1,11 @@
import {
Component,
EventEmitter,
Injector,
Input,
OnChanges,
Output,
SimpleChanges
} from '@angular/core';
import { Component, EventEmitter, Injector, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { Field } from '../file-attributes-csv-import-dialog.component';
import { FileAttributeConfig } from '@redaction/red-ui-http';
import { FilterService } from '../../../../shared/services/filter.service';
import { SearchService } from '../../../../shared/services/search.service';
import { ScreenStateService } from '../../../../shared/services/screen-state.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { SortingService } from '../../../../../services/sorting.service';
import { BaseListingComponent } from '../../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
@Component({
selector: 'redaction-active-fields-listing',
@ -27,11 +19,7 @@ export class ActiveFieldsListingComponent extends BaseListingComponent<Field> im
@Output() setHoveredColumn = new EventEmitter<string>();
@Output() toggleFieldActive = new EventEmitter<Field>();
readonly typeOptions = [
FileAttributeConfig.TypeEnum.TEXT,
FileAttributeConfig.TypeEnum.NUMBER,
FileAttributeConfig.TypeEnum.DATE
];
readonly typeOptions = [FileAttributeConfig.TypeEnum.TEXT, FileAttributeConfig.TypeEnum.NUMBER, FileAttributeConfig.TypeEnum.DATE];
constructor(protected readonly _injector: Injector) {
super(_injector);
@ -47,12 +35,8 @@ export class ActiveFieldsListingComponent extends BaseListingComponent<Field> im
}
deactivateSelection() {
this.allEntities
.filter(field => this.isSelected(field))
.forEach(field => (field.primaryAttribute = false));
this._screenStateService.setEntities([
...this.allEntities.filter(field => !this.isSelected(field))
]);
this.allEntities.filter(field => this.isSelected(field)).forEach(field => (field.primaryAttribute = false));
this._screenStateService.setEntities([...this.allEntities.filter(field => !this.isSelected(field))]);
this.entitiesChange.emit(this.allEntities);
this._screenStateService.setSelectedEntitiesIds([]);
}

View File

@ -3,20 +3,16 @@ import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from
import { AppStateService } from '@state/app-state.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import * as Papa from 'papaparse';
import {
FileAttributeConfig,
FileAttributesConfig,
FileAttributesControllerService
} from '@redaction/red-ui-http';
import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http';
import { Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
export interface Field {
id?: string;
@ -70,10 +66,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
this.dossierTemplateId = data.dossierTemplateId;
this.baseConfigForm = this._formBuilder.group({
filenameMappingColumnHeaderName: [
'',
[Validators.required, this._autocompleteStringValidator()]
],
filenameMappingColumnHeaderName: ['', [Validators.required, this._autocompleteStringValidator()]],
delimiter: [undefined, Validators.required],
encoding: ['UTF-8', Validators.required]
});
@ -103,16 +96,12 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
this.parseResult.meta.fields = Object.keys(this.parseResult.data[0]);
}
this._screenStateService.setEntities(
this.parseResult.meta.fields.map(field => this._buildAttribute(field))
);
this._screenStateService.setEntities(this.parseResult.meta.fields.map(field => this._buildAttribute(field)));
this._screenStateService.setDisplayedEntities(this.allEntities);
this.activeFields = [];
for (const entity of this.allEntities) {
const existing = this.data.existingConfiguration.fileAttributeConfigs.find(
a => a.csvColumnHeader === entity.csvColumn
);
const existing = this.data.existingConfiguration.fileAttributeConfigs.find(a => a.csvColumnHeader === entity.csvColumn);
if (existing) {
entity.id = existing.id;
entity.name = existing.label;
@ -124,34 +113,21 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
}
}
this.filteredKeyOptions = this.baseConfigForm
.get('filenameMappingColumnHeaderName')
.valueChanges.pipe(
startWith(
this.baseConfigForm.get('filenameMappingColumnHeaderName').value as string
),
map((value: string) =>
this.allEntities
.filter(
field =>
field.csvColumn.toLowerCase().indexOf(value.toLowerCase()) !==
-1
)
.map(field => field.csvColumn)
)
);
this.filteredKeyOptions = this.baseConfigForm.get('filenameMappingColumnHeaderName').valueChanges.pipe(
startWith(this.baseConfigForm.get('filenameMappingColumnHeaderName').value as string),
map((value: string) =>
this.allEntities
.filter(field => field.csvColumn.toLowerCase().indexOf(value.toLowerCase()) !== -1)
.map(field => field.csvColumn)
)
);
if (
this.data.existingConfiguration &&
this.allEntities.find(
entity =>
entity.csvColumn ===
this.data.existingConfiguration.filenameMappingColumnHeaderName
)
this.allEntities.find(entity => entity.csvColumn === this.data.existingConfiguration.filenameMappingColumnHeaderName)
) {
this.baseConfigForm.patchValue({
filenameMappingColumnHeaderName:
this.data.existingConfiguration.filenameMappingColumnHeaderName
filenameMappingColumnHeaderName: this.data.existingConfiguration.filenameMappingColumnHeaderName
});
}
@ -206,9 +182,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
const newPrimary = !!this.activeFields.find(attr => attr.primaryAttribute);
if (newPrimary) {
this.data.existingConfiguration.fileAttributeConfigs.forEach(
attr => (attr.primaryAttribute = false)
);
this.data.existingConfiguration.fileAttributeConfigs.forEach(attr => (attr.primaryAttribute = false));
}
const fileAttributes = {
@ -229,9 +203,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
};
try {
await this._fileAttributesControllerService
.setFileAttributesConfig(fileAttributes, this.dossierTemplateId)
.toPromise();
await this._fileAttributesControllerService.setFileAttributesConfig(fileAttributes, this.dossierTemplateId).toPromise();
this._notificationService.showToastNotification(
this._translateService.instant('file-attributes-csv-import.save.success', {
count: this.activeFields.length
@ -260,9 +232,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
if (!column) {
this.columnSample = [];
} else {
this.columnSample = this.parseResult.data
.filter(row => !!row[column])
.map(row => row[column]);
this.columnSample = this.parseResult.data.filter(row => !!row[column]).map(row => row[column]);
}
}, 0);
}
@ -283,9 +253,7 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent
csvColumn,
name: csvColumn,
temporaryName: csvColumn,
type: isNumber
? FileAttributeConfig.TypeEnum.NUMBER
: FileAttributeConfig.TypeEnum.TEXT,
type: isNumber ? FileAttributeConfig.TypeEnum.NUMBER : FileAttributeConfig.TypeEnum.TEXT,
readonly: false,
primaryAttribute: false
};

View File

@ -4,12 +4,12 @@ import { Colors, DictionaryControllerService } from '@redaction/red-ui-http';
import { ActivatedRoute } from '@angular/router';
import { PermissionsService } from '@services/permissions.service';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { LoadingService } from '../../../../services/loading.service';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { LoadingService } from '@services/loading.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { ScreenNames, SortingService } from '@services/sorting.service';
import { BaseListingComponent } from '@shared/base/base-listing.component';
@Component({
templateUrl: './default-colors-screen.component.html',
@ -60,9 +60,7 @@ export class DefaultColorsScreenComponent
private async _loadColors() {
this._loadingService.start();
const data = await this._dictionaryControllerService
.getColors(this._appStateService.activeDossierTemplateId)
.toPromise();
const data = await this._dictionaryControllerService.getColors(this._appStateService.activeDossierTemplateId).toPromise();
this._colorsObj = data;
this._screenStateService.setEntities(
Object.keys(data).map(key => ({

View File

@ -6,15 +6,15 @@ import { catchError, defaultIfEmpty, tap } from 'rxjs/operators';
import { forkJoin, of } from 'rxjs';
import { PermissionsService } from '@services/permissions.service';
import { ActivatedRoute } from '@angular/router';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { TypeValueWrapper } from '../../../../models/file/type-value.wrapper';
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
import { TranslateService } from '@ngx-translate/core';
import { LoadingService } from '../../../../services/loading.service';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { LoadingService } from '@services/loading.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { ScreenNames, SortingService } from '@services/sorting.service';
import { BaseListingComponent } from '@shared/base/base-listing.component';
import { AdminDialogService } from '../../services/admin-dialog.service';
const toChartConfig = (dict: TypeValueWrapper): DoughnutChartConfig => ({
value: dict.entries ? dict.entries.length : 0,
@ -28,10 +28,7 @@ const toChartConfig = (dict: TypeValueWrapper): DoughnutChartConfig => ({
styleUrls: ['./dictionary-listing-screen.component.scss'],
providers: [FilterService, SearchService, ScreenStateService, SortingService]
})
export class DictionaryListingScreenComponent
extends BaseListingComponent<TypeValueWrapper>
implements OnInit
{
export class DictionaryListingScreenComponent extends BaseListingComponent<TypeValueWrapper> implements OnInit {
chartData: DoughnutChartConfig[] = [];
constructor(
@ -56,15 +53,10 @@ export class DictionaryListingScreenComponent
this._loadDictionaryData();
}
openDeleteDictionariesDialog(
$event?: MouseEvent,
types = this._screenStateService.selectedEntitiesIds
) {
openDeleteDictionariesDialog($event?: MouseEvent, types = this._screenStateService.selectedEntitiesIds) {
this._dialogService.openDialog('confirm', $event, null, async () => {
this._loadingService.start();
await this._dictionaryControllerService
.deleteTypes(types, this._appStateService.activeDossierTemplateId)
.toPromise();
await this._dictionaryControllerService.deleteTypes(types, this._appStateService.activeDossierTemplateId).toPromise();
this._screenStateService.setSelectedEntitiesIds([]);
await this._appStateService.loadDictionaryData();
this._loadDictionaryData(false);
@ -92,8 +84,7 @@ export class DictionaryListingScreenComponent
}
private _loadDictionaryData(loadEntries = true): void {
const appStateDictionaryData =
this._appStateService.dictionaryData[this._appStateService.activeDossierTemplateId];
const appStateDictionaryData = this._appStateService.dictionaryData[this._appStateService.activeDossierTemplateId];
const entities = Object.values(appStateDictionaryData).filter(d => !d.virtual);
if (!loadEntries)
@ -110,16 +101,14 @@ export class DictionaryListingScreenComponent
if (!loadEntries) return;
const dataObs = this.allEntities.map(dict =>
this._dictionaryControllerService
.getDictionaryForType(this._appStateService.activeDossierTemplateId, dict.type)
.pipe(
tap(values => (dict.entries = values.entries ?? [])),
catchError(() => {
console.log('error');
dict.entries = [];
return of({});
})
)
this._dictionaryControllerService.getDictionaryForType(this._appStateService.activeDossierTemplateId, dict.type).pipe(
tap(values => (dict.entries = values.entries ?? [])),
catchError(() => {
console.log('error');
dict.entries = [];
return of({});
})
)
);
forkJoin(dataObs)

View File

@ -9,8 +9,8 @@ import { ComponentHasChanges } from '@guards/can-deactivate.guard';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
import { DictionarySaveService } from '@shared/services/dictionary-save.service';
import { TypeValueWrapper } from '../../../../models/file/type-value.wrapper';
import { LoadingService } from '../../../../services/loading.service';
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
import { LoadingService } from '@services/loading.service';
@Component({
selector: 'redaction-dictionary-overview-screen',
@ -75,9 +75,7 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
$event?.stopPropagation();
this._dialogService.openDialog('confirm', $event, null, async () => {
await this._dictionaryControllerService
.deleteTypes([this.dictionary.type], this.dictionary.dossierTemplateId)
.toPromise();
await this._dictionaryControllerService.deleteTypes([this.dictionary.type], this.dictionary.dossierTemplateId).toPromise();
await this._appStateService.loadDictionaryData();
await this._router.navigate([
'/main',
@ -113,13 +111,7 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
saveEntries(entries: string[]) {
this.processing = true;
this._dictionarySaveService
.saveEntries(
entries,
this.entries,
this.dictionary.dossierTemplateId,
this.dictionary.type,
null
)
.saveEntries(entries, this.entries, this.dictionary.dossierTemplateId, this.dictionary.type, null)
.subscribe(
() => {
this.processing = false;
@ -133,19 +125,15 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
private _loadEntries() {
this.processing = true;
this._dictionaryControllerService
.getDictionaryForType(this.dictionary.dossierTemplateId, this.dictionary.type)
.subscribe(
data => {
this.processing = false;
this.entries = data.entries.sort((str1, str2) =>
str1.localeCompare(str2, undefined, { sensitivity: 'accent' })
);
},
() => {
this.processing = false;
this.entries = [];
}
);
this._dictionaryControllerService.getDictionaryForType(this.dictionary.dossierTemplateId, this.dictionary.type).subscribe(
data => {
this.processing = false;
this.entries = data.entries.sort((str1, str2) => str1.localeCompare(str2, undefined, { sensitivity: 'accent' }));
},
() => {
this.processing = false;
this.entries = [];
}
);
}
}

View File

@ -1,14 +1,14 @@
import { Component, Injector, OnInit } from '@angular/core';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
import { DossierAttributeConfig, DossierAttributesControllerService } from '@redaction/red-ui-http';
import { AppStateService } from '../../../../state/app-state.service';
import { AppStateService } from '@state/app-state.service';
import { ActivatedRoute } from '@angular/router';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { LoadingService } from '../../../../services/loading.service';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { PermissionsService } from '@services/permissions.service';
@Component({

View File

@ -6,11 +6,11 @@ import { AdminDialogService } from '../../services/admin-dialog.service';
import { DossierTemplateModelWrapper } from '../../../../models/file/dossier-template-model.wrapper';
import { LoadingService } from '../../../../services/loading.service';
import { DossierTemplateControllerService } from '@redaction/red-ui-http';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
@Component({
templateUrl: './dossier-templates-listing-screen.component.html',
@ -18,10 +18,7 @@ import { BaseListingComponent } from '../../../shared/base/base-listing.componen
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [FilterService, SearchService, ScreenStateService, SortingService]
})
export class DossierTemplatesListingScreenComponent
extends BaseListingComponent<DossierTemplateModelWrapper>
implements OnInit
{
export class DossierTemplatesListingScreenComponent extends BaseListingComponent<DossierTemplateModelWrapper> implements OnInit {
constructor(
private readonly _dialogService: AdminDialogService,
private readonly _appStateService: AppStateService,
@ -44,9 +41,7 @@ export class DossierTemplatesListingScreenComponent
openDeleteTemplatesDialog($event?: MouseEvent) {
return this._dialogService.openDialog('confirm', $event, null, async () => {
this._loadingService.start();
await this._dossierTemplateControllerService
.deleteDossierTemplates(this._screenStateService.selectedEntitiesIds)
.toPromise();
await this._dossierTemplateControllerService.deleteDossierTemplates(this._screenStateService.selectedEntitiesIds).toPromise();
this._screenStateService.setSelectedEntitiesIds([]);
await this._appStateService.loadAllDossierTemplates();
await this._appStateService.loadDictionaryData();
@ -64,16 +59,11 @@ export class DossierTemplatesListingScreenComponent
}
openAddDossierTemplateDialog() {
this._dialogService.openDialog(
'addEditDossierTemplate',
null,
null,
async newDossierTemplate => {
if (newDossierTemplate) {
this.loadDossierTemplatesData();
}
this._dialogService.openDialog('addEditDossierTemplate', null, null, async newDossierTemplate => {
if (newDossierTemplate) {
this.loadDossierTemplatesData();
}
);
});
}
private _loadDossierTemplateStats() {

View File

@ -1,22 +1,15 @@
import {
ChangeDetectionStrategy,
Component,
ElementRef,
Injector,
OnInit,
ViewChild
} from '@angular/core';
import { ChangeDetectionStrategy, Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { ActivatedRoute } from '@angular/router';
import { AdminDialogService } from '../../services/admin-dialog.service';
import { LoadingService } from '../../../../services/loading.service';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
@Component({
templateUrl: './file-attributes-listing-screen.component.html',
@ -24,10 +17,7 @@ import { BaseListingComponent } from '../../../shared/base/base-listing.componen
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [FilterService, SearchService, ScreenStateService, SortingService]
})
export class FileAttributesListingScreenComponent
extends BaseListingComponent<FileAttributeConfig>
implements OnInit
{
export class FileAttributesListingScreenComponent extends BaseListingComponent<FileAttributeConfig> implements OnInit {
private _existingConfiguration: FileAttributesConfig;
@ViewChild('fileInput') private _fileInput: ElementRef;
@ -75,10 +65,7 @@ export class FileAttributesListingScreenComponent
.toPromise();
} else {
await this._fileAttributesService
.deleteFileAttributes(
this._screenStateService.selectedEntitiesIds,
this._appStateService.activeDossierTemplateId
)
.deleteFileAttributes(this._screenStateService.selectedEntitiesIds, this._appStateService.activeDossierTemplateId)
.toPromise();
}
await this._loadData();

View File

@ -1,6 +1,6 @@
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AppStateService } from '../../../../state/app-state.service';
import { AppStateService } from '@state/app-state.service';
import { ReportTemplate, ReportTemplateControllerService } from '@redaction/red-ui-http';
import { download } from '../../../../utils/file-download-utils';
import { AdminDialogService } from '../../services/admin-dialog.service';

View File

@ -5,11 +5,11 @@ import { Dossier, StatusControllerService } from '@redaction/red-ui-http';
import { LoadingService } from '../../../../services/loading.service';
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
import * as moment from 'moment';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
import { DossiersService } from '../../../dossier/services/dossiers.service';
@Component({

View File

@ -1,11 +1,4 @@
import {
ChangeDetectionStrategy,
Component,
Injector,
OnInit,
QueryList,
ViewChildren
} from '@angular/core';
import { ChangeDetectionStrategy, Component, Injector, OnInit, QueryList, ViewChildren } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { UserService } from '@services/user.service';
import { User, UserControllerService } from '@redaction/red-ui-http';
@ -14,12 +7,12 @@ import { TranslateService } from '@ngx-translate/core';
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
import { TranslateChartService } from '@services/translate-chart.service';
import { LoadingService } from '../../../../services/loading.service';
import { InitialsAvatarComponent } from '../../../shared/components/initials-avatar/initials-avatar.component';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { InitialsAvatarComponent } from '@shared/components/initials-avatar/initials-avatar.component';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@ -86,9 +79,7 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
}
bulkDelete() {
this.openDeleteUsersDialog(
this._screenStateService.entities.filter(u => this.isSelected(u))
);
this.openDeleteUsersDialog(this._screenStateService.entities.filter(u => this.isSelected(u)));
}
trackById(index: number, user: User) {
@ -96,9 +87,7 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
}
private async _loadData() {
this._screenStateService.setEntities(
await this._userControllerService.getAllUsers().toPromise()
);
this._screenStateService.setEntities(await this._userControllerService.getAllUsers().toPromise());
await this.userService.loadAllUsers();
this.filterService.filterEntities();
this._computeStats();
@ -114,38 +103,27 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
label: 'INACTIVE'
},
{
value: this.allEntities.filter(
user => user.roles.length === 1 && user.roles[0] === 'RED_USER'
).length,
value: this.allEntities.filter(user => user.roles.length === 1 && user.roles[0] === 'RED_USER').length,
color: 'REGULAR',
label: 'REGULAR'
},
{
value: this.allEntities.filter(
user => this.userService.isManager(user) && !this.userService.isAdmin(user)
).length,
value: this.allEntities.filter(user => this.userService.isManager(user) && !this.userService.isAdmin(user)).length,
color: 'MANAGER',
label: 'RED_MANAGER'
},
{
value: this.allEntities.filter(
user => this.userService.isManager(user) && this.userService.isAdmin(user)
).length,
value: this.allEntities.filter(user => this.userService.isManager(user) && this.userService.isAdmin(user)).length,
color: 'MANAGER_ADMIN',
label: 'MANAGER_ADMIN'
},
{
value: this.allEntities.filter(
user =>
this.userService.isUserAdmin(user) && !this.userService.isAdmin(user)
).length,
value: this.allEntities.filter(user => this.userService.isUserAdmin(user) && !this.userService.isAdmin(user)).length,
color: 'USER_ADMIN',
label: 'RED_USER_ADMIN'
},
{
value: this.allEntities.filter(
user => this.userService.isAdmin(user) && !this.userService.isManager(user)
).length,
value: this.allEntities.filter(user => this.userService.isAdmin(user) && !this.userService.isManager(user)).length,
color: 'ADMIN',
label: 'RED_ADMIN'
}

View File

@ -11,7 +11,7 @@ import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-
import { ConfirmDeleteUsersDialogComponent } from '../dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
import { FileAttributesCsvImportDialogComponent } from '../dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
import { ComponentType } from '@angular/cdk/portal';
import { DialogService } from '../../shared/services/dialog.service';
import { DialogService } from '@shared/services/dialog.service';
import { AddEditDossierAttributeDialogComponent } from '../dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component';
type DialogType =

View File

@ -1,18 +1,15 @@
import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { UserService } from '@services/user.service';
import {
FileManagementControllerService,
ReanalysisControllerService
} from '@redaction/red-ui-http';
import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http';
import { PermissionsService } from '@services/permissions.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { FileActionService } from '../../services/file-action.service';
import { from, Observable } from 'rxjs';
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { LoadingService } from '../../../../services/loading.service';
import { ConfirmationDialogInput } from '../../../shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { LoadingService } from '@services/loading.service';
import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
@Component({
selector: 'redaction-dossier-overview-bulk-actions',
@ -44,10 +41,7 @@ export class DossierOverviewBulkActionsComponent {
get selectedFiles(): FileStatusWrapper[] {
return this.selectedFileIds.map(fileId =>
this._appStateService.getFileById(
this._appStateService.activeDossier.dossier.dossierId,
fileId
)
this._appStateService.getFileById(this._appStateService.activeDossier.dossier.dossierId, fileId)
);
}
@ -69,10 +63,7 @@ export class DossierOverviewBulkActionsComponent {
(acc, file) => acc && (file.isUnderReview || file.isUnassigned),
true
);
const allFilesAreUnderApproval = selectedFiles.reduce(
(acc, file) => acc && file.isUnderApproval,
true
);
const allFilesAreUnderApproval = selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
return allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval;
}
return false;
@ -81,42 +72,27 @@ export class DossierOverviewBulkActionsComponent {
get canAssignToSelf() {
return (
this.allSelectedFilesCanBeAssignedIntoSameState &&
this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canAssignToSelf(file),
true
)
this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canAssignToSelf(file), true)
);
}
get canAssign() {
return (
this.allSelectedFilesCanBeAssignedIntoSameState &&
this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canAssignUser(file),
true
)
this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canAssignUser(file), true)
);
}
get canDelete() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canDeleteFile(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canDeleteFile(file), true);
}
get canReanalyse() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canReanalyseFile(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canReanalyseFile(file), true);
}
get canOcr() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canOcrFile(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canOcrFile(file), true);
}
get fileStatuses() {
@ -125,51 +101,31 @@ export class DossierOverviewBulkActionsComponent {
// Under review
get canSetToUnderReview() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canSetUnderReview(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true);
}
// Under approval
get canSetToUnderApproval() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canSetUnderApproval(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true);
}
// Approve
get isReadyForApproval() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.isReadyForApproval(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true);
}
get canApprove() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canApprove(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canApprove(file), true);
}
// Undo approval
get canUndoApproval() {
return this.selectedFiles.reduce(
(acc, file) => acc && this._permissionsService.canUndoApproval(file),
true
);
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true);
}
get assignTooltip() {
const allFilesAreUnderApproval = this.selectedFiles.reduce(
(acc, file) => acc && file.isUnderApproval,
true
);
return allFilesAreUnderApproval
? 'dossier-overview.assign-approver'
: 'dossier-overview.assign-reviewer';
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
return allFilesAreUnderApproval ? 'dossier-overview.assign-approver' : 'dossier-overview.assign-reviewer';
}
delete() {
@ -212,23 +168,15 @@ export class DossierOverviewBulkActionsComponent {
);
} else {
this._performBulkAction(
this._fileActionService.setFileUnderApproval(
this.selectedFiles,
this._appStateService.activeDossier.approverIds[0]
)
this._fileActionService.setFileUnderApproval(this.selectedFiles, this._appStateService.activeDossier.approverIds[0])
);
}
}
async reanalyse() {
const fileIds = this.selectedFiles
.filter(file => this._permissionsService.fileRequiresReanalysis(file))
.map(file => file.fileId);
const fileIds = this.selectedFiles.filter(file => this._permissionsService.fileRequiresReanalysis(file)).map(file => file.fileId);
this._performBulkAction(
this._reanalysisControllerService.reanalyzeFilesForDossier(
fileIds,
this._appStateService.activeDossier.dossierId
)
this._reanalysisControllerService.reanalyzeFilesForDossier(fileIds, this._appStateService.activeDossier.dossierId)
);
}
@ -250,9 +198,7 @@ export class DossierOverviewBulkActionsComponent {
assign() {
this._loadingService.start();
const files = this.selectedFileIds.map(fileId =>
this._appStateService.getFileById(this._appStateService.activeDossierId, fileId)
);
const files = this.selectedFileIds.map(fileId => this._appStateService.getFileById(this._appStateService.activeDossierId, fileId));
const mode = files[0].isUnderApproval ? 'approver' : 'reviewer';

View File

@ -8,7 +8,7 @@ import { StatusSorter } from '@utils/sorters/status-sorter';
import { UserService } from '@services/user.service';
import { User } from '@redaction/red-ui-http';
import { NotificationService } from '@services/notification.service';
import { FilterService } from '../../../shared/services/filter.service';
import { FilterService } from '@shared/services/filter.service';
import { FileStatusWrapper } from '../../../../models/file/file-status.wrapper';
@Component({
@ -70,9 +70,7 @@ export class DossierDetailsComponent implements OnInit {
});
}
this.documentsChartData.sort((a, b) => StatusSorter[a.key] - StatusSorter[b.key]);
this.documentsChartData = this.translateChartService.translateStatus(
this.documentsChartData
);
this.documentsChartData = this.translateChartService.translateStatus(this.documentsChartData);
this._changeDetectorRef.detectChanges();
}

View File

@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
import { AppStateService } from '@state/app-state.service';
import { FilterService } from '../../../shared/services/filter.service';
import { FilterService } from '@shared/services/filter.service';
@Component({
selector: 'redaction-dossier-listing-details',
@ -13,8 +13,5 @@ export class DossierListingDetailsComponent<T> {
@Input() dossiersChartData: DoughnutChartConfig[];
@Input() documentsChartData: DoughnutChartConfig[];
constructor(
readonly appStateService: AppStateService,
readonly filterService: FilterService<T>
) {}
constructor(readonly appStateService: AppStateService, readonly filterService: FilterService<T>) {}
}

View File

@ -4,8 +4,8 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { AppStateService } from '@state/app-state.service';
import { FileActionService } from '../../services/file-action.service';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { ConfirmationDialogInput } from '../../../shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { LoadingService } from '../../../../services/loading.service';
import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { LoadingService } from '@services/loading.service';
import { FileManagementControllerService } from '@redaction/red-ui-http';
@Component({
@ -48,9 +48,7 @@ export class FileActionsComponent implements OnInit {
return 'file-preview.toggle-analysis.only-managers';
}
return this.fileStatus?.isExcluded
? 'file-preview.toggle-analysis.enable'
: 'file-preview.toggle-analysis.disable';
return this.fileStatus?.isExcluded ? 'file-preview.toggle-analysis.enable' : 'file-preview.toggle-analysis.disable';
}
get canAssignToSelf() {
@ -86,9 +84,7 @@ export class FileActionsComponent implements OnInit {
}
get assignTooltip() {
return this.fileStatus.isUnderApproval
? 'dossier-overview.assign-approver'
: 'dossier-overview.assign-reviewer';
return this.fileStatus.isUnderApproval ? 'dossier-overview.assign-approver' : 'dossier-overview.assign-reviewer';
}
ngOnInit(): void {
@ -124,9 +120,7 @@ export class FileActionsComponent implements OnInit {
}),
async () => {
this._loadingService.start();
await this._fileManagementControllerService
.deleteFiles([this.fileStatus.fileId], this.fileStatus.dossierId)
.toPromise();
await this._fileManagementControllerService.deleteFiles([this.fileStatus.fileId], this.fileStatus.dossierId).toPromise();
await this.appStateService.reloadActiveDossierFiles();
this.actionPerformed.emit('delete');
this._loadingService.stop();
@ -162,11 +156,7 @@ export class FileActionsComponent implements OnInit {
setFileUnderApproval($event: MouseEvent) {
$event.stopPropagation();
if (this.appStateService.activeDossier.approverIds.length > 1) {
this._fileActionService.assignDossierApprover(
this.fileStatus,
() => this.actionPerformed.emit('assign-reviewer'),
true
);
this._fileActionService.assignDossierApprover(this.fileStatus, () => this.actionPerformed.emit('assign-reviewer'), true);
} else {
this._fileActionService.setFileUnderApproval(this.fileStatus).subscribe(() => {
this.reloadDossiers('set-under-approval');
@ -206,8 +196,6 @@ export class FileActionsComponent implements OnInit {
async toggleAnalysis() {
await this._fileActionService.toggleAnalysis(this.fileStatus).toPromise();
await this.appStateService.getFiles();
this.actionPerformed.emit(
this.fileStatus?.isExcluded ? 'enable-analysis' : 'disable-analysis'
);
this.actionPerformed.emit(this.fileStatus?.isExcluded ? 'enable-analysis' : 'disable-analysis');
}
}

View File

@ -19,7 +19,7 @@ import { debounce } from '@utils/debounce';
import { FileDataModel } from '@models/file/file-data.model';
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
import { CommentsComponent } from '../comments/comments.component';
import { PermissionsService } from '../../../../services/permissions.service';
import { PermissionsService } from '@services/permissions.service';
import { TranslateService } from '@ngx-translate/core';
import { WebViewerInstance } from '@pdftron/webviewer';

View File

@ -1,10 +1,10 @@
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { PermissionsService } from '../../../../services/permissions.service';
import { PermissionsService } from '@services/permissions.service';
import { FormBuilder, FormGroup } from '@angular/forms';
import { PageRange, ReanalysisControllerService } from '@redaction/red-ui-http';
import { FileDataModel } from '../../../../models/file/file-data.model';
import { NotificationService, NotificationType } from '../../../../services/notification.service';
import { LoadingService } from '../../../../services/loading.service';
import { FileDataModel } from '@models/file/file-data.model';
import { NotificationService, NotificationType } from '@services/notification.service';
import { LoadingService } from '@services/loading.service';
import { TranslateService } from '@ngx-translate/core';
@Component({
@ -34,9 +34,7 @@ export class PageExclusionComponent implements OnChanges {
ngOnChanges(changes: SimpleChanges) {
if (changes.fileData) {
const excludedPages = (this.fileData?.fileStatus?.excludedPages || []).sort(
(p1, p2) => p1 - p2
);
const excludedPages = (this.fileData?.fileStatus?.excludedPages || []).sort((p1, p2) => p1 - p2);
this.excludedPagesRanges = excludedPages.reduce((ranges, page) => {
if (!ranges.length) {
return [{ startPage: page, endPage: page }];

View File

@ -24,12 +24,12 @@ import { AnnotationActionsService } from '../../services/annotation-actions.serv
import { UserPreferenceService } from '@services/user-preference.service';
import { BASE_HREF } from '../../../../tokens';
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
import { LoadingService } from '../../../../services/loading.service';
import { LoadingService } from '@services/loading.service';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { ConfirmationDialogInput } from '../../../shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { loadCompareDocumentWrapper } from '../../utils/compare-mode.utils';
import { PdfViewerUtils } from '../../utils/pdf-viewer.utils';
import { ViewMode } from '../../../../models/file/view-mode';
import { ViewMode } from '@models/file/view-mode';
import TextTool = Tools.TextTool;
@Component({
@ -105,9 +105,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
// viewer init
this.instance.setFitMode('FitPage');
const instanceDisplayMode = this.instance.docViewer
.getDisplayModeManager()
.getDisplayMode();
const instanceDisplayMode = this.instance.docViewer.getDisplayModeManager().getDisplayMode();
instanceDisplayMode.mode = this.viewMode === 'STANDARD' ? 'Single' : 'Facing';
this.instance.docViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode);
}
@ -123,15 +121,11 @@ export class PdfViewerComponent implements OnInit, OnChanges {
const pdfData = fileReader.result;
const PDFNet = this.instance.PDFNet;
await PDFNet.initialize(
environment.licenseKey ? atob(environment.licenseKey) : null
);
await PDFNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null);
const mergedDocument = await PDFNet.PDFDoc.create();
const compareDocument = await PDFNet.PDFDoc.createFromBuffer(<any>pdfData);
const currentDocument = await PDFNet.PDFDoc.createFromBuffer(
await this.fileData.arrayBuffer()
);
const currentDocument = await PDFNet.PDFDoc.createFromBuffer(await this.fileData.arrayBuffer());
const currentDocumentPageCount = await currentDocument.getPageCount();
const compareDocumentPageCount = await compareDocument.getPageCount();
@ -186,9 +180,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
this.viewMode = 'STANDARD';
const PDFNet = this.instance.PDFNet;
await PDFNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null);
const currentDocument = await PDFNet.PDFDoc.createFromBuffer(
await this.fileData.arrayBuffer()
);
const currentDocument = await PDFNet.PDFDoc.createFromBuffer(await this.fileData.arrayBuffer());
this.instance.loadDocument(currentDocument, {
filename: this.fileStatus ? this.fileStatus.filename : 'document.pdf'
});
@ -221,16 +213,12 @@ export class PdfViewerComponent implements OnInit, OnChanges {
this._configureTextPopup();
this.instance.annotManager.on('annotationSelected', (annotations, action) => {
this.annotationSelected.emit(
this.instance.annotManager.getSelectedAnnotations().map(ann => ann.Id)
);
this.annotationSelected.emit(this.instance.annotManager.getSelectedAnnotations().map(ann => ann.Id));
if (action === 'deselected') {
this._toggleRectangleAnnotationAction(true);
} else {
this._configureAnnotationSpecificActions(annotations);
this._toggleRectangleAnnotationAction(
annotations.length === 1 && annotations[0].ReadOnly
);
this._toggleRectangleAnnotationAction(annotations.length === 1 && annotations[0].ReadOnly);
}
});
@ -238,10 +226,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
// when a rectangle is drawn,
// it returns one annotation with tool name 'AnnotationCreateRectangle;
// this will auto select rectangle after drawing
if (
annotations.length === 1 &&
annotations[0].ToolName === 'AnnotationCreateRectangle'
) {
if (annotations.length === 1 && annotations[0].ToolName === 'AnnotationCreateRectangle') {
this.instance.annotManager.selectAnnotations(annotations);
}
});
@ -284,9 +269,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
this.instance.iframeWindow.addEventListener('visibilityChanged', (event: any) => {
if (event.detail.element === 'searchPanel') {
const inputElement = this.instance.iframeWindow.document.getElementById(
'SearchPanel__input'
) as HTMLInputElement;
const inputElement = this.instance.iframeWindow.document.getElementById('SearchPanel__input') as HTMLInputElement;
setTimeout(() => {
inputElement.value = '';
}, 0);
@ -364,9 +347,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
type: 'actionButton',
element: 'closeCompare',
dataElement: 'closeCompareButton',
img: this._convertPath(
'/assets/icons/general/pdftron-action-close-compare.svg'
),
img: this._convertPath('/assets/icons/general/pdftron-action-close-compare.svg'),
title: 'Leave Compare Mode',
onClick: () => {
this.closeCompareMode();
@ -394,9 +375,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
return;
}
const annotationWrappers = viewerAnnotations
.map(va => this.annotations.find(a => a.id === va.Id))
.filter(va => !!va);
const annotationWrappers = viewerAnnotations.map(va => this.annotations.find(a => a.id === va.Id)).filter(va => !!va);
this.instance.annotationPopup.update([]);
if (annotationWrappers.length === 0) {
@ -405,15 +384,9 @@ export class PdfViewerComponent implements OnInit, OnChanges {
}
// Add hide action as last item
const allAnnotationsHaveImageAction = annotationWrappers.reduce(
(acc, next) => acc && next.isImage,
true
);
const allAnnotationsHaveImageAction = annotationWrappers.reduce((acc, next) => acc && next.isImage, true);
if (allAnnotationsHaveImageAction) {
const allAreVisible = viewerAnnotations.reduce(
(acc, next) => next.isVisible() && acc,
true
);
const allAreVisible = viewerAnnotations.reduce((acc, next) => next.isVisible() && acc, true);
this.instance.annotationPopup.add([
{
@ -437,10 +410,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
}
this.instance.annotationPopup.add(
this._annotationActionsService.getViewerAvailableActions(
annotationWrappers,
this.annotationsChanged
)
this._annotationActionsService.getViewerAvailableActions(annotationWrappers, this.annotationsChanged)
);
}
@ -449,17 +419,12 @@ export class PdfViewerComponent implements OnInit, OnChanges {
type: 'actionButton',
dataElement: 'add-rectangle',
img: this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'),
title: this._translateService.instant(
this._manualAnnotationService.getTitle('REDACTION')
),
title: this._translateService.instant(this._manualAnnotationService.getTitle('REDACTION')),
onClick: () => {
const selectedAnnotations = this.instance.annotManager.getSelectedAnnotations();
const activeAnnotation = selectedAnnotations[0];
const activePage = selectedAnnotations[0].getPageNumber();
const quad = this._annotationDrawService.annotationToQuads(
activeAnnotation,
this.instance
);
const quad = this._annotationDrawService.annotationToQuads(activeAnnotation, this.instance);
const quadsObject = {};
quadsObject[activePage] = [quad];
const mre = this._getManualRedactionEntry(quadsObject, 'Rectangle');
@ -469,13 +434,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
this.instance.enableElements(['shapeToolGroupButton', 'rectangleToolDivider']);
// dispatch event
this.manualAnnotationRequested.emit(
new ManualRedactionEntryWrapper(
[quad],
mre,
'REDACTION',
'RECTANGLE',
activeAnnotation.Id
)
new ManualRedactionEntryWrapper([quad], mre, 'REDACTION', 'RECTANGLE', activeAnnotation.Id)
);
}
});
@ -509,19 +468,13 @@ export class PdfViewerComponent implements OnInit, OnChanges {
type: 'actionButton',
dataElement: 'add-false-positive',
img: this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg'),
title: this._translateService.instant(
this._manualAnnotationService.getTitle('FALSE_POSITIVE')
),
title: this._translateService.instant(this._manualAnnotationService.getTitle('FALSE_POSITIVE')),
onClick: () => {
const selectedQuads = this.instance.docViewer.getSelectedTextQuads();
const text = this.instance.docViewer.getSelectedText();
const mre = this._getManualRedactionEntry(selectedQuads, text, true);
this.manualAnnotationRequested.emit(
new ManualRedactionEntryWrapper(
this.instance.docViewer.getSelectedTextQuads(),
mre,
'FALSE_POSITIVE'
)
new ManualRedactionEntryWrapper(this.instance.docViewer.getSelectedTextQuads(), mre, 'FALSE_POSITIVE')
);
}
});
@ -531,19 +484,13 @@ export class PdfViewerComponent implements OnInit, OnChanges {
type: 'actionButton',
dataElement: 'add-dictionary',
img: this._convertPath('/assets/icons/general/pdftron-action-add-dict.svg'),
title: this._translateService.instant(
this._manualAnnotationService.getTitle('DICTIONARY')
),
title: this._translateService.instant(this._manualAnnotationService.getTitle('DICTIONARY')),
onClick: () => {
const selectedQuads = this.instance.docViewer.getSelectedTextQuads();
const text = this.instance.docViewer.getSelectedText();
const mre = this._getManualRedactionEntry(selectedQuads, text, true);
this.manualAnnotationRequested.emit(
new ManualRedactionEntryWrapper(
this.instance.docViewer.getSelectedTextQuads(),
mre,
'DICTIONARY'
)
new ManualRedactionEntryWrapper(this.instance.docViewer.getSelectedTextQuads(), mre, 'DICTIONARY')
);
}
});
@ -552,19 +499,13 @@ export class PdfViewerComponent implements OnInit, OnChanges {
type: 'actionButton',
dataElement: 'add-redaction',
img: this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'),
title: this._translateService.instant(
this._manualAnnotationService.getTitle('REDACTION')
),
title: this._translateService.instant(this._manualAnnotationService.getTitle('REDACTION')),
onClick: () => {
const selectedQuads = this.instance.docViewer.getSelectedTextQuads();
const text = this.instance.docViewer.getSelectedText();
const mre = this._getManualRedactionEntry(selectedQuads, text, true);
this.manualAnnotationRequested.emit(
new ManualRedactionEntryWrapper(
this.instance.docViewer.getSelectedTextQuads(),
mre,
'REDACTION'
)
new ManualRedactionEntryWrapper(this.instance.docViewer.getSelectedTextQuads(), mre, 'REDACTION')
);
}
});
@ -600,22 +541,13 @@ export class PdfViewerComponent implements OnInit, OnChanges {
}
}
private _getManualRedactionEntry(
quads: any,
text: string,
convertQuads: boolean = false
): ManualRedactionEntry {
private _getManualRedactionEntry(quads: any, text: string, convertQuads: boolean = false): ManualRedactionEntry {
text = text.replace(/-\n/gi, '');
const entry: ManualRedactionEntry = { positions: [] };
for (const key of Object.keys(quads)) {
for (const quad of quads[key]) {
const page = parseInt(key, 10);
entry.positions.push(
this.utils.toPosition(
page,
convertQuads ? this.utils.translateQuads(page, quad) : quad
)
);
entry.positions.push(this.utils.toPosition(page, convertQuads ? this.utils.translateQuads(page, quad) : quad));
}
}
entry.value = text;

View File

@ -4,8 +4,8 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { LegalBasisMappingControllerService } from '@redaction/red-ui-http';
import { AppStateService } from '../../../../state/app-state.service';
import { PermissionsService } from '../../../../services/permissions.service';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
export interface LegalBasisOption {
label?: string;

View File

@ -1,10 +1,10 @@
import { Component, Inject, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DossierWrapper } from '../../../../state/model/dossier.wrapper';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
import { DictionarySaveService } from '@shared/services/dictionary-save.service';
import { AppStateService } from '../../../../state/app-state.service';
import { PermissionsService } from '../../../../services/permissions.service';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
@Component({
selector: 'redaction-dossier-dictionary-dialog',
@ -23,9 +23,7 @@ export class DossierDictionaryDialogComponent {
private readonly _appStateService: AppStateService,
private readonly _dictionarySaveService: DictionarySaveService
) {
this.canEdit =
this.permissionsService.isDossierMember(this.dossier) ||
this.permissionsService.isAdmin();
this.canEdit = this.permissionsService.isDossierMember(this.dossier) || this.permissionsService.isAdmin();
}
saveDossierDictionary() {
@ -39,10 +37,7 @@ export class DossierDictionaryDialogComponent {
)
.subscribe(async () => {
await this._appStateService.reloadActiveDossierFiles();
this._appStateService.updateDossierDictionary(
this.dossier.dossierTemplateId,
this.dossier.dossierId
);
this._appStateService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.dossierId);
this.dialogRef.close();
});
}

View File

@ -0,0 +1,21 @@
<form *ngIf="attributesForm" [formGroup]="attributesForm">
<div>
<div class="heading">
{{ 'edit-dossier-dialog.nav-items.custom-dossier-attributes' | translate }}
</div>
<div *ngFor="let attr of customAttributes" class="red-input-group w-300">
<label>{{ attr.label }}</label>
<input [formControlName]="attr.id" [name]="attr.id" type="text" />
</div>
</div>
<div class="separator"></div>
<div>
<div class="heading">
{{ 'edit-dossier-dialog.nav-items.image-attributes' | translate }}
</div>
<div *ngFor="let attr of imageAttributes" class="red-input-group w-300">
<label>{{ attr.label }}</label>
<input [formControlName]="attr.id" [name]="attr.id" type="text" />
</div>
</div>
</form>

View File

@ -0,0 +1,24 @@
@import '../../../../../../assets/styles/red-variables';
:host {
display: flex;
min-height: 100%;
form {
display: flex;
flex: 1;
> div {
flex: 1;
padding: 24px 32px;
}
.separator {
flex: none;
height: 100%;
width: 1px;
padding: 0;
background-color: $separator;
}
}
}

View File

@ -0,0 +1,97 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
import { DossierAttributeConfig, DossierAttributesControllerService } from '@redaction/red-ui-http';
import { LoadingService } from '@services/loading.service';
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'redaction-edit-dossier-attributes',
templateUrl: './edit-dossier-attributes.component.html',
styleUrls: ['./edit-dossier-attributes.component.scss']
})
export class EditDossierAttributesComponent implements EditDossierSectionInterface, OnInit {
@Input() dossierWrapper: DossierWrapper;
@Output() updateDossier = new EventEmitter<any>();
customAttributes: (DossierAttributeConfig & { value: any })[] = [];
imageAttributes: (DossierAttributeConfig & { value: any })[] = [];
attributesMapping: (DossierAttributeConfig & { value: any })[] = [];
attributesForm: FormGroup;
constructor(
private readonly _appStateService: AppStateService,
private readonly _permissionsService: PermissionsService,
private readonly _dossierAttributesService: DossierAttributesControllerService,
private readonly _loadingService: LoadingService,
private readonly _formBuilder: FormBuilder
) {}
get changed() {
for (const attr of this.attributesMapping) {
if (this._parseAttrValue(attr.value) !== this._parseAttrValue(this.attributesForm.get(attr.id).value)) {
return true;
}
}
return false;
}
get disabled() {
return !this._permissionsService.isOwner(this.dossierWrapper);
}
async ngOnInit() {
this._loadingService.start();
await this._loadAttributes();
this._initForm();
this._loadingService.stop();
}
async save() {
this._loadingService.start();
const dossierAttributeList = this.attributesMapping.map(attr => ({
dossierAttributeId: attr.id,
value: this.attributesForm.get(attr.id).value
}));
await this._dossierAttributesService.setDossierAttributes({ dossierAttributeList }, this.dossierWrapper.dossierId).toPromise();
await this._loadAttributes();
this._loadingService.stop();
}
updatedDossier($event) {
this.updateDossier.emit($event);
}
revert() {
this._initForm();
}
private _parseAttrValue(value: any) {
return [null, undefined, ''].includes(value) ? undefined : value;
}
private async _loadAttributes() {
const attributes = await this._dossierAttributesService.getDossierAttributes(this.dossierWrapper.dossierId).toPromise();
const attributesConfig = await this._dossierAttributesService
.getDossierAttributesConfig(this.dossierWrapper.dossierTemplateId)
.toPromise();
this.attributesMapping = attributesConfig.dossierAttributeConfigs.map(config => ({
...config,
value: attributes.dossierAttributeList.find(attr => attr.dossierAttributeId === config.id)?.value
}));
this.customAttributes = this.attributesMapping.filter(attr => attr.type !== 'IMAGE');
this.imageAttributes = this.attributesMapping.filter(attr => attr.type === 'IMAGE');
}
private _initForm() {
const controlsConfig = {};
for (const attribute of this.attributesMapping) {
controlsConfig[attribute.id] = attribute.value;
}
this.attributesForm = this._formBuilder.group(controlsConfig);
}
}

View File

@ -1,8 +1,8 @@
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { AppStateService } from '../../../../../state/app-state.service';
import { DossierWrapper } from '../../../../../state/model/dossier.wrapper';
import { AppStateService } from '@state/app-state.service';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { PermissionsService } from '../../../../../services/permissions.service';
import { PermissionsService } from '@services/permissions.service';
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
import { DictionarySaveService } from '@shared/services/dictionary-save.service';
@ -23,9 +23,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
private readonly _dictionarySaveService: DictionarySaveService,
private readonly _permissionsService: PermissionsService
) {
this.canEdit =
this._permissionsService.isDossierMember(this.dossierWrapper) ||
this._permissionsService.isAdmin();
this.canEdit = this._permissionsService.isDossierMember(this.dossierWrapper) || this._permissionsService.isAdmin();
}
get changed() {
@ -47,10 +45,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
false
)
.subscribe(async () => {
this._appStateService.updateDossierDictionary(
this.dossierWrapper.dossierTemplateId,
this.dossierWrapper.dossierId
);
this._appStateService.updateDossierDictionary(this.dossierWrapper.dossierTemplateId, this.dossierWrapper.dossierId);
this.updateDossier.emit();
});
}

View File

@ -1,8 +1,8 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { DossierTemplateModel } 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 { AppStateService } from '@state/app-state.service';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
@Component({
@ -19,10 +19,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
@Input() dossierWrapper: DossierWrapper;
@Output() updateDossier = new EventEmitter<any>();
constructor(
private readonly _appStateService: AppStateService,
private readonly _formBuilder: FormBuilder
) {}
constructor(private readonly _appStateService: AppStateService, private readonly _formBuilder: FormBuilder) {}
get reportTypesLength() {
return this.dossierForm.controls['reportTypes']?.value?.length || 0;
@ -34,9 +31,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
get changed() {
for (const key of Object.keys(this.dossierForm.getRawValue())) {
if (
this.dossierWrapper.dossier[key].length !== this.dossierForm.get(key).value.length
) {
if (this.dossierWrapper.dossier[key].length !== this.dossierForm.get(key).value.length) {
return true;
}
@ -65,10 +60,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
},
{
validators: control =>
control.value.reportTypes?.length > 0 ||
control.value.downloadFileTypes?.length > 0
? null
: { downloadPackage: true }
control.value.reportTypes?.length > 0 || control.value.downloadFileTypes?.length > 0 ? null : { downloadPackage: true }
}
);
}

View File

@ -14,23 +14,16 @@
></div>
</redaction-side-nav>
<div>
<div class="content">
<div class="heading">
{{
'edit-dossier-dialog.nav-items.' +
(activeNavItem.title || activeNavItem.key) | translate
}}
<div [class.no-padding]="noPaddingTab" class="content">
<div *ngIf="showHeading" class="heading">
{{ 'edit-dossier-dialog.nav-items.' + (activeNavItem.title || activeNavItem.key) | translate }}
<div
*ngIf="activeNav === 'dossier-dictionary'"
class="small-label stats-subtitle"
>
<div *ngIf="showSubtitle" class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:entries"></mat-icon>
{{
'edit-dossier-dialog.dictionary.entries'
| translate
: { length: (dossierWrapper.type?.entries || []).length }
| translate: { length: (dossierWrapper.type?.entries || []).length }
}}
</div>
</div>
@ -59,6 +52,12 @@
*ngIf="activeNav === 'members'"
[dossierWrapper]="dossierWrapper"
></redaction-edit-dossier-team-members>
<redaction-edit-dossier-attributes
(updateDossier)="updatedDossier($event)"
*ngIf="activeNav === 'dossier-attributes'"
[dossierWrapper]="dossierWrapper"
></redaction-edit-dossier-attributes>
</div>
<div class="dialog-actions">
@ -71,18 +70,10 @@
{{ 'edit-dossier-dialog.actions.save' | translate }}
</button>
<div
(click)="revert()"
class="all-caps-label cancel"
translate="edit-dossier-dialog.actions.revert"
></div>
<div (click)="revert()" class="all-caps-label cancel" translate="edit-dossier-dialog.actions.revert"></div>
</div>
</div>
</div>
<redaction-circle-button
class="dialog-close"
icon="red:close"
mat-dialog-close
></redaction-circle-button>
<redaction-circle-button class="dialog-close" icon="red:close" mat-dialog-close></redaction-circle-button>
</section>

View File

@ -18,7 +18,11 @@
height: calc(100% - 81px);
box-sizing: border-box;
.heading {
&.no-padding {
padding: 0;
}
::ng-deep .heading {
margin-bottom: 24px;
}
}

View File

@ -6,12 +6,13 @@ import { DossierWrapper } from '../../../../state/model/dossier.wrapper';
import { EditDossierGeneralInfoComponent } from './general-info/edit-dossier-general-info.component';
import { EditDossierDownloadPackageComponent } from './download-package/edit-dossier-download-package.component';
import { EditDossierSectionInterface } from './edit-dossier-section.interface';
import { NotificationService, NotificationType } from '../../../../services/notification.service';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component';
import { EditDossierTeamMembersComponent } from './team-members/edit-dossier-team-members.component';
import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component';
type Section = 'dossier-info' | 'download-package' | 'dossier-dictionary' | 'members';
type Section = 'dossier-info' | 'download-package' | 'dossier-dictionary' | 'members' | 'dossier-attributes';
@Component({
templateUrl: './edit-dossier-dialog.component.html',
@ -22,20 +23,19 @@ export class EditDossierDialogComponent {
{ key: 'dossier-info', title: 'general-info' },
{ key: 'download-package', title: 'choose-download' },
{ key: 'dossier-dictionary', title: 'dossier-dictionary' },
{ key: 'members', title: 'team-members' }
{ key: 'members', title: 'team-members' },
{ key: 'dossier-attributes' }
// TODO:
// { key: 'dossier-attributes' },
// { key: 'report-attributes' }
];
activeNav: Section;
dossierWrapper: DossierWrapper;
@ViewChild(EditDossierGeneralInfoComponent)
generalInfoComponent: EditDossierGeneralInfoComponent;
@ViewChild(EditDossierDownloadPackageComponent)
downloadPackageComponent: EditDossierDownloadPackageComponent;
@ViewChild(EditDossierGeneralInfoComponent) generalInfoComponent: EditDossierGeneralInfoComponent;
@ViewChild(EditDossierDownloadPackageComponent) downloadPackageComponent: EditDossierDownloadPackageComponent;
@ViewChild(EditDossierDictionaryComponent) dictionaryComponent: EditDossierDictionaryComponent;
@ViewChild(EditDossierTeamMembersComponent) membersComponent: EditDossierTeamMembersComponent;
@ViewChild(EditDossierAttributesComponent) attributesComponent: EditDossierAttributesComponent;
constructor(
private readonly _appStateService: AppStateService,
@ -64,10 +64,23 @@ export class EditDossierDialogComponent {
'dossier-info': this.generalInfoComponent,
'download-package': this.downloadPackageComponent,
'dossier-dictionary': this.dictionaryComponent,
members: this.membersComponent
members: this.membersComponent,
'dossier-attributes': this.attributesComponent
}[this.activeNav];
}
get noPaddingTab(): boolean {
return ['dossier-attributes'].includes(this.activeNav);
}
get showHeading(): boolean {
return !['dossier-attributes'].includes(this.activeNav);
}
get showSubtitle(): boolean {
return ['dossier-dictionary'].includes(this.activeNav);
}
updatedDossier(updatedDossier: DossierWrapper) {
this._notificationService.showToastNotification(
this._translateService.instant('edit-dossier-dialog.change-successful'),

View File

@ -6,14 +6,11 @@ import * as moment from 'moment';
import { DossierWrapper } from '../../../../../state/model/dossier.wrapper';
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import { PermissionsService } from '../../../../../services/permissions.service';
import { PermissionsService } from '@services/permissions.service';
import { Router } from '@angular/router';
import { MatDialogRef } from '@angular/material/dialog';
import { EditDossierDialogComponent } from '../edit-dossier-dialog.component';
import {
NotificationService,
NotificationType
} from '../../../../../services/notification.service';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
@Component({
@ -47,12 +44,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
if (this.hasDueDate !== !!this.dossierWrapper.dueDate) {
return true;
}
if (
this.hasDueDate &&
!moment(this.dossierWrapper.dueDate).isSame(
moment(this.dossierForm.get(key).value)
)
) {
if (this.hasDueDate && !moment(this.dossierWrapper.dueDate).isSame(moment(this.dossierForm.get(key).value))) {
return true;
}
} else if (this.dossierWrapper[key] !== this.dossierForm.get(key).value) {

View File

@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core
import { AppStateService } from '../../../../../state/app-state.service';
import { DossierWrapper } from '../../../../../state/model/dossier.wrapper';
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { PermissionsService } from '../../../../../services/permissions.service';
import { PermissionsService } from '@services/permissions.service';
import { TeamMembersManagerComponent } from '../../../components/team-members-manager/team-members-manager.component';
@Component({
@ -16,10 +16,7 @@ export class EditDossierTeamMembersComponent implements EditDossierSectionInterf
@ViewChild(TeamMembersManagerComponent) managerComponent: TeamMembersManagerComponent;
constructor(
private readonly _appStateService: AppStateService,
private readonly _permissionsService: PermissionsService
) {}
constructor(private readonly _appStateService: AppStateService, private readonly _permissionsService: PermissionsService) {}
get changed() {
return this.managerComponent.changed;

View File

@ -10,7 +10,7 @@ import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry
import { ManualAnnotationService } from '../../services/manual-annotation.service';
import { ManualAnnotationResponse } from '@models/file/manual-annotation-response';
import { PermissionsService } from '@services/permissions.service';
import { TypeValueWrapper } from '../../../../models/file/type-value.wrapper';
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
export interface LegalBasisOption {
label?: string;
@ -76,8 +76,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
this.isDocumentAdmin = this._permissionsService.isApprover();
this.isFalsePositiveRequest = this.manualRedactionEntryWrapper.type === 'FALSE_POSITIVE';
this.isDictionaryRequest =
this.manualRedactionEntryWrapper.type === 'DICTIONARY' || this.isFalsePositiveRequest;
this.isDictionaryRequest = this.manualRedactionEntryWrapper.type === 'DICTIONARY' || this.isFalsePositiveRequest;
this.redactionForm = this._formBuilder.group({
reason: this.isDictionaryRequest ? [null] : [null, Validators.required],
@ -87,11 +86,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
comment: this.isDocumentAdmin ? [null] : [null, Validators.required]
});
for (const key of Object.keys(
this._appStateService.dictionaryData[
this._appStateService.activeDossier.dossierTemplateId
]
)) {
for (const key of Object.keys(this._appStateService.dictionaryData[this._appStateService.activeDossier.dossierTemplateId])) {
const dictionaryData = this._appStateService.getDictionaryTypeValue(key);
if (!dictionaryData.virtual && dictionaryData.addToDictionaryAction) {
this.redactionDictionaries.push(dictionaryData);
@ -102,15 +97,10 @@ export class ManualAnnotationDialogComponent implements OnInit {
handleAddRedaction() {
this._enhanceManualRedaction(this.manualRedactionEntryWrapper.manualRedactionEntry);
this._manualAnnotationService
.addAnnotation(this.manualRedactionEntryWrapper.manualRedactionEntry)
.subscribe(
response =>
this.dialogRef.close(
new ManualAnnotationResponse(this.manualRedactionEntryWrapper, response)
),
() => this.dialogRef.close()
);
this._manualAnnotationService.addAnnotation(this.manualRedactionEntryWrapper.manualRedactionEntry).subscribe(
response => this.dialogRef.close(new ManualAnnotationResponse(this.manualRedactionEntryWrapper, response)),
() => this.dialogRef.close()
);
}
private _enhanceManualRedaction(addRedactionRequest: AddRedactionRequest) {

View File

@ -1,8 +1,8 @@
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { PermissionsService } from '../../../../services/permissions.service';
import { PermissionsService } from '@services/permissions.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AnnotationWrapper } from '../../../../models/file/annotation.wrapper';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
@Component({
selector: 'redaction-recategorize-image-dialog',

View File

@ -46,13 +46,10 @@ import { ScrollButtonComponent } from './components/scroll-button/scroll-button.
import { ChangeLegalBasisDialogComponent } from './dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
import { PageExclusionComponent } from './components/page-exclusion/page-exclusion.component';
import { RecategorizeImageDialogComponent } from './dialogs/recategorize-image-dialog/recategorize-image-dialog.component';
import { EditDossierAttributesComponent } from './dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component';
import { DossiersService } from './services/dossiers.service';
const screens = [
DossierListingScreenComponent,
DossierOverviewScreenComponent,
FilePreviewScreenComponent
];
const screens = [DossierListingScreenComponent, DossierOverviewScreenComponent, FilePreviewScreenComponent];
const dialogs = [
AddDossierDialogComponent,
@ -87,6 +84,7 @@ const components = [
EditDossierDownloadPackageComponent,
EditDossierDictionaryComponent,
EditDossierTeamMembersComponent,
EditDossierAttributesComponent,
TeamMembersManagerComponent,
ScrollButtonComponent,
PageExclusionComponent,

View File

@ -23,11 +23,11 @@ import {
dossierTemplateChecker
} from '@shared/components/filters/popup-filter/utils/filter-utils';
import { UserPreferenceService } from '../../../../services/user-preference.service';
import { ButtonConfig } from '../../../shared/components/page-header/models/button-config.model';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { ButtonConfig } from '@shared/components/page-header/models/button-config.model';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { BaseListingComponent } from '@shared/base/base-listing.component';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
@Component({

View File

@ -1,14 +1,4 @@
import {
ChangeDetectorRef,
Component,
ElementRef,
HostListener,
Injector,
OnDestroy,
OnInit,
TemplateRef,
ViewChild
} from '@angular/core';
import { ChangeDetectorRef, Component, ElementRef, HostListener, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
import { NotificationService, NotificationType } from '@services/notification.service';
import { AppStateService } from '@state/app-state.service';
@ -31,19 +21,16 @@ import { convertFiles, handleFileDrop } from '@utils/file-drop-utils';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
import {
annotationFilterChecker,
keyChecker
} from '@shared/components/filters/popup-filter/utils/filter-utils';
import { annotationFilterChecker, keyChecker } from '@shared/components/filters/popup-filter/utils/filter-utils';
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service';
import { FilterConfig } from '@shared/components/page-header/models/filter-config.model';
import { ActionConfig } from '@shared/components/page-header/models/action-config.model';
import { FilterService } from '../../../shared/services/filter.service';
import { SearchService } from '../../../shared/services/search.service';
import { ScreenStateService } from '../../../shared/services/screen-state.service';
import { FilterService } from '@shared/services/filter.service';
import { SearchService } from '@shared/services/search.service';
import { ScreenStateService } from '@shared/services/screen-state.service';
import { ScreenNames, SortingService } from '../../../../services/sorting.service';
import { BaseListingComponent } from '../../../shared/base/base-listing.component';
import { BaseListingComponent } from '@shared/base/base-listing.component';
@Component({
templateUrl: './dossier-overview-screen.component.html',
@ -103,15 +90,11 @@ export class DossierOverviewScreenComponent
}
get checkedRequiredFilters() {
return this.filterService
.getFilter('quickFilters')
?.values.filter(f => f.required && f.checked);
return this.filterService.getFilter('quickFilters')?.values.filter(f => f.required && f.checked);
}
get checkedNotRequiredFilters() {
return this.filterService
.getFilter('quickFilters')
?.values.filter(f => !f.required && f.checked);
return this.filterService.getFilter('quickFilters')?.values.filter(f => !f.required && f.checked);
}
isLastOpenedFile(fileStatus: FileStatusWrapper): boolean {
@ -195,11 +178,9 @@ export class DossierOverviewScreenComponent
}
isProcessing(fileStatusWrapper: FileStatusWrapper) {
return [
FileStatus.StatusEnum.REPROCESS,
FileStatus.StatusEnum.FULLREPROCESS,
FileStatus.StatusEnum.PROCESSING
].includes(fileStatusWrapper.status);
return [FileStatus.StatusEnum.REPROCESS, FileStatus.StatusEnum.FULLREPROCESS, FileStatus.StatusEnum.PROCESSING].includes(
fileStatusWrapper.status
);
}
reloadDossiers() {
@ -280,9 +261,7 @@ export class DossierOverviewScreenComponent
}
recentlyModifiedChecker = (file: FileStatusWrapper) =>
moment(file.lastUpdated)
.add(this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS), 'hours')
.isAfter(moment());
moment(file.lastUpdated).add(this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS), 'hours').isAfter(moment());
private _loadEntitiesFromState() {
if (this.activeDossier) this._screenStateService.setEntities(this.activeDossier.files);
@ -309,8 +288,7 @@ export class DossierOverviewScreenComponent
allDistinctFileStatusWrapper.add(file.status);
allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY'));
if (this.permissionsService.fileRequiresReanalysis(file))
allDistinctNeedsWork.add('analysis');
if (this.permissionsService.fileRequiresReanalysis(file)) allDistinctNeedsWork.add('analysis');
if (file.hintsOnly) allDistinctNeedsWork.add('hint');
if (file.hasRedactions) allDistinctNeedsWork.add('redaction');
if (file.hasRequests) allDistinctNeedsWork.add('suggestion');
@ -377,10 +355,7 @@ export class DossierOverviewScreenComponent
checker: (file: FileStatusWrapper) =>
this.checkedRequiredFilters.reduce((acc, f) => acc && f.checker(file), true) &&
(this.checkedNotRequiredFilters.length === 0 ||
this.checkedNotRequiredFilters.reduce(
(acc, f) => acc || f.checker(file),
false
))
this.checkedNotRequiredFilters.reduce((acc, f) => acc || f.checker(file), false))
});
this._createActionConfigs();
@ -389,9 +364,7 @@ export class DossierOverviewScreenComponent
private _createQuickFilters() {
let quickFilters = [];
if (this._screenStateService.entities.filter(this.recentlyModifiedChecker).length > 0) {
const recentPeriod = this._appConfigService.getConfig(
AppConfigKey.RECENT_PERIOD_IN_HOURS
);
const recentPeriod = this._appConfigService.getConfig(AppConfigKey.RECENT_PERIOD_IN_HOURS);
quickFilters = [
{
key: 'recent',
@ -408,9 +381,7 @@ export class DossierOverviewScreenComponent
...quickFilters,
{
key: 'assigned-to-me',
label: this._translateService.instant(
'dossier-overview.quick-filters.assigned-to-me'
),
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-me'),
checker: (file: FileStatusWrapper) => file.currentReviewer === this.user.id
},
{
@ -420,11 +391,8 @@ export class DossierOverviewScreenComponent
},
{
key: 'assigned-to-others',
label: this._translateService.instant(
'dossier-overview.quick-filters.assigned-to-others'
),
checker: (file: FileStatusWrapper) =>
!!file.currentReviewer && file.currentReviewer !== this.user.id
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-others'),
checker: (file: FileStatusWrapper) => !!file.currentReviewer && file.currentReviewer !== this.user.id
}
];
}

View File

@ -1,12 +1,4 @@
import {
ChangeDetectorRef,
Component,
HostListener,
NgZone,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import { ChangeDetectorRef, Component, HostListener, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router';
import { AppStateService } from '@state/app-state.service';
import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
@ -41,11 +33,8 @@ import { FileWorkloadComponent } from '../../components/file-workload/file-workl
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
import { FilterModel } from '@shared/components/filters/popup-filter/model/filter.model';
import {
handleFilterDelta,
processFilters
} from '@shared/components/filters/popup-filter/utils/filter-utils';
import { LoadingService } from '../../../../services/loading.service';
import { handleFilterDelta, processFilters } from '@shared/components/filters/popup-filter/utils/filter-utils';
import { LoadingService } from '@services/loading.service';
import { stampPDFPage } from '../../../../utils/page-stamper';
import { TranslateService } from '@ngx-translate/core';
@ -117,9 +106,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
}
get assignTooltip(): string {
return this.appStateService.activeFile.isUnderApproval
? 'dossier-overview.assign-approver'
: this.assignOrChangeReviewerTooltip;
return this.appStateService.activeFile.isUnderApproval ? 'dossier-overview.assign-approver' : this.assignOrChangeReviewerTooltip;
}
get annotations(): AnnotationWrapper[] {
@ -139,25 +126,15 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
}
get canSwitchToRedactedView() {
return (
this.fileData &&
!this.permissionsService.fileRequiresReanalysis() &&
!this.fileData.fileStatus.isExcluded
);
return this.fileData && !this.permissionsService.fileRequiresReanalysis() && !this.fileData.fileStatus.isExcluded;
}
get canSwitchToDeltaView() {
return (
this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 &&
!this.fileData.fileStatus.isExcluded
);
return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.fileStatus.isExcluded;
}
get canAssign(): boolean {
return (
!this.editingReviewer &&
(this.permissionsService.canAssignUser() || this.permissionsService.canAssignToSelf())
);
return !this.editingReviewer && (this.permissionsService.canAssignUser() || this.permissionsService.canAssignToSelf());
}
get displayData() {
@ -181,9 +158,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
}
get assignOrChangeReviewerTooltip() {
return this.currentReviewer
? 'file-preview.change-reviewer'
: 'file-preview.assign-reviewer';
return this.currentReviewer ? 'file-preview.change-reviewer' : 'file-preview.assign-reviewer';
}
get currentReviewer(): string {
@ -204,9 +179,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
get canAssignReviewer(): boolean {
return (
!this.currentReviewer &&
this.permissionsService.canAssignUser() &&
this.appStateService.activeDossier.hasMoreThanOneReviewer
!this.currentReviewer && this.permissionsService.canAssignUser() && this.appStateService.activeDossier.hasMoreThanOneReviewer
);
}
@ -217,12 +190,8 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
switch (this.viewMode) {
case 'STANDARD': {
this._setAnnotationsColor(redactions, 'annotationColor');
const standardEntries = annotations.filter(
a => !a.getCustomData('changeLogRemoved')
);
const nonStandardEntries = annotations.filter(a =>
a.getCustomData('changeLogRemoved')
);
const standardEntries = annotations.filter(a => !a.getCustomData('changeLogRemoved'));
const nonStandardEntries = annotations.filter(a => a.getCustomData('changeLogRemoved'));
this._show(standardEntries);
this._hide(nonStandardEntries);
break;
@ -271,9 +240,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
this._updateCanPerformActions();
try {
const key = 'Dossier-Recent-' + this.dossierId;
await this._userPreferenceControllerService
.savePreferences([this.fileId], key)
.toPromise();
await this._userPreferenceControllerService.savePreferences([this.fileId], key).toPromise();
} catch (error) {
console.error(error);
}
@ -299,35 +266,22 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
console.error(error);
}
}
console.log(
'[REDACTION] Delete previous annotations time: ' +
(new Date().getTime() - startTime) +
'ms'
);
console.log('[REDACTION] Delete previous annotations time: ' + (new Date().getTime() - startTime) + 'ms');
const processStartTime = new Date().getTime();
this.annotationData = this.fileData.getAnnotations(
this.appStateService.dictionaryData[
this.appStateService.activeDossier.dossierTemplateId
],
this.appStateService.dictionaryData[this.appStateService.activeDossier.dossierTemplateId],
this.permissionsService.currentUser,
this.viewMode,
this.userPreferenceService.areDevFeaturesEnabled
);
const annotationFilters = this._annotationProcessingService.getAnnotationFilter(
this.annotations
);
const annotationFilters = this._annotationProcessingService.getAnnotationFilter(this.annotations);
this.primaryFilters = processFilters(this.primaryFilters, annotationFilters);
this.secondaryFilters = processFilters(
this.secondaryFilters,
AnnotationProcessingService.secondaryAnnotationFilters
);
this.secondaryFilters = processFilters(this.secondaryFilters, AnnotationProcessingService.secondaryAnnotationFilters);
this._workloadComponent?.filtersChanged({
primary: this.primaryFilters,
secondary: this.secondaryFilters
});
console.log(
'[REDACTION] Process time: ' + (new Date().getTime() - processStartTime) + 'ms'
);
console.log('[REDACTION] Process time: ' + (new Date().getTime() - processStartTime) + 'ms');
console.log(
'[REDACTION] Annotation Redraw and filter rebuild time: ' +
(new Date().getTime() - startTime) +
@ -348,11 +302,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
this._changeDetectorRef.detectChanges();
}
selectAnnotations(
annotations?:
| AnnotationWrapper[]
| { annotations: AnnotationWrapper[]; multiSelect: boolean }
) {
selectAnnotations(annotations?: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }) {
if (annotations) {
this.viewerComponent.utils.selectAnnotations(annotations);
} else {
@ -371,24 +321,19 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
openManualAnnotationDialog($event: ManualRedactionEntryWrapper) {
this._ngZone.run(() => {
this.dialogRef = this._dialogService.openManualAnnotationDialog(
$event,
async (response: ManualAnnotationResponse) => {
if (response?.annotationId) {
const annotation = this._instance.annotManager.getAnnotationById(
response.manualRedactionEntryWrapper.rectId
);
this._instance.annotManager.deleteAnnotation(annotation);
this.fileData.fileStatus = await this.appStateService.reloadActiveFile();
const distinctPages = $event.manualRedactionEntry.positions
.map(p => p.page)
.filter((item, pos, self) => self.indexOf(item) === pos);
distinctPages.forEach(page => {
this._cleanupAndRedrawManualAnnotationsForEntirePage(page);
});
}
this.dialogRef = this._dialogService.openManualAnnotationDialog($event, async (response: ManualAnnotationResponse) => {
if (response?.annotationId) {
const annotation = this._instance.annotManager.getAnnotationById(response.manualRedactionEntryWrapper.rectId);
this._instance.annotManager.deleteAnnotation(annotation);
this.fileData.fileStatus = await this.appStateService.reloadActiveFile();
const distinctPages = $event.manualRedactionEntry.positions
.map(p => p.page)
.filter((item, pos, self) => self.indexOf(item) === pos);
distinctPages.forEach(page => {
this._cleanupAndRedrawManualAnnotationsForEntirePage(page);
});
}
);
});
});
}
@ -407,10 +352,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
return;
}
if (
!ALL_HOTKEY_ARRAY.includes($event.key) ||
this.dialogRef?.getState() === MatDialogState.OPEN
) {
if (!ALL_HOTKEY_ARRAY.includes($event.key) || this.dialogRef?.getState() === MatDialogState.OPEN) {
return;
}
@ -524,9 +466,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
const reviewerName = this.userService.getNameForId(reviewerId);
const { dossierId, fileId, filename } = this.fileData.fileStatus;
await this._statusControllerService
.setFileReviewer(dossierId, fileId, reviewerId)
.toPromise();
await this._statusControllerService.setFileReviewer(dossierId, fileId, reviewerId).toPromise();
const msg = `Successfully assigned ${reviewerName} to file: ${filename}`;
this._notificationService.showToastNotification(msg);
@ -549,13 +489,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
downloadOriginalFile() {
this._fileManagementControllerService
.downloadOriginalFile(
this.dossierId,
this.fileId,
true,
this.fileData.fileStatus.cacheIdentifier,
'response'
)
.downloadOriginalFile(this.dossierId, this.fileId, true, this.fileData.fileStatus.cacheIdentifier, 'response')
.subscribe(data => {
download(data, this.fileData.fileStatus.filename);
});
@ -608,17 +542,15 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
this.filesAutoUpdateTimer = timer(0, 5000)
.pipe(tap(async () => await this.appStateService.reloadActiveFile()))
.subscribe();
this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe(
async (fileStatus: FileStatusWrapper) => {
if (fileStatus.fileId === this.fileId) {
await this._loadFileData(!this._reloadFileOnReanalysis);
this._reloadFileOnReanalysis = false;
this.viewReady = true;
this._updateCanPerformActions();
this._cleanupAndRedrawManualAnnotations();
}
this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe(async (fileStatus: FileStatusWrapper) => {
if (fileStatus.fileId === this.fileId) {
await this._loadFileData(!this._reloadFileOnReanalysis);
this._reloadFileOnReanalysis = false;
this.viewReady = true;
this._updateCanPerformActions();
this._cleanupAndRedrawManualAnnotations();
}
);
});
}
private _unsubscribeFromFileUpdates(): void {
@ -663,10 +595,8 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
/* Get the documentElement (<html>) to display the page in fullscreen */
private _cleanupAndRedrawManualAnnotations() {
this._fileDownloadService
.loadActiveFileRedactionLogPreview()
.subscribe(redactionLogPreview => {
this.fileData.redactionLog = redactionLogPreview;
this._fileDownloadService.loadActiveFileRedactionLogPreview().subscribe(redactionLogPreview => {
this.fileData.redactionLog = redactionLogPreview;
this._annotationDrawService.drawAnnotations(
this._instance,
this.annotationData.allAnnotations,
@ -681,18 +611,14 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
const currentPageAnnotationIds = currentPageAnnotations.map(a => a.id);
this.fileData.fileStatus = await this.appStateService.reloadActiveFile();
this._fileDownloadService
.loadActiveFileRedactionLogPreview()
.subscribe(redactionLogPreview => {
this.fileData.redactionLog = redactionLogPreview;
this._fileDownloadService.loadActiveFileRedactionLogPreview().subscribe(redactionLogPreview => {
this.fileData.redactionLog = redactionLogPreview;
this.rebuildFilters();
if (this.viewMode === 'STANDARD') {
currentPageAnnotationIds.forEach(id => {
this._findAndDeleteAnnotation(id);
});
const newPageAnnotations = this.annotations.filter(
item => item.pageNumber === page
);
const newPageAnnotations = this.annotations.filter(item => item.pageNumber === page);
this._handleDeltaAnnotationFilters(currentPageAnnotations, newPageAnnotations);
this._annotationDrawService.drawAnnotations(
this._instance,
@ -704,22 +630,16 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
});
}
private _handleDeltaAnnotationFilters(
currentPageAnnotations: AnnotationWrapper[],
newPageAnnotations: AnnotationWrapper[]
) {
private _handleDeltaAnnotationFilters(currentPageAnnotations: AnnotationWrapper[], newPageAnnotations: AnnotationWrapper[]) {
const hasAnyFilterSet =
this.primaryFilters.find(f => f.checked || f.indeterminate) ||
this.secondaryFilters.find(f => f.checked || f.indeterminate);
this.primaryFilters.find(f => f.checked || f.indeterminate) || this.secondaryFilters.find(f => f.checked || f.indeterminate);
if (!hasAnyFilterSet) {
return;
}
const oldPageSpecificFilters =
this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations);
const newPageSpecificFilters =
this._annotationProcessingService.getAnnotationFilter(newPageAnnotations);
const oldPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations);
const newPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(newPageAnnotations);
handleFilterDelta(oldPageSpecificFilters, newPageSpecificFilters, this.primaryFilters);
this._workloadComponent.filtersChanged({
primary: this.primaryFilters,

View File

@ -17,12 +17,12 @@ import { ManualAnnotationService } from './manual-annotation.service';
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
import { DossierDictionaryDialogComponent } from '../dialogs/dossier-dictionary-dialog/dossier-dictionary-dialog.component';
import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
import { FileStatusWrapper } from '../../../models/file/file-status.wrapper';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
import { AppConfigService } from '../../app-config/app-config.service';
import { ChangeLegalBasisDialogComponent } from '../dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
import { RecategorizeImageDialogComponent } from '../dialogs/recategorize-image-dialog/recategorize-image-dialog.component';
import { DialogService } from '../../shared/services/dialog.service';
import { DialogService } from '@shared/services/dialog.service';
import { ComponentType } from '@angular/cdk/portal';
const dialogConfig = {
@ -67,10 +67,7 @@ export class DossiersDialogService extends DialogService<DialogType> {
super(_dialog);
}
openManualAnnotationDialog(
$event: ManualRedactionEntryWrapper,
cb?: Function
): MatDialogRef<ManualAnnotationDialogComponent> {
openManualAnnotationDialog($event: ManualRedactionEntryWrapper, cb?: Function): MatDialogRef<ManualAnnotationDialogComponent> {
const ref = this._dialog.open(ManualAnnotationDialogComponent, {
...dialogConfig,
autoFocus: true,
@ -96,13 +93,11 @@ export class DossiersDialogService extends DialogService<DialogType> {
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
ref.afterClosed().subscribe(result => {
if (result) {
this._manualAnnotationService
.approveRequest(annotation.id)
.subscribe(acceptResult => {
if (callback) {
callback(acceptResult);
}
});
this._manualAnnotationService.approveRequest(annotation.id).subscribe(acceptResult => {
if (callback) {
callback(acceptResult);
}
});
}
});
@ -132,10 +127,7 @@ export class DossiersDialogService extends DialogService<DialogType> {
return ref;
}
openForceRedactionDialog(
$event: MouseEvent,
cb?: Function
): MatDialogRef<ForceRedactionDialogComponent> {
openForceRedactionDialog($event: MouseEvent, cb?: Function): MatDialogRef<ForceRedactionDialogComponent> {
$event?.stopPropagation();
const ref = this._dialog.open(ForceRedactionDialogComponent, {
...dialogConfig
@ -203,11 +195,7 @@ export class DossiersDialogService extends DialogService<DialogType> {
return ref;
}
openDeleteDossierDialog(
$event: MouseEvent,
dossier: DossierWrapper,
cb?: Function
): MatDialogRef<ConfirmationDialogComponent> {
openDeleteDossierDialog($event: MouseEvent, dossier: DossierWrapper, cb?: Function): MatDialogRef<ConfirmationDialogComponent> {
$event.stopPropagation();
const period = this._appConfigService.getConfig('DELETE_RETENTION_HOURS');
const ref = this._dialog.open(ConfirmationDialogComponent, {
@ -299,11 +287,7 @@ export class DossiersDialogService extends DialogService<DialogType> {
return ref;
}
openRemoveAnnotationModal(
$event: MouseEvent,
annotation: AnnotationWrapper,
callback: () => void
) {
openRemoveAnnotationModal($event: MouseEvent, annotation: AnnotationWrapper, callback: () => void) {
$event?.stopPropagation();
const ref = this._dialog.open(ConfirmationDialogComponent, {
@ -313,13 +297,11 @@ export class DossiersDialogService extends DialogService<DialogType> {
ref.afterClosed().subscribe(result => {
if (result) {
this._manualAnnotationService
.removeOrSuggestRemoveAnnotation(annotation)
.subscribe(() => {
if (callback) {
callback();
}
});
this._manualAnnotationService.removeOrSuggestRemoveAnnotation(annotation).subscribe(() => {
if (callback) {
callback();
}
});
}
});

View File

@ -1,8 +1,8 @@
import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
import { ViewMode } from '../../../models/file/view-mode';
import { ViewMode } from '@models/file/view-mode';
import { translateQuads } from '../../../utils/pdf-coordinates';
import { Rectangle } from '@redaction/red-ui-http';
import { AnnotationWrapper } from '../../../models/file/annotation.wrapper';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
const DISABLED_HOTKEYS = [
'CTRL+SHIFT+EQUAL',
@ -74,9 +74,7 @@ export class PdfViewerUtils {
}
try {
return this.isCompareMode
? Math.ceil(this.instance?.docViewer?.getPageCount() / 2)
: this.instance?.docViewer?.getPageCount();
return this.isCompareMode ? Math.ceil(this.instance?.docViewer?.getPageCount() / 2) : this.instance?.docViewer?.getPageCount();
} catch (e) {
console.error(e);
return null;
@ -93,9 +91,7 @@ export class PdfViewerUtils {
navigateToPage(pageNumber: string | number) {
const parsedNumber = typeof pageNumber === 'string' ? parseInt(pageNumber, 10) : pageNumber;
this._navigateToPage(
this.paginationOffset === 2 ? parsedNumber * this.paginationOffset - 1 : parsedNumber
);
this._navigateToPage(this.paginationOffset === 2 ? parsedNumber * this.paginationOffset - 1 : parsedNumber);
}
previousPage() {
@ -106,12 +102,7 @@ export class PdfViewerUtils {
nextPage() {
if (this._currentInternalPage < this._totalInternalPages) {
this._navigateToPage(
Math.min(
this._currentInternalPage + this.paginationOffset,
this._totalInternalPages
)
);
this._navigateToPage(Math.min(this._currentInternalPage + this.paginationOffset, this._totalInternalPages));
}
}
@ -144,9 +135,7 @@ export class PdfViewerUtils {
this.instance.annotManager.deselectAllAnnotations();
}
selectAnnotations(
$event: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }
) {
selectAnnotations($event: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }) {
let annotations: AnnotationWrapper[];
let multiSelect: boolean;
if ($event instanceof Array) {

View File

@ -14,11 +14,7 @@ export function processFilters(oldFilters: FilterModel[], newFilters: FilterMode
return newFilters;
}
export function handleFilterDelta(
oldFilters: FilterModel[],
newFilters: FilterModel[],
allFilters: FilterModel[]
) {
export function handleFilterDelta(oldFilters: FilterModel[], newFilters: FilterModel[], allFilters: FilterModel[]) {
const newFiltersDelta = {};
for (const newFilter of newFilters) {
const oldFilter = oldFilters.find(f => f.key === newFilter.key);
@ -87,13 +83,7 @@ export function handleCheckedValue(filter: FilterModel) {
}
}
export function checkFilter(
entity: any,
filters: FilterModel[],
validate: Function,
validateArgs: any = [],
matchAll: boolean = false
) {
export function checkFilter(entity: any, filters: FilterModel[], validate: Function, validateArgs: any = [], matchAll: boolean = false) {
const hasChecked = filters.find(f => f.checked);
if (validateArgs) {
@ -121,8 +111,7 @@ export function checkFilter(
return filterMatched;
}
export const keyChecker = (key: string) => (entity: any, filter: FilterModel) =>
entity[key] === filter.key;
export const keyChecker = (key: string) => (entity: any, filter: FilterModel) => entity[key] === filter.key;
export const annotationFilterChecker = (
input: FileStatusWrapper | DossierWrapper,
@ -158,38 +147,24 @@ export const annotationFilterChecker = (
}
};
export const dossierStatusChecker = (dw: DossierWrapper, filter: FilterModel) =>
dw.hasStatus(filter.key);
export const dossierStatusChecker = (dw: DossierWrapper, filter: FilterModel) => dw.hasStatus(filter.key);
export const dossierMemberChecker = (dw: DossierWrapper, filter: FilterModel) =>
dw.hasMember(filter.key);
export const dossierMemberChecker = (dw: DossierWrapper, filter: FilterModel) => dw.hasMember(filter.key);
export const dossierTemplateChecker = (dw: DossierWrapper, filter: FilterModel) =>
dw.dossierTemplateId === filter.key;
export const dossierTemplateChecker = (dw: DossierWrapper, filter: FilterModel) => dw.dossierTemplateId === filter.key;
export const dueDateChecker = (dw: DossierWrapper, filter: FilterModel) =>
dw.dueDateMatches(filter.key);
export const dueDateChecker = (dw: DossierWrapper, filter: FilterModel) => dw.dueDateMatches(filter.key);
export const addedDateChecker = (dw: DossierWrapper, filter: FilterModel) =>
dw.addedDateMatches(filter.key);
export const addedDateChecker = (dw: DossierWrapper, filter: FilterModel) => dw.addedDateMatches(filter.key);
export const dossierApproverChecker = (dw: DossierWrapper, filter: FilterModel) =>
dw.approverIds.includes(filter.key);
export const dossierApproverChecker = (dw: DossierWrapper, filter: FilterModel) => dw.approverIds.includes(filter.key);
export function getFilteredEntities<T>(entities: T[], filters: FilterWrapper[]) {
const filteredEntities: T[] = [];
for (const entity of entities) {
let add = true;
for (const filter of filters) {
add =
add &&
checkFilter(
entity,
filter.values,
filter.checker,
filter.checkerArgs,
filter.matchAll
);
add = add && checkFilter(entity, filter.values, filter.checker, filter.checkerArgs, filter.matchAll);
}
if (add) {
filteredEntities.push(entity);

View File

@ -1,6 +1,6 @@
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { NotificationService, NotificationType } from '../../../services/notification.service';
import { NotificationService, NotificationType } from '@services/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { DictionaryControllerService } from '@redaction/red-ui-http';
import { tap } from 'rxjs/operators';
@ -36,20 +36,9 @@ export class DictionarySaveService {
// can add at least 1 - block UI
let obs: Observable<any>;
if (entriesToAdd.length > 0) {
obs = this._dictionaryControllerService.addEntry(
entriesToAdd,
dossierTemplateId,
type,
dossierId,
true
);
obs = this._dictionaryControllerService.addEntry(entriesToAdd, dossierTemplateId, type, dossierId, true);
} else {
obs = this._dictionaryControllerService.deleteEntries(
initialEntries,
dossierTemplateId,
type,
dossierId
);
obs = this._dictionaryControllerService.deleteEntries(initialEntries, dossierTemplateId, type, dossierId);
}
return obs.pipe(
@ -57,9 +46,7 @@ export class DictionarySaveService {
() => {
if (showToast) {
this._notificationService.showToastNotification(
this._translateService.instant(
'dictionary-overview.success.generic'
),
this._translateService.instant('dictionary-overview.success.generic'),
null,
NotificationType.SUCCESS
);

View File

@ -831,7 +831,9 @@
"general-info": "General Information",
"members": "Members",
"report-attributes": "Report Attributes",
"team-members": "Team Members"
"team-members": "Team Members",
"custom-dossier-attributes": "Custom Dossier Attributes",
"image-attributes": "Image Attributes"
},
"unsaved-changes": "You have unsaved changes. Save or revert before changing the tab."
},