Added Navigation to next question by pressing on a button. Introduces MarkForConsideration Component

This commit is contained in:
Ioannis Kalyvas 2018-11-01 18:02:15 +02:00
parent bdcc628862
commit 01afdabb21
25 changed files with 519 additions and 329 deletions

1
.gitignore vendored
View File

@ -34,3 +34,4 @@ temp/
*.jar
*.lst
dmp-frontend/.vscode/
*.docx

View File

@ -40,7 +40,9 @@ public class DMPDaoImpl extends DatabaseAccess<DMP> implements DMPDao {
if (criteria.getProjects() != null && !criteria.getProjects().isEmpty())
query.where(((builder, root) -> root.get("project").in(criteria.getProjects())));
if (!criteria.getAllVersions())
query.initSubQuery(String.class).where((builder, root) -> builder.equal(root.get("version"), query.<String>subQueryMax((builder1, externalRoot, nestedRoot) -> builder1.equal(externalRoot.get("groupId"), nestedRoot.get("groupId")), Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "version")), String.class)));
query.initSubQuery(String.class).where((builder, root) -> builder.equal(root.get("version"),
query.<String>subQueryMax((builder1, externalRoot, nestedRoot) -> builder1.equal(externalRoot.get("groupId"),
nestedRoot.get("groupId")), Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "version")), String.class)));
if (criteria.getGroupIds() != null && !criteria.getGroupIds().isEmpty())
query.where((builder, root) -> root.get("groupId").in(criteria.getGroupIds()));
query.where((builder, root) -> builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue()));

View File

@ -72,7 +72,6 @@ public class DevelDatabaseConfiguration {
properties.setProperty("hibernate.c3p0.maxPoolSize", "70");
properties.setProperty("hibernate.c3p0.timeout", "5000");
properties.setProperty("hibernate.connection.release_mode", "after_transaction");
//properties.setProperty("hibernate.connection.provider_class", "org.hibernate.c3p0.internal.C3P0ConnectionProvider");
return properties;
}
}

View File

@ -44,13 +44,7 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
if (principal == null) throw new UnauthorisedException("Authentication Information Missing");
if (!claimList.contains(Authorities.ANONYMOUS) && !principal.isAuthorized(claimList))
throw new UnauthorisedException("You are not Authorized For this Action");
/*Principal principal1 = new Principal();
principal1.setId(UUID.fromString("46366b8a-a712-4e0c-a499-1a3a0f209325"));
principal1.setToken(UUID.fromString("19031e80-6534-4aa5-b68a-78e97042c968"));
principal1.setName("Ioannis Kalyvas");
principal1.setAvatarUrl("https://lh5.googleusercontent.com/-X65vX1QO_Ew/AAAAAAAAAAI/AAAAAAAAAAA/AAN31DU5lFIOwD_fZiYW96D410pn6v4E-Q/s96-c/photo.jpg");
principal1.setAuthorities(new HashSet<>(Arrays.asList(Authorities.ADMIN, Authorities.USER)));
principal1.setExpiresAt(addADay(new Date()));*/
return principal;
}

View File

