Dataset Profile editor. Drag and drop navigation table of contents.
This commit is contained in:
parent
da7f91df96
commit
081995e243
|
@ -1,5 +1,5 @@
|
||||||
import { Component, Input, OnChanges, OnInit } from '@angular/core';
|
import { Component, Input, OnChanges, OnInit } from '@angular/core';
|
||||||
import { FormArray, FormControl, FormGroup } from '@angular/forms';
|
import { FormArray, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
|
||||||
import { FieldEditorModel } from '../../../admin/field-editor-model';
|
import { FieldEditorModel } from '../../../admin/field-editor-model';
|
||||||
import { Guid } from '@common/types/guid';
|
import { Guid } from '@common/types/guid';
|
||||||
import { RuleEditorModel } from '../../../admin/rule-editor-model';
|
import { RuleEditorModel } from '../../../admin/rule-editor-model';
|
||||||
|
@ -184,6 +184,8 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
field.ordinal = (this.form.get('fields') as FormArray).length;
|
field.ordinal = (this.form.get('fields') as FormArray).length;
|
||||||
|
|
||||||
const fieldForm = field.buildForm();
|
const fieldForm = field.buildForm();
|
||||||
|
fieldForm.setValidators(this.customFieldValidator());
|
||||||
|
// fieldForm.get('viewStyle').get('renderStyle').setValidators(Validators.required);
|
||||||
|
|
||||||
(<FormArray>this.form.get('fields')).push(fieldForm);
|
(<FormArray>this.form.get('fields')).push(fieldForm);
|
||||||
this.setTargetField(fieldForm);
|
this.setTargetField(fieldForm);
|
||||||
|
@ -329,6 +331,8 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
field.ordinal = (this.form.get('fields') as FormArray).length;
|
field.ordinal = (this.form.get('fields') as FormArray).length;
|
||||||
|
|
||||||
const fieldForm = field.buildForm();
|
const fieldForm = field.buildForm();
|
||||||
|
fieldForm.setValidators(this.customFieldValidator());
|
||||||
|
// fieldForm.get('viewStyle').get('renderStyle').setValidators(Validators.required);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -421,5 +425,51 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private customFieldValidator(): ValidatorFn{
|
||||||
|
return (control):ValidationErrors | null=>{
|
||||||
|
DatasetProfileFieldViewStyle
|
||||||
|
switch(control.get('viewStyle').get('renderStyle').value){
|
||||||
|
|
||||||
|
case DatasetProfileFieldViewStyle.TextArea:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.BooleanDecision:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.ComboBox:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.CheckBox:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.FreeText:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.RadioBox:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.DatePicker:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.InternalDmpEntities:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.ExternalDatasets:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.DataRepositories:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Registries:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Services:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Tags:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Researchers:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Organizations:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.DatasetIdentifier:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Currency:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Validation:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return {inputTypeNotValid: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,9 +68,10 @@
|
||||||
</mat-select> -->
|
</mat-select> -->
|
||||||
|
|
||||||
<!-- NEW VERSION -->
|
<!-- NEW VERSION -->
|
||||||
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VIEW-STYLE' | translate}}" [(value)]="viewType" (selectionChange)="onInputTypeChange()"
|
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VIEW-STYLE' | translate}}" [(ngModel)]="viewType" (selectionChange)="onInputTypeChange()"
|
||||||
[disabled]="viewOnly"
|
[disabled]="viewOnly"
|
||||||
required>
|
required
|
||||||
|
>
|
||||||
<mat-option [value]="viewTypeEnum.TextArea">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.TextArea)}}</mat-option>
|
<mat-option [value]="viewTypeEnum.TextArea">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.TextArea)}}</mat-option>
|
||||||
<mat-option [value]="viewTypeEnum.FreeText">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.FreeText)}}</mat-option>
|
<mat-option [value]="viewTypeEnum.FreeText">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.FreeText)}}</mat-option>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
@ -107,6 +108,8 @@
|
||||||
|
|
||||||
</mat-select>
|
</mat-select>
|
||||||
<mat-error *ngIf="this.form.get('viewStyle').get('renderStyle').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
<mat-error *ngIf="this.form.get('viewStyle').get('renderStyle').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
<mat-error *ngIf="this.form.hasError('inputTypeNotValid')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<!-- Combo Box -->
|
<!-- Combo Box -->
|
||||||
|
@ -210,3 +213,4 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
{{form.touched|json}}
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
|
||||||
import { FormArray, FormControl, FormGroup } from '@angular/forms';
|
import { AbstractControl, AbstractControlOptions, FormArray, FormControl, FormGroup, FormGroupDirective, NgForm } from '@angular/forms';
|
||||||
import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style';
|
import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style';
|
||||||
import { ValidationType } from '@app/core/common/enum/validation-type';
|
import { ValidationType } from '@app/core/common/enum/validation-type';
|
||||||
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
|
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
|
||||||
|
@ -34,7 +34,7 @@ import { AutoCompleteFieldDataEditorModel } from '../../../admin/field-data/auto
|
||||||
import { DatasetsAutoCompleteFieldDataEditorModel } from '../../../admin/field-data/datasets-autocomplete-field-data-editor-mode';
|
import { DatasetsAutoCompleteFieldDataEditorModel } from '../../../admin/field-data/datasets-autocomplete-field-data-editor-mode';
|
||||||
import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profile-combo-box-type';
|
import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profile-combo-box-type';
|
||||||
import { Guid } from '@common/types/guid';
|
import { Guid } from '@common/types/guid';
|
||||||
import { MatSlideToggleChange } from '@angular/material';
|
import { ErrorStateMatcher, MatSlideToggleChange } from '@angular/material';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-dataset-profile-editor-field-component',
|
selector: 'app-dataset-profile-editor-field-component',
|
||||||
|
@ -501,4 +501,5 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
|
||||||
onDelete(){
|
onDelete(){
|
||||||
this.delete.emit();
|
this.delete.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -46,7 +46,8 @@
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
||||||
<ng-container *ngIf="stepper.selectedIndex === (steps.length-1)">
|
<ng-container *ngIf="false">
|
||||||
|
<!-- <ng-container *ngIf="stepper.selectedIndex === (steps.length-1)"> -->
|
||||||
<ng-container *ngIf="!viewOnly">
|
<ng-container *ngIf="!viewOnly">
|
||||||
|
|
||||||
<button mat-button class="navigate-btn ml-2"
|
<button mat-button class="navigate-btn ml-2"
|
||||||
|
@ -350,11 +351,17 @@
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- <div class="row">
|
<div class="row">
|
||||||
<button (click)="printForm()">
|
<button (click)="printForm()">
|
||||||
console form
|
console form
|
||||||
</button>
|
</button>
|
||||||
</div> -->
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<button (click)="printMyErrors()">
|
||||||
|
print errors
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<!-- <div class="row">
|
<!-- <div class="row">
|
||||||
<button (click)="foo()">foo</button>
|
<button (click)="foo()">foo</button>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import { of as observableOf, Observable } from 'rxjs';
|
import { of as observableOf, Observable } from 'rxjs';
|
||||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||||
import { AfterViewInit, Component, OnChanges, OnInit, QueryList, SimpleChanges, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, OnChanges, OnInit, QueryList, SimpleChanges, ViewChild } from '@angular/core';
|
||||||
import { Form, FormArray, FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
import { AbstractControl, Form, FormArray, FormBuilder, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatHorizontalStepper, MatStep } from '@angular/material/stepper';
|
import { MatHorizontalStepper, MatStep } from '@angular/material/stepper';
|
||||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
||||||
|
@ -38,7 +38,7 @@ import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/vi
|
||||||
import { CdkStep, StepperSelectionEvent } from '@angular/cdk/stepper';
|
import { CdkStep, StepperSelectionEvent } from '@angular/cdk/stepper';
|
||||||
import { DatasetDescriptionCompositeFieldEditorModel, DatasetDescriptionFieldEditorModel, DatasetDescriptionFormEditorModel, DatasetDescriptionPageEditorModel, DatasetDescriptionSectionEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model';
|
import { DatasetDescriptionCompositeFieldEditorModel, DatasetDescriptionFieldEditorModel, DatasetDescriptionFormEditorModel, DatasetDescriptionPageEditorModel, DatasetDescriptionSectionEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model';
|
||||||
import { Rule } from '@app/core/model/dataset-profile-definition/rule';
|
import { Rule } from '@app/core/model/dataset-profile-definition/rule';
|
||||||
|
import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style';
|
||||||
const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json');
|
const skipDisable: any[] = require('../../../../../assets/resources/skipDisable.json');
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -532,8 +532,6 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
if(this.selectedTocEntry){
|
if(this.selectedTocEntry){
|
||||||
this.selectedTocEntry = this._findTocEntryById(this.selectedTocEntry.id, this.toCEntries);
|
this.selectedTocEntry = this._findTocEntryById(this.selectedTocEntry.id, this.toCEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.updateOrdinals(this.toCEntries);
|
this.updateOrdinals(this.toCEntries);
|
||||||
return this.toCEntries;
|
return this.toCEntries;
|
||||||
}
|
}
|
||||||
|
@ -551,6 +549,22 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//sort tocentries based on their ordinality
|
||||||
|
private _sortToCentries(entries: ToCEntry[]){
|
||||||
|
if(!entries || !entries.length) return;
|
||||||
|
entries.sort(this._compareOrdinals);
|
||||||
|
entries.forEach(e=>{
|
||||||
|
this._sortToCentries(e.subEntries)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private _compareOrdinals(a, b){
|
||||||
|
|
||||||
|
const aValue = a.form.get('ordinal').value as number;
|
||||||
|
const bValue = b.form.get('ordinal').value as number;
|
||||||
|
|
||||||
|
// if(!aValue || !bValue) return 0;
|
||||||
|
return aValue - bValue;
|
||||||
|
}
|
||||||
|
|
||||||
toCEntries:ToCEntry[];
|
toCEntries:ToCEntry[];
|
||||||
|
|
||||||
|
@ -601,6 +615,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
pageToAdd.subEntries.push(item);
|
pageToAdd.subEntries.push(item);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
this._sortToCentries(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,9 +693,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tocEntryFound) return tocEntryFound;
|
return tocEntryFound? tocEntryFound: null;
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
addNewEntry(tce: Foo) {
|
addNewEntry(tce: Foo) {
|
||||||
|
|
||||||
|
@ -688,81 +701,83 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
|
|
||||||
//define entry type
|
//define entry type
|
||||||
switch (tce.childType) {
|
switch (tce.childType) {
|
||||||
case ToCEntryType.Page: //CALLED FROM PAGE
|
case ToCEntryType.Page:
|
||||||
//create section
|
|
||||||
// this.addPage();
|
|
||||||
// this.displayItem(child);
|
|
||||||
|
|
||||||
|
|
||||||
//ceate page editor model and give ordinal
|
|
||||||
const page: PageEditorModel = new PageEditorModel(this.dataModel.pages.length);
|
const page: PageEditorModel = new PageEditorModel(this.dataModel.pages.length);
|
||||||
this.dataModel.pages.push(page);
|
const pageForm = page.buildForm();
|
||||||
(<FormArray>this.form.get('pages')).push(page.buildForm());
|
// this.dataModel.pages.push(page);
|
||||||
|
|
||||||
|
|
||||||
//make new entry selected
|
|
||||||
const pagesArray = (this.form.get('pages') as FormArray);
|
const pagesArray = (this.form.get('pages') as FormArray);
|
||||||
const addedEntry = pagesArray.at(pagesArray.length-1) as FormGroup;
|
pagesArray.push(pageForm);
|
||||||
|
|
||||||
this.selectedTocEntry = this._findTocEntryById(addedEntry.get('id').value, this.getTocEntries());
|
this.refreshToCEntries();
|
||||||
|
this.selectedTocEntry = this._findTocEntryById(pageForm.get('id').value, this.toCEntries);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ToCEntryType.Section: //adding a section
|
case ToCEntryType.Section:
|
||||||
|
|
||||||
const section: SectionEditorModel = new SectionEditorModel();
|
const section: SectionEditorModel = new SectionEditorModel();
|
||||||
//give id
|
|
||||||
section.id = Guid.create().toString();
|
section.id = Guid.create().toString();
|
||||||
let sectionsArray:FormArray;
|
let sectionsArray:FormArray;
|
||||||
|
|
||||||
//TODO CHECK FOR FORM.ROOT ERROR
|
if (parent.type === ToCEntryType.Page) {//FIRST LEVEL SECTION
|
||||||
if (parent.type === ToCEntryType.Page) {
|
|
||||||
//FIRST LEVEL SECTION
|
|
||||||
|
|
||||||
//give ordinal and link to parent
|
|
||||||
section.page = parent.id;
|
|
||||||
section.ordinal = (this.form.get('sections') as FormArray).length;
|
|
||||||
(<FormArray>this.form.get('sections')).push(section.buildForm());
|
|
||||||
|
|
||||||
sectionsArray = this.form.get('sections') as FormArray;
|
sectionsArray = this.form.get('sections') as FormArray;
|
||||||
} else if( parent.type == ToCEntryType.Section) { //subsection
|
|
||||||
|
section.page = parent.id;
|
||||||
|
section.ordinal = sectionsArray.length;
|
||||||
|
sectionsArray.push(section.buildForm());
|
||||||
|
|
||||||
|
} else if( parent.type == ToCEntryType.Section) { //SUBSECTION OF SECTION
|
||||||
|
sectionsArray = parent.form.get('sections') as FormArray;
|
||||||
|
|
||||||
//adding page parent MAYBE NOT NEEDED
|
//adding page parent MAYBE NOT NEEDED
|
||||||
section.page = parent.form.get('page').value;
|
section.page = parent.form.get('page').value;
|
||||||
//MAYBE NOT NEEDED
|
//MAYBE NOT NEEDED
|
||||||
section.ordinal = (parent.form.get('sections') as FormArray).length;
|
section.ordinal = sectionsArray.length;
|
||||||
(<FormArray>parent.form.get('sections')).push(section.buildForm());
|
sectionsArray.push(section.buildForm());
|
||||||
// (child.form.parent as FormArray).push(section.buildForm());
|
// (child.form.parent as FormArray).push(section.buildForm());
|
||||||
|
|
||||||
sectionsArray = parent.form.get('sections') as FormArray;
|
|
||||||
}else{
|
}else{
|
||||||
console.error('BUg found');
|
console.error('Section can only bee child of a page or another section');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const sectionAdded = sectionsArray.at(sectionsArray.length -1) as FormGroup;
|
const sectionAdded = sectionsArray.at(sectionsArray.length -1) as FormGroup;
|
||||||
|
|
||||||
this.selectedTocEntry = this._findTocEntryById(sectionAdded.get('id').value, this.getTocEntries());
|
|
||||||
|
this.refreshToCEntries();
|
||||||
|
this.selectedTocEntry = this._findTocEntryById(sectionAdded.get('id').value, this.toCEntries);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ToCEntryType.FieldSet:
|
case ToCEntryType.FieldSet:
|
||||||
const fieldSet: FieldSetEditorModel = new FieldSetEditorModel();
|
|
||||||
|
|
||||||
//create one field form fieldset
|
//create one field form fieldset
|
||||||
const field: FieldEditorModel = new FieldEditorModel(); //to ask
|
const field: FieldEditorModel = new FieldEditorModel();
|
||||||
field.id = Guid.create().toString();
|
field.id = Guid.create().toString();
|
||||||
field.ordinal = 0;//first filed in the fields list
|
field.ordinal = 0;//first filed in the fields list
|
||||||
fieldSet.fields.push(field);
|
const fieldForm = field.buildForm();
|
||||||
|
fieldForm.setValidators(this.customFieldValidator());
|
||||||
|
// fieldForm.get('viewStyle').get('renderStyle').setValidators(Validators.required);
|
||||||
|
|
||||||
|
// fieldSet.fields.push(field);
|
||||||
// field.ordinal = fieldSet.fields.length-1;
|
// field.ordinal = fieldSet.fields.length-1;
|
||||||
|
|
||||||
|
const fieldSetsArray = parent.form.get('fieldSets') as FormArray
|
||||||
|
|
||||||
//give fieldset id and ordinal
|
//give fieldset id and ordinal
|
||||||
fieldSet.id = Guid.create().toString();
|
const fieldSet: FieldSetEditorModel = new FieldSetEditorModel();
|
||||||
fieldSet.ordinal = (parent.form.get('fieldSets') as FormArray).length;
|
const fieldSetId = Guid.create().toString();
|
||||||
|
fieldSet.id = fieldSetId;
|
||||||
|
fieldSet.ordinal = fieldSetsArray.length;
|
||||||
|
const fieldsetForm = fieldSet.buildForm();
|
||||||
|
|
||||||
(<FormArray>parent.form.get('fieldSets')).push(fieldSet.buildForm());
|
|
||||||
|
|
||||||
const parentArray = parent.form.get('fieldSets') as FormArray;
|
|
||||||
const addedFieldSet = parentArray.at(parentArray.length - 1);
|
|
||||||
|
|
||||||
this.selectedTocEntry = this._findTocEntryById(addedFieldSet.get('id').value, this.getTocEntries());
|
(fieldsetForm.get('fields') as FormArray).push(fieldForm);
|
||||||
|
fieldSetsArray.push(fieldsetForm);
|
||||||
|
|
||||||
|
this.refreshToCEntries();
|
||||||
|
this.selectedTocEntry = this._findTocEntryById(fieldSetId, this.toCEntries);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -770,10 +785,57 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.refreshToCEntries();
|
// this.refreshToCEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private customFieldValidator(): ValidatorFn{
|
||||||
|
return (control):ValidationErrors | null=>{
|
||||||
|
DatasetProfileFieldViewStyle
|
||||||
|
switch(control.get('viewStyle').get('renderStyle').value){
|
||||||
|
|
||||||
|
case DatasetProfileFieldViewStyle.TextArea:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.BooleanDecision:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.ComboBox:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.CheckBox:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.FreeText:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.RadioBox:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.DatePicker:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.InternalDmpEntities:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.ExternalDatasets:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.DataRepositories:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Registries:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Services:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Tags:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Researchers:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Organizations:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.DatasetIdentifier:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Currency:
|
||||||
|
return null;
|
||||||
|
case DatasetProfileFieldViewStyle.Validation:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return {inputTypeNotValid: true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
onRemoveEntry(tce: ToCEntry){
|
onRemoveEntry(tce: ToCEntry){
|
||||||
|
|
||||||
|
@ -1282,7 +1344,6 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
}
|
}
|
||||||
|
|
||||||
cloneFieldSet(fieldset: FormGroup){
|
cloneFieldSet(fieldset: FormGroup){
|
||||||
//TODO
|
|
||||||
const values = fieldset.getRawValue();
|
const values = fieldset.getRawValue();
|
||||||
const parentArray = fieldset.parent as FormArray;
|
const parentArray = fieldset.parent as FormArray;
|
||||||
|
|
||||||
|
@ -1332,4 +1393,124 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
|
||||||
this.checkFormValidation();
|
this.checkFormValidation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFormValidationErrors() {
|
||||||
|
Object.keys(this.form.controls).forEach(key => {
|
||||||
|
|
||||||
|
const controlErrors: ValidationErrors = this.form.get(key).errors;
|
||||||
|
if (controlErrors != null) {
|
||||||
|
Object.keys(controlErrors).forEach(keyError => {
|
||||||
|
console.log('Key control: ' + key + ', keyError: ' + keyError + ', err value: ', controlErrors[keyError]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(this.form.invalid){
|
||||||
|
console.log('this form is invalid!');
|
||||||
|
console.log(this.form.errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
printMyErrors(){
|
||||||
|
// this._printToCentriesErrrors(this.toCEntries);
|
||||||
|
this._getErrors(this.form);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private _printToCentriesErrrors(entries: ToCEntry[]){
|
||||||
|
|
||||||
|
if(!entries || !entries.length) return;
|
||||||
|
|
||||||
|
entries.forEach(e=>{
|
||||||
|
|
||||||
|
|
||||||
|
// if(e.form instanceof FormGroup) console.log('is Formgroup');
|
||||||
|
// if(e.form instanceof FormControl) console.log('is formcontrols');
|
||||||
|
// if(e.form instanceof FormArray) console.log('isForm array');
|
||||||
|
|
||||||
|
|
||||||
|
const form = e.form as FormGroup;
|
||||||
|
if(form.invalid){
|
||||||
|
const controls = form.controls;
|
||||||
|
const keys = Object.keys(controls);
|
||||||
|
keys.forEach(key=>{
|
||||||
|
const control = controls[key];
|
||||||
|
|
||||||
|
if(control.invalid){
|
||||||
|
console.log('control ', key, 'is invalid');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// console.log('keys,', keys);
|
||||||
|
|
||||||
|
|
||||||
|
this._printToCentriesErrrors(e.subEntries);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private _getErrors(aControl: AbstractControl){
|
||||||
|
|
||||||
|
if(aControl instanceof FormGroup) console.log('is Formgroup');
|
||||||
|
if(aControl instanceof FormControl)console.log( aControl.errors);
|
||||||
|
if(aControl instanceof FormArray) console.log('isForm array');
|
||||||
|
if(aControl.valid) return;
|
||||||
|
|
||||||
|
let controlType = 'control';
|
||||||
|
|
||||||
|
if(aControl instanceof FormGroup) controlType="fg"
|
||||||
|
if(aControl instanceof FormControl) controlType="fc";
|
||||||
|
if(aControl instanceof FormArray) controlType="fa";
|
||||||
|
|
||||||
|
|
||||||
|
//invalid
|
||||||
|
switch (controlType){
|
||||||
|
case 'fg':
|
||||||
|
|
||||||
|
const controls = (aControl as FormGroup).controls;
|
||||||
|
const keys = Object.keys(controls);
|
||||||
|
keys.forEach(key=>{
|
||||||
|
const control = controls[key];
|
||||||
|
// if(control.invalid){
|
||||||
|
this._getErrors(control);
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
case 'fc':
|
||||||
|
//form control print errors
|
||||||
|
console.log(aControl.errors);
|
||||||
|
break;
|
||||||
|
case 'fa':
|
||||||
|
const fa = (aControl as FormArray);
|
||||||
|
fa.controls.forEach(control=>{
|
||||||
|
this._getErrors(control);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// const controls = rootForm.controls;
|
||||||
|
// const keys = Object.keys(controls);
|
||||||
|
// keys.forEach(key=>{
|
||||||
|
// const control = controls[key];
|
||||||
|
|
||||||
|
|
||||||
|
// if(control.invalid){
|
||||||
|
// console.log('control ', key, 'is invalid');
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-auto d-flex align-items-center" >
|
<div class="col-auto d-flex align-items-center" >
|
||||||
<span class="badge-ball"
|
<span class="badge-ball"
|
||||||
*ngIf="!(!((parentLink?.subEntriesType == tocEntryType.FieldSet) && !selectedItemInLinks) || itemSelected?.id == parentLink.id)">
|
*ngIf="!(!((parentLink?.subEntriesType == tocEntryType.FieldSet) && !selectedItemInLinks) || itemSelected?.id == parentLink.id ||isDragging)">
|
||||||
{{parentLink.subEntries?.length}}
|
{{parentLink.subEntries?.length}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
@ -48,98 +48,108 @@
|
||||||
|
|
||||||
<!-- When item is not selected then show only the pages (first level) -->
|
<!-- When item is not selected then show only the pages (first level) -->
|
||||||
<!-- <ng-container *ngIf="tocEntryIsChildOf(itemSelected,parentLink) || (!itemSelected && parentLink?.subEntriesType == tocEntryType.Page)"> -->
|
<!-- <ng-container *ngIf="tocEntryIsChildOf(itemSelected,parentLink) || (!itemSelected && parentLink?.subEntriesType == tocEntryType.Page)"> -->
|
||||||
<div cdkDropList class="ml-2" [ngClass]="{'border-left-active':itemSelected?.id == parentLink?.id, 'pl-1':itemSelected?.id == parentLink?.id}"
|
<div dragula="TABLEDRAG" class="ml-2"
|
||||||
[hidden]="!((parentLink?.subEntriesType!= tocEntryType.FieldSet) || selectedItemInLinks || parentLink?.id === itemSelected?.id || dragHoveringOver)"
|
[ngClass]="{'border-left-active':itemSelected?.id == parentLink?.id, 'pl-1':itemSelected?.id == parentLink?.id, 'pb-4': isDragging && (parentLink?.type!= tocEntryType.FieldSet) && (parentLink?.id != draggingItemId) }"
|
||||||
(cdkDropListDropped)="drop($event)"
|
[hidden]="!((parentLink?.subEntriesType!= tocEntryType.FieldSet) || selectedItemInLinks || parentLink?.id === itemSelected?.id || dragHoveringOver ||isDragging)"
|
||||||
class="cdk-link-list"
|
class="cdk-link-list"
|
||||||
[cdkDropListSortingDisabled]="viewOnly"
|
|
||||||
[cdkDropListConnectedTo]="[]"
|
|
||||||
(cdkDropListEntered)="hoveroverEnter()"
|
|
||||||
(cdkDropListExited)="hoveroverLeft()"
|
|
||||||
(cdkDropListDropped)="hoveroverLeft()"
|
|
||||||
[id]="parentLink.id"
|
[id]="parentLink.id"
|
||||||
[cdkDropListData]="links"
|
[ngStyle]="{'border': overContainerId === parentLink?.id? '1px solid #129D99': '', 'min-height': ((!links?.length||(links.length ==1) ) && (parentLink?.type != tocEntryType.FieldSet) && (isDragging) && (draggingItemId != parentLink?.id)) ? '3em':'inherit'}"
|
||||||
>
|
>
|
||||||
|
<ng-container *ngIf="draggingItemId != parentLink?.id">
|
||||||
|
|
||||||
|
<div *ngFor="let link of links; last as isLast"
|
||||||
|
[ngClass]="{'mb-3': link.type === tocEntryType.Page}"
|
||||||
|
[id]="DRAGULA_ITEM_ID_PREFIX + link.id"
|
||||||
|
>
|
||||||
|
<div class="docs-link mt-0">
|
||||||
|
<!-- <div class="link-name"> -->
|
||||||
|
|
||||||
|
<!-- <div class="table-item row">
|
||||||
|
<div class="col link-info">
|
||||||
|
<span style="cursor: pointer;" [ngClass]="{'active': itemSelected?.id == link.id}" (click)="itemClicked(link)" >
|
||||||
|
{{link.numbering}} {{link.label? link.label : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="table-item-actions col-auto" *ngIf="!viewOnly">
|
||||||
|
<button class="mat-button" (click)="deleteEntry(link)"><mat-icon>delete</mat-icon></button>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
|
||||||
<div *ngFor="let link of links; last as isLast"
|
<!-- For dev purposes -->
|
||||||
[ngClass]="{'mb-3': link.type === tocEntryType.Page}"
|
<!-- <ng-container [ngSwitch]="link.type">
|
||||||
cdkDrag
|
<div *ngSwitchCase="tocEntryType.FieldSet">
|
||||||
[cdkDragStartDelay]="50"
|
<span style="background-color: yellow;"> Fieldset</span>
|
||||||
>
|
</div>
|
||||||
<div class="docs-link mt-0">
|
<div *ngSwitchCase="tocEntryType.Page">
|
||||||
<!-- <div class="link-name"> -->
|
<span style="background-color: lightblue;"> Page</span>
|
||||||
|
</div>
|
||||||
<!-- <div class="table-item row">
|
<div *ngSwitchCase="tocEntryType.Section">
|
||||||
<div class="col link-info">
|
<span style="background-color: lightgreen;"> Section</span>
|
||||||
<span style="cursor: pointer;" [ngClass]="{'active': itemSelected?.id == link.id}" (click)="itemClicked(link)" >
|
</div>
|
||||||
{{link.numbering}} {{link.label? link.label : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}}
|
</ng-container> -->
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="table-item-actions col-auto" *ngIf="!viewOnly">
|
|
||||||
<button class="mat-button" (click)="deleteEntry(link)"><mat-icon>delete</mat-icon></button>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
|
|
||||||
<!-- For dev purposes -->
|
|
||||||
<!-- <ng-container [ngSwitch]="link.type">
|
|
||||||
<div *ngSwitchCase="tocEntryType.FieldSet">
|
|
||||||
<span style="background-color: yellow;"> Fieldset</span>
|
|
||||||
</div>
|
|
||||||
<div *ngSwitchCase="tocEntryType.Page">
|
|
||||||
<span style="background-color: lightblue;"> Page</span>
|
|
||||||
</div>
|
|
||||||
<div *ngSwitchCase="tocEntryType.Section">
|
|
||||||
<span style="background-color: lightgreen;"> Section</span>
|
|
||||||
</div>
|
|
||||||
</ng-container> -->
|
|
||||||
<!-- </div> -->
|
|
||||||
<!-- <button cdkDragHandle>drab</button> -->
|
|
||||||
<div class="ml-3">
|
|
||||||
<app-dataset-profile-table-of-contents-internal-section
|
|
||||||
[links]="link.subEntries"
|
|
||||||
(itemClick)="itemClicked($event)"
|
|
||||||
(removeEntry)="deleteEntry($event)"
|
|
||||||
[parentLink]="link"
|
|
||||||
[itemSelected] = "itemSelected"
|
|
||||||
(createFooEntry)="createNewEntry($event)"
|
|
||||||
[viewOnly]="viewOnly"
|
|
||||||
(dataNeedsRefresh)="onDataNeedsRefresh()"
|
|
||||||
[dropListGroup]="dropListGroup"
|
|
||||||
[dragHoveringOver]="dragHoveringOver"
|
|
||||||
[dropListStruct]="dropListStruct"
|
|
||||||
[depth]="depth+1">
|
|
||||||
</app-dataset-profile-table-of-contents-internal-section>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- <div *ngIf="links && !viewOnly && !(parentLink?.subEntriesType == tocEntryType.Page) " > -->
|
|
||||||
<ng-container *ngIf="selectedItemInLinks && (link.type != tocEntryType.Page) && isLast && (!viewOnly) &&(link.type != tocEntryType.FieldSet)">
|
|
||||||
<button class="mat-button add-new-entry" style="padding-left: 0px;" (click)="createNewEntry({childType:link.type,parent:parentLink})">
|
|
||||||
<!-- <mat-icon>add</mat-icon> -->
|
|
||||||
<ng-container [ngSwitch]="link.type">
|
|
||||||
<ng-container *ngSwitchCase="tocEntryType.Section">
|
|
||||||
Subsection +
|
|
||||||
</ng-container>
|
|
||||||
<!-- <ng-container *ngSwitchCase="tocEntryType.Page">
|
|
||||||
Section
|
|
||||||
</ng-container> -->
|
|
||||||
<ng-container *ngSwitchCase="tocEntryType.FieldSet">
|
|
||||||
Field +
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
</ng-container>
|
|
||||||
</button>
|
|
||||||
<!-- <button (click)="showDroplists()">show droplist</button> -->
|
|
||||||
</ng-container>
|
|
||||||
<!-- </div> -->
|
<!-- </div> -->
|
||||||
</div>
|
<!-- <button cdkDragHandle>drab</button> -->
|
||||||
</div>
|
<div class="ml-3">
|
||||||
|
<app-dataset-profile-table-of-contents-internal-section
|
||||||
|
[links]="link.subEntries"
|
||||||
|
(itemClick)="itemClicked($event)"
|
||||||
|
(removeEntry)="deleteEntry($event)"
|
||||||
|
[parentLink]="link"
|
||||||
|
[itemSelected] = "itemSelected"
|
||||||
|
(createFooEntry)="createNewEntry($event)"
|
||||||
|
[viewOnly]="viewOnly"
|
||||||
|
(dataNeedsRefresh)="onDataNeedsRefresh()"
|
||||||
|
[dropListGroup]="dropListGroup"
|
||||||
|
[dragHoveringOver]="dragHoveringOver"
|
||||||
|
[dropListStruct]="dropListStruct"
|
||||||
|
[depth]="depth+1"
|
||||||
|
[DRAGULA_ITEM_ID_PREFIX]="DRAGULA_ITEM_ID_PREFIX"
|
||||||
|
[overContainerId]="overContainerId"
|
||||||
|
[isDragging]="isDragging"
|
||||||
|
[draggingItemId]="draggingItemId"
|
||||||
|
[parentRootId]="parentRootId">
|
||||||
|
</app-dataset-profile-table-of-contents-internal-section>
|
||||||
|
|
||||||
</div> <!-- END OF LOOP-->
|
|
||||||
|
|
||||||
|
<ng-container *ngIf="!isDragging">
|
||||||
|
|
||||||
|
<!-- <div *ngIf="links && !viewOnly && !(parentLink?.subEntriesType == tocEntryType.Page) " > -->
|
||||||
|
<ng-container *ngIf="selectedItemInLinks && (link.type != tocEntryType.Page) && isLast && (!viewOnly) &&(link.type != tocEntryType.FieldSet)">
|
||||||
|
<button class="mat-button add-new-entry" style="padding-left: 0px;" (click)="createNewEntry({childType:link.type,parent:parentLink})">
|
||||||
|
<!-- <mat-icon>add</mat-icon> -->
|
||||||
|
<ng-container [ngSwitch]="link.type">
|
||||||
|
<ng-container *ngSwitchCase="tocEntryType.Section">
|
||||||
|
Subsection +
|
||||||
|
</ng-container>
|
||||||
|
<!-- <ng-container *ngSwitchCase="tocEntryType.Page">
|
||||||
|
Section
|
||||||
|
</ng-container> -->
|
||||||
|
<ng-container *ngSwitchCase="tocEntryType.FieldSet">
|
||||||
|
Field +
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
</button>
|
||||||
|
<!-- <button (click)="showDroplists()">show droplist</button> -->
|
||||||
|
</ng-container>
|
||||||
|
<!-- </div> -->
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div> <!-- END OF LOOP-->
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<ng-container *ngIf="!isDragging">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- BUILD SUBENTRIES IF THEY DONT EXIST -- CURRENT ITEM DOES HAVE CHILDREN -->
|
<!-- BUILD SUBENTRIES IF THEY DONT EXIST -- CURRENT ITEM DOES HAVE CHILDREN -->
|
||||||
<div *ngIf="(!links && parentLink.type!= tocEntryType.FieldSet) && !viewOnly &&parentLink?.id == itemSelected?.id" class="docs-link mt-0">
|
<div *ngIf="(!links && parentLink.type!= tocEntryType.FieldSet) && !viewOnly &&parentLink?.id == itemSelected?.id" class="docs-link mt-0">
|
||||||
<div class="ml-3">
|
<div class="ml-3">
|
||||||
|
@ -181,14 +191,16 @@
|
||||||
</button>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div> -->
|
</div> -->
|
||||||
<!-- </ng-container> -->
|
<!-- </ng-container> -->
|
||||||
|
|
||||||
<!-- Only for the page -->
|
<!-- Only for the page -->
|
||||||
<div *ngIf="parentLink?.subEntriesType == tocEntryType.Page && !viewOnly">
|
<div *ngIf="parentLink?.subEntriesType == tocEntryType.Page && !viewOnly">
|
||||||
<button class="mat-button ml-3 mt-2" (click)="createNewEntry({childType:parentLink.subEntriesType,parent:parentLink})" style="padding-left:0px">
|
<button class="mat-button ml-3 mt-2" (click)="createNewEntry({childType:parentLink.subEntriesType,parent:parentLink})" style="padding-left:0px">
|
||||||
<!-- <mat-icon>add</mat-icon> -->
|
<!-- <mat-icon>add</mat-icon> -->
|
||||||
Section +
|
Section +
|
||||||
</button>
|
</button>
|
||||||
<!-- <button (click)="showDroplists()">show droplist</button>
|
<!-- <button (click)="showDroplists()">show droplist</button>
|
||||||
<button (click)="showStructs()">structs</button> -->
|
<button (click)="showStructs()">structs</button> -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
</ng-container>
|
|
@ -25,6 +25,11 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
|
||||||
|
|
||||||
@Input() parentLink: ToCEntry;
|
@Input() parentLink: ToCEntry;
|
||||||
@Input() itemSelected: ToCEntry;
|
@Input() itemSelected: ToCEntry;
|
||||||
|
@Input() DRAGULA_ITEM_ID_PREFIX;
|
||||||
|
@Input() overContainerId: string;
|
||||||
|
@Input() isDragging;
|
||||||
|
@Input() draggingItemId: string;
|
||||||
|
@Input() parentRootId: string;
|
||||||
|
|
||||||
@Input() viewOnly: boolean;
|
@Input() viewOnly: boolean;
|
||||||
// @Input() dropListGroup: Set<string> = new Set<string>();
|
// @Input() dropListGroup: Set<string> = new Set<string>();
|
||||||
|
@ -193,4 +198,35 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
|
||||||
onDataNeedsRefresh(){
|
onDataNeedsRefresh(){
|
||||||
this.dataNeedsRefresh.emit();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -9,11 +9,16 @@
|
||||||
<app-dataset-profile-table-of-contents-internal-section [links]="links" (itemClick)="itemClicked($event)"
|
<app-dataset-profile-table-of-contents-internal-section [links]="links" (itemClick)="itemClicked($event)"
|
||||||
(newEntry)="addNewEntry($event)" (removeEntry)="deleteEntry($event)"
|
(newEntry)="addNewEntry($event)" (removeEntry)="deleteEntry($event)"
|
||||||
(createFooEntry)="createNewEntry($event)"
|
(createFooEntry)="createNewEntry($event)"
|
||||||
[parentLink]="{ subEntriesType: tocEntryType.Page, subEntries : links , id: 'foo'}"
|
[parentLink]="{ subEntriesType: tocEntryType.Page, subEntries : links , id: ROOT_ID}"
|
||||||
[itemSelected]="itemSelected"
|
[itemSelected]="itemSelected"
|
||||||
[viewOnly]="viewOnly"
|
[viewOnly]="viewOnly"
|
||||||
(dataNeedsRefresh)="onDataNeedsRefresh()"
|
(dataNeedsRefresh)="onDataNeedsRefresh()"
|
||||||
[dropListGroup]="[]"
|
[dropListGroup]="[]"
|
||||||
|
[DRAGULA_ITEM_ID_PREFIX]="DRAGULA_ITEM_ID_PREFIX"
|
||||||
|
[overContainerId]="overcontainer"
|
||||||
|
[isDragging]="isDragging"
|
||||||
|
[draggingItemId]="draggingItemId"
|
||||||
|
[parentRootId]="ROOT_ID"
|
||||||
></app-dataset-profile-table-of-contents-internal-section>
|
></app-dataset-profile-table-of-contents-internal-section>
|
||||||
|
|
||||||
<!-- <span *ngFor="let link of links; let i = index" (click)="toggle(link); goToStep(link);" class="docs-link mt-0">
|
<!-- <span *ngFor="let link of links; let i = index" (click)="toggle(link); goToStep(link);" class="docs-link mt-0">
|
||||||
|
|
|
@ -6,6 +6,8 @@ import { distinctUntilChanged } from 'rxjs/operators';
|
||||||
import { type } from 'os';
|
import { type } from 'os';
|
||||||
import { SimpleChanges } from '@angular/core';
|
import { SimpleChanges } from '@angular/core';
|
||||||
import { Foo, ToCEntry, ToCEntryType } from './table-of-contents-entry';
|
import { Foo, ToCEntry, ToCEntryType } from './table-of-contents-entry';
|
||||||
|
import { DragulaService } from 'ng2-dragula';
|
||||||
|
import { FormArray } from '@angular/forms';
|
||||||
|
|
||||||
export interface Link {
|
export interface Link {
|
||||||
/* id of the section*/
|
/* id of the section*/
|
||||||
|
@ -54,15 +56,420 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
|
||||||
|
|
||||||
@Input() isActive: boolean;
|
@Input() isActive: boolean;
|
||||||
show: boolean = false;
|
show: boolean = false;
|
||||||
|
isDragging: boolean = false;
|
||||||
|
draggingItemId: string = null;
|
||||||
|
|
||||||
tocEntryType = ToCEntryType;
|
tocEntryType = ToCEntryType;
|
||||||
|
|
||||||
|
DRAGULA_ITEM_ID_PREFIX="table_item_id_";
|
||||||
|
ROOT_ID: string = "ROOT_ID";//no special meaning
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DOCUMENT) private _document: Document) {
|
@Inject(DOCUMENT) private _document: Document,
|
||||||
|
private dragulaService: DragulaService
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
|
||||||
|
if(this.dragulaService.find('TABLEDRAG')){
|
||||||
|
this.dragulaService.destroy('TABLEDRAG');
|
||||||
|
}
|
||||||
|
|
||||||
|
const dragula = this.dragulaService.createGroup('TABLEDRAG', {
|
||||||
|
invalid: (el,handle)=>{
|
||||||
|
// const elid = el.id;
|
||||||
|
// if(!el.id) return true;
|
||||||
|
|
||||||
|
// const elementId = (el.id as string).replace(this.DRAGULA_ITEM_ID_PREFIX,'');
|
||||||
|
// const entry = this._findTocEntryById(elementId, this.links);
|
||||||
|
// if(!entry) return true;
|
||||||
|
// if(entry.type != this.tocEntryType.FieldSet) return true;
|
||||||
|
// console.log(el);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const drake = dragula.drake;
|
||||||
|
|
||||||
|
drake.on('drop', (el, target, source,sibling)=>{
|
||||||
|
// console.log('el:', el);
|
||||||
|
// console.log('target:', target);
|
||||||
|
// console.log('source:', source);
|
||||||
|
// console.log('sibling:', el);
|
||||||
|
|
||||||
|
const elementId = (el.id as string).replace(this.DRAGULA_ITEM_ID_PREFIX,'');
|
||||||
|
const targetId = target.id as string;
|
||||||
|
const sourceId = source.id as string;
|
||||||
|
|
||||||
|
|
||||||
|
if(!(elementId && targetId && sourceId)){
|
||||||
|
console.error('Elements not have an id');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const element:ToCEntry = this._findTocEntryById(elementId, this.links);
|
||||||
|
const targetContainer:ToCEntry = this._findTocEntryById(targetId , this.links);
|
||||||
|
const sourceContainer:ToCEntry = this._findTocEntryById(sourceId, this.links);
|
||||||
|
|
||||||
|
if(!(element && (targetContainer ||((element.type===ToCEntryType.Page) && (targetId === this.ROOT_ID))) && (sourceContainer||((element.type===ToCEntryType.Page) && (sourceId === this.ROOT_ID))))){
|
||||||
|
console.info('Could not find elements');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
drake.cancel(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch(element.type){
|
||||||
|
case ToCEntryType.FieldSet:
|
||||||
|
if(targetContainer.type != this.tocEntryType.Section){
|
||||||
|
console.error('Fieldsets can only be childs of section');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check if target container has no sections
|
||||||
|
if((targetContainer.form.get('sections') as FormArray).length){
|
||||||
|
console.error('Fieldsets can only be childs of section thas has no section children');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldsetForm = element.form;
|
||||||
|
const targetFieldsets = targetContainer.form.get('fieldSets') as FormArray;
|
||||||
|
const sourceFieldsets = sourceContainer.form.get('fieldSets') as FormArray;
|
||||||
|
|
||||||
|
if(!targetFieldsets){
|
||||||
|
console.error('Not target fieldsets container found');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sourceOrdinal=-1;
|
||||||
|
let idx = -1;
|
||||||
|
sourceFieldsets.controls.forEach((elem,index)=>{
|
||||||
|
if(elem.get('id').value === elementId){
|
||||||
|
sourceOrdinal = elem.get('ordinal').value;
|
||||||
|
idx = index
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(sourceOrdinal>=0 && idx>=0){
|
||||||
|
sourceFieldsets.removeAt(idx);
|
||||||
|
|
||||||
|
sourceFieldsets.controls.forEach(control=>{
|
||||||
|
const ordinal = control.get('ordinal');
|
||||||
|
if(ordinal.value>= sourceOrdinal){
|
||||||
|
const updatedOrdinalVal = ordinal.value -1;
|
||||||
|
ordinal.setValue(updatedOrdinalVal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let position:number = targetFieldsets.length;
|
||||||
|
|
||||||
|
if(!sibling ||!sibling.id){
|
||||||
|
console.info('No sibling Id found');
|
||||||
|
}else{
|
||||||
|
const siblingId = (sibling.id as string).replace(this.DRAGULA_ITEM_ID_PREFIX,'');
|
||||||
|
let siblingIndex = -1;
|
||||||
|
targetFieldsets.controls.forEach((e,idx)=>{
|
||||||
|
if(e.get('id').value === siblingId){
|
||||||
|
siblingIndex = idx;
|
||||||
|
position = e.get('ordinal').value;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
if(siblingIndex>=0 && (position!=targetFieldsets.length)){
|
||||||
|
|
||||||
|
targetFieldsets.controls.filter(control=> control.get('ordinal').value >= position).forEach(control=>{
|
||||||
|
const ordinal = control.get('ordinal');
|
||||||
|
const updatedOrdinalVal = ordinal.value +1;
|
||||||
|
ordinal.setValue(updatedOrdinalVal);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fieldsetForm.get('ordinal').setValue(position);
|
||||||
|
targetFieldsets.insert(position,fieldsetForm);
|
||||||
|
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ToCEntryType.Section:
|
||||||
|
|
||||||
|
if(targetContainer.type == ToCEntryType.Section){
|
||||||
|
if((targetContainer.form.get('fieldSets')as FormArray).length){
|
||||||
|
console.info('Target container must only contain section children');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetSections = targetContainer.form.get('sections') as FormArray;
|
||||||
|
const elementSectionForm = element.form;
|
||||||
|
const sourceSections = elementSectionForm.parent as FormArray;
|
||||||
|
|
||||||
|
if(!(targetSections && sourceSections && elementSectionForm)){
|
||||||
|
console.info('Could not load sections');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let idx = -1;
|
||||||
|
sourceSections.controls.forEach((section,i)=>{
|
||||||
|
if(section.get('id').value === elementId){
|
||||||
|
idx = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!(idx>=0)){
|
||||||
|
console.info('Could not find element in Parent container');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSections.controls.filter(control=>control.get('ordinal').value >= elementSectionForm.get('ordinal').value).forEach(control=>{
|
||||||
|
const ordinal = control.get('ordinal');
|
||||||
|
const updatedOrdinalVal = ordinal.value -1;
|
||||||
|
ordinal.setValue(updatedOrdinalVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
sourceSections.removeAt(idx);
|
||||||
|
|
||||||
|
let targetOrdinal = targetSections.length;
|
||||||
|
|
||||||
|
if(sibling && sibling.id){
|
||||||
|
const siblingId = sibling.id.replace(this.DRAGULA_ITEM_ID_PREFIX,'');
|
||||||
|
|
||||||
|
targetSections.controls.forEach((section,i)=>{
|
||||||
|
if(section.get('id').value === siblingId){
|
||||||
|
targetOrdinal = section.get('ordinal').value;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if(targetOrdinal!=targetSections.length){
|
||||||
|
// section.get('ordinal').setValue(i+1);
|
||||||
|
targetSections.controls.filter(control=> control.get('ordinal').value>=targetOrdinal).forEach(control=>{
|
||||||
|
const ordinal = control.get('ordinal');
|
||||||
|
const updatedOrdinalVal = ordinal.value+1;
|
||||||
|
ordinal.setValue(updatedOrdinalVal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
console.info('no siblings found');
|
||||||
|
}
|
||||||
|
elementSectionForm.get('ordinal').setValue(targetOrdinal);
|
||||||
|
targetSections.insert(targetOrdinal, elementSectionForm);
|
||||||
|
|
||||||
|
}else if(targetContainer.type === ToCEntryType.Page){
|
||||||
|
const pageId = targetContainer.form.get('id').value;
|
||||||
|
|
||||||
|
const rootform = targetContainer.form.root;
|
||||||
|
const sectionForm = element.form;
|
||||||
|
const parentSections = sectionForm.parent as FormArray;
|
||||||
|
|
||||||
|
let parentIndex = -1;
|
||||||
|
parentSections.controls.forEach((section,i )=>{
|
||||||
|
if(section.get('id').value === elementId){
|
||||||
|
parentIndex = i
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
if(parentIndex<0){
|
||||||
|
console.info('could not locate section in parents array');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//update parent sections ordinal
|
||||||
|
parentSections.controls.filter(section=>section.get('ordinal').value >= sectionForm.get('ordinal').value).forEach(section=>{
|
||||||
|
const ordinal = section.get('ordinal');
|
||||||
|
const updatedOrdinalVal = ordinal.value -1;
|
||||||
|
ordinal.setValue(updatedOrdinalVal);
|
||||||
|
})
|
||||||
|
|
||||||
|
parentSections.removeAt(parentIndex);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let position = 0;
|
||||||
|
if(targetContainer.subEntries){
|
||||||
|
position = targetContainer.subEntries.length;
|
||||||
|
}
|
||||||
|
//populate sections
|
||||||
|
const targetSectionsArray = rootform.get('sections') as FormArray;
|
||||||
|
|
||||||
|
|
||||||
|
if(sibling && sibling.id){
|
||||||
|
const siblingId= sibling.id.replace(this.DRAGULA_ITEM_ID_PREFIX, '');
|
||||||
|
let indx = -1;
|
||||||
|
|
||||||
|
targetContainer.subEntries.forEach((e,i)=>{//TOOD TO CHECK IF ORDINAL AND INDEX IS THE SAME
|
||||||
|
if(e.form.get('id').value === siblingId){
|
||||||
|
indx = i;
|
||||||
|
position = e.form.get('ordinal').value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(indx>=0 && position !=targetContainer.subEntries.length) {
|
||||||
|
|
||||||
|
// e.form.get('ordinal').setValue(i+1);
|
||||||
|
targetContainer.subEntries.filter(e=>e.form.get('ordinal').value >= position).forEach(e=>{
|
||||||
|
const ordinal = e.form.get('ordinal');
|
||||||
|
const updatedOrdinalVal = ordinal.value +1;
|
||||||
|
ordinal.setValue(updatedOrdinalVal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
console.info('No sibling found');
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionForm.get('ordinal').setValue(position);
|
||||||
|
sectionForm.get('page').setValue(targetContainer.id);
|
||||||
|
targetSectionsArray.push(sectionForm);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
console.info('Drag not support to specific container');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
break;
|
||||||
|
case ToCEntryType.Page:
|
||||||
|
if(targetId != this.ROOT_ID){
|
||||||
|
console.info('A page element can only be at top level');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rootForm = element.form.root;
|
||||||
|
if(!rootForm){
|
||||||
|
console.info('Could not find root!')
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const pages = rootForm.get('pages') as FormArray;
|
||||||
|
const pageForm = element.form;
|
||||||
|
|
||||||
|
let index = -1;
|
||||||
|
|
||||||
|
pages.controls.forEach((page,i)=>{
|
||||||
|
if(page.get('id').value === elementId){
|
||||||
|
index =i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(index<0){
|
||||||
|
console.info('Could not locate page on pages');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//ordinality
|
||||||
|
pages.controls.filter(page=> page.get('ordinal').value> pageForm.get('ordinal').value).forEach(page=>{
|
||||||
|
const ordinal = page.get('ordinal');
|
||||||
|
const ordinalVal = ordinal.value - 1;
|
||||||
|
ordinal.setValue(ordinalVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
pages.removeAt(index);
|
||||||
|
|
||||||
|
let targetPosition = pages.length;
|
||||||
|
|
||||||
|
if(sibling){
|
||||||
|
const siblingId = sibling.id.replace(this.DRAGULA_ITEM_ID_PREFIX, '');
|
||||||
|
|
||||||
|
pages.controls.forEach((page,i)=>{
|
||||||
|
if(page.get('id').value === siblingId){
|
||||||
|
targetPosition = page.get('ordinal').value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pageForm.get('ordinal').setValue(targetPosition);
|
||||||
|
|
||||||
|
//update ordinality
|
||||||
|
pages.controls.filter(page=> page.get('ordinal').value>= targetPosition).forEach(page=>{
|
||||||
|
const ordinal = page.get('ordinal');
|
||||||
|
const ordinalVal = ordinal.value +1;
|
||||||
|
ordinal.setValue(ordinalVal);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
pages.insert(targetPosition, pageForm);
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
console.error('Could not support moving objects for specific type of element');
|
||||||
|
this.dataNeedsRefresh.emit();
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
drake.on('drag',(el,source)=>{
|
||||||
|
this.isDragging = true;
|
||||||
|
this.draggingItemId = (el.id as string).replace(this.DRAGULA_ITEM_ID_PREFIX, '');
|
||||||
|
});
|
||||||
|
drake.on('over',(el, container, source)=>{
|
||||||
|
try {
|
||||||
|
this.overcontainer = container.id;
|
||||||
|
} catch (error) {
|
||||||
|
this.overcontainer = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
drake.on('dragend',(el)=>{
|
||||||
|
this.isDragging = false;
|
||||||
|
this.draggingItemId = null;
|
||||||
|
this.overcontainer = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
overcontainer: string = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
//emit value every 500ms
|
//emit value every 500ms
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
/* added to the source element while its mirror is dragged */
|
/* added to the source element while its mirror is dragged */
|
||||||
.gu-transit {
|
.gu-transit {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
border: 1px dashed red;
|
||||||
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
|
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
|
||||||
filter: alpha(opacity=20);
|
filter: alpha(opacity=20);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue