diff --git a/angular.json b/angular.json
index 700f0f37e..bef6f9183 100644
--- a/angular.json
+++ b/angular.json
@@ -1,4 +1,7 @@
{
+ "cli": {
+ "analytics": "4b8eed12-a1e6-4b7a-9ea2-925b27941271"
+ },
"version": 1,
"projects": {
"common-ui": {
diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts
index 24a5d3557..b13a5055e 100644
--- a/apps/red-ui/src/app/app-routing.module.ts
+++ b/apps/red-ui/src/app/app-routing.module.ts
@@ -35,7 +35,6 @@ const routes: Routes = [
component: BaseScreenComponent,
loadChildren: () => import('./modules/dossier/dossiers.module').then(m => m.DossiersModule),
canActivate: [CompositeRouteGuard],
- canDeactivate: [DossiersGuard],
data: {
routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard, DossiersGuard],
requiredRoles: ['RED_USER', 'RED_MANAGER'],
diff --git a/apps/red-ui/src/app/app.component.ts b/apps/red-ui/src/app/app.component.ts
index 168178363..b6d58256f 100644
--- a/apps/red-ui/src/app/app.component.ts
+++ b/apps/red-ui/src/app/app.component.ts
@@ -1,4 +1,5 @@
import { Component, ViewContainerRef } from '@angular/core';
+import { RouterHistoryService } from '@services/router-history.service';
@Component({
selector: 'redaction-root',
@@ -6,6 +7,7 @@ import { Component, ViewContainerRef } from '@angular/core';
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
- // View container ref needs to be injected for the color picker to work
- constructor(public viewContainerRef: ViewContainerRef) {}
+ // ViewContainerRef needs to be injected for the color picker to work
+ // RouterHistoryService needs to be injected for last dossiers screen to be updated on first app load
+ constructor(public viewContainerRef: ViewContainerRef, private readonly _routerHistoryService: RouterHistoryService) {}
}
diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts
index 1ae19dd51..a1d31741d 100644
--- a/apps/red-ui/src/app/app.module.ts
+++ b/apps/red-ui/src/app/app.module.ts
@@ -7,7 +7,6 @@ import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
import { ApiPathInterceptor } from '@utils/api-path-interceptor';
import { MissingTranslationHandler, TranslateCompiler, TranslateLoader, TranslateModule } from '@ngx-translate/core';
-import { languageInitializer } from '@i18n/language.initializer';
import { LanguageService } from '@i18n/language.service';
import { ToastrModule } from 'ngx-toastr';
import { ServiceWorkerModule } from '@angular/service-worker';
diff --git a/apps/red-ui/src/app/components/base-screen/base-screen.component.html b/apps/red-ui/src/app/components/base-screen/base-screen.component.html
index 04d3e1bc7..534a5c4fb 100644
--- a/apps/red-ui/src/app/components/base-screen/base-screen.component.html
+++ b/apps/red-ui/src/app/components/base-screen/base-screen.component.html
@@ -7,7 +7,7 @@
-
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts
index c48c4fafc..16f9f5e8f 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts
@@ -31,7 +31,15 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
) {}
get changed(): boolean {
- return this.form.get('reason').value.legalBasis !== this._data.annotations[0].legalBasis;
+ return (
+ this.form.get('reason').value.legalBasis !== this._data.annotations[0].legalBasis ||
+ this.form.get('section').value !== this._data.annotations[0].section ||
+ this.form.get('classification').value !== this._data.annotations[0].value
+ );
+ }
+
+ get allRectangles(): boolean {
+ return this._data.annotations.reduce((acc, a) => acc && a.rectangle, true);
}
async ngOnInit() {
@@ -55,13 +63,17 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
return this._formBuilder.group({
reason: [null, Validators.required],
comment: this.isDocumentAdmin ? [null] : [null, Validators.required],
+ classification: [this.allRectangles ? this._data.annotations[0].value : null],
+ section: [this._data.annotations[0].section],
});
}
save() {
this.dialogRef.close({
legalBasis: this.form.get('reason').value.legalBasis,
+ section: this.form.get('section').value,
comment: this.form.get('comment').value,
+ value: this.form.get('classification').value,
});
}
}
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html
index 3c4108bcc..7319b9040 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html
@@ -4,6 +4,7 @@
[itemSize]="50"
[noDataText]="'edit-dossier-dialog.deleted-documents.no-data.title' | translate"
[selectionEnabled]="true"
+ [tableColumnConfigs]="tableColumnConfigs"
[tableItemClasses]="{ disabled: disabledFn }"
noDataIcon="iqser:document"
>
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts
index 8959c4e45..87235becf 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts
@@ -124,17 +124,13 @@ export class EditDossierDialogComponent extends BaseDialogComponent {
return this.activeComponent?.disabled;
}
- afterSave() {
- this._toaster.success(_('edit-dossier-dialog.change-successful'), { params: { dossierName: this._dossierName } });
- }
-
async save(closeAfterSave: boolean = false) {
this._loadingService.start();
const result = await this.activeComponent.save();
this._loadingService.stop();
if (result.success) {
- this.afterSave();
+ this._toaster.success(_('edit-dossier-dialog.change-successful'), { params: { dossierName: this._dossierName } });
}
if (result.success && closeAfterSave) {
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts
index 97c6b20cc..4f7d35d7d 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts
@@ -116,7 +116,6 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
});
this._dialogService.openDialog('confirm', null, data, async () => {
await this._dossiersService.delete(this.dossier).toPromise();
- this._editDossierDialogRef.componentInstance.afterSave();
this._editDossierDialogRef.close();
this._router.navigate(['main', 'dossiers']).then(() => this._notifyDossierDeleted());
});
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html b/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html
index 1788ae51a..46db18d59 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html
@@ -3,19 +3,37 @@
-
+
{{ format(data.manualRedactionEntryWrapper.manualRedactionEntry.value) }}
-
+
+
+
+
+
+ {{ displayedDictionaryLabel }}
+
+
+ {{ dictionary.label }}
+
+
+
+
+
-
-
-
+
+
+
-
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts
index 55ce35c2b..710b4fc6b 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts
@@ -28,7 +28,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
isDictionaryRequest: boolean;
isFalsePositiveRequest: boolean;
- redactionDictionaries: Dictionary[] = [];
+ possibleDictionaries: Dictionary[] = [];
legalOptions: LegalBasisOption[] = [];
private readonly _dossier: Dossier;
@@ -51,7 +51,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
this.redactionForm = this._getForm();
- this.redactionDictionaries = this._redactionDictionaries;
+ this.possibleDictionaries = this._possibleDictionaries;
}
get title() {
@@ -61,24 +61,25 @@ export class ManualAnnotationDialogComponent implements OnInit {
get displayedDictionaryLabel() {
const dictType = this.redactionForm.get('dictionary').value;
if (dictType) {
- return this.redactionDictionaries.find(d => d.type === dictType).label;
+ return this.possibleDictionaries.find(d => d.type === dictType).label;
}
return null;
}
- private get _redactionDictionaries(): Dictionary[] {
- const redactionDictionaries: Dictionary[] = [];
+ private get _possibleDictionaries(): Dictionary[] {
+ const possibleDictionaries: Dictionary[] = [];
const dossier = this._dossier;
for (const key of Object.keys(this._appStateService.dictionaryData[dossier.dossierTemplateId])) {
const dictionaryData = this._appStateService.getDictionary(key, dossier.dossierTemplateId);
if (!dictionaryData.virtual && dictionaryData.addToDictionaryAction) {
- redactionDictionaries.push(dictionaryData);
+ possibleDictionaries.push(dictionaryData);
}
}
- redactionDictionaries.sort((a, b) => a.label.localeCompare(b.label));
- return redactionDictionaries;
+ possibleDictionaries.sort((a, b) => a.label.localeCompare(b.label));
+
+ return possibleDictionaries;
}
async ngOnInit() {
@@ -111,11 +112,13 @@ export class ManualAnnotationDialogComponent implements OnInit {
private _getForm(): FormGroup {
return this._formBuilder.group({
+ section: [null],
reason: this.isDictionaryRequest ? [null] : [null, Validators.required],
dictionary: this.isDictionaryRequest
? [this.isFalsePositiveRequest ? 'false_positive' : null, Validators.required]
: ['manual', Validators.required],
comment: this.isDocumentAdmin ? [null] : [null, Validators.required],
+ classification: ['non-readable content'],
});
}
@@ -133,5 +136,9 @@ export class ManualAnnotationDialogComponent implements OnInit {
}
const commentValue = this.redactionForm.get('comment').value;
addRedactionRequest.comment = commentValue ? { text: commentValue } : null;
+ addRedactionRequest.section = this.redactionForm.get('section').value;
+ addRedactionRequest.value = addRedactionRequest.rectangle
+ ? this.redactionForm.get('classification').value
+ : addRedactionRequest.value;
}
}
diff --git a/apps/red-ui/src/app/modules/dossier/dossiers-routing.module.ts b/apps/red-ui/src/app/modules/dossier/dossiers-routing.module.ts
index 9d30432ae..cb75a3558 100644
--- a/apps/red-ui/src/app/modules/dossier/dossiers-routing.module.ts
+++ b/apps/red-ui/src/app/modules/dossier/dossiers-routing.module.ts
@@ -3,22 +3,20 @@ import { RouterModule, Routes } from '@angular/router';
import { SearchScreenComponent } from './screens/search-screen/search-screen.component';
import { FilePreviewGuard } from '@guards/file-preview.guard';
import { DossierFilesGuard } from '@guards/dossier-files-guard';
-import { GoBackGuard } from '@guards/go-back-guard.service';
import { CompositeRouteGuard } from '@iqser/common-ui';
+import { BreadcrumbTypes } from '@red/domain';
const routes: Routes = [
{
path: 'search',
component: SearchScreenComponent,
- canActivate: [GoBackGuard],
- canDeactivate: [GoBackGuard],
},
{
path: ':dossierId',
canActivate: [CompositeRouteGuard],
- canDeactivate: [DossierFilesGuard],
data: {
routeGuards: [DossierFilesGuard],
+ breadcrumbs: [BreadcrumbTypes.main, BreadcrumbTypes.dossier],
},
loadChildren: () => import('./screens/dossier-overview/dossier-overview.module').then(m => m.DossierOverviewModule),
},
@@ -27,14 +25,15 @@ const routes: Routes = [
canActivate: [CompositeRouteGuard],
data: {
routeGuards: [DossierFilesGuard, FilePreviewGuard],
+ breadcrumbs: [BreadcrumbTypes.main, BreadcrumbTypes.dossier, BreadcrumbTypes.file],
},
- canDeactivate: [FilePreviewGuard],
loadChildren: () => import('./screens/file-preview-screen/file-preview.module').then(m => m.FilePreviewModule),
},
{
path: '',
pathMatch: 'full',
loadChildren: () => import('./screens/dossiers-listing/dossiers-listing.module').then(m => m.DossiersListingModule),
+ data: { breadcrumbs: [BreadcrumbTypes.main] },
},
];
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html
index 1010b0c02..7074f226c 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html
@@ -23,6 +23,7 @@
[noMatchText]="'dossier-overview.no-match.title' | translate"
[selectionEnabled]="true"
[showNoDataButton]="true"
+ [tableColumnConfigs]="tableColumnConfigs"
[tableItemClasses]="{ disabled: disabledFn, 'last-opened': lastOpenedFn }"
helpModeKey="document-list"
>
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts
index 147dba9b7..bf8865bdd 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts
@@ -17,7 +17,7 @@ import { FileUploadService } from '@upload-download/services/file-upload.service
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
import * as moment from 'moment';
import { Observable, timer } from 'rxjs';
-import { filter, switchMap, tap } from 'rxjs/operators';
+import { filter, skip, switchMap, tap } from 'rxjs/operators';
import { convertFiles, Files, handleFileDrop } from '@utils/index';
import {
CircleButtonTypes,
@@ -73,6 +73,7 @@ export class DossierOverviewScreenComponent extends ListingComponent
imple
private readonly _needsWorkFilterTemplate: TemplateRef;
@ViewChild('fileInput', { static: true }) private readonly _fileInput: ElementRef;
@ViewChild(TableComponent) private readonly _tableComponent: TableComponent;
+ private _fileAttributeConfigs: IFileAttributeConfig[];
constructor(
protected readonly _injector: Injector,
@@ -99,19 +100,7 @@ export class DossierOverviewScreenComponent extends ListingComponent imple
.getEntityChanged$(this.dossierId)
.pipe(tap(dossier => (this.dossierTemplateId = dossier.dossierTemplateId)));
this.currentDossier = this._dossiersService.find(this.dossierId);
-
- this.fileAttributeConfigs = this._fileAttributesService.getFileAttributeConfig(
- this.currentDossier.dossierTemplateId,
- )?.fileAttributeConfigs;
- this.tableColumnConfigs = this.configService.tableConfig(this.displayedAttributes);
- }
-
- private _fileAttributeConfigs: IFileAttributeConfig[];
-
- set fileAttributeConfigs(value: IFileAttributeConfig[]) {
- this._fileAttributeConfigs = value || [];
- this.displayedInFileListAttributes = this._fileAttributeConfigs.filter(config => config.displayedInFileList);
- this.displayedAttributes = this.displayedInFileListAttributes.filter(c => c.displayedInFileList);
+ this._updateFileAttributes();
}
get checkedRequiredFilters(): NestedFilter[] {
@@ -123,6 +112,7 @@ export class DossierOverviewScreenComponent extends ListingComponent imple
}
disabledFn = (file: File) => file.excluded;
+
lastOpenedFn = (file: File) => this._userPreferenceService.getLastOpenedFileForDossier(file.dossierId) === file.id;
async ngOnInit(): Promise {
@@ -150,11 +140,15 @@ export class DossierOverviewScreenComponent extends ListingComponent imple
this._computeAllFilters();
});
- this.addSubscription = this._dossierTemplatesService.entityChanged$.subscribe(() => {
- this.fileAttributeConfigs = this._fileAttributesService.getFileAttributeConfig(
- this.currentDossier.dossierTemplateId,
- )?.fileAttributeConfigs;
- });
+ this.addSubscription = this._dossierTemplatesService
+ .getEntityChanged$(this.currentDossier.dossierTemplateId)
+ .pipe(
+ skip(1),
+ tap(() => {
+ this._updateFileAttributes();
+ }),
+ )
+ .subscribe();
try {
this.dossierAttributes = await this._dossierAttributesService.getWithValues(this.currentDossier);
@@ -170,14 +164,12 @@ export class DossierOverviewScreenComponent extends ListingComponent imple
super.ngOnDestroy();
}
- async ngOnAttach() {
- await this.ngOnInit();
+ ngOnAttach() {
+ this._fileDropOverlayService.initFileDropHandling(this.dossierId);
this._tableComponent?.scrollToLastIndex();
}
- ngOnDetach() {
- this.ngOnDestroy();
- }
+ ngOnDetach() {}
forceReanalysisAction($event: LongPressEvent) {
this.analysisForced = !$event.touchEnd && this._userPreferenceService.areDevFeaturesEnabled;
@@ -203,6 +195,15 @@ export class DossierOverviewScreenComponent extends ListingComponent imple
recentlyModifiedChecker = (file: File) =>
moment(file.lastUpdated).add(this._appConfigService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment());
+ private _updateFileAttributes(): void {
+ this._fileAttributeConfigs =
+ this._fileAttributesService.getFileAttributeConfig(this.currentDossier.dossierTemplateId)?.fileAttributeConfigs || [];
+ this.displayedInFileListAttributes = this._fileAttributeConfigs.filter(config => config.displayedInFileList);
+ this.displayedAttributes = this.displayedInFileListAttributes.filter(c => c.displayedInFileList);
+ this.tableColumnConfigs = this.configService.tableConfig(this.displayedAttributes);
+ this._computeAllFilters();
+ }
+
private async _reloadFiles() {
await this._filesService.loadAll(this.dossierId).toPromise();
this._computeAllFilters();
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.html
index 16f8d9509..a0cd34fa2 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/screen/dossiers-listing-screen.component.html
@@ -13,6 +13,7 @@
[noDataText]="'dossier-listing.no-data.title' | translate"
[noMatchText]="'dossier-listing.no-match.title' | translate"
[showNoDataButton]="currentUser.isManager"
+ [tableColumnConfigs]="tableColumnConfigs"
helpModeKey="dossier-list"
noDataIcon="red:folder"
>
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/document-info/document-info.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/document-info/document-info.component.html
index f5f1120fe..6d6f693e2 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/document-info/document-info.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/document-info/document-info.component.html
@@ -2,6 +2,7 @@
>,
- text: string,
+ text?: string,
convertQuads = false,
): IManualRedactionEntry {
const entry: IManualRedactionEntry = { positions: [] };
@@ -633,6 +631,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
}
entry.value = text;
+ entry.rectangle = !text;
return entry;
}
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html
index c1a6573a4..3b8387637 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html
@@ -79,6 +79,7 @@
*ngIf="displayPdfViewer"
[annotations]="annotations"
[canPerformActions]="canPerformAnnotationActions$ | async"
+ [class.hidden]="!ready"
[dossier]="dossier"
[fileData]="fileData?.fileData"
[file]="file"
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.scss
index d29663f2a..bfbe391d2 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.scss
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.scss
@@ -62,3 +62,7 @@
max-width: 400px;
width: 400px;
}
+
+redaction-pdf-viewer.hidden {
+ visibility: hidden;
+}
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts
index e802c64a7..ec3849327 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts
@@ -1,14 +1,4 @@
-import {
- ChangeDetectionStrategy,
- ChangeDetectorRef,
- Component,
- HostListener,
- NgZone,
- OnDestroy,
- OnInit,
- TemplateRef,
- ViewChild,
-} from '@angular/core';
+import { ChangeDetectorRef, Component, HostListener, NgZone, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router';
import { AppStateService } from '@state/app-state.service';
import { Core, WebViewerInstance } from '@pdftron/webviewer';
@@ -64,7 +54,6 @@ const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
templateUrl: './file-preview-screen.component.html',
styleUrls: ['./file-preview-screen.component.scss'],
providers: [FilterService, ExcludedPagesService, ViewModeService, MultiSelectService, DocumentInfoService],
- changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnInit, OnDestroy, OnAttach, OnDetach {
readonly circleButtonTypes = CircleButtonTypes;
@@ -84,6 +73,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
readonly viewDocumentInfo$: Observable;
readonly file$: Observable;
readonly fileId: string;
+ ready = false;
private _instance: WebViewerInstance;
private _lastPage: string;
private _reloadFileOnReanalysis = false;
@@ -177,13 +167,16 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
async updateViewMode(): Promise {
- const annotations = this._getAnnotations(a => a.getCustomData('redacto-manager'));
+ const ocrAnnotationIds = this.annotationData.allAnnotations.filter(a => a.isOCR).map(a => a.id);
+ const annotations = this._getAnnotations(a => a.getCustomData('redact-manager'));
const redactions = annotations.filter(a => a.getCustomData('redaction'));
switch (this.viewModeService.viewMode) {
case 'STANDARD': {
this._setAnnotationsColor(redactions, 'annotationColor');
- const standardEntries = annotations.filter(a => a.getCustomData('changeLogRemoved') === 'false');
+ const standardEntries = annotations
+ .filter(a => a.getCustomData('changeLogRemoved') === 'false')
+ .filter(a => !ocrAnnotationIds.includes(a.Id));
const nonStandardEntries = annotations.filter(a => a.getCustomData('changeLogRemoved') === 'true');
this._show(standardEntries);
this._hide(nonStandardEntries);
@@ -225,10 +218,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
await this.ngOnInit();
this._lastPage = previousRoute.queryParams.page;
this._changeDetectorRef.markForCheck();
- this._loadingService.stop();
}
async ngOnInit(): Promise {
+ this.ready = false;
this._loadingService.start();
await this.userPreferenceService.saveLastOpenedFileForDossier(this.dossierId, this.fileId);
this._subscribeToFileUpdates();
@@ -403,6 +396,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
async viewerReady($event: WebViewerInstance) {
this._instance = $event;
+ this.ready = true;
await this._stampPDF();
await this._cleanupAndRedrawManualAnnotations();
this._setExcludedPageStyles();
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts
index 94b0625fd..156fcd7c6 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/document-info.service.ts
@@ -27,9 +27,9 @@ export class DocumentInfoService {
fileAttributes$(fileId: string, dossierId: string, dossierTemplateId: string) {
const getAttributes = () => this._fileAttributesService.getFileAttributeConfig(dossierTemplateId).fileAttributeConfigs;
- const dossierTemplateChange$ = this._dossierTemplatesService.entityChanged$.pipe(
- filter(template => template.dossierTemplateId === dossierTemplateId),
- );
+ const dossierTemplateChange$ = this._dossierTemplatesService
+ .getEntityChanged$(dossierTemplateId)
+ .pipe(filter(template => template.dossierTemplateId === dossierTemplateId));
const fileChange$ = this._filesMapService.watch$(dossierId, fileId);
return merge(dossierTemplateChange$, fileChange$).pipe(
map(getAttributes),
diff --git a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html
index 76b7bdbbf..5c44f4aca 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html
@@ -16,6 +16,7 @@
[itemSize]="85"
[noDataText]="'search-screen.no-data' | translate"
[noMatchText]="'search-screen.no-match' | translate"
+ [tableColumnConfigs]="tableColumnConfigs"
noDataIcon="iqser:search"
>
@@ -55,6 +56,10 @@
+
+
+
+
imp
readonly tableHeaderLabel = _('search-screen.table-header');
readonly tableColumnConfigs: TableColumnConfig[] = [
{ label: _('search-screen.cols.document'), width: '2fr' },
+ { label: _('search-screen.cols.assignee') },
{ label: _('search-screen.cols.status') },
{ label: _('search-screen.cols.dossier') },
{ label: _('search-screen.cols.pages'), width: 'auto' },
@@ -134,6 +135,7 @@ export class SearchScreenComponent extends ListingComponent imp
unmatched: unmatchedTerms || null,
highlights,
status: file.workflowStatus,
+ assignee: file.assignee,
numberOfPages: file.numberOfPages,
dossierName: this._dossiersService.find(dossierId).dossierName,
filename: file.filename,
diff --git a/apps/red-ui/src/app/modules/dossier/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/dossier/services/annotation-actions.service.ts
index 816c7f418..87f773043 100644
--- a/apps/red-ui/src/app/modules/dossier/services/annotation-actions.service.ts
+++ b/apps/red-ui/src/app/modules/dossier/services/annotation-actions.service.ts
@@ -88,10 +88,17 @@ export class AnnotationActionsService {
'changeLegalBasis',
$event,
{ annotations, dossier: this._dossier(file) },
- (data: { comment: string; legalBasis: string }) => {
+ (data: { comment: string; legalBasis: string; section: string; value: string }) => {
annotations.forEach(annotation => {
this._processObsAndEmit(
- this._manualAnnotationService.changeLegalBasis(annotation.annotationId, file, data.legalBasis, data.comment),
+ this._manualAnnotationService.changeLegalBasis(
+ annotation.annotationId,
+ file,
+ data.section,
+ data.value,
+ data.legalBasis,
+ data.comment,
+ ),
annotation,
annotationsChanged,
);
@@ -383,7 +390,7 @@ export class AnnotationActionsService {
}
updateHiddenAnnotation(annotations: AnnotationWrapper[], viewerAnnotations: Annotation[], hidden: boolean) {
- const annotationId = (viewerAnnotations[0] as any).Dx;
+ const annotationId = viewerAnnotations[0].Id;
const annotationToBeUpdated = annotations.find((a: AnnotationWrapper) => a.annotationId === annotationId);
annotationToBeUpdated.hidden = hidden;
}
diff --git a/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts
index f777317a6..ecdccdbc9 100644
--- a/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts
+++ b/apps/red-ui/src/app/modules/dossier/services/annotation-draw.service.ts
@@ -180,7 +180,7 @@ export class AnnotationDrawService {
(hideSkipped && annotationWrapper.isSkipped) ||
annotationWrapper.isOCR ||
annotationWrapper.hidden;
- annotation.setCustomData('redacto-manager', 'true');
+ annotation.setCustomData('redact-manager', 'true');
annotation.setCustomData('redaction', String(annotationWrapper.isRedacted));
annotation.setCustomData('skipped', String(annotationWrapper.isSkipped));
annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry));
diff --git a/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts b/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts
index aa9c72a1f..e633cfb30 100644
--- a/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts
+++ b/apps/red-ui/src/app/modules/dossier/services/manual-annotation.service.ts
@@ -102,11 +102,11 @@ export class ManualAnnotationService extends GenericService
}
// /manualRedaction/request/legalBasis
- changeLegalBasis(annotationId: string, file: File, legalBasis: string, comment?: string) {
+ changeLegalBasis(annotationId: string, file: File, section: string, value: string, legalBasis: string, comment?: string) {
const mode: AnnotationActionMode = this._permissionsService.isApprover(this._dossier(file))
? 'change-legal-basis'
: 'request-change-legal-basis';
- return this._makeRequest(mode, file, { annotationId, legalBasis, comment });
+ return this._makeRequest(mode, file, { annotationId, legalBasis, comment, section, value });
}
// this wraps
diff --git a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts
index f13b86b1a..964825091 100644
--- a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts
@@ -21,7 +21,6 @@ import {
ConfirmationDialogInput,
IqserTooltipPosition,
LoadingService,
- Required,
Toaster,
} from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@@ -40,7 +39,7 @@ import { DocumentInfoService } from '../../../screens/file-preview-screen/servic
import { ExpandableFileActionsComponent } from '@shared/components/expandable-file-actions/expandable-file-actions.component';
@Component({
- selector: 'redaction-file-actions',
+ selector: 'redaction-file-actions [file] [type]',
templateUrl: './file-actions.component.html',
styleUrls: ['./file-actions.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -49,8 +48,8 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = this._userService.currentUser;
- @Input() @Required() file: File;
- @Input() @Required() type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
+ @Input() file: File;
+ @Input() type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
@Input() maxWidth: number;
@Output() readonly ocredFile = new EventEmitter();
@@ -58,28 +57,30 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
assignTooltip?: string;
buttonType?: CircleButtonType;
- showUndoApproval: boolean;
- showAssignToSelf: boolean;
- showAssign: boolean;
- showDelete: boolean;
- showOCR: boolean;
- canReanalyse: boolean;
- showUnderReview: boolean;
- showUnderApproval: boolean;
- showApprove: boolean;
- canToggleAnalysis: boolean;
- showStatusBar: boolean;
- showOpenDocument: boolean;
- showReanalyseFilePreview: boolean;
- showReanalyseDossierOverview: boolean;
- analysisForced: boolean;
+ showUndoApproval = false;
+ showAssignToSelf = false;
+ showAssign = false;
+ showDelete = false;
+ showOCR = false;
+ canReanalyse = false;
+ showUnderReview = false;
+ showUnderApproval = false;
+ showApprove = false;
+ canToggleAnalysis = false;
+ showStatusBar = false;
+ showOpenDocument = false;
+ showReanalyseFilePreview = false;
+ showReanalyseDossierOverview = false;
+ analysisForced = false;
isDossierOverview = false;
isDossierOverviewList = false;
isDossierOverviewWorkflow = false;
isFilePreview = false;
tooltipPosition: IqserTooltipPosition;
buttons: Action[];
- @ViewChild(ExpandableFileActionsComponent) _expandableActionsComponent: ExpandableFileActionsComponent;
+
+ @ViewChild(ExpandableFileActionsComponent)
+ private readonly _expandableActionsComponent: ExpandableFileActionsComponent;
constructor(
@Optional() private readonly _excludedPagesService: ExcludedPagesService,
@@ -100,8 +101,9 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
super();
}
- @HostBinding('class.keep-visible') get expanded() {
- return this._expandableActionsComponent?.expanded;
+ @HostBinding('class.keep-visible')
+ get expanded() {
+ return !!this._expandableActionsComponent?.expanded;
}
private get _toggleTooltip(): string {
diff --git a/apps/red-ui/src/app/services/breadcrumbs.service.ts b/apps/red-ui/src/app/services/breadcrumbs.service.ts
index 4d6b7d478..6dd0d9cae 100644
--- a/apps/red-ui/src/app/services/breadcrumbs.service.ts
+++ b/apps/red-ui/src/app/services/breadcrumbs.service.ts
@@ -1,7 +1,12 @@
import { Injectable } from '@angular/core';
-import { List, shareDistinctLast } from '@iqser/common-ui';
-import { IsActiveMatchOptions } from '@angular/router';
-import { BehaviorSubject, Observable } from 'rxjs';
+import { List } from '@iqser/common-ui';
+import { ActivatedRouteSnapshot, IsActiveMatchOptions, NavigationEnd, Router } from '@angular/router';
+import { BehaviorSubject, Observable, of } from 'rxjs';
+import { filter, pluck } from 'rxjs/operators';
+import { FilesMapService } from '@services/entity-services/files-map.service';
+import { DossiersService } from '@services/entity-services/dossiers.service';
+import { TranslateService } from '@ngx-translate/core';
+import { BreadcrumbTypes } from '@red/domain';
export type RouterLinkActiveOptions = { exact: boolean } | IsActiveMatchOptions;
@@ -18,40 +23,79 @@ export type Breadcrumbs = List;
})
export class BreadcrumbsService {
readonly breadcrumbs$: Observable;
- readonly showGoBack$: Observable;
- private readonly _showGoBack$ = new BehaviorSubject(false);
private readonly _store$ = new BehaviorSubject([]);
- constructor() {
+ constructor(
+ private readonly _router: Router,
+ private readonly _translateService: TranslateService,
+ private readonly _filesMapService: FilesMapService,
+ private readonly _dossiersService: DossiersService,
+ ) {
this.breadcrumbs$ = this._store$.asObservable();
- this.showGoBack$ = this._showGoBack$.asObservable().pipe(shareDistinctLast());
+
+ this._router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => {
+ const root = this._router.routerState.snapshot.root;
+ this._clear();
+ this._addBreadcrumbs(root.firstChild);
+ });
}
get breadcrumbs() {
return this._store$.value;
}
- append(breadcrumb: Breadcrumb) {
- const existing = this._store$.value.find(item => item.routerLink.toString() === breadcrumb.routerLink.toString());
- if (existing) {
- this.remove(existing.routerLink);
- }
+ private _append(breadcrumb: Breadcrumb) {
this._store$.next([...this._store$.value, breadcrumb]);
}
- clear() {
+ private _clear() {
this._store$.next([]);
}
- remove(routerLink: string[]) {
- this._store$.next(this._store$.value.filter(item => item.routerLink.toString() !== routerLink.toString()));
+ private _addBreadcrumbs(route: ActivatedRouteSnapshot) {
+ if (route.firstChild) {
+ this._addBreadcrumbs(route.firstChild);
+ return;
+ }
+
+ for (const breadcrumb of route.data.breadcrumbs || []) {
+ switch (breadcrumb) {
+ case BreadcrumbTypes.main:
+ this._addMainBreadcrumb();
+ break;
+ case BreadcrumbTypes.dossier:
+ this._addDossierBreadcrumb(route);
+ break;
+ case BreadcrumbTypes.file:
+ this._addFileBreadcrumb(route);
+ break;
+ }
+ }
}
- showGoBack() {
- this._showGoBack$.next(true);
+ private _addMainBreadcrumb(): void {
+ this._append({
+ name$: of(this._translateService.instant('top-bar.navigation-items.dossiers')),
+ routerLink: ['/main', 'dossiers'],
+ routerLinkActiveOptions: { exact: true },
+ });
}
- hideGoBack() {
- this._showGoBack$.next(false);
+ private _addDossierBreadcrumb(route: ActivatedRouteSnapshot): void {
+ const dossierId = route.paramMap.get('dossierId');
+ this._append({
+ name$: this._dossiersService.getEntityChanged$(dossierId).pipe(pluck('dossierName')),
+ routerLink: ['/main', 'dossiers', dossierId],
+ routerLinkActiveOptions: { exact: true },
+ });
+ }
+
+ private _addFileBreadcrumb(route: ActivatedRouteSnapshot): void {
+ const dossierId = route.paramMap.get('dossierId');
+ const fileId = route.paramMap.get('fileId');
+ this._append({
+ name$: this._filesMapService.watch$(dossierId, fileId).pipe(pluck('filename')),
+ routerLink: ['/main', 'dossiers', dossierId, 'file', fileId],
+ });
}
}
diff --git a/apps/red-ui/src/app/services/entity-services/files-map.service.ts b/apps/red-ui/src/app/services/entity-services/files-map.service.ts
index a8f69b6a4..b861090da 100644
--- a/apps/red-ui/src/app/services/entity-services/files-map.service.ts
+++ b/apps/red-ui/src/app/services/entity-services/files-map.service.ts
@@ -70,8 +70,11 @@ export class FilesMapService {
}
replace(entity: File) {
- const all = this.get(entity.dossierId).filter(file => file.fileId !== entity.fileId);
- this.set(entity.dossierId, [...all, entity]);
+ const existingFile = this.get(entity.dossierId).find(file => file.fileId === entity.fileId);
+ if (existingFile.lastUpdated !== entity.lastUpdated) {
+ const all = this.get(entity.dossierId).filter(file => file.fileId !== entity.fileId);
+ this.set(entity.dossierId, [...all, entity]);
+ }
}
watch$(key: string, entityId: string): Observable {
diff --git a/apps/red-ui/src/app/services/general-settings.service.ts b/apps/red-ui/src/app/services/general-settings.service.ts
index 9eae86e67..10353d8c2 100644
--- a/apps/red-ui/src/app/services/general-settings.service.ts
+++ b/apps/red-ui/src/app/services/general-settings.service.ts
@@ -2,7 +2,6 @@ import { Injectable, Injector } from '@angular/core';
import { GenericService, RequiredParam, Validate } from '@iqser/common-ui';
import { IGeneralConfiguration } from '@red/domain';
import { UserService } from '@services/user.service';
-import { of } from 'rxjs';
@Injectable({
providedIn: 'root',
@@ -13,7 +12,7 @@ export class GeneralSettingsService extends GenericService event.type === KeycloakEventType.OnReady),
+ switchMap(() => from(keycloakService.isLoggedIn())),
+ switchMap(loggedIn => (!loggedIn ? throwError('Not Logged In') : of({}))),
mergeMapTo(generalSettingsService.getGeneralConfigurations()),
tap(configuration => configService.updateDisplayName(configuration.displayName)),
+ tap(() => userPreferenceService.reload()),
+ tap(() => languageService.chooseAndSetInitialLanguage()),
catchError(() => {
title.setTitle('RedactManager');
return of({});
}),
- tap(() => userPreferenceService.reload()),
- tap(() => languageService.chooseAndSetInitialLanguage()),
take(1),
)
.toPromise();
diff --git a/apps/red-ui/src/app/utils/functions.ts b/apps/red-ui/src/app/utils/functions.ts
index 9eab788bf..80d4222b5 100644
--- a/apps/red-ui/src/app/utils/functions.ts
+++ b/apps/red-ui/src/app/utils/functions.ts
@@ -41,7 +41,7 @@ export function getFirstRelevantTextPart(text, direction: 'FORWARD' | 'BACKWARD'
accumulator += char;
- return spaceCount >= 2;
+ return spaceCount >= 3;
};
if (direction === 'FORWARD') {
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index ce5e8969d..aeec13bf8 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -359,6 +359,8 @@
"comment": "Comment",
"legalBasis": "Legal Basis",
"reason": "Select redaction reason",
+ "section": "Paragraph / Location",
+ "classification": "Value / Classification",
"reason-placeholder": "Select a reason..."
},
"header": "Edit Redaction Reason"
@@ -1258,6 +1260,8 @@
"dictionary": "Dictionary",
"legalBasis": "Legal Basis",
"reason": "Reason",
+ "section": "Paragraph / Location",
+ "classification": "Value / Classification",
"reason-placeholder": "Select a reason ...",
"rectangle": "Custom Rectangle",
"text": "Selected text:"
@@ -1488,6 +1492,7 @@
"cols": {
"document": "Document",
"dossier": "Dossier",
+ "assignee": "Assignee",
"pages": "Pages",
"status": "Status"
},
diff --git a/libs/common-ui b/libs/common-ui
index a82a08cd8..caf4838be 160000
--- a/libs/common-ui
+++ b/libs/common-ui
@@ -1 +1 @@
-Subproject commit a82a08cd89e33325a789f5b433cd80adc8aa5e59
+Subproject commit caf4838be63574740e5380c74ad96fe21f7a456b
diff --git a/libs/red-domain/src/lib/files/file.model.ts b/libs/red-domain/src/lib/files/file.model.ts
index 4e839dace..81148059e 100644
--- a/libs/red-domain/src/lib/files/file.model.ts
+++ b/libs/red-domain/src/lib/files/file.model.ts
@@ -104,7 +104,7 @@ export class File extends Entity implements IFile {
this.isNew = this.workflowStatus === WorkflowFileStatuses.NEW;
this.isUnderReview = this.workflowStatus === WorkflowFileStatuses.UNDER_REVIEW;
this.isUnderApproval = this.workflowStatus === WorkflowFileStatuses.UNDER_APPROVAL;
- this.canBeApproved = !this.analysisRequired && !this.hasSuggestions;
+ this.canBeApproved = !this.analysisRequired && !this.hasSuggestions && !this.isProcessing && !this.isError;
this.canBeOpened = !this.isError && !this.isPending && this.numberOfAnalyses > 0;
this.canBeOCRed = !this.excluded && !this.lastOCRTime && (this.isNew || this.isUnderReview || this.isUnderApproval);
diff --git a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts
index ca567f0e8..40040a583 100644
--- a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts
+++ b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts
@@ -10,4 +10,6 @@ export interface IAddRedactionRequest {
reason?: string;
type?: string;
value?: string;
+ section?: string;
+ rectangle?: boolean;
}
diff --git a/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts b/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts
index 45ae9f6c1..a8a9abf9d 100644
--- a/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts
+++ b/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts
@@ -16,4 +16,5 @@ export interface IManualRedactionEntry {
type?: string;
user?: string;
value?: string;
+ rectangle?: boolean;
}
diff --git a/libs/red-domain/src/lib/redaction-log/redaction-log-entry.ts b/libs/red-domain/src/lib/redaction-log/redaction-log-entry.ts
index 209fc808f..c2577442e 100644
--- a/libs/red-domain/src/lib/redaction-log/redaction-log-entry.ts
+++ b/libs/red-domain/src/lib/redaction-log/redaction-log-entry.ts
@@ -14,6 +14,7 @@ export interface IRedactionLogEntry {
engines?: List;
excluded?: boolean;
hint?: boolean;
+ rectangle?: boolean;
id?: string;
image?: boolean;
imageHasTransparency?: boolean;
diff --git a/libs/red-domain/src/lib/search/search-list-item.ts b/libs/red-domain/src/lib/search/search-list-item.ts
index c1b2b700b..1b5006a56 100644
--- a/libs/red-domain/src/lib/search/search-list-item.ts
+++ b/libs/red-domain/src/lib/search/search-list-item.ts
@@ -3,6 +3,7 @@ import { IListable, List } from '@iqser/common-ui';
export interface ISearchListItem extends IListable {
readonly dossierId: string;
readonly filename: string;
+ readonly assignee: string;
readonly unmatched: List | null;
readonly highlights: Record;
readonly routerLink: string;
diff --git a/libs/red-domain/src/lib/shared/breadcrumb-types.ts b/libs/red-domain/src/lib/shared/breadcrumb-types.ts
new file mode 100644
index 000000000..3366c25a2
--- /dev/null
+++ b/libs/red-domain/src/lib/shared/breadcrumb-types.ts
@@ -0,0 +1,7 @@
+export type BreadcrumbType = 'main' | 'dossier' | 'file';
+
+export const BreadcrumbTypes = {
+ main: 'main' as BreadcrumbType,
+ dossier: 'dossier' as BreadcrumbType,
+ file: 'file' as BreadcrumbType,
+};
diff --git a/libs/red-domain/src/lib/shared/index.ts b/libs/red-domain/src/lib/shared/index.ts
index 235e2d28c..0991e932d 100644
--- a/libs/red-domain/src/lib/shared/index.ts
+++ b/libs/red-domain/src/lib/shared/index.ts
@@ -1,4 +1,5 @@
export * from './sorters/status-sorter';
+export * from './breadcrumb-types';
export * from './types';
export * from './rules';
export * from './watermark';
diff --git a/package.json b/package.json
index 193a7a3be..287c958c5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "redaction",
- "version": "3.103.0",
+ "version": "3.105.0",
"private": true,
"license": "MIT",
"scripts": {
diff --git a/paligo-theme.tar.gz b/paligo-theme.tar.gz
index 6aace6a6d..646cc9b83 100644
Binary files a/paligo-theme.tar.gz and b/paligo-theme.tar.gz differ