Merge branch 'ui-redesign' of gitlab.eudat.eu:dmp/OpenAIRE-EUDAT-DMP-service-pilot into ui-redesign
This commit is contained in:
commit
6a10c26c67
|
@ -137,7 +137,7 @@ public class DashBoardManager {
|
||||||
|
|
||||||
List<Integer> roles = new LinkedList<>();
|
List<Integer> roles = new LinkedList<>();
|
||||||
List<Dmp> finalDmps = dmps;
|
List<Dmp> finalDmps = dmps;
|
||||||
CompletableFuture dmpFuture = dataManagementPlanRepository.getAuthenticated(dmps != null ? dataManagementPlanRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDmps.stream().map(Dmp::getId).collect(Collectors.toList()))) : dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria), principal.getId(), roles).countAsync()
|
CompletableFuture dmpFuture = dataManagementPlanRepository.getAuthenticated(dmps != null ? dataManagementPlanRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDmps.stream().map(Dmp::getId).collect(Collectors.toList()))) : dataManagementPlanRepository.getWithCriteria(dataManagementPlanCriteria), principal.getId(), roles).distinct().countAsync()
|
||||||
.whenComplete((dmpsStats, throwable) -> statistics.setTotalDataManagementPlanCount(dmpsStats));
|
.whenComplete((dmpsStats, throwable) -> statistics.setTotalDataManagementPlanCount(dmpsStats));
|
||||||
List<eu.eudat.elastic.entities.Dataset> finalDatasets = datasets;
|
List<eu.eudat.elastic.entities.Dataset> finalDatasets = datasets;
|
||||||
CompletableFuture datasetFuture = datasetRepository.getAuthenticated(datasets != null ? datasetRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDatasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList()))) : datasetRepository.getWithCriteria(datasetCriteria), user, roles).countAsync()
|
CompletableFuture datasetFuture = datasetRepository.getAuthenticated(datasets != null ? datasetRepository.asQueryable().where((builder, root) -> root.get("id").in(finalDatasets.stream().map(x -> UUID.fromString(x.getId())).collect(Collectors.toList()))) : datasetRepository.getWithCriteria(datasetCriteria), user, roles).countAsync()
|
||||||
|
|
|
@ -189,7 +189,7 @@ public class DataManagementPlanManager {
|
||||||
.whenComplete((resultList, throwable) -> dataTable.setData(resultList));
|
.whenComplete((resultList, throwable) -> dataTable.setData(resultList));
|
||||||
}
|
}
|
||||||
|
|
||||||
CompletableFuture countFuture = authItems.countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count));
|
CompletableFuture countFuture = authItems.distinct().countAsync().whenComplete((count, throwable) -> dataTable.setTotalCount(count));
|
||||||
CompletableFuture.allOf(itemsFuture, countFuture).join();
|
CompletableFuture.allOf(itemsFuture, countFuture).join();
|
||||||
return dataTable;
|
return dataTable;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.eudat.models.rda.mapper;
|
||||||
import eu.eudat.data.entities.*;
|
import eu.eudat.data.entities.*;
|
||||||
import eu.eudat.logic.services.ApiContext;
|
import eu.eudat.logic.services.ApiContext;
|
||||||
import eu.eudat.logic.utilities.helpers.StreamDistinctBy;
|
import eu.eudat.logic.utilities.helpers.StreamDistinctBy;
|
||||||
|
import eu.eudat.models.rda.Cost;
|
||||||
import eu.eudat.models.rda.Dmp;
|
import eu.eudat.models.rda.Dmp;
|
||||||
import eu.eudat.models.rda.DmpId;
|
import eu.eudat.models.rda.DmpId;
|
||||||
import net.minidev.json.JSONObject;
|
import net.minidev.json.JSONObject;
|
||||||
|
@ -43,16 +44,34 @@ public class DmpRDAMapper {
|
||||||
|
|
||||||
Map<String, Object> extraProperties = new org.json.JSONObject(dmp.getExtraProperties()).toMap();
|
Map<String, Object> extraProperties = new org.json.JSONObject(dmp.getExtraProperties()).toMap();
|
||||||
if (!extraProperties.isEmpty()) {
|
if (!extraProperties.isEmpty()) {
|
||||||
|
if (extraProperties.get("language") != null) {
|
||||||
rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(extraProperties.get("language").toString()));
|
rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(extraProperties.get("language").toString()));
|
||||||
}
|
}
|
||||||
|
if (extraProperties.get("costs") != null) {
|
||||||
|
rda.setCost(new ArrayList<>());
|
||||||
|
((List) extraProperties.get("costs")).forEach(costl -> {
|
||||||
|
Cost cost = new Cost();
|
||||||
|
Map<String, Object> code = new org.json.JSONObject((String) ((Map) costl).get("code")).toMap();
|
||||||
|
cost.setCurrencyCode(Cost.CurrencyCode.fromValue((String) code.get("value")));
|
||||||
|
cost.setDescription((String) ((Map) costl).get("description"));
|
||||||
|
cost.setTitle((String) ((Map) costl).get("title"));
|
||||||
|
cost.setValue(((Integer) ((Map) costl).get("value")).doubleValue());
|
||||||
|
rda.getCost().add(cost);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (extraProperties.get("contact") != null) {
|
||||||
|
UserInfo contact = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(UUID.fromString((String)extraProperties.get("contact")));
|
||||||
|
rda.setContact(ContactRDAMapper.toRDA(contact));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
UserInfo creator;
|
/*UserInfo creator;
|
||||||
if (dmp.getCreator() != null) {
|
if (dmp.getCreator() != null) {
|
||||||
creator = dmp.getCreator();
|
creator = dmp.getCreator();
|
||||||
} else {
|
} else {
|
||||||
creator = dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).map(UserDMP::getUser).findFirst().orElse(new UserInfo());
|
creator = dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).map(UserDMP::getUser).findFirst().orElse(new UserInfo());
|
||||||
}
|
}
|
||||||
rda.setContact(ContactRDAMapper.toRDA(creator));
|
rda.setContact(ContactRDAMapper.toRDA(creator));*/
|
||||||
rda.setContributor(new ArrayList<>());
|
rda.setContributor(new ArrayList<>());
|
||||||
if (dmp.getResearchers() != null && !dmp.getResearchers().isEmpty()) {
|
if (dmp.getResearchers() != null && !dmp.getResearchers().isEmpty()) {
|
||||||
rda.getContributor().addAll(dmp.getResearchers().stream().map(ContributorRDAMapper::toRDA).collect(Collectors.toList()));
|
rda.getContributor().addAll(dmp.getResearchers().stream().map(ContributorRDAMapper::toRDA).collect(Collectors.toList()));
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
|
import { ValidationContext } from '@common/forms/validation/validation-context';
|
||||||
|
|
||||||
|
export interface CostModel {
|
||||||
|
code: string;
|
||||||
|
description: string;
|
||||||
|
title: string;
|
||||||
|
value: number;
|
||||||
|
}
|
|
@ -32,6 +32,8 @@ import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-
|
||||||
import { CommonUiModule } from '@common/ui/common-ui.module';
|
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||||
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
|
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
|
||||||
import { AddOrganizationComponent } from './editor/add-organization/add-organization.component';
|
import { AddOrganizationComponent } from './editor/add-organization/add-organization.component';
|
||||||
|
import { AddCostComponent } from './editor/cost-editor/add-cost/add-cost.component';
|
||||||
|
import { CostListingComponent } from './editor/cost-editor/cost-listing/cost-listing.component';
|
||||||
import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dialog.component';
|
import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dialog.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -71,7 +73,10 @@ import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dial
|
||||||
DatasetsTabComponent,
|
DatasetsTabComponent,
|
||||||
DmpCloneComponent,
|
DmpCloneComponent,
|
||||||
AddOrganizationComponent,
|
AddOrganizationComponent,
|
||||||
DmpCriteriaDialogComponent
|
DmpCriteriaDialogComponent,
|
||||||
|
AddOrganizationComponent,
|
||||||
|
AddCostComponent,
|
||||||
|
CostListingComponent
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
DmpInvitationDialogComponent,
|
DmpInvitationDialogComponent,
|
||||||
|
@ -80,7 +85,9 @@ import { DmpCriteriaDialogComponent } from './listing/criteria/dmp-criteria-dial
|
||||||
DmpFinalizeDialogComponent,
|
DmpFinalizeDialogComponent,
|
||||||
DmpUploadDialogue,
|
DmpUploadDialogue,
|
||||||
AddOrganizationComponent,
|
AddOrganizationComponent,
|
||||||
DmpCriteriaDialogComponent
|
DmpCriteriaDialogComponent,
|
||||||
|
AddOrganizationComponent,
|
||||||
|
AddCostComponent
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class DmpModule { }
|
export class DmpModule { }
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<form *ngIf="formGroup" [formGroup]="formGroup">
|
||||||
|
<h1 mat-dialog-title>{{'ADDEDITCOST-EDITOR.ADD-TITLE' | translate}}</h1>
|
||||||
|
<div mat-dialog-content class="row">
|
||||||
|
<mat-form-field class="col-12">
|
||||||
|
<app-single-auto-complete [formControl]="formGroup.get('code')" placeholder="{{'ADDEDITCOST-EDITOR.CODE' | translate}}" [configuration]="currencyAutoCompleteConfiguration">
|
||||||
|
</app-single-auto-complete>
|
||||||
|
<mat-error *ngIf="formGroup.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="col-12">
|
||||||
|
<input matInput formControlName="description" placeholder="{{'ADDEDITCOST-EDITOR.DESCRIPTION' | translate}}">
|
||||||
|
<mat-error *ngIf="formGroup.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="col-12">
|
||||||
|
<input matInput formControlName="title" placeholder="{{'ADDEDITCOST-EDITOR.TITLE' | translate}}" required>
|
||||||
|
<mat-error *ngIf="formGroup.get('title').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field class="col-12">
|
||||||
|
<input matInput formControlName="value" placeholder="{{'ADDEDITCOST-EDITOR.VALUE' | translate}}" type="number">
|
||||||
|
<mat-error *ngIf="formGroup.get('value').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="ml-auto col-auto"><button mat-raised-button mat-dialog-close type="button">{{'ADDEDITCOST-EDITOR.ACTIONS.CANCEL' | translate}}</button></div>
|
||||||
|
<div class="col-auto"><button mat-raised-button [disabled]="!isFormValid()" color="primary" (click)="addCost()" type="button">{{'ADDEDITCOST-EDITOR.ACTIONS.SAVE' | translate}}</button></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||||
|
import { ExternalResearcherService } from '@app/core/services/external-sources/researcher/external-researcher.service';
|
||||||
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { CostEditorModel } from './add-cost.model';
|
||||||
|
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { LocalFetchModel } from '@app/core/model/local-fetch/local-fetch.model';
|
||||||
|
import { CurrencyService } from '@app/core/services/currency/currency.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-add-cost-component',
|
||||||
|
templateUrl: 'add-cost.component.html',
|
||||||
|
})
|
||||||
|
export class AddCostComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
|
public formGroup: FormGroup;
|
||||||
|
|
||||||
|
currencyAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
|
||||||
|
filterFn: this.searchCurrency.bind(this),
|
||||||
|
initialItems: () => this.searchCurrency(''),
|
||||||
|
displayFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||||
|
titleFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||||
|
valueAssign: (item) => JSON.stringify(item)
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private externalResearcherService: ExternalResearcherService,
|
||||||
|
public dialogRef: MatDialogRef<AddCostComponent>,
|
||||||
|
private currencyService: CurrencyService,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: any
|
||||||
|
) { super(); }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
const cost = new CostEditorModel();
|
||||||
|
this.formGroup = cost.buildForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
send(value: any) {
|
||||||
|
this.externalResearcherService.createResearcher(this.formGroup.value)
|
||||||
|
.pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
null, null, () => this.dialogRef.close()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
addCost() {
|
||||||
|
this.dialogRef.close(this.formGroup.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
isFormValid() {
|
||||||
|
return this.formGroup.valid;
|
||||||
|
}
|
||||||
|
|
||||||
|
searchCurrency(like: string): Observable<LocalFetchModel[]> {
|
||||||
|
return this.currencyService.get(like);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
import { ResearcherModel } from '@app/core/model/researcher/researcher';
|
||||||
|
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';
|
||||||
|
import { OrganizationModel } from '@app/core/model/organisation/organization';
|
||||||
|
import { CostModel } from '@app/core/model/dmp/cost';
|
||||||
|
|
||||||
|
export class CostEditorModel implements CostModel{
|
||||||
|
public code: string;
|
||||||
|
public description: string;
|
||||||
|
public title: string;
|
||||||
|
public value: number;
|
||||||
|
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
|
||||||
|
|
||||||
|
fromModel(item: CostModel): CostEditorModel {
|
||||||
|
this.code = item.code;
|
||||||
|
this.description = item.description;
|
||||||
|
this.title = item.title;
|
||||||
|
this.value = item.value;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
|
||||||
|
if (context == null) { context = this.createValidationContext(); }
|
||||||
|
const formGroup = new FormBuilder().group({
|
||||||
|
code: [{ value: this.code, disabled: disabled }, context.getValidation('code').validators],
|
||||||
|
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
|
||||||
|
title: [{ value: this.title, disabled: disabled }, context.getValidation('title').validators],
|
||||||
|
value: [{ value: this.value, disabled: disabled }, context.getValidation('value').validators]
|
||||||
|
});
|
||||||
|
|
||||||
|
return formGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
createValidationContext(): ValidationContext {
|
||||||
|
const baseContext: ValidationContext = new ValidationContext();
|
||||||
|
baseContext.validation.push({ key: 'code', validators: [] });
|
||||||
|
baseContext.validation.push({ key: 'description', validators: [] });
|
||||||
|
baseContext.validation.push({ key: 'title', validators: [BackendErrorValidator(this.validationErrorModel, 'title')] });
|
||||||
|
baseContext.validation.push({ key: 'value', validators: [] });
|
||||||
|
return baseContext;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
<mat-card class="row listing-container">
|
||||||
|
|
||||||
|
<ng-template #costTemplate let-cost let-i="index">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-auto">
|
||||||
|
<mat-form-field>
|
||||||
|
<app-single-auto-complete [formControl]="cost.get('code')" placeholder="{{'ADDEDITCOST-EDITOR.CODE' | translate}}" [configuration]="currencyAutoCompleteConfiguration"></app-single-auto-complete>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="{{'ADDEDITCOST-EDITOR.DESCRIPTION' | translate}}" type="text" [formControl]="cost.get('description')">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="{{'ADDEDITCOST-EDITOR.TITLE' | translate}}" type="text" [formControl]="cost.get('title')">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<mat-form-field>
|
||||||
|
<input matInput placeholder="{{'ADDEDITCOST-EDITOR.VALUE' | translate}}" type="text" [formControl]="cost.get('value')">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="row"*ngIf="cost.disabled">
|
||||||
|
<div class=" ml-auto col-auto"><button type="button" mat-raised-button color="primary" (click)="switchEditMode(i)">Edit</button></div>
|
||||||
|
<div class="col-auto"><button type="button" mat-raised-button color="red" (click)="removeCost(i)">Delete</button></div>
|
||||||
|
</div>
|
||||||
|
<div class="row"*ngIf="!cost.disabled">
|
||||||
|
<div class=" ml-auto col-auto" *ngIf="!cost.disabled"><button type="button" mat-raised-button color="primary" (click)="switchEditMode(i)">Save</button></div>
|
||||||
|
<div class="col-auto" *ngIf="!cost.disabled"><button type="button" mat-raised-button (click)="revertEdits(i)">Cancel</button></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
<mat-card class="col-12 cost-element" *ngFor="let cost of form['controls']; let i = index">
|
||||||
|
<ng-container *ngTemplateOutlet="costTemplate; context: { $implicit: cost, index: i }">
|
||||||
|
</ng-container>
|
||||||
|
</mat-card>
|
||||||
|
</mat-card>
|
|
@ -0,0 +1,10 @@
|
||||||
|
.listing-container {
|
||||||
|
height: fit-content;
|
||||||
|
width: fit-content;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cost-element {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
|
import { FormArray, FormControl } from '@angular/forms';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { CostModel } from '@app/core/model/dmp/cost';
|
||||||
|
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
|
||||||
|
import { CurrencyService } from '@app/core/services/currency/currency.service';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { LocalFetchModel } from '@app/core/model/local-fetch/local-fetch.model';
|
||||||
|
import { CostEditorModel } from '../add-cost/add-cost.model';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-cost-listing',
|
||||||
|
templateUrl: './cost-listing.component.html',
|
||||||
|
styleUrls: ['./cost-listing.component.scss']
|
||||||
|
})
|
||||||
|
export class CostListingComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() form: FormArray;
|
||||||
|
|
||||||
|
private cost: CostEditorModel[] = [];
|
||||||
|
|
||||||
|
currencyAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
|
||||||
|
filterFn: this.searchCurrency.bind(this),
|
||||||
|
initialItems: () => this.searchCurrency(''),
|
||||||
|
displayFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||||
|
titleFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
|
||||||
|
valueAssign: (item) => JSON.stringify(item)
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private currencyService: CurrencyService,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
searchCurrency(like: string): Observable<LocalFetchModel[]> {
|
||||||
|
return this.currencyService.get(like);
|
||||||
|
}
|
||||||
|
|
||||||
|
switchEditMode(event: number) {
|
||||||
|
const control = this.form.at(event);
|
||||||
|
if (control.disabled) {
|
||||||
|
this.cost[event] = control.value;
|
||||||
|
control.enable();
|
||||||
|
} else {
|
||||||
|
control.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCost(event: number) {
|
||||||
|
this.form.removeAt(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
revertEdits(event: number) {
|
||||||
|
this.form.at(event).setValue(this.cost[event]);
|
||||||
|
this.form.at(event).disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,30 +1,53 @@
|
||||||
import { ValidationContext } from '@common/forms/validation/validation-context';
|
import { ValidationContext } from '@common/forms/validation/validation-context';
|
||||||
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||||||
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
|
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
|
||||||
|
import { CostModel } from '@app/core/model/dmp/cost';
|
||||||
|
import { isNullOrUndefined } from 'util';
|
||||||
|
import { CostEditorModel } from '../cost-editor/add-cost/add-cost.model';
|
||||||
|
|
||||||
export class ExtraPropertiesFormModel {
|
export class ExtraPropertiesFormModel {
|
||||||
public language: string;
|
public language: string;
|
||||||
public license: string;
|
public license: string;
|
||||||
public visible: boolean;
|
public visible: boolean;
|
||||||
public publicDate: Date;
|
public publicDate: Date;
|
||||||
|
public contact: string;
|
||||||
|
public costs: CostEditorModel[] = [];
|
||||||
|
|
||||||
fromModel(item: any): ExtraPropertiesFormModel {
|
fromModel(item: any): ExtraPropertiesFormModel {
|
||||||
this.language = item.language;
|
this.language = item.language;
|
||||||
this.license = item.license;
|
this.license = item.license;
|
||||||
this.visible = item.visible;
|
this.visible = item.visible;
|
||||||
this.publicDate = item.publicDate;
|
this.publicDate = item.publicDate;
|
||||||
|
this.contact = item.contact;
|
||||||
|
if (!isNullOrUndefined(item.costs)) {
|
||||||
|
(<any[]>item.costs).forEach(element => {
|
||||||
|
this.costs.push(new CostEditorModel().fromModel(element));
|
||||||
|
});
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
|
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
|
||||||
if (context == null) { context = this.createValidationContext(); }
|
if (context == null) { context = this.createValidationContext(); }
|
||||||
|
const formBuilder = new FormBuilder();
|
||||||
const formGroup = new FormBuilder().group({
|
const formGroup = new FormBuilder().group({
|
||||||
language: [{ value: this.language, disabled: disabled }, context.getValidation('language').validators],
|
language: [{ value: this.language, disabled: disabled }, context.getValidation('language').validators],
|
||||||
license: [{ value: this.license, disabled: disabled }, context.getValidation('license').validators],
|
license: [{ value: this.license, disabled: disabled }, context.getValidation('license').validators],
|
||||||
visible: [{ value: this.visible, disabled: disabled }, context.getValidation('visible').validators],
|
visible: [{ value: this.visible, disabled: disabled }, context.getValidation('visible').validators],
|
||||||
publicDate: [{ value: this.publicDate, disabled: disabled }, context.getValidation('publicDate').validators]
|
publicDate: [{ value: this.publicDate, disabled: disabled }, context.getValidation('publicDate').validators],
|
||||||
|
contact: [{ value: this.contact, disabled: disabled }, context.getValidation('contact').validators],
|
||||||
|
// costs: [{ value: this.costs, disabled: disabled }, context.getValidation('costs').validators]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const costArray = new Array<FormGroup>();
|
||||||
|
//if (this.externalDatasets && this.externalDatasets.length > 0) {
|
||||||
|
this.costs.forEach(item => {
|
||||||
|
costArray.push(item.buildForm(context.getValidation('costs').descendantValidations, true));
|
||||||
|
});
|
||||||
|
// } else {
|
||||||
|
// //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled));
|
||||||
|
// }
|
||||||
|
formGroup.addControl('costs', formBuilder.array(costArray));
|
||||||
return formGroup;
|
return formGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +57,8 @@ export class ExtraPropertiesFormModel {
|
||||||
baseContext.validation.push({ key: 'license', validators: [] });
|
baseContext.validation.push({ key: 'license', validators: [] });
|
||||||
baseContext.validation.push({ key: 'visible', validators: [] });
|
baseContext.validation.push({ key: 'visible', validators: [] });
|
||||||
baseContext.validation.push({ key: 'publicDate', validators: [] });
|
baseContext.validation.push({ key: 'publicDate', validators: [] });
|
||||||
|
baseContext.validation.push({ key: 'contact', validators: [] });
|
||||||
|
baseContext.validation.push({ key: 'costs', validators: [] });
|
||||||
return baseContext;
|
return baseContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
<app-single-auto-complete [formControl]="formGroup.get('extraProperties').get('license')" placeholder="{{'DMP-EDITOR.FIELDS.LICENSE' | translate}}" [configuration]="licenseAutoCompleteConfiguration">
|
<app-single-auto-complete [formControl]="formGroup.get('extraProperties').get('license')" placeholder="{{'DMP-EDITOR.FIELDS.LICENSE' | translate}}" [configuration]="licenseAutoCompleteConfiguration">
|
||||||
</app-single-auto-complete>
|
</app-single-auto-complete>
|
||||||
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('backendError')">
|
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('backendError')">
|
||||||
{{formGroup.get('extraProperties').get('language').getError('backendError').message}}</mat-error>
|
{{formGroup.get('extraProperties').get('license').getError('backendError').message}}</mat-error>
|
||||||
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('required')">
|
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('required')">
|
||||||
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
@ -117,13 +117,36 @@
|
||||||
<input matInput [matDatepicker]="picker" [formControl]="formGroup.get('extraProperties').get('publicDate')" placeholder="{{'DMP-EDITOR.FIELDS.PUBLICATION' | translate}}">
|
<input matInput [matDatepicker]="picker" [formControl]="formGroup.get('extraProperties').get('publicDate')" placeholder="{{'DMP-EDITOR.FIELDS.PUBLICATION' | translate}}">
|
||||||
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
|
||||||
<mat-datepicker #picker></mat-datepicker>
|
<mat-datepicker #picker></mat-datepicker>
|
||||||
<mat-error *ngIf="formGroup.get('extraProperties').get('visible').hasError('backendError')">
|
<mat-error *ngIf="formGroup.get('extraProperties').get('publicDate').hasError('backendError')">
|
||||||
{{formGroup.get('extraProperties').get('visible').getError('backendError').message}}</mat-error>
|
{{formGroup.get('extraProperties').get('publicDate').getError('backendError').message}}</mat-error>
|
||||||
<mat-error *ngIf="formGroup.get('extraProperties').get('visible').hasError('required')">
|
<mat-error *ngIf="formGroup.get('extraProperties').get('publicDate').hasError('required')">
|
||||||
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<!-- <h4 mat-subheader class="col-12">{{'DMP-EDITOR.FIELDS.PROFILE' | translate}}</h4> -->
|
<!-- <h4 mat-subheader class="col-12">{{'DMP-EDITOR.FIELDS.PROFILE' | translate}}</h4> -->
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row pt-3">
|
||||||
|
<mat-form-field class="col-sm-12 col-md-8">
|
||||||
|
<!-- <app-multiple-auto-complete [formControl]="formGroup.get('extraProperties').get('language')" placeholder="{{'DMP-EDITOR.FIELDS.RESEARCHERS' | translate}}" [configuration]="researchersAutoCompleteConfiguration">
|
||||||
|
</app-multiple-auto-complete> -->
|
||||||
|
<mat-select [formControl]="formGroup.get('extraProperties').get('contact')" placeholder="{{'DMP-EDITOR.FIELDS.CONTACT' | translate}}">
|
||||||
|
<mat-option *ngFor="let vis of getAssociates()" [value]="vis.id">
|
||||||
|
{{vis.name | translate}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error *ngIf="formGroup.get('extraProperties').get('contact').hasError('backendError')">
|
||||||
|
{{formGroup.get('extraProperties').get('contact').getError('backendError').message}}</mat-error>
|
||||||
|
<mat-error *ngIf="formGroup.get('extraProperties').get('contact').hasError('required')">
|
||||||
|
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
<!-- <h4 mat-subheader class="col-12">{{'DMP-EDITOR.FIELDS.PROFILE' | translate}}</h4> -->
|
||||||
|
</div>
|
||||||
|
<div class="row pt-3">
|
||||||
|
<mat-label class="col-12 cost-placeholder">Costs</mat-label>
|
||||||
|
<app-cost-listing class="col-12" [form] = "formGroup.get('extraProperties').get('costs')"></app-cost-listing>
|
||||||
|
<button class="col-12 cost-add" matSuffix class="input-btn" type="button" (click)="addCost($event)">
|
||||||
|
<mat-icon class="icon-btn">add_circle</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="row pt-2">
|
<div class="row pt-2">
|
||||||
<mat-form-field class="col-sm-12 col-md-8">
|
<mat-form-field class="col-sm-12 col-md-8">
|
||||||
<app-single-auto-complete [required]="false" [formControl]="formGroup.get('profile')" placeholder="{{'DMP-EDITOR.FIELDS.TEMPLATE' | translate}}" [configuration]="dmpProfileAutoCompleteConfiguration">
|
<app-single-auto-complete [required]="false" [formControl]="formGroup.get('profile')" placeholder="{{'DMP-EDITOR.FIELDS.TEMPLATE' | translate}}" [configuration]="dmpProfileAutoCompleteConfiguration">
|
||||||
|
|
|
@ -37,3 +37,11 @@
|
||||||
::ng-deep .mat-form-field-appearance-legacy .mat-form-field-wrapper {
|
::ng-deep .mat-form-field-appearance-legacy .mat-form-field-wrapper {
|
||||||
padding-bottom: 1.25em;
|
padding-bottom: 1.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cost-placeholder {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cost-add {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { FormGroup } from '@angular/forms';
|
import { FormGroup, FormArray } from '@angular/forms';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
|
import { DataTableRequest } from '@app/core/model/data-table/data-table-request';
|
||||||
import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile';
|
import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile';
|
||||||
|
@ -26,6 +26,8 @@ import { ConfigurationService } from '@app/core/services/configuration/configura
|
||||||
import { LanguageInfoService } from '@app/core/services/culture/language-info-service';
|
import { LanguageInfoService } from '@app/core/services/culture/language-info-service';
|
||||||
import { LanguageInfo } from '@app/core/model/language-info';
|
import { LanguageInfo } from '@app/core/model/language-info';
|
||||||
import { LicenseCriteria } from '@app/core/query/license/license-criteria';
|
import { LicenseCriteria } from '@app/core/query/license/license-criteria';
|
||||||
|
import { AddCostComponent } from '../cost-editor/add-cost/add-cost.component';
|
||||||
|
import { CostEditorModel } from '../cost-editor/add-cost/add-cost.model';
|
||||||
|
|
||||||
interface Visible {
|
interface Visible {
|
||||||
value: boolean;
|
value: boolean;
|
||||||
|
@ -253,4 +255,27 @@ export class GeneralTabComponent extends BaseComponent implements OnInit {
|
||||||
getLanguageInfos(): LanguageInfo[] {
|
getLanguageInfos(): LanguageInfo[] {
|
||||||
return this.languageInfoService.getLanguageInfoValues();
|
return this.languageInfoService.getLanguageInfoValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAssociates(): any[] {
|
||||||
|
let associates: any[] = [];
|
||||||
|
//associates = (this.formGroup.get('researchers').value as any[]);
|
||||||
|
associates = associates.concat(this.formGroup.get('associatedUsers').value);
|
||||||
|
return associates;
|
||||||
|
}
|
||||||
|
|
||||||
|
addCost(event: MouseEvent) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const dialogRef = this.dialog.open(AddCostComponent, {
|
||||||
|
data: this.formGroup.get('extraProperties').get('costs')
|
||||||
|
});
|
||||||
|
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
|
||||||
|
if (result) {
|
||||||
|
const costsArray = this.formGroup.get('extraProperties').get('costs').value || [];
|
||||||
|
costsArray.push(result);
|
||||||
|
let costeditModel: CostEditorModel = new CostEditorModel();
|
||||||
|
costeditModel = costeditModel.fromModel(result);
|
||||||
|
(<FormArray>this.formGroup.get('extraProperties').get('costs')).push(costeditModel.buildForm(null, true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,7 +756,8 @@
|
||||||
"LANGUAGE": "Language",
|
"LANGUAGE": "Language",
|
||||||
"LICENSE": "License",
|
"LICENSE": "License",
|
||||||
"VISIBILITY": "Visibility",
|
"VISIBILITY": "Visibility",
|
||||||
"PUBLICATION": "Publication Date"
|
"PUBLICATION": "Publication Date",
|
||||||
|
"CONTACT": "Contact"
|
||||||
},
|
},
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"GO-TO-GRANT": "Go To DMP Grant",
|
"GO-TO-GRANT": "Go To DMP Grant",
|
||||||
|
@ -1031,6 +1032,18 @@
|
||||||
"CANCEL": "Cancel"
|
"CANCEL": "Cancel"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ADDEDITCOST-EDITOR": {
|
||||||
|
"ADD-TITLE": "Add a Cost",
|
||||||
|
"EDIT-TITLE": "Edit the Cost",
|
||||||
|
"CODE": "Code",
|
||||||
|
"DESCRIPTION": "Description",
|
||||||
|
"TITLE": "Title",
|
||||||
|
"VALUE": "Value",
|
||||||
|
"ACTIONS": {
|
||||||
|
"SAVE": "Save",
|
||||||
|
"CANCEL": "Cancel"
|
||||||
|
}
|
||||||
|
},
|
||||||
"DMP-WIZARD": {
|
"DMP-WIZARD": {
|
||||||
"FIRST-STEP": {
|
"FIRST-STEP": {
|
||||||
"DMP": "DMP Editor",
|
"DMP": "DMP Editor",
|
||||||
|
|
Loading…
Reference in New Issue