add hasTemplates property to sections, it indicates if descriptions templates can be added in a section

This commit is contained in:
Bernaldo Mihasi 2023-09-11 08:59:47 +03:00
parent 4219d90039
commit bbe4975176
8 changed files with 429 additions and 407 deletions

View File

@ -20,6 +20,7 @@ public class Section implements XmlSerializable<Section> {
private String description;
private Integer ordinal;
private List<FieldModel> fields;
private Boolean hasTemplates;
private List<DescriptionTemplate> descriptionTemplates;
public UUID getId() {
@ -57,6 +58,13 @@ public class Section implements XmlSerializable<Section> {
this.fields = fields;
}
public Boolean getHasTemplates() {
return hasTemplates;
}
public void setHasTemplates(Boolean hasTemplates) {
this.hasTemplates = hasTemplates;
}
public List<DescriptionTemplate> getDescriptionTemplates() {
return descriptionTemplates;
}
@ -71,6 +79,7 @@ public class Section implements XmlSerializable<Section> {
rootElement.setAttribute("label", this.label);
rootElement.setAttribute("description", this.description);
rootElement.setAttribute("ordinal", String.valueOf(this.ordinal));
rootElement.setAttribute("hasTemplates", String.valueOf(this.hasTemplates));
List<FieldModel> temp = this.fields.stream().filter(f -> f.getCategory().equals(FieldCategory.SYSTEM)).collect(Collectors.toList());
List<SystemField> systemFieldsList = temp.stream().map(FieldModel::toSystemField).collect(Collectors.toList());
Element systemFields = doc.createElement("systemFields");
@ -100,6 +109,7 @@ public class Section implements XmlSerializable<Section> {
this.label = item.getAttribute("label");
this.description = item.getAttribute("description");
this.ordinal = Integer.valueOf(item.getAttribute("ordinal"));
this.hasTemplates = Boolean.valueOf(item.getAttribute("hasTemplates"));
this.fields = new LinkedList<>();
Element systemFields = (Element) XmlBuilder.getNodeFromListByTagName(item.getChildNodes(), "systemFields");
if (systemFields != null) {

View File

@ -12,8 +12,7 @@ public enum SystemFieldType {
GRANT(7),
PROJECT(8),
LICENSE(9),
ACCESS_RIGHTS(10),
DESCRIPTION_TEMPLATES(11);
ACCESS_RIGHTS(10);
private int type;
@ -49,8 +48,6 @@ public enum SystemFieldType {
return LICENSE;
case 10:
return ACCESS_RIGHTS;
case 11:
return DESCRIPTION_TEMPLATES;
default:
throw new RuntimeException("Unsupported System Field Type");
}

View File

@ -18,6 +18,7 @@ export interface SectionDmpBlueprint {
description: string;
ordinal: number;
fields: FieldInSection[];
hasTemplates: boolean;
descriptionTemplates?: DescriptionTemplatesInSection[];
}

View File

@ -11,6 +11,7 @@ import { DmpProfileCriteriaComponent } from './listing/criteria/dmp-profile-crit
import { DmpProfileListingComponent } from './listing/dmp-profile-listing.component';
import { NgxDropzoneModule } from "ngx-dropzone";
import { DragDropModule } from '@angular/cdk/drag-drop';
import { AutoCompleteModule } from "@app/library/auto-complete/auto-complete.module";
@NgModule({
imports: [
@ -20,7 +21,8 @@ import { DragDropModule } from '@angular/cdk/drag-drop';
ConfirmationDialogModule,
DmpProfileRoutingModule,
NgxDropzoneModule,
DragDropModule
DragDropModule,
AutoCompleteModule
],
declarations: [
DmpProfileEditorComponent,

View File

@ -1,5 +1,8 @@
import { FormBuilder, FormGroup } from "@angular/forms";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { DescriptionTemplatesInSection, DmpBlueprint, DmpBlueprintDefinition, FieldCategory, FieldInSection, SectionDmpBlueprint } from "@app/core/model/dmp/dmp-blueprint/dmp-blueprint";
import { BackendErrorValidator } from "@common/forms/validation/custom-validator";
import { ValidationErrorModel } from "@common/forms/validation/error-model/validation-error-model";
import { ValidationContext } from "@common/forms/validation/validation-context";
export class DmpBlueprintEditor {
public id: string;
@ -8,6 +11,7 @@ export class DmpBlueprintEditor {
public status: number;
public created: Date;
public modified: Date;
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
fromModel(item: DmpBlueprint): DmpBlueprintEditor {
this.id = item.id;
@ -19,18 +23,30 @@ export class DmpBlueprintEditor {
return this;
}
buildForm(): FormGroup {
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
if (context == null) { context = this.createValidationContext(); }
const formGroup = new FormBuilder().group({
id: [this.id],
label: [this.label],
status: [this.status],
created: [this.created],
modified: [this.modified]
id: [{ value: this.id, disabled: disabled }, context.getValidation('id')],
label: [{ value: this.label, disabled: disabled }, context.getValidation('label')],
status: [{ value: this.status, disabled: disabled }, context.getValidation('status')],
created: [{ value: this.created, disabled: disabled }, context.getValidation('created')],
modified: [{ value: this.modified, disabled: disabled }, context.getValidation('modified')],
});
formGroup.addControl('definition', this.definition.buildForm());
return formGroup;
}
createValidationContext(): ValidationContext {
const baseContext: ValidationContext = new ValidationContext();
baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
baseContext.validation.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] });
baseContext.validation.push({ key: 'definition', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'definition')] });
baseContext.validation.push({ key: 'created', validators: [] });
baseContext.validation.push({ key: 'modified', validators: [] });
return baseContext;
}
}
export class DmpBlueprintDefinitionEditor {
@ -61,7 +77,9 @@ export class SectionDmpBlueprintEditor {
public description: string;
public ordinal: number;
public fields: FieldInSectionEditor[] = new Array<FieldInSectionEditor>();
public hasTemplates: boolean;
public descriptionTemplates: DescriptionTemplatesInSectionEditor[] = new Array<DescriptionTemplatesInSectionEditor>();
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
fromModel(item: SectionDmpBlueprint): SectionDmpBlueprintEditor {
this.id = item.id;
@ -69,16 +87,19 @@ export class SectionDmpBlueprintEditor {
this.description = item.description;
this.ordinal = item.ordinal;
if (item.fields) { item.fields.map(x => this.fields.push(new FieldInSectionEditor().fromModel(x))); }
this.hasTemplates = item.hasTemplates;
if (item.descriptionTemplates) { item.descriptionTemplates.map(x => this.descriptionTemplates.push(new DescriptionTemplatesInSectionEditor().fromModel(x))); }
return this;
}
buildForm(): FormGroup {
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
if (context == null) { context = this.createValidationContext(); }
const formGroup = new FormBuilder().group({
id: [this.id],
label: [this.label],
description: [this.description],
ordinal: [this.ordinal]
id: [{ value: this.id, disabled: disabled }, context.getValidation('id')],
label: [{ value: this.label, disabled: disabled }, context.getValidation('label')],
description: [{ value: this.description, disabled: disabled }, context.getValidation('description')],
ordinal: [{ value: this.ordinal, disabled: disabled }, context.getValidation('ordinal')],
hasTemplates: [{ value: this.hasTemplates, disabled: disabled }, context.getValidation('hasTemplates')]
});
const formBuilder = new FormBuilder();
const fieldsFormArray = new Array<FormGroup>();
@ -95,6 +116,17 @@ export class SectionDmpBlueprintEditor {
formGroup.addControl('descriptionTemplates', formBuilder.array(descriptionTemplatesFormArray));
return formGroup;
}
createValidationContext(): ValidationContext {
const baseContext: ValidationContext = new ValidationContext();
baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] });
baseContext.validation.push({ key: 'ordinal', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'ordinal')] });
baseContext.validation.push({ key: 'hasTemplates', validators: [BackendErrorValidator(this.validationErrorModel, 'hasTemplates')] });
baseContext.validation.push({ key: 'descriptionTemplates', validators: [BackendErrorValidator(this.validationErrorModel, 'descriptionTemplates')] });
return baseContext;
}
}
export class FieldInSectionEditor {
@ -106,6 +138,7 @@ export class FieldInSectionEditor {
public description: string;
public required: boolean;
public ordinal: number;
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
fromModel(item: FieldInSection): FieldInSectionEditor {
this.id = item.id;
@ -119,19 +152,33 @@ export class FieldInSectionEditor {
return this;
}
buildForm(): FormGroup {
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
if (context == null) { context = this.createValidationContext(); }
const formGroup = new FormBuilder().group({
id: [this.id],
category: [this.category],
type: [this.type],
label: [this.label],
placeholder: [this.placeholder],
description: [this.description],
required: [this.required],
ordinal: [this.ordinal]
id: [{ value: this.id, disabled: disabled }, context.getValidation('id')],
category: [{ value: this.category, disabled: disabled }, context.getValidation('category')],
type: [{ value: this.type, disabled: disabled }, context.getValidation('type')],
label: [{ value: this.label, disabled: disabled }, context.getValidation('label')],
placeholder: [{ value: this.placeholder, disabled: disabled }, context.getValidation('placeholder')],
description: [{ value: this.description, disabled: disabled }, context.getValidation('description')],
required: [{ value: this.required, disabled: disabled }, context.getValidation('required')],
ordinal: [{ value: this.ordinal, disabled: disabled }, context.getValidation('ordinal')]
});
return formGroup;
}
createValidationContext(): ValidationContext {
const baseContext: ValidationContext = new ValidationContext();
baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
baseContext.validation.push({ key: 'category', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'category')] });
baseContext.validation.push({ key: 'type', validators: [BackendErrorValidator(this.validationErrorModel, 'type')] });
baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
baseContext.validation.push({ key: 'placeholder', validators: [BackendErrorValidator(this.validationErrorModel, 'placeholder')] });
baseContext.validation.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] });
baseContext.validation.push({ key: 'required', validators: [BackendErrorValidator(this.validationErrorModel, 'required')] });
baseContext.validation.push({ key: 'ordinal', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'ordinal')] });
return baseContext;
}
}
export class DescriptionTemplatesInSectionEditor {
@ -140,6 +187,7 @@ export class DescriptionTemplatesInSectionEditor {
public label: string;
public minMultiplicity: number;
public maxMultiplicity: number;
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
fromModel(item: DescriptionTemplatesInSection): DescriptionTemplatesInSectionEditor {
this.id = item.id;
@ -150,16 +198,27 @@ export class DescriptionTemplatesInSectionEditor {
return this;
}
buildForm(): FormGroup {
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
if (context == null) { context = this.createValidationContext(); }
const formGroup = new FormBuilder().group({
id: [this.id],
descriptionTemplateId: [this.descriptionTemplateId],
label: [this.label],
minMultiplicity: [this.minMultiplicity],
maxMultiplicity: [this.maxMultiplicity]
id: [{ value: this.id, disabled: disabled }, context.getValidation('id')],
descriptionTemplateId: [{ value: this.descriptionTemplateId, disabled: disabled }, context.getValidation('descriptionTemplateId')],
label: [{ value: this.label, disabled: disabled }, context.getValidation('label')],
minMultiplicity: [{ value: this.minMultiplicity, disabled: disabled }, context.getValidation('minMultiplicity')],
maxMultiplicity: [{ value: this.maxMultiplicity, disabled: disabled }, context.getValidation('maxMultiplicity')]
});
return formGroup;
}
createValidationContext(): ValidationContext {
const baseContext: ValidationContext = new ValidationContext();
baseContext.validation.push({ key: 'id', validators: [BackendErrorValidator(this.validationErrorModel, 'id')] });
baseContext.validation.push({ key: 'descriptionTemplateId', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'descriptionTemplateId')] });
baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] });
baseContext.validation.push({ key: 'minMultiplicity', validators: [BackendErrorValidator(this.validationErrorModel, 'minMultiplicity')] });
baseContext.validation.push({ key: 'maxMultiplicity', validators: [BackendErrorValidator(this.validationErrorModel, 'maxMultiplicity')] });
return baseContext;
}
}
// export class ExtraFieldsInSectionEditor {

