Adds the ability to create a Project from the DMP Editor - (Issue #87)

This commit is contained in:
apapachristou 2019-06-12 16:01:55 +03:00
parent aee4010d4d
commit edc411be40
9 changed files with 164 additions and 30 deletions

View File

@ -51,7 +51,7 @@
<mat-icon class="mr-2">work_outline</mat-icon>
{{ 'DMP-LISTING.COLUMNS.PROJECT' | translate }}
</ng-template>
<app-project-tab [formGroup]="formGroup"></app-project-tab>
<app-project-tab [formGroup]="formGroup.get('project')" [isNew]="isNew"></app-project-tab>
</mat-tab>
<mat-tab [disabled]="isNew">
<ng-template mat-tab-label>
@ -95,7 +95,10 @@
</button>
</div> -->
<div *ngIf="this.formGroup.enabled">
<button mat-raised-button type="submit" [disabled]="!formGroup.valid" class="text-uppercase dark-theme mr-2" color="primary">
<button *ngIf="!isNew" mat-raised-button type="submit" [disabled]="!formGroup.valid" class="text-uppercase dark-theme mr-2" color="primary">
{{'DMP-EDITOR.ACTIONS.SAVE-CHANGES' | translate}}
</button>
<button *ngIf="isNew" mat-raised-button type="submit" [disabled]="!formGroup.valid" class="text-uppercase dark-theme mr-2" color="primary">
{{'DMP-EDITOR.ACTIONS.SAVE' | translate}}
</button>
</div>

View File

@ -42,6 +42,7 @@ import { DmpFinalizeDialogComponent } from './dmp-finalize-dialog/dmp-finalize-d
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 { ProjectTabModel } from './project-tab/project-tab-model';
@Component({
selector: 'app-dmp-editor-component',
@ -110,7 +111,9 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
this.dmpService.getSingle(itemId).map(data => data as DmpModel)
.pipe(takeUntil(this._destroyed))
.subscribe(async data => {
this.dmp = new DmpEditorModel().fromModel(data);
this.dmp = new DmpEditorModel();
this.dmp.project = new ProjectTabModel();
this.dmp.fromModel(data);
this.formGroup = this.dmp.buildForm();
//this.registerFormEventsForDmpProfile(this.dmp.definition);
if (!this.editMode || this.dmp.status === Status.Inactive) { this.formGroup.disable(); }
@ -122,7 +125,6 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
label: this.language.instant('NAV-BAR.MY-DMPS'),
url: "/plans"
});
const breadcrumb = await this.projectService.getSingle(this.dmp.project.id).map(x => ({ label: x.label, url: '/projects/edit/' + x.id }) as BreadcrumbItem).toPromise();
breadCrumbs.push({
parentComponentName: 'DmpListingComponent',
label: this.dmp.label,
@ -137,10 +139,11 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
});
} else if (projectId != null) {
this.isNew = true;
this.projectService.getSingle(projectId).map(data => data as ProjectListingModel)
this.projectService.getSingle(projectId).map(data => data as ProjectTabModel)
.pipe(takeUntil(this._destroyed))
.subscribe(data => {
this.dmp = new DmpEditorModel();
this.dmp.project = new ProjectTabModel();
this.dmp.project = data;
this.formGroup = this.dmp.buildForm();
//this.registerFormEventsForDmpProfile();
@ -153,7 +156,9 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
this.dmpService.getSinglePublic(publicId).map(data => data as DmpModel)
.pipe(takeUntil(this._destroyed))
.subscribe(async data => {
this.dmp = new DmpEditorModel().fromModel(data);
this.dmp = new DmpEditorModel();
this.dmp.project = new ProjectTabModel();
this.dmp.fromModel(data);
this.formGroup = this.dmp.buildForm();
//this.registerFormEventsForDmpProfile(this.dmp.definition);
if (!this.editMode || this.dmp.status === Status.Inactive) { this.formGroup.disable(); }
@ -175,6 +180,7 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC
});
} else {
this.dmp = new DmpEditorModel();
this.dmp.project = new ProjectTabModel();
this.formGroup = this.dmp.buildForm();
this.registerFormEventsForNewItem();
if (this.isAuthenticated) {

View File

@ -14,6 +14,7 @@ import { UserModel } from "../../../core/model/user/user";
import { ValidJsonValidator } from "../../../library/auto-complete/auto-complete-custom-validator";
import { UserInfoListingModel } from "../../../core/model/user/user-info-listing";
import { DatasetModel } from "../../../core/model/dataset/dataset";
import { ProjectTabModel } from "./project-tab/project-tab-model";
export class DmpEditorModel {
public id: string;
@ -25,7 +26,7 @@ export class DmpEditorModel {
public creator: UserModel;
public status: Status = Status.Active;
public description: String;
public project: ProjectListingModel;
public project: ProjectTabModel;
public organisations: OrganizationModel[] = [];
public researchers: ResearcherModel[] = [];
public profiles: DmpProfile[] = [];
@ -45,7 +46,7 @@ export class DmpEditorModel {
this.status = item.status;
this.lockable = item.lockable;
this.description = item.description;
this.project = item.project;
this.project.fromModel(item.project);
this.organisations = item.organisations;
this.researchers = item.researchers;
this.profiles = item.profiles;
@ -69,7 +70,7 @@ export class DmpEditorModel {
version: [{ value: this.version, disabled: disabled }, context.getValidation('version').validators],
status: [{ value: this.status, disabled: disabled }, context.getValidation('status').validators],
description: [{ value: this.description, disabled: disabled }],
project: [{ value: this.project, disabled: disabled }, context.getValidation('project').validators],
project: this.project.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],

View File

@ -0,0 +1,49 @@
import { Status } from "../../../../core/common/enum/Status";
import { ProjectListingModel } from "../../../../core/model/project/project-listing";
import { ValidationErrorModel } from "../../../../common/forms/validation/error-model/validation-error-model";
import { ProjectEditorWizardModel } from "../../../quick-wizard/project-editor/project-editor-wizard-model";
import { ValidationContext } from "../../../../common/forms/validation/validation-context";
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
import { BackendErrorValidator } from "../../../../common/forms/validation/custom-validator";
import { ValidJsonValidator } from "../../../../library/auto-complete/auto-complete-custom-validator";
export class ProjectTabModel {
public id: string;
public label?: string;
public status: Status = Status.Active;
public description: String;
public existProject: ProjectListingModel;
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
fromModel(item: ProjectListingModel): ProjectTabModel {
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;
}
}

View File

@ -1,17 +1,53 @@
<div class="container-fluid">
<div class="row">
<div class="col-6 pt-4 pb-4 pl-4">
<mat-form-field>
<app-single-auto-complete required='true' [formControl]="formGroup.get('project')"
placeholder="{{this.languageResolverService.getBy('dmpEditor') | translate}}"
[configuration]="projectAutoCompleteConfiguration">
</app-single-auto-complete>
<mat-error *ngIf="formGroup.get('project').hasError('backendError')">
{{formGroup.get('project').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('project').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<form *ngIf="formGroup" [formGroup]="formGroup">
<!-- Toggle Between Add Project or Use Existing -->
<div class="row">
<div class="col-12 add-project" *ngIf="isCreateNew" (click)="create()">
<mat-icon>keyboard_backspace</mat-icon>
<span>{{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.EXIST' | translate}}</span>
</div>
<div class="col-12 add-project" *ngIf="!isCreateNew" (click)="create()">
<mat-icon>add</mat-icon>
<span>{{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.ACTIONS.CREATE-NEW' | translate}}</span>
</div>
</div>
<!-- Create New DMP Mode -->
<div class="row" *ngIf="!isCreateNew">
<div class="col-6 pb-4 pl-4">
<mat-form-field>
<app-single-auto-complete required='true' [formControl]="formGroup.get('existProject')"
placeholder="{{this.languageResolverService.getBy('dmpEditor') | translate}}"
[configuration]="projectAutoCompleteConfiguration">
</app-single-auto-complete>
</mat-form-field>
</div>
</div>
<!-- <app-dynamic-fields-project [formGroup]="formGroup"></app-dynamic-fields-project> -->
</div>
<!-- Create New Project -->
<div class="row" *ngIf="isCreateNew">
<div class="col-6 pb-4 pl-4">
<mat-form-field class="col-md-12">
<input matInput
placeholder="{{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.FIRST-STEP.FIELDS.LABEL' | translate}}"
type="text" name="label" [formControl]="formGroup.get('label')" required>
<mat-error *ngIf="formGroup.get('label').hasError('backendError')">
{{formGroup.get('label').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('label').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
<mat-form-field class="col-md-12">
<textarea matInput class="description-area"
placeholder="{{'QUICKWIZARD.CREATE-ADD.CREATE.QUICKWIZARD_CREATE.FIRST-STEP.FIELDS.DESCRIPTION' | translate}}"
[formControl]="formGroup.get('description')" required></textarea>
<mat-error *ngIf="formGroup.get('description').hasError('backendError')">
{{formGroup.get('description').getError('backendError').message}}</mat-error>
<mat-error *ngIf="formGroup.get('description').hasError('required')">
{{'GENERAL.VALIDATION.REQUIRED' | translate}}</mat-error>
</mat-form-field>
</div>
</div>
</form>
</div>

View File

@ -0,0 +1,8 @@
.add-project {
display: flex;
justify-content: flex-end;
margin-top: 1.5em;
padding-right: 2em;
cursor: pointer;
color: #0070c0;
}

View File

@ -5,6 +5,7 @@ import { RequestItem } from '../../../../core/query/request-item';
import { ProjectCriteria } from '../../../../core/query/project/project-criteria';
import { ProjectService } from '../../../../core/services/project/project.service';
import { LanguageResolverService } from '../../../../services/language-resolver/language-resolver.service';
import { ProjectTabModel } from './project-tab-model';
@Component({
selector: 'app-project-tab',
@ -13,7 +14,10 @@ import { LanguageResolverService } from '../../../../services/language-resolver/
})
export class ProjectTabComponent implements OnInit {
@Input() formGroup: FormGroup = null;
@Input() formGroup: FormGroup;
@Input() isNew: boolean;
isCreateNew = false;
project: ProjectTabModel;
projectAutoCompleteConfiguration: SingleAutoCompleteConfiguration;
@ -23,12 +27,25 @@ export class ProjectTabComponent implements OnInit {
) { }
ngOnInit() {
const projectRequestItem: RequestItem<ProjectCriteria> = new RequestItem();
projectRequestItem.criteria = new ProjectCriteria();
this.projectAutoCompleteConfiguration = {
filterFn: this.searchProject.bind(this),
initialItems: (extraData) => this.searchProject(''),
displayFn: (item) => item['label'],
titleFn: (item) => item['label']
};
if (!this.formGroup) {
this.project = new ProjectTabModel();
this.formGroup = this.project.buildForm();
}
this.formGroup.get('existProject').enable();
this.formGroup.get('label').disable();
this.formGroup.get('description').disable();
}
searchProject(query: string) {
@ -38,4 +55,20 @@ export class ProjectTabComponent implements OnInit {
return this.projectService.getWithExternal(projectRequestItem);
}
create() {
this.isCreateNew = !this.isCreateNew;
if (this.isCreateNew) {
this.formGroup.get('existProject').disable();
// this.formGroup.get('existProject').reset();
this.formGroup.get('label').enable();
this.formGroup.get('description').enable();
} else {
this.formGroup.get('existProject').enable();
this.formGroup.get('label').disable();
this.formGroup.get('label').reset();
this.formGroup.get('description').disable();
this.formGroup.get('description').reset();
}
}
}

View File

@ -18,19 +18,16 @@ export class QuickWizardEditorWizardModel {
fromModelProject(item: ProjectListingModel): QuickWizardEditorWizardModel {
this.project.fromModel(item);
return this;
}
fromModelDmp(item: DmpModel): QuickWizardEditorWizardModel {
this.dmp.fromModel(item);
return this;
}
fromModelDataset(item: DatasetWizardEditorModel[]): QuickWizardEditorWizardModel {
this.datasets.fromModel(item);
return this;
}
@ -40,7 +37,7 @@ export class QuickWizardEditorWizardModel {
project: new ProjectEditorWizardModel().buildForm(),
dmp: new DmpEditorWizardModel().buildForm(),
datasets: new DatasetEditorWizardModel().buildForm()
});
return formGroup;
}
@ -49,8 +46,8 @@ export class QuickWizardEditorWizardModel {
// const baseContext: ValidationContext = new ValidationContext();
// baseContext.validation.push({ key: 'project', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'project')] });
// baseContext.validation.push({ key: 'dmp', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'dmp')] });
// baseContext.validation.push({ key: 'datasets', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'datasets')] });
// baseContext.validation.push({ key: 'datasets', validators: [Validators.required, BackendErrorValidator(this.validationErrorModel, 'datasets')] });
// return baseContext;
// }
}
}

View File

@ -481,7 +481,8 @@
"ACTIONS": {
"GO-TO-PROJECT": "Go To DMP Project",
"GO-TO-DATASETS": "Go To Datasets",
"SAVE": "Save Changes",
"SAVE-CHANGES": "Save Changes",
"SAVE": "Save",
"CANCEL": "Cancel",
"DELETE": "Delete",
"FINALISE": "Finalize"