Skip to content

Commit 1f1cfc5

Browse files
danieleninfoatarix83
authored andcommitted
Merged in task/dspace-cris-2023_02_x/DSC-2215_item_access_conditions (pull request DSpace#2920)
[CST-16309] update status handling Approved-by: Giuseppe Digilio
2 parents fe7ea18 + 7526985 commit 1f1cfc5

5 files changed

Lines changed: 196 additions & 8 deletions

File tree

src/app/core/config/models/config-submission-access.model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ export class SubmissionAccessModel extends ConfigObject {
3737
@autoserialize
3838
singleAccessCondition: boolean;
3939

40+
/**
41+
* Whether the field is mandatory
42+
*/
43+
@autoserialize
44+
required: boolean;
45+
4046
/**
4147
* The links to all related resources returned by the rest api.
4248
*/

src/app/shared/mocks/submission.mock.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3868,6 +3868,95 @@ export const mockAccessesFormData = {
38683868
]
38693869
};
38703870

3871+
export const mockAccessesServiceData = {
3872+
discoverable: true,
3873+
accessConditions: [
3874+
{
3875+
accessConditionGroup: {
3876+
name: [
3877+
{
3878+
value: 'openaccess',
3879+
language: null,
3880+
authority: null,
3881+
display: 'openaccess',
3882+
confidence: -1,
3883+
place: 0,
3884+
otherInformation: null
3885+
}
3886+
],
3887+
},
3888+
},
3889+
{
3890+
accessConditionGroup: {
3891+
name: [
3892+
{
3893+
value: 'lease',
3894+
language: null,
3895+
authority: null,
3896+
display: 'lease',
3897+
confidence: -1,
3898+
place: 0,
3899+
otherInformation: null
3900+
}
3901+
],
3902+
endDate: [
3903+
{
3904+
value: {
3905+
year: 2019,
3906+
month: 1,
3907+
day: 16
3908+
},
3909+
language: null,
3910+
authority: null,
3911+
display: {
3912+
year: 2019,
3913+
month: 1,
3914+
day: 16
3915+
},
3916+
confidence: -1,
3917+
place: 0,
3918+
otherInformation: null
3919+
}
3920+
],
3921+
}
3922+
},
3923+
{
3924+
accessConditionGroup: {
3925+
name: [
3926+
{
3927+
value: 'embargo',
3928+
language: null,
3929+
authority: null,
3930+
display: 'lease',
3931+
confidence: -1,
3932+
place: 0,
3933+
otherInformation: null
3934+
}
3935+
],
3936+
startDate: [
3937+
{
3938+
value: {
3939+
year: 2019,
3940+
month: 1,
3941+
day: 16
3942+
},
3943+
language: null,
3944+
authority: null,
3945+
display: {
3946+
year: 2019,
3947+
month: 1,
3948+
day: 16
3949+
},
3950+
confidence: -1,
3951+
place: 0,
3952+
otherInformation: null
3953+
}
3954+
],
3955+
}
3956+
}
3957+
]
3958+
};
3959+
38713960
// mockDeduplicationMatches id for Workflow decision
38723961
export const mockDeduplicationWorkflowId = '78ca1d06-cce7-4ee9-abda-46440d9b0bb7';
38733962
// mockDeduplicationMatches id for Submitter decision

src/app/submission/sections/accesses/section-accesses.component.spec.ts

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import {
4141
} from '@ng-dynamic-forms/core';
4242
import { AppState } from '../../../app.reducer';
4343
import { getMockFormService } from '../../../shared/mocks/form-service.mock';
44-
import { mockAccessesFormData } from '../../../shared/mocks/submission.mock';
44+
import { mockAccessesFormData, mockAccessesServiceData } from '../../../shared/mocks/submission.mock';
4545
import { accessConditionChangeEvent, checkboxChangeEvent } from '../../../shared/testing/form-event.stub';
4646
import { XSRFService } from '../../../core/xsrf/xsrf.service';
4747
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
@@ -120,6 +120,7 @@ describe('SubmissionSectionAccessesComponent', () => {
120120
formService.validateAllFormFields.and.callFake(() => null);
121121
formService.isValid.and.returnValue(observableOf(true));
122122
formService.getFormData.and.returnValue(observableOf(mockAccessesFormData));
123+
sectionsServiceStub.getSectionErrors.and.returnValue(observableOf(null));
123124
submissionAccessesConfigService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(accessConditionSectionConfigRes) as any);
124125
fixture.detectChanges();
125126
}));
@@ -183,6 +184,7 @@ describe('SubmissionSectionAccessesComponent', () => {
183184
formService.validateAllFormFields.and.callFake(() => null);
184185
formService.isValid.and.returnValue(observableOf(true));
185186
formService.getFormData.and.returnValue(observableOf(mockAccessesFormData));
187+
sectionsServiceStub.getSectionErrors.and.returnValue(observableOf(null));
186188
submissionAccessesConfigService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(accessConditionSectionSingleAccessConfigRes) as any);
187189
fixture.detectChanges();
188190
}));
@@ -264,6 +266,7 @@ describe('SubmissionSectionAccessesComponent', () => {
264266
formService.validateAllFormFields.and.callFake(() => null);
265267
formService.isValid.and.returnValue(observableOf(true));
266268
formService.getFormData.and.returnValue(observableOf(mockAccessesFormData));
269+
sectionsServiceStub.getSectionErrors.and.returnValue(observableOf(null));
267270
fixture.detectChanges();
268271
}));
269272

