import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop'; import { DOCUMENT } from '@angular/common'; import { Component, EventEmitter, Inject, Input, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; import { BaseComponent } from '@common/base/base.component'; import { Foo, ToCEntry, ToCEntryType } from '../table-of-contents-entry'; @Component({ selector: 'app-dataset-profile-table-of-contents-internal-section', styleUrls: ['./table-of-contents-internal-section.scss'], templateUrl: './table-of-contents-internal-section.html' }) export class DatasetProfileTableOfContentsInternalSection extends BaseComponent implements OnInit { @Input() links: ToCEntry[]; @Output() itemClick = new EventEmitter(); @Output() newEntry = new EventEmitter(); @Output() removeEntry = new EventEmitter(); @Output() createFooEntry = new EventEmitter(); @Output() dataNeedsRefresh = new EventEmitter(); @Input() parentLink: ToCEntry; @Input() itemSelected: ToCEntry; @Input() DRAGULA_ITEM_ID_PREFIX; @Input() overContainerId: string; @Input() isDragging; @Input() draggingItemId: string; @Input() parentRootId: string; @Input() colorizeInvalid:boolean = false; @Input() viewOnly: boolean; // @Input() dropListGroup: Set = new Set(); @Input() dropListGroup: string[]; @Input() dragHoveringOver: boolean = false; @Input() depth: number = 0; // @Input() dropListStruct: { id: string, depth: number}[] = []; constructor( @Inject(DOCUMENT) private _document: Document) { super(); } tocEntryType = ToCEntryType; // showStructs(){ // console.log(this.dropListStruct.sort(this.compareFn)); // } // get orderedListGroup(){ // return this.dropListStruct.sort(this.compareFn).map(element=> element.id); // } compareFn(a, b){ if(a.depth> b.depth) return -1; if(a.depth< b.depth) return 1; return 0; } ngOnInit(): void { // if(this.parentLink.id && this.dropListGroup){ // if(!this.dropListGroup.includes(this.parentLink.id)){ // this.dropListGroup.unshift(this.parentLink.id);//TODO // } // } // this.dropListStruct.push({ // id: this.parentLink.id, // depth: this.depth // }); // if(this.links){ // this.links.forEach(link=>{ // this.dropListGroup.push(link.id); // }) // } // this.dropListGroup.add(this.parentLink.id) } showDroplists(){ console.log(this.dropListGroup); } hoveroverEnter(){ // console.log('user hovering drag over', this.parentLink.id, this.parentLink.label); this.dragHoveringOver = true; } hoveroverLeft(){ this.dragHoveringOver = false; } fellowContainers(){ return this.dropListGroup.filter(dl=> dl != this.parentLink.id); } ngOnChanges(changes: SimpleChanges) { } // get grouListIds(){ // return Array.from(this.dropListGroup); // } itemClicked(item: ToCEntry) { //leaf node this.itemClick.emit(item); } deleteEntry(currentLink: ToCEntry){ this.removeEntry.emit(currentLink); } createNewEntry(foo: Foo){ this.createFooEntry.emit(foo); } tocEntryIsChildOf(testingChild: ToCEntry,parent: ToCEntry): boolean{ if(!testingChild || !parent) return false; if(testingChild.id == parent.id){return true;} if(parent.subEntries){ let childFound:boolean = false; parent.subEntries.forEach(subEntry=>{ if(this.tocEntryIsChildOf(testingChild, subEntry)){ childFound = true; return true; } }) return childFound; } return false; } get selectedItemInLinks(){ if(!this.links || !this.itemSelected) return false; const link = this.links.find(l=>l.id === this.itemSelected.id); if(link) return true; return false; } // appendAndGetDroplists(dropList: CdkDropList){ // this.dropListGroup.push(dropList); // return this.dropListGroup; // } drop(event: CdkDragDrop) { // if(!this.links || !this.links.length) return; if(event.container === event.previousContainer){ moveItemInArray(this.links, event.previousIndex, event.currentIndex); let arrayToUpdate: FormArray = this.links[0].form.parent as FormArray; // if(this.parentLink && this.parentLink.form){ // switch(this.parentLink.subEntriesType){ // case this.tocEntryType.Field: // arrayToUpdate = (this.parentLink.form.get('fields') as FormArray); // break; // case this.tocEntryType.FieldSet: // arrayToUpdate = (this.parentLink.form.get('fieldSets') as FormArray); // break; // case this.tocEntryType.Section: // arrayToUpdate = (this.parentLink.form.get('sections') as FormArray); // break // } // } if(arrayToUpdate.controls){ moveItemInArray(arrayToUpdate.controls, event.previousIndex, event.currentIndex); //update ordinality arrayToUpdate.controls.forEach((element,idx ) => { element.get('ordinal').setValue(idx); element.updateValueAndValidity(); }); } this.dataNeedsRefresh.emit(); }else{ console.log('not same container'); } console.log(event.container.id); } onDataNeedsRefresh(){ this.dataNeedsRefresh.emit(); } get hoveringOverParent(){ if(!this.overContainerId) return false; const child = this._findTocEntryById(this.overContainerId, this.parentLink.subEntries); if(!child) return false; return true; } private _findTocEntryById(id: string, tocentries: ToCEntry[]): ToCEntry{ if(!tocentries){ return null; } let tocEntryFound = tocentries.find(entry=>entry.id === id); if(tocEntryFound){ return tocEntryFound; } for(let entry of tocentries){ const result = this._findTocEntryById(id, entry.subEntries); if(result){ tocEntryFound = result; break; } } return tocEntryFound? tocEntryFound: null; } colorError():boolean{ if(!this.colorizeInvalid) return false; const form = this.parentLink.form; if(!form || form.valid || !form.touched) return false; const allFieldsAreTouched = this.allFieldsAreTouched(form); //fieldset may have errros that are inside its controls and not in the fieldsetFormGroup if(this.parentLink.type === this.tocEntryType.FieldSet && allFieldsAreTouched) return true; if(form.errors && allFieldsAreTouched) return true; //checking form controls if have errors let hasErrors = false; if(allFieldsAreTouched){ if(form instanceof FormGroup){ const formGroup = form as FormGroup; const controls = Object.keys(formGroup.controls); controls.forEach(control=>{ if(formGroup.get(control).errors){ hasErrors = true; } }) } } return hasErrors; } allFieldsAreTouched(aControl:AbstractControl){//auto na testaroume if(!aControl|| aControl.untouched) return false; if(aControl instanceof FormControl){ return aControl.touched; }else if(aControl instanceof FormGroup){ const controlKeys = Object.keys((aControl as FormGroup).controls); let areAllTouched = true; controlKeys.forEach(key=>{ if(!this.allFieldsAreTouched(aControl.get(key))){ areAllTouched = false; } }) // const areAllTouched = controlKeys.reduce((acc, key)=>acc && this._allFieldsAreTouched(aControl.get(key)), true); return areAllTouched; }else if(aControl instanceof FormArray){ const controls = (aControl as FormArray).controls; // const areAllTouched = controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true); let areAllTouched = true; // controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true); controls.forEach(control=>{ if(!this.allFieldsAreTouched(control)){ areAllTouched = false; } }); return areAllTouched; } return false; } }