diff --git a/src/app/core/config/models/config.model.ts b/src/app/core/config/models/config.model.ts index fabb16eb23..53250ee045 100644 --- a/src/app/core/config/models/config.model.ts +++ b/src/app/core/config/models/config.model.ts @@ -6,6 +6,12 @@ import { excludeFromEquals } from '../../utilities/equals.decorators'; export abstract class ConfigObject implements CacheableObject { + /** + * The name for this configuration + */ + @autoserialize + public id: string; + /** * The name for this configuration */ diff --git a/src/app/core/submission/submission-response-parsing.service.ts b/src/app/core/submission/submission-response-parsing.service.ts index d9a6ef50e0..6afd20ae9d 100644 --- a/src/app/core/submission/submission-response-parsing.service.ts +++ b/src/app/core/submission/submission-response-parsing.service.ts @@ -16,6 +16,10 @@ import { FormFieldMetadataValueObject } from '../../shared/form/builder/models/f import { SubmissionObject } from './models/submission-object.model'; import { WorkflowItem } from './models/workflowitem.model'; import { WorkspaceItem } from './models/workspaceitem.model'; +import { SubmissionDefinitionsModel } from '../config/models/config-submission-definitions.model'; +import { SubmissionSectionModel } from '../config/models/config-submission-section.model'; +import { SectionsType } from '../../submission/sections/sections-type'; +import { SectionDataModel } from '../../submission/sections/models/section.model'; /** * Export a function to check if object has same properties of FormFieldMetadataValueObject @@ -136,24 +140,29 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService processedList.forEach((item) => { - item = Object.assign({}, item); // In case data is an Instance of WorkspaceItem normalize field value of all the section of type form if (item instanceof WorkspaceItem || item instanceof WorkflowItem) { if (item.sections) { + const sectionConfigs = (item.submissionDefinition as SubmissionDefinitionsModel).sections.page; const precessedSection = Object.create({}); // Iterate over all workspaceitem's sections Object.keys(item.sections) .forEach((sectionId) => { - if (typeof item.sections[sectionId] === 'object' && (isNotEmpty(item.sections[sectionId]) && + const sectionConfig: SubmissionSectionModel = sectionConfigs.find((config) => config.id === sectionId); + let sectionData = item.sections[sectionId]; + if (sectionConfig && sectionConfig.sectionType === SectionsType.SubmissionForm) { + sectionData = item.item.metadata; + } + if (typeof sectionData === 'object' && (isNotEmpty(sectionData) && // When Upload section is disabled, add to submission only if there are files - (!item.sections[sectionId].hasOwnProperty('files') || isNotEmpty((item.sections[sectionId] as any).files)))) { + (!sectionData.hasOwnProperty('files') || isNotEmpty((sectionData as any).files)))) { const sectiondata = Object.create({}); // Iterate over all sections property - Object.keys(item.sections[sectionId]) + Object.keys(sectionData) .forEach((metdadataId) => { - const entry = item.sections[sectionId][metdadataId]; + const entry = sectionData[metdadataId]; // If entry is not an array, for sure is not a section of type form if (Array.isArray(entry)) { sectiondata[metdadataId] = []; diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html index fb69ed92f5..636eac2309 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-issue/journal-issue-grid-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html index 53713b47ee..1faa4ed5db 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal-volume/journal-volume-grid-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html index 594a0e0dc1..cb3220bd8e 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/journal/journal-grid-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html index 0f9b5894f9..1ae772a3c3 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-issue/journal-issue-search-result-grid-element.component.html @@ -17,7 +17,7 @@
- +

diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html index 16e2a8b847..75d29781b7 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal-volume/journal-volume-search-result-grid-element.component.html @@ -17,7 +17,7 @@
- +

diff --git a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html index 4902eec71e..8c7e5c2f44 100644 --- a/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html +++ b/src/app/entity-groups/journal-entities/item-grid-elements/search-result-grid-elements/journal/journal-search-result-grid-element.component.html @@ -17,7 +17,7 @@
- +

diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html index 398feea260..395d6eba20 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-issue/journal-issue-list-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html index bf967e6e78..a3f604900e 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal-volume/journal-volume-list-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html index 3e4dfb0b48..ca028c1659 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/journal/journal-list-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html index 38094c5c79..45482972ec 100644 --- a/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html +++ b/src/app/entity-groups/journal-entities/item-list-elements/search-result-list-elements/journal-issue/journal-issue-search-result-list-element.component.html @@ -1,4 +1,4 @@ - + + + + diff --git a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html index a431f5979f..8a53609c55 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/person/person-grid-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html index 0c87599399..4a240baca9 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/project/project-grid-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html index 1f64856583..cf4e4a6b52 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/org-unit/org-unit-search-result-grid-element.component.html @@ -17,7 +17,7 @@
- +

diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html index cbe93b2545..1b45c7c4f9 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/person/person-search-result-grid-element.component.html @@ -17,7 +17,7 @@
- +

diff --git a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html index 22182d50be..ac3c3ea453 100644 --- a/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html +++ b/src/app/entity-groups/research-entities/item-grid-elements/search-result-grid-elements/project/project-search-result-grid-element.component.html @@ -17,7 +17,7 @@
- +

diff --git a/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.html index 03ef45c7a4..cf2dc3e61c 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/org-unit/org-unit-list-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html index dbc3a42a05..290635ea27 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/person/person-list-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html index 8f74452eaa..6f229c00e0 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/project/project-list-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html index f08d0fdc11..5f570cb021 100644 --- a/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html +++ b/src/app/entity-groups/research-entities/item-list-elements/search-result-list-elements/org-unit/org-unit-search-result-list-element.component.html @@ -1,4 +1,4 @@ - +
+ - + diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html index c2595f603e..377c77e7f7 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.html @@ -43,6 +43,7 @@ + +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts index e72af14091..cf53e811bb 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts @@ -256,7 +256,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo this.relationshipValue$ = observableCombineLatest([this.item$.pipe(take(1)), relationship$]).pipe( switchMap(([item, relationship]: [Item, Relationship]) => relationship.leftItem.pipe( - getSucceededRemoteData(), + getAllSucceededRemoteData(), getRemoteDataPayload(), map((leftItem: Item) => { return new ReorderableRelationship(relationship, leftItem.uuid !== item.uuid, this.relationshipService, this.store, this.model.submissionId) @@ -267,16 +267,17 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo ); } } - if (this.model.relationshipConfig) { - const relationshipOptions = Object.assign(new RelationshipOptions(), this.model.relationshipConfig); - this.listId = 'list-' + this.model.relationshipConfig.relationshipType; + if (this.model.relationshipConfig || (this.isRelationship && !this.model.repeatable)) { + const config = this.model.relationshipConfig || this.model.relationship; + const relationshipOptions = Object.assign(new RelationshipOptions(), config); + this.listId = 'list-' + relationshipOptions.relationshipType; this.setItem(); const subscription = this.selectableListService.getSelectableList(this.listId).pipe( find((list: SelectableListState) => hasNoValue(list)), switchMap(() => this.item$.pipe(take(1))), switchMap((item) => { const relationshipsRD$ = this.relationshipService.getItemRelationshipsByLabel(item, - this.model.relationshipConfig.relationshipType, + relationshipOptions.relationshipType, undefined, followLink('leftItem'), followLink('rightItem'), diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts index e29dc4e3f1..9212dfd33a 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-metadata-list-element/existing-metadata-list-element.component.ts @@ -145,9 +145,9 @@ export class ReorderableRelationship extends Reorderable { * Update the Reorderable */ update(): Observable> { - this.store.dispatch(new UpdateRelationshipAction(this.relationship, this.submissionID)) + this.store.dispatch(new UpdateRelationshipAction(this.relationship, this.submissionID)); const updatedRelationship$ = this.relationshipService.updatePlace(this).pipe( - getSucceededRemoteData(), + getSucceededRemoteData() ); updatedRelationship$.subscribe(() => { @@ -208,7 +208,6 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges, const relationMD: MetadataValue = this.submissionItem.firstMetadata(this.relationshipOptions.metadataField, { value: this.relatedItem.uuid }); if (hasValue(relationMD)) { const metadataRepresentationMD: MetadataValue = this.submissionItem.firstMetadata(this.metadataFields, { authority: relationMD.authority }); - const nextValue = Object.assign( new ItemMetadataRepresentation(metadataRepresentationMD), this.relatedItem diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.html new file mode 100644 index 0000000000..e791c41d6e --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.html @@ -0,0 +1,14 @@ +
+ + + + + + + + + +
diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.scss b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.scss new file mode 100644 index 0000000000..ab63e324bd --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.scss @@ -0,0 +1,3 @@ +span.text-contents{ + padding: $btn-padding-y 0; +} diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.spec.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.spec.ts new file mode 100644 index 0000000000..5c5d9e05ab --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.spec.ts @@ -0,0 +1,100 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExistingRelationListElementComponent } from './existing-relation-list-element.component'; +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service'; +import { select, Store } from '@ngrx/store'; +import { Item } from '../../../../../core/shared/item.model'; +import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model'; +import { RelationshipOptions } from '../../models/relationship-options.model'; +import { createSuccessfulRemoteDataObject$ } from '../../../../testing/utils'; +import { RemoveRelationshipAction } from '../relation-lookup-modal/relationship.actions'; +import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; +import { of as observableOf } from 'rxjs'; +import { ReorderableRelationship } from '../existing-metadata-list-element/existing-metadata-list-element.component'; + +describe('ExistingRelationListElementComponent', () => { + let component: ExistingRelationListElementComponent; + let fixture: ComponentFixture; + let selectionService; + let store; + let listID; + let submissionItem; + let relationship; + let reoRel; + let metadataFields; + let relationshipOptions; + let uuid1; + let uuid2; + let relatedItem; + let leftItemRD$; + let rightItemRD$; + let relatedSearchResult; + let submissionId; + let relationshipService; + + function init() { + uuid1 = '91ce578d-2e63-4093-8c73-3faafd716000'; + uuid2 = '0e9dba1c-e1c3-4e05-a539-446f08ef57a7'; + selectionService = jasmine.createSpyObj('selectionService', ['deselectSingle']); + store = jasmine.createSpyObj('store', ['dispatch']); + listID = '1234-listID'; + submissionItem = Object.assign(new Item(), { uuid: uuid1 }); + metadataFields = ['dc.contributor.author']; + relationshipOptions = Object.assign(new RelationshipOptions(), { relationshipType: 'isPublicationOfAuthor', filter: 'test.filter', searchConfiguration: 'personConfiguration', nameVariants: true }) + relatedItem = Object.assign(new Item(), { uuid: uuid2 }); + leftItemRD$ = createSuccessfulRemoteDataObject$(relatedItem); + rightItemRD$ = createSuccessfulRemoteDataObject$(submissionItem); + relatedSearchResult = Object.assign(new ItemSearchResult(), { indexableObject: relatedItem }); + relationshipService = { + updatePlace:() => observableOf({}) + } as any; + + relationship = Object.assign(new Relationship(), { leftItem: leftItemRD$, rightItem: rightItemRD$ }); + submissionId = '1234'; + reoRel = new ReorderableRelationship(relationship, true, relationshipService, {} as any, submissionId); + } + + beforeEach(async(() => { + init(); + TestBed.configureTestingModule({ + declarations: [ExistingRelationListElementComponent], + providers: [ + { provide: SelectableListService, useValue: selectionService }, + { provide: Store, useValue: store }, + ], + schemas: [NO_ERRORS_SCHEMA] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExistingRelationListElementComponent); + component = fixture.componentInstance; + component.listId = listID; + component.submissionItem = submissionItem; + component.reoRel = reoRel; + component.metadataFields = metadataFields; + component.relationshipOptions = relationshipOptions; + component.submissionId = submissionId; + fixture.detectChanges(); + component.ngOnChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('removeSelection', () => { + it('should deselect the object in the selectable list service', () => { + component.removeSelection(); + expect(selectionService.deselectSingle).toHaveBeenCalledWith(listID, relatedSearchResult); + }); + + it('should dispatch a RemoveRelationshipAction', () => { + component.removeSelection(); + const action = new RemoveRelationshipAction(submissionItem, relatedItem, relationshipOptions.relationshipType, submissionId); + expect(store.dispatch).toHaveBeenCalledWith(action); + }); + }) +}); diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.ts new file mode 100644 index 0000000000..a3f5060c32 --- /dev/null +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/existing-relation-list-element/existing-relation-list-element.component.ts @@ -0,0 +1,168 @@ +import { Component, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; +import { FormControl } from '@angular/forms'; +import { DynamicFormArrayGroupModel } from '@ng-dynamic-forms/core'; +import { Store } from '@ngrx/store'; +import { Observable, of as observableOf, Subscription } from 'rxjs'; +import { filter } from 'rxjs/operators'; +import { AppState } from '../../../../../app.reducer'; +import { Item } from '../../../../../core/shared/item.model'; +import { getAllSucceededRemoteData, getRemoteDataPayload } from '../../../../../core/shared/operators'; +import { hasValue, isNotEmpty } from '../../../../empty.util'; +import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; +import { SelectableListService } from '../../../../object-list/selectable-list/selectable-list.service'; +import { FormFieldMetadataValueObject } from '../../models/form-field-metadata-value.model'; +import { RelationshipOptions } from '../../models/relationship-options.model'; +import { DynamicConcatModel } from '../models/ds-dynamic-concat.model'; +import { RemoveRelationshipAction } from '../relation-lookup-modal/relationship.actions'; +import { ViewMode } from '../../../../../core/shared/view-mode.model'; +import { ReorderableRelationship } from '../existing-metadata-list-element/existing-metadata-list-element.component'; + +// tslint:disable:max-classes-per-file +/** + * Abstract class that defines objects that can be reordered + */ +export abstract class Reorderable { + + constructor(public oldIndex?: number, public newIndex?: number) { + } + + /** + * Return the id for this Reorderable + */ + abstract getId(): string; + + /** + * Return the place metadata for this Reorderable + */ + abstract getPlace(): number; + + /** + * Update the Reorderable + */ + abstract update(): Observable; + + /** + * Returns true if the oldIndex of this Reorderable + * differs from the newIndex + */ + get hasMoved(): boolean { + return this.oldIndex !== this.newIndex + } +} + +/** + * A Reorderable representation of a FormFieldMetadataValue + */ +export class ReorderableFormFieldMetadataValue extends Reorderable { + + constructor( + public metadataValue: FormFieldMetadataValueObject, + public model: DynamicConcatModel, + public control: FormControl, + public group: DynamicFormArrayGroupModel, + oldIndex?: number, + newIndex?: number + ) { + super(oldIndex, newIndex); + this.metadataValue = metadataValue; + } + + /** + * Return the id for this Reorderable + */ + getId(): string { + if (hasValue(this.metadataValue.authority)) { + return this.metadataValue.authority; + } else { + // can't use UUIDs, they're generated client side + return this.metadataValue.value; + } + } + + /** + * Return the place metadata for this Reorderable + */ + getPlace(): number { + return this.metadataValue.place; + } + + /** + * Update the Reorderable + */ + update(): Observable { + this.oldIndex = this.newIndex; + return observableOf(this.metadataValue); + } + +} + +/** + * Represents a single existing relationship value as metadata in submission + */ +@Component({ + selector: 'ds-existing-relation-list-element', + templateUrl: './existing-relation-list-element.component.html', + styleUrls: ['./existing-relation-list-element.component.scss'] +}) +export class ExistingRelationListElementComponent implements OnInit, OnChanges, OnDestroy { + @Input() listId: string; + @Input() submissionItem: Item; + @Input() reoRel: ReorderableRelationship; + @Input() metadataFields: string[]; + @Input() relationshipOptions: RelationshipOptions; + @Input() submissionId: string; + relatedItem: Item; + viewType = ViewMode.ListElement; + + /** + * List of subscriptions to unsubscribe from + */ + private subs: Subscription[] = []; + + constructor( + private selectableListService: SelectableListService, + private store: Store + ) { + } + + ngOnInit(): void { + this.ngOnChanges(); + } + + /** + * Change callback for the component + */ + ngOnChanges() { + if (hasValue(this.reoRel)) { + const item$ = this.reoRel.useLeftItem ? + this.reoRel.relationship.leftItem : this.reoRel.relationship.rightItem; + this.subs.push(item$.pipe( + getAllSucceededRemoteData(), + getRemoteDataPayload(), + filter((item: Item) => hasValue(item) && isNotEmpty(item.uuid)) + ).subscribe((item: Item) => { + this.relatedItem = item; + })); + } + } + + /** + * Removes the selected relationship from the list + */ + removeSelection() { + this.selectableListService.deselectSingle(this.listId, Object.assign(new ItemSearchResult(), { indexableObject: this.relatedItem })); + this.store.dispatch(new RemoveRelationshipAction(this.submissionItem, this.relatedItem, this.relationshipOptions.relationshipType, this.submissionId)); + } + + /** + * Unsubscribe from all subscriptions + */ + ngOnDestroy(): void { + this.subs + .filter((sub) => hasValue(sub)) + .forEach((sub) => sub.unsubscribe()); + } + +} + +// tslint:enable:max-classes-per-file diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.model.ts index 0fa2b3e5ed..5eb9aa8dd2 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.model.ts @@ -5,6 +5,7 @@ export const DYNAMIC_FORM_CONTROL_TYPE_DISABLED = 'EMPTY'; export interface DsDynamicDisabledModelConfig extends DsDynamicInputModelConfig { value?: any; + hasSelectableMetadata: boolean; } /** @@ -14,11 +15,14 @@ export class DynamicDisabledModel extends DsDynamicInputModel { @serializable() readonly type: string = DYNAMIC_FORM_CONTROL_TYPE_DISABLED; @serializable() value: any; + @serializable() hasSelectableMetadata: boolean; constructor(config: DsDynamicDisabledModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); this.readOnly = true; this.disabled = true; + this.hasSelectableMetadata = config.hasSelectableMetadata; + this.valueUpdates.next(config.value); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-concat.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-concat.model.ts index 60e4d23e67..a34d701f25 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-concat.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-concat.model.ts @@ -20,6 +20,7 @@ export interface DynamicConcatModelConfig extends DynamicFormGroupModelConfig { required: boolean; metadataFields: string[]; submissionId: string; + hasSelectableMetadata: boolean; } export class DynamicConcatModel extends DynamicFormGroupModel { @@ -32,6 +33,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel { @serializable() hint?: string; @serializable() metadataFields: string[]; @serializable() submissionId: string; + @serializable() hasSelectableMetadata: boolean; isCustomGroup = true; valueUpdates: Subject; @@ -46,6 +48,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel { this.hint = config.hint; this.metadataFields = config.metadataFields; this.submissionId = config.submissionId; + this.hasSelectableMetadata = config.hasSelectableMetadata; this.valueUpdates = new Subject(); this.valueUpdates.subscribe((value: string) => this.value = value); } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts index 24145bb023..ed7f399085 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-input.model.ts @@ -17,6 +17,8 @@ export interface DsDynamicInputModelConfig extends DynamicInputModelConfig { repeatable: boolean; metadataFields: string[]; submissionId: string; + hasSelectableMetadata: boolean; + } export class DsDynamicInputModel extends DynamicInputModel { @@ -29,6 +31,7 @@ export class DsDynamicInputModel extends DynamicInputModel { @serializable() repeatable?: boolean; @serializable() metadataFields: string[]; @serializable() submissionId: string; + @serializable() hasSelectableMetadata: boolean; constructor(config: DsDynamicInputModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); @@ -39,6 +42,7 @@ export class DsDynamicInputModel extends DynamicInputModel { this.value = config.value; this.relationship = config.relationship; this.submissionId = config.submissionId; + this.hasSelectableMetadata = config.hasSelectableMetadata; this.language = config.language; if (!this.language) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts index bacedfb087..8925d8fd87 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/ds-dynamic-row-array-model.ts @@ -8,6 +8,7 @@ export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig relationshipConfig: RelationshipOptions; metadataKey: string; metadataFields: string[]; + hasSelectableMetadata: boolean; } export class DynamicRowArrayModel extends DynamicFormArrayModel { @@ -17,6 +18,7 @@ export class DynamicRowArrayModel extends DynamicFormArrayModel { @serializable() relationshipConfig: RelationshipOptions; @serializable() metadataKey: string; @serializable() metadataFields: string[]; + @serializable() hasSelectableMetadata: boolean; isRowArray = true; constructor(config: DynamicRowArrayModelConfig, layout?: DynamicFormControlLayout) { @@ -27,5 +29,6 @@ export class DynamicRowArrayModel extends DynamicFormArrayModel { this.relationshipConfig = config.relationshipConfig; this.metadataKey = config.metadataKey; this.metadataFields = config.metadataFields; + this.hasSelectableMetadata = config.hasSelectableMetadata; } } diff --git a/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts b/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts index c885b737c2..9cd0421ea6 100644 --- a/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts +++ b/src/app/shared/form/builder/parsers/disabled-field-parser.spec.ts @@ -51,7 +51,7 @@ describe('DisabledFieldParser test suite', () => { it('should set init value properly', () => { initFormValues = { description: [ - new FormFieldMetadataValueObject('test description'), + 'test description', ], }; const expectedValue ='test description'; @@ -59,7 +59,7 @@ describe('DisabledFieldParser test suite', () => { const parser = new DisabledFieldParser(submissionId, field, initFormValues, parserOptions); const fieldModel = parser.parse(); - expect(fieldModel.value).toEqual(expectedValue); + expect(fieldModel.value.value).toEqual(expectedValue); }); }); diff --git a/src/app/shared/form/builder/parsers/disabled-field-parser.ts b/src/app/shared/form/builder/parsers/disabled-field-parser.ts index 14d7051466..330c288fe9 100644 --- a/src/app/shared/form/builder/parsers/disabled-field-parser.ts +++ b/src/app/shared/form/builder/parsers/disabled-field-parser.ts @@ -9,7 +9,7 @@ export class DisabledFieldParser extends FieldParser { public modelFactory(fieldValue?: FormFieldMetadataValueObject | any, label?: boolean): any { const emptyModelConfig: DsDynamicDisabledModelConfig = this.initModel(null, label); - this.setValues(emptyModelConfig, fieldValue); + this.setValues(emptyModelConfig, fieldValue, true); return new DynamicDisabledModel(emptyModelConfig) } } diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index 91583d70cd..3f44ce59f7 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -45,17 +45,17 @@ export abstract class FieldParser { if (Array.isArray(this.configData.selectableMetadata) && this.configData.selectableMetadata.length === 1) { metadataKey = this.configData.selectableMetadata[0].metadata; } - const config = { id: uniqueId() + '_array', label: this.configData.label, initialCount: this.getInitArrayIndex(), notRepeatable: !this.configData.repeatable, relationshipConfig: this.configData.selectableRelationship, - required: JSON.parse( this.configData.mandatory), + required: JSON.parse(this.configData.mandatory), submissionId: this.submissionId, metadataKey, metadataFields: this.getAllFieldIds(), + hasSelectableMetadata: isNotEmpty(this.configData.selectableMetadata), groupFactory: () => { let model; let isFirstModelInArray = true; @@ -192,7 +192,7 @@ export abstract class FieldParser { return ids; } } else { - return [this.configData.selectableRelationship.relationshipType]; + return ['relation.' + this.configData.selectableRelationship.relationshipType]; } } @@ -216,7 +216,8 @@ export abstract class FieldParser { controlModel.relationship = Object.assign(new RelationshipOptions(), this.configData.selectableRelationship); } controlModel.repeatable = this.configData.repeatable; - controlModel.metadataFields = isNotEmpty(this.configData.selectableMetadata) ? this.configData.selectableMetadata.map((metadataObject) => metadataObject.metadata) : []; + controlModel.metadataFields = this.getAllFieldIds() || []; + controlModel.hasSelectableMetadata = isNotEmpty(this.configData.selectableMetadata); controlModel.submissionId = this.submissionId; // Set label diff --git a/src/app/shared/mocks/mock-form-models.ts b/src/app/shared/mocks/mock-form-models.ts index 3106ba5492..cd6228417b 100644 --- a/src/app/shared/mocks/mock-form-models.ts +++ b/src/app/shared/mocks/mock-form-models.ts @@ -55,7 +55,8 @@ export const qualdropInputConfig = { repeatable: false, value: 'test', submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockQualdropSelectModel = new DynamicSelectModel(qualdropSelectConfig); @@ -82,7 +83,8 @@ const rowArrayQualdropConfig = { required: false, submissionId: '1234', metadataKey: 'dc.some.key', - metadataFields: ['dc.some.key'] + metadataFields: ['dc.some.key'], + hasSelectableMetadata: false } as DynamicRowArrayModelConfig; export const MockRowArrayQualdropModel: DynamicRowArrayModel = new DynamicRowArrayModel(rowArrayQualdropConfig); @@ -139,7 +141,8 @@ const relationGroupConfig = { 'issue test 2' ], }, - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const MockRelationModel: DynamicRelationGroupModel = new DynamicRelationGroupModel(relationGroupConfig); @@ -168,7 +171,8 @@ export const inputWithLanguageAndAuthorityConfig = { id: 'testWithLanguageAndAuthority', }, submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockInputWithLanguageAndAuthorityModel = new DsDynamicInputModel(inputWithLanguageAndAuthorityConfig); @@ -192,7 +196,8 @@ export const inputWithLanguageConfig = { repeatable: false, value: 'testWithLanguage', submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockInputWithLanguageModel = new DsDynamicInputModel(inputWithLanguageConfig); @@ -221,7 +226,8 @@ export const inputWithLanguageAndAuthorityArrayConfig = { id: 'testLanguageAndAuthorityArray', }], submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockInputWithLanguageAndAuthorityArrayModel = new DsDynamicInputModel(inputWithLanguageAndAuthorityArrayConfig); @@ -234,7 +240,8 @@ export const inputWithFormFieldValueConfig = { repeatable: false, value: new FormFieldMetadataValueObject('testWithFormFieldValue'), submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockInputWithFormFieldValueModel = new DsDynamicInputModel(inputWithFormFieldValueConfig); @@ -247,7 +254,8 @@ export const inputWithAuthorityValueConfig = { repeatable: false, value: Object.assign({}, new AuthorityValue(), { value: 'testWithAuthorityValue', id: 'testWithAuthorityValue', display: 'testWithAuthorityValue' }), submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockInputWithAuthorityValueModel = new DsDynamicInputModel(inputWithAuthorityValueConfig); @@ -260,7 +268,8 @@ export const inputWithObjectValueConfig = { repeatable: false, value: { value: 'testWithObjectValue', id: 'testWithObjectValue', display: 'testWithObjectValue' }, submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockInputWithObjectValueModel = new DsDynamicInputModel(inputWithObjectValueConfig); @@ -277,7 +286,8 @@ export const fileFormEditInputConfig = { disabled: false, repeatable: false, submissionId: '1234', - metadataFields: [] + metadataFields: [], + hasSelectableMetadata: false }; export const mockFileFormEditInputModel = new DsDynamicInputModel(fileFormEditInputConfig); diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts index 4e6e206ddd..87b3347752 100644 --- a/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts +++ b/src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.ts @@ -46,6 +46,11 @@ export class ListableObjectComponentLoaderComponent implements OnInit { */ @Input() listID: string; + /** + * Whether to show the badge label or not + */ + @Input() showLabel: boolean = true; + /** * Directive hook used to place the dynamic child component */ @@ -68,6 +73,7 @@ export class ListableObjectComponentLoaderComponent implements OnInit { (componentRef.instance as any).index = this.index; (componentRef.instance as any).linkType = this.linkType; (componentRef.instance as any).listID = this.listID; + (componentRef.instance as any).showLabel = this.showLabel; } /** diff --git a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts index 3602f45ede..61e7662750 100644 --- a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts +++ b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts @@ -29,6 +29,11 @@ export class AbstractListableElementComponent { */ @Input() index: number; + /** + * Whether to show the badge label or not + */ + @Input() showLabel: boolean = true; + /** * The available link types */ diff --git a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html index 81ee3ebcce..c60a3b6d42 100644 --- a/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html +++ b/src/app/shared/object-grid/item-grid-element/item-types/publication/publication-grid-element.component.html @@ -1 +1 @@ - + diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html index ec0b792e34..3c2d54b003 100644 --- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html +++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/publication/publication-search-result-grid-element.component.html @@ -15,7 +15,7 @@
- +

diff --git a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html index acc3ee4194..dcebcfd56a 100644 --- a/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html +++ b/src/app/shared/object-list/item-list-element/item-types/publication/publication-list-element.component.html @@ -1 +1 @@ - \ No newline at end of file + diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.html index 3d2604585d..bd00e4aff1 100644 --- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.html +++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-types/publication/publication-search-result-list-element.component.html @@ -1,4 +1,4 @@ - +
diff --git a/src/app/submission/edit/submission-edit.component.ts b/src/app/submission/edit/submission-edit.component.ts index 908f473136..2340f52ac8 100644 --- a/src/app/submission/edit/submission-edit.component.ts +++ b/src/app/submission/edit/submission-edit.component.ts @@ -13,6 +13,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { SubmissionObject } from '../../core/submission/models/submission-object.model'; import { Collection } from '../../core/shared/collection.model'; import { RemoteData } from '../../core/data/remote-data'; +import { Item } from '../../core/shared/item.model'; /** * This component allows to edit an existing workspaceitem/workflowitem. @@ -59,6 +60,7 @@ export class SubmissionEditComponent implements OnDestroy, OnInit { * @type {Array} */ private subs: Subscription[] = []; + private item: Item; /** * Initialize instance variables @@ -96,6 +98,7 @@ export class SubmissionEditComponent implements OnDestroy, OnInit { this.collectionId = (submissionObjectRD.payload.collection as Collection).id; this.selfUrl = submissionObjectRD.payload._links.self.href; this.sections = submissionObjectRD.payload.sections; + this.item = submissionObjectRD.payload.item as Item; this.submissionDefinition = (submissionObjectRD.payload.submissionDefinition as SubmissionDefinitionsModel); this.changeDetectorRef.detectChanges(); } diff --git a/src/app/submission/form/submission-form.component.spec.ts b/src/app/submission/form/submission-form.component.spec.ts index c8e10da518..d24e1e5a73 100644 --- a/src/app/submission/form/submission-form.component.spec.ts +++ b/src/app/submission/form/submission-form.component.spec.ts @@ -20,6 +20,7 @@ import { AuthServiceStub } from '../../shared/testing/auth-service-stub'; import { AuthService } from '../../core/auth/auth.service'; import { HALEndpointServiceStub } from '../../shared/testing/hal-endpoint-service-stub'; import { createTestComponent } from '../../shared/testing/utils'; +import { Item } from '../../core/shared/item.model'; describe('SubmissionFormComponent Component', () => { @@ -66,7 +67,7 @@ describe('SubmissionFormComponent Component', () => { `; + [submissionId]="submissionId" [item]="item">`; testFixture = createTestComponent(html, TestComponent) as ComponentFixture; testComp = testFixture.componentInstance; @@ -118,6 +119,7 @@ describe('SubmissionFormComponent Component', () => { comp.submissionDefinition = submissionDefinition; comp.selfUrl = selfUrl; comp.sections = sectionsData; + comp.item = new Item(); submissionServiceStub.getSubmissionObject.and.returnValue(observableOf(submissionState)); submissionServiceStub.getSubmissionSections.and.returnValue(observableOf(sectionsList)); @@ -143,6 +145,7 @@ describe('SubmissionFormComponent Component', () => { selfUrl, submissionDefinition, sectionsData, + comp.item, null); expect(submissionServiceStub.startAutoSave).toHaveBeenCalled(); }); @@ -153,6 +156,7 @@ describe('SubmissionFormComponent Component', () => { comp.submissionDefinition = submissionDefinition; comp.selfUrl = selfUrl; comp.sections = sectionsData; + comp.item = new Item(); comp.onCollectionChange(submissionObjectNew); @@ -168,7 +172,9 @@ describe('SubmissionFormComponent Component', () => { submissionId, selfUrl, submissionObjectNew.submissionDefinition, - submissionObjectNew.sections); + submissionObjectNew.sections, + comp.item, + ); }); it('should update only collection id on collection change when submission definition is not changed', () => { @@ -178,6 +184,7 @@ describe('SubmissionFormComponent Component', () => { comp.submissionDefinition = submissionDefinition; comp.selfUrl = selfUrl; comp.sections = sectionsData; + comp.item = new Item(); comp.onCollectionChange({ collection: { diff --git a/src/app/submission/form/submission-form.component.ts b/src/app/submission/form/submission-form.component.ts index 0b8cfce619..9aed2da792 100644 --- a/src/app/submission/form/submission-form.component.ts +++ b/src/app/submission/form/submission-form.component.ts @@ -14,6 +14,7 @@ import { UploaderOptions } from '../../shared/uploader/uploader-options.model'; import { SubmissionObjectEntry } from '../objects/submission-objects.reducer'; import { SectionDataObject } from '../sections/models/section-data.model'; import { SubmissionService } from '../submission.service'; +import { Item } from '../../core/shared/item.model'; /** * This component represents the submission form. @@ -30,6 +31,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { * @type {string} */ @Input() collectionId: string; + @Input() item: Item; /** * The list of submission's sections @@ -150,6 +152,7 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { this.selfUrl, this.submissionDefinition, this.sections, + this.item, null); this.changeDetectorRef.detectChanges(); }) @@ -191,7 +194,8 @@ export class SubmissionFormComponent implements OnChanges, OnDestroy { this.submissionId, submissionObject._links.self.href, this.submissionDefinition, - this.sections); + this.sections, + this.item); } else { this.changeDetectorRef.detectChanges(); } diff --git a/src/app/submission/objects/submission-objects.actions.ts b/src/app/submission/objects/submission-objects.actions.ts index a6b4e3285c..1e3e44aba9 100644 --- a/src/app/submission/objects/submission-objects.actions.ts +++ b/src/app/submission/objects/submission-objects.actions.ts @@ -10,6 +10,7 @@ import { import { SubmissionObject } from '../../core/submission/models/submission-object.model'; import { SubmissionDefinitionsModel } from '../../core/config/models/config-submission-definitions.model'; import { SectionsType } from '../sections/sections-type'; +import { Item } from '../../core/shared/item.model'; /** * For each action type in an action group, make a simple @@ -273,6 +274,7 @@ export class InitSubmissionFormAction implements Action { selfUrl: string; submissionDefinition: SubmissionDefinitionsModel; sections: WorkspaceitemSectionsObject; + item: Item; errors: SubmissionSectionError[]; }; @@ -297,8 +299,9 @@ export class InitSubmissionFormAction implements Action { selfUrl: string, submissionDefinition: SubmissionDefinitionsModel, sections: WorkspaceitemSectionsObject, + item: Item, errors: SubmissionSectionError[]) { - this.payload = { collectionId, submissionId, selfUrl, submissionDefinition, sections, errors }; + this.payload = { collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors }; } } @@ -477,6 +480,7 @@ export class ResetSubmissionFormAction implements Action { selfUrl: string; sections: WorkspaceitemSectionsObject; submissionDefinition: SubmissionDefinitionsModel; + item: Item; }; /** @@ -493,8 +497,8 @@ export class ResetSubmissionFormAction implements Action { * @param submissionDefinition * the submission's form definition */ - constructor(collectionId: string, submissionId: string, selfUrl: string, sections: WorkspaceitemSectionsObject, submissionDefinition: SubmissionDefinitionsModel) { - this.payload = { collectionId, submissionId, selfUrl, sections, submissionDefinition }; + constructor(collectionId: string, submissionId: string, selfUrl: string, sections: WorkspaceitemSectionsObject, submissionDefinition: SubmissionDefinitionsModel, item: Item) { + this.payload = { collectionId, submissionId, selfUrl, sections, submissionDefinition, item }; } } diff --git a/src/app/submission/objects/submission-objects.effects.spec.ts b/src/app/submission/objects/submission-objects.effects.spec.ts index 40c5cc9dd0..3ee370a254 100644 --- a/src/app/submission/objects/submission-objects.effects.spec.ts +++ b/src/app/submission/objects/submission-objects.effects.spec.ts @@ -47,6 +47,7 @@ import { MockTranslateLoader } from '../../shared/mocks/mock-translate-loader'; import { MockStore } from '../../shared/testing/mock-store'; import { AppState } from '../../app.reducer'; import parseSectionErrors from '../utils/parseSectionErrors'; +import { Item } from '../../core/shared/item.model'; describe('SubmissionObjectEffects test suite', () => { let submissionObjectEffects: SubmissionObjectEffects; @@ -101,6 +102,7 @@ describe('SubmissionObjectEffects test suite', () => { selfUrl: selfUrl, submissionDefinition: submissionDefinition, sections: {}, + item: {metadata: {}}, errors: [], } } @@ -153,6 +155,7 @@ describe('SubmissionObjectEffects test suite', () => { selfUrl: selfUrl, submissionDefinition: submissionDefinition, sections: {}, + item: new Item(), errors: [], } } @@ -165,6 +168,7 @@ describe('SubmissionObjectEffects test suite', () => { selfUrl, submissionDefinition, {}, + new Item(), null ) }); diff --git a/src/app/submission/objects/submission-objects.effects.ts b/src/app/submission/objects/submission-objects.effects.ts index a6d9fec995..0d5c285ba0 100644 --- a/src/app/submission/objects/submission-objects.effects.ts +++ b/src/app/submission/objects/submission-objects.effects.ts @@ -4,8 +4,8 @@ import { Store } from '@ngrx/store'; import { TranslateService } from '@ngx-translate/core'; import { union } from 'lodash'; -import { from as observableFrom, of as observableOf } from 'rxjs'; -import { catchError, map, mergeMap, switchMap, tap, withLatestFrom } from 'rxjs/operators'; +import { from as observableFrom, Observable, of as observableOf } from 'rxjs'; +import { catchError, map, mergeMap, switchMap, take, tap, withLatestFrom } from 'rxjs/operators'; import { SubmissionObject } from '../../core/submission/models/submission-object.model'; import { WorkflowItem } from '../../core/submission/models/workflowitem.model'; import { WorkspaceitemSectionUploadObject } from '../../core/submission/models/workspaceitem-section-upload.model'; @@ -44,6 +44,9 @@ import { UpdateSectionDataAction } from './submission-objects.actions'; import { SubmissionObjectEntry } from './submission-objects.reducer'; +import { Item } from '../../core/shared/item.model'; +import { RemoteData } from '../../core/data/remote-data'; +import { getRemoteDataPayload, getSucceededRemoteData } from '../../core/shared/operators'; @Injectable() export class SubmissionObjectEffects { @@ -61,7 +64,12 @@ export class SubmissionObjectEffects { const sectionId = selfLink.substr(selfLink.lastIndexOf('/') + 1); const config = sectionDefinition._links.config ? (sectionDefinition._links.config.href || sectionDefinition._links.config) : ''; const enabled = (sectionDefinition.mandatory) || (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); + let sectionData; + if (sectionDefinition.sectionType != SectionsType.SubmissionForm) { + sectionData = (isNotUndefined(action.payload.sections) && isNotUndefined(action.payload.sections[sectionId])) ? action.payload.sections[sectionId] : Object.create(null); + } else { + sectionData = action.payload.item.metadata; + } const sectionErrors = null; mappedActions.push( new InitSectionAction( @@ -99,6 +107,7 @@ export class SubmissionObjectEffects { action.payload.selfUrl, action.payload.submissionDefinition, action.payload.sections, + action.payload.item, null ))); @@ -334,6 +343,7 @@ export class SubmissionObjectEffects { if (notify && !currentState.sections[sectionId].enabled) { this.submissionService.notifyNewSection(submissionId, sectionId, currentState.sections[sectionId].sectionType); } + console.log(sectionId, sectionData); mappedActions.push(new UpdateSectionDataAction(submissionId, sectionId, sectionData, sectionErrors)); } }); diff --git a/src/app/submission/submission.service.ts b/src/app/submission/submission.service.ts index ac0cd7bec8..a13519e1cd 100644 --- a/src/app/submission/submission.service.ts +++ b/src/app/submission/submission.service.ts @@ -46,6 +46,7 @@ import { RemoteDataError } from '../core/data/remote-data-error'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject } from '../shared/testing/utils'; import { RequestService } from '../core/data/request.service'; import { SearchService } from '../core/shared/search/search.service'; +import { Item } from '../core/shared/item.model'; /** * A service that provides methods used in submission process. @@ -164,8 +165,9 @@ export class SubmissionService { selfUrl: string, submissionDefinition: SubmissionDefinitionsModel, sections: WorkspaceitemSectionsObject, + item: Item, errors: SubmissionSectionError[]) { - this.store.dispatch(new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, sections, errors)); + this.store.dispatch(new InitSubmissionFormAction(collectionId, submissionId, selfUrl, submissionDefinition, sections, item, errors)); } /** @@ -503,9 +505,10 @@ export class SubmissionService { submissionId: string, selfUrl: string, submissionDefinition: SubmissionDefinitionsModel, - sections: WorkspaceitemSectionsObject + sections: WorkspaceitemSectionsObject, + item: Item ) { - this.store.dispatch(new ResetSubmissionFormAction(collectionId, submissionId, selfUrl, sections, submissionDefinition)); + this.store.dispatch(new ResetSubmissionFormAction(collectionId, submissionId, selfUrl, sections, submissionDefinition, item)); } /** diff --git a/src/app/submission/submit/submission-submit.component.html b/src/app/submission/submit/submission-submit.component.html index c9e8c6b51a..2ceaf5a6de 100644 --- a/src/app/submission/submit/submission-submit.component.html +++ b/src/app/submission/submit/submission-submit.component.html @@ -3,6 +3,7 @@ diff --git a/src/app/submission/submit/submission-submit.component.ts b/src/app/submission/submit/submission-submit.component.ts index d3d3ca4e66..deced3ef26 100644 --- a/src/app/submission/submit/submission-submit.component.ts +++ b/src/app/submission/submit/submission-submit.component.ts @@ -10,6 +10,7 @@ import { NotificationsService } from '../../shared/notifications/notifications.s import { SubmissionService } from '../submission.service'; import { SubmissionObject } from '../../core/submission/models/submission-object.model'; import { Collection } from '../../core/shared/collection.model'; +import { Item } from '../../core/shared/item.model'; /** * This component allows to submit a new workspaceitem. @@ -26,6 +27,7 @@ export class SubmissionSubmitComponent implements OnDestroy, OnInit { * @type {string} */ public collectionId: string; + public item: Item; /** * The collection id input to create a new submission @@ -98,6 +100,7 @@ export class SubmissionSubmitComponent implements OnDestroy, OnInit { this.selfUrl = submissionObject._links.self.href; this.submissionDefinition = (submissionObject.submissionDefinition as SubmissionDefinitionsModel); this.submissionId = submissionObject.id; + this.item = submissionObject.item as Item; this.changeDetectorRef.detectChanges(); } }