From 911cf8905c8c4a61172d81951f86850d3653e46d Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Mon, 19 Feb 2024 17:03:31 +1300 Subject: [PATCH] [TLC-674] Hide empty duplicate section UNLESS config overrides A new config property allows the user to force the duplicate section to be displayed even if there are no duplicates as sometimes this is useful information to a reviewer or submitter --- config/config.example.yml | 4 ++++ .../objects/submission-objects.actions.ts | 22 +++++++++++++++++ .../objects/submission-objects.effects.ts | 24 +++++++++++++------ .../objects/submission-objects.reducer.ts | 23 +++++++++++++++++- .../section-duplicates.component.html | 2 +- src/config/config.util.spec.ts | 1 + src/config/default-app-config.ts | 3 +++ src/config/submission-config.interface.ts | 5 ++++ src/environments/environment.test.ts | 3 +++ 9 files changed, 78 insertions(+), 9 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index 8b010ba6ea..6a35fb40f1 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -131,6 +131,10 @@ submission: # NOTE: after how many time (milliseconds) submission is saved automatically # eg. timer: 5 * (1000 * 60); // 5 minutes timer: 0 + # Always show the duplicate detection section if enabled, even if there are no potential duplicates detected + # (a message will be displayed to indicate no matches were found) + duplicateDetection: + alwaysShowSection: false icons: metadata: # NOTE: example of configuration diff --git a/src/app/submission/objects/submission-objects.actions.ts b/src/app/submission/objects/submission-objects.actions.ts index 86d90f05f3..24d9378f35 100644 --- a/src/app/submission/objects/submission-objects.actions.ts +++ b/src/app/submission/objects/submission-objects.actions.ts @@ -56,6 +56,9 @@ export const SubmissionObjectActionTypes = { DISCARD_SUBMISSION_SUCCESS: type('dspace/submission/DISCARD_SUBMISSION_SUCCESS'), DISCARD_SUBMISSION_ERROR: type('dspace/submission/DISCARD_SUBMISSION_ERROR'), + // Clearing active section types + CLEAN_DUPLICATE_DETECTION: type('dspace/submission/CLEAN_DUPLICATE_DETECTION'), + // Upload file types NEW_FILE: type('dspace/submission/NEW_FILE'), EDIT_FILE_DATA: type('dspace/submission/EDIT_FILE_DATA'), @@ -240,6 +243,25 @@ export class UpdateSectionDataAction implements Action { } } +/** + * Removes data and makes 'detect-duplicate' section not visible. + */ +export class CleanDuplicateDetectionAction implements Action { + type = SubmissionObjectActionTypes.CLEAN_DUPLICATE_DETECTION; + payload: { + submissionId: string; + }; + + /** + * creates a new CleanDetectDuplicateAction + * + * @param submissionId Id of the submission on which perform the action + */ + constructor(submissionId: string ) { + this.payload = { submissionId }; + } +} + export class UpdateSectionDataSuccessAction implements Action { type = SubmissionObjectActionTypes.UPDATE_SECTION_DATA_SUCCESS; } diff --git a/src/app/submission/objects/submission-objects.effects.ts b/src/app/submission/objects/submission-objects.effects.ts index c34e8c908e..c4fd42b0d3 100644 --- a/src/app/submission/objects/submission-objects.effects.ts +++ b/src/app/submission/objects/submission-objects.effects.ts @@ -43,7 +43,8 @@ import { SubmissionObjectAction, SubmissionObjectActionTypes, UpdateSectionDataAction, - UpdateSectionDataSuccessAction + UpdateSectionDataSuccessAction, + CleanDuplicateDetectionAction } from './submission-objects.actions'; import {SubmissionObjectEntry} from './submission-objects.reducer'; import {Item} from '../../core/shared/item.model'; @@ -58,6 +59,7 @@ import {SubmissionSectionError} from './submission-section-error.model'; import { WorkspaceitemSectionDuplicatesObject } from '../../core/submission/models/workspaceitem-section-duplicates.model'; +import { environment } from '../../../environments/environment'; @Injectable() export class SubmissionObjectEffects { @@ -74,10 +76,11 @@ export class SubmissionObjectEffects { const selfLink = sectionDefinition._links.self.href || sectionDefinition._links.self; const sectionId = selfLink.substr(selfLink.lastIndexOf('/') + 1); const config = sectionDefinition._links.config ? (sectionDefinition._links.config.href || sectionDefinition._links.config) : ''; - // A section is enabled if it is mandatory (except duplicate detection) or contains data in its section payload + // A section is enabled if it is mandatory or contains data in its section payload + // except for detect duplicate steps which will be hidden with no data unless overridden in config, even if mandatory const enabled = (sectionDefinition.mandatory && (sectionDefinition.sectionType !== SectionsType.Duplicates)) || (isNotEmpty(action.payload.sections) && action.payload.sections.hasOwnProperty(sectionId) - && (sectionDefinition.sectionType === SectionsType.Duplicates && isNotEmpty((action.payload.sections[sectionId] as WorkspaceitemSectionDuplicatesObject).potentialDuplicates)) + && (sectionDefinition.sectionType === SectionsType.Duplicates && (alwaysDisplayDuplicates() || isNotEmpty((action.payload.sections[sectionId] as WorkspaceitemSectionDuplicatesObject).potentialDuplicates))) ); let sectionData; if (sectionDefinition.sectionType !== SectionsType.SubmissionForm) { @@ -442,10 +445,13 @@ export class SubmissionObjectEffects { mappedActions.push(new UpdateSectionDataAction(submissionId, sherpaPoliciesSectionId, null, [], [])); } - // When Duplicate Detection step is enabled, add it only if there are duplicates - const duplicatesSectionId = findKey(currentState.sections, (section) => section.sectionType === SectionsType.Duplicates); - if (isNotUndefined(duplicatesSectionId) && isNotEmpty(currentState.sections[duplicatesSectionId]?.data) && isEmpty(sections[duplicatesSectionId])) { - mappedActions.push(new UpdateSectionDataAction(submissionId, duplicatesSectionId, null, [], [])); + // When Duplicate Detection step is enabled, add it only if there are duplicates in the response section data + // or if configuration overrides this behaviour + if (!alwaysDisplayDuplicates()) { + const duplicatesSectionId = findKey(currentState.sections, (section) => section.sectionType === SectionsType.Duplicates); + if (isNotUndefined(duplicatesSectionId) && isEmpty((sections[duplicatesSectionId] as WorkspaceitemSectionDuplicatesObject).potentialDuplicates)) { + mappedActions.push(new CleanDuplicateDetectionAction(submissionId)); + } } }); } @@ -493,3 +499,7 @@ function filterErrors(sectionForm: FormState, sectionErrors: SubmissionSectionEr }); return filteredErrors; } + +function alwaysDisplayDuplicates(): boolean { + return (environment.submission.duplicateDetection.alwaysShowSection); +} diff --git a/src/app/submission/objects/submission-objects.reducer.ts b/src/app/submission/objects/submission-objects.reducer.ts index 4970e25d32..c81f98db6a 100644 --- a/src/app/submission/objects/submission-objects.reducer.ts +++ b/src/app/submission/objects/submission-objects.reducer.ts @@ -5,7 +5,7 @@ import isEqual from 'lodash/isEqual'; import uniqWith from 'lodash/uniqWith'; import { - ChangeSubmissionCollectionAction, + ChangeSubmissionCollectionAction, CleanDuplicateDetectionAction, CompleteInitSubmissionFormAction, DeleteSectionErrorsAction, DeleteUploadedFileAction, @@ -229,6 +229,10 @@ export function submissionObjectReducer(state = initialState, action: Submission return removeSectionErrors(state, action as RemoveSectionErrorsAction); } + case SubmissionObjectActionTypes.CLEAN_DUPLICATE_DETECTION: { + return cleanDuplicateDetectionSection(state, action as CleanDuplicateDetectionAction); + } + default: { return state; } @@ -856,3 +860,20 @@ function deleteFile(state: SubmissionObjectState, action: DeleteUploadedFileActi } return state; } + +function cleanDuplicateDetectionSection(state: SubmissionObjectState, action: CleanDuplicateDetectionAction): SubmissionObjectState { + if (isNotEmpty(state[ action.payload.submissionId ])) { + return Object.assign({}, state, { + [ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], { + sections: Object.assign({}, state[ action.payload.submissionId ].sections, { + [ 'duplicates' ]: Object.assign({}, state[ action.payload.submissionId ].sections.duplicates, { + enabled: false, + data: { potentialDuplicates: [] } + }) + }) + }) + }); + } else { + return state; + } +} diff --git a/src/app/submission/sections/duplicates/section-duplicates.component.html b/src/app/submission/sections/duplicates/section-duplicates.component.html index a6c3abd981..78c9e5df28 100644 --- a/src/app/submission/sections/duplicates/section-duplicates.component.html +++ b/src/app/submission/sections/duplicates/section-duplicates.component.html @@ -4,7 +4,7 @@ Template for the detect duplicates submission section component -->
-