@@ -277,4 +280,82 @@ describe('SubmissionSectionAccessesComponent', () => {
277280
});
278281

279282
});
283+
284+
describe('when section is required', () => {
285+
286+
const service = getSectionAccessesService();
287+
288+
beforeEach(async () => {
289+
await TestBed.configureTestingModule({
290+
imports: [
291+
BrowserModule,
292+
TranslateModule.forRoot()
293+
],
294+
declarations: [SubmissionSectionAccessesComponent, FormComponent],
295+
providers: [
296+
{ provide: SectionsService, useValue: sectionsServiceStub },
297+
{ provide: SubmissionAccessesConfigDataService, useValue: submissionAccessesConfigService },
298+
{ provide: SectionAccessesService, useValue: service },
299+
{ provide: SectionFormOperationsService, useValue: sectionFormOperationsService },
300+
{ provide: JsonPatchOperationsBuilder, useValue: operationsBuilder },
301+
{ provide: TranslateService, useValue: getMockTranslateService() },
302+
{ provide: FormService, useValue: getMockFormService() },
303+
{ provide: Store, useValue: storeStub },
304+
{ provide: XSRFService, useValue: {} },
305+
{ provide: SubmissionJsonPatchOperationsService, useValue: SubmissionJsonPatchOperationsServiceStub },
306+
{ provide: 'sectionDataProvider', useValue: sectionData },
307+
{ provide: 'submissionIdProvider', useValue: '1508' },
308+
FormBuilderService
309+
]
310+
})
311+
.compileComponents();
312+
});
313+
314+
beforeEach(inject([Store], (store: Store<AppState>) => {
315+
fixture = TestBed.createComponent(SubmissionSectionAccessesComponent);
316+
component = fixture.componentInstance;
317+
formService = TestBed.inject(FormService);
318+
formService.validateAllFormFields.and.callFake(() => null);
319+
formService.isValid.and.returnValue(observableOf(true));
320+
formService.getFormData.and.returnValue(observableOf(mockAccessesFormData));
321+
sectionsServiceStub.getSectionErrors.and.returnValue(observableOf(null));
322+
submissionAccessesConfigService.findByHref.and.returnValue(createSuccessfulRemoteDataObject$(accessConditionSectionConfigRes) as any);
323+
fixture.detectChanges();
324+
}));
325+
326+
it('should have section status invalid on init', (done) => {
327+
component.required$.next(true);
328+
service.getAccessesData.and.returnValue(observableOf({}));
329+
fixture.detectChanges();
330+
331+
component.getSectionStatus().subscribe(status => {
332+
expect(status).toEqual(false);
333+
done();
334+
});
335+
});
336+
337+
it('should have section status valid if there are data and no error', (done) => {
338+
service.getAccessesData.and.returnValue(observableOf(mockAccessesServiceData));
339+
component.required$.next(true);
340+
fixture.detectChanges();
341+
342+
component.getSectionStatus().subscribe(status => {
343+
expect(status).toEqual(true);
344+
done();
345+
});
346+
});
347+
348+
it('should have section status invalid if there are data and errors', (done) => {
349+
service.getAccessesData.and.returnValue(observableOf(mockAccessesServiceData));
350+
component.required$.next(true);
351+
sectionsServiceStub.getSectionErrors.and.returnValue(observableOf({error: 'testError'}));
352+
353+
fixture.detectChanges();
354+
355+
component.getSectionStatus().subscribe(status => {
356+
expect(status).toEqual(false);
357+
done();
358+
});
359+
});
360+
});
280361
});

