Merge branch 'WizardDescriptionRefactor' into Development

# Conflicts:
#	dmp-frontend/src/assets/i18n/pt.json
This commit is contained in:
Kristian Ntavidi 2021-04-06 10:28:25 +03:00
commit 49a15d2ccc
167 changed files with 11358 additions and 1028 deletions

View File

@ -31,6 +31,7 @@
"moment": "^2.24.0", "moment": "^2.24.0",
"moment-timezone": "^0.5.26", "moment-timezone": "^0.5.26",
"ng-dialog-animation": "^9.0.3", "ng-dialog-animation": "^9.0.3",
"ng2-dragula": "^2.1.1",
"ngx-cookie-service": "^2.2.0", "ngx-cookie-service": "^2.2.0",
"ngx-cookieconsent": "^2.2.3", "ngx-cookieconsent": "^2.2.3",
"ngx-dropzone": "^2.2.2", "ngx-dropzone": "^2.2.2",

View File

@ -2,7 +2,7 @@
import { of as observableOf, Subscription } from 'rxjs'; import { of as observableOf, Subscription } from 'rxjs';
import { switchMap, filter, map, takeUntil } from 'rxjs/operators'; import { switchMap, filter, map, takeUntil } from 'rxjs/operators';
import { Component, OnInit } from '@angular/core'; import { AfterViewInit, Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { environment } from '../environments/environment'; import { environment } from '../environments/environment';
@ -18,6 +18,8 @@ import { ConfigurationService } from './core/services/configuration/configuratio
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { MatomoInjector } from 'ngx-matomo'; import { MatomoInjector } from 'ngx-matomo';
import { MatomoService } from './core/services/matomo/matomo-service'; import { MatomoService } from './core/services/matomo/matomo-service';
import { SideNavService } from './core/services/sidenav/side-nav.sevice';
import { MatSidenav } from '@angular/material';
declare const gapi: any; declare const gapi: any;
@ -28,14 +30,17 @@ declare var $: any;
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'] styleUrls: ['./app.component.scss']
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit, AfterViewInit {
hasBreadCrumb = observableOf(false); hasBreadCrumb = observableOf(false);
sideNavOpen = false; // sideNavOpen = false;
private sideNavSubscription: Subscription;
helpContentEnabled: boolean; helpContentEnabled: boolean;
private statusChangeSubscription: Subscription; private statusChangeSubscription: Subscription;
onlySplash = true; onlySplash = true;
@ViewChild('sidenav', {static:false}) sidenav:MatSidenav;
constructor( constructor(
private router: Router, private router: Router,
private route: ActivatedRoute, private route: ActivatedRoute,
@ -49,12 +54,47 @@ export class AppComponent implements OnInit {
private language: LanguageService, private language: LanguageService,
private configurationService: ConfigurationService, private configurationService: ConfigurationService,
private location: Location, private location: Location,
private matomoService: MatomoService private matomoService: MatomoService,
private sidenavService: SideNavService
) { ) {
this.initializeServices(); this.initializeServices();
this.matomoService.init(); this.matomoService.init();
this.helpContentEnabled = configurationService.helpService.enabled; this.helpContentEnabled = configurationService.helpService.enabled;
} }
ngAfterViewInit(): void {
setTimeout(() => {
this.sideNavSubscription = this.sidenavService.status().subscribe(isopen=>{
const hamburger = document.getElementById('hamburger');
if(isopen){
//update value of hamburfer
if(!hamburger){//try later
setTimeout(() => {
const hamburger = document.getElementById('hamburger');
if(hamburger){
hamburger.classList.add('change');
}
}, 300);
}else{
hamburger.classList.add('change');
}
this.sidenav.open()
}else{//closed
if(!hamburger){//try later
setTimeout(() => {
const hamburger = document.getElementById('hamburger');
if(hamburger){
hamburger.classList.remove('change');
}
}, 300);
}else{
hamburger.classList.remove('change');
}
this.sidenav.close();
}
});
});
}
onActivate(event: any) { onActivate(event: any) {
this.breadCrumbResolverService.push(event); this.breadCrumbResolverService.push(event);
@ -79,7 +119,9 @@ export class AppComponent implements OnInit {
this.onlySplash = false; this.onlySplash = false;
} }
if (!this.cookieService.check("cookiesConsent")) { if (!this.cookieService.check("cookiesConsent")) {
this.cookieService.set("cookiesConsent", "false", 356); // this.cookieService.set("cookiesConsent", "false", 356);
this.cookieService.set("cookiesConsent", "false", 356,null,null,false, 'Lax');
} }
this.hasBreadCrumb = this.router.events.pipe( this.hasBreadCrumb = this.router.events.pipe(
@ -112,7 +154,8 @@ export class AppComponent implements OnInit {
this.statusChangeSubscription = this.ccService.statusChange$.subscribe((event: NgcStatusChangeEvent) => { this.statusChangeSubscription = this.ccService.statusChange$.subscribe((event: NgcStatusChangeEvent) => {
if (event.status == "dismiss") { if (event.status == "dismiss") {
this.cookieService.set("cookiesConsent", "true", 365); // this.cookieService.set("cookiesConsent", "true", 365);
this.cookieService.set("cookiesConsent", "true", 356,null,null,false, 'Lax');
} }
}); });
@ -134,7 +177,7 @@ export class AppComponent implements OnInit {
} }
this.ccService.destroy(); this.ccService.destroy();
this.ccService.init(this.ccService.getConfig()); this.ccService.init(this.ccService.getConfig());
}) });
} }
translateTitle(ttl: string) { translateTitle(ttl: string) {
@ -153,6 +196,9 @@ export class AppComponent implements OnInit {
ngOnDestroy() { ngOnDestroy() {
this.statusChangeSubscription.unsubscribe(); this.statusChangeSubscription.unsubscribe();
if(this.sideNavSubscription){
this.sideNavSubscription.unsubscribe();
}
} }
login() { login() {

View File

@ -32,6 +32,7 @@ import { TranslateServerLoader } from './core/services/language/server.loader';
import { MatomoService } from './core/services/matomo/matomo-service'; import { MatomoService } from './core/services/matomo/matomo-service';
import { GuidedTourModule } from './library/guided-tour/guided-tour.module'; import { GuidedTourModule } from './library/guided-tour/guided-tour.module';
import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module'; import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module';
import { DragulaModule } from 'ng2-dragula';
// AoT requires an exported function for factories // AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient, appConfig: ConfigurationService) { export function HttpLoaderFactory(http: HttpClient, appConfig: ConfigurationService) {
@ -107,7 +108,8 @@ const appearance: MatFormFieldDefaultOptions = {
SidebarModule, SidebarModule,
NgcCookieConsentModule.forRoot(cookieConfig), NgcCookieConsentModule.forRoot(cookieConfig),
Oauth2DialogModule, Oauth2DialogModule,
GuidedTourModule.forRoot() GuidedTourModule.forRoot(),
DragulaModule.forRoot()
], ],
declarations: [ declarations: [
AppComponent, AppComponent,

View File

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

View File

@ -6,12 +6,17 @@ export class DatasetIdModel {
type: string; type: string;
constructor(data: any) { constructor(data: any) {
try{
const parsed = JSON.parse(data); const parsed = JSON.parse(data);
if (!isNullOrUndefined(parsed)) { if (!isNullOrUndefined(parsed)) {
this.identifier = parsed.identifier; this.identifier = parsed.identifier;
this.type = parsed.type; this.type = parsed.type;
} }
} }
catch(error){
console.warn('Could not parse DatasetIdModel');
}
}
buildForm(): FormGroup { buildForm(): FormGroup {
return new FormBuilder().group({ return new FormBuilder().group({

View File

@ -1,6 +1,8 @@
import { AutoCompleteSingleData } from "@app/core/model/dataset-profile-definition/field-data/field-data";
import { BaseCriteria } from "../base-criteria"; import { BaseCriteria } from "../base-criteria";
export class DatasetExternalAutocompleteCriteria extends BaseCriteria { export class DatasetExternalAutocompleteCriteria extends BaseCriteria {
public profileID: String; public profileID: String;
public fieldID: String; public fieldID: String;
public autocompleteOptions: AutoCompleteSingleData;
} }

View File

@ -81,7 +81,8 @@ export class AuthService extends BaseService {
return this.http.post(url, loginInfo, { headers: this.headers }).pipe( return this.http.post(url, loginInfo, { headers: this.headers }).pipe(
map((res: any) => { map((res: any) => {
const principal = this.current(res.payload); const principal = this.current(res.payload);
this.cookieService.set('cookiesConsent', 'true', 356); // this.cookieService.set('cookiesConsent', 'true', 356);
this.cookieService.set("cookiesConsent", "true", 356,null,null,false, 'Lax');
//this.loginContextSubject.next(true); //this.loginContextSubject.next(true);
return principal; return principal;
}), }),
@ -105,7 +106,8 @@ export class AuthService extends BaseService {
return this.http.post(url, credentials, { headers: this.headers }).pipe( return this.http.post(url, credentials, { headers: this.headers }).pipe(
map((res: any) => { map((res: any) => {
const principal = this.current(res.payload); const principal = this.current(res.payload);
this.cookieService.set('cookiesConsent', 'true', 356); // this.cookieService.set('cookiesConsent', 'true', 356);
this.cookieService.set("cookiesConsent", "true", 356,null,null,false, 'Lax');
//this.loginContextSubject.next(true); //this.loginContextSubject.next(true);
return principal; return principal;
}), }),

View File

@ -1,11 +1,12 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable, of } from 'rxjs';
import { environment } from '../../../../environments/environment'; import { environment } from '../../../../environments/environment';
import { DatasetExternalAutocompleteCriteria } from '../../query/dataset/daatset-external-autocomplete-criteria'; import { DatasetExternalAutocompleteCriteria } from '../../query/dataset/daatset-external-autocomplete-criteria';
import { RequestItem } from '../../query/request-item'; import { RequestItem } from '../../query/request-item';
import { DatasetProfileService } from '../dataset-profile/dataset-profile.service'; import { DatasetProfileService } from '../dataset-profile/dataset-profile.service';
import { ConfigurationService } from '../configuration/configuration.service'; import { ConfigurationService } from '../configuration/configuration.service';
import { map } from 'rxjs/operators';
@Injectable() @Injectable()
export class DatasetExternalAutocompleteService { export class DatasetExternalAutocompleteService {
@ -27,4 +28,14 @@ export class DatasetExternalAutocompleteService {
return this.httpClient.post(this.configurationService.server + 'search/autocomplete', lookUpItem); return this.httpClient.post(this.configurationService.server + 'search/autocomplete', lookUpItem);
} }
queryApi(requestItem: RequestItem<DatasetExternalAutocompleteCriteria>):Observable<any>{ //TODO
return of([
{
label:'Preview not supported yet',
source:''
}
]);
}
} }

View File

@ -0,0 +1,24 @@
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { BehaviorSubject } from "rxjs";
@Injectable({
providedIn:'root'
})
export class SideNavService {
private sidebar$:BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
public status():Observable<boolean>{
return this.sidebar$.asObservable();
}
public setStatus(isOpen: boolean){
this.sidebar$.next(isOpen);
}
public toggle(){
this.sidebar$.next(!this.sidebar$.getValue());
}
}

View File

@ -12,6 +12,7 @@ import { DatasetProfileInternalDmpEntitiesType } from '../../common/enum/dataset
import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order'; import { RecentActivityOrder } from '@app/core/common/enum/recent-activity-order';
import { Role } from '@app/core/common/enum/role'; import { Role } from '@app/core/common/enum/role';
import { RoleOrganizationType } from '@app/core/common/enum/role-organization-type'; import { RoleOrganizationType } from '@app/core/common/enum/role-organization-type';
import { ViewStyleType } from '@app/ui/admin/dataset-profile/editor/components/field/view-style-enum';
@Injectable() @Injectable()
export class EnumUtils { export class EnumUtils {
@ -90,6 +91,30 @@ export class EnumUtils {
case DatasetProfileFieldViewStyle.Validation: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.VALIDATION'); case DatasetProfileFieldViewStyle.Validation: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.VALIDATION');
} }
} }
toDatasetProfileViewTypeString(status: ViewStyleType) :string{
switch (status) {
case ViewStyleType.BooleanDecision: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.BOOLEAN-DECISION');
case ViewStyleType.CheckBox: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.CHECKBOX');
case ViewStyleType.Select: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.SELECT');
case ViewStyleType.InternalDmpEntities: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.INTERNAL-DMP-ENTITIES');
case ViewStyleType.FreeText: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.FREE-TEXT');
case ViewStyleType.RadioBox: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.RADIO-BOX');
case ViewStyleType.TextArea: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.TEXT-AREA');
case ViewStyleType.DatePicker: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.DATE-PICKER');
case ViewStyleType.ExternalDatasets: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.EXTERNAL-DATASETS');
case ViewStyleType.DataRepositories: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.DATA-REPOSITORIES');
case ViewStyleType.Registries: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.REGISTRIES');
case ViewStyleType.Services: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.SERVICES');
case ViewStyleType.Tags: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.TAGS');
case ViewStyleType.Researchers: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.RESEARCHERS');
case ViewStyleType.Organizations: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.ORGANIZATIONS');
case ViewStyleType.DatasetIdentifier: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.DATASET-IDENTIFIER');
case ViewStyleType.Currency: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.CURRENCY');
case ViewStyleType.Validation: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.VALIDATION');
case ViewStyleType.Other: return this.language.instant('TYPES.DATASET-PROFILE-FIELD-VIEW-STYLE.OTHER');
}
}
toDatasetProfileComboBoxTypeString(status: DatasetProfileComboBoxType): string { toDatasetProfileComboBoxTypeString(status: DatasetProfileComboBoxType): string {
switch (status) { switch (status) {

View File

@ -10,7 +10,7 @@
</mat-chip> </mat-chip>
</ng-container> </ng-container>
</mat-chip-list> </mat-chip-list>
<input matInput #autocompleteInput class="col" [name]="id" autocomplete="off" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)"> <input matInput #autocompleteInput class="col" [class.hide-placeholder]="hidePlaceholder" [name]="id" autocomplete="off" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)">
<!-- The attribute autocomplete="nope", set by downshift, is ignored in Chrome 67 and Opera 54 (latest at the time of writing) <!-- The attribute autocomplete="nope", set by downshift, is ignored in Chrome 67 and Opera 54 (latest at the time of writing)
<input matInput #autocompleteInput class="col" [name]="id" autocomplete="nope" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)"> --> <input matInput #autocompleteInput class="col" [name]="id" autocomplete="nope" #autocompleteTrigger="matAutocompleteTrigger" [placeholder]="placeholder" [matAutocomplete]="autocomplete" [value]="inputValue" (keyup)="onKeyUp($event)" (keydown)="onKeyDown($event)" [disabled]="disabled" (focus)="_onInputFocus()" (blur)="onBlur($event)" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="autoSelectFirstOptionOnBlur" (matChipInputTokenEnd)="_addItem($event)"> -->
<mat-icon *ngIf="!disabled" class="align-arrow-right" matSuffix>arrow_drop_down</mat-icon> <mat-icon *ngIf="!disabled" class="align-arrow-right" matSuffix>arrow_drop_down</mat-icon>

View File

@ -44,3 +44,24 @@
max-height: 4.8em !important; max-height: 4.8em !important;
overflow: auto !important; overflow: auto !important;
} }
.hide-placeholder{
&::-webkit-input-placeholder {
/* WebKit browsers */
color: transparent;
}
&:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: transparent;
}
&::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: transparent;
}
&:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: transparent;
}
&::placeholder {
color: transparent;
}
}

View File

@ -66,6 +66,7 @@ export class MultipleAutoCompleteComponent extends _CustomComponentMixinBase imp
get shouldLabelFloat() { return this.focused || !this.empty; } get shouldLabelFloat() { return this.focused || !this.empty; }
@Input() hidePlaceholder: boolean = false;
@Input() @Input()
get placeholder() { return this._placeholder; } get placeholder() { return this._placeholder; }
set placeholder(placeholder) { set placeholder(placeholder) {

View File

@ -388,7 +388,10 @@ export class GuidedTourComponent implements AfterViewInit, OnDestroy {
} }
const scrollAdjustment = this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0; const scrollAdjustment = this.currentTourStep.scrollAdjustment ? this.currentTourStep.scrollAdjustment : 0;
const tourStepHeight = typeof this.tourStep.nativeElement.getBoundingClientRect === 'function' ? this.tourStep.nativeElement.getBoundingClientRect().height : 0; let tourStepHeight = 0;
if (this.tourStep != null && this.tourStep.nativeElement != null && typeof this.tourStep.nativeElement.getBoundingClientRect === 'function') {
tourStepHeight = this.tourStep.nativeElement.getBoundingClientRect().height;
}
const elementHeight = this.selectedElementRect.height + scrollAdjustment + tourStepHeight; const elementHeight = this.selectedElementRect.height + scrollAdjustment + tourStepHeight;
if ((this.windowRef.nativeWindow.innerHeight - this.topOfPageAdjustment) < elementHeight) { if ((this.windowRef.nativeWindow.innerHeight - this.topOfPageAdjustment) < elementHeight) {

View File

@ -1,7 +1,7 @@
import { FieldDataEditorModel } from './field-data-editor-model'; import { FieldDataEditorModel } from './field-data-editor-model';
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 { FieldDataOptionEditorModel } from './field-data-option-editor-model'; import { FieldDataOptionEditorModel } from './field-data-option-editor-model';
import { FormGroup } from '@angular/forms'; import { FormGroup, Validators } from '@angular/forms';
import { AutoCompleteFieldData, AutoCompleteSingleData } from '@app/core/model/dataset-profile-definition/field-data/field-data'; import { AutoCompleteFieldData, AutoCompleteSingleData } from '@app/core/model/dataset-profile-definition/field-data/field-data';
export class AutoCompleteSingleDataEditorModel extends FieldDataEditorModel<AutoCompleteSingleDataEditorModel> { export class AutoCompleteSingleDataEditorModel extends FieldDataEditorModel<AutoCompleteSingleDataEditorModel> {
@ -16,8 +16,8 @@ export class AutoCompleteSingleDataEditorModel extends FieldDataEditorModel<Auto
buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup { buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup {
const formGroup = this.formBuilder.group({ const formGroup = this.formBuilder.group({
label: [{ value: this.label, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.label')) }], label: [{ value: this.label, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.label')) }],
url: [{ value: this.url, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.url')) }], url: [{ value: this.url, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.url')) },[Validators.required]],
optionsRoot: [{ value: this.optionsRoot, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.optionsRoot')) }], optionsRoot: [{ value: this.optionsRoot, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.optionsRoot')) }, [Validators.required]],
autoCompleteType: [{ value: this.autoCompleteType, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.autoCompleteType')) }] autoCompleteType: [{ value: this.autoCompleteType, disabled: (disabled && !skipDisable.includes('AutoCompleteSingleDataEditorModel.autoCompleteType')) }]
}); });
formGroup.addControl('autoCompleteOptions', this.autoCompleteOptions.buildForm(disabled, skipDisable)); formGroup.addControl('autoCompleteOptions', this.autoCompleteOptions.buildForm(disabled, skipDisable));

View File

@ -1,4 +1,4 @@
import { FormBuilder, FormGroup } from '@angular/forms'; import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FieldDataOption } from '../../../../../core/model/dataset-profile-definition/field-data/field-data'; import { FieldDataOption } from '../../../../../core/model/dataset-profile-definition/field-data/field-data';
import { FieldDataEditorModel } from './field-data-editor-model'; import { FieldDataEditorModel } from './field-data-editor-model';
@ -9,8 +9,8 @@ export class FieldDataOptionEditorModel extends FieldDataEditorModel<FieldDataOp
buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup { buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup {
return new FormBuilder().group({ return new FormBuilder().group({
label: [{ value: this.label, disabled: (disabled && !skipDisable.includes('FieldDataOptionEditorModel.label')) }], label: [{ value: this.label, disabled: (disabled && !skipDisable.includes('FieldDataOptionEditorModel.label')) },[Validators.required]],
value: [{ value: this.value, disabled: (disabled && !skipDisable.includes('FieldDataOptionEditorModel.value')) }], value: [{ value: this.value, disabled: (disabled && !skipDisable.includes('FieldDataOptionEditorModel.value')) },[Validators.required]],
source: [{ value: this.source, disabled: (disabled && !skipDisable.includes('FieldDataOptionEditorModel.source')) }] source: [{ value: this.source, disabled: (disabled && !skipDisable.includes('FieldDataOptionEditorModel.source')) }]
}); });
} }

View File

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

View File

@ -27,6 +27,9 @@ import { ResearchersDataEditorModel } from './field-data/researchers-data-editor
import { OrganizationsDataEditorModel } from './field-data/organizations-data-editor-models'; import { OrganizationsDataEditorModel } from './field-data/organizations-data-editor-models';
import { DatasetIdentifierDataEditorModel } from './field-data/dataset-identifier-data-editor-models'; import { DatasetIdentifierDataEditorModel } from './field-data/dataset-identifier-data-editor-models';
import { CurrencyDataEditorModel } from './field-data/currency-data-editor-models'; import { CurrencyDataEditorModel } from './field-data/currency-data-editor-models';
import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profile-combo-box-type';
import { EditorCustomValidators } from '../editor/custom-validators/editor-custom-validators';
import { ValidationDataEditorModel } from './field-data/validation-data-editor-models';
export class FieldEditorModel extends BaseFormModel { export class FieldEditorModel extends BaseFormModel {
@ -68,13 +71,14 @@ export class FieldEditorModel extends BaseFormModel {
if (this.viewStyle.renderStyle === 'datePicker') { this.data = new DatePickerDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'datePicker') { this.data = new DatePickerDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'externalDatasets') { this.data = new ExternalDatasetsDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'externalDatasets') { this.data = new ExternalDatasetsDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'dataRepositories') { this.data = new DataRepositoriesDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'dataRepositories') { this.data = new DataRepositoriesDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'registeries') { this.data = new RegistriesDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'registries') { this.data = new RegistriesDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'services') { this.data = new ServicesDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'services') { this.data = new ServicesDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'tags') { this.data = new TagsDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'tags') { this.data = new TagsDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'researchers') { this.data = new ResearchersDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'researchers') { this.data = new ResearchersDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'organizations') { this.data = new OrganizationsDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'organizations') { this.data = new OrganizationsDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'datasetIdentifier') { this.data = new DatasetIdentifierDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'datasetIdentifier') { this.data = new DatasetIdentifierDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'currency') { this.data = new CurrencyDataEditorModel().fromModel(item.data); } if (this.viewStyle.renderStyle === 'currency') { this.data = new CurrencyDataEditorModel().fromModel(item.data); }
if (this.viewStyle.renderStyle === 'validation') { this.data = new ValidationDataEditorModel().fromModel(item.data); }
} }
} }
return this; return this;
@ -96,6 +100,57 @@ export class FieldEditorModel extends BaseFormModel {
if (this.data) { formGroup.addControl('data', this.data.buildForm(disabled, skipDisable)); } if (this.data) { formGroup.addControl('data', this.data.buildForm(disabled, skipDisable)); }
else { formGroup.addControl('data', new WordListFieldDataEditorModel().buildForm(disabled, skipDisable)); } else { formGroup.addControl('data', new WordListFieldDataEditorModel().buildForm(disabled, skipDisable)); }
// //append validators
this._appendCustomValidators(formGroup);
// //setting up listeners
// formGroup.get('viewStyle').valueChanges.subscribe(changes=>{
// // const viewStyleChanges:{cssClass:string, renderStyle: string} = changes;
// this._removeCustomValidators(formGroup);
// this._appendCustomValidators(formGroup);
// })
return formGroup; return formGroup;
} }
private _appendCustomValidators(formGroup: FormGroup){
const renderStyleValue = formGroup.get('viewStyle').get('renderStyle').value;
if(renderStyleValue === 'checkBox'){
formGroup.get('defaultValue').get('value').setValidators(Validators.required);
formGroup.get('defaultValue').get('value').updateValueAndValidity();
}else if(renderStyleValue === 'combobox'){
try{
const comboType = formGroup.get('data').get('type').value;
if(comboType === DatasetProfileComboBoxType.Autocomplete){//As 'Other' in UI
formGroup.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('autoCompleteSingleDataList'));
}else if(comboType === DatasetProfileComboBoxType.WordList){
formGroup.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('options'));
}
}catch(e){
console.error('Error setting validators.');
console.error(e);
}
}else if(renderStyleValue === 'radiobox'){
formGroup.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('options'));
}
formGroup.get('data').updateValueAndValidity();
}
// private _removeCustomValidators(formGroup:FormGroup){
// const renderStyleValue = formGroup.get('viewStyle').get('renderStyle').value;
// if(renderStyleValue != 'checkBox'){
// formGroup.get('defaultValue').get('value').clearValidators();
// }else if(renderStyleValue === 'combobox'){
// formGroup.get('data').clearValidators();
// }
// }
// private _buildData(formGroup: FormGroup){
// }
} }

View File

@ -35,7 +35,7 @@ export class FieldSetEditorModel extends BaseFormModel {
const formGroup = this.formBuilder.group({ const formGroup = this.formBuilder.group({
id: [{ value: this.id, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.id')) }, [Validators.required, Validators.pattern('^[^<_>]+$')]], id: [{ value: this.id, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.id')) }, [Validators.required, Validators.pattern('^[^<_>]+$')]],
ordinal: [{ value: this.ordinal, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.ordinal')) }], ordinal: [{ value: this.ordinal, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.ordinal')) }],
title: [{ value: this.title, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.title')) }], title: [{ value: this.title, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.title')) }, [Validators.required]],
description: [{ value: this.description, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.description')) }], description: [{ value: this.description, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.description')) }],
extendedDescription: [{ value: this.extendedDescription, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.extendedDescription')) }], extendedDescription: [{ value: this.extendedDescription, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.extendedDescription')) }],
additionalInformation: [{ value: this.additionalInformation, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.additionalInformation')) }], additionalInformation: [{ value: this.additionalInformation, disabled: (disabled && !skipDisable.includes('FieldSetEditorModel.additionalInformation')) }],

View File

@ -1,4 +1,4 @@
import { FormGroup } from "@angular/forms"; import { FormGroup, Validators } from "@angular/forms";
import { Rule } from "../../../../core/model/admin/dataset-profile/dataset-profile"; import { Rule } from "../../../../core/model/admin/dataset-profile/dataset-profile";
import { BaseFormModel } from "../../../../core/model/base-form-model"; import { BaseFormModel } from "../../../../core/model/base-form-model";
@ -21,9 +21,9 @@ export class RuleEditorModel extends BaseFormModel {
buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup { buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup {
const formGroup = this.formBuilder.group({ const formGroup = this.formBuilder.group({
// sourceField: [this.sourceField], // sourceField: [this.sourceField],
target: [{ value: this.target, disabled: (disabled && !skipDisable.includes('RuleEditorModel.target')) }], target: [{ value: this.target, disabled: (disabled && !skipDisable.includes('RuleEditorModel.target')) }, [Validators.required]],
ruleStyle: [{ value: this.ruleStyle, disabled: (disabled && !skipDisable.includes('RuleEditorModel.ruleStyle')) }], ruleStyle: [{ value: this.ruleStyle, disabled: (disabled && !skipDisable.includes('RuleEditorModel.ruleStyle')) }],
value: [{ value: this.value, disabled: (disabled && !skipDisable.includes('RuleEditorModel.value')) }], value: [{ value: this.value, disabled: (disabled && !skipDisable.includes('RuleEditorModel.value')) }, [Validators.required]],
ruleType: [{ value: this.ruleType, disabled: (disabled && !skipDisable.includes('RuleEditorModel.ruleType')) }], ruleType: [{ value: this.ruleType, disabled: (disabled && !skipDisable.includes('RuleEditorModel.ruleType')) }],
valueType: [{ value: this.valueType, disabled: (disabled && !skipDisable.includes('RuleEditorModel.valueType')) }] valueType: [{ value: this.valueType, disabled: (disabled && !skipDisable.includes('RuleEditorModel.valueType')) }]
}); });

View File

@ -1,6 +1,7 @@
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms'; import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { Section } from '../../../../core/model/admin/dataset-profile/dataset-profile'; import { Section } from '../../../../core/model/admin/dataset-profile/dataset-profile';
import { BaseFormModel } from '../../../../core/model/base-form-model'; import { BaseFormModel } from '../../../../core/model/base-form-model';
import { EditorCustomValidators } from '../editor/custom-validators/editor-custom-validators';
import { FieldSetEditorModel } from './field-set-editor-model'; import { FieldSetEditorModel } from './field-set-editor-model';
export class SectionEditorModel extends BaseFormModel { export class SectionEditorModel extends BaseFormModel {
@ -29,7 +30,7 @@ export class SectionEditorModel extends BaseFormModel {
const formGroup: FormGroup = new FormBuilder().group({ const formGroup: FormGroup = new FormBuilder().group({
id: [{ value: this.id, disabled: (disabled && !skipDisable.includes('SectionEditorModel.id')) }, [Validators.required, Validators.pattern('^[^<_>]+$')]], id: [{ value: this.id, disabled: (disabled && !skipDisable.includes('SectionEditorModel.id')) }, [Validators.required, Validators.pattern('^[^<_>]+$')]],
page: [{ value: this.page, disabled: (disabled && !skipDisable.includes('SectionEditorModel.page')) }, [Validators.required]], page: [{ value: this.page, disabled: (disabled && !skipDisable.includes('SectionEditorModel.page')) }, [Validators.required]],
title: [{ value: this.title, disabled: (disabled && !skipDisable.includes('SectionEditorModel.title')) }], title: [{ value: this.title, disabled: (disabled && !skipDisable.includes('SectionEditorModel.title')) } , [Validators.required]],
description: [{ value: this.description, disabled: (disabled && !skipDisable.includes('SectionEditorModel.description')) }], description: [{ value: this.description, disabled: (disabled && !skipDisable.includes('SectionEditorModel.description')) }],
ordinal: [{ value: this.ordinal, disabled: (disabled && !skipDisable.includes('SectionEditorModel.ordinal')) }, [Validators.required]], ordinal: [{ value: this.ordinal, disabled: (disabled && !skipDisable.includes('SectionEditorModel.ordinal')) }, [Validators.required]],
defaultVisibility: [{ value: this.defaultVisibility, disabled: (disabled && !skipDisable.includes('SectionEditorModel.defaultVisibility')) }] defaultVisibility: [{ value: this.defaultVisibility, disabled: (disabled && !skipDisable.includes('SectionEditorModel.defaultVisibility')) }]
@ -53,6 +54,8 @@ export class SectionEditorModel extends BaseFormModel {
if (!formGroup.controls['defaultVisibility'].value) { formGroup.controls['defaultVisibility'].setValue(true); } if (!formGroup.controls['defaultVisibility'].value) { formGroup.controls['defaultVisibility'].setValue(true); }
formGroup.setValidators(EditorCustomValidators.sectionHasAtLeastOneChildOf('fieldSets','sections'));
formGroup.updateValueAndValidity();
return formGroup; return formGroup;
} }
} }

View File

@ -1,4 +1,4 @@
import { FormGroup } from "@angular/forms"; import { FormGroup, Validators } from "@angular/forms";
import { ViewStyle } from "../../../../core/model/admin/dataset-profile/dataset-profile"; import { ViewStyle } from "../../../../core/model/admin/dataset-profile/dataset-profile";
import { BaseFormModel } from "../../../../core/model/base-form-model"; import { BaseFormModel } from "../../../../core/model/base-form-model";
@ -15,7 +15,7 @@ export class ViewStyleEditorModel extends BaseFormModel {
buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup { buildForm(disabled: boolean = false, skipDisable: Array<String> = []): FormGroup {
const formGroup = this.formBuilder.group({ const formGroup = this.formBuilder.group({
cssClass: [{ value: this.cssClass, disabled: (disabled && !skipDisable.includes('ViewStyleEditorModel.cssClass')) }], cssClass: [{ value: this.cssClass, disabled: (disabled && !skipDisable.includes('ViewStyleEditorModel.cssClass')) }],
renderStyle: [{ value: this.renderStyle, disabled: (disabled && !skipDisable.includes('ViewStyleEditorModel.renderStyle')) }] renderStyle: [{ value: this.renderStyle, disabled: (disabled && !skipDisable.includes('ViewStyleEditorModel.renderStyle')) }, Validators.required]
}); });
return formGroup; return formGroup;
} }

View File

@ -1,6 +1,5 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormattingModule } from '@app/core/formatting.module'; import { FormattingModule } from '@app/core/formatting.module';
import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module';
import { DatasetProfileRoutingModule } from '@app/ui/admin/dataset-profile/dataset-profile.routing'; import { DatasetProfileRoutingModule } from '@app/ui/admin/dataset-profile/dataset-profile.routing';
import { DatasetProfileEditorCompositeFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component'; import { DatasetProfileEditorCompositeFieldComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-field/dataset-profile-editor-composite-field.component';
import { DatasetProfileEditorDefaultValueComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-profile-editor-default-value/component-profile-editor-default-value.component'; import { DatasetProfileEditorDefaultValueComponent } from '@app/ui/admin/dataset-profile/editor/components/composite-profile-editor-default-value/component-profile-editor-default-value.component';
@ -23,21 +22,38 @@ import { DatasetProfileEditorRuleComponent } from '@app/ui/admin/dataset-profile
import { DatasetProfileEditorSectionComponent } from '@app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component'; import { DatasetProfileEditorSectionComponent } from '@app/ui/admin/dataset-profile/editor/components/section/dataset-profile-editor-section.component';
import { DatasetProfileEditorComponent } from '@app/ui/admin/dataset-profile/editor/dataset-profile-editor.component'; import { DatasetProfileEditorComponent } from '@app/ui/admin/dataset-profile/editor/dataset-profile-editor.component';
import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component'; import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component';
import { DialodConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; import { DialogConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component';
import { DatasetProfileListingComponent } from '@app/ui/admin/dataset-profile/listing/dataset-profile-listing.component'; import { DatasetProfileListingComponent } from '@app/ui/admin/dataset-profile/listing/dataset-profile-listing.component';
import { DatasetModule } from '@app/ui/dataset/dataset.module';
import { FormProgressIndicationModule } from '@app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module';
import { TableOfContentsModule } from '@app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents.module';
import { CommonFormsModule } from '@common/forms/common-forms.module'; import { CommonFormsModule } from '@common/forms/common-forms.module';
import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module';
import { CommonUiModule } from '@common/ui/common-ui.module'; import { CommonUiModule } from '@common/ui/common-ui.module';
import { ParseStatus } from './listing/pipe/parse-status.pipe'; import { AngularStickyThingsModule } from '@w11k/angular-sticky-things';
import { DatasetProfileEditorExternalDatasetsFieldComponent } from './editor/components/field-type/external-datasets/dataset-profile-editor-external-datasets-field.component'; import { DatasetProfileEditorCurrencyFieldComponent } from './editor/components/field-type/currency/dataset-profile-editor-currency-field.component';
import { DatasetProfileEditorDataRepositoriesFieldComponent } from './editor/components/field-type/data-repositories/dataset-profile-editor-data-repositories-field.component'; import { DatasetProfileEditorDataRepositoriesFieldComponent } from './editor/components/field-type/data-repositories/dataset-profile-editor-data-repositories-field.component';
import { DatasetProfileEditorDatasetIdentifierFieldComponent } from './editor/components/field-type/dataset-identifier/dataset-profile-editor-dataset-identifier-field.component';
import { DatasetProfileEditorExternalDatasetsFieldComponent } from './editor/components/field-type/external-datasets/dataset-profile-editor-external-datasets-field.component';
import { DatasetProfileEditorOrganizationsFieldComponent } from './editor/components/field-type/organizations/dataset-profile-editor-organizations-field.component';
import { DatasetProfileEditorRegistriesFieldComponent } from './editor/components/field-type/registries/dataset-profile-editor-registries-field.component'; import { DatasetProfileEditorRegistriesFieldComponent } from './editor/components/field-type/registries/dataset-profile-editor-registries-field.component';
import { DatasetProfileEditorResearchersFieldComponent } from './editor/components/field-type/researchers/dataset-profile-editor-researchers-field.component';
import { DatasetProfileEditorServicesFieldComponent } from './editor/components/field-type/services/dataset-profile-editor-services-field.component'; import { DatasetProfileEditorServicesFieldComponent } from './editor/components/field-type/services/dataset-profile-editor-services-field.component';
import { DatasetProfileEditorTagsFieldComponent } from './editor/components/field-type/tags/dataset-profile-editor-tags-field.component'; import { DatasetProfileEditorTagsFieldComponent } from './editor/components/field-type/tags/dataset-profile-editor-tags-field.component';
import { DatasetProfileEditorResearchersFieldComponent } from './editor/components/field-type/researchers/dataset-profile-editor-researchers-field.component';
import { DatasetProfileEditorOrganizationsFieldComponent } from './editor/components/field-type/organizations/dataset-profile-editor-organizations-field.component';
import { DatasetProfileEditorDatasetIdentifierFieldComponent } from './editor/components/field-type/dataset-identifier/dataset-profile-editor-dataset-identifier-field.component';
import { DatasetProfileEditorCurrencyFieldComponent } from './editor/components/field-type/currency/dataset-profile-editor-currency-field.component';
import { DatasetProfileEditorValidatorFieldComponent } from './editor/components/field-type/validator/dataset-profile-editor-validator-field.component'; import { DatasetProfileEditorValidatorFieldComponent } from './editor/components/field-type/validator/dataset-profile-editor-validator-field.component';
import { NgxDropzoneModule } from 'ngx-dropzone';
import { ParseStatus } from './listing/pipe/parse-status.pipe';
import { DatasetProfileTableOfContents } from './table-of-contents/table-of-contents';
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';
import {DragulaModule} from 'ng2-dragula';
//matrial
import {MatBadgeModule} from '@angular/material/badge';
import { DatasetProfileEditorSectionFieldSetComponent } from './editor/components/section-fieldset/dataset-profile-editor-section-fieldset.component';
import { FinalPreviewComponent } from './editor/components/final-preview/final-preview.component';
@NgModule({ @NgModule({
imports: [ imports: [
@ -45,7 +61,14 @@ import { DatasetProfileEditorValidatorFieldComponent } from './editor/components
CommonFormsModule, CommonFormsModule,
FormattingModule, FormattingModule,
DatasetProfileRoutingModule, DatasetProfileRoutingModule,
ConfirmationDialogModule ConfirmationDialogModule,
NgxDropzoneModule,
FormProgressIndicationModule,
DatasetModule,
AngularStickyThingsModule,
DragDropModule,
MatBadgeModule,
DragulaModule
], ],
declarations: [ declarations: [
DatasetProfileListingComponent, DatasetProfileListingComponent,
@ -66,7 +89,7 @@ import { DatasetProfileEditorValidatorFieldComponent } from './editor/components
DatasetProfileEditorDatePickerFieldComponent, DatasetProfileEditorDatePickerFieldComponent,
DatasetProfileEditorWordListFieldComponent, DatasetProfileEditorWordListFieldComponent,
DatasetProfileEditorDefaultValueComponent, DatasetProfileEditorDefaultValueComponent,
DialodConfirmationUploadDatasetProfiles, DialogConfirmationUploadDatasetProfiles,
DatasetProfileEditorInternalDmpEntitiesFieldComponent, DatasetProfileEditorInternalDmpEntitiesFieldComponent,
DatasetProfileEditorResearchersAutoCompleteFieldComponent, DatasetProfileEditorResearchersAutoCompleteFieldComponent,
DatasetProfileEditorDatasetsAutoCompleteFieldComponent, DatasetProfileEditorDatasetsAutoCompleteFieldComponent,
@ -81,10 +104,14 @@ import { DatasetProfileEditorValidatorFieldComponent } from './editor/components
DatasetProfileEditorOrganizationsFieldComponent, DatasetProfileEditorOrganizationsFieldComponent,
DatasetProfileEditorDatasetIdentifierFieldComponent, DatasetProfileEditorDatasetIdentifierFieldComponent,
DatasetProfileEditorCurrencyFieldComponent, DatasetProfileEditorCurrencyFieldComponent,
DatasetProfileEditorValidatorFieldComponent DatasetProfileEditorValidatorFieldComponent,
DatasetProfileTableOfContents,
DatasetProfileTableOfContentsInternalSection,
DatasetProfileEditorSectionFieldSetComponent,
FinalPreviewComponent
], ],
entryComponents: [ entryComponents: [
DialodConfirmationUploadDatasetProfiles DialogConfirmationUploadDatasetProfiles
] ]
}) })
export class DatasetProfileModule { } export class DatasetProfileModule { }

View File

@ -0,0 +1,64 @@
import { animate, keyframes, state, style, transition, trigger } from "@angular/animations";
export const STEPPER_ANIMATIONS = [
trigger('previous_btn',[
transition(':enter',[
style({'transform': 'translateX(100%)', 'z-index':'9999', 'opacity':0.4}),
animate('600ms ease-out', style({
'transform': 'translateX(0)',
'opacity':1
}))
]),
transition(':leave',[
style({
'transform': 'translateX(0)',
'opacity':'1',
'z-index':'9999'
}),
animate('800ms ease-out', keyframes([
style({'transform': 'translateX(120%)', offset:0.8}),
style({'opacity': '0.2', offset:0.96})
]))
])
]),
trigger('next_btn', [
transition(':leave',[
style({opacity:1, position:'absolute', 'z-index':'9999'}),
animate('700ms ease-out', keyframes( [
style({ transform:'translateX(-100%)', offset:0.6}),
style({ opacity:'0.2', offset:0.87})
]))
]),
transition(':enter',[
style({opacity:0.3, 'z-index':'9999', transform:'translateX(-100%)'}),
animate('600ms ease-out', style({ opacity:'1', transform:'translateX(0)' }))
])
]),
trigger('finalize_btn',[
transition(':enter',[
style({opacity:0.3}),
animate('400ms ease-in', style({opacity:1}))
]),
transition(':leave',[
style({opacity:1, position:'absolute'}),
animate('600ms ease-in', style({opacity:0.3}))
])
])
];
export const GENERAL_ANIMATIONS = [
trigger('enterIn',[
transition(':enter',[
style({
transform:'scale(0)',
'transform-origin':'50% 0',
opacity:0
}),
animate('800ms ease', style({transform:'scale(1)', opacity:1}))
])
]),
trigger('fadeElement',[
state('updated',style({opacity:0})),
transition("*=>updated",
animate('2s 1s ease-out'))
])
]

View File

@ -1,11 +1,17 @@
<div class="row">
<!-- TO LINK -->
<!-- <div class="row">
<h4 *ngIf="isComposite" class="col-auto titleStile">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.TITLE' | translate}}</h4> <h4 *ngIf="isComposite" class="col-auto titleStile">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.TITLE' | translate}}</h4>
<h4 *ngIf="!isComposite" class="col-auto titleStile">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.SIMPLE-FIELD-TITLE' | translate}}</h4> <h4 *ngIf="!isComposite" class="col-auto titleStile">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.SIMPLE-FIELD-TITLE' | translate}}</h4>
<mat-checkbox class="col-auto" [(ngModel)]="isComposite" (ngModelChange)="onIsCompositeChange(isComposite)" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.COMPOSITE-CHECKBOX' | translate}}</mat-checkbox> <mat-checkbox class="col-auto" [(ngModel)]="isComposite" (ngModelChange)="onIsCompositeChange(isComposite)" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.COMPOSITE-CHECKBOX' | translate}}</mat-checkbox>
<mat-checkbox class="col-auto" [(ngModel)]="isMultiplicityEnabled" (ngModelChange)="onIsMultiplicityEnabledChange(isMultiplicityEnabled)" <mat-checkbox class="col-auto" [(ngModel)]="isMultiplicityEnabled" (ngModelChange)="onIsMultiplicityEnabledChange(isMultiplicityEnabled)"
[disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.MULTIPLICITY-CHECKBOX' | translate}}</mat-checkbox> [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.MULTIPLICITY-CHECKBOX' | translate}}</mat-checkbox>
<mat-checkbox class="col" [formControl]="this.form.get('hasCommentField')">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.COMMENT-CHECKBOX' | translate}}</mat-checkbox> <mat-checkbox class="col" [formControl]="this.form.get('hasCommentField')">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.COMMENT-CHECKBOX' | translate}}</mat-checkbox>
</div> </div> -->
<!-- TO LINK -->
<!--
<div class="row"> <div class="row">
<mat-form-field *ngIf="isComposite" class="col"> <mat-form-field *ngIf="isComposite" class="col">
<input matInput type="string" placeholder="Id" [formControl]="form.get('id')" required> <input matInput type="string" placeholder="Id" [formControl]="form.get('id')" required>
@ -36,34 +42,124 @@
<input matInput type="number" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ORDER' | translate}}" <input matInput type="number" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ORDER' | translate}}"
[formControl]="this.form.get('ordinal')" required> [formControl]="this.form.get('ordinal')" required>
</mat-form-field> </mat-form-field>
</div> -->
<!-- ID TOP RIGHT CORNER -->
<!-- <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> -->
<!-- MAIN CONTENT -->
<div class="main-content-page" [ngClass]="{'pb-2': !hasFocus}">
<!-- TITLE -->
<div class="col-12">
<div class="row fielset-header">
<!-- <div class="col-auto d-flex">
<div class="align-self-center">
{{numbering}}
</div> </div>
<div class="row"> </div> -->
<mat-form-field class="col"> <mat-form-field appearance="none" class="numbering-label" [ngStyle]="calculateLabelWidth(numbering)">
<textarea matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION' | translate}}" <input [ngClass]="{'text-danger':form.get('title').invalid &&form.get('title').touched}" matInput type="text" [value]="numbering" disabled>
[formControl]="this.form.get('description')"></textarea> </mat-form-field>
<!-- [appearance]="titleControl.focused? 'legacy':'none'" floatLabel="never" -->
<mat-form-field class="col field-title" [appearance]="'none'" floatLabel="never">
<input matInput type="text" [placeholder]="('DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' |translate)+' '+('DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.QUESTION'| translate)" #titleControl="matInput"
[formControl]="this.form.get('title')">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="row"> </div>
<mat-form-field class="col"> <div style="position: relative;" class="col-8">
<textarea matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION' | translate}}"
[formControl]="this.form.get('extendedDescription')"></textarea>
<ng-container *ngIf="hasFocus">
<div class="row" *ngIf="showDescription">
<mat-form-field class="col p-0 underline-line-field" appearance="legacy">
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION' | translate}}"
[formControl]="this.form.get('description')">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="row"> <div class="row" *ngIf="showExtendedDescription">
<mat-form-field class="col"> <mat-form-field class="col p-0 underline-line-field" appearance="legacy">
<textarea matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ADDITIONAL-INFORMATION' | translate}}" <input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION' | translate}}"
[formControl]="this.form.get('additionalInformation')"></textarea> [formControl]="this.form.get('extendedDescription')"/>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="row"> <div class="row" *ngIf="showAdditionalInfo">
<app-dataset-profile-editor-field-component class="col-12" *ngIf="!isComposite" [form]="form.get('fields').get(''+0)" [showOrdinal]="false" <mat-form-field class="col p-0 underline-line-field" appearance="legacy">
[indexPath]="indexPath + 'f' + 0" [viewOnly]="viewOnly"></app-dataset-profile-editor-field-component> <input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ADDITIONAL-INFORMATION' | translate}}"
[formControl]="this.form.get('additionalInformation')"/>
</mat-form-field>
</div> </div>
<div class="row">
<mat-form-field *ngIf="isMultiplicityEnabled" class="col pl-0 underline-line-field" appearance="legacy">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.MULTIPLICITY-MIN' | translate}}"
type="number" [formControl]="form.get('multiplicity').get('min')" required>
<mat-error *ngIf="form.get('multiplicity').get('min').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}
</mat-error>
</mat-form-field>
<mat-form-field *ngIf="isMultiplicityEnabled" class="col pr-0 underline-line-field" appearance="legacy">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.MULTIPLICITY-MAX' | translate}}"
type="number" [formControl]="this.form.get('multiplicity').get('max')" required>
<mat-error *ngIf="form.get('multiplicity').get('max').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}
</mat-error>
</mat-form-field>
</div>
</ng-container>
</div>
<!-- FIELDS DETAILS AND ACTIONS -->
<div class="row">
<!-- FIELDS -->
<div class="col">
<div class="">
<ng-container *ngFor="let field of form.get('fields')['controls']; let i=index" >
<div class="row bg-white" style="position: relative;" (click)="setTargetField(field)"
>
<!-- field-container -->
<!-- [ngClass]="{'field-container-active': (field.get('id').value === targetField?.get('id').value) && hasFocus}" -->
<!-- <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> -->
<!-- *ngIf="!isComposite" -->
<app-dataset-profile-editor-field-component class="col-12"
[form]="form.get('fields').get(''+i)" [showOrdinal]="false"
[indexPath]="indexPath + 'f' + i" [viewOnly]="viewOnly"
[expandView]="hasFocus"
[canBeDeleted]="form.get('fields')['controls'].length !=1"
(delete)="deleteField(i)">
</app-dataset-profile-editor-field-component>
</div>
<hr *ngIf="hasFocus">
</ng-container>
<!--
<div *ngIf="isComposite" class="row"> <div *ngIf="isComposite" class="row">
<h4 class="col-12 titleStile">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.SUB-FIELDS-TITLE' | translate}} <h4 class="col-12 titleStile">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.SUB-FIELDS-TITLE' | translate}}
</h4> </h4>
<div class="col-12"> <div class="col-12">
<mat-expansion-panel *ngFor="let field of form.get('fields')['controls'] let i=index;" #panel> <mat-expansion-panel *ngFor="let field of form.get('fields')['controls'] let i=index;" #panel class="field-container">
<div class="field-id-container">
random id
</div>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title class="cardTitle">{{i + 1}}. {{getFieldTile(field, i)}}</mat-panel-title> <mat-panel-title class="cardTitle">{{i + 1}}. {{getFieldTile(field, i)}}</mat-panel-title>
<div class="row"> <div class="row">
@ -80,4 +176,244 @@
<div class="col-12"> <div class="col-12">
<button mat-button class="full-width" (click)="addNewField()" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.ACTIONS.ADD-CHILD-FIELD' | translate}}</button> <button mat-button class="full-width" (click)="addNewField()" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.ACTIONS.ADD-CHILD-FIELD' | translate}}</button>
</div> </div>
</div> -->
</div> </div>
</div>
<!-- PREVIEW -->
<div class="col-12" >
<div class="mb-1" *ngIf="hasFocus" class="d-flex" style="justify-content: space-between;">
<span style="font-weight: bold;">{{'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.PREVIEW' | translate}}</span>
<span [@fadeElement]="updatedClass" *ngIf="firstField?.get('viewStyle').get('renderStyle').value">
<ng-container *ngIf="!previewDirty">
Preview updated!
</ng-container>
<ng-container *ngIf="previewDirty">
... caculating preview
</ng-container>
</span>
</div>
<div [id]="'preview_container'+ form.get('id').value" class="w-100" style="margin-right: -15px; margin-left: -15px;" >
<div *ngIf="previewForm && showPreview && firstField?.get('viewStyle').get('renderStyle').value">
<app-form-section-inner [form]="previewForm">
</app-form-section-inner>
</div>
</div>
<div class="w-100" *ngIf="!firstField?.get('viewStyle').get('renderStyle').value">
<em>
{{'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.NOT-INITIALIZED' | translate}}
</em>
</div>
<hr *ngIf="hasFocus">
</div>
</div>
<ng-container *ngIf="hasFocus">
<div class="row justify-content-end pt-2" >
<div class="col-auto">
<ul class="list-unstyled list-inline fieldset-actions-list d-flex align-items-center text-primary-blue">
<!-- <li class="list-inline-item" (click)="addNewField()"><mat-icon>folder</mat-icon> <small>Add input</small></li> -->
<li class="list-inline-item" *ngIf="!viewOnly">
<img src="/assets/images/editor/icons/add_input_set.svg" [matMenuTriggerFor]="inputmenu" style="width: 18px;transform: translateY(-1px);" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELDSET.ADD-INPUT' | translate" class="input_icon" alt="Add Input icon">
<!-- <mat-icon [matMenuTriggerFor]="inputmenu" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELDSET.ADD-INPUT' | translate">folder</mat-icon> -->
<mat-menu #inputmenu="matMenu" [class]="'add_input_menu'">
<!-- <button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.TextArea)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.TextArea)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.FreeText)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.FreeText)}}</button>
<mat-divider></mat-divider>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.BooleanDecision)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.BooleanDecision)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.RadioBox)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.RadioBox)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Select)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Select)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.CheckBox)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.CheckBox)}}</button>
<mat-divider></mat-divider>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.DatePicker)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DatePicker)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Currency)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Currency)}}</button>
<mat-divider></mat-divider>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Registries)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Registries)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Services)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Services)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Researchers)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Researchers)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Organizations)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Organizations)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.ExternalDatasets)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.ExternalDatasets)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.DataRepositories)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DataRepositories)}}</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Other)">{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Other)}}</button>
<mat-divider></mat-divider>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.InternalDmpEntities)">Internal DMPs</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Tags)">Tags</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.DatasetIdentifier)">Dataset Identifier</button>
<button class="mat-menu-item" (click)="addNewInput(viewTypeEnum.Validation)">Validation</button>
-->
<mat-action-list>
<button mat-list-item (click)="addNewInput(viewTypeEnum.TextArea)">
<img src="/assets/images/editor/icons/text_area.svg" class="input_icon" alt="Text Area icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.TextArea)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.FreeText)">
<img src="/assets/images/editor/icons/free_text.svg" class="input_icon" alt="Free Text icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.FreeText)}}
</button>
<mat-divider></mat-divider>
<button mat-list-item (click)="addNewInput(viewTypeEnum.BooleanDecision)">
<img src="/assets/images/editor/icons/boolean.svg" class="input_icon" alt="Boolean icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.BooleanDecision)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.RadioBox)">
<img src="/assets/images/editor/icons/radio_box.svg" class="input_icon" alt="RadioBox icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.RadioBox)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Select)">
<span class="input_icon">
<img src="/assets/images/editor/icons/select.svg" alt="Select icon">
</span>
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Select)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.CheckBox)">
<img src="/assets/images/editor/icons/checkbox.svg" class="input_icon" alt="CheckBox Icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.CheckBox)}}
</button>
<mat-divider></mat-divider>
<button mat-list-item (click)="addNewInput(viewTypeEnum.DatePicker)">
<img src="/assets/images/editor/icons/date_picker.svg" class="input_icon" alt="DatePicker Icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DatePicker)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Currency)">
<img src="/assets/images/editor/icons/currency.svg" class="input_icon" alt="Currency Icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Currency)}}
</button>
<mat-divider></mat-divider>
<button mat-list-item (click)="$event.stopPropagation();" style="font-style: italic;">
<img src="/assets/images/editor/icons/api.svg" class="input_icon" alt="APIs icon">
APIs
</button>
<mat-action-list class="ml-4">
<button mat-list-item (click)="addNewInput(viewTypeEnum.Registries)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Registries icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Registries)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Services)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Services icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Services)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Researchers)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Researchers icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Researchers)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Organizations)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Organizations icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Organizations)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.ExternalDatasets)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="External Datasets icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.ExternalDatasets)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.DataRepositories)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="DataRepositories icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DataRepositories)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Other)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Other icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Other)}}
</button>
</mat-action-list>
<mat-divider></mat-divider>
<button mat-list-item (click)="$event.stopPropagation();" style="font-style: italic;">
<img src="/assets/images/editor/icons/argos_entities.svg" class="input_icon" alt="Argos Entities icon">
Argos Entities
</button>
<mat-action-list class="ml-4">
<button mat-list-item (click)="addNewInput(viewTypeEnum.InternalDmpEntities)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Internal Dmp icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.InternalDmpEntities)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Tags)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Tags icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Tags)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.DatasetIdentifier)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Datset Identifier icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DatasetIdentifier)}}
</button>
<button mat-list-item (click)="addNewInput(viewTypeEnum.Validation)">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Validation icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Validation)}}
</button>
</mat-action-list>
</mat-action-list>
</mat-menu>
</li>
<!-- <li class="list-inline-item"><mat-icon>folder</mat-icon><small>CommentField</small></li> -->
<li class="list-inline-item">
<mat-checkbox class="fieldset-checkbox-action-dataset-profile-editor" [formControl]="this.form.get('hasCommentField')" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELDSET.INCLUDE-COMMENT-FIELD' | translate">{{'DATASET-PROFILE-EDITOR.ACTIONS.FIELDSET.COMMENT-FIELD' | translate}}</mat-checkbox>
</li>
<li class="list-inline-item">
<mat-checkbox class="fieldset-checkbox-action-dataset-profile-editor" [checked]="isMultiplicityEnabled" (change)="onIsMultiplicityEnabledChange($event)" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELDSET.ENABLE-MULTIPLICITY' | translate" [disabled]="viewOnly">
{{'DATASET-PROFILE-EDITOR.ACTIONS.FIELDSET.MULTIPLICITY' | translate}}
</mat-checkbox>
</li>
<li class="list-inline-item">
<!-- <mat-icon>more_vert</mat-icon> -->
<mat-icon [matMenuTriggerFor]="menu" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELDSET.MORE' | translate" style="transform: translateY(-1px);">more_vert</mat-icon>
<mat-menu #menu="matMenu">
<!-- TODO to check -->
<mat-checkbox class="mat-menu-item" (click)="$event.stopPropagation()" [(ngModel)]="showDescription">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.DESCRIPTION' | translate}}</mat-checkbox>
<mat-checkbox class="mat-menu-item" (click)="$event.stopPropagation()" [(ngModel)]="showExtendedDescription">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.EXTENDED-DESCRIPTION' | translate}}</mat-checkbox>
<mat-checkbox class="mat-menu-item" (click)="$event.stopPropagation()" [(ngModel)]="showAdditionalInfo">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.ADDITIONAL-INFORMATION' | translate}}</mat-checkbox>
</mat-menu>
</li>
</ul>
</div>
</div>
</ng-container>
</div>
<!--
<span>Preview</span>
<app-form-composite-field [form]="previewForm" *ngIf="previewForm">
</app-form-composite-field> -->
<!--
Current FORM: {{this.form.value |json}}
<br>
Target: {{this.targetField?.value |json}} -->
<!--
<button (click)="generatePreview()">Generate preview</button>
-->

