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 a834930bc1..29ba29e68f 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 @@ -23,11 +23,31 @@ export abstract class Reorderable { abstract getPlace(): number; } -export class ReorderableRelationship extends Reorderable { - relationship: Relationship; - useLeftItem: boolean; +export class ReorderableMetadataValue extends Reorderable { - constructor(relationship: Relationship, useLeftItem: boolean, oldIndex?: number, newIndex?: number) { + constructor(public metadataValue: MetadataValue, oldIndex?: number, newIndex?: number) { + super(oldIndex, newIndex); + this.metadataValue = metadataValue; + } + + 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; + } + } + + getPlace(): number { + return this.metadataValue.place; + } + +} + +export class ReorderableRelationship extends Reorderable { + + constructor(public relationship: Relationship, public useLeftItem: boolean, oldIndex?: number, newIndex?: number) { super(oldIndex, newIndex); this.relationship = relationship; this.useLeftItem = useLeftItem; diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts index 76f55f2fb3..f18dcd146d 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/array-group/dynamic-form-array.component.ts @@ -1,20 +1,39 @@ -import { Component, EventEmitter, Input, NgZone, Output, QueryList, SimpleChanges } from '@angular/core'; +import { CdkDragDrop } from '@angular/cdk/drag-drop'; +import { Component, EventEmitter, Input, NgZone, Output, QueryList } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { - DynamicFormArrayComponent, DynamicFormArrayGroupModel, + DynamicFormArrayComponent, + DynamicFormArrayGroupModel, DynamicFormArrayModel, - DynamicFormControlCustomEvent, DynamicFormControlEvent, + DynamicFormControlCustomEvent, + DynamicFormControlEvent, DynamicFormControlModel, DynamicFormLayout, - DynamicFormLayoutService, DynamicFormService, + DynamicFormLayoutService, + DynamicFormService, DynamicFormValidationService, DynamicTemplateDirective } from '@ng-dynamic-forms/core'; -import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; -import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model'; -import { Reorderable, ReorderableRelationship } from '../../existing-metadata-list-element/existing-metadata-list-element.component'; import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; -import { getSucceededRemoteData } from '../../../../../../core/shared/operators'; +import { map, switchMap, take, tap } from 'rxjs/operators'; import { RelationshipService } from '../../../../../../core/data/relationship.service'; +import { RemoteData } from '../../../../../../core/data/remote-data'; +import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model'; +import { Item } from '../../../../../../core/shared/item.model'; +import { MetadataValue } from '../../../../../../core/shared/metadata.models'; +import { + getAllSucceededRemoteData, + getRemoteDataPayload, getSucceededRemoteData +} from '../../../../../../core/shared/operators'; +import { SubmissionObject } from '../../../../../../core/submission/models/submission-object.model'; +import { SubmissionObjectDataService } from '../../../../../../core/submission/submission-object-data.service'; +import { hasValue, isNotEmpty } from '../../../../../empty.util'; +import { FormFieldMetadataValueObject } from '../../../models/form-field-metadata-value.model'; +import { + Reorderable, ReorderableMetadataValue, + ReorderableRelationship +} from '../../existing-metadata-list-element/existing-metadata-list-element.component'; +import { DynamicConcatModel } from '../ds-dynamic-concat.model'; +import { DynamicRowArrayModel } from '../ds-dynamic-row-array-model'; @Component({ selector: 'ds-dynamic-form-array', @@ -25,7 +44,7 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { @Input() bindId = true; @Input() group: FormGroup; @Input() layout: DynamicFormLayout; - @Input() model: DynamicFormArrayModel; + private _model: DynamicRowArrayModel; @Input() templates: QueryList | undefined; /* tslint:disable:no-output-rename */ @@ -34,25 +53,106 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { @Output('dfFocus') focus: EventEmitter = new EventEmitter(); @Output('ngbEvent') customEvent: EventEmitter = new EventEmitter(); + private submissionItem: Item; + private reorderables: Reorderable[]; + + get model(): DynamicRowArrayModel { + return this._model; + }; + + @Input() set model(model: DynamicRowArrayModel) { + this._model = model; + this.onSetModel(); + }; /* tslint:enable:no-output-rename */ constructor(protected layoutService: DynamicFormLayoutService, protected validationService: DynamicFormValidationService, protected relationshipService: RelationshipService, + protected submissionObjectService: SubmissionObjectDataService, protected zone: NgZone, protected formService: DynamicFormService ) { super(layoutService, validationService); } - moveSelection(event: CdkDragDrop) { - this.zone.runOutsideAngular(() => { - this.model.moveGroup(event.previousIndex,event.currentIndex - event.previousIndex); - this.model.groups.forEach( - (group: DynamicFormArrayGroupModel) => { - console.log(group.group[0]); - } + private onSetModel(): void { + this.submissionObjectService + .findById(this.model.submissionId).pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable>) + .pipe( + getSucceededRemoteData(), + getRemoteDataPayload() + ) ) + ).subscribe((item) => this.submissionItem = item); + + this.updateReorderables(this._model.groups); + } + + private updateReorderables(groups: DynamicFormArrayGroupModel[]): void { + const reorderable$arr: Array> = groups + .map((group: DynamicFormArrayGroupModel, index: number) => { + const formFieldMetadataValue: FormFieldMetadataValueObject = (group.group[0] as DynamicConcatModel).value as FormFieldMetadataValueObject; + if (hasValue(formFieldMetadataValue)) { + const value = Object.assign(new MetadataValue(), { + value: formFieldMetadataValue.display, + language: formFieldMetadataValue.language, + place: formFieldMetadataValue.place, + authority: formFieldMetadataValue.authority, + confidence: formFieldMetadataValue.confidence + }); + if (value.isVirtual) { + console.log('value.virtualValue', value.virtualValue); + this.relationshipService.findById(value.virtualValue) + .pipe( + tap((relationship: Relationship) => console.log('relationship', relationship)), + getSucceededRemoteData(), + getRemoteDataPayload(), + switchMap((relationship: Relationship) => + relationship.leftItem.pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + map((leftItem: Item) => { + return new ReorderableRelationship( + relationship, + leftItem.uuid !== this.submissionItem.uuid, + index, + index + ); + }), + ) + ) + ); + } else { + return observableOf(new ReorderableMetadataValue(value, index, index)); + } + } + }); + + observableCombineLatest(...reorderable$arr) + .subscribe((reorderables: Reorderable[]) => { + if (isNotEmpty(this.reorderables)) { + reorderables.forEach((newReorderable: Reorderable) => { + const match = this.reorderables.find((reo: Reorderable) => reo.getId() === newReorderable.getId()); + if (hasValue(match)) { + newReorderable.oldIndex = match.newIndex; + } + }) + } + this.reorderables = reorderables; + console.log('this.reorderables', this.reorderables); + }); + } + + moveSelection(event: CdkDragDrop) { + this.model.moveGroup(event.previousIndex,event.currentIndex - event.previousIndex); + this.updateReorderables(this._model.groups); + + // this.zone.runOutsideAngular(() => { + // return observableCombineLatest(reorderables.map((rel: ReorderableRelationship) => { // if (rel.oldIndex !== rel.newIndex) { // return this.relationshipService.updatePlace(rel); @@ -61,7 +161,7 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { // } // }) // ).pipe(getSucceededRemoteData()).subscribe(); - }) + // }) } } 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 7de319bf56..432446c56c 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 @@ -3,16 +3,19 @@ import { DynamicFormArrayModel, DynamicFormArrayModelConfig, DynamicFormControlL export interface DynamicRowArrayModelConfig extends DynamicFormArrayModelConfig { notRepeatable: boolean; required: boolean; + submissionId: string; } export class DynamicRowArrayModel extends DynamicFormArrayModel { @serializable() notRepeatable = false; @serializable() required = false; + @serializable() submissionId: string; isRowArray = true; constructor(config: DynamicRowArrayModelConfig, layout?: DynamicFormControlLayout) { super(config, layout); this.notRepeatable = config.notRepeatable; this.required = config.required; + this.submissionId = config.submissionId; } } diff --git a/src/app/shared/form/builder/parsers/field-parser.ts b/src/app/shared/form/builder/parsers/field-parser.ts index ac137f8f1f..7b83d20e1d 100644 --- a/src/app/shared/form/builder/parsers/field-parser.ts +++ b/src/app/shared/form/builder/parsers/field-parser.ts @@ -50,6 +50,7 @@ export abstract class FieldParser { initialCount: this.getInitArrayIndex() + 1, notRepeatable: !this.configData.repeatable || hasValue(this.configData.selectableRelationship), required: isNotEmpty(this.configData.mandatory), + submissionId: this.submissionId, groupFactory: () => { let model; let isFirstModelInArray = true; diff --git a/src/app/shared/mocks/mock-form-models.ts b/src/app/shared/mocks/mock-form-models.ts index e4f9ec3131..9a6ef13731 100644 --- a/src/app/shared/mocks/mock-form-models.ts +++ b/src/app/shared/mocks/mock-form-models.ts @@ -79,7 +79,8 @@ const rowArrayQualdropConfig = { groupFactory: () => { return [MockQualdropModel]; }, - required: false + required: false, + submissionId: '1234' } as DynamicRowArrayModelConfig; export const MockRowArrayQualdropModel: DynamicRowArrayModel = new DynamicRowArrayModel(rowArrayQualdropConfig);