diff --git a/dmp-frontend/src/app/core/common/enum/project-type.ts b/dmp-frontend/src/app/core/common/enum/project-type.ts new file mode 100644 index 000000000..3355f80ed --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/project-type.ts @@ -0,0 +1,4 @@ +export enum ProjectType { + External = 0, + Internal = 1 +} diff --git a/dmp-frontend/src/app/core/core-service.module.ts b/dmp-frontend/src/app/core/core-service.module.ts index 6b923628c..42148c2f3 100644 --- a/dmp-frontend/src/app/core/core-service.module.ts +++ b/dmp-frontend/src/app/core/core-service.module.ts @@ -26,6 +26,7 @@ import { UiNotificationService } from './services/notification/ui-notification-s import { ProgressIndicationService } from './services/progress-indication/progress-indication-service'; import { GrantFileUploadService } from './services/grant/grant-file-upload.service'; import { GrantService } from './services/grant/grant.service'; +import { ProjectService } from './services/project/project.service'; import { SearchBarService } from './services/search-bar/search-bar.service'; import { TimezoneService } from './services/timezone/timezone-service'; import { UserService } from './services/user/user.service'; @@ -34,6 +35,7 @@ import { TypeUtils } from './services/utilities/type-utils.service'; import { QuickWizardService } from './services/quick-wizard/quick-wizard.service'; import { OrganisationService } from './services/organisation/organisation.service'; import { EmailConfirmationService } from './services/email-confirmation/email-confirmation.service'; +import { FunderService } from './services/funder/funder.service'; // // // This is shared module that provides all the services. Its imported only once on the AppModule. @@ -69,6 +71,8 @@ export class CoreServiceModule { DashboardService, LanguageResolverService, GrantService, + ProjectService, + FunderService, GrantFileUploadService, DmpService, DmpProfileService, diff --git a/dmp-frontend/src/app/core/model/dmp/dmp.ts b/dmp-frontend/src/app/core/model/dmp/dmp.ts index ee0a894e3..fd91ba248 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp.ts @@ -7,6 +7,8 @@ import { UserModel } from "../user/user"; import { DmpDynamicField } from "./dmp-dynamic-field"; import { UserInfoListingModel } from "../user/user-info-listing"; import { DatasetModel } from "../dataset/dataset"; +import { ProjectModel } from "../project/project"; +import { FunderModel } from "../funder/funder"; export interface DmpModel { id: string; @@ -18,6 +20,8 @@ export interface DmpModel { lockable: boolean; description: String; grant: GrantListingModel; + project: ProjectModel; + funder: FunderModel; datasets: DatasetModel[]; datasetsToBeFinalized: string[]; profiles: DmpProfile[]; diff --git a/dmp-frontend/src/app/core/model/funder/funder.ts b/dmp-frontend/src/app/core/model/funder/funder.ts new file mode 100644 index 000000000..8a0046dfb --- /dev/null +++ b/dmp-frontend/src/app/core/model/funder/funder.ts @@ -0,0 +1,12 @@ +import { Status } from "../../common/enum/Status"; + +export class FunderModel { + id: string; + label: string; + reference: string; + definition: string; + status: Status; + created: Date; + modified: Date; + type: number; +} diff --git a/dmp-frontend/src/app/core/model/project/project.ts b/dmp-frontend/src/app/core/model/project/project.ts new file mode 100644 index 000000000..6f401f312 --- /dev/null +++ b/dmp-frontend/src/app/core/model/project/project.ts @@ -0,0 +1,26 @@ +import { Status } from "../../common/enum/Status"; +import { UrlListingItem } from "../../../library/url-listing/url-listing-item"; +import { ProjectType } from "../../common/enum/project-type"; + +export class ProjectModel { + id?: string; + label?: string; + abbreviation?: string; + reference?: string; + type?: ProjectType; + uri?: String; + status?: Status; + startDate?: Date; + endDate?: Date; + description?: String; + contentUrl?: string; + files?: ContentFile[]; + dmps?: UrlListingItem[]; +} + +export interface ContentFile { + filename?: string; + id?: string; + location?: string; + type?: 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 new file mode 100644 index 000000000..97a93a4e2 --- /dev/null +++ b/dmp-frontend/src/app/core/query/funder/funder-criteria.ts @@ -0,0 +1,3 @@ +import { BaseCriteria } from "../base-criteria"; + +export class FunderCriteria extends BaseCriteria { } diff --git a/dmp-frontend/src/app/core/query/project/project-criteria.ts b/dmp-frontend/src/app/core/query/project/project-criteria.ts new file mode 100644 index 000000000..a3b87757a --- /dev/null +++ b/dmp-frontend/src/app/core/query/project/project-criteria.ts @@ -0,0 +1,3 @@ +import { BaseCriteria } from "../base-criteria"; + +export class ProjectCriteria extends BaseCriteria { } diff --git a/dmp-frontend/src/app/core/services/funder/funder.service.ts b/dmp-frontend/src/app/core/services/funder/funder.service.ts new file mode 100644 index 000000000..aa5961fb8 --- /dev/null +++ b/dmp-frontend/src/app/core/services/funder/funder.service.ts @@ -0,0 +1,23 @@ +import { Observable } from "rxjs"; +import { Injectable } from "@angular/core"; +import { HttpHeaders } from "@angular/common/http"; +import { RequestItem } from "../../query/request-item"; +import { BaseCriteria } from "../../query/base-criteria"; +import { BaseHttpService } from "../http/base-http.service"; +import { environment } from '../../../../environments/environment'; +import { FunderCriteria } from "../../query/funder/funder-criteria"; + +@Injectable() +export class FunderService { + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'funders/'; + } + + getWithExternal(requestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'external', requestItem, { headers: this.headers }); + // return this.http.post(this.actionUrl + 'external', requestItem, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/core/services/project/project.service.ts b/dmp-frontend/src/app/core/services/project/project.service.ts new file mode 100644 index 000000000..710b20efc --- /dev/null +++ b/dmp-frontend/src/app/core/services/project/project.service.ts @@ -0,0 +1,23 @@ +import { Observable } from "rxjs"; +import { Injectable } from "@angular/core"; +import { HttpHeaders } from "@angular/common/http"; +import { RequestItem } from "../../query/request-item"; +import { BaseCriteria } from "../../query/base-criteria"; +import { BaseHttpService } from "../http/base-http.service"; +import { environment } from '../../../../environments/environment'; +import { ProjectCriteria } from "../../query/project/project-criteria"; + +@Injectable() +export class ProjectService { + private actionUrl: string; + private headers: HttpHeaders; + + constructor(private http: BaseHttpService) { + this.actionUrl = environment.Server + 'projects/'; + } + + getWithExternal(requestItem: RequestItem): Observable { + return this.http.post(this.actionUrl + 'external', requestItem, { headers: this.headers }); + // return this.http.post(this.actionUrl + 'external', requestItem, { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html index b548e8fca..e4344cbc4 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.html @@ -9,8 +9,7 @@

