Dataset profile editor. Minor ui visibility fixes. Table of contents can slide.

This commit is contained in:
Kristian Ntavidi 2021-03-03 12:10:11 +02:00
parent ca0babc6af
commit 87b79c2049
13 changed files with 160 additions and 136 deletions

View File

@ -94,7 +94,7 @@ export interface ResearchersFieldData extends FieldData {
}
export interface OrganizationsFieldData extends FieldData {
export interface OrganizationsFieldData extends AutoCompleteFieldData {
}

View File

@ -4,16 +4,19 @@ import { OrganizationsFieldData } from '../../../../../core/model/dataset-profil
export class OrganizationsDataEditorModel extends FieldDataEditorModel<OrganizationsDataEditorModel> {
public label: string;
public multiAutoComplete: boolean = false;
buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup {
const formGroup = this.formBuilder.group({
label: [{ value: this.label, disabled: (disabled && !skipDisable.includes('OrganizationsDataEditorModel.label')) }]
label: [{ value: this.label, disabled: (disabled && !skipDisable.includes('OrganizationsDataEditorModel.label')) }],
multiAutoComplete: [{ value: this.multiAutoComplete, disabled: (disabled && !skipDisable.includes('OrganizationsDataEditorModel.multiAutoComplete')) }]
});
return formGroup;
}
fromModel(item: OrganizationsFieldData): OrganizationsDataEditorModel {
this.label = item.label;
this.multiAutoComplete = item.multiAutoComplete;
return this;
}
}

View File

@ -30,6 +30,7 @@ import { DatasetsAutoCompleteFieldDataEditorModel } from '../../../admin/field-d
import { DatasetIdentifierDataEditorModel } from '../../../admin/field-data/dataset-identifier-data-editor-models';
import { CurrencyDataEditorModel } from '../../../admin/field-data/currency-data-editor-models';
import { ValidationDataEditorModel } from '../../../admin/field-data/validation-data-editor-models';
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
@Component({
selector: 'app-dataset-profile-editor-composite-field-component',
@ -61,7 +62,8 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
constructor(
private dialog: MatDialog,
private language: TranslateService,
public enumUtils: EnumUtils
public enumUtils: EnumUtils,
public datasetProfileService: DatasetProfileService
) { }
ngOnChanges(){
@ -358,6 +360,7 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
case this.viewTypeEnum.Other:
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
fieldForm.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE
break;
case this.viewTypeEnum.InternalDmpEntities:
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.InternalDmpEntities)
@ -407,7 +410,7 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
case this.viewTypeEnum.Organizations:
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Organizations)
// this.form.addControl('data', new OrganizationsDataEditorModel().buildForm());
fieldForm.addControl('data', new DatasetsAutoCompleteFieldDataEditorModel().buildForm());
fieldForm.addControl('data', new DatasetsAutoCompleteFieldDataEditorModel().buildForm()); //TODO
break;
case this.viewTypeEnum.DatasetIdentifier:
fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatasetIdentifier)

View File

@ -26,10 +26,10 @@
</mat-form-field>
<!-- ComboBox -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.ComboBox && comboBoxType === comboBoxTypeEnum.Autocomplete">
<!-- <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.ComboBox && comboBoxType === comboBoxTypeEnum.Autocomplete">
<mat-label>{{placeHolder}}</mat-label>
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form" [required]="required">
</mat-form-field>
</mat-form-field> -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.ComboBox && comboBoxType === comboBoxTypeEnum.WordList">
<mat-label>{{placeHolder}}</mat-label>
<mat-select [formControl]="form" [placeholder]="placeHolder" [required]="required">

View File

@ -5,14 +5,14 @@
<div class="col-auto">
<ul class="list-unstyled list-inline d-flex align-items-center">
<li class="list-inline-item" >
<mat-slide-toggle [checked]="isRequired" (change)="toggleRequired($event)" labelPosition="before" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.MAKE-IT-REQUIRED' | translate">
<mat-slide-toggle [checked]="isRequired" (change)="toggleRequired($event)" labelPosition="before" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.MAKE-IT-REQUIRED' | translate" [disabled]="!viewType">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}
</mat-slide-toggle>
</li>
<li class="list-inline-item" *ngIf="!viewOnly">
<li class="list-inline-item" *ngIf="!viewOnly && viewType">
<mat-icon style="cursor: pointer;" (click)="addNewRule()" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.ADD-VISIBILITY-RULE' | translate">visibility</mat-icon>
</li>
<li class="list-inline-item" *ngIf="!viewOnly">
<li class="list-inline-item" *ngIf="!viewOnly && viewType">
<mat-icon style="cursor: pointer;" (click)="onDelete()" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.DELETE-INPUT' | translate">delete</mat-icon>
</li>
@ -71,7 +71,6 @@
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VIEW-STYLE' | translate}}" [(ngModel)]="viewType" (selectionChange)="onInputTypeChange()"
[disabled]="viewOnly"
[errorStateMatcher]="this"
required
>
<mat-option [value]="viewTypeEnum.TextArea">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.TextArea)}}</mat-option>
<mat-option [value]="viewTypeEnum.FreeText">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.FreeText)}}</mat-option>
@ -215,4 +214,6 @@
</div>
</div>
</ng-container>
<!-- {{form.touched|json}} -->
<!-- {{form.touched|json}} -->
<!-- {{form.value |json}} -->

