Dataset Profile Editor. Same level drag n drop on table. UI fixes

This commit is contained in:
Kristian Ntavidi 2021-02-19 16:35:14 +02:00
parent 96ebf7c0d0
commit 3dde61a379
12 changed files with 267 additions and 44 deletions

View File

@ -47,6 +47,11 @@ import { DatasetProfileTableOfContents } from './table-of-contents/table-of-cont
import { DatasetProfileTableOfContentsInternalSection } from './table-of-contents/table-of-contents-internal-section/table-of-contents-internal-section';
import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service';
import {DragDropModule} from '@angular/cdk/drag-drop';
//matrial
import {MatBadgeModule} from '@angular/material/badge';
@NgModule({
imports: [
CommonUiModule,
@ -58,7 +63,8 @@ import {DragDropModule} from '@angular/cdk/drag-drop';
FormProgressIndicationModule,
DatasetModule,
AngularStickyThingsModule,
DragDropModule
DragDropModule,
MatBadgeModule
],
declarations: [
DatasetProfileListingComponent,

View File

@ -46,12 +46,12 @@
<!-- ID TOP RIGHT CORNER -->
<div class="field-id-container">
<!-- <div class="field-id-container">
{{this.form.get('id').value}}
<button mat-mini-fab class="field-id-container-icon">
<mat-icon>delete</mat-icon>
</button>
</div>
</div> -->
@ -78,13 +78,13 @@
[formControl]="this.form.get('description')">
</mat-form-field>
</div>
<div class="row">
<div class="row" *ngIf="showExtendedDescription">
<mat-form-field class="col" appearance="legacy">
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION' | translate}}"
[formControl]="this.form.get('extendedDescription')"/>
</mat-form-field>
</div>
<div class="row">
<div class="row" *ngIf="showAdditionalInfo">
<mat-form-field class="col" appearance="legacy">
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ADDITIONAL-INFORMATION' | translate}}"
[formControl]="this.form.get('additionalInformation')"/>
@ -121,12 +121,12 @@
<ng-container *ngFor="let field of form.get('fields')['controls']; let i=index" >
<div class="row field-container bg-white" style="position: relative;" (click)="setTargetField(field)"
[ngClass]="{'field-container-active': field.get('id').value === targetField?.get('id').value}">
<div class="field-id-container">
{{form.get('fields').get(''+i).get('id').value}}
<!-- <div class="field-id-container">
{{form.get('fields').get(''+i).get('id').value}} -->
<!-- <button mat-mini-fab class="field-id-container-icon" (click)="DeleteField(i)">
<mat-icon>delete</mat-icon>
</button> -->
</div>
<!-- </div> -->
<!-- *ngIf="!isComposite" -->
<app-dataset-profile-editor-field-component class="col-12"
[form]="form.get('fields').get(''+i)" [showOrdinal]="false"
@ -188,7 +188,27 @@
</button>
</mat-list-item>
</ng-container>
<!-- Additional info and Extended -->
<mat-list-item>
<!-- <mat-icon matListIcon>folder</mat-icon> -->
<mat-checkbox matLine [(ngModel)]="showExtendedDescription">
Extended Description
</mat-checkbox>
</mat-list-item>
<mat-list-item>
<!-- <mat-icon matListIcon>folder</mat-icon> -->
<mat-checkbox matLine [(ngModel)]="showAdditionalInfo">
Additional Information
</mat-checkbox>
</mat-list-item>
<!-- INPUT SETTINGS -->
<h3 matSubheader>Input settings</h3>

View File

@ -29,7 +29,7 @@ $blue-color-light: #5cf7f2;
box-shadow: 0px 1px 2px rgb(173, 173, 173) ;
padding: 3em;
border-radius: .3em;
border-left: 0.3em solid yellow;
// border-left: 0.3em solid yellow;
padding-bottom: 2em;
margin-bottom: 2em;

View File

@ -24,6 +24,8 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
@Input() numbering: string;
showAdditionalInfo: boolean = false;
showExtendedDescription: boolean = false;
previewForm: FormGroup;
// isComposite = false;
@ -37,6 +39,8 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
ngOnChanges(){
this.setTargetField(null);
this.showExtendedDescription = !!this.form.get('extendedDescription').value;
this.showAdditionalInfo = !!this.form.get('additionalInformation').value;
}
get isMultiplicityEnabled(){
@ -71,6 +75,9 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
this.targetField = (this.form.get('fields') as FormArray).at(0) as FormGroup;
}
this.showExtendedDescription = !!this.form.get('extendedDescription').value;
this.showAdditionalInfo = !!this.form.get('additionalInformation').value;
}
@ -149,7 +156,11 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnCh
field.ordinal = (this.form.get('fields') as FormArray).length;
(<FormArray>this.form.get('fields')).push(field.buildForm());
const fieldForm = field.buildForm();
(<FormArray>this.form.get('fields')).push(fieldForm);
this.setTargetField(fieldForm);
}
DeleteField(index) {

View File

@ -169,7 +169,7 @@
<ng-container>
<div class="row">
<div class="col-12">
<div class="col-12" *ngIf="expandView">
<span style="font-weight: bold">Preview</span>
</div>
<!-- <div class="col-12">

View File

@ -1,6 +1,6 @@
<!-- View Only : {{viewOnly}} -->
<div class="main-content" style="max-width:1500px">
<div class="main-content">
<div class="container-fluid dataset-profile-editor" *ngIf="form" [formGroup]='form'>
<h3 *ngIf="isNew && !isClone && !isNewVersion">{{'DATASET-PROFILE-EDITOR.TITLE.NEW-PROFILE' | translate}}</h3>
<h3 *ngIf="isNew && isClone">
@ -119,7 +119,7 @@
<!-- TABLE -->
<div class="col-3">
<dataset-profile-table-of-contents class="toc-pane-container"
[links]="getTocEntries()"
[links]="toCEntries"
(stepFound)="onStepFound($event)"
(currentLinks)="getLinks($event)"
(itemClick)="displayItem($event)"
@ -127,7 +127,8 @@
(createEntry) = "addNewEntry($event)"
(removeEntry)="onRemoveEntry($event)"
[itemSelected]="selectedTocEntry"
[viewOnly]="viewOnly">
[viewOnly]="viewOnly"
(dataNeedsRefresh)="onDataNeedsRefresh()">
</dataset-profile-table-of-contents>
</div>
@ -172,7 +173,7 @@
<app-dataset-profile-editor-section-component class="col-12"
*ngIf="selectedTocEntry.type === tocEntryEnumValues.Section"
[form]="selectedTocEntry.form" [indexPath]="'tbd'" [viewOnly]="viewOnly"
(fieldsetAdded)="displayItem(_findTocEntryById($event, getTocEntries()))">
(fieldsetAdded)="displayItem(_findTocEntryById($event, getTocEntries())); onDataNeedsRefresh();">
</app-dataset-profile-editor-section-component>
<!-- FIELDSET INFO -->
@ -299,11 +300,11 @@
</ng-container>
<!-- <div class="row">
<div class="row">
<button (click)="printForm()">
console form
</button>
</div> -->
</div>
<!-- <div class="row">
<button (click)="foo()">foo</button>
</div> -->

View File

@ -181,6 +181,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
setTimeout(() => {
this.steps = this.stepper.steps;
});
this.refreshToCEntries();
}
});
@ -205,9 +206,8 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
setTimeout(() => {
this.steps = this.stepper.steps;
});
//SHOW THE FIRST PAGE
const tocentries = this.getTocEntries();
const tocentries = this.refreshToCEntries();
if(tocentries && tocentries.length){
this.selectedTocEntry = tocentries[0];
}
@ -525,6 +525,20 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
// });
}
private refreshToCEntries(): ToCEntry[]{
this.toCEntries = this.getTocEntries();
//update selected tocentry
if(this.selectedTocEntry){
this.selectedTocEntry = this._findTocEntryById(this.selectedTocEntry.id, this.toCEntries);
}
return this.toCEntries;
}
toCEntries:ToCEntry[];
getTocEntries(): ToCEntry[] {
if (this.form == null) { return []; }
const result: ToCEntry[] = [];
@ -741,7 +755,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
break;
}
this.refreshToCEntries();
}
@ -922,6 +936,8 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
}
}
this.refreshToCEntries();
}
tocEntryIsChildOf(testingChild: ToCEntry,parent: ToCEntry): boolean{
@ -1197,4 +1213,7 @@ export class DatasetProfileEditorComponent extends BaseComponent implements OnIn
}
previewForm:FormGroup;
onDataNeedsRefresh(){
this.refreshToCEntries();
}
}