View File

@ -9,3 +9,105 @@
.titleStile{ .titleStile{
font-weight: bold; font-weight: bold;
} }
//REFACTOR SECTION
//Palete
$blue-color : #129D99;
$blue-color-light: #5cf7f2;
.actions-list{
border-radius: 7px;
box-shadow: 0 1px 0.8em $blue-color;
padding: 1em 0em;
font-size: small;
}
.field-container{
box-shadow: 0px 1px 2px rgb(173, 173, 173) ;
padding: 3em;
border-radius: .3em;
// border-left: 0.3em solid yellow;
padding-bottom: 2em;
margin-bottom: 2em;
}
.field-container-active{
box-shadow: 0px 1px 2px rgb(173, 173, 173) ;
padding: 3em;
border-radius: .3em;
border-left: 0.3em solid $blue-color;
padding-bottom: 2em;
margin-bottom: 2em;
}
.field-id-container{
background-color: $blue-color-light;
position: absolute;
right: 0;
top: 0;
padding: .6em 1.2em;
overflow: visible;
.field-id-container-icon{
position: absolute;
top: -50%;
}
}
.main-content-page{
padding: 0em 1.5em;
}
.fielset-header{
font-size: 1.5em;
font-weight: bold;
// .numbering{
// padding: 0.5em 0em;
// }
}
.fieldset-actions-list{
margin: 0;
cursor: pointer;
}
// ::ng-deep .main-content-page .fieldset-header .field-title .mat-form-field-infix{
// border-top: 0px;
// }
.numbering-label .mat-input-element:disabled{
color: #212121;
}
:host ::ng-deep .fieldset-checkbox-action-dataset-profile-editor
{
.mat-checkbox-label{
font-size: 0.8em;
color: #212121;
transform: translateY(3px);
}
}
.input_icon{
width: 14px;
margin-right: 0.5em;
// display: flex;
// align-items: center;
}
::ng-deep .mat-menu-panel{
max-height: 32em;
}
:host ::ng-deep .fielset-header .mat-form-field-wrapper{
padding-bottom: 0px;
}
// ::ng-deep .underline-line-field .mat-form-field-appearance-legacy .mat-form-field-wapper{
// padding-bottom: 1.25em !important;
// }

View File

@ -1,38 +1,291 @@
import { Component, Input, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, Input, OnChanges, OnInit } from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms'; import { AbstractControl, 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 { 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';
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 { BooleanDecisionFieldDataEditorModel } from '../../../admin/field-data/boolean-decision-field-data-editor-model';
import { CheckBoxFieldDataEditorModel } from '../../../admin/field-data/check-box-field-data-editor-model';
import { WordListFieldDataEditorModel } from '../../../admin/field-data/word-list-field-data-editor-model';
import { AutoCompleteFieldDataEditorModel } from '../../../admin/field-data/auto-complete-field-data-editor-model';
import { ResearchersAutoCompleteFieldDataEditorModel } from '../../../admin/field-data/researchers-auto-complete-field-data-editor-model';
import { FreeTextFieldDataEditorModel } from '../../../admin/field-data/free-text-field-data-editor-model';
import { RadioBoxFieldDataEditorModel } from '../../../admin/field-data/radio-box-field-data-editor-model';
import { TextAreaFieldDataEditorModel } from '../../../admin/field-data/text-area-field-data-editor-model';
import { DatePickerDataEditorModel } from '../../../admin/field-data/date-picker-data-editor-models';
import { ExternalDatasetsDataEditorModel } from '../../../admin/field-data/external-datasets-data-editor-models';
import { DataRepositoriesDataEditorModel } from '../../../admin/field-data/data-repositories-data-editor-models';
import { RegistriesDataEditorModel } from '../../../admin/field-data/registries-data-editor-models';
import { ServicesDataEditorModel } from '../../../admin/field-data/services-data-editor-models';
import { TagsDataEditorModel } from '../../../admin/field-data/tags-data-editor-models';
import { DatasetsAutoCompleteFieldDataEditorModel } from '../../../admin/field-data/datasets-autocomplete-field-data-editor-mode';
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';
import { OrganizationsDataEditorModel } from '../../../admin/field-data/organizations-data-editor-models';
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 { debounce, debounceTime } from 'rxjs/operators';
import { setUncaughtExceptionCaptureCallback } from 'process';
import { GENERAL_ANIMATIONS } from '../../animations/animations';
@Component({ @Component({
selector: 'app-dataset-profile-editor-composite-field-component', selector: 'app-dataset-profile-editor-composite-field-component',
templateUrl: './dataset-profile-editor-composite-field.component.html', templateUrl: './dataset-profile-editor-composite-field.component.html',
styleUrls: ['./dataset-profile-editor-composite-field.component.scss'] styleUrls: ['./dataset-profile-editor-composite-field.component.scss'],
animations:[GENERAL_ANIMATIONS]
}) })
export class DatasetProfileEditorCompositeFieldComponent implements OnInit { export class DatasetProfileEditorCompositeFieldComponent implements OnInit, OnChanges {
@Input() form: FormGroup; @Input() form: FormGroup;
@Input() indexPath: string; @Input() indexPath: string;
@Input() viewOnly: boolean; @Input() viewOnly: boolean;
isComposite = false; @Input() numbering: string;
isMultiplicityEnabled = false; @Input() hasFocus: boolean = false;
showPreview: boolean = true;
previewDirty: boolean = false;
showDescription: boolean = true;
showAdditionalInfo: boolean = false;
showExtendedDescription: boolean = false;
previewForm: FormGroup = null;
// isComposite = false;
// isMultiplicityEnabled = false;
viewStyleEnum = DatasetProfileFieldViewStyle;
viewTypeEnum = ViewStyleType;
private myCustomValidators:EditorCustomValidators = new EditorCustomValidators();
constructor(
private dialog: MatDialog,
private language: TranslateService,
public enumUtils: EnumUtils,
public datasetProfileService: DatasetProfileService
) { }
ngOnChanges(){
// this.setTargetField(null);
// this.showExtendedDescription = !!this.form.get('extendedDescription').value;
// this.showAdditionalInfo = !!this.form.get('additionalInformation').value;
}
get firstField(){
try{
return (this.form.get('fields') as FormArray).at(0);
}catch{
return null;
}
}
get isMultiplicityEnabled(){
if(!this.form.get('multiplicity')){
return false;
}
if (this.form.get('multiplicity').value.min > 0 || this.form.get('multiplicity').value.max > 0) {
return true;
}
return false;
}
constructor() { }
ngOnInit() { ngOnInit() {
//this.addNewField(); //this.addNewField();
if (this.form.get('multiplicity')) { // if (this.form.get('multiplicity')) {
if (this.form.get('multiplicity').value.min > 1 || this.form.get('multiplicity').value.max > 1) { // if (this.form.get('multiplicity').value.min > 1 || this.form.get('multiplicity').value.max > 1) {
this.isMultiplicityEnabled = true; // this.isMultiplicityEnabled = true;
} // }
} // }
this.isComposite = (this.form.get('fields') as FormArray).length > 1; // this.isComposite = (this.form.get('fields') as FormArray).length > 1;
if (this.viewOnly) { if (this.viewOnly) {
this.form.get('hasCommentField').disable(); this.form.get('hasCommentField').disable();
} }
//SET UP TARGET FIELD
// if((this.form.get('fields') as FormArray).length>0){
// //get the first field in list
// 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;
this.form.valueChanges.subscribe(changes=>{
// this.previewForm = null;
this.previewDirty = true;
this.generatePreviewForm();
});
this.previewSubject$.pipe(debounceTime(600)).subscribe(model=>{
const updatedForm = model.buildForm();
this.reloadPreview(updatedForm)
})
this.generatePreviewForm();
} }
get updatedClass(){
if(this.previewDirty) return '';
else return 'updated';
}
private reloadPreview(updatedForm: FormGroup){
setTimeout(() => {
const previewContainer = document.getElementById('preview_container'+ this.form.get('id').value);
// let clientHeight = -1;
if(previewContainer){
// console.log(previewContainer);
const clientHeight = previewContainer.clientHeight;
// console.log(clientHeight);
if(clientHeight){
previewContainer.style.height = clientHeight.toString() + 'px';
// console.log('height:' ,previewContainer.style.height);
}
}
this.showPreview = false;
this.previewDirty = true;
this.previewForm = updatedForm;
setTimeout(() => {
this.showPreview = true;
this.previewDirty = false;
if(previewContainer){
setTimeout(() => {
if(previewContainer){
previewContainer.style.height = 'auto';
}
});
}
});
});
}
previewSubject$: Subject<DatasetDescriptionSectionEditorModel> = new Subject<DatasetDescriptionSectionEditorModel>();
private generatePreviewForm(){
const formValue:FieldSet = this.form.getRawValue();
const fields:FieldDefinition[] = formValue.fields.map(editorField=>this._fieldToFieldDefinition(editorField));
const compositeField: CompositeField = {
id: formValue.id,
additionalInformation: formValue.additionalInformation,
extendedDescription: formValue.extendedDescription,
numbering:'',
title: formValue.title,
ordinal: formValue.ordinal,
description: formValue.description,
hasCommentField: formValue.hasCommentField,
commentFieldValue: '',
multiplicity: {max:formValue.multiplicity.max, min : formValue.multiplicity.min},
multiplicityItems:null,
fields: fields.map(editorField=>{
const model = new DatasetDescriptionFieldEditorModel().fromModel(editorField);
if(model.viewStyle.renderStyle === this.viewStyleEnum.CheckBox){
model.value = model.value?"true":"false";//patch
}
return model;
})
}
const section = new DatasetDescriptionSectionEditorModel();
section.title = '';
section.numbering = '';
const compositeForm = new DatasetDescriptionCompositeFieldEditorModel().fromModel(compositeField)
section.compositeFields = [compositeForm];
this.previewSubject$.next(section);
}
private _fieldToFieldDefinition(editorField: Field): FieldDefinition{
const field = {
id: editorField.id,
title: '',
page: editorField.page,
numbering:'',
multiplicity:null,
multiplicityItems: null,
viewStyle: editorField.viewStyle,
defaultValue:editorField.defaultValue,
value: null,
validations: editorField.validations,
} as FieldDefinition;
field.data = editorField.data;
// return new DatasetDescriptionFieldEditorModel().fromModel(field);
return field;
}
// generatePreview(){
// const editorModel = new DatasetDescriptionCompositeFieldEditorModel();
// editorModel.title = this.form.get('title').value;
// editorModel.description = this.form.get('description').value;
// editorModel.extendedDescription = this.form.get('extendedDescription').value;
// editorModel.additionalInformation = this.form.get('additionalInformation').value;
// editorModel.hasCommentField = this.form.get('hasCommentField').value;
// editorModel.fields = [];
// (this.form.get('fields') as FormArray).controls.forEach(field=>{
// const fieldEditorModel = new DatasetDescriptionFieldEditorModel();
// fieldEditorModel.viewStyle= {
// renderStyle: field.get('viewStyle').get('renderStyle').value,
// cssClass: null
// };
// fieldEditorModel.defaultValue = field.get('defaultValue').value;
// switch (field.get('viewStyle').get('renderStyle').value) {
// case DatasetProfileFieldViewStyle.TextArea:
// fieldEditorModel.data = {
// label: field.get('data').get('label').value
// };
// break;
// default:
// break;
// }
// editorModel.fields.push(fieldEditorModel);
// });
// this.previewForm = editorModel.buildForm();
// }
onIsCompositeChange(isComposite: boolean) { onIsCompositeChange(isComposite: boolean) {
if (!isComposite && (<FormArray>this.form.get('fields')).length > 1) { if (!isComposite && (<FormArray>this.form.get('fields')).length > 1) {
for (let i = 0; i < (<FormArray>this.form.get('fields')).length - 1; i++) { for (let i = 0; i < (<FormArray>this.form.get('fields')).length - 1; i++) {
@ -46,25 +299,594 @@ export class DatasetProfileEditorCompositeFieldComponent implements OnInit {
} }
} }
onIsMultiplicityEnabledChange(isMultiplicityEnabled: boolean) { onIsMultiplicityEnabledChange(isMultiplicityEnabled: MatCheckboxChange) {
if (!isMultiplicityEnabled) {
(<FormControl>this.form.get('multiplicity').get('min')).setValue(0); const multiplicity = this.form.get('multiplicity') as FormGroup;
(<FormControl>this.form.get('multiplicity').get('max')).setValue(0);
const minControl = multiplicity.get('min');
const maxControl = multiplicity.get('max');
if (isMultiplicityEnabled.checked) {
minControl.setValue(0);
maxControl.setValue(1);
}else{
minControl.setValue(0);
maxControl.setValue(0);
} }
minControl.updateValueAndValidity();
maxControl.updateValueAndValidity();
} }
addNewField() { addNewField() {
const field: FieldEditorModel = new FieldEditorModel(); const field: FieldEditorModel = new FieldEditorModel();
field.id=Guid.create().toString(); field.id=Guid.create().toString();
(<FormArray>this.form.get('fields')).push(field.buildForm());
field.ordinal = (this.form.get('fields') as FormArray).length;
const fieldForm = field.buildForm();
// fieldForm.setValidators(this.customFieldValidator());
// fieldForm.get('viewStyle').get('renderStyle').setValidators(Validators.required);
(<FormArray>this.form.get('fields')).push(fieldForm);
this.setTargetField(fieldForm);
fieldForm.updateValueAndValidity();
} }
DeleteField(index) { DeleteField(index) {
(<FormArray>this.form.get('fields')).removeAt(index);
const fieldsForm = <FormArray>this.form.get('fields');
fieldsForm.removeAt(index);
// calculate ordinals
fieldsForm.controls.forEach((field, idx)=>{
field.get('ordinal').setValue(idx);
field.updateValueAndValidity();
})
} }
getFieldTile(formGroup: FormGroup, index: number) { getFieldTile(formGroup: FormGroup, index: number) {
if (formGroup.get('title') && formGroup.get('title').value && formGroup.get('title').value.length > 0) { return formGroup.get('title').value; } if (formGroup.get('title') && formGroup.get('title').value && formGroup.get('title').value.length > 0) { return formGroup.get('title').value; }
return "Field " + (index + 1); return "Field " + (index + 1);
} }
targetField:FormGroup;
validationTypeEnum = ValidationType;
addVisibilityRule(targetField: FormGroup){
const rule: RuleEditorModel = new RuleEditorModel();
(<FormArray>targetField.get('visible').get('rules')).push(rule.buildForm());
} }
toggleRequired(targetField: FormGroup, event:MatCheckboxChange){
let validationsControl = targetField.get('validations') as FormControl;
let validations: Array<ValidationType> = validationsControl.value;
if(event.checked){
if(!validations.includes(ValidationType.Required)){//IS ALREADY REQUIRED
// validationsControl.setValue(validations.filter(validator=> validator != ValidationType.Required));
// validationsControl.updateValueAndValidity();
validations.push(ValidationType.Required);
// validationsControl.setValue(validations);
validationsControl.updateValueAndValidity();
}
}else{
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{
// //SET REQUIRED VALIDATOR
// console.log('setting required validator');
// validations.push(ValidationType.Required);
// validationsControl.setValue(validations);
// validationsControl.updateValueAndValidity();
// }
}
setTargetField(field:FormGroup){
this.targetField = field;
}
deleteTargetField(){
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
restoreFocus: false,
data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
isDeleteConfirmation: true
}
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
this._deleteTargetField();
}
});
}
private _deleteTargetField(){
if(!this.targetField) return;
let index = -1;
const fields = this.form.get('fields') as FormArray;
for(let i=0;i< fields.length; i++){
let field = fields.at(i);
if(field.get('id').value === this.targetField.get('id').value){//index found
index = i;
break;
}
}
if(index>=0){//target found in fields
this.DeleteField(index);
this.targetField = null;
}
}
deleteField(index: number){
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
restoreFocus: false,
data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
isDeleteConfirmation: true
}
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
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{
}
const field = {
id: Guid.create().toString(),
ordinal: targetOrdinal,
visible:{rules:[],style:null},
validations:[],
viewStyle:{}
} as Field;
// const field: FieldEditorModel = new FieldEditorModel();
// field.id=Guid.create().toString();
// field.ordinal = (this.form.get('fields') as FormArray).length;
// const fieldForm = field.buildForm();
// fieldForm.setValidators(this.customFieldValidator());
// fieldForm.get('viewStyle').get('renderStyle').setValidators(Validators.required);
// if (fieldForm.get('data')) {
// fieldForm.removeControl('data');
// }
switch (type) {
case this.viewTypeEnum.BooleanDecision:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.BooleanDecision)
// fieldForm.addControl('data', new BooleanDecisionFieldDataEditorModel().buildForm());
const data: BooleanDecisionFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.BooleanDecision;
field.data = data;
break;
}
case this.viewTypeEnum.CheckBox:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.CheckBox)
// fieldForm.addControl('data', new CheckBoxFieldDataEditorModel().buildForm());
const data: CheckBoxFieldData = {
label:''
}
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());
// fieldForm.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('options'));
// fieldForm.get('data').updateValueAndValidity();
const firstOption = {label:'', value:''} as FieldDataOption;
const data:WordListFieldData = {
label:'',
multiList:false,
options:[firstOption],
type:DatasetProfileComboBoxType.WordList
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.ComboBox;
field.data = data;
break;
}
case this.viewTypeEnum.Other:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
// fieldForm.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE
// fieldForm.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('autoCompleteSingleDataList'));
// fieldForm.get('data').updateValueAndValidity();
const data: AutoCompleteFieldData = {
autoCompleteSingleDataList:[],
multiAutoComplete: false,
label:'',
type: DatasetProfileComboBoxType.Autocomplete
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.ComboBox;
field.data = data;
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,
type: DatasetProfileInternalDmpEntitiesType.Dmps
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.InternalDmpEntities;
field.data = data;
break;
}
case this.viewTypeEnum.FreeText:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.FreeText)
// fieldForm.addControl('data', new FreeTextFieldDataEditorModel().buildForm());
const data: FreeTextFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.FreeText;
field.data = data;
break;
}
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'));
// fieldForm.get('data').updateValueAndValidity();
const data: RadioBoxFieldData= {
label:'',
options: []
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.RadioBox;
field.data = data;
break;
}
case this.viewTypeEnum.TextArea:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.TextArea)
// fieldForm.addControl('data', new TextAreaFieldDataEditorModel().buildForm());
const data: TextAreaFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.TextArea;
field.data = data;
break;
}
case this.viewTypeEnum.DatePicker:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatePicker)
// fieldForm.addControl('data', new DatePickerDataEditorModel().buildForm());
const data: DatePickerFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.DatePicker;
break;
}
case this.viewTypeEnum.ExternalDatasets:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ExternalDatasets)
// fieldForm.addControl('data', new ExternalDatasetsDataEditorModel().buildForm());
const data: ExternalDatasetsFieldData = {
label:'',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.ExternalDatasets;
field.data = data;
break;
}
case this.viewTypeEnum.DataRepositories:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DataRepositories)
// fieldForm.addControl('data', new DataRepositoriesDataEditorModel().buildForm());
const data: DataRepositoriesFieldData = {
label: '',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.DataRepositories;
field.data = data;
break;
}
case this.viewTypeEnum.Registries:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Registries)
// fieldForm.addControl('data', new RegistriesDataEditorModel().buildForm());
const data:RegistriesFieldData = {
label: '',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Registries;
field.data = data;
break;
}
case this.viewTypeEnum.Services:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Services)
// fieldForm.addControl('data', new ServicesDataEditorModel().buildForm());
const data:ServicesFieldData = {
label:'',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Services;
field.data = data;
break;
}
case this.viewTypeEnum.Tags:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Tags)
// fieldForm.addControl('data', new TagsDataEditorModel().buildForm());
const data: TagsFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Tags;
field.data = data;
break;
}
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());
// field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Researchers;
const data : ResearchersAutoCompleteFieldData = {
label:'',
multiAutoComplete: false,
type: DatasetProfileInternalDmpEntitiesType.Researchers
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.InternalDmpEntities;
field.data = data;
break;
}
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())
// fieldForm.addControl('data', new DatasetsAutoCompleteFieldDataEditorModel().buildForm()); //TODO
const data = {
autoCompleteSingleDataList:[],
label:'',
multiAutoComplete: false,
} as OrganizationsFieldData; //TODO
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Organizations;
field.data = data;
break;
}
case this.viewTypeEnum.DatasetIdentifier:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatasetIdentifier)
// fieldForm.addControl('data', new DatasetIdentifierDataEditorModel().buildForm());
const data : DatasetIdentifierFieldData = {
label:''
}
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());
const data: CurrencyFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Currency;
field.data = data;
break;
}
case this.viewTypeEnum.Validation:{
// fieldForm.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Validation)
// fieldForm.addControl('data', new ValidationDataEditorModel().buildForm());
const data:ValidationFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Validation;
field.data = data;
break;
}
}
(<FormArray>this.form.get('fields')).push(new FieldEditorModel().fromModel(field).buildForm());
// fieldForm.get('viewStyle').get('renderStyle').updateValueAndValidity();
// fieldForm.get('data').updateValueAndValidity();
}
// 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}
// }
// }
// }
// private _atLeastOneElementListValidator(arrayToCheck): ValidatorFn{
// return (control: AbstractControl): ValidationErrors | null=>{
// const fa = control.get(arrayToCheck) as FormArray;
// if(fa.length === 0){
// return {emptyArray: true};
// }
// return null;
// }
// }
calculateLabelWidth(numbering: string){
const width = numbering.split('.').reduce((acc,item)=> item+acc,'').length;
return {'width':width+'em'}
}
}

View File

@ -1,7 +1,8 @@
<div class="row"> <div class="row">
<!-- BooleanDecision --> <!-- BooleanDecision -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.BooleanDecision"> <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.BooleanDecision">
<mat-select [formControl]="form" [placeholder]="placeHolder" [required]="required"> <mat-label>{{placeHolder}}</mat-label>
<mat-select [formControl]="form" [placeholder]="placeHolder">
<mat-option [value]="null">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.NONE' | <mat-option [value]="null">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.NONE' |
translate}}</mat-option> translate}}</mat-option>
<mat-option [value]="'true'">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.BOOLEAN-DECISION.YES' <mat-option [value]="'true'">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.BOOLEAN-DECISION.YES'
@ -16,7 +17,8 @@
<!-- CheckBox --> <!-- CheckBox -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.CheckBox"> <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.CheckBox">
<mat-select [formControl]="form" [placeholder]="placeHolder" [required]="required"> <mat-label>{{placeHolder}}</mat-label>
<mat-select [formControl]="form" [placeholder]="placeHolder" >
<mat-option [value]="'true'">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.CHECK-BOX.CHECKED' | translate}}</mat-option> <mat-option [value]="'true'">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.CHECK-BOX.CHECKED' | translate}}</mat-option>
<mat-option [value]="'false'">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.CHECK-BOX.UNCHECKED' | translate}}</mat-option> <mat-option [value]="'false'">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.CHECK-BOX.UNCHECKED' | translate}}</mat-option>
</mat-select> </mat-select>
@ -24,11 +26,13 @@
</mat-form-field> </mat-form-field>
<!-- ComboBox --> <!-- 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"> <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-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.ComboBox && comboBoxType === comboBoxTypeEnum.WordList">
<mat-select [formControl]="form" [placeholder]="placeHolder" [required]="required"> <mat-label>{{placeHolder}}</mat-label>
<mat-select [formControl]="form" [placeholder]="placeHolder" >
<mat-option [value]="null">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.NONE' | translate }}</mat-option> <mat-option [value]="null">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.NONE' | translate }}</mat-option>
<mat-option *ngFor="let opt of formArrayOptions['controls']" [value]="opt.get('value').value">{{opt.get('label').value}}</mat-option> <mat-option *ngFor="let opt of formArrayOptions['controls']" [value]="opt.get('value').value">{{opt.get('label').value}}</mat-option>
</mat-select> </mat-select>
@ -36,25 +40,30 @@
</mat-form-field> </mat-form-field>
<!-- InternalDmpEntities --> <!-- InternalDmpEntities -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.InternalDmpEntities && internalDmpEntitiesType === internalDmpEntitiesTypeEnum.Researchers"> <!-- <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.InternalDmpEntities && internalDmpEntitiesType === internalDmpEntitiesTypeEnum.Researchers">
<mat-label>{{placeHolder}}</mat-label>
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form" [required]="required"> <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.InternalDmpEntities && internalDmpEntitiesType === internalDmpEntitiesTypeEnum.Datasets"> <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.InternalDmpEntities && internalDmpEntitiesType === internalDmpEntitiesTypeEnum.Datasets">
<mat-label>{{placeHolder}}</mat-label>
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form" [required]="required"> <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.InternalDmpEntities && internalDmpEntitiesType === internalDmpEntitiesTypeEnum.Dmps"> <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.InternalDmpEntities && internalDmpEntitiesType === internalDmpEntitiesTypeEnum.Dmps">
<mat-label>{{placeHolder}}</mat-label>
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form" [required]="required"> <input matInput type="text" [placeholder]="placeHolder" [formControl]="form" [required]="required">
</mat-form-field> </mat-form-field> -->
<!-- FreeText --> <!-- FreeText -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.FreeText"> <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.FreeText">
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form" [required]="required"> <mat-label>{{placeHolder}}</mat-label>
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form" >
<mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<!-- RadioBox --> <!-- RadioBox -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.RadioBox"> <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.RadioBox">
<mat-select [formControl]="form" [placeholder]="placeHolder" [required]="required"> <mat-label>{{placeHolder}}</mat-label>
<mat-select [formControl]="form" [placeholder]="placeHolder" >
<mat-option [value]="null">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.NONE' | translate}}</mat-option> <mat-option [value]="null">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.DEFAULT-VALUES.NONE' | translate}}</mat-option>
<mat-option *ngFor="let opt of formArrayOptions['controls']" [value]="opt.get('value').value">{{opt.get('label').value}}</mat-option> <mat-option *ngFor="let opt of formArrayOptions['controls']" [value]="opt.get('value').value">{{opt.get('label').value}}</mat-option>
</mat-select> </mat-select>
@ -63,14 +72,16 @@
<!-- TextArea --> <!-- TextArea -->
<mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.TextArea"> <mat-form-field class="col-md-12" *ngIf="viewStyle === viewStyleEnum.TextArea">
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form" [required]="required"> <mat-label>{{placeHolder}}</mat-label>
<input matInput type="text" [placeholder]="placeHolder" [formControl]="form">
<mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<!-- DatePicker --> <!-- DatePicker -->
<mat-form-field class="col-12" *ngIf="viewStyle === viewStyleEnum.DatePicker"> <mat-form-field class="col-12" *ngIf="viewStyle === viewStyleEnum.DatePicker">
<!--(focus)="date.open()" (click)="date.open()"--> <!--(focus)="date.open()" (click)="date.open()"-->
<input matInput [placeholder]="placeHolder" class="table-input" [matDatepicker]="date" [formControl]="form" [required]="required"> <mat-label>{{placeHolder}}</mat-label>
<input matInput [placeholder]="placeHolder" class="table-input" [matDatepicker]="date" [formControl]="form" >
<mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle>
<mat-datepicker #date></mat-datepicker> <mat-datepicker #date></mat-datepicker>
<mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}} <mat-error *ngIf="form.hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}

View File

@ -17,7 +17,7 @@ export class DatasetProfileEditorDefaultValueComponent implements OnInit {
@Input() comboBoxType: DatasetProfileComboBoxType; @Input() comboBoxType: DatasetProfileComboBoxType;
@Input() internalDmpEntitiesType: DatasetProfileInternalDmpEntitiesType; @Input() internalDmpEntitiesType: DatasetProfileInternalDmpEntitiesType;
@Input() placeHolder: String; @Input() placeHolder: String;
@Input() required: Boolean; // @Input() required: Boolean;
comboBoxTypeEnum = DatasetProfileComboBoxType; comboBoxTypeEnum = DatasetProfileComboBoxType;
internalDmpEntitiesTypeEnum = DatasetProfileInternalDmpEntitiesType; internalDmpEntitiesTypeEnum = DatasetProfileInternalDmpEntitiesType;

View File

@ -6,12 +6,34 @@
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput type="string" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-PLACEHOLDER' | translate}}" <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
<h6 style="font-weight: bold" class="col-auto">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-SOURCE-TITLE' | translate}}</h6>
<button mat-raised-button type="button" class="col-auto" (click)="addSource()">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-ADD_SOURCE' | translate}}</button> <h6 class="col-12" style="font-weight: bold">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-SOURCE-TITLE' | translate}}</h6>
<div class="col-12 d-flex align-items-center" style="margin-bottom: 1em;">
<button mat-raised-button
type="button"
(click)="addSource()"
style="margin-right: 2em;"
>
<!-- [ngClass]="{'text-danger':form.get('data').errors?.emptyArray && form.touched}" -->
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-ADD_SOURCE' | translate}}
</button>
<!-- *ngIf="form.get('data').errors?.emptyArray && form.get('data').touched" -->
<div class="d-flex" *ngIf="form.get('data').errors?.emptyArray && form.get('data').touched">
<mat-icon
class="text-danger"
matTooltip="At least one source must be provided."
>warning_amber</mat-icon>
<small class="text-danger">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.ERROR-MESSAGES.FIELD-OTHER-SOURCES-REQUIRED'| translate}}</small>
</div>
</div>
</div> </div>
<div *ngFor="let singleForm of multiForm.controls; let i = index" class="row"> <div *ngFor="let singleForm of multiForm.controls; let i = index" class="row">
@ -24,20 +46,29 @@
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-12"> <mat-form-field class="col-md-12">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-URL' | translate}}" [formControl]="this.singleForm.get('url')"> <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-URL' | translate}}</mat-label>
<input matInput [formControl]="singleForm.get('url')">
<mat-error *ngIf="singleForm.get('url').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-3"> <mat-form-field class="col-md-3">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-OPTIONS-ROOT' | translate}}" <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-OPTIONS-ROOT' | translate}}</mat-label>
[formControl]="this.singleForm.get('optionsRoot')"> <input matInput
[formControl]="singleForm.get('optionsRoot')">
<mat-error *ngIf="singleForm.get('optionsRoot').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-3"> <mat-form-field class="col-md-3">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-LABEL' | translate}}" [formControl]="this.singleForm.get('autoCompleteOptions').get('label')"> <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-LABEL' | translate}}</mat-label>
<input matInput [formControl]="singleForm.get('autoCompleteOptions').get('label')">
<mat-error *ngIf="singleForm.get('autoCompleteOptions').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-3"> <mat-form-field class="col-md-3">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-VALUE' | translate}}" [formControl]="this.singleForm.get('autoCompleteOptions').get('value')"> <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-VALUE' | translate}}</mat-label>
<input matInput [formControl]="singleForm.get('autoCompleteOptions').get('value')">
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-3"> <mat-form-field class="col-md-3">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-SOURCE' | translate}}" [formControl]="this.singleForm.get('autoCompleteOptions').get('source')"> <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-AUTOCOMPLETE-SOURCE' | translate}}</mat-label>
<input matInput [formControl]="singleForm.get('autoCompleteOptions').get('source')">
<mat-error *ngIf="singleForm.get('autoCompleteOptions').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<button mat-button type="button" (click)="removeSource(i)"><mat-icon>delete</mat-icon></button> <button mat-button type="button" (click)="removeSource(i)"><mat-icon>delete</mat-icon></button>
</div> </div>

View File

@ -1,8 +1,9 @@
<div class="row" *ngIf="form.get('data')"> <!-- <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-BOOLEAN-DECISION-TITLE' | translate}}</h5> <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-BOOLEAN-DECISION-TITLE' | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput type="string" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-BOOLEAN-DECISION-PLACEHOLDER' | translate}}" [formControl]="form.get('data').get('label')"> <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-BOOLEAN-DECISION-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div> -->

View File

@ -3,6 +3,7 @@
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-TITLE' | translate}}</h5> <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-TITLE' | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput type="string" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}" [formControl]="form.get('data').get('label')"> <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,10 +1,10 @@
<div class="row"> <div class="row">
<mat-form-field class="col-12"> <!-- <mat-form-field class="col-12">
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-COMBO-BOX-TYPE' | translate}}" [formControl]="this.form.get('data').get('type')"> <mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-COMBO-BOX-TYPE' | translate}}" [formControl]="this.form.get('data').get('type')">
<mat-option [value]="options.Autocomplete">{{enumUtils.toDatasetProfileComboBoxTypeString(options.Autocomplete)}}</mat-option> <mat-option [value]="options.Autocomplete">{{enumUtils.toDatasetProfileComboBoxTypeString(options.Autocomplete)}}</mat-option>
<mat-option [value]="options.WordList">{{enumUtils.toDatasetProfileComboBoxTypeString(options.WordList)}}</mat-option> <mat-option [value]="options.WordList">{{enumUtils.toDatasetProfileComboBoxTypeString(options.WordList)}}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field> -->
<app-dataset-profile-editor-auto-complete-field-component *ngIf="this.form.get('data').get('type').value === options.Autocomplete" class="col-12" [form]="form"></app-dataset-profile-editor-auto-complete-field-component> <app-dataset-profile-editor-auto-complete-field-component *ngIf="this.form.get('data').get('type').value === options.Autocomplete" class="col-12" [form]="form"></app-dataset-profile-editor-auto-complete-field-component>
<app-dataset-profile-editor-word-list-field-component *ngIf="this.form.get('data').get('type').value === options.WordList" class="col-12" [form]="form"></app-dataset-profile-editor-word-list-field-component> <app-dataset-profile-editor-word-list-field-component *ngIf="this.form.get('data').get('type').value === options.WordList" class="col-12" [form]="form"></app-dataset-profile-editor-word-list-field-component>
</div> </div>

View File

@ -22,7 +22,7 @@ export class DatasetProfileEditorComboBoxFieldComponent extends BaseComponent im
) { super(); } ) { super(); }
ngOnInit() { ngOnInit() {
this.setupListeners(); // this.setupListeners();
} }
setupListeners() { setupListeners() {

View File

@ -1,9 +1,9 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CURRENCY-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CURRENCY-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,12 +1,12 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATA-REPOSITORIES-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')"> <mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}} {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}}
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATA-REPOSITORIES-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,9 +1,9 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATASET-IDENTIFIER-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATASET-IDENTIFIER-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -6,7 +6,8 @@
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput type="string" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATASETS-PLACEHOLDER' | translate}}" <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATASETS-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -2,8 +2,8 @@
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -6,7 +6,8 @@
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput type="string" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DMPS-PLACEHOLDER' | translate}}" <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DMPS-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,13 +1,13 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-EXTERNAL-DATASETS-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')"> <mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}} {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}}
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-EXTERNAL-DATASETS-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -4,8 +4,8 @@
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-FREE-TEXT-TITLE' | translate}}</h5> {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-FREE-TEXT-TITLE' | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-FREE-TEXT-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-FREE-TEXT-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,13 +1,13 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-ORGANIZATIONS-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')"> <mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}} {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}}
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-ORGANIZATIONS-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,24 +1,29 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<div class="col-12">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-TITLE' <h5 style="font-weight: bold; display: inline-block; margin-right: 2em;">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-TITLE'
| translate}}</h5> | translate}}</h5>
<ng-container *ngIf="form.get('data').errors?.emptyArray && form.get('data').touched">
<mat-icon class="text-danger translateY-3">warning_amber</mat-icon>
<small class="text-danger">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.ERROR-MESSAGES.FIELD-RADIO-AT-LEAST-ONE-REQUIRED'| translate}}</small>
</ng-container>
</div>
<mat-form-field class="col-12"> <!-- <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field> -->
<div class="col-12"> <div class="col-12">
<div *ngFor="let option of form.get('data').get('options')['controls'] index as i" class="row"> <div *ngFor="let option of form.get('data').get('options')['controls'] index as i" class="row">
<mat-form-field class="col"> <mat-form-field class="col">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-LABEL' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-LABEL' | translate}}"
[formControl]="this.form.get('data').get('options').get(''+i).get('label')"> [formControl]="this.form.get('data').get('options').get(''+i).get('label')">
</mat-form-field> </mat-form-field>
<mat-form-field class="col"> <mat-form-field class="col">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-VALUE' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RADIO-BOX-VALUE' | translate}}"
[formControl]="this.form.get('data').get('options').get(''+i).get('value')"> [formControl]="this.form.get('data').get('options').get(''+i).get('value')">
</mat-form-field> </mat-form-field>
<button mat-icon-button class="col-auto" (click)="deleteRow(i)" type="button" <button mat-icon-button class="col-auto" (click)="deleteRow(i)" type="button"

View File

@ -1,12 +1,12 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-REGISTRIES-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')"> <mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}} {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}}
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-REGISTRIES-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -6,7 +6,8 @@
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput type="string" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RESEARCHERS-PLACEHOLDER' | translate}}" <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RESEARCHERS-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,12 +1,12 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RESEARCHERS-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')"> <mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}} {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}}
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RESEARCHERS-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,12 +1,12 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-SERVICES-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')"> <mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiAutoComplete')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}} {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-AUTOCOMPLETE' | translate}}
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-SERVICES-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,9 +1,9 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-TAGS-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-TAGS-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -4,7 +4,10 @@
| translate}}</h5> | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput type="string" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-TEXT-AREA-PLACEHOLDER' | translate}}" <mat-label>
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-TEXT-AREA-PLACEHOLDER' | translate}}
</mat-label>
<input matInput type="string"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,9 +1,9 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-DATE-PICKER-TITLE' <h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-VALIDATOR-TITLE'
| translate}}</h5> | translate}}</h5>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-VALIDATOR-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-CHECKBOX-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
</div> </div>

View File

@ -1,28 +1,33 @@
<div class="row" *ngIf="form.get('data')"> <div class="row" *ngIf="form.get('data')">
<div class="col-12">
<h5 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-TITLE' <h5 style="font-weight: bold; display: inline-block; margin-right: 2em;">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-TITLE'
| translate}}</h5> | translate}}</h5>
<ng-container *ngIf="form.get('data').errors?.emptyArray && form.get('data').touched">
<mat-icon class="text-danger translateY-3">warning_amber</mat-icon>
<small class="text-danger">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.ERROR-MESSAGES.FIELD-SELECT-AT-LEAST-ONE-REQUIRED' |translate}}</small>
</ng-container>
</div>
<mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiList')"> <mat-checkbox class="col-auto" [formControl]="this.form.get('data').get('multiList')">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-WORDLIST' | translate}} {{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-MULTIPLE-WORDLIST' | translate}}
</mat-checkbox> </mat-checkbox>
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-PLACEHOLDER' | translate}}</mat-label>
<input matInput type="string" <input matInput type="string"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-PLACEHOLDER' | translate}}"
[formControl]="form.get('data').get('label')"> [formControl]="form.get('data').get('label')">
</mat-form-field> </mat-form-field>
<div class="col-12"> <div class="col-12">
<div *ngFor="let option of form.get('data').get('options')['controls'] index as i" class="row"> <div *ngFor="let option of form.get('data').get('options')['controls'] index as i" class="row">
<mat-form-field class="col"> <mat-form-field class="col">
<input matInput <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-LABEL' | translate}}</mat-label>
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-LABEL' | translate}}" <input matInput type="text" [formControl]="form.get('data').get('options').get(''+i).get('label')">
type="text" [formControl]="form.get('data').get('options').get(''+i).get('label')">
</mat-form-field> </mat-form-field>
<mat-form-field class="col"> <mat-form-field class="col">
<input matInput <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-VALUE' | translate}}</mat-label>
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-WORD-LIST-VALUE' | translate}}" <input matInput [formControl]="form.get('data').get('options').get(''+i).get('value')">
[formControl]="form.get('data').get('options').get(''+i).get('value')">
</mat-form-field> </mat-form-field>
<button mat-icon-button class="col-auto" (click)="deleteRow(i)" type="button" <button mat-icon-button class="col-auto" (click)="deleteRow(i)" type="button"
[disabled]="this.form.disabled"> [disabled]="this.form.disabled">

View File

@ -1,34 +1,175 @@
<ng-container *ngIf="expandView">
<!-- ACTIONS PER FIELD -->
<div class="row justify-content-end mb-1 mt-1">
<div class="col-auto">
<ul class="list-unstyled list-inline d-flex align-items-center">
<li class="list-inline-item" >
<mat-slide-toggle class="field-toggler" [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 && viewType && canApplyVisibility">
<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 && viewType && canBeDeleted">
<mat-icon style="cursor: pointer;" (click)="onDelete()" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.DELETE-INPUT' | translate">delete</mat-icon>
</li>
</ul>
</div>
</div>
<div class="row"> <div class="row">
<mat-form-field class="col"> <!-- <mat-form-field class="col">
<input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.ID' | translate}}" type="text" [formControl]="this.form.get('id')" <input matInput placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.ID' | translate}}" type="text" [formControl]="this.form.get('id')"
required> required>
<mat-error *ngIf="this.form.get('id').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="this.form.get('id').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="this.form.get('id').hasError('pattern')">{{'GENERAL.VALIDATION.PATTERN-_' | translate}}</mat-error> <mat-error *ngIf="this.form.get('id').hasError('pattern')">{{'GENERAL.VALIDATION.PATTERN-_' | translate}}</mat-error>
</mat-form-field> </mat-form-field> -->
<mat-form-field class="col"> <mat-form-field class="col">
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VIEW-STYLE' | translate}}" [formControl]="this.form.get('viewStyle').get('renderStyle')" <!-- <mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VIEW-STYLE' | translate}}" [formControl]="this.form.get('viewStyle').get('renderStyle')"
required> required>
<mat-option [value]="viewStyleEnum.BooleanDecision">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.BooleanDecision)}}</mat-option>
<mat-option [value]="viewStyleEnum.CheckBox">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.CheckBox)}}</mat-option>
<mat-option [value]="viewStyleEnum.TextArea">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.TextArea)}}</mat-option> <mat-option [value]="viewStyleEnum.TextArea">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.TextArea)}}</mat-option>
<mat-option [value]="viewStyleEnum.FreeText">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.FreeText)}}</mat-option> <mat-option [value]="viewStyleEnum.FreeText">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.FreeText)}}</mat-option>
<mat-option [value]="viewStyleEnum.ComboBox">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.ComboBox)}}</mat-option> <mat-divider></mat-divider>
<mat-option [value]="viewStyleEnum.InternalDmpEntities">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.InternalDmpEntities)}}</mat-option> <mat-option [value]="viewStyleEnum.BooleanDecision">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.BooleanDecision)}}</mat-option>
<mat-option [value]="viewStyleEnum.RadioBox">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.RadioBox)}}</mat-option> <mat-option [value]="viewStyleEnum.RadioBox">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.RadioBox)}}</mat-option>
<mat-option [value]="viewStyleEnum.CheckBox">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.CheckBox)}}</mat-option>
<mat-option [value]="viewStyleEnum.ComboBox">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.ComboBox)}}</mat-option>
<mat-divider></mat-divider>
<mat-option [value]="viewStyleEnum.DatePicker">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.DatePicker)}}</mat-option> <mat-option [value]="viewStyleEnum.DatePicker">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.DatePicker)}}</mat-option>
<mat-option [value]="viewStyleEnum.ExternalDatasets">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.ExternalDatasets)}}</mat-option> <mat-option [value]="viewStyleEnum.Currency">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Currency)}}</mat-option>
<mat-option [value]="viewStyleEnum.DataRepositories">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.DataRepositories)}}</mat-option>
<mat-divider></mat-divider>
<mat-optgroup label="APIs">
<mat-option [value]="viewStyleEnum.Registries">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Registries)}}</mat-option> <mat-option [value]="viewStyleEnum.Registries">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Registries)}}</mat-option>
<mat-option [value]="viewStyleEnum.Services">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Services)}}</mat-option> <mat-option [value]="viewStyleEnum.Services">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Services)}}</mat-option>
<mat-option [value]="viewStyleEnum.Tags">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Tags)}}</mat-option>
<mat-option [value]="viewStyleEnum.Researchers">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Researchers)}}</mat-option> <mat-option [value]="viewStyleEnum.Researchers">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Researchers)}}</mat-option>
<mat-option [value]="viewStyleEnum.Organizations">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Organizations)}}</mat-option> <mat-option [value]="viewStyleEnum.Organizations">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Organizations)}}</mat-option>
<mat-option [value]="viewStyleEnum.ExternalDatasets">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.ExternalDatasets)}}</mat-option>
<mat-option [value]="viewStyleEnum.DataRepositories">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.DataRepositories)}}</mat-option>
</mat-optgroup>
<mat-divider></mat-divider>
<mat-optgroup label="Argos Entities">
<mat-option [value]="viewStyleEnum.InternalDmpEntities">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.InternalDmpEntities)}}</mat-option>
<mat-option [value]="viewStyleEnum.Tags">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Tags)}}</mat-option>
<mat-option [value]="viewStyleEnum.DatasetIdentifier">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.DatasetIdentifier)}}</mat-option> <mat-option [value]="viewStyleEnum.DatasetIdentifier">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.DatasetIdentifier)}}</mat-option>
<mat-option [value]="viewStyleEnum.Currency">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Currency)}}</mat-option>
<mat-option [value]="viewStyleEnum.Validation">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Validation)}}</mat-option> <mat-option [value]="viewStyleEnum.Validation">{{enumUtils.toDatasetProfileFieldViewStyleString(viewStyleEnum.Validation)}}</mat-option>
</mat-optgroup>
</mat-select> -->
<!-- NEW VERSION -->
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VIEW-STYLE' | translate}}" [(ngModel)]="viewType" (selectionChange)="onInputTypeChange()"
[disabled]="viewOnly"
[errorStateMatcher]="this"
>
<mat-option [value]="viewTypeEnum.TextArea">
<img src="/assets/images/editor/icons/text_area.svg" class="input_icon" alt="TextArea icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.TextArea)}}
</mat-option>
<mat-option [value]="viewTypeEnum.FreeText">
<img src="/assets/images/editor/icons/free_text.svg" class="input_icon" alt="FreeText icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.FreeText)}}
</mat-option>
<mat-divider></mat-divider>
<mat-option [value]="viewTypeEnum.BooleanDecision">
<img src="/assets/images/editor/icons/boolean.svg" class="input_icon" alt="Boolean icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.BooleanDecision)}}
</mat-option>
<mat-option [value]="viewTypeEnum.RadioBox">
<img src="/assets/images/editor/icons/radio_box.svg" class="input_icon" alt="RadioBox icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.RadioBox)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Select">
<span class="input_icon">
<img src="/assets/images/editor/icons/select.svg" style="padding-right: 7px;" alt="Select icon">
</span>
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Select)}}
</mat-option>
<mat-option [value]="viewTypeEnum.CheckBox">
<img src="/assets/images/editor/icons/checkbox.svg" class="input_icon" alt="CheckBox icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.CheckBox)}}
</mat-option>
<!-- TODO -->
<mat-divider></mat-divider>
<mat-option [value]="viewTypeEnum.DatePicker">
<img src="/assets/images/editor/icons/date_picker.svg" class="input_icon" alt="DatePicker icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DatePicker)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Currency">
<img src="/assets/images/editor/icons/currency.svg" class="input_icon" alt="Current icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Currency)}}
</mat-option>
<mat-divider></mat-divider>
<!-- APIS -->
<mat-optgroup label="APIs">
<mat-option [value]="viewTypeEnum.Registries">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Registries icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Registries)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Services">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Services icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Services)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Researchers">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Researchers icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Researchers)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Organizations">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Organizations icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Organizations)}}
</mat-option>
<mat-option [value]="viewTypeEnum.ExternalDatasets">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="ExternalDatasets icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.ExternalDatasets)}}
</mat-option>
<mat-option [value]="viewTypeEnum.DataRepositories">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="DataRepositories icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DataRepositories)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Other">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Other icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Other)}}
</mat-option>
</mat-optgroup>
<!-- TODO -->
<mat-divider></mat-divider>
<mat-optgroup label="Argos Entities">
<mat-option [value]="viewTypeEnum.InternalDmpEntities">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="InternalDmpEntities icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.InternalDmpEntities)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Tags">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Tags icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Tags)}}
</mat-option>
<mat-option [value]="viewTypeEnum.DatasetIdentifier">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="DatasetIdentifier icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.DatasetIdentifier)}}
</mat-option>
<mat-option [value]="viewTypeEnum.Validation">
<img src="/assets/images/editor/icons/api_entity.svg" class="input_icon" alt="Validation icon">
{{enumUtils.toDatasetProfileViewTypeString(viewTypeEnum.Validation)}}
</mat-option>
</mat-optgroup>
</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 >{{'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 -->
@ -36,20 +177,13 @@
<input matInput type="number" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.ORDER' | translate}}" [formControl]="this.form.get('ordinal')" required> <input matInput type="number" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.ORDER' | translate}}" [formControl]="this.form.get('ordinal')" required>
</mat-form-field> </mat-form-field>
<!-- Default Value -->
<app-component-profile-editor-default-value-component *ngIf="form.get('viewStyle').get('renderStyle').value" class="col"
[viewStyle]="form.get('viewStyle').get('renderStyle').value" [form]="this.form.get('defaultValue').get('value')" [formArrayOptions]="form.get('data')?.get('options')"
[comboBoxType]="this.form.get('data')?.get('type')?.value" [internalDmpEntitiesType]="this.form.get('data')?.get('type')?.value"
placeHolder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.DEFAULT-VALUE' | translate}}" [required]="defaulValueRequired(form.get('viewStyle').get('renderStyle').value)">
</app-component-profile-editor-default-value-component>
<!-- Validation --> <!-- Validation -->
<mat-form-field class="col" *ngIf="!(defaulValueRequired(form.get('viewStyle').get('renderStyle').value))"> <!-- <mat-form-field class="col" *ngIf="!(defaulValueRequired(form.get('viewStyle').get('renderStyle').value))">
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VALIDATION' | translate}}" [formControl]="this.form.get('validations')" <mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.VALIDATION' | translate}}" [formControl]="this.form.get('validations')"
multiple> multiple>
<mat-option [value]="validationTypeEnum.Required">{{enumUtils.toDatasetProfileFieldValidationTypeString(validationTypeEnum.Required)}}</mat-option> <mat-option [value]="validationTypeEnum.Required">{{enumUtils.toDatasetProfileFieldValidationTypeString(validationTypeEnum.Required)}}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field> -->
<mat-form-field class="col"> <mat-form-field class="col">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.RDA-COMMON-STANDARDS' | translate}}</mat-label> <mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.COMPOSITE-FIELD.FIELDS.RDA-COMMON-STANDARDS' | translate}}</mat-label>
@ -61,8 +195,15 @@
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<!-- Default Value -->
<app-component-profile-editor-default-value-component *ngIf="form.get('viewStyle').get('renderStyle').value" class="col-12"
[viewStyle]="form.get('viewStyle').get('renderStyle').value" [form]="this.form.get('defaultValue').get('value')" [formArrayOptions]="form.get('data')?.get('options')"
[comboBoxType]="this.form.get('data')?.get('type')?.value" [internalDmpEntitiesType]="this.form.get('data')?.get('type')?.value"
placeHolder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.DEFAULT-VALUE' | translate}}">
</app-component-profile-editor-default-value-component>
</div> </div>
<div class="row" [ngSwitch]="form.get('viewStyle').get('renderStyle').value"> <div class="row" [ngSwitch]="form.get('viewStyle').get('renderStyle').value" *ngIf="expandView">
<app-dataset-profile-editor-combo-box-field-component *ngSwitchCase="viewStyleEnum.ComboBox" class="col-12" [form]="form"></app-dataset-profile-editor-combo-box-field-component> <app-dataset-profile-editor-combo-box-field-component *ngSwitchCase="viewStyleEnum.ComboBox" class="col-12" [form]="form"></app-dataset-profile-editor-combo-box-field-component>
<app-dataset-profile-internal-dmp-entities-field-component *ngSwitchCase="viewStyleEnum.InternalDmpEntities" class="col-12" [form]="form"></app-dataset-profile-internal-dmp-entities-field-component> <app-dataset-profile-internal-dmp-entities-field-component *ngSwitchCase="viewStyleEnum.InternalDmpEntities" class="col-12" [form]="form"></app-dataset-profile-internal-dmp-entities-field-component>
<app-dataset-profile-editor-radio-box-field-component *ngSwitchCase="viewStyleEnum.RadioBox" class="col-12" [form]="form"></app-dataset-profile-editor-radio-box-field-component> <app-dataset-profile-editor-radio-box-field-component *ngSwitchCase="viewStyleEnum.RadioBox" class="col-12" [form]="form"></app-dataset-profile-editor-radio-box-field-component>
@ -85,13 +226,62 @@
<app-dataset-profile-editor-currency-field-component *ngSwitchCase="viewStyleEnum.Currency" class="col-12" [form]="form"></app-dataset-profile-editor-currency-field-component> <app-dataset-profile-editor-currency-field-component *ngSwitchCase="viewStyleEnum.Currency" class="col-12" [form]="form"></app-dataset-profile-editor-currency-field-component>
<app-dataset-profile-editor-validator-field-component *ngSwitchCase="viewStyleEnum.Validation" class="col-12" [form]="form"></app-dataset-profile-editor-validator-field-component> <app-dataset-profile-editor-validator-field-component *ngSwitchCase="viewStyleEnum.Validation" class="col-12" [form]="form"></app-dataset-profile-editor-validator-field-component>
</div> </div>
<div class="row"> <div class="row" *ngIf="this.form.get('viewStyle').get('renderStyle').value">
<ng-container *ngIf="form.get('visible').get('rules')?.value.length">
<h4 class="col-12" style="font-weight: bold">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.RULES-TITLE' | translate}} <h4 class="col-12" style="font-weight: bold">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.RULES-TITLE' | translate}}
</h4> </h4>
<app-dataset-profile-editor-rule-component class="col-12" [form]="form.get('visible').get('rules')" [viewStyleForCheck]="form.get('viewStyle').get('renderStyle').value" <app-dataset-profile-editor-rule-component class="col-12" [form]="form.get('visible').get('rules')" [viewStyleForCheck]="form.get('viewStyle').get('renderStyle').value"
[formArrayOptionsForCheck]="this.form.get('data')?.get('options')" [comboBoxTypeForCheck]="this.form.get('data')?.get('type')?.value" [formArrayOptionsForCheck]="this.form.get('data')?.get('options')" [comboBoxTypeForCheck]="this.form.get('data')?.get('type')?.value"
[viewOnly]="viewOnly"></app-dataset-profile-editor-rule-component> [viewOnly]="viewOnly"
<div class="col-12" *ngIf="!viewOnly"> [formControlForCheck]="form"></app-dataset-profile-editor-rule-component>
<!-- <div class="col-12" *ngIf="!viewOnly">
<button mat-button class="full-width" (click)="addNewRule()" [disabled]="!form.get('viewStyle').get('renderStyle').value">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.ACTIONS.ADD-RULE' | translate}}</button> <button mat-button class="full-width" (click)="addNewRule()" [disabled]="!form.get('viewStyle').get('renderStyle').value">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.ACTIONS.ADD-RULE' | translate}}</button>
</div> -->
</ng-container>
<!-- <div class="row">
<button (click)="generatePreview()">Generate Preview</button>
</div> -->
</div>
</ng-container>
<!-- PREVIEW -->
<!-- <ng-container *ngIf="false">
<div class="row">
<div class="col-12" *ngIf="expandView && previewForm">
<span style="font-weight: bold">{{'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.PREVIEW' | translate}}</span>
</div> -->
<!-- <div class="col-12">
<mat-radio-group [(ngModel)]="showPreview">
<mat-radio-button [value]="true">Yes</mat-radio-button>
<mat-radio-button [value]="false">No</mat-radio-button>
</mat-radio-group>
</div> -->
<!--
<div class="col-12" *ngIf="showPreview">
<ng-container *ngIf="viewType === viewTypeEnum.Other else regularField">
<app-form-field [form]="previewForm" *ngIf="previewForm" [autocompleteOptions]="form.get('data').get('autoCompleteSingleDataList').getRawValue()">
</app-form-field>
</ng-container>
<ng-template #regularField>
<app-form-field [form]="previewForm" *ngIf="previewForm">
</app-form-field>
</ng-template>
</div>
<div class="col-12" *ngIf="!this.form.get('viewStyle').get('renderStyle').value">
<em>
{{'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.NOT-INITIALIZED' | translate}}
</em>
</div> </div>
</div> </div>
</ng-container> -->
<!-- {{form.touched|json}} -->

