diff --git a/src/app/core/data/relationship.service.ts b/src/app/core/data/relationship.service.ts index 34ea75708e..07701011d3 100644 --- a/src/app/core/data/relationship.service.ts +++ b/src/app/core/data/relationship.service.ts @@ -292,8 +292,9 @@ export class RelationshipService extends DataService { } public getNameVariant(listID: string, itemID: string): Observable { + console.log(listID, itemID); return this.appStore.pipe( - select(relationshipStateSelector(listID, itemID)), map((state: RelationshipState) => hasValue(state) ? state.nameVariant : undefined) + select(relationshipStateSelector(listID, itemID)), tap((t) => console.log(t)), map((state: RelationshipState) => hasValue(state) ? state.nameVariant : undefined) ); } 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 34d2cd574b..8c6e2502a9 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 @@ -89,7 +89,7 @@ import { ItemDataService } from '../../../../core/data/item-data.service'; import { RemoveRelationshipAction } from './relation-lookup-modal/relationship.actions'; import { Store } from '@ngrx/store'; import { AppState } from '../../../../app.reducer'; -import { ViewMode } from '../../../../core/shared/view-mode.model'; +import { RelationshipOptions } from '../models/relationship-options.model'; export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type | null { switch (model.type) { @@ -273,9 +273,10 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo const modalComp = this.modalRef.componentInstance; modalComp.repeatable = this.model.repeatable; modalComp.listId = this.listId; - modalComp.relationship = this.model.relationship; + modalComp.relationshipOptions = this.model.relationship; modalComp.label = this.model.label; modalComp.itemRD$ = this.model.workspaceItem.item; + modalComp.metadataFields = this.model.metadataFields; } removeSelection(object: SearchResult) { 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 b8c16c3c7e..237a1ab8f2 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 @@ -19,6 +19,7 @@ export interface DynamicConcatModelConfig extends DynamicFormGroupModelConfig { relationship?: RelationshipOptions; repeatable: boolean; required: boolean; + metadataFields: string[]; } export class DynamicConcatModel extends DynamicFormGroupModel { @@ -29,6 +30,8 @@ export class DynamicConcatModel extends DynamicFormGroupModel { @serializable() relationship?: RelationshipOptions; @serializable() repeatable?: boolean; @serializable() required?: boolean; + @serializable() metadataFields: string[]; + isCustomGroup = true; valueUpdates: Subject; @@ -41,6 +44,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel { this.workspaceItem = config.workspaceItem; this.repeatable = config.repeatable; this.required = config.required; + this.metadataFields = config.metadataFields; this.valueUpdates = new Subject(); this.valueUpdates.subscribe((value: string) => this.value = value); @@ -64,7 +68,7 @@ export class DynamicConcatModel extends DynamicFormGroupModel { let tempValue: string; if (typeof value === 'string') { - tempValue = value; + tempValue = value; } else { tempValue = 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 db68f18c3e..68a074d903 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 @@ -21,6 +21,7 @@ export interface DsDynamicInputModelConfig extends DynamicInputModelConfig { value?: any; relationship?: RelationshipOptions; repeatable: boolean; + metadataFields: string[]; } export class DsDynamicInputModel extends DynamicInputModel { @@ -32,11 +33,12 @@ export class DsDynamicInputModel extends DynamicInputModel { @serializable() workspaceItem: WorkspaceItem; @serializable() relationship?: RelationshipOptions; @serializable() repeatable?: boolean; + @serializable() metadataFields: string[]; constructor(config: DsDynamicInputModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); this.repeatable = config.repeatable; - + this.metadataFields = config.metadataFields; this.hint = config.hint; this.readOnly = config.readOnly; this.value = config.value; @@ -90,5 +92,4 @@ export class DsDynamicInputModel extends DynamicInputModel { this.language = this.languageCodes ? this.languageCodes[0].code : null; } } - } 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 88e380107d..52f983e723 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 @@ -12,7 +12,7 @@ ; context: Context; + metadataFields: string; constructor( public modal: NgbActiveModal, @@ -55,30 +56,11 @@ export class DsDynamicLookupRelationModalComponent implements OnInit { ngOnInit(): void { this.selection$ = this.selectableListService.getSelectableList(this.listId).pipe(map((listState: SelectableListState) => hasValue(listState) && hasValue(listState.selection) ? listState.selection : [])); - if (this.relationship.nameVariants) { + if (this.relationshipOptions.nameVariants) { this.context = Context.Submission; } - this.itemRD$.pipe( - switchMap((itemRD: RemoteData) => this.relationshipService.getItemRelationshipsByLabel(itemRD.payload, this.relationship.relationshipType)), - getSucceededRemoteData(), - getRemoteDataPayload(), - map((relationships: PaginatedList) => relationships.page.) - ); - combineLatest(this.itemRD$, this.selection$) - .pipe( - take(1), - switchMap(([itemRD, objects]: [RemoteData, ListableObject[]]) => { - return combineLatest(objects.map((obj: Item) => this.relationshipService.getRelationshipsByRelatedItemIds(itemRD.payload, [obj.uuid]) - .pipe(take(1), map((rels: Relationship[]) => [rels[0], obj.uuid] as [Relationship, string]))) - ) - } - ) - ).subscribe((relations: [Relationship, string][]) => { - relations.forEach((([rel, id]: [Relationship, string]) => { - this.relationshipService.setNameVariant(this.listId, id, rel.) - })) - } - ) + this.itemRD$.subscribe((r) => console.log(r)); + this.setExistingNameVariants(); } close() { @@ -87,18 +69,27 @@ export class DsDynamicLookupRelationModalComponent implements OnInit { select(...selectableObjects: SearchResult[]) { this.zone.runOutsideAngular( - () => this.itemRD$ - .pipe( - getSucceededRemoteData(), - tap((itemRD: RemoteData) => { - return selectableObjects.forEach((object) => - this.store.dispatch(new AddRelationshipAction(itemRD.payload, object.indexableObject, this.relationship.relationshipType)) - ); - } - ) - ).subscribe()); - } + () => { + const obs: Observable = combineLatest(...selectableObjects.map((sri: SearchResult) => { + return this.relationshipService.getNameVariant(this.listId, sri.indexableObject.uuid) + .pipe(map((nameVariant: string) => { + return { + item: sri.indexableObject, + nameVariant + } + }) + ) + }) + ); + combineLatest(this.itemRD$.pipe(getSucceededRemoteData()), obs) + .subscribe(([itemRD, obs]: [RemoteData, any[]]) => { + return obs.forEach((object: any) => + this.store.dispatch(new AddRelationshipAction(itemRD.payload, object.item, this.relationshipOptions.relationshipType, object.nameVariant)) + ); + }) + }); + } deselect(...selectableObjects: SearchResult[]) { this.zone.runOutsideAngular( @@ -106,11 +97,44 @@ export class DsDynamicLookupRelationModalComponent implements OnInit { getSucceededRemoteData(), tap((itemRD: RemoteData) => { return selectableObjects.forEach((object) => - this.store.dispatch(new RemoveRelationshipAction(itemRD.payload, object.indexableObject, this.relationship.relationshipType)) + this.store.dispatch(new RemoveRelationshipAction(itemRD.payload, object.indexableObject, this.relationshipOptions.relationshipType)) ); } ) ).subscribe() ); } + + setExistingNameVariants() { + const virtualMDs$: Observable = this.itemRD$.pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + map((item: Item) => item.allMetadata(this.metadataFields).filter((mdValue) => mdValue.isVirtual))); + + const relatedItemPairs$: Observable<[Item, Item][]> = virtualMDs$.pipe( + switchMap((mds: MetadataValue[]) => combineLatest(mds.map((md: MetadataValue) => this.relationshipService.findById(md.virtualValue).pipe(getSucceededRemoteData(), getRemoteDataPayload())))), + switchMap((relationships: Relationship[]) => combineLatest(relationships.map((relationship: Relationship) => + combineLatest( + relationship.leftItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()), + relationship.rightItem.pipe(getSucceededRemoteData(), getRemoteDataPayload()) + )) + ) + ), + ); + + const relatedItems$: Observable = combineLatest(relatedItemPairs$, this.itemRD$).pipe( + map(([relatedItemPairs, itemRD]: [[Item, Item][], RemoteData]) => relatedItemPairs.map(([left, right]: [Item, Item]) => left.uuid === itemRD.payload.uuid ? left : right)) + ); + + combineLatest(virtualMDs$, relatedItems$).pipe(take(1)).subscribe(([virtualMDs, relatedItems]) => { + let index: number = 0; + virtualMDs.forEach( + (md: MetadataValue) => { + this.relationshipService.setNameVariant(this.listId, relatedItems[index].uuid, md.value); + index++; + } + ); + } + ) + } } \ No newline at end of file diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index 147512a01f..9092445905 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -188,7 +188,7 @@ export abstract class FieldParser { controlModel.workspaceItem = this.workspaceItem; controlModel.relationship = this.configData.selectableRelationship; controlModel.repeatable = this.configData.repeatable; - + controlModel.metadataFields = isNotEmpty(this.configData.selectableMetadata) ? this.configData.selectableMetadata.map((metadataObject) => metadataObject.metadata) : []; // Set label this.setLabel(controlModel, label); diff --git a/src/app/shared/mocks/mock-form-models.ts b/src/app/shared/mocks/mock-form-models.ts index 2bc99fc69f..96647d654e 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 = { disabled: false, repeatable: false, value: 'test', - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockQualdropSelectModel = new DynamicSelectModel(qualdropSelectConfig); @@ -134,7 +135,8 @@ const relationGroupConfig = { 'issue test 2' ], }, - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const MockRelationModel: DynamicRelationGroupModel = new DynamicRelationGroupModel(relationGroupConfig); @@ -162,7 +164,8 @@ export const inputWithLanguageAndAuthorityConfig = { display: 'testWithLanguageAndAuthority', id: 'testWithLanguageAndAuthority', }, - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockInputWithLanguageAndAuthorityModel = new DsDynamicInputModel(inputWithLanguageAndAuthorityConfig); @@ -185,7 +188,8 @@ export const inputWithLanguageConfig = { disabled: false, repeatable: false, value: 'testWithLanguage', - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockInputWithLanguageModel = new DsDynamicInputModel(inputWithLanguageConfig); @@ -213,7 +217,8 @@ export const inputWithLanguageAndAuthorityArrayConfig = { display: 'testLanguageAndAuthorityArray', id: 'testLanguageAndAuthorityArray', }], - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockInputWithLanguageAndAuthorityArrayModel = new DsDynamicInputModel(inputWithLanguageAndAuthorityArrayConfig); @@ -225,7 +230,8 @@ export const inputWithFormFieldValueConfig = { disabled: false, repeatable: false, value: new FormFieldMetadataValueObject('testWithFormFieldValue'), - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockInputWithFormFieldValueModel = new DsDynamicInputModel(inputWithFormFieldValueConfig); @@ -237,7 +243,8 @@ export const inputWithAuthorityValueConfig = { disabled: false, repeatable: false, value: Object.assign({}, new AuthorityValue(), { value: 'testWithAuthorityValue', id: 'testWithAuthorityValue', display: 'testWithAuthorityValue' }), - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockInputWithAuthorityValueModel = new DsDynamicInputModel(inputWithAuthorityValueConfig); @@ -249,7 +256,8 @@ export const inputWithObjectValueConfig = { disabled: false, repeatable: false, value: { value: 'testWithObjectValue', id: 'testWithObjectValue', display: 'testWithObjectValue' }, - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockInputWithObjectValueModel = new DsDynamicInputModel(inputWithObjectValueConfig); @@ -265,7 +273,8 @@ export const fileFormEditInputConfig = { readOnly: false, disabled: false, repeatable: false, - workspaceItem: new WorkspaceItem() + workspaceItem: new WorkspaceItem(), + metadataFields: [] }; export const mockFileFormEditInputModel = new DsDynamicInputModel(fileFormEditInputConfig); diff --git a/src/app/submission/sections/form/section-form.component.ts b/src/app/submission/sections/form/section-form.component.ts index e593bf2989..f9b3ff78b0 100644 --- a/src/app/submission/sections/form/section-form.component.ts +++ b/src/app/submission/sections/form/section-form.component.ts @@ -241,6 +241,7 @@ export class SubmissionSectionformComponent extends SectionModelComponent { message: msg, path: '/sections/' + this.sectionData.id }; + console.error(e.stack); this.sectionService.setSectionError(this.submissionId, this.sectionData.id, sectionError); } }