DM-311 simple workflow

This commit is contained in:
Dan Percic 2023-06-27 20:23:02 +03:00
parent e4c355cb0a
commit 2dca5bf3f5
4 changed files with 153 additions and 119 deletions

View File

@ -49,11 +49,11 @@ import { Roles } from '@users/roles';
@Injectable()
export class ConfigService {
readonly listingMode$: Observable<ListingMode>;
readonly #dossierId = getParam(DOSSIER_ID);
readonly #currentUser = getCurrentUser<User>();
readonly #config = getConfig<AppConfig>();
readonly #listingMode$: BehaviorSubject<ListingMode>;
readonly listingMode$: Observable<ListingMode>;
constructor(
private readonly _permissionsService: PermissionsService,
@ -87,63 +87,10 @@ export class ConfigService {
}
workflowConfig(): WorkflowConfig<File, WorkflowFileStatus> {
const { NEW, UNDER_REVIEW, UNDER_APPROVAL, APPROVED } = WorkflowFileStatuses;
const newColumn: WorkflowColumn<File, typeof NEW> = {
label: workflowFileStatusTranslations[NEW],
key: NEW,
enterFn: files => this._bulkActionsService.setToNew(files),
enterPredicate: files => this._permissionsService.canSetToNew(files, this.#dossier),
color: '#D3D5DA',
entities: new BehaviorSubject([]),
};
const underReviewColumn: WorkflowColumn<File, typeof UNDER_REVIEW> = {
label: workflowFileStatusTranslations[UNDER_REVIEW],
enterFn: async files => {
const statuses: WorkflowFileStatus[] = [UNDER_APPROVAL, APPROVED];
if (statuses.includes(files[0].workflowStatus)) {
await this._bulkActionsService.backToUnderReview(files);
} else {
await this._bulkActionsService.assignToMe(files);
}
},
enterPredicate: files => {
const dossier = this.#dossier;
return (
this._permissionsService.canSetUnderReview(files, dossier) ||
this._permissionsService.canAssignToSelf(files, dossier) ||
this._permissionsService.canAssignUser(files, dossier) ||
this._permissionsService.canUndoApproval(files, dossier)
);
},
key: UNDER_REVIEW,
color: '#FDBD00',
entities: new BehaviorSubject([]),
};
const underApprovalColumn: WorkflowColumn<File, typeof UNDER_APPROVAL> = {
label: workflowFileStatusTranslations[UNDER_APPROVAL],
enterFn: files => this._bulkActionsService.setToUnderApproval(files),
enterPredicate: files => {
const dossier = this.#dossier;
return (
this._permissionsService.canSetUnderApproval(files, dossier) || this._permissionsService.canUndoApproval(files, dossier)
);
},
key: UNDER_APPROVAL,
color: '#374C81',
entities: new BehaviorSubject([]),
};
const approvedColumn: WorkflowColumn<File, typeof APPROVED> = {
label: workflowFileStatusTranslations[APPROVED],
enterFn: files => this._bulkActionsService.approve(files),
enterPredicate: files => this._permissionsService.canBeApproved(files, this.#dossier),
key: APPROVED,
color: '#48C9F7',
entities: new BehaviorSubject([]),
};
const newColumn = this.#getNewColumn();
const underReviewColumn = this.#getUnderReviewColumn();
const underApprovalColumn = this.#getUnderApprovalColumn();
const approvedColumn = this.#getApprovedColumn();
return {
columnIdentifierFn: entity => entity.workflowStatus,
@ -152,12 +99,24 @@ export class ConfigService {
};
}
workflowConfigRss(): WorkflowConfig<File, WorkflowFileStatus> {
const newColumn = this.#getNewColumn();
const underReviewColumn = this.#getUnderReviewColumn();
const approvedColumn = this.#getApprovedColumn();
return {
columnIdentifierFn: entity => entity.workflowStatus,
itemVersionFn: (entity: File) => `${entity.lastUpdated}-${entity.numberOfAnalyses}`,
columns: [newColumn, underReviewColumn, approvedColumn],
};
}
actionConfig(dossierId: string, disabled$: Observable<boolean>): List<ActionConfig> {
return [
{
id: 'editDossier',
label: this._translateService.instant('dossier-overview.header-actions.edit'),
action: () => this._openEditDossierDialog(dossierId),
action: () => this.#openEditDossierDialog(dossierId),
icon: 'iqser:edit',
hide: !this.#currentUser.isManager && !this._iqserPermissionsService.has(Roles.dossiers.edit),
helpModeKey: 'edit_dossier_in_dossier',
@ -306,7 +265,7 @@ export class ConfigService {
);
}
this._sortByName([...allDistinctPeople]).forEach(userId => {
this.#sortByName([...allDistinctPeople]).forEach(userId => {
peopleFilters.push(
new NestedFilter({
id: userId,
@ -376,7 +335,7 @@ export class ConfigService {
filterGroups.push({
slug: 'quickFilters',
filters: this._quickFilters(entities),
filters: this.#quickFilters(entities),
checker: (file: File) =>
checkedRequiredFilters().reduce((acc, f) => acc && f.checker(file), true) &&
(checkedNotRequiredFilters().length === 0 || checkedNotRequiredFilters().reduce((acc, f) => acc || f.checker(file), false)),
@ -410,7 +369,71 @@ export class ConfigService {
_assignedToOthersChecker = (file: File) => file.assignee && file.assignee !== this._userService.currentUser.id;
private _quickFilters(entities: File[]): NestedFilter[] {
#getNewColumn(): WorkflowColumn<File, typeof WorkflowFileStatuses.NEW> {
return {
label: workflowFileStatusTranslations[WorkflowFileStatuses.NEW],
key: WorkflowFileStatuses.NEW,
enterFn: files => this._bulkActionsService.setToNew(files),
enterPredicate: files => this._permissionsService.canSetToNew(files, this.#dossier),
color: '#D3D5DA',
entities: new BehaviorSubject([]),
};
}
#getUnderReviewColumn(): WorkflowColumn<File, typeof WorkflowFileStatuses.UNDER_REVIEW> {
return {
label: workflowFileStatusTranslations[WorkflowFileStatuses.UNDER_REVIEW],
enterFn: async files => {
const statuses: WorkflowFileStatus[] = [WorkflowFileStatuses.UNDER_APPROVAL, WorkflowFileStatuses.APPROVED];
if (statuses.includes(files[0].workflowStatus)) {
await this._bulkActionsService.backToUnderReview(files);
} else {
await this._bulkActionsService.assignToMe(files);
}
},
enterPredicate: files => {
const dossier = this.#dossier;
return (
this._permissionsService.canSetUnderReview(files, dossier) ||
this._permissionsService.canAssignToSelf(files, dossier) ||
this._permissionsService.canAssignUser(files, dossier) ||
this._permissionsService.canUndoApproval(files, dossier)
);
},
key: WorkflowFileStatuses.UNDER_REVIEW,
color: '#FDBD00',
entities: new BehaviorSubject([]),
};
}
#getUnderApprovalColumn(): WorkflowColumn<File, typeof WorkflowFileStatuses.UNDER_APPROVAL> {
return {
label: workflowFileStatusTranslations[WorkflowFileStatuses.UNDER_APPROVAL],
enterFn: files => this._bulkActionsService.setToUnderApproval(files),
enterPredicate: files => {
const dossier = this.#dossier;
return (
this._permissionsService.canSetUnderApproval(files, dossier) || this._permissionsService.canUndoApproval(files, dossier)
);
},
key: WorkflowFileStatuses.UNDER_APPROVAL,
color: '#374C81',
entities: new BehaviorSubject([]),
};
}
#getApprovedColumn(): WorkflowColumn<File, typeof WorkflowFileStatuses.APPROVED> {
return {
label: workflowFileStatusTranslations[WorkflowFileStatuses.APPROVED],
enterFn: files => this._bulkActionsService.approve(files),
enterPredicate: files => this._permissionsService.canBeApproved(files, this.#dossier),
key: WorkflowFileStatuses.APPROVED,
color: '#48C9F7',
entities: new BehaviorSubject([]),
};
}
#quickFilters(entities: File[]): NestedFilter[] {
const recentPeriod = this.#config.RECENT_PERIOD_IN_HOURS;
return [
{
@ -447,11 +470,11 @@ export class ConfigService {
].map(filter => new NestedFilter(filter));
}
private _openEditDossierDialog(dossierId: string) {
#openEditDossierDialog(dossierId: string) {
this._dialogService.openDialog('editDossier', { dossierId });
}
private _sortByName(ids: string[]) {
#sortByName(ids: string[]) {
return ids.sort((a, b) => this._userService.getName(a).localeCompare(this._userService.getName(b)));
}
}

View File

@ -20,6 +20,7 @@ import {
CustomError,
ErrorService,
getParam,
IqserPermissionsService,
ListingComponent,
ListingModes,
listingProvidersFactory,
@ -44,6 +45,7 @@ import { FilesService } from '@services/files/files.service';
import { BulkActionsService } from '../services/bulk-actions.service';
import { DossiersService } from '@services/dossiers/dossiers.service';
import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider';
import { Roles } from '@users/roles';
@Component({
templateUrl: './dossier-overview-screen.component.html',
@ -51,10 +53,15 @@ import { dossiersServiceProvider } from '@services/entity-services/dossiers.serv
providers: [...listingProvidersFactory(DossierOverviewScreenComponent), ConfigService, BulkActionsService, dossiersServiceProvider],
})
export class DossierOverviewScreenComponent extends ListingComponent<File> implements OnInit, OnAttach, OnDetach, OnDestroy {
#dossier: Dossier;
@ViewChild('needsWorkFilterTemplate', { read: TemplateRef, static: true })
private readonly _needsWorkFilterTemplate: TemplateRef<unknown>;
@ViewChild('fileInput', { static: true }) private readonly _fileInput: ElementRef;
@ViewChild(TableComponent) private readonly _tableComponent: TableComponent<Dossier>;
private _fileAttributeConfigs: IFileAttributeConfig[];
readonly listingModes = ListingModes;
readonly circleButtonTypes = CircleButtonTypes;
readonly tableHeaderLabel = _('dossier-overview.table-header.title');
collapsedDetails = false;
dossierAttributes: DossierAttributeWithValue[] = [];
tableColumnConfigs: readonly TableColumnConfig<File>[];
@ -70,18 +77,13 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
readonly dossierId = getParam(DOSSIER_ID);
readonly workflowConfig: WorkflowConfig<File, WorkflowFileStatus>;
readonly dossierAttributes$: Observable<DossierAttributeConfig[]>;
#dossier: Dossier;
@ViewChild('needsWorkFilterTemplate', { read: TemplateRef, static: true })
private readonly _needsWorkFilterTemplate: TemplateRef<unknown>;
@ViewChild('fileInput', { static: true }) private readonly _fileInput: ElementRef;
@ViewChild(TableComponent) private readonly _tableComponent: TableComponent<Dossier>;
private _fileAttributeConfigs: IFileAttributeConfig[];
constructor(
readonly configService: ConfigService,
private readonly _errorService: ErrorService,
private readonly _filesService: FilesService,
readonly permissionsService: PermissionsService,
iqserPermissionsService: IqserPermissionsService,
private readonly _loadingService: LoadingService,
private readonly _fileMapService: FilesMapService,
private readonly _dossiersService: DossiersService,
@ -97,7 +99,8 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
this.dossier$ = _dossiersService.getEntityChanged$(this.dossierId).pipe(tap(dossier => (this.#dossier = dossier)));
this.dossierAttributes$ = this._dossierAttributesService.all$.pipe(tap(() => this.#updateDossierAttributes()));
this.#dossier = _dossiersService.find(this.dossierId);
this.workflowConfig = configService.workflowConfig();
const hasRss = iqserPermissionsService.has(Roles.getRss);
this.workflowConfig = hasRss ? configService.workflowConfigRss() : configService.workflowConfig();
this.files$ = merge(this.#files$, this.#dossierFilesChange$).pipe(shareLast());
this.#updateFileAttributes();
}

View File

@ -55,7 +55,7 @@ export class PermissionsService {
entities.length &&
this.isAdmin() &&
this._iqserPermissionsService.has(Roles.dictionaryTypes.delete) &&
entities.reduce((acc, _entity) => this._canDeleteEntity(_entity) && acc, true)
entities.reduce((acc, _entity) => this.#canDeleteEntity(_entity) && acc, true)
);
}
@ -94,7 +94,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
const sameState = new Set(files.map(f => f.excluded)).size === 1;
return sameState && files.reduce((acc, _file) => this._canToggleAnalysis(_file, dossier) && acc, true);
return sameState && files.reduce((acc, _file) => this.#canToggleAnalysis(_file, dossier) && acc, true);
}
showToggleAnalysis(dossier: Dossier): boolean {
@ -105,21 +105,21 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.reanalyze) &&
files.reduce((acc, _file) => this._canReanalyseFile(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canReanalyseFile(_file, dossier) && acc, true)
);
}
canEnableAutoAnalysis(files: File[], dossier: Dossier): boolean {
return (
this._iqserPermissionsService.has(Roles.files.reanalyze) &&
files.reduce((acc, _file) => this._canEnableAutoAnalysis(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canEnableAutoAnalysis(_file, dossier) && acc, true)
);
}
canDisableAutoAnalysis(files: File[], dossier: Dossier): boolean {
return (
this._iqserPermissionsService.has(Roles.files.reanalyze) &&
files.reduce((acc, _file) => this._canDisableAutoAnalysis(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canDisableAutoAnalysis(_file, dossier) && acc, true)
);
}
@ -131,7 +131,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.delete) &&
files.reduce((acc, _file) => this._canSoftDeleteFile(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canSoftDeleteFile(_file, dossier) && acc, true)
);
}
@ -139,7 +139,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.delete) &&
files.reduce((acc, _file) => this._canRestoreFile(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canRestoreFile(_file, dossier) && acc, true)
);
}
@ -147,7 +147,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.delete) &&
files.reduce((acc, _file) => this._canHardDeleteFile(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canHardDeleteFile(_file, dossier) && acc, true)
);
}
@ -155,7 +155,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.reanalyze) &&
files.reduce((acc, _file) => this._canOcrFile(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canOcrFile(_file, dossier) && acc, true)
);
}
@ -163,7 +163,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.setReviewer) &&
files.reduce((acc, _file) => this._canAssignToSelf(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canAssignToSelf(_file, dossier) && acc, true)
);
}
@ -171,7 +171,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.setReviewer) &&
files.reduce((acc, _file) => this._canAssignUser(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canAssignUser(_file, dossier) && acc, true)
);
}
@ -179,25 +179,25 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.setReviewer) &&
files.reduce((acc, _file) => this._canUnassignUser(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canUnassignUser(_file, dossier) && acc, true)
);
}
canSetToNew(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canSetToNew(_file, dossier) && acc, true);
return files.reduce((acc, _file) => this.#canSetToNew(_file, dossier) && acc, true);
}
canSetUnderReview(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file;
return files.reduce((acc, _file) => this._canSetUnderReview(_file, dossier) && acc, true);
return files.reduce((acc, _file) => this.#canSetUnderReview(_file, dossier) && acc, true);
}
canBeApproved(file: File | File[], dossier: Dossier): boolean {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.setApproved) &&
files.reduce((acc, _file) => this._canBeApproved(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canBeApproved(_file, dossier) && acc, true)
);
}
@ -205,7 +205,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.setApproved) &&
files.reduce((acc, _file) => this._isReadyForApproval(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#isReadyForApproval(_file, dossier) && acc, true)
);
}
@ -213,7 +213,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.setUnderApproval) &&
files.reduce((acc, _file) => this._canSetUnderApproval(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canSetUnderApproval(_file, dossier) && acc, true)
);
}
@ -247,7 +247,7 @@ export class PermissionsService {
const files = file instanceof File ? [file] : file;
return (
this._iqserPermissionsService.has(Roles.files.setApproved) &&
files.reduce((acc, _file) => this._canUndoApproval(_file, dossier) && acc, true)
files.reduce((acc, _file) => this.#canUndoApproval(_file, dossier) && acc, true)
);
}
@ -354,11 +354,11 @@ export class PermissionsService {
return this._iqserPermissionsService.has(Roles.rules.write) && this.isAdmin();
}
private _canDeleteEntity(entity: Dictionary): boolean {
#canDeleteEntity(entity: Dictionary): boolean {
return !entity.systemManaged;
}
private _canOcrFile(file: File, dossier: Dossier): boolean {
#canOcrFile(file: File, dossier: Dossier): boolean {
return (
dossier.isActive &&
!!file.lastProcessed &&
@ -367,7 +367,7 @@ export class PermissionsService {
);
}
private _canToggleAnalysis(file: File, dossier: Dossier): boolean {
#canToggleAnalysis(file: File, dossier: Dossier): boolean {
return (
dossier.isActive &&
!!file.lastProcessed &&
@ -376,78 +376,86 @@ export class PermissionsService {
);
}
private _canSoftDeleteFile(file: File, dossier: Dossier): boolean {
#canSoftDeleteFile(file: File, dossier: Dossier): boolean {
return dossier.isActive && (this.isAssigneeOrApprover(file, dossier) || (!file.assignee && this.isDossierMember(dossier)));
}
private _canRestoreFile(file: File, dossier: Dossier): boolean {
#canRestoreFile(file: File, dossier: Dossier): boolean {
return this.isAssigneeOrApprover(file, dossier);
}
private _canHardDeleteFile(file: File, dossier: Dossier): boolean {
#canHardDeleteFile(file: File, dossier: Dossier): boolean {
return this.isAssigneeOrApprover(file, dossier) || (!file.assignee && this.isDossierMember(dossier));
}
private _canReanalyseFile(file: File, dossier: Dossier): boolean {
#canReanalyseFile(file: File, dossier: Dossier): boolean {
return dossier.isActive && this.isAssigneeOrApprover(file, dossier) && file.analysisRequired;
}
private _canEnableAutoAnalysis(file: File, dossier: Dossier): boolean {
#canEnableAutoAnalysis(file: File, dossier: Dossier): boolean {
return (
dossier.isActive && file.excludedFromAutomaticAnalysis && this.isFileAssignee(file) && !file.isApproved && !!file.lastProcessed
);
}
private _canDisableAutoAnalysis(file: File, dossier: Dossier): boolean {
#canDisableAutoAnalysis(file: File, dossier: Dossier): boolean {
return (
dossier.isActive && !file.excludedFromAutomaticAnalysis && this.isFileAssignee(file) && !file.isApproved && !!file.lastProcessed
);
}
/** UNDER_REVIEW => NEW */
private _canSetToNew(file: File, dossier: Dossier): boolean {
#canSetToNew(file: File, dossier: Dossier): boolean {
return dossier.isActive && file.isUnderReview && this.isAssigneeOrApprover(file, dossier);
}
/** UNDER_REVIEW => UNDER_APPROVAL */
private _canSetUnderApproval(file: File, dossier: Dossier): boolean {
return dossier.isActive && file.isUnderReview && this.isAssigneeOrApprover(file, dossier);
#canSetUnderApproval(file: File, dossier: Dossier): boolean {
const hasRss = this._iqserPermissionsService.has(Roles.getRss);
const fileCanBeSetUnderApproval = !hasRss && file.isUnderReview;
return dossier.isActive && fileCanBeSetUnderApproval && this.isAssigneeOrApprover(file, dossier);
}
/** UNDER_APPROVAL => UNDER_REVIEW OR NEW => UNDER_REVIEW */
private _canSetUnderReview(file: File, dossier: Dossier): boolean {
#canSetUnderReview(file: File, dossier: Dossier): boolean {
if (!dossier.isActive) {
return false;
}
return file.isUnderApproval && this.isAssigneeOrApprover(file, dossier);
const hasRss = this._iqserPermissionsService.has(Roles.getRss);
const fileCanBeSetUnderReview = file.isUnderApproval || (hasRss && file.isApproved);
return fileCanBeSetUnderReview && this.isAssigneeOrApprover(file, dossier);
}
/** UNDER_APPROVAL => APPROVED */
private _canBeApproved(file: File, dossier: Dossier): boolean {
return this._isReadyForApproval(file, dossier) && file.canBeApproved;
#canBeApproved(file: File, dossier: Dossier): boolean {
return this.#isReadyForApproval(file, dossier) && file.canBeApproved;
}
private _isReadyForApproval(file: File, dossier: Dossier): boolean {
return dossier.isActive && file.isUnderApproval && this.isAssigneeOrApprover(file, dossier);
#isReadyForApproval(file: File, dossier: Dossier) {
const hasRss = this._iqserPermissionsService.has(Roles.getRss);
const fileCanBeApproved = file.isUnderApproval || (hasRss && file.isUnderReview);
return dossier.isActive && fileCanBeApproved && this.isAssigneeOrApprover(file, dossier);
}
/** APPROVED => UNDER_APPROVAL */
private _canUndoApproval(file: File, dossier: Dossier): boolean {
return dossier.isActive && file.isApproved && this.isApprover(dossier);
#canUndoApproval(file: File, dossier: Dossier): boolean {
const hasRss = this._iqserPermissionsService.has(Roles.getRss);
const fileCanBeSetUnderApproval = !hasRss && file.isApproved;
return dossier.isActive && fileCanBeSetUnderApproval && this.isApprover(dossier);
}
private _assignmentPrecondition(file: File, dossier: Dossier): boolean {
#assignmentPrecondition(file: File, dossier: Dossier): boolean {
return dossier.isActive && !file.isError && !file.isProcessing && !!file.lastProcessed;
}
private _canAssignToSelf(file: File, dossier: Dossier): boolean {
const precondition = this._assignmentPrecondition(file, dossier) && !this.isFileAssignee(file);
#canAssignToSelf(file: File, dossier: Dossier): boolean {
const precondition = this.#assignmentPrecondition(file, dossier) && !this.isFileAssignee(file);
return precondition && (this.isApprover(dossier) || (this.isDossierMember(dossier) && (file.isNew || file.isUnderReview)));
}
private _canAssignUser(file: File, dossier: Dossier) {
const precondition = this._assignmentPrecondition(file, dossier);
#canAssignUser(file: File, dossier: Dossier) {
const precondition = this.#assignmentPrecondition(file, dossier);
if (precondition) {
if ((file.isNew || file.isUnderReview) && dossier.hasReviewers && this.isDossierMember(dossier)) {
@ -460,7 +468,7 @@ export class PermissionsService {
return false;
}
private _canUnassignUser(file: File, dossier: Dossier) {
return this._assignmentPrecondition(file, dossier) && !!file.assignee && this.isAssigneeOrApprover(file, dossier);
#canUnassignUser(file: File, dossier: Dossier) {
return this.#assignmentPrecondition(file, dossier) && !!file.assignee && this.isAssigneeOrApprover(file, dossier);
}
}

View File

@ -1435,7 +1435,7 @@
},
"file-status": {
"analyse": "Analyzing",
"approved": "Approved",
"approved": "Done",
"error": "Re-processing required",
"figure-detection-analyzing": "",
"full-processing": "Processing",
@ -1453,7 +1453,7 @@
"table-parsing-analyzing": "Table Parsing",
"unassigned": "Unassigned",
"under-approval": "Under Approval",
"under-review": "Under Review",
"under-review": "In Progress",
"unprocessed": "Unprocessed"
},
"file-upload": {