Add contact field and "add cost" dialog

This commit is contained in:
George Kalampokis 2020-07-01 14:26:58 +03:00
parent 08f7d4aca4
commit a7a8e3db35
9 changed files with 222 additions and 8 deletions

View File

@ -0,0 +1,9 @@
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ValidationContext } from '@common/forms/validation/validation-context';
export interface CostModel {
code: string;
description: string;
title: string;
value: number;
}

View File

@ -32,6 +32,8 @@ import { FormValidationErrorsDialogModule } from '@common/forms/form-validation-
import { CommonUiModule } from '@common/ui/common-ui.module';
import { MultipleChoiceDialogModule } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.module';
import { AddOrganizationComponent } from './editor/add-organization/add-organization.component';
import { AddCostComponent } from './editor/cost-editor/add-cost/add-cost.component';
import { CostListingComponent } from './editor/cost-editor/cost-listing/cost-listing.component';
@NgModule({
imports: [
@ -69,7 +71,9 @@ import { AddOrganizationComponent } from './editor/add-organization/add-organiza
GrantTabComponent,
DatasetsTabComponent,
DmpCloneComponent,
AddOrganizationComponent
AddOrganizationComponent,
AddCostComponent,
CostListingComponent
],
entryComponents: [
DmpInvitationDialogComponent,
@ -77,7 +81,8 @@ import { AddOrganizationComponent } from './editor/add-organization/add-organiza
AvailableProfilesComponent,
DmpFinalizeDialogComponent,
DmpUploadDialogue,
AddOrganizationComponent
AddOrganizationComponent,
AddCostComponent
]
})
export class DmpModule { }

View File

@ -0,0 +1,28 @@
<form *ngIf="formGroup" [formGroup]="formGroup">
<h1 mat-dialog-title>{{'ADDEDITCOST-EDITOR.ADD-TITLE' | translate}}</h1>
<div mat-dialog-content class="row">
<mat-form-field class="col-12">
<app-single-auto-complete [formControl]="formGroup.get('code')" placeholder="{{'ADDEDITCOST-EDITOR.CODE' | translate}}" [configuration]="currencyAutoCompleteConfiguration">
</app-single-auto-complete>
<mat-error *ngIf="formGroup.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<mat-form-field class="col-12">
<input matInput formControlName="description" placeholder="{{'ADDEDITCOST-EDITOR.DESCRIPTION' | translate}}">
<mat-error *ngIf="formGroup.get('description').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<mat-form-field class="col-12">
<input matInput formControlName="title" placeholder="{{'ADDEDITCOST-EDITOR.TITLE' | translate}}" required>
<mat-error *ngIf="formGroup.get('title').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<mat-form-field class="col-12">
<input matInput formControlName="value" placeholder="{{'ADDEDITCOST-EDITOR.VALUE' | translate}}" type="number">
<mat-error *ngIf="formGroup.get('value').hasError('required')">{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<div class="col-12">
<div class="row">
<div class="ml-auto col-auto"><button mat-raised-button mat-dialog-close type="button">{{'ADDEDITCOST-EDITOR.ACTIONS.CANCEL' | translate}}</button></div>
<div class="col-auto"><button mat-raised-button [disabled]="!isFormValid()" color="primary" (click)="addCost()" type="button">{{'ADDEDITCOST-EDITOR.ACTIONS.SAVE' | translate}}</button></div>
</div>
</div>
</div>
</form>

View File

@ -0,0 +1,60 @@
import { Component, Inject, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ExternalResearcherService } from '@app/core/services/external-sources/researcher/external-researcher.service';
import { BaseComponent } from '@common/base/base.component';
import { takeUntil } from 'rxjs/operators';
import { CostEditorModel } from './add-cost.model';
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
import { Observable } from 'rxjs';
import { LocalFetchModel } from '@app/core/model/local-fetch/local-fetch.model';
import { CurrencyService } from '@app/core/services/currency/currency.service';
@Component({
selector: 'app-add-cost-component',
templateUrl: 'add-cost.component.html',
})
export class AddCostComponent extends BaseComponent implements OnInit {
public formGroup: FormGroup;
currencyAutoCompleteConfiguration: SingleAutoCompleteConfiguration = {
filterFn: this.searchCurrency.bind(this),
initialItems: () => this.searchCurrency(''),
displayFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
titleFn: (item) => typeof (item) == 'string' ? JSON.parse(item)['name'] : item.name,
valueAssign: (item) => typeof (item) == 'string' ? JSON.parse(item)['value'] : item.value
};
constructor(
private externalResearcherService: ExternalResearcherService,
public dialogRef: MatDialogRef<AddCostComponent>,
private currencyService: CurrencyService,
@Inject(MAT_DIALOG_DATA) public data: any
) { super(); }
ngOnInit(): void {
const cost = new CostEditorModel();
this.formGroup = cost.buildForm();
}
send(value: any) {
this.externalResearcherService.createResearcher(this.formGroup.value)
.pipe(takeUntil(this._destroyed))
.subscribe(
null, null, () => this.dialogRef.close()
);
}
addCost() {
this.dialogRef.close(this.formGroup.value);
}
isFormValid() {
return this.formGroup.valid;
}
searchCurrency(like: string): Observable<LocalFetchModel[]> {
return this.currencyService.get(like);
}
}

View File

@ -0,0 +1,44 @@
import { FormBuilder, FormGroup } from '@angular/forms';
import { ResearcherModel } from '@app/core/model/researcher/researcher';
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
import { ValidationContext } from '@common/forms/validation/validation-context';
import { OrganizationModel } from '@app/core/model/organisation/organization';
import { CostModel } from '@app/core/model/dmp/cost';
export class CostEditorModel implements CostModel{
public code: string;
public description: string;
public title: string;
public value: number;
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
fromModel(item: CostModel): CostEditorModel {
this.code = item.code;
this.description = item.description;
this.title = item.title;
this.value = item.value;
return this;
}
buildForm(context: ValidationContext = null, disabled: boolean = false): FormGroup {
if (context == null) { context = this.createValidationContext(); }
const formGroup = new FormBuilder().group({
code: [{ value: this.code, disabled: disabled }, context.getValidation('code').validators],
description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators],
title: [{ value: this.title, disabled: disabled }, context.getValidation('title').validators],
value: [{ value: this.value, disabled: disabled }, context.getValidation('value').validators]
});
return formGroup;
}
createValidationContext(): ValidationContext {
const baseContext: ValidationContext = new ValidationContext();
baseContext.validation.push({ key: 'code', validators: [] });
baseContext.validation.push({ key: 'description', validators: [] });
baseContext.validation.push({ key: 'title', validators: [BackendErrorValidator(this.validationErrorModel, 'title')] });
baseContext.validation.push({ key: 'value', validators: [] });
return baseContext;
}
}

