argos/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/section-fieldset/dataset-profile-editor-sect...

268 lines
7.2 KiB
TypeScript

import { OnDestroy } from '@angular/core';
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { Guid } from '@common/types/guid';
import { isNullOrUndefined } from '@swimlane/ngx-datatable';
import { DragulaService } from 'ng2-dragula';
import { pipe, Subject, Subscription } from 'rxjs';
import { debounceTime, delay, tap } from 'rxjs/operators';
import { FieldEditorModel } from '../../../admin/field-editor-model';
import { FieldSetEditorModel } from '../../../admin/field-set-editor-model';
import { ToCEntry, ToCEntryType } from '../../../table-of-contents/table-of-contents-entry';
import { GENERAL_ANIMATIONS } from '../../animations/animations';
@Component({
selector: 'app-dataset-profile-editor-section-fieldset-component',
templateUrl: './dataset-profile-editor-section-fieldset.component.html',
styleUrls: ['./dataset-profile-editor-section-fieldset.component.scss'],
animations:[GENERAL_ANIMATIONS]
})
export class DatasetProfileEditorSectionFieldSetComponent implements OnInit, OnChanges, OnDestroy {
// @Input() form: FormGroup;
//@Input() dataModel: SectionEditorModel;
// @Input() indexPath: string;
@Input() viewOnly: boolean;
// @Input() numbering: string;
@Input() tocentry: ToCEntry;
@Output() selectedEntryId = new EventEmitter<string>();
@Output() dataNeedsRefresh = new EventEmitter<void> ();
@Output() removeFieldSet = new EventEmitter<string>();
@Output() addNewFieldSet = new EventEmitter<FormGroup>();
@Output() cloneFieldSet = new EventEmitter<FormGroup>();
// FIELDSET_PREFIX_ID="FIELDSET_PREFIX_ID";
// @Output() fieldsetAdded = new EventEmitter<String>(); //returns the id of the fieldset added
idprefix = "id";
readonly dragula_prefix = "dragulaid";
private subs = new Subscription();
private FIELDSETS = 'FIELDSETS';
private initializer = new Subject<void>();
private scroller = new Subject<string>();
// private $selectedFieldsetId = new Subject<string>();
constructor(
private dragulaService: DragulaService,
private myElement: ElementRef
)
{
if(this.dragulaService.find(this.FIELDSETS)){
this.dragulaService.destroy(this.FIELDSETS);
}
this.dragulaService.createGroup(this.FIELDSETS,{
moves:(el, container, handle)=>{
// if(this.viewOnly) return false; //uncomment if want to unable drag n drop in viewonly mode
if(el.id != (this.dragula_prefix+this.tocentry.id)) return false;
if(handle.className && handle.classList.contains('handle')) return true;
return false;
}
});
this.subs.add(this.dragulaService.drop(this.FIELDSETS).subscribe(obs=>{
(this.form.get('fieldSets') as FormArray).controls.forEach((e,i)=>{
e.get('ordinal').setValue(i);
});
// obs.
this.dataNeedsRefresh.emit();
return ;
}));
const initializerSub = this.initializer
.pipe(
debounceTime(100)
)
.subscribe(() =>{
this.initialize();
});
this.subs.add(initializerSub);
this.subs.add(
this.scroller
.pipe(debounceTime(700))
.subscribe(id => {
if(isNullOrUndefined(id)){
this._scrollOnTop();
return ;
}
this._scrollToElement(id);
})
);
// this.subs.add(
// this.$selectedFieldsetId
// .pipe(
// debounceTime(100)
// )
// .subscribe(id => this.selectedEntryId.emit(id))
// );
}
ngOnDestroy(){
// console.log('elemement destroyed -->');
this.subs.unsubscribe();
}
ngOnChanges(changes: SimpleChanges): void {
this.initializer.next();
}
form;
numbering;
private _selectedFieldSetId: string = null;
get selectedFieldSetId(){
return this._selectedFieldSetId;
}
set selectedFieldSetId(id: string){
if(id === this._selectedFieldSetId) return;
this._selectedFieldSetId = id;
this.selectedEntryId.emit(id);
}
// private _findParentSection():FormGroup{
// const parent = this.form.parent;
// return parent;
// }
private initialize(){
if(this.tocentry.type === ToCEntryType.Section){
this.form = this.tocentry.form;
this.numbering = this.tocentry.numbering;
this._selectedFieldSetId = null;
// this.scroller.next(null);
this._scrollOnTop(true);
}else if(this.tocentry.type === ToCEntryType.FieldSet){
this.form = this.tocentry.form.parent.parent;
const numberingArray = this.tocentry.numbering.split('.');
if(numberingArray.length){
numberingArray.splice(numberingArray.length-1);
this.numbering = numberingArray.join('.');
}else{
// console.warn('!not found numbering');
}
this._selectedFieldSetId = this.tocentry.id;
// this._scrollToElement(this.selectedFieldSetId);
this.scroller.next(this.tocentry.id);
}else{//scroll on top
// this._scrollOnTop();
this.scroller.next(null);
}
}
private _scrollToElement(id: string){
let el = this.myElement.nativeElement.querySelector("#"+this.idprefix+id);
if(el){
el.scrollIntoView({behavior: "smooth", block:'start'});
}
}
private _scrollOnTop(instant?: boolean){
const el = this.myElement.nativeElement.querySelector('#topofcontainer');
if(el){
if(instant){
el.scrollIntoView({ block:'end'});
}else{
el.scrollIntoView({behavior:'smooth', block:'end'});
}
}
}
ngOnInit() {
}
onRemoveFieldSet(fieldsetId: string){
this.removeFieldSet.emit(fieldsetId);
}
onCloneFieldSet(fieldset: FormGroup){
this.cloneFieldSet.emit(fieldset);
}
onAddFieldSet(){
// this.addNewFieldSet.emit(this.form);
try{
const length = (this.form.get('fieldSets') as FormArray).length;
if(length === 0){
this.addFieldSetAfter(-9999, 0);
return;
}
else{
const lastElement = (this.form.get('fieldSets') as FormArray).at(length -1);
this.addFieldSetAfter(lastElement.get('ordinal').value, length-1);
}
} catch {}
}
addFieldSetAfter(afterOrdinal: number, afterIndex: number):void{
const field: FieldEditorModel = new FieldEditorModel();
field.id = Guid.create().toString();
field.ordinal = 0;//first filed in the fields list
const fieldForm = field.buildForm();
//give fieldset id and ordinal
const fieldSet: FieldSetEditorModel = new FieldSetEditorModel();
const fieldSetId = Guid.create().toString();
fieldSet.id = fieldSetId;
fieldSet.ordinal = afterOrdinal < 0? 0 :afterOrdinal;
const parentArray = this.form.get('fieldSets') as FormArray;
parentArray.controls.forEach(fieldset=>{
const ordinalControl = fieldset.get('ordinal');
const ordinalValue = ordinalControl.value;
if(ordinalValue > afterOrdinal){
ordinalControl.setValue(ordinalValue +1);
}
});
const fieldsetForm = fieldSet.buildForm();
(fieldsetForm.get('fields') as FormArray).push(fieldForm);
const index = afterOrdinal < 0 ? 0: afterIndex +1;
parentArray.insert(index, fieldsetForm);
this.dataNeedsRefresh.emit();
// this.selectedFieldSetId = fieldSetId;
setTimeout(() => {
this.selectedFieldSetId = fieldSetId;
}, 200);
}
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;
}
}