Merge remote-tracking branch 'origin/main' into CST-5270-sherpa-romeo-integration

# Conflicts:
#	src/app/submission/objects/submission-objects.effects.ts
This commit is contained in:
Giuseppe Digilio
2022-04-27 15:56:36 +02:00
10 changed files with 113 additions and 189 deletions

View File

@@ -9,4 +9,9 @@ EXPOSE 4000
# We run yarn install with an increased network timeout (5min) to avoid "ESOCKETTIMEDOUT" errors from hub.docker.com
# See, for example https://github.com/yarnpkg/yarn/issues/5540
RUN yarn install --network-timeout 300000
CMD yarn run start:dev
# On startup, run in DEVELOPMENT mode (this defaults to live reloading enabled, etc).
# Listen / accept connections from all IP addresses.
# NOTE: At this time it is only possible to run Docker container in Production mode
# if you have a public IP. See https://github.com/DSpace/dspace-angular/issues/1485
CMD yarn serve --host 0.0.0.0

View File

@@ -42,6 +42,7 @@ describe('New Submission page', () => {
cy.get('button#deposit').click();
// A warning alert should display.
cy.get('ds-notification div.alert-success').should('not.exist');
cy.get('ds-notification div.alert-warning').should('be.visible');
// First section should have an exclamation error in the header

View File

@@ -1,21 +1,35 @@
import { Component, HostListener, Injector, OnInit } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { combineLatest, combineLatest as observableCombineLatest, Observable, BehaviorSubject } from 'rxjs';
import { debounceTime, first, map, take, filter, distinctUntilChanged, withLatestFrom } from 'rxjs/operators';
import { BehaviorSubject, combineLatest as observableCombineLatest, combineLatest, Observable } from 'rxjs';
import { debounceTime, distinctUntilChanged, filter, first, map, take, withLatestFrom } from 'rxjs/operators';
import { AuthService } from '../../core/auth/auth.service';
import {
ScriptDataService,
METADATA_EXPORT_SCRIPT_NAME,
METADATA_IMPORT_SCRIPT_NAME,
METADATA_EXPORT_SCRIPT_NAME
ScriptDataService
} from '../../core/data/processes/script-data.service';
import { slideHorizontal, slideSidebar } from '../../shared/animations/slide';
import { CreateCollectionParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component';
import { CreateCommunityParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component';
import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component';
import { EditCollectionSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component';
import { EditCommunitySelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component';
import { EditItemSelectorComponent } from '../../shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component';
import { ExportMetadataSelectorComponent } from '../../shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component';
import {
CreateCollectionParentSelectorComponent
} from '../../shared/dso-selector/modal-wrappers/create-collection-parent-selector/create-collection-parent-selector.component';
import {
CreateCommunityParentSelectorComponent
} from '../../shared/dso-selector/modal-wrappers/create-community-parent-selector/create-community-parent-selector.component';
import {
CreateItemParentSelectorComponent
} from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component';
import {
EditCollectionSelectorComponent
} from '../../shared/dso-selector/modal-wrappers/edit-collection-selector/edit-collection-selector.component';
import {
EditCommunitySelectorComponent
} from '../../shared/dso-selector/modal-wrappers/edit-community-selector/edit-community-selector.component';
import {
EditItemSelectorComponent
} from '../../shared/dso-selector/modal-wrappers/edit-item-selector/edit-item-selector.component';
import {
ExportMetadataSelectorComponent
} from '../../shared/dso-selector/modal-wrappers/export-metadata-selector/export-metadata-selector.component';
import { LinkMenuItemModel } from '../../shared/menu/menu-item/models/link.model';
import { OnClickMenuItemModel } from '../../shared/menu/menu-item/models/onclick.model';
import { TextMenuItemModel } from '../../shared/menu/menu-item/models/text.model';
@@ -26,7 +40,7 @@ import { AuthorizationDataService } from '../../core/data/feature-authorization/
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { MenuID } from '../../shared/menu/menu-id.model';
import { MenuItemType } from '../../shared/menu/menu-item-type.model';
import { Router, ActivatedRoute } from '@angular/router';
import { ActivatedRoute } from '@angular/router';
/**
* Component representing the admin sidebar
@@ -86,12 +100,12 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
* Set and calculate all initial values of the instance variables
*/
ngOnInit(): void {
this.createMenu();
super.ngOnInit();
this.sidebarWidth = this.variableService.getVariable('sidebarItemsWidth');
this.authService.isAuthenticated()
.subscribe((loggedIn: boolean) => {
if (loggedIn) {
this.createMenu();
this.menuService.showMenu(this.menuID);
}
});
@@ -368,10 +382,10 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
];
menuList.forEach((menuSection) => this.menuService.addSection(this.menuID, menuSection));
observableCombineLatest(
observableCombineLatest([
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
this.scriptDataService.scriptWithNameExistsAndCanExecute(METADATA_EXPORT_SCRIPT_NAME)
).pipe(
]).pipe(
filter(([authorized, metadataExportScriptExists]: boolean[]) => authorized && metadataExportScriptExists),
take(1)
).subscribe(() => {
@@ -430,10 +444,10 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
shouldPersistOnRouteChange: true
})));
observableCombineLatest(
observableCombineLatest([
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
this.scriptDataService.scriptWithNameExistsAndCanExecute(METADATA_IMPORT_SCRIPT_NAME)
).pipe(
]).pipe(
filter(([authorized, metadataImportScriptExists]: boolean[]) => authorized && metadataImportScriptExists),
take(1)
).subscribe(() => {
@@ -559,10 +573,10 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
* Create menu sections dependent on whether or not the current user can manage access control groups
*/
createAccessControlMenuSections() {
observableCombineLatest(
observableCombineLatest([
this.authorizationService.isAuthorized(FeatureID.AdministratorOf),
this.authorizationService.isAuthorized(FeatureID.CanManageGroups)
).subscribe(([isSiteAdmin, canManageGroups]) => {
]).subscribe(([isSiteAdmin, canManageGroups]) => {
const menuList = [
/* Access Control */
{

View File

@@ -201,7 +201,6 @@ export class AppComponent implements OnInit, AfterViewInit {
if (event instanceof NavigationStart) {
resolveEndFound = false;
this.isRouteLoading$.next(true);
this.isThemeLoading$.next(true);
} else if (event instanceof ResolveEnd) {
resolveEndFound = true;
const activatedRouteSnapShot: ActivatedRouteSnapshot = event.state.root;

View File

@@ -1,4 +1,4 @@
<div class="outer-wrapper" *ngIf="!shouldShowFullscreenLoader; else fullScreenLoader">
<div class="outer-wrapper" [class.d-none]="shouldShowFullscreenLoader">
<ds-themed-admin-sidebar></ds-themed-admin-sidebar>
<div class="inner-wrapper" [@slideSidebarPadding]="{
value: (!(sidebarVisible | async) ? 'hidden' : (slideSidebarOver | async) ? 'shown' : 'expanded'),
@@ -22,8 +22,7 @@
<ds-notifications-board [options]="notificationOptions">
</ds-notifications-board>
<ng-template #fullScreenLoader>
<div class="ds-full-screen-loader">
<ds-loading [showMessage]="false"></ds-loading>
</div>
</ng-template>
<div class="ds-full-screen-loader" *ngIf="shouldShowFullscreenLoader">
<ds-loading [showMessage]="false"></ds-loading>
</div>

View File

@@ -4,6 +4,7 @@ import { FormBuilder } from '@angular/forms';
import { Subscription } from 'rxjs';
import { SearchEvent } from '../eperson-group-list.component';
import { isNotNull } from '../../../../empty.util';
/**
* A component used to show a search box for groups.
@@ -54,7 +55,7 @@ export class GroupSearchBoxComponent {
submit(data: any) {
const event: SearchEvent = {
scope: '',
query: data.query
query: isNotNull(data) ? data.query : ''
};
this.search.emit(event);
}

View File

@@ -421,7 +421,8 @@ export class SaveSubmissionFormSuccessAction implements Action {
payload: {
submissionId: string;
submissionObject: SubmissionObject[];
notify?: boolean
showNotifications?: boolean;
showErrors?: boolean;
};
/**
@@ -431,9 +432,13 @@ export class SaveSubmissionFormSuccessAction implements Action {
* the submission's ID
* @param submissionObject
* the submission's Object
* @param showNotifications
* a boolean representing if to show notifications on save
* @param showErrors
* a boolean representing if to show errors on save
*/
constructor(submissionId: string, submissionObject: SubmissionObject[], notify?: boolean) {
this.payload = { submissionId, submissionObject, notify };
constructor(submissionId: string, submissionObject: SubmissionObject[], showNotifications?: boolean, showErrors?: boolean) {
this.payload = { submissionId, submissionObject, showNotifications, showErrors };
}
}

View File

@@ -237,6 +237,7 @@ describe('SubmissionObjectEffects test suite', () => {
b: new SaveSubmissionFormSuccessAction(
submissionId,
mockSubmissionRestResponse as any,
true,
true
)
});
@@ -260,6 +261,7 @@ describe('SubmissionObjectEffects test suite', () => {
b: new SaveSubmissionFormSuccessAction(
submissionId,
mockSubmissionRestResponse as any,
false,
false
)
});
@@ -884,6 +886,7 @@ describe('SubmissionObjectEffects test suite', () => {
});
expect(submissionObjectEffects.saveAndDeposit$).toBeObservable(expected);
expect(notificationsServiceStub.warning).not.toHaveBeenCalled();
});
it('should return a SAVE_SUBMISSION_FORM_SUCCESS action when there are errors', () => {
@@ -910,10 +913,11 @@ describe('SubmissionObjectEffects test suite', () => {
submissionJsonPatchOperationsServiceStub.jsonPatchByResourceType.and.returnValue(observableOf(response));
const expected = cold('--b-', {
b: new SaveSubmissionFormSuccessAction(submissionId, response as any[])
b: new SaveSubmissionFormSuccessAction(submissionId, response as any[], false, true)
});
expect(submissionObjectEffects.saveAndDeposit$).toBeObservable(expected);
expect(notificationsServiceStub.warning).toHaveBeenCalled();
});
it('should catch errors and return a SAVE_SUBMISSION_FORM_ERROR', () => {

View File

@@ -1,4 +1,3 @@
import { WorkspaceitemSectionSherpaPoliciesObject } from './../../core/submission/models/workspaceitem-section-sherpa-policies.model';
import { Injectable } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
@@ -44,7 +43,7 @@ import {
UpdateSectionDataAction,
UpdateSectionDataSuccessAction
} from './submission-objects.actions';
import { SubmissionObjectEntry } from './submission-objects.reducer';
import { SubmissionObjectEntry} from './submission-objects.reducer';
import { Item } from '../../core/shared/item.model';
import { RemoteData } from '../../core/data/remote-data';
import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
@@ -61,12 +60,12 @@ export class SubmissionObjectEffects {
/**
* Dispatch a [InitSectionAction] for every submission sections and dispatch a [CompleteInitSubmissionFormAction]
*/
loadForm$ = createEffect(() => this.actions$.pipe(
loadForm$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.INIT_SUBMISSION_FORM),
map((action: InitSubmissionFormAction) => {
const definition = action.payload.submissionDefinition;
const mappedActions = [];
definition.sections.page.forEach((sectionDefinition: any, index) => {
definition.sections.page.forEach((sectionDefinition: any) => {
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) : '';
@@ -78,7 +77,6 @@ export class SubmissionObjectEffects {
sectionData = action.payload.item.metadata;
}
const sectionErrors = isNotEmpty(action.payload.errors) ? (action.payload.errors[sectionId] || null) : null;
mappedActions.push(
new InitSectionAction(
action.payload.submissionId,
@@ -93,123 +91,7 @@ export class SubmissionObjectEffects {
sectionErrors
)
);
if (index === definition.sections.page.length - 1) {
mappedActions.push(
new InitSectionAction(
action.payload.submissionId,
'sherpaPolicies',
'submit.progressbar.sherpaPolicies',
'submit.progressbar.sherpaPolicies',
true,
SectionsType.SherpaPolicies,
{ main: null, other: 'READONLY' },
true,
{
'id': 'sherpaPolicies',
'retrievalTime': '2022-04-20T09:44:39.870+00:00',
'sherpaResponse': [
{
'error': false,
'message': null,
'metadata': {
'id': 23803,
'uri': 'http://v2.sherpa.ac.uk/id/publication/23803',
'dateCreated': '2012-11-20 14:51:52',
'dateModified': '2020-03-06 11:25:54',
'inDOAJ': false,
'publiclyVisible': true
},
'journals': [{
'titles': ['The Lancet', 'Lancet'],
'url': 'http://www.thelancet.com/journals/lancet/issue/current',
'issns': ['0140-6736', '1474-547X'],
'romeoPub': 'Elsevier: The Lancet',
'zetoPub': 'Elsevier: The Lancet',
'publisher': {
'name': 'Elsevier',
'relationshipType': null,
'country': null,
'uri': 'http://www.elsevier.com/',
'identifier': null,
'publicationCount': 0,
'paidAccessDescription': 'Open access',
'paidAccessUrl': 'https://www.elsevier.com/about/open-science/open-access'
},
'publishers': [{
'name': 'Elsevier',
'relationshipType': null,
'country': null,
'uri': 'http://www.elsevier.com/',
'identifier': null,
'publicationCount': 0,
'paidAccessDescription': 'Open access',
'paidAccessUrl': 'https://www.elsevier.com/about/open-science/open-access'
}],
'policies': [{
'id': 0,
'openAccessPermitted': false,
'uri': null,
'internalMoniker': 'Lancet',
'permittedVersions': [{
'articleVersion': 'submitted',
'option': 1,
'conditions': ['Upon publication publisher copyright and source must be acknowledged', 'Upon publication must link to publisher version'],
'prerequisites': [],
'locations': ['Author\'s Homepage', 'Preprint Repository'],
'licenses': [],
'embargo': null
}, {
'articleVersion': 'accepted',
'option': 1,
'conditions': ['Publisher copyright and source must be acknowledged', 'Must link to publisher version'],
'prerequisites': [],
'locations': ['Author\'s Homepage', 'Institutional Website'],
'licenses': ['CC BY-NC-ND'],
'embargo': null
}, {
'articleVersion': 'accepted',
'option': 2,
'conditions': ['Publisher copyright and source must be acknowledged', 'Must link to publisher version'],
'prerequisites': ['If Required by Funder'],
'locations': ['Non-Commercial Repository'],
'licenses': ['CC BY-NC-ND'],
'embargo': null
}, {
'articleVersion': 'accepted',
'option': 3,
'conditions': ['Publisher copyright and source must be acknowledged', 'Must link to publisher version'],
'prerequisites': [],
'locations': ['Non-Commercial Repository'],
'licenses': [],
'embargo': null
}],
'urls': {
'http://download.thelancet.com/flatcontentassets/authors/lancet-information-for-authors.pdf': 'Guidelines for Authors',
'http://www.thelancet.com/journals/lancet/article/PIIS0140-6736%2813%2960720-5/fulltext': 'The Lancet journals welcome a new open access policy',
'http://www.thelancet.com/lancet-information-for-authors/after-publication': 'What happens after publication?',
'http://www.thelancet.com/lancet/information-for-authors/disclosure-of-results': 'Disclosure of results before publication',
'https://www.elsevier.com/__data/assets/pdf_file/0005/78476/external-embargo-list.pdf': 'Journal Embargo Period List',
'https://www.elsevier.com/__data/assets/pdf_file/0011/78473/UK-Embargo-Periods.pdf': 'Journal Embargo List for UK Authors'
},
'openAccessProhibited': false,
'publicationCount': 0,
'preArchiving': 'can',
'postArchiving': 'can',
'pubArchiving': 'cannot'
}],
'inDOAJ': false
}]
}
]
} as WorkspaceitemSectionSherpaPoliciesObject,
null
)
);
}
});
console.log(mappedActions);
return { action: action, definition: definition, mappedActions: mappedActions };
}),
mergeMap((result) => {
@@ -222,7 +104,7 @@ export class SubmissionObjectEffects {
/**
* Dispatch a [InitSubmissionFormAction]
*/
resetForm$ = createEffect(() => this.actions$.pipe(
resetForm$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.RESET_SUBMISSION_FORM),
map((action: ResetSubmissionFormAction) =>
new InitSubmissionFormAction(
@@ -238,40 +120,41 @@ export class SubmissionObjectEffects {
/**
* Dispatch a [SaveSubmissionFormSuccessAction] or a [SaveSubmissionFormErrorAction] on error
*/
saveSubmission$ = createEffect(() => this.actions$.pipe(
saveSubmission$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_SUBMISSION_FORM),
switchMap((action: SaveSubmissionFormAction) => {
return this.operationsService.jsonPatchByResourceType(
this.submissionService.getSubmissionObjectLinkName(),
action.payload.submissionId,
'sections').pipe(
map((response: SubmissionObject[]) => new SaveSubmissionFormSuccessAction(action.payload.submissionId, response, action.payload.isManual)),
catchError(() => observableOf(new SaveSubmissionFormErrorAction(action.payload.submissionId))));
map((response: SubmissionObject[]) => new SaveSubmissionFormSuccessAction(action.payload.submissionId, response, action.payload.isManual, action.payload.isManual)),
catchError(() => observableOf(new SaveSubmissionFormErrorAction(action.payload.submissionId))));
})));
/**
* Dispatch a [SaveForLaterSubmissionFormSuccessAction] or a [SaveSubmissionFormErrorAction] on error
*/
saveForLaterSubmission$ = createEffect(() => this.actions$.pipe(
saveForLaterSubmission$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_FOR_LATER_SUBMISSION_FORM),
switchMap((action: SaveForLaterSubmissionFormAction) => {
return this.operationsService.jsonPatchByResourceType(
this.submissionService.getSubmissionObjectLinkName(),
action.payload.submissionId,
'sections').pipe(
map((response: SubmissionObject[]) => new SaveForLaterSubmissionFormSuccessAction(action.payload.submissionId, response)),
catchError(() => observableOf(new SaveSubmissionFormErrorAction(action.payload.submissionId))));
map((response: SubmissionObject[]) => new SaveForLaterSubmissionFormSuccessAction(action.payload.submissionId, response)),
catchError(() => observableOf(new SaveSubmissionFormErrorAction(action.payload.submissionId))));
})));
/**
* Call parseSaveResponse and dispatch actions
*/
saveSubmissionSuccess$ = createEffect(() => this.actions$.pipe(
saveSubmissionSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_SUBMISSION_FORM_SUCCESS),
withLatestFrom(this.store$),
map(([action, currentState]: [SaveSubmissionFormSuccessAction, any]) => {
return this.parseSaveResponse((currentState.submission as SubmissionState).objects[action.payload.submissionId],
action.payload.submissionObject, action.payload.submissionId, currentState.forms, action.payload.notify);
action.payload.submissionObject, action.payload.submissionId, currentState.forms,
action.payload.showNotifications, action.payload.showErrors);
}),
mergeMap((actions) => observableFrom(actions))));
@@ -279,19 +162,19 @@ export class SubmissionObjectEffects {
* Call parseSaveResponse and dispatch actions.
* Notification system is forced to be disabled.
*/
saveSubmissionSectionSuccess$ = createEffect(() => this.actions$.pipe(
saveSubmissionSectionSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_SUBMISSION_SECTION_FORM_SUCCESS),
withLatestFrom(this.store$),
map(([action, currentState]: [SaveSubmissionSectionFormSuccessAction, any]) => {
return this.parseSaveResponse((currentState.submission as SubmissionState).objects[action.payload.submissionId],
action.payload.submissionObject, action.payload.submissionId, currentState.forms, false);
action.payload.submissionObject, action.payload.submissionId, currentState.forms, false, false);
}),
mergeMap((actions) => observableFrom(actions))));
/**
* Dispatch a [SaveSubmissionSectionFormSuccessAction] or a [SaveSubmissionSectionFormErrorAction] on error
*/
saveSection$ = createEffect(() => this.actions$.pipe(
saveSection$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_SUBMISSION_SECTION_FORM),
switchMap((action: SaveSubmissionSectionFormAction) => {
return this.operationsService.jsonPatchByResourceID(
@@ -299,14 +182,14 @@ export class SubmissionObjectEffects {
action.payload.submissionId,
'sections',
action.payload.sectionId).pipe(
map((response: SubmissionObject[]) => new SaveSubmissionSectionFormSuccessAction(action.payload.submissionId, response)),
catchError(() => observableOf(new SaveSubmissionSectionFormErrorAction(action.payload.submissionId))));
map((response: SubmissionObject[]) => new SaveSubmissionSectionFormSuccessAction(action.payload.submissionId, response)),
catchError(() => observableOf(new SaveSubmissionSectionFormErrorAction(action.payload.submissionId))));
})));
/**
* Show a notification on error
*/
saveError$ = createEffect(() => this.actions$.pipe(
saveError$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_SUBMISSION_FORM_ERROR, SubmissionObjectActionTypes.SAVE_SUBMISSION_SECTION_FORM_ERROR),
withLatestFrom(this.store$),
tap(() => this.notificationsService.error(null, this.translate.get('submission.sections.general.save_error_notice')))), { dispatch: false });
@@ -314,7 +197,7 @@ export class SubmissionObjectEffects {
/**
* Call parseSaveResponse and dispatch actions or dispatch [SaveSubmissionFormErrorAction] on error
*/
saveAndDeposit$ = createEffect(() => this.actions$.pipe(
saveAndDeposit$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_AND_DEPOSIT_SUBMISSION),
withLatestFrom(this.submissionService.hasUnsavedModification()),
switchMap(([action, hasUnsavedModification]: [SaveAndDepositSubmissionAction, boolean]) => {
@@ -335,7 +218,13 @@ export class SubmissionObjectEffects {
if (this.canDeposit(response)) {
return new DepositSubmissionAction(action.payload.submissionId);
} else {
return new SaveSubmissionFormSuccessAction(action.payload.submissionId, response);
this.notificationsService.warning(
null,
this.translate.instant('submission.sections.general.cannot_deposit'),
null,
true
);
return new SaveSubmissionFormSuccessAction(action.payload.submissionId, response, false, true);
}
}),
catchError(() => observableOf(new SaveSubmissionFormErrorAction(action.payload.submissionId))));
@@ -344,7 +233,7 @@ export class SubmissionObjectEffects {
/**
* Dispatch a [DepositSubmissionSuccessAction] or a [DepositSubmissionErrorAction] on error
*/
depositSubmission$ = createEffect(() => this.actions$.pipe(
depositSubmission$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.DEPOSIT_SUBMISSION),
withLatestFrom(this.store$),
switchMap(([action, state]: [DepositSubmissionAction, any]) => {
@@ -356,7 +245,7 @@ export class SubmissionObjectEffects {
/**
* Show a notification on success and redirect to MyDSpace page
*/
saveForLaterSubmissionSuccess$ = createEffect(() => this.actions$.pipe(
saveForLaterSubmissionSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.SAVE_FOR_LATER_SUBMISSION_FORM_SUCCESS),
tap(() => this.notificationsService.success(null, this.translate.get('submission.sections.general.save_success_notice'))),
tap(() => this.submissionService.redirectToMyDSpace())), { dispatch: false });
@@ -364,7 +253,7 @@ export class SubmissionObjectEffects {
/**
* Show a notification on success and redirect to MyDSpace page
*/
depositSubmissionSuccess$ = createEffect(() => this.actions$.pipe(
depositSubmissionSuccess$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.DEPOSIT_SUBMISSION_SUCCESS),
tap(() => this.notificationsService.success(null, this.translate.get('submission.sections.general.deposit_success_notice'))),
tap(() => this.submissionService.redirectToMyDSpace())), { dispatch: false });
@@ -372,14 +261,14 @@ export class SubmissionObjectEffects {
/**
* Show a notification on error
*/
depositSubmissionError$ = createEffect(() => this.actions$.pipe(
depositSubmissionError$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.DEPOSIT_SUBMISSION_ERROR),
tap(() => this.notificationsService.error(null, this.translate.get('submission.sections.general.deposit_error_notice')))), { dispatch: false });
/**
* Dispatch a [DiscardSubmissionSuccessAction] or a [DiscardSubmissionErrorAction] on error
*/
discardSubmission$ = createEffect(() => this.actions$.pipe(
discardSubmission$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.DISCARD_SUBMISSION),
switchMap((action: DepositSubmissionAction) => {
return this.submissionService.discardSubmission(action.payload.submissionId).pipe(
@@ -390,7 +279,7 @@ export class SubmissionObjectEffects {
/**
* Adds all metadata an item to the SubmissionForm sections of the submission
*/
addAllMetadataToSectionData = createEffect(() => this.actions$.pipe(
addAllMetadataToSectionData = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.UPDATE_SECTION_DATA),
switchMap((action: UpdateSectionDataAction) => {
return this.sectionService.getSectionState(action.payload.submissionId, action.payload.sectionId, SectionsType.Upload)
@@ -431,18 +320,18 @@ export class SubmissionObjectEffects {
/**
* Show a notification on error
*/
discardSubmissionError$ = createEffect(() => this.actions$.pipe(
discardSubmissionError$ = createEffect(() => this.actions$.pipe(
ofType(SubmissionObjectActionTypes.DISCARD_SUBMISSION_ERROR),
tap(() => this.notificationsService.error(null, this.translate.get('submission.sections.general.discard_error_notice')))), { dispatch: false });
constructor(private actions$: Actions,
private notificationsService: NotificationsService,
private operationsService: SubmissionJsonPatchOperationsService,
private sectionService: SectionsService,
private store$: Store<any>,
private submissionService: SubmissionService,
private submissionObjectService: SubmissionObjectDataService,
private translate: TranslateService) {
private notificationsService: NotificationsService,
private operationsService: SubmissionJsonPatchOperationsService,
private sectionService: SectionsService,
private store$: Store<any>,
private submissionService: SubmissionService,
private submissionObjectService: SubmissionObjectDataService,
private translate: TranslateService) {
}
/**
@@ -481,18 +370,23 @@ export class SubmissionObjectEffects {
* A boolean that indicate if show notification or not
* @return SubmissionObjectAction[]
* List of SubmissionObjectAction to dispatch
* @param showNotifications
* A boolean representing if to show notifications on save
* @param showErrors
* A boolean representing if to show errors on save
*/
protected parseSaveResponse(
currentState: SubmissionObjectEntry,
response: SubmissionObject[],
submissionId: string,
forms: FormState,
notify: boolean = true): SubmissionObjectAction[] {
showNotifications: boolean = true,
showErrors: boolean = true): SubmissionObjectAction[] {
const mappedActions = [];
if (isNotEmpty(response)) {
if (notify) {
if (showNotifications) {
this.notificationsService.success(null, this.translate.get('submission.sections.general.save_success_notice'));
}
@@ -504,7 +398,7 @@ export class SubmissionObjectEffects {
if (errors && !isEmpty(errors)) {
// to avoid dispatching an action for every error, create an array of errors per section
errorsList = parseSectionErrors(errors);
if (notify) {
if (showNotifications) {
this.notificationsService.warning(null, this.translate.get('submission.sections.general.sections_not_valid'));
}
}
@@ -523,12 +417,12 @@ export class SubmissionObjectEffects {
continue;
}
if (notify && !currentState.sections[sectionId].enabled) {
if (showNotifications && !currentState.sections[sectionId].enabled) {
this.submissionService.notifyNewSection(submissionId, sectionId, currentState.sections[sectionId].sectionType);
}
const sectionForm = getForm(forms, currentState, sectionId);
const filteredErrors = filterErrors(sectionForm, sectionErrors, currentState.sections[sectionId].sectionType, notify);
const filteredErrors = filterErrors(sectionForm, sectionErrors, currentState.sections[sectionId].sectionType, showErrors);
mappedActions.push(new UpdateSectionDataAction(submissionId, sectionId, sectionData, filteredErrors, sectionErrors));
}
});

View File

@@ -3828,6 +3828,8 @@
"submission.sections.general.add-more": "Add more",
"submission.sections.general.cannot_deposit": "Deposit cannot be completed due to errors in the form.<br>Please fill out all required fields to complete the deposit.",
"submission.sections.general.collection": "Collection",
"submission.sections.general.deposit_error_notice": "There was an issue when submitting the item, please try again later.",