Pull request #224: Exclude pages from redaction
Merge in RED/ui from RED-1618 to master * commit '751ccb5ef4c844f61bcb777af5f5783b297da9bc': Exclude pages icon Exclude pages from redaction Fixed comments params order
This commit is contained in:
commit
2767809cd2
@ -196,4 +196,8 @@ export class FileStatusWrapper {
|
|||||||
get cacheIdentifier() {
|
get cacheIdentifier() {
|
||||||
return btoa(this.fileStatus.lastUploaded + this.fileStatus.lastOCRTime);
|
return btoa(this.fileStatus.lastUploaded + this.fileStatus.lastOCRTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get excludedPages(): number[] {
|
||||||
|
return this.fileStatus.excludedPages;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,8 @@
|
|||||||
*ngIf="permissionsService.canAddComment()"
|
*ngIf="permissionsService.canAddComment()"
|
||||||
[form]="commentForm"
|
[form]="commentForm"
|
||||||
[placeholder]="translateService.instant('comments.add-comment')"
|
[placeholder]="translateService.instant('comments.add-comment')"
|
||||||
type="submit"
|
icon="red:collapse"
|
||||||
|
type="action"
|
||||||
width="full"
|
width="full"
|
||||||
></redaction-input-with-action>
|
></redaction-input-with-action>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectorRef, Component, HostBinding, Input } from '@angular/core';
|
import { ChangeDetectorRef, Component, HostBinding, Input } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
import { Comment } from '@redaction/red-ui-http';
|
import { Comment } from '@redaction/red-ui-http';
|
||||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
@ -28,7 +28,7 @@ export class CommentsComponent {
|
|||||||
private readonly _manualAnnotationService: ManualAnnotationService
|
private readonly _manualAnnotationService: ManualAnnotationService
|
||||||
) {
|
) {
|
||||||
this.commentForm = this._formBuilder.group({
|
this.commentForm = this._formBuilder.group({
|
||||||
value: ['', Validators.required]
|
value: ['']
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -58,6 +58,15 @@
|
|||||||
tooltipPosition="below"
|
tooltipPosition="below"
|
||||||
></redaction-circle-button>
|
></redaction-circle-button>
|
||||||
|
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="toggleExcludePages()"
|
||||||
|
*ngIf="screen === 'file-preview'"
|
||||||
|
[attr.aria-expanded]="activeExcludePages"
|
||||||
|
icon="red:exclude-pages"
|
||||||
|
tooltip="file-preview.exclude-pages"
|
||||||
|
tooltipPosition="below"
|
||||||
|
></redaction-circle-button>
|
||||||
|
|
||||||
<!-- Ready for approval-->
|
<!-- Ready for approval-->
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="setFileUnderApproval($event)"
|
(action)="setFileUnderApproval($event)"
|
||||||
@ -136,8 +145,8 @@
|
|||||||
<!-- exclude from redaction -->
|
<!-- exclude from redaction -->
|
||||||
<div class="red-input-group">
|
<div class="red-input-group">
|
||||||
<mat-slide-toggle
|
<mat-slide-toggle
|
||||||
(click)="$event.stopPropagation()"
|
|
||||||
(change)="toggleAnalysis()"
|
(change)="toggleAnalysis()"
|
||||||
|
(click)="$event.stopPropagation()"
|
||||||
[checked]="!fileStatus?.isExcluded"
|
[checked]="!fileStatus?.isExcluded"
|
||||||
[class.mr-24]="screen === 'dossier-overview'"
|
[class.mr-24]="screen === 'dossier-overview'"
|
||||||
[disabled]="!permissionsService.canToggleAnalysis(fileStatus)"
|
[disabled]="!permissionsService.canToggleAnalysis(fileStatus)"
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
|||||||
export class FileActionsComponent implements OnInit {
|
export class FileActionsComponent implements OnInit {
|
||||||
@Input() fileStatus: FileStatusWrapper;
|
@Input() fileStatus: FileStatusWrapper;
|
||||||
@Input() activeDocumentInfo: boolean;
|
@Input() activeDocumentInfo: boolean;
|
||||||
|
@Input() activeExcludePages: boolean;
|
||||||
@Output() actionPerformed = new EventEmitter<string>();
|
@Output() actionPerformed = new EventEmitter<string>();
|
||||||
actionMenuOpen: boolean;
|
actionMenuOpen: boolean;
|
||||||
|
|
||||||
@ -104,6 +105,10 @@ export class FileActionsComponent implements OnInit {
|
|||||||
this.actionPerformed.emit('view-document-info');
|
this.actionPerformed.emit('view-document-info');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleExcludePages() {
|
||||||
|
this.actionPerformed.emit('view-exclude-pages');
|
||||||
|
}
|
||||||
|
|
||||||
openDeleteFileDialog($event: MouseEvent) {
|
openDeleteFileDialog($event: MouseEvent) {
|
||||||
this._dialogService.openDeleteFilesDialog(
|
this._dialogService.openDeleteFilesDialog(
|
||||||
$event,
|
$event,
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
<div class="right-title heading" translate="file-preview.tabs.annotations.label">
|
<div
|
||||||
|
*ngIf="!excludePages"
|
||||||
|
class="right-title heading"
|
||||||
|
translate="file-preview.tabs.annotations.label"
|
||||||
|
>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
(click)="multiSelectActive = true"
|
(click)="multiSelectActive = true"
|
||||||
@ -16,14 +20,28 @@
|
|||||||
></redaction-popup-filter>
|
></redaction-popup-filter>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
*ngIf="excludePages"
|
||||||
|
class="right-title heading"
|
||||||
|
translate="file-preview.tabs.exclude-pages.label"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="closeExcludePagesView.emit()"
|
||||||
|
icon="red:close"
|
||||||
|
tooltip="file-preview.tabs.exclude-pages.close"
|
||||||
|
tooltipPosition="before"
|
||||||
|
></redaction-circle-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="right-content">
|
<div class="right-content">
|
||||||
<div class="read-only d-flex" *ngIf="isReadOnly" [class.justify-center]="!isProcessing">
|
<div *ngIf="isReadOnly" [class.justify-center]="!isProcessing" class="read-only d-flex">
|
||||||
<div class="flex-align-items-center" *ngIf="isProcessing">
|
<div *ngIf="isProcessing" class="flex-align-items-center">
|
||||||
<span class="read-only-text" [translate]="fileData.fileStatus.status"></span>
|
<span [translate]="fileData.fileStatus.status" class="read-only-text"></span>
|
||||||
<mat-progress-bar class="w-100" [mode]="'indeterminate'"></mat-progress-bar>
|
<mat-progress-bar [mode]="'indeterminate'" class="w-100"></mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-center">
|
<div class="flex-center">
|
||||||
<mat-icon svgIcon="red:read-only" class="red-white"></mat-icon>
|
<mat-icon class="red-white" svgIcon="red:read-only"></mat-icon>
|
||||||
<span class="read-only-text" translate="readonly"></span>
|
<span class="read-only-text" translate="readonly"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -89,133 +107,150 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="overflow: hidden; width: 100%">
|
<div style="overflow: hidden; width: 100%">
|
||||||
<div attr.anotation-page-header="{{ activeViewerPage }}" class="page-separator">
|
<ng-container *ngIf="!excludePages">
|
||||||
<span *ngIf="!!activeViewerPage" class="all-caps-label">
|
<div attr.anotation-page-header="{{ activeViewerPage }}" class="page-separator">
|
||||||
<span translate="page"></span> {{ activeViewerPage }} -
|
<span *ngIf="!!activeViewerPage" class="all-caps-label">
|
||||||
{{ activeAnnotationsLength || 0 }}
|
<span translate="page"></span> {{ activeViewerPage }} -
|
||||||
<span
|
{{ activeAnnotationsLength || 0 }}
|
||||||
[translate]="activeAnnotationsLength === 1 ? 'annotation' : 'annotations'"
|
<span
|
||||||
></span>
|
[translate]="
|
||||||
</span>
|
activeAnnotationsLength === 1 ? 'annotation' : 'annotations'
|
||||||
|
"
|
||||||
|
></span>
|
||||||
|
</span>
|
||||||
|
|
||||||
<div *ngIf="multiSelectActive">
|
<div *ngIf="multiSelectActive">
|
||||||
<div (click)="selectAllOnActivePage()" class="all-caps-label primary pointer">
|
<div
|
||||||
All
|
(click)="selectAllOnActivePage()"
|
||||||
</div>
|
class="all-caps-label primary pointer"
|
||||||
<div (click)="deselectAllOnActivePage()" class="all-caps-label primary pointer">
|
translate="file-preview.tabs.annotations.select-all"
|
||||||
None
|
></div>
|
||||||
|
<div
|
||||||
|
(click)="deselectAllOnActivePage()"
|
||||||
|
class="all-caps-label primary pointer"
|
||||||
|
translate="file-preview.tabs.annotations.select-none"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
#annotationsElement
|
|
||||||
(keydown)="preventKeyDefault($event)"
|
|
||||||
(keyup)="preventKeyDefault($event)"
|
|
||||||
[class.active-panel]="!pagesPanelActive"
|
|
||||||
class="annotations"
|
|
||||||
redactionHasScrollbar
|
|
||||||
tabindex="1"
|
|
||||||
>
|
|
||||||
<ng-container *ngIf="!displayedAnnotations[activeViewerPage]">
|
|
||||||
<redaction-empty-state
|
|
||||||
[horizontalPadding]="24"
|
|
||||||
[verticalPadding]="40"
|
|
||||||
icon="red:document"
|
|
||||||
screen="file-preview"
|
|
||||||
></redaction-empty-state>
|
|
||||||
<div class="no-annotations-buttons-container mt-32">
|
|
||||||
<redaction-icon-button
|
|
||||||
(action)="jumpToPreviousWithAnnotations()"
|
|
||||||
[disabled]="activeViewerPage <= displayedPages[0]"
|
|
||||||
icon="red:nav-prev"
|
|
||||||
text="file-preview.tabs.annotations.jump-to-previous"
|
|
||||||
type="show-bg"
|
|
||||||
></redaction-icon-button>
|
|
||||||
<redaction-icon-button
|
|
||||||
(action)="jumpToNextWithAnnotations()"
|
|
||||||
[disabled]="
|
|
||||||
activeViewerPage >= displayedPages[displayedPages.length - 1]
|
|
||||||
"
|
|
||||||
class="mt-8"
|
|
||||||
icon="red:nav-next"
|
|
||||||
text="file-preview.tabs.annotations.jump-to-next"
|
|
||||||
type="show-bg"
|
|
||||||
></redaction-icon-button>
|
|
||||||
</div>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
(click)="annotationClicked(annotation, $event)"
|
#annotationsElement
|
||||||
*ngFor="let annotation of displayedAnnotations[activeViewerPage]?.annotations"
|
(keydown)="preventKeyDefault($event)"
|
||||||
[class.active]="annotationIsSelected(annotation)"
|
(keyup)="preventKeyDefault($event)"
|
||||||
[class.multi-select-active]="multiSelectActive"
|
[class.active-panel]="!pagesPanelActive"
|
||||||
attr.annotation-id="{{ annotation.id }}"
|
class="annotations"
|
||||||
attr.annotation-page="{{ activeViewerPage }}"
|
redactionHasScrollbar
|
||||||
class="annotation-wrapper"
|
tabindex="1"
|
||||||
>
|
>
|
||||||
<div class="active-bar-marker"></div>
|
<ng-container *ngIf="!displayedAnnotations[activeViewerPage]">
|
||||||
<div [class.removed]="annotation.isChangeLogRemoved" class="annotation">
|
<redaction-empty-state
|
||||||
<redaction-hidden-action
|
[horizontalPadding]="24"
|
||||||
(action)="logAnnotation(annotation)"
|
[verticalPadding]="40"
|
||||||
[requiredClicks]="2"
|
icon="red:document"
|
||||||
>
|
screen="file-preview"
|
||||||
<div
|
></redaction-empty-state>
|
||||||
[matTooltip]="annotation.content"
|
<div class="no-annotations-buttons-container mt-32">
|
||||||
class="details"
|
<redaction-icon-button
|
||||||
matTooltipPosition="above"
|
(action)="jumpToPreviousWithAnnotations()"
|
||||||
|
[disabled]="activeViewerPage <= displayedPages[0]"
|
||||||
|
icon="red:nav-prev"
|
||||||
|
text="file-preview.tabs.annotations.jump-to-previous"
|
||||||
|
type="show-bg"
|
||||||
|
></redaction-icon-button>
|
||||||
|
<redaction-icon-button
|
||||||
|
(action)="jumpToNextWithAnnotations()"
|
||||||
|
[disabled]="
|
||||||
|
activeViewerPage >= displayedPages[displayedPages.length - 1]
|
||||||
|
"
|
||||||
|
class="mt-8"
|
||||||
|
icon="red:nav-next"
|
||||||
|
text="file-preview.tabs.annotations.jump-to-next"
|
||||||
|
type="show-bg"
|
||||||
|
></redaction-icon-button>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<div
|
||||||
|
(click)="annotationClicked(annotation, $event)"
|
||||||
|
*ngFor="
|
||||||
|
let annotation of displayedAnnotations[activeViewerPage]?.annotations
|
||||||
|
"
|
||||||
|
[class.active]="annotationIsSelected(annotation)"
|
||||||
|
[class.multi-select-active]="multiSelectActive"
|
||||||
|
attr.annotation-id="{{ annotation.id }}"
|
||||||
|
attr.annotation-page="{{ activeViewerPage }}"
|
||||||
|
class="annotation-wrapper"
|
||||||
|
>
|
||||||
|
<div class="active-bar-marker"></div>
|
||||||
|
<div [class.removed]="annotation.isChangeLogRemoved" class="annotation">
|
||||||
|
<redaction-hidden-action
|
||||||
|
(action)="logAnnotation(annotation)"
|
||||||
|
[requiredClicks]="2"
|
||||||
>
|
>
|
||||||
<redaction-type-annotation-icon
|
|
||||||
[annotation]="annotation"
|
|
||||||
></redaction-type-annotation-icon>
|
|
||||||
<div class="flex-1">
|
|
||||||
<div>
|
|
||||||
<strong>{{ annotation.typeLabel | translate }}</strong>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="annotation?.dictionary !== 'manual'">
|
|
||||||
<strong>
|
|
||||||
<span>{{ annotation.descriptor | translate }}</span
|
|
||||||
>: </strong
|
|
||||||
>{{ annotation.dictionary | humanize: false }}
|
|
||||||
</div>
|
|
||||||
<div *ngIf="annotation.shortContent && !annotation.isHint">
|
|
||||||
<strong><span translate="content"></span>: </strong
|
|
||||||
>{{ annotation.shortContent }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="active-icon-marker-container">
|
|
||||||
<redaction-round-checkbox
|
|
||||||
*ngIf="
|
|
||||||
multiSelectActive && annotationIsSelected(annotation)
|
|
||||||
"
|
|
||||||
[active]="true"
|
|
||||||
></redaction-round-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="actions-wrapper">
|
|
||||||
<div
|
<div
|
||||||
(click)="toggleExpandComments(annotation, $event)"
|
[matTooltip]="annotation.content"
|
||||||
[matTooltip]="commentsTooltip(annotation)"
|
class="details"
|
||||||
class="comments-counter"
|
|
||||||
matTooltipPosition="above"
|
matTooltipPosition="above"
|
||||||
>
|
>
|
||||||
<mat-icon svgIcon="red:comment"></mat-icon>
|
<redaction-type-annotation-icon
|
||||||
{{ annotation.comments.length }}
|
[annotation]="annotation"
|
||||||
|
></redaction-type-annotation-icon>
|
||||||
|
<div class="flex-1">
|
||||||
|
<div>
|
||||||
|
<strong>{{ annotation.typeLabel | translate }}</strong>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="annotation?.dictionary !== 'manual'">
|
||||||
|
<strong>
|
||||||
|
<span>{{ annotation.descriptor | translate }}</span
|
||||||
|
>: </strong
|
||||||
|
>{{ annotation.dictionary | humanize: false }}
|
||||||
|
</div>
|
||||||
|
<div *ngIf="annotation.shortContent && !annotation.isHint">
|
||||||
|
<strong><span translate="content"></span>: </strong
|
||||||
|
>{{ annotation.shortContent }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="active-icon-marker-container">
|
||||||
|
<redaction-round-checkbox
|
||||||
|
*ngIf="
|
||||||
|
multiSelectActive &&
|
||||||
|
annotationIsSelected(annotation)
|
||||||
|
"
|
||||||
|
[active]="true"
|
||||||
|
></redaction-round-checkbox>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="actions" *ngIf="!multiSelectActive">
|
|
||||||
<ng-container
|
<div class="actions-wrapper">
|
||||||
[ngTemplateOutletContext]="{ annotation: annotation }"
|
<div
|
||||||
[ngTemplateOutlet]="annotationActionsTemplate"
|
(click)="toggleExpandComments(annotation, $event)"
|
||||||
></ng-container>
|
[matTooltip]="commentsTooltip(annotation)"
|
||||||
|
class="comments-counter"
|
||||||
|
matTooltipPosition="above"
|
||||||
|
>
|
||||||
|
<mat-icon svgIcon="red:comment"></mat-icon>
|
||||||
|
{{ annotation.comments.length }}
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!multiSelectActive" class="actions">
|
||||||
|
<ng-container
|
||||||
|
[ngTemplateOutletContext]="{ annotation: annotation }"
|
||||||
|
[ngTemplateOutlet]="annotationActionsTemplate"
|
||||||
|
></ng-container>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<redaction-comments [annotation]="annotation"></redaction-comments>
|
||||||
<redaction-comments [annotation]="annotation"></redaction-comments>
|
</redaction-hidden-action>
|
||||||
</redaction-hidden-action>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</ng-container>
|
||||||
|
|
||||||
|
<redaction-page-exclusion
|
||||||
|
(actionPerformed)="actionPerformed.emit($event)"
|
||||||
|
*ngIf="excludePages"
|
||||||
|
[fileData]="fileData"
|
||||||
|
></redaction-page-exclusion>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -233,7 +233,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f9fafb;
|
background-color: $grey-8;
|
||||||
|
|
||||||
::ng-deep .annotation-actions {
|
::ng-deep .annotation-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -40,6 +40,7 @@ export class FileWorkloadComponent {
|
|||||||
@Input() secondaryFilters: FilterModel[];
|
@Input() secondaryFilters: FilterModel[];
|
||||||
@Input() fileData: FileDataModel;
|
@Input() fileData: FileDataModel;
|
||||||
@Input() hideSkipped: boolean;
|
@Input() hideSkipped: boolean;
|
||||||
|
@Input() excludePages: boolean;
|
||||||
@Input() annotationActionsTemplate: TemplateRef<any>;
|
@Input() annotationActionsTemplate: TemplateRef<any>;
|
||||||
@Output() shouldDeselectAnnotationsOnPageChangeChange = new EventEmitter<boolean>();
|
@Output() shouldDeselectAnnotationsOnPageChangeChange = new EventEmitter<boolean>();
|
||||||
@Output() selectAnnotations = new EventEmitter<
|
@Output() selectAnnotations = new EventEmitter<
|
||||||
@ -49,6 +50,8 @@ export class FileWorkloadComponent {
|
|||||||
@Output() selectPage = new EventEmitter<number>();
|
@Output() selectPage = new EventEmitter<number>();
|
||||||
@Output() toggleSkipped = new EventEmitter<any>();
|
@Output() toggleSkipped = new EventEmitter<any>();
|
||||||
@Output() annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
@Output() annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||||
|
@Output() closeExcludePagesView = new EventEmitter();
|
||||||
|
@Output() actionPerformed = new EventEmitter<string>();
|
||||||
displayedPages: number[] = [];
|
displayedPages: number[] = [];
|
||||||
pagesPanelActive = true;
|
pagesPanelActive = true;
|
||||||
@ViewChildren(CommentsComponent) annotationCommentsComponents: QueryList<CommentsComponent>;
|
@ViewChildren(CommentsComponent) annotationCommentsComponents: QueryList<CommentsComponent>;
|
||||||
@ -56,9 +59,9 @@ export class FileWorkloadComponent {
|
|||||||
@ViewChild('quickNavigation') private _quickNavigationElement: ElementRef;
|
@ViewChild('quickNavigation') private _quickNavigationElement: ElementRef;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private readonly _permissionsService: PermissionsService,
|
||||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||||
private readonly _annotationProcessingService: AnnotationProcessingService,
|
private readonly _annotationProcessingService: AnnotationProcessingService,
|
||||||
private readonly _permissionsService: PermissionsService,
|
|
||||||
private readonly _translateService: TranslateService
|
private readonly _translateService: TranslateService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -71,18 +74,6 @@ export class FileWorkloadComponent {
|
|||||||
|
|
||||||
private _multiSelectActive = false;
|
private _multiSelectActive = false;
|
||||||
|
|
||||||
get isProcessing(): boolean {
|
|
||||||
return this.fileData.fileStatus?.isProcessing;
|
|
||||||
}
|
|
||||||
|
|
||||||
get activeAnnotationsLength(): number | undefined {
|
|
||||||
return this.displayedAnnotations[this.activeViewerPage]?.annotations?.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isReadOnly(): boolean {
|
|
||||||
return !this._permissionsService.canPerformAnnotationActions();
|
|
||||||
}
|
|
||||||
|
|
||||||
get multiSelectActive(): boolean {
|
get multiSelectActive(): boolean {
|
||||||
return this._multiSelectActive;
|
return this._multiSelectActive;
|
||||||
}
|
}
|
||||||
@ -97,6 +88,18 @@ export class FileWorkloadComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isProcessing(): boolean {
|
||||||
|
return this.fileData?.fileStatus?.isProcessing;
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeAnnotationsLength(): number | undefined {
|
||||||
|
return this.displayedAnnotations[this.activeViewerPage]?.annotations?.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isReadOnly(): boolean {
|
||||||
|
return !this._permissionsService.canPerformAnnotationActions();
|
||||||
|
}
|
||||||
|
|
||||||
private get _firstSelectedAnnotation() {
|
private get _firstSelectedAnnotation() {
|
||||||
return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null;
|
return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null;
|
||||||
}
|
}
|
||||||
@ -224,15 +227,21 @@ export class FileWorkloadComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scrollAnnotationsToPage(page: number, mode: 'always' | 'if-needed' = 'if-needed') {
|
scrollAnnotationsToPage(page: number, mode: 'always' | 'if-needed' = 'if-needed') {
|
||||||
const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(
|
if (this._annotationsElement) {
|
||||||
`div[anotation-page-header="${page}"]`
|
const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(
|
||||||
);
|
`div[anotation-page-header="${page}"]`
|
||||||
FileWorkloadComponent._scrollToFirstElement(elements, mode);
|
);
|
||||||
|
FileWorkloadComponent._scrollToFirstElement(elements, mode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@debounce()
|
@debounce()
|
||||||
scrollToSelectedAnnotation() {
|
scrollToSelectedAnnotation() {
|
||||||
if (!this.selectedAnnotations || this.selectedAnnotations.length === 0) {
|
if (
|
||||||
|
!this.selectedAnnotations ||
|
||||||
|
this.selectedAnnotations.length === 0 ||
|
||||||
|
!this._annotationsElement
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(
|
const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(
|
||||||
@ -420,9 +429,11 @@ export class FileWorkloadComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _scrollQuickNavigationToPage(page: number) {
|
private _scrollQuickNavigationToPage(page: number) {
|
||||||
const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(
|
if (this._quickNavigationElement) {
|
||||||
`#quick-nav-page-${page}`
|
const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(
|
||||||
);
|
`#quick-nav-page-${page}`
|
||||||
FileWorkloadComponent._scrollToFirstElement(elements);
|
);
|
||||||
|
FileWorkloadComponent._scrollToFirstElement(elements);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,41 @@
|
|||||||
|
<div *ngIf="permissionsService.canExcludePages()" class="exclude-pages-input-container">
|
||||||
|
<redaction-input-with-action
|
||||||
|
(action)="excludePagesRange()"
|
||||||
|
[form]="excludePagesForm"
|
||||||
|
hint="file-preview.tabs.exclude-pages.hint"
|
||||||
|
icon="red:check"
|
||||||
|
placeholder="file-preview.tabs.exclude-pages.input-placeholder"
|
||||||
|
type="action"
|
||||||
|
width="full"
|
||||||
|
></redaction-input-with-action>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="excludedPagesRanges.length" class="all-caps-label-container">
|
||||||
|
<div
|
||||||
|
class="all-caps-label"
|
||||||
|
translate="file-preview.tabs.exclude-pages.removed-from-redaction"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ranges" redactionHasScrollbar>
|
||||||
|
<div *ngFor="let range of excludedPagesRanges" class="range">
|
||||||
|
<ng-container *ngIf="range.startPage === range.endPage">
|
||||||
|
{{ range.startPage }}
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngIf="range.startPage !== range.endPage">
|
||||||
|
{{ range.startPage }}-{{ range.endPage }}
|
||||||
|
</ng-container>
|
||||||
|
<redaction-circle-button
|
||||||
|
(action)="includePagesRange(range)"
|
||||||
|
*ngIf="permissionsService.canExcludePages()"
|
||||||
|
icon="red:undo"
|
||||||
|
tooltip="file-preview.tabs.exclude-pages.put-back"
|
||||||
|
></redaction-circle-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
*ngIf="!permissionsService.canExcludePages() && !excludedPagesRanges.length"
|
||||||
|
class="no-excluded heading-l"
|
||||||
|
translate="file-preview.tabs.exclude-pages.no-excluded"
|
||||||
|
></div>
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
@import '../../../../../assets/styles/red-variables';
|
||||||
|
@import '../../../../../assets/styles/red-mixins';
|
||||||
|
|
||||||
|
:host {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.exclude-pages-input-container {
|
||||||
|
background-color: $grey-6;
|
||||||
|
padding: 15px 15px 16px 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.all-caps-label-container {
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-bottom: 1px solid $separator;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ranges {
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.range {
|
||||||
|
padding-left: 17px;
|
||||||
|
padding-right: 16px;
|
||||||
|
border-bottom: 1px solid $separator;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
height: 50px;
|
||||||
|
|
||||||
|
redaction-circle-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $grey-8;
|
||||||
|
|
||||||
|
redaction-circle-button {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-scrollbar:hover {
|
||||||
|
@include scroll-bar;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
.range {
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-excluded {
|
||||||
|
padding: 50px 16px;
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||||
|
import { PermissionsService } from '../../../../services/permissions.service';
|
||||||
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
import { PageRange, ReanalysisControllerService } from '@redaction/red-ui-http';
|
||||||
|
import { FileDataModel } from '../../../../models/file/file-data.model';
|
||||||
|
import { NotificationService, NotificationType } from '../../../../services/notification.service';
|
||||||
|
import { LoadingService } from '../../../../services/loading.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-page-exclusion',
|
||||||
|
templateUrl: './page-exclusion.component.html',
|
||||||
|
styleUrls: ['./page-exclusion.component.scss']
|
||||||
|
})
|
||||||
|
export class PageExclusionComponent implements OnChanges {
|
||||||
|
@Input() fileData: FileDataModel;
|
||||||
|
@Output() actionPerformed = new EventEmitter<string>();
|
||||||
|
|
||||||
|
excludePagesForm: FormGroup;
|
||||||
|
excludedPagesRanges: PageRange[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly permissionsService: PermissionsService,
|
||||||
|
private readonly _formBuilder: FormBuilder,
|
||||||
|
private readonly _reanalysisControllerService: ReanalysisControllerService,
|
||||||
|
private readonly _notificationService: NotificationService,
|
||||||
|
private readonly _loadingService: LoadingService,
|
||||||
|
private readonly _translateService: TranslateService
|
||||||
|
) {
|
||||||
|
this.excludePagesForm = this._formBuilder.group({
|
||||||
|
value: ['']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (changes.fileData) {
|
||||||
|
const excludedPages = (this.fileData?.fileStatus?.excludedPages || []).sort(
|
||||||
|
(p1, p2) => p1 - p2
|
||||||
|
);
|
||||||
|
this.excludedPagesRanges = excludedPages.reduce((ranges, page) => {
|
||||||
|
if (!ranges.length) {
|
||||||
|
return [{ startPage: page, endPage: page }];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page === ranges[ranges.length - 1].endPage + 1) {
|
||||||
|
ranges[ranges.length - 1].endPage = page;
|
||||||
|
} else {
|
||||||
|
ranges.push({ startPage: page, endPage: page });
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async excludePagesRange() {
|
||||||
|
this._loadingService.start();
|
||||||
|
try {
|
||||||
|
const pageRanges = this.excludePagesForm
|
||||||
|
.get('value')
|
||||||
|
.value.split(',')
|
||||||
|
.map(range => {
|
||||||
|
const splitted = range.split('-');
|
||||||
|
const startPage = parseInt(splitted[0], 10);
|
||||||
|
const endPage = splitted.length > 1 ? parseInt(splitted[1], 10) : startPage;
|
||||||
|
if (!startPage || !endPage) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
startPage,
|
||||||
|
endPage
|
||||||
|
};
|
||||||
|
});
|
||||||
|
await this._reanalysisControllerService
|
||||||
|
.excludePages(
|
||||||
|
{
|
||||||
|
pageRanges: pageRanges
|
||||||
|
},
|
||||||
|
this.fileData.fileStatus.dossierId,
|
||||||
|
this.fileData.fileStatus.fileId
|
||||||
|
)
|
||||||
|
.toPromise();
|
||||||
|
this.excludePagesForm.reset();
|
||||||
|
this.actionPerformed.emit('exclude-pages');
|
||||||
|
} catch (e) {
|
||||||
|
this._notificationService.showToastNotification(
|
||||||
|
this._translateService.instant('file-preview.tabs.exclude-pages.error'),
|
||||||
|
null,
|
||||||
|
NotificationType.ERROR
|
||||||
|
);
|
||||||
|
this._loadingService.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async includePagesRange(range: PageRange) {
|
||||||
|
this._loadingService.start();
|
||||||
|
await this._reanalysisControllerService
|
||||||
|
.includePages(
|
||||||
|
{
|
||||||
|
pageRanges: [range]
|
||||||
|
},
|
||||||
|
this.fileData.fileStatus.dossierId,
|
||||||
|
this.fileData.fileStatus.fileId
|
||||||
|
)
|
||||||
|
.toPromise();
|
||||||
|
this.excludePagesForm.reset();
|
||||||
|
this.actionPerformed.emit('exclude-pages');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -45,6 +45,7 @@ import { EditDossierTeamMembersComponent } from './dialogs/edit-dossier-dialog/t
|
|||||||
import { TeamMembersManagerComponent } from './components/team-members-manager/team-members-manager.component';
|
import { TeamMembersManagerComponent } from './components/team-members-manager/team-members-manager.component';
|
||||||
import { TeamMembersDialogComponent } from './dialogs/team-members-dialog/team-members-dialog.component';
|
import { TeamMembersDialogComponent } from './dialogs/team-members-dialog/team-members-dialog.component';
|
||||||
import { ScrollButtonComponent } from './components/scroll-button/scroll-button.component';
|
import { ScrollButtonComponent } from './components/scroll-button/scroll-button.component';
|
||||||
|
import { PageExclusionComponent } from './components/page-exclusion/page-exclusion.component';
|
||||||
|
|
||||||
const screens = [
|
const screens = [
|
||||||
DossierListingScreenComponent,
|
DossierListingScreenComponent,
|
||||||
@ -87,6 +88,7 @@ const components = [
|
|||||||
EditDossierTeamMembersComponent,
|
EditDossierTeamMembersComponent,
|
||||||
TeamMembersManagerComponent,
|
TeamMembersManagerComponent,
|
||||||
ScrollButtonComponent,
|
ScrollButtonComponent,
|
||||||
|
PageExclusionComponent,
|
||||||
|
|
||||||
...screens,
|
...screens,
|
||||||
...dialogs
|
...dialogs
|
||||||
|
|||||||
@ -56,11 +56,11 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<redaction-assign-user-dropdown
|
<redaction-assign-user-dropdown
|
||||||
*ngIf="editingReviewer"
|
|
||||||
[value]="currentReviewer"
|
|
||||||
[options]="singleUsersSelectOptions"
|
|
||||||
(save)="assignReviewer($event)"
|
|
||||||
(cancel)="editingReviewer = false"
|
(cancel)="editingReviewer = false"
|
||||||
|
(save)="assignReviewer($event)"
|
||||||
|
*ngIf="editingReviewer"
|
||||||
|
[options]="singleUsersSelectOptions"
|
||||||
|
[value]="currentReviewer"
|
||||||
></redaction-assign-user-dropdown>
|
></redaction-assign-user-dropdown>
|
||||||
|
|
||||||
<div *ngIf="canAssign" class="assign-actions-wrapper">
|
<div *ngIf="canAssign" class="assign-actions-wrapper">
|
||||||
@ -95,6 +95,7 @@
|
|||||||
(actionPerformed)="fileActionPerformed($event)"
|
(actionPerformed)="fileActionPerformed($event)"
|
||||||
*ngIf="viewReady"
|
*ngIf="viewReady"
|
||||||
[activeDocumentInfo]="viewDocumentInfo"
|
[activeDocumentInfo]="viewDocumentInfo"
|
||||||
|
[activeExcludePages]="excludePages"
|
||||||
></redaction-file-actions>
|
></redaction-file-actions>
|
||||||
|
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
@ -152,7 +153,12 @@
|
|||||||
|
|
||||||
<div class="right-container">
|
<div class="right-container">
|
||||||
<redaction-empty-state
|
<redaction-empty-state
|
||||||
*ngIf="viewReady && appStateService.activeFile.isExcluded && !viewDocumentInfo"
|
*ngIf="
|
||||||
|
viewReady &&
|
||||||
|
appStateService.activeFile.isExcluded &&
|
||||||
|
!viewDocumentInfo &&
|
||||||
|
!excludePages
|
||||||
|
"
|
||||||
[horizontalPadding]="40"
|
[horizontalPadding]="40"
|
||||||
icon="red:needs-work"
|
icon="red:needs-work"
|
||||||
text="file-preview.tabs.is-excluded"
|
text="file-preview.tabs.is-excluded"
|
||||||
@ -166,7 +172,9 @@
|
|||||||
|
|
||||||
<redaction-file-workload
|
<redaction-file-workload
|
||||||
#fileWorkloadComponent
|
#fileWorkloadComponent
|
||||||
|
(actionPerformed)="fileActionPerformed($event)"
|
||||||
(annotationsChanged)="annotationsChangedByReviewAction($event)"
|
(annotationsChanged)="annotationsChangedByReviewAction($event)"
|
||||||
|
(closeExcludePagesView)="excludePages = false"
|
||||||
(deselectAnnotations)="deselectAnnotations($event)"
|
(deselectAnnotations)="deselectAnnotations($event)"
|
||||||
(selectAnnotations)="selectAnnotations($event)"
|
(selectAnnotations)="selectAnnotations($event)"
|
||||||
(selectPage)="selectPage($event)"
|
(selectPage)="selectPage($event)"
|
||||||
@ -177,6 +185,7 @@
|
|||||||
[annotationActionsTemplate]="annotationActionsTemplate"
|
[annotationActionsTemplate]="annotationActionsTemplate"
|
||||||
[annotations]="annotations"
|
[annotations]="annotations"
|
||||||
[dialogRef]="dialogRef"
|
[dialogRef]="dialogRef"
|
||||||
|
[excludePages]="excludePages"
|
||||||
[fileData]="fileData"
|
[fileData]="fileData"
|
||||||
[hideSkipped]="hideSkipped"
|
[hideSkipped]="hideSkipped"
|
||||||
[primaryFilters]="primaryFilters"
|
[primaryFilters]="primaryFilters"
|
||||||
|
|||||||
@ -45,6 +45,7 @@ import {
|
|||||||
handleFilterDelta,
|
handleFilterDelta,
|
||||||
processFilters
|
processFilters
|
||||||
} from '@shared/components/filters/popup-filter/utils/filter-utils';
|
} from '@shared/components/filters/popup-filter/utils/filter-utils';
|
||||||
|
import { LoadingService } from '../../../../services/loading.service';
|
||||||
|
|
||||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||||
|
|
||||||
@ -71,6 +72,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
|||||||
hideSkipped = false;
|
hideSkipped = false;
|
||||||
displayPDFViewer = false;
|
displayPDFViewer = false;
|
||||||
viewDocumentInfo = false;
|
viewDocumentInfo = false;
|
||||||
|
excludePages = false;
|
||||||
|
|
||||||
private _instance: WebViewerInstance;
|
private _instance: WebViewerInstance;
|
||||||
private _lastPage: string;
|
private _lastPage: string;
|
||||||
@ -94,7 +96,8 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
|||||||
private readonly _fileDownloadService: PdfViewerDataService,
|
private readonly _fileDownloadService: PdfViewerDataService,
|
||||||
private readonly _statusControllerService: StatusControllerService,
|
private readonly _statusControllerService: StatusControllerService,
|
||||||
private readonly _ngZone: NgZone,
|
private readonly _ngZone: NgZone,
|
||||||
private readonly _fileManagementControllerService: FileManagementControllerService
|
private readonly _fileManagementControllerService: FileManagementControllerService,
|
||||||
|
private readonly _loadingService: LoadingService
|
||||||
) {
|
) {
|
||||||
document.documentElement.addEventListener('fullscreenchange', () => {
|
document.documentElement.addEventListener('fullscreenchange', () => {
|
||||||
if (!document.fullscreenElement) {
|
if (!document.fullscreenElement) {
|
||||||
@ -169,6 +172,36 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
|||||||
return this.appStateService.activeFile.fileStatus.lastReviewer;
|
return this.appStateService.activeFile.fileStatus.lastReviewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get assignOrChangeReviewerTooltip() {
|
||||||
|
return this.currentReviewer
|
||||||
|
? 'file-preview.change-reviewer'
|
||||||
|
: 'file-preview.assign-reviewer';
|
||||||
|
}
|
||||||
|
|
||||||
|
get currentReviewer(): string {
|
||||||
|
return this.appStateService.activeFile.currentReviewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
get status(): FileStatus.StatusEnum {
|
||||||
|
return this.appStateService.activeFile.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
get statusBarConfig(): [{ length: number; color: FileStatus.StatusEnum }] {
|
||||||
|
return [{ length: 1, color: this.status }];
|
||||||
|
}
|
||||||
|
|
||||||
|
get isUnderReviewOrApproval(): boolean {
|
||||||
|
return this.status === 'UNDER_REVIEW' || this.status === 'UNDER_APPROVAL';
|
||||||
|
}
|
||||||
|
|
||||||
|
get canAssignReviewer(): boolean {
|
||||||
|
return (
|
||||||
|
!this.currentReviewer &&
|
||||||
|
this.permissionsService.canAssignUser() &&
|
||||||
|
this.appStateService.activeDossier.hasMoreThanOneReviewer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
updateViewMode() {
|
updateViewMode() {
|
||||||
const annotations = this._getAnnotations(a => a.getCustomData('redacto-manager'));
|
const annotations = this._getAnnotations(a => a.getCustomData('redacto-manager'));
|
||||||
const redactions = annotations.filter(a => a.getCustomData('redaction'));
|
const redactions = annotations.filter(a => a.getCustomData('redaction'));
|
||||||
@ -441,10 +474,22 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
|||||||
await this.appStateService.reloadActiveDossierFiles();
|
await this.appStateService.reloadActiveDossierFiles();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'exclude-pages':
|
||||||
|
await this.appStateService.reloadActiveDossierFiles();
|
||||||
|
await this._loadFileData();
|
||||||
|
this._loadingService.stop();
|
||||||
|
return;
|
||||||
|
|
||||||
case 'view-document-info':
|
case 'view-document-info':
|
||||||
this.viewDocumentInfo = !this.viewDocumentInfo;
|
this.viewDocumentInfo = !this.viewDocumentInfo;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'view-exclude-pages':
|
||||||
|
this.excludePages = !this.excludePages;
|
||||||
|
this._workloadComponent.multiSelectActive = false;
|
||||||
|
this.viewDocumentInfo = false;
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
this._updateCanPerformActions();
|
this._updateCanPerformActions();
|
||||||
}
|
}
|
||||||
@ -509,36 +554,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
get assignOrChangeReviewerTooltip() {
|
|
||||||
return this.currentReviewer
|
|
||||||
? 'file-preview.change-reviewer'
|
|
||||||
: 'file-preview.assign-reviewer';
|
|
||||||
}
|
|
||||||
|
|
||||||
get currentReviewer(): string {
|
|
||||||
return this.appStateService.activeFile.currentReviewer;
|
|
||||||
}
|
|
||||||
|
|
||||||
get status(): FileStatus.StatusEnum {
|
|
||||||
return this.appStateService.activeFile.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
get statusBarConfig(): [{ length: number; color: FileStatus.StatusEnum }] {
|
|
||||||
return [{ length: 1, color: this.status }];
|
|
||||||
}
|
|
||||||
|
|
||||||
get isUnderReviewOrApproval(): boolean {
|
|
||||||
return this.status === 'UNDER_REVIEW' || this.status === 'UNDER_APPROVAL';
|
|
||||||
}
|
|
||||||
|
|
||||||
get canAssignReviewer(): boolean {
|
|
||||||
return (
|
|
||||||
!this.currentReviewer &&
|
|
||||||
this.permissionsService.canAssignUser() &&
|
|
||||||
this.appStateService.activeDossier.hasMoreThanOneReviewer
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// <!-- Dev Mode Features-->
|
// <!-- Dev Mode Features-->
|
||||||
async openSSRFilePreview() {
|
async openSSRFilePreview() {
|
||||||
window.open(`/pdf-preview/${this.dossierId}/${this.fileId}`, '_blank');
|
window.open(`/pdf-preview/${this.dossierId}/${this.fileId}`, '_blank');
|
||||||
@ -576,7 +591,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach,
|
|||||||
|
|
||||||
private async _loadFileData(performUpdate: boolean = false): Promise<void> {
|
private async _loadFileData(performUpdate: boolean = false): Promise<void> {
|
||||||
const fileData = await this._fileDownloadService.loadActiveFileData().toPromise();
|
const fileData = await this._fileDownloadService.loadActiveFileData().toPromise();
|
||||||
console.log(fileData);
|
|
||||||
if (!fileData.fileStatus.isPending && !fileData.fileStatus.isError) {
|
if (!fileData.fileStatus.isPending && !fileData.fileStatus.isError) {
|
||||||
if (performUpdate) {
|
if (performUpdate) {
|
||||||
this.fileData.redactionLog = fileData.redactionLog;
|
this.fileData.redactionLog = fileData.redactionLog;
|
||||||
|
|||||||
@ -30,19 +30,19 @@ export class ManualAnnotationService {
|
|||||||
addComment(comment: string, annotationId: string) {
|
addComment(comment: string, annotationId: string) {
|
||||||
return this._manualRedactionControllerService.addComment(
|
return this._manualRedactionControllerService.addComment(
|
||||||
{ text: comment },
|
{ text: comment },
|
||||||
|
annotationId,
|
||||||
this._appStateService.activeDossierId,
|
this._appStateService.activeDossierId,
|
||||||
this._appStateService.activeFileId,
|
this._appStateService.activeFileId
|
||||||
annotationId
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this wraps /manualRedaction/comment/undo
|
// this wraps /manualRedaction/comment/undo
|
||||||
deleteComment(commentId: string, annotationId: string) {
|
deleteComment(commentId: string, annotationId: string) {
|
||||||
return this._manualRedactionControllerService.undoComment(
|
return this._manualRedactionControllerService.undoComment(
|
||||||
this._appStateService.activeDossierId,
|
|
||||||
this._appStateService.activeFileId,
|
|
||||||
annotationId,
|
annotationId,
|
||||||
commentId
|
commentId,
|
||||||
|
this._appStateService.activeDossierId,
|
||||||
|
this._appStateService.activeFileId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -39,6 +39,7 @@ export class IconsModule {
|
|||||||
'edit',
|
'edit',
|
||||||
'entries',
|
'entries',
|
||||||
'error',
|
'error',
|
||||||
|
'exclude-pages',
|
||||||
'exit-fullscreen',
|
'exit-fullscreen',
|
||||||
'expand',
|
'expand',
|
||||||
'folder',
|
'folder',
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<form (submit)="type === 'submit' && submit()" [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<div [style.max-width]="computedWidth" [style.width]="computedWidth" class="red-input-group">
|
<div [style.max-width]="computedWidth" [style.width]="computedWidth" class="red-input-group">
|
||||||
<input
|
<input
|
||||||
[formControlName]="formControlName"
|
[formControlName]="formControlName"
|
||||||
@ -8,6 +8,8 @@
|
|||||||
type="text"
|
type="text"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<span *ngIf="hint" [translate]="hint" class="hint"></span>
|
||||||
|
|
||||||
<!-- Search-->
|
<!-- Search-->
|
||||||
<mat-icon
|
<mat-icon
|
||||||
*ngIf="type === 'search' && !hasContent"
|
*ngIf="type === 'search' && !hasContent"
|
||||||
@ -26,11 +28,11 @@
|
|||||||
|
|
||||||
<!-- Submit-->
|
<!-- Submit-->
|
||||||
<redaction-circle-button
|
<redaction-circle-button
|
||||||
(action)="submit($event)"
|
(action)="executeAction($event)"
|
||||||
*ngIf="type === 'submit'"
|
*ngIf="type === 'action'"
|
||||||
[disabled]="form.invalid"
|
[disabled]="!hasContent"
|
||||||
|
[icon]="icon"
|
||||||
[size]="25"
|
[size]="25"
|
||||||
icon="red:collapse"
|
|
||||||
>
|
>
|
||||||
</redaction-circle-button>
|
</redaction-circle-button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,6 +9,6 @@ mat-icon.disabled {
|
|||||||
|
|
||||||
redaction-circle-button {
|
redaction-circle-button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 5px;
|
top: 4px;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,10 @@ import { FormGroup } from '@angular/forms';
|
|||||||
export class InputWithActionComponent {
|
export class InputWithActionComponent {
|
||||||
@Input() form: FormGroup;
|
@Input() form: FormGroup;
|
||||||
@Input() placeholder: string;
|
@Input() placeholder: string;
|
||||||
|
@Input() hint: string;
|
||||||
@Input() width: number | 'full' = 250;
|
@Input() width: number | 'full' = 250;
|
||||||
@Input() type: 'search' | 'submit';
|
@Input() type: 'search' | 'action';
|
||||||
|
@Input() icon: string;
|
||||||
@Output() action = new EventEmitter<any>();
|
@Output() action = new EventEmitter<any>();
|
||||||
|
|
||||||
get formControlName(): 'query' | 'value' {
|
get formControlName(): 'query' | 'value' {
|
||||||
@ -18,7 +20,7 @@ export class InputWithActionComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get hasContent() {
|
get hasContent() {
|
||||||
return !!this.form.get(this.formControlName).value.length;
|
return !!this.form.get(this.formControlName).value?.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
get computedWidth() {
|
get computedWidth() {
|
||||||
@ -29,7 +31,7 @@ export class InputWithActionComponent {
|
|||||||
this.form.patchValue({ query: '' });
|
this.form.patchValue({ query: '' });
|
||||||
}
|
}
|
||||||
|
|
||||||
submit($event?: MouseEvent) {
|
executeAction($event?: MouseEvent) {
|
||||||
$event?.stopPropagation();
|
$event?.stopPropagation();
|
||||||
if (this.hasContent) {
|
if (this.hasContent) {
|
||||||
this.action.emit();
|
this.action.emit();
|
||||||
|
|||||||
@ -216,4 +216,11 @@ export class PermissionsService {
|
|||||||
canAddComment(fileStatus = this._activeFile): boolean {
|
canAddComment(fileStatus = this._activeFile): boolean {
|
||||||
return this.isFileReviewer(fileStatus) || this.isApprover();
|
return this.isFileReviewer(fileStatus) || this.isApprover();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canExcludePages(fileStatus = this._activeFile): boolean {
|
||||||
|
return (
|
||||||
|
['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status) &&
|
||||||
|
(this.isFileReviewer(fileStatus) || this.isApprover())
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -375,7 +375,19 @@
|
|||||||
"label": "Workload",
|
"label": "Workload",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
"jump-to-previous": "Jump to Previous",
|
"jump-to-previous": "Jump to Previous",
|
||||||
"jump-to-next": "Jump to Next"
|
"jump-to-next": "Jump to Next",
|
||||||
|
"select-all": "All",
|
||||||
|
"select-none": "None"
|
||||||
|
},
|
||||||
|
"exclude-pages": {
|
||||||
|
"label": "Exclude Pages",
|
||||||
|
"close": "Close",
|
||||||
|
"error": "Error! Invalid page selection.",
|
||||||
|
"input-placeholder": "e.g. 1-20,22,32",
|
||||||
|
"hint": "Minus (-) for range and comma (,) for enumeration.",
|
||||||
|
"removed-from-redaction": "Removed from redaction",
|
||||||
|
"put-back": "Put back",
|
||||||
|
"no-excluded": "No excluded pages."
|
||||||
},
|
},
|
||||||
"is-excluded": "Redaction is disabled for this document."
|
"is-excluded": "Redaction is disabled for this document."
|
||||||
},
|
},
|
||||||
@ -392,6 +404,7 @@
|
|||||||
"last-reviewer": "Last Reviewed by:",
|
"last-reviewer": "Last Reviewed by:",
|
||||||
"fullscreen": "Full Screen (F)",
|
"fullscreen": "Full Screen (F)",
|
||||||
"document-info": "Your Document Info lives here. This includes metadata required on each document.",
|
"document-info": "Your Document Info lives here. This includes metadata required on each document.",
|
||||||
|
"exclude-pages": "Exclude pages from redaction",
|
||||||
"new-tab-ssr": "Open Document in Server Side Rendering Mode",
|
"new-tab-ssr": "Open Document in Server Side Rendering Mode",
|
||||||
"html-debug": "Open Document HTML Debug",
|
"html-debug": "Open Document HTML Debug",
|
||||||
"download-original-file": "Download Original File",
|
"download-original-file": "Download Original File",
|
||||||
|
|||||||
14
apps/red-ui/src/assets/icons/general/exclude-pages.svg
Normal file
14
apps/red-ui/src/assets/icons/general/exclude-pages.svg
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg height="14px" version="1.1" viewBox="0 0 14 14" width="14px"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g fill="none" fill-rule="evenodd" id="Styleguide" stroke="none" stroke-width="1">
|
||||||
|
<g fill="currentColor" fill-rule="nonzero"
|
||||||
|
id="Export-just-icons" transform="translate(-346.000000, -902.000000)">
|
||||||
|
<g id="status" transform="translate(346.000000, 902.000000)">
|
||||||
|
<path
|
||||||
|
d="M14,0 L14,11.2 L11.2,11.2 L11.2,14 L0,14 L0,2.8 L2.8,2.8 L2.8,0 L14,0 Z M2.8,4.2 L1.4,4.2 L1.4,12.6 L9.8,12.6 L9.8,11.2 L2.8,11.2 L2.8,4.2 Z M12.6,1.4 L4.2,1.4 L4.2,9.8 L12.6,9.8 L12.6,1.4 Z M9.88492424,3.12512627 L10.8748737,4.11507576 L9.39,5.6 L10.8748737,7.08492424 L9.88492424,8.07487373 L8.4,6.59 L6.91507576,8.07487373 L5.92512627,7.08492424 L7.41,5.6 L5.92512627,4.11507576 L6.91507576,3.12512627 L8.4,4.61 L9.88492424,3.12512627 Z"
|
||||||
|
id="pages"></path>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1012 B |
@ -106,7 +106,7 @@ cdk-virtual-scroll-viewport {
|
|||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
> div {
|
> div {
|
||||||
background-color: #f9fafb;
|
background-color: $grey-8;
|
||||||
|
|
||||||
&.selection-column redaction-round-checkbox {
|
&.selection-column redaction-round-checkbox {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user