Added new file statuses

This commit is contained in:
Adina Țeudan 2021-11-15 23:01:31 +02:00
parent 29f55d4608
commit 71cd722bfa
19 changed files with 110 additions and 132 deletions

View File

@ -4,7 +4,7 @@ import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/si
import { TranslateChartService } from '@services/translate-chart.service';
import { UserService } from '@services/user.service';
import { FilterService, shareLast, Toaster } from '@iqser/common-ui';
import { fileStatusTranslations } from '../../../../translations/file-status-translations';
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { Dossier, DossierAttributeWithValue, DossierStats, IDossierRequest, StatusSorter, User } from '@red/domain';
import { DossiersService } from '@services/entity-services/dossiers.service';
@ -61,7 +61,7 @@ export class DossierDetailsComponent {
const documentsChartData: DoughnutChartConfig[] = Object.keys(stats.fileCountPerWorkflowStatus).map(status => ({
value: stats.fileCountPerWorkflowStatus[status],
color: status,
label: fileStatusTranslations[status],
label: workflowFileStatusTranslations[status],
key: status,
}));
documentsChartData.sort((a, b) => StatusSorter.byStatus(a.key, b.key));

View File

@ -49,12 +49,11 @@
<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="file.isProcessing" class="small-label loading" translate="dossier-overview.file-listing.file-entry.file-processing"></div>
<iqser-status-bar
*ngIf="file.isWorkable"
[configs]="[
{
color: file.status,
color: file.workflowStatus,
length: 1
}
]"

View File

