From e179d90f127ccf9b6b0e8f86cf120be06edd445e Mon Sep 17 00:00:00 2001 From: apapachristou Date: Thu, 15 Oct 2020 13:46:59 +0300 Subject: [PATCH] Adds progress bar on DMP editor --- dmp-frontend/src/app/ui/dmp/dmp.module.ts | 5 +- .../ui/dmp/editor/dmp-editor.component.html | 17 +++- .../ui/dmp/editor/dmp-editor.component.scss | 8 ++ .../app/ui/dmp/editor/dmp-editor.component.ts | 25 +++++- .../src/app/ui/dmp/editor/dmp-editor.model.ts | 6 +- .../funding-info/funding-info.component.html | 4 +- .../extra-properties-form.model.ts | 14 ++-- .../editor/grant-tab/project-form-model.ts | 4 +- .../editor/main-info/main-info.component.html | 18 ++--- .../form-progress-indication.component.html | 4 +- .../form-progress-indication.component.scss | 16 ++++ .../form-progress-indication.component.ts | 81 ++++++++++++++++--- .../form-progress-indication.module.ts | 18 +++++ .../dataset-description-form.module.ts | 5 +- 14 files changed, 186 insertions(+), 39 deletions(-) create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.scss create mode 100644 dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module.ts diff --git a/dmp-frontend/src/app/ui/dmp/dmp.module.ts b/dmp-frontend/src/app/ui/dmp/dmp.module.ts index 243f3e605..3f37ce449 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp.module.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp.module.ts @@ -46,6 +46,8 @@ import { LicenseInfoComponent } from './editor/license-info/license-info.compone import { StartNewDatasetDialogComponent } from './start-new-dataset-dialogue/start-new-dataset-dialog.component'; import { NgxDropzoneModule } from 'ngx-dropzone'; import { DmpToDatasetDialogComponent } from './dmp-to-dataset/dmp-to-dataset-dialog.component'; +import { FormProgressIndicationComponent } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component'; +import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module'; @NgModule({ imports: [ @@ -62,7 +64,8 @@ import { DmpToDatasetDialogComponent } from './dmp-to-dataset/dmp-to-dataset-dia MultipleChoiceDialogModule, DatasetEditorDetailsModule, DatasetDescriptionFormModule, - NgxDropzoneModule + NgxDropzoneModule, + FormProgressIndicationModule ], declarations: [ DmpListingComponent, 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 9e4f13bf1..39392ceac 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 @@ -33,10 +33,18 @@
{{'DMP-EDITOR.STEPPER.USER-GUIDE' | translate}}
    -
  1. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (7)
  2. -
  3. {{'DMP-EDITOR.STEPPER.FUNDING-INFO' | translate}} (3)
  4. +
  5. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (1)
  6. +
  7. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (done)
  8. +
  9. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (2)
  10. +
  11. {{'DMP-EDITOR.STEPPER.MAIN-INFO' | translate}} (done)
  12. + +
  13. {{'DMP-EDITOR.STEPPER.FUNDING-INFO' | translate}} (2)
  14. +
  15. {{'DMP-EDITOR.STEPPER.FUNDING-INFO' | translate}} (done)
  16. +
  17. {{'DMP-EDITOR.STEPPER.LICENSE-INFO' | translate}}
  18. -
  19. {{'DMP-EDITOR.STEPPER.DATASET-INFO' | translate}}
  20. + +
  21. {{'DMP-EDITOR.STEPPER.DATASET-INFO' | translate}} (1)
  22. +
  23. {{'DMP-EDITOR.STEPPER.DATASET-INFO' | translate}} (done)
  24. @@ -70,6 +78,9 @@
    {{'DMP-EDITOR.ACTIONS.SAVE' | translate}} & {{'DMP-LISTING.ACTIONS.ADD-DATASET-SHORT' | translate}}
+
+ +
diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss index 7126fa67e..e36d917d7 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-editor.component.scss @@ -442,6 +442,14 @@ mat-icon.size-16 { list-style-type: none; } +.done-icon { + display: inline-flex; + vertical-align: middle; + font-size: 16px !important; + height: auto; + width: auto; +} + // ::ng-deep .mat-tab-labels { // justify-content: space-between; // } 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 e37083cbc..6e5a702a3 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 @@ -413,7 +413,6 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC } public isFormValid() { - this.formGroup.markAllAsTouched(); return this.formGroup.valid; // return this.formGroup.get('label').valid && this.formGroup.get('profiles').valid && // (this.formGroup.get('funder').get('label').valid || this.formGroup.get('funder').get('existFunder').valid) && @@ -896,6 +895,30 @@ export class DmpEditorComponent extends BaseComponent implements OnInit, IBreadC this.dmp.id != null ? this.router.navigate(['/plans', 'edit', this.dmp.id]) : this.router.navigate(['/plans']); } + mainInfoValid(): boolean { + if (this.formGroup.get('label').valid) { + if (this.formGroup.get('publicDate')) { + if (this.formGroup.get('publicDate').valid) { + return true; + } else if (this.formGroup.get('publicDate').invalid) { + return false + } + } else { + return true; + } + } else { + return false; + } + } + + fundingInfoValid(): boolean { + return this.formGroup.get('funder') && this.formGroup.get('funder').valid && this.formGroup.get('grant') && this.formGroup.get('grant').valid; + } + + datasetInfoValid(): boolean { + return this.formGroup.get('profiles') && this.formGroup.get('profiles').valid && this.formGroup.get('profiles').value.length > 0; + } + // advancedClicked() { // const dialogRef = this.dialog.open(ExportMethodDialogComponent, { // maxWidth: '500px', 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 38edd04aa..b95e0e8e0 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 @@ -92,7 +92,7 @@ export class DmpEditorModel { groupId: [{ value: this.groupId, disabled: disabled }, context.getValidation('groupId').validators], 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 }], + description: [{ value: this.description, disabled: disabled }, context.getValidation('description').validators], grant: this.grant.buildForm(), project: this.project.buildForm(), funder: this.funder.buildForm(), @@ -135,10 +135,10 @@ export class DmpEditorModel { baseContext.validation.push({ key: 'groupId', validators: [BackendErrorValidator(this.validationErrorModel, 'groupId')] }); baseContext.validation.push({ key: 'version', validators: [BackendErrorValidator(this.validationErrorModel, 'version')] }); 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: 'description', validators: [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: 'funder', validators: [Validators.required, 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/funding-info/funding-info.component.html b/dmp-frontend/src/app/ui/dmp/editor/funding-info/funding-info.component.html index 5a1bfa8d1..61104beb1 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 @@ -112,14 +112,14 @@
- + {{projectFormGroup.get('label').getError('backendError').message}} {{'GENERAL.VALIDATION.REQUIRED' | translate}} - + {{projectFormGroup.get('description').getError('backendError').message}} diff --git a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts index c2dc45d91..6ff2f48cb 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/general-tab/extra-properties-form.model.ts @@ -4,6 +4,7 @@ import { BackendErrorValidator } from '@common/forms/validation/custom-validator import { CostModel } from '@app/core/model/dmp/cost'; import { isNullOrUndefined } from 'util'; import { CostEditorModel } from '../cost-editor/add-cost/add-cost.model'; +import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model'; export class ExtraPropertiesFormModel { public language: string; @@ -12,6 +13,7 @@ export class ExtraPropertiesFormModel { public publicDate: Date; public contact: string; public costs: CostEditorModel[] = []; + public validationErrorModel: ValidationErrorModel = new ValidationErrorModel(); fromModel(item: any): ExtraPropertiesFormModel { this.language = item.language; @@ -53,12 +55,12 @@ export class ExtraPropertiesFormModel { createValidationContext(): ValidationContext { const baseContext: ValidationContext = new ValidationContext(); - baseContext.validation.push({ key: 'language', validators: [] }); - 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: [] }); + baseContext.validation.push({ key: 'language', validators: [BackendErrorValidator(this.validationErrorModel, 'language')] }); + baseContext.validation.push({ key: 'license', validators: [BackendErrorValidator(this.validationErrorModel, 'license')] }); + baseContext.validation.push({ key: 'visible', validators: [BackendErrorValidator(this.validationErrorModel, 'visible')] }); + baseContext.validation.push({ key: 'publicDate', validators: [BackendErrorValidator(this.validationErrorModel, 'publicDate')] }); + baseContext.validation.push({ key: 'contact', validators: [BackendErrorValidator(this.validationErrorModel, 'contact')] }); + baseContext.validation.push({ key: 'costs', validators: [BackendErrorValidator(this.validationErrorModel, 'costs')] }); 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 826221b30..83178a711 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 @@ -36,9 +36,9 @@ export class ProjectFormModel { 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: 'label', validators: [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: 'description', validators: [BackendErrorValidator(this.validationErrorModel, 'description')] }); baseContext.validation.push({ key: 'existProject', validators: [BackendErrorValidator(this.validationErrorModel, 'existProject')] }); return baseContext; } diff --git a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html index aa20383a8..f83b80bf7 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/main-info/main-info.component.html @@ -127,7 +127,7 @@
-
1.7 {{'DMP-EDITOR.FIELDS.CONTACT' | translate}}
+
1.7 {{'DMP-EDITOR.FIELDS.CONTACT' | translate}}*
@@ -147,17 +147,17 @@
-
1.8 {{'DMP-EDITOR.FIELDS.PUBLICATION' | translate}}
+
1.8 {{'DMP-EDITOR.FIELDS.PUBLICATION' | translate}}*
- - - - - {{formGroup.get('extraProperties').get('publicDate').getError('backendError').message}} - - {{'GENERAL.VALIDATION.REQUIRED' | translate}} + + + + + {{formGroup.get('extraProperties').get('publicDate').getError('backendError').message}} + + {{'GENERAL.VALIDATION.REQUIRED' | translate}}
diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html index d25935d91..8244bf0e9 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.html @@ -1,3 +1,5 @@ 
- +
{{progressSoFar}} {{'GENERAL.PREPOSITIONS.OF' | translate}} {{total}}
+ +
{{value}}%
diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.scss b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.scss new file mode 100644 index 000000000..a15510639 --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.scss @@ -0,0 +1,16 @@ +.percentage { + color: #212121; + opacity: 0.7; + font-weight: 400; + font-size: 0.875rem; +} + +.progress-bar { + border-radius: 20px; + height: 11px; + +} + +::ng-deep .mat-progress-bar .mat-progress-bar-fill::after { + border-radius: 20px !important; +} diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts index 9a9b222d4..fc9fa6b3d 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.component.ts @@ -1,36 +1,46 @@ -import { Component, Input, OnInit } from '@angular/core'; -import { AbstractControl, FormArray, FormGroup } from '@angular/forms'; +import { Component, ElementRef, Input, OnInit } from '@angular/core'; +import { AbstractControl, FormArray, FormControl, FormGroup } from '@angular/forms'; import { VisibilityRulesService } from '@app/ui/misc/dataset-description-form/visibility-rules/visibility-rules.service'; import { BaseComponent } from '@common/base/base.component'; import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-form-progress-indication', - templateUrl: './form-progress-indication.component.html' + templateUrl: './form-progress-indication.component.html', + styleUrls: ['./form-progress-indication.component.scss'] }) export class FormProgressIndicationComponent extends BaseComponent implements OnInit { @Input() formGroup: FormGroup; + @Input() isEditor: boolean; @Input() public progressValueAccuracy = 2; determinateProgressValue: number; + progressSoFar: number; + total: number; + percent: number; constructor(private visibilityRulesService: VisibilityRulesService) { super(); } public value = 0; ngOnInit() { - this.calculateValueForProgressbar(); + setTimeout(() => {this.calculateValueForProgressbar();}); this.formGroup .valueChanges .pipe(takeUntil(this._destroyed)) .subscribe(control => { - this.calculateValueForProgressbar(); + setTimeout(() => {this.calculateValueForProgressbar();}); }); } calculateValueForProgressbar() { - const progressSoFar = this.countFormControlsWithValueForProgress(this.formGroup); - const total = this.CountFormControlDepthLengthFotTotal(this.formGroup); - const perc = (progressSoFar / total) * 100; - this.value = Number.parseFloat(perc.toPrecision(this.progressValueAccuracy)); + if (this.isEditor) { + this.progressSoFar = this.countFormControlsValidForProgress(this.formGroup); + this.total = this.countFormControlsRequiredFieldsForTotal(this.formGroup); + } else { + this.progressSoFar = this.countFormControlsWithValueForProgress(this.formGroup); + this.total = this.CountFormControlDepthLengthFotTotal(this.formGroup); + } + this.percent = (this.progressSoFar / this.total) * 100; + this.value = Number.parseFloat(this.percent.toPrecision(this.progressValueAccuracy)); } countFormControlsWithValueForProgress(formControl: AbstractControl): number { @@ -125,4 +135,57 @@ export class FormProgressIndicationComponent extends BaseComponent implements On } return valueCurent; } + + countFormControlsValidForProgress(formControl: AbstractControl): number { + let valueCurrent = 0; + if (formControl instanceof FormControl) { + if (this.controlRequired(formControl) && this.controlEnabled(formControl) && formControl['nativeElement'] && formControl.valid) { + valueCurrent++; + } + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + valueCurrent = valueCurrent + this.countFormControlsValidForProgress(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + valueCurrent = valueCurrent + this.countFormControlsValidForProgress(item); + }); + } + return valueCurrent; + } + + countFormControlsRequiredFieldsForTotal(formControl: AbstractControl): number { + let valueCurrent = 0; + if (formControl instanceof FormControl) { + if (this.controlRequired(formControl) && this.controlEnabled(formControl) && formControl['nativeElement']) { + valueCurrent++; + } + } else if (formControl instanceof FormGroup) { + Object.keys(formControl.controls).forEach(item => { + const control = formControl.get(item); + valueCurrent = valueCurrent + this.countFormControlsRequiredFieldsForTotal(control); + }); + } else if (formControl instanceof FormArray) { + formControl.controls.forEach(item => { + valueCurrent = valueCurrent + this.countFormControlsRequiredFieldsForTotal(item); + }); + } + return valueCurrent; + } + + controlRequired(formControl: AbstractControl) { + if (formControl.validator) { + const validator = formControl.validator({} as AbstractControl); + if (validator && validator.required) { + return true; + } + } else { return false } + } + + controlEnabled(formControl: AbstractControl) { + if (formControl.enabled) { + return true; + } else { return false } + } } diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module.ts new file mode 100644 index 000000000..f287d329d --- /dev/null +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { CommonFormsModule } from '@common/forms/common-forms.module'; +import { CommonUiModule } from '@common/ui/common-ui.module'; +import { FormProgressIndicationComponent } from './form-progress-indication.component'; + +@NgModule({ + imports: [ + CommonUiModule, + CommonFormsModule + ], + declarations: [ + FormProgressIndicationComponent + ], + exports: [ + FormProgressIndicationComponent + ] +}) +export class FormProgressIndicationModule { } diff --git a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts index 0fd99cddc..6dbc01fa1 100644 --- a/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts +++ b/dmp-frontend/src/app/ui/misc/dataset-description-form/dataset-description-form.module.ts @@ -12,18 +12,19 @@ import { CommonUiModule } from '@common/ui/common-ui.module'; import { FormCompositeTitleComponent } from './components/form-composite-title/form-composite-title.component'; import { ExternalSourcesModule } from '../external-sources/external-sources.module'; import { DatasetDescriptionComponent } from './dataset-description.component'; +import { FormProgressIndicationModule } from './components/form-progress-indication/form-progress-indication.module'; @NgModule({ imports: [ CommonUiModule, CommonFormsModule, AutoCompleteModule, - ExternalSourcesModule + ExternalSourcesModule, + FormProgressIndicationModule ], declarations: [ DatasetDescriptionFormComponent, DatasetDescriptionComponent, - FormProgressIndicationComponent, FormSectionComponent, FormCompositeFieldComponent, FormFieldComponent,