From 5e77f78a1ce9adc3e53d8566a7f339ae03b3cafa Mon Sep 17 00:00:00 2001 From: Kristan Ntavidi Date: Tue, 23 Mar 2021 12:39:04 +0200 Subject: [PATCH] Dataset Profile Editor. Table of contents numbering drag and drop fix. Fix issues in dragging as well. --- ...ofile-editor-section-fieldset.component.ts | 29 ++++++-- .../dataset-profile-editor.component.html | 2 +- .../dataset-profile-editor.component.ts | 37 ++++++---- .../table-of-contents-entry.ts | 5 ++ .../table-of-contents/table-of-contents.ts | 67 ++++++++++--------- 5 files changed, 88 insertions(+), 52 deletions(-) diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section-fieldset/dataset-profile-editor-section-fieldset.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section-fieldset/dataset-profile-editor-section-fieldset.component.ts index 51bc04cb7..4257b6517 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section-fieldset/dataset-profile-editor-section-fieldset.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section-fieldset/dataset-profile-editor-section-fieldset.component.ts @@ -1,5 +1,5 @@ import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; -import { Inject } from '@angular/core'; +import { ChangeDetectorRef, Inject, OnDestroy } from '@angular/core'; import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { FormArray, FormGroup } from '@angular/forms'; import { FieldEditorModel } from '@app/ui/admin/dataset-profile/admin/field-editor-model'; @@ -18,7 +18,7 @@ import { ToCEntry, ToCEntryType } from '../../../table-of-contents/table-of-cont styleUrls: ['./dataset-profile-editor-section-fieldset.component.scss'] }) -export class DatasetProfileEditorSectionFieldSetComponent extends BaseComponent implements OnInit, OnChanges { +export class DatasetProfileEditorSectionFieldSetComponent implements OnInit, OnChanges, OnDestroy { // @Input() form: FormGroup; //@Input() dataModel: SectionEditorModel; // @Input() indexPath: string; @@ -41,7 +41,6 @@ export class DatasetProfileEditorSectionFieldSetComponent extends BaseComponent private myElement: ElementRef ) { - super(); if(this.dragulaService.find(this.FIELDSETS)){ this.dragulaService.destroy(this.FIELDSETS); } @@ -70,10 +69,20 @@ export class DatasetProfileEditorSectionFieldSetComponent extends BaseComponent } ngOnDestroy(){ + // console.log('elemement destroyed -->'); + this.subs.unsubscribe(); } ngOnChanges(changes: SimpleChanges): void { + // console.log('---------element updated-------'); + // console.log('numbering before:', this.numbering); + + this.initialize(); + // console.log('----post update----'); + // console.log('numbering now', this.numbering, ' changes detected:', changes); + + } @@ -113,6 +122,8 @@ export class DatasetProfileEditorSectionFieldSetComponent extends BaseComponent if(numberingArray.length){ numberingArray.splice(numberingArray.length-1); this.numbering = numberingArray.join('.'); + }else{ + // console.warn('!not found numbering'); } this.selectedFieldSetId = this.tocentry.id; @@ -128,12 +139,18 @@ export class DatasetProfileEditorSectionFieldSetComponent extends BaseComponent if(el){ + /* + Give time to template to build itself (extending and collapsing). + In case we are dragging from one container to another, then the ui takes around 600ms to build + individual previews (dataset-profile-editor-field.component.ts); + + */ setTimeout(() => { const el = this.myElement.nativeElement.querySelector("#"+this.idprefix+id); if(el){ el.scrollIntoView({behavior: "smooth"}); } - }, 300); + }, 1100); }else{ this._scrollOnTop(); } @@ -150,7 +167,9 @@ export class DatasetProfileEditorSectionFieldSetComponent extends BaseComponent } ngOnInit() { - this.initialize(); + // console.log('<-- element created'); + // this.initialize(); + //TODO diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html index 310cb5f40..5379e9c9c 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.html @@ -198,7 +198,7 @@ (removeEntry)="onRemoveEntry($event)" [itemSelected]="selectedTocEntry" [viewOnly]="viewOnly" - (dataNeedsRefresh)="onDataNeedsRefresh()" + (dataNeedsRefresh)="onDataNeedsRefresh($event)" [colorizeInvalid]="colorizeInvalid"> diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts index 6942cd9f7..34ade722e 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts @@ -44,6 +44,8 @@ import { SideNavService } from '@app/core/services/sidenav/side-nav.sevice'; import { EditorCustomValidators, EditorCustomValidatorsEnum } from './custom-validators/editor-custom-validators'; import { CustomErrorValidator } from '@common/forms/validation/custom-validator'; import { STEPPER_ANIMATIONS } from './animations/animations'; + + const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json'); @Component({ @@ -556,18 +558,18 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn return this.toCEntries; } - private updateOrdinals(tocentries: ToCEntry[]){ + // private updateOrdinals(tocentries: ToCEntry[]){ - if(!tocentries || !tocentries.length) return; - tocentries.forEach((e,idx)=>{ - const ordinalControl = e.form.get('ordinal'); - if(ordinalControl){ - ordinalControl.setValue(idx); - ordinalControl.updateValueAndValidity(); - } - this.updateOrdinals(e.subEntries); - }); - } + // if(!tocentries || !tocentries.length) return; + // tocentries.forEach((e,idx)=>{ + // const ordinalControl = e.form.get('ordinal'); + // if(ordinalControl){ + // ordinalControl.setValue(idx); + // ordinalControl.updateValueAndValidity(); + // } + // this.updateOrdinals(e.subEntries); + // }); + // } //sort tocentries based on their ordinality private _sortToCentries(entries: ToCEntry[]){ @@ -708,7 +710,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn private _findTocEntryById(id: string, tocentries: ToCEntry[]): ToCEntry{ - if(!tocentries){ + if(!tocentries || !tocentries.length){ return null; } @@ -1414,8 +1416,15 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn } // previewForm:FormGroup; - onDataNeedsRefresh(){ - this.refreshToCEntries(); + onDataNeedsRefresh(params?){ + + const tocentries = this.refreshToCEntries(); + + if(params && params.draggedItemId){ + if(params.draggedItemId){ + this.displayItem(this._findTocEntryById(params.draggedItemId, tocentries)); + } + } } cloneFieldSet(fieldset: FormGroup){ diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents-entry.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents-entry.ts index cb8afe41b..896933079 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents-entry.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents-entry.ts @@ -21,4 +21,9 @@ export enum ToCEntryType { export interface Foo { childType: ToCEntryType, parent: ToCEntry +} + +export interface TableUpdateInfo{ + draggedItemId?: string; + data?:any; } \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.ts index 7010a5756..a729bc7b0 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/table-of-contents/table-of-contents.ts @@ -5,11 +5,12 @@ import { interval, Subject, Subscription } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators'; import { type } from 'os'; import { SimpleChanges } from '@angular/core'; -import { Foo, ToCEntry, ToCEntryType } from './table-of-contents-entry'; +import { Foo, TableUpdateInfo, ToCEntry, ToCEntryType } from './table-of-contents-entry'; import { DragulaService } from 'ng2-dragula'; import { FormArray } from '@angular/forms'; import { MatSnackBar, MatSnackBarConfig } from '@angular/material'; import { TranslateService } from '@ngx-translate/core'; +import { ContentObserver } from '@angular/cdk/observers'; export interface Link { /* id of the section*/ @@ -44,7 +45,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn @Output() createEntry = new EventEmitter();//TODO - @Output() dataNeedsRefresh = new EventEmitter(); + @Output() dataNeedsRefresh = new EventEmitter(); @Input() itemSelected: ToCEntry; @Input() colorizeInvalid: boolean = false; @@ -96,8 +97,8 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn const timeNow = new Date().getTime(); if(timeNow - this._dragStartedAt> 600){ - console.log('timenow: ', timeNow); - console.log('timestarted', this._dragStartedAt); + // console.log('timenow: ', timeNow); + // console.log('timestarted', this._dragStartedAt); this._dragStartedAt = null; }else{ @@ -135,7 +136,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn switch(element.type){ - case ToCEntryType.FieldSet: + case ToCEntryType.FieldSet:{ if(targetContainer.type != this.tocEntryType.Section){ // const message = 'Fieldset can only be child of Subsections'; const message = this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.TABLE-OF-CONTENTS.ERROR-MESSAGES.FIELDSET-MUST-HAVE-PARENT-SECTION'); @@ -179,11 +180,12 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn sourceFieldsets.controls.forEach(control=>{ const ordinal = control.get('ordinal'); - if(ordinal.value>= sourceOrdinal){ + if((ordinal.value>= sourceOrdinal) && sourceOrdinal>0){ const updatedOrdinalVal = ordinal.value -1; ordinal.setValue(updatedOrdinalVal); } }); + sourceFieldsets.controls.sort(this._compareOrdinals); } let position:number = targetFieldsets.length; @@ -201,7 +203,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn }); - if(siblingIndex>=0 && (position!=targetFieldsets.length)){ + if(siblingIndex>=0){ //sibling found targetFieldsets.controls.filter(control=> control.get('ordinal').value >= position).forEach(control=>{ const ordinal = control.get('ordinal'); @@ -215,11 +217,12 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn fieldsetForm.get('ordinal').setValue(position); targetFieldsets.insert(position,fieldsetForm); - - this.dataNeedsRefresh.emit(); + targetFieldsets.controls.sort(this._compareOrdinals); + this.dataNeedsRefresh.emit({draggedItemId: elementId}); break; - case ToCEntryType.Section: + } + case ToCEntryType.Section:{ if(targetContainer.type == ToCEntryType.Section){ if((targetContainer.form.get('fieldSets')as FormArray).length){ @@ -256,7 +259,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn sourceSections.controls.filter(control=>control.get('ordinal').value >= elementSectionForm.get('ordinal').value).forEach(control=>{ const ordinal = control.get('ordinal'); - const updatedOrdinalVal = ordinal.value -1; + const updatedOrdinalVal = ordinal.value? ordinal.value -1: 0; ordinal.setValue(updatedOrdinalVal); }); @@ -274,14 +277,14 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn } }) - if(targetOrdinal!=targetSections.length){ + // if(targetOrdinal!=targetSections.length){//mporei na einai idio // section.get('ordinal').setValue(i+1); targetSections.controls.filter(control=> control.get('ordinal').value>=targetOrdinal).forEach(control=>{ const ordinal = control.get('ordinal'); const updatedOrdinalVal = ordinal.value+1; ordinal.setValue(updatedOrdinalVal); }); - } + // } }else{ console.info('no siblings found'); @@ -290,7 +293,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn targetSections.insert(targetOrdinal, elementSectionForm); }else if(targetContainer.type === ToCEntryType.Page){ - const pageId = targetContainer.form.get('id').value; + // const pageId = targetContainer.form.get('id').value; const rootform = targetContainer.form.root; const sectionForm = element.form; @@ -313,7 +316,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn //update parent sections ordinal parentSections.controls.filter(section=>section.get('ordinal').value >= sectionForm.get('ordinal').value).forEach(section=>{ const ordinal = section.get('ordinal'); - const updatedOrdinalVal = ordinal.value -1; + const updatedOrdinalVal = ordinal.value?ordinal.value -1: 0; ordinal.setValue(updatedOrdinalVal); }) @@ -333,13 +336,13 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn const siblingId= sibling.id.replace(this.DRAGULA_ITEM_ID_PREFIX, ''); let indx = -1; - targetContainer.subEntries.forEach((e,i)=>{//TOOD TO CHECK IF ORDINAL AND INDEX IS THE SAME + targetContainer.subEntries.forEach((e,i)=>{ if(e.form.get('id').value === siblingId){ indx = i; position = e.form.get('ordinal').value; } }); - if(indx>=0 && position !=targetContainer.subEntries.length) { + if(indx>=0) { // e.form.get('ordinal').setValue(i+1); targetContainer.subEntries.filter(e=>e.form.get('ordinal').value >= position).forEach(e=>{ @@ -368,9 +371,10 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn - this.dataNeedsRefresh.emit(); + this.dataNeedsRefresh.emit({draggedItemId: elementId}); break; - case ToCEntryType.Page: + } + case ToCEntryType.Page:{ if(targetId != this.ROOT_ID){ // const message = 'A page element can only be at top level'; const message = this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.TABLE-OF-CONTENTS.ERROR-MESSAGES.PAGE-ELEMENT-ONLY-TOP-LEVEL'); @@ -407,9 +411,9 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn //ordinality - pages.controls.filter(page=> page.get('ordinal').value> pageForm.get('ordinal').value).forEach(page=>{ + pages.controls.filter(page=> page.get('ordinal').value>= pageForm.get('ordinal').value).forEach(page=>{ const ordinal = page.get('ordinal'); - const ordinalVal = ordinal.value - 1; + const ordinalVal = ordinal.value? ordinal.value - 1: 0; ordinal.setValue(ordinalVal); }); @@ -437,9 +441,9 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn pages.insert(targetPosition, pageForm); - this.dataNeedsRefresh.emit(); + this.dataNeedsRefresh.emit({draggedItemId:elementId}); break; - + } default: console.error('Could not support moving objects for specific type of element'); @@ -464,18 +468,9 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn } }); drake.on('dragend',(el)=>{ - const draggingItem = this.draggingItemId; this.isDragging = false; this.draggingItemId = null; this.overcontainer = null; - - - const entry = this._findTocEntryById(draggingItem, this.links); - - if(entry){ - this.itemClicked(entry); - } - }); @@ -554,6 +549,14 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn duration:2000 } + private _compareOrdinals(a, b){ + + const aValue = a.get('ordinal').value as number; + const bValue = b.get('ordinal').value as number; + + // if(!aValue || !bValue) return 0; + return aValue - bValue; + } }