@ -12,8 +12,8 @@ import {
TableColumnConfig,
WorkflowConfig,
} from '@iqser/common-ui';
import { File, FileStatus, FileStatuses, IFileAttributeConfig, StatusSorter } from '@red/domain';
import { fileStatusTranslations } from '../../translations/file-status-translations';
import { File, IFileAttributeConfig, StatusSorter, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
import { FileActionService } from '../../shared/services/file-action.service';
import { AppStateService } from '@state/app-state.service';
import { PermissionsService } from '@services/permissions.service';
@ -92,41 +92,41 @@ export class ConfigService {
];
}
workflowConfig(reloadDossiers: () => Promise<void>): WorkflowConfig<File, FileStatus> {
workflowConfig(reloadDossiers: () => Promise<void>): WorkflowConfig<File, WorkflowFileStatus> {
return {
columnIdentifierFn: entity => entity.status,
columnIdentifierFn: entity => entity.workflowStatus,
itemVersionFn: (entity: File) => `${entity.lastUpdated}-${entity.numberOfAnalyses}`,
columns: [
{
label: fileStatusTranslations[FileStatuses.UNASSIGNED],
key: FileStatuses.UNASSIGNED,
label: workflowFileStatusTranslations[WorkflowFileStatuses.UNASSIGNED],
key: WorkflowFileStatuses.UNASSIGNED,
enterFn: this._unassignFn(reloadDossiers),
enterPredicate: (file: File) => this._permissionsService.canUnassignUser(file),
color: '#D3D5DA',
},
{
label: fileStatusTranslations[FileStatuses.UNDER_REVIEW],
label: workflowFileStatusTranslations[WorkflowFileStatuses.UNDER_REVIEW],
enterFn: this._underReviewFn(reloadDossiers),
enterPredicate: (file: File) =>
this._permissionsService.canSetUnderReview(file) ||
this._permissionsService.canAssignToSelf(file) ||
this._permissionsService.canAssignUser(file),
key: FileStatuses.UNDER_REVIEW,
key: WorkflowFileStatuses.UNDER_REVIEW,
color: '#FDBD00',
},
{
label: fileStatusTranslations[FileStatuses.UNDER_APPROVAL],
label: workflowFileStatusTranslations[WorkflowFileStatuses.UNDER_APPROVAL],
enterFn: this._underApprovalFn(reloadDossiers),
enterPredicate: (file: File) =>
this._permissionsService.canSetUnderApproval(file) || this._permissionsService.canUndoApproval(file),
key: FileStatuses.UNDER_APPROVAL,
key: WorkflowFileStatuses.UNDER_APPROVAL,
color: '#374C81',
},
{
label: fileStatusTranslations[FileStatuses.APPROVED],
label: workflowFileStatusTranslations[WorkflowFileStatuses.APPROVED],
enterFn: this._approveFn(reloadDossiers),
enterPredicate: (file: File) => this._permissionsService.isReadyForApproval(file) && file.canBeApproved,
key: FileStatuses.APPROVED,
key: WorkflowFileStatuses.APPROVED,
color: '#48C9F7',
},
],
@ -141,7 +141,7 @@ export class ConfigService {
checkedRequiredFilters: () => NestedFilter[],
checkedNotRequiredFilters: () => NestedFilter[],
) {
const allDistinctFileStatuses = new Set<string>();
const allDistinctWorkflowFileStatuses = new Set<string>();
const allDistinctPeople = new Set<string>();
const allDistinctAddedDates = new Set<string>();
const allDistinctNeedsWork = new Set<string>();
@ -152,7 +152,7 @@ export class ConfigService {
entities.forEach(file => {
allDistinctPeople.add(file.currentReviewer);
allDistinctFileStatuses.add(file.status);
allDistinctWorkflowFileStatuses.add(file.workflowStatus);
allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY'));
if (file.analysisRequired) {
@ -196,11 +196,11 @@ export class ConfigService {
});
if (listingMode === ListingModes.table) {
const statusFilters = [...allDistinctFileStatuses].map(
const statusFilters = [...allDistinctWorkflowFileStatuses].map(
status =>
new NestedFilter({
id: status,
label: this._translateService.instant(fileStatusTranslations[status]),
label: this._translateService.instant(workflowFileStatusTranslations[status]),
}),
);
@ -209,7 +209,7 @@ export class ConfigService {
label: this._translateService.instant('filters.status'),
icon: 'red:status',
filters: statusFilters.sort((a, b) => StatusSorter[a.id] - StatusSorter[b.id]),
checker: keyChecker('status'),
checker: keyChecker('workflowStatus'),
});
}
@ -333,12 +333,12 @@ export class ConfigService {
{
id: 'unassigned',
label: this._translateService.instant('dossier-overview.quick-filters.unassigned'),
checker: (file: File) => !file.currentReviewer,
checker: (file: File) => file.isUnassigned,
},
{
id: 'assigned-to-others',
label: this._translateService.instant('dossier-overview.quick-filters.assigned-to-others'),
checker: (file: File) => !!file.currentReviewer && file.currentReviewer !== this._userService.currentUser.id,
checker: (file: File) => !file.isUnassigned && file.currentReviewer !== this._userService.currentUser.id,
},
].map(filter => new NestedFilter(filter));
}

View File

@ -11,7 +11,7 @@ import {
TemplateRef,
ViewChild,
} from '@angular/core';
import { Dossier, DossierAttributeWithValue, File, FileStatus, IFileAttributeConfig } from '@red/domain';
import { Dossier, DossierAttributeWithValue, File, IFileAttributeConfig, WorkflowFileStatus } from '@red/domain';
import { AppStateService } from '@state/app-state.service';
import { FileDropOverlayService } from '@upload-download/services/file-drop-overlay.service';
import { FileUploadModel } from '@upload-download/model/file-upload.model';
@ -74,7 +74,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
analysisForced: boolean;
displayedInFileListAttributes: IFileAttributeConfig[] = [];
displayedAttributes: IFileAttributeConfig[] = [];
readonly workflowConfig: WorkflowConfig<File, FileStatus> = this._configService.workflowConfig(() => this.reloadFiles());
readonly workflowConfig: WorkflowConfig<File, WorkflowFileStatus> = this._configService.workflowConfig(() => this.reloadFiles());
readonly actionConfigs: readonly ActionConfig[];
readonly dossier$: Observable<Dossier>;
readonly dossierId: string;
@ -265,7 +265,8 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
'primaryAttribute',
'numberOfPages',
'assignee',
'status',
'workflowStatus',
'processingStatus',
'lastUpdated',
'lastUploaded',
'lastProcessed',

View File

@ -4,7 +4,7 @@ import { FilterService, mapEach } from '@iqser/common-ui';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { combineLatest, Observable } from 'rxjs';
import { Dossier, DossierStats, DossierStatuses, FileCountPerWorkflowStatus, StatusSorter } from '@red/domain';
import { fileStatusTranslations } from '../../../../translations/file-status-translations';
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
import { TranslateChartService } from '@services/translate-chart.service';
import { filter, map, switchMap } from 'rxjs/operators';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@ -60,7 +60,7 @@ export class DossiersListingDetailsComponent {
({
value: chartData[status],
color: status,
label: fileStatusTranslations[status],
label: workflowFileStatusTranslations[status],
key: status,
} as DoughnutChartConfig),
);

View File

@ -5,7 +5,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { TranslateService } from '@ngx-translate/core';
import { UserPreferenceService } from '@services/user-preference.service';
import { UserService } from '@services/user.service';
import { fileStatusTranslations } from '../../translations/file-status-translations';
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
import { dossierMemberChecker, dossierTemplateChecker, RedactionFilterSorter } from '@utils/index';
import { workloadTranslations } from '../../translations/workload-translations';
import { AppStateService } from '@state/app-state.service';
@ -113,7 +113,7 @@ export class ConfigService {
status =>
new NestedFilter({
id: status,
label: this._translateService.instant(fileStatusTranslations[status]),
label: this._translateService.instant(workflowFileStatusTranslations[status]),
}),
);

View File

@ -35,7 +35,7 @@
<iqser-status-bar [configs]="statusBarConfig" [small]="true"></iqser-status-bar>
<div class="all-caps-label mr-16 ml-8">
{{ translations[file.status] | translate }}
{{ translations[file.workflowStatus] | translate }}
<span *ngIf="isUnderReviewOrApproval">{{ 'by' | translate }}:</span>
</div>
</ng-container>

View File

@ -33,7 +33,7 @@ import { AnnotationData, FileDataModel } from '@models/file/file-data.model';
import { FileActionService } from '../../shared/services/file-action.service';
import { AnnotationDrawService } from '../../services/annotation-draw.service';
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
import { Dossier, File, FileStatus, User, ViewMode } from '@red/domain';
import { Dossier, File, User, ViewMode, WorkflowFileStatus } from '@red/domain';
import { PermissionsService } from '@services/permissions.service';
import { Observable, timer } from 'rxjs';
import { UserPreferenceService } from '@services/user-preference.service';
@ -44,7 +44,7 @@ import { FileWorkloadComponent } from '../../components/file-workload/file-workl
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
import { clearStamps, stampPDFPage } from '@utils/page-stamper';
import { TranslateService } from '@ngx-translate/core';
import { fileStatusTranslations } from '../../translations/file-status-translations';
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
import { handleFilterDelta } from '@utils/filter-utils';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FileActionsComponent } from '../../shared/components/file-actions/file-actions.component';
@ -65,7 +65,7 @@ const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
})
export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnInit, OnDestroy, OnAttach, OnDetach {
readonly circleButtonTypes = CircleButtonTypes;
readonly translations = fileStatusTranslations;
readonly translations = workflowFileStatusTranslations;
dialogRef: MatDialogRef<unknown>;
viewMode: ViewMode = 'STANDARD';
@ -183,12 +183,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
: this._translateService.instant('file-preview.assign-reviewer');
}
get statusBarConfig(): [{ length: number; color: FileStatus }] {
return [{ length: 1, color: this.file.status }];
get statusBarConfig(): [{ length: number; color: WorkflowFileStatus }] {
return [{ length: 1, color: this.file.workflowStatus }];
}
get isUnderReviewOrApproval(): boolean {
return this.file.status === 'UNDER_REVIEW' || this.file.status === 'UNDER_APPROVAL';
return this.file.isUnderReview || this.file.isUnderApproval;
}
canAssign(file: File): boolean {

View File

@ -15,7 +15,7 @@ import { merge, Observable } from 'rxjs';
import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { fileStatusTranslations } from '../../translations/file-status-translations';
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
import { TranslateService } from '@ngx-translate/core';
import { RouterHistoryService } from '@services/router-history.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
@ -37,7 +37,7 @@ function toSearchInput(query: string, dossierIds: List | string): ISearchInput {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SearchScreenComponent extends ListingComponent<ISearchListItem> implements OnDestroy {
readonly fileStatusTranslations = fileStatusTranslations;
readonly fileStatusTranslations = workflowFileStatusTranslations;
readonly searchPositions = SearchPositions;
readonly tableHeaderLabel = _('search-screen.table-header');
@ -139,7 +139,7 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
dossierId,
unmatched: unmatchedTerms || null,
highlights,
status: file.status,
status: file.workflowStatus,
numberOfPages: file.numberOfPages,
dossierName: this._dossiersService.find(dossierId).dossierName,
filename: file.filename,

View File

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { Dossier, File, FileStatus } from '@red/domain';
import { Dossier, File, WorkflowFileStatus } from '@red/domain';
import { AppStateService } from '@state/app-state.service';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import {
@ -45,7 +45,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
@Output() readonly actionPerformed = new EventEmitter<string>();
dossier$: Observable<Dossier>;
statusBarConfig?: List<StatusBarConfig<FileStatus>>;
statusBarConfig?: List<StatusBarConfig<WorkflowFileStatus>>;
tooltipPosition?: 'below' | 'above';
toggleTooltip?: string;
assignTooltip?: string;
@ -234,7 +234,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
}
setup() {
this.statusBarConfig = [{ color: this.file.status, length: 1 }];
this.statusBarConfig = [{ color: this.file.workflowStatus, length: 1 }];
this.tooltipPosition = this.isFilePreview ? 'below' : 'above';
this.assignTooltip = this.file.isUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
this.buttonType = this.isFilePreview ? CircleButtonTypes.default : CircleButtonTypes.dark;

View File

@ -1,18 +1,21 @@
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FileStatus } from '@red/domain';
import { ProcessingFileStatus, WorkflowFileStatus } from '@red/domain';
export const fileStatusTranslations: { [key in FileStatus]: string } = {
export const workflowFileStatusTranslations: { [key in WorkflowFileStatus]: string } = {
APPROVED: _('file-status.approved'),
UNASSIGNED: _('file-status.unassigned'),
UNDER_APPROVAL: _('file-status.under-approval'),
UNDER_REVIEW: _('file-status.under-review'),
};
export const processingFileStatusTranslations: { [key in ProcessingFileStatus]: string } = {
PROCESSED: _('file-status.processed'),
DELETED: _('file-status.deleted'),
ERROR: _('file-status.error'),
EXCLUDED: _('file-status.excluded'),
FULLREPROCESS: _('file-status.full-reprocess'),
INDEXING: _('file-status.indexing'),
OCR_PROCESSING: _('file-status.ocr-processing'),
PROCESSING: _('file-status.processing'),
REPROCESS: _('file-status.reprocess'),
UNASSIGNED: _('file-status.unassigned'),
UNDER_APPROVAL: _('file-status.under-approval'),
UNDER_REVIEW: _('file-status.under-review'),
UNPROCESSED: _('file-status.unprocessed'),
};

View File

@ -22,7 +22,7 @@ export class PermissionsService {
}
canToggleAnalysis(file: File, dossier: Dossier): boolean {
return this.isReviewerOrApprover(file, dossier) && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status);
return this.isReviewerOrApprover(file, dossier) && (file.isUnassigned || file.isUnderReview || file.isUnderApproval);
}
canReanalyseFile(file: File, dossier: Dossier): boolean {
@ -102,8 +102,9 @@ export class PermissionsService {
return dossier?.memberIds.includes(user.id);
}
// TODO: Remove '?', after we make sure file is loaded before page
canPerformAnnotationActions(file: File): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file?.status) && this.isFileReviewer(file);
return (file?.isUnderReview || file?.isUnderApproval) && this.isFileReviewer(file);
}
canUndoApproval(file: File): boolean {
@ -111,7 +112,7 @@ export class PermissionsService {
}
canMarkPagesAsViewed(file: File): boolean {
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file?.status) && this.isFileReviewer(file);
return (file.isUnderReview || file.isUnderApproval) && this.isFileReviewer(file);
}
canDownloadFiles(file: File): boolean {
@ -137,7 +138,7 @@ export class PermissionsService {
canExcludePages(file: File): boolean {
const dossier = this._getDossier(file);
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file.status) && (this.isFileReviewer(file) || this.isApprover(dossier));
return (file.isUnderReview || file.isUnderApproval) && (this.isFileReviewer(file) || this.isApprover(dossier));
}
canDeleteComment(comment: IComment, file: File) {

View File

@ -698,8 +698,7 @@
"file-listing": {
"file-entry": {
"file-error": "Re-processing required",
"file-pending": "Pending...",
"file-processing": "Processing"
"file-pending": "Pending..."
}
},
"filters": {
@ -1081,10 +1080,10 @@
"approved": "Approved",
"deleted": "Deleted",
"error": "Re-processing required",
"excluded": "Excluded",
"full-reprocess": "Processing",
"indexing": "Processing",
"ocr-processing": "OCR Processing",
"processed": "Processed",
"processing": "Processing",
"reprocess": "Processing",
"unassigned": "Unassigned",

@ -1 +1 @@
Subproject commit 8beb712c5492dd77e81f46cb67752615f582ecf4
Subproject commit 643df41d09d3a1d159adbb1f2cf3cefa26002bc8

View File

@ -1,26 +1,4 @@
export const WorkflowFileStatuses = {
APPROVED: 'APPROVED',
UNASSIGNED: 'UNASSIGNED',
UNDER_APPROVAL: 'UNDER_APPROVAL',
UNDER_REVIEW: 'UNDER_REVIEW',
} as const;
export type WorkflowFileStatus = keyof typeof WorkflowFileStatuses;
import { ProcessingFileStatus, WorkflowFileStatus } from '../files';
export type FileCountPerWorkflowStatus = { [key in WorkflowFileStatus]?: number };
export const ProcessingFileStatuses = {
DELETED: 'DELETED',
ERROR: 'ERROR',
FULLREPROCESS: 'FULLREPROCESS',
INDEXING: 'INDEXING',
OCR_PROCESSING: 'OCR_PROCESSING',
PROCESSED: 'PROCESSED',
PROCESSING: 'PROCESSING',
REPROCESS: 'REPROCESS',
UNPROCESSED: 'UNPROCESSED',
} as const;
export type ProcessingFileStatus = keyof typeof ProcessingFileStatuses;
export type FileCountPerProcessingStatus = { [key in ProcessingFileStatus]?: number };

View File

@ -1,15 +1,15 @@
import { Entity, List } from '@iqser/common-ui';
import { StatusSorter } from '../shared';
import { FileStatus, FileStatuses } from './types';
import { ProcessingFileStatus, ProcessingFileStatuses, WorkflowFileStatus, WorkflowFileStatuses } from './types';
import { IFile } from './file';
import { FileAttributes, IFileAttributesConfig } from '../file-attributes';
const processingStatuses: List<FileStatus> = [
FileStatuses.REPROCESS,
FileStatuses.FULLREPROCESS,
FileStatuses.OCR_PROCESSING,
FileStatuses.INDEXING,
FileStatuses.PROCESSING,
const processingStatuses: List<ProcessingFileStatus> = [
ProcessingFileStatuses.REPROCESS,
ProcessingFileStatuses.FULLREPROCESS,
ProcessingFileStatuses.OCR_PROCESSING,
ProcessingFileStatuses.INDEXING,
ProcessingFileStatuses.PROCESSING,
] as const;
export class File extends Entity<IFile> implements IFile {
@ -40,10 +40,11 @@ export class File extends Entity<IFile> implements IFile {
readonly numberOfAnalyses: number;
readonly numberOfPages?: number;
readonly rulesVersion?: number;
readonly status: FileStatus;
readonly uploader?: string;
readonly excludedPages?: number[];
readonly hasSuggestions: boolean;
readonly processingStatus: ProcessingFileStatus;
readonly workflowStatus: WorkflowFileStatus;
readonly primaryAttribute?: string;
lastOpened = false;
@ -90,30 +91,31 @@ export class File extends Entity<IFile> implements IFile {
this.lastUploaded = file.lastUploaded;
this.legalBasisVersion = file.legalBasisVersion;
this.numberOfAnalyses = file.numberOfAnalyses;
this.status = ['REPROCESS', 'FULLREPROCESS', 'INDEXING'].includes(file.status) ? FileStatuses.PROCESSING : file.status;
this.isError = this.status === FileStatuses.ERROR;
this.processingStatus = file.processingStatus;
this.workflowStatus = file.workflowStatus;
this.isError = this.processingStatus === ProcessingFileStatuses.ERROR;
this.numberOfPages = this.isError ? 0 : file.numberOfPages ?? 0;
this.rulesVersion = file.rulesVersion;
this.uploader = file.uploader;
this.excludedPages = file.excludedPages;
this.hasSuggestions = !!file.hasSuggestions;
this.statusSort = StatusSorter[this.status];
this.statusSort = StatusSorter[this.workflowStatus];
if (this.lastUpdated && this.lastOCRTime) {
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.isPending = this.processingStatus === ProcessingFileStatuses.UNPROCESSED;
this.isProcessing = processingStatuses.includes(this.processingStatus);
this.isApproved = this.workflowStatus === WorkflowFileStatuses.APPROVED;
this.isUnassigned = this.workflowStatus === WorkflowFileStatuses.UNASSIGNED;
this.isUnderReview = this.workflowStatus === WorkflowFileStatuses.UNDER_REVIEW;
this.isUnderApproval = this.workflowStatus === WorkflowFileStatuses.UNDER_APPROVAL;
this.canBeApproved = !this.analysisRequired && !this.hasSuggestions;
this.canBeOpened = !this.isError && !this.isPending && this.numberOfAnalyses > 0;
this.isWorkable = !this.isProcessing && this.canBeOpened;
this.canBeOCRed = !this.excluded && !this.lastOCRTime && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(this.status);
this.canBeOCRed = !this.excluded && !this.lastOCRTime && (this.isUnassigned || this.isUnderReview || this.isUnderApproval);
if (fileAttributesConfig) {
const primary = fileAttributesConfig.fileAttributeConfigs?.find(c => c.primaryAttribute);

View File

@ -1,7 +1,7 @@
/**
* Object containing information on a specific file.
*/
import { FileStatus } from './types';
import { ProcessingFileStatus, WorkflowFileStatus } from './types';
import { FileAttributes } from '../file-attributes';
export interface IFile {
@ -130,12 +130,12 @@ export interface IFile {
* Shows if the file is soft deleted.
*/
readonly softDeleted?: string;
/**
* The status of the file with regard to its analysis an review processes.
*/
readonly status: FileStatus;
/**
* The ID of the user who uploaded the file.
*/
readonly uploader?: string;
readonly processingStatus: ProcessingFileStatus;
readonly workflowStatus: WorkflowFileStatus;
}

View File

@ -1,17 +1,22 @@
export const FileStatuses = {
export const WorkflowFileStatuses = {
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',
} as const;
export type WorkflowFileStatus = keyof typeof WorkflowFileStatuses;
export const ProcessingFileStatuses = {
DELETED: 'DELETED',
ERROR: 'ERROR',
FULLREPROCESS: 'FULLREPROCESS',
INDEXING: 'INDEXING',
OCR_PROCESSING: 'OCR_PROCESSING',
PROCESSED: 'PROCESSED',
PROCESSING: 'PROCESSING',
REPROCESS: 'REPROCESS',
UNPROCESSED: 'UNPROCESSED',
} as const;
export type FileStatus = keyof typeof FileStatuses;
export type ProcessingFileStatus = keyof typeof ProcessingFileStatuses;

View File

@ -1,32 +1,22 @@
import { FileStatus } from '../../files';
import { WorkflowFileStatus } from '../../files';
type StatusSorterItem = { key: FileStatus } | FileStatus | string;
type Sorter = Record<FileStatus, number> & {
type StatusSorterItem = { key: WorkflowFileStatus } | WorkflowFileStatus | string;
type Sorter = Record<WorkflowFileStatus, number> & {
byStatus: <T extends StatusSorterItem>(a: T, b: T) => number;
};
export const StatusSorter: Sorter = {
ERROR: 0,
DELETED: 0,
FULLREPROCESS: 0,
EXCLUDED: 0,
INDEXING: 0,
UNPROCESSED: 1,
REPROCESS: 5,
PROCESSING: 5,
OCR_PROCESSING: 7,
UNASSIGNED: 10,
UNDER_REVIEW: 15,
UNDER_APPROVAL: 20,
APPROVED: 25,
UNASSIGNED: 1,
UNDER_REVIEW: 2,
UNDER_APPROVAL: 3,
APPROVED: 4,
byStatus: (a: StatusSorterItem, b: StatusSorterItem): number => {
if (typeof a !== typeof b) {
throw TypeError('Used different types when calling StatusSorter.byStatus1');
}
const x = typeof a === 'string' ? (a as FileStatus) : a.key;
const y = typeof b === 'string' ? (b as FileStatus) : b.key;
const x = typeof a === 'string' ? (a as WorkflowFileStatus) : a.key;
const y = typeof b === 'string' ? (b as WorkflowFileStatus) : b.key;
return StatusSorter[x] - StatusSorter[y];
},
};