mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Final commit detect duplicate
This commit is contained in:
@@ -299,11 +299,11 @@
|
||||
"submit.progressbar.describe.stepone": "Describe",
|
||||
"submit.progressbar.describe.steptwo": "Describe",
|
||||
"submit.progressbar.describe.stepcustom": "Describe",
|
||||
"submit.progressbar.describe.deduplication": "Potential duplicates",
|
||||
"submit.progressbar.describe.recycle": "Recycle",
|
||||
"submit.progressbar.upload": "Upload files",
|
||||
"submit.progressbar.license": "Deposit license",
|
||||
"submit.progressbar.cclicense": "Creative commons license",
|
||||
"submit.progressbar.detect-duplicate": "Potential duplicates",
|
||||
|
||||
"upload": {
|
||||
"info": "Here you will find all the files currently in the item. You can update the fle metadata and access conditions or <strong>upload additional files just dragging&dropping them everywhere in the page</strong>",
|
||||
@@ -321,20 +321,26 @@
|
||||
"group-label": "Group"
|
||||
}
|
||||
},
|
||||
"deduplication": {
|
||||
"duplicated": "It's a duplicate",
|
||||
"not_duplicated": "It's not a duplicate",
|
||||
"duplicated_ctrl": "Mark the record to merge",
|
||||
"duplicated_help": "Click here if this is a duplicate of your item",
|
||||
"not_duplicated_help": "Click here if this is not a duplicate of your item",
|
||||
"note_help": "Please enter your reason for the duplication into the box below.",
|
||||
"note_placeholder": "Describe the reason of duplication",
|
||||
"clear_decision": "Undo",
|
||||
"clear_decision_help": "Click for clear the decision about this pontential duplicate",
|
||||
"your_decision": "Your choice:",
|
||||
"submitter_decision": "Submitter choice:",
|
||||
"detect-duplicate": {
|
||||
"duplicate-detected": "Potential duplicate detected",
|
||||
"duplicate": "It's a duplicate",
|
||||
"not-duplicate": "It's not a duplicate",
|
||||
"confirm-duplicate": "Confirm (It's a duplicate)",
|
||||
"confirm-not-duplicate": "Confirm (It's not a duplicate)",
|
||||
"duplicate-ctrl": "Mark the record to merge",
|
||||
"duplicate-help": "Click here if this is a duplicate of your item",
|
||||
"not-duplicate-help": "Click here if this is not a duplicate of your item",
|
||||
"note-help": "Please enter your reason for the duplication into the box below.",
|
||||
"note-placeholder": "Describe the reason of duplication",
|
||||
"clear-decision": "Undo",
|
||||
"clear-decision-help": "Click for clear the decision about this pontential duplicate",
|
||||
"decision-success-notice": "Choice registered successfully",
|
||||
"no-decision": "No decision yet",
|
||||
"submitter-decision": "Submitter decision:",
|
||||
"submitter-note": "Submitter note:",
|
||||
"disclaimer": "The system has identified some potential duplicates. Please carefully review the list and flag each occurency with the appropriate choice or discard this submission.",
|
||||
"disclaimer_ctrl": "The system has identified some potential duplicates. Please carefully review the list and the submitter comments and perform the appropriate action."
|
||||
"disclaimer-ctrl": "The system has identified some potential duplicates. Please carefully review the list and the submitter comments and perform the appropriate action.",
|
||||
"disclaimer-no-match": "All your feedback on potential duplicates have been registered correctly."
|
||||
},
|
||||
"recycle": {
|
||||
"disclaimer": "The following existent information are not valid within the selected collection. Please copy them to the appropriate metadata if applicable. Use the discard button to remove these information when done."
|
||||
|
@@ -1,14 +1,12 @@
|
||||
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
|
||||
import { WorkspaceitemSectionUploadFileObject } from './workspaceitem-section-upload-file.model';
|
||||
import { FormFieldChangedObject } from '../../../shared/form/builder/models/form-field-unexpected-object.model';
|
||||
import { Item } from '../../shared/item.model';
|
||||
|
||||
import { DSpaceObject } from '../../shared/dspace-object.model';
|
||||
|
||||
export interface WorkspaceitemSectionDeduplicationObject {
|
||||
matches: DeduplicationSchema[];
|
||||
export interface WorkspaceitemSectionDetectDuplicateObject {
|
||||
matches: {
|
||||
[itemId: string]: DetectDuplicateMatch;
|
||||
};
|
||||
}
|
||||
|
||||
export interface DeduplicationSchema {
|
||||
export interface DetectDuplicateMatch {
|
||||
submitterDecision?: string; // [reject|verify]
|
||||
submitterNote?: string;
|
||||
submitterTime?: string; // (readonly)
|
||||
@@ -17,5 +15,7 @@ export interface DeduplicationSchema {
|
||||
workflowNote?: string;
|
||||
workflowTime?: string; // (readonly)
|
||||
|
||||
matchObject?: DSpaceObject; // item, workspaceItem, workflowItem
|
||||
adminDecision?: string;
|
||||
|
||||
matchObject?: Item;
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import { WorkspaceitemSectionUploadObject } from './workspaceitem-section-upload
|
||||
import { isNotEmpty, isNotNull } from '../../../shared/empty.util';
|
||||
import { FormFieldLanguageValueObject } from '../../../shared/form/builder/models/form-field-language-value.model';
|
||||
import { WorkspaceitemSectionRecycleObject } from './workspaceitem-section-recycle.model';
|
||||
import { WorkspaceitemSectionDeduplicationObject } from './workspaceitem-section-deduplication.model';
|
||||
import { WorkspaceitemSectionDetectDuplicateObject } from './workspaceitem-section-deduplication.model';
|
||||
import { FormFieldMetadataValueObject } from '../../../shared/form/builder/models/form-field-metadata-value.model';
|
||||
|
||||
export class WorkspaceitemSectionsObject {
|
||||
@@ -61,5 +61,5 @@ export type WorkspaceitemSectionDataType
|
||||
| WorkspaceitemSectionFormObject
|
||||
| WorkspaceitemSectionLicenseObject
|
||||
| WorkspaceitemSectionRecycleObject
|
||||
| WorkspaceitemSectionDeduplicationObject
|
||||
| WorkspaceitemSectionDetectDuplicateObject
|
||||
| string;
|
||||
|
@@ -52,12 +52,9 @@ export const SubmissionObjectActionTypes = {
|
||||
DISCARD_SUBMISSION: type('dspace/submission/DISCARD_SUBMISSION'),
|
||||
DISCARD_SUBMISSION_SUCCESS: type('dspace/submission/DISCARD_SUBMISSION_SUCCESS'),
|
||||
DISCARD_SUBMISSION_ERROR: type('dspace/submission/DISCARD_SUBMISSION_ERROR'),
|
||||
SET_WORKSPACE_DUPLICATION: type('/sections/deduplication/SET_WORKSPACE_DUPLICATION'),
|
||||
SET_WORKSPACE_DUPLICATION_SUCCESS: type('/sections/deduplication/SET_WORKSPACE_DUPLICATION_SUCCESS'),
|
||||
SET_WORKSPACE_DUPLICATION_ERROR: type('/sections/deduplication/SET_WORKSPACE_DUPLICATION_ERROR'),
|
||||
SET_WORKFLOW_DUPLICATION: type('/sections/deduplication/SET_WORKFLOW_DUPLICATION'),
|
||||
SET_WORKFLOW_DUPLICATION_SUCCESS: type('/sections/deduplication/SET_WORKFLOW_DUPLICATION_SUCCESS'),
|
||||
SET_WORKFLOW_DUPLICATION_ERROR: type('/sections/deduplication/SET_WORKFLOW_DUPLICATION_ERROR'),
|
||||
SET_DUPLICATE_DECISION: type('dspace/submission/SET_DUPLICATE_DECISION'),
|
||||
SET_DUPLICATE_DECISION_SUCCESS: type('dspace/submission/SET_DUPLICATE_DECISION_SUCCESS'),
|
||||
SET_DUPLICATE_DECISION_ERROR: type('dspace/submission/SET_DUPLICATE_DECISION_ERROR'),
|
||||
|
||||
// Upload file types
|
||||
NEW_FILE: type('dspace/submission/NEW_FILE'),
|
||||
@@ -763,129 +760,63 @@ export class DeleteUploadedFileAction implements Action {
|
||||
}
|
||||
}
|
||||
|
||||
export class SetWorkspaceDuplicatedAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_WORKSPACE_DUPLICATION;
|
||||
export class SetDuplicateDecisionAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_DUPLICATE_DECISION;
|
||||
payload: {
|
||||
index: number;
|
||||
decision: string;
|
||||
note?: string
|
||||
submissionId: string;
|
||||
sectionId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new SetWorkspaceDuplicatedAction
|
||||
* Create a new SetDuplicateDecisionAction
|
||||
*
|
||||
* @param index
|
||||
* the index in matches array
|
||||
* @param decision
|
||||
* the submitter's decision ('verify'|'reject'|null)
|
||||
* @param note
|
||||
* the submitter's note, for 'verify' decision only
|
||||
* @param submissionId
|
||||
* the submission's ID
|
||||
* @param sectionId
|
||||
* the section's ID
|
||||
*/
|
||||
constructor(payload: any) {
|
||||
this.payload = payload;
|
||||
constructor(submissionId: string, sectionId: string) {
|
||||
this.payload = { submissionId, sectionId };
|
||||
}
|
||||
}
|
||||
|
||||
export class SetWorkspaceDuplicatedSuccessAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_WORKSPACE_DUPLICATION_SUCCESS;
|
||||
export class SetDuplicateDecisionSuccessAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_DUPLICATE_DECISION_SUCCESS;
|
||||
payload: {
|
||||
index: number;
|
||||
decision: string;
|
||||
note?: string
|
||||
submissionId: string;
|
||||
sectionId: string;
|
||||
submissionObject: SubmissionObject[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new SetWorkspaceDuplicatedSuccessAction
|
||||
* Create a new SetDuplicateDecisionSuccessAction
|
||||
*
|
||||
* @param index
|
||||
* the index in matches array
|
||||
* @param decision
|
||||
* the submitter's decision ('verify'|'reject'|null)
|
||||
* @param note
|
||||
* the submitter's note, for 'verify' decision only
|
||||
* @param submissionId
|
||||
* the submission's ID
|
||||
* @param sectionId
|
||||
* the section's ID
|
||||
* @param submissionObjects
|
||||
* the submission's Object
|
||||
*/
|
||||
constructor(payload: any) {
|
||||
this.payload = payload;
|
||||
constructor(submissionId: string, sectionId: string, submissionObject: SubmissionObject[]) {
|
||||
this.payload = { submissionId, sectionId, submissionObject };
|
||||
}
|
||||
}
|
||||
|
||||
export class SetWorkspaceDuplicatedErrorAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_WORKSPACE_DUPLICATION_ERROR;
|
||||
export class SetDuplicateDecisionErrorAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_DUPLICATE_DECISION_ERROR;
|
||||
payload: {
|
||||
index: number;
|
||||
submissionId: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new SetWorkspaceDuplicatedErrorAction
|
||||
* Create a new SetDuplicateDecisionErrorAction
|
||||
*
|
||||
* @param index
|
||||
* the index in matches array
|
||||
* @param submissionId
|
||||
* the submission's ID
|
||||
*/
|
||||
constructor(index: number) {
|
||||
this.payload = { index };
|
||||
}
|
||||
}
|
||||
|
||||
export class SetWorkflowDuplicatedAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_WORKFLOW_DUPLICATION;
|
||||
payload: {
|
||||
index: number;
|
||||
decision: string;
|
||||
note?: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new SetWorkflowDuplicatedAction
|
||||
*
|
||||
* @param index
|
||||
* the index in matches array
|
||||
* @param decision
|
||||
* the controller's decision ('verify'|'reject'|null)
|
||||
* @param note
|
||||
* the controller's note, for 'verify' decision only
|
||||
*/
|
||||
constructor(payload: any) {
|
||||
this.payload = payload;
|
||||
}
|
||||
}
|
||||
|
||||
export class SetWorkflowDuplicatedSuccessAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_WORKFLOW_DUPLICATION_SUCCESS;
|
||||
payload: {
|
||||
index: number;
|
||||
decision: string;
|
||||
note?: string
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new SetWorkflowDuplicatedSuccessAction
|
||||
*
|
||||
* @param index
|
||||
* the index in matches array
|
||||
* @param decision
|
||||
* the controller's decision ('verify'|'reject'|null)
|
||||
* @param note
|
||||
* the controller's note, for 'verify' decision only
|
||||
*/
|
||||
constructor(payload: any) {
|
||||
this.payload = payload;
|
||||
}
|
||||
}
|
||||
|
||||
export class SetWorkflowDuplicatedErrorAction implements Action {
|
||||
type = SubmissionObjectActionTypes.SET_WORKFLOW_DUPLICATION_ERROR;
|
||||
payload: {
|
||||
index: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new SetWorkflowDuplicatedErrorAction
|
||||
*
|
||||
* @param index
|
||||
* the index in matches array
|
||||
*/
|
||||
constructor(index: number) {
|
||||
this.payload = { index };
|
||||
constructor(submissionId: string) {
|
||||
this.payload = { submissionId };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -928,9 +859,6 @@ export type SubmissionObjectAction = DisableSectionAction
|
||||
| SaveSubmissionSectionFormSuccessAction
|
||||
| SaveSubmissionSectionFormErrorAction
|
||||
| SetActiveSectionAction
|
||||
| SetWorkspaceDuplicatedAction
|
||||
| SetWorkspaceDuplicatedSuccessAction
|
||||
| SetWorkspaceDuplicatedErrorAction
|
||||
| SetWorkflowDuplicatedAction
|
||||
| SetWorkflowDuplicatedSuccessAction
|
||||
| SetWorkflowDuplicatedErrorAction;
|
||||
| SetDuplicateDecisionAction
|
||||
| SetDuplicateDecisionSuccessAction
|
||||
| SetDuplicateDecisionErrorAction;
|
||||
|
@@ -22,12 +22,7 @@ import {
|
||||
SaveSubmissionSectionFormAction,
|
||||
SaveSubmissionSectionFormErrorAction,
|
||||
SaveSubmissionSectionFormSuccessAction,
|
||||
SetWorkflowDuplicatedAction,
|
||||
SetWorkflowDuplicatedErrorAction,
|
||||
SetWorkflowDuplicatedSuccessAction,
|
||||
SetWorkspaceDuplicatedAction,
|
||||
SetWorkspaceDuplicatedErrorAction,
|
||||
SetWorkspaceDuplicatedSuccessAction,
|
||||
SetDuplicateDecisionAction, SetDuplicateDecisionErrorAction, SetDuplicateDecisionSuccessAction,
|
||||
SubmissionObjectActionTypes,
|
||||
UpdateSectionDataAction
|
||||
} from './submission-objects.actions';
|
||||
@@ -43,11 +38,13 @@ import { Workflowitem } from '../../core/submission/models/workflowitem.model';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DeduplicationService } from '../sections/deduplication/deduplication.service';
|
||||
import { DetectDuplicateService } from '../sections/detect-duplicate/detect-duplicate.service';
|
||||
import { SubmissionState } from '../submission.reducers';
|
||||
import { SubmissionObjectEntry } from './submission-objects.reducer';
|
||||
import { SubmissionSectionModel } from '../../core/shared/config/config-submission-section.model';
|
||||
import parseSectionErrors from '../utils/parseSectionErrors';
|
||||
import { SectionsType } from '../sections/sections-type';
|
||||
import { WorkspaceitemSectionsObject } from '../../core/submission/models/workspaceitem-sections.model';
|
||||
|
||||
@Injectable()
|
||||
export class SubmissionObjectEffects {
|
||||
@@ -60,7 +57,7 @@ export class SubmissionObjectEffects {
|
||||
definition.sections.forEach((sectionDefinition: SubmissionSectionModel, index: number) => {
|
||||
const sectionId = sectionDefinition._links.self.substr(sectionDefinition._links.self.lastIndexOf('/') + 1);
|
||||
const config = sectionDefinition._links.config || '';
|
||||
const enabled = sectionDefinition.mandatory || (isNotEmpty(action.payload.sections) && action.payload.sections.hasOwnProperty(sectionId));
|
||||
const enabled = (sectionDefinition.mandatory && sectionDefinition.sectionType !== SectionsType.DetectDuplicate) || (isNotEmpty(action.payload.sections) && action.payload.sections.hasOwnProperty(sectionId));
|
||||
const sectionData = (isNotUndefined(action.payload.sections) && isNotUndefined(action.payload.sections[sectionId])) ? action.payload.sections[sectionId] : Object.create(null);
|
||||
const sectionErrors = null;
|
||||
mappedActions.push(
|
||||
@@ -127,9 +124,7 @@ export class SubmissionObjectEffects {
|
||||
.map(([action, currentState]: [SaveSubmissionFormSuccessAction | SaveSubmissionSectionFormSuccessAction, any]) => {
|
||||
return this.parseSaveResponse((currentState.submission as SubmissionState).objects[action.payload.submissionId], action.payload.submissionObject, action.payload.submissionId);
|
||||
})
|
||||
.mergeMap((actions) => {
|
||||
return Observable.from(actions);
|
||||
});
|
||||
.mergeMap((actions) => Observable.from(actions));
|
||||
|
||||
@Effect() saveSection$ = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SAVE_SUBMISSION_SECTION_FORM)
|
||||
@@ -143,6 +138,31 @@ export class SubmissionObjectEffects {
|
||||
.catch(() => Observable.of(new SaveSubmissionSectionFormErrorAction(action.payload.submissionId)));
|
||||
});
|
||||
|
||||
@Effect() saveDuplicateDecision$ = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_DUPLICATE_DECISION)
|
||||
.switchMap((action: SetDuplicateDecisionAction) => {
|
||||
return this.operationsService.jsonPatchByResourceID(
|
||||
this.submissionService.getSubmissionObjectLinkName(),
|
||||
action.payload.submissionId,
|
||||
'sections',
|
||||
action.payload.sectionId)
|
||||
.map((response: SubmissionObject[]) => new SetDuplicateDecisionSuccessAction(action.payload.submissionId, action.payload.sectionId, response))
|
||||
.catch(() => Observable.of(new SetDuplicateDecisionErrorAction(action.payload.submissionId)));
|
||||
});
|
||||
|
||||
@Effect({dispatch: false}) setDuplicateDecisionSuccess$ = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_DUPLICATE_DECISION_SUCCESS)
|
||||
.do(() => this.notificationsService.success(null, this.translate.get('submission.sections.detect-duplicate.decision-success-notice')));
|
||||
|
||||
/* @Effect() setDuplicateDecisionSuccess$ = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_DUPLICATE_DECISION_SUCCESS)
|
||||
.withLatestFrom(this.store$)
|
||||
.map(([action, currentState]: [SetDuplicateDecisionSuccessAction, any]) => {
|
||||
this.notificationsService.success(null, this.translate.get('submission.sections.detect-duplicate.decision-success-notice'));
|
||||
return this.parseSaveResponse((currentState.submission as SubmissionState).objects[action.payload.submissionId], action.payload.submissionObject, action.payload.submissionId, false);
|
||||
})
|
||||
.mergeMap((actions) => Observable.from(actions));*/
|
||||
|
||||
@Effect() saveAndDepositSection$ = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SAVE_AND_DEPOSIT_SUBMISSION)
|
||||
.withLatestFrom(this.store$)
|
||||
@@ -202,79 +222,13 @@ export class SubmissionObjectEffects {
|
||||
.ofType(SubmissionObjectActionTypes.DISCARD_SUBMISSION_ERROR)
|
||||
.do(() => this.notificationsService.error(null, this.translate.get('submission.sections.general.discard_error_notice')));
|
||||
|
||||
@Effect()
|
||||
public wsDuplication: Observable<Action> = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_WORKSPACE_DUPLICATION)
|
||||
.map((action: SetWorkspaceDuplicatedAction) => {
|
||||
// return this.deduplicationService.setWorkspaceDuplicated(action.payload)
|
||||
// .first()
|
||||
// .map((response) => {
|
||||
console.log('Effect of SET_WORKSPACE_DUPLICATION');
|
||||
// TODO JSON PATCH
|
||||
// const pathCombiner = new JsonPatchOperationPathCombiner('sections', 'deduplication');
|
||||
// const path = ''; // `metadata/${metadataKey}`; // TODO
|
||||
// this.operationsBuilder.add(pathCombiner.getPath(path), action.payload, true);
|
||||
return new SetWorkspaceDuplicatedSuccessAction(action.payload);
|
||||
})
|
||||
.catch((error) => Observable.of(new SetWorkspaceDuplicatedErrorAction(error)));
|
||||
|
||||
@Effect({dispatch: false})
|
||||
public wsDuplicationSuccess: Observable<Action> = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_WORKSPACE_DUPLICATION_SUCCESS)
|
||||
// TODO
|
||||
.do((action: SetWorkspaceDuplicatedAction) => {
|
||||
console.log('Effect of SET_WORKSPACE_DUPLICATION_SUCCESS');
|
||||
this.deduplicationService.setWorkspaceDuplicationSuccess(action.payload);
|
||||
});
|
||||
|
||||
@Effect({dispatch: false})
|
||||
public wsDuplicationError: Observable<Action> = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_WORKSPACE_DUPLICATION_ERROR)
|
||||
.do((action: SetWorkspaceDuplicatedAction) => {
|
||||
console.log('Effect of SET_WORKSPACE_DUPLICATION_ERROR');
|
||||
this.deduplicationService.setWorkspaceDuplicationError(action.payload);
|
||||
});
|
||||
|
||||
@Effect()
|
||||
public wfDuplication: Observable<Action> = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_WORKFLOW_DUPLICATION)
|
||||
.map((action: SetWorkflowDuplicatedAction) => {
|
||||
// return this.deduplicationService.setWorkflowDuplicated(action.payload)
|
||||
// .first()
|
||||
// .map((response) => {
|
||||
console.log('Effect of SET_WORKFLOW_DUPLICATION');
|
||||
// TODO JSON PATCH
|
||||
// const pathCombiner = new JsonPatchOperationPathCombiner('sections', 'deduplication');
|
||||
// const path = ''; // `metadata/${metadataKey}`; // TODO
|
||||
// this.operationsBuilder.add(pathCombiner.getPath(path), action.payload, true);
|
||||
return new SetWorkflowDuplicatedSuccessAction(action.payload);
|
||||
})
|
||||
.catch((error) => Observable.of(new SetWorkflowDuplicatedErrorAction(error)));
|
||||
|
||||
@Effect({dispatch: false})
|
||||
public wfDuplicationSuccess: Observable<Action> = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_WORKFLOW_DUPLICATION_SUCCESS)
|
||||
// TODO
|
||||
.do((action: SetWorkflowDuplicatedAction) => {
|
||||
console.log('Effect of SET_WORKFLOW_DUPLICATION_SUCCESS');
|
||||
this.deduplicationService.setWorkflowDuplicationSuccess(action.payload);
|
||||
});
|
||||
|
||||
@Effect({dispatch: false})
|
||||
public wfDuplicationError: Observable<Action> = this.actions$
|
||||
.ofType(SubmissionObjectActionTypes.SET_WORKFLOW_DUPLICATION_ERROR)
|
||||
.do((action: SetWorkflowDuplicatedAction) => {
|
||||
console.log('Effect of SET_WORKFLOW_DUPLICATION_ERROR');
|
||||
this.deduplicationService.setWorkflowDuplicationError(action.payload);
|
||||
});
|
||||
|
||||
constructor(private actions$: Actions,
|
||||
private notificationsService: NotificationsService,
|
||||
private operationsService: JsonPatchOperationsService<SubmitDataResponseDefinitionObject>,
|
||||
private sectionService: SectionsService,
|
||||
private store$: Store<any>,
|
||||
private submissionService: SubmissionService,
|
||||
private deduplicationService: DeduplicationService,
|
||||
private deduplicationService: DetectDuplicateService,
|
||||
private translate: TranslateService) {
|
||||
}
|
||||
|
||||
@@ -293,11 +247,13 @@ export class SubmissionObjectEffects {
|
||||
return canDeposit;
|
||||
}
|
||||
|
||||
protected parseSaveResponse(currentState: SubmissionObjectEntry, response: SubmissionObject[], submissionId: string) {
|
||||
protected parseSaveResponse(currentState: SubmissionObjectEntry, response: SubmissionObject[], submissionId: string, notify: boolean = true) {
|
||||
const mappedActions = [];
|
||||
|
||||
if (isNotEmpty(response)) {
|
||||
this.notificationsService.success(null, this.translate.get('submission.sections.general.save_success_notice'));
|
||||
if (notify) {
|
||||
this.notificationsService.success(null, this.translate.get('submission.sections.general.save_success_notice'));
|
||||
}
|
||||
|
||||
// to avoid dispatching an action for every error, create an array of errors per section
|
||||
response.forEach((item: Workspaceitem | Workflowitem) => {
|
||||
@@ -307,19 +263,20 @@ export class SubmissionObjectEffects {
|
||||
|
||||
if (errors && !isEmpty(errors)) {
|
||||
errorsList = parseSectionErrors(errors);
|
||||
this.notificationsService.warning(null, this.translate.get('submission.sections.general.sections_not_valid'));
|
||||
if (notify) {
|
||||
this.notificationsService.warning(null, this.translate.get('submission.sections.general.sections_not_valid'));
|
||||
}
|
||||
}
|
||||
|
||||
const sections = (item.sections && isNotEmpty(item.sections)) ? item.sections : {};
|
||||
|
||||
const sections: WorkspaceitemSectionsObject = (item.sections && isNotEmpty(item.sections)) ? item.sections : {};
|
||||
const sectionsKeys: string[] = union(Object.keys(sections), Object.keys(errorsList));
|
||||
|
||||
sectionsKeys
|
||||
.forEach((sectionId) => {
|
||||
const sectionErrors = errorsList[sectionId] || [];
|
||||
const sectionData = sections[sectionId] || {};
|
||||
if (!currentState.sections[sectionId].enabled) {
|
||||
this.submissionService.notifyNewSection(sectionId);
|
||||
if (notify && !currentState.sections[sectionId].enabled) {
|
||||
this.submissionService.notifyNewSection(submissionId, sectionId, currentState.sections[sectionId].sectionType);
|
||||
}
|
||||
mappedActions.push(new UpdateSectionDataAction(submissionId, sectionId, sectionData, sectionErrors));
|
||||
});
|
||||
|
@@ -27,16 +27,18 @@ import {
|
||||
SaveSubmissionFormErrorAction,
|
||||
SaveSubmissionSectionFormSuccessAction,
|
||||
SaveSubmissionSectionFormErrorAction,
|
||||
SetWorkspaceDuplicatedAction,
|
||||
SetWorkflowDuplicatedAction,
|
||||
InitSectionAction,
|
||||
RemoveSectionErrorsAction,
|
||||
SaveForLaterSubmissionFormAction,
|
||||
SaveAndDepositSubmissionAction, SaveForLaterSubmissionFormSuccessAction, SaveForLaterSubmissionFormErrorAction
|
||||
SaveAndDepositSubmissionAction,
|
||||
SaveForLaterSubmissionFormSuccessAction,
|
||||
SaveForLaterSubmissionFormErrorAction,
|
||||
SetDuplicateDecisionAction, SetDuplicateDecisionSuccessAction, SetDuplicateDecisionErrorAction
|
||||
} from './submission-objects.actions';
|
||||
import { WorkspaceitemSectionDataType } from '../../core/submission/models/workspaceitem-sections.model';
|
||||
import { WorkspaceitemSectionUploadObject } from '../../core/submission/models/workspaceitem-section-upload.model';
|
||||
import { SectionsType } from '../sections/sections-type';
|
||||
import { WorkspaceitemSectionDetectDuplicateObject } from '../../core/submission/models/workspaceitem-section-deduplication.model';
|
||||
|
||||
export interface SectionVisibility {
|
||||
main: any;
|
||||
@@ -74,6 +76,7 @@ export interface SubmissionObjectEntry {
|
||||
sections?: SubmissionSectionEntry;
|
||||
isLoading?: boolean;
|
||||
savePending?: boolean;
|
||||
saveDecisionPending?: boolean;
|
||||
depositPending?: boolean;
|
||||
}
|
||||
|
||||
@@ -192,15 +195,6 @@ export function submissionObjectReducer(state = initialState, action: Submission
|
||||
return deleteFile(state, action as DeleteUploadedFileAction);
|
||||
}
|
||||
|
||||
// deduplication
|
||||
case SubmissionObjectActionTypes.SET_WORKSPACE_DUPLICATION: {
|
||||
return updateDeduplication(state, action as SetWorkspaceDuplicatedAction);
|
||||
}
|
||||
|
||||
case SubmissionObjectActionTypes.SET_WORKFLOW_DUPLICATION: {
|
||||
return updateDeduplication(state, action as SetWorkflowDuplicatedAction);
|
||||
}
|
||||
|
||||
// errors actions
|
||||
case SubmissionObjectActionTypes.ADD_SECTION_ERROR: {
|
||||
return addError(state, action as InertSectionErrorsAction);
|
||||
@@ -214,6 +208,19 @@ export function submissionObjectReducer(state = initialState, action: Submission
|
||||
return removeSectionErrors(state, action as RemoveSectionErrorsAction);
|
||||
}
|
||||
|
||||
// detect duplicate
|
||||
case SubmissionObjectActionTypes.SET_DUPLICATE_DECISION: {
|
||||
return startSaveDecision(state, action as SetDuplicateDecisionAction);
|
||||
}
|
||||
|
||||
case SubmissionObjectActionTypes.SET_DUPLICATE_DECISION_SUCCESS: {
|
||||
return setDuplicateMatches(state, action as SetDuplicateDecisionSuccessAction);
|
||||
}
|
||||
|
||||
case SubmissionObjectActionTypes.SET_DUPLICATE_DECISION: {
|
||||
return endSaveDecision(state, action as SetDuplicateDecisionErrorAction);
|
||||
}
|
||||
|
||||
default: {
|
||||
return state;
|
||||
}
|
||||
@@ -319,6 +326,7 @@ function initSubmission(state: SubmissionObjectState, action: InitSubmissionForm
|
||||
sections: Object.create(null),
|
||||
isLoading: true,
|
||||
savePending: false,
|
||||
saveDecisionPending: false,
|
||||
depositPending: false,
|
||||
};
|
||||
return newState;
|
||||
@@ -740,7 +748,7 @@ function deleteFile(state: SubmissionObjectState, action: DeleteUploadedFileActi
|
||||
[ action.payload.submissionId ]: Object.assign({}, state[action.payload.submissionId], {
|
||||
sections: Object.assign({}, state[action.payload.submissionId].sections,
|
||||
Object.assign({}, {
|
||||
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
||||
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections[ action.payload.sectionId ], {
|
||||
data: Object.assign({}, state[ action.payload.submissionId ].sections[ action.payload.sectionId ].data, {
|
||||
files: newData
|
||||
})
|
||||
@@ -754,25 +762,74 @@ function deleteFile(state: SubmissionObjectState, action: DeleteUploadedFileActi
|
||||
return state;
|
||||
}
|
||||
|
||||
// ------ Detect duplicate functions ------ //
|
||||
|
||||
/**
|
||||
* Update a Workspace deduplication match.
|
||||
* Set decision flag to true
|
||||
*
|
||||
* @param state
|
||||
* the current state
|
||||
* @param action
|
||||
* a SetWorkspaceDuplicatedAction or SetWorkflowDuplicatedAction
|
||||
* an SetDuplicateDecisionAction
|
||||
* @return SubmissionObjectState
|
||||
* the new state, with the match parameter changed.
|
||||
* the new state, with the decision flag changed.
|
||||
*/
|
||||
function updateDeduplication(state: SubmissionObjectState, action: SetWorkspaceDuplicatedAction|SetWorkflowDuplicatedAction): SubmissionObjectState {
|
||||
const matches = Object.assign([], (state[(action.payload as any).submissionId].sections.deduplication.data as any).matches);
|
||||
const newMatch = (action.payload as any).data;
|
||||
matches.forEach( (match, i) => {
|
||||
if (i === action.payload.index) {
|
||||
matches.splice(i, 1, Object.assign({}, match, newMatch));
|
||||
return;
|
||||
}
|
||||
});
|
||||
// const updatedMatches = Object.assign({}, matches, newMatch);
|
||||
return Object.assign({}, state, {[(action.payload as any).submissionId]: {sections: {deduplication: {data: {matches}}}}});
|
||||
function startSaveDecision(state: SubmissionObjectState, action: SetDuplicateDecisionAction): SubmissionObjectState {
|
||||
if (hasValue(state[ action.payload.submissionId ])) {
|
||||
return Object.assign({}, state, {
|
||||
[ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], {
|
||||
saveDecisionPending: true,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
function setDuplicateMatches(state: SubmissionObjectState, action: SetDuplicateDecisionSuccessAction) {
|
||||
const index: any = findKey(
|
||||
action.payload.submissionObject,
|
||||
{id: parseInt(action.payload.submissionId, 10)});
|
||||
const sectionData = action.payload.submissionObject[index].sections[ action.payload.sectionId ] as WorkspaceitemSectionDetectDuplicateObject;
|
||||
const newData = (sectionData && sectionData.matches) ? sectionData : Object.create({});
|
||||
|
||||
if (hasValue(state[ action.payload.submissionId ].sections[ action.payload.sectionId ])) {
|
||||
return Object.assign({}, state, {
|
||||
[ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], {
|
||||
sections: Object.assign({}, state[ action.payload.submissionId ].sections,
|
||||
Object.assign({}, {
|
||||
[ action.payload.sectionId ]: Object.assign({}, state[ action.payload.submissionId ].sections [ action.payload.sectionId ], {
|
||||
enabled: true,
|
||||
data: newData
|
||||
})
|
||||
})
|
||||
),
|
||||
saveDecisionPending: false
|
||||
})
|
||||
});
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set decision flag to false
|
||||
*
|
||||
* @param state
|
||||
* the current state
|
||||
* @param action
|
||||
* an SetDuplicateDecisionSuccessAction or SetDuplicateDecisionErrorAction
|
||||
* @return SubmissionObjectState
|
||||
* the new state, with the decision flag changed.
|
||||
*/
|
||||
function endSaveDecision(state: SubmissionObjectState, action: SetDuplicateDecisionSuccessAction | SetDuplicateDecisionErrorAction): SubmissionObjectState {
|
||||
if (hasValue(state[ action.payload.submissionId ])) {
|
||||
return Object.assign({}, state, {
|
||||
[ action.payload.submissionId ]: Object.assign({}, state[ action.payload.submissionId ], {
|
||||
saveDecisionPending: false,
|
||||
})
|
||||
});
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
@@ -1,51 +0,0 @@
|
||||
import { Store } from '@ngrx/store';
|
||||
import { SubmissionState } from '../../submission.reducers';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { HttpHeaders } from '@angular/common/http';
|
||||
import { HttpOptions } from '../../../core/dspace-rest-v2/dspace-rest-v2.service';
|
||||
|
||||
@Injectable()
|
||||
export class DeduplicationService {
|
||||
|
||||
constructor(private store: Store<SubmissionState>) {
|
||||
}
|
||||
|
||||
// setWorkspaceDuplicated(payload: any): Observable<any> {
|
||||
// const options: HttpOptions = Object.create({});
|
||||
// let headers = new HttpHeaders();
|
||||
// headers = headers.append('Content-Type', 'application/json');
|
||||
// options.headers = headers;
|
||||
// // TODO REST CALL
|
||||
// // return this.restService.postToEndpoint('workspace/deduplication', payload, null, options);
|
||||
// return Observable.of(payload);
|
||||
// }
|
||||
|
||||
setWorkspaceDuplicationSuccess(payload: any): void {
|
||||
// TODO
|
||||
|
||||
}
|
||||
|
||||
setWorkspaceDuplicationError(payload: any): void {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// setWorkflowDuplicated(payload: any): Observable<any> {
|
||||
// const options: HttpOptions = Object.create({});
|
||||
// let headers = new HttpHeaders();
|
||||
// headers = headers.append('Content-Type', 'application/json');
|
||||
// options.headers = headers;
|
||||
// // TODO REST CALL
|
||||
// // return this.restService.postToEndpoint('workflow/deduplication', payload, null, options);
|
||||
// return Observable.of(payload);
|
||||
// }
|
||||
|
||||
setWorkflowDuplicationSuccess(payload: any): void {
|
||||
// TODO Update the redux store
|
||||
|
||||
}
|
||||
|
||||
setWorkflowDuplicationError(payload: any): void {
|
||||
// TODO Update the redux store
|
||||
}
|
||||
}
|
@@ -1,57 +1,50 @@
|
||||
<!--<ds-item-list-preview-->
|
||||
<!--[item]="item"-->
|
||||
<!--[object]="object"-->
|
||||
<!--></ds-item-list-preview>-->
|
||||
<ds-item-list-preview
|
||||
[item]="item"
|
||||
[object]="object"
|
||||
></ds-item-list-preview>
|
||||
|
||||
|
||||
<!--<button (click)="toggleSubmitterDecision()"-->
|
||||
<!--class="btn btn-link">-->
|
||||
<!--<span *ngIf="isWorkFlow && !showSubmitterDecision"> <i class="fa fa-angle-double-down"></i> Show submitter decision</span>-->
|
||||
<!--<span *ngIf="isWorkFlow && showSubmitterDecision"> <i class="fa fa-angle-double-up"></i> Hide submitter decision</span>-->
|
||||
<!--</button>-->
|
||||
|
||||
<!--<div *ngIf="showSubmitterDecision">-->
|
||||
<div>
|
||||
<label><strong> {{submitterDecisionLabel | async}} </strong>
|
||||
<span [ngClass]="{'label': true,
|
||||
'label-warning': match.submitterDecision == 'verify',
|
||||
'label-success': match.submitterDecision == 'reject',
|
||||
'label-default': (match.submitterDecision == undefined || match.submitterDecision == null)}">
|
||||
{{submitterDecisionTxt}}
|
||||
</span>
|
||||
</label>
|
||||
<div *ngIf="isWorkFlow" class="mt-2">
|
||||
<form>
|
||||
<div class="form-group mb-2">
|
||||
<label class="mb-1" for="submitterDecision"><strong> {{'submission.sections.detect-duplicate.submitter-decision' | translate}} </strong></label><br>
|
||||
<span id="submitterDecision" class="badge badge-pill {{decisionLabelClass}}">
|
||||
{{submitterDecision$ | async}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-group" *ngIf="submitterNote">
|
||||
<label for="submitterNote"><strong>{{'submission.sections.detect-duplicate.submitter-note' | translate}}</strong></label>
|
||||
<textarea class="form-control" id="submitterNote" rows="3" readonly>{{submitterNote}}</textarea>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<!--<div>-->
|
||||
<!--<label><strong> Explaination: </strong>-->
|
||||
<!--<span class="label">-->
|
||||
<!--I want to provide the fulltext of this article-->
|
||||
<!--</span>-->
|
||||
<!--</label>-->
|
||||
<!--</div>-->
|
||||
|
||||
<div class="mb-3" *ngIf="!decidedYet">
|
||||
<div class="mt-3 mb-2" *ngIf="!hasDecision">
|
||||
<button type="button"
|
||||
class="btn btn-warning"
|
||||
ngbTooltip="{{'submission.sections.deduplication.duplicated_help' | translate}}"
|
||||
ngbTooltip="{{'submission.sections.detect-duplicate.duplicate-help' | translate}}"
|
||||
[disabled]="(processingVerify | async) || (processingReject | async)"
|
||||
(click)="openModal(modal)">
|
||||
<span> {{duplicatedBtnLabel | async}}</span>
|
||||
<span *ngIf="(processingVerify | async)"><i class='fa fa-circle-o-notch fa-spin'></i> {{'submission.workflow.tasks.generic.processing' | translate}}</span>
|
||||
<span *ngIf="!(processingVerify | async)">{{duplicateBtnLabel$ | async}}</span>
|
||||
</button>
|
||||
|
||||
<button type="button"
|
||||
class="btn btn-success"
|
||||
ngbTooltip="{{'submission.sections.deduplication.not_duplicated_help' | translate}}"
|
||||
(click)="setAsNotDuplicated()">
|
||||
|
||||
<span> {{'submission.sections.deduplication.not_duplicated' | translate}}</span>
|
||||
ngbTooltip="{{'submission.sections.detect-duplicate.not-duplicate-help' | translate}}"
|
||||
[disabled]="(processingReject | async) || (processingVerify | async)"
|
||||
(click)="setAsNotDuplicate()">
|
||||
<span *ngIf="(processingReject | async)"><i class='fa fa-circle-o-notch fa-spin'></i> {{'submission.workflow.tasks.generic.processing' | translate}}</span>
|
||||
<span *ngIf="!(processingReject | async)">{{notDuplicateBtnLabel$ | async}}</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mb-3" *ngIf="decidedYet">
|
||||
<div class="mt-3 mb-2" *ngIf="hasDecision">
|
||||
<button type="button"
|
||||
class="btn btn-danger"
|
||||
ngbTooltip="{{'submission.sections.deduplication.clear_decision_help' | translate}}"
|
||||
ngbTooltip="{{'submission.sections.detect-duplicate.clear-decision-help' | translate}}"
|
||||
(click)="clearDecision()">
|
||||
<span> {{'submission.sections.deduplication.clear_decision' | translate}}</span>
|
||||
<span> {{'submission.sections.detect-duplicate.clear-decision' | translate}}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -67,20 +60,19 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-info" role="alert">
|
||||
{{'submission.sections.deduplication.note_help' | translate}}
|
||||
{{'submission.sections.detect-duplicate.note-help' | translate}}
|
||||
</div>
|
||||
<form (ngSubmit)="setAsDuplicated();" [formGroup]="rejectForm" >
|
||||
<textarea
|
||||
style="width: 100%"
|
||||
formControlName="reason"
|
||||
rows="4"
|
||||
placeholder="{{'submission.sections.deduplication.note_placeholder' | translate}}"></textarea>
|
||||
<button
|
||||
id="btn-chat"
|
||||
class="btn btn-danger btn-lg btn-block mt-3"
|
||||
[disabled]="!rejectForm.valid"
|
||||
type="submit">
|
||||
<span>{{'submission.sections.deduplication.duplicated' | translate}}</span>
|
||||
<form (ngSubmit)="setAsDuplicate();" [formGroup]="rejectForm" >
|
||||
<textarea class="w-100"
|
||||
formControlName="reason"
|
||||
rows="4"
|
||||
placeholder="{{'submission.sections.detect-duplicate.note-placeholder' | translate}}"></textarea>
|
||||
<button id="btn-chat"
|
||||
class="btn btn-danger btn-lg btn-block mt-3"
|
||||
[disabled]="!rejectForm.valid"
|
||||
type="submit">
|
||||
<span *ngIf="(processingReject | async)"><i class='fa fa-circle-o-notch fa-spin'></i> {{'submission.workflow.tasks.generic.processing' | translate}}</span>
|
||||
<span *ngIf="!(processingReject | async)">{{'submission.sections.detect-duplicate.duplicate' | translate}}</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
@@ -1,164 +1,146 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { Item } from '../../../../core/shared/item.model';
|
||||
import { DeduplicationSchema } from '../../../../core/submission/models/workspaceitem-section-deduplication.model';
|
||||
import { DetectDuplicateMatch } from '../../../../core/submission/models/workspaceitem-section-deduplication.model';
|
||||
import { SubmissionService } from '../../../submission.service';
|
||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { SubmissionState } from '../../../submission.reducers';
|
||||
import { DeduplicationService } from '../deduplication.service';
|
||||
import { DetectDuplicateService } from '../detect-duplicate.service';
|
||||
import { JsonPatchOperationsBuilder } from '../../../../core/json-patch/builder/json-patch-operations-builder';
|
||||
import { JsonPatchOperationPathCombiner } from '../../../../core/json-patch/builder/json-patch-operation-path-combiner';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { SubmissionScopeType } from '../../../../core/submission/submission-scope-type';
|
||||
import { DuplicateDecisionValue } from '../models/duplicate-decision-value';
|
||||
import { DuplicateDecision } from '../models/duplicate-decision.model';
|
||||
import { DuplicateDecisionType } from '../models/duplicate-decision-type';
|
||||
import { isNotEmpty } from '../../../../shared/empty.util';
|
||||
import { SectionsService } from '../../sections.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-deduplication-match',
|
||||
templateUrl: 'deduplication-match.component.html',
|
||||
selector: 'ds-duplicate-match',
|
||||
templateUrl: 'duplicate-match.component.html',
|
||||
})
|
||||
|
||||
export class DeduplicationMatchComponent implements OnInit {
|
||||
@Input()
|
||||
sectionId: string;
|
||||
@Input()
|
||||
match: DeduplicationSchema;
|
||||
@Input()
|
||||
submissionId: string;
|
||||
@Input()
|
||||
index: string;
|
||||
export class DuplicateMatchComponent implements OnInit {
|
||||
@Input() sectionId: string;
|
||||
@Input() itemId: string;
|
||||
@Input() match: DetectDuplicateMatch;
|
||||
@Input() submissionId: string;
|
||||
@Input() index: string;
|
||||
|
||||
object = {hitHighlights: []};
|
||||
item: Item;
|
||||
isWorkFlow = false;
|
||||
showSubmitterDecision = false;
|
||||
submitterDecisionTxt: string;
|
||||
decisionType: DuplicateDecisionType;
|
||||
submitterDecision$: Observable<string>;
|
||||
submitterNote: string;
|
||||
|
||||
decidedYet: boolean;
|
||||
hasDecision: boolean;
|
||||
|
||||
closeResult: string; // for modal
|
||||
rejectForm: FormGroup;
|
||||
modalRef: NgbModalRef;
|
||||
pathCombiner: JsonPatchOperationPathCombiner;
|
||||
public processingVerify: Observable<boolean> = Observable.of(false);
|
||||
public processingReject: Observable<boolean> = Observable.of(false);
|
||||
decisionLabelClass: string;
|
||||
duplicateBtnLabel$: Observable<string>;
|
||||
notDuplicateBtnLabel$: Observable<string>;
|
||||
|
||||
duplicatedBtnLabel: Observable<string>;
|
||||
submitterDecisionLabel: Observable<string>;
|
||||
|
||||
constructor(private deduplicationService: DeduplicationService,
|
||||
private submissionService: SubmissionService,
|
||||
private modalService: NgbModal,
|
||||
constructor(private detectDuplicateService: DetectDuplicateService,
|
||||
private formBuilder: FormBuilder,
|
||||
private store: Store<SubmissionState>,
|
||||
protected operationsBuilder: JsonPatchOperationsBuilder,
|
||||
private modalService: NgbModal,
|
||||
private operationsBuilder: JsonPatchOperationsBuilder,
|
||||
private sectionService: SectionsService,
|
||||
private submissionService: SubmissionService,
|
||||
private translate: TranslateService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if ((this.match.matchObject as any).item) {
|
||||
// WSI & WFI
|
||||
this.item = Object.assign(new Item(), (this.match.matchObject as any).item);
|
||||
} else {
|
||||
// Item
|
||||
this.item = Object.assign(new Item(), this.match.matchObject);
|
||||
}
|
||||
|
||||
this.isWorkFlow = this.submissionService.getSubmissionScope() === SubmissionScopeType.WorkflowItem;
|
||||
this.decisionType = this.isWorkFlow ? DuplicateDecisionType.WORKFLOW : DuplicateDecisionType.WORKSPACE;
|
||||
this.item = Object.assign(new Item(), this.match.matchObject);
|
||||
|
||||
this.rejectForm = this.formBuilder.group({
|
||||
reason: ['', Validators.required]
|
||||
});
|
||||
|
||||
this.decidedYet = this.isWorkFlow ?
|
||||
this.match.workflowDecision !== null ? true : false
|
||||
: this.match.submitterDecision !== null ? true : false;
|
||||
this.hasDecision = this.isWorkFlow ?
|
||||
this.match.workflowDecision !== null
|
||||
: this.match.submitterDecision !== null;
|
||||
|
||||
if (this.match.submitterDecision) {
|
||||
if (this.match.submitterDecision === 'verify') {
|
||||
this.submitterDecisionTxt = 'It\'s a duplicate';
|
||||
} else {
|
||||
this.submitterDecisionTxt = 'It\'s not a duplicate';
|
||||
}
|
||||
this.submitterDecision$ = (this.match.submitterDecision === DuplicateDecisionValue.Reject) ?
|
||||
this.translate.get('submission.sections.detect-duplicate.not-duplicate') :
|
||||
this.translate.get('submission.sections.detect-duplicate.duplicate');
|
||||
this.decisionLabelClass = (this.match.submitterDecision === DuplicateDecisionValue.Reject) ? 'badge-success' : 'badge-warning';
|
||||
this.submitterNote = this.match.submitterNote;
|
||||
} else {
|
||||
this.submitterDecisionTxt = 'Not decided';
|
||||
this.submitterDecision$ = this.translate.get('submission.sections.detect-duplicate.no-decision');
|
||||
this.decisionLabelClass = 'badge-light';
|
||||
}
|
||||
|
||||
this.pathCombiner = new JsonPatchOperationPathCombiner('sections', this.sectionId, 'matches', this.index);
|
||||
this.pathCombiner = new JsonPatchOperationPathCombiner('sections', this.sectionId);
|
||||
|
||||
this.duplicatedBtnLabel = this.isWorkFlow ?
|
||||
this.translate.get('submission.sections.deduplication.duplicated_ctrl')
|
||||
: this.translate.get('submission.sections.deduplication.duplicated');
|
||||
this.duplicateBtnLabel$ = this.isWorkFlow ?
|
||||
((this.match.submitterDecision === DuplicateDecisionValue.Verify) ?
|
||||
this.translate.get('submission.sections.detect-duplicate.confirm-duplicate') :
|
||||
this.translate.get('submission.sections.detect-duplicate.duplicate-ctrl'))
|
||||
: this.translate.get('submission.sections.detect-duplicate.duplicate');
|
||||
|
||||
this.submitterDecisionLabel = this.isWorkFlow ?
|
||||
this.translate.get('submission.sections.deduplication.submitter_decision')
|
||||
: this.translate.get('submission.sections.deduplication.your_decision');
|
||||
this.notDuplicateBtnLabel$ = (this.isWorkFlow && this.match.submitterDecision === DuplicateDecisionValue.Reject) ?
|
||||
this.translate.get('submission.sections.detect-duplicate.confirm-not-duplicate') :
|
||||
this.translate.get('submission.sections.detect-duplicate.not-duplicate');
|
||||
|
||||
}
|
||||
|
||||
setAsDuplicated() {
|
||||
console.log('Setting item #' + this.item.uuid + ' as duplicated...');
|
||||
this.dispatchAction(true);
|
||||
setAsDuplicate() {
|
||||
this.processingVerify = Observable.of(true);
|
||||
const decision = new DuplicateDecision(
|
||||
DuplicateDecisionValue.Verify,
|
||||
this.decisionType,
|
||||
this.rejectForm.get('reason').value);
|
||||
|
||||
this.dispatchAction(decision);
|
||||
this.modalRef.dismiss();
|
||||
}
|
||||
|
||||
setAsNotDuplicated() {
|
||||
console.log('Setting item #' + this.item.uuid + ' as not duplicated...');
|
||||
this.dispatchAction(false);
|
||||
setAsNotDuplicate() {
|
||||
this.processingReject = Observable.of(true);
|
||||
const decision = new DuplicateDecision(
|
||||
DuplicateDecisionValue.Reject,
|
||||
this.decisionType);
|
||||
|
||||
this.dispatchAction(decision);
|
||||
}
|
||||
|
||||
clearDecision() {
|
||||
console.log('Clearing item #' + this.item.uuid + ' from previous decision...');
|
||||
const decision = new DuplicateDecision(
|
||||
DuplicateDecisionValue.Undo,
|
||||
this.decisionType);
|
||||
|
||||
this.dispatchAction(decision);
|
||||
|
||||
}
|
||||
|
||||
private dispatchAction(duplicated: boolean, clear?: boolean): void {
|
||||
private dispatchAction(decision: DuplicateDecision): void {
|
||||
const pathDecision = Array.of('matches', this.itemId, this.isWorkFlow ? 'workflowDecision' : 'submitterDecision').join('/');
|
||||
const payload = {
|
||||
submissionId: this.submissionId,
|
||||
index: this.index,
|
||||
data: {} as DeduplicationSchema
|
||||
value: isNotEmpty(decision.value) ? decision.value : null,
|
||||
note: isNotEmpty(decision.note) ? decision.note : null
|
||||
};
|
||||
|
||||
// Call workflow action
|
||||
const decision = clear ? null : duplicated ? 'verify' : 'reject';
|
||||
const pathDecision = this.isWorkFlow ? 'workflowDecision' : 'submitterDecision';
|
||||
this.operationsBuilder.add(this.pathCombiner.getPath(pathDecision), decision, false, true);
|
||||
// dispatch patch operation only when section is active
|
||||
this.sectionService.isSectionActive(this.submissionId, this.sectionId)
|
||||
.filter((isActive: boolean) => isActive)
|
||||
.take(1)
|
||||
.subscribe(() => {
|
||||
this.operationsBuilder.add(this.pathCombiner.getPath(pathDecision), payload, false, true);
|
||||
this.detectDuplicateService.saveDuplicateDecision(this.submissionId, this.sectionId)
|
||||
});
|
||||
|
||||
if (!clear && duplicated) {
|
||||
const note = this.rejectForm.get('reason').value;
|
||||
const pathNote = this.isWorkFlow ? 'workflowNote' : 'submitterNote';
|
||||
this.operationsBuilder.add(this.pathCombiner.getPath(pathNote), note, false, true);
|
||||
}
|
||||
|
||||
// const now = new Date();
|
||||
// const time = now.getUTCFullYear() + '/' + now.getUTCMonth() + 1 + '/' + now.getDay();
|
||||
|
||||
// if (this.isWorkFlow) {
|
||||
// // Call workflow action
|
||||
// payload.data.workflowDecision = clear ? null : duplicated ? 'verify' : 'reject';
|
||||
// // payload.data.workflowTime = time;
|
||||
// if (!clear && duplicated) {
|
||||
// const note = this.rejectForm.get('reason').value;
|
||||
// payload.data.workflowNote = note;
|
||||
// }
|
||||
// // Dispatch WorkFLOW action
|
||||
// // this.store.dispatch(new SetWorkflowDuplicatedAction(payload));
|
||||
// const path = 'workflowDecision'
|
||||
// this.operationsBuilder.add(this.pathCombiner.getPath(path), payload.data.workflowDecision, false, true);
|
||||
//
|
||||
// } else {
|
||||
// // Call workspace action
|
||||
// payload.data.submitterDecision = clear ? null : duplicated ? 'verify' : 'reject';
|
||||
// // payload.data.submitterTime = time;
|
||||
// if (!clear && duplicated) {
|
||||
// const note = this.rejectForm.get('reason').value;
|
||||
// payload.data.submitterNote = note;
|
||||
// }
|
||||
// // Dispatch workSPACE action
|
||||
// this.store.dispatch(new SetWorkspaceDuplicatedAction(payload));
|
||||
// }
|
||||
}
|
||||
|
||||
toggleSubmitterDecision() {
|
||||
this.showSubmitterDecision = !this.showSubmitterDecision;
|
||||
}
|
||||
|
||||
openModal(modal) {
|
||||
|
@@ -1,38 +1,32 @@
|
||||
<ds-loading *ngIf="isLoading" message="Loading..."></ds-loading>
|
||||
|
||||
<ng-container *ngIf="(sectionDataObs | async)?.matches.length == 0">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h3 class="text-center"><span class="text-muted">No duplicated yet.</span></h3>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="(totalMatch$ | async) === 0">
|
||||
<ds-alert [type]="AlertTypeEnum.Info" [content]="('submission.sections.detect-duplicate.disclaimer-no-match' | translate)"></ds-alert>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="(sectionDataObs | async)?.matches.length > 0">
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{{ disclaimer | async }}
|
||||
</div>
|
||||
<ng-container *ngIf="(totalMatch$ | async) > 0">
|
||||
<ds-alert [type]="AlertTypeEnum.Warning" [content]="(disclaimer | async)"></ds-alert>
|
||||
|
||||
<ds-pagination
|
||||
[paginationOptions]="config"
|
||||
[collectionSize]="(sectionDataObs | async)?.matches.length"
|
||||
[collectionSize]="(totalMatch$ | async)"
|
||||
[sortOptions]="sortConfig"
|
||||
[hideGear]="true"
|
||||
[hidePagerWhenSinglePage]="false"
|
||||
(pageChange)="setPage($event)">
|
||||
|
||||
<ul class="list-unstyled">
|
||||
<li *ngFor="let match of (sectionDataObs | async)?.matches
|
||||
| paginate: {id: config.id, itemsPerPage: config.pageSize, currentPage: config.currentPage}; let i = index"
|
||||
class="mt-4 mb-4">
|
||||
|
||||
<ds-deduplication-match
|
||||
<li *ngFor="let item of (sectionData$ | async)?.matches | dsObjNgFor
|
||||
| paginate: {id: config.id, itemsPerPage: config.pageSize, currentPage: config.currentPage}; let i = index; let l = last"
|
||||
class="mt-4 mb-4"
|
||||
[class.border-bottom]="!l">
|
||||
<ds-duplicate-match
|
||||
*ngVar="(i + (config.currentPage-1)*config.pageSize) as totalIndex"
|
||||
[sectionId]="sectionData.id"
|
||||
[match]="match"
|
||||
[match]="item.value"
|
||||
[submissionId]="submissionId"
|
||||
[index]=totalIndex></ds-deduplication-match>
|
||||
[index]=totalIndex
|
||||
[itemId]="item.key"></ds-duplicate-match>
|
||||
</li>
|
||||
</ul>
|
||||
</ds-pagination>
|
||||
|
@@ -1,40 +1,45 @@
|
||||
import { SectionsType } from '../sections-type';
|
||||
import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, Inject, OnDestroy, OnInit } from '@angular/core';
|
||||
import { SectionModelComponent } from '../models/section.model';
|
||||
import { renderSectionFor } from '../sections-decorator';
|
||||
import { SectionDataObject } from '../models/section-data.model';
|
||||
import { SubmissionState } from '../../submission.reducers';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||
import { PaginationComponentOptions } from '../../../shared/pagination/pagination-component-options.model';
|
||||
import { submissionSectionDataFromIdSelector } from '../../selectors';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { isNotEmpty } from '../../../shared/empty.util';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { SubmissionService } from '../../submission.service';
|
||||
import { SubmissionScopeType } from '../../../core/submission/submission-scope-type';
|
||||
import { AlertType } from '../../../shared/alerts/aletrs-type';
|
||||
import { DetectDuplicateService } from './detect-duplicate.service';
|
||||
import { SectionsService } from '../sections.service';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { hasValue } from '../../../shared/empty.util';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-deduplication-section',
|
||||
// styleUrls: ['./section-deduplication.component.scss'],
|
||||
templateUrl: './section-deduplication.component.html',
|
||||
templateUrl: './section-detect-duplicate.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.Default
|
||||
})
|
||||
|
||||
@renderSectionFor(SectionsType.Deduplication)
|
||||
export class DeduplicationSectionComponent extends SectionModelComponent implements OnInit {
|
||||
@renderSectionFor(SectionsType.DetectDuplicate)
|
||||
export class DetectDuplicateSectionComponent extends SectionModelComponent implements OnDestroy, OnInit {
|
||||
public AlertTypeEnum = AlertType;
|
||||
public isLoading = true;
|
||||
public sectionDataObs: Observable<any>;
|
||||
public matches = [];
|
||||
public sectionData$: Observable<any>;
|
||||
public matches = {};
|
||||
public totalMatch$: Observable<number>;
|
||||
|
||||
config: PaginationComponentOptions;
|
||||
sortConfig: SortOptions;
|
||||
|
||||
isWorkFlow = false;
|
||||
disclaimer: Observable<string>;
|
||||
sub: Subscription;
|
||||
|
||||
constructor(protected store: Store<SubmissionState>,
|
||||
constructor(private detectDuplicateService: DetectDuplicateService,
|
||||
private translate: TranslateService,
|
||||
private sectionService: SectionsService,
|
||||
private submissionService: SubmissionService,
|
||||
@Inject('collectionIdProvider') public injectedCollectionId: string,
|
||||
@Inject('sectionDataProvider') public injectedSectionData: SectionDataObject,
|
||||
@@ -48,26 +53,34 @@ export class DeduplicationSectionComponent extends SectionModelComponent impleme
|
||||
this.config.pageSize = 2;
|
||||
this.sortConfig = new SortOptions('dc.title', SortDirection.ASC);
|
||||
|
||||
this.sectionDataObs = this.store.select(submissionSectionDataFromIdSelector(this.submissionId, this.sectionData.id))
|
||||
.filter((sd) => isNotEmpty(sd))
|
||||
.startWith({matches: []})
|
||||
.distinctUntilChanged()
|
||||
.map((sd) => {
|
||||
return sd;
|
||||
});
|
||||
this.sectionData$ = this.detectDuplicateService.getDuplicateMatches(this.submissionId, this.sectionData.id);
|
||||
|
||||
this.totalMatch$ = this.detectDuplicateService.getDuplicateTotalMatches(this.submissionId, this.sectionData.id);
|
||||
|
||||
this.isWorkFlow = this.submissionService.getSubmissionScope() === SubmissionScopeType.WorkflowItem;
|
||||
|
||||
this.disclaimer = this.isWorkFlow ?
|
||||
this.translate.get('submission.sections.deduplication.disclaimer_ctrl')
|
||||
: this.translate.get('submission.sections.deduplication.disclaimer');
|
||||
this.translate.get('submission.sections.detect-duplicate.disclaimer-ctrl')
|
||||
: this.translate.get('submission.sections.detect-duplicate.disclaimer');
|
||||
|
||||
this.isLoading = false;
|
||||
|
||||
this.sub = this.totalMatch$
|
||||
.map((totalMatches: number) => totalMatches === 0)
|
||||
.distinctUntilChanged()
|
||||
.subscribe((status: boolean) => {
|
||||
this.sectionService.setSectionStatus(this.submissionId, this.sectionData.id, status);
|
||||
})
|
||||
}
|
||||
|
||||
setPage(page) {
|
||||
console.log('Select page #', page);
|
||||
this.config.currentPage = page;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (hasValue(this.sub)) {
|
||||
this.sub.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
import { Store } from '@ngrx/store';
|
||||
import { SubmissionState } from '../../submission.reducers';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SetDuplicateDecisionAction } from '../../objects/submission-objects.actions';
|
||||
import { submissionSectionDataFromIdSelector } from '../../selectors';
|
||||
import { WorkspaceitemSectionDetectDuplicateObject } from '../../../core/submission/models/workspaceitem-section-deduplication.model';
|
||||
import { isEmpty } from '../../../shared/empty.util';
|
||||
|
||||
@Injectable()
|
||||
export class DetectDuplicateService {
|
||||
|
||||
constructor(private store: Store<SubmissionState>) {
|
||||
}
|
||||
|
||||
getDuplicateMatches(submissionId: string, sectionId: string) {
|
||||
return this.store.select(submissionSectionDataFromIdSelector(submissionId, sectionId))
|
||||
.map((sectionData: WorkspaceitemSectionDetectDuplicateObject) => {
|
||||
return (isEmpty(sectionData)) ? {matches: {}} : sectionData
|
||||
})
|
||||
.startWith({matches: {}})
|
||||
.distinctUntilChanged();
|
||||
}
|
||||
|
||||
getDuplicateTotalMatches(submissionId: string, sectionId: string) {
|
||||
return this.getDuplicateMatches(submissionId, sectionId)
|
||||
.map((sectionData: WorkspaceitemSectionDetectDuplicateObject) => Object.keys(sectionData.matches).length)
|
||||
.distinctUntilChanged();
|
||||
}
|
||||
|
||||
saveDuplicateDecision(submissionId: string, sectionId: string): void {
|
||||
this.store.dispatch(new SetDuplicateDecisionAction(submissionId, sectionId));
|
||||
}
|
||||
}
|
@@ -134,7 +134,7 @@ export class SectionsDirective implements OnDestroy, OnInit {
|
||||
|
||||
public setFocus(event) {
|
||||
if (!this.active) {
|
||||
this.store.dispatch(new SetActiveSectionAction(this.submissionId, this.sectionId));
|
||||
this.submissionService.setActiveSection(this.submissionId, this.sectionId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@ import { hasValue, isEmpty, isNotEmpty, isNotUndefined } from '../../shared/empt
|
||||
import {
|
||||
DisableSectionAction,
|
||||
EnableSectionAction,
|
||||
InertSectionErrorsAction, RemoveSectionErrorsAction,
|
||||
InertSectionErrorsAction, RemoveSectionErrorsAction, SectionStatusChangeAction,
|
||||
UpdateSectionDataAction
|
||||
} from '../objects/submission-objects.actions';
|
||||
import {
|
||||
@@ -24,12 +24,14 @@ import parseSectionErrorPaths, { SectionErrorPath } from '../utils/parseSectionE
|
||||
import { FormAddError, FormClearErrorsAction, FormRemoveErrorAction } from '../../shared/form/form.actions';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { SubmissionService } from '../submission.service';
|
||||
|
||||
@Injectable()
|
||||
export class SectionsService {
|
||||
|
||||
constructor(private notificationsService: NotificationsService,
|
||||
private scrollToService: ScrollToService,
|
||||
private submissionService: SubmissionService,
|
||||
private store: Store<SubmissionState>,
|
||||
private translate: TranslateService) {
|
||||
}
|
||||
@@ -86,6 +88,12 @@ export class SectionsService {
|
||||
.distinctUntilChanged();
|
||||
}
|
||||
|
||||
public isSectionActive(submissionId, sectionId): Observable<boolean> {
|
||||
return this.submissionService.getActiveSectionId(submissionId)
|
||||
.map((activeSectionId: string) => sectionId === activeSectionId)
|
||||
.distinctUntilChanged();
|
||||
}
|
||||
|
||||
public isSectionEnabled(submissionId, sectionId): Observable<boolean> {
|
||||
return this.store.select(submissionSectionFromIdSelector(submissionId, sectionId))
|
||||
.filter((sectionObj) => hasValue(sectionObj))
|
||||
@@ -150,4 +158,8 @@ export class SectionsService {
|
||||
public setSectionError(submissionId: string, sectionId: string, error: SubmissionSectionError) {
|
||||
this.store.dispatch(new InertSectionErrorsAction(submissionId, sectionId, error));
|
||||
}
|
||||
|
||||
public setSectionStatus(submissionId: string, sectionId: string, status: boolean) {
|
||||
this.store.dispatch(new SectionStatusChangeAction(submissionId, sectionId, status));
|
||||
}
|
||||
}
|
||||
|
@@ -29,9 +29,9 @@ import { UploadSectionFileEditComponent } from './sections/upload/file/edit/file
|
||||
import { UploadSectionFileViewComponent } from './sections/upload/file/view/file-view.component';
|
||||
import { AccessConditionsComponent } from './sections/upload/accessConditions/accessConditions.component';
|
||||
import { RecycleSectionComponent } from './sections/recycle/section-recycle.component';
|
||||
import { DeduplicationSectionComponent } from './sections/deduplication/section-deduplication.component';
|
||||
import { DeduplicationMatchComponent } from './sections/deduplication/match/deduplication-match.component';
|
||||
import { DeduplicationService } from './sections/deduplication/deduplication.service';
|
||||
import { DetectDuplicateSectionComponent } from './sections/detect-duplicate/section-detect-duplicate.component';
|
||||
import { DuplicateMatchComponent } from './sections/detect-duplicate/duplicate-match/duplicate-match.component';
|
||||
import { DetectDuplicateService } from './sections/detect-duplicate/detect-duplicate.service';
|
||||
import { SubmissionSubmitComponent } from './submit/submission-submit.component';
|
||||
|
||||
@NgModule({
|
||||
@@ -62,8 +62,8 @@ import { SubmissionSubmitComponent } from './submit/submission-submit.component'
|
||||
UploadSectionFileEditComponent,
|
||||
UploadSectionFileViewComponent,
|
||||
RecycleSectionComponent,
|
||||
DeduplicationSectionComponent,
|
||||
DeduplicationMatchComponent,
|
||||
DetectDuplicateSectionComponent,
|
||||
DuplicateMatchComponent,
|
||||
],
|
||||
entryComponents: [
|
||||
DefaultSectionComponent,
|
||||
@@ -72,7 +72,7 @@ import { SubmissionSubmitComponent } from './submit/submission-submit.component'
|
||||
LicenseSectionComponent,
|
||||
SectionContainerComponent,
|
||||
RecycleSectionComponent,
|
||||
DeduplicationSectionComponent],
|
||||
DetectDuplicateSectionComponent],
|
||||
exports: [
|
||||
SubmissionEditComponent,
|
||||
SubmissionFormComponent,
|
||||
@@ -83,7 +83,7 @@ import { SubmissionSubmitComponent } from './submit/submission-submit.component'
|
||||
SectionsService,
|
||||
SubmissionRestService,
|
||||
SubmissionUploadsConfigService,
|
||||
DeduplicationService
|
||||
DetectDuplicateService
|
||||
]
|
||||
})
|
||||
export class SubmissionModule {
|
||||
|
@@ -7,7 +7,7 @@ import { Store } from '@ngrx/store';
|
||||
|
||||
import { submissionSelector, SubmissionState } from './submission.reducers';
|
||||
import { hasValue, isEmpty, isNotUndefined } from '../shared/empty.util';
|
||||
import { SaveSubmissionFormAction } from './objects/submission-objects.actions';
|
||||
import { SaveSubmissionFormAction, SetActiveSectionAction } from './objects/submission-objects.actions';
|
||||
import {
|
||||
SubmissionObjectEntry,
|
||||
SubmissionSectionEntry,
|
||||
@@ -26,6 +26,8 @@ import { RouteService } from '../shared/services/route.service';
|
||||
import { SectionsType } from './sections/sections-type';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { NotificationsService } from '../shared/notifications/notifications.service';
|
||||
import { ScrollToConfigOptions, ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
||||
import { NotificationOptions } from '../shared/notifications/models/notification-options.model';
|
||||
|
||||
@Injectable()
|
||||
export class SubmissionService {
|
||||
@@ -38,6 +40,7 @@ export class SubmissionService {
|
||||
protected restService: SubmissionRestService,
|
||||
protected router: Router,
|
||||
protected routeService: RouteService,
|
||||
protected scrollToService: ScrollToService,
|
||||
protected store: Store<SubmissionState>,
|
||||
protected translate: TranslateService) {
|
||||
}
|
||||
@@ -79,6 +82,7 @@ export class SubmissionService {
|
||||
const availableSections: SectionDataObject[] = [];
|
||||
Object.keys(sections)
|
||||
.filter((sectionId) => !this.isSectionHidden(sections[sectionId] as SubmissionSectionObject))
|
||||
// .filter((sectionId) => sections[sectionId].sectionType !== SectionsType.DetectDuplicate || isNotEmpty(sections[sectionId].data))
|
||||
.forEach((sectionId) => {
|
||||
const sectionObject: SectionDataObject = Object.create({});
|
||||
sectionObject.config = sections[sectionId].config;
|
||||
@@ -105,6 +109,7 @@ export class SubmissionService {
|
||||
Object.keys(sections)
|
||||
.filter((sectionId) => !this.isSectionHidden(sections[sectionId] as SubmissionSectionObject))
|
||||
.filter((sectionId) => !sections[sectionId].enabled)
|
||||
.filter((sectionId) => sections[sectionId].sectionType !== SectionsType.DetectDuplicate)
|
||||
.forEach((sectionId) => {
|
||||
const sectionObject: SectionDataObject = Object.create({});
|
||||
sectionObject.header = sections[sectionId].header;
|
||||
@@ -196,6 +201,13 @@ export class SubmissionService {
|
||||
.startWith(false);
|
||||
}
|
||||
|
||||
getSubmissionDuplicateDecisionProcessingStatus(submissionId: string): Observable<boolean> {
|
||||
return this.getSubmissionObject(submissionId)
|
||||
.map((state: SubmissionObjectEntry) => state.saveDecisionPending)
|
||||
.distinctUntilChanged()
|
||||
.startWith(false);
|
||||
}
|
||||
|
||||
redirectToMyDSpace() {
|
||||
const previousUrl = this.routeService.getPreviousUrl();
|
||||
if (isEmpty(previousUrl)) {
|
||||
@@ -205,12 +217,28 @@ export class SubmissionService {
|
||||
}
|
||||
}
|
||||
|
||||
notifyNewSection(sectionId: string, sectionType?: SectionsType) {
|
||||
this.translate.get('submission.sections.general.metadata-extracted-new-section', {sectionId})
|
||||
.take(1)
|
||||
.subscribe((m) => {
|
||||
this.notificationsService.info(null, m, null, true);
|
||||
});
|
||||
notifyNewSection(submissionId: string, sectionId: string, sectionType?: SectionsType) {
|
||||
|
||||
if (sectionType === SectionsType.DetectDuplicate) {
|
||||
this.setActiveSection(submissionId, sectionId);
|
||||
this.translate.get('submission.sections.detect-duplicate.duplicate-detected', {sectionId})
|
||||
.take(1)
|
||||
.subscribe((msg) => {
|
||||
this.notificationsService.warning(null, msg, new NotificationOptions(0));
|
||||
});
|
||||
const config: ScrollToConfigOptions = {
|
||||
target: sectionId,
|
||||
offset: -70
|
||||
};
|
||||
|
||||
this.scrollToService.scrollTo(config);
|
||||
} else {
|
||||
this.translate.get('submission.sections.general.metadata-extracted-new-section', {sectionId})
|
||||
.take(1)
|
||||
.subscribe((msg) => {
|
||||
this.notificationsService.info(null, msg, null, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
retrieveSubmission(submissionId): Observable<SubmissionObject> {
|
||||
return this.restService.getDataById(this.getSubmissionObjectLinkName(), submissionId)
|
||||
@@ -219,6 +247,10 @@ export class SubmissionService {
|
||||
.map((submissionObjects: SubmissionObject[]) => submissionObjects[0]);
|
||||
}
|
||||
|
||||
setActiveSection(submissionId, sectionId) {
|
||||
this.store.dispatch(new SetActiveSectionAction(submissionId, sectionId));
|
||||
}
|
||||
|
||||
startAutoSave(submissionId) {
|
||||
this.stopAutoSave();
|
||||
console.log('AUTOSAVE ON!!!');
|
||||
|
Reference in New Issue
Block a user