From b486a27e4829a395ec7a408e3fb3a916bf45d690 Mon Sep 17 00:00:00 2001 From: Kristan Ntavidi Date: Fri, 30 Apr 2021 10:57:13 +0300 Subject: [PATCH] Unique identifiers(in references) on on researchers, organisations, funders, grants, projects (frontend) ( !! Needs configurationw with backend ). Backend error messages translate to PT. --- .../core/model/organisation/organization.ts | 1 + .../app/core/query/funder/funder-criteria.ts | 4 +- .../app/core/query/grant/grant-criteria.ts | 1 + .../core/query/project/project-criteria.ts | 4 +- .../query/researcher/researcher-criteria.ts | 1 + .../external-sources.service.ts | 10 +- .../recent-edited-activity.component.ts | 4 +- ...ecent-edited-dataset-activity.component.ts | 2 +- .../recent-edited-dmp-activity.component.ts | 2 +- .../add-organization.component.html | 9 + .../add-organization.component.ts | 46 ++- .../add-organization.model.ts | 4 + .../add-researcher.component.html | 8 + .../add-researcher.component.ts | 53 +++- .../add-researcher/add-researcher.model.ts | 8 +- .../app/ui/dmp/editor/dmp-editor.component.ts | 2 +- .../funding-info/funding-info.component.html | 24 ++ .../funding-info/funding-info.component.ts | 274 +++++++++++++++++- .../general-tab/general-tab.component.ts | 1 + .../dmp/editor/grant-tab/funder-form-model.ts | 3 + .../dmp/editor/grant-tab/grant-tab-model.ts | 3 + .../editor/grant-tab/project-form-model.ts | 3 + .../editor/main-info/main-info.component.ts | 2 + .../ui/dmp/overview/dmp-overview.component.ts | 4 +- .../start-new-dmp-dialog.component.ts | 2 +- dmp-frontend/src/assets/i18n/de.json | 13 +- dmp-frontend/src/assets/i18n/en.json | 13 +- dmp-frontend/src/assets/i18n/es.json | 13 +- dmp-frontend/src/assets/i18n/gr.json | 13 +- dmp-frontend/src/assets/i18n/pt.json | 20 +- dmp-frontend/src/assets/i18n/sk.json | 13 +- dmp-frontend/src/assets/i18n/sr.json | 13 +- dmp-frontend/src/assets/i18n/tr.json | 13 +- 33 files changed, 545 insertions(+), 41 deletions(-) diff --git a/dmp-frontend/src/app/core/model/organisation/organization.ts b/dmp-frontend/src/app/core/model/organisation/organization.ts index 9cdc13e05..7cc4afa30 100644 --- a/dmp-frontend/src/app/core/model/organisation/organization.ts +++ b/dmp-frontend/src/app/core/model/organisation/organization.ts @@ -6,4 +6,5 @@ export interface OrganizationModel { label: string; status: Status; tag: string; + reference?: string; } diff --git a/dmp-frontend/src/app/core/query/funder/funder-criteria.ts b/dmp-frontend/src/app/core/query/funder/funder-criteria.ts index 97a93a4e2..6c37051b8 100644 --- a/dmp-frontend/src/app/core/query/funder/funder-criteria.ts +++ b/dmp-frontend/src/app/core/query/funder/funder-criteria.ts @@ -1,3 +1,5 @@ import { BaseCriteria } from "../base-criteria"; -export class FunderCriteria extends BaseCriteria { } +export class FunderCriteria extends BaseCriteria { + exactReference:string; + } diff --git a/dmp-frontend/src/app/core/query/grant/grant-criteria.ts b/dmp-frontend/src/app/core/query/grant/grant-criteria.ts index 587060466..da457031c 100644 --- a/dmp-frontend/src/app/core/query/grant/grant-criteria.ts +++ b/dmp-frontend/src/app/core/query/grant/grant-criteria.ts @@ -6,4 +6,5 @@ export class GrantCriteria extends BaseCriteria { public periodEnd: Date; public funderReference: String; public grantStateType: GrantStateType; + public exactReference: string; } diff --git a/dmp-frontend/src/app/core/query/project/project-criteria.ts b/dmp-frontend/src/app/core/query/project/project-criteria.ts index a3b87757a..47a0d88b9 100644 --- a/dmp-frontend/src/app/core/query/project/project-criteria.ts +++ b/dmp-frontend/src/app/core/query/project/project-criteria.ts @@ -1,3 +1,5 @@ import { BaseCriteria } from "../base-criteria"; -export class ProjectCriteria extends BaseCriteria { } +export class ProjectCriteria extends BaseCriteria { + exactReference: string; + } diff --git a/dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts b/dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts index 3eda8ff2a..fd529c381 100644 --- a/dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts +++ b/dmp-frontend/src/app/core/query/researcher/researcher-criteria.ts @@ -2,4 +2,5 @@ import { BaseCriteria } from "../base-criteria"; export class ResearcherCriteria extends BaseCriteria { public name: String; + public reference?: string; } diff --git a/dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts b/dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts index 724233ea3..dc04b7f3a 100644 --- a/dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts +++ b/dmp-frontend/src/app/core/services/external-sources/external-sources.service.ts @@ -67,8 +67,14 @@ export class ExternalSourcesService { return this.http.post(this.configurationService.server + 'researchers/getWithExternal', requestItem, { headers: this.headers }); } - public searchDMPOrganizations(like: string): Observable { - return this.http.get(this.actionUrl + 'organisations' + '?query=' + like, { headers: this.headers }); + public searchDMPOrganizations(like: string, reference?: string): Observable { + const params = { + query:like + } + if(reference){ + params['reference'] = reference; + } + return this.http.get(this.actionUrl + 'organisations', { headers: this.headers, params: params }); } // TODO: currently not used. diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts index d004c57bb..84eac2e7c 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-activity/recent-edited-activity.component.ts @@ -322,7 +322,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn } onDeleteCallbackError(error) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(error.error.message ? this.language.instant(error.error.message) : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); } onCloneOrNewVersionCallbackSuccess(dmpId: String): void { @@ -331,7 +331,7 @@ export class RecentEditedActivityComponent extends BaseComponent implements OnIn } onCloneOrNewVersionCallbackError(error: any) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-CLONE'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(error.error.message ? this.language.instant(error.error.message) : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-CLONE'), SnackBarNotificationLevel.Error); } redirect(id: string, type: RecentActivityType) { diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts index 83d4596f8..0955ec5c3 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-dataset-activity/recent-edited-dataset-activity.component.ts @@ -350,7 +350,7 @@ export class RecentEditedDatasetActivityComponent extends BaseComponent implemen } onDeleteCallbackError(error) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(error.error.message ? this.language.instant(error.error.message) : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); } openUpdateDatasetProfileDialogue(id: string) { diff --git a/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts b/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts index 74a40e06b..e0492ccd8 100644 --- a/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts +++ b/dmp-frontend/src/app/ui/dashboard/recent-edited-dmp-activity/recent-edited-dmp-activity.component.ts @@ -302,7 +302,7 @@ export class RecentEditedDmpActivityComponent extends BaseComponent implements O } onDeleteCallbackError(error) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(error.error.message ? this.language.instant(error.error.message) : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); } onCloneOrNewVersionCallbackSuccess(dmpId: String): void { diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.html b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.html index 15d3aa702..750c2bdff 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.html @@ -1,6 +1,15 @@

{{'ADDORGANIZATION-EDITOR.TITLE' | translate}}

+ + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + {{'DMP-EDITOR.MAIN-INFO.ORGANISATION-IDENTIFIER-EXISTS' | translate}} + check + clear + {{'DMP-EDITOR.MAIN-INFO.IDENTIFIER-EXISTS-ORGANISATION-LIST' | translate}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts index 517cb2158..1c7915468 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.component.ts @@ -1,9 +1,12 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; +import { AbstractControl, AsyncValidatorFn, FormControl, FormGroup, ValidationErrors } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; import { ExternalResearcherService } from '@app/core/services/external-sources/researcher/external-researcher.service'; +import { OrganisationService } from '@app/core/services/organisation/organisation.service'; import { BaseComponent } from '@common/base/base.component'; -import { takeUntil } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { debounceTime, distinctUntilChanged, first, map, mergeMap, takeUntil } from 'rxjs/operators'; import { OrganizationEditorModel } from './add-organization.model'; @Component({ @@ -14,15 +17,30 @@ export class AddOrganizationComponent extends BaseComponent implements OnInit { public formGroup: FormGroup; + private existingReferences: string[] = []; + get referenceExists(){ + const reference = this.formGroup.get('reference').value; + + return this.existingReferences.find((r)=>r === reference) + } constructor( + private externalSourcesService: ExternalSourcesService, private externalResearcherService: ExternalResearcherService, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } + ) { + super(); + if(data){ + const researchers = (data as FormControl).value ; + if(researchers){ + this.existingReferences = (researchers as Array).map(researcher => researcher.reference); + } + }} ngOnInit(): void { const researcher = new OrganizationEditorModel(); this.formGroup = researcher.buildForm(); + this.formGroup.get('reference').setAsyncValidators(this.organizationUniqueIdentifier()); } send(value: any) { @@ -38,6 +56,26 @@ export class AddOrganizationComponent extends BaseComponent implements OnInit { } isFormValid() { - return this.formGroup.valid; + return this.formGroup.valid && !this.referenceExists; + } + private organizationUniqueIdentifier(): AsyncValidatorFn{ + return (control: AbstractControl) :Observable =>{ + return control.valueChanges.pipe( + debounceTime(600), + mergeMap(value=>this.externalSourcesService.searchDMPOrganizations('',value)), + takeUntil(this._destroyed), + map((response)=>{ + if(response && response.length){ + const internalOrganizations = (response as Array).filter(organization=> organization.key === "Internal"); + + if(internalOrganizations && internalOrganizations.length){ + return {organizationIdentifierExists:true}; + } + } + return null; + }) + + ).pipe(first()) + } } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts index 444b3ae7c..582212274 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/add-organization/add-organization.model.ts @@ -9,16 +9,19 @@ export class OrganizationEditorModel { public id: String; public name: String; public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + public reference: string; fromModel(item: OrganizationModel): OrganizationEditorModel { this.id = item.id; this.name = item.name; + this.reference = item.reference; return this; } buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ + reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators], name: [{ value: this.name, disabled: disabled }, context.getValidation('name').validators] }); @@ -28,6 +31,7 @@ export class OrganizationEditorModel { createValidationContext(): ValidationContext { const baseContext: ValidationContext = new ValidationContext(); baseContext.validation.push({ key: 'name', validators: [BackendErrorValidator(this.validationErrorModel, 'name')] }); + baseContext.validation.push({ key: 'reference', validators: [BackendErrorValidator(this.validationErrorModel, 'reference')] }); return baseContext; } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html index cf0654d1a..26d784fd5 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.html @@ -1,6 +1,14 @@

{{'ADDRESEARCHERS-EDITOR.TITLE' | translate}}

+ + + + {{'DMP-EDITOR.MAIN-INFO.RESEARCHER-IDENTIFIER-EXISTS' | translate}} + check + clear + {{'DMP-EDITOR.MAIN-INFO.IDENTIFIER-EXISTS-RESEARCHER-LIST' | translate}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts index ca87c4f60..036e5f475 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.component.ts @@ -1,10 +1,12 @@ import { Component, Inject, OnInit } from '@angular/core'; -import { FormGroup } from '@angular/forms'; +import { AbstractControl, AsyncValidatorFn, FormControl, FormGroup, ValidationErrors } from '@angular/forms'; import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { ExternalSourcesService } from '@app/core/services/external-sources/external-sources.service'; import { ExternalResearcherService } from '@app/core/services/external-sources/researcher/external-researcher.service'; import { ResearcherEditorModel } from '@app/ui/dmp/editor/add-researcher/add-researcher.model'; import { BaseComponent } from '@common/base/base.component'; -import { takeUntil } from 'rxjs/operators'; +import { Observable } from 'rxjs'; +import { debounceTime, distinctUntilChanged, filter, first, map, mergeMap, startWith, takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-add-researcher-component', @@ -14,15 +16,34 @@ export class AddResearcherComponent extends BaseComponent implements OnInit { public formGroup: FormGroup; + // private readonly _REFERENCE_PREFIX:string = "dmp:"; + private existingReferences: string[] = []; + get referenceExists(){ + const reference = this.formGroup.get('reference').value; + + return this.existingReferences.find((r)=>r === reference) + } + constructor( + private externalSourcesService: ExternalSourcesService, private externalResearcherService: ExternalResearcherService, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any - ) { super(); } + ) { super(); + + if(data){ + const researchers = (data as FormControl).value ; + if(researchers){ + this.existingReferences = (researchers as Array).map(researcher => researcher.reference); + } + } + } ngOnInit(): void { const researcher = new ResearcherEditorModel(); this.formGroup = researcher.buildForm(); + + this.formGroup.get('reference').setAsyncValidators(this.researcherUniqueIdentifier()); } send(value: any) { @@ -34,10 +55,34 @@ export class AddResearcherComponent extends BaseComponent implements OnInit { } addResearcher() { + + const formValue = this.formGroup.value; + formValue.reference = formValue.reference; this.dialogRef.close(this.formGroup.value); } isFormValid() { - return this.formGroup.valid; + return this.formGroup.valid && !this.referenceExists; + } + + private researcherUniqueIdentifier(): AsyncValidatorFn{ + return (control: AbstractControl) :Observable =>{ + return control.valueChanges.pipe( + debounceTime(600), + takeUntil(this._destroyed), + mergeMap(value=>this.externalSourcesService.searchDMPResearchers({criteria:{name: '',like: null,reference:value }})), + map((response)=>{ + if(response && response.length){ + let internalEntries = (response as any[]).filter(record=>record.key === 'Internal'); + if(internalEntries && internalEntries.length){ + internalEntries = internalEntries.filter(record=> (record.reference === (control.value))); + } + return internalEntries && internalEntries.length? {researcherIdentifierExists:true} : null; + } + return null; + }) + + ).pipe(first()) + } } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts index 80dca6276..af8586f95 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/add-researcher/add-researcher.model.ts @@ -1,4 +1,4 @@ -import { FormBuilder, FormGroup } from '@angular/forms'; +import {FormBuilder, FormGroup, ValidationErrors } 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'; @@ -11,19 +11,22 @@ export class ResearcherEditorModel { public uri: String; public email: String; public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + public reference: String; + fromModel(item: ResearcherModel): ResearcherEditorModel { this.id = item.id; this.name = item.name; this.email = item.email; this.uri = item.uri; - + this.reference = item.reference; return this; } buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { if (context == null) { context = this.createValidationContext(); } const formGroup = new FormBuilder().group({ + reference: [{ value: this.reference, disabled: disabled },context.getValidation('reference')], firstName: [{ value: this.name, disabled: disabled }, context.getValidation('firstName').validators], lastName: [{ value: this.lastName, disabled: disabled }, context.getValidation('lastName').validators] }); @@ -33,6 +36,7 @@ export class ResearcherEditorModel { createValidationContext(): ValidationContext { const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'reference', validators: [BackendErrorValidator(this.validationErrorModel, 'reference')] }); baseContext.validation.push({ key: 'firstName', validators: [BackendErrorValidator(this.validationErrorModel, 'firstName')] }); baseContext.validation.push({ key: 'lastName', validators: [BackendErrorValidator(this.validationErrorModel, 'lastName')] }); return baseContext; diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts index b7f55a84f..b01094924 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.ts @@ -471,7 +471,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC onSubmit(addNew?: boolean, showAddDatasetDialog?: boolean): void { this.scrollTop = document.getElementById('editor-form').scrollTop; - + // return; this.dmpService.createDmp(this.formGroup.getRawValue()) .pipe(takeUntil(this._destroyed)) .subscribe( diff --git a/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.html b/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.html index 61104beb1..7dfd317d6 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.html @@ -22,6 +22,14 @@
+ + + + {{'DMP-EDITOR.FUNDING-INFO.IDENTIFIER-FUNDER-EXISTS' | translate}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + check + clear + @@ -63,6 +71,14 @@
+ + + + {{'DMP-EDITOR.FUNDING-INFO.IDENTIFIER-GRANT-EXISTS' | translate}} + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + check + clear + @@ -111,6 +127,13 @@
+ + + + {{'DMP-EDITOR.FUNDING-INFO.IDENTIFIER-PROJECT-EXISTS' | translate}} + check + clear + @@ -143,4 +166,5 @@
+ diff --git a/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.ts b/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.ts index f3a6392cd..701dc86dd 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.ts @@ -1,6 +1,6 @@ import { BaseComponent } from '@common/base/base.component'; import { OnInit, Component, Input, EventEmitter, Output } from '@angular/core'; -import { FormGroup } from '@angular/forms'; +import { AbstractControl, FormGroup, Validators } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { GrantTabModel } from '../grant-tab/grant-tab-model'; import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration'; @@ -11,9 +11,10 @@ import { RequestItem } from '@app/core/query/request-item'; import { GrantCriteria } from '@app/core/query/grant/grant-criteria'; import { ProjectCriteria } from '@app/core/query/project/project-criteria'; import { FunderCriteria } from '@app/core/query/funder/funder-criteria'; -import { takeUntil } from 'rxjs/operators'; +import { debounceTime, filter, map, switchMap, takeUntil, tap } from 'rxjs/operators'; import { GrantEditorModel } from '@app/ui/grant/editor/grant-editor.model'; +import { isNullOrUndefined } from '@swimlane/ngx-datatable'; @Component({ selector: 'funding-info', templateUrl: './funding-info.component.html', @@ -44,6 +45,9 @@ export class FundingInfoComponent extends BaseComponent implements OnInit { projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; funderAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + isFunderPending:boolean = false; + isGrantPending:boolean = false; + isProjectPending:boolean = false; constructor( private grantService: GrantService, private projectService: ProjectService, @@ -67,6 +71,8 @@ export class FundingInfoComponent extends BaseComponent implements OnInit { this.configureAutoCompletes(); + this.initializeReferenceValidators(); + this.isCreateNew = (this.grantformGroup.get('label').value != null && this.grantformGroup.get('label').value.length > 0); this.isCreateNewProject = (this.projectFormGroup.get('label').value != null && this.projectFormGroup.get('label').value.length > 0); this.isCreateNewFunder = (this.funderFormGroup.get('label').value != null && this.funderFormGroup.get('label').value.length > 0); @@ -84,6 +90,112 @@ export class FundingInfoComponent extends BaseComponent implements OnInit { this.configureAutoCompletes(); }); } + initializeReferenceValidators() { + + //Validator for funder + this.funderFormGroup.get('reference').valueChanges.pipe( + takeUntil(this._destroyed), + filter(value =>!isNullOrUndefined(value)), + tap(_=>this.isFunderPending = true), + debounceTime(500), + switchMap(value=> { + const requestItem = new RequestItem(); + requestItem.criteria = new FunderCriteria(); + requestItem.criteria.exactReference = value; + return this.funderService.getWithExternal(requestItem).pipe(takeUntil(this._destroyed)); + }), + map(response=>{ + if(response && response.length){ + const internalFunders = (response as Array).filter(funder=> funder.key === 'Internal'); + + if(internalFunders && internalFunders.length){ + return {funderIdentifierExists:true}; + } + return null; + } + return null; + }) + ) + .subscribe(error=>{ + this.isFunderPending = false; + this.funderFormGroup.get('reference').setErrors(error); + if(!error && this.funderFormGroup.get('reference').validator){ + const validator = this.funderFormGroup.get('reference').validator({} as AbstractControl); + if(validator && validator.required && this.funderFormGroup.get('reference').touched && !this.funderFormGroup.get('reference').value){ + this.funderFormGroup.get('reference').setErrors({required : true}); + } + } + }); + + //Validator for grants + this.grantformGroup.get('reference').valueChanges.pipe( + takeUntil(this._destroyed), + filter(value =>!isNullOrUndefined(value)), + tap(_=> this.isGrantPending = true), + debounceTime(500), + switchMap(value=> { + const requestItem = new RequestItem(); + requestItem.criteria = new GrantCriteria(); + requestItem.criteria.exactReference = value; + return this.grantService.getWithExternal(requestItem).pipe(takeUntil(this._destroyed)); + }), + map(response=>{ + if(response && response.length){ + const internalGrants = (response as Array).filter(grant=> grant.key === 'Internal'); + + if(internalGrants && internalGrants.length){ + return {grantIdentifierExists:true}; + } + return null; + } + return null; + }) + ) + .subscribe(error=>{ + this.isGrantPending = false; + this.grantformGroup.get('reference').setErrors(error); + if(!error && this.grantformGroup.get('reference').validator){ + const validator = this.grantformGroup.get('reference').validator({} as AbstractControl); + if(validator && validator.required && this.grantformGroup.get('reference').touched && !this.grantformGroup.get('reference').value){ + this.grantformGroup.get('reference').setErrors({required : true}); + } + } + }); + + //validator for projects + this.projectFormGroup.get('reference').valueChanges.pipe( + takeUntil(this._destroyed), + filter(value =>!isNullOrUndefined(value)), + tap(_ => this.isProjectPending = true), + debounceTime(500), + switchMap(value=> { + const requestItem = new RequestItem(); + requestItem.criteria = new ProjectCriteria(); + requestItem.criteria.exactReference = value; + return this.projectService.getWithExternal(requestItem).pipe(takeUntil(this._destroyed)); + }), + map(response=>{ + if(response && response.length){ + const internalProjects = (response as Array).filter(project=> project.key === 'Internal'); + if(internalProjects && internalProjects.length){ + return {projectIdentifierExists:true}; + } + return null; + } + return null; + }) + ) + .subscribe(error=>{ + this.isProjectPending = false; + this.projectFormGroup.get('reference').setErrors(error); + if(!error && this.projectFormGroup.get('reference').validator){ + const validator = this.projectFormGroup.get('reference').validator({} as AbstractControl); + if(validator && validator.required && this.projectFormGroup.get('reference').touched && !this.projectFormGroup.get('reference').value){ + this.projectFormGroup.get('reference').setErrors({required : true}); + } + } + }); + } configureAutoCompletes(): void { this.funderAutoCompleteConfiguration = { @@ -161,22 +273,34 @@ export class FundingInfoComponent extends BaseComponent implements OnInit { this.grantformGroup.get('existGrant').disable(); this.grantformGroup.get('label').enable(); this.grantformGroup.get('description').enable(); + + this.grantformGroup.get('reference').setValidators(Validators.required); + this.grantformGroup.get('reference').updateValueAndValidity(); } else if (this.isClone && !this.isNewVersion) { this.grantformGroup.get('existGrant').enable(); this.grantformGroup.get('label').disable(); this.grantformGroup.get('label').reset(); this.grantformGroup.get('description').disable(); this.grantformGroup.get('description').reset(); + + this.grantformGroup.get('reference').clearValidators(); + this.grantformGroup.get('reference').updateValueAndValidity(); } else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) { this.grantformGroup.get('existGrant').disable(); this.grantformGroup.get('label').disable(); this.grantformGroup.get('description').disable(); + + this.grantformGroup.get('reference').clearValidators(); + this.grantformGroup.get('reference').updateValueAndValidity(); } else { this.grantformGroup.get('existGrant').enable(); this.grantformGroup.get('label').disable(); this.grantformGroup.get('label').reset(); this.grantformGroup.get('description').disable(); this.grantformGroup.get('description').reset(); + + this.grantformGroup.get('reference').clearValidators(); + this.grantformGroup.get('reference').updateValueAndValidity(); } } @@ -185,22 +309,34 @@ export class FundingInfoComponent extends BaseComponent implements OnInit { this.projectFormGroup.get('existProject').disable(); this.projectFormGroup.get('label').enable(); this.projectFormGroup.get('description').enable(); + + this.projectFormGroup.get('reference').setValidators(Validators.required); + this.projectFormGroup.get('reference').updateValueAndValidity(); } else if (this.isClone && !this.isNewVersion) { this.projectFormGroup.get('existProject').enable(); this.projectFormGroup.get('label').disable() this.projectFormGroup.get('label').reset(); this.projectFormGroup.get('description').disable(); this.projectFormGroup.get('description').reset(); + + this.projectFormGroup.get('reference').clearValidators(); + this.projectFormGroup.get('reference').updateValueAndValidity(); } else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) { this.projectFormGroup.get('existProject').disable(); this.projectFormGroup.get('label').disable(); this.projectFormGroup.get('description').disable(); + + this.projectFormGroup.get('reference').clearValidators(); + this.projectFormGroup.get('reference').updateValueAndValidity(); } else { this.projectFormGroup.get('existProject').enable(); this.projectFormGroup.get('label').disable(); this.projectFormGroup.get('label').reset(); this.projectFormGroup.get('description').disable(); this.projectFormGroup.get('description').reset(); + + this.projectFormGroup.get('reference').clearValidators(); + this.projectFormGroup.get('reference').updateValueAndValidity(); } } @@ -208,21 +344,35 @@ export class FundingInfoComponent extends BaseComponent implements OnInit { if (this.isCreateNewFunder) { this.funderFormGroup.get('existFunder').disable(); this.funderFormGroup.get('label').enable(); + + this.funderFormGroup.get('reference').setValidators(Validators.required); + this.funderFormGroup.get('reference').updateValueAndValidity(); + } else if (this.isClone && !this.isNewVersion) { if (this.funderFormGroup.get('existFunder')) { this.funderFormGroup.get('existFunder').enable(); this.funderFormGroup.get('label').disable(); this.funderFormGroup.get('label').reset(); + this.funderFormGroup.get('reference').clearValidators(); + this.funderFormGroup.get('reference').updateValueAndValidity(); } else { this.funderFormGroup.get('label').enable(); + this.funderFormGroup.get('reference').setValidators(Validators.required); + this.funderFormGroup.get('reference').updateValueAndValidity(); } } else if (this.isFinalized || this.isNewVersion || !this.isUserOwner) { this.funderFormGroup.get('existFunder').disable(); this.funderFormGroup.get('label').disable(); + + this.funderFormGroup.get('reference').clearValidators(); + this.funderFormGroup.get('reference').updateValueAndValidity(); } else { this.funderFormGroup.enable(); this.funderFormGroup.get('label').disable(); this.funderFormGroup.get('label').reset(); + + this.funderFormGroup.get('reference').clearValidators(); + this.funderFormGroup.get('reference').updateValueAndValidity(); } } @@ -255,4 +405,124 @@ export class FundingInfoComponent extends BaseComponent implements OnInit { showToggleButton() { return (!this.isFinalized && this.isUserOwner) || this.isClone; } + + // private grantUniqueIdentifier(): AsyncValidatorFn{ + // return (control: AbstractControl) :Observable =>{ + // return control.valueChanges.pipe( + // debounceTime(600), + // distinctUntilChanged(), + // mergeMap(value=>{ + // const requestItem = new RequestItem(); + // requestItem.criteria = new GrantCriteria(); + // requestItem.criteria.exactReference = value; + // return this.grantService.getWithExternal(requestItem); + // }), + // takeUntil(this._destroyed), + // map((response)=>{ + // if(response && response.length){ + // const internalGrants = (response as Array).filter(grant=> grant.key === "Internal"); + // if(internalGrants && internalGrants.length){ + // return {grantIdentifierExists:true}; + // } + // } + // return null; + // // return response && response.length? {grantIdentifierExists:true} : null; + // }) + + // ).pipe(first()) + // } + // } + // private funderUniqueIdentifier(): AsyncValidatorFn{ + // return (control: AbstractControl) :Observable =>{ + + // if(!control.valueChanges){ + // return of(null); + // } + + // return control.valueChanges.pipe( + // debounceTime(600), + // // distinctUntilChanged(), + // switchMap(value=>{ + // const requestItem = new RequestItem(); + // requestItem.criteria = new FunderCriteria(); + // requestItem.criteria.exactReference = value; + // console.log('perasame mia fora'); + // return this.funderService.getWithExternal(requestItem); + // }), + // takeUntil(this._destroyed), + // map((response)=>{ + + // console.log('pername map'); + // //got response + // if(response && response.length){ + // const internalFunders = (response as Array).filter(funder=> funder.key === 'Internal'); + + // if(internalFunders && internalFunders.length){ + // return {funderIdentifierExists:true}; + // } + // return null; + // } + + // return null; + // } + // ), + // first() + + // ) + + // // const requestItem = new RequestItem(); + // // requestItem.criteria = new FunderCriteria(); + // // requestItem.criteria.exactReference = control.value; + // // return this.funderService.getWithExternal(requestItem).pipe( + // // takeUntil(this._destroyed), + // // map((response)=>{ + // // if(response && response.length){ + // // const internalFunders = (response as Array).filter(funder=> funder.key === 'Internal'); + + // // if(internalFunders && internalFunders.length){ + // // return {funderIdentifierExists:true}; + // // } + // // return null; + // // } + + // // return null; + // // }) + // // ) + + // } + // } + + + // private grantProjectIdentifier(): AsyncValidatorFn{ + // return (control: AbstractControl) :Observable =>{ + // return control.valueChanges.pipe( + // debounceTime(600), + // distinctUntilChanged(), + // mergeMap(value=>{ + // const requestItem = new RequestItem(); + // requestItem.criteria = new ProjectCriteria(); + // requestItem.criteria.exactReference = value; + // // return this.grantService.getWithExternal(requestItem); + // return this.projectService.getWithExternal(requestItem); + // }), + // takeUntil(this._destroyed), + // map((response)=>{ + // if(response && response.length){ + // const internalProjects = (response as Array).filter(grant=> grant.key === "Internal"); + // if(internalProjects && internalProjects.length){ + // return {projectIdentifierExists:true}; + // } + // } + // return null; + // // return response && response.length? {grantIdentifierExists:true} : null; + // }) + + // ).pipe(first()) + // } + // } + + + private consoleForm(){ + console.log(this.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 720e4b883..038fbe007 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 @@ -199,6 +199,7 @@ export class GeneralTabComponent extends BaseComponent implements OnInit { id: null, status: 0, key: "Internal", + reference: result.reference }; const researchersArray = this.formGroup.get('researchers').value || []; researchersArray.push(newItem); diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts index 4ad0c6e7d..a2e00cd8d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts @@ -12,6 +12,7 @@ export class FunderFormModel { public status: Status = Status.Active; public existFunder: FunderModel; public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + public reference: string; fromModel(item: FunderModel): FunderFormModel { @@ -27,6 +28,7 @@ export class FunderFormModel { label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], existFunder: [{ value: this.existFunder, disabled: disabled }, context.getValidation('existFunder').validators], + reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators], }); return formGroup; } @@ -37,6 +39,7 @@ export class FunderFormModel { baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); baseContext.validation.push({ key: 'status', validators: [] }); baseContext.validation.push({ key: 'existFunder', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'existFunder')] }); + baseContext.validation.push({ key: 'reference', validators: [BackendErrorValidator(this.validationErrorModel, 'reference')] }); return baseContext; } diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts index 4c01cfbfc..9a922c6a7 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab-model.ts @@ -15,6 +15,7 @@ export class GrantTabModel { public existGrant: GrantListingModel; public funderId: String; public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + public reference: string; fromModel(item: GrantListingModel): GrantTabModel { @@ -32,6 +33,7 @@ export class GrantTabModel { description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], existGrant: [{ value: this.existGrant, disabled: disabled }, context.getValidation('existGrant').validators], funderId: [{ value: this.funderId, disabled: disabled }, context.getValidation('funderId').validators], + reference: [{ value: this.funderId, disabled: disabled }, context.getValidation('reference').validators], }); return formGroup; } @@ -44,6 +46,7 @@ export class GrantTabModel { baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] }); baseContext.validation.push({ key: 'existGrant', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.validationErrorModel, 'existGrant')] }); baseContext.validation.push({ key: 'funderId', validators: [ValidJsonValidator, BackendErrorValidator(this.validationErrorModel, 'funderId')] }); + baseContext.validation.push({ key: 'reference', validators: [BackendErrorValidator(this.validationErrorModel, 'reference')] }); return baseContext; } diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts index 83178a711..fbcee5fe4 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts @@ -13,6 +13,7 @@ export class ProjectFormModel { public description: String; public existProject: ProjectModel; public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + public reference: string; fromModel(item: ProjectModel): ProjectFormModel { @@ -29,6 +30,7 @@ export class ProjectFormModel { status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], existProject: [{ value: this.existProject, disabled: disabled }, context.getValidation('existProject').validators], + reference: [{ value: this.reference, disabled: disabled }, context.getValidation('reference').validators], }); return formGroup; } @@ -40,6 +42,7 @@ export class ProjectFormModel { baseContext.validation.push({ key: 'status', validators: [] }); baseContext.validation.push({ key: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] }); baseContext.validation.push({ key: 'existProject', validators: [BackendErrorValidator(this.validationErrorModel, 'existProject')] }); + baseContext.validation.push({ key: 'reference', validators: [BackendErrorValidator(this.validationErrorModel, 'reference')] }); return baseContext; } diff --git a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts index 653380fbb..64594cf37 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.ts @@ -130,6 +130,7 @@ export class MainInfoComponent extends BaseComponent implements OnInit { id: null, status: 0, key: "Internal", + reference: result.reference }; const researchersArray = this.formGroup.get('researchers').value || []; researchersArray.push(newItem); @@ -169,6 +170,7 @@ export class MainInfoComponent extends BaseComponent implements OnInit { id: null, status: 0, key: "Internal", + reference: result.reference }; const organizationsArray = this.formGroup.get('organisations').value || []; organizationsArray.push(newItem); diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index 021b44d7c..5e203919a 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -311,7 +311,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } onDeleteCallbackError(error) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(error.error.message ? this.language.instant(error.error.message) : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); } onUpdateCallbackSuccess(): void { @@ -511,7 +511,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { maxWidth: '600px', restoreFocus: false, data: { - message: message, + message: this.language.instant(message), titles: [this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN'), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')] } }); diff --git a/dmp-frontend/src/app/ui/dmp/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts index 7e52b8d8b..f9b46a8d4 100644 --- a/dmp-frontend/src/app/ui/dmp/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/start-new-dmp-dialogue/start-new-dmp-dialog.component.ts @@ -86,7 +86,7 @@ export class StartNewDmpDialogComponent extends BaseComponent { } private onCallbackImportFail(error: any) { - this.uiNotificationService.snackBarNotification(error.message, SnackBarNotificationLevel.Error); + this.uiNotificationService.snackBarNotification(this.language.instant(error.message), SnackBarNotificationLevel.Error); } } diff --git a/dmp-frontend/src/assets/i18n/de.json b/dmp-frontend/src/assets/i18n/de.json index 4dfa5fba9..4eb969ee9 100644 --- a/dmp-frontend/src/assets/i18n/de.json +++ b/dmp-frontend/src/assets/i18n/de.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "A DMP in Argos consists of key information about research, such as purpose, objectives and researchers involved, but also about documentation of research datasets, namely dataset descriptions, that highlight the steps followed and the means used across data management activities.", "HINT": "A brief description of what the DMP is about, it’s scope and objectives.", - "TYPING": "Type more letters of the name so its more possible to find the correct one." + "TYPING": "Type more letters of the name so its more possible to find the correct one.", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "You are using the DMP editor. Add here information about the scope, funding, actors of your DMP and decide on access and re-use issues for the DMP output that you are creating.", - "FIND": "Couldn't find the correct one?" + "FIND": "Couldn't find the correct one?", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "A DMP in Argos consists of key information about research, such as purpose, objectives and researchers involved, but also about documentation of research datasets, namely dataset descriptions, that highlight the steps followed and the means used across data management activities.", diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 8ca742e8a..d83161051 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "A DMP in Argos consists of key information about research, such as purpose, objectives and researchers involved, but also about documentation of research datasets that highlight the steps followed and the means used across data management activities.", "HINT": "A brief description of what the DMP is about, it’s scope and objectives.", - "TYPING": "Type more letters of the name so its more possible to find the correct one." + "TYPING": "Type more letters of the name so its more possible to find the correct one.", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "You are using the DMP editor. Add here information about the scope, funding, actors of your DMP and decide on access and re-use issues for the DMP output that you are creating.", - "FIND": "Couldn't find the correct one?" + "FIND": "Couldn't find the correct one?", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "A DMP in Argos consists of key information about research, such as purpose, objectives and researchers involved, but also about documentation of research datasets that highlight the steps followed and the means used across data management activities.", diff --git a/dmp-frontend/src/assets/i18n/es.json b/dmp-frontend/src/assets/i18n/es.json index 0902b7807..6ddb744ed 100644 --- a/dmp-frontend/src/assets/i18n/es.json +++ b/dmp-frontend/src/assets/i18n/es.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "Un PGD en Argos consiste en la información clave sobre una investigación. Para este propósito se incluyen además de objetivos e investigaciones la documentación sobre los datasets de la investigación. En concreto la descripción de los dataset que resalta los pasos seguidos y los medios usados en las actividades administrativas.", "HINT": "Una breve descripción sobre que trata el PGD, su ámbito y objetivos", - "TYPING": "Escriba más letras del nombre para que sea más probable encontrar el correcto" + "TYPING": "Escriba más letras del nombre para que sea más probable encontrar el correcto", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "You are using the DMP editor. Add here information about the scope, funding, actors of your DMP and decide on access and re-use issues for the DMP output that you are creating.", - "FIND": "¿No se encontró el correcto?" + "FIND": "¿No se encontró el correcto?", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "Un PGD en Argos consiste en la información clave sobre una investigación. Para este propósito se incluyen además de objetivos e investigaciones la documentación sobre los datasets de la investigación. En concreto la descripción de los dataset que resalta los pasos seguidos y los medios usados en las actividades administrativas.", diff --git a/dmp-frontend/src/assets/i18n/gr.json b/dmp-frontend/src/assets/i18n/gr.json index a41bf4fbe..3e02286b3 100644 --- a/dmp-frontend/src/assets/i18n/gr.json +++ b/dmp-frontend/src/assets/i18n/gr.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "Ένα Σχέδιο Διαχείρισης στο Argos αποτελείται από τις βασικές πληροφορίες σχετικά με την έρευνα, όπως ο σκοπός, οι στόχοι και οι εμπλεκόμενοι ερευνητές, αλλά και σχετικά με την τεκμηρίωση των ερευνητικών συνόλων δεδομένων, δηλαδή τις περιγραφές δεδομένων που υπογραμμίζουν τα βήματα που ακολουθήθηκαν και τα μέσα που χρησιμοποιήθηκαν σε όλες τις δραστηριότητες διαχείρισης δεδομένων.", "HINT": "Μία σύντομη περιγραφή του τι αφορά το Σχέδιο Διαχείρισης Δεδομένων, του πεδίου εφαρμογής και των στόχων του.", - "TYPING": "Προσθέστε περισσότερα γράμματα στο όνομα ώστε να είναι πιο πιθανό να βρείτε το σωστό." + "TYPING": "Προσθέστε περισσότερα γράμματα στο όνομα ώστε να είναι πιο πιθανό να βρείτε το σωστό.", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "You are using the DMP editor. Add here information about the scope, funding, actors of your DMP and decide on access and re-use issues for the DMP output that you are creating.", - "FIND": "Δεν μπορέσατε να βρείτε το σωστό;" + "FIND": "Δεν μπορέσατε να βρείτε το σωστό;", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "Ένα Σχέδιο Διαχείρισης στο Argos αποτελείται από τις βασικές πληροφορίες σχετικά με την έρευνα, όπως ο σκοπός, οι στόχοι και οι εμπλεκόμενοι ερευνητές, αλλά και σχετικά με την τεκμηρίωση των ερευνητικών συνόλων δεδομένων, δηλαδή τις περιγραφές δεδομένων που υπογραμμίζουν τα βήματα που ακολουθήθηκαν και τα μέσα που χρησιμοποιήθηκαν σε όλες τις δραστηριότητες διαχείρισης δεδομένων.", diff --git a/dmp-frontend/src/assets/i18n/pt.json b/dmp-frontend/src/assets/i18n/pt.json index 2fd6ede35..8ec45c514 100644 --- a/dmp-frontend/src/assets/i18n/pt.json +++ b/dmp-frontend/src/assets/i18n/pt.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "Um PGD no Argos inclui informação chave sobre a investigação, nomeadamente a sua finalidade, objetivos e investigadores envolvidos. Inclui também informação sobre a documentação de Datasets da investigação, destacando as etapas seguidas e os meios utilizados nas atividades de gestão de dados.", "HINT": "Uma breve descrição sobre o tema do PGD, o seu âmbito e objetivos.", - "TYPING": "Digite mais letras do nome para que seja possível encontrá-lo mais facilmente." + "TYPING": "Digite mais letras do nome para que seja possível encontrá-lo mais facilmente.", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "Um Plano de Gestão de Dados (PGD) permite uma maior proximidade com o local onde os seus dados são gerados, analisados e armazenados. O Argos é uma ferramenta aberta, extensível e colaborativa que disponibiliza Planos de Gestão de Dados FAIR e Abertos.", - "FIND": "Não foi possível encontrar um adequado?" + "FIND": "Não foi possível encontrar um adequado?", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "Um PGD no Argos inclui informação chave sobre a investigação, nomeadamente a sua finalidade, objetivos e investigadores envolvidos. Inclui também informação sobre a documentação de Datasets da investigação, destacando as etapas seguidas e os meios utilizados nas atividades de gestão de dados.", @@ -1729,5 +1738,10 @@ "DRAFT": "Rascunho", "FINALIZED": "Concluído", "DELETED": "Deleted" - } + }, + "This account has no Zenodo Token":"Esta conta não tem nenhum Token Zenodo?", + "File format is not supported": "Ficheiro a importar deverá ser em formato .json", + "You cannot Remove Datamanagement Plan with Datasets": "Não pode remover o Plano de Gestão de Dados porque contém pelo menos um modelo de dados associado", + "Failed to create DOI for the Data Management Plan.": "Falha na criação do DOI para o Plano de Gestão de Dados", + "No entity found for query": "Não foi possível eliminar o item pretendido" } diff --git a/dmp-frontend/src/assets/i18n/sk.json b/dmp-frontend/src/assets/i18n/sk.json index 757b7ed09..b2b434eb8 100644 --- a/dmp-frontend/src/assets/i18n/sk.json +++ b/dmp-frontend/src/assets/i18n/sk.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "DMP v platforme Argos tvoria kľúčové informácie o výskume, ako sú napríklad účel, ciele, a zapojení výskumníci, ale aj informácie o dokumentácii výskumných súborov dát, hlavne o typoch súborov dát, ktoré ukazujú postupnosť krokov a prostriedkov používaných v rámci manažmentu dát.", "HINT": "Stručný opis toho, čoho sa DMP týka, jeho rozsah a ciele.", - "TYPING": "Napíšte viac písmen názvu, aby bolo možné nájsť správny DMP." + "TYPING": "Napíšte viac písmen názvu, aby bolo možné nájsť správny DMP.", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "You are using the DMP editor. Add here information about the scope, funding, actors of your DMP and decide on access and re-use issues for the DMP output that you are creating.", - "FIND": "Nenašli ste správny súbor?" + "FIND": "Nenašli ste správny súbor?", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "DMP v platforme Argos tvoria kľúčové informácie o výskume, ako sú napríklad účel, ciele, a zapojení výskumníci, ale aj o dokumentácii výskumných súborov dát, hlavne informácie o typoch súborov dát, ktoré ukazujú postupnosť krokov a prostriedkov používaných v rámci manažmentu dát.", diff --git a/dmp-frontend/src/assets/i18n/sr.json b/dmp-frontend/src/assets/i18n/sr.json index 26d49d8dd..33d91d8a9 100644 --- a/dmp-frontend/src/assets/i18n/sr.json +++ b/dmp-frontend/src/assets/i18n/sr.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "Plan upravljanja podacima (eng. Data Management Plan) u Argosu sadrži osnovne informacije o istraživanju, kao što su svrha i ciljevi istraživanja, ali i informacije o angažovanim istraživačima. Takođe, Plan sadrži i informacije o skupovima istraživačkih podataka koje ukazuju na procedure primenjene u upravljanju podacima.", "HINT": "Kratki opis Plana sa namenom i ciljevima.", - "TYPING": "Unesite još neko slovo da bismo lakše pronašli tačno ime." + "TYPING": "Unesite još neko slovo da bismo lakše pronašli tačno ime.", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "Plan upravljanja podacima (eng. Data Management Plan) se sastoji od Vaših planova za upravljanje podacima i sadrži informacije kako su nastali, kako su analizirani i na koji način su sačuvani podaci. Argos je otvoren kolaboracioni alat sa mogućnošću nadogradnje i koji podržava otvorene FAIR principe za upravljanje podacima.", - "FIND": "Niste pronašli?" + "FIND": "Niste pronašli?", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "Plan upravljanja podacima (eng. Data Management Plan) u Argosu sadrži osnovne informacije o istraživanju, kao što su svrha i ciljevi istraživanja, ali i informacije o angažovanim istraživačima. Plan sadrži i informacije o skupovima istraživačkih podataka koje ukazuju na procedure primenjene u upravljanju podacima.", diff --git a/dmp-frontend/src/assets/i18n/tr.json b/dmp-frontend/src/assets/i18n/tr.json index 158cb4ab6..0a4ac60a6 100644 --- a/dmp-frontend/src/assets/i18n/tr.json +++ b/dmp-frontend/src/assets/i18n/tr.json @@ -1004,11 +1004,20 @@ "MAIN-INFO": { "INTRO": "Argos'taki bir VYP, araştırma veri setlerinin dokümantasyonu, yani veri yönetimi faaliyetlerinde kullanılan araçları ve izlenen adımları vurgulayan veri seti açıklamaları gibi araştırma hakkında temel bilgilerden oluşur.", "HINT": "VYP'nin ne hakkında olduğunun, kapsamının ve hedeflerinin kısa bir açıklaması.", - "TYPING": "Doğru olanı bulabilmek için daha fazla harf yazın." + "TYPING": "Doğru olanı bulabilmek için daha fazla harf yazın.", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "RESEARCHER-IDENTIFIER-EXISTS": "A researcher with the given identifier already exists.", + "ORGANISATION-IDENTIFIER-EXSTS": "An organisation with the given identifier already exists.", + "IDENTIFIER-EXISTS-RESEARCHER-LIST":"This identifier is already used by a researcher in the researchers list.", + "IDENTIFIER-EXISTS-ORGANISATION-LIST":"This identifier is already used by an organisation in the organisations list." }, "FUNDING-INFO": { "INTRO": "You are using the DMP editor. Add here information about the scope, funding, actors of your DMP and decide on access and re-use issues for the DMP output that you are creating.", - "FIND": "Doğru bir tane bulamadınız mı?" + "FIND": "Doğru bir tane bulamadınız mı?", + "UNIQUE-IDENTIFIER": "Unique Identifier", + "IDENTIFIER-FUNDER-EXISTS": "A funder with the given identifier exists.", + "IDENTIFIER-GRANT-EXISTS": "A grant with the given identifier exists.", + "IDENTIFIER-PROJECT-EXISTS": "A project with the given identifier exists." }, "DATASET-INFO": { "INTRO": "Argos'taki bir VYP, araştırma veri setlerinin dokümantasyonu, yani, takip edilen adımları ve veri yönetimi faaliyetlerinde kullanılan araçları vurgulayan veri seti açıklamaları gibi araştırmayla ilgili amaç, hedefler ve araştırmacılar gibi önemli bilgilerden oluşur.",