{{ 'submission.sections.duplicates.none' | translate }}

+
{{ 'submission.sections.duplicates.none' | translate }}
{{ 'submission.sections.duplicates.detected' | translate }}
diff --git a/src/config/config.util.spec.ts b/src/config/config.util.spec.ts index 4dc2b67260..cbf3bb329f 100644 --- a/src/config/config.util.spec.ts +++ b/src/config/config.util.spec.ts @@ -13,6 +13,7 @@ describe('Config Util', () => { expect(appConfig.ui.useProxies).toEqual(true); expect(appConfig.submission.autosave.metadata).toEqual([]); + expect(appConfig.submission.duplicateDetection.alwaysShowSection).toEqual(false); expect(appConfig.themes.length).toEqual(1); expect(appConfig.themes[0].name).toEqual('dspace'); diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index 9ba5ee9a35..5283dea4e1 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -154,6 +154,9 @@ export class DefaultAppConfig implements AppConfig { */ timer: 0 }, + duplicateDetection: { + alwaysShowSection: false + }, typeBind: { field: 'dc.type' }, diff --git a/src/config/submission-config.interface.ts b/src/config/submission-config.interface.ts index b0d1df900f..afc81a39e2 100644 --- a/src/config/submission-config.interface.ts +++ b/src/config/submission-config.interface.ts @@ -5,6 +5,10 @@ interface AutosaveConfig extends Config { timer: number; } +interface DuplicateDetectionConfig extends Config { + alwaysShowSection: boolean; +} + interface TypeBindConfig extends Config { field: string; } @@ -29,6 +33,7 @@ export interface ConfidenceIconConfig extends Config { export interface SubmissionConfig extends Config { autosave: AutosaveConfig; + duplicateDetection: DuplicateDetectionConfig; typeBind: TypeBindConfig; icons: IconsConfig; } diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index 6f3ab32fa9..11354ca439 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -121,6 +121,9 @@ export const environment: BuildConfig = { // NOTE: every how many minutes submission is saved automatically timer: 5 }, + duplicateDetection: { + alwaysShowSection: false + }, typeBind: { field: 'dc.type' },