FileStatusWrapper => File

This commit is contained in:
Dan Percic 2021-09-26 16:44:01 +03:00
parent 0222d01e5d
commit 11f804c526
36 changed files with 504 additions and 538 deletions

View File

@ -1,5 +1,5 @@
import { RedactionChangeLog, RedactionLog, ViewedPages } from '@redaction/red-ui-http';
import { FileStatusWrapper } from './file-status.wrapper';
import { File } from './file';
import { AnnotationWrapper } from './annotation.wrapper';
import { RedactionLogEntryWrapper } from './redaction-log-entry.wrapper';
import { ViewMode } from './view-mode';
@ -13,7 +13,7 @@ export class AnnotationData {
export class FileDataModel {
constructor(
public fileStatus: FileStatusWrapper,
public file: File,
public fileData: Blob,
public redactionLog: RedactionLog,
public redactionChangeLog: RedactionChangeLog,
@ -29,7 +29,7 @@ export class FileDataModel {
const entries: RedactionLogEntryWrapper[] = this._convertData();
let allAnnotations = entries
.map(entry => AnnotationWrapper.fromData(entry))
.filter(ann => !this.fileStatus.excludedPages.includes(ann.pageNumber));
.filter(ann => !this.file.excludedPages.includes(ann.pageNumber));
if (!areDevFeaturesEnabled) {
allAnnotations = allAnnotations.filter(annotation => !annotation.isFalsePositive);

View File

@ -1,106 +0,0 @@
import { IListable } from '@iqser/common-ui';
import { FileAttributesConfig, FileStatus } from '@redaction/red-ui-http';
import { StatusSorter } from '@utils/sorters/status-sorter';
const processingStatuses = [
FileStatus.StatusEnum.REPROCESS,
FileStatus.StatusEnum.FULLREPROCESS,
FileStatus.StatusEnum.OCRPROCESSING,
FileStatus.StatusEnum.INDEXING,
FileStatus.StatusEnum.PROCESSING
] as const;
export class FileStatusWrapper implements FileStatus, IListable {
readonly added = this.fileStatus.added;
readonly allManualRedactionsApplied = this.fileStatus.allManualRedactionsApplied;
readonly analysisDuration = this.fileStatus.analysisDuration;
readonly analysisRequired = this.fileStatus.analysisRequired && !this.fileStatus.excluded;
readonly approvalDate = this.fileStatus.approvalDate;
readonly currentReviewer = this.fileStatus.currentReviewer;
readonly dictionaryVersion = this.fileStatus.dictionaryVersion;
readonly dossierDictionaryVersion = this.fileStatus.dossierDictionaryVersion;
readonly dossierId = this.fileStatus.dossierId;
readonly excluded = this.fileStatus.excluded;
readonly fileAttributes = this.fileStatus.fileAttributes;
readonly fileId = this.fileStatus.fileId;
readonly filename = this.fileStatus.filename;
readonly hasAnnotationComments = this.fileStatus.hasAnnotationComments;
readonly hasHints = this.fileStatus.hasHints;
readonly hasImages = this.fileStatus.hasImages;
readonly hasRedactions = this.fileStatus.hasRedactions;
readonly hasUpdates = this.fileStatus.hasUpdates;
readonly lastOCRTime = this.fileStatus.lastOCRTime;
readonly lastProcessed = this.fileStatus.lastProcessed;
readonly lastReviewer = this.fileStatus.lastReviewer;
readonly lastUpdated = this.fileStatus.lastUpdated;
readonly lastUploaded = this.fileStatus.lastUploaded;
readonly legalBasisVersion = this.fileStatus.legalBasisVersion;
readonly numberOfAnalyses = this.fileStatus.numberOfAnalyses;
readonly numberOfPages = this.fileStatus.numberOfPages;
readonly rulesVersion = this.fileStatus.rulesVersion;
readonly status = this._status;
readonly uploader = this.fileStatus.uploader;
readonly excludedPages = this.fileStatus.excludedPages;
readonly hasSuggestions = this.fileStatus.hasSuggestions;
readonly dossierTemplateId = this.fileStatus.dossierTemplateId;
primaryAttribute: string;
lastOpened: boolean;
constructor(readonly fileStatus: FileStatus, public reviewerName: string, fileAttributesConfig?: FileAttributesConfig) {
if (fileAttributesConfig) {
const primary = fileAttributesConfig.fileAttributeConfigs?.find(c => c.primaryAttribute);
if (primary && fileStatus.fileAttributes?.attributeIdToValue) {
this.primaryAttribute = fileStatus.fileAttributes?.attributeIdToValue[primary.id];
}
if (!this.primaryAttribute) {
// Fallback here
this.primaryAttribute = '-';
}
}
if (!this.fileAttributes || !this.fileAttributes.attributeIdToValue) {
this.fileAttributes = { attributeIdToValue: {} };
}
}
readonly statusSort = StatusSorter[this.status];
readonly pages = this._pages;
readonly cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime);
readonly hintsOnly = this.hasHints && !this.hasRedactions;
readonly hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions;
readonly isUnassigned = !this.currentReviewer;
readonly isError = this.status === FileStatus.StatusEnum.ERROR;
readonly isProcessing = processingStatuses.includes(this.status);
readonly isApproved = this.status === FileStatus.StatusEnum.APPROVED;
readonly isPending = this.status === FileStatus.StatusEnum.UNPROCESSED;
readonly isUnderReview = this.status === FileStatus.StatusEnum.UNDERREVIEW;
readonly isUnderApproval = this.status === FileStatus.StatusEnum.UNDERAPPROVAL;
readonly canBeApproved = !this.analysisRequired && !this.hasSuggestions;
readonly canBeOpened = !this.isError && !this.isPending;
readonly isWorkable = !this.isProcessing && this.canBeOpened;
readonly canBeOCRed = !this.excluded && !this.lastOCRTime && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(this.status);
get id(): string {
return this.fileId;
}
get searchKey(): string {
return this.filename;
}
private get _pages() {
if (this.fileStatus.status === 'ERROR') {
return -1;
}
return this.fileStatus.numberOfPages ? this.fileStatus.numberOfPages : 0;
}
private get _status(): FileStatus.StatusEnum {
return this.fileStatus.status === FileStatus.StatusEnum.REPROCESS || this.fileStatus.status === FileStatus.StatusEnum.FULLREPROCESS
? FileStatus.StatusEnum.PROCESSING
: this.fileStatus.status;
}
}

View File

@ -0,0 +1,138 @@
import { IListable } from '@iqser/common-ui';
import { FileAttributes, FileAttributesConfig, FileStatus, FileStatuses, IFile, List } from '@redaction/red-ui-http';
import { StatusSorter } from '@utils/sorters/status-sorter';
const processingStatuses: List<FileStatus> = [
FileStatuses.REPROCESS,
FileStatuses.FULLREPROCESS,
FileStatuses.OCR_PROCESSING,
FileStatuses.INDEXING,
FileStatuses.PROCESSING
] as const;
export class File implements IFile, IListable {
readonly added: string;
readonly allManualRedactionsApplied: boolean;
readonly analysisDuration: number;
readonly analysisRequired: boolean;
readonly approvalDate: string;
readonly currentReviewer: string;
readonly dictionaryVersion: number;
readonly dossierDictionaryVersion: number;
readonly dossierId: string;
readonly excluded: boolean;
readonly fileAttributes: FileAttributes;
readonly fileId: string;
readonly filename: string;
readonly hasAnnotationComments: boolean;
readonly hasHints: boolean;
readonly hasImages: boolean;
readonly hasRedactions: boolean;
readonly hasUpdates: boolean;
readonly lastOCRTime: string;
readonly lastProcessed: string;
readonly lastReviewer: string;
readonly lastUpdated: string;
readonly lastUploaded: string;
readonly legalBasisVersion: number;
readonly numberOfAnalyses: number;
readonly numberOfPages: number;
readonly rulesVersion: number;
readonly status: FileStatus;
readonly uploader: string;
readonly excludedPages: number[];
readonly hasSuggestions: boolean;
readonly dossierTemplateId: string;
primaryAttribute: string;
lastOpened: boolean;
readonly statusSort: number;
readonly cacheIdentifier: string;
readonly hintsOnly: boolean;
readonly hasNone: boolean;
readonly isUnassigned: boolean;
readonly isError: boolean;
readonly isProcessing: boolean;
readonly isApproved: boolean;
readonly isPending: boolean;
readonly isUnderReview: boolean;
readonly isUnderApproval: boolean;
readonly canBeApproved: boolean;
readonly canBeOpened: boolean;
readonly isWorkable: boolean;
readonly canBeOCRed: boolean;
constructor(file: IFile, public reviewerName: string, fileAttributesConfig?: FileAttributesConfig) {
this.added = file.added;
this.allManualRedactionsApplied = file.allManualRedactionsApplied;
this.analysisDuration = file.analysisDuration;
this.analysisRequired = file.analysisRequired && !file.excluded;
this.approvalDate = file.approvalDate;
this.currentReviewer = file.currentReviewer;
this.dictionaryVersion = file.dictionaryVersion;
this.dossierDictionaryVersion = file.dossierDictionaryVersion;
this.dossierId = file.dossierId;
this.excluded = file.excluded;
this.fileAttributes = file.fileAttributes;
this.fileId = file.fileId;
this.filename = file.filename;
this.hasAnnotationComments = file.hasAnnotationComments;
this.hasHints = file.hasHints;
this.hasImages = file.hasImages;
this.hasRedactions = file.hasRedactions;
this.hasUpdates = file.hasUpdates;
this.lastOCRTime = file.lastOCRTime;
this.lastProcessed = file.lastProcessed;
this.lastReviewer = file.lastReviewer;
this.lastUpdated = file.lastUpdated;
this.lastUploaded = file.lastUploaded;
this.legalBasisVersion = file.legalBasisVersion;
this.numberOfAnalyses = file.numberOfAnalyses;
this.status = ['REPROCESS', 'FULLREPROCESS'].includes(file.status) ? FileStatuses.PROCESSING : file.status;
this.isError = this.status === FileStatuses.ERROR;
this.numberOfPages = this.isError ? -1 : file.numberOfPages ?? 0;
this.rulesVersion = file.rulesVersion;
this.uploader = file.uploader;
this.excludedPages = file.excludedPages;
this.hasSuggestions = file.hasSuggestions;
this.dossierTemplateId = file.dossierTemplateId;
this.statusSort = StatusSorter[this.status];
this.cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime);
this.hintsOnly = this.hasHints && !this.hasRedactions;
this.hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions;
this.isUnassigned = !this.currentReviewer;
this.isProcessing = processingStatuses.includes(this.status);
this.isApproved = this.status === FileStatuses.APPROVED;
this.isPending = this.status === FileStatuses.UNPROCESSED;
this.isUnderReview = this.status === FileStatuses.UNDER_REVIEW;
this.isUnderApproval = this.status === FileStatuses.UNDER_APPROVAL;
this.canBeApproved = !this.analysisRequired && !this.hasSuggestions;
this.canBeOpened = !this.isError && !this.isPending;
this.isWorkable = !this.isProcessing && this.canBeOpened;
this.canBeOCRed = !this.excluded && !this.lastOCRTime && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(this.status);
if (fileAttributesConfig) {
const primary = fileAttributesConfig.fileAttributeConfigs?.find(c => c.primaryAttribute);
if (primary && file.fileAttributes?.attributeIdToValue) {
this.primaryAttribute = file.fileAttributes?.attributeIdToValue[primary.id];
}
if (!this.primaryAttribute) {
// Fallback here
this.primaryAttribute = '-';
}
}
if (!this.fileAttributes || !this.fileAttributes.attributeIdToValue) {
this.fileAttributes = { attributeIdToValue: {} };
}
}
get id(): string {
return this.fileId;
}
get searchKey(): string {
return this.filename;
}
}

View File

@ -2,7 +2,7 @@ import { Component, EventEmitter, Output } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http';
import { PermissionsService } from '@services/permissions.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { FileActionService } from '../../services/file-action.service';
import { Observable } from 'rxjs';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
@ -19,8 +19,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
export class DossierOverviewBulkActionsComponent {
readonly circleButtonTypes = CircleButtonTypes;
@Output()
reload = new EventEmitter();
@Output() readonly reload = new EventEmitter();
constructor(
private readonly _appStateService: AppStateService,
@ -31,14 +30,14 @@ export class DossierOverviewBulkActionsComponent {
private readonly _fileActionService: FileActionService,
private readonly _loadingService: LoadingService,
private readonly _translateService: TranslateService,
private readonly _entitiesService: EntitiesService<FileStatusWrapper>
private readonly _entitiesService: EntitiesService<File>
) {}
get dossier() {
return this._appStateService?.activeDossier;
}
get selectedFiles(): FileStatusWrapper[] {
get selectedFiles(): File[] {
return this._entitiesService.selected;
}
@ -91,21 +90,18 @@ export class DossierOverviewBulkActionsComponent {
return this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true);
}
get fileStatuses() {
return this.selectedFiles.map(file => file.fileStatus.status);
get files() {
return this.selectedFiles.map(file => file.status);
}
// Under review
get canSetToUnderReview() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true);
}
// Under approval
get canSetToUnderApproval() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true);
}
// Approve
get isReadyForApproval() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true);
}
@ -114,7 +110,6 @@ export class DossierOverviewBulkActionsComponent {
return this.selectedFiles.reduce((acc, file) => acc && file.canBeApproved, true);
}
// Undo approval
get canUndoApproval() {
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true);
}
@ -156,7 +151,7 @@ export class DossierOverviewBulkActionsComponent {
this._assignFiles('approver', true);
} else {
this._performBulkAction(
this._fileActionService.setFileUnderApproval(this.selectedFiles, this._appStateService.activeDossier.approverIds[0])
this._fileActionService.setFilesUnderApproval(this.selectedFiles, this._appStateService.activeDossier.approverIds[0])
);
}
}
@ -169,11 +164,11 @@ export class DossierOverviewBulkActionsComponent {
}
ocr() {
this._performBulkAction(this._fileActionService.ocrFile(this.selectedFiles));
this._performBulkAction(this._fileActionService.ocrFiles(this.selectedFiles));
}
setToUnderReview() {
this._performBulkAction(this._fileActionService.setFileUnderReview(this.selectedFiles));
this._performBulkAction(this._fileActionService.setFilesUnderReview(this.selectedFiles));
}
approveDocuments() {
@ -187,11 +182,11 @@ export class DossierOverviewBulkActionsComponent {
question: _('confirmation-dialog.approve-multiple-files.question')
}),
() => {
this._performBulkAction(this._fileActionService.setFileApproved(this.selectedFiles));
this._performBulkAction(this._fileActionService.setFilesApproved(this.selectedFiles));
}
);
} else {
this._performBulkAction(this._fileActionService.setFileApproved(this.selectedFiles));
this._performBulkAction(this._fileActionService.setFilesApproved(this.selectedFiles));
}
}

