diff --git a/src/app/core/data/relationship-type.service.ts b/src/app/core/data/relationship-type.service.ts index c017bc716b..aeb4fd50a9 100644 --- a/src/app/core/data/relationship-type.service.ts +++ b/src/app/core/data/relationship-type.service.ts @@ -10,7 +10,7 @@ import { getRemoteDataPayload, getResponseFromEntry, getSucceededRemoteData } from '../shared/operators'; -import { DeleteRequest, FindAllOptions, GetRequest, PostRequest, RestRequest } from './request.models'; +import { DeleteRequest, FindAllOptions, FindAllRequest, GetRequest, PostRequest, RestRequest } from './request.models'; import { Observable } from 'rxjs/internal/Observable'; import { RestResponse } from '../cache/response.models'; import { Item } from '../shared/item.model'; @@ -50,20 +50,25 @@ export class RelationshipTypeService { getAllRelationshipTypes(options: FindAllOptions): Observable>> { const link$ = this.halService.getEndpoint(this.linkPath); - link$ + return link$ .pipe( - // map((url) => ) - map((endpointURL: string) => new GetRequest(this.requestService.generateRequestId(), endpointURL)), + map((endpointURL: string) => new FindAllRequest(this.requestService.generateRequestId(), endpointURL, options)), configureRequest(this.requestService), - ).subscribe(); - return this.rdbService.buildList(link$); + switchMap(() => this.rdbService.buildList(link$)) + ); } /** * Get the RelationshipType for a relationship type by label * @param label */ - getRelationshipTypeByLabel(label: string) { - this.getAllRelationshipTypes + getRelationshipTypeByLabel(label: string): Observable { + return this.getAllRelationshipTypes({ currentPage: 1, elementsPerPage: Number.MAX_VALUE }).pipe( + map((typeListRD: RemoteData>) => + typeListRD.payload.page.find((type: RelationshipType) => + type.leftLabel === label || type.rightLabel === label + ) + ), + ); } } diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 1891769e65..57eff62008 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -25,6 +25,8 @@ import { compareArraysUsingIds, filterRelationsByTypeLabel, relationsToItems } from '../../+item-page/simple/item-types/shared/item-relationships-utils'; +import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service'; +import { HttpHeaders } from '@angular/common/http'; /** * The service handling all relationship requests @@ -64,11 +66,16 @@ export class RelationshipService { ); } - addRelationship(item1: Item, item2: Item): Observable { + addRelationship(typeId: string, item1: Item, item2: Item): Observable { + const options: HttpOptions = Object.create({}); + let headers = new HttpHeaders(); + headers = headers.append('Content-Type', 'text/uri-list'); + options.headers = headers; return this.halService.getEndpoint(this.linkPath).pipe( isNotEmptyOperator(), distinctUntilChanged(), - map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL, `${item1.self} ${item2.self}`)), + map((endpointUrl: string) => `${endpointUrl}?relationshipType=${typeId}`), + map((endpointURL: string) => new PostRequest(this.requestService.generateRequestId(), endpointURL, `${item1.self} \n ${item2.self}`, options)), configureRequest(this.requestService), switchMap((restRequest: RestRequest) => this.requestService.getByUUID(restRequest.uuid)), getResponseFromEntry() 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 aabbe146c7..d00d5e2c72 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 @@ -69,7 +69,7 @@ import { DsDynamicFormArrayComponent } from './models/array-group/dynamic-form-a import { DsDynamicRelationGroupComponent } from './models/relation-group/dynamic-relation-group.components'; import { DYNAMIC_FORM_CONTROL_TYPE_RELATION_GROUP } from './models/relation-group/dynamic-relation-group.model'; import { DsDatePickerInlineComponent } from './models/date-picker-inline/dynamic-date-picker-inline.component'; -import { map, tap } from 'rxjs/operators'; +import { map, switchMap, tap } from 'rxjs/operators'; import { SelectableListState } from '../../../object-list/selectable-list/selectable-list.reducer'; import { Observable } from 'rxjs'; import { SearchResult } from '../../../search/search-result.model'; @@ -85,6 +85,13 @@ import { MetadataRepresentationType } from '../../../../core/shared/metadata-rep import { MetadatumRepresentation } from '../../../../core/shared/metadata-representation/metadatum/metadatum-representation.model'; import { relationship } from '../../../../core/cache/builders/build-decorators'; import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; +import { RelationshipTypeService } from '../../../../core/data/relationship-type.service'; +import { RelationshipType } from '../../../../core/shared/item-relationships/relationship-type.model'; +import { RelationshipOptions } from '../models/relationship-options.model'; +import { DsDynamicInputModel } from './models/ds-dynamic-input.model'; +import { getSucceededRemoteData } from '../../../../core/shared/operators'; +import { RemoteData } from '../../../../core/data/remote-data'; +import { Item } from '../../../../core/shared/item.model'; export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type | null { switch (model.type) { @@ -174,7 +181,6 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo modalRef: NgbModalRef; modelValueMDRepresentation; listId: string; - filter: string; searchConfig: string; /* tslint:disable:no-output-rename */ @@ -198,7 +204,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo protected translateService: TranslateService, private modalService: NgbModal, private relationService: RelationshipService, - private selectableListService: SelectableListService + private selectableListService: SelectableListService, ) { super(componentFactoryResolver, layoutService, validationService); } @@ -206,13 +212,20 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo ngOnInit(): void { this.hasRelationLookup = hasValue(this.model.relationship); if (this.hasRelationLookup) { - this.filter = this.model.relationship.filter; - this.searchConfig = this.model.relationship.searchConfiguration; this.listId = 'list-' + this.model.relationship.relationshipType; + + + this.model.workspaceItem.item.pipe( + getSucceededRemoteData(), + switchMap((itemRD: RemoteData) => this.relationService.getRelatedItemsByLabel(itemRD.payload, this.model.relationship.relationshipType)), + map((items: Item[]) => items.map((item) => Object.assign(new SearchResult(), { indexableObject: item }))) + ).subscribe((relatedItems) => this.selectableListService.select(this.listId, relatedItems)); + this.model.value = this.selectableListService.getSelectableList(this.listId).pipe( map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : []), ); this.modelValueMDRepresentation = this.model.value.pipe(map((result: SearchResult[]) => result.map((element: SearchResult) => Object.assign(new ItemMetadataRepresentation(), element.indexableObject)))) + } } @@ -261,11 +274,10 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo this.modalRef = this.modalService.open(DsDynamicLookupRelationModalComponent, { size: 'lg' }); const modalComp = this.modalRef.componentInstance; modalComp.repeatable = this.model.repeatable; - modalComp.relationKey = this.model.name; modalComp.listId = this.listId; - modalComp.filter = this.filter; - modalComp.searchConfiguration = this.searchConfig; + modalComp.relationship = this.model.relationship; modalComp.label = this.model.label; + modalComp.item = this.model.workspaceItem.item; } removeSelection(object: SearchResult) { diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts index a141caa474..173509acf9 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/disabled/dynamic-disabled.component.ts @@ -25,6 +25,5 @@ export class DsDynamicDisabledComponent extends DynamicFormControlComponent { protected relationshipTypeService: RelationshipTypeService ) { super(layoutService, validationService); - relationshipTypeService.getRelationshipTypeByLabel('test').subscribe(); } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html index 410a139b02..2039a86d0f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.html @@ -69,7 +69,8 @@ [searchConfig]="this.searchConfig" [selectable]="true" [selectionConfig]="{ repeatable: repeatable, listId: listId }" - (deselectObject)="allSelected = false" + (deselectObject)="deselect($event)" + (selectObject)="select($event)" > diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts index 4553268733..5e4350cf8e 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/relation-lookup-modal/dynamic-lookup-relation-modal.component.ts @@ -18,6 +18,13 @@ import { SelectableListState } from '../../../../object-list/selectable-list/sel import { ListableObject } from '../../../../object-collection/shared/listable-object.model'; import { RouteService } from '../../../../services/route.service'; import { getSucceededRemoteData } from '../../../../../core/shared/operators'; +import { RelationshipTypeService } from '../../../../../core/data/relationship-type.service'; +import { RelationshipType } from '../../../../../core/shared/item-relationships/relationship-type.model'; +import { RelationshipService } from '../../../../../core/data/relationship.service'; +import { Item } from '../../../../../core/shared/item.model'; +import { RelationshipOptions } from '../../models/relationship-options.model'; +import { combineLatest as observableCombineLatest } from 'rxjs'; +import { relationship } from '../../../../../core/cache/builders/build-decorators'; @Component({ selector: 'ds-dynamic-lookup-relation-modal', @@ -31,12 +38,11 @@ import { getSucceededRemoteData } from '../../../../../core/shared/operators'; ] }) export class DsDynamicLookupRelationModalComponent implements OnInit { - relationKey: string; label: string; - filter: string; - searchConfiguration: string; + relationship: RelationshipOptions; + item: Observable>; listId: string; - resultsRD$: Observable>>>; + resultsRD$: Observable>>>; searchConfig: PaginatedSearchOptions; repeatable: boolean; searchQuery; @@ -48,20 +54,32 @@ export class DsDynamicLookupRelationModalComponent implements OnInit { pageSize: 10 }); selection$: Observable; + relationshipType: Observable; - constructor(public modal: NgbActiveModal, private searchService: SearchService, private router: Router, private selectableListService: SelectableListService, private searchConfigService: SearchConfigurationService, private routeService: RouteService) { + constructor( + public modal: NgbActiveModal, + private searchService: SearchService, + private router: Router, + private selectableListService: SelectableListService, + private searchConfigService: SearchConfigurationService, + private routeService: RouteService, + private relationshipService: RelationshipService, + private relationshipTypeService: RelationshipTypeService + ) { } ngOnInit(): void { this.resetRoute(); - this.routeService.setParameter('fixedFilterQuery', this.filter); - this.routeService.setParameter('configuration', this.searchConfiguration); + this.routeService.setParameter('fixedFilterQuery', this.relationship.filter); + this.routeService.setParameter('configuration', this.relationship.searchConfiguration); + + this.relationshipType = this.relationshipTypeService.getRelationshipTypeByLabel(this.relationship.relationshipType); this.selection$ = this.selectableListService.getSelectableList(this.listId).pipe(map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : [])); this.someSelected$ = this.selection$.pipe(map((selection) => isNotEmpty(selection))); this.resultsRD$ = this.searchConfigService.paginatedSearchOptions.pipe( map((options) => { - return Object.assign(new PaginatedSearchOptions({}), options, { fixedFilter: this.filter, configuration: this.searchConfiguration }) + return Object.assign(new PaginatedSearchOptions({}), options, { fixedFilter: this.relationship.filter, configuration: this.relationship.searchConfiguration }) }), switchMap((options) => { this.searchConfig = options; @@ -128,4 +146,18 @@ export class DsDynamicLookupRelationModalComponent implements OnInit { this.allSelected = false; this.selectableListService.deselectAll(this.listId); } + + + select(selectableObject: SearchResult) { + observableCombineLatest(this.relationshipType, this.item).pipe(take(1)).subscribe( + ([type, itemRD]: [RelationshipType, RemoteData]) => { + const isSwitched = type.rightLabel === this.relationship.relationshipType; + if (isSwitched) { + this.relationshipService.addRelationship('1', selectableObject.indexableObject, itemRD.payload).pipe(getSucceededRemoteData()).subscribe(); + } else { + this.relationshipService.addRelationship('1', itemRD.payload, selectableObject.indexableObject).pipe(getSucceededRemoteData()).subscribe(); + } + } + ) + } } \ No newline at end of file diff --git a/src/app/submission/sections/form/section-form.component.ts b/src/app/submission/sections/form/section-form.component.ts index 49cc62566a..3715c2a34e 100644 --- a/src/app/submission/sections/form/section-form.component.ts +++ b/src/app/submission/sections/form/section-form.component.ts @@ -102,7 +102,7 @@ export class SubmissionSectionformComponent extends SectionModelComponent { */ protected subs: Subscription[] = []; - protected workspaceItem; + protected workspaceItem: Workspaceitem; /** * The FormComponent reference */ @@ -154,10 +154,10 @@ export class SubmissionSectionformComponent extends SectionModelComponent { flatMap(() => combineLatestObservable( this.sectionService.getSectionData(this.submissionId, this.sectionData.id), - this.workspaceItemDataService.findById(this.submissionId).pipe(getSucceededRemoteData()) + this.workspaceItemDataService.findById(this.submissionId).pipe(getSucceededRemoteData(), map((wsiRD: RemoteData) => wsiRD.payload)) )), take(1)) - .subscribe(([sectionData, workspaceItem]: [WorkspaceitemSectionFormObject, RemoteData]) => { + .subscribe(([sectionData, workspaceItem]: [WorkspaceitemSectionFormObject, Workspaceitem]) => { if (isUndefined(this.formModel)) { this.sectionData.errors = []; // Is the first loading so init form