{{ 'DMP-EDITOR.TITLE.NEW' | translate }}

- @@ -30,8 +29,7 @@ save_alt{{ 'DMP-LISTING.ACTIONS.ADV-EXP' | translate }} -
@@ -51,7 +49,7 @@ work_outline {{ 'DMP-LISTING.COLUMNS.GRANT' | translate }} - + @@ -83,28 +81,25 @@
-
-
- -
-
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 63b043919..df8154172 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 @@ -34,6 +34,8 @@ import { AuthService } from '../../../core/services/auth/auth.service'; import { ExportMethodDialogComponent } from '../../../library/export-method-dialog/export-method-dialog.component'; import { UserInfoListingModel } from '../../../core/model/user/user-info-listing'; import { GrantTabModel } from './grant-tab/grant-tab-model'; +import { ProjectFormModel } from './grant-tab/project-form-model'; +import { FunderFormModel } from './grant-tab/funder-form-model'; @Component({ selector: 'app-dmp-editor-component', @@ -64,6 +66,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC private dmpProfileService: DmpProfileService, private dmpService: DmpService, private grantService: GrantService, + // private projectService: ProjectService, private externalSourcesService: ExternalSourcesService, private route: ActivatedRoute, private snackBar: MatSnackBar, @@ -84,7 +87,6 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC .pipe(takeUntil(this._destroyed)) .subscribe((params: Params) => { const itemId = params['id']; - const grantId = params['grantId']; const publicId = params['publicId']; const queryParams = this.route.snapshot.queryParams; const tabToNav = queryParams['tab']; @@ -108,6 +110,8 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC .subscribe(async data => { this.dmp = new DmpEditorModel(); this.dmp.grant = new GrantTabModel(); + this.dmp.project = new ProjectFormModel(); + this.dmp.funder = new FunderFormModel(); this.dmp.fromModel(data); this.formGroup = this.dmp.buildForm(); //this.registerFormEventsForDmpProfile(this.dmp.definition); @@ -135,19 +139,6 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.associatedUsers = data.associatedUsers; this.people = data.users; }); - } else if (grantId != null) { - this.isNew = true; - this.grantService.getSingle(grantId).map(data => data as GrantTabModel) - .pipe(takeUntil(this._destroyed)) - .subscribe(data => { - this.dmp = new DmpEditorModel(); - this.dmp.grant = new GrantTabModel(); - this.dmp.grant = data; - this.formGroup = this.dmp.buildForm(); - //this.registerFormEventsForDmpProfile(); - this.formGroup.get('grant').disable(); - this.registerFormEventsForNewItem(); - }); } else if (publicId != null) { this.isNew = false; this.isPublic = true; @@ -156,6 +147,8 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC .subscribe(async data => { this.dmp = new DmpEditorModel(); this.dmp.grant = new GrantTabModel(); + this.dmp.project = new ProjectFormModel(); + this.dmp.funder = new FunderFormModel(); this.dmp.fromModel(data); this.formGroup = this.dmp.buildForm(); //this.registerFormEventsForDmpProfile(this.dmp.definition); @@ -177,8 +170,11 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC // } }); } else { + console.log('4'); this.dmp = new DmpEditorModel(); this.dmp.grant = new GrantTabModel(); + this.dmp.project = new ProjectFormModel(); + this.dmp.funder = new FunderFormModel(); this.formGroup = this.dmp.buildForm(); this.registerFormEventsForNewItem(); if (this.isAuthenticated) { @@ -250,13 +246,13 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.dmpService.createDmp(this.formGroup.getRawValue()) .pipe(takeUntil(this._destroyed)) .subscribe( - complete => { - if (showAddDatasetDialog) { - this.addDatasetOpenDialog(complete); - } - else { this.onCallbackSuccess() } - }, - error => this.onCallbackError(error) + complete => { + if (showAddDatasetDialog) { + this.addDatasetOpenDialog(complete); + } + else { this.onCallbackSuccess() } + }, + error => this.onCallbackError(error) ); } @@ -304,8 +300,8 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.dmpService.delete(this.dmp.id) .pipe(takeUntil(this._destroyed)) .subscribe( - complete => { this.onCallbackSuccess() }, - error => this.onDeleteCallbackError(error) + complete => { this.onCallbackSuccess() }, + error => this.onDeleteCallbackError(error) ); } }); diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts index f289c5679..cd7bf98f8 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.model.ts @@ -19,6 +19,8 @@ import { DmpProfileExternalAutoCompleteFieldDataEditorModel } from "../../admin/ import { DmpProfileType } from "../../../core/common/enum/dmp-profile-type"; import { DmpProfileFieldDataType } from "../../../core/common/enum/dmp-profile-field-type"; import { DmpProfileField } from "../../../core/model/dmp-profile/dmp-profile-field"; +import { ProjectFormModel } from "./grant-tab/project-form-model"; +import { FunderFormModel } from "./grant-tab/funder-form-model"; export class DmpEditorModel { public id: string; @@ -31,6 +33,8 @@ export class DmpEditorModel { public status: Status = Status.Active; public description: String; public grant: GrantTabModel; + public project: ProjectFormModel; + public funder: FunderFormModel; public organisations: OrganizationModel[] = []; public researchers: ResearcherModel[] = []; public profiles: DmpProfile[] = []; @@ -52,6 +56,8 @@ export class DmpEditorModel { this.lockable = item.lockable; this.description = item.description; this.grant.fromModel(item.grant); + this.project.fromModel(item.project); + this.funder.fromModel(item.funder); this.organisations = item.organisations; this.researchers = item.researchers; this.profiles = item.profiles; @@ -77,6 +83,8 @@ export class DmpEditorModel { status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], description: [{ value: this.description, disabled: disabled }], grant: this.grant.buildForm(), + project: this.project.buildForm(), + funder: this.funder.buildForm(), organisations: [{ value: this.organisations, disabled: disabled }, context.getValidation('organisations').validators], researchers: [{ value: this.researchers, disabled: disabled }, context.getValidation('researchers').validators], profiles: [{ value: this.profiles, disabled: disabled }, context.getValidation('profiles').validators], @@ -112,6 +120,8 @@ export class DmpEditorModel { baseContext.validation.push({ key: 'status', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'status')] }); baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] }); baseContext.validation.push({ key: 'grant', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'grant')] }); + baseContext.validation.push({ key: 'project', validators: [BackendErrorValidator(this.validationErrorModel, 'project')] }); + baseContext.validation.push({ key: 'funder', validators: [BackendErrorValidator(this.validationErrorModel, 'funder')] }); baseContext.validation.push({ key: 'organisations', validators: [BackendErrorValidator(this.validationErrorModel, 'organisations')] }); baseContext.validation.push({ key: 'researchers', validators: [BackendErrorValidator(this.validationErrorModel, 'researchers')] }); baseContext.validation.push({ key: 'profiles', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.validationErrorModel, 'profiles')] }); 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 new file mode 100644 index 000000000..1108dc7ce --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/funder-form-model.ts @@ -0,0 +1,46 @@ +import { Status } from "../../../../core/common/enum/Status"; +import { FunderModel } from "../../../../core/model/funder/funder"; +import { ValidationErrorModel } from "../../../../common/forms/validation/error-model/validation-error-model"; +import { ValidationContext } from "../../../../common/forms/validation/validation-context"; +import { FormGroup, FormBuilder, Validators } from "@angular/forms"; +import { BackendErrorValidator } from "../../../../common/forms/validation/custom-validator"; +import { ValidJsonValidator } from "../../../../library/auto-complete/auto-complete-custom-validator"; + +export class FunderFormModel { + public id: string; + public label?: string; + public status: Status = Status.Active; + public definition: String; + public existFunder: FunderModel; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + + + fromModel(item: FunderModel): FunderFormModel { + this.existFunder = item; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } + + const formGroup = new FormBuilder().group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], + status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators], + definition: [{ value: this.definition, disabled: disabled }, context.getValidation('definition').validators], + existFunder: [{ value: this.existFunder, disabled: disabled }, context.getValidation('existFunder').validators], + }); + return formGroup; + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); + baseContext.validation.push({ key: 'status', validators: [] }); + baseContext.validation.push({ key: 'definition', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'definition')] }); + baseContext.validation.push({ key: 'existFunder', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.validationErrorModel, 'existFunder')] }); + return baseContext; + } + +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html index b74756506..2c11660f4 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.html @@ -1,53 +1,122 @@
- -
-
- keyboard_backspace - {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST' | translate}} + +
+
+ + + +
-
- add - {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.CREATE-NEW' | translate}} + + +
+ + + + {{funderFormGroup.get('label').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+ + +
+
+
+ settings_backup_restore + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST-FUNDER' | translate}} +
+
+ add + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.CREATE-NEW-FUNDER' | translate}} +
+
-
-
+
+
- +
-
- - -
-
- - + +
+ + {{formGroup.get('label').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} - - + + {{formGroup.get('description').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}}
+ + +
+
+
+ settings_backup_restore + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST' | translate}} +
+
+ add + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.CREATE-NEW' | translate}} +
+
+
+
+
+ + + + +
+ + +
+ + + + {{formGroup.get('label').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{formGroup.get('description').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}} + +
+ + +
+
+
+ settings_backup_restore + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST-PROJECT' | translate}} +
+
+ add + {{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.CREATE-NEW-PROJECT' | translate}} +
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.scss b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.scss index 502365566..c61311679 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.scss +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.scss @@ -1,8 +1,27 @@ -.add-grant { +.add-entity { display: flex; - justify-content: flex-end; - margin-top: 1.5em; - padding-right: 2em; + // justify-content: flex-end; + // margin-top: 1.5em; + align-self: center; + padding-bottom: 1em; cursor: pointer; color: #0070c0; } + +.add-entity:after { + background: none repeat scroll 0 0 transparent; + bottom: 0; + content: ""; + display: block; + height: 2px; + left: 50%; + position: absolute; + background: #0070c0; + transition: width 0.3s ease 0s, left 0.3s ease 0s; + width: 0; +} + +.add-entity:hover:after { + width: 100%; + left: 0; +} diff --git a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts index 44f98ed51..a86d1fc7d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/grant-tab.component.ts @@ -6,6 +6,10 @@ import { GrantCriteria } from '../../../../core/query/grant/grant-criteria'; import { GrantService } from '../../../../core/services/grant/grant.service'; import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service'; import { GrantTabModel } from './grant-tab-model'; +import { ProjectService } from '../../../../core/services/project/project.service'; +import { FunderService } from '../../../../core/services/funder/funder.service'; +import { FunderCriteria } from '../../../../core/query/funder/funder-criteria'; +import { ProjectCriteria } from '../../../../core/query/project/project-criteria'; @Component({ selector: 'app-grant-tab', @@ -15,15 +19,23 @@ import { GrantTabModel } from './grant-tab-model'; export class GrantTabComponent implements OnInit { @Input() formGroup: FormGroup; + @Input() projectFormGroup: FormGroup; + @Input() funderFormGroup: FormGroup; @Input() isNew: boolean; @Input() isFinalized: boolean; isCreateNew = false; + isCreateNewProject = false; + isCreateNewFunder = false; grant: GrantTabModel; grantAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration; + funderAutoCompleteConfiguration: SingleAutoCompleteConfiguration; constructor( private grantService: GrantService, + private projectService: ProjectService, + private funderService: FunderService, public languageResolverService: LanguageResolverService ) { } @@ -39,8 +51,26 @@ export class GrantTabComponent implements OnInit { titleFn: (item) => item['label'] }; + this.projectAutoCompleteConfiguration = { + filterFn: this.searchProject.bind(this), + initialItems: (extraData) => this.searchProject(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'] + } + + this.funderAutoCompleteConfiguration = { + filterFn: this.searchFunder.bind(this), + initialItems: (extraData) => this.searchFunder(''), + displayFn: (item) => item['label'], + titleFn: (item) => item['label'] + } + this.isCreateNew = (this.formGroup.get('label').value != null && this.formGroup.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); this.setValidators(); + this.setProjectValidators(); + this.setFunderValidators(); } searchGrant(query: string) { @@ -50,11 +80,35 @@ export class GrantTabComponent implements OnInit { return this.grantService.getWithExternal(grantRequestItem); } + searchProject(query: string) { + const projectRequestItem: RequestItem = new RequestItem(); + projectRequestItem.criteria = new GrantCriteria(); + projectRequestItem.criteria.like = query; + return this.projectService.getWithExternal(projectRequestItem); + } + + searchFunder(query: string) { + const funderRequestItem: RequestItem = new RequestItem(); + funderRequestItem.criteria = new FunderCriteria(); + funderRequestItem.criteria.like = query; + return this.funderService.getWithExternal(funderRequestItem); + } + create() { this.isCreateNew = !this.isCreateNew; this.setValidators(); } + createProject() { + this.isCreateNewProject = !this.isCreateNewProject; + this.setProjectValidators(); + } + + createFunder() { + this.isCreateNewFunder = !this.isCreateNewFunder; + this.setFunderValidators(); + } + setValidators() { if (this.isCreateNew) { this.formGroup.get('existGrant').disable(); @@ -74,4 +128,38 @@ export class GrantTabComponent implements OnInit { } } + setProjectValidators() { + if (this.isCreateNewProject) { + this.projectFormGroup.get('existProject').disable(); + this.projectFormGroup.get('label').enable(); + this.projectFormGroup.get('description').enable(); + } else if (this.isFinalized) { + this.projectFormGroup.get('existProject').disable(); + this.projectFormGroup.get('label').disable(); + this.projectFormGroup.get('description').disable(); + } + 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(); + } + } + + setFunderValidators() { + if (this.isCreateNewFunder) { + this.funderFormGroup.get('existFunder').disable(); + this.funderFormGroup.get('label').enable(); + } else if (this.isFinalized) { + this.funderFormGroup.get('existFunder').disable(); + this.funderFormGroup.get('label').disable(); + } + else { + this.funderFormGroup.get('existFunder').enable(); + this.funderFormGroup.get('label').disable(); + this.funderFormGroup.get('label').reset(); + } + } + } 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 new file mode 100644 index 000000000..931cbcee5 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/grant-tab/project-form-model.ts @@ -0,0 +1,46 @@ +import { Status } from "../../../../core/common/enum/Status"; +import { ProjectModel } from "../../../../core/model/project/project"; +import { ValidationErrorModel } from "../../../../common/forms/validation/error-model/validation-error-model"; +import { ValidationContext } from "../../../../common/forms/validation/validation-context"; +import { FormGroup, FormBuilder, Validators } from "@angular/forms"; +import { BackendErrorValidator } from "../../../../common/forms/validation/custom-validator"; +import { ValidJsonValidator } from "../../../../library/auto-complete/auto-complete-custom-validator"; + +export class ProjectFormModel { + public id: string; + public label?: string; + public status: Status = Status.Active; + public description: String; + public existProject: ProjectModel; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); + + + fromModel(item: ProjectModel): ProjectFormModel { + this.existProject = item; + return this; + } + + buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup { + if (context == null) { context = this.createValidationContext(); } + + const formGroup = new FormBuilder().group({ + id: [{ value: this.id, disabled: disabled }, context.getValidation('id').validators], + label: [{ value: this.label, disabled: disabled }, context.getValidation('label').validators], + 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], + }); + return formGroup; + } + + createValidationContext(): ValidationContext { + const baseContext: ValidationContext = new ValidationContext(); + baseContext.validation.push({ key: 'id', validators: [] }); + baseContext.validation.push({ key: 'label', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'label')] }); + baseContext.validation.push({ key: 'status', validators: [] }); + baseContext.validation.push({ key: 'description', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'description')] }); + baseContext.validation.push({ key: 'existProject', validators: [Validators.required, ValidJsonValidator, BackendErrorValidator(this.validationErrorModel, 'existProject')] }); + return baseContext; + } + +} diff --git a/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html index fc3400a05..36cb637cd 100644 --- a/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html +++ b/dmp-frontend/src/app/ui/dmp/wizard/editor/dmp-wizard-editor.component.html @@ -13,7 +13,7 @@ diff --git a/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.html b/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.html index 9c24bfe7f..6449d06f1 100644 --- a/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.html +++ b/dmp-frontend/src/app/ui/grant/listing/criteria/grant-criteria.component.html @@ -8,14 +8,14 @@ search - + {{'GENERAL.VALIDATION.GRANT-START-AFTER-END' | translate}} - + {{'GENERAL.VALIDATION.GRANT-START-AFTER-END' | translate}} diff --git a/dmp-frontend/src/app/ui/grant/listing/grant-listing.component.html b/dmp-frontend/src/app/ui/grant/listing/grant-listing.component.html index 54019523f..5090b1016 100644 --- a/dmp-frontend/src/app/ui/grant/listing/grant-listing.component.html +++ b/dmp-frontend/src/app/ui/grant/listing/grant-listing.component.html @@ -3,7 +3,7 @@
-

{{languageResolverService.getBy('listingTitle') | translate}}

+

{{'GRANT-LISTING.TITLE' | translate}}

diff --git a/dmp-frontend/src/app/ui/misc/navigation/navigation.component.html b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.html index 9c8c41a62..6c0094a15 100644 --- a/dmp-frontend/src/app/ui/misc/navigation/navigation.component.html +++ b/dmp-frontend/src/app/ui/misc/navigation/navigation.component.html @@ -6,8 +6,7 @@ {{'NAV-BAR.PUBLIC-DATASETS' | translate}}
- {{this.languageResolver.getBy('navbar') | - translate}} + {{'NAV-BAR.GRANTS' | translate}} {{'NAV-BAR.DMPS' | translate}} {{'NAV-BAR.DATASETS' | translate}} {{'NAV-BAR.USERS' | translate}} diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 784597401..48a2aa62a 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -552,7 +552,7 @@ }, "FIELDS": { "NAME": "Title", - "GRANT": "Related Grant", + "RELATED-GRANT": "Related Grant", "DESCRIPTION": "Description", "ORGANISATIONS": "Organizations", "ORGANISATIONS-HINT": "Add here the names of the organizations contributing to the creation and revision of the DMPs", @@ -561,6 +561,7 @@ "TEMPLATE": "DMP Template", "DATASET-TEMPLATES": "Related Dataset Description Templates", "PROFILE": "DMP Template", + "PROJECT": "Project", "GRANT": "Grant", "FUNDER": "Funder", "STATUS": "DMP Status" @@ -972,8 +973,12 @@ "SAVE-AND-FINALIZE": "Save and Finalize", "NEXT": "Next", "BACK": "Back", - "CREATE-NEW": "Add grant", - "EXIST": "Existing Grant" + "CREATE-NEW": "Add Grant", + "EXIST": "Use Existing Grant", + "CREATE-NEW-PROJECT": "Add Project", + "EXIST-PROJECT": "Use Existing Project", + "CREATE-NEW-FUNDER": "Add Funder", + "EXIST-FUNDER": "Use Existing Funder" }, "FIRST-STEP": { "TITLE": "Grant", @@ -982,7 +987,9 @@ "OR": "or", "FIELDS": { "SELECT-GRANT": "Select the grant that the DMP is associated with", - "LABEL": "Grant Name", + "GRANT-LABEL": "Grant Name", + "FUNDER-LABEL": "Funder Name", + "PROJECT-LABEL": "Project Name", "LABEL-HINT": "Add the name of the grant as it appears in the call for grant proposal", "DESCRIPTION": "Description", "DESCRIPTION-HINT": "Briefly explain the aims and objectives of the grant"