From 253b2e84d18d55eca4481d479274c54916e96cd4 Mon Sep 17 00:00:00 2001 From: Giuseppe Date: Wed, 18 Dec 2024 21:13:44 +0100 Subject: [PATCH] Fix issue with submission sections visibility (#3276) * Removing position-fixed bootstrap class so that navbar links are available again (cherry picked from commit 351abaa5c2071c3bc56c72abf2bdc8cfb22062a9) * A new approach so that the elements of the ds-file-dropzone-no-uploader component don't overlap the navbar and make it inaccessible (cherry picked from commit 2c259f5ae937a26f37b0dd00ea46b70f4fef7e0d) * [DURACOM-291] fix submission section visibility in order to rely on the configured section scope * Removing position-fixed bootstrap class so that navbar links are available again (cherry picked from commit 351abaa5c2071c3bc56c72abf2bdc8cfb22062a9) * A new approach so that the elements of the ds-file-dropzone-no-uploader component don't overlap the navbar and make it inaccessible (cherry picked from commit 2c259f5ae937a26f37b0dd00ea46b70f4fef7e0d) --------- Co-authored-by: root --- .../models/config-submission-section.model.ts | 22 +- .../form/submission-form.component.ts | 8 +- .../objects/section-visibility.model.ts | 6 + .../objects/submission-objects.actions.ts | 11 +- .../submission-objects.effects.spec.ts | 1 + .../objects/submission-objects.effects.ts | 1 + .../submission-objects.reducer.spec.ts | 2 + .../objects/submission-objects.reducer.ts | 1 + .../submission-section-object.model.ts | 10 +- .../sections/sections.service.spec.ts | 295 ++++++++++++++++-- .../submission/sections/sections.service.ts | 13 +- src/app/submission/submission.service.spec.ts | 241 ++++++++++++-- src/app/submission/submission.service.ts | 13 +- 13 files changed, 536 insertions(+), 88 deletions(-) diff --git a/src/app/core/config/models/config-submission-section.model.ts b/src/app/core/config/models/config-submission-section.model.ts index feb4fc9cb07..13e19544dcf 100644 --- a/src/app/core/config/models/config-submission-section.model.ts +++ b/src/app/core/config/models/config-submission-section.model.ts @@ -4,20 +4,16 @@ import { inheritSerialization, } from 'cerialize'; +import { + SectionScope, + SectionVisibility, +} from '../../../submission/objects/section-visibility.model'; import { SectionsType } from '../../../submission/sections/sections-type'; import { typedObject } from '../../cache/builders/build-decorators'; import { HALLink } from '../../shared/hal-link.model'; import { ConfigObject } from './config.model'; import { SUBMISSION_SECTION_TYPE } from './config-type'; -/** - * An interface that define section visibility and its properties. - */ -export interface SubmissionSectionVisibility { - main: any; - other: any; -} - @typedObject @inheritSerialization(ConfigObject) export class SubmissionSectionModel extends ConfigObject { @@ -35,6 +31,12 @@ export class SubmissionSectionModel extends ConfigObject { @autoserialize mandatory: boolean; + /** + * The submission scope for this section + */ + @autoserialize + scope: SectionScope; + /** * A string representing the kind of section object */ @@ -42,10 +44,10 @@ export class SubmissionSectionModel extends ConfigObject { sectionType: SectionsType; /** - * The [SubmissionSectionVisibility] object for this section + * The [SectionVisibility] object for this section */ @autoserialize - visibility: SubmissionSectionVisibility; + visibility: SectionVisibility; /** * The {@link HALLink}s for this SubmissionSectionModel diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index 2e97c2df63f..74c262befcd 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -22,10 +22,7 @@ import { import { AuthService } from '../../core/auth/auth.service'; import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model'; -import { - SubmissionSectionModel, - SubmissionSectionVisibility, -} from '../../core/config/models/config-submission-section.model'; +import { SubmissionSectionModel } from '../../core/config/models/config-submission-section.model'; import { Collection } from '../../core/shared/collection.model'; import { HALEndpointService } from '../../core/shared/hal-endpoint.service'; import { Item } from '../../core/shared/item.model'; @@ -38,6 +35,7 @@ import { } from '../../shared/empty.util'; import { ThemedLoadingComponent } from '../../shared/loading/themed-loading.component'; import { UploaderOptions } from '../../shared/upload/uploader/uploader-options.model'; +import { SectionVisibility } from '../objects/section-visibility.model'; import { SubmissionError } from '../objects/submission-error.model'; import { SubmissionObjectEntry } from '../objects/submission-objects.reducer'; import { SubmissionSectionContainerComponent } from '../sections/container/section-container.component'; @@ -233,7 +231,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { /** * Returns the visibility object of the collection section */ - private getCollectionVisibility(): SubmissionSectionVisibility { + private getCollectionVisibility(): SectionVisibility { const submissionSectionModel: SubmissionSectionModel = this.submissionDefinition.sections.page.find( (section) => isEqual(section.sectionType, SectionsType.Collection), diff --git a/src/app/submission/objects/section-visibility.model.ts b/src/app/submission/objects/section-visibility.model.ts index c41735178c1..16cf16b2ab2 100644 --- a/src/app/submission/objects/section-visibility.model.ts +++ b/src/app/submission/objects/section-visibility.model.ts @@ -5,3 +5,9 @@ export interface SectionVisibility { main: any; other: any; } + + +export enum SectionScope { + Submission = 'SUBMISSION', + Workflow = 'WORKFLOW', +} diff --git a/src/app/submission/objects/submission-objects.actions.ts b/src/app/submission/objects/submission-objects.actions.ts index e075ce5e5ba..956c8f95336 100644 --- a/src/app/submission/objects/submission-objects.actions.ts +++ b/src/app/submission/objects/submission-objects.actions.ts @@ -11,7 +11,10 @@ import { } from '../../core/submission/models/workspaceitem-sections.model'; import { type } from '../../shared/ngrx/type'; import { SectionsType } from '../sections/sections-type'; -import { SectionVisibility } from './section-visibility.model'; +import { + SectionScope, + SectionVisibility, +} from './section-visibility.model'; import { SubmissionError } from './submission-error.model'; import { SubmissionSectionError } from './submission-section-error.model'; @@ -120,6 +123,7 @@ export class InitSectionAction implements Action { header: string; config: string; mandatory: boolean; + scope: SectionScope; sectionType: SectionsType; visibility: SectionVisibility; enabled: boolean; @@ -140,6 +144,8 @@ export class InitSectionAction implements Action { * the section's config * @param mandatory * the section's mandatory + * @param scope + * the section's scope * @param sectionType * the section's type * @param visibility @@ -156,12 +162,13 @@ export class InitSectionAction implements Action { header: string, config: string, mandatory: boolean, + scope: SectionScope, sectionType: SectionsType, visibility: SectionVisibility, enabled: boolean, data: WorkspaceitemSectionDataType, errors: SubmissionSectionError[]) { - this.payload = { submissionId, sectionId, header, config, mandatory, sectionType, visibility, enabled, data, errors }; + this.payload = { submissionId, sectionId, header, config, mandatory, scope, sectionType, visibility, enabled, data, errors }; } } diff --git a/src/app/submission/objects/submission-objects.effects.spec.ts b/src/app/submission/objects/submission-objects.effects.spec.ts index 4a3e08384d4..a16dc365f25 100644 --- a/src/app/submission/objects/submission-objects.effects.spec.ts +++ b/src/app/submission/objects/submission-objects.effects.spec.ts @@ -167,6 +167,7 @@ describe('SubmissionObjectEffects test suite', () => { sectionDefinition.header, config, sectionDefinition.mandatory, + sectionDefinition.scope, sectionDefinition.sectionType, sectionDefinition.visibility, enabled, diff --git a/src/app/submission/objects/submission-objects.effects.ts b/src/app/submission/objects/submission-objects.effects.ts index 9afb6cec40f..ef1610794cf 100644 --- a/src/app/submission/objects/submission-objects.effects.ts +++ b/src/app/submission/objects/submission-objects.effects.ts @@ -116,6 +116,7 @@ export class SubmissionObjectEffects { sectionDefinition.header, config, sectionDefinition.mandatory, + sectionDefinition.scope, sectionDefinition.sectionType, sectionDefinition.visibility, enabled, diff --git a/src/app/submission/objects/submission-objects.reducer.spec.ts b/src/app/submission/objects/submission-objects.reducer.spec.ts index 2389a5600c8..2bbb875c3cd 100644 --- a/src/app/submission/objects/submission-objects.reducer.spec.ts +++ b/src/app/submission/objects/submission-objects.reducer.spec.ts @@ -237,6 +237,7 @@ describe('submissionReducer test suite', () => { header: 'submit.progressbar.describe.stepone', config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone', mandatory: true, + scope: null, sectionType: 'submission-form', visibility: undefined, collapsed: false, @@ -257,6 +258,7 @@ describe('submissionReducer test suite', () => { 'submit.progressbar.describe.stepone', 'https://rest.api/dspace-spring-rest/api/config/submissionforms/traditionalpageone', true, + null, SectionsType.SubmissionForm, undefined, true, diff --git a/src/app/submission/objects/submission-objects.reducer.ts b/src/app/submission/objects/submission-objects.reducer.ts index 82e33062cda..a34cf236b94 100644 --- a/src/app/submission/objects/submission-objects.reducer.ts +++ b/src/app/submission/objects/submission-objects.reducer.ts @@ -565,6 +565,7 @@ function initSection(state: SubmissionObjectState, action: InitSectionAction): S header: action.payload.header, config: action.payload.config, mandatory: action.payload.mandatory, + scope: action.payload.scope, sectionType: action.payload.sectionType, visibility: action.payload.visibility, collapsed: false, diff --git a/src/app/submission/objects/submission-section-object.model.ts b/src/app/submission/objects/submission-section-object.model.ts index 7338539607b..5d8a14c7450 100644 --- a/src/app/submission/objects/submission-section-object.model.ts +++ b/src/app/submission/objects/submission-section-object.model.ts @@ -1,6 +1,9 @@ import { WorkspaceitemSectionDataType } from '../../core/submission/models/workspaceitem-sections.model'; import { SectionsType } from '../sections/sections-type'; -import { SectionVisibility } from './section-visibility.model'; +import { + SectionScope, + SectionVisibility, +} from './section-visibility.model'; import { SubmissionSectionError } from './submission-section-error.model'; /** @@ -22,6 +25,11 @@ export interface SubmissionSectionObject { */ mandatory: boolean; + /** + * The submission scope for this section + */ + scope: SectionScope; + /** * The section type */ diff --git a/src/app/submission/sections/sections.service.spec.ts b/src/app/submission/sections/sections.service.spec.ts index d8644a0db86..0241564ab73 100644 --- a/src/app/submission/sections/sections.service.spec.ts +++ b/src/app/submission/sections/sections.service.spec.ts @@ -35,6 +35,7 @@ import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; import { SubmissionServiceStub } from '../../shared/testing/submission-service.stub'; +import { SectionScope } from '../objects/section-visibility.model'; import { DisableSectionAction, EnableSectionAction, @@ -265,46 +266,282 @@ describe('SectionsService test suite', () => { }); describe('isSectionReadOnly', () => { - it('should return an observable of true when it\'s a readonly section and scope is not workspace', () => { - store.select.and.returnValue(observableOf({ - visibility: { - main: null, - other: 'READONLY', - }, - })); + describe('when submission scope is workspace', () => { + describe('and section scope is workspace', () => { + it('should return an observable of true when visibility main is READONLY and visibility other is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: { + main: 'READONLY', + other: null, + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); + it('should return an observable of true when both visibility main and other are READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: { + main: 'READONLY', + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); + it('should return an observable of false when visibility main is null and visibility other is READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: { + main: null, + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); + it('should return an observable of false when visibility is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: null, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); - const expected = cold('(b|)', { - b: true, }); - expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); - }); + describe('and section scope is workflow', () => { + it('should return an observable of false when visibility main is READONLY and visibility other is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: { + main: 'READONLY', + other: null, + }, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); + it('should return an observable of true when both visibility main and other are READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: { + main: 'READONLY', + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); + it('should return an observable of true when visibility main is null and visibility other is READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: { + main: null, + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); + it('should return an observable of false when visibility is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: null, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); - it('should return an observable of false when it\'s a readonly section and scope is workspace', () => { - store.select.and.returnValue(observableOf({ - visibility: { - main: null, - other: 'READONLY', - }, - })); - - const expected = cold('(b|)', { - b: false, }); - expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + describe('and section scope is null', () => { + it('should return an observable of false', () => { + store.select.and.returnValue(observableOf({ + scope: null, + visibility: null, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkspaceItem)).toBeObservable(expected); + }); + }); }); - it('should return an observable of false when it\'s not a readonly section', () => { - store.select.and.returnValue(observableOf({ - visibility: null, - })); + describe('when submission scope is workflow', () => { + describe('and section scope is workspace', () => { + it('should return an observable of false when visibility main is READONLY and visibility other is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: { + main: 'READONLY', + other: null, + }, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + it('should return an observable of true when both visibility main and other are READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: { + main: 'READONLY', + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + it('should return an observable of true when visibility main is null and visibility other is READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: { + main: null, + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + it('should return an observable of false when visibility is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Submission, + visibility: null, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + + }); + + describe('and section scope is workflow', () => { + it('should return an observable of true when visibility main is READONLY and visibility other is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: { + main: 'READONLY', + other: null, + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + it('should return an observable of true when both visibility main and other is READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: { + main: 'READONLY', + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: true, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + it('should return an observable of false when visibility main is null and visibility other is READONLY', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: { + main: null, + other: 'READONLY', + }, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + it('should return an observable of false when visibility is null', () => { + store.select.and.returnValue(observableOf({ + scope: SectionScope.Workflow, + visibility: null, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); - const expected = cold('(b|)', { - b: false, }); - expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + describe('and section scope is null', () => { + it('should return an observable of false', () => { + store.select.and.returnValue(observableOf({ + scope: null, + visibility: null, + })); + + const expected = cold('(b|)', { + b: false, + }); + + expect(service.isSectionReadOnly(submissionId, sectionId, SubmissionScopeType.WorkflowItem)).toBeObservable(expected); + }); + }); }); }); diff --git a/src/app/submission/sections/sections.service.ts b/src/app/submission/sections/sections.service.ts index 6cc064283ee..cec60a9cdf3 100644 --- a/src/app/submission/sections/sections.service.ts +++ b/src/app/submission/sections/sections.service.ts @@ -36,6 +36,7 @@ import { FormClearErrorsAction } from '../../shared/form/form.actions'; import { FormError } from '../../shared/form/form.reducer'; import { FormService } from '../../shared/form/form.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; +import { SectionScope } from '../objects/section-visibility.model'; import { DisableSectionAction, EnableSectionAction, @@ -347,10 +348,14 @@ export class SectionsService { return this.store.select(submissionSectionFromIdSelector(submissionId, sectionId)).pipe( filter((sectionObj) => hasValue(sectionObj)), map((sectionObj: SubmissionSectionObject) => { - return isNotEmpty(sectionObj.visibility) - && ((sectionObj.visibility.other === 'READONLY' && submissionScope !== SubmissionScopeType.WorkspaceItem) - || (sectionObj.visibility.main === 'READONLY' && submissionScope === SubmissionScopeType.WorkspaceItem) - ); + if (isEmpty(submissionScope) || isEmpty(sectionObj.visibility) || isEmpty(sectionObj.scope)) { + return false; + } + const convertedSubmissionScope: SectionScope = submissionScope.valueOf() === SubmissionScopeType.WorkspaceItem.valueOf() ? + SectionScope.Submission : SectionScope.Workflow; + const visibility = convertedSubmissionScope.valueOf() === sectionObj.scope.valueOf() ? + sectionObj.visibility.main : sectionObj.visibility.other; + return visibility === 'READONLY'; }), distinctUntilChanged()); } diff --git a/src/app/submission/submission.service.spec.ts b/src/app/submission/submission.service.spec.ts index 0ba8e5d9a21..b8f982101ce 100644 --- a/src/app/submission/submission.service.spec.ts +++ b/src/app/submission/submission.service.spec.ts @@ -52,6 +52,7 @@ import { NotificationsService } from '../shared/notifications/notifications.serv import { createFailedRemoteDataObject } from '../shared/remote-data.utils'; import { SubmissionJsonPatchOperationsServiceStub } from '../shared/testing/submission-json-patch-operations-service.stub'; import { SubmissionRestServiceStub } from '../shared/testing/submission-rest-service.stub'; +import { SectionScope } from './objects/section-visibility.model'; import { CancelSubmissionFormAction, ChangeSubmissionCollectionAction, @@ -82,6 +83,7 @@ describe('SubmissionService test suite', () => { extraction: { config: '', mandatory: true, + scope: SectionScope.Submission, sectionType: 'utils', visibility: { main: 'HIDDEN', @@ -98,6 +100,7 @@ describe('SubmissionService test suite', () => { collection: { config: '', mandatory: true, + scope: SectionScope.Submission, sectionType: 'collection', visibility: { main: 'HIDDEN', @@ -237,6 +240,7 @@ describe('SubmissionService test suite', () => { extraction: { config: '', mandatory: true, + scope: SectionScope.Submission, sectionType: 'utils', visibility: { main: 'HIDDEN', @@ -253,6 +257,7 @@ describe('SubmissionService test suite', () => { collection: { config: '', mandatory: true, + scope: SectionScope.Submission, sectionType: 'collection', visibility: { main: 'HIDDEN', @@ -590,6 +595,7 @@ describe('SubmissionService test suite', () => { describe('getSubmissionSections', () => { it('should return submission form sections', () => { + spyOn(service, 'getSubmissionScope').and.returnValue(SubmissionScopeType.WorkspaceItem); spyOn((service as any).store, 'select').and.returnValue(hot('a|', { a: subState.objects[826], })); @@ -759,6 +765,7 @@ describe('SubmissionService test suite', () => { describe('getSubmissionStatus', () => { it('should return properly submission status', () => { + spyOn(service, 'getSubmissionScope').and.returnValue(SubmissionScopeType.WorkspaceItem); spyOn((service as any).store, 'select').and.returnValue(hot('-a-b', { a: subState, b: validSubState, @@ -818,41 +825,207 @@ describe('SubmissionService test suite', () => { }); describe('isSectionHidden', () => { - it('should return true/false when section is hidden/visible', () => { - let section: any = { - config: '', - header: '', - mandatory: true, - sectionType: 'collection' as any, - visibility: { - main: 'HIDDEN', - other: 'HIDDEN', - }, - collapsed: false, - enabled: true, - data: {}, - errorsToShow: [], - serverValidationErrors: [], - isLoading: false, - isValid: false, - }; - expect(service.isSectionHidden(section)).toBeTruthy(); - - section = { - header: 'submit.progressbar.describe.keyinformation', - config: 'https://rest.api/dspace-spring-rest/api/config/submissionforms/keyinformation', - mandatory: true, - sectionType: 'submission-form', - collapsed: false, - enabled: true, - data: {}, - errorsToShow: [], - serverValidationErrors: [], - isLoading: false, - isValid: false, - }; - expect(service.isSectionHidden(section)).toBeFalsy(); + describe('when submission scope is workspace', () => { + beforeEach(() => { + spyOn(service, 'getSubmissionScope').and.returnValue(SubmissionScopeType.WorkspaceItem); + }); + + describe('and section scope is workspace', () => { + it('should return true when visibility main is HIDDEN and visibility other is null', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: { + main: 'HIDDEN', + other: null, + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return true when both visibility main and other are HIDDEN', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: { + main: 'HIDDEN', + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return false when visibility main is null and visibility other is HIDDEN', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: { + main: null, + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + it('should return false when visibility is null', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: null, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + }); + + describe('and section scope is workflow', () => { + it('should return false when visibility main is HIDDEN and visibility other is null', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: { + main: 'HIDDEN', + other: null, + }, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + it('should return true when both visibility main and other are HIDDEN', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: { + main: 'HIDDEN', + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return true when visibility main is null and visibility other is HIDDEN', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: { + main: null, + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return false when visibility is null', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: null, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + }); + + describe('and section scope is null', () => { + it('should return false', () => { + let section: any = { + scope: null, + visibility: { + main: 'HIDDEN', + other: null, + }, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + }); + }); + + describe('when submission scope is workflow', () => { + beforeEach(() => { + spyOn(service, 'getSubmissionScope').and.returnValue(SubmissionScopeType.WorkflowItem); + }); + + describe('and section scope is workspace', () => { + it('should return false when visibility main is HIDDEN and visibility other is null', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: { + main: 'HIDDEN', + other: null, + }, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + it('should return true when both visibility main and other are HIDDEN', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: { + main: 'HIDDEN', + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return true when visibility main is null and visibility other is HIDDEN', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: { + main: null, + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return false when visibility is null', () => { + let section: any = { + scope: SectionScope.Submission, + visibility: null, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + }); + + describe('and section scope is workflow', () => { + it('should return true when visibility main is HIDDEN and visibility other is null', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: { + main: 'HIDDEN', + other: null, + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return true when both visibility main and other are HIDDEN', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: { + main: 'HIDDEN', + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeTrue(); + }); + it('should return false when visibility main is null and visibility other is HIDDEN', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: { + main: null, + other: 'HIDDEN', + }, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + it('should return false when visibility is null', () => { + let section: any = { + scope: SectionScope.Workflow, + visibility: null, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + }); + + describe('and section scope is null', () => { + it('should return false', () => { + let section: any = { + scope: null, + visibility: { + main: 'HIDDEN', + other: null, + }, + }; + expect(service.isSectionHidden(section)).toBeFalse(); + }); + }); + + }); + + }); describe('isSubmissionLoading', () => { diff --git a/src/app/submission/submission.service.ts b/src/app/submission/submission.service.ts index 19c8893a7ee..ba8eff4f382 100644 --- a/src/app/submission/submission.service.ts +++ b/src/app/submission/submission.service.ts @@ -50,6 +50,7 @@ import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject, } from '../shared/remote-data.utils'; +import { SectionScope } from './objects/section-visibility.model'; import { SubmissionError } from './objects/submission-error.model'; import { CancelSubmissionFormAction, @@ -504,9 +505,15 @@ export class SubmissionService { * true if section is hidden, false otherwise */ isSectionHidden(sectionData: SubmissionSectionObject): boolean { - return (isNotUndefined(sectionData.visibility) - && sectionData.visibility.main === 'HIDDEN' - && sectionData.visibility.other === 'HIDDEN'); + const submissionScope: SubmissionScopeType = this.getSubmissionScope(); + if (isEmpty(submissionScope) || isEmpty(sectionData.visibility) || isEmpty(sectionData.scope)) { + return false; + } + const convertedSubmissionScope: SectionScope = submissionScope.valueOf() === SubmissionScopeType.WorkspaceItem.valueOf() ? + SectionScope.Submission : SectionScope.Workflow; + const visibility = convertedSubmissionScope.valueOf() === sectionData.scope.valueOf() ? + sectionData.visibility.main : sectionData.visibility.other; + return visibility === 'HIDDEN'; } /**