@ -11,10 +11,8 @@ import { HttpClient, HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
import { HostConfiguration } from './app.constants';
import { BaseHttpModule } from './utilities/cite-http-service-module/cite-http.module';
import { LoginOptions } from './user-management/utilties/LoginOptions';
import { LoginModule } from './user-management/login.module';
import { SharedModule } from './shared/shared.module';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';

View File

@ -29,6 +29,7 @@
</div>
<mat-horizontal-stepper [linear]="isLinear" #stepper>
<mat-step [stepControl]="formGroup">
<div *ngIf="this.isActiveStep(0)">
<form *ngIf="formGroup" [formGroup]="formGroup">
<app-single-auto-complete [required]="true" [reactiveFormControl]="formGroup.get('dmp')" placeholder="{{'DATASET-EDITOR.FIELDS.DMP' | translate}}"
[configuration]="dmpAutoCompleteConfiguration">
@ -49,8 +50,10 @@
</button>
</div>
</form>
</div>
</mat-step>
<mat-step [stepControl]="formGroup">
<div *ngIf="this.isActiveStep(1)">
<form *ngIf="formGroup" [formGroup]="formGroup">
<ng-template matStepLabel>{{'DATASET-WIZARD.SECOND-STEP.TITLE' | translate}}</ng-template>
@ -200,10 +203,11 @@
{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}
</mat-card-title>
</mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('tags') && tagsTemplate && externalSourcesConfiguration" [options]="externalSourcesConfiguration.tags"
placeholder="{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}" [parentTemplate]='tagsTemplate' [displayFunction]='tagsDisplayFunc'
[formGroup]="formGroup.get('tags')" [viewOnly]='viewOnly' [subtitleFunction]='tagsDisplaySubtitleFunc'
[autoCompleteConfiguration]="tagsAutoCompleteConfiguration" (onItemChange)="tagsOnItemChange($event)">
<app-external-item-listing *ngIf="formGroup.get('tags') && tagsTemplate && externalSourcesConfiguration"
[options]="externalSourcesConfiguration.tags" placeholder="{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}"
[parentTemplate]='tagsTemplate' [displayFunction]='tagsDisplayFunc' [formGroup]="formGroup.get('tags')"
[viewOnly]='viewOnly' [subtitleFunction]='tagsDisplaySubtitleFunc' [autoCompleteConfiguration]="tagsAutoCompleteConfiguration"
(onItemChange)="tagsOnItemChange($event)">
</app-external-item-listing>
<ng-template #tagsTemplate let-suggestion let-i="index" let-callback="function">
@ -226,8 +230,10 @@
| translate}}</button>
</div>
</form>
</div>
</mat-step>
<mat-step>
<div *ngIf="this.isActiveStep(2)">
<ng-template matStepLabel>{{'DATASET-WIZARD.THIRD-STEP.TITLE' | translate}}</ng-template>
<app-dynamic-form class="full-width" *ngIf="formGroup && datasetWizardModel && datasetWizardModel.datasetProfileDefinition"
[form]="this.formGroup.get('datasetProfileDefinition')" [dataModel]="datasetWizardModel"></app-dynamic-form>
@ -235,6 +241,18 @@
<button style="margin-top:10px;" matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK'
| translate}}</button>
</div>
</div>
</mat-step>
<mat-step>
<div *ngIf="this.isActiveStep(3)">
<ng-template matStepLabel>{{'DATASET-WIZARD.FOURTH-STEP.TITLE' | translate}}</ng-template>
<app-dynamic-form-pending-questions-display class="full-width" *ngIf="formGroup && datasetWizardModel && datasetWizardModel.datasetProfileDefinition"
[form]="this.formGroup.get('datasetProfileDefinition')" [dataModel]="datasetWizardModel"></app-dynamic-form-pending-questions-display>
<div class="navigation-buttons-container">
<button style="margin-top:10px;" matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK'
| translate}}</button>
</div>
</div>
</mat-step>
</mat-horizontal-stepper>
</div>

View File

@ -155,7 +155,7 @@ export class DatasetWizardComponent implements OnInit, AfterViewInit, IBreadCrum
loadDataOnStart: true
};
this.route.params.subscribe((params: Params) => {
const params = this.route.snapshot.params;
this.itemId = params['id'];
const dmpId = params['dmpId'];
if (this.itemId != null) {
@ -236,7 +236,6 @@ export class DatasetWizardComponent implements OnInit, AfterViewInit, IBreadCrum
this.loadDatasetProfiles();
});
}
});
}
ngAfterViewInit() {
@ -490,4 +489,8 @@ export class DatasetWizardComponent implements OnInit, AfterViewInit, IBreadCrum
this.viewOnly = true;
this.formGroup.disable();
}
isActiveStep(index: number) {
return this.stepper.selectedIndex === index;
}
}

View File

@ -36,6 +36,8 @@
<textarea matInput formControlName="value" matTextareaAutosize matAutosizeMinRows="2" matAutosizeMaxRows="10"
[required]="field.validationRequired">
</textarea>
<button mat-button *ngIf="!form.get('value').disabled && form.get('value').value" matSuffix mat-icon-button
aria-label="Clear" (click)="this.form.patchValue({'value': ''})">

View File

