import { AfterViewInit, Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild, Output, EventEmitter } from '@angular/core'; import { AbstractControl, AbstractControlOptions, FormArray, FormGroup } from '@angular/forms'; import { MatExpansionPanel } from '@angular/material'; import { MatHorizontalStepper } from '@angular/material/stepper'; import { Rule } from '@app/core/model/dataset-profile-definition/rule'; import { DatasetProfileTableOfContentsInternalSection } from '@app/ui/admin/dataset-profile/table-of-contents/table-of-contents-internal-section/table-of-contents-internal-section'; import { LinkToScroll } from '@app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents'; import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service'; import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-dataset-description', templateUrl: './dataset-description.component.html', styleUrls: ['./dataset-description.component.scss'] }) export class DatasetDescriptionComponent extends BaseComponent implements OnInit, AfterViewInit, OnChanges { // @ViewChild('stepper', { static: false }) stepper: MatHorizontalStepper; @Input() path: string; @Input() visibilityRules: Rule[] = []; @Input() datasetProfileId: String; @Input() linkToScroll: LinkToScroll; @Output() formChanged: EventEmitter = new EventEmitter(); @Output() fieldsetFocusChange: EventEmitter = new EventEmitter(); tocentries: ToCEntry[]; @Input() form: FormGroup; @Input() TOCENTRY_ID_PREFIX=""; private _form: FormGroup; constructor( private visibilityRulesService: VisibilityRulesService, ) { super(); } ngOnInit() { this.visibilityRulesService.buildVisibilityRules(this.visibilityRules, this.form); // if (this.form) { // this.form.valueChanges // .pipe(takeUntil(this._destroyed)) // .subscribe(val => { // this.formChanged.emit(val); // }); // } this.tocentries = this.getTocEntries(); } ngOnChanges(changes: SimpleChanges) { // When the form is changed set stepper index to 0. // if (this.stepper && changes['form'] && !changes['form'].isFirstChange()) { // this.stepper.selectedIndex = 0; // } else if (this.stepper && changes['linkToScroll'] && changes['linkToScroll'].currentValue) { // if (changes['linkToScroll'].currentValue.page >= 0) { // this.stepper.selectedIndex = changes['linkToScroll'].currentValue.page; // } // } } ngAfterViewInit() { } onAskedToScroll(panel: MatExpansionPanel, id?:string){ panel.open(); this.fieldsetFocusChange.emit(id); } private _buildRecursively(form: FormGroup,whatAmI:ToCEntryType):ToCEntry{ if(!form) return null; switch(whatAmI){ case ToCEntryType.Section: const sections = form.get('sections') as FormArray; const fieldsets = form.get('compositeFields') as FormArray; const tempResult:ToCEntry[] = []; if(sections &§ions.length){ sections.controls.forEach(section=>{ tempResult.push(this._buildRecursively(section as FormGroup, ToCEntryType.Section)); }); }else if(fieldsets && fieldsets.length){ fieldsets.controls.forEach(fieldset=>{ tempResult.push(this._buildRecursively(fieldset as FormGroup, ToCEntryType.FieldSet)); }); } return { form: form, id: form.get('id').value, label: form.get('title').value, numbering: '', subEntries:tempResult, subEntriesType: sections &§ions.length? ToCEntryType.Section: ToCEntryType.FieldSet, type: ToCEntryType.Section, ordinal: form.get('ordinal').value } case ToCEntryType.FieldSet: return { form: form, label:form.get('title').value, id: form.get('id').value, numbering:'s', subEntries:[], subEntriesType: ToCEntryType.Field, type: ToCEntryType.FieldSet, ordinal: form.get('ordinal').value } } } private _sortByOrdinal(tocentries: ToCEntry[]){ if(!tocentries || !tocentries.length) return; tocentries.sort(this._customCompare); tocentries.forEach(entry=>{ this._sortByOrdinal(entry.subEntries); }); } private _customCompare(a,b){ return a.ordinal - b.ordinal; } private _calculateNumbering(tocentries: ToCEntry[], depth:number[] = []){ if(!tocentries || !tocentries.length){ return; } let prefixNumbering = depth.length? depth.join('.'): ''; if(depth.length) prefixNumbering = prefixNumbering+"."; tocentries.forEach((entry,i)=>{ entry.numbering = prefixNumbering + (i+1); this._calculateNumbering(entry.subEntries, [...depth, i+1]) }); } getTocEntries(): ToCEntry[] { if (this.form == null) { return []; } const result: ToCEntry[] = []; //build parent pages (this.form.get('pages') as FormArray).controls.forEach((pageElement, i) => { result.push({ id: i+'id', label: pageElement.get('title').value, type: ToCEntryType.Page, form: pageElement, numbering: (i + 1).toString(), subEntriesType: ToCEntryType.Section, subEntries:[], ordinal: pageElement.get('ordinal').value } as ToCEntry) }); result.forEach((entry,i)=>{ const sections = entry.form.get('sections') as FormArray; sections.controls.forEach(section=>{ const tempResults = this._buildRecursively(section as FormGroup,ToCEntryType.Section); entry.subEntries.push(tempResults); }); }); this._sortByOrdinal(result); //calculate numbering this._calculateNumbering(result); return result; } } export interface ToCEntry { id: string; label: string; subEntriesType: ToCEntryType; subEntries: ToCEntry[]; type: ToCEntryType; form: AbstractControl; numbering: string; ordinal: number; } export enum ToCEntryType { Page = 0, Section = 1, FieldSet = 2, Field = 3 }