View File

@ -1,3 +1,38 @@
.full-width { .full-width {
width: 100%; width: 100%;
} }
.preview-box{
padding: 1em;
border: 1px solid #e8dcdc;
border-radius: 0.3em;
}
mat-radio-button{
padding-right: 1em;
}
li.list-inline-item{
color: #129D99;
.mat-icon{
vertical-align: bottom;
}
}
:host ::ng-deep .field-toggler
{
.mat-slide-toggle-content{
font-size: 0.8em;
color: #212121;
}
.mat-slide-toggle.mat-checked .mat-slide-toggle-thumb {
background-color:#129D99 ;
}
}
.input_icon{
width: 14px;
margin-right: 0.5em;
}

View File

@ -1,6 +1,6 @@
 
import { Component, Input, OnInit } 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, ValidationErrors, ValidatorFn } 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';
@ -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 { 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 { RuleEditorModel } from '@app/ui/admin/dataset-profile/admin/rule-editor-model';
import { BaseComponent } from '@common/base/base.component'; 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 { ExternalDatasetEditorModel } from '@app/ui/dataset/dataset-wizard/dataset-wizard-editor.model';
import { DataRepositoriesDataEditorModel } from '../../../admin/field-data/data-repositories-data-editor-models'; import { DataRepositoriesDataEditorModel } from '../../../admin/field-data/data-repositories-data-editor-models';
import { RegistriesDataEditorModel } from '../../../admin/field-data/registries-data-editor-models'; import { RegistriesDataEditorModel } from '../../../admin/field-data/registries-data-editor-models';
@ -27,139 +27,810 @@ import { DatasetIdentifierDataEditorModel } from '../../../admin/field-data/data
import { ExternalDatasetsDataEditorModel } from '../../../admin/field-data/external-datasets-data-editor-models'; import { ExternalDatasetsDataEditorModel } from '../../../admin/field-data/external-datasets-data-editor-models';
import { CurrencyDataEditorModel } from '../../../admin/field-data/currency-data-editor-models'; import { CurrencyDataEditorModel } from '../../../admin/field-data/currency-data-editor-models';
import { ValidationDataEditorModel } from '../../../admin/field-data/validation-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 { 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';
import { EditorCustomValidators } from '../../custom-validators/editor-custom-validators';
import { Field } from '@app/core/model/admin/dataset-profile/dataset-profile';
import { DatasetProfileInternalDmpEntitiesType } from '@app/core/common/enum/dataset-profile-internal-dmp-entities-type';
import { FieldEditorModel } from '../../../admin/field-editor-model';
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';
@Component({ @Component({
selector: 'app-dataset-profile-editor-field-component', selector: 'app-dataset-profile-editor-field-component',
templateUrl: './dataset-profile-editor-field.component.html', templateUrl: './dataset-profile-editor-field.component.html',
styleUrls: ['./dataset-profile-editor-field.component.scss'] styleUrls: ['./dataset-profile-editor-field.component.scss']
}) })
export class DatasetProfileEditorFieldComponent extends BaseComponent implements OnInit { export class DatasetProfileEditorFieldComponent extends BaseComponent implements OnInit, ErrorStateMatcher {
@Input() viewOnly: boolean; @Input() viewOnly: boolean;
@Input() form: FormGroup; @Input() form: FormGroup;
@Input() showOrdinal = true; @Input() showOrdinal = true;
@Input() indexPath: string; @Input() indexPath: string;
validationTypeEnum = ValidationType; validationTypeEnum = ValidationType;
viewStyleEnum = DatasetProfileFieldViewStyle; viewStyleEnum = DatasetProfileFieldViewStyle;
isFieldMultiplicityEnabled = false; // isFieldMultiplicityEnabled = false;
viewType: ViewStyleType;
viewTypeEnum = ViewStyleType;
// private subject$:Subject<DatasetDescriptionFieldEditorModel> = new Subject<DatasetDescriptionFieldEditorModel>();
@Input() expandView: boolean = true;
@Input() canBeDeleted:boolean = true;
@Output() delete = new EventEmitter<void>();
constructor( constructor(
public enumUtils: EnumUtils, public enumUtils: EnumUtils,
public datasetProfileService: DatasetProfileService public datasetProfileService: DatasetProfileService
) { super(); } ) { super();
}
isErrorState(control: FormControl, form: FormGroupDirective | NgForm): boolean {
if(this.form.get('viewStyle').untouched) return false;
return this.form.get('viewStyle').invalid;
}
ngOnInit() { ngOnInit() {
if (this.form.get('multiplicity')) {
if (this.form.get('multiplicity').value.min > 1 && this.form.get('multiplicity').value.max > 1) {
this.isFieldMultiplicityEnabled = true;
}
}
// this.addNewRule();
this.form.get('viewStyle').get('renderStyle').valueChanges // this.subject$.pipe(takeUntil(this._destroyed)).pipe(debounceTime(600)).subscribe(model=>{
.pipe(takeUntil(this._destroyed)) // this.previewForm = model.buildForm();
.subscribe(x => { // });
if (this.form.get('data')) {
this.form.removeControl('data');
switch (x) {
// 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){
// this.matcher.setReference(this.form);
const type = this.form.get('viewStyle').get('renderStyle').value;
switch(type){
case DatasetProfileFieldViewStyle.BooleanDecision: case DatasetProfileFieldViewStyle.BooleanDecision:
this.form.addControl('data', new BooleanDecisionFieldDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.BooleanDecision;
break; break;
case DatasetProfileFieldViewStyle.CheckBox: case DatasetProfileFieldViewStyle.CheckBox:
this.form.addControl('data', new CheckBoxFieldDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.CheckBox;
break; break;
case DatasetProfileFieldViewStyle.ComboBox: case DatasetProfileFieldViewStyle.ComboBox:
this.form.addControl('data', new WordListFieldDataEditorModel().buildForm());
const comboType = this.form.get('data').get('type').value;
if(comboType === DatasetProfileComboBoxType.Autocomplete){
this.viewType = this.viewTypeEnum.Other;
}else if(comboType === DatasetProfileComboBoxType.WordList){
this.viewType = this.viewTypeEnum.Select;
}
break; break;
case DatasetProfileFieldViewStyle.InternalDmpEntities: case DatasetProfileFieldViewStyle.InternalDmpEntities:
this.form.addControl('data', new ResearchersAutoCompleteFieldDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.InternalDmpEntities;
break; break;
case DatasetProfileFieldViewStyle.FreeText: case DatasetProfileFieldViewStyle.FreeText:
this.form.addControl('data', new FreeTextFieldDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.FreeText;
break; break;
case DatasetProfileFieldViewStyle.RadioBox: case DatasetProfileFieldViewStyle.RadioBox:
this.form.addControl('data', new RadioBoxFieldDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.RadioBox;
break; break;
case DatasetProfileFieldViewStyle.TextArea: case DatasetProfileFieldViewStyle.TextArea:
this.form.addControl('data', new TextAreaFieldDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.TextArea;
break; break;
case DatasetProfileFieldViewStyle.DatePicker: case DatasetProfileFieldViewStyle.DatePicker:
this.form.addControl('data', new DatePickerDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.DatePicker;
break; break;
case DatasetProfileFieldViewStyle.ExternalDatasets: case DatasetProfileFieldViewStyle.ExternalDatasets:
this.form.addControl('data', new ExternalDatasetsDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.ExternalDatasets;
break; break;
case DatasetProfileFieldViewStyle.DataRepositories: case DatasetProfileFieldViewStyle.DataRepositories:
this.form.addControl('data', new DataRepositoriesDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.DataRepositories;
break; break;
case DatasetProfileFieldViewStyle.Registries: case DatasetProfileFieldViewStyle.Registries:
this.form.addControl('data', new RegistriesDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.Registries;
break; break;
case DatasetProfileFieldViewStyle.Services: case DatasetProfileFieldViewStyle.Services:
this.form.addControl('data', new ServicesDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.Services;
break; break;
case DatasetProfileFieldViewStyle.Tags: case DatasetProfileFieldViewStyle.Tags:
this.form.addControl('data', new TagsDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.Tags;
break; break;
case DatasetProfileFieldViewStyle.Researchers: case DatasetProfileFieldViewStyle.Researchers:
this.form.addControl('data', new ResearchersDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.Researchers; //TODO RESEARCHERS
break; break;
case DatasetProfileFieldViewStyle.Organizations: case DatasetProfileFieldViewStyle.Organizations:
this.form.addControl('data', new OrganizationsDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.Organizations;
break; break;
case DatasetProfileFieldViewStyle.DatasetIdentifier: case DatasetProfileFieldViewStyle.DatasetIdentifier:
this.form.addControl('data', new DatasetIdentifierDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.DatasetIdentifier;
break; break;
case DatasetProfileFieldViewStyle.Currency: case DatasetProfileFieldViewStyle.Currency:
this.form.addControl('data', new CurrencyDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.Currency;
break; break;
case DatasetProfileFieldViewStyle.Validation: case DatasetProfileFieldViewStyle.Validation:
this.form.addControl('data', new ValidationDataEditorModel().buildForm()); this.viewType = this.viewTypeEnum.Validation;
break; break;
} }
}
});
} }
defaulValueRequired(viewStile: DatasetProfileFieldViewStyle): boolean { // this.showPreview = true;
switch (viewStile) {
case DatasetProfileFieldViewStyle.CheckBox:
return true;
case DatasetProfileFieldViewStyle.RadioBox:
case DatasetProfileFieldViewStyle.TextArea:
case DatasetProfileFieldViewStyle.FreeText:
case DatasetProfileFieldViewStyle.ComboBox:
case DatasetProfileFieldViewStyle.InternalDmpEntities:
case DatasetProfileFieldViewStyle.BooleanDecision:
case DatasetProfileFieldViewStyle.DatePicker:
case DatasetProfileFieldViewStyle.ExternalDatasets:
case DatasetProfileFieldViewStyle.DataRepositories:
case DatasetProfileFieldViewStyle.Registries:
case DatasetProfileFieldViewStyle.Services:
case DatasetProfileFieldViewStyle.Tags:
case DatasetProfileFieldViewStyle.Registries:
case DatasetProfileFieldViewStyle.Organizations:
case DatasetProfileFieldViewStyle.DatasetIdentifier:
case DatasetProfileFieldViewStyle.Currency:
case DatasetProfileFieldViewStyle.Validation:
return false;
default:
return false;
}
}
onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled: boolean) {
if (!isFieldMultiplicityEnabled) { // this.addNewRule();
(<FormControl>this.form.get('multiplicity').get('min')).setValue(0);
(<FormControl>this.form.get('multiplicity').get('max')).setValue(0); // this.form.get('viewStyle').get('renderStyle').valueChanges
} // .pipe(takeUntil(this._destroyed))
// .subscribe(x => {
// // const previewStatus = this.showPreview;
// //!! Important to be before the if statement
// this.showPreview = false;
// if (this.form.get('data')) {
// this.form.removeControl('data');
// switch (x) {
// case DatasetProfileFieldViewStyle.BooleanDecision:
// this.form.addControl('data', new BooleanDecisionFieldDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.CheckBox:
// this.form.addControl('data', new CheckBoxFieldDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.ComboBox:
// this.form.addControl('data', new WordListFieldDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.InternalDmpEntities:
// this.form.addControl('data', new ResearchersAutoCompleteFieldDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.FreeText:
// this.form.addControl('data', new FreeTextFieldDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.RadioBox:
// this.form.addControl('data', new RadioBoxFieldDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.TextArea:
// this.form.addControl('data', new TextAreaFieldDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.DatePicker:
// this.form.addControl('data', new DatePickerDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.ExternalDatasets:
// this.form.addControl('data', new ExternalDatasetsDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.DataRepositories:
// this.form.addControl('data', new DataRepositoriesDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.Registries:
// this.form.addControl('data', new RegistriesDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.Services:
// this.form.addControl('data', new ServicesDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.Tags:
// this.form.addControl('data', new TagsDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.Researchers:
// this.form.addControl('data', new ResearchersDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.Organizations:
// this.form.addControl('data', new OrganizationsDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.DatasetIdentifier:
// this.form.addControl('data', new DatasetIdentifierDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.Currency:
// this.form.addControl('data', new CurrencyDataEditorModel().buildForm());
// break;
// case DatasetProfileFieldViewStyle.Validation:
// this.form.addControl('data', new ValidationDataEditorModel().buildForm());
// break;
// }
// }
// //reset the preview status
// // this.showPreview = previewStatus;
// this.showPreview = true;
// });
} }
// defaulValueRequired(viewStile: DatasetProfileFieldViewStyle): boolean {
// switch (viewStile) {
// case DatasetProfileFieldViewStyle.CheckBox:
// return true;
// case DatasetProfileFieldViewStyle.RadioBox:
// case DatasetProfileFieldViewStyle.TextArea:
// case DatasetProfileFieldViewStyle.FreeText:
// case DatasetProfileFieldViewStyle.ComboBox:
// case DatasetProfileFieldViewStyle.InternalDmpEntities:
// case DatasetProfileFieldViewStyle.BooleanDecision:
// case DatasetProfileFieldViewStyle.DatePicker:
// case DatasetProfileFieldViewStyle.ExternalDatasets:
// case DatasetProfileFieldViewStyle.DataRepositories:
// case DatasetProfileFieldViewStyle.Registries:
// case DatasetProfileFieldViewStyle.Services:
// case DatasetProfileFieldViewStyle.Tags:
// case DatasetProfileFieldViewStyle.Registries:
// case DatasetProfileFieldViewStyle.Organizations:
// case DatasetProfileFieldViewStyle.DatasetIdentifier:
// case DatasetProfileFieldViewStyle.Currency:
// case DatasetProfileFieldViewStyle.Validation:
// return false;
// default:
// return false;
// }
// }
// onIsFieldMultiplicityEnabledChange(isFieldMultiplicityEnabled: boolean) {
// if (!isFieldMultiplicityEnabled) {
// (<FormControl>this.form.get('multiplicity').get('min')).setValue(0);
// (<FormControl>this.form.get('multiplicity').get('max')).setValue(0);
// }
// }
addNewRule() { addNewRule() {
const rule: RuleEditorModel = new RuleEditorModel(); const rule: RuleEditorModel = new RuleEditorModel();
(<FormArray>this.form.get('visible').get('rules')).push(rule.buildForm()); (<FormArray>this.form.get('visible').get('rules')).push(rule.buildForm());
} }
private _formChangesSubscription:Subscription;
private _showPreview: boolean = false;;
// get showPreview(): boolean{
// return this._showPreview;
// }
// set showPreview(value:boolean){
// if(value == false){//hide preview
// //close subsciption
// if(this._formChangesSubscription){
// this._formChangesSubscription.unsubscribe();
// this._formChangesSubscription = null;
// }
// }
// if(value == true){
// //value is already true
// if(this._showPreview){
// if(this._formChangesSubscription){
// this._formChangesSubscription.unsubscribe();
// this._formChangesSubscription = null;
// }
// }
// //initialize
// if(this.form.get('viewStyle').get('renderStyle').value){
// this._generatePreviewForm();
// }
// this._formChangesSubscription = this.form.valueChanges.subscribe(()=>{
// this._generatePreviewForm();
// });
// }
// this._showPreview = value;
// }
// previewForm: FormGroup;
// private _generatePreviewForm(){
// if(!this.form.get('data')){
// return;
// }
// this.previewForm = null;
// const fieldEditorModel = new DatasetDescriptionFieldEditorModel();
// fieldEditorModel.viewStyle= {
// renderStyle: this.form.get('viewStyle').get('renderStyle').value,
// 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);
// if(this.form.get('viewStyle').get('renderStyle').value == DatasetProfileFieldViewStyle.CheckBox){
// fieldEditorModel.value = this.form.get('defaultValue').get('value').value === 'true';
// }
// // if(this.form.get('viewStyle').get('renderStyle').value == DatasetProfileFieldViewStyle.Researchers){
// // fieldEditorModel.data = new ResearchersAutoCompleteFieldDataEditorModel().buildForm().getRawValue();
// // }
// if(fieldEditorModel.viewStyle.renderStyle === DatasetProfileFieldViewStyle.Validation || (fieldEditorModel.viewStyle.renderStyle === DatasetProfileFieldViewStyle.DatasetIdentifier)
// || (fieldEditorModel.viewStyle.renderStyle === DatasetProfileFieldViewStyle.Tags)
// ){
// fieldEditorModel.value = null;
// }
// // 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(() => {
// // this.previewForm = fieldEditorModel.buildForm();
// // });
// };
get canApplyVisibility():boolean{
switch(this.viewType){
case this.viewTypeEnum.TextArea:
case this.viewTypeEnum.FreeText:
case this.viewTypeEnum.BooleanDecision:
case this.viewTypeEnum.RadioBox:
case this.viewTypeEnum.Select:
case this.viewTypeEnum.CheckBox:
case this.viewTypeEnum.DatePicker:
return true;
}
return false;
}
// validTicket:string;
// generatePreview(){
// const fieldEditorModel = new DatasetDescriptionFieldEditorModel();
// fieldEditorModel.viewStyle= {
// renderStyle: this.form.get('viewStyle').get('renderStyle').value,
// cssClass: null
// };
// fieldEditorModel.defaultValue = this.form.get('defaultValue').value;
// switch (this.form.get('viewStyle').get('renderStyle').value) {
// case DatasetProfileFieldViewStyle.TextArea:
// fieldEditorModel.data = {
// label: this.form.get('data').get('label').value
// };
// break;
// default:
// break;
// }
// // this.previewForm = fieldEditorModel.buildForm();
// }
onInputTypeChange(){
const x = this.viewType;
// this.showPreview = false;
const field: Field = this.form.getRawValue();
// field.defaultValue = {type:null, value: null};
field.defaultValue = undefined;
if(!this.canApplyVisibility){
field.visible.rules = [];
}
// 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:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.BooleanDecision)
// this.form.addControl('data', new BooleanDecisionFieldDataEditorModel().buildForm());
const data: BooleanDecisionFieldData = {
label:""
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.BooleanDecision;
field.data = data;
break;
}
case this.viewTypeEnum.CheckBox:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.CheckBox)
// this.form.addControl('data', new CheckBoxFieldDataEditorModel().buildForm());
const data: CheckBoxFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.CheckBox;
field.data = data;
break;
}
case this.viewTypeEnum.Select:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
// this.form.addControl('data', new WordListFieldDataEditorModel().buildForm());
// this.form.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('options'));
// this.form.get('data').updateValueAndValidity();
const option1 = {label:'', value:''} as FieldDataOption;
const data:WordListFieldData = {
label:'',
multiList:false,
options:[option1],
type:DatasetProfileComboBoxType.WordList
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.ComboBox;
field.data = data;
break;
}
case this.viewTypeEnum.Other:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ComboBox)
// this.form.addControl('data', new AutoCompleteFieldDataEditorModel().buildForm()); //TODO SEE
// this.form.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('autoCompleteSingleDataList'));
// this.form.get('data').updateValueAndValidity();
const data: AutoCompleteFieldData = {
autoCompleteSingleDataList:[],
multiAutoComplete: false,
label:'',
type: DatasetProfileComboBoxType.Autocomplete
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.ComboBox;
field.data = data;
break;
}
case this.viewTypeEnum.InternalDmpEntities:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.InternalDmpEntities)
// this.form.addControl('data', new ResearchersAutoCompleteFieldDataEditorModel().buildForm());//TODO TO SEE
const data: DmpsAutoCompleteFieldData = {
label:'',
multiAutoComplete: false,
type: DatasetProfileInternalDmpEntitiesType.Dmps
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.InternalDmpEntities;
field.data = data;
break;
}
case this.viewTypeEnum.FreeText:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.FreeText)
// this.form.addControl('data', new FreeTextFieldDataEditorModel().buildForm());
const data: FreeTextFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.FreeText;
field.data = data;
break;
}
case this.viewTypeEnum.RadioBox:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.RadioBox)
// this.form.addControl('data', new RadioBoxFieldDataEditorModel().buildForm());
// this.form.get('data').setValidators(EditorCustomValidators.atLeastOneElementListValidator('options'));
// this.form.get('data').updateValueAndValidity();
const data: RadioBoxFieldData= {
label:'',
options: []
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.RadioBox;
field.data = data;
break;
}
case this.viewTypeEnum.TextArea:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.TextArea)
// this.form.addControl('data', new TextAreaFieldDataEditorModel().buildForm());
const data: TextAreaFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.TextArea;
field.data = data;
break;
}
case this.viewTypeEnum.DatePicker:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatePicker)
// this.form.addControl('data', new DatePickerDataEditorModel().buildForm());
const data: DatePickerFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.DatePicker;
field.data = data;
break;
}
case this.viewTypeEnum.ExternalDatasets:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.ExternalDatasets)
// this.form.addControl('data', new ExternalDatasetsDataEditorModel().buildForm());
const data: ExternalDatasetsFieldData = {
label:'',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.ExternalDatasets;
field.data = data;
break;
}
case this.viewTypeEnum.DataRepositories:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DataRepositories)
// this.form.addControl('data', new DataRepositoriesDataEditorModel().buildForm());
const data: DataRepositoriesFieldData = {
label: '',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.DataRepositories;
field.data = data;
break;
}
case this.viewTypeEnum.Registries:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Registries)
// this.form.addControl('data', new RegistriesDataEditorModel().buildForm());
const data:RegistriesFieldData = {
label: '',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Registries;
field.data = data;
break;
}
case this.viewTypeEnum.Services:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Services)
// this.form.addControl('data', new ServicesDataEditorModel().buildForm());
const data:ServicesFieldData = {
label:'',
multiAutoComplete: false
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Services;
field.data = data;
break;
}
case this.viewTypeEnum.Tags:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Tags)
// this.form.addControl('data', new TagsDataEditorModel().buildForm());
const data: TagsFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Tags;
field.data = data;
break;
}
case this.viewTypeEnum.Researchers:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Researchers)
// // this.form.addControl('data', new ResearchersDataEditorModel().buildForm()); //TODO TO ASK
// this.form.addControl('data', new ResearchersAutoCompleteFieldDataEditorModel().buildForm());
// field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Researchers;
const data : ResearchersAutoCompleteFieldData = {
label:'',
multiAutoComplete: false,
type: DatasetProfileInternalDmpEntitiesType.Researchers
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.InternalDmpEntities;
field.data = data;
break;
}
case this.viewTypeEnum.Organizations:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Organizations)
// this.form.addControl('data', new OrganizationsDataEditorModel().buildForm());
const data = {
autoCompleteSingleDataList:[],
label:'',
multiAutoComplete: false,
} as OrganizationsFieldData; //TODO
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Organizations;
field.data = data;
break;
}
case this.viewTypeEnum.DatasetIdentifier:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.DatasetIdentifier)
// this.form.addControl('data', new DatasetIdentifierDataEditorModel().buildForm());
const data : DatasetIdentifierFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.DatasetIdentifier;
field.data = data;
break;
}
case this.viewTypeEnum.Currency:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Currency)
// this.form.addControl('data', new CurrencyDataEditorModel().buildForm());
const data: CurrencyFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Currency;
field.data = data;
break;
}
case this.viewTypeEnum.Validation:{
// this.form.get('viewStyle').get('renderStyle').setValue(DatasetProfileFieldViewStyle.Validation)
// this.form.addControl('data', new ValidationDataEditorModel().buildForm());
const data:ValidationFieldData = {
label:''
}
field.viewStyle.renderStyle = DatasetProfileFieldViewStyle.Validation;
field.data = data;
break;
}
}
// this.form.get('data').updateValueAndValidity();
// this.form.get('viewStyle').get('renderStyle').updateValueAndValidity();
// this.form.updateValueAndValidity();
const form = (new FieldEditorModel).fromModel(field).buildForm();
const fields = this.form.parent as FormArray;
let index = -1;
fields.controls.forEach((control,i)=>{
if(this.form.get('id').value === control.get('id').value){
index = i
}
});
if(index>=0){
fields.removeAt(index);
fields.insert(index, form);
this.form = form;
}
// setTimeout(() => { //TODO
// this.showPreview = true;
// });
}
toggleRequired(event:MatSlideToggleChange){
let validationsControl = this.form.get('validations') as FormControl;
let validations: Array<ValidationType> = validationsControl.value;
if(event.checked){
if(!validations.includes(ValidationType.Required)){//IS ALREADY REQUIRED
// validationsControl.setValue(validations.filter(validator=> validator != ValidationType.Required));
// validationsControl.updateValueAndValidity();
validations.push(ValidationType.Required);
// validationsControl.setValue(validations);
validationsControl.updateValueAndValidity();
}
}else{
validationsControl.setValue(validations.filter(validator=> validator != ValidationType.Required));
validationsControl.updateValueAndValidity();
}
}
get isRequired(){
let validationsControl = this.form.get('validations') as FormControl;
let validations: Array<ValidationType> = validationsControl.value;
if(validations.includes(ValidationType.Required)){
return true;
}
return false;
}
onDelete(){
this.delete.emit();
}
} }

View File

@ -0,0 +1,21 @@
export enum ViewStyleType{
TextArea = "textarea",
BooleanDecision = "booleanDecision",
CheckBox = "checkBox",
FreeText = "freetext",
RadioBox = "radiobox",
DatePicker = "datePicker",
InternalDmpEntities = "internalDmpEntities",
ExternalDatasets = "externalDatasets",
DataRepositories = "dataRepositories",
Registries = "registries",
Services = "services",
Tags = "tags",
Researchers = "researchers",
Organizations = "organizations",
DatasetIdentifier = "datasetIdentifier",
Currency = "currency",
Validation = 'validation',
Select ="selection",
Other ="other"
}

View File

@ -0,0 +1,3 @@
<app-dataset-description [form]="formGroup" [visibilityRules]="visibilityRules" *ngIf="formGroup">
</app-dataset-description>

View File

@ -0,0 +1,28 @@
import { Component, Input, OnInit} from '@angular/core';
import { Rule } from '@app/core/model/dataset-profile-definition/rule';
import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service';
@Component({
selector: 'app-final-preview-component',
templateUrl: './final-preview.component.html',
styleUrls: ['./final-preview.component.scss'],
providers:[VisibilityRulesService]
})
export class FinalPreviewComponent implements OnInit {
@Input() formGroup = null;
@Input() visibilityRules:Rule[] = [];
constructor(private visibilityRulesService: VisibilityRulesService){
}
ngOnInit(): void {
this.visibilityRulesService.buildVisibilityRules(this.visibilityRules, this.formGroup);
}
}

View File