View File

@ -4,21 +4,47 @@
</span> -->
<div class="table-item row" *ngIf="!(parentLink.type == undefined)">
<div class="col link-info">
<span style="cursor: pointer;" [ngClass]="{'active': itemSelected?.id == parentLink?.id}" (click)="itemClicked(parentLink)" >
<div class="col link-info"
[ngStyle]="{'padding-top': (!((parentLink?.subEntriesType == tocEntryType.FieldSet) && !selectedItemInLinks) || itemSelected?.id == parentLink.id)? '0em': '.6em'}"
>
<!-- <span style="cursor: pointer;" [ngClass]="{'active': itemSelected?.id == parentLink?.id}" (click)="itemClicked(parentLink)" >
{{parentLink?.numbering}} {{parentLink?.label? parentLink?.label : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}}
</span> -->
<span style="cursor: pointer;" [ngClass]="{'active': itemSelected?.id == parentLink?.id}" (click)="itemClicked(parentLink)"
[matBadge]="parentLink.subEntries?.length"
matBadgeOverlap="false"
[matBadgeHidden]="!((parentLink?.subEntriesType == tocEntryType.FieldSet) && !selectedItemInLinks) || itemSelected?.id == parentLink.id"
matBadgePosition="before"
matBadgeColor="accent"
matBadgeSize="small"
[ngStyle]="{'font-size' : (parentLink.type == tocEntryType.FieldSet? '.9rem':'1rem')}"
>
<!-- {{parentLink?.numbering}} {{parentLink?.label? parentLink?.label : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}} -->
{{parentLink?.numbering}} {{parentLink?.form.get('title').value? parentLink?.form.get('title').value : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}}
</span>
</div>
<div class="col-auto" *ngIf="!viewOnly && (itemSelected?.id == parentLink?.id)">
<span class="mat-button" (click)="deleteEntry(parentLink)"><mat-icon>delete</mat-icon></span>
<span style="cursor: pointer;" (click)="deleteEntry(parentLink)"><mat-icon>delete</mat-icon></span>
</div>
</div>
<!-- When item is not selected then show only the pages (first level) -->
<!-- <ng-container *ngIf="tocEntryIsChildOf(itemSelected,parentLink) || (!itemSelected && parentLink?.subEntriesType == tocEntryType.Page)"> -->
<div cdkDropList>
<ng-container *ngFor="let link of links">
<div class="docs-link mt-0" [ngClass]="{'border-left':itemSelected?.id == parentLink?.id}">
<div cdkDropList class="ml-2" [ngClass]="{'border-left-active':itemSelected?.id == parentLink?.id, 'pl-1':itemSelected?.id == parentLink?.id}"
*ngIf="(parentLink?.subEntriesType!= tocEntryType.FieldSet) || selectedItemInLinks || parentLink?.id === itemSelected?.id"
(cdkDropListDropped)="drop($event)"
class="cdk-link-list"
>
<div *ngFor="let link of links; last as isLast"
[ngClass]="{'mb-3': link.type === tocEntryType.Page}"
cdkDrag
[cdkDragStartDelay]="50"
>
<div class="docs-link mt-0">
<!-- <div class="link-name"> -->
<!-- <div class="table-item row">
@ -47,7 +73,7 @@
</ng-container> -->
<!-- </div> -->
<!-- <button cdkDragHandle>drab</button> -->
<div class="ml-2">
<div class="ml-3">
<app-dataset-profile-table-of-contents-internal-section
[links]="link.subEntries"
(itemClick)="itemClicked($event)"
@ -55,17 +81,40 @@
[parentLink]="link"
[itemSelected] = "itemSelected"
(createFooEntry)="createNewEntry($event)"
[viewOnly]="viewOnly">
[viewOnly]="viewOnly"
(dataNeedsRefresh)="onDataNeedsRefresh()">
</app-dataset-profile-table-of-contents-internal-section>
</div>
</div><!-- END OF LOOP-->
</ng-container>
<!-- <div *ngIf="links && !viewOnly && !(parentLink?.subEntriesType == tocEntryType.Page) " > -->
<ng-container *ngIf="selectedItemInLinks && (link.type != tocEntryType.Page) && isLast && (!viewOnly)">
<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">
Fieldset
</ng-container>
</ng-container>
</button>
</ng-container>
<!-- </div> -->
</div>
</div>
</div> <!-- END OF LOOP-->
</div>
<!-- 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 class="ml-2">
<div class="ml-3">
<!-- Give option to generate section -->
<button class="mat-button" style="padding-left: 0px; display: block;" (click)="createNewEntry({childType:tocEntryType.Section,parent:parentLink})">
@ -73,21 +122,20 @@
</button>
<!-- Give option to generate fieldset (only if parent is section)-->
<!-- <button *ngIf="parentLink.type == tocEntryType.Section" class="mat-button" style="padding-left: 0px;" (click)="createNewEntry({childType:tocEntryType.FieldSet,parent:parentLink})">
<!-- Give option to generate fieldset (only if parent is section) -->
<button *ngIf="parentLink.type == tocEntryType.Section" class="mat-button" style="padding-left: 0px;" (click)="createNewEntry({childType:tocEntryType.FieldSet,parent:parentLink})">
<mat-icon>add</mat-icon> Fieldset
</button> -->
</button>
</div>
</div>
<!-- BUILD TYPE OF SAME LEVEL AS LINK OF LINKS -->
<div *ngIf="links && !viewOnly && !(parentLink?.subEntriesType == tocEntryType.Page) && parentLink?.id == itemSelected?.id" >
<ng-container *ngIf="parentLink?.subEntriesType != tocEntryType.FieldSet">
<!-- <div *ngIf="links && !viewOnly && !(parentLink?.subEntriesType == tocEntryType.Page) " >
<ng-container >
<button class="mat-button" style="padding-left: 0px;" (click)="createNewEntry({childType:parentLink.subEntriesType,parent:parentLink})">
<mat-icon>add</mat-icon>
<!-- Create => {{parentLink?.subEntriesType}} -->
<ng-container [ngSwitch]="parentLink?.subEntriesType">
<ng-container *ngSwitchCase="tocEntryType.Section">
Subsection
@ -95,19 +143,19 @@
<ng-container *ngSwitchCase="tocEntryType.Page">
Section
</ng-container>
<!-- <ng-container *ngSwitchCase="tocEntryType.FieldSet">
<ng-container *ngSwitchCase="tocEntryType.FieldSet">
Fieldset
</ng-container> -->
</ng-container>
</ng-container>
</button>
</ng-container>
</div>
</div> -->
<!-- </ng-container> -->
<!-- Only for the page -->
<div *ngIf="parentLink?.subEntriesType == tocEntryType.Page && !viewOnly">
<button class="mat-button" (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> Section
</button>
</div>

View File

@ -96,7 +96,64 @@
.link-info{
// display: inline-block; cursor: pointer;
// padding-top: .6em;
// padding-left: .6em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
// .border-left-active{
// border-left: 1px solid #000;
// }
.cdk-link-list {
display: block;
// background: white;
overflow: hidden;
}
.link-box {
padding: 20px 10px;
border-bottom: solid 1px #ccc;
color: rgba(0, 0, 0, 0.87);
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
cursor: move;
background: white;
font-size: 14px;
}
.cdk-drag-preview {
background-color: #FFF;
box-sizing: border-box;
border-radius: 4px;
box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
0 8px 10px 1px rgba(0, 0, 0, 0.14),
0 3px 14px 2px rgba(0, 0, 0, 0.12);
.add-new-entry{
display: none;
}
}
.cdk-drag-placeholder {
opacity: 0;
}
.cdk-drag-animating {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}
.link-box:last-child {
border: none;
}
.cdk-link-list.cdk-drop-list-dragging .link-box:not(.cdk-drag-placeholder) {
transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
}

View File

@ -1,5 +1,7 @@
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { DOCUMENT } from '@angular/common';
import { Component, EventEmitter, Inject, Input, OnInit, Output, SimpleChanges } from '@angular/core';
import { FormArray } from '@angular/forms';
import { BaseComponent } from '@common/base/base.component';
import { Foo, ToCEntry, ToCEntryType } from '../table-of-contents-entry';
@ -17,6 +19,10 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
@Output() createFooEntry = new EventEmitter<Foo>();
@Output() dataNeedsRefresh = new EventEmitter<void>();
@Input() parentLink: ToCEntry;
@Input() itemSelected: ToCEntry;
@ -70,4 +76,54 @@ export class DatasetProfileTableOfContentsInternalSection extends BaseComponent
}
return false;
}
get selectedItemInLinks(){
if(!this.links || !this.itemSelected) return false;
const link = this.links.find(l=>l.id === this.itemSelected.id);
if(link) return true;
return false;
}
drop(event: CdkDragDrop<string[]>) {
if(!this.links || !this.links.length) return;
moveItemInArray(this.links, event.previousIndex, event.currentIndex);
let arrayToUpdate: FormArray = this.links[0].form.parent as FormArray;
// if(this.parentLink && this.parentLink.form){
// switch(this.parentLink.subEntriesType){
// case this.tocEntryType.Field:
// arrayToUpdate = (this.parentLink.form.get('fields') as FormArray);
// break;
// case this.tocEntryType.FieldSet:
// arrayToUpdate = (this.parentLink.form.get('fieldSets') as FormArray);
// break;
// case this.tocEntryType.Section:
// arrayToUpdate = (this.parentLink.form.get('sections') as FormArray);
// break
// }
// }
if(arrayToUpdate.controls){
moveItemInArray(arrayToUpdate.controls, event.previousIndex, event.currentIndex);
//update ordinality
arrayToUpdate.controls.forEach((element,idx ) => {
element.get('ordinal').setValue(idx);
element.updateValueAndValidity();
});
}
this.dataNeedsRefresh.emit();
// moveItemInArray(this.links, event.previousIndex, event.currentIndex);
// console.log('dropped');
}
onDataNeedsRefresh(){
this.dataNeedsRefresh.emit();
}
}

View File

@ -12,6 +12,7 @@
[parentLink]="{ subEntriesType: tocEntryType.Page, subEntries : links }"
[itemSelected]="itemSelected"
[viewOnly]="viewOnly"
(dataNeedsRefresh)="onDataNeedsRefresh()"
></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">

View File

@ -44,6 +44,7 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
@Output() createEntry = new EventEmitter<Foo>();
@Output() dataNeedsRefresh = new EventEmitter<void>();
@Input() itemSelected: ToCEntry;
@Input() viewOnly: boolean;
@ -198,10 +199,13 @@ export class DatasetProfileTableOfContents extends BaseComponent implements OnIn
createNewEntry(foo: Foo){
this.createEntry.emit(foo);
}
onDataNeedsRefresh(){
this.dataNeedsRefresh.emit();
}
}
export interface LinkToScroll {
page: number;
section: number;
}