From 7a3f3f2fd51ccb4b9ef952260e5af81955a6dbb5 Mon Sep 17 00:00:00 2001 From: "k.triantafyllou" Date: Tue, 19 Oct 2021 11:08:38 +0300 Subject: [PATCH] Add reordering for inputs in a dataset template --- .../dataset-profile/dataset-profile.module.ts | 33 +-- ...file-editor-composite-field.component.html | 107 ++++---- ...file-editor-composite-field.component.scss | 19 +- ...rofile-editor-composite-field.component.ts | 234 +++++++++++------- ...ataset-profile-editor-field.component.html | 7 +- .../dataset-profile-editor-field.component.ts | 9 +- .../dataset-profile-editor.component.ts | 10 +- .../transition-group-item.directive.ts | 16 ++ .../transition-group.component.ts | 106 ++++++++ .../transition-group.module.ts | 13 + dmp-frontend/src/assets/config/config.json | 2 +- dmp-frontend/src/assets/i18n/de.json | 4 +- dmp-frontend/src/assets/i18n/en.json | 4 +- dmp-frontend/src/assets/i18n/es.json | 4 +- dmp-frontend/src/assets/i18n/gr.json | 4 +- dmp-frontend/src/assets/i18n/pt.json | 4 +- dmp-frontend/src/assets/i18n/sk.json | 4 +- dmp-frontend/src/assets/i18n/sr.json | 4 +- dmp-frontend/src/assets/i18n/tr.json | 4 +- dmp-frontend/src/styles.scss | 5 + 20 files changed, 407 insertions(+), 186 deletions(-) create mode 100644 dmp-frontend/src/app/ui/transition-group/transition-group-item.directive.ts create mode 100644 dmp-frontend/src/app/ui/transition-group/transition-group.component.ts create mode 100644 dmp-frontend/src/app/ui/transition-group/transition-group.module.ts diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts index 660ab6101..44a213352 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/dataset-profile.module.ts @@ -53,26 +53,27 @@ 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 {HttpClientModule} from "@angular/common/http"; import {AngularEditorModule} from "@kolkov/angular-editor"; +import {TransitionGroupModule} from "@app/ui/transition-group/transition-group.module"; @NgModule({ - imports: [ - CommonUiModule, - CommonFormsModule, - FormattingModule, - DatasetProfileRoutingModule, - ConfirmationDialogModule, - NgxDropzoneModule, - FormProgressIndicationModule, - DatasetModule, - AngularStickyThingsModule, - DragDropModule, - MatBadgeModule, - DragulaModule, - AutoCompleteModule, - HttpClientModule, AngularEditorModule, - ], + imports: [ + CommonUiModule, + CommonFormsModule, + FormattingModule, + DatasetProfileRoutingModule, + ConfirmationDialogModule, + NgxDropzoneModule, + FormProgressIndicationModule, + DatasetModule, + AngularStickyThingsModule, + DragDropModule, + MatBadgeModule, + DragulaModule, + AutoCompleteModule, + HttpClientModule, AngularEditorModule, TransitionGroupModule, + ], declarations: [ DatasetProfileListingComponent, DatasetProfileCriteriaComponent, diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html index 1069e7252..3604c017b 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.html @@ -1,4 +1,3 @@ - - -
- - -
- - - - - - - - -
+
+
+ + + + + + + +
+
    +
  • + keyboard_arrow_up +
  • +
  • + keyboard_arrow_down +
  • +
+
+

- - - +
  • @@ -221,7 +226,7 @@ - + - + - + - + - + - + - - + + @@ -383,9 +388,9 @@ more_vert - {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION' | translate}} - {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION' | translate}} - {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ADDITIONAL-INFORMATION' | translate}} + {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION' | translate}} + {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION' | translate}} + {{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ADDITIONAL-INFORMATION' | translate}}
  • @@ -393,21 +398,21 @@
    - +
    - - - diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.scss b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.scss index 9b73377a3..a53d303c5 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.scss +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.scss @@ -53,7 +53,7 @@ $blue-color-light: #5cf7f2; .field-id-container-icon{ position: absolute; top: -50%; - + } } @@ -64,7 +64,7 @@ $blue-color-light: #5cf7f2; .fielset-header{ font-size: 1.5em; font-weight: bold; - + // .numbering{ // padding: 0.5em 0em; // } @@ -84,7 +84,7 @@ $blue-color-light: #5cf7f2; color: #212121; } -:host ::ng-deep .fieldset-checkbox-action-dataset-profile-editor +:host ::ng-deep .fieldset-checkbox-action-dataset-profile-editor { .mat-checkbox-label{ font-size: 0.8em; @@ -134,6 +134,13 @@ $blue-color-light: #5cf7f2; font-style: italic; } -// ::ng-deep .underline-line-field .mat-form-field-appearance-legacy .mat-form-field-wapper{ -// padding-bottom: 1.25em !important; -// } \ No newline at end of file +.field-input { + position: relative; +} + +.field-input .arrows { + position: absolute; + top: 0; + left: 50%; + transform: translateX(-50%); +} diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts index 306eaa17a..89dead325 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component.ts @@ -1,30 +1,56 @@ -import { Component, Input, OnChanges, OnInit } from '@angular/core'; -import { FormArray, FormControl, FormGroup} from '@angular/forms'; -import { FieldEditorModel } from '../../../admin/field-editor-model'; -import { Guid } from '@common/types/guid'; -import { RuleEditorModel } from '../../../admin/rule-editor-model'; -import { ValidationType } from '@app/core/common/enum/validation-type'; -import { MatCheckboxChange } from '@angular/material/checkbox'; -import { DatasetDescriptionCompositeFieldEditorModel, DatasetDescriptionFieldEditorModel, DatasetDescriptionFormEditorModel, DatasetDescriptionSectionEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model'; -import { DatasetProfileFieldViewStyle } from '@app/core/common/enum/dataset-profile-field-view-style'; -import { MatDialog } from '@angular/material/dialog'; -import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; -import { TranslateService } from '@ngx-translate/core'; -import { ViewStyleType } from '../field/view-style-enum'; -import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; -import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; -import { EditorCustomValidators } from '../../custom-validators/editor-custom-validators'; -import { Field, FieldSet } from '@app/core/model/admin/dataset-profile/dataset-profile'; -import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profile-combo-box-type'; -import { DatasetProfileInternalDmpEntitiesType } from '@app/core/common/enum/dataset-profile-internal-dmp-entities-type'; -import { AutoCompleteFieldData, BooleanDecisionFieldData, CheckBoxFieldData, CurrencyFieldData, DataRepositoriesFieldData, DatasetIdentifierFieldData, DatePickerFieldData, DmpsAutoCompleteFieldData, ExternalDatasetsFieldData, FieldDataOption, FreeTextFieldData, OrganizationsFieldData, RadioBoxFieldData, RegistriesFieldData, ResearchersAutoCompleteFieldData, ServicesFieldData, TagsFieldData, TextAreaFieldData, ValidationFieldData, WordListFieldData } from '@app/core/model/dataset-profile-definition/field-data/field-data'; -import { CompositeField } from '@app/core/model/dataset-profile-definition/composite-field'; +import {Component, Input, OnChanges, OnInit, ViewChild} from '@angular/core'; +import {AbstractControl, FormArray, FormControl, FormGroup} from '@angular/forms'; +import {FieldEditorModel} from '../../../admin/field-editor-model'; +import {Guid} from '@common/types/guid'; +import {RuleEditorModel} from '../../../admin/rule-editor-model'; +import {ValidationType} from '@app/core/common/enum/validation-type'; +import {MatCheckboxChange} from '@angular/material/checkbox'; +import { + DatasetDescriptionCompositeFieldEditorModel, + DatasetDescriptionFieldEditorModel, + DatasetDescriptionSectionEditorModel +} from '@app/ui/misc/dataset-description-form/dataset-description-form.model'; +import {DatasetProfileFieldViewStyle} from '@app/core/common/enum/dataset-profile-field-view-style'; +import {MatDialog} from '@angular/material/dialog'; +import {ConfirmationDialogComponent} from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import {TranslateService} from '@ngx-translate/core'; +import {ViewStyleType} from '../field/view-style-enum'; +import {EnumUtils} from '@app/core/services/utilities/enum-utils.service'; +import {DatasetProfileService} from '@app/core/services/dataset-profile/dataset-profile.service'; +import {EditorCustomValidators} from '../../custom-validators/editor-custom-validators'; +import {Field, FieldSet} from '@app/core/model/admin/dataset-profile/dataset-profile'; +import {DatasetProfileComboBoxType} from '@app/core/common/enum/dataset-profile-combo-box-type'; +import {DatasetProfileInternalDmpEntitiesType} from '@app/core/common/enum/dataset-profile-internal-dmp-entities-type'; +import { + AutoCompleteFieldData, + BooleanDecisionFieldData, + CheckBoxFieldData, + CurrencyFieldData, + DataRepositoriesFieldData, + DatasetIdentifierFieldData, + DatePickerFieldData, + DmpsAutoCompleteFieldData, + ExternalDatasetsFieldData, + FieldDataOption, + FreeTextFieldData, + OrganizationsFieldData, + RadioBoxFieldData, + RegistriesFieldData, + ResearchersAutoCompleteFieldData, + ServicesFieldData, + TagsFieldData, + TextAreaFieldData, + ValidationFieldData, + WordListFieldData +} from '@app/core/model/dataset-profile-definition/field-data/field-data'; +import {CompositeField} from '@app/core/model/dataset-profile-definition/composite-field'; import {Field as FieldDefinition} from '@app/core/model/dataset-profile-definition/field'; -import { Subject } from 'rxjs'; -import { debounceTime, delay, map, takeUntil, tap } from 'rxjs/operators'; -import { GENERAL_ANIMATIONS } from '../../animations/animations'; -import { BaseComponent } from '@common/base/base.component'; +import {Subject} from 'rxjs'; +import {debounceTime, delay, map, takeUntil, tap} from 'rxjs/operators'; +import {GENERAL_ANIMATIONS} from '../../animations/animations'; +import {BaseComponent} from '@common/base/base.component'; import {AngularEditorConfig} from "@kolkov/angular-editor"; +import {TransitionGroupComponent} from "@app/ui/transition-group/transition-group.component"; @Component({ selector: 'app-dataset-profile-editor-composite-field-component', @@ -73,7 +99,8 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i @Input() numbering: string; @Input() hasFocus: boolean = false; - + @ViewChild("inputs") inputs: TransitionGroupComponent; + showPreview: boolean = true; previewDirty: boolean = false; @@ -96,7 +123,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i private language: TranslateService, public enumUtils: EnumUtils, public datasetProfileService: DatasetProfileService - ) { + ) { super(); } @@ -104,6 +131,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // this.setTargetField(null); // this.showExtendedDescription = !!this.form.get('extendedDescription').value; // this.showAdditionalInfo = !!this.form.get('additionalInformation').value; + console.log(this.form.get('fields')['controls']) } get firstField(){ @@ -153,7 +181,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // this.previewForm = null; this.previewDirty = true; this.generatePreviewForm(); - + }); this.previewSubject$ .pipe(debounceTime(600)) @@ -191,7 +219,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i if(previewContainer){ previewContainer.style.height = 'auto'; } - + // const updatedForm = model.buildForm(); // this.reloadPreview(updatedForm) }); @@ -207,7 +235,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } private reloadPreview(updatedForm: FormGroup){ setTimeout(() => { - + const previewContainer = document.getElementById('preview_container'+ this.form.get('id').value); // let clientHeight = -1; if(previewContainer){ @@ -227,7 +255,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i setTimeout(() => { - + this.showPreview = true; this.previewDirty = false; @@ -238,7 +266,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } }); } - }); + }); }); } @@ -247,7 +275,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i private generatePreviewForm(){ const formValue:FieldSet = this.form.getRawValue(); const fields:FieldDefinition[] = formValue.fields.map(editorField=>this._fieldToFieldDefinition(editorField)); - + const compositeField: CompositeField = { id: formValue.id, @@ -268,7 +296,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } return model; }) - } + } const section = new DatasetDescriptionSectionEditorModel(); @@ -314,7 +342,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // (this.form.get('fields') as FormArray).controls.forEach(field=>{ // const fieldEditorModel = new DatasetDescriptionFieldEditorModel(); - + // fieldEditorModel.viewStyle= { // renderStyle: field.get('viewStyle').get('renderStyle').value, // cssClass: null @@ -322,15 +350,15 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // fieldEditorModel.defaultValue = field.get('defaultValue').value; // switch (field.get('viewStyle').get('renderStyle').value) { // case DatasetProfileFieldViewStyle.TextArea: - // fieldEditorModel.data = { + // fieldEditorModel.data = { // label: field.get('data').get('label').value // }; // break; - + // default: // break; // } - + // editorModel.fields.push(fieldEditorModel); // }); @@ -369,7 +397,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i minControl.updateValueAndValidity(); maxControl.updateValueAndValidity(); - + } addNewField() { @@ -380,11 +408,11 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i const fieldForm = field.buildForm(); // fieldForm.setValidators(this.customFieldValidator()); - + // fieldForm.get('viewStyle').get('renderStyle').setValidators(Validators.required); (this.form.get('fields')).push(fieldForm); - + this.setTargetField(fieldForm); fieldForm.updateValueAndValidity(); } @@ -393,7 +421,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i const fieldsForm = this.form.get('fields'); fieldsForm.removeAt(index); - + this.inputs.init(); // calculate ordinals fieldsForm.controls.forEach((field, idx)=>{ field.get('ordinal').setValue(idx); @@ -417,7 +445,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i (targetField.get('visible').get('rules')).push(rule.buildForm()); } toggleRequired(targetField: FormGroup, event:MatCheckboxChange){ - + let validationsControl = targetField.get('validations') as FormControl; let validations: Array = validationsControl.value; @@ -433,12 +461,12 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i validationsControl.setValue(validations.filter(validator=> validator != ValidationType.Required)); validationsControl.updateValueAndValidity(); } - - + + // if(validations.includes(ValidationType.Required)){//IS ALREADY REQUIRED // validationsControl.setValue(validations.filter(validator=> validator != ValidationType.Required)); // validationsControl.updateValueAndValidity(); - // }else{ + // }else{ // //SET REQUIRED VALIDATOR // console.log('setting required validator'); // validations.push(ValidationType.Required); @@ -446,17 +474,13 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // validationsControl.updateValueAndValidity(); // } } - setTargetField(field:FormGroup){ - this.targetField = field; + setTargetField(field:AbstractControl){ + this.targetField = field; } - - - - deleteTargetField(){ - + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { restoreFocus: false, data: { @@ -471,7 +495,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i this._deleteTargetField(); } }); - + } @@ -498,7 +522,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } deleteField(index: number){ - + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { restoreFocus: false, data: { @@ -513,21 +537,21 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i this.DeleteField(index); } }); - + } addNewInput(type: ViewStyleType){ - + const fieldsArray = this.form.get('fields') as FormArray; - + let targetOrdinal = fieldsArray.length; try{ targetOrdinal = fieldsArray.controls.map(control=> control.get('ordinal').value).reduce((a,b)=>Math.max(a,b)) +1; }catch{ - + } @@ -550,8 +574,8 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // const fieldForm = field.buildForm(); // fieldForm.setValidators(this.customFieldValidator()); // fieldForm.get('viewStyle').get('renderStyle').setValidators(Validators.required); - - + + // if (fieldForm.get('data')) { // fieldForm.removeControl('data'); @@ -573,7 +597,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.CheckBox:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.CheckBox) // fieldForm.addControl('data', new CheckBoxFieldDataEditorModel().buildForm()); const data: CheckBoxFieldData = { @@ -582,12 +606,12 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.CheckBox; field.data = data; - + break; } case this.viewTypeEnum.Select:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox) // fieldForm.addControl('data', new WordListFieldDataEditorModel().buildForm()); @@ -610,7 +634,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.Other:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox) // fieldForm.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE @@ -630,10 +654,10 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i break; }case this.viewTypeEnum.InternalDmpEntities:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.InternalDmpEntities) // fieldForm.addControl('data', new ResearchersAutoCompleteFieldDataEditorModel().buildForm());//TODO TO SEE - + const data: DmpsAutoCompleteFieldData = { label:'', multiAutoComplete: false, @@ -648,7 +672,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.FreeText:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.FreeText) // fieldForm.addControl('data', new FreeTextFieldDataEditorModel().buildForm()); @@ -662,7 +686,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.RadioBox:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.RadioBox) // fieldForm.addControl('data', new RadioBoxFieldDataEditorModel().buildForm()); // fieldForm.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('options')); @@ -679,7 +703,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.TextArea:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.TextArea) // fieldForm.addControl('data', new TextAreaFieldDataEditorModel().buildForm()); @@ -694,7 +718,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.DatePicker:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatePicker) // fieldForm.addControl('data', new DatePickerDataEditorModel().buildForm()); const data: DatePickerFieldData = { @@ -707,7 +731,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.ExternalDatasets:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ExternalDatasets) // fieldForm.addControl('data', new ExternalDatasetsDataEditorModel().buildForm()); const data: ExternalDatasetsFieldData = { @@ -721,7 +745,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.DataRepositories:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DataRepositories) // fieldForm.addControl('data', new DataRepositoriesDataEditorModel().buildForm()); @@ -737,10 +761,10 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.Registries:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Registries) // fieldForm.addControl('data', new RegistriesDataEditorModel().buildForm()); - + const data:RegistriesFieldData = { label: '', multiAutoComplete: false @@ -753,7 +777,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.Services:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Services) // fieldForm.addControl('data', new ServicesDataEditorModel().buildForm()); @@ -769,7 +793,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.Tags:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Tags) // fieldForm.addControl('data', new TagsDataEditorModel().buildForm()); @@ -783,7 +807,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.Researchers:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Researchers) // this.form.addControl('data', new ResearchersDataEditorModel().buildForm()); //TODO TO ASK // fieldForm.addControl('data', new ResearchersAutoCompleteFieldDataEditorModel().buildForm()); @@ -798,10 +822,10 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.InternalDmpEntities; // field.data = {label:''} - + field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Researchers; field.data = data; - + @@ -809,7 +833,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.Organizations:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Organizations) // fieldForm.addControl('data', new OrganizationsDataEditorModel().buildForm()); // this.form.addControl('data', new OrganizationsDataEditorModel().buildForm()) @@ -819,8 +843,8 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i autoCompleteSingleDataList:[], label:'', multiAutoComplete: false, - - } as OrganizationsFieldData; //TODO + + } as OrganizationsFieldData; //TODO field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Organizations; field.data = data; @@ -829,7 +853,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.DatasetIdentifier:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatasetIdentifier) // fieldForm.addControl('data', new DatasetIdentifierDataEditorModel().buildForm()); @@ -839,12 +863,12 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.DatasetIdentifier; field.data = data; - + break; } case this.viewTypeEnum.Currency:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Currency) // fieldForm.addControl('data', new CurrencyDataEditorModel().buildForm()); @@ -858,7 +882,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } case this.viewTypeEnum.Validation:{ - + // fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Validation) // fieldForm.addControl('data', new ValidationDataEditorModel().buildForm()); @@ -874,9 +898,10 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i } (this.form.get('fields')).push(new FieldEditorModel().fromModel(field).buildForm()); + this.inputs.init(); // fieldForm.get('viewStyle').get('renderStyle').updateValueAndValidity(); // fieldForm.get('data').updateValueAndValidity(); - + } @@ -930,7 +955,7 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i // private _atLeastOneElementListValidator(arrayToCheck): ValidatorFn{ // return (control: AbstractControl): ValidationErrors | null=>{ - + // const fa = control.get(arrayToCheck) as FormArray; // if(fa.length === 0){ @@ -948,6 +973,37 @@ export class DatasetProfileEditorCompositeFieldComponent extends BaseComponent i return {'width':width+'em'} } + + get fieldsArray(): FormArray { + if(this.form && this.form.get('fields')) { + return this.form.get('fields') as FormArray; + } + return null; + } + + move(index, direction: "up" | "down" = "up") { + this.inputs.init(); + if (direction === "up" && this.canGoUp(index)) { + let temp = this.fieldsArray.at(index); + this.fieldsArray.removeAt(index); + this.fieldsArray.insert(index-1, temp); + } else if (direction === "down" && this.canGoDown(index)) { + let temp = this.fieldsArray.at(index+1); + this.fieldsArray.removeAt(index+1); + this.fieldsArray.insert(index, temp); + } + this.fieldsArray.controls.forEach((field, index) => { + field.get('ordinal').setValue(index); + }); + } + + canGoUp(index: number): boolean { + return index > 0; + } + + canGoDown(index: number): boolean { + return index < (this.fieldsArray.length - 1); + } } diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html index 63a60bf65..7a82c2b48 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.html @@ -1,8 +1,9 @@ -
    -
    +
    + +
    • @@ -12,7 +13,7 @@ -
    • +
    • delete
    diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts index 6dbf3db7e..5d1d9a30d 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/components/field/dataset-profile-editor-field.component.ts @@ -274,7 +274,7 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements private _formChangesSubscription:Subscription; - private _showPreview: boolean = false;; + private _showPreview: boolean = false; // get showPreview(): boolean{ @@ -801,12 +801,7 @@ export class DatasetProfileEditorFieldComponent extends BaseComponent implements get isRequired(){ let validationsControl = this.form.get('validations') as FormControl; let validations: Array = validationsControl.value; - - if(validations.includes(ValidationType.Required)){ - return true; - } - return false; - + return validations.includes(ValidationType.Required); } diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts index e5fb0b33b..cd4385d16 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/editor/dataset-profile-editor.component.ts @@ -311,14 +311,14 @@ export class DatasetProfileEditorComponent extends CheckDeactivateBaseComponent }, 400); // this._initializeFormValidity(tocentries); - //Checking invalid visibilty RULES + //Checking invalid visibilty RULES const fieldsetEntries = this._getAllFieldSets(this.toCEntries); const fieldSetHavingInvalidVisibilityRules:ToCEntry[] = fieldsetEntries .filter(entry=>{ const fieldsFormGroup = entry.form.get('fields'); const invalid = (fieldsFormGroup as FormArray).controls.filter(field=>{ return this.hasInvalidVisibilityRule(field as FormGroup); - + }); if(invalid && invalid.length){ return true; @@ -342,7 +342,7 @@ export class DatasetProfileEditorComponent extends CheckDeactivateBaseComponent if(confirm){ this.removeFieldSetVisibilityRules(fieldSetHavingInvalidVisibilityRules); this.uiNotificationService.snackBarNotification(this.language.instant('DATASET-PROFILE-EDITOR.ERRORS.INVALID-VISIBILITY-RULES.REMOVE-SUCCESS'), SnackBarNotificationLevel.Success); - + }else{ console.log('User not confirmed'); } @@ -393,7 +393,7 @@ export class DatasetProfileEditorComponent extends CheckDeactivateBaseComponent return true; } return false; - + }catch{ return false; } @@ -1227,7 +1227,7 @@ export class DatasetProfileEditorComponent extends CheckDeactivateBaseComponent //in case selectedtocentrhy is child of the removed element // this.refreshToCEntries(); - this.onDataNeedsRefresh(); + this.onDataNeedsRefresh(); this.form.updateValueAndValidity(); } diff --git a/dmp-frontend/src/app/ui/transition-group/transition-group-item.directive.ts b/dmp-frontend/src/app/ui/transition-group/transition-group-item.directive.ts new file mode 100644 index 000000000..a9b08f970 --- /dev/null +++ b/dmp-frontend/src/app/ui/transition-group/transition-group-item.directive.ts @@ -0,0 +1,16 @@ +import {Directive, ElementRef} from "@angular/core"; + +@Directive({ + selector: '[transition-group-item]' +}) +export class TransitionGroupItemDirective { + prevPos: any; + newPos: any; + el: HTMLElement; + moved: boolean; + moveCallback: any; + + constructor(elRef: ElementRef) { + this.el = elRef.nativeElement; + } +} diff --git a/dmp-frontend/src/app/ui/transition-group/transition-group.component.ts b/dmp-frontend/src/app/ui/transition-group/transition-group.component.ts new file mode 100644 index 000000000..62d89b8e1 --- /dev/null +++ b/dmp-frontend/src/app/ui/transition-group/transition-group.component.ts @@ -0,0 +1,106 @@ +import {TransitionGroupItemDirective} from "./transition-group-item.directive"; +import {AfterViewInit, Component, ContentChildren, Input, OnDestroy, QueryList} from "@angular/core"; +import {Subscription} from "rxjs"; +import Timeout = NodeJS.Timeout; + +@Component({ + selector: '[transition-group]', + template: '' +}) +export class TransitionGroupComponent implements AfterViewInit, OnDestroy { + @ContentChildren(TransitionGroupItemDirective) items: QueryList; + private subscription: Subscription; + private timeout: Timeout; + + ngAfterViewInit() { + this.init(); + this.subscription = this.items.changes.subscribe(items => { + items.forEach(item => item.prevPos = item.newPos || item.prevPos); + items.forEach(this.runCallback); + this.refreshPosition('newPos'); + items.forEach(item => item.prevPos = item.prevPos || item.newPos); // for new items + + const animate = () => { + items.forEach(this.applyTranslation); + this['_forceReflow'] = document.body.offsetHeight; // force reflow to put everything in position + this.items.forEach(this.runTransition.bind(this)); + } + + const willMoveSome = items.some((item) => { + const dx = item.prevPos.left - item.newPos.left; + const dy = item.prevPos.top - item.newPos.top; + return dx || dy; + }); + + if (willMoveSome) { + animate(); + } else { + setTimeout(() => { // for removed items + this.refreshPosition('newPos'); + animate(); + }, 0); + } + }); + } + + ngOnDestroy() { + this.clear(); + if (this.subscription) { + this.subscription.unsubscribe(); + } + } + + clear() { + if (this.timeout) { + clearTimeout(this.timeout); + } + } + + init() { + this.clear(); + this.refreshPosition('prevPos'); + this.refreshPosition('newPos'); + } + + runCallback(item: TransitionGroupItemDirective) { + if (item.moveCallback) { + item.moveCallback(); + } + } + + runTransition(item: TransitionGroupItemDirective) { + if (!item.moved) { + return; + } + const cssClass = 'list-move'; + let el = item.el; + let style: any = el.style; + el.classList.add(cssClass); + style.transform = style.WebkitTransform = style.transitionDuration = ''; + el.addEventListener('transitionend', item.moveCallback = (e: any) => { + if (!e || /transform$/.test(e.propertyName)) { + el.removeEventListener('transitionend', item.moveCallback); + item.moveCallback = null; + el.classList.remove(cssClass); + } + }); + } + + refreshPosition(prop: string) { + this.items.forEach(item => { + item[prop] = item.el.getBoundingClientRect(); + }); + } + + applyTranslation(item: TransitionGroupItemDirective) { + item.moved = false; + const dx = item.prevPos.left - item.newPos.left; + const dy = item.prevPos.top - item.newPos.top; + if (dx || dy) { + item.moved = true; + let style: any = item.el.style; + style.transform = style.WebkitTransform = 'translate(' + dx + 'px,' + dy + 'px)'; + style.transitionDuration = '0s'; + } + } +} diff --git a/dmp-frontend/src/app/ui/transition-group/transition-group.module.ts b/dmp-frontend/src/app/ui/transition-group/transition-group.module.ts new file mode 100644 index 000000000..a1d3d0cd9 --- /dev/null +++ b/dmp-frontend/src/app/ui/transition-group/transition-group.module.ts @@ -0,0 +1,13 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {TransitionGroupItemDirective} from "./transition-group-item.directive"; +import {TransitionGroupComponent} from "./transition-group.component"; + +@NgModule({ + declarations: [TransitionGroupItemDirective, TransitionGroupComponent], + imports: [CommonModule], + exports: [TransitionGroupItemDirective, TransitionGroupComponent] +}) +export class TransitionGroupModule { + +} diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index ea878f347..35b504a22 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -10,7 +10,7 @@ "loginProviders": { "enabled": [1, 2, 3, 4, 5, 6, 7, 8], "facebookConfiguration": { "clientId": "" }, - "googleConfiguration": { "clientId": "" }, + "googleConfiguration": { "clientId": "524432312250-sc9qsmtmbvlv05r44onl6l93ia3k9deo.apps.googleusercontent.com" }, "linkedInConfiguration": { "clientId": "", "oauthUrl": "https://www.linkedin.com/oauth/v2/authorization", diff --git a/dmp-frontend/src/assets/i18n/de.json b/dmp-frontend/src/assets/i18n/de.json index 3a96f16ce..6497a015c 100644 --- a/dmp-frontend/src/assets/i18n/de.json +++ b/dmp-frontend/src/assets/i18n/de.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Add Conditional Question", "DELETE-INPUT": "Delete this input", "PREVIEW": "Preview", - "NOT-INITIALIZED": "Not initialized yet" + "NOT-INITIALIZED": "Not initialized yet", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Add input", diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 9d7750272..a146bbf73 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Make Conditional Question", "DELETE-INPUT": "Delete this input", "PREVIEW": "Preview", - "NOT-INITIALIZED": "Not initialized yet" + "NOT-INITIALIZED": "Not initialized yet", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Add input", diff --git a/dmp-frontend/src/assets/i18n/es.json b/dmp-frontend/src/assets/i18n/es.json index b8758d2a8..ec066abf0 100644 --- a/dmp-frontend/src/assets/i18n/es.json +++ b/dmp-frontend/src/assets/i18n/es.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Add Conditional Question", "DELETE-INPUT": "Delete this input", "PREVIEW": "Preview", - "NOT-INITIALIZED": "Not initialized yet" + "NOT-INITIALIZED": "Not initialized yet", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Add input", diff --git a/dmp-frontend/src/assets/i18n/gr.json b/dmp-frontend/src/assets/i18n/gr.json index bc4ca2531..ae060c04e 100644 --- a/dmp-frontend/src/assets/i18n/gr.json +++ b/dmp-frontend/src/assets/i18n/gr.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Add Conditional Question", "DELETE-INPUT": "Delete this input", "PREVIEW": "Preview", - "NOT-INITIALIZED": "Not initialized yet" + "NOT-INITIALIZED": "Not initialized yet", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Add input", diff --git a/dmp-frontend/src/assets/i18n/pt.json b/dmp-frontend/src/assets/i18n/pt.json index 684c00bcf..b6fefd66c 100644 --- a/dmp-frontend/src/assets/i18n/pt.json +++ b/dmp-frontend/src/assets/i18n/pt.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Adione Questão Condicionada", "DELETE-INPUT": "Eliminar este input", "PREVIEW": "Pré-visualização", - "NOT-INITIALIZED": "Ainda não iniciado" + "NOT-INITIALIZED": "Ainda não iniciado", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Adicionar novo input", diff --git a/dmp-frontend/src/assets/i18n/sk.json b/dmp-frontend/src/assets/i18n/sk.json index 10090dbaa..19d26b22c 100644 --- a/dmp-frontend/src/assets/i18n/sk.json +++ b/dmp-frontend/src/assets/i18n/sk.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Add Conditional Question", "DELETE-INPUT": "Delete this input", "PREVIEW": "Preview", - "NOT-INITIALIZED": "Not initialized yet" + "NOT-INITIALIZED": "Not initialized yet", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Add input", diff --git a/dmp-frontend/src/assets/i18n/sr.json b/dmp-frontend/src/assets/i18n/sr.json index 60a55825e..3627e2048 100644 --- a/dmp-frontend/src/assets/i18n/sr.json +++ b/dmp-frontend/src/assets/i18n/sr.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Add Conditional Question", "DELETE-INPUT": "Delete this input", "PREVIEW": "Preview", - "NOT-INITIALIZED": "Not initialized yet" + "NOT-INITIALIZED": "Not initialized yet", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Add input", diff --git a/dmp-frontend/src/assets/i18n/tr.json b/dmp-frontend/src/assets/i18n/tr.json index 9bc8613bd..eea5922d5 100644 --- a/dmp-frontend/src/assets/i18n/tr.json +++ b/dmp-frontend/src/assets/i18n/tr.json @@ -533,7 +533,9 @@ "ADD-VISIBILITY-RULE": "Add Conditional Question", "DELETE-INPUT": "Delete this input", "PREVIEW": "Preview", - "NOT-INITIALIZED": "Not initialized yet" + "NOT-INITIALIZED": "Not initialized yet", + "MOVE-UP": "Move this input above", + "MOVE-DOWN": "Move this input below" }, "FIELDSET": { "ADD-INPUT": "Add input", diff --git a/dmp-frontend/src/styles.scss b/dmp-frontend/src/styles.scss index b57d42eba..bd009402b 100644 --- a/dmp-frontend/src/styles.scss +++ b/dmp-frontend/src/styles.scss @@ -296,3 +296,8 @@ border: 1px solid #f44336 !important; } // end of CSS for (@kolkov/angular-editor) + +/* Transition Group */ +.list-move { + transition: transform 1s; +}