@ -1,24 +1,99 @@
<div class="row" *ngFor="let ruleFormGroup of form['controls'] let i=index;" [formGroup]="ruleFormGroup"> <div class="row" *ngFor="let ruleFormGroup of form['controls'] let i=index;" [formGroup]="ruleFormGroup">
<span class="col-auto">{{i + 1}}</span> <span class="col-auto align-self-center">{{i + 1}}</span>
<span class="col-auto">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-IF'| translate}}</span> <!-- <span class="col-auto">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-IF'| translate}}</span> -->
<!-- Value --> <!-- Value -->
<app-component-profile-editor-default-value-component class="col" [viewStyle]="viewStyleForCheck" [form]="ruleFormGroup.get('value')" <!-- <app-component-profile-editor-default-value-component class="col" [viewStyle]="viewStyleForCheck" [form]="ruleFormGroup.get('value')"
[formArrayOptions]="formArrayOptionsForCheck" [comboBoxType]="comboBoxTypeForCheck" placeHolder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RULES-VALUE' | translate}}" [formArrayOptions]="formArrayOptionsForCheck" [comboBoxType]="comboBoxTypeForCheck" placeHolder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.FIELD.FIELDS.FIELD-RULES-VALUE' | translate}}"
required="true"></app-component-profile-editor-default-value-component> -->
<app-component-profile-editor-default-value-component class="col align-self-center" [viewStyle]="viewStyleForCheck" [form]="ruleFormGroup.get('value')"
[formArrayOptions]="formArrayOptionsForCheck" [comboBoxType]="comboBoxTypeForCheck" placeHolder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-IF'| translate}}"
required="true"></app-component-profile-editor-default-value-component> required="true"></app-component-profile-editor-default-value-component>
<span class="col-auto">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-THEN'| translate}}</span> <!-- <span class="col-auto">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-THEN'| translate}}</span> -->
<!-- Field Or Section ID --> <!-- Field Or Section ID -->
<mat-form-field class="col-auto"> <!-- <mat-form-field class="col-auto">
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.TARGET' | translate}}" <input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.TARGET' | translate}}"
formControlName="target" (change)="targetValidation()" required> formControlName="target" (change)="targetValidation()" required>
<mat-error>{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error>{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
-->
<!-- SELECTION -->
<mat-form-field class="col align-self-center">
<mat-label>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.RULE-THEN'| translate}}</mat-label>
<mat-select formControlName="target" (openedChange)="computeOptions($event)">
<!-- SHOW SECTIONS -->
<!-- <mat-optgroup label="Sections" *ngIf="false">
<mat-option *ngFor="let option of sectionOptions" [value]="option.id" style="line-height: normal;"
[disabled]="parentIds.includes(option.id)">
<span>
{{option.label? option.label:'<'+ ('DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate) + '>'}}
</span> <br>
<small>
{{option.id}}
</small>
</mat-option>
</mat-optgroup> -->
<!-- SHOW FIELDSETS -->
<mat-optgroup [label]="'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.FIELDSETS' | translate">
<mat-option *ngFor="let option of fieldSetOptions" [value]="option.id" style="line-height: normal;"
[disabled]="parentIds.includes(option.id) || hiddenBy.includes(option.id)"
[matTooltip]="getToolTipMessage(option.id)"
[matTooltipShowDelay]="700"
>
<span>
{{option.label? option.label:'<'+ ('DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate) + '>'}}
</span> <br>
<small>
{{option.id}}
</small>
</mat-option>
</mat-optgroup>
<!-- SHOW FIELDS -->
<mat-optgroup [label]="'DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.FIELDS.FIELDS' | translate">
<mat-option *ngFor="let option of fieldOptions" [value]="option.id" style="line-height: normal;"
[disabled]="parentIds.includes(option.id) ||hiddenBy.includes(option.id)"
[matTooltip]="getToolTipMessage(option.id)"
[matTooltipShowDelay]="700"
>
<span>
{{option.label? option.label:'<'+ ('DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate) + '>'}}
</span> <br>
<small>
{{option.id}}
</small>
</mat-option>
</mat-optgroup>
<div class="col-auto"><button mat-icon-button type="button" (click)="deleteRule(i);" [disabled]="viewOnly"> </mat-select>
<mat-error>{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<div class="col-auto align-self-center"><button mat-icon-button type="button" (click)="deleteRule(i);" [disabled]="viewOnly">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
</button> </button>
</div> </div>
</div> </div>
<!--
{{parentIds |json}}
<br>
{{this.formControlForCheck.value | json}} -->
<!--
<ng-template #optionTemplate>
<span>
{{option.label? option.label: '< Not Set> '}}
</span> <br>
<small>
{{option.id}}
</small>
</ng-template> -->

View File

@ -1,7 +1,10 @@
import { Component, Input } from '@angular/core'; import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { FormArray, FormControl } from '@angular/forms'; import { FormArray, FormControl, FormGroup } from '@angular/forms';
import { DatasetProfileFieldViewStyle } from '../../../../../../core/common/enum/dataset-profile-field-view-style'; import { DatasetProfileFieldViewStyle } from '../../../../../../core/common/enum/dataset-profile-field-view-style';
import { DatasetProfileComboBoxType } from '../../../../../../core/common/enum/dataset-profile-combo-box-type'; import { DatasetProfileComboBoxType } from '../../../../../../core/common/enum/dataset-profile-combo-box-type';
import { ToCEntryType } from '../../../table-of-contents/table-of-contents-entry';
import { Rule } from '@app/core/model/admin/dataset-profile/dataset-profile';
import { TranslateService } from '@ngx-translate/core';
@Component({ @Component({
selector: 'app-dataset-profile-editor-rule-component', selector: 'app-dataset-profile-editor-rule-component',
@ -9,7 +12,8 @@ import { DatasetProfileComboBoxType } from '../../../../../../core/common/enum/d
styleUrls: ['./dataset-profile-editor-rule.component.scss'] styleUrls: ['./dataset-profile-editor-rule.component.scss']
}) })
export class DatasetProfileEditorRuleComponent { export class DatasetProfileEditorRuleComponent implements OnInit{
@Input() form: FormArray; @Input() form: FormArray;
@ -19,6 +23,16 @@ export class DatasetProfileEditorRuleComponent {
@Input() comboBoxTypeForCheck: DatasetProfileComboBoxType; @Input() comboBoxTypeForCheck: DatasetProfileComboBoxType;
@Input() viewOnly: boolean; @Input() viewOnly: boolean;
options: OptionItem[];
sectionOptions: OptionItem[];
fieldSetOptions: OptionItem[];
fieldOptions: OptionItem[];
constructor(private language: TranslateService){
}
targetValidation() { targetValidation() {
//TODO //TODO
} }
@ -26,4 +40,170 @@ export class DatasetProfileEditorRuleComponent {
deleteRule(index) { deleteRule(index) {
this.form.removeAt(index); this.form.removeAt(index);
} }
ngOnInit(): void {
this._computeOptions();
}
private _computeOptions(){
this.options = this.getOptions();
this.sectionOptions = [];
this.fieldOptions = [];
this.fieldSetOptions = [];
this.options.forEach(option=>{
switch (option.type) {
case ToCEntryType.Field:
this.fieldOptions.push(option);
break;
case ToCEntryType.FieldSet:
this.fieldSetOptions.push(option);
break;
case ToCEntryType.Section:
this.sectionOptions.push(option);
break;
default:
break;
}
});
//remove options to hide if given fieldset is already hidden by option
this.fieldOptions.forEach(e=>this._buildHiddenBy(e));
this.fieldSetOptions.forEach(e=>this._buildHiddenBy(e));
}
computeOptions(isOpened: boolean){
if(isOpened){
this._computeOptions();
}
}
private _buildHiddenBy(fo:OptionItem){
try{
this.fieldOptions.forEach(foption=>{
const rules = (foption.form.get('visible').get('rules') as FormArray).controls.map(c=>(c as FormGroup).getRawValue()) as Rule[]
const targets = rules.map(rule=>rule.target);
targets.forEach(target=>{
if(fo.parentsIds.includes(target) && !fo.hiddenBy.includes(foption.id)){
fo.hiddenBy.push(...foption.parentsIds);
}
})
});
}catch{
console.log('error');
}
}
getOptions():OptionItem[]{
const rootForm = this.form.root;
if(rootForm){
// const parentSections = rootForm.get('sections') as FormArray;
const result:OptionItem[] =[];
const sections = rootForm.get('sections') as FormArray;
if(sections){
sections.controls.forEach(section=>{
const subResult = this.buildOptions(section as FormGroup, ToCEntryType.Section,[]);
result.push(...subResult);
});
}
//return options
return result;
}
//nothing found
return [];
}
private buildOptions(form: FormGroup, type: ToCEntryType, parentIds:string[]):OptionItem[]{
const sections = form.get('sections') as FormArray;
const fieldSets = form.get('fieldSets') as FormArray;
const fields = form.get('fields') as FormArray;
const result:OptionItem[] = [];
// parentIds.push(form.get('id').value);
const currentOptionItem:OptionItem = {
id: form.get('id').value,
type: type,
label: type ===ToCEntryType.Field? form.get('data').get('label').value :form.get('title').value,
// parentsIds: [form.get('id').value]
parentsIds: [...parentIds, form.get('id').value],
form: form,
hiddenBy:[]
}
result.push(currentOptionItem);
if(sections){
sections.controls.forEach(section=>{
result.push( ...this.buildOptions(section as FormGroup, ToCEntryType.Section, currentOptionItem.parentsIds) );
});
}
if(fieldSets){
fieldSets.controls.forEach(fieldset=>{
result.push( ...this.buildOptions(fieldset as FormGroup, ToCEntryType.FieldSet, currentOptionItem.parentsIds) );
});
}
if(fields){
fields.controls.forEach(field=>{
result.push( ...this.buildOptions(field as FormGroup, ToCEntryType.Field, currentOptionItem.parentsIds) ); //TODO NA TO DOUME
});
}
return result;
}
get parentIds(): string[]{
if(!this.formControlForCheck.get('id')) return [];
const current = this.options.find(opt=> opt.id === this.formControlForCheck.get('id').value);
if(current){
return current.parentsIds;
}
return [];
}
get hiddenBy(): string[]{
if(!this.formControlForCheck.get('id')) return [];
const current = this.options.find(opt=> opt.id === this.formControlForCheck.get('id').value);
if(current){
return current.hiddenBy;
}
return [];
}
getToolTipMessage(id: string){
if(this.parentIds.includes(id)){
// return 'Cannot hide element that contain the field';
return this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.HINTS.ELEMENT-CHILD-OF-TARGET');
}else if(this.hiddenBy.includes(id)){
return this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.RULE.HINTS.ELEMENT-HIDDEN-FROM-ELEMENT');
}
return '';
}
}
interface OptionItem{
id: string,
label: string,
type: ToCEntryType,
parentsIds: string[],
form:FormGroup,
hiddenBy:string[]
} }

View File

@ -0,0 +1,154 @@
<div id="topofcontainer"></div>
<div class="row" [id]="idprefix+form.get('id').value">
<div class="col-12" >
<div class="row">
<!-- SECTION INFO -->
<mat-card style="margin-bottom: 2em; padding: 2em;" class="col-9">
<mat-card-content>
<app-dataset-profile-editor-section-component
[form]="form"
[viewOnly]="viewOnly"
>
</app-dataset-profile-editor-section-component>
</mat-card-content>
</mat-card>
<div class="col-2 col-xl-auto ml-4" *ngIf="!selectedFieldSetId && !viewOnly">
<div class="row bg-white actions-list">
<nav>
<label class="action-list-label">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.GENERAL-TOOLS' | translate}}</label>
<ul class="list-unstyled">
<li class="mli">
<div class="action-list-item" (click)="onAddFieldSet()">
<!-- <mat-icon class="action-list-icon">folder</mat-icon> -->
<img src="/assets/images/editor/icons/add_input_set.svg" class="input_icon" alt="Add Question icon">
<span class="action-list-text" >{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.NEW-INPUT-SET' | translate}}</span>
</div>
</li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<!-- FIELDSET INFO -->
<div class="col-12" dragula="FIELDSETS" [(dragulaModel)]="form.get('fieldSets').controls">
<div style="margin-bottom: 2em;" class="row"
*ngFor="let fieldset of form.get('fieldSets')?.controls ; let i=index"[id]="idprefix+fieldset.get('id').value"
>
<!-- <h4 style="font-weight: bold" class="col-12">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.FIELDS-TITLE' |
translate}}</h4> -->
<!-- <div class="col-12"> -->
<!-- <mat-card-title class="col">{{i + 1}}. {{getFieldTile(fieldControl, i)}}
</mat-card-title> -->
<!-- <button mat-icon-button type="button" class="deleteBtn col-auto"
(click)="deleteFieldSet(selectedTocEntry.form, i);" [disabled]="viewOnly">
<mat-icon>delete</mat-icon>
</button> -->
<mat-card class="col-9"
(click)="selectedFieldSetId = fieldset.get('id').value"
[ngClass]="{'field-container-active': fieldset.get('id').value === selectedFieldSetId}">
<mat-card-content>
<mat-card-header *ngIf="(fieldset.get('id').value === selectedFieldSetId) && !viewOnly">
<mat-icon class="handle" style="display:inline-block; margin: 0px auto; cursor: grab;transform: rotate(90deg);" cdkDragHandle>drag_indicator</mat-icon>
</mat-card-header>
<app-dataset-profile-editor-composite-field-component [form]="fieldset"
[viewOnly]="viewOnly"
[numbering]="numbering + '.'+ (i+1)"
[hasFocus]="fieldset.get('id').value === selectedFieldSetId">
</app-dataset-profile-editor-composite-field-component>
</mat-card-content>
</mat-card>
<div class="col-2 col-xl-auto ml-4" *ngIf="selectedFieldSetId === fieldset.get('id').value &&(!viewOnly)">
<div class="row bg-white actions-list">
<nav *ngIf="!viewOnly">
<label class="action-list-label">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.GENERAL-TOOLS' | translate}}</label>
<ul class="list-unstyled">
<li class="mli">
<div class="action-list-item" (click)="onAddFieldSet()">
<!-- <mat-icon class="action-list-icon">folder</mat-icon> -->
<img src="/assets/images/editor/icons/add_input_set.svg" class="input_icon" alt="Add Question icon">
<span class="action-list-text" >{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.NEW-INPUT-SET' | translate}}</span>
</div>
</li>
<li class="mli">
<div class="action-list-item" (click)="onCloneFieldSet(fieldset)">
<!-- <mat-icon class="action-list-icon">file_copy</mat-icon> -->
<img src="/assets/images/editor/icons/clone.svg" class="input_icon" alt="Clone icon">
<span class="action-list-text">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.CLONE' | translate}}</span>
</div>
</li>
<li class="mli">
<div class="action-list-item" (click)="onRemoveFieldSet(selectedFieldSetId)">
<mat-icon class="action-list-icon">delete</mat-icon>
<span class="action-list-text">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}}</span>
</div>
</li>
</ul>
</nav>
</div>
</div>
<!-- </div> -->
<!-- <div class="col-12"><button mat-button class="full-width" (click)="addField()"
[disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.ACTIONS.ADD-FIELD'
| translate}}</button></div> -->
</div>
</div>
</div>
<!-- COPIA -->
<!-- <div class="row"> -->
<!-- SECTION INFO -->
<!-- <app-dataset-profile-editor-section-component class="col-12 content-displayer p-2" style="margin-bottom: 2em;"
[form]="selectedTocEntry.form"
[viewOnly]="viewOnly"
(fieldsetAdded)="displayItem(_findTocEntryById($event, getTocEntries())); onDataNeedsRefresh();">
</app-dataset-profile-editor-section-component> -->
<!-- FIELDSET INFO -->
<!-- <div class="col-12 content-displayer p-2" style="margin-bottom: 2em;"
*ngFor="let fieldset of selectedTocEntry.form.get('fieldSets')?.controls ; let i=index"> -->
<!-- <h4 style="font-weight: bold" class="col-12">
{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.FIELDS-TITLE' |
translate}}</h4> -->
<!-- <div class="col-12"> -->
<!-- <mat-card-title class="col">{{i + 1}}. {{getFieldTile(fieldControl, i)}}
</mat-card-title> -->
<!-- <button mat-icon-button type="button" class="deleteBtn col-auto"
(click)="deleteFieldSet(selectedTocEntry.form, i);" [disabled]="viewOnly">
<mat-icon>delete</mat-icon>
</button> -->
<!-- <app-dataset-profile-editor-composite-field-component class="p-0" [form]="fieldset"
[indexPath]="'indexPath' + 'cf' + 'i'" [viewOnly]="viewOnly"
[numbering]="selectedTocEntry.numbering + '.'+ (i+1)">
</app-dataset-profile-editor-composite-field-component> -->
<!-- </div> -->
<!-- <div class="col-12"><button mat-button class="full-width" (click)="addField()"
[disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.ACTIONS.ADD-FIELD'
| translate}}</button></div> -->
<!-- </div> -->
<!-- </div> -->

View File

@ -0,0 +1,60 @@
$blue-color : #129D99;
$blue-color-light: #5cf7f2;
.field-container-active{
border-radius: .3em;
border-left: 0.3em solid $blue-color;
}
.fieldset-actions-list li{
cursor: pointer;
}
.actions-list{
// border: 1px solid $blue-color;
// box-shadow: 0px 3px 12px #129D9999;
border-radius: 4px;
// padding-top: 1rem;
padding: 1em 0.9em;
padding-bottom: 3em;
min-width: 166px;
.mat-list-item-content{
padding: 0px;
}
.action-list-item{
display: flex;
align-items: center;
cursor: pointer;
.action-list-icon{
font-size: 1.2em;
// padding-right: 1em;
width: 14px;
margin-right: 0.5em;
margin-left: -.09em;
height: auto;
color: #129D99;;
}
.input_icon{
width: 14px;
margin-right: .5em;
}
.action-list-text{
font-size: 0.9em;
}
}
.action-list-label{
color: #212121;
font-size: small;
opacity: 0.6;
}
.list-unstyled{
margin-bottom: 0.2rem;
}
}

View File

@ -0,0 +1,307 @@
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
import { ChangeDetectorRef, Inject, OnDestroy } from '@angular/core';
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms';
import { FieldEditorModel } from '@app/ui/admin/dataset-profile/admin/field-editor-model';
import { FieldSetEditorModel } from '@app/ui/admin/dataset-profile/admin/field-set-editor-model';
import { SectionEditorModel } from '@app/ui/admin/dataset-profile/admin/section-editor-model';
import { BaseComponent } from '@common/base/base.component';
import { Guid } from '@common/types/guid';
import { DragulaService } from 'ng2-dragula';
import { Subscription } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ToCEntry, ToCEntryType } from '../../../table-of-contents/table-of-contents-entry';
@Component({
selector: 'app-dataset-profile-editor-section-fieldset-component',
templateUrl: './dataset-profile-editor-section-fieldset.component.html',
styleUrls: ['./dataset-profile-editor-section-fieldset.component.scss']
})
export class DatasetProfileEditorSectionFieldSetComponent implements OnInit, OnChanges, OnDestroy {
// @Input() form: FormGroup;
//@Input() dataModel: SectionEditorModel;
// @Input() indexPath: string;
@Input() viewOnly: boolean;
// @Input() numbering: string;
@Input() tocentry: ToCEntry;
@Output() selectedEntryId = new EventEmitter<string>();
@Output() dataNeedsRefresh = new EventEmitter<void> ();
@Output() removeFieldSet = new EventEmitter<string>();
@Output() addNewFieldSet = new EventEmitter<FormGroup>();
@Output() cloneFieldSet = new EventEmitter<FormGroup>();
// FIELDSET_PREFIX_ID="FIELDSET_PREFIX_ID";
// @Output() fieldsetAdded = new EventEmitter<String>(); //returns the id of the fieldset added
idprefix = "id";
private subs = new Subscription();
private FIELDSETS = 'FIELDSETS';
constructor(
private dragulaService: DragulaService,
private myElement: ElementRef
)
{
if(this.dragulaService.find(this.FIELDSETS)){
this.dragulaService.destroy(this.FIELDSETS);
}
this.dragulaService.createGroup(this.FIELDSETS,{
moves:(el, container, handle)=>{
// if(this.viewOnly) return false; //uncomment if want to unable drag n drop in viewonly mode
if(el.id != (this.idprefix+this.tocentry.id)) return false;
if(handle.className && handle.classList.contains('handle')) return true;
return false;
}
});
this.subs.add(this.dragulaService.drop(this.FIELDSETS).subscribe(obs=>{
(this.form.get('fieldSets') as FormArray).controls.forEach((e,i)=>{
e.get('ordinal').setValue(i);
});
// obs.
this.dataNeedsRefresh.emit();
return ;
}));
}
ngOnDestroy(){
// console.log('elemement destroyed -->');
this.subs.unsubscribe();
}
ngOnChanges(changes: SimpleChanges): void {
// console.log('---------element updated-------');
// console.log('numbering before:', this.numbering);
this.initialize();
// console.log('----post update----');
// console.log('numbering now', this.numbering, ' changes detected:', changes);
}
form;
numbering;
private _selectedFieldSetId: string = null;
get selectedFieldSetId(){
return this._selectedFieldSetId;
}
set selectedFieldSetId(id: string){
if(id === this._selectedFieldSetId) return;
this._selectedFieldSetId = id;
this.selectedEntryId.emit(this._selectedFieldSetId);
}
private _findParentSection():FormGroup{
const parent = this.form.parent;
return parent;
}
private initialize(){
if(this.tocentry.type === ToCEntryType.Section){
this.form = this.tocentry.form;
this.numbering = this.tocentry.numbering;
this._selectedFieldSetId = null;
// this._scrollToElement(this.tocentry.id);
this._scrollOnTop();
}else if(this.tocentry.type === ToCEntryType.FieldSet){
this.form = this.tocentry.form.parent.parent;
const numberingArray = this.tocentry.numbering.split('.');
if(numberingArray.length){
numberingArray.splice(numberingArray.length-1);
this.numbering = numberingArray.join('.');
}else{
// console.warn('!not found numbering');
}
this.selectedFieldSetId = this.tocentry.id;
this._scrollToElement(this.selectedFieldSetId);
}else{//scroll on top
this._scrollOnTop();
}
}
private _scrollToElement(id: string){
let el = this.myElement.nativeElement.querySelector("#"+this.idprefix+id);
// let el = this.myElement.nativeElement.getElementbyId (this.selectedFieldSetId);
if(el){
/*
Give time to template to build itself (extending and collapsing).
In case we are dragging from one container to another, then the ui takes around 600ms to build
individual previews (dataset-profile-editor-field.component.ts);
*/
setTimeout(() => {
const el = this.myElement.nativeElement.querySelector("#"+this.idprefix+id);
if(el){
el.scrollIntoView({behavior: "smooth"});
}
}, 700);
}
}
private _scrollOnTop(){
setTimeout(() => {
const el = this.myElement.nativeElement.querySelector('#topofcontainer');
if(el){
el.scrollIntoView({behavior:'smooth'})
}
},200);
}
ngOnInit() {
// console.log('<-- element created');
// this.initialize();
//TODO
// this.form.root.get('pages').valueChanges
// .pipe(takeUntil(this._destroyed))
// .subscribe(x =>
// this.keepPageSelectionValid(x)
// );
}
drop(event: CdkDragDrop<string[]>) {
// if(!this.links || !this.links.length) return;
if(event.container === event.previousContainer){
// moveItemInArray(this.links, event.previousIndex, event.currentIndex);
let arrayToUpdate: FormArray = this.form.get('fieldSets') 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();
}else{
console.log('not same container');
}
}
onRemoveFieldSet(fieldsetId: string){
this.removeFieldSet.emit(fieldsetId);
}
onCloneFieldSet(fieldset: FormGroup){
this.cloneFieldSet.emit(fieldset);
}
onAddFieldSet(){
this.addNewFieldSet.emit(this.form);
}
// addField() {
// const fieldSet: FieldSetEditorModel = new FieldSetEditorModel();
// fieldSet.ordinal = (this.form.get('fieldSets') as FormArray).length;
// const field: FieldEditorModel = new FieldEditorModel();
// field.id = Guid.create().toString();
// field.ordinal = 0;//first field in fields
// fieldSet.fields.push(field);
// // if (this.dataModel.fieldSets) {
// fieldSet.id = Guid.create().toString();
// //this.dataModel.fieldSets.push(fieldSet);
// //}
// const fieldsetsArray = this.form.get('fieldSets') as FormArray;
// fieldsetsArray.push(fieldSet.buildForm());
// const fieldSetForm = fieldsetsArray.at(fieldsetsArray.length-1);
// //emit id inserted
// if(fieldSetForm){
// const id: string = fieldSetForm.get('id').value;
// this.fieldsetAdded.emit(id);
// }
// }
// addSectioninSection() {
// const section: SectionEditorModel = new SectionEditorModel();
// //this.dataModel.sections.push(section);
// (<FormArray>this.form.get('sections')).push(section.buildForm());
// }
// DeleteSectionInSection(index) {
// //this.dataModel.sections.splice(index, 1);
// (<FormArray>this.form.get('sections')).removeAt(index);
// }
// deleteFieldSet(index) {
// //this.dataModel.fieldSets.splice(index, 1);
// (<FormArray>this.form.get('fieldSets')).removeAt(index);
// }
// keepPageSelectionValid(pagesJson: Array<any>) {
// const selectedPage = this.form.get('page').value as String;
// // const pages: Array<PageEditorModel> = JsonSerializer.fromJSONArray(pagesJson, Page);
// if (pagesJson.find(elem => elem.id === selectedPage) === undefined) {
// this.form.get('page').reset();
// }
// }
// getFieldTile(formGroup: FormGroup, index: number) {
// if (formGroup.get('title') && formGroup.get('title').value && formGroup.get('title').value.length > 0) { return formGroup.get('title').value; }
// return "Field " + (index + 1);
// }
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;
}
}

View File

@ -1,31 +1,42 @@
<div [formGroup]="form" class="row dataset-profile-editor"> <div [formGroup]="form" class="row dataset-profile-editor">
<h4 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.TITLE' | translate}}</h4> <!-- <h4 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.TITLE' | translate}}</h4> -->
<!-- <div class="heading col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.TITLE' | translate}}</div> -->
<mat-form-field class="col-md-3"> <!-- <mat-form-field class="col-md-3">
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.ID' | translate}}" <input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.ID' | translate}}"
formControlName="id" required> formControlName="id" required>
<mat-error *ngIf="form.get('id').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="form.get('id').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
<mat-error *ngIf="form.get('id').hasError('pattern')">{{'GENERAL.VALIDATION.PATTERN-_' | translate}}</mat-error> <mat-error *ngIf="form.get('id').hasError('pattern')">{{'GENERAL.VALIDATION.PATTERN-_' | translate}}</mat-error>
</mat-form-field> </mat-form-field> -->
<mat-form-field class="col-md-3">
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.TITLE' | translate}}" <div class="heading col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-NAME' | translate}} *</div>
<div class="hint col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-NAME-HINT' | translate}}</div>
<mat-form-field class="col-12">
<input matInput type="text" [placeholder]="('DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate)+ ' '+ ('DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION' | translate)"
formControlName="title"> formControlName="title">
<mat-error >{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field>
<mat-form-field class="col-md-3"> <!-- <mat-form-field class="col-md-3">
<mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.PAGE' | translate}}" formControlName="page" <mat-select placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.PAGE' | translate}}" formControlName="page"
required> required>
<mat-option *ngFor="let pageGroup of form.root.get('pages')['controls'];" [value]="pageGroup.get('id').value">{{pageGroup.get('title').value}}</mat-option> <mat-option *ngFor="let pageGroup of form.root.get('pages')['controls'];" [value]="pageGroup.get('id').value">{{pageGroup.get('title').value}}</mat-option>
</mat-select> </mat-select>
<mat-error *ngIf="form.get('page').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> <mat-error *ngIf="form.get('page').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field> </mat-form-field> -->
<mat-form-field class="col-md-3"> <!-- <mat-form-field class="col-md-3">
<input matInput type="number" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.ORDER' | translate}}" <input matInput type="number" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.ORDER' | translate}}"
formControlName="ordinal"> formControlName="ordinal">
</mat-form-field> </mat-form-field> -->
<mat-form-field class="col-md-12"> <div class="heading col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-DESCRIPTION' | translate}} </div>
<div class="hint col-12">{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION-DESCRIPTION-HINT' | translate}}</div>
<mat-form-field class="col-12">
<input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.DESCRIPTION' | translate}}" <input matInput type="text" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.DESCRIPTION' | translate}}"
formControlName="description"> formControlName="description">
<!-- <mat-error >{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error> -->
</mat-form-field> </mat-form-field>
<!-- <div class="col-md-6"> <!-- <div class="col-md-6">
<label>Default Visibility</label> <label>Default Visibility</label>
<mat-radio-group formControlName="defaultVisibility" class="full-width"> <mat-radio-group formControlName="defaultVisibility" class="full-width">
@ -33,7 +44,8 @@
<mat-radio-button [value]="false">false</mat-radio-button> <mat-radio-button [value]="false">false</mat-radio-button>
</mat-radio-group> </mat-radio-group>
</div> --> </div> -->
<h4 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.FIELDS-TITLE' |
<!-- <h4 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.FIELDS-TITLE' |
translate}}</h4> translate}}</h4>
<div class="col-12"> <div class="col-12">
<mat-card class="field-card" *ngFor="let fieldControl of form.get('fieldSets')['controls'] let i=index;"> <mat-card class="field-card" *ngFor="let fieldControl of form.get('fieldSets')['controls'] let i=index;">
@ -46,28 +58,40 @@
</div> </div>
</mat-card> </mat-card>
</div> </div>
-->
<!-- Able to add fieldsets if only the sections has no subsections -->
<!-- <ng-container *ngIf="form.get('sections').controls?.length == 0">
<div class="col-12"><button mat-button class="full-width" (click)="addField()" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.ACTIONS.ADD-FIELD' <div class="col-12"><button mat-button class="full-width" (click)="addField()" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.ACTIONS.ADD-FIELD'
| translate}}</button></div> | translate}}</button>
<h4 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.SUB-SECTIONS-TITLE' | </div>
</ng-container> -->
<!-- SUBSECTIONS -->
<!-- <h4 style="font-weight: bold" class="col-12">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.FIELDS.SUB-SECTIONS-TITLE' |
translate}}</h4> translate}}</h4>
<div *ngIf="dataModel.sections.length > 0" class="col-12"> <div *ngIf="form.get('sections')['controls'].length > 0" class="col-12">
<mat-expansion-panel *ngFor="let section of dataModel.sections; let i=index;" #panel> <mat-expansion-panel *ngFor="let sectionFormGroup of form.get('sections')['controls']; let i=index;" #panel>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title>{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}}</mat-panel-title> <mat-panel-title>{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}}</mat-panel-title>
<div class="row deleteBtn"> <div class="row deleteBtn"> -->
<!-- <span class="col">{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}}</span> --> <!-- <span class="col">{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}}</span> -->
<button mat-icon-button type="button" class="deleteBtn col-auto" (click)="DeleteSectionInSection(i);" [disabled]="viewOnly"> <!-- <button mat-icon-button type="button" class="deleteBtn col-auto" (click)="DeleteSectionInSection(i);" [disabled]="viewOnly">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
</button> </button>
</div> </div>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<div id="{{indexPath + 's' + i}}" *ngIf="panel.expanded" class="row"> <div id="{{indexPath + 's' + i}}" *ngIf="panel.expanded" class="row">
<app-dataset-profile-editor-section-component class="col-12" [form]="form.get('sections').get(''+i)" [dataModel]="section" <app-dataset-profile-editor-section-component class="col-12" [form]="form.get('sections').get(''+i)"
[indexPath]="indexPath + 's' + i" [viewOnly]="viewOnly"></app-dataset-profile-editor-section-component> [indexPath]="indexPath + 's' + i" [viewOnly]="viewOnly"></app-dataset-profile-editor-section-component>
</div> </div>
</mat-expansion-panel> </mat-expansion-panel>
</div> </div>
<div class="col-12"><button mat-button class="full-width" (click)="addSectioninSection()" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.ACTIONS.ADD-SUB-SECTION' <div class="col-12"><button mat-button class="full-width" (click)="addSectioninSection()" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.STEPS.FORM.SECTION.ACTIONS.ADD-SUB-SECTION'
| translate}}</button></div> | translate}}</button></div> -->
</div> </div>

View File

@ -1,4 +1,6 @@
.dataset-profile-editor { .dataset-profile-editor {
.field-card { .field-card {
margin-bottom: 1em; margin-bottom: 1em;
} }
@ -6,3 +8,24 @@
.deleteBtn{ .deleteBtn{
margin-right:2em; margin-right:2em;
} }
.heading {
text-align: left;
font-weight: 700;
font-size: 18px;
letter-spacing: 0px;
color: #212121;
opacity: 0.81;
// margin-top: 1.625rem;
margin-bottom: 0.625rem;
}
.hint {
text-align: left;
font-weight: 400;
font-size: 16px;
letter-spacing: 0px;
color: #212121;
opacity: 0.81;
margin-bottom: 0.125rem;
}

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'; import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { FormArray, FormGroup } from '@angular/forms'; import { FormArray, FormGroup } from '@angular/forms';
import { FieldEditorModel } from '@app/ui/admin/dataset-profile/admin/field-editor-model'; import { FieldEditorModel } from '@app/ui/admin/dataset-profile/admin/field-editor-model';
import { FieldSetEditorModel } from '@app/ui/admin/dataset-profile/admin/field-set-editor-model'; import { FieldSetEditorModel } from '@app/ui/admin/dataset-profile/admin/field-set-editor-model';
@ -15,45 +15,59 @@ import { takeUntil } from 'rxjs/operators';
export class DatasetProfileEditorSectionComponent extends BaseComponent implements OnInit { export class DatasetProfileEditorSectionComponent extends BaseComponent implements OnInit {
@Input() form: FormGroup; @Input() form: FormGroup;
@Input() dataModel: SectionEditorModel; //@Input() dataModel: SectionEditorModel;
@Input() indexPath: string; @Input() indexPath: string;
@Input() viewOnly: boolean; @Input() viewOnly: boolean;
@Output() fieldsetAdded = new EventEmitter<String>(); //returns the id of the fieldset added
constructor() { super(); } constructor() { super(); }
ngOnInit() { ngOnInit() {
this.form.root.get('pages').valueChanges
.pipe(takeUntil(this._destroyed)) //TODO
.subscribe(x => // this.form.root.get('pages').valueChanges
this.keepPageSelectionValid(x) // .pipe(takeUntil(this._destroyed))
); // .subscribe(x =>
// this.keepPageSelectionValid(x)
// );
} }
addField() { addField() {
const fieldSet: FieldSetEditorModel = new FieldSetEditorModel(); const fieldSet: FieldSetEditorModel = new FieldSetEditorModel();
fieldSet.ordinal = (this.form.get('fieldSets') as FormArray).length;
const field: FieldEditorModel = new FieldEditorModel(); const field: FieldEditorModel = new FieldEditorModel();
field.id = Guid.create().toString(); field.id = Guid.create().toString();
field.ordinal = 0;//first field in fields
fieldSet.fields.push(field); fieldSet.fields.push(field);
if (this.dataModel.fieldSets) { // if (this.dataModel.fieldSets) {
fieldSet.id = Guid.create().toString(); fieldSet.id = Guid.create().toString();
this.dataModel.fieldSets.push(fieldSet); //this.dataModel.fieldSets.push(fieldSet);
//}
const fieldsetsArray = this.form.get('fieldSets') as FormArray;
fieldsetsArray.push(fieldSet.buildForm());
const fieldSetForm = fieldsetsArray.at(fieldsetsArray.length-1);
//emit id inserted
if(fieldSetForm){
const id: string = fieldSetForm.get('id').value;
this.fieldsetAdded.emit(id);
} }
(<FormArray>this.form.get('fieldSets')).push(fieldSet.buildForm());
} }
addSectioninSection() { addSectioninSection() {
const section: SectionEditorModel = new SectionEditorModel(); const section: SectionEditorModel = new SectionEditorModel();
this.dataModel.sections.push(section); //this.dataModel.sections.push(section);
(<FormArray>this.form.get('sections')).push(section.buildForm()); (<FormArray>this.form.get('sections')).push(section.buildForm());
} }
DeleteSectionInSection(index) { DeleteSectionInSection(index) {
this.dataModel.sections.splice(index, 1); //this.dataModel.sections.splice(index, 1);
(<FormArray>this.form.get('sections')).removeAt(index); (<FormArray>this.form.get('sections')).removeAt(index);
} }
deleteFieldSet(index) { deleteFieldSet(index) {
this.dataModel.fieldSets.splice(index, 1); //this.dataModel.fieldSets.splice(index, 1);
(<FormArray>this.form.get('fieldSets')).removeAt(index); (<FormArray>this.form.get('fieldSets')).removeAt(index);
} }

View File

@ -0,0 +1,67 @@
import { Inject, Injectable } from "@angular/core";
import { AbstractControl, FormArray, ValidationErrors, ValidatorFn } from "@angular/forms";
export class EditorCustomValidators{
static atLeastOneElementListValidator(arrayToCheck): ValidatorFn{
return (control: AbstractControl): ValidationErrors | null=>{
const fa = control.get(arrayToCheck) as FormArray;
if(!fa || fa.length === 0){
return {[EditorCustomValidatorsEnum.emptyArray]: true};
}
return null;
}
}
static pagesHaveAtLeastOneSection(pagesArrayName:string,sectionsArrayName:string ): ValidatorFn{
return (control: AbstractControl): ValidationErrors | null=>{
const pages = control.get(pagesArrayName) as FormArray;
const sections = control.get(sectionsArrayName) as FormArray;
const pageIdsArray = pages.controls.map(page=>page.get('id').value);
const sectionsPageIds = sections.controls.map(section=> section.get('page').value);
let invalidMessage = null;
pageIdsArray.forEach(pageId=>{
if(!sectionsPageIds.includes(pageId)){
invalidMessage = {[EditorCustomValidatorsEnum.atLeastOneSectionInPage]:true};
}
})
return invalidMessage;
}
}
static sectionHasAtLeastOneChildOf(fieldsetsArrayName, sectionsArrayName): ValidatorFn{
return (control: AbstractControl): ValidationErrors | null=>{
const fieldsets = control.get(fieldsetsArrayName) as FormArray;
const sections = control.get(sectionsArrayName) as FormArray;
if((fieldsets && fieldsets.length) || (sections && sections.length)){
return null;
}
return {[EditorCustomValidatorsEnum.sectionMustHaveOneChild] : true};
}
}
}
export enum EditorCustomValidatorsEnum{
sectionMustHaveOneChild = "sectionMustHaveOneChild",
atLeastOneSectionInPage = 'atLeastOneSectionInPage',
emptyArray="emptyArray"
}

View File

@ -3,6 +3,7 @@ import { DatasetProfile } from '../../../../core/model/admin/dataset-profile/dat
import { BaseFormModel } from '../../../../core/model/base-form-model'; import { BaseFormModel } from '../../../../core/model/base-form-model';
import { PageEditorModel } from '../admin/page-editor-model'; import { PageEditorModel } from '../admin/page-editor-model';
import { SectionEditorModel } from '../admin/section-editor-model'; import { SectionEditorModel } from '../admin/section-editor-model';
import { EditorCustomValidators } from './custom-validators/editor-custom-validators';
export class DatasetProfileEditorModel extends BaseFormModel { export class DatasetProfileEditorModel extends BaseFormModel {
@ -48,6 +49,10 @@ export class DatasetProfileEditorModel extends BaseFormModel {
pagesFormArray.push(form); pagesFormArray.push(form);
}); });
formGroup.addControl('pages', this.formBuilder.array(pagesFormArray)); formGroup.addControl('pages', this.formBuilder.array(pagesFormArray));
formGroup.setValidators([EditorCustomValidators.atLeastOneElementListValidator('pages'), EditorCustomValidators.pagesHaveAtLeastOneSection('pages','sections')]);
formGroup.updateValueAndValidity();
return formGroup; return formGroup;
} }
} }

