diff --git a/apps/red-ui/src/app/models/file/annotation.permissions.ts b/apps/red-ui/src/app/models/file/annotation.permissions.ts
index 55dc11761..81c805e68 100644
--- a/apps/red-ui/src/app/models/file/annotation.permissions.ts
+++ b/apps/red-ui/src/app/models/file/annotation.permissions.ts
@@ -1,24 +1,25 @@
import { UserWrapper } from '@services/user.service';
import { AnnotationWrapper } from './annotation.wrapper';
+import { isArray } from 'rxjs/internal-compatibility';
export class AnnotationPermissions {
- canUndo: boolean;
+ canUndo = true;
- canAcceptRecommendation: boolean;
- canMarkTextOnlyAsFalsePositive: boolean;
- canMarkAsFalsePositive: boolean;
+ canAcceptRecommendation = true;
+ canMarkTextOnlyAsFalsePositive = true;
+ canMarkAsFalsePositive = true;
- canRemoveOrSuggestToRemoveOnlyHere: boolean;
- canRemoveOrSuggestToRemoveFromDictionary: boolean;
+ canRemoveOrSuggestToRemoveOnlyHere = true;
+ canRemoveOrSuggestToRemoveFromDictionary = true;
- canAcceptSuggestion: boolean;
- canRejectSuggestion: boolean;
+ canAcceptSuggestion = true;
+ canRejectSuggestion = true;
- canForceRedaction: boolean;
+ canForceRedaction = true;
- canChangeLegalBasis: boolean;
+ canChangeLegalBasis = true;
- canRecategorizeImage: boolean;
+ canRecategorizeImage = true;
get canPerformMultipleRemoveActions() {
return (
@@ -30,42 +31,64 @@ export class AnnotationPermissions {
);
}
- static forUser(isApprover: boolean, user: UserWrapper, annotation: AnnotationWrapper) {
- const permissions: AnnotationPermissions = new AnnotationPermissions();
+ static forUser(
+ isApprover: boolean,
+ user: UserWrapper,
+ annotations: AnnotationWrapper | AnnotationWrapper[]
+ ) {
+ if (!isArray(annotations)) {
+ annotations = [annotations];
+ }
- permissions.canUndo =
- (!isApprover && annotation.isSuggestion) ||
- (isApprover && annotation.isUndoableActionForApprover);
+ const summedPermissions: AnnotationPermissions = new AnnotationPermissions();
- permissions.canForceRedaction = annotation.isSkipped && !permissions.canUndo;
+ for (const annotation of annotations) {
+ const permissions: AnnotationPermissions = new AnnotationPermissions();
+ permissions.canUndo =
+ (!isApprover && annotation.isSuggestion) ||
+ (isApprover && annotation.isUndoableActionForApprover);
- permissions.canAcceptRecommendation = annotation.isRecommendation;
+ permissions.canForceRedaction = annotation.isSkipped && !permissions.canUndo;
- permissions.canMarkAsFalsePositive =
- annotation.canBeMarkedAsFalsePositive && !annotation.force;
- permissions.canMarkTextOnlyAsFalsePositive =
- annotation.canBeMarkedAsFalsePositiveWithTextOnly && !annotation.force;
+ permissions.canAcceptRecommendation = annotation.isRecommendation;
- permissions.canRemoveOrSuggestToRemoveOnlyHere = annotation.isRedacted && !annotation.force;
- permissions.canRemoveOrSuggestToRemoveFromDictionary =
- annotation.isRedacted &&
- !annotation.isManualRedaction &&
- annotation.isModifyDictionary &&
- !annotation.force;
+ permissions.canMarkAsFalsePositive =
+ annotation.canBeMarkedAsFalsePositive && !annotation.force;
+ permissions.canMarkTextOnlyAsFalsePositive =
+ annotation.canBeMarkedAsFalsePositiveWithTextOnly && !annotation.force;
- permissions.canAcceptSuggestion =
- isApprover && (annotation.isSuggestion || annotation.isDeclinedSuggestion);
- permissions.canRejectSuggestion =
- isApprover &&
- (annotation.isSuggestion ||
- (annotation.isReadyForAnalysis &&
- !permissions.canUndo &&
- annotation.superType !== 'pending-analysis'));
+ permissions.canRemoveOrSuggestToRemoveOnlyHere =
+ annotation.isRedacted && !annotation.force;
+ permissions.canRemoveOrSuggestToRemoveFromDictionary =
+ annotation.isRedacted &&
+ !annotation.isManualRedaction &&
+ annotation.isModifyDictionary &&
+ !annotation.force;
- permissions.canChangeLegalBasis = !annotation.isManualRedaction && annotation.isRedacted;
+ permissions.canAcceptSuggestion =
+ isApprover && (annotation.isSuggestion || annotation.isDeclinedSuggestion);
+ permissions.canRejectSuggestion =
+ isApprover &&
+ (annotation.isSuggestion ||
+ (annotation.isReadyForAnalysis &&
+ !permissions.canUndo &&
+ annotation.superType !== 'pending-analysis'));
- permissions.canRecategorizeImage = annotation.isImage;
+ permissions.canChangeLegalBasis =
+ !annotation.isManualRedaction && annotation.isRedacted;
- return permissions;
+ permissions.canRecategorizeImage = annotation.isImage;
+
+ summedPermissions._merge(permissions);
+ }
+ return summedPermissions;
+ }
+
+ private _merge(permissions: AnnotationPermissions) {
+ for (const key of Object.keys(this)) {
+ if (typeof this[key] === 'boolean') {
+ this[key] = this[key] && permissions[key];
+ }
+ }
}
}
diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts
index 46d25d634..268c5efa5 100644
--- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts
+++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts
@@ -76,28 +76,15 @@ export class AnnotationWrapper {
}
get canBeMarkedAsFalsePositive() {
- return (
- (this.isRecommendation || this.superType === 'redaction') &&
- (this.hasTextAfter || this.hasTextBefore) &&
- !this.isImage
- );
+ return (this.isRecommendation || this.superType === 'redaction') && (this.hasTextAfter || this.hasTextBefore) && !this.isImage;
}
get canBeMarkedAsFalsePositiveWithTextOnly() {
- return (
- !this.canBeMarkedAsFalsePositive &&
- (this.isRecommendation || this.superType === 'redaction') &&
- !this.isImage
- );
+ return !this.canBeMarkedAsFalsePositive && (this.isRecommendation || this.superType === 'redaction') && !this.isImage;
}
get isSuperTypeBasedColor() {
- return (
- this.isSkipped ||
- this.isSuggestion ||
- this.isReadyForAnalysis ||
- this.isDeclinedSuggestion
- );
+ return this.isSkipped || this.isSuggestion || this.isReadyForAnalysis || this.isDeclinedSuggestion;
}
get isSkipped() {
@@ -115,9 +102,7 @@ export class AnnotationWrapper {
get isFalsePositive() {
return (
this.dictionary?.toLowerCase() === 'false_positive' &&
- (this.superType === 'skipped' ||
- this.superType === 'hint' ||
- this.superType === 'redaction')
+ (this.superType === 'skipped' || this.superType === 'hint' || this.superType === 'redaction')
);
}
@@ -168,10 +153,7 @@ export class AnnotationWrapper {
}
get isSuggestionRemove() {
- return (
- this.superType === 'suggestion-remove' ||
- this.superType === 'suggestion-remove-dictionary'
- );
+ return this.superType === 'suggestion-remove' || this.superType === 'suggestion-remove-dictionary';
}
get isModifyDictionary() {
@@ -179,10 +161,7 @@ export class AnnotationWrapper {
}
get isConvertedRecommendation() {
- return (
- this.isRecommendation &&
- (this.superType === 'suggestion-add-dictionary' || this.superType === 'add-dictionary')
- );
+ return this.isRecommendation && (this.superType === 'suggestion-add-dictionary' || this.superType === 'add-dictionary');
}
get isRecommendation() {
@@ -234,21 +213,13 @@ export class AnnotationWrapper {
return annotationWrapper;
}
- private static _handleRecommendations(
- annotationWrapper: AnnotationWrapper,
- redactionLogEntry: RedactionLogEntryWrapper
- ) {
+ private static _handleRecommendations(annotationWrapper: AnnotationWrapper, redactionLogEntry: RedactionLogEntryWrapper) {
if (annotationWrapper.superType === 'recommendation') {
- annotationWrapper.recommendationType = redactionLogEntry.type.substr(
- 'recommendation_'.length
- );
+ annotationWrapper.recommendationType = redactionLogEntry.type.substr('recommendation_'.length);
}
}
- private static _setSuperType(
- annotationWrapper: AnnotationWrapper,
- redactionLogEntryWrapper: RedactionLogEntryWrapper
- ) {
+ private static _setSuperType(annotationWrapper: AnnotationWrapper, redactionLogEntryWrapper: RedactionLogEntryWrapper) {
if (redactionLogEntryWrapper.recommendation) {
if (redactionLogEntryWrapper.redacted) {
annotationWrapper.superType = 'recommendation';
@@ -288,9 +259,14 @@ export class AnnotationWrapper {
if (annotationWrapper.dictionary?.toLowerCase() === 'false_positive') {
if (redactionLogEntryWrapper.status === 'REQUESTED') {
annotationWrapper.superType = 'suggestion-add-dictionary';
+ return;
}
if (redactionLogEntryWrapper.status === 'APPROVED') {
annotationWrapper.superType = 'add-dictionary';
+ return;
+ }
+ if (!redactionLogEntryWrapper.manual) {
+ annotationWrapper.superType = 'skipped';
}
return;
}
@@ -299,16 +275,20 @@ export class AnnotationWrapper {
if (redactionLogEntryWrapper.dictionaryEntry) {
if (redactionLogEntryWrapper.status === 'REQUESTED') {
annotationWrapper.superType = 'suggestion-add-dictionary';
+ return;
}
if (redactionLogEntryWrapper.status === 'APPROVED') {
annotationWrapper.superType = 'add-dictionary';
+ return;
}
} else {
if (redactionLogEntryWrapper.status === 'REQUESTED') {
annotationWrapper.superType = 'suggestion-add';
+ return;
}
if (redactionLogEntryWrapper.status === 'APPROVED') {
annotationWrapper.superType = 'manual-redaction';
+ return;
}
}
}
@@ -322,40 +302,29 @@ export class AnnotationWrapper {
: 'suggestion-remove-dictionary';
} else {
annotationWrapper.superType =
- redactionLogEntryWrapper.manualRedactionType === 'ADD'
- ? 'suggestion-add'
- : 'suggestion-remove';
+ redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'suggestion-add' : 'suggestion-remove';
}
+ return;
}
if (redactionLogEntryWrapper.status === 'APPROVED') {
if (redactionLogEntryWrapper.dictionaryEntry) {
annotationWrapper.superType =
- redactionLogEntryWrapper.manualRedactionType === 'ADD'
- ? 'add-dictionary'
- : 'remove-dictionary';
+ redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'add-dictionary' : 'remove-dictionary';
} else {
annotationWrapper.superType =
- redactionLogEntryWrapper.manualRedactionType === 'ADD'
- ? 'manual-redaction'
- : 'remove-only-here';
+ redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'manual-redaction' : 'remove-only-here';
}
+ return;
}
}
if (!annotationWrapper.superType) {
- annotationWrapper.superType = annotationWrapper.redaction
- ? 'redaction'
- : annotationWrapper.hint
- ? 'hint'
- : 'skipped';
+ annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'skipped';
}
}
- private static _createContent(
- annotationWrapper: AnnotationWrapper,
- entry: RedactionLogEntryWrapper
- ) {
+ private static _createContent(annotationWrapper: AnnotationWrapper, entry: RedactionLogEntryWrapper) {
let content = '';
if (entry.matchedRule) {
content += 'Rule ' + entry.matchedRule + ' matched \n\n';
diff --git a/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.html b/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.html
index 46c3227c9..87ec5e4cf 100644
--- a/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.html
+++ b/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.html
@@ -1,115 +1,131 @@
-
+
-
+
+
+
+
+
+
+
+
diff --git a/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.scss b/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.scss
index c7dfd10cf..a9168e3ac 100644
--- a/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.scss
+++ b/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.scss
@@ -14,4 +14,8 @@
> *:not(:last-child) {
margin-right: 2px;
}
+
+ &.always-visible {
+ display: flex;
+ }
}
diff --git a/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.ts b/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.ts
index 63e9b72ba..790c99fbe 100644
--- a/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/components/annotation-actions/annotation-actions.component.ts
@@ -4,7 +4,7 @@ import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
import { AnnotationPermissions } from '@models/file/annotation.permissions';
import { AnnotationActionsService } from '../../services/annotation-actions.service';
-import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
+import { WebViewerInstance } from '@pdftron/webviewer';
@Component({
selector: 'redaction-annotation-actions',
@@ -12,9 +12,13 @@ import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
styleUrls: ['./annotation-actions.component.scss']
})
export class AnnotationActionsComponent implements OnInit {
- @Input() annotation: AnnotationWrapper;
+ @Input() btnType: 'dark-bg' | 'primary' = 'dark-bg';
+ @Input() tooltipPosition: 'before' | 'above' = 'before';
+
+ @Input() _annotations: AnnotationWrapper[];
@Input() canPerformAnnotationActions: boolean;
@Input() viewer: WebViewerInstance;
+ @Input() alwaysVisible: boolean;
@Output() annotationsChanged = new EventEmitter
();
@@ -26,27 +30,62 @@ export class AnnotationActionsComponent implements OnInit {
private _permissionsService: PermissionsService
) {}
- get viewerAnnotation(): Annotations.Annotation {
- return this.viewer.annotManager.getAnnotationById(this.annotation.id);
+ get annotations(): AnnotationWrapper[] {
+ return this._annotations;
+ }
+
+ @Input()
+ set annotations(value: AnnotationWrapper[]) {
+ this._annotations = value.filter(a => a !== undefined);
+ this._setPermissions();
+ }
+
+ get viewerAnnotations() {
+ if (this.viewer?.annotManager) {
+ return this._annotations.map(a => this.viewer?.annotManager?.getAnnotationById(a.id));
+ } else {
+ return [];
+ }
+ }
+
+ get isVisible() {
+ return this.viewerAnnotations?.reduce((accumulator, annotation) => annotation?.isVisible() && accumulator, true);
+ }
+
+ get isImage() {
+ return this.annotations?.reduce((accumulator, annotation) => annotation.isImage && accumulator, true);
}
ngOnInit(): void {
- this.annotationPermissions = AnnotationPermissions.forUser(
- this._permissionsService.isApprover(),
- this._permissionsService.currentUser,
- this.annotation
- );
+ this._setPermissions();
+ }
+
+ suggestRemoveAnnotations($event, removeFromDict: boolean) {
+ $event.stopPropagation();
+ this.annotationActionsService.suggestRemoveAnnotation($event, this.annotations, removeFromDict, this.annotationsChanged);
+ }
+
+ markAsFalsePositive($event) {
+ this.annotationActionsService.markAsFalsePositive($event, this.annotations, this.annotationsChanged);
}
hideAnnotation($event: MouseEvent) {
$event.stopPropagation();
- this.viewer.annotManager.hideAnnotations([this.viewerAnnotation]);
+ this.viewer.annotManager.hideAnnotations(this.viewerAnnotations);
this.viewer.annotManager.deselectAllAnnotations();
}
showAnnotation($event: MouseEvent) {
$event.stopPropagation();
- this.viewer.annotManager.showAnnotations([this.viewerAnnotation]);
+ this.viewer.annotManager.showAnnotations(this.viewerAnnotations);
this.viewer.annotManager.deselectAllAnnotations();
}
+
+ private _setPermissions() {
+ this.annotationPermissions = AnnotationPermissions.forUser(
+ this._permissionsService.isApprover(),
+ this._permissionsService.currentUser,
+ this.annotations
+ );
+ }
}
diff --git a/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.html b/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.html
deleted file mode 100644
index 89cf90056..000000000
--- a/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.scss b/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.scss
deleted file mode 100644
index 6a6a6408d..000000000
--- a/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-:host {
- display: flex;
-
- > *:not(:last-child) {
- margin-right: 2px;
- }
-}
diff --git a/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.ts b/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.ts
deleted file mode 100644
index fdf89b446..000000000
--- a/apps/red-ui/src/app/modules/dossier/components/annotation-remove-actions/annotation-remove-actions.component.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
-import { AppStateService } from '@state/app-state.service';
-import { AnnotationWrapper } from '@models/file/annotation.wrapper';
-import { AnnotationActionsService } from '../../services/annotation-actions.service';
-import { AnnotationPermissions } from '@models/file/annotation.permissions';
-import { PermissionsService } from '@services/permissions.service';
-import { MatMenuTrigger } from '@angular/material/menu';
-
-@Component({
- selector: 'redaction-annotation-remove-actions',
- templateUrl: './annotation-remove-actions.component.html',
- styleUrls: ['./annotation-remove-actions.component.scss']
-})
-export class AnnotationRemoveActionsComponent {
- @Output() menuOpenChange = new EventEmitter();
- @Input() annotationsChanged: EventEmitter;
- @Input() menuOpen: boolean;
- @Input() btnType: 'dark-bg' | 'primary' = 'dark-bg';
- @Input() tooltipPosition: 'before' | 'above' = 'before';
-
- @ViewChild(MatMenuTrigger) matMenuTrigger: MatMenuTrigger;
- permissions: {
- canRemoveOrSuggestToRemoveOnlyHere: boolean;
- canRemoveOrSuggestToRemoveFromDictionary: boolean;
- canMarkAsFalsePositive: boolean;
- };
-
- constructor(
- readonly appStateService: AppStateService,
- private readonly _annotationActionsService: AnnotationActionsService,
- private readonly _permissionsService: PermissionsService
- ) {}
-
- private _annotations: AnnotationWrapper[];
-
- get annotations(): AnnotationWrapper[] {
- return this._annotations;
- }
-
- @Input()
- set annotations(value: AnnotationWrapper[]) {
- this._annotations = value.filter(a => a !== undefined);
- this._setPermissions();
- }
-
- suggestRemoveAnnotations($event, removeFromDict: boolean) {
- $event.stopPropagation();
- this._annotationActionsService.suggestRemoveAnnotation(
- $event,
- this.annotations,
- removeFromDict,
- this.annotationsChanged
- );
- }
-
- markAsFalsePositive($event) {
- this._annotationActionsService.markAsFalsePositive(
- $event,
- this.annotations,
- this.annotationsChanged
- );
- }
-
- private _setPermissions() {
- this.permissions = {
- canRemoveOrSuggestToRemoveOnlyHere: this._annotationsPermissions([
- 'canRemoveOrSuggestToRemoveOnlyHere'
- ]),
- canRemoveOrSuggestToRemoveFromDictionary: this._annotationsPermissions([
- 'canRemoveOrSuggestToRemoveFromDictionary'
- ]),
- canMarkAsFalsePositive: this._annotationsPermissions([
- 'canMarkAsFalsePositive',
- 'canMarkTextOnlyAsFalsePositive'
- ])
- };
- }
-
- private _annotationsPermissions(keys: string[]): boolean {
- return this.annotations.reduce((prevValue, annotation) => {
- const annotationPermissions = AnnotationPermissions.forUser(
- this._permissionsService.isApprover(),
- this._permissionsService.currentUser,
- annotation
- );
- const hasAtLeastOnePermission = keys.reduce(
- (acc, key) => acc || annotationPermissions[key],
- false
- );
- return prevValue && hasAtLeastOnePermission;
- }, true);
- }
-}
diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html
index c44947014..29cd7505d 100644
--- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html
+++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html
@@ -1,8 +1,4 @@
-
+
-
+
{{ selectedAnnotations?.length || 0 }} selected
- 0"
- [annotationsChanged]="annotationsChanged"
+ (annotationsChanged)="annotationsChanged.emit($event)"
+ [canPerformAnnotationActions]="!isReadOnly"
[annotations]="selectedAnnotations"
+ [viewer]="viewer"
+ [alwaysVisible]="true"
btnType="primary"
tooltipPosition="above"
- >
+ >
-
+
{{ activeViewerPage }} -
{{ activeAnnotationsLength || 0 }}
-
+
@@ -142,25 +129,11 @@
redactionHasScrollbar
tabindex="1"
>
-
-
-
+
+
+
{{ 'file-preview.tabs.annotations.page-is' | translate }}
-
+
.
@@ -175,9 +148,7 @@
>
= displayedPages[displayedPages.length - 1]
- "
+ [disabled]="activeViewerPage >= displayedPages[displayedPages.length - 1]"
class="mt-8"
icon="red:nav-next"
text="file-preview.tabs.annotations.jump-to-next"
@@ -188,9 +159,7 @@
-
-
-
+
+
+
{{ annotation.typeLabel | translate }}
@@ -222,8 +182,7 @@
>{{ annotation.dictionary | humanize: false }}
- : {{ annotation.shortContent }}
+ : {{ annotation.shortContent }}
@@ -269,14 +228,9 @@
-
+
-
+
{{ filter.key | humanize: false }}
diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts
index 1603de47d..a90d7dac6 100644
--- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts
@@ -21,6 +21,7 @@ import { FilterModel } from '@shared/components/filters/popup-filter/model/filte
import { CommentsComponent } from '../comments/comments.component';
import { PermissionsService } from '../../../../services/permissions.service';
import { TranslateService } from '@ngx-translate/core';
+import { WebViewerInstance } from '@pdftron/webviewer';
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
@@ -42,10 +43,9 @@ export class FileWorkloadComponent {
@Input() hideSkipped: boolean;
@Input() excludePages: boolean;
@Input() annotationActionsTemplate: TemplateRef;
+ @Input() viewer: WebViewerInstance;
@Output() shouldDeselectAnnotationsOnPageChangeChange = new EventEmitter();
- @Output() selectAnnotations = new EventEmitter<
- AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }
- >();
+ @Output() selectAnnotations = new EventEmitter();
@Output() deselectAnnotations = new EventEmitter();
@Output() selectPage = new EventEmitter();
@Output() toggleSkipped = new EventEmitter();
@@ -103,10 +103,7 @@ export class FileWorkloadComponent {
return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null;
}
- private static _scrollToFirstElement(
- elements: HTMLElement[],
- mode: 'always' | 'if-needed' = 'if-needed'
- ) {
+ private static _scrollToFirstElement(elements: HTMLElement[], mode: 'always' | 'if-needed' = 'if-needed') {
if (elements.length > 0) {
scrollIntoView(elements[0], {
behavior: 'smooth',
@@ -128,9 +125,7 @@ export class FileWorkloadComponent {
toggleExpandComments(annotation: AnnotationWrapper, $event: MouseEvent) {
$event.stopPropagation();
- this.annotationCommentsComponents
- .find(c => c.annotation === annotation)
- .toggleExpandComments();
+ this.annotationCommentsComponents.find(c => c.annotation === annotation).toggleExpandComments();
}
logAnnotation(annotation: AnnotationWrapper) {
@@ -138,9 +133,7 @@ export class FileWorkloadComponent {
}
pageHasSelection(page: number) {
- return (
- this.multiSelectActive && !!this.selectedAnnotations?.find(a => a.pageNumber === page)
- );
+ return this.multiSelectActive && !!this.selectedAnnotations?.find(a => a.pageNumber === page);
}
selectAllOnActivePage() {
@@ -227,20 +220,14 @@ export class FileWorkloadComponent {
scrollAnnotationsToPage(page: number, mode: 'always' | 'if-needed' = 'if-needed') {
if (this._annotationsElement) {
- const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(
- `div[anotation-page-header="${page}"]`
- );
+ const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[anotation-page-header="${page}"]`);
FileWorkloadComponent._scrollToFirstElement(elements, mode);
}
}
@debounce()
scrollToSelectedAnnotation() {
- if (
- !this.selectedAnnotations ||
- this.selectedAnnotations.length === 0 ||
- !this._annotationsElement
- ) {
+ if (!this.selectedAnnotations || this.selectedAnnotations.length === 0 || !this._annotationsElement) {
return;
}
const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(
@@ -251,10 +238,7 @@ export class FileWorkloadComponent {
scrollQuickNavigation() {
let quickNavPageIndex = this.displayedPages.findIndex(p => p >= this.activeViewerPage);
- if (
- quickNavPageIndex === -1 ||
- this.displayedPages[quickNavPageIndex] !== this.activeViewerPage
- ) {
+ if (quickNavPageIndex === -1 || this.displayedPages[quickNavPageIndex] !== this.activeViewerPage) {
quickNavPageIndex = Math.max(0, quickNavPageIndex - 1);
}
this._scrollQuickNavigationToPage(this.displayedPages[quickNavPageIndex]);
@@ -274,10 +258,7 @@ export class FileWorkloadComponent {
}
preventKeyDefault($event: KeyboardEvent) {
- if (
- COMMAND_KEY_ARRAY.includes($event.key) &&
- !(($event.target as any).localName === 'input')
- ) {
+ if (COMMAND_KEY_ARRAY.includes($event.key) && !(($event.target as any).localName === 'input')) {
$event.preventDefault();
}
}
@@ -296,26 +277,18 @@ export class FileWorkloadComponent {
private _selectFirstAnnotationOnCurrentPageIfNecessary() {
if (
- (!this._firstSelectedAnnotation ||
- this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) &&
+ (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) &&
this.displayedPages.indexOf(this.activeViewerPage) >= 0
) {
- this.selectAnnotations.emit([
- this.displayedAnnotations[this.activeViewerPage].annotations[0]
- ]);
+ this.selectAnnotations.emit([this.displayedAnnotations[this.activeViewerPage].annotations[0]]);
}
}
private _navigateAnnotations($event: KeyboardEvent) {
- if (
- !this._firstSelectedAnnotation ||
- this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber
- ) {
+ if (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) {
if (this.displayedPages.indexOf(this.activeViewerPage) !== -1) {
// Displayed page has annotations
- return this.selectAnnotations.emit([
- this.displayedAnnotations[this.activeViewerPage].annotations[0]
- ]);
+ return this.selectAnnotations.emit([this.displayedAnnotations[this.activeViewerPage].annotations[0]]);
}
// Displayed page doesn't have annotations
if ($event.key === 'ArrowDown') {
@@ -345,8 +318,7 @@ export class FileWorkloadComponent {
this.selectAnnotations.emit([annotationsOnPage[idx + 1]]);
} else if (pageIdx + 1 < this.displayedPages.length) {
// If not last page
- const nextPageAnnotations =
- this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations;
+ const nextPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations;
this.shouldDeselectAnnotationsOnPageChange = false;
this.shouldDeselectAnnotationsOnPageChangeChange.emit(false);
this.selectAnnotations.emit([nextPageAnnotations[0]]);
@@ -356,8 +328,7 @@ export class FileWorkloadComponent {
this.selectAnnotations.emit([annotationsOnPage[idx - 1]]);
} else if (pageIdx) {
// If not first page
- const prevPageAnnotations =
- this.displayedAnnotations[this.displayedPages[pageIdx - 1]].annotations;
+ const prevPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx - 1]].annotations;
this.shouldDeselectAnnotationsOnPageChange = false;
this.shouldDeselectAnnotationsOnPageChangeChange.emit(false);
this.selectAnnotations.emit([prevPageAnnotations[prevPageAnnotations.length - 1]]);
@@ -421,9 +392,7 @@ export class FileWorkloadComponent {
private _scrollQuickNavigationToPage(page: number) {
if (this._quickNavigationElement) {
- const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(
- `#quick-nav-page-${page}`
- );
+ const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${page}`);
FileWorkloadComponent._scrollToFirstElement(elements);
}
}
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 5a62738d6..2c6d72c7e 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
@@ -30,11 +30,13 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
private readonly _permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
public dialogRef: MatDialogRef,
- @Inject(MAT_DIALOG_DATA) public annotation: AnnotationWrapper
+ @Inject(MAT_DIALOG_DATA) public annotations: AnnotationWrapper[]
) {}
get changed(): boolean {
- return this.legalBasisForm.get('reason').value.legalBasis !== this.annotation.legalBasis;
+ return (
+ this.legalBasisForm.get('reason').value.legalBasis !== this.annotations[0].legalBasis
+ );
}
async ngOnInit() {
@@ -58,7 +60,7 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
this.legalBasisForm.patchValue({
reason: this.legalOptions.find(
- option => option.legalBasis === this.annotation.legalBasis
+ option => option.legalBasis === this.annotations[0].legalBasis
)
});
}
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/recategorize-image-dialog/recategorize-image-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/recategorize-image-dialog/recategorize-image-dialog.component.ts
index e803cd26a..6a58fdb94 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/recategorize-image-dialog/recategorize-image-dialog.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/recategorize-image-dialog/recategorize-image-dialog.component.ts
@@ -18,18 +18,18 @@ export class RecategorizeImageDialogComponent implements OnInit {
private readonly _permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
public dialogRef: MatDialogRef,
- @Inject(MAT_DIALOG_DATA) public annotation: AnnotationWrapper
+ @Inject(MAT_DIALOG_DATA) public annotations: AnnotationWrapper[]
) {}
get changed(): boolean {
- return this.recategorizeImageForm.get('type').value !== this.annotation.dictionary;
+ return this.recategorizeImageForm.get('type').value !== this.annotations[0].dictionary;
}
async ngOnInit() {
this.isDocumentAdmin = this._permissionsService.isApprover();
this.recategorizeImageForm = this._formBuilder.group({
- type: [this.annotation.dictionary, Validators.required],
+ type: [this.annotations[0].dictionary, Validators.required],
comment: this.isDocumentAdmin ? [null] : [null, Validators.required]
});
}
diff --git a/apps/red-ui/src/app/modules/dossier/dossiers.module.ts b/apps/red-ui/src/app/modules/dossier/dossiers.module.ts
index 1d5031442..a1a7c7482 100644
--- a/apps/red-ui/src/app/modules/dossier/dossiers.module.ts
+++ b/apps/red-ui/src/app/modules/dossier/dossiers.module.ts
@@ -34,7 +34,6 @@ import { PdfViewerDataService } from './services/pdf-viewer-data.service';
import { ManualAnnotationService } from './services/manual-annotation.service';
import { AnnotationDrawService } from './services/annotation-draw.service';
import { AnnotationProcessingService } from './services/annotation-processing.service';
-import { AnnotationRemoveActionsComponent } from './components/annotation-remove-actions/annotation-remove-actions.component';
import { DossierDictionaryDialogComponent } from './dialogs/dossier-dictionary-dialog/dossier-dictionary-dialog.component';
import { EditDossierDialogComponent } from './dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
import { EditDossierGeneralInfoComponent } from './dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component';
@@ -84,7 +83,6 @@ const components = [
DossierListingActionsComponent,
DocumentInfoComponent,
FileWorkloadComponent,
- AnnotationRemoveActionsComponent,
EditDossierGeneralInfoComponent,
EditDossierDownloadPackageComponent,
EditDossierDictionaryComponent,
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 5f574af01..f00f3a050 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
@@ -32,8 +32,7 @@
-
-
+
{{ status | translate }}
@@ -84,10 +83,7 @@
-
+
@@ -153,12 +149,7 @@
-
-
+
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 ebaf549c2..477033369 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
@@ -76,22 +76,24 @@ export class AnnotationActionsService {
changeLegalBasis(
$event: MouseEvent,
- annotation: AnnotationWrapper,
+ annotations: AnnotationWrapper[],
annotationsChanged: EventEmitter
) {
this._dialogService.openChangeLegalBasisDialog(
$event,
- annotation,
+ annotations,
(data: { comment: string; legalBasis: string }) => {
- this._processObsAndEmit(
- this._manualAnnotationService.changeLegalBasis(
- annotation.annotationId,
- data.legalBasis,
- data.comment
- ),
- annotation,
- annotationsChanged
- );
+ annotations.forEach(annotation => {
+ this._processObsAndEmit(
+ this._manualAnnotationService.changeLegalBasis(
+ annotation.annotationId,
+ data.legalBasis,
+ data.comment
+ ),
+ annotation,
+ annotationsChanged
+ );
+ });
}
);
}
@@ -142,22 +144,24 @@ export class AnnotationActionsService {
recategorizeImage(
$event: MouseEvent,
- annotation: AnnotationWrapper,
+ annotations: AnnotationWrapper[],
annotationsChanged: EventEmitter
) {
this._dialogService.openRecategorizeImageDialog(
$event,
- annotation,
+ annotations,
(data: { type: string; comment: string }) => {
- this._processObsAndEmit(
- this._manualAnnotationService.recategorizeImage(
- annotation.annotationId,
- data.type,
- data.comment
- ),
- annotation,
- annotationsChanged
- );
+ annotations.forEach(annotation => {
+ this._processObsAndEmit(
+ this._manualAnnotationService.recategorizeImage(
+ annotation.annotationId,
+ data.type,
+ data.comment
+ ),
+ annotation,
+ annotationsChanged
+ );
+ });
}
);
}
@@ -218,7 +222,7 @@ export class AnnotationActionsService {
title: this._translateService.instant('annotation-actions.recategorize-image'),
onClick: () => {
this._ngZone.run(() => {
- this.recategorizeImage(null, annotations[0], annotationsChanged);
+ this.recategorizeImage(null, annotations, annotationsChanged);
});
}
});
diff --git a/apps/red-ui/src/app/modules/dossier/services/dossiers-dialog.service.ts b/apps/red-ui/src/app/modules/dossier/services/dossiers-dialog.service.ts
index f1aa10c3a..01e4ce2d8 100644
--- a/apps/red-ui/src/app/modules/dossier/services/dossiers-dialog.service.ts
+++ b/apps/red-ui/src/app/modules/dossier/services/dossiers-dialog.service.ts
@@ -150,13 +150,13 @@ export class DossiersDialogService extends DialogService {
openChangeLegalBasisDialog(
$event: MouseEvent,
- annotation: AnnotationWrapper,
+ annotations: AnnotationWrapper[],
cb?: Function
): MatDialogRef {
$event?.stopPropagation();
const ref = this._dialog.open(ChangeLegalBasisDialogComponent, {
...dialogConfig,
- data: annotation
+ data: annotations
});
ref.afterClosed().subscribe(async result => {
if (result && cb) {
@@ -168,13 +168,13 @@ export class DossiersDialogService extends DialogService {
openRecategorizeImageDialog(
$event: MouseEvent,
- annotation: AnnotationWrapper,
+ annotations: AnnotationWrapper[],
cb?: Function
): MatDialogRef {
$event?.stopPropagation();
const ref = this._dialog.open(RecategorizeImageDialogComponent, {
...dialogConfig,
- data: annotation
+ data: annotations
});
ref.afterClosed().subscribe(async result => {
if (result && cb) {
diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json
index 4b001a0b1..6cfc820ed 100644
--- a/apps/red-ui/src/assets/config/config.json
+++ b/apps/red-ui/src/assets/config/config.json
@@ -1,6 +1,6 @@
{
- "OAUTH_URL": "https://red-staging.iqser.cloud/auth/realms/redaction",
- "API_URL": "https://red-staging.iqser.cloud/redaction-gateway-v1",
+ "OAUTH_URL": "https://dev-06.iqser.cloud/auth/realms/redaction",
+ "API_URL": "https://dev-06.iqser.cloud/redaction-gateway-v1",
"OAUTH_CLIENT_ID": "redaction",
"BACKEND_APP_VERSION": "4.4.40",
"FRONTEND_APP_VERSION": "1.1",