View File

@ -3,7 +3,7 @@ import { FileAttributesConfig } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { AutoUnsubscribe } from '@iqser/common-ui';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
@Component({
selector: 'redaction-document-info',
@ -11,7 +11,7 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
styleUrls: ['./document-info.component.scss']
})
export class DocumentInfoComponent extends AutoUnsubscribe implements OnInit {
@Input() file: FileStatusWrapper;
@Input() file: File;
@Output() closeDocumentInfoView = new EventEmitter();
fileAttributesConfig: FileAttributesConfig;

View File

@ -7,8 +7,8 @@
<ng-container *ngTemplateOutlet="actions"></ng-container>
</ng-container>
<ng-template #actions redactionLongPress (longPress)="forceReanalysisAction($event)">
<div *ngIf="fileStatus" class="file-actions">
<ng-template #actions (longPress)="forceReanalysisAction($event)" redactionLongPress>
<div *ngIf="file" class="file-actions">
<iqser-circle-button
(action)="openDocument()"
*ngIf="showOpenDocument"
@ -48,7 +48,7 @@
<!-- download redacted file-->
<redaction-file-download-btn
[dossier]="appStateService.activeDossier"
[file]="fileStatus"
[file]="file"
[tooltipClass]="'small'"
[tooltipPosition]="tooltipPosition"
[type]="buttonType"
@ -67,7 +67,7 @@
(action)="toggleExcludePages()"
*ngIf="showExcludePages"
[attr.aria-expanded]="activeExcludePages"
[showDot]="!!fileStatus.excludedPages?.length"
[showDot]="!!file.excludedPages?.length"
[tooltip]="'file-preview.exclude-pages' | translate"
icon="red:exclude-pages"
tooltipPosition="below"
@ -99,9 +99,7 @@
*ngIf="showApprove"
[disabled]="!fileStatus.canBeApproved"
[tooltipPosition]="tooltipPosition"
[tooltip]="
fileStatus.canBeApproved ? ('dossier-overview.approve' | translate) : ('dossier-overview.approve-disabled' | translate)
"
[tooltip]="file.canBeApproved ? ('dossier-overview.approve' | translate) : ('dossier-overview.approve-disabled' | translate)"
[type]="buttonType"
icon="red:approved"
></iqser-circle-button>
@ -150,7 +148,7 @@
<mat-slide-toggle
(change)="toggleAnalysis()"
(click)="$event.stopPropagation()"
[checked]="!fileStatus?.excluded"
[checked]="!file?.excluded"
[class.mr-24]="isDossierOverviewList"
[disabled]="!canToggleAnalysis"
[matTooltipPosition]="tooltipPosition"

View File

@ -1,6 +1,6 @@
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { AppStateService } from '@state/app-state.service';
import { FileActionService } from '../../services/file-action.service';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
@ -10,8 +10,8 @@ import { FileManagementControllerService, FileStatus } from '@redaction/red-ui-h
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { UserService } from '@services/user.service';
import { filter } from 'rxjs/operators';
import { UserPreferenceService } from '../../../../services/user-preference.service';
import { LongPressEvent } from '../../../shared/directives/long-press.directive';
import { UserPreferenceService } from '@services/user-preference.service';
import { LongPressEvent } from '@shared/directives/long-press.directive';
@Component({
selector: 'redaction-file-actions',
@ -22,13 +22,13 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = this._userService.currentUser;
@Input() fileStatus: FileStatusWrapper;
@Input() file: File;
@Input() activeDocumentInfo: boolean;
@Input() activeExcludePages: boolean;
@Input() @Required() type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
@Output() actionPerformed = new EventEmitter<string>();
@Output() readonly actionPerformed = new EventEmitter<string>();
statusBarConfig?: readonly StatusBarConfig<FileStatus.StatusEnum>[];
statusBarConfig?: readonly StatusBarConfig<FileStatus>[];
tooltipPosition?: 'below' | 'above';
toggleTooltip?: string;
assignTooltip?: string;
@ -84,7 +84,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
return _('file-preview.toggle-analysis.only-managers');
}
return this.fileStatus?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
return this.file?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
}
ngOnInit(): void {
@ -92,12 +92,10 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
this.fileStatus = this.appStateService.activeFile;
}
this._setup();
this.addSubscription = this.appStateService.fileChanged$
.pipe(filter(file => file.fileId === this.fileStatus?.fileId))
.subscribe(fileStatus => {
this.fileStatus = fileStatus;
this._setup();
});
this.addSubscription = this.appStateService.fileChanged$.pipe(filter(file => file.fileId === this.file?.fileId)).subscribe(file => {
this.file = file;
this._setup();
});
this.addSubscription = this.appStateService.dossierChanged$.subscribe(() => {
this._setup();
@ -127,7 +125,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
async () => {
this._loadingService.start();
await this._fileManagementControllerService
.deleteFiles([this.fileStatus.fileId], this.fileStatus.dossierId)
.deleteFiles([this.file.fileId], this.file.dossierId)
.toPromise()
.catch(error => {
this._toaster.error(_('error.http.generic'), { params: error });
@ -140,8 +138,8 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
}
assign($event: MouseEvent) {
const mode = this.fileStatus.isUnderApproval ? 'approver' : 'reviewer';
const files = [this.fileStatus];
const mode = this.file.isUnderApproval ? 'approver' : 'reviewer';
const files = [this.file];
this._dialogService.openDialog('assignFile', $event, { mode, files }, () => {
this.actionPerformed.emit('assign-reviewer');
});
@ -150,7 +148,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
async assignToMe($event: MouseEvent) {
$event.stopPropagation();
await this._fileActionService.assignToMe(this.fileStatus, () => {
await this._fileActionService.assignToMe([this.file], () => {
this.reloadDossiers('reanalyse');
});
}
@ -159,7 +157,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
if ($event) {
$event.stopPropagation();
}
this.addSubscription = this._fileActionService.reanalyseFile(this.fileStatus).subscribe(() => {
this.addSubscription = this._fileActionService.reanalyseFile(this.file).subscribe(() => {
this.reloadDossiers('reanalyse');
});
}
@ -167,9 +165,9 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
setFileUnderApproval($event: MouseEvent) {
$event.stopPropagation();
if (this.appStateService.activeDossier.approverIds.length > 1) {
this._fileActionService.assignFile('approver', $event, this.fileStatus, () => this.reloadDossiers('assign-reviewer'), true);
this._fileActionService.assignFile('approver', $event, this.file, () => this.reloadDossiers('assign-reviewer'), true);
} else {
this.addSubscription = this._fileActionService.setFileUnderApproval(this.fileStatus).subscribe(() => {
this.addSubscription = this._fileActionService.setFilesUnderApproval([this.file]).subscribe(() => {
this.reloadDossiers('set-under-approval');
});
}
@ -177,7 +175,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
setFileApproved($event: MouseEvent) {
$event.stopPropagation();
if (this.fileStatus.hasUpdates) {
if (this.file.hasUpdates) {
this._dialogService.openDialog(
'confirm',
$event,
@ -196,7 +194,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
ocrFile($event: MouseEvent) {
$event.stopPropagation();
this.addSubscription = this._fileActionService.ocrFile(this.fileStatus).subscribe(() => {
this.addSubscription = this._fileActionService.ocrFiles([this.file]).subscribe(() => {
this.reloadDossiers('ocr-file');
});
}
@ -205,7 +203,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
this._fileActionService.assignFile(
'reviewer',
$event,
this.fileStatus,
this.file,
() => this.reloadDossiers('assign-reviewer'),
ignoreDialogChanges
);
@ -218,9 +216,9 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
}
async toggleAnalysis() {
await this._fileActionService.toggleAnalysis(this.fileStatus).toPromise();
await this._fileActionService.toggleAnalysis(this.file).toPromise();
await this.appStateService.getFiles();
this.actionPerformed.emit(this.fileStatus?.excluded ? 'enable-analysis' : 'disable-analysis');
this.actionPerformed.emit(this.file?.excluded ? 'enable-analysis' : 'disable-analysis');
}
ngOnChanges(changes: SimpleChanges): void {
@ -231,12 +229,12 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
forceReanalysisAction($event: LongPressEvent) {
if (this._userPreferenceService.areDevFeaturesEnabled) {
this.canReanalyse = $event.touchEnd ? this.permissionsService.canReanalyseFile(this.fileStatus) : true;
this.canReanalyse = $event.touchEnd ? this.permissionsService.canReanalyseFile(this.file) : true;
}
}
private _setFileApproved() {
this.addSubscription = this._fileActionService.setFileApproved(this.fileStatus).subscribe(() => {
this.addSubscription = this._fileActionService.setFilesApproved([this.file]).subscribe(() => {
this.reloadDossiers('set-approved');
});
}

View File

@ -93,7 +93,7 @@
</div>
<div
(click)="scrollQuickNavLast()"
[class.disabled]="activeViewerPage === fileData?.fileStatus?.numberOfPages"
[class.disabled]="activeViewerPage === fileData?.file?.numberOfPages"
[matTooltip]="'file-preview.quick-nav.jump-last' | translate"
class="jump"
matTooltipPosition="above"
@ -141,7 +141,7 @@
[verticalPadding]="40"
icon="red:document"
>
<ng-container *ngIf="fileData?.fileStatus?.excludedPages?.includes(activeViewerPage)">
<ng-container *ngIf="fileData?.file?.excludedPages?.includes(activeViewerPage)">
{{ 'file-preview.tabs.annotations.page-is' | translate }}
<a
(click)="actionPerformed.emit('view-exclude-pages')"
@ -171,15 +171,15 @@
</ng-container>
<redaction-annotations-list
[canMultiSelect]="!isReadOnly"
[annotations]="(displayedAnnotations$ | async)?.get(activeViewerPage)"
[selectedAnnotations]="selectedAnnotations"
[annotationActionsTemplate]="annotationActionsTemplate"
[(multiSelectActive)]="multiSelectActive"
[activeViewerPage]="activeViewerPage"
(deselectAnnotations)="deselectAnnotations.emit($event)"
(pagesPanelActive)="pagesPanelActive = $event"
(selectAnnotations)="selectAnnotations.emit($event)"
(deselectAnnotations)="deselectAnnotations.emit($event)"
[(multiSelectActive)]="multiSelectActive"
[activeViewerPage]="activeViewerPage"
[annotationActionsTemplate]="annotationActionsTemplate"
[annotations]="(displayedAnnotations$ | async)?.get(activeViewerPage)"
[canMultiSelect]="!isReadOnly"
[selectedAnnotations]="selectedAnnotations"
></redaction-annotations-list>
</div>
</ng-container>
@ -187,7 +187,7 @@
<redaction-page-exclusion
(actionPerformed)="actionPerformed.emit($event)"
*ngIf="excludePages"
[fileStatus]="fileData.fileStatus"
[file]="fileData.file"
></redaction-page-exclusion>
</div>
</div>

View File

@ -43,8 +43,10 @@ export class FileWorkloadComponent {
@Output() readonly actionPerformed = new EventEmitter<string>();
displayedPages: number[] = [];
pagesPanelActive = true;
readonly displayedAnnotations$ = this._displayedAnnotations$;
@ViewChild('annotationsElement') private readonly _annotationsElement: ElementRef;
@ViewChild('quickNavigation') private readonly _quickNavigationElement: ElementRef;
private _annotations$ = new BehaviorSubject<AnnotationWrapper[]>([]);
constructor(
private readonly _permissionsService: PermissionsService,
@ -53,9 +55,6 @@ export class FileWorkloadComponent {
private readonly _annotationProcessingService: AnnotationProcessingService
) {}
private _annotations$ = new BehaviorSubject<AnnotationWrapper[]>([]);
readonly displayedAnnotations$ = this._displayedAnnotations$;
@Input()
set annotations(value: AnnotationWrapper[]) {
this._annotations$.next(value);
@ -78,7 +77,7 @@ export class FileWorkloadComponent {
}
get isProcessing(): boolean {
return this.fileData?.fileStatus?.isProcessing;
return this.fileData?.file?.isProcessing;
}
get activeAnnotations(): AnnotationWrapper[] | undefined {
@ -93,6 +92,14 @@ export class FileWorkloadComponent {
return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null;
}
private get _displayedAnnotations$(): Observable<Map<number, AnnotationWrapper[]>> {
const primary$ = this._filterService.getFilterModels$('primaryFilters');
const secondary$ = this._filterService.getFilterModels$('secondaryFilters');
return combineLatest([this._annotations$, primary$, secondary$]).pipe(
map(([annotations, primary, secondary]) => this._filterAnnotations(annotations, primary, secondary))
);
}
private static _scrollToFirstElement(elements: HTMLElement[], mode: 'always' | 'if-needed' = 'if-needed') {
if (elements.length > 0) {
scrollIntoView(elements[0], {
@ -120,19 +127,6 @@ export class FileWorkloadComponent {
this.deselectAnnotations.emit(this.activeAnnotations);
}
private _filterAnnotations(
annotations: AnnotationWrapper[],
primary: INestedFilter[],
secondary: INestedFilter[] = []
): Map<number, AnnotationWrapper[]> {
if (!primary) {
return;
}
this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary);
this.displayedPages = [...this.displayedAnnotations.keys()];
return this.displayedAnnotations;
}
@HostListener('window:keyup', ['$event'])
handleKeyEvent($event: KeyboardEvent): void {
if (
@ -210,7 +204,7 @@ export class FileWorkloadComponent {
}
scrollQuickNavLast(): void {
this.selectPage.emit(this.fileData.fileStatus.numberOfPages);
this.selectPage.emit(this.fileData.file.numberOfPages);
}
pageSelectedByClick($event: number): void {
@ -232,12 +226,17 @@ export class FileWorkloadComponent {
this.selectPage.emit(this._nextPageWithAnnotations());
}
private get _displayedAnnotations$(): Observable<Map<number, AnnotationWrapper[]>> {
const primary$ = this._filterService.getFilterModels$('primaryFilters');
const secondary$ = this._filterService.getFilterModels$('secondaryFilters');
return combineLatest([this._annotations$, primary$, secondary$]).pipe(
map(([annotations, primary, secondary]) => this._filterAnnotations(annotations, primary, secondary))
);
private _filterAnnotations(
annotations: AnnotationWrapper[],
primary: INestedFilter[],
secondary: INestedFilter[] = []
): Map<number, AnnotationWrapper[]> {
if (!primary) {
return;
}
this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary);
this.displayedPages = [...this.displayedAnnotations.keys()];
return this.displayedAnnotations;
}
private _selectFirstAnnotationOnCurrentPageIfNecessary() {

View File

@ -1,6 +1,6 @@
import { Component, Input } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { Dossier } from '../../../../state/model/dossier';
@Component({
@ -9,7 +9,7 @@ import { Dossier } from '../../../../state/model/dossier';
styleUrls: ['./needs-work-badge.component.scss']
})
export class NeedsWorkBadgeComponent {
@Input() needsWorkInput: FileStatusWrapper | Dossier;
@Input() needsWorkInput: File | Dossier;
constructor(private readonly _appStateService: AppStateService) {}
@ -38,15 +38,15 @@ export class NeedsWorkBadgeComponent {
}
get hasImages() {
return this.needsWorkInput instanceof FileStatusWrapper && this.needsWorkInput.hasImages;
return this.needsWorkInput instanceof File && this.needsWorkInput.hasImages;
}
get hasUpdates() {
return this.needsWorkInput instanceof FileStatusWrapper && this.needsWorkInput.hasUpdates;
return this.needsWorkInput instanceof File && this.needsWorkInput.hasUpdates;
}
get hasAnnotationComments(): boolean {
return this.needsWorkInput instanceof FileStatusWrapper && (<any>this.needsWorkInput).hasAnnotationComments;
return this.needsWorkInput instanceof File && (<any>this.needsWorkInput).hasAnnotationComments;
}
reanalysisRequired() {

View File

@ -1,9 +1,9 @@
import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { PageRange, ReanalysisControllerService } from '@redaction/red-ui-http';
import { InputWithActionComponent, Toaster, LoadingService } from '@iqser/common-ui';
import { InputWithActionComponent, LoadingService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
@Component({
selector: 'redaction-page-exclusion',
@ -11,7 +11,7 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
styleUrls: ['./page-exclusion.component.scss']
})
export class PageExclusionComponent implements OnChanges {
@Input() fileStatus: FileStatusWrapper;
@Input() file: File;
@Output() readonly actionPerformed = new EventEmitter<string>();
excludedPagesRanges: PageRange[] = [];
@ -25,7 +25,7 @@ export class PageExclusionComponent implements OnChanges {
) {}
ngOnChanges(): void {
const excludedPages = (this.fileStatus?.excludedPages || []).sort((p1, p2) => p1 - p2);
const excludedPages = (this.file?.excludedPages || []).sort((p1, p2) => p1 - p2);
this.excludedPagesRanges = excludedPages.reduce((ranges, page) => {
if (!ranges.length) {
return [{ startPage: page, endPage: page }];
@ -60,8 +60,8 @@ export class PageExclusionComponent implements OnChanges {
{
pageRanges: pageRanges
},
this.fileStatus.dossierId,
this.fileStatus.fileId
this.file.dossierId,
this.file.fileId
)
.toPromise();
this._inputComponent.reset();
@ -79,8 +79,8 @@ export class PageExclusionComponent implements OnChanges {
{
pageRanges: [range]
},
this.fileStatus.dossierId,
this.fileStatus.fileId
this.file.dossierId,
this.file.fileId
)
.toPromise();
this._inputComponent.reset();

View File

@ -1,5 +1,5 @@
<div class="page">
<div #viewer [id]="fileStatus.fileId" class="viewer"></div>
<div #viewer [id]="file.fileId" class="viewer"></div>
</div>
<input #compareFileInput (change)="uploadFile($event.target['files'])" class="file-upload-input" type="file" />

View File

@ -17,7 +17,7 @@ import { TranslateService } from '@ngx-translate/core';
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { ManualAnnotationService } from '../../services/manual-annotation.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { environment } from '@environments/environment';
import { AnnotationDrawService } from '../../services/annotation-draw.service';
import { AnnotationActionsService } from '../../services/annotation-actions.service';
@ -43,18 +43,18 @@ import Annotation = Core.Annotations.Annotation;
})
export class PdfViewerComponent implements OnInit, OnChanges {
@Input() fileData: Blob;
@Input() fileStatus: FileStatusWrapper;
@Input() file: File;
@Input() canPerformActions = false;
@Input() annotations: AnnotationWrapper[];
@Input() shouldDeselectAnnotationsOnPageChange = true;
@Input() multiSelectActive: boolean;
@Output() fileReady = new EventEmitter();
@Output() annotationSelected = new EventEmitter<string[]>();
@Output() manualAnnotationRequested = new EventEmitter<ManualRedactionEntryWrapper>();
@Output() pageChanged = new EventEmitter<number>();
@Output() keyUp = new EventEmitter<KeyboardEvent>();
@Output() viewerReady = new EventEmitter<WebViewerInstance>();
@Output() annotationsChanged = new EventEmitter<AnnotationWrapper>();
@Output() readonly fileReady = new EventEmitter();
@Output() readonly annotationSelected = new EventEmitter<string[]>();
@Output() readonly manualAnnotationRequested = new EventEmitter<ManualRedactionEntryWrapper>();
@Output() readonly pageChanged = new EventEmitter<number>();
@Output() readonly keyUp = new EventEmitter<KeyboardEvent>();
@Output() readonly viewerReady = new EventEmitter<WebViewerInstance>();
@Output() readonly annotationsChanged = new EventEmitter<AnnotationWrapper>();
@ViewChild('viewer', { static: true }) viewer: ElementRef;
@ViewChild('compareFileInput', { static: true }) compareFileInput: ElementRef;
instance: WebViewerInstance;
@ -146,7 +146,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
compareDocument,
mergedDocument,
this.instance,
this.fileStatus,
this.file,
() => {
this.viewMode = 'COMPARE';
},
@ -188,7 +188,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null);
const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.fileData.arrayBuffer());
this.instance.UI.loadDocument(currentDocument, {
filename: this.fileStatus ? this.fileStatus.filename : 'document.pdf'
filename: this.file ? this.file.filename : 'document.pdf'
});
this.instance.UI.disableElements(['closeCompareButton']);
this.instance.UI.enableElements(['compareButton']);
@ -571,7 +571,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
private _loadDocument() {
if (this.fileData) {
this.instance.UI.loadDocument(this.fileData, {
filename: this.fileStatus ? this.fileStatus.filename : 'document.pdf'
filename: this.file ? this.file.filename : 'document.pdf'
});
}
}

View File

@ -5,14 +5,14 @@ import { AppStateService } from '@state/app-state.service';
import { UserService } from '@services/user.service';
import { Toaster } from '@iqser/common-ui';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { Dossier } from '../../../../state/model/dossier';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
class DialogData {
mode: 'approver' | 'reviewer';
dossier?: Dossier;
files?: FileStatusWrapper[];
files?: File[];
ignoreChanged?: boolean;
}

View File

@ -1,9 +1,9 @@
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { FileAttributesControllerService, FileStatus, IFileAttributeConfig } from '@redaction/red-ui-http';
import { FileAttributesControllerService, IFile, IFileAttributeConfig } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Dossier } from '../../../../state/model/dossier';
import { Dossier } from '@state/model/dossier';
@Component({
templateUrl: './document-info-dialog.component.html',
@ -11,7 +11,7 @@ import { Dossier } from '../../../../state/model/dossier';
})
export class DocumentInfoDialogComponent implements OnInit {
documentInfoForm: FormGroup;
file: FileStatus;
file: IFile;
attributes: IFileAttributeConfig[];
private _dossier: Dossier;
@ -21,7 +21,7 @@ export class DocumentInfoDialogComponent implements OnInit {
private readonly _formBuilder: FormBuilder,
private readonly _fileAttributesService: FileAttributesControllerService,
public dialogRef: MatDialogRef<DocumentInfoDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: FileStatus
@Inject(MAT_DIALOG_DATA) public data: IFile
) {
this.file = this.data;
this._dossier = this._appStateService.getDossierById(this.file.dossierId);

View File

@ -10,7 +10,7 @@ import {
SortingOrders,
TableColumnConfig
} from '@iqser/common-ui';
import { FileManagementControllerService, FileStatus, StatusControllerService } from '@redaction/red-ui-http';
import { FileManagementControllerService, IFile, StatusControllerService } from '@redaction/red-ui-http';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import * as moment from 'moment';
import { ConfigService } from '@services/config.service';
@ -21,7 +21,7 @@ import { ConfirmationDialogInput, TitleColors } from '@shared/dialogs/confirmati
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import { AppStateService } from '@state/app-state.service';
interface FileListItem extends FileStatus, IListable {
interface FileListItem extends IFile, IListable {
readonly canRestore: boolean;
readonly restoreDate: string;
}
@ -156,11 +156,11 @@ export class EditDossierDeletedDocumentsComponent extends ListingComponent<FileL
this.entitiesService.setSelected([]);
}
private _toListItems(files: FileStatus[]): FileListItem[] {
private _toListItems(files: IFile[]): FileListItem[] {
return files.map(file => this._toListItem(file));
}
private _toListItem(file: FileStatus): FileListItem {
private _toListItem(file: IFile): FileListItem {
const restoreDate = this._getRestoreDate(file.softDeleted);
return {
id: file.fileId,

View File

@ -91,7 +91,7 @@
<redaction-dossier-overview-bulk-actions (reload)="bulkActionPerformed()"></redaction-dossier-overview-bulk-actions>
</ng-template>
<ng-template #filenameTemplate let-fileStatus="entity">
<ng-template #filenameTemplate let-file="entity">
<div class="cell">
<div>
<div [class.error]="fileStatus.isError" [matTooltip]="fileStatus.filename" class="table-item-title" matTooltipPosition="above">
@ -109,71 +109,71 @@
</div>
</ng-template>
<ng-template #addedOnTemplate let-fileStatus="entity">
<ng-template #addedOnTemplate let-file="entity">
<div class="cell">
<div [class.error]="fileStatus.isError" class="small-label">
{{ fileStatus.added | date: 'd MMM. yyyy, hh:mm a' }}
<div [class.error]="file.isError" class="small-label">
{{ file.added | date: 'd MMM. yyyy, hh:mm a' }}
</div>
</div>
</ng-template>
<ng-template #attributeTemplate let-config="extra" let-fileStatus="entity">
<ng-template #attributeTemplate let-config="extra" let-file="entity">
<div class="cell">
{{ fileStatus.fileAttributes.attributeIdToValue[config.id] }}
{{ file.fileAttributes.attributeIdToValue[config.id] }}
</div>
</ng-template>
<ng-template #needsWorkTemplate let-fileStatus="entity">
<ng-template #needsWorkTemplate let-file="entity">
<!-- always show A for error-->
<div *ngIf="fileStatus.isError" class="cell">
<div *ngIf="file.isError" class="cell">
<redaction-annotation-icon color="#dd4d50" label="A" type="square"></redaction-annotation-icon>
</div>
<div *ngIf="!fileStatus.isError" class="cell">
<redaction-needs-work-badge [needsWorkInput]="fileStatus"></redaction-needs-work-badge>
<div *ngIf="!file.isError" class="cell">
<redaction-needs-work-badge [needsWorkInput]="file"></redaction-needs-work-badge>
</div>
</ng-template>
<ng-template #reviewerTemplate let-fileStatus="entity">
<div *ngIf="!fileStatus.isError" class="user-column cell">
<redaction-initials-avatar [userId]="fileStatus.currentReviewer" [withName]="true"></redaction-initials-avatar>
<ng-template #reviewerTemplate let-file="entity">
<div *ngIf="!file.isError" class="user-column cell">
<redaction-initials-avatar [userId]="file.currentReviewer" [withName]="true"></redaction-initials-avatar>
</div>
</ng-template>
<ng-template #pagesTemplate let-fileStatus="entity">
<div *ngIf="!fileStatus.isError" class="cell">
<ng-template #pagesTemplate let-file="entity">
<div *ngIf="!file.isError" class="cell">
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:pages"></mat-icon>
{{ fileStatus.numberOfPages }}
{{ file.numberOfPages }}
</div>
</div>
</div>
</ng-template>
<ng-template #statusTemplate let-fileStatus="entity">
<div [class.extend-cols]="fileStatus.isError" class="status-container cell">
<div *ngIf="fileStatus.isError" class="small-label error" translate="dossier-overview.file-listing.file-entry.file-error"></div>
<div *ngIf="fileStatus.isPending" class="small-label" translate="dossier-overview.file-listing.file-entry.file-pending"></div>
<ng-template #statusTemplate let-file="entity">
<div [class.extend-cols]="file.isError" class="status-container cell">
<div *ngIf="file.isError" class="small-label error" translate="dossier-overview.file-listing.file-entry.file-error"></div>
<div *ngIf="file.isPending" class="small-label" translate="dossier-overview.file-listing.file-entry.file-pending"></div>
<div
*ngIf="fileStatus.isProcessing"
*ngIf="file.isProcessing"
class="small-label loading"
translate="dossier-overview.file-listing.file-entry.file-processing"
></div>
<iqser-status-bar
*ngIf="fileStatus.isWorkable"
*ngIf="file.isWorkable"
[configs]="[
{
color: fileStatus.status,
color: file.status,
length: 1
}
]"
></iqser-status-bar>
<redaction-file-actions
(actionPerformed)="actionPerformed()"
*ngIf="!fileStatus.isProcessing"
[fileStatus]="fileStatus"
(actionPerformed)="calculateData()"
*ngIf="!file.isProcessing"
[file]="file"
class="mr-4"
type="dossier-overview-list"
></redaction-file-actions>

View File

@ -19,13 +19,13 @@ import { StatusOverlayService } from '@upload-download/services/status-overlay.s
import { TranslateService } from '@ngx-translate/core';
import * as moment from 'moment';
import { DossierDetailsComponent } from '../../components/dossier-details/dossier-details.component';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { UserService } from '@services/user.service';
import { timer } from 'rxjs';
import { tap } from 'rxjs/operators';
import { RedactionFilterSorter } from '@utils/sorters/redaction-filter-sorter';
import { StatusSorter } from '@utils/sorters/status-sorter';
import { convertFiles, handleFileDrop } from '@utils/file-drop-utils';
import { convertFiles, Files, handleFileDrop } from '@utils/file-drop-utils';
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy';
import { ConfigService } from '@services/config.service';
@ -63,7 +63,7 @@ import StatusEnum = FileStatus.StatusEnum;
styleUrls: ['./dossier-overview-screen.component.scss'],
providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DossierOverviewScreenComponent) }]
})
export class DossierOverviewScreenComponent extends ListingComponent<FileStatusWrapper> implements OnInit, OnDestroy, OnDetach, OnAttach {
export class DossierOverviewScreenComponent extends ListingComponent<File> implements OnInit, OnDestroy, OnDetach, OnAttach {
readonly listingModes = ListingModes;
readonly circleButtonTypes = CircleButtonTypes;
readonly currentUser = this._userService.currentUser;
@ -77,7 +77,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
hide: !this.currentUser.isManager
}
];
tableColumnConfigs: readonly TableColumnConfig<FileStatusWrapper>[] = [];
tableColumnConfigs: readonly TableColumnConfig<File>[] = [];
collapsedDetails = false;
dossierAttributes: DossierAttributeWithValue[] = [];
fileAttributeConfigs: IFileAttributeConfig[];
@ -303,7 +303,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
event.preventDefault();
}
async uploadFiles(files: File[] | FileList): Promise<void> {
async uploadFiles(files: Files): Promise<void> {
await this._uploadFiles(convertFiles(files, this.currentDossier));
this._fileInput.nativeElement.value = null;
}
@ -335,11 +335,11 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
this.collapsedDetails = !this.collapsedDetails;
}
recentlyModifiedChecker = (file: FileStatusWrapper) =>
recentlyModifiedChecker = (file: File) =>
moment(file.lastUpdated).add(this._configService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment());
private _configureTableColumns() {
const dynamicColumns: TableColumnConfig<FileStatusWrapper>[] = [];
const dynamicColumns: TableColumnConfig<File>[] = [];
for (const config of this.displayedInFileListAttributes) {
if (config.displayedInFileList) {
dynamicColumns.push({ label: config.label, notTranslatable: true, template: this.attributeTemplate, extra: config });
@ -372,7 +372,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
},
{
label: _('dossier-overview.table-col-names.pages'),
sortByKey: 'pages',
sortByKey: 'numberOfPages',
template: this.pagesTemplate
},
{
@ -534,14 +534,14 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
label: value === '-' ? this._translateService.instant('filters.empty') : value
})
),
checker: (input: FileStatusWrapper, filter: INestedFilter) => filter.id === input.fileAttributes.attributeIdToValue[id]
checker: (input: File, filter: INestedFilter) => filter.id === input.fileAttributes.attributeIdToValue[id]
});
});
this.filterService.addFilterGroup({
slug: 'quickFilters',
filters: this._createQuickFilters(),
checker: (file: FileStatusWrapper) =>
checker: (file: File) =>
this.checkedRequiredFilters.reduce((acc, f) => acc && f.checker(file), true) &&
(this.checkedNotRequiredFilters.length === 0 ||
this.checkedNotRequiredFilters.reduce((acc, f) => acc || f.checker(file), false))
@ -586,17 +586,17 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
{
id: 'assigned-to-me',
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-me'),
checker: (file: FileStatusWrapper) => file.currentReviewer === this.currentUser.id
checker: (file: File) => file.currentReviewer === this.currentUser.id
},
{
id: 'unassigned',
label: this._translateService.instant('dossier-overview.quick-filters.unassigned'),
checker: (file: FileStatusWrapper) => !file.currentReviewer
checker: (file: File) => !file.currentReviewer
},
{
id: 'assigned-to-others',
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-others'),
checker: (file: FileStatusWrapper) => !!file.currentReviewer && file.currentReviewer !== this.currentUser.id
checker: (file: File) => !!file.currentReviewer && file.currentReviewer !== this.currentUser.id
}
].map(filter => new NestedFilter(filter));
}

View File

@ -142,7 +142,7 @@
[annotations]="annotations"
[canPerformActions]="canPerformAnnotationActions"
[fileData]="displayData"
[fileStatus]="appStateService.activeFile"
[file]="appStateService.activeFile"
[multiSelectActive]="multiSelectActive"
[shouldDeselectAnnotationsOnPageChange]="shouldDeselectAnnotationsOnPageChange"
></redaction-pdf-viewer>
@ -159,7 +159,7 @@
<redaction-document-info
(closeDocumentInfoView)="viewDocumentInfo = false"
*ngIf="viewDocumentInfo"
[file]="fileData.fileStatus"
[file]="fileData.file"
></redaction-document-info>
<redaction-file-workload

View File

@ -21,7 +21,7 @@ import { AnnotationData, FileDataModel } from '@models/file/file-data.model';
import { FileActionService } from '../../services/file-action.service';
import { AnnotationDrawService } from '../../services/annotation-draw.service';
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { PermissionsService } from '@services/permissions.service';
import { timer } from 'rxjs';
import { UserPreferenceService } from '@services/user-preference.service';
@ -73,6 +73,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
viewDocumentInfo = false;
excludePages = false;
@ViewChild(PdfViewerComponent) readonly viewerComponent: PdfViewerComponent;
@ViewChild('fileActions') fileActions: FileActionsComponent;
private _instance: WebViewerInstance;
private _lastPage: string;
private _reloadFileOnReanalysis = false;
@ -82,7 +83,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
static: true
})
private readonly _filterTemplate: TemplateRef<INestedFilter>;
@ViewChild('fileActions') fileActions: FileActionsComponent;
constructor(
readonly appStateService: AppStateService,
@ -148,11 +148,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
get canSwitchToRedactedView(): boolean {
return this.fileData && !this.fileData.fileStatus.analysisRequired && !this.fileData.fileStatus.excluded;
return this.fileData && !this.fileData.file.analysisRequired && !this.fileData.file.excluded;
}
get canSwitchToDeltaView(): boolean {
return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.fileStatus.excluded;
return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.file.excluded;
}
get canAssign(): boolean {
@ -176,7 +176,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
get lastReviewer(): string | undefined {
return this.appStateService.activeFile.fileStatus.lastReviewer;
return this.appStateService.activeFile.lastReviewer;
}
get assignOrChangeReviewerTooltip(): string {
@ -189,11 +189,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
return this.appStateService.activeFile.currentReviewer;
}
get status(): FileStatus.StatusEnum {
get status(): FileStatus {
return this.appStateService.activeFile.status;
}
get statusBarConfig(): [{ length: number; color: FileStatus.StatusEnum }] {
get statusBarConfig(): [{ length: number; color: FileStatus }] {
return [{ length: 1, color: this.status }];
}
@ -261,7 +261,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
this._updateCanPerformActions();
this._subscribeToFileUpdates();
if (this.fileData?.fileStatus?.analysisRequired) {
if (this.fileData?.file?.analysisRequired) {
this.fileActions.reanalyseFile();
}
}
@ -355,7 +355,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
response.manualRedactionEntryWrapper.rectId
);
this._instance.Core.annotationManager.deleteAnnotation(annotation);
this.fileData.fileStatus = await this.appStateService.reloadActiveFile();
this.fileData.file = await this.appStateService.reloadActiveFile();
const distinctPages = entryWrapper.manualRedactionEntry.positions
.map(p => p.page)
.filter((item, pos, self) => self.indexOf(item) === pos);
@ -490,7 +490,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
async assignToMe() {
await this._fileActionService.assignToMe(this.fileData.fileStatus, async () => {
await this._fileActionService.assignToMe([this.fileData.file], async () => {
await this.appStateService.reloadActiveFile();
this._updateCanPerformActions();
});
@ -500,7 +500,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
const reviewerId = typeof user === 'string' ? user : user.id;
const reviewerName = this.userService.getNameForId(reviewerId);
const { dossierId, fileId, filename } = this.fileData.fileStatus;
const { dossierId, fileId, filename } = this.fileData.file;
await this._statusControllerService.setFileReviewer(dossierId, fileId, reviewerId).toPromise();
this._toaster.info(_('assignment.reviewer'), { params: { reviewerName, filename } });
@ -523,9 +523,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
downloadOriginalFile() {
this.addSubscription = this._fileManagementControllerService
.downloadOriginalFile(this.dossierId, this.fileId, true, this.fileData.fileStatus.cacheIdentifier, 'response')
.downloadOriginalFile(this.dossierId, this.fileId, true, this.fileData.file.cacheIdentifier, 'response')
.subscribe(data => {
download(data, this.fileData.fileStatus.filename);
download(data, this.fileData.file.filename);
});
}
@ -561,7 +561,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
if (excludedPages && excludedPages.length > 0) {
const pdfNet = this._instance.Core.PDFNet;
const document = await this._instance.Core.documentViewer.getDocument().getPDFDoc();
await clearStamps(document, pdfNet, [...Array(this.fileData.fileStatus.numberOfPages).keys()]);
await clearStamps(document, pdfNet, [...Array(this.fileData.file.numberOfPages).keys()]);
await stampPDFPage(
document,
pdfNet,
@ -577,7 +577,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
private async _stampExcludedPages() {
await this._doStampExcludedPages(this.fileData.fileStatus.excludedPages);
await this._doStampExcludedPages(this.fileData.file.excludedPages);
this._instance.Core.documentViewer.refreshAll();
this._instance.Core.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage);
this._changeDetectorRef.detectChanges();
@ -585,8 +585,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
private _subscribeToFileUpdates(): void {
this.addSubscription = timer(0, 5000).subscribe(async () => await this.appStateService.reloadActiveFile());
this.addSubscription = this.appStateService.fileReanalysed$.subscribe(async (fileStatus: FileStatusWrapper) => {
if (fileStatus.fileId === this.fileId) {
this.addSubscription = this.appStateService.fileReanalysed$.subscribe(async (file: File) => {
if (file.fileId === this.fileId) {
await this._loadFileData(!this._reloadFileOnReanalysis);
this._reloadFileOnReanalysis = false;
this._loadingService.stop();
@ -606,11 +606,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
private async _loadFileData(performUpdate = false): Promise<void> {
const fileData = await this._fileDownloadService.loadActiveFileData().toPromise();
if (!fileData.fileStatus?.isPending && !fileData.fileStatus?.isError) {
if (!fileData.file?.isPending && !fileData.file?.isError) {
if (performUpdate) {
this.fileData.redactionLog = fileData.redactionLog;
this.fileData.redactionChangeLog = fileData.redactionChangeLog;
this.fileData.fileStatus = fileData.fileStatus;
this.fileData.file = fileData.file;
this.rebuildFilters(true);
} else {
this.fileData = fileData;
@ -620,7 +620,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
return;
}
if (fileData.fileStatus.isError) {
if (fileData.file.isError) {
await this._router.navigate(['/main/dossiers/' + this.dossierId]);
}
}
@ -648,7 +648,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
private async _cleanupAndRedrawManualAnnotationsForEntirePage(page: number) {
const currentPageAnnotations = this.annotations.filter(a => a.pageNumber === page);
const currentPageAnnotationIds = currentPageAnnotations.map(a => a.id);
this.fileData.fileStatus = await this.appStateService.reloadActiveFile();
this.fileData.file = await this.appStateService.reloadActiveFile();
this._fileDownloadService.loadActiveFileRedactionLog().subscribe(redactionLogPreview => {
this.fileData.redactionLog = redactionLogPreview;

View File

@ -2,9 +2,8 @@ import { Injectable } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { UserService } from '@services/user.service';
import { ReanalysisControllerService, StatusControllerService } from '@redaction/red-ui-http';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { PermissionsService } from '@services/permissions.service';
import { isArray } from 'rxjs/internal-compatibility';
import { DossiersDialogService } from './dossiers-dialog.service';
import { ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@ -21,108 +20,87 @@ export class FileActionService {
private readonly _appStateService: AppStateService
) {}
reanalyseFile(fileStatusWrapper?: FileStatusWrapper) {
if (!fileStatusWrapper) {
fileStatusWrapper = this._appStateService.activeFile;
}
return this._reanalysisControllerService.reanalyzeFile(this._appStateService.activeDossier.id, fileStatusWrapper.fileId, true);
reanalyseFile(file = this._appStateService.activeFile) {
return this._reanalysisControllerService.reanalyzeFile(this._appStateService.activeDossier.id, file.fileId, true);
}
toggleAnalysis(fileStatusWrapper?: FileStatusWrapper) {
if (!fileStatusWrapper) {
fileStatusWrapper = this._appStateService.activeFile;
}
return this._reanalysisControllerService.toggleAnalysis(
fileStatusWrapper.dossierId,
fileStatusWrapper.fileId,
!fileStatusWrapper.excluded
);
toggleAnalysis(file = this._appStateService.activeFile) {
return this._reanalysisControllerService.toggleAnalysis(file.dossierId, file.fileId, !file.excluded);
}
async assignToMe(fileStatus?: FileStatusWrapper | FileStatusWrapper[], callback?: Function) {
async assignToMe(files?: File[], callback?: Function) {
return new Promise<void>((resolve, reject) => {
if (!isArray(fileStatus)) {
fileStatus = [fileStatus];
}
const atLeastOneFileHasReviewer = fileStatus.reduce((acc, fs) => acc || !!fs.currentReviewer, false);
const atLeastOneFileHasReviewer = files.reduce((acc, fs) => acc || !!fs.currentReviewer, false);
if (atLeastOneFileHasReviewer) {
const data = new ConfirmationDialogInput({
title: _('confirmation-dialog.assign-file-to-me.title'),
question: _('confirmation-dialog.assign-file-to-me.question')
});
this._dialogService.openDialog('confirm', null, data, () => {
this._assignReviewerToCurrentUser(fileStatus, callback)
this._assignReviewerToCurrentUser(files, callback)
.then(() => resolve())
.catch(() => reject());
});
} else {
this._assignReviewerToCurrentUser(fileStatus, callback)
this._assignReviewerToCurrentUser(files, callback)
.then(() => resolve())
.catch(() => reject());
}
});
}
setFileUnderApproval(fileStatus: FileStatusWrapper | FileStatusWrapper[], approverId?: string) {
if (!isArray(fileStatus)) {
fileStatus = [fileStatus];
}
setFilesUnderApproval(files: File[], approverId?: string) {
if (!approverId) {
approverId = this._appStateService.activeDossier.approverIds[0];
}
return this._statusControllerService.setStatusUnderApprovalForList(
fileStatus.map(f => f.fileId),
files.map(f => f.fileId),
approverId,
this._appStateService.activeDossierId
);
}
setFileApproved(fileStatus: FileStatusWrapper | FileStatusWrapper[]): Observable<any> {
if (!isArray(fileStatus)) {
fileStatus = [fileStatus];
}
setFilesApproved(files: File[]) {
return this._statusControllerService.setStatusApprovedForList(
fileStatus.map(f => f.fileId),
files.map(f => f.fileId),
this._appStateService.activeDossierId
);
}
setFileUnderReview(fileStatus: FileStatusWrapper | FileStatusWrapper[]) {
if (!isArray(fileStatus)) {
fileStatus = [fileStatus];
}
setFilesUnderReview(files: File[]) {
return this._statusControllerService.setStatusUnderReviewForList(
fileStatus.map(f => f.fileId),
files.map(f => f.fileId),
this._appStateService.activeDossierId
);
}
ocrFile(fileStatus: FileStatusWrapper | FileStatusWrapper[]) {
if (!isArray(fileStatus)) {
fileStatus = [fileStatus];
}
ocrFiles(files: File[]) {
return this._reanalysisControllerService.ocrFiles(
fileStatus.map(f => f.fileId),
files.map(f => f.fileId),
this._appStateService.activeDossierId
);
}
assignFile(mode: 'reviewer' | 'approver', $event: MouseEvent, file?: FileStatusWrapper, callback?: Function, ignoreChanged = false) {
const files = file ? [file] : [this._appStateService.activeFile];
const data = { mode, files, ignoreChanged };
this._dialogService.openDialog('assignFile', $event, data, callback);
assignFile(
mode: 'reviewer' | 'approver',
$event: MouseEvent,
file = this._appStateService.activeFile,
callback?: Function,
ignoreChanged = false
) {
const data = { mode, files: [file], ignoreChanged };
this._dialogService.openDialog('assignFile', $event, data, async () => {
if (callback) {
callback();
}
});
}
private async _assignReviewerToCurrentUser(fileStatus: FileStatusWrapper | FileStatusWrapper[], callback?: Function) {
if (!isArray(fileStatus)) {
fileStatus = [fileStatus];
}
private async _assignReviewerToCurrentUser(files: File[], callback?: Function) {
await this._statusControllerService
.setFileReviewerForList(
fileStatus.map(f => f.fileId),
files.map(f => f.fileId),
this._appStateService.activeDossierId,
this._userService.currentUser.id
)

View File

@ -10,7 +10,7 @@ import {
import { FileDataModel } from '@models/file/file-data.model';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
@Injectable()
export class PdfViewerDataService {
@ -59,13 +59,7 @@ export class PdfViewerDataService {
return of({ pages: [] });
}
downloadOriginalFile(fileStatus: FileStatusWrapper): Observable<any> {
return this._fileManagementControllerService.downloadOriginalFile(
fileStatus.dossierId,
fileStatus.fileId,
true,
fileStatus.cacheIdentifier,
'body'
);
downloadOriginalFile(file: File): Observable<any> {
return this._fileManagementControllerService.downloadOriginalFile(file.dossierId, file.fileId, true, file.cacheIdentifier, 'body');
}
}

View File

@ -1,7 +1,7 @@
import { FileStatus } from '@redaction/red-ui-http';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
export const fileStatusTranslations: { [key in FileStatus.StatusEnum]: string } = {
export const fileStatusTranslations: { [key in FileStatus]: string } = {
APPROVED: _('file-status.approved'),
DELETED: _('file-status.deleted'),
ERROR: _('file-status.error'),

View File

@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Input, OnDestroy } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { Dossier } from '../../../../../state/model/dossier';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { FileDownloadService } from '@upload-download/services/file-download.service';
import { Toaster } from '@iqser/common-ui';
import { AutoUnsubscribe, CircleButtonType, CircleButtonTypes } from '@iqser/common-ui';
@ -18,7 +18,7 @@ export type MenuState = 'OPEN' | 'CLOSED';
})
export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestroy {
@Input() dossier: Dossier;
@Input() file: FileStatusWrapper | FileStatusWrapper[];
@Input() file: File | File[];
@Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above';
@Input() type: CircleButtonType = CircleButtonTypes.default;
@Input() tooltipClass: string;

View File

@ -4,7 +4,7 @@ import { interval, Observable } from 'rxjs';
import { ConfigService } from '@services/config.service';
import { TranslateService } from '@ngx-translate/core';
import { Dossier } from '@state/model/dossier';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { mergeMap, tap } from 'rxjs/operators';
import { DownloadStatusWrapper } from '../model/download-status.wrapper';
import { AppStateService } from '@state/app-state.service';
@ -34,10 +34,10 @@ export class FileDownloadService {
});
}
downloadFiles(fileStatusWrappers: FileStatusWrapper[], dossier: Dossier): Observable<any> {
downloadFiles(files: File[], dossier: Dossier): Observable<any> {
return this._downloadControllerService
.prepareDownload({
fileIds: fileStatusWrappers.map(f => f.fileId),
fileIds: files.map(f => f.fileId),
dossierId: dossier.id
})
.pipe(mergeMap(() => this.getDownloadStatus()));

View File

@ -1,9 +1,9 @@
import { Injectable } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { UserService } from './user.service';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { Comment } from '@redaction/red-ui-http';
import { Dossier } from '../state/model/dossier';
import { Dossier } from '@state/model/dossier';
@Injectable({
providedIn: 'root'
@ -11,7 +11,7 @@ import { Dossier } from '../state/model/dossier';
export class PermissionsService {
constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService) {}
private get _activeFile(): FileStatusWrapper | undefined {
private get _activeFile(): File | undefined {
return this._appStateService.activeFile;
}
@ -19,42 +19,39 @@ export class PermissionsService {
return this._appStateService.activeDossier;
}
isReviewerOrApprover(fileStatus?: FileStatusWrapper): boolean {
return this.isFileReviewer(fileStatus) || this.isApprover();
isReviewerOrApprover(file?: File): boolean {
return this.isFileReviewer(file) || this.isApprover();
}
displayReanalyseBtn(dossier = this._activeDossier): boolean {
return this.isApprover(dossier) && dossier.files.filter(file => file.analysisRequired).length > 0;
}
canToggleAnalysis(fileStatus: FileStatusWrapper): boolean {
return this.isReviewerOrApprover(fileStatus) && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status);
canToggleAnalysis(file: File): boolean {
return this.isReviewerOrApprover(file) && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status);
}
canReanalyseFile(fileStatus = this._activeFile): boolean {
return (
(fileStatus.analysisRequired && (this.isReviewerOrApprover(fileStatus) || fileStatus.isUnassigned)) ||
(fileStatus.isError && fileStatus.isUnassigned)
);
canReanalyseFile(file = this._activeFile): boolean {
return (file.analysisRequired && (this.isReviewerOrApprover(file) || file.isUnassigned)) || (file.isError && file.isUnassigned);
}
isFileReviewer(fileStatus = this._activeFile): boolean {
return fileStatus.currentReviewer === this._userService.currentUser.id;
isFileReviewer(file = this._activeFile): boolean {
return file.currentReviewer === this._userService.currentUser.id;
}
canDeleteFile(fileStatus = this._activeFile, dossier?: Dossier): boolean {
return (this.isOwner(dossier) && !fileStatus.isApproved) || fileStatus.isUnassigned;
canDeleteFile(file = this._activeFile, dossier?: Dossier): boolean {
return (this.isOwner(dossier) && !file.isApproved) || file.isUnassigned;
}
canAssignToSelf(fileStatus = this._activeFile): boolean {
const precondition = this.isDossierMember() && !fileStatus.isProcessing && !fileStatus.isError && !fileStatus.isApproved;
canAssignToSelf(file = this._activeFile): boolean {
const precondition = this.isDossierMember() && !file.isProcessing && !file.isError && !file.isApproved;
const isTheOnlyReviewer = !this._appStateService.activeDossier?.hasReviewers;
if (precondition) {
if (
(fileStatus.isUnassigned || (fileStatus.isUnderReview && !this.isFileReviewer(fileStatus))) &&
(this.isApprover() || isTheOnlyReviewer || (this.isDossierReviewer() && fileStatus.isUnassigned))
(file.isUnassigned || (file.isUnderReview && !this.isFileReviewer(file))) &&
(this.isApprover() || isTheOnlyReviewer || (this.isDossierReviewer() && file.isUnassigned))
) {
return true;
}
@ -62,30 +59,30 @@ export class PermissionsService {
return false;
}
canAssignUser(fileStatus = this._activeFile): boolean {
const precondition = !fileStatus.isProcessing && !fileStatus.isError && !fileStatus.isApproved && this.isApprover();
canAssignUser(file = this._activeFile): boolean {
const precondition = !file.isProcessing && !file.isError && !file.isApproved && this.isApprover();
if (precondition) {
if ((fileStatus.isUnassigned || fileStatus.isUnderReview) && this._activeDossier.hasReviewers) {
if ((file.isUnassigned || file.isUnderReview) && this._activeDossier.hasReviewers) {
return true;
}
if (fileStatus.isUnderApproval && this._activeDossier.approverIds.length > 1) {
if (file.isUnderApproval && this._activeDossier.approverIds.length > 1) {
return true;
}
}
return false;
}
canSetUnderReview(fileStatus = this._activeFile): boolean {
return fileStatus?.isUnderApproval && this.isApprover();
canSetUnderReview(file = this._activeFile): boolean {
return file?.isUnderApproval && this.isApprover();
}
isReadyForApproval(fileStatus = this._activeFile): boolean {
return this.canSetUnderReview(fileStatus);
isReadyForApproval(file = this._activeFile): boolean {
return this.canSetUnderReview(file);
}
canSetUnderApproval(fileStatus = this._activeFile): boolean {
return fileStatus?.isUnderReview && this.isReviewerOrApprover(fileStatus);
canSetUnderApproval(file = this._activeFile): boolean {
return file?.isUnderReview && this.isReviewerOrApprover(file);
}
isOwner(dossier = this._activeDossier, user = this._userService.currentUser): boolean {
@ -104,25 +101,25 @@ export class PermissionsService {
return dossier?.memberIds.includes(user.id);
}
canPerformAnnotationActions(fileStatus = this._activeFile): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus?.status) && this.isFileReviewer(fileStatus);
canPerformAnnotationActions(file = this._activeFile): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file?.status) && this.isFileReviewer(file);
}
canUndoApproval(fileStatus = this._activeFile): boolean {
return fileStatus?.isApproved && this.isApprover();
canUndoApproval(file = this._activeFile): boolean {
return file?.isApproved && this.isApprover();
}
canMarkPagesAsViewed(fileStatus = this._activeFile): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus?.status) && this.isFileReviewer(fileStatus);
canMarkPagesAsViewed(file = this._activeFile): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file?.status) && this.isFileReviewer(file);
}
canDownloadFiles(fileStatus = this._activeFile): boolean {
const dossier = this._appStateService.getDossierById(fileStatus?.dossierId);
canDownloadFiles(file = this._activeFile): boolean {
const dossier = this._appStateService.getDossierById(file?.dossierId);
if (!dossier) {
return false;
}
return fileStatus.isApproved && this.isApprover(dossier);
return file.isApproved && this.isApprover(dossier);
}
canDeleteDossier(dossier = this._activeDossier): boolean {
@ -133,15 +130,15 @@ export class PermissionsService {
return user.isAdmin;
}
canAddComment(fileStatus = this._activeFile): boolean {
return (this.isFileReviewer(fileStatus) || this.isApprover()) && !fileStatus.isApproved;
canAddComment(file = this._activeFile): boolean {
return (this.isFileReviewer(file) || this.isApprover()) && !file.isApproved;
}
canExcludePages(fileStatus = this._activeFile): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status) && (this.isFileReviewer(fileStatus) || this.isApprover());
canExcludePages(file = this._activeFile): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status) && (this.isFileReviewer(file) || this.isApprover());
}
canDeleteComment(comment: Comment, fileStatus = this._activeFile) {
return (comment.user === this._userService.currentUser.id || this.isApprover()) && !fileStatus.isApproved;
canDeleteComment(comment: Comment, file = this._activeFile) {
return (comment.user === this._userService.currentUser.id || this.isApprover()) && !file.isApproved;
}
}

View File

@ -4,8 +4,8 @@ import {
DossierTemplateControllerService,
FileAttributesConfig,
FileAttributesControllerService,
FileStatus,
IDossier,
IFile,
ReanalysisControllerService,
StatusControllerService
} from '@redaction/red-ui-http';
@ -16,7 +16,7 @@ import { UserService } from '@services/user.service';
import { forkJoin, Observable, of, Subject } from 'rxjs';
import { catchError, map, tap } from 'rxjs/operators';
import { FALLBACK_COLOR, hexToRgb } from '@utils/functions';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { Dossier } from './model/dossier';
import { TypeValue } from '@models/file/type-value';
import { DossierTemplate } from '@models/file/dossier-template';
@ -40,8 +40,8 @@ export interface AppState {
providedIn: 'root'
})
export class AppStateService {
readonly fileChanged$ = new Subject<FileStatusWrapper>();
readonly fileReanalysed$ = new Subject<FileStatusWrapper>();
readonly fileChanged$ = new Subject<File>();
readonly fileReanalysed$ = new Subject<File>();
readonly dossierChanged$ = new Subject<Dossier>();
readonly dossierTemplateChanged$ = new Subject<DossierTemplate>();
@ -91,7 +91,7 @@ export class AppStateService {
return this._dictionaryData;
}
get aggregatedFiles(): FileStatusWrapper[] {
get aggregatedFiles(): File[] {
return this.allDossiers.reduce((acc, { files }) => [...acc, ...files], []);
}
@ -133,7 +133,7 @@ export class AppStateService {
return this.allDossiers?.length > 0;
}
get activeFile(): FileStatusWrapper | undefined {
get activeFile(): File | undefined {
return this.activeDossier?.files.find(f => f.fileId === this.activeFileId);
}
@ -242,7 +242,7 @@ export class AppStateService {
const activeFile = await this._statusControllerService.getFileStatus(this.activeDossierId, this.activeFileId).toPromise();
activeFile.dossierTemplateId = dossierTemplateId;
const activeFileWrapper = new FileStatusWrapper(
const activeFileWrapper = new File(
activeFile,
this._userService.getNameForId(activeFile.currentReviewer),
this.getFileAttributeConfig(activeFile.dossierTemplateId)
@ -659,12 +659,12 @@ export class AppStateService {
await this._userPreferenceService.saveLastOpenedFileForDossier(dossierId, fileId);
}
private _getExistingFiles(dossierId: string): FileStatusWrapper[] {
private _getExistingFiles(dossierId: string): File[] {
const dossier = this.allDossiers.find(p => p.id === dossierId);
return dossier?.files ?? [];
}
private _processFiles(dossier: Dossier, files: FileStatus[], emitEvents: boolean = true) {
private _processFiles(dossier: Dossier, files: IFile[], emitEvents: boolean = true) {
const oldFiles = [...dossier.files];
const fileStatusChangedEvent = [];
@ -677,7 +677,7 @@ export class AppStateService {
for (const oldFile of oldFiles) {
if (oldFile.fileId === file.fileId) {
// emit when analysis count changed
const fileStatusWrapper = new FileStatusWrapper(
const fileStatusWrapper = new File(
file,
this._userService.getNameForId(file.currentReviewer),
this.getFileAttributeConfig(file.dossierTemplateId)
@ -696,7 +696,7 @@ export class AppStateService {
}
// emit for new file
if (!found) {
const fsw = new FileStatusWrapper(
const fsw = new File(
file,
this._userService.getNameForId(file.currentReviewer),
this.getFileAttributeConfig(file.dossierTemplateId)
@ -707,11 +707,7 @@ export class AppStateService {
dossier.files = files.map(
file =>
new FileStatusWrapper(
file,
this._userService.getNameForId(file.currentReviewer),
this.getFileAttributeConfig(file.dossierTemplateId)
)
new File(file, this._userService.getNameForId(file.currentReviewer), this.getFileAttributeConfig(file.dossierTemplateId))
);
this._computeStats();

View File

@ -1,4 +1,4 @@
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { Dictionary, DossierStatus, DownloadFileType, IDossier, List } from '@redaction/red-ui-http';
import { IListable } from '@iqser/common-ui';
@ -36,7 +36,7 @@ export class Dossier implements IDossier, IListable {
allFilesApproved?: boolean;
type?: Dictionary;
constructor(dossier: IDossier, private _files: FileStatusWrapper[] = []) {
constructor(dossier: IDossier, private _files: File[] = []) {
this.id = dossier.dossierId;
this.dossierId = dossier.dossierId;
this.approverIds = dossier.approverIds;
@ -63,11 +63,11 @@ export class Dossier implements IDossier, IListable {
return this.dossierName;
}
get files() {
get files(): File[] {
return this._files;
}
set files(files: FileStatusWrapper[]) {
set files(files: File[]) {
this._files = files ? files : [];
this._recomputeFileStatus();
}
@ -76,7 +76,7 @@ export class Dossier implements IDossier, IListable {
return !!this._files.find(f => f.status === status);
}
hasMember(memberId: string) {
hasMember(memberId: string): boolean {
return this.memberIds.indexOf(memberId) >= 0;
}

View File

@ -1,5 +1,5 @@
import { FileUploadModel } from '@upload-download/model/file-upload.model';
import { Dossier } from '../state/model/dossier';
import { Dossier } from '@state/model/dossier';
export function handleFileDrop(event: DragEvent, dossier: Dossier, uploadFiles: (files: FileUploadModel[]) => void) {
event.preventDefault();
@ -30,6 +30,8 @@ export function isCsv(file: FileUploadModel): boolean {
return file.file.type?.toLowerCase() === 'text/csv' || file.file.name.toLowerCase().endsWith('.csv');
}
export type Files = FileList | File[];
export function convertFiles(files: FileList | File[], dossier: Dossier): FileUploadModel[] {
let uploadFiles: FileUploadModel[] = [];
for (let i = 0; i < files.length; i++) {

View File

@ -1,4 +1,4 @@
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import { File } from '@models/file/file';
import { Dossier } from '../state/model/dossier';
import { handleCheckedValue, INestedFilter } from '@iqser/common-ui';
@ -45,7 +45,7 @@ export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INest
});
}
export const annotationFilterChecker = (input: FileStatusWrapper | Dossier, filter: INestedFilter) => {
export const annotationFilterChecker = (input: File | Dossier, filter: INestedFilter) => {
switch (filter.id) {
case 'analysis': {
if (input instanceof Dossier) {
@ -67,13 +67,13 @@ export const annotationFilterChecker = (input: FileStatusWrapper | Dossier, filt
return input.hasNone;
}
case 'updated': {
return input instanceof FileStatusWrapper && input.hasUpdates;
return input instanceof File && input.hasUpdates;
}
case 'image': {
return input instanceof FileStatusWrapper && input.hasImages;
return input instanceof File && input.hasImages;
}
case 'comment': {
return input instanceof FileStatusWrapper && input.hasAnnotationComments;
return input instanceof File && input.hasAnnotationComments;
}
}
};

View File

@ -1,3 +1,3 @@
import { FileStatus } from '@redaction/red-ui-http';
export type Color = FileStatus.StatusEnum | DossierStatus.StatusEnum;
export type Color = FileStatus | DossierStatus.StatusEnum;

View File

@ -10,16 +10,16 @@
* Do not edit the class manually.
*/ /* tslint:disable:no-unused-variable member-ordering */
import { Inject, Injectable, Optional } from '@angular/core';
import { HttpClient, HttpEvent, HttpHeaders, HttpParams, HttpResponse } from '@angular/common/http';
import { CustomHttpUrlEncodingCodec } from '../encoder';
import { Inject, Injectable, Optional } from "@angular/core";
import { HttpClient, HttpEvent, HttpHeaders, HttpParams, HttpResponse } from "@angular/common/http";
import { CustomHttpUrlEncodingCodec } from "../encoder";
import { Observable } from 'rxjs';
import { Observable } from "rxjs";
import { FileStatus } from '../model/fileStatus';
import { IFile } from "../model/file";
import { BASE_PATH } from '../variables';
import { Configuration } from '../configuration';
import { BASE_PATH } from "../variables";
import { Configuration } from "../configuration";
@Injectable()
export class StatusControllerService {
@ -48,13 +48,9 @@ export class StatusControllerService {
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public getDeletedFileStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable<Array<FileStatus>>;
public getDeletedFileStatus(
dossierId: string,
observe?: 'response',
reportProgress?: boolean
): Observable<HttpResponse<Array<FileStatus>>>;
public getDeletedFileStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<FileStatus>>>;
public getDeletedFileStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable<Array<IFile>>;
public getDeletedFileStatus(dossierId: string, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Array<IFile>>>;
public getDeletedFileStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<IFile>>>;
public getDeletedFileStatus(dossierId: string, observe: any = 'body', reportProgress: boolean = false): Observable<any> {
if (dossierId === null || dossierId === undefined) {
throw new Error('Required parameter dossierId was null or undefined when calling getDeletedFileStatus.');
@ -76,7 +72,7 @@ export class StatusControllerService {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
return this.httpClient.request<Array<FileStatus>>(
return this.httpClient.request<Array<IFile>>(
'get',
`${this.basePath}/status/softdeleted/${encodeURIComponent(String(dossierId))}`,
{
@ -95,11 +91,11 @@ export class StatusControllerService {
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public getDossierStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable<Array<FileStatus>>;
public getDossierStatus(dossierId: string, observe?: 'body', reportProgress?: boolean): Observable<Array<IFile>>;
public getDossierStatus(dossierId: string, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Array<FileStatus>>>;
public getDossierStatus(dossierId: string, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<Array<IFile>>>;
public getDossierStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<FileStatus>>>;
public getDossierStatus(dossierId: string, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<Array<IFile>>>;
public getDossierStatus(dossierId: string, observe: any = 'body', reportProgress: boolean = false): Observable<any> {
if (dossierId === null || dossierId === undefined) {
@ -122,7 +118,7 @@ export class StatusControllerService {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
return this.httpClient.request<Array<FileStatus>>('get', `${this.basePath}/status/${encodeURIComponent(String(dossierId))}`, {
return this.httpClient.request<Array<IFile>>('get', `${this.basePath}/status/${encodeURIComponent(String(dossierId))}`, {
withCredentials: this.configuration.withCredentials,
headers: headers,
observe: observe,
@ -138,21 +134,16 @@ export class StatusControllerService {
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public getFileStatus(dossierId: string, fileId: string, observe?: 'body', reportProgress?: boolean): Observable<FileStatus>;
public getFileStatus(dossierId: string, fileId: string, observe?: 'body', reportProgress?: boolean): Observable<IFile>;
public getFileStatus(
dossierId: string,
fileId: string,
observe?: 'response',
reportProgress?: boolean
): Observable<HttpResponse<FileStatus>>;
): Observable<HttpResponse<IFile>>;
public getFileStatus(
dossierId: string,
fileId: string,
observe?: 'events',
reportProgress?: boolean
): Observable<HttpEvent<FileStatus>>;
public getFileStatus(dossierId: string, fileId: string, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<IFile>>;
public getFileStatus(dossierId: string, fileId: string, observe: any = 'body', reportProgress: boolean = false): Observable<any> {
if (dossierId === null || dossierId === undefined) {
@ -179,7 +170,7 @@ export class StatusControllerService {
headers = headers.set('Accept', httpHeaderAcceptSelected);
}
return this.httpClient.request<FileStatus>(
return this.httpClient.request<IFile>(
'get',
`${this.basePath}/status/${encodeURIComponent(String(dossierId))}/${encodeURIComponent(String(fileId))}`,
{
@ -202,19 +193,19 @@ export class StatusControllerService {
body: Array<string>,
observe?: 'body',
reportProgress?: boolean
): Observable<{ [key: string]: Array<FileStatus> }>;
): Observable<{ [key: string]: Array<IFile> }>;
public getFileStatusForDossiers(
body: Array<string>,
observe?: 'response',
reportProgress?: boolean
): Observable<HttpResponse<{ [key: string]: Array<FileStatus> }>>;
): Observable<HttpResponse<{ [key: string]: Array<IFile> }>>;
public getFileStatusForDossiers(
body: Array<string>,
observe?: 'events',
reportProgress?: boolean
): Observable<HttpEvent<{ [key: string]: Array<FileStatus> }>>;
): Observable<HttpEvent<{ [key: string]: Array<IFile> }>>;
public getFileStatusForDossiers(body: Array<string>, observe: any = 'body', reportProgress: boolean = false): Observable<any> {
if (body === null || body === undefined) {
@ -244,7 +235,7 @@ export class StatusControllerService {
headers = headers.set('Content-Type', httpContentTypeSelected);
}
return this.httpClient.request<{ [key: string]: Array<FileStatus> }>('post', `${this.basePath}/status`, {
return this.httpClient.request<{ [key: string]: Array<IFile> }>('post', `${this.basePath}/status`, {
body: body,
withCredentials: this.configuration.withCredentials,
headers: headers,

View File

@ -14,43 +14,43 @@ import { FileAttributes } from './fileAttributes';
/**
* Object containing information on a specific file.
*/
export interface FileStatus {
export interface IFile {
/**
* Date and time when the file was added to the system.
*/
added?: string;
readonly added?: string;
/**
* Shows if all manual changes have been applied by a reanalysis.
*/
allManualRedactionsApplied?: boolean;
readonly allManualRedactionsApplied?: boolean;
/**
* Shows how long the last analysis took
*/
analysisDuration?: number;
readonly analysisDuration?: number;
/**
* Shows if the file requires reanalysis.
*/
analysisRequired?: boolean;
readonly analysisRequired?: boolean;
/**
* Shows the date of approval, if approved.
*/
approvalDate?: string;
readonly approvalDate?: string;
/**
* The current reviewer's (if any) user id.
*/
currentReviewer?: string;
readonly currentReviewer?: string;
/**
* Shows which dictionary versions was used during the analysis.
*/
dictionaryVersion?: number;
readonly dictionaryVersion?: number;
/**
* Shows which dossier dictionary versions was used during the analysis.
*/
dossierDictionaryVersion?: number;
readonly dossierDictionaryVersion?: number;
/**
* The ID of the dossier the file belongs to.
*/
dossierId?: string;
readonly dossierId?: string;
/**
* The dossierTemplateId for this file.
*/
@ -58,130 +58,116 @@ export interface FileStatus {
/**
* Shows if the file was excluded from analysis.
*/
excluded?: boolean;
readonly excluded?: boolean;
/**
* Set of excluded pages for this file.
*/
excludedPages?: Array<number>;
readonly excludedPages?: Array<number>;
fileAttributes?: FileAttributes;
/**
* The ID of the file.
*/
fileId?: string;
readonly fileId?: string;
/**
* The file's name.
*/
filename?: string;
readonly filename?: string;
/**
* Shows if this file has comments on annotations.
*/
hasAnnotationComments?: boolean;
readonly hasAnnotationComments?: boolean;
/**
* Shows if any hints were found during the analysis.
*/
hasHints?: boolean;
readonly hasHints?: boolean;
/**
* Shows if any images were found during the analysis.
*/
hasImages?: boolean;
readonly hasImages?: boolean;
/**
* Shows if any redactions were found during the analysis.
*/
hasRedactions?: boolean;
readonly hasRedactions?: boolean;
/**
* Shows if any requests were found during the analysis.
*/
hasRequests?: boolean;
readonly hasRequests?: boolean;
/**
* Shows if there are any Suggestions in this file.
*/
hasSuggestions?: boolean;
readonly hasSuggestions?: boolean;
/**
* Shows if there is any change between the previous and current analysis.
*/
hasUpdates?: boolean;
readonly hasUpdates?: boolean;
/**
* Date and time when the files attributes was last updated.
*/
lastFileAttributeChange?: string;
readonly lastFileAttributeChange?: string;
/**
* Shows if this file has been OCRed by us. Last Time of OCR.
*/
lastOCRTime?: string;
readonly lastOCRTime?: string;
/**
* Shows the last date of a successful analysis.
*/
lastProcessed?: string;
readonly lastProcessed?: string;
/**
* The last reviewer's (if any) user id.
*/
lastReviewer?: string;
readonly lastReviewer?: string;
/**
* Date and time when the file was last updated.
*/
lastUpdated?: string;
readonly lastUpdated?: string;
/**
* Shows last date the document was uploaded.
*/
lastUploaded?: string;
readonly lastUploaded?: string;
/**
* Shows which legal basis versions was used during the analysis.
*/
legalBasisVersion?: number;
readonly legalBasisVersion?: number;
/**
* The number of times the file has been analyzed.
*/
numberOfAnalyses?: number;
readonly numberOfAnalyses?: number;
/**
* The number of pages of the file.
*/
numberOfPages?: number;
readonly numberOfPages?: number;
/**
* Shows which rules versions was used during the analysis.
*/
rulesVersion?: number;
readonly rulesVersion?: number;
/**
* Shows if the file is soft deleted.
*/
softDeleted?: string;
readonly softDeleted?: string;
/**
* The status of the file with regard to its analysis an review processes.
*/
status?: FileStatus.StatusEnum;
readonly status?: FileStatus;
/**
* The ID of the user who uploaded the file.
*/
uploader?: string;
readonly uploader?: string;
}
export namespace FileStatus {
export type StatusEnum =
| 'APPROVED'
| 'DELETED'
| 'ERROR'
| 'EXCLUDED'
| 'FULLREPROCESS'
| 'INDEXING'
| 'OCR_PROCESSING'
| 'PROCESSING'
| 'REPROCESS'
| 'UNASSIGNED'
| 'UNDER_APPROVAL'
| 'UNDER_REVIEW'
| 'UNPROCESSED';
export const StatusEnum = {
APPROVED: 'APPROVED' as StatusEnum,
DELETED: 'DELETED' as StatusEnum,
ERROR: 'ERROR' as StatusEnum,
EXCLUDED: 'EXCLUDED' as StatusEnum,
FULLREPROCESS: 'FULLREPROCESS' as StatusEnum,
INDEXING: 'INDEXING' as StatusEnum,
OCRPROCESSING: 'OCR_PROCESSING' as StatusEnum,
PROCESSING: 'PROCESSING' as StatusEnum,
REPROCESS: 'REPROCESS' as StatusEnum,
UNASSIGNED: 'UNASSIGNED' as StatusEnum,
UNDERAPPROVAL: 'UNDER_APPROVAL' as StatusEnum,
UNDERREVIEW: 'UNDER_REVIEW' as StatusEnum,
UNPROCESSED: 'UNPROCESSED' as StatusEnum
} as const;
}
export const FileStatuses = {
APPROVED: 'APPROVED',
DELETED: 'DELETED',
ERROR: 'ERROR',
EXCLUDED: 'EXCLUDED',
FULLREPROCESS: 'FULLREPROCESS',
INDEXING: 'INDEXING',
OCR_PROCESSING: 'OCR_PROCESSING',
PROCESSING: 'PROCESSING',
REPROCESS: 'REPROCESS',
UNASSIGNED: 'UNASSIGNED',
UNDER_APPROVAL: 'UNDER_APPROVAL',
UNDER_REVIEW: 'UNDER_REVIEW',
UNPROCESSED: 'UNPROCESSED'
} as const;
export type FileStatus = keyof typeof FileStatuses;

View File

@ -31,7 +31,7 @@ export * from './downloadStatusResponse';
export * from './fileAttributeConfig';
export * from './fileAttributes';
export * from './fileAttributesConfig';
export * from './fileStatus';
export * from './file';
export * from './fileUploadResult';
export * from './forceRedactionRequest';
export * from './generalConfigurationModel';

View File

@ -41,12 +41,12 @@ export namespace ReportData {
ERROR: 'ERROR' as StatusEnum,
EXCLUDED: 'EXCLUDED' as StatusEnum,
FULLREPROCESS: 'FULLREPROCESS' as StatusEnum,
OCRPROCESSING: 'OCR_PROCESSING' as StatusEnum,
OCR_PROCESSING: 'OCR_PROCESSING' as StatusEnum,
PROCESSING: 'PROCESSING' as StatusEnum,
REPROCESS: 'REPROCESS' as StatusEnum,
UNASSIGNED: 'UNASSIGNED' as StatusEnum,
UNDERAPPROVAL: 'UNDER_APPROVAL' as StatusEnum,
UNDERREVIEW: 'UNDER_REVIEW' as StatusEnum,
UNDER_APPROVAL: 'UNDER_APPROVAL' as StatusEnum,
UNDER_REVIEW: 'UNDER_REVIEW' as StatusEnum,
UNPROCESSED: 'UNPROCESSED' as StatusEnum
};
}

View File

@ -26,7 +26,7 @@
"lint": "nx workspace-lint && nx lint",
"lint-fix": "nx workspace-lint --fix && nx lint --fix",
"nx": "nx",
"start": "nx serve",
"start": "nx serve --hmr",
"test": "nx test",
"update": "nx migrate latest",
"migrate": "nx migrate --run-migrations",