View File

@ -1,5 +1,17 @@
<div class="main-content"> <!-- View Only : {{viewOnly}} -->
<div class="main-content">
<div class="container-fluid dataset-profile-editor" *ngIf="form" [formGroup]='form'> <div class="container-fluid dataset-profile-editor" *ngIf="form" [formGroup]='form'>
<!-- Total steps: {{stepper.steps.length}} -->
<div class="row" style="padding: 2em; margin-bottom: 1em; background: #F5F5F5 0% 0% no-repeat padding-box;" >
<div class="col-12" style="margin-bottom: 2em;">
<h3 *ngIf="isNew && !isClone && !isNewVersion">{{'DATASET-PROFILE-EDITOR.TITLE.NEW-PROFILE' | translate}}</h3> <h3 *ngIf="isNew && !isClone && !isNewVersion">{{'DATASET-PROFILE-EDITOR.TITLE.NEW-PROFILE' | translate}}</h3>
<h3 *ngIf="isNew && isClone"> <h3 *ngIf="isNew && isClone">
<span *ngIf="isClone">{{'DATASET-PROFILE-EDITOR.TITLE.NEW-PROFILE-CLONE' | translate}}</span> <span *ngIf="isClone">{{'DATASET-PROFILE-EDITOR.TITLE.NEW-PROFILE-CLONE' | translate}}</span>
@ -11,86 +23,428 @@
</h3> </h3>
<h3 *ngIf="!isNew">{{form.get('label').value}}</h3> <h3 *ngIf="!isNew">{{form.get('label').value}}</h3>
<mat-form-field class="full-width">
<input matInput formControlName="label" placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-TITLE' | translate}}" required> <div class="d-flex justify-content-end pb-3" *ngIf="form.get('status').value==1">
<mat-error *ngIf="form.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}} <button mat-raised-button color="primary" (click)="downloadXML();" type="button">{{
'DATASET-WIZARD.ACTIONS.DOWNLOAD-XML' | translate }}</button>
</div>
</div>
<!-- Steps Navigation -->
<div class="col-12 d-flex" *ngIf="steps">
<div class="col-7 bg-white" style="overflow: hidden; padding: 0px" id="progress-container">
<div id="progress" [ngStyle]="progressStyle"></div>
<div class="row h-100">
<div class="col text-center align-self-center" *ngFor="let step of steps; index as idx">
<span (click)="stepper.selectedIndex=idx"
class="stepper-title-label"
[ngClass]="{'stepper-title-label-locked': !isStepUnlocked(idx),'stepper-title-label-completed':idx < stepper.selectedIndex} ">
<ng-container *ngIf="(step.completed &&(idx!=steps.length-1)) else numberLabel">
<mat-icon style="font-size:0.7em; height: 0px;">done</mat-icon>
</ng-container>
<ng-template #numberLabel>
{{idx+1}}
</ng-template>
{{step.label}}
</span>
</div>
</div>
</div>
<div class="col d-flex justify-content-end">
<button [@previous_btn] mat-button class="navigate-btn" (click)="stepper.previous()" *ngIf="stepper.selectedIndex !=0">
<!-- <mat-icon>navigate_before</mat-icon> -->
{{'DMP-EDITOR.STEPPER.PREVIOUS' | translate}}
</button>
<button mat-button class="navigate-btn ml-3"
[@next_btn]
(click)="validateStep(stepper.selectedIndex);stepper.next();"
*ngIf="stepper.selectedIndex != (steps.length-1)"
[ngClass]="{'navigate-btn-disabled': !isStepCompleted(stepper.selectedIndex)}">
<mat-icon style="font-size: 1.66em;">navigate_next</mat-icon>{{'DMP-EDITOR.STEPPER.NEXT' | translate}}
</button>
<ng-container *ngIf="steps.length-1 === stepper.selectedIndex">
<!-- <ng-container *ngIf="stepper.selectedIndex === (steps.length-1)"> -->
<ng-container *ngIf="!viewOnly">
<!-- <button mat-button class="navigate-btn ml-2"
(click)='onSubmit()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.SAVE' |
translate}}</button> -->
<!-- <button mat-button class="finalize-btn ml-2"
(click)='finalize()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.FINALIZE' |
translate}}</button> -->
</ng-container>
<!-- //TODO -->
<ng-container *ngIf="true">
<!-- <button mat-button class="navigate-btn ml-2"
(click)='onSubmit()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.SAVE' |
translate}}</button> -->
<!-- <button mat-button class="finalize-btn ml-2"
(click)='finalize()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.FINALIZE' |
translate}}</button> -->
<button [@finalize_btn] mat-button class="finalize-btn ml-3"
[disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.FINALIZE' |
translate}}</button>
</ng-container>
<!-- SAVE BUTTON WHEN FINALIZED-->
<ng-container *ngIf="false">
<ng-container *ngIf="showUpdateButton()">
<!-- <button mat-button class="navigate-btn ml-2"
(click)='checkFormValidation()'
[disabled]="form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.VALIDATE' | translate}}</button> -->
<button mat-button class="navigate-btn ml-2"
(click)='updateFinalized()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.UPDATE' |
translate}}</button>
</ng-container>
</ng-container>
</ng-container>
</div>
</div>
</div>
<mat-horizontal-stepper [linear]="true" #stepper class="stepper" (selectionChange)="onMatStepperSelectionChange($event)" style="padding-left: 8px; padding-right: 15px;">
<!-- IMPORTANT TO BE !INVALID (WHEN THE TEMPLATE IS FINALIZED THE CONTORLS ARE DISABLED) -->
<mat-step [label]="'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate" [completed]="(!form.get('label').invalid && !form.get('description').invalid && !form.get('language').invalid)" >
<!-- <ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TITLE' | translate}}
</ng-template> -->
<div class="row">
<div class="col-12">
<div class="heading">1.1 {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-NAME'| translate}} *</div>
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-NAME-HINT'| translate}}</div>
<mat-form-field class="full-width basic-info-input">
<input matInput [formControl]="form.get('label')"
placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-TITLE' | translate}}">
<mat-error *ngIf="form.get('label').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' |
translate}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</div>
<mat-form-field class="full-width"> <div class="col-12">
<input matInput formControlName="description" placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-DESCRIPTION' | translate}}" required> <div class="heading">1.2 {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-DESCRIPTION'| translate}} *</div>
<mat-error *ngIf="form.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}} <!-- <div class="hint">{{'DMP-EDITOR.MAIN-INFO.HINT' | translate}}</div> -->
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-DESCRIPTION-HINT'| translate}}</div>
<mat-form-field class="full-width basic-info-input">
<textarea matInput [formControl]="form.get('description')" cdkTextareaAutosize cdkAutosizeMinRows="4" cdkAutosizeMaxRows="5"
placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-DESCRIPTION-PLACEHOLDER'| translate}}">
</textarea>
<mat-error *ngIf="form.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED'
| translate}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</div>
<mat-form-field class="full-width"> <div class="col-12">
<!-- <div class="heading">1.3 {{'DMP-EDITOR.FIELDS.LANGUAGE' | translate}}</div> -->
<div class="heading">1.3 {{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-LANGUAGE'| translate}} *</div>
<mat-form-field class="full-width basic-info-input">
<!-- <input matInput formControlName="description" placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-DESCRIPTION' | translate}}" required> --> <!-- <input matInput formControlName="description" placeholder="{{'DATASET-PROFILE-EDITOR.FIELDS.DATASET-DESCRIPTION' | translate}}" required> -->
<mat-select formControlName="language"> <mat-select [formControl]="form.get('language')" placeholder="{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.DATASET-TEMPLATE-SELECT-LANGUAGE'| translate}}">
<mat-option *ngFor="let lang of getLanguageInfos()" [value]="lang.code"> <mat-option *ngFor="let lang of getLanguageInfos()" [value]="lang.code">
{{ lang.name }} {{ lang.name }}
</mat-option> </mat-option>
</mat-select> </mat-select>
<mat-error *ngIf="form.get('language').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}} <mat-error *ngIf="form.get('language').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' |
translate}}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
</div>
<div class="d-flex justify-content-end pb-3" *ngIf="form.get('status').value==1"> <!-- <div class="col-12">
<button mat-raised-button color="primary" (click)="downloadXML();" type="button">{{ 'DATASET-WIZARD.ACTIONS.DOWNLOAD-XML' | translate }}</button> <button mat-button class="full-width" (click)="addPage()"
</div> [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.ACTIONS.NEXT' | translate}}</button>
<mat-horizontal-stepper [linear]="true" #stepper> </div> -->
<mat-step>
<ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.PAGES.TITLE' | translate}}</ng-template>
<div class="row">
<app-dataset-profile-editor-page-component class="col-12" [form]="form.get('pages')" [viewOnly]="viewOnly"></app-dataset-profile-editor-page-component>
<div class="col-12">
<button mat-button class="full-width" (click)="addPage()" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.ACTIONS.ADD-PAGE' | translate}}</button>
</div>
</div> </div>
</mat-step> </mat-step>
<mat-step> <!-- <mat-step>
<ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate}}</ng-template> <ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.PAGES.TITLE' | translate}}</ng-template>
<div class="row"> <div class="row">
<app-dataset-profile-editor-page-component class="col-12" [form]="form.get('pages')"
[viewOnly]="viewOnly"></app-dataset-profile-editor-page-component>
<div class="col-12">
<button mat-button class="full-width" (click)="addPage()"
[disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.ACTIONS.ADD-PAGE' | translate}}</button>
</div>
</div>
</mat-step> -->
<mat-step [label]="'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate" [completed]="form.valid">
<!-- <ng-template matStepLabel>{{'DATASET-PROFILE-EDITOR.STEPS.FORM.TITLE' | translate}}</ng-template> -->
<div class="row">
<!-- TABLE -->
<div class="col-3">
<div class="row sticky-top" style="top : 2em;">
<dataset-profile-table-of-contents class="toc-pane-container col"
[links]="toCEntries"
(itemClick)="displayItem($event)"
(createEntry) = "addNewEntry($event)"
(removeEntry)="onRemoveEntry($event)"
[itemSelected]="selectedTocEntry"
[viewOnly]="viewOnly"
(dataNeedsRefresh)="onDataNeedsRefresh($event)"
[colorizeInvalid]="colorizeInvalid">
</dataset-profile-table-of-contents>
</div>
</div>
<!-- DISPLAYER -->
<div class="col ml-3">
<div class="row">
<div class="col">
<div class="row" *ngIf="selectedTocEntry">
<!-- PAGE INFO -->
<div class="col-12 content-displayer" *ngIf="selectedTocEntry.type === tocEntryEnumValues.Page">
<form [formGroup]="selectedTocEntry.form" class="page-infos">
<div class="row">
<!-- PAGE NAME -->
<div class="col-12">
<div class="heading">{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.PAGE-NAME' | translate}} *</div>
<div class="hint">{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.PAGE-NAME-HINT' | translate}}</div>
<mat-form-field>
<input type="text" matInput formControlName="title" [placeholder]="('DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate) +' '+ ('DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.PAGE' |translate)">
<mat-error >{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-12" *ngIf="!viewOnly && (!selectedTocEntry?.subEntries?.length)">
<button class="create-section-btn" (click)="addNewEntry({parent:selectedTocEntry, childType: tocEntryEnumValues.Section})">Create section</button>
</div>
<!-- PAGE ID -->
<!-- <div class="col">
<div class="heading">Page id *</div>
<mat-form-field>
<input type="text" matInput formControlName="id">
</mat-form-field>
</div> -->
</div>
<!-- <div class="row">
<div class="col">
<div class="heading">Ordinal *</div>
<mat-form-field>
<input type="text" matInput formControlName="ordinal">
</mat-form-field>
</div>
</div> -->
</form>
</div>
<div class="col-12" *ngIf="(selectedTocEntry.type === tocEntryEnumValues.Section) || (selectedTocEntry.type === tocEntryEnumValues.FieldSet)" >
<app-dataset-profile-editor-section-fieldset-component
[tocentry]="selectedTocEntry"
[viewOnly]="viewOnly"
(addNewFieldSet)="addNewEntry({childType: tocEntryEnumValues.FieldSet,parent: {form: $event}})"
(removeFieldSet)="onRemoveEntry(_findTocEntryById($event, toCEntries))"
(cloneFieldSet)="cloneFieldSet($event)"
(selectedEntryId)="displayItem(_findTocEntryById($event, getTocEntries()))"
(dataNeedsRefresh)="onDataNeedsRefresh()"
>
</app-dataset-profile-editor-section-fieldset-component>
</div>
</div>
<div class="content-displayer row justify-content-center" *ngIf="!numOfPages" style="min-height: 30em;">
<div class="col-auto align-self-center">
<div class="row w-100 justify-content-center">
<div class="col-auto">
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.ACTIONS.NOTHING-HERE-HINT'| translate}}
</div>
</div>
<div class="row justify-content-center">
<div class="col-auto d-flex aling-contents-center">
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.ACTIONS.START-CREATING-PAGE-START'| translate}}
<mat-icon color="accent" style="font-size: 1.5em; text-align: center; width: 1.5em;">add</mat-icon>
<strong style="cursor: pointer;" (click)="addNewEntry({childType: tocEntryEnumValues.Page,parent: null})">
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.ACTIONS.START-CREATING-PAGE-END'| translate}}
</strong>
</div>
</div>
</div>
</div>
</div>
<!-- TOOLBAR -->
<!-- <div class="col-auto"
*ngIf="((selectedTocEntry?.type == tocEntryEnumValues.Section)||(selectedTocEntry?.type == tocEntryEnumValues.FieldSet) )&&(selectedTocEntry?.subEntriesType != tocEntryEnumValues.Section) && !viewOnly">
<div class="row" class="actions-list bg-white sticky-top" style="top: 2em;">
<nav *ngIf="!viewOnly">
<label class="action-list-label">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.GENERAL-TOOLS' | translate}}</label>
<ul class="list-unstyled">
<li *ngIf="selectedTocEntry.type === tocEntryEnumValues.FieldSet" class="mli">
<div class="action-list-item" (click)="addNewEntry({childType: tocEntryEnumValues.FieldSet,parent: {form: selectedTocEntry.form.parent.parent}})">
<img src="/assets/images/editor/icons/add_input_set.svg" class="input_icon" alt="Add Question icon">
<mat-icon class="action-list-icon">folder</mat-icon>
<span class="action-list-text" >{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.NEW-INPUT-SET' | translate}}</span>
</div>
</li>
<li *ngIf="selectedTocEntry.type === tocEntryEnumValues.Section" class="mli">
<div class="action-list-item" (click)="addNewEntry({childType: tocEntryEnumValues.FieldSet,parent: selectedTocEntry})">
<mat-icon class="action-list-icon">folder</mat-icon>
<img src="/assets/images/editor/icons/add_input_set.svg" class="input_icon" alt="Add Question icon">
<span class="action-list-text" >{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.NEW-INPUT-SET' | translate}}</span>
</div>
</li>
<li *ngIf="selectedTocEntry.type === tocEntryEnumValues.FieldSet" class="mli">
<div class="action-list-item" (click)="cloneFieldSet(selectedTocEntry.form)">
<mat-icon class="action-list-icon">file_copy</mat-icon>
<img src="/assets/images/editor/icons/clone.svg" class="input_icon" alt="Clone icon">
<span class="action-list-text">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.CLONE' | translate}}</span>
</div>
</li>
<li *ngIf="selectedTocEntry.type === tocEntryEnumValues.FieldSet" class="mli">
<div class="action-list-item" (click)="onRemoveEntry(selectedTocEntry)">
<mat-icon class="action-list-icon">delete</mat-icon>
<span class="action-list-text">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}}</span>
</div>
</li>
</ul>
</nav> -->
<!-- <ng-container *ngIf="!viewOnly">
<h3 matSubheader>{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.GENERAL-TOOLS' | translate}}</h3>
<mat-list-item *ngIf="selectedTocEntry.type === tocEntryEnumValues.FieldSet" class="mli">
<div class="action-list-item">
<mat-icon class="action-list-icon">folder</mat-icon>
<span class="action-list-text" (click)="addNewEntry({childType: tocEntryEnumValues.FieldSet,parent: {form: selectedTocEntry.form.parent.parent}})" >{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.NEW-INPUT-SET' | translate}}</span>
</div>
</mat-list-item>
<mat-list-item *ngIf="selectedTocEntry.type === tocEntryEnumValues.Section" class="mli">
<div class="action-list-item">
<mat-icon class="action-list-icon">folder</mat-icon>
<span class="action-list-text" (click)="addNewEntry({childType: tocEntryEnumValues.FieldSet,parent: selectedTocEntry})" >{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.NEW-INPUT-SET' | translate}}</span>
</div>
</mat-list-item>
<mat-list-item *ngIf="selectedTocEntry.type === tocEntryEnumValues.FieldSet" class="mli">
<div class="action-list-item">
<mat-icon class="action-list-icon">file_copy</mat-icon>
<span class="action-list-text" (click)="cloneFieldSet(selectedTocEntry.form)">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.CLONE' | translate}}</span>
</div>
</mat-list-item>
<mat-list-item *ngIf="selectedTocEntry.type === tocEntryEnumValues.FieldSet" class="mli">
<div class="action-list-item">
<mat-icon class="action-list-icon">delete</mat-icon>
<span class="action-list-text" (click)="onRemoveEntry(selectedTocEntry)">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}}</span>
</div>
</mat-list-item>
</ng-container> -->
<!-- </div>
</div> -->
</div>
<!--
<mat-accordion class="col-12" [multi]="true"> <mat-accordion class="col-12" [multi]="true">
<mat-expansion-panel *ngFor="let section of dataModel.sections; let i=index;" #panel> <mat-expansion-panel *ngFor="let section of dataModel.sections; let i=index;" #panel>
<mat-expansion-panel-header> <mat-expansion-panel-header>
<mat-panel-title>{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}} <mat-panel-title class="toc-page-header">{{i + 1}}. {{form.get('sections').get(''+i).get('title').value}}
</mat-panel-title> </mat-panel-title>
<button mat-icon-button type="button" class="deleteBtn" (click)="DeleteSection(i);" [disabled]="viewOnly"> <button mat-icon-button type="button" class="deleteBtn" (click)="DeleteSection(i);"
[disabled]="viewOnly">
<mat-icon>delete</mat-icon> <mat-icon>delete</mat-icon>
</button> </button>
</mat-expansion-panel-header> </mat-expansion-panel-header>
<div id="{{'s' + i}}" class="row" *ngIf="panel.expanded"> <div id="{{'s' + i}}" class="row" *ngIf="panel.expanded">
<app-dataset-profile-editor-section-component class="col-12" [form]="form.get('sections').get(''+i)" [dataModel]="section" [indexPath]="'s' + i" [viewOnly]="viewOnly"> <app-dataset-profile-editor-section-component class="col-12"
[form]="form.get('sections').get(''+i)" [dataModel]="section"
[indexPath]="'s' + i" [viewOnly]="viewOnly">
</app-dataset-profile-editor-section-component> </app-dataset-profile-editor-section-component>
</div> </div>
</mat-expansion-panel> </mat-expansion-panel>
</mat-accordion> </mat-accordion> -->
<div class="col-12">
<button mat-button (click)="addSection()" class="full-width" [disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.ACTIONS.ADD-SECTION' | translate}}</button>
</div> </div>
<!-- <div class="col-12">
<button mat-button (click)="addSection()" class="full-width"
[disabled]="viewOnly">{{'DATASET-PROFILE-EDITOR.ACTIONS.ADD-SECTION' | translate}}</button>
</div> -->
</div> </div>
</mat-step> </mat-step>
<!-- <mat-step> <mat-step [label]="'DATASET-PROFILE-EDITOR.ACTIONS.PREVIEW-AND-FINALIZE' | translate">
<ng-template matStepLabel>{{'DATASET-PROFILE.PREVIEW' | translate}}</ng-template> <!-- {{'DATASET-PROFILE-EDITOR.ACTIONS.PREVIEW-AND-FINALIZE' | translate}} -->
<div *ngIf='this.isStepActive(2)'> <!-- <button (click)="generatePreviewForm()">foo</button> -->
<app-dynamic-form *ngIf="dataWizardModel && previewerFormGroup" [form]="this.previewerFormGroup" [dataModel]="dataWizardModel"></app-dynamic-form> <ng-container *ngIf="formGroup">
</div>
</mat-step> --> <app-final-preview-component [formGroup]="formGroup" [visibilityRules]="visibilityRules">
</app-final-preview-component>
<!--
<app-dataset-description [form]="formGroup" [visibilityRules]="visibilityRules" *ngIf="formGroup">
</app-dataset-description> -->
</ng-container>
</mat-step>
</mat-horizontal-stepper> </mat-horizontal-stepper>
<ng-container *ngIf="true">
<div class="d-flex"> <div class="d-flex">
<!-- SAVE BUTTON --> <!-- SAVE BUTTON -->
<div class="col-6 d-flex" *ngIf="!viewOnly"> <div class="col-6 d-flex" *ngIf="!viewOnly">
<div class="row mt-4"> <div class="row mt-4">
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto" (click)='checkFormValidation()' [disabled]="form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.VALIDATE' | translate}}</button> <ng-container *ngIf="false">
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto" (click)='onSubmit()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.SAVE' | translate}}</button> <button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto"
<button mat-raised-button class="col-auto" color="primary" type="button col-auto" (click)='finalize()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.FINALIZE' | translate}}</button> (click)='checkFormValidation()'
[disabled]="form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.VALIDATE' | translate}}</button>
</ng-container>
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto"
(click)='onSubmit()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.SAVE' |
translate}}</button>
<button mat-raised-button class="col-auto" color="primary" type="button col-auto"
(click)='finalize()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.FINALIZE' |
translate}}</button>
</div> </div>
</div> </div>
<!-- SAVE BUTTON WHEN FINALIZED--> <!-- SAVE BUTTON WHEN FINALIZED-->
<div class="col-6 d-flex" *ngIf="showUpdateButton()"> <div class="col-6 d-flex" *ngIf="showUpdateButton()">
<div class="row mt-4"> <div class="row mt-4">
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto" (click)='checkFormValidation()' [disabled]="form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.VALIDATE' | translate}}</button> <ng-container *ngIf="false">
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto" (click)='updateFinalized()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.UPDATE' | translate}}</button> <button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto"
(click)='checkFormValidation()'
[disabled]="form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.VALIDATE' | translate}}</button>
</ng-container>
<button mat-raised-button class="col-auto mr-2" color="primary" type="button col-auto"
(click)='updateFinalized()' [disabled]="!form.valid">{{'DATASET-PROFILE-EDITOR.ACTIONS.UPDATE' |
translate}}</button>
</div> </div>
</div> </div>
<!-- DELETE BUTTON --> <!-- DELETE BUTTON -->
@ -102,5 +456,32 @@
</div> </div>
</div> </div>
</div> </div>
</ng-container>
<!-- <div class="row">
<button (click)="printForm()">
console form
</button>
</div> -->
<!-- <div *ngIf="form">{{form.value | json}}</div>
<br> -->
<!-- <br>
<div class="row">
{{form.controls?.sections.value |json}}
</div> -->
<!-- {{form.value | json}} -->
<!-- <div class="row">
<button (click)="printMyErrors()">
print errors
</button>
</div> -->
<!-- <div class="row">
<button (click)="foo()">foo</button>
</div> -->
</div> </div>
</div> </div>

View File

@ -9,3 +9,222 @@
.deleteBtn{ .deleteBtn{
margin-right:2em; margin-right:2em;
} }
// REFACTORED CSS
.stepper{
background-color: transparent;
min-height: 500px;
}
.content-displayer{
background-color: #fff;
border-radius: 7px;
box-shadow: 0px 1px 2px #bfbfbf;
padding: 0em;
// padding-top: 0em;
overflow: visible;
// min-height: 30em;
}
.heading {
text-align: left;
font-weight: 700;
font-size: 18px;
letter-spacing: 0px;
color: #212121;
opacity: 0.81;
// margin-top: 1.625rem;
margin-bottom: 0.625rem;
}
.hint {
text-align: left;
font-weight: 400;
font-size: 16px;
letter-spacing: 0px;
color: #212121;
opacity: 0.81;
margin-bottom: 0.125rem;
}
//TO CHECK
:host ::ng-deep .mat-horizontal-content-container {
overflow: visible;
// padding: 0px;
}
:host ::ng-deep .mat-form-field-outline{
background-color: #ffffff4f;
}
:host ::ng-deep .mat-horizontal-stepper-header-container {
display: none !important;
}
#progress{
position: absolute;
height: 100%;
width: 100%;
clip-path: polygon(0 0, 0 0, 0 0, 0 0);
transition-property: clip-path;
transition-duration: 600ms;
transition-timing-function: ease-out;
transition-delay: 50ms;
box-shadow: 0px 1px 2px #bfbfbf;
background-color: #F7DD72;
}
#progress-container{
box-shadow: 1px 1px 6px #00000029;;
// border-radius: .3em;
}
// .import-btn {
// background: #ffffff 0% 0% no-repeat padding-box;
// border-radius: 30px;
// // color: #129d99;
// // border: 1px solid #129d99;
// padding-left: 2em;
// padding-right: 2em;
// color: #000;
// border: 1px solid #000;
// }
.navigate-btn {
border-radius: 30px;
background-color: #f7dd72;
border: 1px solid transparent;
padding-left: 2em;
padding-right: 2em;
box-shadow: 0px 3px 6px #1E202029;
transition-property: background-color, color;
transition-duration: 200ms;
transition-delay: 50ms;
transition-timing-function: ease-in-out;
}
.navigate-btn-disabled{
background-color: #CBCBCB;
color: #FFF;
}
.create-section-btn {
border-radius: 30px;
background-color: #f7dd72;
border: 1px solid transparent;
padding-left: 1em;
padding-right: 1em;
box-shadow: 0px 3px 6px #1E202029;
line-height: 1.7em;
}
$blue-color : #129D99;
$blue-color-light: #5cf7f2;
.finalize-btn {
border-radius: 30px;
border: 1px solid #129D99;
background: transparent;
padding-left: 2em;
padding-right: 2em;
box-shadow: 0px 3px 6px #1E202029;
color: #129D99;
}
.stepper-title-label{
cursor: pointer;
transition-property: color, opacity;
transition-duration: 200ms;
transition-delay: 50ms;
transition-timing-function: ease-in-out;
color: #212121;
font-size: 0.9em;
}
.stepper-title-label-locked{
color: #DEDEDE;
}
.stepper-title-label-completed{
opacity: 0.5;
}
.page-infos{
padding: 2em;
}
.mat-subheader{
padding: 0px;
}
//for the acitons list toolbar
// .mat-list-item.mat-list-item-with-avatar{
// padding-left: 0em;
// }
.actions-list{
// border: 1px solid $blue-color;
box-shadow: 0px 3px 12px #129D9999;
border-radius: 4px;
// padding-top: 1rem;
padding: 1em 0.9em;
min-width: 166px;
.mat-list-item-content{
padding: 0px;
}
.action-list-item{
display: flex;
align-items: center;
cursor: pointer;
.action-list-icon{
font-size: 1.2em;
// padding-right: 1em;
width: 14px;
margin-right: 0.5em;
margin-left: -.09em;
height: auto;
color: #129D99;;
}
.input_icon{
width: 14px;
margin-right: .5em;
}
.action-list-text{
font-size: 0.9em;
}
}
.action-list-label{
color: #212121;
font-size: small;
opacity: 0.6;
}
.list-unstyled{
margin-bottom: 0.2rem;
}
}
// .mli{
// height: auto;
// }
:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-outline {
background: #fafafa !important;
}
:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
font-size: 1rem;
padding: 0.6em 0 1em 0 !important;
}
.basic-info-input{
margin-top: 2em;
margin-bottom: 2em;
}

View File

@ -1,23 +1,23 @@
<div class="dmp-criteria"> <div class="row align-items-end">
<mat-card class="mat-card"> <div class="col-auto">
<div class="row"> <div class="d-lg-inline-block pr-2 text-muted">
<mat-form-field class="col-md-6"> <span>{{'CRITERIA.USERS.SHOW' | translate}}:</span>
<input matInput placeholder=" {{'CRITERIA.DATASET-PROFILE.LIKE'| translate}}" name="datasetProfileLike" </div>
[(ngModel)]="criteria.like" (ngModelChange)="controlModified()">
</mat-form-field> <mat-form-field class="status-form-field">
<mat-form-field class="col-md-6">
<mat-select [(ngModel)]="criteria.status" (ngModelChange)="controlModified()" placeholder=" {{'CRITERIA.DATASET-PROFILE.STATUS' | translate}}"> <mat-select [(ngModel)]="criteria.status" (ngModelChange)="controlModified()" placeholder=" {{'CRITERIA.DATASET-PROFILE.STATUS' | translate}}">
<mat-option [value]="null">{{'DATASET-PROFILE-STATUS.NONE' | translate}}</mat-option> <mat-option [value]="null">{{'DATASET-PROFILE-STATUS.NONE' | translate}}</mat-option>
<mat-option [value]="0">{{'DATASET-PROFILE-STATUS.DRAFT' | translate}}</mat-option> <mat-option [value]="0">{{'DATASET-PROFILE-STATUS.DRAFT' | translate}}</mat-option>
<mat-option [value]="1">{{'DATASET-PROFILE-STATUS.FINALIZED' | translate}}</mat-option> <mat-option [value]="1">{{'DATASET-PROFILE-STATUS.FINALIZED' | translate}}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
<div class="col"></div>
<div class="col-auto"> </div>
<!-- imgFileInput.click() && --> <div class="col-auto ml-lg-auto">
<button mat-raised-button class="col-auto" color="primary" (click)="openDialog()" <mat-form-field class="search-form-field">
type="button">{{ 'DATASET-WIZARD.UPLOAD.UPLOAD-XML' | translate }}</button> <input matInput placeholder=" {{'CRITERIA.DATASET-PROFILE.LIKE'| translate}}" name="datasetProfileLike"
[(ngModel)]="criteria.like" (ngModelChange)="controlModified()">
<mat-icon matPrefix>search</mat-icon>
</mat-form-field>
</div> </div>
</div> </div>
</mat-card>
</div>

View File

@ -0,0 +1,17 @@
.mat-form-field{
display: inline-block !important;
}
:host ::ng-deep .status-form-field .mat-form-field-wrapper {
background-color: white !important;
padding-bottom: 0 !important;
}
:host ::ng-deep .search-form-field .mat-form-field-wrapper {
background-color: white !important;
padding-bottom: 0 !important;
}
:host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
padding: 0.3rem 0rem 0.6rem 0rem !important;
}

View File

@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria'; import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-profile-criteria';
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
import { DialodConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component'; import { DialogConfirmationUploadDatasetProfiles } from '@app/ui/admin/dataset-profile/listing/criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component';
import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component'; import { BaseCriteriaComponent } from '@app/ui/misc/criteria/base-criteria.component';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
@ -11,7 +11,7 @@ import { takeUntil } from 'rxjs/operators';
@Component({ @Component({
selector: 'app-dataset-profile-criteria-component', selector: 'app-dataset-profile-criteria-component',
templateUrl: './dataset-profile.component.html', templateUrl: './dataset-profile.component.html',
styleUrls: ['./dataset-profile.component.scss'], styleUrls: ['./dataset-profile.component.scss']
}) })
export class DatasetProfileCriteriaComponent extends BaseCriteriaComponent implements OnInit { export class DatasetProfileCriteriaComponent extends BaseCriteriaComponent implements OnInit {
@ -47,26 +47,4 @@ export class DatasetProfileCriteriaComponent extends BaseCriteriaComponent imple
} }
} }
openDialog(): void {
const dialogRef = this.dialog.open(DialodConfirmationUploadDatasetProfiles, {
width: '500px',
restoreFocus: false,
data: {
message: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-TITLE'),
confirmButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML'),
cancelButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-CANCEL'),
name: "",
file: FileList,
sucsess: false
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(data => {
if (data && data.sucsess && data.name != null && data.file != null) {
this.datasetService.uploadFile(data.file, data.name)
.pipe(takeUntil(this._destroyed))
.subscribe();
}
});
}
} }

View File

@ -4,22 +4,41 @@
<h4>{{ data.message }}</h4> <h4>{{ data.message }}</h4>
</div> </div>
<div class="col-auto ml-auto"> <div class="col-auto ml-auto">
<input class="hidden" type="file" #imgFileInput (change)="selectXML($event)" accept="text/xml" /> <mat-icon class="close-btn" (click)="cancel()">close</mat-icon>
<button class="col-auto attach-file" (click)="imgFileInput.click()" type="button"> </div>
<mat-icon color="{{btnColore}}">attach_file</mat-icon> </div>
<div class="row">
<div class="col-12">
<ngx-dropzone class="drop-file" (change)="selectXML($event)" [accept]="'text/xml'" [multiple]="false">
<ngx-dropzone-preview class="file-preview" [removable]="true" *ngIf="hasProfile()" (removed)="onRemove()">
<ngx-dropzone-label class="file-label">{{ selectedFileName }}</ngx-dropzone-label>
</ngx-dropzone-preview>
</ngx-dropzone>
</div>
</div>
<div class="row">
<div class="col-12 d-flex justify-content-center attach-btn">
<button mat-button type="button" class="col-auto attach-file" (click)="imgFileInput.click()">
<mat-icon class="mr-2">input</mat-icon>
<span *ngIf="!hasProfile()">{{'GENERAL.START-NEW-DMP-DIALOG.UPLOAD-FILE' | translate}}</span>
<span *ngIf="hasProfile()">{{'GENERAL.START-NEW-DMP-DIALOG.REPLACE-FILE' | translate}}</span>
</button> </button>
<input class="hidden" type="file" #imgFileInput (change)="selectXML($event)" accept="text/xml" />
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<mat-form-field class="col-12"> <mat-form-field class="col-12">
<input matInput placeholder="{{'DATASET-WIZARD.UPLOAD.UPLOAD-XML-NAME'| translate}}" name="datasetProfileName" [(ngModel)]="data.name"> <input matInput placeholder="{{'DATASET-WIZARD.UPLOAD.UPLOAD-XML-NAME'| translate}}" name="datasetProfileName" [(ngModel)]="data.name">
</mat-form-field> </mat-form-field>
<div class="col-auto"> <div class="col-auto">
<button mat-raised-button type="button" (click)="cancel()">{{ data.cancelButton }}</button> <button mat-button type="button" class="cancel-btn" (click)="cancel()">{{ data.cancelButton }}</button>
</div> </div>
<div class="col"></div> <div class="col"></div>
<div class="col-auto"> <div class="col-auto">
<button mat-raised-button color="primary" type="button" (click)="confirm()" [disabled]="!hasProfile()">{{ data.confirmButton }}</button> <button mat-button color="primary" class="next-btn" type="button" (click)="confirm()" [disabled]="!hasProfile()">{{ data.confirmButton }}</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,3 +1,102 @@
.hidden { .hidden {
display: none; display: none;
} }
.cancel-btn {
background: #ffffff 0% 0% no-repeat padding-box;
border: 1px solid #b5b5b5;
border-radius: 30px;
width: 101px;
height: 43px;
color: #212121;
font-weight: 500;
}
.next-btn {
background: #ffffff 0% 0% no-repeat padding-box;
border: 1px solid #129d99;
border-radius: 30px;
opacity: 1;
width: 101px;
height: 43px;
color: #129d99;
font-weight: 500;
}
.next-btn[disabled] {
width: 100px;
height: 43px;
background: #ffffff 0% 0% no-repeat padding-box;
border: 1px solid #b5b5b5;
border-radius: 30px;
opacity: 1;
}
.next-btn:not([disabled]):hover {
background-color: #129d99;
color: #ffffff;
}
//ngx dropzone
.drop-file {
background-color: #fafafa;
border: 1px dashed #d1d1d1;
border-radius: 4px;
max-width: 480px;
height: 98px;
margin-top: 0.5rem;
}
.file-preview {
height: auto !important;
width: auto !important;
max-width: 500px !important;
min-height: 1rem !important;
background-color: #e0e0e0 !important;
background-image: none !important;
color: rgba(0, 0, 0, 0.87) !important;
font-weight: 500 !important;
border-radius: 24px !important;
line-height: 1.25 !important;
}
.file-label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 14px !important;
}
::ng-deep ngx-dropzone-remove-badge {
opacity: 1 !important;
margin-left: .5rem !important;
position: initial !important;
}
//attach file
.attach-btn {
top: -20px;
}
.attach-file {
width: 156px;
height: 44px;
color: #ffffff;
background: #129d99 0% 0% no-repeat padding-box;
box-shadow: 0px 3px 6px #1e202029;
border-radius: 30px;
}
.attach-file:hover {
background-color: #ffffff;
border: 1px solid #129d99;
color: #129d99;
}
.close-btn:hover{
cursor: pointer;
}