@ -19,10 +19,10 @@ import { Subscription } from 'rxjs';
export class DynamicFormFieldComponent implements OnInit, OnChanges, OnDestroy {
@Input() field: Field;
form: FormGroup;
@Input() pathName: string;
@Input() path: string;
change: Subscription;
trackByFn = (index, item) => item ? item['id'] : null;
constructor(private route: ActivatedRoute, public visibilityRulesService: VisibilityRulesService) {
}

View File

@ -1,14 +1,20 @@
<div *ngIf="form" [id]="compositeField.id" [formGroup]="form">
<div *ngIf="compositeField.fields.length == 1" class="fieldset-component">
<h5 *ngIf="compositeField.title" style="font-weight:bold; color: #3a3737;">{{compositeField.numbering}} {{compositeField.title}}</h5>
<h5 *ngIf="compositeField.title" style="font-weight:bold; color: #3a3737;">{{compositeField.numbering}}
{{compositeField.title}}
<a *ngIf="this.markForConsiderationService.exists(compositeField)" (click)="markForConsideration()" style="cursor: pointer">
Mark For Consideration
</a>
</h5>
<div class="content-left-margin">
<h5 *ngIf="compositeField.description">{{compositeField.description}}</h5>
<h5 *ngIf="compositeField.extendedDescription" class="fieldset-extended-desc">
<i>{{compositeField.extendedDescription}}</i>
</h5>
<app-df-field *ngIf="compositeField.fields.length == 1" [field]="compositeField.fields[0]" [pathName]="pathName+'.fields.'+0"></app-df-field>
<app-df-field *ngIf="compositeField.fields.length == 1" [field]="compositeField.fields[0]"></app-df-field>
</div>
</div>
@ -28,13 +34,14 @@
</div>
</div>
<app-df-field [field]="field" [pathName]="pathName+'.fields.'+i"></app-df-field>
<app-df-field #{{}} [field]="field"></app-df-field>
<div *ngIf="field">
<div *ngFor="let multipleField of field.multiplicityItems; let j = index; trackBy: trackByFn">
<app-df-field [field]="multipleField" [pathName]="pathName+'.fields.'+i+'.multiplicityItems.'+j"></app-df-field>
<app-df-field [field]="multipleField"></app-df-field>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -3,6 +3,8 @@ import { CompositeField } from '../../models/CompositeField';
import { FormGroup, FormArray } from '@angular/forms';
import { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy } from '@angular/core';
import { Field } from '../../models/Field';
import { MarkForConsiderationService } from '../../utilities/mark-for-considerations/mark-for-consideration.service';
import { FormFocusService } from '../../utilities/form-focus-service/form-focus.service';
@Component({
selector: 'app-df-composite-field',
templateUrl: './dynamic-form-composite-field.html',
@ -15,11 +17,13 @@ export class DynamicFormCompositeFieldComponent implements OnInit {
@Input() compositeField: CompositeField;
form: FormGroup;
@Input() pathName: string;
@Input() path: string;
trackByFn = (index, item) => item ? item['id'] : null;
constructor(private visibilityRulesService: VisibilityRulesService) {
constructor(
private visibilityRulesService: VisibilityRulesService,
private markForConsiderationService: MarkForConsiderationService,
private formFocusService: FormFocusService
) {
}
ngOnInit() {
@ -28,10 +32,13 @@ export class DynamicFormCompositeFieldComponent implements OnInit {
}
}
addMultipleField(fieldIndex: number) {
const field: Field = this.compositeField.fields[fieldIndex].cloneForMultiplicity(fieldIndex, '');
this.compositeField.fields[fieldIndex].multiplicityItems.push(field);
(<FormArray>(this.form.get('fields').get('' + fieldIndex).get('multiplicityItems'))).push(field.buildForm());
}
markForConsideration() {
this.markForConsiderationService.markForConsideration(this.compositeField);
}
}

View File

@ -9,10 +9,10 @@
</a>
</div>
</div>
<app-df-composite-field [compositeField]="compositeField" [path]="path" [pathName]="pathName+'.compositeFields.'+i"></app-df-composite-field>
<app-df-composite-field [compositeField]="compositeField"></app-df-composite-field>
<div *ngIf="compositeField">
<div *ngFor="let multipleCompositeField of compositeField.multiplicityItems; let j = index; trackBy: trackByFn">
<app-df-composite-field [compositeField]="multipleCompositeField" [pathName]="pathName+'.compositeFields.'+i+'.multiplicityItems.'+j"></app-df-composite-field>
<app-df-composite-field [compositeField]="multipleCompositeField"></app-df-composite-field>
</div>
</div>
</div>

View File

@ -18,16 +18,19 @@
Add one more fieldset +
</a>
</div>
<app-df-composite-field [compositeField]="compositeField" [path]="path" [pathName]="pathName+'.compositeFields.'+i"></app-df-composite-field>
<app-df-composite-field [compositeField]="compositeField"></app-df-composite-field>
<div *ngIf="compositeField">
<div *ngFor="let multipleCompositeField of compositeField.multiplicityItems; let j = index; trackBy: trackByFn">
<app-df-composite-field [compositeField]="multipleCompositeField" [pathName]="pathName+'.compositeFields.'+i+'.multiplicityItems.'+j"></app-df-composite-field>
<app-df-composite-field [compositeField]="multipleCompositeField"></app-df-composite-field>
</div>
<div *ngIf="compositeField.hasCommentField" [formGroup]="form.get('compositeFields').get(''+i)">
<mat-form-field>
<input matInput formControlName="commentFieldValue" placeholder="comment">
</mat-form-field>
</div>
<button mat-icon-button type="button" (click)="next(compositeField)">
<mat-icon>expand_more</mat-icon>
</button>
</div>
</div>

View File

@ -3,6 +3,7 @@ import { FormGroup, Form, FormArray } from '@angular/forms';
import { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy, AfterViewInit } from '@angular/core';
import { CompositeField } from '../../models/CompositeField';
import { Section } from '../../models/Section';
import { FormFocusService } from '../../utilities/form-focus-service/form-focus.service';
@Component({
@ -20,7 +21,10 @@ export class DynamicFormSectionComponent implements OnInit, AfterViewInit {
@Input() pathName: string;
@Input() path: string;
trackByFn = (index, item) => item ? item['id'] : null;
constructor(public visibilityRulesService: VisibilityRulesService) { }
constructor(
public visibilityRulesService: VisibilityRulesService,
private formFocusService: FormFocusService
) { }
ngOnInit() {
if (this.section) {
@ -47,4 +51,8 @@ export class DynamicFormSectionComponent implements OnInit, AfterViewInit {
}
return false;
}
next(compositeField: CompositeField) {
this.formFocusService.focusNext(compositeField);
}
}

View File

@ -32,6 +32,9 @@ import { NgModule } from '@angular/core';
import { DatasetProfileAdmin } from '../services/datasetProfileAdmin/datasetProfileAfmin.service';
import { DatasetProfileService } from '../services/dataset-profile.service';
import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.service';
import { DynamicFormPendingQuestionsDisplayComponent } from './helpers/dynamic-form-pending-questions/dynamic-form-pending-questions-display.component';
import { MarkForConsiderationService } from '../utilities/mark-for-considerations/mark-for-consideration.service';
import { FormFocusService } from '../utilities/form-focus-service/form-focus.service';
@NgModule({
@ -57,6 +60,7 @@ import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.
DynamicFormCompositeFieldComponent,
DynamicFieldBooleanDecisionComponent,
DynamicFieldRadioBoxComponent,
DynamicFormPendingQuestionsDisplayComponent,
TableOfContentsComponent,
TableOfContentsFieldSetComponent,
TableOfContentsGroupComponent,
@ -76,6 +80,7 @@ import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.
DynamicFormCompositeFieldComponent,
DynamicFieldBooleanDecisionComponent,
DynamicFieldRadioBoxComponent,
DynamicFormPendingQuestionsDisplayComponent,
TableOfContentsComponent,
TableOfContentsFieldSetComponent,
TableOfContentsGroupComponent,
@ -92,7 +97,9 @@ import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.
PaginationService,
DatasetProfileService,
DatasetProfileAdmin,
DatasetWizardService
DatasetWizardService,
MarkForConsiderationService,
FormFocusService
]
})

View File

@ -6,11 +6,17 @@ import { BaseHttpService } from '../../utilities/cite-http-service-module/base-h
import { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service';
import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel';
import { DatasetWizardModel } from '../../models/datasets/DatasetWizardModel';
import { Component, Input, OnInit, ViewEncapsulation, AfterViewInit } from '@angular/core';
import { Component, Input, OnInit, ViewEncapsulation, AfterViewInit, ViewChild } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router';
import 'rxjs/add/operator/switchMap';
import '../../utilities/enhancers/flatJoinOn';
import { Location } from '@angular/common';
import { MarkForConsiderationService } from '../../utilities/mark-for-considerations/mark-for-consideration.service';
import { FormFocusService } from '../../utilities/form-focus-service/form-focus.service';
import { CompositeField } from '../../models/CompositeField';
import { Pair } from '../../models/helpers/Pair';
import { MatStepper } from '@angular/material';
@Component({
selector: 'app-dynamic-form',
@ -19,6 +25,7 @@ import { Location } from '@angular/common';
'./dynamic-form.component.scss'
],
providers: [
FormFocusService
],
encapsulation: ViewEncapsulation.None,
})
@ -31,6 +38,7 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
datasetProfileDefinitionModel: DatasetProfileDefinitionModel;
private progressbar = false;
private currentPageIndex = 0;
@ViewChild('stepper') stepper: MatStepper;
@Input() dataModel: DatasetWizardModel = new DatasetWizardModel();
@Input() path: string;
@ -43,11 +51,9 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
constructor(
private router: Router,
private _location: Location,
private route: ActivatedRoute,
private visibilityRulesService: VisibilityRulesService,
private http: BaseHttpService,
private datasetWizardService: DatasetWizardService,
private formFocusService: FormFocusService
) {
//this.datasetId = route.snapshot.params['id'];
}
@ -64,14 +70,26 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
this.visibilityRulesService.buildVisibilityRules(rules);
this.datasetProfileDefinitionModel = this.dataModel.datasetProfileDefinition;
this.visibilityRulesService.setModel(this.datasetProfileDefinitionModel);
this.createPagination();
this.progressbar = true;
const sections: Pair<Section[], number>[] = this.datasetProfileDefinitionModel.pages.map(page => new Pair<Section[], number>(page.sections, page.ordinal)).filter(x => x);
const compositeFields: Pair<CompositeField[], number>[] = sections.map(section => new Pair<CompositeField[], number>(section.left.flatMap(sec => sec.compositeFields), section.right)).filter(x => x);
const nestedSections: Pair<Section[], number>[] = sections.map(section => new Pair<Section[], number>(section.left.flatMap(x => x.sections), section.right)).filter(x => x);
const nestedCompositeFields: Pair<CompositeField[], number>[] = nestedSections.map(section => new Pair<CompositeField[], number>(section.left.flatMap(x => x.compositeFields), section.right)).filter(x => x);
const compositeFieldsUnion: Pair<CompositeField[], number>[] = compositeFields.concat(nestedCompositeFields);
//const fields = compositeFieldsUnion.flatJoinOn(x => x.right);
this.formFocusService.setFields(compositeFieldsUnion);
this.route.fragment.subscribe((fragment: string) => {
const self = this;
setTimeout(function () { self.scrollTo(fragment); });
});
}
ngAfterViewInit() {
this.visibilityRulesService.triggerVisibilityEvaluation();
this.route.queryParams.subscribe((params) => {
if (params && 'page' in params) {
this.changeCurrentPage(params['page']);
@ -79,35 +97,17 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
});
}
ngAfterViewInit() {
this.visibilityRulesService.triggerVisibilityEvaluation();
}
toggleSidebar() {
this.visibleSidebar = !this.visibleSidebar;
}
// getPages(model: DatasetProfileDefinitionModel): Array<number> {
// let pageSet = new Set<number>();
// model.sections.forEach(section => {
// pageSet.add(section.page);
// });
// return Array.from(pageSet).sort((a, b) => a - b);
// }
shouldDisplaySection(section: Section): Boolean {
return (section.page) === this.currentPageIndex;
}
createPagination() {
/*this.pages.forEach(item => {
this.stepperItems.push({
label: '',
})
});*/
}
changePageIndex(index: any) {
@ -120,16 +120,14 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
if (!element) { return; }
element.scrollIntoView();
this.visibleSidebar = true;
const scrollElement = document.querySelector('.scrollableContent');
//scrollElement.scrollTop = topElement.offsetTop;
}
changeCurrentPage(pageString: string) {
if (!pageString) { return; }
//if (!pageString) { return; }
const page = parseInt(pageString);
if (isNaN(page)) { return; }
/*if (isNaN(page)) { return; }
const pageIndex = this.pages.indexOf(page);
if (pageIndex === -1) { return; }
this.currentPageIndex = page;
if (pageIndex === -1) { return; }*/
this.stepper.selectedIndex = page;
}
}

View File

@ -0,0 +1,4 @@
<div *ngFor="let field of this.markForConsideration.getFields()">
<app-df-composite-field [compositeField]="field">
</app-df-composite-field>
</div>

View File

@ -1,5 +1,15 @@
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
import { Component, ViewEncapsulation, OnInit, Input } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { VisibilityRulesService } from '../../../utilities/visibility-rules/visibility-rules.service';
import { JsonSerializer } from '../../../utilities/JsonSerializer';
import { Rule } from '../../../models/Rule';
import { DatasetWizardModel } from '../../../models/datasets/DatasetWizardModel';
import { DatasetProfileDefinitionModel } from '../../../models/DatasetProfileDefinitionModel';
import { Section } from '../../../models/Section';
import { CompositeField } from '../../../models/CompositeField';
import '../../../utilities/enhancers/flatMap';
import { Field } from '../../../models/Field';
import { MarkForConsiderationService } from '../../../utilities/mark-for-considerations/mark-for-consideration.service';
@Component({
selector: 'app-dynamic-form-pending-questions-display',
templateUrl: './dynamic-form-pending-questions-display.component.html',
@ -11,7 +21,32 @@ import { Component, ViewEncapsulation, OnInit } from '@angular/core';
encapsulation: ViewEncapsulation.None,
})
export class DynamicFormPendingQuestionsDisplayComponent implements OnInit {
constructor(
private visibilityRulesService: VisibilityRulesService,
private markForConsideration: MarkForConsiderationService) {
}
datasetProfileDefinitionModel: DatasetProfileDefinitionModel;
@Input()
form: FormGroup;
@Input() dataModel: DatasetWizardModel = new DatasetWizardModel();
fields: CompositeField[];
ngOnInit(): void {
throw new Error('Method not implemented.');
const rules: Rule[] = JsonSerializer.fromJSONArray(this.dataModel.datasetProfileDefinition.rules, Rule);
this.datasetProfileDefinitionModel = this.dataModel.datasetProfileDefinition;
const sections: Section[] = this.datasetProfileDefinitionModel.pages.flatMap(page => page.sections).filter(x => x);
const compositeFields: CompositeField[] = sections.flatMap(section => section.compositeFields).filter(x => x);
const nestedSections: Section[] = sections.flatMap(section => section.sections).filter(x => x);
const nestedCompositeFiels: CompositeField[] = nestedSections.flatMap(section => section.compositeFields).filter(x => x);
const compositeFieldsUnion = compositeFields.concat(nestedCompositeFiels);
//const fields: Field[] = compositeFields.flatMap(composite => composite.fields).concat(nestedCompositeFiels.flatMap(composite => composite.fields));
const fields = compositeFieldsUnion.filter(compositeField => this.visibilityRulesService.checkElementVisibility(compositeField.id))
.filter(compositeField => compositeField.fields.filter(x => x && x.validationRequired && this.visibilityRulesService.getFormGroup(x.id).value == null).length > 0);
fields.forEach(x => this.markForConsideration.markForConsideration(x));
}
}

View File

@ -0,0 +1,9 @@
export class Pair<L, R> {
public readonly left: L;
public readonly right: R;
constructor(left: L, right: R) {
this.left = left;
this.right = right;
}
}

View File

@ -0,0 +1,9 @@
interface Array<T> {
flatJoinOn<E, J>(by: (item: T) => J): Array<E>;
}
Array.prototype.flatJoinOn = function (f: Function) {
return this.groupBy(f).reduce((ys: any, x: any) => {
return ys.concat(f.call(this, x));
}, []);
};

View File

@ -0,0 +1,9 @@
interface Array<T> {
flatMap<E>(callback: (t: T) => Array<E>): Array<E>;
}
Array.prototype.flatMap = function (f: Function) {
return this.reduce((ys: any, x: any) => {
return ys.concat(f.call(this, x));
}, []);
};

View File

@ -0,0 +1,11 @@
interface Array<T> {
groupBy<E, J>(by: (item: T) => J): Array<Array<E>>;
}
Array.prototype.groupBy = function (f: Function) {
return this.reduce((ys: any, x: any) => {
ys[f.call(this, x)] = ys[f.call(this, x)] || [];
ys[f.call(this, x)].push(x);
return ys;
}, []);
};

View File

@ -0,0 +1,36 @@
import { Injectable } from '@angular/core';
import { CompositeField } from '../../models/CompositeField';
import { Router, ActivatedRoute } from '@angular/router';
import { Pair } from '../../models/helpers/Pair';
import '../../utilities/enhancers/groupBy';
import { VisibilityRulesService } from '../visibility-rules/visibility-rules.service';
@Injectable()
export class FormFocusService {
private compositeFields: Pair<CompositeField[], number>[] = [];
constructor(
public router: Router,
public route: ActivatedRoute,
public visibilityService: VisibilityRulesService
) {
}
setFields(compositeFields: Pair<CompositeField[], number>[]) {
this.compositeFields = compositeFields;
}
focusNext(field: CompositeField) {
const flattenedCompositeFields = this.compositeFields.groupBy(x => x.right)
.map(x => x.reduce((first: Pair<CompositeField[], number>, second: Pair<CompositeField[], number>) =>
(new Pair<CompositeField[], number>(first.left.concat(second.left), first.right))));
const page = flattenedCompositeFields.filter(x => x['left'].map(y => y.id).indexOf(field.id) !== -1)[0];
let pageIndex = page['right'];
const currentFields = page['left'].filter(x => this.visibilityService.checkElementVisibility(x.id)).map(x => x.id);
const fieldIndex = currentFields.indexOf(field.id);
if (fieldIndex === currentFields.length - 1) { pageIndex = pageIndex + 1; }
this.router.navigate(['datasets/' + this.route.snapshot.url[0] + '/' + this.route.snapshot.url[1]], { fragment: page['left'].filter(x => this.visibilityService.checkElementVisibility(x.id))[fieldIndex].id, queryParams: { page: pageIndex } });
}
}

View File

@ -0,0 +1,22 @@
import { Injectable } from '@angular/core';
import { CompositeField } from '../../models/CompositeField';
@Injectable()
export class MarkForConsiderationService {
private compositeFields: CompositeField[] = [];
markForConsideration(field: CompositeField) {
if (this.exists(field)) {
this.compositeFields.push(field);
}
}
getFields() {
return this.compositeFields;
}
exists(field: CompositeField) {
return this.compositeFields.map(x => x.id).indexOf(field.id) === -1;
}
}

View File

@ -39,7 +39,7 @@ export class VisibilityRulesService {
}
public checkElementVisibility(id: string): boolean {
if (!this.elementVisibilityMap.has(id) || this.elementVisibilityMap.get(id)) { return true; } else { return false; }
return !this.elementVisibilityMap.has(id) || this.elementVisibilityMap.get(id);
}
public buildVisibilityRules(item: Array<Rule>) {
@ -90,7 +90,7 @@ export class VisibilityRulesService {
parseValue(value: any) {
if (typeof value === 'string') {
if (value === 'true') { return true; } else if (value === 'false') { return false; } else { return value; }
if (value === 'true') { return true; } else if (value === 'false') { return false; } else { return this.translate(value); }
} else { return value; }
}
@ -137,4 +137,12 @@ export class VisibilityRulesService {
}
}
}
private translate(item: any) {
try {
return JSON.parse(item).value;
} catch (error) {
return item;
}
}
}