mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
switch to patch for reorderin
This commit is contained in:
@@ -48,7 +48,9 @@ export abstract class Reorderable {
|
||||
/**
|
||||
* Update the Reorderable
|
||||
*/
|
||||
abstract update(): Observable<any>;
|
||||
update(): void {
|
||||
this.oldIndex = this.newIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the oldIndex of this Reorderable
|
||||
@@ -95,14 +97,6 @@ export class ReorderableFormFieldMetadataValue extends Reorderable {
|
||||
return this.metadataValue.place;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Reorderable
|
||||
*/
|
||||
update(): Observable<FormFieldMetadataValueObject> {
|
||||
this.oldIndex = this.newIndex;
|
||||
return observableOf(this.metadataValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,23 +134,6 @@ export class ReorderableRelationship extends Reorderable {
|
||||
return this.relationship.leftPlace
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Reorderable
|
||||
*/
|
||||
update(): Observable<RemoteData<Relationship>> {
|
||||
this.store.dispatch(new UpdateRelationshipAction(this.relationship, this.submissionID))
|
||||
const updatedRelationship$ = this.relationshipService.updatePlace(this).pipe(
|
||||
getSucceededRemoteData(),
|
||||
);
|
||||
|
||||
updatedRelationship$.subscribe(() => {
|
||||
this.oldIndex = this.newIndex;
|
||||
|
||||
});
|
||||
|
||||
return updatedRelationship$;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -35,8 +35,8 @@
|
||||
[model]="_model"
|
||||
[templates]="templates"
|
||||
[ngClass]="[getClass('element', 'host', _model), getClass('grid', 'host', _model)]"
|
||||
(dfBlur)="update(idx)"
|
||||
(dfChange)="update(idx)"
|
||||
(dfBlur)="update($event, idx)"
|
||||
(dfChange)="update($event, idx)"
|
||||
(dfFocus)="onFocus($event)"
|
||||
(ngbEvent)="onCustomEvent($event, null, true)"></ds-dynamic-form-control-container>
|
||||
</ng-template>
|
||||
|
@@ -1,60 +1,25 @@
|
||||
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
||||
import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
EventEmitter,
|
||||
Input,
|
||||
NgZone,
|
||||
OnInit,
|
||||
Output,
|
||||
QueryList
|
||||
} from '@angular/core';
|
||||
import { AbstractControl, FormControl, FormGroup } from '@angular/forms';
|
||||
import { Component, EventEmitter, Input, Output, QueryList } from '@angular/core';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
import {
|
||||
DynamicFormArrayComponent,
|
||||
DynamicFormArrayGroupModel,
|
||||
DynamicFormControlCustomEvent,
|
||||
DynamicFormControlEvent, DynamicFormControlEventType,
|
||||
DynamicFormControlEvent,
|
||||
DynamicFormControlEventType,
|
||||
DynamicFormLayout,
|
||||
DynamicFormLayoutService,
|
||||
DynamicFormService,
|
||||
DynamicFormValidationService,
|
||||
DynamicTemplateDirective
|
||||
} from '@ng-dynamic-forms/core';
|
||||
import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
|
||||
import { map, switchMap, take, tap, filter } 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 {
|
||||
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,
|
||||
ReorderableFormFieldMetadataValue,
|
||||
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';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { SubmissionService } from '../../../../../../submission/submission.service';
|
||||
import { AppState } from '../../../../../../app.reducer';
|
||||
import { followLink } from '../../../../../utils/follow-link-config.model';
|
||||
import { ObjectCacheService } from '../../../../../../core/cache/object-cache.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-dynamic-form-array',
|
||||
templateUrl: './dynamic-form-array.component.html',
|
||||
styleUrls: ['./dynamic-form-array.component.scss']
|
||||
})
|
||||
export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent implements OnInit {
|
||||
export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent {
|
||||
|
||||
@Input() bindId = true;
|
||||
@Input() group: FormGroup;
|
||||
@@ -68,169 +33,37 @@ export class DsDynamicFormArrayComponent extends DynamicFormArrayComponent imple
|
||||
@Output('dfFocus') focus: EventEmitter<DynamicFormControlEvent> = new EventEmitter<DynamicFormControlEvent>();
|
||||
@Output('ngbEvent') customEvent: EventEmitter<DynamicFormControlCustomEvent> = new EventEmitter();
|
||||
|
||||
private submissionItem: Item;
|
||||
private reorderables: Reorderable[] = [];
|
||||
|
||||
/* tslint:enable:no-output-rename */
|
||||
|
||||
constructor(protected layoutService: DynamicFormLayoutService,
|
||||
protected validationService: DynamicFormValidationService,
|
||||
protected objectCacheService: ObjectCacheService,
|
||||
protected relationshipService: RelationshipService,
|
||||
protected changeDetectorRef: ChangeDetectorRef,
|
||||
protected submissionObjectService: SubmissionObjectDataService,
|
||||
protected zone: NgZone,
|
||||
protected formService: DynamicFormService,
|
||||
private submissionService: SubmissionService,
|
||||
private store: Store<AppState>,
|
||||
) {
|
||||
super(layoutService, validationService);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.submissionObjectService
|
||||
.findById(this.model.submissionId, followLink('item')).pipe(
|
||||
getSucceededRemoteData(),
|
||||
getRemoteDataPayload(),
|
||||
switchMap((submissionObject: SubmissionObject) => (submissionObject.item as Observable<RemoteData<Item>>)
|
||||
.pipe(
|
||||
getSucceededRemoteData(),
|
||||
getRemoteDataPayload()
|
||||
)
|
||||
)
|
||||
).subscribe((item) => {
|
||||
this.submissionItem = item;
|
||||
this.updateReorderables(false);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private updateReorderables(shouldPropagateChanges = true): void {
|
||||
this.zone.runOutsideAngular(() => {
|
||||
let groups = this.model.groups.map((group, index) => [group, (this.control as any).controls[index]]);
|
||||
groups = [...groups, groups[0]];
|
||||
const reorderable$arr: Array<Observable<Reorderable>> = groups
|
||||
.filter(([group, control], index) => index > 0 && hasValue((group.group[0] as any).value)) // disregard the first group, it is always empty to ensure the first field remains empty
|
||||
.map(([group, control]: [DynamicFormArrayGroupModel, AbstractControl], index: number) => {
|
||||
const model = group.group[0] as DynamicConcatModel;
|
||||
let formFieldMetadataValue: FormFieldMetadataValueObject = model.value as FormFieldMetadataValueObject;
|
||||
if (hasValue(formFieldMetadataValue)) {
|
||||
const metadataValue = Object.assign(new MetadataValue(), {
|
||||
value: formFieldMetadataValue.display,
|
||||
language: formFieldMetadataValue.language,
|
||||
place: formFieldMetadataValue.place,
|
||||
authority: formFieldMetadataValue.authority,
|
||||
confidence: formFieldMetadataValue.confidence
|
||||
});
|
||||
if (metadataValue.isVirtual) {
|
||||
return this.relationshipService.findById(metadataValue.virtualValue, followLink('leftItem'))
|
||||
.pipe(
|
||||
filter((relRD: RemoteData<Relationship>) => hasValue(relRD.payload)),
|
||||
take(1),
|
||||
getRemoteDataPayload(),
|
||||
switchMap((relationship: Relationship) =>
|
||||
relationship.leftItem.pipe(
|
||||
filter((itemRD: RemoteData<Item>) => hasValue(itemRD.payload)),
|
||||
take(1),
|
||||
getRemoteDataPayload(),
|
||||
map((leftItem: Item) => {
|
||||
return new ReorderableRelationship(
|
||||
relationship,
|
||||
leftItem.uuid !== this.submissionItem.uuid,
|
||||
this.relationshipService,
|
||||
this.store,
|
||||
this.model.submissionId,
|
||||
index,
|
||||
index
|
||||
);
|
||||
}),
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
if (typeof formFieldMetadataValue === 'string') {
|
||||
formFieldMetadataValue = Object.assign(new FormFieldMetadataValueObject(), {
|
||||
value: formFieldMetadataValue,
|
||||
display: formFieldMetadataValue,
|
||||
place: index,
|
||||
});
|
||||
}
|
||||
return observableOf(new ReorderableFormFieldMetadataValue(formFieldMetadataValue, model as any, control as FormControl, group, index, index));
|
||||
}
|
||||
} else {
|
||||
formFieldMetadataValue = Object.assign(new FormFieldMetadataValueObject(), {
|
||||
value: '',
|
||||
display: '',
|
||||
place: index,
|
||||
});
|
||||
return observableOf(new ReorderableFormFieldMetadataValue(formFieldMetadataValue, model as any, control as FormControl, group, index, index));
|
||||
}
|
||||
});
|
||||
|
||||
observableCombineLatest(reorderable$arr)
|
||||
.subscribe((reorderables: Reorderable[]) => {
|
||||
reorderables.forEach((newReorderable: Reorderable) => {
|
||||
const match = this.reorderables.find((reo: Reorderable) => reo.getId() === newReorderable.getId());
|
||||
if (hasValue(match)) {
|
||||
newReorderable.oldIndex = match.newIndex;
|
||||
} else {
|
||||
newReorderable.oldIndex = -1;
|
||||
}
|
||||
});
|
||||
|
||||
this.reorderables = reorderables;
|
||||
|
||||
if (shouldPropagateChanges) {
|
||||
const movedReoRels: Array<Reorderable> = [];
|
||||
let hasMetadataField = false;
|
||||
this.reorderables.forEach((reorderable: Reorderable, index: number) => {
|
||||
if (reorderable.hasMoved) {
|
||||
if (reorderable instanceof ReorderableFormFieldMetadataValue) {
|
||||
const prevIndex = reorderable.oldIndex;
|
||||
hasMetadataField = true;
|
||||
reorderable.update().pipe(take(1)).subscribe((v) => {
|
||||
const reoMD = reorderable as ReorderableFormFieldMetadataValue;
|
||||
reoMD.model.value = reoMD.metadataValue;
|
||||
this.onChange({
|
||||
$event: { previousIndex: prevIndex },
|
||||
context: { index },
|
||||
control: reoMD.control,
|
||||
group: this.group,
|
||||
model: reoMD.model,
|
||||
type: DynamicFormControlEventType.Change
|
||||
});
|
||||
});
|
||||
} else if (reorderable instanceof ReorderableRelationship) {
|
||||
movedReoRels.push(reorderable)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (isNotEmpty(movedReoRels) && hasMetadataField && hasValue(this.model.relationshipConfig)) {
|
||||
// if it's a mix between entities and regular metadata fields,
|
||||
// we need to save, since they use different endpoints and
|
||||
// otherwise they'll get out of sync.
|
||||
this.submissionService.dispatchSave(this.model.submissionId);
|
||||
}
|
||||
|
||||
observableCombineLatest(
|
||||
movedReoRels.map((movedReoRel) => movedReoRel.update().pipe(take(1)))
|
||||
).subscribe(() => {
|
||||
this.changeDetectorRef.detectChanges();
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
moveSelection(event: CdkDragDrop<Relationship>) {
|
||||
this.model.moveGroup(event.previousIndex, event.currentIndex - event.previousIndex);
|
||||
this.updateReorderables();
|
||||
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);
|
||||
}
|
||||
|
||||
update(index: number) {
|
||||
if (index > 0) {
|
||||
this.updateReorderables();
|
||||
}
|
||||
update(event: any, index: number) {
|
||||
const $event = Object.assign({}, event, {
|
||||
context: { index: index - 1}
|
||||
});
|
||||
|
||||
console.log('$event', $event);
|
||||
|
||||
this.onChange($event)
|
||||
}
|
||||
}
|
||||
|
@@ -366,14 +366,7 @@ export class SectionFormOperationsService {
|
||||
value, true);
|
||||
} else if (previousValue.isPathEqual(this.formBuilder.getPath(event.model)) || hasStoredValue) {
|
||||
// Here model has a previous value changed or stored in the server
|
||||
if (!value.hasValue()) {
|
||||
// New value is empty, so dispatch a remove operation
|
||||
if (this.getArrayIndexFromEvent(event) === 0) {
|
||||
this.operationsBuilder.remove(pathCombiner.getPath(segmentedPath));
|
||||
} else {
|
||||
this.operationsBuilder.remove(pathCombiner.getPath(path));
|
||||
}
|
||||
} else if (hasValue(event.$event) && hasValue(event.$event.previousIndex)) {
|
||||
if (hasValue(event.$event) && hasValue(event.$event.previousIndex)) {
|
||||
if (event.$event.previousIndex < 0) {
|
||||
this.operationsBuilder.add(
|
||||
pathCombiner.getPath(segmentedPath),
|
||||
@@ -384,6 +377,13 @@ export class SectionFormOperationsService {
|
||||
pathCombiner.getPath(segmentedPath + '/' + event.$event.previousIndex).path
|
||||
)
|
||||
}
|
||||
} else if (!value.hasValue()) {
|
||||
// New value is empty, so dispatch a remove operation
|
||||
if (this.getArrayIndexFromEvent(event) === 0) {
|
||||
this.operationsBuilder.remove(pathCombiner.getPath(segmentedPath));
|
||||
} else {
|
||||
this.operationsBuilder.remove(pathCombiner.getPath(path));
|
||||
}
|
||||
} else {
|
||||
// New value is not equal from the previous one, so dispatch a replace operation
|
||||
this.operationsBuilder.replace(
|
||||
|
Reference in New Issue
Block a user