View File

@ -15,7 +15,7 @@ import { TextAreaFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admi
import { WordListFieldDataEditorModel } from '@app/ui/admin/dataset-profile/admin/field-data/word-list-field-data-editor-model';
import { RuleEditorModel } from '@app/ui/admin/dataset-profile/admin/rule-editor-model';
import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators';
import { debounce, debounceTime, takeUntil } from 'rxjs/operators';
import { ExternalDatasetEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model';
import { DataRepositoriesDataEditorModel } from '../../../admin/field-data/data-repositories-data-editor-models';
import { RegistriesDataEditorModel } from '../../../admin/field-data/registries-data-editor-models';
@ -28,13 +28,14 @@ import { ExternalDatasetsDataEditorModel } from '../../../admin/field-data/exter
import { CurrencyDataEditorModel } from '../../../admin/field-data/currency-data-editor-models';
import { ValidationDataEditorModel } from '../../../admin/field-data/validation-data-editor-models';
import { DatasetDescriptionFieldEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model';
import { Subscription } from 'rxjs';
import { Subject, Subscription } from 'rxjs';
import { ViewStyleType } from './view-style-enum';
import { AutoCompleteFieldDataEditorModel } from '../../../admin/field-data/auto-complete-field-data-editor-model';
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 { Guid } from '@common/types/guid';
import { ErrorStateMatcher, MatSlideToggleChange } from '@angular/material';
import { DefaultValueEditorModel } from '../../../admin/default-value-editor-model';
@Component({
selector: 'app-dataset-profile-editor-field-component',
@ -48,11 +49,12 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
@Input() indexPath: string;
validationTypeEnum = ValidationType;
viewStyleEnum = DatasetProfileFieldViewStyle;
isFieldMultiplicityEnabled = false;
// isFieldMultiplicityEnabled = false;
viewType: ViewStyleType;
viewTypeEnum = ViewStyleType;
// matcher:MyErrorStateMatcher = new MyErrorStateMatcher();
private subject$:Subject<DatasetDescriptionFieldEditorModel> = new Subject<DatasetDescriptionFieldEditorModel>();
@Input() expandView: boolean = true;
@ -63,7 +65,9 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
constructor(
public enumUtils: EnumUtils,
public datasetProfileService: DatasetProfileService
) { super(); }
) { super();
}
isErrorState(control: FormControl, form: FormGroupDirective | NgForm): boolean {
@ -74,12 +78,19 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
}
ngOnInit() {
this.subject$.pipe(takeUntil(this._destroyed)).pipe(debounceTime(600)).subscribe(model=>{
this.previewForm = model.buildForm();
});
this.showPreview = true;
if (this.form.get('multiplicity')) {
if (this.form.get('multiplicity').value.min > 1 && this.form.get('multiplicity').value.max > 1) {
this.isFieldMultiplicityEnabled = true;
}
}
// if (this.form.get('multiplicity')) {
// if (this.form.get('multiplicity').value.min > 1 && this.form.get('multiplicity').value.max > 1) {
// this.isFieldMultiplicityEnabled = true;
// }
// }
if(this.form.get('viewStyle').get('renderStyle').value){
@ -262,12 +273,12 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled: boolean) {
if (!isFieldMultiplicityEnabled) {
(<FormControl>this.form.get('multiplicity').get('min')).setValue(0);
(<FormControl>this.form.get('multiplicity').get('max')).setValue(0);
}
}
// onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled: boolean) {
// if (!isFieldMultiplicityEnabled) {
// (<FormControl>this.form.get('multiplicity').get('min')).setValue(0);
// (<FormControl>this.form.get('multiplicity').get('max')).setValue(0);
// }
// }
addNewRule() {
const rule: RuleEditorModel = new RuleEditorModel();
@ -328,7 +339,6 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
cssClass: null
};
fieldEditorModel.data = (this.form.get('data') as FormGroup).getRawValue();
fieldEditorModel.value = this.form.get('defaultValue').get('value').value;
fieldEditorModel.validationRequired = (this.form.get('validations').value as Array<ValidationType>).includes(ValidationType.Required);
@ -341,14 +351,16 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
// }
const myTicket = Guid.create().toString();
this.validTicket = myTicket;
setTimeout(() => { //TODO
//user hasnt make any new change to inputs /show preview
if(myTicket === this.validTicket){
this.previewForm = fieldEditorModel.buildForm();
}
}, 600);
// const myTicket = Guid.create().toString();
// this.validTicket = myTicket;
// setTimeout(() => { //TODO
// //user hasnt make any new change to inputs /show preview
// if(myTicket === this.validTicket){
// this.previewForm = fieldEditorModel.buildForm();
// }
// }, 600);
this.subject$.next(fieldEditorModel);
// setTimeout(() => {
@ -356,7 +368,9 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
// });
};
validTicket:string;
// validTicket:string;
// generatePreview(){
// const fieldEditorModel = new DatasetDescriptionFieldEditorModel();
@ -390,6 +404,11 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
if (this.form.get('data')) {
this.form.removeControl('data');
}
this.form.removeControl('defaultValue');
const defaultValueModel = new DefaultValueEditorModel();
this.form.addControl('defaultValue',defaultValueModel.buildForm());
switch (x) {
case this.viewTypeEnum.BooleanDecision:
@ -455,8 +474,7 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
break;
case this.viewTypeEnum.Organizations:
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Organizations)
// this.form.addControl('data', new OrganizationsDataEditorModel().buildForm());
this.form.addControl('data', new DatasetsAutoCompleteFieldDataEditorModel().buildForm());
this.form.addControl('data', new OrganizationsDataEditorModel().buildForm());
break;
case this.viewTypeEnum.DatasetIdentifier:
this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatasetIdentifier)
@ -513,26 +531,4 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements
this.delete.emit();
}
}
// class MyErrorStateMatcher implements ErrorStateMatcher {
// reference: AbstractControl;
// setReference(acontrol: AbstractControl){
// this.reference = acontrol;
// }
// isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
// if(this.reference){
// if(this.reference.valid) return false;
// return this.reference.touched && this.reference.invalid;
// }
// return true;
// }
// }
}

