-
+
-
diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.scss b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.scss
index bdae60f2f..b708a86bd 100644
--- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.scss
+++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.scss
@@ -1,20 +1,3 @@
-.vertical-line {
- width: 1px;
- height: 30px;
- background-color: var(--iqser-separator);
- margin: 0 16px;
-}
-
-.page-header {
- max-width: 100vw;
-}
-
-.actions-container {
- display: flex;
- justify-content: flex-end;
- align-items: center;
-}
-
.content-inner {
position: absolute;
}
@@ -25,8 +8,8 @@
.right-container {
padding: 0;
- width: 350px;
- min-width: 350px;
+ width: var(--workload-width);
+ min-width: var(--workload-width);
position: relative;
display: flex;
flex-direction: column;
@@ -54,6 +37,10 @@
display: flex;
flex: 1;
}
+
+ &.documine-container {
+ width: 70%;
+ }
}
.analysis-progress {
diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts
index ea41e52b8..8cfc9074c 100644
--- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts
+++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts
@@ -1,18 +1,4 @@
-import {
- AfterViewInit,
- ChangeDetectorRef,
- Component,
- computed,
- effect,
- ElementRef,
- HostListener,
- NgZone,
- OnDestroy,
- OnInit,
- TemplateRef,
- ViewChild,
-} from '@angular/core';
-import { MatDialog } from '@angular/material/dialog';
+import { ChangeDetectorRef, Component, effect, NgZone, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { ComponentCanDeactivate } from '@guards/can-deactivate.guard';
@@ -23,16 +9,13 @@ import {
CustomError,
ErrorService,
getConfig,
- HelpModeService,
IConfirmationDialogData,
IqserDialog,
- IqserPermissionsService,
- isIqserDevMode,
LoadingService,
Toaster,
} from '@iqser/common-ui';
import { copyLocalStorageFiltersValues, FilterService, NestedFilter, processFilters } from '@iqser/common-ui/lib/filtering';
-import { AutoUnsubscribe, Bind, bool, Debounce, List, OnAttach, OnDetach } from '@iqser/common-ui/lib/utils';
+import { AutoUnsubscribe, Bind, bool, List, OnAttach, OnDetach } from '@iqser/common-ui/lib/utils';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { ManualRedactionEntryTypes, ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
import { Dictionary, File, ViewModes } from '@red/domain';
@@ -46,8 +29,6 @@ import { PermissionsService } from '@services/permissions.service';
import { ReanalysisService } from '@services/reanalysis.service';
import { Roles } from '@users/roles';
import { PreferencesKeys, UserPreferenceService } from '@users/user-preference.service';
-import { saveAs } from 'file-saver';
-import JSZip from 'jszip';
import { NGXLogger } from 'ngx-logger';
import { combineLatest, first, firstValueFrom, Observable, of, pairwise } from 'rxjs';
import { catchError, filter, map, startWith, switchMap, tap } from 'rxjs/operators';
@@ -73,11 +54,8 @@ import { ManualRedactionService } from './services/manual-redaction.service';
import { PdfProxyService } from './services/pdf-proxy.service';
import { SkippedService } from './services/skipped.service';
import { StampService } from './services/stamp.service';
-import { TablesService } from './services/tables.service';
import { ViewModeService } from './services/view-mode.service';
-import { ALL_HOTKEYS } from './utils/constants';
import { RedactTextData } from './utils/dialog-types';
-import { AnnotationActionsService } from './services/annotation-actions.service';
import { MultiSelectService } from './services/multi-select.service';
@Component({
@@ -85,26 +63,18 @@ import { MultiSelectService } from './services/multi-select.service';
styleUrls: ['./file-preview-screen.component.scss'],
providers: filePreviewScreenProviders,
})
-export class FilePreviewScreenComponent
- extends AutoUnsubscribe
- implements AfterViewInit, OnInit, OnDestroy, OnAttach, OnDetach, ComponentCanDeactivate
-{
+export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnInit, OnDestroy, OnAttach, OnDetach, ComponentCanDeactivate {
readonly circleButtonTypes = CircleButtonTypes;
readonly roles = Roles;
- fullScreen = false;
readonly fileId = this.state.fileId;
readonly dossierId = this.state.dossierId;
- readonly lastAssignee = computed(() => this.getLastAssignee());
- width: number;
- readonly isIqserDevMode = isIqserDevMode();
@ViewChild('annotationFilterTemplate', {
read: TemplateRef,
static: false,
})
private readonly _filterTemplate: TemplateRef
;
#loadAllAnnotationsEnabled = false;
- @ViewChild('actionsWrapper', { static: false }) private readonly _actionsWrapper: ElementRef;
- readonly #isDocumine = getConfig().IS_DOCUMINE;
+ protected readonly isDocumine = getConfig().IS_DOCUMINE;
constructor(
readonly pdf: PdfViewer,
@@ -113,7 +83,6 @@ export class FilePreviewScreenComponent
readonly userPreferenceService: UserPreferenceService,
readonly pdfProxyService: PdfProxyService,
readonly configService: ConfigService,
- private readonly _iqserPermissionsService: IqserPermissionsService,
private readonly _listingService: AnnotationsListingService,
private readonly _router: Router,
private readonly _ngZone: NgZone,
@@ -142,11 +111,7 @@ export class FilePreviewScreenComponent
private readonly _filesService: FilesService,
private readonly _fileManagementService: FileManagementService,
private readonly _readableRedactionsService: ReadableRedactionsService,
- private readonly _helpModeService: HelpModeService,
private readonly _dossierTemplatesService: DossierTemplatesService,
- private readonly _dialog: MatDialog,
- private readonly _tablesService: TablesService,
- private readonly _annotationActionsService: AnnotationActionsService,
private readonly _multiSelectService: MultiSelectService,
) {
super();
@@ -216,12 +181,6 @@ export class FilePreviewScreenComponent
);
}
- getLastAssignee() {
- const { isApproved, lastReviewer, lastApprover } = this.state.file();
- const isRss = this._iqserPermissionsService.has(this.roles.getRss);
- return isApproved ? (isRss ? lastReviewer : lastApprover) : lastReviewer;
- }
-
deleteEarmarksOnViewChange$() {
const isChangingFromEarmarksViewMode$ = this._viewModeService.viewMode$.pipe(
pairwise(),
@@ -298,24 +257,15 @@ export class FilePreviewScreenComponent
this._viewerHeaderService.resetCompareButtons();
this._viewerHeaderService.enableLoadAllAnnotations(); // Reset the button state (since the viewer is reused between files)
super.ngOnDetach();
- document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener);
this.pdf.instance.UI.hotkeys.off('esc');
this._changeRef.markForCheck();
}
ngOnDestroy() {
- document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener);
this.pdf.instance.UI.hotkeys.off('esc');
super.ngOnDestroy();
}
- @Bind()
- fullscreenListener() {
- if (!document.fullscreenElement) {
- this.fullScreen = false;
- }
- }
-
@Bind()
handleEscInsideViewer($event: KeyboardEvent) {
$event.preventDefault();
@@ -352,6 +302,7 @@ export class FilePreviewScreenComponent
}
async ngOnInit(): Promise {
+ document.getElementById('viewer').classList.add(this.isDocumine ? 'documine-viewer' : 'redaction-viewer');
const file = this.state.file();
if (!file) {
@@ -368,19 +319,10 @@ export class FilePreviewScreenComponent
this.pdfProxyService.configureElements();
this.#restoreOldFilters();
- document.documentElement.addEventListener('fullscreenchange', this.fullscreenListener);
this.pdf.instance.UI.hotkeys.on('esc', this.handleEscInsideViewer);
- this.#openComponentLogDialogIfDefault();
this._viewerHeaderService.resetLayers();
}
- ngAfterViewInit() {
- const _observer = new ResizeObserver((entries: ResizeObserverEntry[]) => {
- this._updateItemWidth(entries[0]);
- });
- _observer.observe(this._actionsWrapper.nativeElement);
- }
-
openManualAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
const file = this.state.file();
@@ -406,68 +348,6 @@ export class FilePreviewScreenComponent
);
}
- toggleFullScreen() {
- this.fullScreen = !this.fullScreen;
- if (this.fullScreen) {
- this.#openFullScreen();
- } else {
- this.closeFullScreen();
- }
- }
-
- @HostListener('document:keyup', ['$event'])
- handleKeyEvent($event: KeyboardEvent) {
- if (this._router.url.indexOf('/file/') < 0) {
- return;
- }
-
- if (!ALL_HOTKEYS.includes($event.key) || this._dialog.openDialogs.length) {
- return;
- }
-
- if (['Escape'].includes($event.key)) {
- $event.preventDefault();
- if (this._annotationManager.resizingAnnotationId) {
- const resizedAnnotation = this._fileDataService
- .annotations()
- .find(annotation => annotation.id === this._annotationManager.resizingAnnotationId);
- this._annotationActionsService.cancelResize(resizedAnnotation).then();
- }
-
- if (this._annotationManager.selected.length) {
- this._annotationManager.deselectAll();
- }
-
- if (this._multiSelectService.active()) {
- this._multiSelectService.deactivate();
- }
-
- this.fullScreen = false;
- this.closeFullScreen();
- this._changeRef.markForCheck();
- }
-
- if (!$event.ctrlKey && !$event.metaKey && ['f', 'F'].includes($event.key)) {
- // if you type in an input, don't toggle full-screen
- if ($event.target instanceof HTMLInputElement || $event.target instanceof HTMLTextAreaElement) {
- return;
- }
- this.toggleFullScreen();
- return;
- }
-
- if (['h', 'H'].includes($event.key)) {
- if ($event.target instanceof HTMLInputElement || $event.target instanceof HTMLTextAreaElement) {
- return;
- }
- this._ngZone.run(() => {
- window.focus();
- this._helpModeService.activateHelpMode(false);
- });
- return;
- }
- }
-
async viewerReady(pageNumber?: string) {
if (pageNumber) {
const file = this.state.file();
@@ -489,21 +369,6 @@ export class FilePreviewScreenComponent
this._changeRef.markForCheck();
}
- closeFullScreen() {
- if (!!document.fullscreenElement && document.exitFullscreen) {
- document.exitFullscreen().then();
- }
- }
-
- async downloadOriginalFile({ cacheIdentifier, dossierId, fileId, filename }: File) {
- const originalFile = this._fileManagementService.downloadOriginal(dossierId, fileId, 'response', cacheIdentifier);
- download(await firstValueFrom(originalFile), filename);
- }
-
- openComponentLogView() {
- this._dialogService.openDialog('componentLog', { file: this.state.file(), dictionaries: this.state.dictionaries });
- }
-
loadAnnotations$() {
const annotations$ = this._fileDataService.annotations$.pipe(
startWith([] as AnnotationWrapper[]),
@@ -549,28 +414,6 @@ export class FilePreviewScreenComponent
return this.#cleanupAndRedrawAnnotations(annotationsToDraw);
}
- async getTables() {
- this._loadingService.start();
-
- const currentPage = this.pdf.currentPage();
- const tables = await this._tablesService.get(this.state.dossierId, this.state.fileId, this.pdf.currentPage());
- await this._annotationDrawService.drawTables(tables, currentPage, this.state.dossierTemplateId);
-
- const filename = this.state.file().filename;
- const zip = new JSZip();
-
- tables.forEach((t, index) => {
- const blob = new Blob([atob(t.csvAsBytes)], {
- type: 'text/csv;charset=utf-8',
- });
- zip.file(filename + '_page' + currentPage + '_table' + (index + 1) + '.csv', blob);
- });
-
- saveAs(await zip.generateAsync({ type: 'blob' }), filename + '_tables.zip');
-
- this._loadingService.stop();
- }
-
async #openRedactTextDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
const file = this.state.file();
@@ -594,12 +437,6 @@ export class FilePreviewScreenComponent
return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined))));
}
- @Debounce(30)
- private _updateItemWidth(entry: ResizeObserverEntry): void {
- this.width = entry.contentRect.width;
- this._changeRef.detectChanges();
- }
-
#getAnnotationsToDraw(oldAnnotations: AnnotationWrapper[], newAnnotations: AnnotationWrapper[]) {
const currentPage = this.pdf.currentPage();
const currentPageAnnotations = this._annotationManager.get(a => a.getPageNumber() === currentPage);
@@ -733,10 +570,6 @@ export class FilePreviewScreenComponent
.pipe(tap(() => this.#handleDeletedFile()))
.subscribe();
- this.addActiveScreenSubscription = this._documentViewer.keyUp$.subscribe($event => {
- this.handleKeyEvent($event);
- });
-
this.addActiveScreenSubscription = this.#earmarks$.subscribe();
this.addActiveScreenSubscription = this.deleteEarmarksOnViewChange$().subscribe();
@@ -867,13 +700,6 @@ export class FilePreviewScreenComponent
});
}
- #openFullScreen() {
- const documentElement = document.documentElement;
- if (documentElement.requestFullscreen) {
- documentElement.requestFullscreen().then();
- }
- }
-
#navigateToDossier() {
this._logger.info('Navigating to ', this.state.dossier().dossierName);
return this._router.navigate([this.state.dossier().routerLink]);
@@ -900,14 +726,8 @@ export class FilePreviewScreenComponent
});
}
- #openComponentLogDialogIfDefault() {
- if (this.permissionsService.canViewRssDialog() && this.userPreferenceService.getOpenScmDialogByDefault()) {
- this.openComponentLogView();
- }
- }
-
#getRedactTextDialog(data: RedactTextData) {
- if (this.#isDocumine) {
+ if (this.isDocumine) {
return this._iqserDialog.openDefault(AddAnnotationDialogComponent, { data });
}
diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts
index 95379d171..f21e31e81 100644
--- a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts
+++ b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts
@@ -72,6 +72,10 @@ import { ManualRedactionService } from './services/manual-redaction.service';
import { TablesService } from './services/tables.service';
import { SelectedAnnotationsTableComponent } from './components/selected-annotations-table/selected-annotations-table.component';
import { SelectedAnnotationsListComponent } from './components/selected-annotations-list/selected-annotations-list.component';
+import { FileHeaderComponent } from './components/file-header/file-header.component';
+import { DocumineExportComponent } from './components/documine-export/documine-export.component';
+import { StructuredComponentManagementComponent } from './components/structured-component-management/structured-component-management.component';
+import { EditableStructuredComponentValueComponent } from './components/editable-structured-component-value/editable-structured-component-value.component';
const routes: IqserRoutes = [
{
@@ -121,6 +125,9 @@ const components = [
FilePreviewScreenComponent,
FilePreviewRightContainerComponent,
ReadonlyBannerComponent,
+ FileHeaderComponent,
+ DocumineExportComponent,
+ StructuredComponentManagementComponent,
];
@NgModule({
@@ -156,6 +163,7 @@ const components = [
DisableStopPropagationDirective,
SelectedAnnotationsTableComponent,
SelectedAnnotationsListComponent,
+ EditableStructuredComponentValueComponent,
],
providers: [FilePreviewDialogService, ManualRedactionService, DocumentUnloadedGuard, TablesService],
})
diff --git a/apps/red-ui/src/app/modules/file-preview/services/component-log-filter.service.ts b/apps/red-ui/src/app/modules/file-preview/services/component-log-filter.service.ts
new file mode 100644
index 000000000..8f58531d7
--- /dev/null
+++ b/apps/red-ui/src/app/modules/file-preview/services/component-log-filter.service.ts
@@ -0,0 +1,43 @@
+import { Injectable } from '@angular/core';
+import { ComponentLogEntry } from '@red/domain';
+import { INestedFilter, NestedFilter } from '@common-ui/filtering';
+
+@Injectable()
+export class ComponentLogFilterService {
+ filterGroups(entities: ComponentLogEntry[]) {
+ const allDistinctComponentLogs = new Set();
+
+ entities?.forEach(entry => allDistinctComponentLogs.add(entry.name));
+
+ const componentLogFilters = [...allDistinctComponentLogs].map(
+ id =>
+ new NestedFilter({
+ id: id,
+ label: id.replaceAll('_', ' '),
+ }),
+ );
+
+ return [
+ {
+ slug: 'componentLogFilters',
+ filters: componentLogFilters,
+ },
+ ];
+ }
+
+ filterComponents(components: ComponentLogEntry[], filters: INestedFilter[]) {
+ const someFiltersChecked = !!filters.find(f => f.checked);
+ if (!someFiltersChecked) {
+ return components;
+ }
+
+ const checkedFiltersIds = filters.reduce((ids, f) => {
+ if (f.checked) {
+ ids.push(f.id);
+ }
+ return ids;
+ }, []);
+
+ return components.filter(c => checkedFiltersIds.includes(c.name));
+ }
+}
diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts
index 283eed614..59af5fef2 100644
--- a/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts
+++ b/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts
@@ -6,16 +6,8 @@ import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/doc
import { ForceAnnotationDialogComponent } from '../dialogs/force-redaction-dialog/force-annotation-dialog.component';
import { HighlightActionDialogComponent } from '../dialogs/highlight-action-dialog/highlight-action-dialog.component';
import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
-import { StructuredComponentManagementDialogComponent } from '../dialogs/structured-component-management-dialog/structured-component-management-dialog.component';
-type DialogType =
- | 'confirm'
- | 'documentInfo'
- | 'componentLog'
- | 'changeLegalBasis'
- | 'forceAnnotation'
- | 'manualAnnotation'
- | 'highlightAction';
+type DialogType = 'confirm' | 'documentInfo' | 'changeLegalBasis' | 'forceAnnotation' | 'manualAnnotation' | 'highlightAction';
@Injectable()
export class FilePreviewDialogService extends DialogService {
@@ -41,10 +33,6 @@ export class FilePreviewDialogService extends DialogService {
highlightAction: {
component: HighlightActionDialogComponent,
},
- componentLog: {
- component: StructuredComponentManagementDialogComponent,
- dialogConfig: { width: '90vw' },
- },
};
constructor(protected readonly _dialog: MatDialog) {
diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts
index 2d0096bfc..3f7d3b0ef 100644
--- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts
+++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts
@@ -135,9 +135,11 @@ export class PdfProxyService {
}
configureElements() {
- const hexColor = this._dictionariesMapService.get(this._state.dossierTemplateId, 'manual').hexColor;
- const color = this._annotationDrawService.convertColor(hexColor);
- this._documentViewer.setRectangleToolStyles(color);
+ const hexColor = this._dictionariesMapService.get(this._state.dossierTemplateId, 'manual')?.hexColor;
+ if (hexColor) {
+ const color = this._annotationDrawService.convertColor(hexColor);
+ this._documentViewer.setRectangleToolStyles(color);
+ }
}
#configureRectangleAnnotationPopup(annotation: Annotation) {
diff --git a/apps/red-ui/src/app/modules/icons/icons.module.ts b/apps/red-ui/src/app/modules/icons/icons.module.ts
index ebd3203ad..1576fccb4 100644
--- a/apps/red-ui/src/app/modules/icons/icons.module.ts
+++ b/apps/red-ui/src/app/modules/icons/icons.module.ts
@@ -29,6 +29,7 @@ export class IconsModule {
'archive',
'arrow-up',
'arrow-down',
+ 'arrow-right',
'assign',
'assign-me',
'attribute',
@@ -41,6 +42,7 @@ export class IconsModule {
'denied',
'disable-analysis',
'double-chevron-right',
+ 'draggable-dots',
'enable-analysis',
'enter',
'entries',
diff --git a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html
index 3fd4bcd55..c64f8a8ed 100644
--- a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html
+++ b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.html
@@ -1,3 +1,3 @@
-
+
diff --git a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.ts
index a9e9f6442..34f006113 100644
--- a/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.ts
+++ b/apps/red-ui/src/app/modules/pdf-viewer/pdf-viewer.component.ts
@@ -1,8 +1,11 @@
import { Component } from '@angular/core';
+import { getConfig } from '@iqser/common-ui';
@Component({
selector: 'redaction-pdf-viewer',
templateUrl: './pdf-viewer.component.html',
styleUrls: ['./pdf-viewer.component.scss'],
})
-export class PdfViewerComponent {}
+export class PdfViewerComponent {
+ protected readonly isDocumine = getConfig().IS_DOCUMINE;
+}
diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts
index 1a97af173..5c35cc60c 100644
--- a/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts
+++ b/apps/red-ui/src/app/modules/pdf-viewer/services/viewer-header.service.ts
@@ -275,6 +275,15 @@ export class ViewerHeaderService {
updateElements(): void {
this._pdf.instance?.UI.setHeaderItems(header => {
+ let deletedDividers = 0;
+ if (this.#isDocumine) {
+ const secondHeaderElement = header.getItems()[1] as IHeaderElement;
+ if (secondHeaderElement.type === 'divider') {
+ header.getItems().splice(1, 1);
+ deletedDividers = 1;
+ }
+ }
+
const enabledItems: IHeaderElement[] = [];
const groups: HeaderElementType[][] = [
[HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON],
@@ -293,18 +302,19 @@ export class ViewerHeaderService {
groups.forEach(group => this.#pushGroup(enabledItems, group));
const loadAllAnnotationsButton = this.#buttons.get(HeaderElements.LOAD_ALL_ANNOTATIONS);
- let startButtons = 11;
- let deleteCount = 15;
+ let startButtons = 10 - deletedDividers;
+ let deleteCount = 14 - deletedDividers;
if (this.#isEnabled(HeaderElements.LOAD_ALL_ANNOTATIONS)) {
if (!header.getItems().includes(loadAllAnnotationsButton)) {
header.get('leftPanelButton').insertAfter(loadAllAnnotationsButton);
}
- startButtons = 12;
- deleteCount = 16;
+ startButtons = 11 - deletedDividers;
+ deleteCount = 15 - deletedDividers;
} else {
header.delete(HeaderElements.LOAD_ALL_ANNOTATIONS);
}
+
header.getItems().splice(startButtons, header.getItems().length - deleteCount, ...enabledItems);
});
diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dictionary-dialog/edit-dictionary-dialog.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dictionary-dialog/edit-dictionary-dialog.component.ts
index 1f31b8b2d..52328de72 100644
--- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dictionary-dialog/edit-dictionary-dialog.component.ts
+++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dictionary-dialog/edit-dictionary-dialog.component.ts
@@ -82,6 +82,4 @@ export class EditDictionaryDialogComponent extends IqserDialogComponent {
@@ -34,21 +35,32 @@ export class ComponentLogService extends GenericService {
);
}
- getComponentLogData(dossierTemplateId: string, dossierId: string, fileId: string): Observable {
+ getComponentLogData(
+ dossierTemplateId: string,
+ dossierId: string,
+ fileId: string,
+ dictionaries: Dictionary[],
+ ): Observable {
return this.#componentLogRequest(dossierTemplateId, dossierId, fileId).pipe(
map(data => data.componentDetails),
catchError(() => of({} as ComponentDetails)),
map(componentDetails => this.#mapComponentDetails(componentDetails)),
mapEach(log => new ComponentLogEntry(log)),
+ map(log => this.#updateDisplayValue(log, dictionaries)),
);
}
- override(dossierId: string, fileId: string, componentOverrides: Record): Observable {
- return this._post({ componentOverrides }, `componentLog/override/${dossierId}/${fileId}`);
+ override(dossierTemplateId: string, dossierId: string, fileId: string, componentLogEntry: IComponentLogEntry) {
+ return this._http.post(
+ `/api/dossier-templates/${dossierTemplateId}/dossiers/${dossierId}/files/${fileId}/overrides`,
+ componentLogEntry,
+ );
}
- revertOverride(dossierId: string, fileId: string, components: string[]): Observable {
- return this._post({ components }, `componentLog/override/revert/${dossierId}/${fileId}`);
+ revertOverride(dossierTemplateId: string, dossierId: string, fileId: string, components: string[]) {
+ return this._http.post(`/api/dossier-templates/${dossierTemplateId}/dossiers/${dossierId}/files/${fileId}/overrides/revert`, {
+ components,
+ });
}
exportJSON(dossierTemplateId: string, dossierId: string, file?: IFile): Observable {
@@ -91,4 +103,17 @@ export class ComponentLogService extends GenericService {
#mapComponentDetails(componentDetails: ComponentDetails): IComponentLogEntry[] {
return Object.keys(componentDetails).reduce((res, key) => (res.push(componentDetails[key]), res), []);
}
+
+ #updateDisplayValue(componentLogs: ComponentLogEntry[], dictionaries: Dictionary[]): ComponentLogEntry[] {
+ for (const componentLog of componentLogs) {
+ for (const componentValue of componentLog.componentValues) {
+ for (const reference of componentValue.entityReferences) {
+ const foundDictionary =
+ dictionaries.find(dict => dict.type === reference.type) ?? ({ label: reference.type } as Dictionary);
+ reference.displayValue = foundDictionary.label;
+ }
+ }
+ }
+ return componentLogs;
+ }
}
diff --git a/apps/red-ui/src/app/utils/filter-utils.ts b/apps/red-ui/src/app/utils/filter-utils.ts
index 68bf58595..c7b1439fd 100644
--- a/apps/red-ui/src/app/utils/filter-utils.ts
+++ b/apps/red-ui/src/app/utils/filter-utils.ts
@@ -1,5 +1,5 @@
import { handleCheckedValue, INestedFilter } from '@iqser/common-ui/lib/filtering';
-import { Dossier, File, User, UserType } from '@red/domain';
+import { ComponentLogEntry, Dossier, File, User, UserType } from '@red/domain';
export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INestedFilter[], allFilters: INestedFilter[]) {
const newFiltersDelta = {};
diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json
index 95df3a6e8..a5f042e1f 100644
--- a/apps/red-ui/src/assets/i18n/redact/de.json
+++ b/apps/red-ui/src/assets/i18n/redact/de.json
@@ -515,7 +515,7 @@
"tooltip": "",
"xml": ""
},
- "component-log-dialog": {
+ "component-management": {
"actions": {
"cancel-edit": "Abbrechen",
"close": "Close",
@@ -526,14 +526,11 @@
"save": "Save",
"undo": "Undo to: {value}"
},
- "annotations": "{type} found on page {page} by rule #{ruleNumber}",
+ "components": "",
"table-header": {
- "annotation-references": "Annotation references",
- "component": "Component",
- "transformation-rule": "Transformation rule",
- "value": "Value"
- },
- "title": "Component view"
+ "component": "",
+ "value": ""
+ }
},
"component-mappings-screen": {
"action": {
@@ -826,6 +823,12 @@
"save": "Dokumenteninformation speichern",
"title": "Datei-Attribute anlegen"
},
+ "documine-export": {
+ "document": "",
+ "document-tooltip": "",
+ "export": "",
+ "export-tooltip": ""
+ },
"dossier-attribute-types": {
"date": "Datum",
"image": "Bild",
@@ -1506,7 +1509,6 @@
"no-data": {
"title": "Auf dieser Seite gibt es keine Anmerkungen."
},
- "open-rss-view": "Open Structured Component Management View",
"quick-nav": {
"jump-first": "Zur ersten Seite springen",
"jump-last": "Zur letzten Seite springen"
@@ -2249,6 +2251,15 @@
"header": "Resize {type}"
}
},
+ "revert-value-dialog": {
+ "actions": {
+ "cancel": "",
+ "revert": ""
+ },
+ "current-values": "",
+ "original-values": "",
+ "title": ""
+ },
"roles": {
"inactive": "Inaktiv",
"manager-admin": "Manager & Admin",
@@ -2542,4 +2553,4 @@
}
},
"yesterday": "Gestern"
-}
\ No newline at end of file
+}
diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json
index 42bb0de03..de7165b4d 100644
--- a/apps/red-ui/src/assets/i18n/redact/en.json
+++ b/apps/red-ui/src/assets/i18n/redact/en.json
@@ -390,6 +390,7 @@
"annotation": {
"pending": "(Pending analysis)"
},
+ "annotations": "Annotations",
"archived-dossiers-listing": {
"no-data": {
"title": "No archived dossiers."
@@ -515,25 +516,20 @@
"tooltip": "",
"xml": ""
},
- "component-log-dialog": {
+ "component-management": {
"actions": {
- "cancel-edit": "Cancel",
- "close": "Close",
- "display-by-default": "Display by default when opening documents",
+ "add": "Add",
+ "cancel": "Cancel",
+ "delete": "Remove value",
"edit": "Edit",
- "export-json": "Export JSON",
- "export-xml": "Export XML",
"save": "Save",
- "undo": "Undo to: {value}"
+ "undo": "Undo"
},
- "annotations": "{type} found on page {page} by rule #{ruleNumber}",
+ "components": "Components",
"table-header": {
- "annotation-references": "Annotation references",
"component": "Component",
- "transformation-rule": "Transformation rule",
"value": "Value"
- },
- "title": "Component view"
+ }
},
"component-mappings-screen": {
"action": {
@@ -826,6 +822,12 @@
"save": "Save document info",
"title": "Enter file attributes"
},
+ "documine-export": {
+ "document": "Document",
+ "document-tooltip": "Document",
+ "export": "Export",
+ "export-tooltip": "Export"
+ },
"dossier-attribute-types": {
"date": "Date",
"image": "Image",
@@ -1506,7 +1508,6 @@
"no-data": {
"title": "There have been no changes to this page."
},
- "open-rss-view": "Open Structured Component Management View",
"quick-nav": {
"jump-first": "Jump to first page",
"jump-last": "Jump to last page"
@@ -2249,6 +2250,15 @@
"header": "Resize {type}"
}
},
+ "revert-value-dialog": {
+ "actions": {
+ "cancel": "Cancel",
+ "revert": "Revert to original values"
+ },
+ "current-values": "Current values",
+ "original-values": "Original values",
+ "title": "Revert to the original values?"
+ },
"roles": {
"inactive": "Inactive",
"manager-admin": "Manager & admin",
@@ -2542,4 +2552,4 @@
}
},
"yesterday": "Yesterday"
-}
\ No newline at end of file
+}
diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json
index 3545578c6..6dc3c29a1 100644
--- a/apps/red-ui/src/assets/i18n/scm/de.json
+++ b/apps/red-ui/src/assets/i18n/scm/de.json
@@ -515,25 +515,20 @@
"tooltip": "Component download",
"xml": "Download as XML"
},
- "component-log-dialog": {
+ "component-management": {
"actions": {
- "cancel-edit": "Cancel",
- "close": "Close",
- "display-by-default": "Display by default when opening documents",
- "edit": "Edit",
- "export-json": "Export JSON",
- "export-xml": "Export XML",
- "save": "Save",
- "undo": "Undo"
+ "add": "",
+ "cancel": "",
+ "delete": "",
+ "edit": "",
+ "save": "",
+ "undo": ""
},
- "annotations": "{type} found on page {page} by rule #{ruleNumber}",
+ "components": "",
"table-header": {
- "annotation-references": "Annotation references",
- "component": "Component",
- "transformation-rule": "Transformation rule",
- "value": "Value"
- },
- "title": "Structured Component Management"
+ "component": "",
+ "value": ""
+ }
},
"component-mappings-screen": {
"action": {
@@ -826,6 +821,12 @@
"save": "Dokumenteninformation speichern",
"title": "Datei-Attribute anlegen"
},
+ "documine-export": {
+ "document": "",
+ "document-tooltip": "",
+ "export": "",
+ "export-tooltip": ""
+ },
"dossier-attribute-types": {
"date": "Datum",
"image": "Bild",
@@ -1506,7 +1507,6 @@
"no-data": {
"title": "Auf dieser Seite gibt es keine Anmerkungen."
},
- "open-rss-view": "Open component view",
"quick-nav": {
"jump-first": "Zur ersten Seite springen",
"jump-last": "Zur letzten Seite springen"
@@ -2249,6 +2249,15 @@
"header": "Resize {type}"
}
},
+ "revert-value-dialog": {
+ "actions": {
+ "cancel": "",
+ "revert": ""
+ },
+ "current-values": "",
+ "original-values": "",
+ "title": ""
+ },
"roles": {
"inactive": "Inaktiv",
"manager-admin": "Manager & admin",
@@ -2542,4 +2551,4 @@
}
},
"yesterday": "Gestern"
-}
\ No newline at end of file
+}
diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json
index 495860a61..d9066d318 100644
--- a/apps/red-ui/src/assets/i18n/scm/en.json
+++ b/apps/red-ui/src/assets/i18n/scm/en.json
@@ -390,6 +390,7 @@
"annotation": {
"pending": "(Pending analysis)"
},
+ "annotations": "Annotations",
"archived-dossiers-listing": {
"no-data": {
"title": "No archived dossiers."
@@ -515,25 +516,20 @@
"tooltip": "Component download",
"xml": "Download as XML"
},
- "component-log-dialog": {
+ "component-management": {
"actions": {
- "cancel-edit": "Cancel",
- "close": "Close",
- "display-by-default": "Display by default when opening documents",
+ "add": "Add",
+ "cancel": "Cancel",
+ "delete": "Remove value",
"edit": "Edit",
- "export-json": "Export JSON",
- "export-xml": "Export XML",
"save": "Save",
- "undo": "Undo to: {value}"
+ "undo": "Undo"
},
- "annotations": "{type} found on page {page} by rule #{ruleNumber}",
+ "components": "Components",
"table-header": {
- "annotation-references": "Annotation references",
"component": "Component",
- "transformation-rule": "Transformation rule",
"value": "Value"
- },
- "title": "Component view"
+ }
},
"component-mappings-screen": {
"action": {
@@ -826,6 +822,12 @@
"save": "Save document info",
"title": "Enter file attributes"
},
+ "documine-export": {
+ "document": "Document",
+ "document-tooltip": "Document",
+ "export": "Export",
+ "export-tooltip": "Export"
+ },
"dossier-attribute-types": {
"date": "Date",
"image": "Image",
@@ -1506,7 +1508,6 @@
"no-data": {
"title": "There have been no changes to this page."
},
- "open-rss-view": "Open component view",
"quick-nav": {
"jump-first": "Jump to first page",
"jump-last": "Jump to last page"
@@ -2249,6 +2250,15 @@
"header": "Resize {type}"
}
},
+ "revert-value-dialog": {
+ "actions": {
+ "cancel": "Cancel",
+ "revert": "Revert to original values"
+ },
+ "current-values": "Current values",
+ "original-values": "Original values",
+ "title": "Revert to the original values?"
+ },
"roles": {
"inactive": "Inactive",
"manager-admin": "Manager & admin",
@@ -2542,4 +2552,4 @@
}
},
"yesterday": "Yesterday"
-}
\ No newline at end of file
+}
diff --git a/apps/red-ui/src/assets/icons/general/arrow-right.svg b/apps/red-ui/src/assets/icons/general/arrow-right.svg
new file mode 100644
index 000000000..d6cb9a8ce
--- /dev/null
+++ b/apps/red-ui/src/assets/icons/general/arrow-right.svg
@@ -0,0 +1,5 @@
+
diff --git a/apps/red-ui/src/assets/icons/general/draggable-dots.svg b/apps/red-ui/src/assets/icons/general/draggable-dots.svg
new file mode 100644
index 000000000..d2b1d8468
--- /dev/null
+++ b/apps/red-ui/src/assets/icons/general/draggable-dots.svg
@@ -0,0 +1,23 @@
+
+
+
+
diff --git a/apps/red-ui/src/assets/pdftron/stylesheet.css b/apps/red-ui/src/assets/pdftron/stylesheet.css
index e62137e5a..a6df83f25 100644
--- a/apps/red-ui/src/assets/pdftron/stylesheet.css
+++ b/apps/red-ui/src/assets/pdftron/stylesheet.css
@@ -55,3 +55,11 @@ button.Button[data-element='LOAD_ALL_ANNOTATIONS'] > img[src='/ui/assets/icons/g
.HeaderItems .Button.active > img {
filter: invert(19%) sepia(100%) saturate(791%) hue-rotate(175deg) brightness(89%) contrast(85%);
}
+
+.MainHeader {
+ height: 36px !important;
+}
+
+.view-header-border {
+ background: rgba(226, 228, 233, 0.9);
+}
diff --git a/apps/red-ui/src/styles.scss b/apps/red-ui/src/styles.scss
index a09022d4c..699dc8d73 100644
--- a/apps/red-ui/src/styles.scss
+++ b/apps/red-ui/src/styles.scss
@@ -163,12 +163,15 @@ $dark-accent-10: darken(vars.$accent, 10%);
body {
--workload-width: 350px;
+ --documine-workload-content-width: 200px;
+ --structured-component-management-width: 30%;
+ --qiuck-navigation-width: 61px;
--iqser-app-name-font-family: OpenSans Extrabold, sans-serif;
--iqser-app-name-font-size: 13px;
--iqser-logo-size: 28px;
}
-#viewer {
+.redaction-viewer {
visibility: hidden;
width: calc(100% - var(--workload-width));
height: calc(100% - calc(var(--iqser-top-bar-height) + 50px));
@@ -176,3 +179,14 @@ body {
left: 0;
position: absolute;
}
+
+.documine-viewer {
+ visibility: hidden;
+ width: calc(
+ 100% - var(--structured-component-management-width) - var(--documine-workload-content-width) - var(--qiuck-navigation-width) - 3px
+ );
+ height: calc(100% - calc(var(--iqser-top-bar-height) + 50px));
+ bottom: 0;
+ right: calc(var(--qiuck-navigation-width) + 2px);
+ position: absolute;
+}
diff --git a/libs/common-ui b/libs/common-ui
index 04eaca160..748cce403 160000
--- a/libs/common-ui
+++ b/libs/common-ui
@@ -1 +1 @@
-Subproject commit 04eaca1600149e3f4e803fd2334c25465197dbf6
+Subproject commit 748cce403285c97e14cd3115a828c94c9d5d4520
diff --git a/libs/red-domain/src/lib/component-log/component-log-entry.ts b/libs/red-domain/src/lib/component-log/component-log-entry.ts
index 6616c843f..1a53a3bb5 100644
--- a/libs/red-domain/src/lib/component-log/component-log-entry.ts
+++ b/libs/red-domain/src/lib/component-log/component-log-entry.ts
@@ -6,16 +6,19 @@ export interface IComponentLogEntry {
name: string;
originalKey: string;
componentValues: IComponentValue[];
+ overridden?: boolean;
}
export class ComponentLogEntry implements IComponentLogEntry {
readonly name: string;
readonly originalKey: string;
readonly componentValues: ComponentValue[];
+ readonly overridden: boolean;
constructor(entry: IComponentLogEntry) {
- this.name = entry.name.replaceAll('_', ' ');
+ this.name = entry.name;
this.originalKey = entry.name;
this.componentValues = entry.componentValues;
+ this.overridden = !!entry.overridden;
}
}
diff --git a/libs/red-domain/src/lib/component-log/component-value.ts b/libs/red-domain/src/lib/component-log/component-value.ts
index e9d680f29..a5d4c776d 100644
--- a/libs/red-domain/src/lib/component-log/component-value.ts
+++ b/libs/red-domain/src/lib/component-log/component-value.ts
@@ -1,17 +1,17 @@
export interface EntityReference {
- readonly id: string;
- readonly type: string;
- readonly entityRuleId: string;
- readonly page: number;
+ id: string;
+ type: string;
+ entityRuleId: string;
+ page: number;
displayValue?: string;
}
export interface IComponentValue {
- readonly value: string;
- readonly originalValue: string;
- readonly valueDescription: string;
- readonly componentRuleId: string;
- readonly entityReferences: EntityReference[];
+ value: string;
+ originalValue: string;
+ valueDescription: string;
+ componentRuleId: string;
+ entityReferences: EntityReference[];
}
export class ComponentValue implements IComponentValue {