From a7a8e3db3537ca99c1c3fe1559a13dfaab5271ca Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Wed, 1 Jul 2020 14:26:58 +0300 Subject: [PATCH 1/7] Add contact field and "add cost" dialog --- dmp-frontend/src/app/core/model/dmp/cost.ts | 9 +++ dmp-frontend/src/app/ui/dmp/dmp.module.ts | 9 ++- .../add-cost/add-cost.component.html | 28 +++++++++ .../add-cost/add-cost.component.ts | 60 +++++++++++++++++++ .../cost-editor/add-cost/add-cost.model.ts | 44 ++++++++++++++ .../extra-properties-form.model.ts | 14 ++++- .../general-tab/general-tab.component.html | 29 +++++++-- .../general-tab/general-tab.component.ts | 22 +++++++ dmp-frontend/src/assets/i18n/en.json | 15 ++++- 9 files changed, 222 insertions(+), 8 deletions(-) create mode 100644 dmp-frontend/src/app/core/model/dmp/cost.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.html create mode 100644 dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.model.ts diff --git a/dmp-frontend/src/app/core/model/dmp/cost.ts b/dmp-frontend/src/app/core/model/dmp/cost.ts new file mode 100644 index 000000000..ab432f02b --- /dev/null +++ b/dmp-frontend/src/app/core/model/dmp/cost.ts @@ -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; +} diff --git a/dmp-frontend/src/app/ui/dmp/dmp.module.ts b/dmp-frontend/src/app/ui/dmp/dmp.module.ts index d331894da..67a9a3f76 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp.module.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp.module.ts @@ -32,6 +32,8 @@ import { FormValidationErrorsDialogModule } from '@common/forms/form-validation- import { CommonUiModule } from '@common/ui/common-ui.module'; import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module'; 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'; @NgModule({ imports: [ @@ -69,7 +71,9 @@ import { AddOrganizationComponent } from './editor/add-organization/add-organiza GrantTabComponent, DatasetsTabComponent, DmpCloneComponent, - AddOrganizationComponent + AddOrganizationComponent, + AddCostComponent, + CostListingComponent ], entryComponents: [ DmpInvitationDialogComponent, @@ -77,7 +81,8 @@ import { AddOrganizationComponent } from './editor/add-organization/add-organiza AvailableProfilesComponent, DmpFinalizeDialogComponent, DmpUploadDialogue, - AddOrganizationComponent + AddOrganizationComponent, + AddCostComponent ] }) export class DmpModule { } diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.html b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.html new file mode 100644 index 000000000..fca4f3c07 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.html @@ -0,0 +1,28 @@ +
+

{{'ADDEDITCOST-EDITOR.ADD-TITLE' | translate}}

+
+ + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts new file mode 100644 index 000000000..e6f8d57e7 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts @@ -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) => typeof (item) == 'string' ? JSON.parse(item)['value'] : item.value + }; + + constructor( + private externalResearcherService: ExternalResearcherService, + public dialogRef: MatDialogRef, + 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 { + return this.currencyService.get(like); + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.model.ts b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.model.ts new file mode 100644 index 000000000..252e4950d --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.model.ts @@ -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; + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts index 89d32c5ce..5d4d4d0a9 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts @@ -1,18 +1,26 @@ import { ValidationContext } from '@common/forms/validation/validation-context'; import { FormGroup, FormBuilder, Validators } from '@angular/forms'; import { BackendErrorValidator } from '@common/forms/validation/custom-validator'; +import { CostModel } from '@app/core/model/dmp/cost'; +import { isNullOrUndefined } from 'util'; export class ExtraPropertiesFormModel { public language: string; public license: string; public visible: boolean; public publicDate: Date; + public contact: string; + public costs: CostModel[] = []; fromModel(item: any): ExtraPropertiesFormModel { this.language = item.language; this.license = item.license; this.visible = item.visible; this.publicDate = item.publicDate; + this.contact = item.contact; + if (!isNullOrUndefined(item.costs)) { + this.costs = item.costs; + } return this; } @@ -23,7 +31,9 @@ export class ExtraPropertiesFormModel { language: [{ value: this.language, disabled: disabled }, context.getValidation('language').validators], license: [{ value: this.license, disabled: disabled }, context.getValidation('license').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] }); return formGroup; } @@ -34,6 +44,8 @@ export class ExtraPropertiesFormModel { baseContext.validation.push({ key: 'license', validators: [] }); baseContext.validation.push({ key: 'visible', validators: [] }); baseContext.validation.push({ key: 'publicDate', validators: [] }); + baseContext.validation.push({ key: 'contact', validators: [] }); + baseContext.validation.push({ key: 'costs', validators: [] }); return baseContext; } diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html index ce433d868..5e18a75dd 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html @@ -88,7 +88,7 @@ - {{formGroup.get('extraProperties').get('language').getError('backendError').message}} + {{formGroup.get('extraProperties').get('license').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} @@ -117,13 +117,34 @@ - - {{formGroup.get('extraProperties').get('visible').getError('backendError').message}} - + + {{formGroup.get('extraProperties').get('publicDate').getError('backendError').message}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} +
+ + + + + {{vis.name | translate}} + + + + {{formGroup.get('extraProperties').get('contact').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + +
+
+ +
diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts index 0dee0573f..54387fa92 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts @@ -26,6 +26,7 @@ import { ConfigurationService } from '@app/core/services/configuration/configura import { LanguageInfoService } from '@app/core/services/culture/language-info-service'; import { LanguageInfo } from '@app/core/model/language-info'; import { LicenseCriteria } from '@app/core/query/license/license-criteria'; +import { AddCostComponent } from '../cost-editor/add-cost/add-cost.component'; interface Visible { value: boolean; @@ -253,4 +254,25 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { getLanguageInfos(): LanguageInfo[] { 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); + this.formGroup.get('extraProperties').get('costs').setValue(costsArray); + } + }); + } } diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 9c5ff334a..31a07273d 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -711,7 +711,8 @@ "LANGUAGE": "Language", "LICENSE": "License", "VISIBILITY": "Visibility", - "PUBLICATION": "Publication Date" + "PUBLICATION": "Publication Date", + "CONTACT": "Contact" }, "ACTIONS": { "GO-TO-GRANT": "Go To DMP Grant", @@ -986,6 +987,18 @@ "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": { "FIRST-STEP": { "DMP": "DMP Editor", From bfb9eaf87c1a330ced54296166ac1ab868683feb Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Wed, 1 Jul 2020 18:33:16 +0300 Subject: [PATCH 2/7] Add costs listing (wip) --- .../cost-listing/cost-listing.component.html | 32 ++++++++++++ .../cost-listing/cost-listing.component.scss | 10 ++++ .../cost-listing/cost-listing.component.ts | 51 +++++++++++++++++++ .../general-tab/general-tab.component.html | 10 ++-- .../general-tab/general-tab.component.scss | 4 ++ 5 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html create mode 100644 dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.scss create mode 100644 dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html new file mode 100644 index 000000000..1fb26780b --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html @@ -0,0 +1,32 @@ + + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+ + + + + +
diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.scss b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.scss new file mode 100644 index 000000000..52f45cc20 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.scss @@ -0,0 +1,10 @@ +.listing-container { + height: fit-content; + width: fit-content; + background-color: whitesmoke; +} + + +.cost-element { + margin-bottom: 1em; +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts new file mode 100644 index 000000000..1272e51c6 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts @@ -0,0 +1,51 @@ +import { Component, OnInit, Input } from '@angular/core'; +import { BaseComponent } from '@common/base/base.component'; +import { FormArray } 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'; + +@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; + + costs: CostModel[] = []; + + 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) => this.getValue(item) + }; + + constructor( + private currencyService: CurrencyService, + ) { + super(); + } + + ngOnInit() { + this.form.valueChanges.pipe(takeUntil(this._destroyed)).subscribe(value => { + this.costs = value; + }); + } + + searchCurrency(like: string): Observable { + return this.currencyService.get(like); +} + + getValue(item: any): any { + console.log(item); + return item; + } + +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html index 5e18a75dd..2d85e7ccc 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html @@ -140,10 +140,12 @@
-
- +
+ Costs + +
diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss index 05d8ae793..595aabb5c 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss @@ -37,3 +37,7 @@ ::ng-deep .mat-form-field-appearance-legacy .mat-form-field-wrapper { padding-bottom: 1.25em; } + +.cost-placeholder { + text-decoration: underline; +} From 747ad60fb1ff2639849e13d770d697cf54d1d906 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Thu, 2 Jul 2020 10:16:11 +0300 Subject: [PATCH 3/7] Update cost listing --- .../general-tab/extra-properties-form.model.ts | 17 ++++++++++++++--- .../editor/general-tab/general-tab.component.ts | 7 +++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts index 5d4d4d0a9..8124cc5d5 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts @@ -3,6 +3,7 @@ import { FormGroup, FormBuilder, Validators } from '@angular/forms'; 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 { public language: string; @@ -10,7 +11,7 @@ export class ExtraPropertiesFormModel { public visible: boolean; public publicDate: Date; public contact: string; - public costs: CostModel[] = []; + public costs: CostEditorModel[] = []; fromModel(item: any): ExtraPropertiesFormModel { this.language = item.language; @@ -26,15 +27,25 @@ export class ExtraPropertiesFormModel { buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { if (context == null) { context = this.createValidationContext(); } - + const formBuilder = new FormBuilder(); const formGroup = new FormBuilder().group({ language: [{ value: this.language, disabled: disabled }, context.getValidation('language').validators], license: [{ value: this.license, disabled: disabled }, context.getValidation('license').validators], visible: [{ value: this.visible, disabled: disabled }, context.getValidation('visible').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] + // costs: [{ value: this.costs, disabled: disabled }, context.getValidation('costs').validators] }); + + const costArray = new Array(); + //if (this.externalDatasets && this.externalDatasets.length > 0) { + this.costs.forEach(item => { + costArray.push(item.buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + }); + // } else { + // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + // } + formGroup.addControl('costs', formBuilder.array(costArray)); return formGroup; } diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts index 54387fa92..f699dad91 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.ts @@ -1,6 +1,6 @@ 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 { DataTableRequest } from '@app/core/model/data-table/data-table-request'; import { DatasetProfileModel } from '@app/core/model/dataset/dataset-profile'; @@ -27,6 +27,7 @@ import { LanguageInfoService } from '@app/core/services/culture/language-info-se import { LanguageInfo } from '@app/core/model/language-info'; 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 { value: boolean; @@ -271,7 +272,9 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { if (result) { const costsArray = this.formGroup.get('extraProperties').get('costs').value || []; costsArray.push(result); - this.formGroup.get('extraProperties').get('costs').setValue(costsArray); + let costeditModel: CostEditorModel = new CostEditorModel(); + costeditModel = costeditModel.fromModel(result); + (this.formGroup.get('extraProperties').get('costs')).push(costeditModel.buildForm(null, true)); } }); } From 62118179ffd2380a72369a3659f97328836a97b6 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Thu, 2 Jul 2020 17:06:47 +0300 Subject: [PATCH 4/7] Update the cost listing (near finalization) and fix some issues while loading costs from the backend --- .../add-cost/add-cost.component.ts | 2 +- .../cost-listing/cost-listing.component.html | 16 ++++++++-- .../cost-listing/cost-listing.component.ts | 30 +++++++++++++------ .../extra-properties-form.model.ts | 6 ++-- .../general-tab/general-tab.component.html | 2 +- .../general-tab/general-tab.component.scss | 4 +++ 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts index e6f8d57e7..7a4da0f75 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/add-cost/add-cost.component.ts @@ -23,7 +23,7 @@ export class AddCostComponent extends BaseComponent implements OnInit { 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) => typeof (item) == 'string' ? JSON.parse(item)['value'] : item.value + valueAssign: (item) => JSON.stringify(item) }; constructor( diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html index 1fb26780b..8ed92f09d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.html @@ -9,20 +9,30 @@
- +
- +
- +
+
+
+
+
+
+
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts index 1272e51c6..16bbc9a89 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/cost-editor/cost-listing/cost-listing.component.ts @@ -1,12 +1,13 @@ import { Component, OnInit, Input } from '@angular/core'; import { BaseComponent } from '@common/base/base.component'; -import { FormArray } from '@angular/forms'; +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', @@ -17,14 +18,14 @@ export class CostListingComponent extends BaseComponent implements OnInit { @Input() form: FormArray; - costs: CostModel[] = []; + 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) => this.getValue(item) + valueAssign: (item) => JSON.stringify(item) }; constructor( @@ -34,18 +35,29 @@ export class CostListingComponent extends BaseComponent implements OnInit { } ngOnInit() { - this.form.valueChanges.pipe(takeUntil(this._destroyed)).subscribe(value => { - this.costs = value; - }); } searchCurrency(like: string): Observable { return this.currencyService.get(like); } - getValue(item: any): any { - console.log(item); - return item; +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(); +} } diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts index 8124cc5d5..8ef442501 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts @@ -20,7 +20,9 @@ export class ExtraPropertiesFormModel { this.publicDate = item.publicDate; this.contact = item.contact; if (!isNullOrUndefined(item.costs)) { - this.costs = item.costs; + (item.costs).forEach(element => { + this.costs.push(new CostEditorModel().fromModel(element)); + }); } return this; } @@ -40,7 +42,7 @@ export class ExtraPropertiesFormModel { const costArray = new Array(); //if (this.externalDatasets && this.externalDatasets.length > 0) { this.costs.forEach(item => { - costArray.push(item.buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); + costArray.push(item.buildForm(context.getValidation('costs').descendantValidations, disabled)); }); // } else { // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html index 2d85e7ccc..78852a3a6 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.html @@ -143,7 +143,7 @@
Costs -
diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss index 595aabb5c..322c63d34 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/general-tab.component.scss @@ -41,3 +41,7 @@ .cost-placeholder { text-decoration: underline; } + +.cost-add { + margin-top: 1em; +} From 094cff06b171186b2b1a7ff2b891231fe59559e2 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Thu, 2 Jul 2020 17:08:38 +0300 Subject: [PATCH 5/7] Properly remove associate Collaborators from a DMP --- .../managers/DataManagementPlanManager.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 9583b2862..8d272f67d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -368,6 +368,14 @@ public class DataManagementPlanManager { apiContext.getOperationsContext().getDatabaseRepository().getGrantDao().createOrUpdate(newDmp.getGrant()); newDmp = apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(newDmp); + if (dataManagementPlan.getUsers() != null && !dataManagementPlan.getUsers().isEmpty()) { + clearUsers(newDmp); + for (UserInfoListingModel userListing : dataManagementPlan.getUsers()) { + UserInfo tempUser = apiContext.getOperationsContext().getDatabaseRepository().getUserInfoDao().find(userListing.getId()); + assignUser(dmp, tempUser, UserDMP.UserDMPRoles.fromInteger(userListing.getRole())); + } + } + // Dataset manipulation for when the DMP is set to be finalized. if (dataManagementPlan.getStatus() == DMP.DMPStatus.FINALISED.getValue()) { if (dataManagementPlan.getDatasetsToBeFinalized() != null && !dataManagementPlan.getDatasetsToBeFinalized().isEmpty()) { @@ -1445,13 +1453,22 @@ public class DataManagementPlanManager { * */ private void assignUser(DMP dmp, UserInfo userInfo) { + this.assignUser(dmp, userInfo, UserDMP.UserDMPRoles.OWNER); + } + + private void assignUser(DMP dmp, UserInfo userInfo, UserDMP.UserDMPRoles role) { UserDMP userDMP = new UserDMP(); userDMP.setDmp(dmp); userDMP.setUser(userInfo); - userDMP.setRole(UserDMP.UserDMPRoles.OWNER.getValue()); + userDMP.setRole(role.getValue()); databaseRepository.getUserDmpDao().createOrUpdate(userDMP); } + private void clearUsers(DMP dmp) { + List userDMPs = apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().asQueryable().where(((builder, root) -> builder.equal(root.get("dmp").get("id"), dmp.getId()))).toList(); + userDMPs.forEach(userDMP -> apiContext.getOperationsContext().getDatabaseRepository().getUserDmpDao().delete(userDMP)); + } + private void assignGrandUserIfInternal(DMP dmp, UserInfo user) { if (dmp.getGrant().getCreationUser() == null && (dmp.getGrant().getReference() != null && dmp.getGrant().getReference().startsWith("dmp:"))) { dmp.getGrant().setCreationUser(user); From 7127f6dbd6773ce5b3c8ca4bc3fb631b57482388 Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Thu, 2 Jul 2020 18:35:16 +0300 Subject: [PATCH 6/7] Minor fix over cost listing --- .../ui/dmp/editor/general-tab/extra-properties-form.model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts index 8ef442501..c2dc45d91 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts @@ -42,7 +42,7 @@ export class ExtraPropertiesFormModel { const costArray = new Array(); //if (this.externalDatasets && this.externalDatasets.length > 0) { this.costs.forEach(item => { - costArray.push(item.buildForm(context.getValidation('costs').descendantValidations, disabled)); + costArray.push(item.buildForm(context.getValidation('costs').descendantValidations, true)); }); // } else { // //externalDatasetsFormArray.push(new ExternalDatasetModel().buildForm(context.getValidation('externalDatasets').descendantValidations, disabled)); From 6d491b5930f487a6a4d2ce03f57ea365ea8fafed Mon Sep 17 00:00:00 2001 From: George Kalampokis Date: Thu, 2 Jul 2020 18:36:18 +0300 Subject: [PATCH 7/7] Rda mapper will now be able to use the new DMP fields --- .../eudat/models/rda/mapper/DmpRDAMapper.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java b/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java index a64649c86..bda50f6ba 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/rda/mapper/DmpRDAMapper.java @@ -3,6 +3,7 @@ package eu.eudat.models.rda.mapper; import eu.eudat.data.entities.*; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.utilities.helpers.StreamDistinctBy; +import eu.eudat.models.rda.Cost; import eu.eudat.models.rda.Dmp; import eu.eudat.models.rda.DmpId; import net.minidev.json.JSONObject; @@ -43,16 +44,34 @@ public class DmpRDAMapper { Map extraProperties = new org.json.JSONObject(dmp.getExtraProperties()).toMap(); if (!extraProperties.isEmpty()) { - rda.setLanguage(LanguageRDAMapper.mapLanguageIsoToRDAIso(extraProperties.get("language").toString())); + if (extraProperties.get("language") != null) { + 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 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) { creator = dmp.getCreator(); } else { 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<>()); if (dmp.getResearchers() != null && !dmp.getResearchers().isEmpty()) { rda.getContributor().addAll(dmp.getResearchers().stream().map(ContributorRDAMapper::toRDA).collect(Collectors.toList()));