src/app/submission/sections/accesses/section-accesses.component.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Component, Inject, ViewChild } from '@angular/core';
33
import { UntypedFormControl } from '@angular/forms';
44

55
import { filter, map, mergeMap, take } from 'rxjs/operators';
6-
import { combineLatest, Observable, of, Subscription } from 'rxjs';
6+
import { BehaviorSubject, combineLatest, Observable, Subscription } from 'rxjs';
77
import { TranslateService } from '@ngx-translate/core';
88

99
import { renderSectionFor } from '../sections-decorator';
@@ -42,7 +42,7 @@ import {
4242
FORM_ACCESS_CONDITION_TYPE_CONFIG,
4343
FORM_ACCESS_CONDITION_TYPE_LAYOUT
4444
} from './section-accesses.model';
45-
import { hasValue, isNotEmpty, isNotNull } from '../../../shared/empty.util';
45+
import { hasValue, isNotEmpty, isNotNull, isObjectEmpty } from '../../../shared/empty.util';
4646
import {
4747
WorkspaceitemSectionAccessesObject
4848
} from '../../../core/submission/models/workspaceitem-section-accesses.model';
@@ -124,6 +124,11 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
124124
*/
125125
public canChangeDiscoverable: boolean;
126126

127+
/**
128+
* Whether the section is required
129+
*/
130+
public required$: BehaviorSubject<boolean> = new BehaviorSubject(false);
131+
127132
/**
128133
* Initialize instance variables
129134
*
@@ -161,7 +166,7 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
161166
* The form model
162167
*/
163168
public initModelData(formModel: DynamicFormControlModel[]) {
164-
this.accessesData.accessConditions.forEach((accessCondition, index) => {
169+
this.accessesData.accessConditions?.forEach((accessCondition, index) => {
165170
Array.of('name', 'startDate', 'endDate')
166171
.filter((key) => accessCondition.hasOwnProperty(key) && isNotEmpty(accessCondition[key]))
167172
.forEach((key) => {
@@ -298,9 +303,8 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
298303
this.canChangeDiscoverable = !!config.canChangeDiscoverable;
299304
this.accessesData = accessData;
300305
this.formModel = this.buildFileEditForm();
306+
this.required$.next(config.required);
301307
});
302-
303-
304308
}
305309

306310
/**
@@ -309,8 +313,14 @@ export class SubmissionSectionAccessesComponent extends SectionModelComponent {
309313
* @return Observable<boolean>
310314
* the section status
311315
*/
312-
protected getSectionStatus(): Observable<boolean> {
313-
return of(true);
316+
getSectionStatus(): Observable<boolean> {
317+
return combineLatest([
318+
this.required$,
319+
this.sectionService.getSectionErrors(this.submissionId, this.sectionData.id),
320+
this.accessesService.getAccessesData(this.submissionId, this.sectionData.id)
321+
]).pipe(
322+
map(([required, errors, accessesData]) => (!required || (required && isObjectEmpty(errors) && !!accessesData?.accessConditions?.length)))
323+
);
314324
}
315325

316326
/**

src/assets/i18n/en.json5

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6453,6 +6453,8 @@
64536453

64546454
"submission.sections.submit.progressbar.itemAccessConditions": "Item access conditions",
64556455

6456+
"error.validation.accessconditions.required": "You must provide a value for the access condition",
6457+
64566458
"submission.sections.submit.progressbar.CClicense": "Creative commons license",
64576459

64586460
"submission.sections.submit.progressbar.custom-url": "Custom url",

0 commit comments

Comments
 (0)