refactor file status
This commit is contained in:
parent
86a84393b5
commit
d8e758ff14
@ -1,23 +1,55 @@
|
||||
import { FileAttributesConfig, FileStatus } from '@redaction/red-ui-http';
|
||||
import { StatusSorter } from '@utils/sorters/status-sorter';
|
||||
|
||||
export class FileStatusWrapper {
|
||||
const processingStatuses = [
|
||||
FileStatus.StatusEnum.REPROCESS,
|
||||
FileStatus.StatusEnum.FULLREPROCESS,
|
||||
FileStatus.StatusEnum.OCRPROCESSING,
|
||||
FileStatus.StatusEnum.INDEXING,
|
||||
FileStatus.StatusEnum.PROCESSING
|
||||
] as const;
|
||||
|
||||
export class FileStatusWrapper implements FileStatus {
|
||||
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;
|
||||
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 hasRequests = this.fileStatus.hasRequests;
|
||||
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;
|
||||
|
||||
primaryAttribute: string;
|
||||
searchField: string;
|
||||
|
||||
constructor(
|
||||
public fileStatus: FileStatus,
|
||||
public reviewerName: string,
|
||||
public dossierTemplateId: string,
|
||||
fileAttributesConfig?: FileAttributesConfig
|
||||
) {
|
||||
this.searchField = fileStatus.filename;
|
||||
|
||||
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];
|
||||
this.searchField += ' ' + this.primaryAttribute;
|
||||
this.filename += ' ' + this.primaryAttribute;
|
||||
}
|
||||
|
||||
if (!this.primaryAttribute) {
|
||||
@ -27,178 +59,40 @@ export class FileStatusWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
get analysisDuration() {
|
||||
return this.fileStatus.analysisDuration;
|
||||
readonly excludedPagesCount = this.excludedPages?.length ?? 0;
|
||||
readonly statusSort = StatusSorter[this.status];
|
||||
readonly pages = this._pages;
|
||||
readonly cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime);
|
||||
|
||||
readonly hasUnappliedSuggestions = !this.allManualRedactionsApplied;
|
||||
readonly hintsOnly = this.hasHints && !this.hasRedactions;
|
||||
readonly hasNone = !this.hasRedactions && !this.hasHints && !this.hasRequests;
|
||||
|
||||
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.hasRequests;
|
||||
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 isUnassigned() {
|
||||
return !this.currentReviewer;
|
||||
}
|
||||
|
||||
get lastProcessed() {
|
||||
return this.fileStatus.lastProcessed;
|
||||
}
|
||||
|
||||
get added() {
|
||||
return this.fileStatus.added;
|
||||
}
|
||||
|
||||
get lastUploaded() {
|
||||
return this.fileStatus.lastUploaded;
|
||||
}
|
||||
|
||||
get hasImages() {
|
||||
return this.fileStatus.hasImages;
|
||||
}
|
||||
|
||||
get hasUpdates() {
|
||||
return this.fileStatus.hasUpdates && !this.hasRequests;
|
||||
}
|
||||
|
||||
get hasUnappliedSuggestions() {
|
||||
return !this.fileStatus.allManualRedactionsApplied;
|
||||
}
|
||||
|
||||
get currentReviewer() {
|
||||
return this.fileStatus.currentReviewer;
|
||||
}
|
||||
|
||||
set currentReviewer(value: string) {
|
||||
this.fileStatus.currentReviewer = value;
|
||||
}
|
||||
|
||||
get fileId() {
|
||||
return this.fileStatus.fileId;
|
||||
}
|
||||
|
||||
get filename() {
|
||||
return this.fileStatus.filename;
|
||||
}
|
||||
|
||||
get hasAnnotationComments() {
|
||||
// return this.fileStatus.hasAnnotationComments;
|
||||
// TODO remove this once backend works properly
|
||||
return false;
|
||||
}
|
||||
|
||||
get ocrTime() {
|
||||
return this.fileStatus.lastOCRTime;
|
||||
}
|
||||
|
||||
get hasHints() {
|
||||
return this.fileStatus.hasHints;
|
||||
}
|
||||
|
||||
get hintsOnly() {
|
||||
return this.fileStatus.hasHints && !this.fileStatus.hasRedactions;
|
||||
}
|
||||
|
||||
get hasRedactions() {
|
||||
return this.fileStatus.hasRedactions;
|
||||
}
|
||||
|
||||
get hasRequests() {
|
||||
return this.fileStatus.hasRequests || this.hasUnappliedSuggestions;
|
||||
}
|
||||
|
||||
get hasNone() {
|
||||
return !this.hasRedactions && !this.hasHints && !this.hasRequests;
|
||||
}
|
||||
|
||||
get lastUpdated() {
|
||||
return this.fileStatus.lastUpdated;
|
||||
}
|
||||
|
||||
get numberOfAnalyses() {
|
||||
return this.fileStatus.numberOfAnalyses;
|
||||
}
|
||||
|
||||
get dossierId() {
|
||||
return this.fileStatus.dossierId;
|
||||
}
|
||||
|
||||
get isExcluded() {
|
||||
return this.fileStatus.excluded;
|
||||
}
|
||||
|
||||
get status() {
|
||||
return this.fileStatus.status === 'REPROCESS' || this.fileStatus.status === 'FULLREPROCESS' ? 'PROCESSING' : this.fileStatus.status;
|
||||
}
|
||||
|
||||
get numberOfPages() {
|
||||
return this.fileStatus.numberOfPages;
|
||||
}
|
||||
|
||||
get numberOfExcludedPages() {
|
||||
return this.fileStatus.excludedPages?.length || 0;
|
||||
}
|
||||
|
||||
get uploader() {
|
||||
return this.fileStatus.uploader;
|
||||
}
|
||||
|
||||
get isPending() {
|
||||
return this.status === FileStatus.StatusEnum.UNPROCESSED;
|
||||
}
|
||||
|
||||
get isProcessing() {
|
||||
return [
|
||||
FileStatus.StatusEnum.REPROCESS,
|
||||
FileStatus.StatusEnum.FULLREPROCESS,
|
||||
FileStatus.StatusEnum.OCRPROCESSING,
|
||||
FileStatus.StatusEnum.INDEXING,
|
||||
FileStatus.StatusEnum.PROCESSING
|
||||
].includes(this.status);
|
||||
}
|
||||
|
||||
get analysisRequired() {
|
||||
return this.fileStatus.analysisRequired && !this.fileStatus.excluded;
|
||||
}
|
||||
|
||||
get statusSort() {
|
||||
return StatusSorter[this.status];
|
||||
}
|
||||
|
||||
get isWorkable() {
|
||||
return !this.isProcessing && !this.isPending && !this.isError;
|
||||
}
|
||||
|
||||
get isApproved() {
|
||||
return this.fileStatus.status === 'APPROVED';
|
||||
}
|
||||
|
||||
get isError() {
|
||||
return this.fileStatus.status === 'ERROR';
|
||||
}
|
||||
|
||||
get pages() {
|
||||
private get _pages() {
|
||||
if (this.fileStatus.status === 'ERROR') {
|
||||
return -1;
|
||||
}
|
||||
return this.fileStatus.numberOfPages ? this.fileStatus.numberOfPages : 0;
|
||||
}
|
||||
|
||||
get isApprovedOrUnderApproval() {
|
||||
return this.status === 'APPROVED' || this.status === 'UNDER_APPROVAL';
|
||||
}
|
||||
|
||||
get isUnassigned() {
|
||||
return !this.currentReviewer;
|
||||
}
|
||||
|
||||
get isUnderReview() {
|
||||
return this.fileStatus.status === 'UNDER_REVIEW';
|
||||
}
|
||||
|
||||
get isUnderApproval() {
|
||||
return this.fileStatus.status === 'UNDER_APPROVAL';
|
||||
}
|
||||
|
||||
get canApprove() {
|
||||
return this.status === 'UNDER_REVIEW' || this.status === 'UNDER_APPROVAL';
|
||||
}
|
||||
|
||||
get cacheIdentifier() {
|
||||
return btoa(this.fileStatus.lastUploaded + this.fileStatus.lastOCRTime);
|
||||
}
|
||||
|
||||
get excludedPages(): number[] {
|
||||
return this.fileStatus.excludedPages;
|
||||
private get _status(): FileStatus.StatusEnum {
|
||||
return this.fileStatus.status === FileStatus.StatusEnum.REPROCESS || this.fileStatus.status === FileStatus.StatusEnum.FULLREPROCESS
|
||||
? FileStatus.StatusEnum.PROCESSING
|
||||
: this.fileStatus.status;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<div class="action-buttons">
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteDossierTemplateDialog($event)"
|
||||
*ngIf="permissionsService.isAdmin()"
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[tooltip]="'dossier-templates-listing.action.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openEditDossierTemplateDialog($event)"
|
||||
*ngIf="permissionsService.isAdmin()"
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[tooltip]="'dossier-templates-listing.action.edit' | translate"
|
||||
icon="red:edit"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -1,34 +1,35 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { DossierTemplateControllerService } from '@redaction/red-ui-http';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-template-actions',
|
||||
templateUrl: './dossier-template-actions.component.html',
|
||||
styleUrls: ['./dossier-template-actions.component.scss']
|
||||
})
|
||||
export class DossierTemplateActionsComponent {
|
||||
export class DossierTemplateActionsComponent implements OnInit {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
@Input() dossierTemplateId: string;
|
||||
@Output() loadDossierTemplatesData = new EventEmitter<any>();
|
||||
|
||||
constructor(
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossierTemplateControllerService: DossierTemplateControllerService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _router: Router,
|
||||
readonly permissionsService: PermissionsService
|
||||
) {
|
||||
if (!this.dossierTemplateId) {
|
||||
this.dossierTemplateId = this._appStateService.activeDossierTemplateId;
|
||||
}
|
||||
private readonly _userService: UserService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _dossierTemplateControllerService: DossierTemplateControllerService
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.dossierTemplateId ??= this._appStateService.activeDossierTemplateId;
|
||||
}
|
||||
|
||||
get dossierTemplate() {
|
||||
@ -48,9 +49,7 @@ export class DossierTemplateActionsComponent {
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
await this._router.navigate(['main', 'admin']);
|
||||
if (this.loadDossierTemplatesData) {
|
||||
this.loadDossierTemplatesData.emit();
|
||||
}
|
||||
this.loadDossierTemplatesData?.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<div class="actions">
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteDictionaryDialog($event)"
|
||||
*ngIf="permissionsService.isAdmin()"
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[tooltip]="'dictionary-overview.action.delete' | translate"
|
||||
icon="red:trash"
|
||||
tooltipPosition="below"
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openEditDictionaryDialog($event)"
|
||||
*ngIf="permissionsService.isAdmin()"
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[tooltip]="'dictionary-overview.action.edit' | translate"
|
||||
icon="red:edit"
|
||||
tooltipPosition="below"
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="fileInput.click()"
|
||||
*ngIf="permissionsService.isAdmin()"
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[tooltip]="'dictionary-overview.action.upload' | translate"
|
||||
icon="red:upload"
|
||||
tooltipPosition="below"
|
||||
@ -56,7 +56,7 @@
|
||||
<redaction-dictionary-manager
|
||||
#dictionaryManager
|
||||
(saveDictionary)="saveEntries($event)"
|
||||
[canEdit]="permissionsService.isAdmin()"
|
||||
[canEdit]="currentUser.isAdmin"
|
||||
[initialEntries]="entries"
|
||||
></redaction-dictionary-manager>
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { DictionaryControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { saveAs } from 'file-saver';
|
||||
@ -12,6 +11,7 @@ import { DictionarySaveService } from '@shared/services/dictionary-save.service'
|
||||
import { TypeValueWrapper } from '@models/file/type-value.wrapper';
|
||||
import { LoadingService } from '@services/loading.service';
|
||||
import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dictionary-overview-screen.component.html',
|
||||
@ -19,33 +19,32 @@ import { CircleButtonTypes } from '@iqser/common-ui';
|
||||
})
|
||||
export class DictionaryOverviewScreenComponent extends ComponentHasChanges implements OnInit {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
|
||||
entries: string[] = [];
|
||||
dictionary: TypeValueWrapper;
|
||||
|
||||
@ViewChild('dictionaryManager', { static: false })
|
||||
private readonly _dictionaryManager: DictionaryManagerComponent;
|
||||
@ViewChild('fileInput') private readonly _fileInput: ElementRef;
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _router: Router,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
protected readonly _translateService: TranslateService,
|
||||
private readonly _dictionarySaveService: DictionarySaveService,
|
||||
private readonly _dictionaryControllerService: DictionaryControllerService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _router: Router,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _loadingService: LoadingService
|
||||
private readonly _dictionaryControllerService: DictionaryControllerService
|
||||
) {
|
||||
super(_translateService);
|
||||
this._appStateService.activateDictionary(
|
||||
this._activatedRoute.snapshot.params.type,
|
||||
this._activatedRoute.snapshot.params.dossierTemplateId
|
||||
);
|
||||
}
|
||||
|
||||
get dictionary(): TypeValueWrapper {
|
||||
return this._appStateService.activeDictionary;
|
||||
this.dictionary = this._appStateService.activeDictionary;
|
||||
}
|
||||
|
||||
get hasChanges() {
|
||||
@ -67,6 +66,7 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
|
||||
async () => {
|
||||
this._loadingService.start();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.dictionary = this._appStateService.activeDictionary;
|
||||
this._loadingService.stop();
|
||||
}
|
||||
);
|
||||
|
||||
@ -89,7 +89,7 @@ export class DossierOverviewBulkActionsComponent {
|
||||
}
|
||||
|
||||
get canOcr() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canOcrFile(file), true);
|
||||
return this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true);
|
||||
}
|
||||
|
||||
get fileStatuses() {
|
||||
@ -112,7 +112,7 @@ export class DossierOverviewBulkActionsComponent {
|
||||
}
|
||||
|
||||
get canApprove() {
|
||||
return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canApprove(file), true);
|
||||
return this.selectedFiles.reduce((acc, file) => acc && file.canBeApproved, true);
|
||||
}
|
||||
|
||||
// Undo approval
|
||||
@ -163,7 +163,7 @@ export class DossierOverviewBulkActionsComponent {
|
||||
}
|
||||
|
||||
async reanalyse() {
|
||||
const fileIds = this.selectedFiles.filter(file => this._permissionsService.fileRequiresReanalysis(file)).map(file => file.fileId);
|
||||
const fileIds = this.selectedFiles.filter(file => file.analysisRequired).map(file => file.fileId);
|
||||
this._performBulkAction(
|
||||
this._reanalysisControllerService.reanalyzeFilesForDossier(fileIds, this._appStateService.activeDossier.dossierId)
|
||||
);
|
||||
|
||||
@ -88,9 +88,11 @@
|
||||
<iqser-circle-button
|
||||
(action)="setFileApproved($event)"
|
||||
*ngIf="readyForApproval"
|
||||
[disabled]="!canApprove"
|
||||
[disabled]="!fileStatus.canBeApproved"
|
||||
[tooltipPosition]="tooltipPosition"
|
||||
[tooltip]="canApprove ? ('dossier-overview.approve' | translate) : ('dossier-overview.approve-disabled' | translate)"
|
||||
[tooltip]="
|
||||
fileStatus.canBeApproved ? ('dossier-overview.approve' | translate) : ('dossier-overview.approve-disabled' | translate)
|
||||
"
|
||||
[type]="buttonType"
|
||||
icon="red:approved"
|
||||
></iqser-circle-button>
|
||||
@ -107,7 +109,7 @@
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="ocrFile($event)"
|
||||
*ngIf="canOcr"
|
||||
*ngIf="fileStatus.canBeOCRed"
|
||||
[tooltipPosition]="tooltipPosition"
|
||||
[tooltip]="'dossier-overview.ocr-file' | translate"
|
||||
[type]="buttonType"
|
||||
@ -140,7 +142,7 @@
|
||||
<mat-slide-toggle
|
||||
(change)="toggleAnalysis()"
|
||||
(click)="$event.stopPropagation()"
|
||||
[checked]="!fileStatus?.isExcluded"
|
||||
[checked]="!fileStatus?.excluded"
|
||||
[class.mr-24]="screen === 'dossier-overview'"
|
||||
[disabled]="!canToggleAnalysis"
|
||||
[matTooltipPosition]="tooltipPosition"
|
||||
|
||||
@ -39,10 +39,8 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
|
||||
canAssign: boolean;
|
||||
canDelete: boolean;
|
||||
canReanalyse: boolean;
|
||||
canOcr: boolean;
|
||||
canSetToUnderReview: boolean;
|
||||
canSetToUnderApproval: boolean;
|
||||
canApprove: boolean;
|
||||
readyForApproval: boolean;
|
||||
canToggleAnalysis: boolean;
|
||||
|
||||
@ -63,7 +61,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
|
||||
return _('file-preview.toggle-analysis.only-managers');
|
||||
}
|
||||
|
||||
return this.fileStatus?.isExcluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
|
||||
return this.fileStatus?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
|
||||
}
|
||||
|
||||
private _setup() {
|
||||
@ -81,10 +79,8 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
|
||||
this.canAssign = this.permissionsService.canAssignUser(this.fileStatus);
|
||||
this.canDelete = this.permissionsService.canDeleteFile(this.fileStatus);
|
||||
this.canReanalyse = this.permissionsService.canReanalyseFile(this.fileStatus);
|
||||
this.canOcr = this.permissionsService.canOcrFile(this.fileStatus);
|
||||
this.canSetToUnderReview = this.permissionsService.canSetUnderReview(this.fileStatus);
|
||||
this.canSetToUnderApproval = this.permissionsService.canSetUnderApproval(this.fileStatus);
|
||||
this.canApprove = this.permissionsService.canApprove(this.fileStatus);
|
||||
this.readyForApproval = this.permissionsService.isReadyForApproval(this.fileStatus);
|
||||
this.canToggleAnalysis = this.permissionsService.canToggleAnalysis(this.fileStatus);
|
||||
}
|
||||
@ -206,6 +202,6 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
|
||||
async toggleAnalysis() {
|
||||
await this._fileActionService.toggleAnalysis(this.fileStatus).toPromise();
|
||||
await this.appStateService.getFiles();
|
||||
this.actionPerformed.emit(this.fileStatus?.isExcluded ? 'enable-analysis' : 'disable-analysis');
|
||||
this.actionPerformed.emit(this.fileStatus?.excluded ? 'enable-analysis' : 'disable-analysis');
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
|
||||
@ -12,7 +11,7 @@ import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
export class NeedsWorkBadgeComponent {
|
||||
@Input() needsWorkInput: FileStatusWrapper | DossierWrapper;
|
||||
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _permissionsService: PermissionsService) {}
|
||||
constructor(private readonly _appStateService: AppStateService) {}
|
||||
|
||||
get suggestionColor() {
|
||||
return this._getDictionaryColor('suggestion');
|
||||
@ -52,9 +51,9 @@ export class NeedsWorkBadgeComponent {
|
||||
|
||||
reanalysisRequired() {
|
||||
if (this.needsWorkInput instanceof DossierWrapper) {
|
||||
return this._permissionsService.dossierReanalysisRequired(this.needsWorkInput);
|
||||
return this.needsWorkInput.reanalysisRequired;
|
||||
} else {
|
||||
return this._permissionsService.fileRequiresReanalysis(this.needsWorkInput);
|
||||
return this.needsWorkInput.analysisRequired;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -251,8 +251,7 @@ export class DossierListingScreenComponent
|
||||
filterTemplate: this._needsWorkTemplate,
|
||||
filters: needsWorkFilters.sort(RedactionFilterSorter.byKey),
|
||||
checker: annotationFilterChecker,
|
||||
matchAll: true,
|
||||
checkerArgs: [this.permissionsService]
|
||||
matchAll: true
|
||||
});
|
||||
|
||||
const dossierTemplateFilters = [...allDistinctDossierTemplates].map<NestedFilter>(id => ({
|
||||
|
||||
@ -57,9 +57,9 @@
|
||||
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
|
||||
<div
|
||||
*cdkVirtualFor="let fileStatus of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
|
||||
[class.disabled]="fileStatus.isExcluded"
|
||||
[class.disabled]="fileStatus.excluded"
|
||||
[class.last-opened]="isLastOpenedFile(fileStatus.fileId)"
|
||||
[class.pointer]="permissionsService.canOpenFile(fileStatus)"
|
||||
[class.pointer]="fileStatus.canBeOpened"
|
||||
[routerLink]="fileLink(fileStatus)"
|
||||
class="table-item"
|
||||
>
|
||||
@ -93,15 +93,15 @@
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:exclude-pages"></mat-icon>
|
||||
{{ fileStatus.numberOfExcludedPages }}
|
||||
{{ fileStatus.excludedPagesCount }}
|
||||
</div>
|
||||
<div
|
||||
*ngIf="fileStatus.ocrTime"
|
||||
*ngIf="fileStatus.lastOCRTime"
|
||||
[matTooltipPosition]="'above'"
|
||||
[matTooltip]="'dossier-overview.ocr-performed' | translate"
|
||||
>
|
||||
<mat-icon svgIcon="red:ocr"></mat-icon>
|
||||
{{ fileStatus.ocrTime | date: 'mediumDate' }}
|
||||
{{ fileStatus.lastOCRTime | date: 'mediumDate' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -144,7 +144,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
.subscribe();
|
||||
|
||||
this.dossierAttributes = await this._dossierAttributesService.getValues(this.currentDossier);
|
||||
this.searchService.setSearchKey('searchField');
|
||||
this.searchService.setSearchKey('filename');
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this._loadingService.stop();
|
||||
@ -210,9 +210,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
}
|
||||
|
||||
fileLink(fileStatus: FileStatusWrapper) {
|
||||
return this.permissionsService.canOpenFile(fileStatus)
|
||||
? [`/main/dossiers/${this.currentDossier.dossierId}/file/${fileStatus.fileId}`]
|
||||
: [];
|
||||
return fileStatus.canBeOpened ? [`/main/dossiers/${this.currentDossier.dossierId}/file/${fileStatus.fileId}`] : [];
|
||||
}
|
||||
|
||||
bulkActionPerformed() {
|
||||
@ -274,7 +272,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
allDistinctFileStatusWrapper.add(file.status);
|
||||
allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY'));
|
||||
|
||||
if (this.permissionsService.fileRequiresReanalysis(file)) allDistinctNeedsWork.add('analysis');
|
||||
if (file.analysisRequired) allDistinctNeedsWork.add('analysis');
|
||||
if (file.hintsOnly) allDistinctNeedsWork.add('hint');
|
||||
if (file.hasRedactions) allDistinctNeedsWork.add('redaction');
|
||||
if (file.hasRequests) allDistinctNeedsWork.add('suggestion');
|
||||
@ -331,8 +329,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
|
||||
filterTemplate: this._needsWorkTemplate,
|
||||
filters: needsWorkFilters.sort(RedactionFilterSorter.byKey),
|
||||
checker: annotationFilterChecker,
|
||||
matchAll: true,
|
||||
checkerArgs: [this.permissionsService]
|
||||
matchAll: true
|
||||
});
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
</div>
|
||||
|
||||
<div class="flex-1 actions-container">
|
||||
<ng-container *ngIf="!appStateService.activeFile.isExcluded">
|
||||
<ng-container *ngIf="!appStateService.activeFile.excluded">
|
||||
<ng-container *ngIf="!appStateService.activeFile.isProcessing">
|
||||
<iqser-status-bar [configs]="statusBarConfig" [small]="true"></iqser-status-bar>
|
||||
|
||||
@ -148,7 +148,7 @@
|
||||
|
||||
<div class="right-container">
|
||||
<redaction-empty-state
|
||||
*ngIf="appStateService.activeFile.isExcluded && !viewDocumentInfo && !excludePages"
|
||||
*ngIf="appStateService.activeFile.excluded && !viewDocumentInfo && !excludePages"
|
||||
[horizontalPadding]="40"
|
||||
[text]="'file-preview.tabs.is-excluded' | translate"
|
||||
icon="red:needs-work"
|
||||
@ -168,7 +168,7 @@
|
||||
(selectAnnotations)="selectAnnotations($event)"
|
||||
(selectPage)="selectPage($event)"
|
||||
(toggleSkipped)="toggleSkipped($event)"
|
||||
*ngIf="!appStateService.activeFile.isExcluded"
|
||||
*ngIf="!appStateService.activeFile.excluded"
|
||||
[(shouldDeselectAnnotationsOnPageChange)]="shouldDeselectAnnotationsOnPageChange"
|
||||
[activeViewerPage]="activeViewerPage"
|
||||
[annotationActionsTemplate]="annotationActionsTemplate"
|
||||
|
||||
@ -131,11 +131,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
get canSwitchToRedactedView() {
|
||||
return this.fileData && !this.permissionsService.fileRequiresReanalysis() && !this.fileData.fileStatus.isExcluded;
|
||||
return this.fileData && !this.fileData.fileStatus.analysisRequired && !this.fileData.fileStatus.excluded;
|
||||
}
|
||||
|
||||
get canSwitchToDeltaView() {
|
||||
return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.fileStatus.isExcluded;
|
||||
return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.fileStatus.excluded;
|
||||
}
|
||||
|
||||
get canAssign(): boolean {
|
||||
@ -231,7 +231,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
async ngOnAttach(previousRoute: ActivatedRouteSnapshot) {
|
||||
if (!this.permissionsService.canOpenFile(this.appStateService.activeFile)) {
|
||||
if (!this.appStateService.activeFile.canBeOpened) {
|
||||
await this._router.navigate(['/main/dossiers/' + this.dossierId]);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ export class FileActionService {
|
||||
return this._reanalysisControllerService.toggleAnalysis(
|
||||
fileStatusWrapper.dossierId,
|
||||
fileStatusWrapper.fileId,
|
||||
!fileStatusWrapper.isExcluded
|
||||
!fileStatusWrapper.excluded
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { handleCheckedValue, NestedFilter } from '@iqser/common-ui';
|
||||
|
||||
export function handleFilterDelta(oldFilters: NestedFilter[], newFilters: NestedFilter[], allFilters: NestedFilter[]) {
|
||||
@ -46,17 +45,13 @@ export function handleFilterDelta(oldFilters: NestedFilter[], newFilters: Nested
|
||||
});
|
||||
}
|
||||
|
||||
export const annotationFilterChecker = (
|
||||
input: FileStatusWrapper | DossierWrapper,
|
||||
filter: NestedFilter,
|
||||
permissionsService: PermissionsService
|
||||
) => {
|
||||
export const annotationFilterChecker = (input: FileStatusWrapper | DossierWrapper, filter: NestedFilter) => {
|
||||
switch (filter.key) {
|
||||
case 'analysis': {
|
||||
if (input instanceof DossierWrapper) {
|
||||
return permissionsService.dossierReanalysisRequired(input);
|
||||
return input.reanalysisRequired;
|
||||
} else {
|
||||
return permissionsService.fileRequiresReanalysis(input);
|
||||
return input.analysisRequired;
|
||||
}
|
||||
}
|
||||
case 'suggestion': {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { UserService, UserWrapper } from './user.service';
|
||||
import { UserService } from './user.service';
|
||||
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
|
||||
import { Comment } from '@redaction/red-ui-http';
|
||||
import { DossierWrapper } from '@state/model/dossier.wrapper';
|
||||
@ -23,16 +23,8 @@ export class PermissionsService {
|
||||
return this.isFileReviewer(fileStatus) || this.isApprover();
|
||||
}
|
||||
|
||||
dossierReanalysisRequired(dossier: DossierWrapper): boolean {
|
||||
for (const file of dossier.files) if (this.fileRequiresReanalysis(file)) return true;
|
||||
}
|
||||
|
||||
fileRequiresReanalysis(fileStatus = this._activeFile): boolean {
|
||||
return fileStatus.analysisRequired;
|
||||
}
|
||||
|
||||
displayReanalyseBtn(dossier = this._activeDossier): boolean {
|
||||
return this.isApprover(dossier) && dossier.files.filter(file => this.fileRequiresReanalysis(file)).length > 0;
|
||||
return this.isApprover(dossier) && dossier.files.filter(file => file.analysisRequired).length > 0;
|
||||
}
|
||||
|
||||
canToggleAnalysis(fileStatus: FileStatusWrapper): boolean {
|
||||
@ -41,7 +33,7 @@ export class PermissionsService {
|
||||
|
||||
canReanalyseFile(fileStatus = this._activeFile): boolean {
|
||||
return (
|
||||
(this.fileRequiresReanalysis(fileStatus) && (this.isReviewerOrApprover(fileStatus) || fileStatus.isUnassigned)) ||
|
||||
(fileStatus.analysisRequired && (this.isReviewerOrApprover(fileStatus) || fileStatus.isUnassigned)) ||
|
||||
(fileStatus.isError && fileStatus.isUnassigned)
|
||||
);
|
||||
}
|
||||
@ -54,10 +46,6 @@ export class PermissionsService {
|
||||
return this.isOwner(dossier) || fileStatus.isUnassigned;
|
||||
}
|
||||
|
||||
isApprovedOrUnderApproval(fileStatus = this._activeFile): boolean {
|
||||
return fileStatus.isApprovedOrUnderApproval;
|
||||
}
|
||||
|
||||
canAssignToSelf(fileStatus = this._activeFile): boolean {
|
||||
const precondition = this.isDossierMember() && !fileStatus.isProcessing && !fileStatus.isError && !fileStatus.isApproved;
|
||||
|
||||
@ -96,10 +84,6 @@ export class PermissionsService {
|
||||
return this.canSetUnderReview(fileStatus);
|
||||
}
|
||||
|
||||
canApprove(fileStatus = this._activeFile): boolean {
|
||||
return !fileStatus?.analysisRequired && !fileStatus.hasRequests;
|
||||
}
|
||||
|
||||
canSetUnderApproval(fileStatus = this._activeFile): boolean {
|
||||
return fileStatus?.isUnderReview && this.isReviewerOrApprover(fileStatus);
|
||||
}
|
||||
@ -124,18 +108,10 @@ export class PermissionsService {
|
||||
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus?.status) && this.isFileReviewer(fileStatus);
|
||||
}
|
||||
|
||||
canOpenFile(fileStatus = this._activeFile): boolean {
|
||||
return !fileStatus?.isError && !fileStatus?.isPending;
|
||||
}
|
||||
|
||||
canUndoApproval(fileStatus = this._activeFile): boolean {
|
||||
return fileStatus?.isApproved && this.isApprover();
|
||||
}
|
||||
|
||||
canUndoUnderApproval(fileStatus = this._activeFile): boolean {
|
||||
return fileStatus?.isUnderApproval && this.isDossierMember();
|
||||
}
|
||||
|
||||
canMarkPagesAsViewed(fileStatus = this._activeFile): boolean {
|
||||
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus?.status) && this.isFileReviewer(fileStatus);
|
||||
}
|
||||
@ -155,16 +131,6 @@ export class PermissionsService {
|
||||
return user.isAdmin;
|
||||
}
|
||||
|
||||
canOcrFile(fileStatus = this._activeFile): boolean {
|
||||
return (
|
||||
!fileStatus.isExcluded && !fileStatus.ocrTime && ['UNASSIGNED', 'UNDER_REVIEW', 'UNDER_APPROVAL'].includes(fileStatus.status)
|
||||
);
|
||||
}
|
||||
|
||||
canManageUsers(user: UserWrapper = this._userService.currentUser): boolean {
|
||||
return user.isUserAdmin;
|
||||
}
|
||||
|
||||
canAddComment(fileStatus = this._activeFile): boolean {
|
||||
return (this.isFileReviewer(fileStatus) || this.isApprover()) && !fileStatus.isApproved;
|
||||
}
|
||||
|
||||
@ -243,7 +243,6 @@ export class AppStateService {
|
||||
const activeFileWrapper = new FileStatusWrapper(
|
||||
activeFile,
|
||||
this._userService.getNameForId(activeFile.currentReviewer),
|
||||
this.activeDossierTemplateId,
|
||||
this._appState.fileAttributesConfig[this.activeDossierTemplateId]
|
||||
);
|
||||
this.activeDossier.files = this.activeDossier?.files.map(file =>
|
||||
@ -669,7 +668,6 @@ export class AppStateService {
|
||||
const fileStatusWrapper = new FileStatusWrapper(
|
||||
file,
|
||||
this._userService.getNameForId(file.currentReviewer),
|
||||
dossier.dossierTemplateId,
|
||||
this._appState.fileAttributesConfig[dossier.dossierTemplateId]
|
||||
);
|
||||
if (JSON.stringify(oldFile) !== JSON.stringify(fileStatusWrapper)) {
|
||||
@ -687,7 +685,6 @@ export class AppStateService {
|
||||
const fsw = new FileStatusWrapper(
|
||||
file,
|
||||
this._userService.getNameForId(file.currentReviewer),
|
||||
dossier.dossierTemplateId,
|
||||
this._appState.fileAttributesConfig[dossier.dossierTemplateId]
|
||||
);
|
||||
fileStatusChangedEvent.push(fsw);
|
||||
@ -699,7 +696,6 @@ export class AppStateService {
|
||||
new FileStatusWrapper(
|
||||
f,
|
||||
this._userService.getNameForId(f.currentReviewer),
|
||||
dossier.dossierTemplateId,
|
||||
this._appState.fileAttributesConfig[dossier.dossierTemplateId]
|
||||
)
|
||||
);
|
||||
|
||||
@ -24,6 +24,7 @@ export class DossierWrapper implements Dossier {
|
||||
readonly hasMoreThanOneReviewer = this.memberIds.length > 1;
|
||||
readonly memberCount = this.memberIds.length;
|
||||
|
||||
reanalysisRequired = this._files.some(file => file.analysisRequired);
|
||||
hasFiles = this._files.length > 0;
|
||||
filesLength = this._files.length;
|
||||
|
||||
@ -81,5 +82,6 @@ export class DossierWrapper implements Dossier {
|
||||
this.hasNone = !this.hasRequests && !this.hasRedactions && !this.hintsOnly;
|
||||
this.hasFiles = this._files.length > 0;
|
||||
this.filesLength = this._files.length;
|
||||
this.reanalysisRequired = this._files.some(file => file.analysisRequired);
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,5 +169,5 @@ export namespace FileStatus {
|
||||
UNDERREVIEW: 'UNDER_REVIEW' as StatusEnum,
|
||||
UNPROCESSED: 'UNPROCESSED' as StatusEnum,
|
||||
INDEXING: 'INDEXING' as StatusEnum
|
||||
};
|
||||
} as const;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user