Dataset description and table-of-contents works with tocentries.
This commit is contained in:
parent
720fa60f9b
commit
ae378899e2
|
@ -54,7 +54,7 @@
|
||||||
<div (click)="changeStep(0)" *ngIf="datasetInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0}">0. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (<mat-icon class="done-icon">done</mat-icon>)</div>
|
<div (click)="changeStep(0)" *ngIf="datasetInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0}">0. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (<mat-icon class="done-icon">done</mat-icon>)</div>
|
||||||
<div class="row toc-pane-container" #boundary (click)="changeStep(1)">
|
<div class="row toc-pane-container" #boundary (click)="changeStep(1)">
|
||||||
<div #spacer></div>
|
<div #spacer></div>
|
||||||
<table-of-contents class="toc-pane-container" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)"></table-of-contents>
|
<table-of-contents [hasFocus]="step === 1" [formGroup]="formGroup" *ngIf="formGroup && formGroup.get('datasetProfileDefinition')" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)" [visibilityRules]="formGroup.get('datasetProfileDefinition').get('rules').value"></table-of-contents>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -89,14 +89,14 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<!-- <div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button (click)="printForm()">Print form</button>
|
<button (click)="printForm()">Print form</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<button (click)="printFormValue()">Print form value</button>
|
<button (click)="printFormValue()">Print form value</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<!-- <div class="main-content">
|
<!-- <div class="main-content">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
|
|
@ -277,6 +277,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: calc(100vh - 246px);
|
height: calc(100vh - 246px);
|
||||||
|
max-width: 366px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stepper-options {
|
.stepper-options {
|
||||||
|
@ -316,6 +317,8 @@
|
||||||
|
|
||||||
.stepper-list {
|
.stepper-list {
|
||||||
.toc-pane-container {
|
.toc-pane-container {
|
||||||
|
padding-left: 0.2rem;
|
||||||
|
overflow-x: hidden;
|
||||||
span {
|
span {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormArray, FormControl, FormGroup } from '@angular/forms';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
@ -45,6 +45,7 @@ import { SaveType } from '@app/core/common/enum/save-type';
|
||||||
import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard';
|
import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard';
|
||||||
import { MatomoService } from '@app/core/services/matomo/matomo-service';
|
import { MatomoService } from '@app/core/services/matomo/matomo-service';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { ToCEntry, ToCEntryType } from '@app/ui/misc/dataset-description-form/dataset-description.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dataset-wizard-component',
|
selector: 'app-dataset-wizard-component',
|
||||||
|
@ -886,18 +887,28 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
|
||||||
}
|
}
|
||||||
|
|
||||||
public changeStep(index: number, dataset?: FormControl) {
|
public changeStep(index: number, dataset?: FormControl) {
|
||||||
|
if(this.step != index){ //view is changing
|
||||||
|
this.resetScroll();
|
||||||
|
}
|
||||||
this.step = index;
|
this.step = index;
|
||||||
this.resetScroll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public nextStep() {
|
public nextStep() {
|
||||||
this.step = this.step < this.maxStep ? this.step + 1 : this.step;
|
if(this.step < this.maxStep){//view is changing
|
||||||
this.resetScroll();
|
this.step +=1;
|
||||||
|
this.resetScroll();
|
||||||
|
}
|
||||||
|
// this.step = this.step < this.maxStep ? this.step + 1 : this.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
public previousStep() {
|
public previousStep() {
|
||||||
this.step = this.step !== 0 ? this.step - 1 : this.step;
|
if(this.step !== 0){
|
||||||
this.resetScroll();
|
|
||||||
|
this.resetScroll();
|
||||||
|
this.step =-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this.step = this.step !== 0 ? this.step - 1 : this.step;
|
||||||
}
|
}
|
||||||
|
|
||||||
private resetScroll() {
|
private resetScroll() {
|
||||||
|
@ -945,4 +956,133 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
|
||||||
printFormValue(){
|
printFormValue(){
|
||||||
console.log(this.formGroup.value);
|
console.log(this.formGroup.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tocentries;
|
||||||
|
// this.tocentries = this.getTocEntries(this.formGroup.get('datasetProfileDefinition')); //TODO
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// get tocentries(){
|
||||||
|
// const form = this.formGroup.get('datasetProfileDefinition')
|
||||||
|
// if(!form) return null;
|
||||||
|
|
||||||
|
// return this.getTocEntries(this.formGroup.get('datasetProfileDefinition'));
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// 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(form): ToCEntry[] {
|
||||||
|
// if (form == null) { return []; }
|
||||||
|
// const result: ToCEntry[] = [];
|
||||||
|
|
||||||
|
// //build parent pages
|
||||||
|
// (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;
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
<ng-container *ngSwitchCase="tocentriesType.FieldSet">
|
<ng-container *ngSwitchCase="tocentriesType.FieldSet">
|
||||||
|
|
||||||
<!-- FIELDSET CASE -->
|
<!-- FIELDSET CASE -->
|
||||||
<div *ngFor="let fieldsetEntry of tocentry.subEntries; let i = index;" class="col-12">
|
<div *ngFor="let fieldsetEntry of tocentry.subEntries; let i = index;" class="col-12" [id]="fieldsetEntry.id">
|
||||||
<!-- <div *ngIf="isElementVisible(compositeField)" class="row"> -->
|
<!-- <div *ngIf="isElementVisible(compositeField)" class="row"> -->
|
||||||
<!-- *ngIf="this.visibilityRulesService.checkElementVisibility(compositeFieldFormGroup.get('id').value)" -->
|
<!-- *ngIf="this.visibilityRulesService.checkElementVisibility(compositeFieldFormGroup.get('id').value)" -->
|
||||||
<div class="row" *ngIf="this.visibilityRulesService.checkElementVisibility(fieldsetEntry.form.get('id').value) && this.visibilityRulesService.scanIfChildsOfCompositeFieldHasVisibleItems(fieldsetEntry.form)">
|
<div class="row" *ngIf="this.visibilityRulesService.checkElementVisibility(fieldsetEntry.form.get('id').value) && this.visibilityRulesService.scanIfChildsOfCompositeFieldHasVisibleItems(fieldsetEntry.form)">
|
||||||
|
|
|
@ -16,22 +16,34 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
<!-- TOCENTRIES -->
|
||||||
<ng-template #toctemplate>
|
<ng-template #toctemplate>
|
||||||
<!--FIRST LEVEL ALWAYS PAGE-->
|
<!--FIRST LEVEL ALWAYS PAGE-->
|
||||||
<div *ngFor="let pageEntry of tocentries; let z = index;">
|
<mat-accordion [multi]="true">
|
||||||
<h4 >
|
|
||||||
{{pageEntry.numbering}} - {{pageEntry.label}}
|
|
||||||
</h4>
|
|
||||||
|
|
||||||
<div *ngFor="let sectionEntry of pageEntry.subEntries; let i = index;">
|
<div *ngFor="let pageEntry of tocentries; let z = index;">
|
||||||
<div class="row">
|
<mat-expansion-panel [expanded]="true">
|
||||||
<app-form-section class="col-12" [tocentry]="sectionEntry" [path]="z+1"
|
|
||||||
[pathName]="'pages.'+z+'.sections.'+i" [datasetProfileId]="datasetProfileId"
|
<mat-expansion-panel-header>
|
||||||
[linkToScroll]="linkToScroll"></app-form-section>
|
<mat-panel-title>
|
||||||
</div>
|
<h4 class="panel-title toc-page-header">
|
||||||
|
{{pageEntry.numbering}}. {{pageEntry.label |uppercase}}
|
||||||
|
</h4>
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<!--
|
||||||
|
<h4 class="toc-page-header">
|
||||||
|
</h4> -->
|
||||||
|
<div *ngFor="let sectionEntry of pageEntry.subEntries; let i = index;">
|
||||||
|
<div class="row">
|
||||||
|
<app-form-section class="col-12" [tocentry]="sectionEntry" [path]="z+1"
|
||||||
|
[pathName]="'pages.'+z+'.sections.'+i" [datasetProfileId]="datasetProfileId"
|
||||||
|
[linkToScroll]="linkToScroll"></app-form-section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</mat-accordion>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -44,7 +44,7 @@ export class DatasetDescriptionComponent extends BaseComponent implements OnInit
|
||||||
// this.formChanged.emit(val);
|
// this.formChanged.emit(val);
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
this.tocentries = this.getTocEntries();
|
this.tocentries = this.getTocEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
<div *ngFor="let entry of tocentries; index as idx">
|
||||||
|
<!-- check if is visible -->
|
||||||
|
<ng-container *ngIf="visibilityRulesService.checkElementVisibility(entry.id)">
|
||||||
|
|
||||||
|
<!-- Is fieldset and has no visible inputs -->
|
||||||
|
<ng-container *ngIf="!(entry.type === tocEntryTypeEnum.FieldSet && !visibilityRulesService.scanIfChildsOfCompositeFieldHasVisibleItems(entry.form))">
|
||||||
|
|
||||||
|
<span class="table-entry"
|
||||||
|
(click)="toggleExpand(idx);navigateToFieldSet(entry, $event); onEntrySelected(entry)"
|
||||||
|
[ngStyle]="calculateStyle(entry)"
|
||||||
|
[ngClass]="calculateClass(entry)"
|
||||||
|
>
|
||||||
|
{{entry.numbering}}. {{entry.label}}
|
||||||
|
<!-- <ng-container *ngIf="entry.subEntries && entry.subEntries.length && !expandChildren[idx]">
|
||||||
|
<small>
|
||||||
|
({{entry.subEntries.length}})
|
||||||
|
</small>
|
||||||
|
|
||||||
|
</ng-container> -->
|
||||||
|
</span>
|
||||||
|
<!-- <div class="table-entry-container">
|
||||||
|
</div> -->
|
||||||
|
<div class="internal-table">
|
||||||
|
<table-of-contents-internal
|
||||||
|
[tocentries]="entry.subEntries"
|
||||||
|
*ngIf="entry.subEntries && entry.subEntries.length && expandChildren[idx]"
|
||||||
|
(entrySelected)="onEntrySelected($event)"
|
||||||
|
[selected]="selected">
|
||||||
|
|
||||||
|
</table-of-contents-internal>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
.internal-table{
|
||||||
|
margin-left: 1.2em;
|
||||||
|
// width: inherit;
|
||||||
|
}
|
||||||
|
// .table-entry-container{
|
||||||
|
// // overflow: hidden;
|
||||||
|
// // width: inherit;
|
||||||
|
// }
|
||||||
|
.table-entry{
|
||||||
|
cursor: pointer;
|
||||||
|
// display: block;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
// overflow: hidden;
|
||||||
|
|
||||||
|
color: rgba(0, 0, 0, 0.54);
|
||||||
|
transition: color 100ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-entry:hover{
|
||||||
|
background-color: #ececec;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
.selected {
|
||||||
|
color: #212121 !important;
|
||||||
|
font-weight: 700 !important;
|
||||||
|
opacity: 1 !important;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
import { DOCUMENT } from '@angular/common';
|
||||||
|
import { Component, EventEmitter, Inject, OnInit, Output, Input } from '@angular/core';
|
||||||
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
|
import { interval, Subject, Subscription } from 'rxjs';
|
||||||
|
import { distinctUntilChanged } from 'rxjs/operators';
|
||||||
|
import { type } from 'os';
|
||||||
|
import { SimpleChanges } from '@angular/core';
|
||||||
|
import { ToCEntry, ToCEntryType } from '../../dataset-description.component';
|
||||||
|
import { VisibilityRulesService } from '../../visibility-rules/visibility-rules.service';
|
||||||
|
import { Rule } from '@app/core/model/dataset-profile-definition/rule';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'table-of-contents-internal',
|
||||||
|
styleUrls: ['./table-of-contents-internal.scss'],
|
||||||
|
templateUrl: './table-of-contents-internal.html'
|
||||||
|
})
|
||||||
|
export class TableOfContentsInternal implements OnInit {
|
||||||
|
|
||||||
|
@Input() tocentries: ToCEntry[] = null;
|
||||||
|
@Input() selected: ToCEntry = null;
|
||||||
|
// @Input() visibilityRules:Rule[] = [];
|
||||||
|
@Output() entrySelected = new EventEmitter<ToCEntry>();
|
||||||
|
|
||||||
|
expandChildren:boolean[];
|
||||||
|
tocEntryTypeEnum = ToCEntryType;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(public visibilityRulesService: VisibilityRulesService){
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
ngOnInit(): void {
|
||||||
|
// console.log('component created');
|
||||||
|
if(this.tocentries){
|
||||||
|
this.expandChildren = this.tocentries.map(()=>false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
// if (!this.isActive && this.links && this.links.length > 0) {
|
||||||
|
// this.links.forEach(link => {
|
||||||
|
// link.selected = false;
|
||||||
|
// })
|
||||||
|
// this.links[0].selected = true;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleExpand(index){
|
||||||
|
this.expandChildren[index] = !this.expandChildren[index];
|
||||||
|
// console.log(this.expandChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToFieldSet(entry:ToCEntry, event){
|
||||||
|
if(entry.type === ToCEntryType.FieldSet){
|
||||||
|
|
||||||
|
const fieldSetId = entry.id;
|
||||||
|
const element = document.getElementById(fieldSetId);
|
||||||
|
if(element){
|
||||||
|
element.scrollIntoView({behavior:'smooth'});
|
||||||
|
// event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onEntrySelected(entry:ToCEntry){
|
||||||
|
this.entrySelected.emit(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
calculateStyle(entry: ToCEntry){
|
||||||
|
const style = {};
|
||||||
|
style['font-size'] = entry.type ===this.tocEntryTypeEnum.FieldSet? '.9em': '1em';
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateClass(entry:ToCEntry){
|
||||||
|
|
||||||
|
if(this.selected && entry.id === this.selected.id){
|
||||||
|
return{'selected': true};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,3 +9,30 @@
|
||||||
<!-- </nav> -->
|
<!-- </nav> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<ng-container *ngIf="tocentries">
|
||||||
|
|
||||||
|
<div class="internal-table-outer col-12">
|
||||||
|
<table-of-contents-internal [tocentries]="tocentries"
|
||||||
|
(entrySelected)="onToCentrySelected($event)"
|
||||||
|
[selected]="tocentrySelected"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
</table-of-contents-internal>
|
||||||
|
</div>
|
||||||
|
</ng-container> -->
|
||||||
|
|
||||||
|
<div *ngIf="tocentries" class="docs-toc-container">
|
||||||
|
|
||||||
|
<div class="scroll-container col-12">
|
||||||
|
<table-of-contents-internal [tocentries]="tocentries"
|
||||||
|
(entrySelected)="onToCentrySelected($event)"
|
||||||
|
[selected]="tocentrySelected"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
</table-of-contents-internal>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -2,11 +2,14 @@ import {CommonModule} from '@angular/common';
|
||||||
import {NgModule} from '@angular/core';
|
import {NgModule} from '@angular/core';
|
||||||
import {TableOfContents} from './table-of-contents';
|
import {TableOfContents} from './table-of-contents';
|
||||||
import {RouterModule} from '@angular/router';
|
import {RouterModule} from '@angular/router';
|
||||||
|
import { TableOfContentsInternal } from './table-of-contents-internal/table-of-contents-internal';
|
||||||
|
import { VisibilityRulesService } from '../visibility-rules/visibility-rules.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [CommonModule, RouterModule],
|
imports: [CommonModule, RouterModule],
|
||||||
declarations: [TableOfContents],
|
declarations: [TableOfContents, TableOfContentsInternal],
|
||||||
exports: [TableOfContents],
|
exports: [TableOfContents],
|
||||||
entryComponents: [TableOfContents],
|
entryComponents: [TableOfContents],
|
||||||
|
providers:[VisibilityRulesService]
|
||||||
})
|
})
|
||||||
export class TableOfContentsModule { }
|
export class TableOfContentsModule { }
|
||||||
|
|
|
@ -68,3 +68,8 @@ span {
|
||||||
.docs-level-h5 {
|
.docs-level-h5 {
|
||||||
margin-left: 24px;
|
margin-left: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// .internal-table-outer{
|
||||||
|
// padding-left: 1.1em;
|
||||||
|
// width: 100%;
|
||||||
|
// }
|
|
@ -5,6 +5,10 @@ import { interval, Subject, Subscription } from 'rxjs';
|
||||||
import { distinctUntilChanged } from 'rxjs/operators';
|
import { distinctUntilChanged } from 'rxjs/operators';
|
||||||
import { type } from 'os';
|
import { type } from 'os';
|
||||||
import { SimpleChanges } from '@angular/core';
|
import { SimpleChanges } from '@angular/core';
|
||||||
|
import { ToCEntry, ToCEntryType } from '../dataset-description.component';
|
||||||
|
import { FormArray, FormGroup } from '@angular/forms';
|
||||||
|
import { VisibilityRulesService } from '../visibility-rules/visibility-rules.service';
|
||||||
|
import { Rule } from '@app/core/model/dataset-profile-definition/rule';
|
||||||
|
|
||||||
export interface Link {
|
export interface Link {
|
||||||
/* id of the section*/
|
/* id of the section*/
|
||||||
|
@ -39,72 +43,99 @@ export class TableOfContents extends BaseComponent implements OnInit {
|
||||||
linksSubject: Subject<HTMLElement[]> = new Subject<HTMLElement[]>();
|
linksSubject: Subject<HTMLElement[]> = new Subject<HTMLElement[]>();
|
||||||
|
|
||||||
@Input() isActive: boolean;
|
@Input() isActive: boolean;
|
||||||
|
|
||||||
|
tocentries: ToCEntry[] = null;
|
||||||
|
// visibilityRules:Rule[] = [];
|
||||||
|
@Input() visibilityRules:Rule[] = [];
|
||||||
|
|
||||||
|
private _tocentrySelected:ToCEntry = null;
|
||||||
|
get tocentrySelected(){
|
||||||
|
|
||||||
|
return this.hasFocus?this._tocentrySelected: null;
|
||||||
|
}
|
||||||
|
set tocentrySelected(value){
|
||||||
|
this._tocentrySelected = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input() formGroup: FormGroup;
|
||||||
|
@Input() hasFocus: boolean = false;
|
||||||
show: boolean = false;
|
show: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DOCUMENT) private _document: Document) {
|
@Inject(DOCUMENT) private _document: Document,
|
||||||
|
public visibilityRulesService: VisibilityRulesService
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
//emit value every 500ms
|
|
||||||
const source = interval(500);
|
if(this.formGroup){
|
||||||
this.subscription = source.subscribe(val => {
|
this.tocentries = this.getTocEntries(this.formGroup.get('datasetProfileDefinition'));
|
||||||
const headers = Array.from(this._document.querySelectorAll(this.headerSelectors)) as HTMLElement[];
|
const fg = this.formGroup.get('datasetProfileDefinition');
|
||||||
this.linksSubject.next(headers);
|
this.visibilityRulesService.buildVisibilityRules(this.visibilityRules, fg);
|
||||||
});
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
//emit value every 500ms
|
||||||
|
const source = interval(500);
|
||||||
|
this.subscription = source.subscribe(val => {
|
||||||
|
const headers = Array.from(this._document.querySelectorAll(this.headerSelectors)) as HTMLElement[];
|
||||||
|
this.linksSubject.next(headers);
|
||||||
|
});
|
||||||
|
|
||||||
if (!this.links || this.links.length === 0) {
|
if (!this.links || this.links.length === 0) {
|
||||||
this.linksSubject.asObservable()
|
this.linksSubject.asObservable()
|
||||||
.pipe(distinctUntilChanged((p: HTMLElement[], q: HTMLElement[]) => JSON.stringify(p) == JSON.stringify(q)))
|
.pipe(distinctUntilChanged((p: HTMLElement[], q: HTMLElement[]) => JSON.stringify(p) == JSON.stringify(q)))
|
||||||
.subscribe(headers => {
|
.subscribe(headers => {
|
||||||
const links: Array<Link> = [];
|
const links: Array<Link> = [];
|
||||||
|
|
||||||
if (headers.length) {
|
if (headers.length) {
|
||||||
let page;
|
let page;
|
||||||
let section;
|
let section;
|
||||||
let show
|
let show
|
||||||
for (const header of headers) {
|
for (const header of headers) {
|
||||||
let name;
|
let name;
|
||||||
let id;
|
let id;
|
||||||
if (header.classList.contains('toc-page-header')) { // deprecated after removing stepper
|
if (header.classList.contains('toc-page-header')) { // deprecated after removing stepper
|
||||||
name = header.innerText.trim().replace(/^link/, '');
|
name = header.innerText.trim().replace(/^link/, '');
|
||||||
id = header.id;
|
id = header.id;
|
||||||
page = header.id.split('_')[1];
|
page = header.id.split('_')[1];
|
||||||
section = undefined;
|
section = undefined;
|
||||||
show = true;
|
show = true;
|
||||||
} else if (header.classList.contains('toc-section-header')) {
|
} else if (header.classList.contains('toc-section-header')) {
|
||||||
name = header.childNodes[0].childNodes[0].childNodes[0].childNodes[0].childNodes[0].nodeValue.trim().replace(/^link/, '');
|
name = header.childNodes[0].childNodes[0].childNodes[0].childNodes[0].childNodes[0].nodeValue.trim().replace(/^link/, '');
|
||||||
id = header.id;
|
id = header.id;
|
||||||
page = header.id.split('.')[1];
|
page = header.id.split('.')[1];
|
||||||
section = header.id;
|
section = header.id;
|
||||||
if (header.id.split('.')[4]) { show = false; }
|
if (header.id.split('.')[4]) { show = false; }
|
||||||
else { show = true; }
|
else { show = true; }
|
||||||
} else if (header.classList.contains('toc-compositeField-header')) {
|
} else if (header.classList.contains('toc-compositeField-header')) {
|
||||||
name = (header.childNodes[0]).nodeValue.trim().replace(/^link/, '');
|
name = (header.childNodes[0]).nodeValue.trim().replace(/^link/, '');
|
||||||
id = header.id;
|
id = header.id;
|
||||||
// id = header.parentElement.parentElement.parentElement.id;
|
// id = header.parentElement.parentElement.parentElement.id;
|
||||||
show = false;
|
show = false;
|
||||||
|
}
|
||||||
|
const { top } = header.getBoundingClientRect();
|
||||||
|
links.push({
|
||||||
|
name,
|
||||||
|
id,
|
||||||
|
type: header.tagName.toLowerCase(),
|
||||||
|
top: top,
|
||||||
|
active: false,
|
||||||
|
page: page,
|
||||||
|
section: section,
|
||||||
|
show: show,
|
||||||
|
selected: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const { top } = header.getBoundingClientRect();
|
|
||||||
links.push({
|
|
||||||
name,
|
|
||||||
id,
|
|
||||||
type: header.tagName.toLowerCase(),
|
|
||||||
top: top,
|
|
||||||
active: false,
|
|
||||||
page: page,
|
|
||||||
section: section,
|
|
||||||
show: show,
|
|
||||||
selected: false
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
this.links = links;
|
||||||
this.links = links;
|
// Initialize selected for button next on dataset wizard component editor
|
||||||
// Initialize selected for button next on dataset wizard component editor
|
this.links.length > 0 ? this.links[0].selected = true : null;
|
||||||
this.links.length > 0 ? this.links[0].selected = true : null;
|
})
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -158,6 +189,125 @@ export class TableOfContents extends BaseComponent implements OnInit {
|
||||||
// return +link.id.split("_", 2)[1];
|
// return +link.id.split("_", 2)[1];
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
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(form): ToCEntry[] {
|
||||||
|
if (form == null) { return []; }
|
||||||
|
const result: ToCEntry[] = [];
|
||||||
|
|
||||||
|
//build parent pages
|
||||||
|
(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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onToCentrySelected(entry: ToCEntry){
|
||||||
|
this.tocentrySelected = entry;
|
||||||
|
// console.log('entry selected', entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinkToScroll {
|
export interface LinkToScroll {
|
||||||
|
|
Loading…
Reference in New Issue