View File

@ -18,10 +18,10 @@
</div>
<div *ngIf="formGroup.get('status').value!=1" class="col-auto">
<button mat-button class="finalize-btn" (click)="finalize()"
[disabled]="true" type="button">{{'DMP-PROFILE-EDITOR.ACTIONS.FINALIZE' | translate }}</button>
[disabled]="!this.isFormValid()" type="button">{{'DMP-PROFILE-EDITOR.ACTIONS.FINALIZE' | translate }}</button>
</div>
</div>
<form *ngIf="dmpBlueprintsFormGroup" (ngSubmit)="onSubmitTest()" [formGroup]="dmpBlueprintsFormGroup">
<form *ngIf="formGroup" (ngSubmit)="formSubmit()" [formGroup]="formGroup">
<mat-card style="padding: 2em;">
<!-- <mat-card-header>
<mat-card-title *ngIf="isNew">
@ -36,13 +36,14 @@
<mat-form-field class="col-lg-6" >
<mat-label>Name</mat-label>
<input matInput type="text" name="label" formControlName="label" required>
<mat-error *ngIf="dmpBlueprintsFormGroup.get('label').hasError('required')">
<mat-error *ngIf="formGroup.get('label').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<h4 class="col-12">Sections</h4>
<ng-container formGroupName="definition">
<div formArrayName="sections" style="width: 100%;" cdkDropList (cdkDropListDropped)="dropSections($event)">
<div *ngFor="let section of sectionsArray().controls; let sectionIndex=index;" class="section-input" cdkDrag>
<div *ngFor="let section of sectionsArray().controls; let sectionIndex=index;" class="section-input" cdkDrag [cdkDragDisabled]="viewOnly">
<ng-container [formGroupName]="sectionIndex">
<div class="col-12">
<div class="row">
@ -80,7 +81,7 @@
<div class="col-6">
<mat-form-field>
<mat-label>System fields</mat-label>
<mat-select multiple>
<mat-select multiple [value]="systemFieldListPerSection[0]">
<mat-option *ngFor="let f of fieldList" [disabled]="systemFieldDisabled(f.type, sectionIndex)" [value]="f.type" (click)="selectedFieldType(f.label, f.type, sectionIndex)">{{f.label}}</mat-option>
</mat-select>
<mat-error *ngIf="fieldsArray(sectionIndex).hasError('required')">
@ -88,7 +89,7 @@
</mat-form-field>
</div>
<div class="col-6">
<button mat-button class="action-btn" type="button" (click)="addExtraField(sectionIndex)">Add extra field</button>
<button mat-button class="action-btn" type="button" (click)="addExtraField(sectionIndex)" [disabled]="viewOnly">Add extra field</button>
<!-- <button mat-button class="action-btn" style="margin-left: 3%;" type="button" (click)="addExtraField(sectionIndex)">Add description templates</button> -->
</div>
</div>
@ -97,7 +98,7 @@
<div class="col-12">
<div formArrayName="fields" cdkDropList (cdkDropListDropped)="drop($event, sectionIndex)">
<div *ngFor="let field of fieldsArray(sectionIndex).controls; let fieldIndex=index;" cdkDrag>
<div *ngFor="let field of fieldsArray(sectionIndex).controls; let fieldIndex=index;" cdkDrag [cdkDragDisabled]="viewOnly">
<ng-container [formGroupName]="fieldIndex">
<div class="col-12" *ngIf="fieldsArray(sectionIndex).length > 0">
<div class="row">
@ -111,7 +112,7 @@
</div>
</div>
</div>
<ng-container *ngIf="field.get('category').value === 0">
<ng-container *ngIf="field.get('category').value === 0 || field.get('category').value === 'SYSTEM'">
<div class="col-2" >
<mat-form-field>
<mat-label>System Field</mat-label>
@ -121,7 +122,9 @@
<div class="col-2">
<mat-form-field>
<mat-label>Label</mat-label>
<input matInput type="text" name="label" formControlName="label">
<input matInput type="text" name="label" formControlName="label" required>
<mat-error *ngIf="field.get('label').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-2">
@ -139,13 +142,13 @@
<div class="centered-row-item col-1">
<mat-checkbox [disabled]="field.get('type').value === 0 || field.get('type').value === 1" formControlName="required">Required</mat-checkbox>
</div>
<div class="field-delete col-1" (click)="removeSystemFieldWithIndex(sectionIndex, fieldIndex)">
<div [hidden]="viewOnly" class="field-delete col-1" (click)="removeSystemFieldWithIndex(sectionIndex, fieldIndex)">
<mat-icon class="field-delete-icon">delete</mat-icon>
<span class="field-delete-text">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}}</span>
</div>
</ng-container>
<ng-container *ngIf="field.get('category').value === 1">
<ng-container *ngIf="field.get('category').value === 1 || field.get('category').value === 'EXTRA'">
<div class="col-2">
<mat-form-field>
<mat-label>Type</mat-label>
@ -154,24 +157,28 @@
{{getExtraFieldTypeValue(extraFieldType)}}
</mat-option>
</mat-select>
<mat-error *ngIf="field.get('type').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-2">
<mat-form-field>
<mat-label>Label</mat-label>
<input matInput type="text" name="label" formControlName="label" required>
<mat-error *ngIf="field.get('label').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
<div class="col-2">
<mat-form-field>
<mat-label>Placeholder</mat-label>
<input matInput type="text" name="placeholder" formControlName="placeholder" required>
<input matInput type="text" name="placeholder" formControlName="placolder">
</mat-form-field>
</div>
<div class="col-2">
<mat-form-field>
<mat-label>Description</mat-label>
<input matInput type="text" name="description" formControlName="description">
<input matInput type="text" name="description" forehmControlName="description">
</mat-form-field>
</div>
<div class="centered-row-item col-1">
@ -179,7 +186,7 @@
Required
</mat-checkbox>
</div>
<div class="field-delete col-1" (click)="removeExtraField(sectionIndex, fieldIndex)">
<div [hidden]="viewOnly" class="field-delete col-1" (click)="removeExtraField(sectionIndex, fieldIndex)">
<mat-icon class="field-delete-icon">delete</mat-icon>
<span class="field-delete-text">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}}</span>
</div>
@ -191,76 +198,70 @@
</div>
</div>
</div>
</div>
</div>
<div class="col-12">
<!-- <mat-form-field>
<mat-label>Description Templates</mat-label> -->
<app-multiple-auto-complete placeholder="Description Templates2" [hidePlaceholder]="true" required='false' [configuration]="profilesAutoCompleteConfiguration">
<div class="row">
<div class="col-12">
<mat-checkbox formControlName="hasTemplates">
Description Templates
</mat-checkbox>
</div>
</div>
</div>
<div class="col-12" *ngIf="section.get('hasTemplates').value == true">
<div class="row">
<div class="col-12">
<mat-form-field>
<mat-label>Description Templates</mat-label>
<app-multiple-auto-complete placeholder="Description Templates" [hidePlaceholder]="true" required='false' [configuration]="profilesAutoCompleteConfiguration" (optionRemoved)="onRemoveTemplate($event, sectionIndex)" (optionSelected)="onOptionSelected($event, sectionIndex)">
</app-multiple-auto-complete>
<!-- <button matSuffix class="input-btn" (click)="allAvailableProfiles($event)">
<mat-icon class="icon-btn">view_list</mat-icon>
</button> -->
<!-- </mat-form-field> -->
</mat-form-field>
</div>
</div>
</div>
</div>
<!-- <div class="col-12">
<div class="row">
<div class="col-12"> -->
<!-- <mat-form-field>
<mat-label>Description Templates</mat-label>
<mat-select (selectionChange)="addDescriptionTemplate($event, sectionIndex)" multiple>
<mat-option *ngFor="let descTemplate of descriptionsList">{{descTemplate}}</mat-option>
</mat-select>
</mat-form-field> -->
<!-- <mat-form-field>
<mat-label>Description Templates</mat-label>
<app-multiple-auto-complete placeholder="Description Templates2" [hidePlaceholder]="true" required='false' [formControl]="section.get('descriptionTemplates')" [configuration]="profilesAutoCompleteConfiguration" (optionRemoved)="onRemoveTemplate($event, sectionIndex)" (optionActionClicked)="onPreviewTemplate($event, sectionIndex)" (optionSelected)="onOptionSelected(sectionIndex)">
</app-multiple-auto-complete> -->
<!-- <button matSuffix class="input-btn" (click)="allAvailableProfiles($event)">
<mat-icon class="icon-btn">view_list</mat-icon>
</button> -->
<!-- </mat-form-field>
</div>
</div>
</div> -->
<!-- <ng-container formArrayName="descriptionTemplates">
<ng-container formArrayName="descriptionTemplates">
<div *ngFor="let descriptionTemplate of descriptionTemplatesArray(sectionIndex).controls; let j=index;" class="section-input" style="width: 100%;">
<ng-container [formGroupName]="j">
<div class="col-12" *ngIf="descriptionTemplatesArray(sectionIndex).length > 0">
<div class="row">
<div class="col-6">
<div class="col-4">
<mat-form-field>
<mat-label>Label</mat-label>
<input matInput type="text" name="name" formControlName="label">
<input matInput type="text" value="descriptionTemplate.get('label')" name="label" formControlName="label">
</mat-form-field>
</div>
<div class="col-3">
<div class="col-4">
<mat-form-field>
<mat-label>Min Multiplicity</mat-label>
<input matInput type="number" name="minMultiplicity" formControlName="minMultiplicity">
<input matInput type="number" min="0" name="minMultiplicity" formControlName="minMultiplicity">
</mat-form-field>
</div>
<div class="col-3">
<div class="col-4">
<mat-form-field>
<mat-label>Max Multiplicity</mat-label>
<input matInput type="number" name="maxMultiplicity" formControlName="maxMultiplicity">
<input matInput type="number" min="0" name="maxMultiplicity" formControlName="maxMultiplicity">
</mat-form-field>
</div>
</div>
</div>
</ng-container>
</div>
</ng-container> -->
</ng-container>
</mat-card>
<div class="col-1">
<div class="row">
<!-- <div class="col-auto dlt-section-btn">
<button mat-button class="action-btn" type="button" click="removeSection(sectionIndex)">Delete</button>
</div> -->
<div class="action-list-item col-auto dlt-section-btn" (click)="removeSection(sectionIndex)">
<div [hidden]="viewOnly" class="action-list-item col-auto dlt-section-btn" (click)="removeSection(sectionIndex)" [disabled]="viewOnly">
<mat-icon class="action-list-icon">delete</mat-icon>
<span class="action-list-text">{{'DATASET-PROFILE-EDITOR.STEPS.TOOLKIT.DELETE' | translate}}</span>
</div>
@ -269,23 +270,14 @@
</div>
</div>
</ng-container>
<!-- <div class="arrows mt-2">
<ul class="list-unstyled list-inline d-flex align-items-center">
<li *ngIf="canGoUp(i)" class="text-muted">
<mat-icon style="cursor: pointer;" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.MOVE-UP' | translate">keyboard_arrow_up</mat-icon>
</li>
<li *ngIf="canGoDown(i)" class="text-muted">
<mat-icon style="cursor: pointer;" [matTooltip]="'DATASET-PROFILE-EDITOR.ACTIONS.FIELD.MOVE-DOWN' | translate">keyboard_arrow_down</mat-icon>
</li>
</ul>
</div> -->
</div>
</div>
</ng-container>
<div class="col-12">
<div class="row">
<div class="col-auto">
<button mat-button class="action-btn" type="button" (click)="addSection()">Add section</button>
<button mat-button class="action-btn" type="button" (click)="addSection()" [disabled]="viewOnly">Add section</button>
</div>
</div>
</div>
@ -386,7 +378,7 @@
</div> -->
<div class="col-auto" *ngIf="!viewOnly">
<button mat-button class="action-btn" type="submit" [disabled]="!dmpBlueprintsFormGroup.valid">
<button mat-button class="action-btn" type="submit">
{{'DMP-PROFILE-EDITOR.ACTIONS.SAVE' | translate}}
</button>
</div>

