diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html index 73b1f5890..b1147ec9b 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.html @@ -1,78 +1,4 @@ - - - - - - - - - - - - - - - - - - - - - + + diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts index 3fbf84edc..21aedf4b5 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts @@ -1,16 +1,16 @@ -import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; import { Dossier, File } from '@red/domain'; import { FileAssignService } from '../../../../shared/services/file-assign.service'; import { DossiersDialogService } from '../../../../services/dossiers-dialog.service'; -import { CircleButtonTypes, ConfirmationDialogInput, LoadingService, Required } from '@iqser/common-ui'; -import { TranslateService } from '@ngx-translate/core'; +import { CircleButtonType, CircleButtonTypes, ConfirmationDialogInput, LoadingService, Required } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { LongPressEvent } from '@shared/directives/long-press.directive'; import { UserPreferenceService } from '@services/user-preference.service'; import { FileManagementService } from '@services/entity-services/file-management.service'; import { ReanalysisService } from '@services/reanalysis.service'; import { FilesService } from '@services/entity-services/files.service'; +import { Action, ActionTypes } from '@shared/components/expandable-file-actions/types'; @Component({ selector: 'redaction-dossier-overview-bulk-actions', @@ -18,11 +18,26 @@ import { FilesService } from '@services/entity-services/files.service'; styleUrls: ['./dossier-overview-bulk-actions.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class DossierOverviewBulkActionsComponent { - readonly circleButtonTypes = CircleButtonTypes; +export class DossierOverviewBulkActionsComponent implements OnChanges { @Input() @Required() dossier: Dossier; @Input() @Required() selectedFiles: File[]; + @Input() buttonType: CircleButtonType = CircleButtonTypes.dark; + analysisForced: boolean; + canAssignToSelf: boolean; + canAssign: boolean; + canDelete: boolean; + canReanalyse: boolean; + canOcr: boolean; + canSetToUnderReview: boolean; + canSetToUnderApproval: boolean; + isReadyForApproval: boolean; + canApprove: boolean; + canUndoApproval: boolean; + assignTooltip: string; + buttons: Action[]; + + private _canMoveToSameState: boolean; constructor( private readonly _dialogService: DossiersDialogService, @@ -31,81 +46,95 @@ export class DossierOverviewBulkActionsComponent { private readonly _permissionsService: PermissionsService, private readonly _fileAssignService: FileAssignService, private readonly _loadingService: LoadingService, - private readonly _translateService: TranslateService, private readonly _userPreferenceService: UserPreferenceService, private readonly _filesService: FilesService, ) {} - get allSelectedFilesCanBeAssignedIntoSameState() { - const allFilesAreUnderReviewOrUnassigned = this.selectedFiles.reduce( - (acc, file) => acc && (file.isUnderReview || file.isNew), - true, - ); - const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true); - return allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval; + private get _buttons(): Action[] { + return [ + { + type: ActionTypes.circleBtn, + action: () => this._delete(), + tooltip: _('dossier-overview.bulk.delete'), + icon: 'iqser:trash', + show: this.canDelete, + }, + { + type: ActionTypes.circleBtn, + action: () => this._assign(), + tooltip: this.assignTooltip, + icon: 'red:assign', + show: this.canAssign, + }, + { + type: ActionTypes.circleBtn, + action: () => this._assignToMe(), + tooltip: _('dossier-overview.assign-me'), + icon: 'red:assign-me', + show: this.canAssignToSelf, + }, + { + type: ActionTypes.circleBtn, + action: () => this._setToUnderApproval(), + tooltip: _('dossier-overview.under-approval'), + icon: 'red:ready-for-approval', + show: this.canSetToUnderApproval, + }, + { + type: ActionTypes.circleBtn, + action: () => this._setToUnderReview(), + tooltip: _('dossier-overview.under-review'), + icon: 'red:undo', + show: this.canSetToUnderReview, + }, + { + type: ActionTypes.downloadBtn, + show: true, + files: this.selectedFiles, + disabled: !this._permissionsService.canDownloadFiles(this.selectedFiles), + }, + { + type: ActionTypes.circleBtn, + action: () => this._approveDocuments(), + disabled: !this.canApprove, + tooltip: this.canApprove ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'), + icon: 'red:approved', + show: this.isReadyForApproval, + }, + { + type: ActionTypes.circleBtn, + action: () => this._setToUnderApproval(), + tooltip: _('dossier-overview.under-approval'), + icon: 'red:undo', + show: this.canUndoApproval, + }, + { + type: ActionTypes.circleBtn, + action: () => this._ocr(), + tooltip: _('dossier-overview.ocr-file'), + icon: 'iqser:ocr', + show: this.canOcr, + }, + { + type: ActionTypes.circleBtn, + action: () => this._reanalyse(), + tooltip: _('dossier-overview.bulk.reanalyse'), + icon: 'iqser:refresh', + show: this.canReanalyse && this.analysisForced, + }, + ].filter(btn => btn.show); } - get canAssignToSelf() { - return ( - this.allSelectedFilesCanBeAssignedIntoSameState && - this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canAssignToSelf(file), true) - ); - } - - get canAssign() { - return ( - this.allSelectedFilesCanBeAssignedIntoSameState && - this.selectedFiles.reduce( - (acc, file) => (acc && this._permissionsService.canAssignUser(file)) || this._permissionsService.canUnassignUser(file), - true, - ) - ); - } - - get canDelete() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canDeleteFile(file), true); - } - - get canReanalyse() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canReanalyseFile(file), true); - } - - get canOcr() { - return this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true); - } - - get canSetToUnderReview() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true); - } - - get canSetToUnderApproval() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true); - } - - get isReadyForApproval() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true); - } - - get canApprove() { - return this.selectedFiles.reduce((acc, file) => acc && file.canBeApproved, true); - } - - get canUndoApproval() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true); - } - - get assignTooltip() { - const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true); - return allFilesAreUnderApproval - ? this._translateService.instant('dossier-overview.assign-approver') - : this._translateService.instant('dossier-overview.assign-reviewer'); + ngOnChanges() { + this._setup(); } forceReanalysisAction($event: LongPressEvent) { this.analysisForced = !$event.touchEnd && this._userPreferenceService.areDevFeaturesEnabled; + this._setup(); } - delete() { + private _delete() { this._dialogService.openDialog( 'confirm', null, @@ -126,7 +155,7 @@ export class DossierOverviewBulkActionsComponent { ); } - async setToUnderApproval() { + private async _setToUnderApproval() { // If more than 1 approver - show dialog and ask who to assign if (this.dossier.approverIds.length > 1) { this._assignFiles('approver', true); @@ -143,14 +172,14 @@ export class DossierOverviewBulkActionsComponent { } } - async reanalyse() { + private async _reanalyse() { this._loadingService.start(); const fileIds = this.selectedFiles.filter(file => file.analysisRequired).map(file => file.fileId); await this._reanalysisService.reanalyzeFilesForDossier(fileIds, this.dossier.id).toPromise(); this._loadingService.stop(); } - async ocr() { + private async _ocr() { this._loadingService.start(); await this._reanalysisService .ocrFiles( @@ -161,7 +190,7 @@ export class DossierOverviewBulkActionsComponent { this._loadingService.stop(); } - async setToUnderReview() { + private async _setToUnderReview() { this._loadingService.start(); await this._filesService .setUnderReviewFor( @@ -172,7 +201,7 @@ export class DossierOverviewBulkActionsComponent { this._loadingService.stop(); } - async approveDocuments(): Promise { + private async _approveDocuments(): Promise { const foundUpdatedFile = this.selectedFiles.find(file => file.hasUpdates); if (foundUpdatedFile) { this._dialogService.openDialog( @@ -205,15 +234,57 @@ export class DossierOverviewBulkActionsComponent { } } - async assignToMe() { + private async _assignToMe() { await this._fileAssignService.assignToMe(this.selectedFiles); } - assign() { + private _assign() { const mode = this.selectedFiles[0].isUnderApproval ? 'approver' : 'reviewer'; this._assignFiles(mode); } + private _setup() { + const allFilesAreUnderReviewOrUnassigned = this.selectedFiles.reduce( + (acc, file) => acc && (file.isUnderReview || file.isNew), + true, + ); + const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true); + this._canMoveToSameState = allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval; + + this.canAssign = + this._canMoveToSameState && + this.selectedFiles.reduce( + (acc, file) => (acc && this._permissionsService.canAssignUser(file)) || this._permissionsService.canUnassignUser(file), + true, + ); + this.canAssignToSelf = + this._canMoveToSameState && + this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canAssignToSelf(file), true); + + this.canDelete = this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canDeleteFile(file), true); + + this.canReanalyse = this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canReanalyseFile(file), true); + + this.canOcr = this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true); + + this.canSetToUnderReview = this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true); + + this.canSetToUnderApproval = this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canSetUnderApproval(file), + true, + ); + + this.isReadyForApproval = this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true); + + this.canApprove = this.selectedFiles.reduce((acc, file) => acc && file.canBeApproved, true); + + this.canUndoApproval = this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true); + + this.assignTooltip = allFilesAreUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer'); + + this.buttons = this._buttons; + } + private _assignFiles(mode: 'reviewer' | 'approver', ignoreChanged = false) { const data = { mode, files: this.selectedFiles, ignoreChanged }; this._dialogService.openDialog('assignFile', null, data); diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html index 042e26b51..9be2ad255 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html @@ -32,6 +32,7 @@ (noDataAction)="fileInput.click()" *ngIf="mode === listingModes.workflow" [addElementIcon]="'iqser:upload'" + [bulkActions]="bulkActions" [config]="workflowConfig" [itemClasses]="{ disabled: disabledFn }" [itemTemplate]="workflowItemTemplate" @@ -55,8 +56,9 @@ diff --git a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts index e429341a8..c389b5f2b 100644 --- a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts +++ b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts @@ -261,6 +261,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy, forceReanalysisAction($event: LongPressEvent) { this.analysisForced = !$event.touchEnd && this._userPreferenceService.areDevFeaturesEnabled; + this._setup(); } private _openDocument() { diff --git a/libs/common-ui b/libs/common-ui index 2d2cd9fcd..ea2d5fc69 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 2d2cd9fcdaaa07877bfe0b04d36a7d924c0b338a +Subproject commit ea2d5fc69b114ee9a8d117f55865a34e2efc0303