View File

@ -147,7 +147,7 @@
<div class="col-3">
<div class="row sticky-top" style="top : 2em">
<div class="row sticky-top" id="style-2" style="top : 2em; max-height: 60vh; overflow-y: scroll;">
<dataset-profile-table-of-contents class="toc-pane-container col"
[links]="toCEntries"
(stepFound)="onStepFound($event)"

View File

@ -103,4 +103,52 @@
border-radius: 3px;
padding-top: 1rem;
padding-bottom: 1rem;
}
}
#style-6::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
background-color: #F5F5F5;
}
#style-6::-webkit-scrollbar
{
width: 6px;
background-color: #F5F5F5;
}
#style-6::-webkit-scrollbar-thumb
{
background-color: rgb(162, 163, 163);
background-image: -webkit-linear-gradient(45deg,
rgba(255, 255, 255, .2) 25%,
transparent 25%,
transparent 50%,
rgba(255, 255, 255, .2) 50%,
rgba(255, 255, 255, .2) 75%,
transparent 75%,
transparent)
}
#style-2::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 10px;
background-color: #F5F5F5;
}
#style-2::-webkit-scrollbar
{
width: 4px;
background-color: #F5F5F5;
}
#style-2::-webkit-scrollbar-thumb
{
border-radius: 2px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: rgb(158, 158, 158)// #FFF;//$blue-color-light;// rgb(162, 163, 163);// #D62929;
}

View File

@ -102,7 +102,6 @@
(dataNeedsRefresh)="onDataNeedsRefresh()"
[dropListGroup]="dropListGroup"
[dragHoveringOver]="dragHoveringOver"
[dropListStruct]="dropListStruct"
[depth]="depth+1"
[DRAGULA_ITEM_ID_PREFIX]="DRAGULA_ITEM_ID_PREFIX"
[overContainerId]="overContainerId"

View File