View File

@ -1,18 +1,26 @@
import { ValidationContext } from '@common/forms/validation/validation-context';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
import { CostModel } from '@app/core/model/dmp/cost';
import { isNullOrUndefined } from 'util';
export class ExtraPropertiesFormModel {
public language: string;
public license: string;
public visible: boolean;
public publicDate: Date;
public contact: string;
public costs: CostModel[] = [];
fromModel(item: any): ExtraPropertiesFormModel {
this.language = item.language;
this.license = item.license;
this.visible = item.visible;
this.publicDate = item.publicDate;
this.contact = item.contact;
if (!isNullOrUndefined(item.costs)) {
this.costs = item.costs;
}
return this;
}
@ -23,7 +31,9 @@ export class ExtraPropertiesFormModel {
language: [{ value: this.language, disabled: disabled }, context.getValidation('language').validators],
license: [{ value: this.license, disabled: disabled }, context.getValidation('license').validators],
visible: [{ value: this.visible, disabled: disabled }, context.getValidation('visible').validators],
publicDate: [{ value: this.publicDate, disabled: disabled }, context.getValidation('publicDate').validators]
publicDate: [{ value: this.publicDate, disabled: disabled }, context.getValidation('publicDate').validators],
contact: [{ value: this.contact, disabled: disabled }, context.getValidation('contact').validators],
costs: [{ value: this.costs, disabled: disabled }, context.getValidation('costs').validators]
});
return formGroup;
}
@ -34,6 +44,8 @@ export class ExtraPropertiesFormModel {
baseContext.validation.push({ key: 'license', validators: [] });
baseContext.validation.push({ key: 'visible', validators: [] });
baseContext.validation.push({ key: 'publicDate', validators: [] });
baseContext.validation.push({ key: 'contact', validators: [] });
baseContext.validation.push({ key: 'costs', validators: [] });
return baseContext;
}

View File