View File

@ -7,30 +7,35 @@ import { Inject, Component } from '@angular/core';
templateUrl: './dialog-confirmation-upload-profiles.component.html', templateUrl: './dialog-confirmation-upload-profiles.component.html',
styleUrls: ['./dialog-confirmation-upload-profiles.component.scss'] styleUrls: ['./dialog-confirmation-upload-profiles.component.scss']
}) })
export class DialodConfirmationUploadDatasetProfiles { export class DialogConfirmationUploadDatasetProfiles {
sizeError = false; sizeError = false;
btnColore:String="primary"; selectedFileName= "";
selectFile =false; selectFile =false;
maxFileSize: number = 1048576; maxFileSize: number = 1048576;
constructor( constructor(
public dialogRef: MatDialogRef<DialodConfirmationUploadDatasetProfiles>, public dialogRef: MatDialogRef<DialogConfirmationUploadDatasetProfiles>,
@Inject(MAT_DIALOG_DATA) public data: any @Inject(MAT_DIALOG_DATA) public data: any
) { } ) { }
selectXML(event) { selectXML(event) {
const file: FileList = event.target.files; let file: FileList = null;
if(event.target && event.target.files){
file = event.target.files;
}else if(event.addedFiles && event.addedFiles.length){
file = event.addedFiles;
}
if(!file) return;//no select closed with cancel . no file selected
const size: number = file[0].size; // Get file size. const size: number = file[0].size; // Get file size.
this.sizeError = size > this.maxFileSize; // Checks if file size is valid. this.sizeError = size > this.maxFileSize; // Checks if file size is valid.
const formdata: FormData = new FormData(); const formdata: FormData = new FormData();
if (!this.sizeError) { if (!this.sizeError) {
this.data.file = file; this.data.file = file;
this.selectFile=true; this.selectFile=true;
this.btnColore="primary"; this.selectedFileName = file[0].name;
}else{
this.btnColore="warn";
} }
this.data.name = file[0].name; this.data.name = file[0].name;
} }
@ -41,7 +46,6 @@ export class DialodConfirmationUploadDatasetProfiles {
} }
confirm() { confirm() {
this.data.name = this.data.name;
this.data.sucsess = true; this.data.sucsess = true;
this.dialogRef.close(this.data); this.dialogRef.close(this.data);
} }
@ -50,4 +54,10 @@ export class DialodConfirmationUploadDatasetProfiles {
return (this.selectFile && !this.sizeError); return (this.selectFile && !this.sizeError);
} }
//remove selected file
onRemove(){
this.data.name="";
this.selectFile = false;
this.selectedFileName = "";
}
} }

View File

@ -1,9 +1,26 @@
<div class="main-content dataset-profile-listing"> <div class="main-content dataset-profile-listing">
<div class="container-fluid"> <div class="container-fluid">
<h3>{{titlePrefix}} {{'DATASET-PROFILE-LISTING.TITLE' | translate}}</h3>
<div class="row">
<div class="col-auto">
<h3>{{titlePrefix}} {{'DATASET-PROFILE-LISTING.TITLE' | translate}}</h3>
</div>
<div class="col-12 col-lg d-flex justify-content-lg-end">
<div class="align-self-center">
<button mat-raised-button class="import-btn" (click)="openDialog()">{{ 'DATASET-WIZARD.UPLOAD.UPLOAD-XML' | translate }}</button>
<button mat-raised-button class="create-btn ml-md-3" [routerLink]="['./new']">Create Dataset Template</button>
</div>
</div>
</div>
<div class="row">
<div class="col-12 mt-5">
<app-dataset-profile-criteria-component></app-dataset-profile-criteria-component> <app-dataset-profile-criteria-component></app-dataset-profile-criteria-component>
<mat-card class="row mat-card"> </div>
</div>
<div class="mat-elevation-z6">
<!-- <mat-card class="row mat-card"> -->
<mat-table [dataSource]="dataSource" matSort (matSortChange)="refresh()"> <mat-table [dataSource]="dataSource" matSort (matSortChange)="refresh()">
<!-- Column Definition: Name --> <!-- Column Definition: Name -->
@ -31,12 +48,12 @@
<ng-container cdkColumnDef="status"> <ng-container cdkColumnDef="status">
<mat-header-cell *matHeaderCellDef mat-sort-header="status">{{'DATASET-PROFILE-LISTING.COLUMNS.STATUS' | <mat-header-cell *matHeaderCellDef mat-sort-header="status">{{'DATASET-PROFILE-LISTING.COLUMNS.STATUS' |
translate}}</mat-header-cell> translate}}</mat-header-cell>
<mat-cell *matCellDef="let row">{{ (row.status | parseStatus) | translate}}</mat-cell> <mat-cell *matCellDef="let row"> <div [ngClass]="['status-chip',getStatusClass(row.status)]">{{ (row.status | parseStatus) | translate}}</div></mat-cell>
</ng-container> </ng-container>
<!-- Column Definition: Submission Time --> <!-- Column Definition: Submission Time -->
<ng-container cdkColumnDef="actions"> <ng-container cdkColumnDef="actions">
<mat-header-cell *matHeaderCellDef>{{'DATASET-PROFILE-LISTING.COLUMNS.ACTIONS' | translate}} <mat-header-cell *matHeaderCellDef><!-- {{'DATASET-PROFILE-LISTING.COLUMNS.ACTIONS' | translate}} -->
</mat-header-cell> </mat-header-cell>
<mat-cell *matCellDef="let row" (click)="$event.stopPropagation()"> <mat-cell *matCellDef="let row" (click)="$event.stopPropagation()">
<mat-menu #actionsMenu="matMenu"> <mat-menu #actionsMenu="matMenu">
@ -50,10 +67,18 @@
<mat-icon>library_books</mat-icon> <mat-icon>library_books</mat-icon>
{{'DATASET-PROFILE-LISTING.ACTIONS.VIEW-VERSIONS' | translate}} {{'DATASET-PROFILE-LISTING.ACTIONS.VIEW-VERSIONS' | translate}}
</button> </button>
<button mat-menu-item (click)="downloadXML(row.id)" *ngIf="row.status === datasetStatusEnum.Finalized">
<mat-icon>download</mat-icon>
{{'DMP-PROFILE-EDITOR.ACTIONS.DOWNLOAD-XML' | translate}}
</button>
<button mat-menu-item (click)="deleteTemplate(row.id)">
<mat-icon>delete</mat-icon>
{{'DATASET-PROFILE-LISTING.ACTIONS.DELETE' | translate}}
</button>
<!--<button *ngIf="row.status==1" mat-menu-item (click)="makeItPublic(row.id)"><mat-icon>people_outline</mat-icon>{{'DATASET-LISTING.ACTIONS.MAKE-IT-PUBLIC' | translate}}</button> --> <!--<button *ngIf="row.status==1" mat-menu-item (click)="makeItPublic(row.id)"><mat-icon>people_outline</mat-icon>{{'DATASET-LISTING.ACTIONS.MAKE-IT-PUBLIC' | translate}}</button> -->
</mat-menu> </mat-menu>
<button mat-icon-button [matMenuTriggerFor]="actionsMenu"> <button mat-icon-button [matMenuTriggerFor]="actionsMenu">
<mat-icon>more_vert</mat-icon> <mat-icon>more_horiz</mat-icon>
</button> </button>
</mat-cell> </mat-cell>
</ng-container> </ng-container>
@ -63,14 +88,10 @@
<!-- (click)="rowClick(row.id)" --> <!-- (click)="rowClick(row.id)" -->
</mat-table> </mat-table>
<mat-paginator #paginator [length]="dataSource?.totalCount" [pageSizeOptions]="[10, 25, 100]"> <mat-paginator #paginator [length]="dataSource?.totalCount" [pageSizeOptions]="[10, 25, 100]">
</mat-paginator> </mat-paginator>
</mat-card> <!-- </mat-card> -->
<div class="row justify-content-end pr-2">
<button mat-fab class="mat-fab-bottom-right" color="primary" [routerLink]="['./new']">
<mat-icon class="mat-24">add</mat-icon>
</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,9 +1,14 @@
.dataset-profile-listing { .dataset-profile-listing {
margin-top: 1rem; margin-top: 1rem;
margin-left: 1rem;
margin-right: 2rem;
} }
.mat-table { .mat-table {
margin: 24px; margin-top: 47px;
// margin-bottom: 20px;
border-radius: 4px;
} }
.mat-fab-bottom-right { .mat-fab-bottom-right {
@ -16,6 +21,10 @@
z-index: 5; z-index: 5;
} }
.mat-header-row{
background: #f3f5f8;
}
.full-width { .full-width {
width: 100%; width: 100%;
} }
@ -26,48 +35,85 @@
.mat-row { .mat-row {
cursor: pointer; cursor: pointer;
min-height: 4.5em;
} }
mat-row:hover { mat-row:hover {
background-color: lightgray; background-color: #eef5f6;
} }
.status-chip{
border-radius: 20px;
padding-left: 1em;
padding-right: 1em;
padding-top: 0.2em;
font-size: .8em;
}
.status-chip-finalized{
color: #568b5a;
background: #9dd1a1 0% 0% no-repeat padding-box;
}
.status-chip-draft{
color: #00c4ff;
background: #d3f5ff 0% 0% no-repeat padding-box;
}
// mat-row:nth-child(even){ // mat-row:nth-child(even){
// background-color:red; // background-color:red;
// } // }
mat-row:nth-child(odd) { // mat-row:nth-child(odd) {
background-color: #0c748914; // background-color: #0c748914;
// background-color: #eef0fb; // // background-color: #eef0fb;
} // }
::ng-deep .mat-paginator-container { :host ::ng-deep .mat-paginator-container {
flex-direction: row-reverse !important; flex-direction: row-reverse !important;
justify-content: space-between !important; justify-content: space-between !important;
background-color: #f6f6f6; background-color: #f6f6f6;
height: 30px; align-items: center;
min-height: 30px !important; // height: 30px;
// min-height: 30px !important;
} }
::ng-deep .mat-paginator-page-size { // ::ng-deep .mat-paginator-page-size {
height: 43px; // height: 43px;
} // }
::ng-deep .mat-paginator-range-label { // ::ng-deep .mat-paginator-range-label {
margin: 15px 32px 0 24px !important; // margin: 15px 32px 0 24px !important;
} // }
::ng-deep .mat-paginator-range-actions { // ::ng-deep .mat-paginator-range-actions {
width: 55% !important; // width: 55% !important;
min-height: 43px !important; // min-height: 43px !important;
justify-content: space-between; // justify-content: space-between;
} // }
::ng-deep .mat-paginator-navigation-previous { // ::ng-deep .mat-paginator-navigation-previous {
margin-left: auto !important; // margin-left: auto !important;
} // }
::ng-deep .mat-icon-button { // ::ng-deep .mat-icon-button {
height: 30px !important; // height: 30px !important;
font-size: 12px !important; // font-size: 12px !important;
// }
.import-btn {
background: #ffffff 0% 0% no-repeat padding-box;
border-radius: 30px;
// color: #129d99;
// border: 1px solid #129d99;
padding-left: 2em;
padding-right: 2em;
color: #000;
border: 1px solid #000;
}
.create-btn {
border-radius: 30px;
background-color: #f7dd72;
padding-left: 2em;
padding-right: 2em;
} }

View File

@ -1,9 +1,11 @@
import { DataSource } from '@angular/cdk/table'; import { DataSource } from '@angular/cdk/table';
import { HttpClient } from '@angular/common/http'; import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Component, OnInit, ViewChild } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort'; import { MatSort } from '@angular/material/sort';
import { ActivatedRoute, Params, Router } from '@angular/router'; import { ActivatedRoute, Params, Router } from '@angular/router';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
import { DataTableRequest } from '@app/core/model/data-table/data-table-request'; import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
import { DatasetListingModel } from '@app/core/model/dataset/dataset-listing'; import { DatasetListingModel } from '@app/core/model/dataset/dataset-listing';
import { DmpModel } from '@app/core/model/dmp/dmp'; import { DmpModel } from '@app/core/model/dmp/dmp';
@ -11,13 +13,17 @@ import { DatasetProfileCriteria } from '@app/core/query/dataset-profile/dataset-
import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service'; import { DatasetProfileService } from '@app/core/services/dataset-profile/dataset-profile.service';
import { DmpService } from '@app/core/services/dmp/dmp.service'; import { DmpService } from '@app/core/services/dmp/dmp.service';
import { MatomoService } from '@app/core/services/matomo/matomo-service'; import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component'; import { DatasetProfileCriteriaComponent } from '@app/ui/admin/dataset-profile/listing/criteria/dataset-profile.component';
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import * as FileSaver from 'file-saver';
import { merge as observableMerge, Observable, of as observableOf } from 'rxjs'; import { merge as observableMerge, Observable, of as observableOf } from 'rxjs';
import { map, startWith, switchMap, takeUntil } from 'rxjs/operators'; import { map, startWith, switchMap, takeUntil } from 'rxjs/operators';
import { DialogConfirmationUploadDatasetProfiles } from './criteria/dialog-confirmation-upload-profile/dialog-confirmation-upload-profiles.component';
import { ParseStatus } from './pipe/parse-status.pipe';
@Component({ @Component({
selector: 'app-dataset-profile-listing-component', selector: 'app-dataset-profile-listing-component',
@ -37,6 +43,7 @@ export class DatasetProfileListingComponent extends BaseComponent implements OnI
titlePrefix: String; titlePrefix: String;
dmpId: String; dmpId: String;
itemId: string; itemId: string;
datasetStatusEnum = DatasetStatus;
constructor( constructor(
private datasetService: DatasetProfileService, private datasetService: DatasetProfileService,
@ -46,7 +53,9 @@ export class DatasetProfileListingComponent extends BaseComponent implements OnI
private language: TranslateService, private language: TranslateService,
private uiNotificationService: UiNotificationService, private uiNotificationService: UiNotificationService,
private httpClient: HttpClient, private httpClient: HttpClient,
private matomoService: MatomoService private matomoService: MatomoService,
private dialog: MatDialog,
private datasetProfileService: DatasetProfileService,
) { ) {
super(); super();
} }
@ -117,11 +126,121 @@ export class DatasetProfileListingComponent extends BaseComponent implements OnI
viewVersions(rowId, rowLabel) { viewVersions(rowId, rowLabel) {
this.router.navigate(['/dataset-profiles/versions/' + rowId], { queryParams: { groupLabel: rowLabel } }); this.router.navigate(['/dataset-profiles/versions/' + rowId], { queryParams: { groupLabel: rowLabel } });
} }
downloadXML(datasetProfileId: string): void {
this.datasetProfileService.downloadXML(datasetProfileId)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/xml' });
const filename = this.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
});
}
getFilenameFromContentDispositionHeader(header: string): string {
const regex: RegExp = new RegExp(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/g);
const matches = header.match(regex);
let filename: string;
for (let i = 0; i < matches.length; i++) {
const match = matches[i];
if (match.includes('filename="')) {
filename = match.substring(10, match.length - 1);
break;
} else if (match.includes('filename=')) {
filename = match.substring(9);
break;
}
}
return filename;
}
deleteTemplate(id: string){
if(id){
const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
restoreFocus: false,
data: {
message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'),
confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'),
isDeleteConfirmation: true
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
//this.form.get('status').setValue(DatasetProfileEnum.DELETED);
this.datasetProfileService.delete(id, null)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Success);
this.refresh();
},
error => {
this.onCallbackError(error);
if (error.error.statusCode == 674) {
this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DATASET-PROFILE-DELETE'), SnackBarNotificationLevel.Error);
} else {
this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error);
}
}
);
}
});
}
}
onCallbackError(errorResponse: HttpErrorResponse) {
this.uiNotificationService.snackBarNotification(errorResponse.message, SnackBarNotificationLevel.Warning);
}
// makeItPublic(id: String) { // makeItPublic(id: String) {
// debugger; // debugger;
// this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe(); // this.datasetService.makeDatasetPublic(id).pipe(takeUntil(this._destroyed)).subscribe();
// } // }
openDialog(): void {
const dialogRef = this.dialog.open(DialogConfirmationUploadDatasetProfiles, {
width: '500px',
restoreFocus: false,
data: {
message: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-TITLE'),
confirmButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML'),
cancelButton: this.language.instant('DATASET-WIZARD.UPLOAD.UPLOAD-XML-FILE-CANCEL'),
name: "",
file: FileList,
sucsess: false
}
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(data => {
if (data && data.sucsess && data.name != null && data.file != null) {
this.datasetService.uploadFile(data.file, data.name)
.pipe(takeUntil(this._destroyed))
.subscribe(_=>{
this.uiNotificationService.snackBarNotification('Template successfully uploaded', SnackBarNotificationLevel.Success);
this.refresh();
},
error=>{
this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error);
}
);
}
});
}
/**
* gets as a a pameter a number representing the status and returns the class that is applied
* to status-chip */
getStatusClass(status: DatasetStatus):string{
if(status == DatasetStatus.Finalized){
return 'status-chip-finalized'
}
return 'status-chip-draft';
}
} }
export class DatasetDataSource extends DataSource<DatasetListingModel> { export class DatasetDataSource extends DataSource<DatasetListingModel> {

View File

@ -1,4 +1,5 @@
import { Pipe, PipeTransform } from '@angular/core'; import { Pipe, PipeTransform } from '@angular/core';
import { DatasetStatus } from '@app/core/common/enum/dataset-status';
@Pipe({ @Pipe({
name: 'parseStatus', name: 'parseStatus',
@ -10,7 +11,17 @@ export class ParseStatus implements PipeTransform {
} }
parseStatus(status: number): string { parseStatus(status: DatasetStatus): string {
return status != 0 ? 'DATASET-PROFILE-STATUS.FINALIZED' : 'DATASET-PROFILE-STATUS.DRAFT';
switch (status) {
case DatasetStatus.Finalized:
return 'DATASET-PROFILE-STATUS.FINALIZED';
case DatasetStatus.Draft:
return 'DATASET-PROFILE-STATUS.DRAFT';
case DatasetStatus.Deleted:
return 'DATASET-PROFILE-STATUS.DRAFT.DELETED';
default:
return 'DATASET-PROFILE-STATUS.DRAFT.NONE';
}
} }
} }

View File

@ -0,0 +1,29 @@
import { AbstractControl } from "@angular/forms";
export interface ToCEntry {
id: string;
label: string;
subEntriesType: ToCEntryType;
subEntries: ToCEntry[];
type: ToCEntryType;
form: AbstractControl;
numbering: string;
}
export enum ToCEntryType {
Page = 0,
Section = 1,
FieldSet = 2,
Field = 3
}
export interface NewEntryType {
childType: ToCEntryType,
parent: ToCEntry
}
export interface TableUpdateInfo{
draggedItemId?: string;
data?:any;
}

View File

@ -0,0 +1,249 @@
<!-- <span style="cursor: pointer;" [ngClass]="{'active': itemSelected?.id == parentLink?.id}" (click)="itemClicked(parentLink)" *ngIf="!(parentLink.type == undefined)" >
{{parentLink?.numbering}} {{parentLink?.label? parentLink?.label : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}}
<span class="mat-button" (click)="deleteEntry(parentLink)" *ngIf="itemSelected?.id == parentLink?.id"><mat-icon>delete</mat-icon></span>
</span> -->
<div class="table-item row align-items-center" *ngIf="!(parentLink.type == undefined)">
<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')}"
> -->
<span class="table-label-element"
[ngClass]="{'table-label-element-active': itemSelected?.id == parentLink?.id, 'text-danger': colorError() ||( (parentLink?.subEntriesType === tocEntryType.FieldSet )&& !colorError() && !selectedItemInLinks && parentLink?.form.invalid && colorizeInvalid && (itemSelected?.id != parentLink?.id) && !_findTocEntryById(itemSelected?.id, parentLink?.subEntries))}"
(click)="itemClicked(parentLink)"
[ngStyle]="{'font-size' : (parentLink.type == tocEntryType.FieldSet? '.9rem':'1rem')}"
[id]="'TABLE_ENTRY'+parentLink.id"
>
<!-- {{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) + ' '+ ( (parentLink.type ===tocEntryType.Page? ('DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.PAGE' | translate) : (parentLink.type === tocEntryType.Section? ('DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION' | translate) : '') ) | lowercase )}} -->
{{parentLink?.numbering}} {{parentLink?.form.get('title').value? parentLink?.form.get('title').value : 'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.UNTITLED' | translate}}
<ng-container *ngIf="!parentLink.form.get('title').value" [ngSwitch]="parentLink.type">
<ng-container *ngSwitchCase="tocEntryType.FieldSet">
{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.QUESTION' | translate |lowercase}}
</ng-container>
<ng-container *ngSwitchCase="tocEntryType.Section">
{{'DATASET-PROFILE-EDITOR.STEPS.SECTION-INFO.SECTION' | translate |lowercase}}
</ng-container>
<ng-container *ngSwitchCase="tocEntryType.Page">
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.PAGE' | translate | lowercase}}
</ng-container>
</ng-container>
<!-- {{parentLink?.numbering}} {{parentLink?.form.get('title').value? parentLink?.form.get('title').value : parentLink.id}} -->
</span>
</div>
<div class="col-auto d-flex align-items-center" >
<ng-container *ngIf="!(!((parentLink?.subEntriesType == tocEntryType.FieldSet) && !selectedItemInLinks) || itemSelected?.id == parentLink.id ||isDragging)">
<!-- <mat-icon class="text-danger" style="font-size: 1.4em;" *ngIf="!colorError() && parentLink?.form.invalid && colorizeInvalid && allFieldsAreTouched(parentLink?.form)">priority_high</mat-icon> -->
<span class="badge-ball"
>
{{parentLink.subEntries?.length}}
</span>
</ng-container>
<span style="cursor: pointer;" (click)="deleteEntry(parentLink)"
[hidden]="!(!viewOnly && (itemSelected?.id == parentLink?.id) && (parentLink?.type != tocEntryType.FieldSet))"
>
<mat-icon style="font-size: 1.4em;">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)"> -->
<!-- [ngClass]="{'border-left-active':itemSelected?.id == parentLink?.id, 'pl-1':itemSelected?.id == parentLink?.id, 'pb-4': isDragging && (parentLink?.type!= tocEntryType.FieldSet) && (parentLink?.id != draggingItemId) }" -->
<div dragula="TABLEDRAG" class="ml-2"
[ngClass]="{'border-left-active':itemSelected?.id == parentLink?.id, 'ml-1':itemSelected?.id == parentLink?.id, 'pb-4': isDragging && (parentLink?.type!= tocEntryType.FieldSet) && (parentLink?.id != draggingItemId) }"
[hidden]="!((parentLink?.subEntriesType!= tocEntryType.FieldSet) || selectedItemInLinks || parentLink?.id === itemSelected?.id ||isDragging)"
class="cdk-link-list"
[id]="parentLink.id"
[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> -->
<!-- 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 [ngClass]="{'ml-3': link.type != tocEntryType.Page }">
<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()"
[DRAGULA_ITEM_ID_PREFIX]="DRAGULA_ITEM_ID_PREFIX"
[overContainerId]="overContainerId"
[isDragging]="isDragging"
[draggingItemId]="draggingItemId"
[parentRootId]="parentRootId"
[colorizeInvalid]="colorizeInvalid">
</app-dataset-profile-table-of-contents-internal-section>
<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">
<div class="d-flex" style="align-items: center;" >
<mat-icon color="accent" style="font-size: 1.6em;margin-left: -0.3em;">add</mat-icon>
<!-- Create new subsection -->
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.ACTIONS.CREATE-NEW-SUBSECTION' |translate}}
</div>
<!-- Subsection + -->
</ng-container>
<!-- <ng-container *ngSwitchCase="tocEntryType.Page">
Section
</ng-container> -->
<ng-container *ngSwitchCase="tocEntryType.FieldSet">
Field +
</ng-container>
</ng-container>
</button>
</ng-container>
<!-- </div> -->
</ng-container>
</div>
</div>
</div> <!-- END OF LOOP-->
</ng-container>
</div>
<ng-container *ngIf="!isDragging">
<!-- 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-3">
<!-- Give option to generate section -->
<button class="mat-button" style="padding-left: 0px; display: block;" (click)="createNewEntry({childType:tocEntryType.Section,parent:parentLink})">
<!-- <mat-icon>add</mat-icon> -->
<!-- Subsection + -->
<div class="d-flex" style="align-items: center;" >
<mat-icon color="accent" style="font-size: 1.6em;margin-left: -0.3em;">add</mat-icon>
<!-- Create new subsection -->
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.ACTIONS.CREATE-NEW-SUBSECTION' |translate}}
</div>
</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})">
Field +
</button> -->
</div>
</div>
<!-- BUILD TYPE OF SAME LEVEL AS LINK OF LINKS -->
<!-- <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>
<ng-container [ngSwitch]="parentLink?.subEntriesType">
<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> -->
<!-- </ng-container> -->
<!-- Only for the page -->
<!-- style="margin-left: -0.5em;" -->
<div *ngIf="parentLink?.subEntriesType == tocEntryType.Page && !viewOnly" >
<button class="mat-button mt-2" (click)="createNewEntry({childType:parentLink.subEntriesType,parent:parentLink})" style="padding-left:0px">
<!-- <mat-icon>add</mat-icon> -->
<div class="d-flex" style="align-items: center;" >
<mat-icon color="accent" style="font-size: 1.6em;margin-left: -0.3em;">add</mat-icon>
<ng-container *ngIf="!links?.length else createsection">
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.ACTIONS.CREATE-FIRST-SECTION'| translate}}
<!-- Create the first section -->
</ng-container>
<ng-template #createsection>
{{'DATASET-PROFILE-EDITOR.STEPS.PAGE-INFO.ACTIONS.CREATE-NEW-SECTION'| translate}}
<!-- Create new section -->
</ng-template>
</div>
</button>
<!-- <button (click)="showDroplists()">show droplist</button>
<button (click)="showStructs()">structs</button> -->
</div>
</ng-container>

View File

@ -0,0 +1,113 @@
// .docs-toc-container {
// width: 100%;
// padding: 5px 0 10px 0px;
// // cursor: pointer;
// // border-left: solid 4px #0c7489;
// .scroll-container {
// overflow-y: auto;
// // calc(100vh - 250px)
// // height: calc(100vh - 250px);
// }
// .docs-link {
// color: rgba(0, 0, 0, 0.54);
// // color: mat-color($app-blue-theme-foreground, secondary-text);
// transition: color 100ms;
// &:hover,
// &.docs-active {
// .link-name {
// background-color: #ececec;
// border-radius: 6px;
// cursor: pointer;;
// // color: #0c7489;
// }
// // color: mat-color($primary, if($is-dark-theme, 200, default));
// }
// }
// }
// .docs-toc-heading {
// margin: 0;
// padding: 0;
// font-size: 13px;
// font-weight: bold;
// }
// .table-item-actions{
// // display: none;
// display: inline-block;
// visibility: hidden;
// }
// .table-item:hover {
// .table-item-actions{
// // display: inline-block;
// visibility: visible;
// }
// }
// .table-item col{
// text-overflow: ellipsis;
// overflow: hidden;
// white-space: nowrap;
// }
.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;
}
.side-bolder{
border-left: 1px solid red;
}
.cdk-link-list {
display: block;
// background: white;
overflow: hidden;
}
$blue-color : #129D99;
$blue-color-light: #5cf7f2;
$yellow: #f7dd72;
.badge-ball{
display: inline-block;
border-radius: 50%;
background-color: #FFF;
font-size: small;
font-weight: bold;
min-width: 2em;
text-align: center;
}
.table-label-element{
cursor: pointer;
// font-weight: normal;
// transition-property: font-weight;
// transition-duration: 160ms;
// transition-delay: 50ms;
// transition-timing-function: ease-in-out;
}
.table-label-element-active{
font-weight: bold;
// color: red;
}

View File

@ -0,0 +1,281 @@
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
import { DOCUMENT } from '@angular/common';
import { Component, EventEmitter, Inject, Input, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core';
import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
import { BaseComponent } from '@common/base/base.component';
import { NewEntryType, ToCEntry, ToCEntryType } from '../table-of-contents-entry';
@Component({
selector: 'app-dataset-profile-table-of-contents-internal-section',
styleUrls: ['./table-of-contents-internal-section.scss'],
templateUrl: './table-of-contents-internal-section.html'
})
export class DatasetProfileTableOfContentsInternalSection extends BaseComponent implements OnInit {
@Input() links: ToCEntry[];
@Output() itemClick = new EventEmitter<ToCEntry>();
@Output() removeEntry = new EventEmitter<ToCEntry>();
@Output() createFooEntry = new EventEmitter<NewEntryType>();
@Output() dataNeedsRefresh = new EventEmitter<void>();
@Input() parentLink: ToCEntry;
@Input() itemSelected: ToCEntry;
@Input() DRAGULA_ITEM_ID_PREFIX;
@Input() overContainerId: string;
@Input() isDragging;
@Input() draggingItemId: string;
@Input() parentRootId: string;
@Input() colorizeInvalid:boolean = false;
@Input() viewOnly: boolean;
// @Input() dropListGroup: Set<string> = new Set<string>();
// @Input() dropListGroup: string[];
// @Input() dragHoveringOver: boolean = false;
// @Input() depth: number = 0;
// @Input() dropListStruct: { id: string, depth: number}[] = [];
constructor(
@Inject(DOCUMENT) private _document: Document) {
super();
}
tocEntryType = ToCEntryType;
// compareFn(a, b){
// if(a.depth> b.depth) return -1;
// if(a.depth< b.depth) return 1;
// return 0;
// }
ngOnInit(): void {
}
// hoveroverEnter(){
// // console.log('user hovering drag over', this.parentLink.id, this.parentLink.label);
// this.dragHoveringOver = true;
// }
// hoveroverLeft(){
// this.dragHoveringOver = false;
// }
ngOnChanges(changes: SimpleChanges) {
}
// get grouListIds(){
// return Array.from(this.dropListGroup);
// }
itemClicked(item: ToCEntry) {
//leaf node
this.itemClick.emit(item);
}
deleteEntry(currentLink: ToCEntry){
this.removeEntry.emit(currentLink);
}
createNewEntry(foo: NewEntryType){
this.createFooEntry.emit(foo);
}
// tocEntryIsChildOf(testingChild: ToCEntry,parent: ToCEntry): boolean{
// if(!testingChild || !parent) return false;
// if(testingChild.id == parent.id){return true;}
// if(parent.subEntries){
// let childFound:boolean = false;
// parent.subEntries.forEach(subEntry=>{
// if(this.tocEntryIsChildOf(testingChild, subEntry)){
// childFound = true;
// return true;
// }
// })
// return childFound;
// }
// 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;
}
// appendAndGetDroplists(dropList: CdkDropList){
// this.dropListGroup.push(dropList);
// return this.dropListGroup;
// }
// drop(event: CdkDragDrop<string[]>) {
// // if(!this.links || !this.links.length) return;
// if(event.container === event.previousContainer){
// 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();
// }else{
// console.log('not same container');
// }
// console.log(event.container.id);
// }
onDataNeedsRefresh(){
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;
// }
public _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;
}
colorError():boolean{
if(!this.colorizeInvalid) return false;
const form = this.parentLink.form;
if((!form || form.valid || !form.touched) && this.parentLink.type !== this.tocEntryType.Page) return false;
const allFieldsAreTouched = this.allFieldsAreTouched(form);
//fieldset may have errros that are inside its controls and not in the fieldsetFormGroup
if(this.parentLink.type === this.tocEntryType.FieldSet && allFieldsAreTouched) return true;
if(form.errors && allFieldsAreTouched) return true;
//check if page has sections
if(this.parentLink.type === this.tocEntryType.Page && allFieldsAreTouched){
const rootForm = form.root;
if(rootForm){
const sections = rootForm.get('sections') as FormArray;
if(!sections.controls.find(section=>section.get('page').value === this.parentLink.id)){
return true;
}
}
}
//checking first child form controls if have errors
let hasErrors = false;
if(allFieldsAreTouched){
if(form instanceof FormGroup){
const formGroup = form as FormGroup;
const controls = Object.keys(formGroup.controls);
controls.forEach(control=>{
if(formGroup.get(control).errors){
hasErrors = true;
}
})
}
}
return hasErrors;
}
allFieldsAreTouched(aControl:AbstractControl){//auto na testaroume
if(!aControl|| aControl.untouched) return false;
if(aControl instanceof FormControl){
return aControl.touched;
}else if(aControl instanceof FormGroup){
const controlKeys = Object.keys((aControl as FormGroup).controls);
let areAllTouched = true;
controlKeys.forEach(key=>{
if(!this.allFieldsAreTouched(aControl.get(key))){
areAllTouched = false;
}
})
// const areAllTouched = controlKeys.reduce((acc, key)=>acc && this._allFieldsAreTouched(aControl.get(key)), true);
return areAllTouched;
}else if(aControl instanceof FormArray){
const controls = (aControl as FormArray).controls;
// const areAllTouched = controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true);
let areAllTouched = true;
// controls.reduce((acc, control)=>acc && this._allFieldsAreTouched(control), true);
controls.forEach(control=>{
if(!this.allFieldsAreTouched(control)){
areAllTouched = false;
}
});
return areAllTouched;
}
return false;
}
}