@ -38,7 +38,7 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
@Input() dragHoveringOver: boolean = false;
@Input() depth: number = 0;
@Input() dropListStruct: { id: string, depth: number}[] = [];
// @Input() dropListStruct: { id: string, depth: number}[] = [];
constructor(
@Inject(DOCUMENT) private _document: Document) {
@ -47,13 +47,13 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
tocEntryType = ToCEntryType;
showStructs(){
console.log(this.dropListStruct.sort(this.compareFn));
}
// showStructs(){
// console.log(this.dropListStruct.sort(this.compareFn));
// }
get orderedListGroup(){
return this.dropListStruct.sort(this.compareFn).map(element=> element.id);
}
// get orderedListGroup(){
// return this.dropListStruct.sort(this.compareFn).map(element=> element.id);
// }
compareFn(a, b){
@ -70,10 +70,10 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
// }
// }
this.dropListStruct.push({
id: this.parentLink.id,
depth: this.depth
});
// this.dropListStruct.push({
// id: this.parentLink.id,
// depth: this.depth
// });
// if(this.links){
// this.links.forEach(link=>{

View File

@ -27,37 +27,4 @@
</span> -->
<!-- </nav> -->
</div>
<!--
<div class="bg-warning">
<ul cdkDropList >
<li cdkDrag>Item2</li>
<li cdkDrag>
<ul cdkDropList>
<li cdkDrag> subitem1</li>
<li cdkDrag> subitem2</li>
<li cdkDrag> subitem3</li>
<li cdkDrag> subitem4</li>
</ul>
</li>
<li cdkDrag>Item4</li>
<li cdkDrag>Item5</li>
</ul>
</div> -->
<!--
<button [matMenuTriggerFor]="animals">meny</button>
<mat-menu #animals="matMenu">
<button mat-menu-item >Vertebrates</button>
<button mat-menu-item [matMenuTriggerFor]="vertebrates">Invertebrates</button>
</mat-menu>
<mat-menu #vertebrates="matMenu">
<button mat-menu-item >Fishes</button>
<button mat-menu-item>Amphibians</button>
<button mat-menu-item >Reptiles</button>
<button mat-menu-item>Birds</button>
<button mat-menu-item>Mammals</button>
</mat-menu> -->
</div>

View File

@ -8,6 +8,7 @@ import { SimpleChanges } from '@angular/core';
import { Foo, ToCEntry, ToCEntryType } from './table-of-contents-entry';
import { DragulaService } from 'ng2-dragula';
import { FormArray } from '@angular/forms';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material';
export interface Link {
/* id of the section*/
@ -66,7 +67,8 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
constructor(
@Inject(DOCUMENT) private _document: Document,
private dragulaService: DragulaService
private dragulaService: DragulaService,
private snackbar: MatSnackBar
) {
super();
@ -75,28 +77,11 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
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 dragula = this.dragulaService.createGroup('TABLEDRAG', {});
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;
@ -124,14 +109,18 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
switch(element.type){
case ToCEntryType.FieldSet:
if(targetContainer.type != this.tocEntryType.Section){
console.error('Fieldsets can only be childs of section');
const message = 'Fieldset can only be child of Subsections';
console.error(message);
this.notifyUser(message)
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');
const message = 'Cannot have inputs and sections on the same level';
this.notifyUser(message);
console.error(message);
this.dataNeedsRefresh.emit();
return;
}
@ -204,7 +193,9 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
if(targetContainer.type == ToCEntryType.Section){
if((targetContainer.form.get('fieldSets')as FormArray).length){
console.info('Target container must only contain section children');
const message = 'Cannot have inputs and sections on the same level';
this.notifyUser(message);
console.info(message);
this.dataNeedsRefresh.emit();
return;
}
@ -336,7 +327,9 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
targetSectionsArray.push(sectionForm);
}else{
console.info('Drag not support to specific container');
const message = 'Drag not support to specific container';
this.notifyUser(message);
console.info(message);
this.dataNeedsRefresh.emit();
return;
}
@ -347,7 +340,9 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
break;
case ToCEntryType.Page:
if(targetId != this.ROOT_ID){
console.info('A page element can only be at top level');
const message = 'A page element can only be at top level';
this.notifyUser(message);
console.info(message);
this.dataNeedsRefresh.emit();
return;
}
@ -448,7 +443,6 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
});
@ -618,8 +612,22 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
onDataNeedsRefresh(){
this.dataNeedsRefresh.emit();
}
notifyUser(message:string){
this.snackbar.open(message, null, this._snackBarConfig);
}
private _snackBarConfig: MatSnackBarConfig = {
duration:2000
}
}
export interface LinkToScroll {
page: number;
section: number;

View File

@ -34,7 +34,6 @@ import { ENTER, COMMA } from '@angular/cdk/keycodes';
import { DatasetIdModel } from '@app/core/model/dataset/dataset-id.model';
import { LocalFetchModel } from '@app/core/model/local-fetch/local-fetch.model';
import { CurrencyService } from '@app/core/services/currency/currency.service';
import { exception } from 'console';
@Component({
selector: 'app-form-field',
@ -287,7 +286,7 @@ export class FormFieldComponent extends BaseComponent implements OnInit {
} else if (this.autocompleteOptions != null) {
autocompleteRequestItem.criteria.autocompleteOptions = this.autocompleteOptions;
} else {
throw exception("Could not load autocomplete options.")
throw "Could not load autocomplete options.";
}
autocompleteRequestItem.criteria.like = query;
return this.datasetExternalAutocompleteService.queryAutocomplete(autocompleteRequestItem);