@ -88,7 +88,7 @@
<app-single-auto-complete [formControl]="formGroup.get('extraProperties').get('license')" placeholder="{{'DMP-EDITOR.FIELDS.LICENSE' | translate}}" [configuration]="licenseAutoCompleteConfiguration">
</app-single-auto-complete>
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('backendError')">
{{formGroup.get('extraProperties').get('language').getError('backendError').message}}</mat-error>
{{formGroup.get('extraProperties').get('license').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('extraProperties').get('license').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
@ -117,13 +117,34 @@
<input matInput [matDatepicker]="picker" [formControl]="formGroup.get('extraProperties').get('publicDate')" placeholder="{{'DMP-EDITOR.FIELDS.PUBLICATION' | translate}}">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
<mat-error *ngIf="formGroup.get('extraProperties').get('visible').hasError('backendError')">
{{formGroup.get('extraProperties').get('visible').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('extraProperties').get('visible').hasError('required')">
<mat-error *ngIf="formGroup.get('extraProperties').get('publicDate').hasError('backendError')">
{{formGroup.get('extraProperties').get('publicDate').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('extraProperties').get('publicDate').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<!-- <h4 mat-subheader class="col-12">{{'DMP-EDITOR.FIELDS.PROFILE' | translate}}</h4> -->
</div>
<div class="row pt-3">
<mat-form-field class="col-sm-12 col-md-8">
<!-- <app-multiple-auto-complete [formControl]="formGroup.get('extraProperties').get('language')" placeholder="{{'DMP-EDITOR.FIELDS.RESEARCHERS' | translate}}" [configuration]="researchersAutoCompleteConfiguration">
</app-multiple-auto-complete> -->
<mat-select [formControl]="formGroup.get('extraProperties').get('contact')" placeholder="{{'DMP-EDITOR.FIELDS.CONTACT' | translate}}">
<mat-option *ngFor="let vis of getAssociates()" [value]="vis.id">
{{vis.name | translate}}
</mat-option>
</mat-select>
<mat-error *ngIf="formGroup.get('extraProperties').get('contact').hasError('backendError')">
{{formGroup.get('extraProperties').get('contact').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('extraProperties').get('contact').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<!-- <h4 mat-subheader class="col-12">{{'DMP-EDITOR.FIELDS.PROFILE' | translate}}</h4> -->
</div>
<div class="row pt-1">
<button matSuffix class="input-btn" type="button" (click)="addCost($event)">
<mat-icon class="icon-btn">add_circle</mat-icon>
</button>
</div>
<div class="row pt-2">
<mat-form-field class="col-sm-12 col-md-8">
<app-single-auto-complete [required]="false" [formControl]="formGroup.get('profile')" placeholder="{{'DMP-EDITOR.FIELDS.TEMPLATE' | translate}}" [configuration]="dmpProfileAutoCompleteConfiguration">

View File

@ -26,6 +26,7 @@ import { ConfigurationService } from '@app/core/services/configuration/configura
import { LanguageInfoService } from '@app/core/services/culture/language-info-service';
import { LanguageInfo } from '@app/core/model/language-info';
import { LicenseCriteria } from '@app/core/query/license/license-criteria';
import { AddCostComponent } from '../cost-editor/add-cost/add-cost.component';
interface Visible {
value: boolean;
@ -253,4 +254,25 @@ export class GeneralTabComponent extends BaseComponent implements OnInit {
getLanguageInfos(): LanguageInfo[] {
return this.languageInfoService.getLanguageInfoValues();
}
getAssociates(): any[] {
let associates: any[] = [];
//associates = (this.formGroup.get('researchers').value as any[]);
associates = associates.concat(this.formGroup.get('associatedUsers').value);
return associates;
}
addCost(event: MouseEvent) {
event.stopPropagation();
const dialogRef = this.dialog.open(AddCostComponent, {
data: this.formGroup.get('extraProperties').get('costs')
});
dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
if (result) {
const costsArray = this.formGroup.get('extraProperties').get('costs').value || [];
costsArray.push(result);
this.formGroup.get('extraProperties').get('costs').setValue(costsArray);
}
});
}
}

View File

@ -711,7 +711,8 @@
"LANGUAGE": "Language",
"LICENSE": "License",
"VISIBILITY": "Visibility",
"PUBLICATION": "Publication Date"
"PUBLICATION": "Publication Date",
"CONTACT": "Contact"
},
"ACTIONS": {
"GO-TO-GRANT": "Go To DMP Grant",
@ -986,6 +987,18 @@
"CANCEL": "Cancel"
}
},
"ADDEDITCOST-EDITOR": {
"ADD-TITLE": "Add a Cost",
"EDIT-TITLE": "Edit the Cost",
"CODE": "Code",
"DESCRIPTION": "Description",
"TITLE": "Title",
"VALUE": "Value",
"ACTIONS": {
"SAVE": "Save",
"CANCEL": "Cancel"
}
},
"DMP-WIZARD": {
"FIRST-STEP": {
"DMP": "DMP Editor",