mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
fix issues with deleting of reorderable array items
This commit is contained in:
@@ -48,7 +48,9 @@
|
|||||||
[listId]="listId"
|
[listId]="listId"
|
||||||
[metadataFields]="model.metadataFields"
|
[metadataFields]="model.metadataFields"
|
||||||
[submissionId]="model.submissionId"
|
[submissionId]="model.submissionId"
|
||||||
[relationshipOptions]="model.relationship">
|
[relationshipOptions]="model.relationship"
|
||||||
|
(remove)="onRemove()"
|
||||||
|
>
|
||||||
</ds-existing-metadata-list-element>
|
</ds-existing-metadata-list-element>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
|
@@ -17,7 +17,7 @@ import {
|
|||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef
|
ViewContainerRef
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { FormGroup } from '@angular/forms';
|
import { FormGroup, FormArray } from '@angular/forms';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
|
DYNAMIC_FORM_CONTROL_TYPE_ARRAY,
|
||||||
@@ -38,7 +38,7 @@ import {
|
|||||||
DynamicFormLayout,
|
DynamicFormLayout,
|
||||||
DynamicFormLayoutService, DynamicFormRelationService,
|
DynamicFormLayoutService, DynamicFormRelationService,
|
||||||
DynamicFormValidationService,
|
DynamicFormValidationService,
|
||||||
DynamicTemplateDirective,
|
DynamicTemplateDirective, DynamicFormArrayGroupModel, DynamicFormArrayModel,
|
||||||
} from '@ng-dynamic-forms/core';
|
} from '@ng-dynamic-forms/core';
|
||||||
import {
|
import {
|
||||||
DynamicNGBootstrapCalendarComponent,
|
DynamicNGBootstrapCalendarComponent,
|
||||||
@@ -107,6 +107,8 @@ import { SubmissionService } from '../../../../submission/submission.service';
|
|||||||
import { followLink } from '../../../utils/follow-link-config.model';
|
import { followLink } from '../../../utils/follow-link-config.model';
|
||||||
import { paginatedRelationsToItems } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils';
|
import { paginatedRelationsToItems } from '../../../../+item-page/simple/item-types/shared/item-relationships-utils';
|
||||||
import { RelationshipOptions } from '../models/relationship-options.model';
|
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<DynamicFormControl> | null {
|
export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type<DynamicFormControl> | null {
|
||||||
switch (model.type) {
|
switch (model.type) {
|
||||||
@@ -234,6 +236,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
|
|||||||
private submissionObjectService: SubmissionObjectDataService,
|
private submissionObjectService: SubmissionObjectDataService,
|
||||||
private ref: ChangeDetectorRef,
|
private ref: ChangeDetectorRef,
|
||||||
private formService: FormService,
|
private formService: FormService,
|
||||||
|
private formBuilderService: FormBuilderService,
|
||||||
private submissionService: SubmissionService
|
private submissionService: SubmissionService
|
||||||
) {
|
) {
|
||||||
super(componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService);
|
super(componentFactoryResolver, layoutService, validationService, dynamicFormComponentService, relationService);
|
||||||
@@ -309,7 +312,7 @@ export class DsDynamicFormControlContainerComponent extends DynamicFormControlCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (changes && !this.isRelationship) {
|
if (changes && !this.isRelationship && hasValue(this.group.get(this.model.id))) {
|
||||||
super.ngOnChanges(changes);
|
super.ngOnChanges(changes);
|
||||||
if (this.model && this.model.placeholder) {
|
if (this.model && this.model.placeholder) {
|
||||||
this.model.placeholder = this.translateService.instant(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.item = this.item;
|
||||||
modalComp.collection = this.collection;
|
modalComp.collection = this.collection;
|
||||||
modalComp.submissionId = this.model.submissionId;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,12 +1,19 @@
|
|||||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit } from '@angular/core';
|
import {
|
||||||
import { AbstractControl, FormControl } from '@angular/forms';
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
OnChanges,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
Output
|
||||||
|
} from '@angular/core';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
import { DynamicFormArrayGroupModel, DynamicFormControlEvent } from '@ng-dynamic-forms/core';
|
import { DynamicFormArrayGroupModel, DynamicFormControlEvent } from '@ng-dynamic-forms/core';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { BehaviorSubject, Observable, of as observableOf, Subject, Subscription } from 'rxjs';
|
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||||
import { filter, switchMap } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
import { AppState } from '../../../../../app.reducer';
|
import { AppState } from '../../../../../app.reducer';
|
||||||
import { RelationshipService } from '../../../../../core/data/relationship.service';
|
import { RelationshipService } from '../../../../../core/data/relationship.service';
|
||||||
import { RemoteData } from '../../../../../core/data/remote-data';
|
|
||||||
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
|
import { Relationship } from '../../../../../core/shared/item-relationships/relationship.model';
|
||||||
import { Item } from '../../../../../core/shared/item.model';
|
import { Item } from '../../../../../core/shared/item.model';
|
||||||
import { ItemMetadataRepresentation } from '../../../../../core/shared/metadata-representation/item/item-metadata-representation.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 { MetadataValue } from '../../../../../core/shared/metadata.models';
|
||||||
import {
|
import {
|
||||||
getAllSucceededRemoteData,
|
getAllSucceededRemoteData,
|
||||||
getRemoteDataPayload,
|
getRemoteDataPayload
|
||||||
getSucceededRemoteData
|
|
||||||
} from '../../../../../core/shared/operators';
|
} from '../../../../../core/shared/operators';
|
||||||
import { hasValue, isNotEmpty } from '../../../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../../empty.util';
|
||||||
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
|
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 { RelationshipOptions } from '../../models/relationship-options.model';
|
||||||
import { DynamicConcatModel } from '../models/ds-dynamic-concat.model';
|
import { DynamicConcatModel } from '../models/ds-dynamic-concat.model';
|
||||||
import { RemoveRelationshipAction, UpdateRelationshipAction } from '../relation-lookup-modal/relationship.actions';
|
import { RemoveRelationshipAction, UpdateRelationshipAction } from '../relation-lookup-modal/relationship.actions';
|
||||||
import { SubmissionObject } from '../../../../../core/submission/models/submission-object.model';
|
|
||||||
|
|
||||||
// tslint:disable:max-classes-per-file
|
// tslint:disable:max-classes-per-file
|
||||||
/**
|
/**
|
||||||
@@ -153,7 +158,7 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges,
|
|||||||
@Input() submissionId: string;
|
@Input() submissionId: string;
|
||||||
metadataRepresentation$: BehaviorSubject<MetadataRepresentation> = new BehaviorSubject<MetadataRepresentation>(undefined);
|
metadataRepresentation$: BehaviorSubject<MetadataRepresentation> = new BehaviorSubject<MetadataRepresentation>(undefined);
|
||||||
relatedItem: Item;
|
relatedItem: Item;
|
||||||
|
@Output() remove: EventEmitter<any> = new EventEmitter();
|
||||||
/**
|
/**
|
||||||
* List of subscriptions to unsubscribe from
|
* List of subscriptions to unsubscribe from
|
||||||
*/
|
*/
|
||||||
@@ -201,7 +206,8 @@ export class ExistingMetadataListElementComponent implements OnInit, OnChanges,
|
|||||||
*/
|
*/
|
||||||
removeSelection() {
|
removeSelection() {
|
||||||
this.selectableListService.deselectSingle(this.listId, Object.assign(new ItemSearchResult(), { indexableObject: this.relatedItem }));
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -13,6 +13,7 @@ import {
|
|||||||
} from '@ng-dynamic-forms/core';
|
} from '@ng-dynamic-forms/core';
|
||||||
import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model';
|
import { Relationship } from '../../../../../../core/shared/item-relationships/relationship.model';
|
||||||
import { DynamicRowArrayModel } from '../ds-dynamic-row-array-model';
|
import { DynamicRowArrayModel } from '../ds-dynamic-row-array-model';
|
||||||
|
import { hasValue } from '../../../../../empty.util';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-dynamic-form-array',
|
selector: 'ds-dynamic-form-array',
|
||||||
@@ -45,6 +46,8 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent {
|
|||||||
this.model.moveGroup(event.previousIndex, event.currentIndex - event.previousIndex);
|
this.model.moveGroup(event.previousIndex, event.currentIndex - event.previousIndex);
|
||||||
const prevIndex = event.previousIndex - 1;
|
const prevIndex = event.previousIndex - 1;
|
||||||
const index = event.currentIndex - 1;
|
const index = event.currentIndex - 1;
|
||||||
|
|
||||||
|
if (hasValue(this.model.groups[index]) && hasValue((this.control as any).controls[index])) {
|
||||||
const $event = {
|
const $event = {
|
||||||
$event: { previousIndex: prevIndex },
|
$event: { previousIndex: prevIndex },
|
||||||
context: { index },
|
context: { index },
|
||||||
@@ -56,14 +59,13 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent {
|
|||||||
|
|
||||||
this.onChange($event);
|
this.onChange($event);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update(event: any, index: number) {
|
update(event: any, index: number) {
|
||||||
const $event = Object.assign({}, event, {
|
const $event = Object.assign({}, event, {
|
||||||
context: { index: index - 1}
|
context: { index: index - 1}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('$event', $event);
|
|
||||||
|
|
||||||
this.onChange($event)
|
this.onChange($event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -119,6 +119,7 @@ export class DsDynamicScrollableDropdownComponent extends DynamicFormControlComp
|
|||||||
|
|
||||||
onSelect(event) {
|
onSelect(event) {
|
||||||
this.group.markAsDirty();
|
this.group.markAsDirty();
|
||||||
|
console.log('onSelect event', event);
|
||||||
this.model.valueUpdates.next(event);
|
this.model.valueUpdates.next(event);
|
||||||
this.change.emit(event);
|
this.change.emit(event);
|
||||||
this.setCurrentValue(event);
|
this.setCurrentValue(event);
|
||||||
|
@@ -144,7 +144,6 @@ export class DsDynamicLookupRelationModalComponent implements OnInit, OnDestroy
|
|||||||
* @param selectableObjects
|
* @param selectableObjects
|
||||||
*/
|
*/
|
||||||
select(...selectableObjects: Array<SearchResult<Item>>) {
|
select(...selectableObjects: Array<SearchResult<Item>>) {
|
||||||
console.log('selectableObjects', selectableObjects);
|
|
||||||
this.zone.runOutsideAngular(
|
this.zone.runOutsideAngular(
|
||||||
() => {
|
() => {
|
||||||
const obs: Observable<any[]> = combineLatest(...selectableObjects.map((sri: SearchResult<Item>) => {
|
const obs: Observable<any[]> = combineLatest(...selectableObjects.map((sri: SearchResult<Item>) => {
|
||||||
|
@@ -15,7 +15,7 @@ import {
|
|||||||
DynamicFormControlEvent,
|
DynamicFormControlEvent,
|
||||||
DynamicFormControlModel,
|
DynamicFormControlModel,
|
||||||
DynamicFormGroupModel,
|
DynamicFormGroupModel,
|
||||||
DynamicFormLayout,
|
DynamicFormLayout, DYNAMIC_FORM_CONTROL_TYPE_GROUP,
|
||||||
} from '@ng-dynamic-forms/core';
|
} from '@ng-dynamic-forms/core';
|
||||||
import { findIndex } from 'lodash';
|
import { findIndex } from 'lodash';
|
||||||
import { FormBuilderService } from './builder/form-builder.service';
|
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 { hasValue, isNotEmpty, isNotNull, isNull } from '../empty.util';
|
||||||
import { FormService } from './form.service';
|
import { FormService } from './form.service';
|
||||||
import { FormEntry, FormError } from './form.reducer';
|
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.
|
* The default form component.
|
||||||
@@ -316,8 +323,17 @@ export class FormComponent implements OnDestroy, OnInit {
|
|||||||
|
|
||||||
// set that field to the new value
|
// set that field to the new value
|
||||||
const model = arrayContext.groups[arrayContext.groups.length - 1].group[0] as any;
|
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];
|
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 {
|
} else {
|
||||||
formArrayControl.controls[formArrayControl.length - 1].setValue(value);
|
formArrayControl.controls[formArrayControl.length - 1].setValue(value);
|
||||||
}
|
}
|
||||||
|
@@ -184,7 +184,7 @@ export class SectionFormOperationsService {
|
|||||||
metadataValueMap.set(groupModel.qualdropId, metadataValueList);
|
metadataValueMap.set(groupModel.qualdropId, metadataValueList);
|
||||||
}
|
}
|
||||||
if (index === fieldIndex) {
|
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);
|
value);
|
||||||
}
|
}
|
||||||
previousValue.delete();
|
previousValue.delete();
|
||||||
} else if (value.hasValue()) {
|
} else if (value.hasValue() && (isUndefined(this.getArrayIndexFromEvent(event))
|
||||||
// Here model has no previous value but a new one
|
|| this.getArrayIndexFromEvent(event) === 0)) {
|
||||||
if (isUndefined(this.getArrayIndexFromEvent(event))
|
|
||||||
|| this.getArrayIndexFromEvent(event) === 0) {
|
|
||||||
// Model is single field or is part of an array model but is the first item,
|
// 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
|
// so dispatch an add operation that initialize the values of a specific metadata
|
||||||
this.operationsBuilder.add(
|
this.operationsBuilder.add(
|
||||||
pathCombiner.getPath(segmentedPath),
|
pathCombiner.getPath(segmentedPath),
|
||||||
value, true);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -276,9 +276,8 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
*/
|
*/
|
||||||
updateForm(sectionData: WorkspaceitemSectionFormObject, errors: SubmissionSectionError[]): void {
|
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;
|
this.sectionData.data = sectionData;
|
||||||
if (this.hasMetadataEnrichment(sectionData)) {
|
|
||||||
this.isUpdating = true;
|
this.isUpdating = true;
|
||||||
this.formModel = null;
|
this.formModel = null;
|
||||||
this.cdr.detectChanges();
|
this.cdr.detectChanges();
|
||||||
@@ -289,9 +288,6 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) {
|
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) {
|
||||||
this.checksForErrors(errors);
|
this.checksForErrors(errors);
|
||||||
}
|
}
|
||||||
} else if (isNotEmpty(errors) || isNotEmpty(this.sectionData.errors)) {
|
|
||||||
this.checksForErrors(errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user