Merge branch 'dossiers-service-resolver'
This commit is contained in:
commit
a5eabfeda5
@ -96,6 +96,7 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
|
|||||||
type: ActionTypes.downloadBtn,
|
type: ActionTypes.downloadBtn,
|
||||||
show: true,
|
show: true,
|
||||||
files: this.selectedFiles,
|
files: this.selectedFiles,
|
||||||
|
dossier: this.dossier,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
@ -175,34 +176,36 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
|
|||||||
this.#canAssign =
|
this.#canAssign =
|
||||||
this.#canMoveToSameState &&
|
this.#canMoveToSameState &&
|
||||||
this.selectedFiles.reduce(
|
this.selectedFiles.reduce(
|
||||||
(acc, file) => (acc && this._permissionsService.canAssignUser(file)) || this._permissionsService.canUnassignUser(file),
|
(acc, file) =>
|
||||||
|
(acc && this._permissionsService.canAssignUser(file, this.dossier)) ||
|
||||||
|
this._permissionsService.canUnassignUser(file, this.dossier),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
this.#canAssignToSelf = this.#canMoveToSameState && this._permissionsService.canAssignToSelf(this.selectedFiles);
|
this.#canAssignToSelf = this.#canMoveToSameState && this._permissionsService.canAssignToSelf(this.selectedFiles, this.dossier);
|
||||||
|
|
||||||
this.#canDelete = this._permissionsService.canDeleteFile(this.selectedFiles);
|
this.#canDelete = this._permissionsService.canDeleteFile(this.selectedFiles, this.dossier);
|
||||||
|
|
||||||
this.#canReanalyse = this._permissionsService.canReanalyseFile(this.selectedFiles);
|
this.#canReanalyse = this._permissionsService.canReanalyseFile(this.selectedFiles, this.dossier);
|
||||||
|
|
||||||
this.#canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis(this.selectedFiles);
|
this.#canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis(this.selectedFiles, this.dossier);
|
||||||
|
|
||||||
this.#canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis(this.selectedFiles);
|
this.#canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis(this.selectedFiles, this.dossier);
|
||||||
|
|
||||||
this.#canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.selectedFiles);
|
this.#canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.selectedFiles, this.dossier);
|
||||||
|
|
||||||
this.#canOcr = this._permissionsService.canOcrFile(this.selectedFiles);
|
this.#canOcr = this._permissionsService.canOcrFile(this.selectedFiles, this.dossier);
|
||||||
|
|
||||||
this.#canSetToNew = this._permissionsService.canSetToNew(this.selectedFiles) && !isWorkflow;
|
this.#canSetToNew = this._permissionsService.canSetToNew(this.selectedFiles, this.dossier) && !isWorkflow;
|
||||||
|
|
||||||
this.#canSetToUnderReview = this._permissionsService.canSetUnderReview(this.selectedFiles) && !isWorkflow;
|
this.#canSetToUnderReview = this._permissionsService.canSetUnderReview(this.selectedFiles, this.dossier) && !isWorkflow;
|
||||||
|
|
||||||
this.#canSetToUnderApproval = this._permissionsService.canSetUnderApproval(this.selectedFiles) && !isWorkflow;
|
this.#canSetToUnderApproval = this._permissionsService.canSetUnderApproval(this.selectedFiles, this.dossier) && !isWorkflow;
|
||||||
|
|
||||||
this.#isReadyForApproval = this._permissionsService.isReadyForApproval(this.selectedFiles) && !isWorkflow;
|
this.#isReadyForApproval = this._permissionsService.isReadyForApproval(this.selectedFiles, this.dossier) && !isWorkflow;
|
||||||
|
|
||||||
this.#canApprove = this._permissionsService.canBeApproved(this.selectedFiles) && !isWorkflow;
|
this.#canApprove = this._permissionsService.canBeApproved(this.selectedFiles, this.dossier) && !isWorkflow;
|
||||||
|
|
||||||
this.#canUndoApproval = this._permissionsService.canUndoApproval(this.selectedFiles) && !isWorkflow;
|
this.#canUndoApproval = this._permissionsService.canUndoApproval(this.selectedFiles, this.dossier) && !isWorkflow;
|
||||||
|
|
||||||
this.#assignTooltip = allFilesAreUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
|
this.#assignTooltip = allFilesAreUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
>
|
>
|
||||||
<redaction-file-download-btn
|
<redaction-file-download-btn
|
||||||
[disabled]="listingService.areSomeSelected$ | async"
|
[disabled]="listingService.areSomeSelected$ | async"
|
||||||
|
[dossier]="dossier"
|
||||||
[files]="entitiesService.all$ | async"
|
[files]="entitiesService.all$ | async"
|
||||||
iqserHelpMode="edit_dossier_in_dossier"
|
iqserHelpMode="edit_dossier_in_dossier"
|
||||||
tooltipPosition="below"
|
tooltipPosition="below"
|
||||||
|
|||||||
@ -56,5 +56,11 @@
|
|||||||
></iqser-status-bar>
|
></iqser-status-bar>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<redaction-file-actions *ngIf="!file.isProcessing" [file]="file" class="mr-4" type="dossier-overview-list"></redaction-file-actions>
|
<redaction-file-actions
|
||||||
|
*ngIf="!file.isProcessing"
|
||||||
|
[dossier]="dossier"
|
||||||
|
[file]="file"
|
||||||
|
class="mr-4"
|
||||||
|
type="dossier-overview-list"
|
||||||
|
></redaction-file-actions>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||||
import { File, IFileAttributeConfig } from '@red/domain';
|
import { Dossier, File, IFileAttributeConfig } from '@red/domain';
|
||||||
import { Required } from '@iqser/common-ui';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-table-item',
|
selector: 'redaction-table-item [file] [dossier] [displayedAttributes] [dossierTemplateId]',
|
||||||
templateUrl: './table-item.component.html',
|
templateUrl: './table-item.component.html',
|
||||||
styleUrls: ['./table-item.component.scss'],
|
styleUrls: ['./table-item.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class TableItemComponent {
|
export class TableItemComponent {
|
||||||
@Input() @Required() file!: File;
|
@Input() file: File;
|
||||||
@Input() @Required() displayedAttributes!: IFileAttributeConfig[];
|
@Input() dossier: Dossier;
|
||||||
|
@Input() displayedAttributes: IFileAttributeConfig[];
|
||||||
@Input() dossierTemplateId: string;
|
@Input() dossierTemplateId: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
<div #actionsWrapper class="actions-wrapper">
|
<div #actionsWrapper class="actions-wrapper">
|
||||||
<redaction-file-actions
|
<redaction-file-actions
|
||||||
*ngIf="!file.isProcessing"
|
*ngIf="!file.isProcessing"
|
||||||
|
[dossier]="dossier"
|
||||||
[file]="file"
|
[file]="file"
|
||||||
[maxWidth]="width"
|
[maxWidth]="width"
|
||||||
type="dossier-overview-workflow"
|
type="dossier-overview-workflow"
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
|
||||||
import { File, IFileAttributeConfig } from '@red/domain';
|
import { Dossier, File, IFileAttributeConfig } from '@red/domain';
|
||||||
import { Debounce, Required } from '@iqser/common-ui';
|
import { Debounce } from '@iqser/common-ui';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-workflow-item',
|
selector: 'redaction-workflow-item [file] [dossier] [displayedAttributes]',
|
||||||
templateUrl: './workflow-item.component.html',
|
templateUrl: './workflow-item.component.html',
|
||||||
styleUrls: ['./workflow-item.component.scss'],
|
styleUrls: ['./workflow-item.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class WorkflowItemComponent implements OnInit {
|
export class WorkflowItemComponent implements OnInit {
|
||||||
@Input() @Required() file!: File;
|
@Input() file: File;
|
||||||
@Input() @Required() displayedAttributes!: IFileAttributeConfig[];
|
@Input() dossier: Dossier;
|
||||||
|
@Input() displayedAttributes: IFileAttributeConfig[];
|
||||||
width: number;
|
width: number;
|
||||||
|
|
||||||
@ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef;
|
@ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
TableColumnConfig,
|
TableColumnConfig,
|
||||||
WorkflowConfig,
|
WorkflowConfig,
|
||||||
} from '@iqser/common-ui';
|
} from '@iqser/common-ui';
|
||||||
import { File, IFileAttributeConfig, StatusSorter, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
|
import { Dossier, File, IFileAttributeConfig, StatusSorter, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
|
||||||
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
|
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
@ -49,7 +49,7 @@ export class ConfigService {
|
|||||||
this._listingMode$.next(listingMode);
|
this._listingMode$.next(listingMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
get workflowConfig(): WorkflowConfig<File, WorkflowFileStatus> {
|
workflowConfig(dossier: Dossier): WorkflowConfig<File, WorkflowFileStatus> {
|
||||||
return {
|
return {
|
||||||
columnIdentifierFn: entity => entity.workflowStatus,
|
columnIdentifierFn: entity => entity.workflowStatus,
|
||||||
itemVersionFn: (entity: File) => `${entity.lastUpdated}-${entity.numberOfAnalyses}`,
|
itemVersionFn: (entity: File) => `${entity.lastUpdated}-${entity.numberOfAnalyses}`,
|
||||||
@ -58,7 +58,7 @@ export class ConfigService {
|
|||||||
label: workflowFileStatusTranslations[WorkflowFileStatuses.NEW],
|
label: workflowFileStatusTranslations[WorkflowFileStatuses.NEW],
|
||||||
key: WorkflowFileStatuses.NEW,
|
key: WorkflowFileStatuses.NEW,
|
||||||
enterFn: (files: File[]) => this._bulkActionsService.setToNew(files),
|
enterFn: (files: File[]) => this._bulkActionsService.setToNew(files),
|
||||||
enterPredicate: (files: File[]) => this._permissionsService.canSetToNew(files),
|
enterPredicate: (files: File[]) => this._permissionsService.canSetToNew(files, dossier),
|
||||||
color: '#D3D5DA',
|
color: '#D3D5DA',
|
||||||
entities: new BehaviorSubject([]),
|
entities: new BehaviorSubject([]),
|
||||||
},
|
},
|
||||||
@ -72,9 +72,9 @@ export class ConfigService {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
enterPredicate: (files: File[]) =>
|
enterPredicate: (files: File[]) =>
|
||||||
this._permissionsService.canSetUnderReview(files) ||
|
this._permissionsService.canSetUnderReview(files, dossier) ||
|
||||||
this._permissionsService.canAssignToSelf(files) ||
|
this._permissionsService.canAssignToSelf(files, dossier) ||
|
||||||
this._permissionsService.canAssignUser(files),
|
this._permissionsService.canAssignUser(files, dossier),
|
||||||
key: WorkflowFileStatuses.UNDER_REVIEW,
|
key: WorkflowFileStatuses.UNDER_REVIEW,
|
||||||
color: '#FDBD00',
|
color: '#FDBD00',
|
||||||
entities: new BehaviorSubject([]),
|
entities: new BehaviorSubject([]),
|
||||||
@ -83,7 +83,8 @@ export class ConfigService {
|
|||||||
label: workflowFileStatusTranslations[WorkflowFileStatuses.UNDER_APPROVAL],
|
label: workflowFileStatusTranslations[WorkflowFileStatuses.UNDER_APPROVAL],
|
||||||
enterFn: (files: File[]) => this._bulkActionsService.setToUnderApproval(files),
|
enterFn: (files: File[]) => this._bulkActionsService.setToUnderApproval(files),
|
||||||
enterPredicate: (files: File[]) =>
|
enterPredicate: (files: File[]) =>
|
||||||
this._permissionsService.canSetUnderApproval(files) || this._permissionsService.canUndoApproval(files),
|
this._permissionsService.canSetUnderApproval(files, dossier) ||
|
||||||
|
this._permissionsService.canUndoApproval(files, dossier),
|
||||||
key: WorkflowFileStatuses.UNDER_APPROVAL,
|
key: WorkflowFileStatuses.UNDER_APPROVAL,
|
||||||
color: '#374C81',
|
color: '#374C81',
|
||||||
entities: new BehaviorSubject([]),
|
entities: new BehaviorSubject([]),
|
||||||
@ -92,7 +93,8 @@ export class ConfigService {
|
|||||||
label: workflowFileStatusTranslations[WorkflowFileStatuses.APPROVED],
|
label: workflowFileStatusTranslations[WorkflowFileStatuses.APPROVED],
|
||||||
enterFn: (files: File[]) => this._bulkActionsService.approve(files),
|
enterFn: (files: File[]) => this._bulkActionsService.approve(files),
|
||||||
enterPredicate: (files: File[]) =>
|
enterPredicate: (files: File[]) =>
|
||||||
this._permissionsService.isReadyForApproval(files) && this._permissionsService.canBeApproved(files),
|
this._permissionsService.isReadyForApproval(files, dossier) &&
|
||||||
|
this._permissionsService.canBeApproved(files, dossier),
|
||||||
key: WorkflowFileStatuses.APPROVED,
|
key: WorkflowFileStatuses.APPROVED,
|
||||||
color: '#48C9F7',
|
color: '#48C9F7',
|
||||||
entities: new BehaviorSubject([]),
|
entities: new BehaviorSubject([]),
|
||||||
|
|||||||
@ -67,6 +67,7 @@
|
|||||||
<redaction-table-item
|
<redaction-table-item
|
||||||
[displayedAttributes]="displayedAttributes"
|
[displayedAttributes]="displayedAttributes"
|
||||||
[dossierTemplateId]="dossier.dossierTemplateId"
|
[dossierTemplateId]="dossier.dossierTemplateId"
|
||||||
|
[dossier]="dossier"
|
||||||
[file]="file"
|
[file]="file"
|
||||||
></redaction-table-item>
|
></redaction-table-item>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -79,5 +80,9 @@
|
|||||||
<input #fileInput (change)="uploadFiles($event.target['files'])" class="file-upload-input" multiple="true" type="file" />
|
<input #fileInput (change)="uploadFiles($event.target['files'])" class="file-upload-input" multiple="true" type="file" />
|
||||||
|
|
||||||
<ng-template #workflowItemTemplate let-entity="entity">
|
<ng-template #workflowItemTemplate let-entity="entity">
|
||||||
<redaction-workflow-item [displayedAttributes]="displayedAttributes" [file]="entity"></redaction-workflow-item>
|
<redaction-workflow-item
|
||||||
|
[displayedAttributes]="displayedAttributes"
|
||||||
|
[dossier]="dossier$ | async"
|
||||||
|
[file]="entity"
|
||||||
|
></redaction-workflow-item>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@ -69,11 +69,11 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
tableColumnConfigs: readonly TableColumnConfig<File>[];
|
tableColumnConfigs: readonly TableColumnConfig<File>[];
|
||||||
displayedInFileListAttributes: IFileAttributeConfig[] = [];
|
displayedInFileListAttributes: IFileAttributeConfig[] = [];
|
||||||
displayedAttributes: IFileAttributeConfig[] = [];
|
displayedAttributes: IFileAttributeConfig[] = [];
|
||||||
readonly workflowConfig: WorkflowConfig<File, WorkflowFileStatus> = this.configService.workflowConfig;
|
readonly workflowConfig: WorkflowConfig<File, WorkflowFileStatus>;
|
||||||
readonly dossier$: Observable<Dossier>;
|
readonly dossier$: Observable<Dossier>;
|
||||||
readonly dossierId: string;
|
readonly dossierId: string;
|
||||||
currentDossier: Dossier;
|
|
||||||
dossierTemplateId: string;
|
dossierTemplateId: string;
|
||||||
|
#currentDossier: Dossier;
|
||||||
@ViewChild('needsWorkFilterTemplate', { read: TemplateRef, static: true })
|
@ViewChild('needsWorkFilterTemplate', { read: TemplateRef, static: true })
|
||||||
private readonly _needsWorkFilterTemplate: TemplateRef<unknown>;
|
private readonly _needsWorkFilterTemplate: TemplateRef<unknown>;
|
||||||
@ViewChild('fileInput', { static: true }) private readonly _fileInput: ElementRef;
|
@ViewChild('fileInput', { static: true }) private readonly _fileInput: ElementRef;
|
||||||
@ -101,11 +101,15 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
) {
|
) {
|
||||||
super(_injector);
|
super(_injector);
|
||||||
this.dossierId = _route.snapshot.paramMap.get(DOSSIER_ID);
|
this.dossierId = _route.snapshot.paramMap.get(DOSSIER_ID);
|
||||||
this.dossier$ = this._dossiersService
|
this.dossier$ = this._dossiersService.getEntityChanged$(this.dossierId).pipe(
|
||||||
.getEntityChanged$(this.dossierId)
|
tap(dossier => {
|
||||||
.pipe(tap(dossier => (this.dossierTemplateId = dossier.dossierTemplateId)));
|
this.dossierTemplateId = dossier.dossierTemplateId;
|
||||||
this.currentDossier = this._dossiersService.find(this.dossierId);
|
this.#currentDossier = this._dossiersService.find(this.dossierId);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
this.#currentDossier = this._dossiersService.find(this.dossierId);
|
||||||
this._updateFileAttributes();
|
this._updateFileAttributes();
|
||||||
|
this.workflowConfig = this.configService.workflowConfig(this.#currentDossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
get checkedRequiredFilters(): NestedFilter[] {
|
get checkedRequiredFilters(): NestedFilter[] {
|
||||||
@ -121,7 +125,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
lastOpenedFn = (file: File) => this._userPreferenceService.getLastOpenedFileForDossier(file.dossierId) === file.id;
|
lastOpenedFn = (file: File) => this._userPreferenceService.getLastOpenedFileForDossier(file.dossierId) === file.id;
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
this._loadEntitiesFromState();
|
this._computeAllFilters();
|
||||||
|
|
||||||
this._setRemovableSubscriptions();
|
this._setRemovableSubscriptions();
|
||||||
|
|
||||||
@ -133,7 +137,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
)
|
)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
if (this.currentDossier.isActive) {
|
if (this.#currentDossier.isActive) {
|
||||||
this._fileDropOverlayService.initFileDropHandling(this.dossierId);
|
this._fileDropOverlayService.initFileDropHandling(this.dossierId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +153,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
this.addSubscription = this._dossierTemplatesService
|
this.addSubscription = this._dossierTemplatesService
|
||||||
.getEntityChanged$(this.currentDossier.dossierTemplateId)
|
.getEntityChanged$(this.#currentDossier.dossierTemplateId)
|
||||||
.pipe(
|
.pipe(
|
||||||
skip(1),
|
skip(1),
|
||||||
tap(() => {
|
tap(() => {
|
||||||
@ -159,7 +163,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.dossierAttributes = await this._dossierAttributesService.getWithValues(this.currentDossier);
|
this.dossierAttributes = await this._dossierAttributesService.getWithValues(this.#currentDossier);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error from dossier overview screen: ', e);
|
console.log('Error from dossier overview screen: ', e);
|
||||||
}
|
}
|
||||||
@ -180,8 +184,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
|
|
||||||
@HostListener('drop', ['$event'])
|
@HostListener('drop', ['$event'])
|
||||||
onDrop(event: DragEvent): void {
|
onDrop(event: DragEvent): void {
|
||||||
const currentDossier = this._dossiersService.find(this.dossierId);
|
handleFileDrop(event, this.#currentDossier, this._uploadFiles.bind(this));
|
||||||
handleFileDrop(event, currentDossier, this._uploadFiles.bind(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('dragover', ['$event'])
|
@HostListener('dragover', ['$event'])
|
||||||
@ -191,7 +194,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
}
|
}
|
||||||
|
|
||||||
async uploadFiles(files: Files): Promise<void> {
|
async uploadFiles(files: Files): Promise<void> {
|
||||||
await this._uploadFiles(convertFiles(files, this.currentDossier));
|
await this._uploadFiles(convertFiles(files, this.#currentDossier));
|
||||||
(this._fileInput as any).nativeElement.value = null;
|
(this._fileInput as any).nativeElement.value = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,18 +213,13 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
|||||||
|
|
||||||
private _updateFileAttributes(): void {
|
private _updateFileAttributes(): void {
|
||||||
this._fileAttributeConfigs =
|
this._fileAttributeConfigs =
|
||||||
this._fileAttributesService.getFileAttributeConfig(this.currentDossier.dossierTemplateId)?.fileAttributeConfigs || [];
|
this._fileAttributesService.getFileAttributeConfig(this.#currentDossier.dossierTemplateId)?.fileAttributeConfigs || [];
|
||||||
this.displayedInFileListAttributes = this._fileAttributeConfigs.filter(config => config.displayedInFileList);
|
this.displayedInFileListAttributes = this._fileAttributeConfigs.filter(config => config.displayedInFileList);
|
||||||
this.displayedAttributes = this.displayedInFileListAttributes.filter(c => c.displayedInFileList);
|
this.displayedAttributes = this.displayedInFileListAttributes.filter(c => c.displayedInFileList);
|
||||||
this.tableColumnConfigs = this.configService.tableConfig(this.displayedAttributes);
|
this.tableColumnConfigs = this.configService.tableConfig(this.displayedAttributes);
|
||||||
this._computeAllFilters();
|
this._computeAllFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _loadEntitiesFromState() {
|
|
||||||
this.currentDossier = this._dossiersService.find(this.dossierId);
|
|
||||||
this._computeAllFilters();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _uploadFiles(files: FileUploadModel[]) {
|
private async _uploadFiles(files: FileUploadModel[]) {
|
||||||
const fileCount = await this._fileUploadService.uploadFiles(files, this.dossierId);
|
const fileCount = await this._fileUploadService.uploadFiles(files, this.dossierId);
|
||||||
if (fileCount) {
|
if (fileCount) {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export class AssignReviewerApproverDialogComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private get _canUnassignFiles() {
|
private get _canUnassignFiles() {
|
||||||
return this.permissionsService.canUnassignUser(this.data.files);
|
return this.permissionsService.canUnassignUser(this.data.files, this.dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Initialize the form with:
|
/** Initialize the form with:
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import {
|
|||||||
ViewChild,
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { Action, ActionTypes, File } from '@red/domain';
|
import { Action, ActionTypes, Dossier, File } from '@red/domain';
|
||||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||||
import {
|
import {
|
||||||
AutoUnsubscribe,
|
AutoUnsubscribe,
|
||||||
@ -42,7 +42,7 @@ import { RedactionImportService } from '../../services/redaction-import.service'
|
|||||||
import { PageRotationService } from '../../../../file-preview/services/page-rotation.service';
|
import { PageRotationService } from '../../../../file-preview/services/page-rotation.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-file-actions [file] [type]',
|
selector: 'redaction-file-actions [file] [type] [dossier]',
|
||||||
templateUrl: './file-actions.component.html',
|
templateUrl: './file-actions.component.html',
|
||||||
styleUrls: ['./file-actions.component.scss'],
|
styleUrls: ['./file-actions.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
@ -52,6 +52,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
|
|||||||
readonly currentUser = this._userService.currentUser;
|
readonly currentUser = this._userService.currentUser;
|
||||||
|
|
||||||
@Input() file: File;
|
@Input() file: File;
|
||||||
|
@Input() dossier: Dossier;
|
||||||
@Input() type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
|
@Input() type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
|
||||||
@Input() maxWidth: number;
|
@Input() maxWidth: number;
|
||||||
@Input() fileActionsHelpModeKey: 'document_features' | 'editor_document_features' = 'document_features';
|
@Input() fileActionsHelpModeKey: 'document_features' | 'editor_document_features' = 'document_features';
|
||||||
@ -161,6 +162,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
|
|||||||
type: ActionTypes.downloadBtn,
|
type: ActionTypes.downloadBtn,
|
||||||
show: true,
|
show: true,
|
||||||
files: [this.file],
|
files: [this.file],
|
||||||
|
dossier: this.dossier,
|
||||||
tooltipClass: 'small',
|
tooltipClass: 'small',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -435,28 +437,29 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
|
|||||||
this.buttonType = this.isFilePreview ? CircleButtonTypes.default : CircleButtonTypes.dark;
|
this.buttonType = this.isFilePreview ? CircleButtonTypes.default : CircleButtonTypes.dark;
|
||||||
this.toggleTooltip = this._toggleTooltip;
|
this.toggleTooltip = this._toggleTooltip;
|
||||||
|
|
||||||
this.showSetToNew = this._permissionsService.canSetToNew(this.file) && !this.isDossierOverviewWorkflow;
|
this.showSetToNew = this._permissionsService.canSetToNew(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
||||||
this.showUndoApproval = this._permissionsService.canUndoApproval(this.file) && !this.isDossierOverviewWorkflow;
|
this.showUndoApproval = this._permissionsService.canUndoApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
||||||
this.showUnderReview = this._permissionsService.canSetUnderReview(this.file) && !this.isDossierOverviewWorkflow;
|
this.showUnderReview = this._permissionsService.canSetUnderReview(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
||||||
this.showUnderApproval = this._permissionsService.canSetUnderApproval(this.file) && !this.isDossierOverviewWorkflow;
|
this.showUnderApproval = this._permissionsService.canSetUnderApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
||||||
this.showApprove = this._permissionsService.isReadyForApproval(this.file) && !this.isDossierOverviewWorkflow;
|
this.showApprove = this._permissionsService.isReadyForApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
||||||
|
|
||||||
this.canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.file);
|
this.canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.file, this.dossier);
|
||||||
this.showToggleAnalysis = this._permissionsService.showToggleAnalysis(this.file);
|
this.showToggleAnalysis = this._permissionsService.showToggleAnalysis(this.dossier);
|
||||||
this.showDelete = this._permissionsService.canDeleteFile(this.file);
|
this.showDelete = this._permissionsService.canDeleteFile(this.file, this.dossier);
|
||||||
this.showOCR = this._permissionsService.canOcrFile(this.file);
|
this.showOCR = this._permissionsService.canOcrFile(this.file, this.dossier);
|
||||||
this.canReanalyse = this._permissionsService.canReanalyseFile(this.file);
|
this.canReanalyse = this._permissionsService.canReanalyseFile(this.file, this.dossier);
|
||||||
this.canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis([this.file]);
|
this.canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis([this.file], this.dossier);
|
||||||
this.canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis([this.file]);
|
this.canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis([this.file], this.dossier);
|
||||||
|
|
||||||
this.showStatusBar = !this.file.isError && !this.file.isUnprocessed && this.isDossierOverviewList;
|
this.showStatusBar = !this.file.isError && !this.file.isUnprocessed && this.isDossierOverviewList;
|
||||||
|
|
||||||
this.showAssignToSelf = this._permissionsService.canAssignToSelf(this.file) && this.isDossierOverview;
|
this.showAssignToSelf = this._permissionsService.canAssignToSelf(this.file, this.dossier) && this.isDossierOverview;
|
||||||
this.showAssign =
|
this.showAssign =
|
||||||
(this._permissionsService.canAssignUser(this.file) || this._permissionsService.canUnassignUser(this.file)) &&
|
(this._permissionsService.canAssignUser(this.file, this.dossier) ||
|
||||||
|
this._permissionsService.canUnassignUser(this.file, this.dossier)) &&
|
||||||
this.isDossierOverview;
|
this.isDossierOverview;
|
||||||
|
|
||||||
this.showImportRedactions = this._permissionsService.canImportRedactions(this.file);
|
this.showImportRedactions = this._permissionsService.canImportRedactions(this.file, this.dossier);
|
||||||
|
|
||||||
const showReanalyse = this.canReanalyse || this.file.excludedFromAutomaticAnalysis || this.analysisForced;
|
const showReanalyse = this.canReanalyse || this.file.excludedFromAutomaticAnalysis || this.analysisForced;
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
|
|
||||||
<redaction-file-download-btn
|
<redaction-file-download-btn
|
||||||
|
[dossier]="dossier"
|
||||||
[files]="files"
|
[files]="files"
|
||||||
[scrollableParentView]="scrollableParentView"
|
[scrollableParentView]="scrollableParentView"
|
||||||
[type]="circleButtonTypes.dark"
|
[type]="circleButtonTypes.dark"
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { annotationChangesTranslations } from '../../../../translations/annotation-changes-translations';
|
import { annotationChangesTranslations } from '../../../../translations/annotation-changes-translations';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { MultiSelectService } from '../../services/multi-select.service';
|
import { MultiSelectService } from '../../services/multi-select.service';
|
||||||
|
import { KeysOf } from '@iqser/common-ui';
|
||||||
|
|
||||||
interface Engine {
|
interface Engine {
|
||||||
readonly icon: string;
|
readonly icon: string;
|
||||||
@ -46,12 +47,13 @@ export class AnnotationDetailsComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _updateChanges(): void {
|
private _updateChanges(): void {
|
||||||
const changesProperties = [
|
const changesProperties: KeysOf<AnnotationWrapper>[] = [
|
||||||
'hasBeenResized',
|
'hasBeenResized',
|
||||||
'hasBeenRecategorized',
|
'hasBeenRecategorized',
|
||||||
'hasLegalBasisChanged',
|
'hasLegalBasisChanged',
|
||||||
'hasBeenForced',
|
|
||||||
'hasBeenRemovedByManualOverride',
|
'hasBeenRemovedByManualOverride',
|
||||||
|
'hasBeenForcedRedaction',
|
||||||
|
'hasBeenForcedHint',
|
||||||
];
|
];
|
||||||
const changes = changesProperties.filter(key => this.annotation[key]);
|
const changes = changesProperties.filter(key => this.annotation[key]);
|
||||||
const header = this._translateService.instant(_('annotation-changes.header'));
|
const header = this._translateService.instant(_('annotation-changes.header'));
|
||||||
|
|||||||
@ -1,34 +1,36 @@
|
|||||||
<ng-container *ngIf="file$ | async as file">
|
<ng-container *ngIf="file$ | async as file">
|
||||||
<div *ngFor="let comment of annotation.comments; trackBy: trackBy" class="comment">
|
<ng-container *ngIf="dossier$ | async as dossier">
|
||||||
<div class="comment-details-wrapper">
|
<div *ngFor="let comment of annotation.comments; trackBy: trackBy" class="comment">
|
||||||
<div [matTooltipPosition]="'above'" [matTooltip]="comment.date | date: 'exactDate'" class="small-label">
|
<div class="comment-details-wrapper">
|
||||||
<strong> {{ comment.user | name }} </strong>
|
<div [matTooltipPosition]="'above'" [matTooltip]="comment.date | date: 'exactDate'" class="small-label">
|
||||||
{{ comment.date | date: 'sophisticatedDate' }}
|
<strong> {{ comment.user | name }} </strong>
|
||||||
|
{{ comment.date | date: 'sophisticatedDate' }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="comment-actions">
|
||||||
|
<iqser-circle-button
|
||||||
|
(action)="deleteComment($event, comment)"
|
||||||
|
*ngIf="permissionsService.canDeleteComment(comment, file, dossier)"
|
||||||
|
[iconSize]="10"
|
||||||
|
[size]="20"
|
||||||
|
class="pointer"
|
||||||
|
icon="iqser:trash"
|
||||||
|
></iqser-circle-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="comment-actions">
|
<div>{{ comment.text }}</div>
|
||||||
<iqser-circle-button
|
|
||||||
(action)="deleteComment($event, comment)"
|
|
||||||
*ngIf="permissionsService.canDeleteComment(comment, file)"
|
|
||||||
[iconSize]="10"
|
|
||||||
[size]="20"
|
|
||||||
class="pointer"
|
|
||||||
icon="iqser:trash"
|
|
||||||
></iqser-circle-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>{{ comment.text }}</div>
|
<iqser-input-with-action
|
||||||
</div>
|
(action)="addComment($event)"
|
||||||
|
*ngIf="permissionsService.canAddComment(file, dossier)"
|
||||||
<iqser-input-with-action
|
[placeholder]="'comments.add-comment' | translate"
|
||||||
(action)="addComment($event)"
|
autocomplete="off"
|
||||||
*ngIf="permissionsService.canAddComment(file)"
|
icon="iqser:collapse"
|
||||||
[placeholder]="'comments.add-comment' | translate"
|
width="full"
|
||||||
autocomplete="off"
|
></iqser-input-with-action>
|
||||||
icon="iqser:collapse"
|
</ng-container>
|
||||||
width="full"
|
|
||||||
></iqser-input-with-action>
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<div (click)="toggleExpandComments($event)" class="all-caps-label pointer hide-comments" translate="comments.hide-comments"></div>
|
<div (click)="toggleExpandComments($event)" class="all-caps-label pointer hide-comments" translate="comments.hide-comments"></div>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, Input, OnChanges, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, Input, OnChanges, ViewChild } from '@angular/core';
|
||||||
import { File, IComment } from '@red/domain';
|
import { Dossier, File, IComment } from '@red/domain';
|
||||||
import { ManualAnnotationService } from '@services/manual-annotation.service';
|
import { ManualAnnotationService } from '@services/manual-annotation.service';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { UserService } from '@services/user.service';
|
import { UserService } from '@services/user.service';
|
||||||
@ -20,6 +20,7 @@ export class CommentsComponent extends AutoUnsubscribe implements OnChanges {
|
|||||||
@Input() annotation: AnnotationWrapper;
|
@Input() annotation: AnnotationWrapper;
|
||||||
readonly trackBy = trackByFactory();
|
readonly trackBy = trackByFactory();
|
||||||
readonly file$: Observable<File>;
|
readonly file$: Observable<File>;
|
||||||
|
readonly dossier$: Observable<Dossier>;
|
||||||
@HostBinding('class.hidden') _hidden = true;
|
@HostBinding('class.hidden') _hidden = true;
|
||||||
@ViewChild(InputWithActionComponent) private readonly _input: InputWithActionComponent;
|
@ViewChild(InputWithActionComponent) private readonly _input: InputWithActionComponent;
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ export class CommentsComponent extends AutoUnsubscribe implements OnChanges {
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.file$ = _stateService.file$;
|
this.file$ = _stateService.file$;
|
||||||
|
this.dossier$ = _stateService.dossier$;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
<ng-container *ngIf="stateService.file$ | async as file">
|
<ng-container *ngIf="stateService.file$ | async as file">
|
||||||
<div class="right-title heading" translate="file-preview.tabs.document-info.label">
|
<div class="right-title heading" translate="file-preview.tabs.document-info.label">
|
||||||
<div>
|
<div *ngIf="stateService.dossier$ | async as dossier">
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="edit(file)"
|
(action)="edit(file)"
|
||||||
*ngIf="permissionsService.canEditFileAttributes(file)"
|
*ngIf="permissionsService.canEditFileAttributes(file, dossier)"
|
||||||
[tooltip]="'file-preview.tabs.document-info.edit' | translate"
|
[tooltip]="'file-preview.tabs.document-info.edit' | translate"
|
||||||
icon="iqser:edit"
|
icon="iqser:edit"
|
||||||
tooltipPosition="before"
|
tooltipPosition="before"
|
||||||
|
|||||||
@ -28,8 +28,8 @@ export class PageExclusionComponent {
|
|||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _state: FilePreviewStateService,
|
private readonly _state: FilePreviewStateService,
|
||||||
) {
|
) {
|
||||||
this.canExcludePages$ = this._state.file$.pipe(
|
this.canExcludePages$ = combineLatest([this._state.file$, this._state.dossier$]).pipe(
|
||||||
map(file => permissionsService.canExcludePages(file)),
|
map(([file, dossier]) => permissionsService.canExcludePages(file, dossier)),
|
||||||
shareLast(),
|
shareLast(),
|
||||||
);
|
);
|
||||||
this.excludedRanges$ = this._excludedRanges$;
|
this.excludedRanges$ = this._excludedRanges$;
|
||||||
|
|||||||
@ -58,17 +58,17 @@ export class UserManagementComponent {
|
|||||||
|
|
||||||
this.canAssignToSelf$ = this.stateService.file$.pipe(
|
this.canAssignToSelf$ = this.stateService.file$.pipe(
|
||||||
combineLatestWith(this.stateService.dossier$),
|
combineLatestWith(this.stateService.dossier$),
|
||||||
map(([file]) => this.permissionsService.canAssignToSelf(file)),
|
map(([file, dossier]) => this.permissionsService.canAssignToSelf(file, dossier)),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
);
|
);
|
||||||
this._canAssignUser$ = this.stateService.file$.pipe(
|
this._canAssignUser$ = this.stateService.file$.pipe(
|
||||||
combineLatestWith(this.stateService.dossier$),
|
combineLatestWith(this.stateService.dossier$),
|
||||||
map(([file]) => this.permissionsService.canAssignUser(file)),
|
map(([file, dossier]) => this.permissionsService.canAssignUser(file, dossier)),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
);
|
);
|
||||||
this._canUnassignUser$ = this.stateService.file$.pipe(
|
this._canUnassignUser$ = this.stateService.file$.pipe(
|
||||||
combineLatestWith(this.stateService.dossier$),
|
combineLatestWith(this.stateService.dossier$),
|
||||||
map(([file]) => this.permissionsService.canUnassignUser(file)),
|
map(([file, dossier]) => this.permissionsService.canUnassignUser(file, dossier)),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
<div class="vertical-line"></div>
|
<div class="vertical-line"></div>
|
||||||
|
|
||||||
<redaction-file-actions
|
<redaction-file-actions
|
||||||
|
[dossier]="dossier"
|
||||||
[file]="file"
|
[file]="file"
|
||||||
fileActionsHelpModeKey="editor_document_features"
|
fileActionsHelpModeKey="editor_document_features"
|
||||||
type="file-preview"
|
type="file-preview"
|
||||||
|
|||||||
@ -137,8 +137,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
|||||||
private get _canPerformAnnotationActions$() {
|
private get _canPerformAnnotationActions$() {
|
||||||
const viewMode$ = this._viewModeService.viewMode$.pipe(tap(() => this.#deactivateMultiSelect()));
|
const viewMode$ = this._viewModeService.viewMode$.pipe(tap(() => this.#deactivateMultiSelect()));
|
||||||
|
|
||||||
return combineLatest([this.stateService.file$, viewMode$, this._viewModeService.compareMode$]).pipe(
|
return combineLatest([this.stateService.file$, this.stateService.dossier$, viewMode$, this._viewModeService.compareMode$]).pipe(
|
||||||
map(([file, viewMode]) => this.permissionsService.canPerformAnnotationActions(file) && viewMode === 'STANDARD'),
|
map(
|
||||||
|
([file, dossier, viewMode]) =>
|
||||||
|
this.permissionsService.canPerformAnnotationActions(file, dossier) && viewMode === 'STANDARD',
|
||||||
|
),
|
||||||
shareDistinctLast(),
|
shareDistinctLast(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { firstValueFrom, from, Observable, pairwise, switchMap } from 'rxjs';
|
import { combineLatest, firstValueFrom, from, Observable, pairwise, switchMap } from 'rxjs';
|
||||||
import { Dossier, File } from '@red/domain';
|
import { Dossier, File } from '@red/domain';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||||
@ -8,7 +8,6 @@ import { boolFactory } from '@iqser/common-ui';
|
|||||||
import { filter, startWith } from 'rxjs/operators';
|
import { filter, startWith } from 'rxjs/operators';
|
||||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||||
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
|
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
|
||||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
|
||||||
import { dossiersServiceResolver } from '@services/entity-services/dossiers.service.provider';
|
import { dossiersServiceResolver } from '@services/entity-services/dossiers.service.provider';
|
||||||
import { wipeFilesCache } from '@red/cache';
|
import { wipeFilesCache } from '@red/cache';
|
||||||
|
|
||||||
@ -31,13 +30,18 @@ export class FilePreviewStateService {
|
|||||||
private readonly _filesMapService: FilesMapService,
|
private readonly _filesMapService: FilesMapService,
|
||||||
private readonly _permissionsService: PermissionsService,
|
private readonly _permissionsService: PermissionsService,
|
||||||
) {
|
) {
|
||||||
|
const dossiersService = dossiersServiceResolver(this._injector);
|
||||||
|
|
||||||
this.fileId = _route.snapshot.paramMap.get(FILE_ID);
|
this.fileId = _route.snapshot.paramMap.get(FILE_ID);
|
||||||
this.dossierId = _route.snapshot.paramMap.get(DOSSIER_ID);
|
this.dossierId = _route.snapshot.paramMap.get(DOSSIER_ID);
|
||||||
this.dossierTemplateId = this._dossiersService.find(this.dossierId).dossierTemplateId;
|
this.dossierTemplateId = dossiersService.find(this.dossierId).dossierTemplateId;
|
||||||
|
|
||||||
this.dossier$ = this._dossiersService.getEntityChanged$(this.dossierId);
|
this.dossier$ = dossiersService.getEntityChanged$(this.dossierId);
|
||||||
this.file$ = _filesMapService.watch$(this.dossierId, this.fileId);
|
this.file$ = _filesMapService.watch$(this.dossierId, this.fileId);
|
||||||
[this.isReadonly$, this.isWritable$] = boolFactory(this.file$, file => !_permissionsService.canPerformAnnotationActions(file));
|
[this.isReadonly$, this.isWritable$] = boolFactory(
|
||||||
|
combineLatest([this.file$, this.dossier$]),
|
||||||
|
([file, dossier]) => !_permissionsService.canPerformAnnotationActions(file, dossier),
|
||||||
|
);
|
||||||
|
|
||||||
this.blob$ = this.#blob$;
|
this.blob$ = this.#blob$;
|
||||||
}
|
}
|
||||||
@ -54,10 +58,6 @@ export class FilePreviewStateService {
|
|||||||
return firstValueFrom(this.blob$);
|
return firstValueFrom(this.blob$);
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _dossiersService(): DossiersService {
|
|
||||||
return dossiersServiceResolver(this._injector);
|
|
||||||
}
|
|
||||||
|
|
||||||
get #blob$() {
|
get #blob$() {
|
||||||
return this.file$.pipe(
|
return this.file$.pipe(
|
||||||
startWith(undefined),
|
startWith(undefined),
|
||||||
|
|||||||
@ -1,21 +1,20 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { File } from '@red/domain';
|
import { Dossier, File } from '@red/domain';
|
||||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||||
import { CircleButtonType, CircleButtonTypes, Toaster } from '@iqser/common-ui';
|
import { CircleButtonType, CircleButtonTypes, Toaster } from '@iqser/common-ui';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
|
||||||
export type MenuState = 'OPEN' | 'CLOSED';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-file-download-btn',
|
selector: 'redaction-file-download-btn [files] [dossier]',
|
||||||
templateUrl: './file-download-btn.component.html',
|
templateUrl: './file-download-btn.component.html',
|
||||||
styleUrls: ['./file-download-btn.component.scss'],
|
styleUrls: ['./file-download-btn.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class FileDownloadBtnComponent implements OnChanges {
|
export class FileDownloadBtnComponent implements OnChanges {
|
||||||
@Input() files: File[];
|
@Input() files: File[];
|
||||||
|
@Input() dossier: Dossier;
|
||||||
@Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above';
|
@Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above';
|
||||||
@Input() type: CircleButtonType = CircleButtonTypes.default;
|
@Input() type: CircleButtonType = CircleButtonTypes.default;
|
||||||
@Input() tooltipClass: string;
|
@Input() tooltipClass: string;
|
||||||
@ -31,7 +30,7 @@ export class FileDownloadBtnComponent implements OnChanges {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnChanges(): void {
|
ngOnChanges(): void {
|
||||||
this.canDownloadFiles = this._permissionsService.canDownloadFiles(this.files);
|
this.canDownloadFiles = this._permissionsService.canDownloadFiles(this.files, this.dossier);
|
||||||
this.tooltip = this.canDownloadFiles ? _('dossier-overview.download-file') : _('dossier-overview.download-file-disabled');
|
this.tooltip = this.canDownloadFiles ? _('dossier-overview.download-file') : _('dossier-overview.download-file-disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,24 +5,25 @@
|
|||||||
[attr.aria-expanded]="btn.ariaExpanded && btn.ariaExpanded | async"
|
[attr.aria-expanded]="btn.ariaExpanded && btn.ariaExpanded | async"
|
||||||
[disabled]="btn.disabled"
|
[disabled]="btn.disabled"
|
||||||
[icon]="btn.icon"
|
[icon]="btn.icon"
|
||||||
|
[iqserHelpMode]="helpModeKey"
|
||||||
|
[scrollableParentView]="scrollableParentView"
|
||||||
[showDot]="btn.showDot"
|
[showDot]="btn.showDot"
|
||||||
[tooltipClass]="btn.tooltipClass"
|
[tooltipClass]="btn.tooltipClass"
|
||||||
[tooltipPosition]="tooltipPosition"
|
[tooltipPosition]="tooltipPosition"
|
||||||
[tooltip]="btn.tooltip | translate"
|
[tooltip]="btn.tooltip | translate"
|
||||||
[type]="btn.buttonType || buttonType"
|
[type]="btn.buttonType || buttonType"
|
||||||
[iqserHelpMode]="helpModeKey"
|
|
||||||
[scrollableParentView]="scrollableParentView"
|
|
||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
|
|
||||||
<!-- download redacted file-->
|
<!-- download redacted file-->
|
||||||
<redaction-file-download-btn
|
<redaction-file-download-btn
|
||||||
*ngIf="btn.type === 'downloadBtn'"
|
*ngIf="btn.type === 'downloadBtn'"
|
||||||
|
[dossier]="btn.dossier"
|
||||||
[files]="btn.files"
|
[files]="btn.files"
|
||||||
|
[iqserHelpMode]="helpModeKey"
|
||||||
|
[scrollableParentView]="scrollableParentView"
|
||||||
[tooltipClass]="btn.tooltipClass"
|
[tooltipClass]="btn.tooltipClass"
|
||||||
[tooltipPosition]="tooltipPosition"
|
[tooltipPosition]="tooltipPosition"
|
||||||
[type]="buttonType"
|
[type]="buttonType"
|
||||||
[iqserHelpMode]="helpModeKey"
|
|
||||||
[scrollableParentView]="scrollableParentView"
|
|
||||||
></redaction-file-download-btn>
|
></redaction-file-download-btn>
|
||||||
|
|
||||||
<!-- exclude from redaction -->
|
<!-- exclude from redaction -->
|
||||||
@ -32,10 +33,10 @@
|
|||||||
(click)="$event.stopPropagation()"
|
(click)="$event.stopPropagation()"
|
||||||
[checked]="btn.checked"
|
[checked]="btn.checked"
|
||||||
[disabled]="btn.disabled"
|
[disabled]="btn.disabled"
|
||||||
|
[iqserHelpMode]="helpModeKey"
|
||||||
[matTooltipPosition]="tooltipPosition"
|
[matTooltipPosition]="tooltipPosition"
|
||||||
[matTooltip]="btn.tooltip | translate"
|
[matTooltip]="btn.tooltip | translate"
|
||||||
[ngClass]="btn.class"
|
[ngClass]="btn.class"
|
||||||
[iqserHelpMode]="helpModeKey"
|
|
||||||
[scrollableParentView]="scrollableParentView"
|
[scrollableParentView]="scrollableParentView"
|
||||||
color="primary"
|
color="primary"
|
||||||
></mat-slide-toggle>
|
></mat-slide-toggle>
|
||||||
|
|||||||
@ -55,7 +55,7 @@ export class ExpandableFileActionsComponent implements OnChanges {
|
|||||||
const downloadBtn = this.actions.find(btn => btn.type === ActionTypes.downloadBtn);
|
const downloadBtn = this.actions.find(btn => btn.type === ActionTypes.downloadBtn);
|
||||||
if (downloadBtn) {
|
if (downloadBtn) {
|
||||||
downloadBtn.action = ($event: MouseEvent) => this._downloadFiles($event, downloadBtn.files);
|
downloadBtn.action = ($event: MouseEvent) => this._downloadFiles($event, downloadBtn.files);
|
||||||
downloadBtn.disabled = !this._permissionsService.canDownloadFiles(downloadBtn.files);
|
downloadBtn.disabled = !this._permissionsService.canDownloadFiles(downloadBtn.files, downloadBtn.dossier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@ import { ActivatedRoute } from '@angular/router';
|
|||||||
import { Injector, ProviderToken } from '@angular/core';
|
import { Injector, ProviderToken } from '@angular/core';
|
||||||
import { DossiersService } from '../dossiers/dossiers.service';
|
import { DossiersService } from '../dossiers/dossiers.service';
|
||||||
|
|
||||||
|
/** Usage in components or services is only allowed in guards or in constructors.
|
||||||
|
* Otherwise, it causes errors on navigation to other screens if the component is reused. */
|
||||||
export const dossiersServiceResolver = (injector: Injector) => {
|
export const dossiersServiceResolver = (injector: Injector) => {
|
||||||
let route: ActivatedRoute = injector.get<ActivatedRoute>(ActivatedRoute);
|
let route: ActivatedRoute = injector.get<ActivatedRoute>(ActivatedRoute);
|
||||||
while (route.firstChild) {
|
while (route.firstChild) {
|
||||||
|
|||||||
@ -73,7 +73,7 @@ export class TrashService extends GenericService<TrashItem> {
|
|||||||
this._permissionsService.canDeleteDossier(dossier),
|
this._permissionsService.canDeleteDossier(dossier),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
switchMap(dossiers => this._dossierStatsService.getFor(dossiers.map(d => d.id) as string[]).pipe(map(() => dossiers))),
|
switchMap(dossiers => this._dossierStatsService.getFor(dossiers.map(d => d.id)).pipe(map(() => dossiers))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,12 +82,12 @@ export class TrashService extends GenericService<TrashItem> {
|
|||||||
map(res => flatMap(Object.values(res))),
|
map(res => flatMap(Object.values(res))),
|
||||||
mapEach(file => new File(file, this._userService.getNameForId(file.assignee), this._activeDossiersService.routerPath)),
|
mapEach(file => new File(file, this._userService.getNameForId(file.assignee), this._activeDossiersService.routerPath)),
|
||||||
mapEach(file => {
|
mapEach(file => {
|
||||||
const dossierTemplateId = this._activeDossiersService.find(file.dossierId).dossierTemplateId;
|
const dossier = this._activeDossiersService.find(file.dossierId);
|
||||||
return new TrashFile(
|
return new TrashFile(
|
||||||
file,
|
file,
|
||||||
dossierTemplateId,
|
dossier.dossierTemplateId,
|
||||||
this._configService.values.DELETE_RETENTION_HOURS as number,
|
this._configService.values.DELETE_RETENTION_HOURS as number,
|
||||||
this._permissionsService.canDeleteFile(file),
|
this._permissionsService.canDeleteFile(file, dossier),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
import { Dossier, File, IComment, IDossier } from '@red/domain';
|
import { Dossier, File, IComment, IDossier } from '@red/domain';
|
||||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { dossiersServiceResolver } from '@services/entity-services/dossiers.service.provider';
|
|
||||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||||
import { FeaturesService } from '@services/features.service';
|
import { FeaturesService } from '@services/features.service';
|
||||||
import { DOSSIERS_ARCHIVE } from '@utils/constants';
|
import { DOSSIERS_ARCHIVE } from '@utils/constants';
|
||||||
@ -18,16 +16,11 @@ export class PermissionsService {
|
|||||||
private readonly _featuresService: FeaturesService,
|
private readonly _featuresService: FeaturesService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
private get _dossiersService(): DossiersService {
|
|
||||||
return dossiersServiceResolver(this._injector);
|
|
||||||
}
|
|
||||||
|
|
||||||
canPerformDossierStatesActions(user = this._userService.currentUser): boolean {
|
canPerformDossierStatesActions(user = this._userService.currentUser): boolean {
|
||||||
return user.isAdmin;
|
return user.isAdmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
isReviewerOrApprover(file: File): boolean {
|
isReviewerOrApprover(file: File, dossier: Dossier): boolean {
|
||||||
const dossier = this._getDossier(file);
|
|
||||||
return this.isFileAssignee(file) || this.isApprover(dossier);
|
return this.isFileAssignee(file) || this.isApprover(dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,45 +36,42 @@ export class PermissionsService {
|
|||||||
return dossier.isActive;
|
return dossier.isActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
canEditFileAttributes(file: File): boolean {
|
canEditFileAttributes(file: File, dossier: Dossier): boolean {
|
||||||
const dossier = this._getDossier(file);
|
|
||||||
return (
|
return (
|
||||||
this._isActive(file) &&
|
dossier.isActive &&
|
||||||
(((file.isUnderReview || file.isNew) && this.isDossierMember(dossier)) || (file.isUnderApproval && this.isApprover(dossier)))
|
(((file.isUnderReview || file.isNew) && this.isDossierMember(dossier)) || (file.isUnderApproval && this.isApprover(dossier)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
canToggleAnalysis(file: File | File[]): boolean {
|
canToggleAnalysis(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const sameState = new Set(files.map(f => f.excluded)).size === 1;
|
const sameState = new Set(files.map(f => f.excluded)).size === 1;
|
||||||
return sameState && files.reduce((acc, _file) => this._canToggleAnalysis(_file) && acc, true);
|
return sameState && files.reduce((acc, _file) => this._canToggleAnalysis(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
showToggleAnalysis(file: File | File[]): boolean {
|
showToggleAnalysis(dossier: Dossier): boolean {
|
||||||
|
return dossier.isActive;
|
||||||
|
}
|
||||||
|
|
||||||
|
canReanalyseFile(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
return this._isActive(files[0]);
|
return files.reduce((acc, _file) => this._canReanalyseFile(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canReanalyseFile(file: File | File[]): boolean {
|
canEnableAutoAnalysis(files: File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
return files.reduce((acc, _file) => this._canEnableAutoAnalysis(_file, dossier) && acc, true);
|
||||||
return files.reduce((acc, _file) => this._canReanalyseFile(_file) && acc, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
canEnableAutoAnalysis(files: File[]): boolean {
|
canDisableAutoAnalysis(files: File[], dossier: Dossier): boolean {
|
||||||
return files.reduce((acc, _file) => this._canEnableAutoAnalysis(_file) && acc, true);
|
return files.reduce((acc, _file) => this._canDisableAutoAnalysis(_file, dossier) && acc, true);
|
||||||
}
|
|
||||||
|
|
||||||
canDisableAutoAnalysis(files: File[]): boolean {
|
|
||||||
return files.reduce((acc, _file) => this._canDisableAutoAnalysis(_file) && acc, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isFileAssignee(file: File): boolean {
|
isFileAssignee(file: File): boolean {
|
||||||
return file.assignee === this._userService.currentUser.id;
|
return file.assignee === this._userService.currentUser.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
canDeleteFile(file: File | File[]): boolean {
|
canDeleteFile(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const dossier = this._getDossier(files[0]);
|
|
||||||
return files.reduce((acc, _file) => this._canDeleteFile(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canDeleteFile(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,53 +79,48 @@ export class PermissionsService {
|
|||||||
return dossier.isActive;
|
return dossier.isActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
canOcrFile(file: File | File[]): boolean {
|
canOcrFile(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const dossier = this._getDossier(files[0]);
|
|
||||||
return files.reduce((acc, _file) => this._canOcrFile(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canOcrFile(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canAssignToSelf(file: File | File[]): boolean {
|
canAssignToSelf(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const dossier = this._getDossier(files[0]);
|
|
||||||
return files.reduce((acc, _file) => this._canAssignToSelf(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canAssignToSelf(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canAssignUser(file: File | File[]): boolean {
|
canAssignUser(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const dossier = this._getDossier(files[0]);
|
|
||||||
return files.reduce((acc, _file) => this._canAssignUser(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canAssignUser(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canUnassignUser(file: File | File[]): boolean {
|
canUnassignUser(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const dossier = this._getDossier(files[0]);
|
|
||||||
return files.reduce((acc, _file) => this._canUnassignUser(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canUnassignUser(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetToNew(file: File | File[]): boolean {
|
canSetToNew(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
return files.reduce((acc, _file) => this._canSetToNew(_file) && acc, true);
|
return files.reduce((acc, _file) => this._canSetToNew(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetUnderReview(file: File | File[]): boolean {
|
canSetUnderReview(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const dossier = this._getDossier(files[0]);
|
return this.isApprover(dossier) && files.reduce((acc, _file) => this._canSetUnderReview(_file, dossier) && acc, true);
|
||||||
return this.isApprover(dossier) && files.reduce((acc, _file) => this._canSetUnderReview(_file) && acc, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
canBeApproved(file: File | File[]): boolean {
|
canBeApproved(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
return files.reduce((acc, _file) => this._canBeApproved(_file) && acc, true);
|
return files.reduce((acc, _file) => this._canBeApproved(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
isReadyForApproval(files: File | File[]): boolean {
|
isReadyForApproval(files: File | File[], dossier: Dossier): boolean {
|
||||||
return this.canSetUnderReview(files);
|
return this.canSetUnderReview(files, dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSetUnderApproval(file: File | File[]): boolean {
|
canSetUnderApproval(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
return files.reduce((acc, _file) => this._canSetUnderApproval(_file) && acc, true);
|
return files.reduce((acc, _file) => this._canSetUnderApproval(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
isOwner(dossier: Dossier, user = this._userService.currentUser): boolean {
|
isOwner(dossier: Dossier, user = this._userService.currentUser): boolean {
|
||||||
@ -146,28 +131,22 @@ export class PermissionsService {
|
|||||||
return dossier.approverIds.indexOf(user.id) >= 0;
|
return dossier.approverIds.indexOf(user.id) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isDossierReviewer(dossier: Dossier, user = this._userService.currentUser): boolean {
|
|
||||||
return this.isDossierMember(dossier, user) && !this.isApprover(dossier, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
isDossierMember(dossier: Dossier, user = this._userService.currentUser): boolean {
|
isDossierMember(dossier: Dossier, user = this._userService.currentUser): boolean {
|
||||||
return dossier.memberIds.includes(user.id);
|
return dossier.memberIds.includes(user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remove '?', after we make sure file is loaded before page
|
canPerformAnnotationActions(file: File, dossier: Dossier): boolean {
|
||||||
canPerformAnnotationActions(file: File): boolean {
|
|
||||||
return (
|
return (
|
||||||
this._isActive(file) &&
|
dossier.isActive &&
|
||||||
!file.isOcrProcessing &&
|
!file.isOcrProcessing &&
|
||||||
!file.excluded &&
|
!file.excluded &&
|
||||||
(file?.isUnderReview || file?.isUnderApproval) &&
|
(file.isUnderReview || file.isUnderApproval) &&
|
||||||
this.isFileAssignee(file)
|
this.isFileAssignee(file)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
canUndoApproval(file: File | File[]): boolean {
|
canUndoApproval(file: File | File[], dossier: Dossier): boolean {
|
||||||
const files = file instanceof File ? [file] : file;
|
const files = file instanceof File ? [file] : file;
|
||||||
const dossier = this._getDossier(files[0]);
|
|
||||||
return files.reduce((acc, _file) => this._canUndoApproval(_file, dossier) && acc, true);
|
return files.reduce((acc, _file) => this._canUndoApproval(_file, dossier) && acc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,11 +154,10 @@ export class PermissionsService {
|
|||||||
return (file.isUnderReview || file.isUnderApproval) && this.isFileAssignee(file);
|
return (file.isUnderReview || file.isUnderApproval) && this.isFileAssignee(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
canDownloadFiles(files: File[]): boolean {
|
canDownloadFiles(files: File[], dossier: Dossier): boolean {
|
||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const dossier = this._getDossier(files[0]);
|
|
||||||
return this.isApprover(dossier) && files.reduce((prev, file) => prev && file.isApproved, true);
|
return this.isApprover(dossier) && files.reduce((prev, file) => prev && file.isApproved, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,29 +195,28 @@ export class PermissionsService {
|
|||||||
return user.isAdmin;
|
return user.isAdmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
canAddComment(file: File): boolean {
|
canAddComment(file: File, dossier: Dossier): boolean {
|
||||||
return (this.isFileAssignee(file) || this.isApprover(this._getDossier(file))) && !file.isApproved;
|
return (this.isFileAssignee(file) || this.isApprover(dossier)) && !file.isApproved;
|
||||||
}
|
}
|
||||||
|
|
||||||
canExcludePages(file: File): boolean {
|
canExcludePages(file: File, dossier: Dossier): boolean {
|
||||||
return this.canPerformAnnotationActions(file);
|
return this.canPerformAnnotationActions(file, dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
canDeleteComment(comment: IComment, file: File) {
|
canDeleteComment(comment: IComment, file: File, dossier: Dossier) {
|
||||||
const dossier = this._getDossier(file);
|
|
||||||
return (comment.user === this._userService.currentUser.id || this.isApprover(dossier)) && !file.isApproved;
|
return (comment.user === this._userService.currentUser.id || this.isApprover(dossier)) && !file.isApproved;
|
||||||
}
|
}
|
||||||
|
|
||||||
canImportRedactions(file: File) {
|
canImportRedactions(file: File, dossier: Dossier) {
|
||||||
return this._isActive(file) && (this.isFileAssignee(file) || this.isApprover(this._getDossier(file))) && !file.isApproved;
|
return dossier.isActive && (this.isFileAssignee(file) || this.isApprover(dossier)) && !file.isApproved;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canOcrFile(file: File, dossier: Dossier): boolean {
|
private _canOcrFile(file: File, dossier: Dossier): boolean {
|
||||||
return dossier.isActive && file.canBeOCRed;
|
return dossier.isActive && file.canBeOCRed;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canToggleAnalysis(file: File): boolean {
|
private _canToggleAnalysis(file: File, dossier: Dossier): boolean {
|
||||||
return this._isActive(file) && this.isFileAssignee(file) && (file.isNew || file.isUnderReview || file.isUnderApproval);
|
return dossier.isActive && this.isFileAssignee(file) && (file.isNew || file.isUnderReview || file.isUnderApproval);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://jira.iqser.com/browse/RED-2787
|
// https://jira.iqser.com/browse/RED-2787
|
||||||
@ -253,22 +230,19 @@ export class PermissionsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canReanalyseFile(file: File): boolean {
|
private _canReanalyseFile(file: File, dossier: Dossier): boolean {
|
||||||
return this._isActive(file) && this.isReviewerOrApprover(file) && file.analysisRequired;
|
return dossier.isActive && this.isReviewerOrApprover(file, dossier) && file.analysisRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canEnableAutoAnalysis(file: File): boolean {
|
private _canEnableAutoAnalysis(file: File, dossier: Dossier): boolean {
|
||||||
return (
|
return (
|
||||||
this._isActive(file) &&
|
dossier.isActive && file.excludedFromAutomaticAnalysis && file.assignee === this._userService.currentUser.id && !file.isApproved
|
||||||
file.excludedFromAutomaticAnalysis &&
|
|
||||||
file.assignee === this._userService.currentUser.id &&
|
|
||||||
!file.isApproved
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canDisableAutoAnalysis(file: File): boolean {
|
private _canDisableAutoAnalysis(file: File, dossier: Dossier): boolean {
|
||||||
return (
|
return (
|
||||||
this._isActive(file) &&
|
dossier.isActive &&
|
||||||
!file.excludedFromAutomaticAnalysis &&
|
!file.excludedFromAutomaticAnalysis &&
|
||||||
file.assignee === this._userService.currentUser.id &&
|
file.assignee === this._userService.currentUser.id &&
|
||||||
!file.isApproved
|
!file.isApproved
|
||||||
@ -277,24 +251,24 @@ export class PermissionsService {
|
|||||||
|
|
||||||
private _canAssignToSelf(file: File, dossier: Dossier): boolean {
|
private _canAssignToSelf(file: File, dossier: Dossier): boolean {
|
||||||
const precondition =
|
const precondition =
|
||||||
this._isActive(file) && this.isDossierMember(dossier) && !this.isFileAssignee(file) && !file.isError && !file.isProcessing;
|
dossier.isActive && this.isDossierMember(dossier) && !this.isFileAssignee(file) && !file.isError && !file.isProcessing;
|
||||||
return precondition && (file.isNew || file.isUnderReview || (file.isUnderApproval && this.isApprover(dossier)));
|
return precondition && (file.isNew || file.isUnderReview || (file.isUnderApproval && this.isApprover(dossier)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canSetUnderApproval(file: File): boolean {
|
private _canSetUnderApproval(file: File, dossier: Dossier): boolean {
|
||||||
return this._isActive(file) && file.isUnderReview && this.isReviewerOrApprover(file);
|
return dossier.isActive && file.isUnderReview && this.isReviewerOrApprover(file, dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canUndoApproval(file: File, dossier: Dossier): boolean {
|
private _canUndoApproval(file: File, dossier: Dossier): boolean {
|
||||||
return this._isActive(file) && file.isApproved && this.isApprover(dossier);
|
return dossier.isActive && file.isApproved && this.isApprover(dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canBeApproved(file: File): boolean {
|
private _canBeApproved(file: File, dossier: Dossier): boolean {
|
||||||
return this._isActive(file) && file.canBeApproved;
|
return dossier.isActive && file.canBeApproved;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canAssignUser(file: File, dossier: Dossier) {
|
private _canAssignUser(file: File, dossier: Dossier) {
|
||||||
const precondition = this._isActive(file) && !file.isProcessing && !file.isError && !file.isApproved && this.isApprover(dossier);
|
const precondition = dossier.isActive && !file.isProcessing && !file.isError && !file.isApproved && this.isApprover(dossier);
|
||||||
|
|
||||||
if (precondition) {
|
if (precondition) {
|
||||||
if ((file.isNew || file.isUnderReview) && dossier.hasReviewers) {
|
if ((file.isNew || file.isUnderReview) && dossier.hasReviewers) {
|
||||||
@ -308,24 +282,14 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _canUnassignUser(file: File, dossier: Dossier) {
|
private _canUnassignUser(file: File, dossier: Dossier) {
|
||||||
return (
|
return dossier.isActive && (file.isUnderReview || file.isUnderApproval) && (this.isFileAssignee(file) || this.isApprover(dossier));
|
||||||
this._isActive(file) && (file.isUnderReview || file.isUnderApproval) && (this.isFileAssignee(file) || this.isApprover(dossier))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canSetToNew(file: File): boolean {
|
private _canSetToNew(file: File, dossier: Dossier): boolean {
|
||||||
return this._isActive(file) && file.isUnderReview;
|
return dossier.isActive && file.isUnderReview;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _canSetUnderReview(file: File): boolean {
|
private _canSetUnderReview(file: File, dossier: Dossier): boolean {
|
||||||
return this._isActive(file) && file.isUnderApproval;
|
return dossier.isActive && file.isUnderApproval;
|
||||||
}
|
|
||||||
|
|
||||||
private _getDossier(file: File): Dossier {
|
|
||||||
return this._dossiersService.find(file.dossierId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _isActive(file: File): boolean {
|
|
||||||
return this._getDossier(file).isActive;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { CircleButtonType } from '@iqser/common-ui';
|
import { CircleButtonType } from '@iqser/common-ui';
|
||||||
import { File } from '../files';
|
import { File } from '../files';
|
||||||
|
import { Dossier } from '../dossiers';
|
||||||
|
|
||||||
export type ActionType = 'circleBtn' | 'downloadBtn' | 'toggle';
|
export type ActionType = 'circleBtn' | 'downloadBtn' | 'toggle';
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ export interface Action {
|
|||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
class?: { [key: string]: boolean };
|
class?: { [key: string]: boolean };
|
||||||
files?: File[];
|
files?: File[];
|
||||||
|
dossier?: Dossier;
|
||||||
type: ActionType;
|
type: ActionType;
|
||||||
readonly helpModeKey?: string;
|
readonly helpModeKey?: string;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user