2020-08-31 18:08:32 +02:00
|
|
|
import { AfterViewInit, Component, Input, OnChanges, OnInit, SimpleChanges, ViewChild, Output, EventEmitter } from '@angular/core';
|
2021-03-09 09:04:50 +01:00
|
|
|
import { AbstractControl, AbstractControlOptions, FormArray, FormGroup } from '@angular/forms';
|
2021-03-18 09:52:18 +01:00
|
|
|
import { MatExpansionPanel } from '@angular/material';
|
2020-07-29 17:04:19 +02:00
|
|
|
import { MatHorizontalStepper } from '@angular/material/stepper';
|
|
|
|
import { Rule } from '@app/core/model/dataset-profile-definition/rule';
|
2021-03-09 09:04:50 +01:00
|
|
|
import { DatasetProfileTableOfContentsInternalSection } from '@app/ui/admin/dataset-profile/table-of-contents/table-of-contents-internal-section/table-of-contents-internal-section';
|
2020-07-29 17:04:19 +02:00
|
|
|
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';
|
2021-04-12 18:08:09 +02:00
|
|
|
import { debounceTime, takeUntil } from 'rxjs/operators';
|
2021-04-13 10:19:09 +02:00
|
|
|
import { VisibilityRuleSource } from './visibility-rules/models/visibility-rule-source';
|
2020-07-29 17:04:19 +02:00
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: 'app-dataset-description',
|
|
|
|
templateUrl: './dataset-description.component.html',
|
|
|
|
styleUrls: ['./dataset-description.component.scss']
|
|
|
|
})
|
|
|
|
export class DatasetDescriptionComponent extends BaseComponent implements OnInit, AfterViewInit, OnChanges {
|
|
|
|
|
2020-09-23 09:21:26 +02:00
|
|
|
// @ViewChild('stepper', { static: false }) stepper: MatHorizontalStepper;
|
2020-07-29 17:04:19 +02:00
|
|
|
@Input() path: string;
|
|
|
|
@Input() visibilityRules: Rule[] = [];
|
|
|
|
@Input() datasetProfileId: String;
|
|
|
|
@Input() linkToScroll: LinkToScroll;
|
2020-08-31 18:08:32 +02:00
|
|
|
@Output() formChanged: EventEmitter<any> = new EventEmitter();
|
2021-04-06 08:57:17 +02:00
|
|
|
@Output() fieldsetFocusChange: EventEmitter<string> = new EventEmitter<string>();
|
|
|
|
|
2021-03-09 09:04:50 +01:00
|
|
|
tocentries: ToCEntry[];
|
|
|
|
@Input() form: FormGroup;
|
|
|
|
|
2021-03-18 09:52:18 +01:00
|
|
|
@Input() TOCENTRY_ID_PREFIX="";
|
2021-04-13 10:19:09 +02:00
|
|
|
@Output() visibilityRulesInstance = new EventEmitter<VisibilityRulesService>();
|
2021-03-09 09:04:50 +01:00
|
|
|
|
2021-04-12 18:08:09 +02:00
|
|
|
public hiddenEntriesIds:string[] = [];
|
2020-07-29 17:04:19 +02:00
|
|
|
|
|
|
|
constructor(
|
|
|
|
private visibilityRulesService: VisibilityRulesService,
|
|
|
|
) {
|
|
|
|
super();
|
2021-03-09 09:04:50 +01:00
|
|
|
|
2020-07-29 17:04:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ngOnInit() {
|
|
|
|
this.visibilityRulesService.buildVisibilityRules(this.visibilityRules, this.form);
|
2021-04-13 10:19:09 +02:00
|
|
|
|
2020-09-24 19:28:03 +02:00
|
|
|
// if (this.form) {
|
|
|
|
// this.form.valueChanges
|
|
|
|
// .pipe(takeUntil(this._destroyed))
|
|
|
|
// .subscribe(val => {
|
|
|
|
// this.formChanged.emit(val);
|
|
|
|
// });
|
|
|
|
// }
|
2021-04-13 10:19:09 +02:00
|
|
|
this.visibilityRulesInstance.emit(this.visibilityRulesService);
|
2021-03-17 10:08:59 +01:00
|
|
|
|
2021-03-09 09:04:50 +01:00
|
|
|
this.tocentries = this.getTocEntries();
|
2021-04-12 18:08:09 +02:00
|
|
|
this.hiddenEntriesIds = this._findHiddenEntries(this.tocentries);
|
|
|
|
|
|
|
|
this.visibilityRulesService.visibilityChange
|
|
|
|
.pipe(
|
|
|
|
takeUntil(this._destroyed),
|
|
|
|
debounceTime(100)
|
|
|
|
)
|
|
|
|
.subscribe(_=>{
|
|
|
|
this.hiddenEntriesIds = this._findHiddenEntries(this.tocentries);
|
|
|
|
})
|
2020-07-29 17:04:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ngOnChanges(changes: SimpleChanges) {
|
|
|
|
|
|
|
|
// When the form is changed set stepper index to 0.
|
2020-09-23 09:21:26 +02:00
|
|
|
// 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;
|
|
|
|
// }
|
|
|
|
// }
|
2020-07-29 17:04:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ngAfterViewInit() {
|
|
|
|
|
|
|
|
}
|
2021-03-09 09:04:50 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-06 08:57:17 +02:00
|
|
|
onAskedToScroll(panel: MatExpansionPanel, id?:string){
|
2021-03-18 09:52:18 +01:00
|
|
|
panel.open();
|
2021-04-06 08:57:17 +02:00
|
|
|
this.fieldsetFocusChange.emit(id);
|
2021-03-18 09:52:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-03-09 09:04:50 +01:00
|
|
|
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[] {
|
2021-04-12 18:08:09 +02:00
|
|
|
if (!this.form) { return []; }
|
2021-03-09 09:04:50 +01:00
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
2021-04-12 18:08:09 +02:00
|
|
|
private _findHiddenEntries(tocentries:ToCEntry[]):string[]{
|
|
|
|
if(!tocentries) return [];
|
|
|
|
|
|
|
|
const invisibleEntries:string[] = []
|
|
|
|
tocentries.forEach(entry=>{
|
|
|
|
if(entry.type === ToCEntryType.FieldSet){
|
|
|
|
const isVisible = this.visibilityRulesService.checkElementVisibility(entry.id);
|
|
|
|
if(!isVisible){
|
|
|
|
invisibleEntries.push(entry.id);
|
|
|
|
}else{
|
|
|
|
//check field inputs
|
|
|
|
const fields = entry.form.get('fields') as FormArray;
|
|
|
|
|
|
|
|
const oneFieldAtLeastIsVisible = fields.controls.some(field=> this.visibilityRulesService.checkElementVisibility(field.get('id').value));
|
|
|
|
if(!oneFieldAtLeastIsVisible){
|
|
|
|
invisibleEntries.push(entry.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
const hiddenEntries = this._findHiddenEntries(entry.subEntries);
|
|
|
|
|
|
|
|
if(entry.subEntries&& (entry.subEntries.every(e=> hiddenEntries.includes(e.id)))){
|
|
|
|
//all children all hidden then hide parent node;
|
|
|
|
invisibleEntries.push(entry.id);
|
|
|
|
}else{
|
|
|
|
invisibleEntries.push(...hiddenEntries);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return invisibleEntries;
|
|
|
|
}
|
2021-03-09 09:04:50 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
export interface ToCEntry {
|
|
|
|
id: string;
|
|
|
|
label: string;
|
|
|
|
subEntriesType: ToCEntryType;
|
|
|
|
subEntries: ToCEntry[];
|
|
|
|
type: ToCEntryType;
|
|
|
|
form: AbstractControl;
|
|
|
|
numbering: string;
|
|
|
|
ordinal: number;
|
2020-07-29 17:04:19 +02:00
|
|
|
}
|
2021-03-09 09:04:50 +01:00
|
|
|
export enum ToCEntryType {
|
|
|
|
Page = 0,
|
|
|
|
Section = 1,
|
|
|
|
FieldSet = 2,
|
|
|
|
Field = 3
|
|
|
|
}
|