View File

@ -1,5 +1,5 @@
import { AfterViewInit, Component } from '@angular/core';
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { DmpProfileFieldDataType } from '@app/core/common/enum/dmp-profile-field-type';
@ -34,9 +34,11 @@ import { AvailableProfilesComponent } from '@app/ui/dmp/editor/available-profile
import { DatasetPreviewDialogComponent } from '@app/ui/dmp/dataset-preview/dataset-preview-dialog.component';
import { CdkDragDrop, CdkDropList, CdkDrag, moveItemInArray } from '@angular/cdk/drag-drop';
import { DmpBlueprint, DmpBlueprintDefinition, ExtraFieldType, FieldCategory, SystemFieldType } from '@app/core/model/dmp/dmp-blueprint/dmp-blueprint';
import { DmpBlueprintEditor } from './dmp-blueprint-editor.model';
import { DescriptionTemplatesInSectionEditor, DmpBlueprintEditor, FieldInSectionEditor, SectionDmpBlueprintEditor } from './dmp-blueprint-editor.model';
import { Guid } from '@common/types/guid';
import { isNullOrUndefined } from '@app/utilities/enhancers/utils';
import { DmpBlueprintListing } from '@app/core/model/dmp/dmp-blueprint/dmp-blueprint-listing';
import { FormValidationErrorsDialogComponent } from '@common/forms/form-validation-errors-dialog/form-validation-errors-dialog.component';
@Component({
@ -73,6 +75,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
{label: 'Access Rights', type: SystemFieldType.ACCESS_RIGHTS}
];
selectedSystemFields: string[] = [];
systemFieldListPerSection: Array<Array<any>> = new Array();
constructor(
private dmpProfileService: DmpProfileService,
@ -112,12 +115,13 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
if (this.dmpProfileId != null) {
this.isNew = false;
this.dmpProfileService.getSingle(this.dmpProfileId).pipe(map(data => data as DmpProfile))
this.dmpProfileService.getSingleBlueprint(this.dmpProfileId).pipe(map(data => data as DmpBlueprint))
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmpProfileModel = new DmpProfileEditorModel().fromModel(data);
this.formGroup = this.dmpProfileModel.buildForm();
if (this.dmpProfileModel.status == DmpProfileStatus.Finalized) {
this.dmpBlueprintModel = new DmpBlueprintEditor().fromModel(data);
this.formGroup = this.dmpBlueprintModel.buildForm();
this.buildSystemFields();
if (this.dmpBlueprintModel.status == DmpProfileStatus.Finalized) {
this.formGroup.disable();
this.viewOnly = true
}
@ -133,6 +137,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
setTimeout(() => {
// this.formGroup = this.dmpProfileModel.buildForm();
// this.addField();
this.dmpBlueprintModel.status = DmpProfileStatus.Draft;
this.formGroup = this.dmpBlueprintModel.buildForm();
});
this.breadCrumbs = observableOf([{
@ -143,10 +148,20 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
}
});
this.initDmpBlueptintForm();
}
buildSystemFields(){
const sections = this.sectionsArray().controls.length;
for(let i = 0; i < sections; i++){
let systemFieldsInSection = new Array();
this.fieldsArray(i).controls.forEach((field) => {
if((field.get('category').value == FieldCategory.SYSTEM || field.get('category').value == 'SYSTEM')){
systemFieldsInSection.push(this.fieldList.find(f => f.type == field.get('type').value).label);
}
})
this.systemFieldListPerSection.push(systemFieldsInSection);
}
}
filterProfiles(value: string): Observable<DatasetProfileModel[]> {
const request = new DataTableRequest<DatasetProfileCriteria>(null, null, { fields: ['+label'] });
@ -156,33 +171,17 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
return this._service.searchDMPProfiles(request);
}
initDmpBlueptintForm(): void {
this.dmpBlueprintsFormGroup = this.fb.group({
label: this.fb.control(''),
sections: this.fb.array([])
});
}
sectionsArray(): FormArray {
return this.dmpBlueprintsFormGroup.get('sections') as FormArray;
}
initSection(ordinal: number): FormGroup {
return this.fb.group({
id: this.fb.control(Guid.create().toString()),
label: this.fb.control(''),
description: this.fb.control(''),
ordinal: this.fb.control(ordinal),
fields: this.fb.array([]),
//systemFields: this.fb.array([]),
descriptionTemplates: this.fb.control(''),
// this.fb.array([this.initDescriptionTemplate()]),
//extraFields: this.fb.array([])
});
//return this.dmpBlueprintsFormGroup.get('sections') as FormArray;
return this.formGroup.get('definition').get('sections') as FormArray;
}
addSection(): void {
this.sectionsArray().push(this.initSection(this.sectionsArray().length));
const section: SectionDmpBlueprintEditor = new SectionDmpBlueprintEditor();
section.id = Guid.create().toString();
section.ordinal = this.sectionsArray().length + 1;
section.hasTemplates = false;
this.sectionsArray().push(section.buildForm());
}
removeSection(sectionIndex: number): void {
@ -193,21 +192,16 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
return this.sectionsArray().at(sectionIndex).get('fields') as FormArray;
}
initField(fieldCategory: FieldCategory, fieldType?: number): FormGroup {
return this.fb.group({
id: this.fb.control(Guid.create().toString()),
category: this.fb.control(fieldCategory),
label: this.fb.control(''),
placeholder: this.fb.control(''),
description: this.fb.control(''),
type: (isNullOrUndefined(fieldType)) ? this.fb.control('') : this.fb.control(fieldType),
required: (!isNullOrUndefined(fieldType) && (fieldType == 0 || fieldType == 1)) ? this.fb.control(true) : this.fb.control(false),
ordinal: this.fb.control('')
});
}
addField(sectionIndex: number, fieldCategory: FieldCategory, fieldType?: number): void {
this.fieldsArray(sectionIndex).push(this.initField(fieldCategory, fieldType));
const field: FieldInSectionEditor = new FieldInSectionEditor();
field.id = Guid.create().toString();
field.ordinal = this.fieldsArray(sectionIndex).length + 1;
field.category = fieldCategory;
if(!isNullOrUndefined(fieldType)){
field.type = fieldType
}
field.required = (!isNullOrUndefined(fieldType) && (fieldType == 0 || fieldType == 1)) ? true : false;
this.fieldsArray(sectionIndex).push(field.buildForm());
}
removeField(sectionIndex: number, fieldIndex: number): void {
@ -231,7 +225,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
}
addSystemField(sectionIndex: number, systemField?: SystemFieldType): void {
this.fieldsArray(sectionIndex).push(this.initField(FieldCategory.SYSTEM, systemField));
this.addField(sectionIndex, FieldCategory.SYSTEM, systemField);
}
transfromEnumToString(type: SystemFieldType): string{
@ -255,7 +249,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
for (let s in this.sectionsArray().controls) {
if (i != sectionIndex) {
for (let f of this.fieldsArray(i).controls) {
if (f.get('category').value == FieldCategory.SYSTEM && f.get('type').value == systemField) {
if ((f.get('category').value == FieldCategory.SYSTEM || f.get('category').value == 'SYSTEM') && f.get('type').value == systemField) {
return true;
}
}
@ -272,7 +266,7 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
removeSystemField(sectionIndex: number, systemField: SystemFieldType): void {
let i = 0;
for(let f of this.fieldsArray(sectionIndex).controls){
if(f.get('category').value == FieldCategory.SYSTEM && f.get('type').value == systemField){
if((f.get('category').value == FieldCategory.SYSTEM || f.get('category').value == 'SYSTEM') && f.get('type').value == systemField){
this.fieldsArray(sectionIndex).removeAt(i);
return;
}
@ -284,15 +278,6 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
return this.sectionsArray().at(sectionIndex).get('descriptionTemplates') as FormArray;
}
initDescriptionTemplate(): FormGroup {
return this.fb.group({
descriptionTemplateId: this.fb.control(''),
label: this.fb.control(''),
minMultiplicity: this.fb.control(''),
maxMultiplicity: this.fb.control('')
});
}
addDescriptionTemplate(descriptionTemplate, sectionIndex: number): void {
this.descriptionTemplatesArray(sectionIndex).push(this.fb.group({
label: this.fb.control(descriptionTemplate.value)
@ -307,20 +292,8 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
return this.sectionsArray().at(sectionIndex).get('extraFields') as FormArray;
}
initExtraField(): FormGroup {
return this.fb.group({
id: this.fb.control(Guid.create().toString()),
label: this.fb.control(''),
placeholder: this.fb.control(''),
description: this.fb.control(''),
type: this.fb.control(''),
required: this.fb.control(false),
ordinal: this.fb.control('')
});
}
addExtraField(sectionIndex: number): void {
this.fieldsArray(sectionIndex).push(this.initField(FieldCategory.EXTRA));
this.addField(sectionIndex, FieldCategory.EXTRA);
}
removeExtraField(sectionIndex: number, fieldIndex: number): void {
@ -343,9 +316,6 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
}
}
onSubmitTest(): void {
}
drop(event: CdkDragDrop<string[]>, sectionIndex: number) {
moveItemInArray(this.fieldsArray(sectionIndex).controls, event.previousIndex, event.currentIndex);
moveItemInArray(this.fieldsArray(sectionIndex).value, event.previousIndex, event.currentIndex);
@ -371,25 +341,31 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
// this.dmpBlueprintsFormGroup.reset();
// }
canGoUp(index: number): boolean {
return index > 0;
}
canGoDown(index: number): boolean {
return index < (this.sectionsArray().length - 1);
}
onRemoveTemplate(event, sectionIndex: number) {
// let found = false;
// const profiles = this.descriptionTemplatesArray(sectionIndex).value;//this.formGroup.get('profiles').value;
// this.formGroup.get('datasets')['controls'].forEach(element => {
// if (element.get('profile').value.id === event.id) {
// found = true;
// this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-REMOVE-TEMPLATE'), SnackBarNotificationLevel.Success);
// }
const profiles = this.descriptionTemplatesArray(sectionIndex).controls;
const foundIndex = profiles.findIndex(profile => profile.get('descriptionTemplateId').value === event.id);
foundIndex !== -1 && this.descriptionTemplatesArray(sectionIndex).removeAt(foundIndex);
}
// onPreviewTemplate(event, sectionIndex: number) {
// const dialogRef = this.dialog.open(DatasetPreviewDialogComponent, {
// width: '590px',
// minHeight: '200px',
// restoreFocus: false,
// data: {
// template: event
// },
// panelClass: 'custom-modalbox'
// });
// if (found) {
// this.formGroup.get('profiles').setValue(profiles);
// dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
// if (result) {
// let profiles = this.sectionsArray().at(sectionIndex).get('descriptionTemplates').value;//this.formGroup.get('profiles').value;
// const profile: DescriptionTemplatesInSectionEditor = new DescriptionTemplatesInSectionEditor();
// profile.id = Guid.create().toString();
// profile.descriptionTemplateId = event.id;
// profile.label = event.label;
// profiles.push(profile.buildForm());
// this.sectionsArray().at(sectionIndex).get('descriptionTemplates').setValue(profiles);//this.formGroup.get('profiles').setValue(profiles);
// this.profilesAutoCompleteConfiguration = {
// filterFn: this.filterProfiles.bind(this),
// initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
@ -398,59 +374,25 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
// subtitleFn: (item) => item['description'],
// popupItemActionIcon: 'visibility'
// };
// }
}
// });
// }
onPreviewTemplate(event, sectionIndex: number) {
const dialogRef = this.dialog.open(DatasetPreviewDialogComponent, {
width: '590px',
minHeight: '200px',
restoreFocus: false,
data: {
template: event
},
panelClass: 'custom-modalbox'
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
let profiles = this.descriptionTemplatesArray(sectionIndex).value;//this.formGroup.get('profiles').value;
profiles.push(event);
this.descriptionTemplatesArray(sectionIndex).setValue(profiles);//this.formGroup.get('profiles').setValue(profiles);
this.profilesAutoCompleteConfiguration = {
filterFn: this.filterProfiles.bind(this),
initialItems: (excludedItems: any[]) => this.filterProfiles('').pipe(map(result => result.filter(resultItem => (excludedItems || []).map(x => x.id).indexOf(resultItem.id) === -1))),
displayFn: (item) => item['label'],
titleFn: (item) => item['label'],
subtitleFn: (item) => item['description'],
popupItemActionIcon: 'visibility'
};
}
});
}
onOptionSelected(sectionIndex: number){
try{
const profiles = this.descriptionTemplatesArray(sectionIndex).value as {id:string, label:string}[];//this.formGroup.get('profiles').value as {id:string, label:string}[];
const profileCounts: Map<String, number> = new Map<String, number>();
profiles.forEach((value) => profileCounts.set(value.id, (profileCounts.get(value.id) !== undefined ? profileCounts.get(value.id): 0 ) + 1));
const duplicateProfiles = profiles.filter((value) => {
let isOk = profileCounts.get(value.id) > 1;
if (isOk) {
profileCounts.set(value.id, 0);
}
return isOk;
});
duplicateProfiles.forEach((value) => profiles.splice(profiles.lastIndexOf(value), 1));
profiles.sort((a,b)=> a.label.localeCompare(b.label));
}
catch{
console.info('Could not sort Dataset Templates')
}
onOptionSelected(item, sectionIndex){
const profile: DescriptionTemplatesInSectionEditor = new DescriptionTemplatesInSectionEditor();
profile.id = Guid.create().toString();
profile.descriptionTemplateId = item.id;
profile.label = item.label;
this.descriptionTemplatesArray(sectionIndex).push(profile.buildForm());
}
formSubmit(): void {
this.formService.touchAllFormFields(this.formGroup);
if (!this.isFormValid()) { return; }
if(!this.hasDescriptionTemplates()) {
this.showValidationErrorsDialog(undefined, ["At least one section should have description templates."]);
return;
}
this.onSubmit();
}
@ -458,8 +400,27 @@ export class DmpProfileEditorComponent extends BaseComponent implements AfterVie
return this.formGroup.valid;
}
hasDescriptionTemplates(): boolean {
const dmpBlueprint: DmpBlueprint = this.formGroup.value;
return (dmpBlueprint.definition.sections.filter(s => s.hasTemplates == true).length > 0) ? true : false;
}
private showValidationErrorsDialog(projectOnly?: boolean, errmess?: string[]) {
const dialogRef = this.dialog.open(FormValidationErrorsDialogComponent, {
disableClose: true,
autoFocus: false,
restoreFocus: false,
data: {
errorMessages:errmess,
projectOnly: projectOnly
},
});
}
onSubmit(): void {
this.dmpProfileService.createDmp(this.formGroup.value)
this.dmpProfileService.createBlueprint(this.formGroup.value)
.pipe(takeUntil(this._destroyed))
.subscribe(
complete => this.onCallbackSuccess(),