View File

@ -0,0 +1,23 @@
<div>
<h3 id="guide-steps">{{'DATASET-PROFILE-EDITOR.STEPS.GENERAL-INFO.TEMPLATE-OUTLINE' | translate}}</h3>
<div class="scroll-container" id="tocentrytable">
<app-dataset-profile-table-of-contents-internal-section [links]="links" (itemClick)="itemClicked($event)"
(removeEntry)="deleteEntry($event)"
(createFooEntry)="createNewEntry($event)"
[parentLink]="{ subEntriesType: tocEntryType.Page, subEntries : links , id: ROOT_ID}"
[itemSelected]="itemSelected"
[viewOnly]="viewOnly"
(dataNeedsRefresh)="onDataNeedsRefresh()"
[DRAGULA_ITEM_ID_PREFIX]="DRAGULA_ITEM_ID_PREFIX"
[overContainerId]="overcontainer"
[isDragging]="isDragging"
[draggingItemId]="draggingItemId"
[parentRootId]="ROOT_ID"
style="padding-right: 1em;"
[colorizeInvalid]="colorizeInvalid"
>
</app-dataset-profile-table-of-contents-internal-section>
</div>
</div>

View File

@ -0,0 +1,62 @@
.scroll-container {
// overflow-y: auto;
max-height: 60vh;
overflow-y: scroll;
padding-left: .2em;
padding-right: 1em;
}
// #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)
// }
#tocentrytable::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 10px;
background-color: #F5F5F5;
}
#tocentrytable::-webkit-scrollbar
{
width: 4px;
background-color: #F5F5F5;
}
#tocentrytable::-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;
}
#guide-steps{
color: #212121;
opacity: 0.6;
font-size: 1.6em;
margin-top: 0px;
}

View File

@ -0,0 +1,559 @@
import { DOCUMENT } from '@angular/common';
import { Component, EventEmitter, Inject, OnInit, Output, Input } from '@angular/core';
import { BaseComponent } from '@common/base/base.component';
import { interval, Subject, Subscription } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';
import { type } from 'os';
import { SimpleChanges } from '@angular/core';
import { NewEntryType, TableUpdateInfo, ToCEntry, ToCEntryType } from './table-of-contents-entry';
import { DragulaService } from 'ng2-dragula';
import { FormArray } from '@angular/forms';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material';
import { TranslateService } from '@ngx-translate/core';
import { ContentObserver } from '@angular/cdk/observers';
@Component({
selector: 'dataset-profile-table-of-contents',
styleUrls: ['./table-of-contents.scss'],
templateUrl: './table-of-contents.html'
})
export class DatasetProfileTableOfContents extends BaseComponent implements OnInit {
@Input() links: ToCEntry[];
@Input() itemSelected: ToCEntry;
@Input() colorizeInvalid: boolean = false;
@Input() viewOnly: boolean;
@Output() itemClick = new EventEmitter<ToCEntry>();
// @Output() newEntry = new EventEmitter<ToCEntry>();
@Output() removeEntry = new EventEmitter<ToCEntry>();
@Output() createEntry = new EventEmitter<NewEntryType>();
@Output() dataNeedsRefresh = new EventEmitter<TableUpdateInfo>();
isDragging: boolean = false;
draggingItemId: string = null;
tocEntryType = ToCEntryType;
DRAGULA_ITEM_ID_PREFIX="table_item_id_";
ROOT_ID: string = "ROOT_ID";//no special meaning
private _dragStartedAt;
private VALID_DROP_TIME = 500;//ms
overcontainer: string = null;
constructor(
@Inject(DOCUMENT) private _document: Document,
private dragulaService: DragulaService,
private snackbar: MatSnackBar,
private language: TranslateService
) {
super();
if(this.dragulaService.find('TABLEDRAG')){
this.dragulaService.destroy('TABLEDRAG');
}
const dragula = this.dragulaService.createGroup('TABLEDRAG', {});
const drake = dragula.drake;
drake.on('drop', (el, target, source,sibling)=>{
if(this._dragStartedAt){
const timeNow = new Date().getTime();
if(timeNow - this._dragStartedAt> this.VALID_DROP_TIME){
// console.log('timenow: ', timeNow);
// console.log('timestarted', this._dragStartedAt);
this._dragStartedAt = null;
}else{
this.dataNeedsRefresh.emit();// even though the data is not changed the TABLE DRAG may has changed
return;
}
}else{
this.dataNeedsRefresh.emit();// even though the data is not changed the TABLE DRAG may has changed
return;
}
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.info('Elements do 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){
// const message = 'Fieldset can only be child of Subsections';
const message = this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.TABLE-OF-CONTENTS.ERROR-MESSAGES.FIELDSET-MUST-HAVE-PARENT-SECTION');
// 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){
// const message = 'Cannot have inputs and sections on the same level';
const message = this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.TABLE-OF-CONTENTS.ERROR-MESSAGES.INPUT-SECTION-SAME-LEVEL');
this.notifyUser(message);
// console.error(message);
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.info('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) && sourceOrdinal>0){
const updatedOrdinalVal = ordinal.value -1;
ordinal.setValue(updatedOrdinalVal);
}
});
sourceFieldsets.controls.sort(this._compareOrdinals);
}
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){ //sibling found
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);
targetFieldsets.controls.sort(this._compareOrdinals);
this.dataNeedsRefresh.emit({draggedItemId: elementId});
break;
}
case ToCEntryType.Section:{
if(targetContainer.type == ToCEntryType.Section){
if((targetContainer.form.get('fieldSets')as FormArray).length){
// const message = 'Cannot have inputs and sections on the same level';
const message = this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.TABLE-OF-CONTENTS.ERROR-MESSAGES.INPUT-SECTION-SAME-LEVEL');;
this.notifyUser(message);
// console.info(message);
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? ordinal.value -1: 0;
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){//mporei na einai idio
// 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?ordinal.value -1: 0;
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)=>{
if(e.form.get('id').value === siblingId){
indx = i;
position = e.form.get('ordinal').value;
}
});
if(indx>=0) {
// 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{
// const message = 'Drag not support to specific container';
const message = this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.TABLE-OF-CONTENTS.ERROR-MESSAGES.DRAG-NOT-SUPPORTED');
this.notifyUser(message);
// console.info(message);
this.dataNeedsRefresh.emit();
return;
}
this.dataNeedsRefresh.emit({draggedItemId: elementId});
break;
}
case ToCEntryType.Page:{
if(targetId != this.ROOT_ID){
// const message = 'A page element can only be at top level';
const message = this.language.instant('DATASET-PROFILE-EDITOR.STEPS.FORM.TABLE-OF-CONTENTS.ERROR-MESSAGES.PAGE-ELEMENT-ONLY-TOP-LEVEL');
this.notifyUser(message);
// console.info(message);
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? ordinal.value - 1: 0;
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({draggedItemId:elementId});
break;
}
default:
console.info('Could not support moving objects for specific type of element');
this.dataNeedsRefresh.emit();
return;
}
});
drake.on('drag',(el,source)=>{
this._dragStartedAt = new Date().getTime();
// console.log('drag fired');
this.isDragging = true;
this.draggingItemId = (el.id as string).replace(this.DRAGULA_ITEM_ID_PREFIX, '');
// setTimeout(() => {
// if(this.isDragging){
// this._scrollIntoDragginItem(this.draggingItemId);
// }
// }, this.VALID_DROP_TIME);
});
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;
});
}
private _scrollIntoDragginItem(id: string){
// const table = document.getElementById('tocentrytable');
// if(table){
// // const element = document.getElementById('TABLE_ENTRY'+id);
// console.log('Table found!');
// const element = document.getElementById('TABLE_ENTRY' + id);
// const elementFromTable = table.closest('#TABLE_ENTRY'+ id);
// if(elementFromTable){
// console.log('found from table:', elementFromTable);
// }
// if(element){
// console.log('Element found!');
// // element.classList.add('text-danger');
// // console.log(element);
// const tableRect = table.getBoundingClientRect();
// const elementRect = element.getBoundingClientRect();
// console.log('tablerect :',tableRect);
// console.log('elementRect :',elementRect);
// const dY = elementRect.top - tableRect.top;
// console.log('Distance from table is ', dY);
// // table.scroll({top:dY,behavior:'smooth'});
// console.log('found from document ', element);
// // element.scrollIntoView();
// }
// // element.scrollIntoView();
// }
}
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 {
}
ngOnChanges(changes: SimpleChanges) {
}
itemClicked(item: ToCEntry){
//leaf node
this.itemClick.emit(item);
}
// addNewEntry(tce: ToCEntry){
// this.newEntry.emit(tce);
// }
deleteEntry(currentLink: ToCEntry){
this.removeEntry.emit(currentLink);
}
createNewEntry(newEntry: NewEntryType){
this.createEntry.emit(newEntry);
}
onDataNeedsRefresh(){
this.dataNeedsRefresh.emit();
}
notifyUser(message:string){
this.snackbar.open(message, null, this._snackBarConfig);
}
private _snackBarConfig: MatSnackBarConfig = {
duration:2000
}
private _compareOrdinals(a, b){
const aValue = a.get('ordinal').value as number;
const bValue = b.get('ordinal').value as number;
// if(!aValue || !bValue) return 0;
return aValue - bValue;
}
}

View File

@ -33,7 +33,7 @@
} }
} }
::ng-deep .mat-paginator-container { :host ::ng-deep .mat-paginator-container {
flex-direction: row-reverse !important; flex-direction: row-reverse !important;
justify-content: space-between !important; justify-content: space-between !important;
background-color: #f6f6f6; background-color: #f6f6f6;
@ -41,25 +41,25 @@
min-height: 30px !important; min-height: 30px !important;
} }
::ng-deep .mat-paginator-page-size { :host ::ng-deep .mat-paginator-page-size {
height: 43px; height: 43px;
} }
::ng-deep .mat-paginator-range-label { :host ::ng-deep .mat-paginator-range-label {
margin: 15px 32px 0 24px !important; margin: 15px 32px 0 24px !important;
} }
::ng-deep .mat-paginator-range-actions { :host ::ng-deep .mat-paginator-range-actions {
width: 55% !important; width: 55% !important;
min-height: 43px !important; min-height: 43px !important;
justify-content: space-between; justify-content: space-between;
} }
::ng-deep .mat-paginator-navigation-previous { :host ::ng-deep .mat-paginator-navigation-previous {
margin-left: auto !important; margin-left: auto !important;
} }
::ng-deep .mat-icon-button { :host ::ng-deep .mat-icon-button {
height: 30px !important; height: 30px !important;
font-size: 12px !important; font-size: 12px !important;
} }

View File

@ -76,11 +76,11 @@
} }
} }
::ng-deep .mat-form-field-wrapper { :host ::ng-deep .mat-form-field-wrapper {
background-color: white !important; background-color: white !important;
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }
::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix { :host ::ng-deep .mat-form-field-appearance-outline .mat-form-field-infix {
padding: 0.3rem 0rem 0.6rem 0rem !important; padding: 0.3rem 0rem 0.6rem 0rem !important;
} }

View File

@ -59,7 +59,7 @@
} }
} }
::ng-deep .mat-paginator-container { :host ::ng-deep .mat-paginator-container {
// flex-direction: row-reverse !important; // flex-direction: row-reverse !important;
// justify-content: space-between !important; // justify-content: space-between !important;
// height: 30px; // height: 30px;

View File

@ -399,24 +399,24 @@ input[type="text"] {
margin-left: 40px; margin-left: 40px;
} }
::ng-deep .mat-tab-group.mat-primary .mat-ink-bar, :host ::ng-deep .mat-tab-group.mat-primary .mat-ink-bar,
.mat-tab-nav-bar.mat-primary .mat-ink-bar { .mat-tab-nav-bar.mat-primary .mat-ink-bar {
background: #129d99; background: #129d99;
height: 5px; height: 5px;
} }
::ng-deep .mat-tab-label { :host ::ng-deep .mat-tab-label {
min-width: auto !important; min-width: auto !important;
background-color: transparent; background-color: transparent;
} }
::ng-deep .mat-tab-label.mat-tab-label-active { :host ::ng-deep .mat-tab-label.mat-tab-label-active {
min-width: auto !important; min-width: auto !important;
background-color: transparent; background-color: transparent;
font-weight: 700; font-weight: 700;
} }
::ng-deep .mat-form-field-wrapper { :host ::ng-deep .mat-form-field-wrapper {
background-color: white !important; background-color: white !important;
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }

View File

@ -165,7 +165,7 @@
</div> </div>
</div> </div>
</div> </div>
<div *ngIf="allRecentActivities && allRecentActivities.length > 0 && allRecentActivities.length >= startIndex + pageSize" class="d-flex justify-content-center"> <div *ngIf="allRecentActivities && allRecentActivities.length > 0 && (allRecentActivities.length >= startIndex + pageSize) && hasMoreActivity" class="d-flex justify-content-center">
<button type="button" class="btn-load-more" (click)="loadMore()">{{'GENERAL.ACTIONS.LOAD-MORE' | translate}}</button> <button type="button" class="btn-load-more" (click)="loadMore()">{{'GENERAL.ACTIONS.LOAD-MORE' | translate}}</button>
</div> </div>
</div> </div>

View File

@ -62,6 +62,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
datasetOffset: number = 0; datasetOffset: number = 0;
pageSize: number = 5; pageSize: number = 5;
dmpFormGroup: FormGroup; dmpFormGroup: FormGroup;
hasMoreActivity:boolean = true;
public formGroup = new FormBuilder().group({ public formGroup = new FormBuilder().group({
like: new FormControl(), like: new FormControl(),
order: new FormControl() order: new FormControl()
@ -605,6 +606,10 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
} }
refresh(): void { refresh(): void {
this.hasMoreActivity = true;
this.datasetOffset = 0;
this.dmpOffset = 0;
const fields: Array<string> = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value]; const fields: Array<string> = [((this.formGroup.get('order').value === 'status') || (this.formGroup.get('order').value === 'label') ? '+' : "-") + this.formGroup.get('order').value];
// const fields: Array<string> = ["-modified"]; // const fields: Array<string> = ["-modified"];
this.startIndex = 0; this.startIndex = 0;
@ -623,6 +628,8 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
this.dmpOffset = this.dmpOffset + 1; this.dmpOffset = this.dmpOffset + 1;
} }
}); });
if(response.length< this.pageSize) {this.hasMoreActivity = false;}
this.totalCountRecentEdited.emit(this.allRecentActivities.length); this.totalCountRecentEdited.emit(this.allRecentActivities.length);
}); });
} }
@ -636,7 +643,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
request.criteria.order = this.formGroup.get("order").value; request.criteria.order = this.formGroup.get("order").value;
this.dashboardService.getRecentActivity(request).pipe(takeUntil(this._destroyed)).subscribe(result => { this.dashboardService.getRecentActivity(request).pipe(takeUntil(this._destroyed)).subscribe(result => {
if (!result) { return []; } if (!result) { this.hasMoreActivity = false; return []; }
result.forEach(recentActivity => { result.forEach(recentActivity => {
if (recentActivity.type === RecentActivityType.Dataset) { if (recentActivity.type === RecentActivityType.Dataset) {
this.datasetOffset = this.datasetOffset + 1; this.datasetOffset = this.datasetOffset + 1;
@ -644,6 +651,8 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn
this.dmpOffset = this.dmpOffset + 1; this.dmpOffset = this.dmpOffset + 1;
} }
}); });
if(result.length<this.pageSize) this.hasMoreActivity = false;
// this.allRecentActivities = this.allRecentActivities.concat(result); // this.allRecentActivities = this.allRecentActivities.concat(result);
this.allRecentActivities = this.allRecentActivities.length > 0 ? this.mergeTwoSortedLists(this.allRecentActivities, result, this.formGroup.get('order').value) : result; this.allRecentActivities = this.allRecentActivities.length > 0 ? this.mergeTwoSortedLists(this.allRecentActivities, result, this.formGroup.get('order').value) : result;
this.totalCountRecentEdited.emit(this.allRecentActivities.length); this.totalCountRecentEdited.emit(this.allRecentActivities.length);

View File

@ -50,11 +50,11 @@
<div class="stepper-title">{{'DMP-EDITOR.STEPPER.USER-GUIDE' | translate}}</div> <div class="stepper-title">{{'DMP-EDITOR.STEPPER.USER-GUIDE' | translate}}</div>
<div class="stepper-options" id="stepper-options"> <div class="stepper-options" id="stepper-options">
<div class="col stepper-list"> <div class="col stepper-list">
<div (click)="changeStep(0)" *ngIf="!datasetInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0}">0. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (2)</div> <div (click)="changeStep(0)" *ngIf="!datasetInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0, 'text-danger':hintErrors}">0. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (2)</div>
<div (click)="changeStep(0)" *ngIf="datasetInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0}">0. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (<mat-icon class="done-icon">done</mat-icon>)</div> <div (click)="changeStep(0)" *ngIf="datasetInfoValid()" class="main-info" [ngClass]="{'active': this.step === 0}">0. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (<mat-icon class="done-icon">done</mat-icon>)</div>
<div class="row toc-pane-container" #boundary (click)="changeStep(1)"> <div class="row toc-pane-container" #boundary (click)="changeStep(1)">
<div #spacer></div> <div #spacer></div>
<table-of-contents class="toc-pane-container" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)"></table-of-contents> <table-of-contents [selectedFieldsetId]="fieldsetIdWithFocus" #table0fContents [showErrors]="showtocentriesErrors" [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hasFocus]="step === 1" [formGroup]="formGroup" *ngIf="formGroup && formGroup.get('datasetProfileDefinition')" [links]="links" [boundary]="boundary" [spacer]="spacer" [isActive]="step !== 0" stickyThing (stepFound)="onStepFound($event)" (currentLinks)="getLinks($event)" [visibilityRules]="formGroup.get('datasetProfileDefinition').get('rules').value"></table-of-contents>
</div> </div>
</div> </div>
</div> </div>
@ -81,14 +81,25 @@
</div> </div>
<div class="col-auto form" id="dataset-editor-form"> <div class="col-auto form" id="dataset-editor-form">
<app-dataset-editor-component [hidden]="this.step !== 0" [formGroup]="formGroup" [dmpId]="formGroup.get('dmp').value.id" [availableProfiles]="formGroup.get('dmp').value.profiles" (formChanged)="formChanged()"></app-dataset-editor-component> <app-dataset-editor-component [hidden]="this.step !== 0" [formGroup]="formGroup" [dmpId]="formGroup.get('dmp').value.id" [availableProfiles]="formGroup.get('dmp').value.profiles" (formChanged)="formChanged()"></app-dataset-editor-component>
<app-dataset-description [hidden]="this.step === 0" *ngIf="formGroup && formGroup.get('datasetProfileDefinition')" [form]="this.formGroup.get('datasetProfileDefinition')" [visibilityRules]="formGroup.get('datasetProfileDefinition').get('rules').value" [datasetProfileId]="formGroup.get('profile').value" [linkToScroll]="linkToScroll"></app-dataset-description> <app-dataset-description [TOCENTRY_ID_PREFIX]="TOCENTRY_ID_PREFIX" [hidden]="this.step === 0" *ngIf="formGroup && formGroup.get('datasetProfileDefinition')" [form]="this.formGroup.get('datasetProfileDefinition')" [visibilityRules]="formGroup.get('datasetProfileDefinition').get('rules').value" [datasetProfileId]="formGroup.get('profile').value" [linkToScroll]="linkToScroll" (fieldsetFocusChange)="fieldsetIdWithFocus = $event"></app-dataset-description>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
<!-- <mat-slide-toggle [(ngModel)]="showtocentriesErrors">
</mat-slide-toggle> -->
<!-- <div class="row">
<div class="col-12">
<button (click)="printForm()">Print form</button>
</div>
<div class="col-12">
<button (click)="printFormValue()">Print form value</button>
</div>
</div> -->
<!-- <div class="main-content"> <!-- <div class="main-content">
<div class="container-fluid"> <div class="container-fluid">

View File

@ -277,6 +277,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: calc(100vh - 246px); height: calc(100vh - 246px);
// max-width: 366px;
} }
.stepper-options { .stepper-options {
@ -316,6 +317,8 @@
.stepper-list { .stepper-list {
.toc-pane-container { .toc-pane-container {
// padding-left: 0.2rem;
// overflow-x: hidden;
span { span {
text-align: left; text-align: left;
font-weight: 400; font-weight: 400;

View File

@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, ViewChild } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms'; import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar'; import { MatSnackBar } from '@angular/material/snack-bar';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
@ -23,7 +23,7 @@ import { DatasetWizardEditorModel } from '@app/ui/dataset/dataset-wizard/dataset
import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item'; import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-item';
import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent'; import { IBreadCrumbComponent } from '@app/ui/misc/breadcrumb/definition/IBreadCrumbComponent';
import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model'; import { DatasetDescriptionFormEditorModel } from '@app/ui/misc/dataset-description-form/dataset-description-form.model';
import { Link, LinkToScroll } from '@app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents'; import { Link, LinkToScroll, TableOfContents } from '@app/ui/misc/dataset-description-form/tableOfContentsMaterial/table-of-contents';
import { BaseComponent } from '@common/base/base.component'; import { BaseComponent } from '@common/base/base.component';
import { FormService } from '@common/forms/form-service'; import { FormService } from '@common/forms/form-service';
import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component'; import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component';
@ -45,6 +45,7 @@ import { SaveType } from '@app/core/common/enum/save-type';
import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard'; import { DatasetWizardModel } from '@app/core/model/dataset/dataset-wizard';
import { MatomoService } from '@app/core/services/matomo/matomo-service'; import { MatomoService } from '@app/core/services/matomo/matomo-service';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { ToCEntry, ToCEntryType } from '@app/ui/misc/dataset-description-form/dataset-description.component';
@Component({ @Component({
selector: 'app-dataset-wizard-component', selector: 'app-dataset-wizard-component',
@ -89,6 +90,13 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
scrollTop: number; scrollTop: number;
tocScrollTop: number; tocScrollTop: number;
links: Link[] = []; links: Link[] = [];
//the table seraches for elements to scroll on page with id (TOCENTRY_ID_PREFIX+fieldsetId<Tocentry>)
TOCENTRY_ID_PREFIX="TocEntRy";
showtocentriesErrors = false;
@ViewChild('table0fContents', {static: false}) table0fContents: TableOfContents;
hintErrors: boolean = false;
fieldsetIdWithFocus:string;
constructor( constructor(
private datasetWizardService: DatasetWizardService, private datasetWizardService: DatasetWizardService,
@ -565,16 +573,124 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
error => this.onCallbackError(error)); error => this.onCallbackError(error));
} }
private _getErrorMessage(formControl: AbstractControl, name: string): string[] {
const errors: string[] = [];
Object.keys(formControl.errors).forEach(key => {
if (key === 'required') { errors.push(this.language.instant(name + ": " + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED'))); }
// if (key === 'required') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + this.getPlaceHolder(formControl) + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.REQUIRED')); }
else if (key === 'email') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.EMAIL')); }
else if (key === 'min') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.MIN-VALUE', { 'min': formControl.getError('min').min })); }
else if (key === 'max') { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.MAX-VALUE', { 'max': formControl.getError('max').max })); }
else { errors.push(this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.THIS-FIELD') + ' "' + name + '" ' + this.language.instant('GENERAL.FORM-VALIDATION-DISPLAY-DIALOG.HAS-ERROR') + ', ' + formControl.errors[key].message); }
});
return errors;
}
private _getPlaceHolder(formControl: any): string {
if (formControl.nativeElement.localName === 'input' || formControl.nativeElement.localName === 'textarea') {
return formControl.nativeElement.getAttribute('placeholder');
} else if (formControl.nativeElement.localName === 'mat-select') {
return formControl.nativeElement.getAttribute('aria-label');
} else if (formControl.nativeElement.localName === 'app-single-auto-complete') {
return (Array.from(formControl.nativeElement.firstChild.children).filter((x: any) => x.localName === 'input')[0] as any).getAttribute('placeholder');
} else if (formControl.nativeElement.localName === 'app-multiple-auto-complete') {
return (Array.from(formControl.nativeElement.firstChild.children).filter((x: any) => x.localName === 'input')[0] as any).getAttribute('placeholder');
}
}
private _buildSemiFormErrorMessages(): string[]{//not including datasetProfileDefinition
const errmess: string[] = [];
Object.keys(this.formGroup.controls).forEach(controlName=>{
if(controlName != 'datasetProfileDefinition' && this.formGroup.get(controlName).invalid){
errmess.push(...this._buildErrorMessagesForAbstractControl(this.formGroup.get(controlName), controlName));
}
})
return errmess;
}
// takes as an input an abstract control and gets its error messages[]
private _buildErrorMessagesForAbstractControl(aControl: AbstractControl, controlName: string):string[]{
const errmess:string[] = [];
if(aControl.invalid){
if(aControl.errors){
//check if has placeholder
if( (<any>aControl).nativeElement !== undefined && (<any>aControl).nativeElement !== null){
const placeholder = this._getPlaceHolder(aControl);
if(placeholder){
controlName = placeholder;
}
}
const errorMessage = this._getErrorMessage(aControl, controlName);
errmess.push(...errorMessage);
}
/*in case the aControl is FormControl then the it should have provided its error messages above.
No need to check case of FormControl below*/
if(aControl instanceof FormGroup){
const fg = aControl as FormGroup;
//check children
Object.keys(fg.controls).forEach(controlName=>{
errmess.push(...this._buildErrorMessagesForAbstractControl(fg.get(controlName), controlName));
});
}else if(aControl instanceof FormArray){
const fa = aControl as FormArray;
fa.controls.forEach((control,index)=>{
errmess.push(... this._buildErrorMessagesForAbstractControl(control, `${controlName} --> ${index+1}`));
});
}
}
return errmess;
}
save(saveType?: SaveType) { save(saveType?: SaveType) {
this.formService.touchAllFormFields(this.formGroup);
Object.keys(this.formGroup.controls).forEach(controlName=>{
if(controlName == 'datasetProfileDefinition'){
return;
}
this.formService.touchAllFormFields(this.formGroup.get(controlName));
})
// this.formService.touchAllFormFields(this.formGroup);
if (!this.isSemiFormValid(this.formGroup)) { if (!this.isSemiFormValid(this.formGroup)) {
this.showValidationErrorsDialog(); //build messages
const errorMessages = this._buildSemiFormErrorMessages();
this.showValidationErrorsDialog(undefined, errorMessages);
this.hintErrors = true;
return; return;
} }
this.submit(saveType); this.submit(saveType);
} }
private showValidationErrorsDialog(projectOnly?: boolean) { private showValidationErrorsDialog(projectOnly?: boolean, errmess?: string[]) {
if(errmess){
const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, {
disableClose: true,
autoFocus: false,
restoreFocus: false,
data: {
errorMessages:errmess,
projectOnly: projectOnly
},
});
}else{
const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, { const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, {
disableClose: true, disableClose: true,
autoFocus: false, autoFocus: false,
@ -586,6 +702,8 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
}); });
} }
}
hasReversableStatus(): boolean { hasReversableStatus(): boolean {
if (this.formGroup.get('dmp').value) { if (this.formGroup.get('dmp').value) {
return (this.formGroup.get('dmp').value.status == DmpStatus.Draft && this.formGroup.get('status').value == DatasetStatus.Finalized); return (this.formGroup.get('dmp').value.status == DmpStatus.Draft && this.formGroup.get('status').value == DatasetStatus.Finalized);
@ -886,18 +1004,30 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
} }
public changeStep(index: number, dataset?: FormControl) { public changeStep(index: number, dataset?: FormControl) {
this.step = index; if(this.step != index){ //view is changing
this.resetScroll(); this.resetScroll();
} }
this.step = index;
}
public nextStep() { public nextStep() {
this.step = this.step < this.maxStep ? this.step + 1 : this.step; if(this.step < this.maxStep){//view is changing
if(this.step === 0 && this.table0fContents){
this.table0fContents.seekToFirstElement();
}
this.step++;
this.resetScroll(); this.resetScroll();
} }
// this.step = this.step < this.maxStep ? this.step + 1 : this.step;
}
public previousStep() { public previousStep() {
this.step = this.step !== 0 ? this.step - 1 : this.step; if(this.step > 0){
this.resetScroll(); this.resetScroll();
this.step--;
}
// this.step = this.step !== 0 ? this.step - 1 : this.step;
} }
private resetScroll() { private resetScroll() {
@ -911,11 +1041,17 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
discardChanges() { discardChanges() {
this.isDiscarded = true; this.isDiscarded = true;
this.hasChanges = false; this.hasChanges = false;
this.hintErrors = false;
if (this.isNew) { if (this.isNew) {
Object.keys(this.formGroup['controls']).forEach((key: string) => { Object.keys(this.formGroup['controls']).forEach((key: string) => {
if (key !== 'dmp') { if (key !== 'dmp' && (key!== 'profile')) {
if(key === 'datasetProfileDefinition'){
this.formGroup.get(key).patchValue(this.datasetProfileDefinitionModel.buildForm().getRawValue);
}else{
this.formGroup.get(key).reset(); this.formGroup.get(key).reset();
} }
}
}); });
} else { } else {
this.formGroup.patchValue(JSON.parse(JSON.stringify(this.formGroupRawValue))); this.formGroup.patchValue(JSON.parse(JSON.stringify(this.formGroupRawValue)));
@ -938,4 +1074,140 @@ export class DatasetWizardComponent extends BaseComponent implements OnInit, IBr
getLinks(currentLinks: Link[]) { getLinks(currentLinks: Link[]) {
this.links = currentLinks; this.links = currentLinks;
} }
printForm(){
console.log(this.formGroup);
}
printFormValue(){
console.log(this.formGroup.value);
}
// tocentries;
// this.tocentries = this.getTocEntries(this.formGroup.get('datasetProfileDefinition')); //TODO
// get tocentries(){
// const form = this.formGroup.get('datasetProfileDefinition')
// if(!form) return null;
// return this.getTocEntries(this.formGroup.get('datasetProfileDefinition'));
// }
// private _buildRecursively(form: FormGroup,whatAmI:ToCEntryType):ToCEntry{
// if(!form) return null;
// switch(whatAmI){
// case ToCEntryType.Section:
// const sections = form.get('sections') as FormArray;
// const fieldsets = form.get('compositeFields') as FormArray;
// const tempResult:ToCEntry[] = [];
// if(sections &&sections.length){
// sections.controls.forEach(section=>{
// tempResult.push(this._buildRecursively(section as FormGroup, ToCEntryType.Section));
// });
// }else if(fieldsets && fieldsets.length){
// fieldsets.controls.forEach(fieldset=>{
// tempResult.push(this._buildRecursively(fieldset as FormGroup, ToCEntryType.FieldSet));
// });
// }
// return {
// form: form,
// id: form.get('id').value,
// label: form.get('title').value,
// numbering: '',
// subEntries:tempResult,
// subEntriesType: sections &&sections.length? ToCEntryType.Section: ToCEntryType.FieldSet,
// type: ToCEntryType.Section,
// ordinal: form.get('ordinal').value
// }
// case ToCEntryType.FieldSet:
// return {
// form: form,
// label:form.get('title').value,
// id: form.get('id').value,
// numbering:'s',
// subEntries:[],
// subEntriesType: ToCEntryType.Field,
// type: ToCEntryType.FieldSet,
// ordinal: form.get('ordinal').value
// }
// }
// }
// private _sortByOrdinal(tocentries: ToCEntry[]){
// if(!tocentries || !tocentries.length) return;
// tocentries.sort(this._customCompare);
// tocentries.forEach(entry=>{
// this._sortByOrdinal(entry.subEntries);
// });
// }
// private _customCompare(a,b){
// return a.ordinal - b.ordinal;
// }
// private _calculateNumbering(tocentries: ToCEntry[], depth:number[] = []){
// if(!tocentries || !tocentries.length){
// return;
// }
// let prefixNumbering = depth.length? depth.join('.'): '';
// if(depth.length) prefixNumbering = prefixNumbering+".";
// tocentries.forEach((entry,i)=>{
// entry.numbering = prefixNumbering + (i+1);
// this._calculateNumbering(entry.subEntries, [...depth, i+1])
// });
// }
// getTocEntries(form): ToCEntry[] {
// if (form == null) { return []; }
// const result: ToCEntry[] = [];
// //build parent pages
// (form.get('pages') as FormArray).controls.forEach((pageElement, i) => {
// result.push({
// id: i+'id',
// label: pageElement.get('title').value,
// type: ToCEntryType.Page,
// form: pageElement,
// numbering: (i + 1).toString(),
// subEntriesType: ToCEntryType.Section,
// subEntries:[],
// ordinal: pageElement.get('ordinal').value
// } as ToCEntry)
// });
// result.forEach((entry,i)=>{
// const sections = entry.form.get('sections') as FormArray;
// sections.controls.forEach(section=>{
// const tempResults = this._buildRecursively(section as FormGroup,ToCEntryType.Section);
// entry.subEntries.push(tempResults);
// });
// });
// this._sortByOrdinal(result);
// //calculate numbering
// this._calculateNumbering(result);
// return result;
// }
} }

View File

@ -1,4 +1,5 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { FormattingModule } from '@app/core/formatting.module';
import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module'; import { AutoCompleteModule } from '@app/library/auto-complete/auto-complete.module';
import { ExportMethodDialogModule } from '@app/library/export-method-dialog/export-method-dialog.module'; import { ExportMethodDialogModule } from '@app/library/export-method-dialog/export-method-dialog.module';
import { UrlListingModule } from '@app/library/url-listing/url-listing.module'; import { UrlListingModule } from '@app/library/url-listing/url-listing.module';
@ -22,14 +23,10 @@ import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-
import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module'; import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module';
import { CommonUiModule } from '@common/ui/common-ui.module'; import { CommonUiModule } from '@common/ui/common-ui.module';
import { AngularStickyThingsModule } from '@w11k/angular-sticky-things'; import { AngularStickyThingsModule } from '@w11k/angular-sticky-things';
import { DatasetCopyDialogModule } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.module';
import { DatasetOverviewModule } from './overview/dataset-overview.module';
import { DatasetCriteriaDialogComponent } from './listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component';
import { DmpEditorComponent } from '../dmp/editor/dmp-editor.component';
import { DatasetEditorDetailsComponent } from '../dmp/editor/dataset-editor-details/dataset-editor-details.component';
import { DatasetEditorDetailsModule } from '../dmp/editor/dataset-editor-details/dataset-editor-details.module';
import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module'; import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module';
import { FormattingModule } from '@app/core/formatting.module'; import { DatasetCopyDialogModule } from './dataset-wizard/dataset-copy-dialogue/dataset-copy-dialogue.module';
import { DatasetCriteriaDialogComponent } from './listing/criteria/dataset-criteria-dialogue/dataset-criteria-dialog.component';
import { DatasetOverviewModule } from './overview/dataset-overview.module';
@NgModule({ @NgModule({
imports: [ imports: [
@ -77,7 +74,10 @@ import { FormattingModule } from '@app/core/formatting.module';
DatasetExternalDataRepositoryDialogEditorComponent, DatasetExternalDataRepositoryDialogEditorComponent,
DatasetExternalDatasetDialogEditorComponent, DatasetExternalDatasetDialogEditorComponent,
DatasetExternalRegistryDialogEditorComponent, DatasetExternalRegistryDialogEditorComponent,
DatasetExternalServiceDialogEditorComponent DatasetExternalServiceDialogEditorComponent,
DatasetEditorComponent,
DatasetDescriptionFormModule
] ]
}) })
export class DatasetModule { } export class DatasetModule { }

Some files were not shown because too many files have changed in this diff Show More