From 53fd559a7c485a3769ce353abe1955313fc96557 Mon Sep 17 00:00:00 2001 From: Art Lowel Date: Wed, 22 Apr 2020 09:49:32 +0200 Subject: [PATCH] fix issues with deleting of reorderable array items --- ...amic-form-control-container.component.html | 4 ++- ...ynamic-form-control-container.component.ts | 22 +++++++++++++--- ...xisting-metadata-list-element.component.ts | 26 ++++++++++++------- .../dynamic-form-array.component.ts | 24 +++++++++-------- .../dynamic-scrollable-dropdown.component.ts | 1 + ...dynamic-lookup-relation-modal.component.ts | 1 - src/app/shared/form/form.component.ts | 20 ++++++++++++-- .../form/section-form-operations.service.ts | 15 +++-------- .../sections/form/section-form.component.ts | 20 ++++++-------- 9 files changed, 81 insertions(+), 52 deletions(-) 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..1b071fcf51 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 @@ -48,7 +48,9 @@ [listId]="listId" [metadataFields]="model.metadataFields" [submissionId]="model.submissionId" - [relationshipOptions]="model.relationship"> + [relationshipOptions]="model.relationship" + (remove)="onRemove()" + > 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..2117f2bc10 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 @@ -17,7 +17,7 @@ import { ViewChild, ViewContainerRef } from '@angular/core'; -import { FormGroup } from '@angular/forms'; +import { FormGroup, FormArray } from '@angular/forms'; import { DYNAMIC_FORM_CONTROL_TYPE_ARRAY, @@ -38,7 +38,7 @@ import { DynamicFormLayout, DynamicFormLayoutService, DynamicFormRelationService, DynamicFormValidationService, - DynamicTemplateDirective, + DynamicTemplateDirective, DynamicFormArrayGroupModel, DynamicFormArrayModel, } from '@ng-dynamic-forms/core'; import { DynamicNGBootstrapCalendarComponent, @@ -107,6 +107,8 @@ import { SubmissionService } from '../../../../submission/submission.service'; import { followLink } from '../../../utils/follow-link-config.model'; import { paginatedRelationsToItems } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils'; import { RelationshipOptions } from '../models/relationship-options.model'; +import { FormBuilderService } from '../form-builder.service'; +import { modalConfigDefaults } from 'ngx-bootstrap/modal/modal-options.class'; export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type | null { switch (model.type) { @@ -234,6 +236,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo private submissionObjectService: SubmissionObjectDataService, private ref: ChangeDetectorRef, private formService: FormService, + private formBuilderService: FormBuilderService, private submissionService: SubmissionService ) { super(componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService); @@ -309,7 +312,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo } ngOnChanges(changes: SimpleChanges) { - if (changes && !this.isRelationship) { + if (changes && !this.isRelationship && hasValue(this.group.get(this.model.id))) { super.ngOnChanges(changes); if (this.model && this.model.placeholder) { this.model.placeholder = this.translateService.instant(this.model.placeholder); @@ -378,6 +381,19 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo modalComp.item = this.item; modalComp.collection = this.collection; modalComp.submissionId = this.model.submissionId; + modalComp.selectEvent + } + + /** + * Callback for the remove event, + * remove the current control from its array + */ + onRemove(): void { + const arrayContext: DynamicFormArrayModel = (this.context as DynamicFormArrayGroupModel).context; + const path = this.formBuilderService.getPath(arrayContext); + const formArrayControl = this.group.root.get(path) as FormArray; + + this.formBuilderService.removeFormArrayGroup(this.context.index, formArrayControl, arrayContext); } /** 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 8490d983c4..f3c72dca47 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 @@ -1,12 +1,19 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit } from '@angular/core'; -import { AbstractControl, FormControl } from '@angular/forms'; +import { + Component, + EventEmitter, + Input, + OnChanges, + OnDestroy, + OnInit, + Output +} from '@angular/core'; +import { FormControl } from '@angular/forms'; import { DynamicFormArrayGroupModel, DynamicFormControlEvent } from '@ng-dynamic-forms/core'; import { Store } from '@ngrx/store'; -import { BehaviorSubject, Observable, of as observableOf, Subject, Subscription } from 'rxjs'; -import { filter, switchMap } from 'rxjs/operators'; +import { BehaviorSubject, Subscription } from 'rxjs'; +import { filter } from 'rxjs/operators'; import { AppState } from '../../../../../app.reducer'; 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 { ItemMetadataRepresentation } from '../../../../../core/shared/metadata-representation/item/item-metadata-representation.model'; @@ -14,8 +21,7 @@ import { MetadataRepresentation } from '../../../../../core/shared/metadata-repr import { MetadataValue } from '../../../../../core/shared/metadata.models'; import { getAllSucceededRemoteData, - getRemoteDataPayload, - getSucceededRemoteData + getRemoteDataPayload } from '../../../../../core/shared/operators'; import { hasValue, isNotEmpty } from '../../../../empty.util'; import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model'; @@ -24,7 +30,6 @@ import { FormFieldMetadataValueObject } from '../../models/form-field-metadata-v import { RelationshipOptions } from '../../models/relationship-options.model'; import { DynamicConcatModel } from '../models/ds-dynamic-concat.model'; import { RemoveRelationshipAction, UpdateRelationshipAction } from '../relation-lookup-modal/relationship.actions'; -import { SubmissionObject } from '../../../../../core/submission/models/submission-object.model'; // tslint:disable:max-classes-per-file /** @@ -153,7 +158,7 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges, @Input() submissionId: string; metadataRepresentation$: BehaviorSubject = new BehaviorSubject(undefined); relatedItem: Item; - + @Output() remove: EventEmitter = new EventEmitter(); /** * List of subscriptions to unsubscribe from */ @@ -201,7 +206,8 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges, */ 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)) + this.store.dispatch(new RemoveRelationshipAction(this.submissionItem, this.relatedItem, this.relationshipOptions.relationshipType, this.submissionId)); + this.remove.emit(); } /** 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 f43b1cb9cb..ea6455a138 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 @@ -13,6 +13,7 @@ import { } from '@ng-dynamic-forms/core'; import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model'; import { DynamicRowArrayModel } from '../ds-dynamic-row-array-model'; +import { hasValue } from '../../../../../empty.util'; @Component({ selector: 'ds-dynamic-form-array', @@ -45,16 +46,19 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { this.model.moveGroup(event.previousIndex, event.currentIndex - event.previousIndex); const prevIndex = event.previousIndex - 1; const index = event.currentIndex - 1; - const $event = { - $event: { previousIndex: prevIndex }, - context: { index }, - control: (this.control as any).controls[index], - group: this.group, - model: this.model.groups[index].group[0], - type: DynamicFormControlEventType.Change - }; - this.onChange($event); + if (hasValue(this.model.groups[index]) && hasValue((this.control as any).controls[index])) { + const $event = { + $event: { previousIndex: prevIndex }, + context: { index }, + control: (this.control as any).controls[index], + group: this.group, + model: this.model.groups[index].group[0], + type: DynamicFormControlEventType.Change + }; + + this.onChange($event); + } } update(event: any, index: number) { @@ -62,8 +66,6 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent { context: { index: index - 1} }); - console.log('$event', $event); - this.onChange($event) } } diff --git a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts index 5eda1372eb..8f24f3f05f 100644 --- a/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts +++ b/src/app/shared/form/builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.component.ts @@ -119,6 +119,7 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp onSelect(event) { this.group.markAsDirty(); + console.log('onSelect event', event); this.model.valueUpdates.next(event); this.change.emit(event); this.setCurrentValue(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 953227c161..bea57189f9 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 @@ -144,7 +144,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy * @param selectableObjects */ select(...selectableObjects: Array>) { - console.log('selectableObjects', selectableObjects); this.zone.runOutsideAngular( () => { const obs: Observable = combineLatest(...selectableObjects.map((sri: SearchResult) => { diff --git a/src/app/shared/form/form.component.ts b/src/app/shared/form/form.component.ts index cf88ec4344..1650cf14d1 100644 --- a/src/app/shared/form/form.component.ts +++ b/src/app/shared/form/form.component.ts @@ -15,7 +15,7 @@ import { DynamicFormControlEvent, DynamicFormControlModel, DynamicFormGroupModel, - DynamicFormLayout, + DynamicFormLayout, DYNAMIC_FORM_CONTROL_TYPE_GROUP, } from '@ng-dynamic-forms/core'; import { findIndex } from 'lodash'; import { FormBuilderService } from './builder/form-builder.service'; @@ -23,6 +23,13 @@ import { Observable, Subscription } from 'rxjs'; import { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util'; import { FormService } from './form.service'; import { FormEntry, FormError } from './form.reducer'; +import { DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN } from './builder/ds-dynamic-form-ui/models/scrollable-dropdown/dynamic-scrollable-dropdown.model'; +import { + QUALDROP_GROUP_SUFFIX, + QUALDROP_VALUE_SUFFIX +} from './builder/ds-dynamic-form-ui/models/ds-dynamic-qualdrop.model'; + +const QUALDROP_GROUP_REGEX = new RegExp(`${QUALDROP_GROUP_SUFFIX}_\\d+$`); /** * The default form component. @@ -316,8 +323,17 @@ export class FormComponent implements OnDestroy, OnInit { // set that field to the new value const model = arrayContext.groups[arrayContext.groups.length - 1].group[0] as any; - if (model.type === 'SCROLLABLE_DROPDOWN') { + if (model.type === DYNAMIC_FORM_CONTROL_TYPE_SCROLLABLE_DROPDOWN) { model.value = Object.values(value)[0]; + } else if (this.formBuilderService.isQualdropGroup(model)) { + const ctrl = formArrayControl.controls[formArrayControl.length - 1]; + const ctrlKey = Object.keys(ctrl.value).find((key: string) => isNotEmpty(key.match(QUALDROP_GROUP_REGEX))); + const valueKey = Object.keys(value).find((key: string) => isNotEmpty(key.match(QUALDROP_GROUP_REGEX))); + if (ctrlKey !== valueKey) { + Object.defineProperty(value, ctrlKey, Object.getOwnPropertyDescriptor(value, valueKey)); + delete value[valueKey]; + } + ctrl.setValue(value); } else { formArrayControl.controls[formArrayControl.length - 1].setValue(value); } diff --git a/src/app/submission/sections/form/section-form-operations.service.ts b/src/app/submission/sections/form/section-form-operations.service.ts index ab837522fd..5026319353 100644 --- a/src/app/submission/sections/form/section-form-operations.service.ts +++ b/src/app/submission/sections/form/section-form-operations.service.ts @@ -184,7 +184,7 @@ export class SectionFormOperationsService { metadataValueMap.set(groupModel.qualdropId, metadataValueList); } if (index === fieldIndex) { - path = groupModel.qualdropId + '/' + (metadataValueMap.get(groupModel.qualdropId).length - 1) + path = groupModel.qualdropId + '/' + (metadataValueList.length - 1) } }); @@ -391,22 +391,13 @@ export class SectionFormOperationsService { value); } previousValue.delete(); - } else if (value.hasValue()) { - // Here model has no previous value but a new one - if (isUndefined(this.getArrayIndexFromEvent(event)) - || this.getArrayIndexFromEvent(event) === 0) { + } else if (value.hasValue() && (isUndefined(this.getArrayIndexFromEvent(event)) + || this.getArrayIndexFromEvent(event) === 0)) { // Model is single field or is part of an array model but is the first item, // so dispatch an add operation that initialize the values of a specific metadata this.operationsBuilder.add( pathCombiner.getPath(segmentedPath), value, true); - } else { - // Model is part of an array model but is not the first item, - // so dispatch an add operation that add a value to an existent metadata - this.operationsBuilder.add( - pathCombiner.getPath(path), - value); - } } } diff --git a/src/app/submission/sections/form/section-form.component.ts b/src/app/submission/sections/form/section-form.component.ts index b708fcf2ab..7d6ddff323 100644 --- a/src/app/submission/sections/form/section-form.component.ts +++ b/src/app/submission/sections/form/section-form.component.ts @@ -276,19 +276,15 @@ export class SubmissionSectionformComponent extends SectionModelComponent { */ updateForm(sectionData: WorkspaceitemSectionFormObject, errors: SubmissionSectionError[]): void { - if (isNotEmpty(sectionData) && !isEqual(sectionData, this.sectionData.data)) { + if (hasValue(sectionData) && !isEqual(sectionData, this.sectionData.data)) { this.sectionData.data = sectionData; - if (this.hasMetadataEnrichment(sectionData)) { - this.isUpdating = true; - this.formModel = null; - this.cdr.detectChanges(); - this.initForm(sectionData); - this.checksForErrors(errors); - this.isUpdating = false; - this.cdr.detectChanges(); - } else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) { - this.checksForErrors(errors); - } + this.isUpdating = true; + this.formModel = null; + this.cdr.detectChanges(); + this.initForm(sectionData); + this.checksForErrors(errors); + this.isUpdating = false; + this.cdr.detectChanges(); } else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) { this.checksForErrors(errors); }