From 485ed43f0311f68dd197a19838605d8791c9998d Mon Sep 17 00:00:00 2001 From: Florent Poittevin <florent.poittevin@unige.ch> Date: Thu, 30 Jan 2020 09:48:05 +0100 Subject: [PATCH] feat: display tooltip on quickstatus and display banner when file is ignored or excluded --- .../deposit-detail-edit.routable.ts | 27 +++++-- .../data-file/deposit-data-file.action.ts | 40 ++++++++++ .../data-file/deposit-data-file.state.ts | 76 +++++++++++++++++++ .../shared-data-table.presentational.html | 2 + ...ed-datafile-quick-status.presentational.ts | 10 +++ ...pp-authorized-organizational-unit.state.ts | 2 +- src/assets/i18n/de.json | 13 +++- src/assets/i18n/en.json | 13 +++- src/assets/i18n/fr.json | 13 +++- .../environment.defaults.model.ts | 2 +- src/environments/environment.defaults.ts | 2 +- 11 files changed, 186 insertions(+), 14 deletions(-) diff --git a/src/app/features/deposit/components/routables/deposit-detail-edit/deposit-detail-edit.routable.ts b/src/app/features/deposit/components/routables/deposit-detail-edit/deposit-detail-edit.routable.ts index 545571abe..d0b7f1b1f 100644 --- a/src/app/features/deposit/components/routables/deposit-detail-edit/deposit-detail-edit.routable.ts +++ b/src/app/features/deposit/components/routables/deposit-detail-edit/deposit-detail-edit.routable.ts @@ -29,6 +29,7 @@ import {DepositFormPresentational} from "@deposit/components/presentationals/dep import {DepositTabEnum} from "@deposit/enums/deposit-tab.enum"; import {DepositHelper} from "@deposit/helpers/deposit.helper"; import {DepositDataFileAction} from "@deposit/stores/data-file/deposit-data-file.action"; +import {DepositDataFileState} from "@deposit/stores/data-file/deposit-data-file.state"; import {DepositPersonAction} from "@deposit/stores/people/deposit-person.action"; import {DepositStatusHistoryAction} from "@deposit/stores/status-history/deposit-status-history.action"; import {DepositStatusHistoryState} from "@deposit/stores/status-history/deposit-status-history.state"; @@ -81,8 +82,10 @@ export class DepositDetailEditRoutable extends SharedAbstractDetailEditRoutable< historyObs: Observable<StatusHistory[]> = MemoizedUtil.select(this._store, DepositStatusHistoryState, state => state.history); isLoadingObs: Observable<boolean> = MemoizedUtil.isLoading(this._store, DepositStatusHistoryState); queryParametersObs: Observable<QueryParameters> = MemoizedUtil.select(this._store, DepositStatusHistoryState, state => state.queryParameters); - @Select((state: LocalStateModel) => state.deposit.deposit_dataFile.numberFilesInErrors) numberFilesInErrorObs: Observable<number | undefined>; - @Select((state: LocalStateModel) => state.deposit.deposit_dataFile.numberFiles) numberFilesObs: Observable<number | undefined>; + numberFilesInErrorObs: Observable<number | undefined> = MemoizedUtil.select(this._store, DepositDataFileState, state => state.numberFilesInErrors); + numberFilesExcludedObs: Observable<number | undefined> = MemoizedUtil.select(this._store, DepositDataFileState, state => state.numberFilesExcluded); + numberFilesIgnoredObs: Observable<number | undefined> = MemoizedUtil.select(this._store, DepositDataFileState, state => state.numberFilesIgnored); + numberFilesObs: Observable<number | undefined> = MemoizedUtil.select(this._store, DepositDataFileState, state => state.numberFiles); @Select(AppState.currentOrgUnitPersonRoleResId) currentPersonRoleObs: Observable<string[]>; @Select(AppState.currentOrgUnitPerson) currentPersonObs: Observable<PersonRole>; @Select(AppState.currentUserApplicationRolesResId) currentUserApplicationRoleObs: Observable<string[]>; @@ -191,10 +194,11 @@ export class DepositDetailEditRoutable extends SharedAbstractDetailEditRoutable< const canDoAlterationActions = this._securityService.depositInEditionStep(deposit); const collectionSize = this._store.selectSnapshot((state: LocalStateModel) => state.deposit.current.collectionSize); - this.subscribe(combineLatest(this.numberFilesObs, this.numberFilesInErrorObs).pipe( + this.subscribe(combineLatest(this.numberFilesObs, this.numberFilesInErrorObs, this.numberFilesExcludedObs, this.numberFilesIgnoredObs).pipe( distinctUntilChanged(), - filter(([numberFiles, numberFilesInError]) => !isNullOrUndefined(numberFiles) && !isNullOrUndefined(numberFilesInError)), - tap(([numberFiles, numberFilesInError]) => { + filter(([numberFiles, numberFilesInError, numberFilesExcluded, numberFilesIgnored]) => + !isNullOrUndefined(numberFiles) && !isNullOrUndefined(numberFilesInError) && !isNullOrUndefined(numberFilesExcluded) && !isNullOrUndefined(numberFilesIgnored)), + tap(([numberFiles, numberFilesInError, numberFilesExcluded, numberFilesIgnored]) => { let canSubmitAction = deposit.status === Deposit.StatusEnum.INPROGRESS; this.messageReasonUnableSubmit = undefined; if (numberFiles === 0 && collectionSize === 0) { @@ -202,10 +206,21 @@ export class DepositDetailEditRoutable extends SharedAbstractDetailEditRoutable< canSubmitAction = false; } + if (numberFilesIgnored > 0) { + this.messageReasonUnableSubmit = TRANSLATE("deposit.error.fileIgnored"); + canSubmitAction = false; + } + + if (numberFilesExcluded > 0) { + this.messageReasonUnableSubmit = TRANSLATE("deposit.error.fileExcluded"); + canSubmitAction = false; + } + if (numberFilesInError > 0) { this.messageReasonUnableSubmit = TRANSLATE("deposit.error.fileInError"); canSubmitAction = false; } + this.canSubmitAction = canSubmitAction; }), )); @@ -276,6 +291,8 @@ export class DepositDetailEditRoutable extends SharedAbstractDetailEditRoutable< getSubResourceWithParentId(id: string): void { this._store.dispatch(new DepositPersonAction.GetAll(id)); this._store.dispatch(new DepositDataFileAction.GetNumberFilesInError(id)); + this._store.dispatch(new DepositDataFileAction.GetNumberFilesExcluded(id)); + this._store.dispatch(new DepositDataFileAction.GetNumberFilesIgnored(id)); this._store.dispatch(new DepositDataFileAction.GetNumberFiles(id)); } diff --git a/src/app/features/deposit/stores/data-file/deposit-data-file.action.ts b/src/app/features/deposit/stores/data-file/deposit-data-file.action.ts index a8a3893b8..875b7e196 100644 --- a/src/app/features/deposit/stores/data-file/deposit-data-file.action.ts +++ b/src/app/features/deposit/stores/data-file/deposit-data-file.action.ts @@ -166,6 +166,46 @@ export namespace DepositDataFileAction { static readonly type: string = `[${state}] Get Number Files in Error Fail`; } + export class GetNumberFilesExcluded extends BaseAction { + static readonly type: string = `[${state}] Get Number Files Excluded`; + + constructor(public parentId: string) { + super(); + } + } + + export class GetNumberFilesExcludedSuccess extends BaseSubAction<GetNumberFilesExcluded> { + static readonly type: string = `[${state}] Get Number Files Excluded Success`; + + constructor(public parentAction: GetNumberFilesExcluded, public numberFilesExcluded: number) { + super(parentAction); + } + } + + export class GetNumberFilesExcludedFail extends BaseSubAction<GetNumberFilesExcluded> { + static readonly type: string = `[${state}] Get Number Files Excluded Fail`; + } + + export class GetNumberFilesIgnored extends BaseAction { + static readonly type: string = `[${state}] Get Number Files Ignored`; + + constructor(public parentId: string) { + super(); + } + } + + export class GetNumberFilesIgnoredSuccess extends BaseSubAction<GetNumberFilesIgnored> { + static readonly type: string = `[${state}] Get Number Files Ignored Success`; + + constructor(public parentAction: GetNumberFilesIgnored, public numberFilesIgnored: number) { + super(parentAction); + } + } + + export class GetNumberFilesIgnoredFail extends BaseSubAction<GetNumberFilesIgnored> { + static readonly type: string = `[${state}] Get Number Files Ignored Fail`; + } + export class Validate extends BaseAction { static readonly type: string = `[${state}] Validate`; diff --git a/src/app/features/deposit/stores/data-file/deposit-data-file.state.ts b/src/app/features/deposit/stores/data-file/deposit-data-file.state.ts index 141e26b46..4c3a44b69 100644 --- a/src/app/features/deposit/stores/data-file/deposit-data-file.state.ts +++ b/src/app/features/deposit/stores/data-file/deposit-data-file.state.ts @@ -54,6 +54,8 @@ export const defaultDepositDataFileValue: () => DepositDataFileStateModel = () = deposit_dataFile_statusHistory: defaultStatusHistoryInitValue(), listFolders: [], numberFilesInErrors: undefined, + numberFilesExcluded: undefined, + numberFilesIgnored: undefined, numberFiles: undefined, }); @@ -61,6 +63,8 @@ export interface DepositDataFileStateModel extends CompositionStateModel<Deposit deposit_dataFile_statusHistory: DepositDataFileStatusHistoryStateModel; listFolders: string[]; numberFilesInErrors: number | undefined; + numberFilesExcluded: number | undefined; + numberFilesIgnored: number | undefined; numberFiles: number | undefined; } @@ -115,6 +119,8 @@ export class DepositDataFileState extends CompositionState<DepositDataFileStateM ctx.dispatch(new DepositDataFileAction.GetAll(action.parentId, undefined, true)); ctx.dispatch(new DepositDataFileAction.GetListFolder(action.parentId)); ctx.dispatch(new DepositDataFileAction.GetNumberFilesInError(action.parentId)); + ctx.dispatch(new DepositDataFileAction.GetNumberFilesExcluded(action.parentId)); + ctx.dispatch(new DepositDataFileAction.GetNumberFilesIgnored(action.parentId)); ctx.dispatch(new DepositDataFileAction.GetNumberFiles(action.parentId)); } @@ -192,6 +198,76 @@ export class DepositDataFileState extends CompositionState<DepositDataFileStateM }); } + @Action(DepositDataFileAction.GetNumberFilesExcluded) + getNumberFilesExcluded(ctx: StateContext<DepositDataFileStateModel>, action: DepositDataFileAction.GetNumberFilesExcluded): Observable<CollectionTyped<DepositDataFile>> { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter + 1, + }); + + const queryParameters = new QueryParameters(environment.minimalPageSizeToRetrievePaginationInfo); + MappingObjectUtil.set(queryParameters.search.searchItems, this.KEY_STATUS, DataFileStatusEnum.EXCLUDED_FILE); + return this.apiService.get<DepositDataFile>(`${this._urlResource}/${action.parentId}/${this._resourceName}`, queryParameters) + .pipe( + tap(collection => { + ctx.dispatch(new DepositDataFileAction.GetNumberFilesExcludedSuccess(action, collection._page.totalItems)); + }), + catchError(error => { + ctx.dispatch(new DepositDataFileAction.GetNumberFilesExcludedFail(action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @Action(DepositDataFileAction.GetNumberFilesExcludedSuccess) + getNumberFilesExcludedSuccess(ctx: StateContext<DepositDataFileStateModel>, action: DepositDataFileAction.GetNumberFilesExcludedSuccess): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + numberFilesExcluded: action.numberFilesExcluded, + }); + } + + @Action(DepositDataFileAction.GetNumberFilesExcludedFail) + getNumberFilesExcludedFail(ctx: StateContext<DepositDataFileStateModel>, action: DepositDataFileAction.GetNumberFilesExcludedFail): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + } + + @Action(DepositDataFileAction.GetNumberFilesIgnored) + getNumberFilesIgnored(ctx: StateContext<DepositDataFileStateModel>, action: DepositDataFileAction.GetNumberFilesIgnored): Observable<CollectionTyped<DepositDataFile>> { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter + 1, + }); + + const queryParameters = new QueryParameters(environment.minimalPageSizeToRetrievePaginationInfo); + MappingObjectUtil.set(queryParameters.search.searchItems, this.KEY_STATUS, DataFileStatusEnum.IGNORED_FILE); + return this.apiService.get<DepositDataFile>(`${this._urlResource}/${action.parentId}/${this._resourceName}`, queryParameters) + .pipe( + tap(collection => { + ctx.dispatch(new DepositDataFileAction.GetNumberFilesIgnoredSuccess(action, collection._page.totalItems)); + }), + catchError(error => { + ctx.dispatch(new DepositDataFileAction.GetNumberFilesIgnoredFail(action)); + throw new SolidifyStateError(this, error); + }), + ); + } + + @Action(DepositDataFileAction.GetNumberFilesIgnoredSuccess) + getNumberFilesIgnoredSuccess(ctx: StateContext<DepositDataFileStateModel>, action: DepositDataFileAction.GetNumberFilesIgnoredSuccess): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + numberFilesIgnored: action.numberFilesIgnored, + }); + } + + @Action(DepositDataFileAction.GetNumberFilesIgnoredFail) + getNumberFilesIgnoredFail(ctx: StateContext<DepositDataFileStateModel>, action: DepositDataFileAction.GetNumberFilesIgnoredFail): void { + ctx.patchState({ + isLoadingCounter: ctx.getState().isLoadingCounter - 1, + }); + } + @Action(DepositDataFileAction.GetNumberFiles) getNumberFiles(ctx: StateContext<DepositDataFileStateModel>, action: DepositDataFileAction.GetNumberFiles): Observable<CollectionTyped<DepositDataFile>> { ctx.patchState({ diff --git a/src/app/shared/components/presentationals/shared-data-table/shared-data-table.presentational.html b/src/app/shared/components/presentationals/shared-data-table/shared-data-table.presentational.html index 4a79f90ca..1a316715d 100644 --- a/src/app/shared/components/presentationals/shared-data-table/shared-data-table.presentational.html +++ b/src/app/shared/components/presentationals/shared-data-table/shared-data-table.presentational.html @@ -166,7 +166,9 @@ </dlcm-shared-compliance-level-rating> <dlcm-shared-datafile-quick-status *ngSwitchCase="dataTableComponentEnum.dataFileQuickStatus" + #quickStatus [value]="getCellData(rowData, col)" + [matTooltip]="quickStatus.toolipToTranslate | translate" > </dlcm-shared-datafile-quick-status> diff --git a/src/app/shared/components/presentationals/shared-datafile-quick-status/shared-datafile-quick-status.presentational.ts b/src/app/shared/components/presentationals/shared-datafile-quick-status/shared-datafile-quick-status.presentational.ts index 0737c533e..50d48ed3d 100644 --- a/src/app/shared/components/presentationals/shared-datafile-quick-status/shared-datafile-quick-status.presentational.ts +++ b/src/app/shared/components/presentationals/shared-datafile-quick-status/shared-datafile-quick-status.presentational.ts @@ -6,6 +6,7 @@ import { } from "@angular/core"; import {SharedAbstractPresentational} from "@shared/components/presentationals/shared-abstract/shared-abstract.presentational"; import {DataFileStatusEnum} from "@shared/enums/business/data-file-status.enum"; +import {TRANSLATE} from "solidify-frontend"; @Component({ selector: "dlcm-shared-datafile-quick-status", @@ -26,21 +27,30 @@ export class SharedDatafileQuickStatusPresentational extends SharedAbstractPrese return this._value; } + toolipToTranslate: string | undefined; + @HostBinding("class") classes: string; getColor(): string { switch (this.value) { case DataFileStatusEnum.READY: + this.toolipToTranslate = TRANSLATE("dataFileQuickStatus.ready"); return "ready"; case DataFileStatusEnum.IN_ERROR: + this.toolipToTranslate = TRANSLATE("dataFileQuickStatus.inError"); + return "error"; case DataFileStatusEnum.EXCLUDED_FILE: + this.toolipToTranslate = TRANSLATE("dataFileQuickStatus.excludedFile"); return "error"; case DataFileStatusEnum.IGNORED_FILE: + this.toolipToTranslate = TRANSLATE("dataFileQuickStatus.ignoredFile"); return "warning"; case DataFileStatusEnum.CLEANED: + this.toolipToTranslate = TRANSLATE("dataFileQuickStatus.cleaned"); return "cleaned"; default: + this.toolipToTranslate = TRANSLATE("dataFileQuickStatus.pending"); return "pending"; } } diff --git a/src/app/stores/authorized-organizational-unit/app-authorized-organizational-unit.state.ts b/src/app/stores/authorized-organizational-unit/app-authorized-organizational-unit.state.ts index 17ca43ca9..e55af50c5 100644 --- a/src/app/stores/authorized-organizational-unit/app-authorized-organizational-unit.state.ts +++ b/src/app/stores/authorized-organizational-unit/app-authorized-organizational-unit.state.ts @@ -23,7 +23,7 @@ export interface AppAuthorizedOrganizationalUnitStateModel extends ResourceState // WARNING : IN SOME CASE WE NEED TO FILTER TO GET ONLY OPENED ORG UNIT const getQueryParameter = () => { - const queryParameters = new QueryParameters(environment.infiniteNumber); + const queryParameters = new QueryParameters(environment.maximalPageSizeToRetrievePaginationInfo); MappingObjectUtil.set(queryParameters.search.searchItems, "openOnly", "false"); return queryParameters; }; diff --git a/src/assets/i18n/de.json b/src/assets/i18n/de.json index 6051abaa3..127b32638 100644 --- a/src/assets/i18n/de.json +++ b/src/assets/i18n/de.json @@ -33,7 +33,6 @@ "VIRUS_CHECKED": "Virus checked", "WEAK_COMPLIANCE": "Weak compliance", "access": { - "organizationalUnitNotFound": "Unable to get data", "search": { "scope": { "all": "All", @@ -962,6 +961,14 @@ } } }, + "dataFileQuickStatus": { + "cleaned": "File cleaned", + "excludedFile": "File to remove", + "ignoredFile": "File to not ignore or remove", + "inError": "In error. File to resume or remove", + "pending": "Processing", + "ready": "No action to do" + }, "deposit": { "accessLevel": "Access Level", "addMeAsAuthor": "add me as author", @@ -1034,7 +1041,9 @@ "doi": "DOI", "edit": "Edit", "error": { - "fileInError": "One or more data files contain errors", + "fileExcluded": "One or more data files are excluded", + "fileIgnored": "One or more data files are ignored", + "fileInError": "One or more data files are in errors", "noFile": "You have to upload a file to submit the deposit" }, "file": { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 6051abaa3..127b32638 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -33,7 +33,6 @@ "VIRUS_CHECKED": "Virus checked", "WEAK_COMPLIANCE": "Weak compliance", "access": { - "organizationalUnitNotFound": "Unable to get data", "search": { "scope": { "all": "All", @@ -962,6 +961,14 @@ } } }, + "dataFileQuickStatus": { + "cleaned": "File cleaned", + "excludedFile": "File to remove", + "ignoredFile": "File to not ignore or remove", + "inError": "In error. File to resume or remove", + "pending": "Processing", + "ready": "No action to do" + }, "deposit": { "accessLevel": "Access Level", "addMeAsAuthor": "add me as author", @@ -1034,7 +1041,9 @@ "doi": "DOI", "edit": "Edit", "error": { - "fileInError": "One or more data files contain errors", + "fileExcluded": "One or more data files are excluded", + "fileIgnored": "One or more data files are ignored", + "fileInError": "One or more data files are in errors", "noFile": "You have to upload a file to submit the deposit" }, "file": { diff --git a/src/assets/i18n/fr.json b/src/assets/i18n/fr.json index 978afc843..143169ebe 100644 --- a/src/assets/i18n/fr.json +++ b/src/assets/i18n/fr.json @@ -33,7 +33,6 @@ "VIRUS_CHECKED": "Virus vérifié", "WEAK_COMPLIANCE": "Conformité faible", "access": { - "organizationalUnitNotFound": "Impossible d'obtenir les données", "search": { "scope": { "all": "Tout", @@ -962,6 +961,14 @@ } } }, + "dataFileQuickStatus": { + "cleaned": "Fichier nettoyé", + "excludedFile": "Fichier à supprimer", + "ignoredFile": "Fichier à ne pas ignorer ou supprimer", + "inError": "En erreur de traitement. Fichier à relancer ou supprimer.", + "pending": "En cours de traitement", + "ready": "Aucune action à effectuer" + }, "deposit": { "accessLevel": "Niveau d'accès", "addMeAsAuthor": "m'ajouter en tant qu'auteur", @@ -1034,7 +1041,9 @@ "doi": "DOI", "edit": "Modifier", "error": { - "fileInError": "Le fichier de données contient une erreur", + "fileExcluded": "Un ou plusieurs fichiers sont exclus", + "fileIgnored": "Un ou plusieurs fichiers sont ignorés", + "fileInError": "Un ou plusieurs fichiers sont en erreurs", "noFile": "Vous devez télécharger un fichier pour pouvoir soumettre le dépôt" }, "file": { diff --git a/src/environments/environment.defaults.model.ts b/src/environments/environment.defaults.model.ts index 87cf773bd..2de2873a2 100644 --- a/src/environments/environment.defaults.model.ts +++ b/src/environments/environment.defaults.model.ts @@ -11,11 +11,11 @@ export interface DlcmEnvironment extends DefaultSolidifyEnvironment { defaultPageSize: number; defaultPageSizeHomePage: number; defaultEnumValuePageSizeOption: number; - infiniteNumber: number; defaultEnumValuePageSizeLazyLoad: number; pageSizeOptions: number[]; defaultHomeOrgUnitSize: number; minimalPageSizeToRetrievePaginationInfo: number; + maximalPageSizeToRetrievePaginationInfo: number; // Base URL For Module Applications ADMIN_APPLICATION: string; diff --git a/src/environments/environment.defaults.ts b/src/environments/environment.defaults.ts index b4211f884..f10d29233 100644 --- a/src/environments/environment.defaults.ts +++ b/src/environments/environment.defaults.ts @@ -19,11 +19,11 @@ export const defaultEnvironment: DlcmEnvironment = { defaultPageSize: 10, defaultPageSizeHomePage: 10, defaultEnumValuePageSizeOption: 10000, - infiniteNumber: 999999999, defaultEnumValuePageSizeLazyLoad: 20, pageSizeOptions: [5, 10, 25, 50, 100], defaultHomeOrgUnitSize: 1000, minimalPageSizeToRetrievePaginationInfo: 1, + maximalPageSizeToRetrievePaginationInfo: 2000, // Base URL For Module Applications ADMIN_APPLICATION: "https://to-set/administration", -- GitLab