mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
[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
This commit is contained in:
@@ -131,6 +131,10 @@ submission:
|
|||||||
# NOTE: after how many time (milliseconds) submission is saved automatically
|
# NOTE: after how many time (milliseconds) submission is saved automatically
|
||||||
# eg. timer: 5 * (1000 * 60); // 5 minutes
|
# eg. timer: 5 * (1000 * 60); // 5 minutes
|
||||||
timer: 0
|
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:
|
icons:
|
||||||
metadata:
|
metadata:
|
||||||
# NOTE: example of configuration
|
# NOTE: example of configuration
|
||||||
|
@@ -56,6 +56,9 @@ export const SubmissionObjectActionTypes = {
|
|||||||
DISCARD_SUBMISSION_SUCCESS: type('dspace/submission/DISCARD_SUBMISSION_SUCCESS'),
|
DISCARD_SUBMISSION_SUCCESS: type('dspace/submission/DISCARD_SUBMISSION_SUCCESS'),
|
||||||
DISCARD_SUBMISSION_ERROR: type('dspace/submission/DISCARD_SUBMISSION_ERROR'),
|
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
|
// Upload file types
|
||||||
NEW_FILE: type('dspace/submission/NEW_FILE'),
|
NEW_FILE: type('dspace/submission/NEW_FILE'),
|
||||||
EDIT_FILE_DATA: type('dspace/submission/EDIT_FILE_DATA'),
|
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 {
|
export class UpdateSectionDataSuccessAction implements Action {
|
||||||
type = SubmissionObjectActionTypes.UPDATE_SECTION_DATA_SUCCESS;
|
type = SubmissionObjectActionTypes.UPDATE_SECTION_DATA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@@ -43,7 +43,8 @@ import {
|
|||||||
SubmissionObjectAction,
|
SubmissionObjectAction,
|
||||||
SubmissionObjectActionTypes,
|
SubmissionObjectActionTypes,
|
||||||
UpdateSectionDataAction,
|
UpdateSectionDataAction,
|
||||||
UpdateSectionDataSuccessAction
|
UpdateSectionDataSuccessAction,
|
||||||
|
CleanDuplicateDetectionAction
|
||||||
} from './submission-objects.actions';
|
} from './submission-objects.actions';
|
||||||
import {SubmissionObjectEntry} from './submission-objects.reducer';
|
import {SubmissionObjectEntry} from './submission-objects.reducer';
|
||||||
import {Item} from '../../core/shared/item.model';
|
import {Item} from '../../core/shared/item.model';
|
||||||
@@ -58,6 +59,7 @@ import {SubmissionSectionError} from './submission-section-error.model';
|
|||||||
import {
|
import {
|
||||||
WorkspaceitemSectionDuplicatesObject
|
WorkspaceitemSectionDuplicatesObject
|
||||||
} from '../../core/submission/models/workspaceitem-section-duplicates.model';
|
} from '../../core/submission/models/workspaceitem-section-duplicates.model';
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SubmissionObjectEffects {
|
export class SubmissionObjectEffects {
|
||||||
@@ -74,10 +76,11 @@ export class SubmissionObjectEffects {
|
|||||||
const selfLink = sectionDefinition._links.self.href || sectionDefinition._links.self;
|
const selfLink = sectionDefinition._links.self.href || sectionDefinition._links.self;
|
||||||
const sectionId = selfLink.substr(selfLink.lastIndexOf('/') + 1);
|
const sectionId = selfLink.substr(selfLink.lastIndexOf('/') + 1);
|
||||||
const config = sectionDefinition._links.config ? (sectionDefinition._links.config.href || sectionDefinition._links.config) : '';
|
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))
|
const enabled = (sectionDefinition.mandatory && (sectionDefinition.sectionType !== SectionsType.Duplicates))
|
||||||
|| (isNotEmpty(action.payload.sections) && action.payload.sections.hasOwnProperty(sectionId)
|
|| (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;
|
let sectionData;
|
||||||
if (sectionDefinition.sectionType !== SectionsType.SubmissionForm) {
|
if (sectionDefinition.sectionType !== SectionsType.SubmissionForm) {
|
||||||
@@ -442,10 +445,13 @@ export class SubmissionObjectEffects {
|
|||||||
mappedActions.push(new UpdateSectionDataAction(submissionId, sherpaPoliciesSectionId, null, [], []));
|
mappedActions.push(new UpdateSectionDataAction(submissionId, sherpaPoliciesSectionId, null, [], []));
|
||||||
}
|
}
|
||||||
|
|
||||||
// When Duplicate Detection step is enabled, add it only if there are duplicates
|
// When Duplicate Detection step is enabled, add it only if there are duplicates in the response section data
|
||||||
const duplicatesSectionId = findKey(currentState.sections, (section) => section.sectionType === SectionsType.Duplicates);
|
// or if configuration overrides this behaviour
|
||||||
if (isNotUndefined(duplicatesSectionId) && isNotEmpty(currentState.sections[duplicatesSectionId]?.data) && isEmpty(sections[duplicatesSectionId])) {
|
if (!alwaysDisplayDuplicates()) {
|
||||||
mappedActions.push(new UpdateSectionDataAction(submissionId, duplicatesSectionId, null, [], []));
|
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;
|
return filteredErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function alwaysDisplayDuplicates(): boolean {
|
||||||
|
return (environment.submission.duplicateDetection.alwaysShowSection);
|
||||||
|
}
|
||||||
|
@@ -5,7 +5,7 @@ import isEqual from 'lodash/isEqual';
|
|||||||
import uniqWith from 'lodash/uniqWith';
|
import uniqWith from 'lodash/uniqWith';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ChangeSubmissionCollectionAction,
|
ChangeSubmissionCollectionAction, CleanDuplicateDetectionAction,
|
||||||
CompleteInitSubmissionFormAction,
|
CompleteInitSubmissionFormAction,
|
||||||
DeleteSectionErrorsAction,
|
DeleteSectionErrorsAction,
|
||||||
DeleteUploadedFileAction,
|
DeleteUploadedFileAction,
|
||||||
@@ -229,6 +229,10 @@ export function submissionObjectReducer(state = initialState, action: Submission
|
|||||||
return removeSectionErrors(state, action as RemoveSectionErrorsAction);
|
return removeSectionErrors(state, action as RemoveSectionErrorsAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case SubmissionObjectActionTypes.CLEAN_DUPLICATE_DETECTION: {
|
||||||
|
return cleanDuplicateDetectionSection(state, action as CleanDuplicateDetectionAction);
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@@ -856,3 +860,20 @@ function deleteFile(state: SubmissionObjectState, action: DeleteUploadedFileActi
|
|||||||
}
|
}
|
||||||
return state;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -4,7 +4,7 @@ Template for the detect duplicates submission section component
|
|||||||
-->
|
-->
|
||||||
<div class="text-sm-left" *ngVar="(this.getDuplicateData() | async) as data">
|
<div class="text-sm-left" *ngVar="(this.getDuplicateData() | async) as data">
|
||||||
<ng-container *ngIf="data?.potentialDuplicates.length == 0">
|
<ng-container *ngIf="data?.potentialDuplicates.length == 0">
|
||||||
<p>{{ 'submission.sections.duplicates.none' | translate }}</p>
|
<div class="alert alert-success w-100">{{ 'submission.sections.duplicates.none' | translate }}</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="data?.potentialDuplicates.length > 0">
|
<ng-container *ngIf="data?.potentialDuplicates.length > 0">
|
||||||
<div class="alert alert-warning w-100">{{ 'submission.sections.duplicates.detected' | translate }}</div>
|
<div class="alert alert-warning w-100">{{ 'submission.sections.duplicates.detected' | translate }}</div>
|
||||||
|
@@ -13,6 +13,7 @@ describe('Config Util', () => {
|
|||||||
expect(appConfig.ui.useProxies).toEqual(true);
|
expect(appConfig.ui.useProxies).toEqual(true);
|
||||||
|
|
||||||
expect(appConfig.submission.autosave.metadata).toEqual([]);
|
expect(appConfig.submission.autosave.metadata).toEqual([]);
|
||||||
|
expect(appConfig.submission.duplicateDetection.alwaysShowSection).toEqual(false);
|
||||||
|
|
||||||
expect(appConfig.themes.length).toEqual(1);
|
expect(appConfig.themes.length).toEqual(1);
|
||||||
expect(appConfig.themes[0].name).toEqual('dspace');
|
expect(appConfig.themes[0].name).toEqual('dspace');
|
||||||
|
@@ -154,6 +154,9 @@ export class DefaultAppConfig implements AppConfig {
|
|||||||
*/
|
*/
|
||||||
timer: 0
|
timer: 0
|
||||||
},
|
},
|
||||||
|
duplicateDetection: {
|
||||||
|
alwaysShowSection: false
|
||||||
|
},
|
||||||
typeBind: {
|
typeBind: {
|
||||||
field: 'dc.type'
|
field: 'dc.type'
|
||||||
},
|
},
|
||||||
|
@@ -5,6 +5,10 @@ interface AutosaveConfig extends Config {
|
|||||||
timer: number;
|
timer: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DuplicateDetectionConfig extends Config {
|
||||||
|
alwaysShowSection: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface TypeBindConfig extends Config {
|
interface TypeBindConfig extends Config {
|
||||||
field: string;
|
field: string;
|
||||||
}
|
}
|
||||||
@@ -29,6 +33,7 @@ export interface ConfidenceIconConfig extends Config {
|
|||||||
|
|
||||||
export interface SubmissionConfig extends Config {
|
export interface SubmissionConfig extends Config {
|
||||||
autosave: AutosaveConfig;
|
autosave: AutosaveConfig;
|
||||||
|
duplicateDetection: DuplicateDetectionConfig;
|
||||||
typeBind: TypeBindConfig;
|
typeBind: TypeBindConfig;
|
||||||
icons: IconsConfig;
|
icons: IconsConfig;
|
||||||
}
|
}
|
||||||
|
@@ -121,6 +121,9 @@ export const environment: BuildConfig = {
|
|||||||
// NOTE: every how many minutes submission is saved automatically
|
// NOTE: every how many minutes submission is saved automatically
|
||||||
timer: 5
|
timer: 5
|
||||||
},
|
},
|
||||||
|
duplicateDetection: {
|
||||||
|
alwaysShowSection: false
|
||||||
|
},
|
||||||
typeBind: {
|
typeBind: {
|
||||||
field: 'dc.type'
|
field: 'dc.type'
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user