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 *.jar
*.lst *.lst
dmp-frontend/.vscode/ 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()) if (criteria.getProjects() != null && !criteria.getProjects().isEmpty())
query.where(((builder, root) -> root.get("project").in(criteria.getProjects()))); query.where(((builder, root) -> root.get("project").in(criteria.getProjects())));
if (!criteria.getAllVersions()) 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()) if (criteria.getGroupIds() != null && !criteria.getGroupIds().isEmpty())
query.where((builder, root) -> root.get("groupId").in(criteria.getGroupIds())); query.where((builder, root) -> root.get("groupId").in(criteria.getGroupIds()));
query.where((builder, root) -> builder.notEqual(root.get("status"), DMP.DMPStatus.DELETED.getValue())); 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.maxPoolSize", "70");
properties.setProperty("hibernate.c3p0.timeout", "5000"); properties.setProperty("hibernate.c3p0.timeout", "5000");
properties.setProperty("hibernate.connection.release_mode", "after_transaction"); properties.setProperty("hibernate.connection.release_mode", "after_transaction");
//properties.setProperty("hibernate.connection.provider_class", "org.hibernate.c3p0.internal.C3P0ConnectionProvider");
return properties; return properties;
} }
} }

View File

@ -44,13 +44,7 @@ public final class PrincipalArgumentResolver implements HandlerMethodArgumentRes
if (principal == null) throw new UnauthorisedException("Authentication Information Missing"); if (principal == null) throw new UnauthorisedException("Authentication Information Missing");
if (!claimList.contains(Authorities.ANONYMOUS) && !principal.isAuthorized(claimList)) if (!claimList.contains(Authorities.ANONYMOUS) && !principal.isAuthorized(claimList))
throw new UnauthorisedException("You are not Authorized For this Action"); 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; return principal;
} }

View File

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

View File

@ -29,211 +29,229 @@
</div> </div>
<mat-horizontal-stepper [linear]="isLinear" #stepper> <mat-horizontal-stepper [linear]="isLinear" #stepper>
<mat-step [stepControl]="formGroup"> <mat-step [stepControl]="formGroup">
<form *ngIf="formGroup" [formGroup]="formGroup"> <div *ngIf="this.isActiveStep(0)">
<app-single-auto-complete [required]="true" [reactiveFormControl]="formGroup.get('dmp')" placeholder="{{'DATASET-EDITOR.FIELDS.DMP' | translate}}" <form *ngIf="formGroup" [formGroup]="formGroup">
[configuration]="dmpAutoCompleteConfiguration"> <app-single-auto-complete [required]="true" [reactiveFormControl]="formGroup.get('dmp')" placeholder="{{'DATASET-EDITOR.FIELDS.DMP' | translate}}"
</app-single-auto-complete> [configuration]="dmpAutoCompleteConfiguration">
<ng-template matStepLabel>{{'DATASET-WIZARD.FIRST-STEP.TITLE' | translate}}</ng-template> </app-single-auto-complete>
<mat-form-field formGroupName="profile"> <ng-template matStepLabel>{{'DATASET-WIZARD.FIRST-STEP.TITLE' | translate}}</ng-template>
<mat-select placeholder=" {{'DATASET-WIZARD.FIRST-STEP.PROFILE'| translate}}" [required]="true" formControlName="id"> <mat-form-field formGroupName="profile">
<mat-option *ngFor="let profile of availableProfiles" [value]="profile.id"> <mat-select placeholder=" {{'DATASET-WIZARD.FIRST-STEP.PROFILE'| translate}}" [required]="true" formControlName="id">
{{profile.label}} <mat-option *ngFor="let profile of availableProfiles" [value]="profile.id">
</mat-option> {{profile.label}}
</mat-select> </mat-option>
<mat-error *ngIf="baseErrorModel?.status">{{baseErrorModel['Criteria.status']}}</mat-error> </mat-select>
</mat-form-field> <mat-error *ngIf="baseErrorModel?.status">{{baseErrorModel['Criteria.status']}}</mat-error>
<app-dataset-editor-component [formGroup]="formGroup"></app-dataset-editor-component> </mat-form-field>
<div class="navigation-buttons-container"> <app-dataset-editor-component [formGroup]="formGroup"></app-dataset-editor-component>
<button matStepperNext mat-raised-button style="float:right;" color="primary">{{'DATASET-WIZARD.ACTIONS.NEXT' | <div class="navigation-buttons-container">
translate}} <button matStepperNext mat-raised-button style="float:right;" color="primary">{{'DATASET-WIZARD.ACTIONS.NEXT' |
</button> translate}}
</div> </button>
</form> </div>
</form>
</div>
</mat-step> </mat-step>
<mat-step [stepControl]="formGroup"> <mat-step [stepControl]="formGroup">
<form *ngIf="formGroup" [formGroup]="formGroup"> <div *ngIf="this.isActiveStep(1)">
<ng-template matStepLabel>{{'DATASET-WIZARD.SECOND-STEP.TITLE' | translate}}</ng-template> <form *ngIf="formGroup" [formGroup]="formGroup">
<ng-template matStepLabel>{{'DATASET-WIZARD.SECOND-STEP.TITLE' | translate}}</ng-template>
<mat-card> <mat-card>
<mat-card-header> <mat-card-header>
<mat-card-title class="thick" *ngIf='!viewOnly'> <mat-card-title class="thick" *ngIf='!viewOnly'>
{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}} {{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}}
<button mat-raised-button color="primary" (click)="addDataRepository()"> <button mat-raised-button color="primary" (click)="addDataRepository()">
{{'DATASET-EDITOR.FIELDS.CREATE'|translate}} {{'DATASET-EDITOR.FIELDS.CREATE'|translate}}
</button> </button>
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('dataRepositories') && dataRepositoriesTemplate && externalSourcesConfiguration" <app-external-item-listing *ngIf="formGroup.get('dataRepositories') && dataRepositoriesTemplate && externalSourcesConfiguration"
[options]="externalSourcesConfiguration.dataRepositories" placeholder="{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}}" [options]="externalSourcesConfiguration.dataRepositories" placeholder="{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES' | translate}}"
[parentTemplate]='dataRepositoriesTemplate' [displayFunction]='dataRepositoryDisplayFunc' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [parentTemplate]='dataRepositoriesTemplate' [displayFunction]='dataRepositoryDisplayFunc' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc'
[formGroup]="formGroup.get('dataRepositories')" [viewOnly]='viewOnly' [autoCompleteConfiguration]="dataRepositoriesAutoCompleteConfiguration" [formGroup]="formGroup.get('dataRepositories')" [viewOnly]='viewOnly' [autoCompleteConfiguration]="dataRepositoriesAutoCompleteConfiguration"
(onItemChange)="dataRepositoriesOnItemChange($event)"> (onItemChange)="dataRepositoriesOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
<ng-template #dataRepositoriesTemplate let-suggestion let-i="index" let-callback="function"> <ng-template #dataRepositoriesTemplate let-suggestion let-i="index" let-callback="function">
<div class="col-md-2"> <div class="col-md-2">
<p> <p>
{{i+1}}) {{suggestion.get('label').value}} {{i+1}}) {{suggestion.get('label').value}}
</p> </p>
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
<mat-form-field> <mat-form-field>
<input matInput placeholder="{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES-INFO' | translate}}" type="text" name="info" <input matInput placeholder="{{'DATASET-EDITOR.FIELDS.DATAREPOSITORIES-INFO' | translate}}" type="text" name="info"
[formControl]="suggestion.get('info')"> [formControl]="suggestion.get('info')">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-2" *ngIf='!viewOnly'> <div class="col-md-2" *ngIf='!viewOnly'>
<button mat-button (click)="callback(i)"> <button mat-button (click)="callback(i)">
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>
</ng-template> </ng-template>
</mat-card> </mat-card>
<mat-card> <mat-card>
<mat-card-header> <mat-card-header>
<mat-card-title class="thick" *ngIf='!viewOnly'> <mat-card-title class="thick" *ngIf='!viewOnly'>
{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}} {{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}}
<button mat-raised-button color="primary" (click)="addExternalDataset()"> <button mat-raised-button color="primary" (click)="addExternalDataset()">
{{'DATASET-EDITOR.FIELDS.CREATE'|translate}} {{'DATASET-EDITOR.FIELDS.CREATE'|translate}}
</button> </button>
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('externalDatasets') && externalDatasetsTemplate && externalSourcesConfiguration" <app-external-item-listing *ngIf="formGroup.get('externalDatasets') && externalDatasetsTemplate && externalSourcesConfiguration"
[options]="externalSourcesConfiguration.externalDatasets" placeholder="{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}}" [options]="externalSourcesConfiguration.externalDatasets" placeholder="{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASETS' | translate}}"
[parentTemplate]='externalDatasetsTemplate' [displayFunction]='externalDatasetDisplayFunc' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [parentTemplate]='externalDatasetsTemplate' [displayFunction]='externalDatasetDisplayFunc' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc'
[formGroup]="formGroup.get('externalDatasets')" [viewOnly]='viewOnly' [autoCompleteConfiguration]="externalDatasetAutoCompleteConfiguration" [formGroup]="formGroup.get('externalDatasets')" [viewOnly]='viewOnly' [autoCompleteConfiguration]="externalDatasetAutoCompleteConfiguration"
(onItemChange)="externalDatasetsOnItemChange($event)"> (onItemChange)="externalDatasetsOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
<ng-template #externalDatasetsTemplate let-suggestion let-i="index" let-callback="function"> <ng-template #externalDatasetsTemplate let-suggestion let-i="index" let-callback="function">
<div class="col-md-2"> <div class="col-md-2">
<p> <p>
{{i+1}}) {{suggestion.get('label').value}} {{i+1}}) {{suggestion.get('label').value}}
</p> </p>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<mat-form-field> <mat-form-field>
<input matInput placeholder="{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASET-INFO' | translate}}" type="text" name="info" <input matInput placeholder="{{'DATASET-EDITOR.FIELDS.EXTERNAL-DATASET-INFO' | translate}}" type="text" name="info"
[formControl]="suggestion.get('info')"> [formControl]="suggestion.get('info')">
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<mat-form-field> <mat-form-field>
<mat-select placeholder="{{'DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-DATASET-TYPE' | translate}}" [formControl]="suggestion.get('type')"> <mat-select placeholder="{{'DATASET-WIZARD.EDITOR.FIELDS.EXTERNAL-DATASET-TYPE' | translate}}" [formControl]="suggestion.get('type')">
<mat-option [value]="0">{{'TYPES.EXTERNAL-DATASET-TYPE.SOURCE' | translate}}</mat-option> <mat-option [value]="0">{{'TYPES.EXTERNAL-DATASET-TYPE.SOURCE' | translate}}</mat-option>
<mat-option [value]="1">{{'TYPES.EXTERNAL-DATASET-TYPE.OUTPUT' | translate}}</mat-option> <mat-option [value]="1">{{'TYPES.EXTERNAL-DATASET-TYPE.OUTPUT' | translate}}</mat-option>
</mat-select> </mat-select>
</mat-form-field> </mat-form-field>
</div> </div>
<div class="col-md-2"> <div class="col-md-2">
<button mat-button (click)="callback(i)" *ngIf='!viewOnly'> <button mat-button (click)="callback(i)" *ngIf='!viewOnly'>
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>
</ng-template> </ng-template>
</mat-card> </mat-card>
<mat-card> <mat-card>
<mat-card-header> <mat-card-header>
<mat-card-title class="thick" *ngIf='!viewOnly'> <mat-card-title class="thick" *ngIf='!viewOnly'>
{{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}} {{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}}
<button mat-raised-button color="primary" (click)="addRegistry()"> <button mat-raised-button color="primary" (click)="addRegistry()">
{{'DATASET-EDITOR.FIELDS.CREATE'|translate}} {{'DATASET-EDITOR.FIELDS.CREATE'|translate}}
</button> </button>
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('registries') && registriesTemplate && externalSourcesConfiguration" <app-external-item-listing *ngIf="formGroup.get('registries') && registriesTemplate && externalSourcesConfiguration"
[options]="externalSourcesConfiguration.registries" placeholder="{{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}}" [options]="externalSourcesConfiguration.registries" placeholder="{{'DATASET-EDITOR.FIELDS.REGISTRIES' | translate}}"
[parentTemplate]='registriesTemplate' [displayFunction]='registriesDisplayFunc' [formGroup]="formGroup.get('registries')" [parentTemplate]='registriesTemplate' [displayFunction]='registriesDisplayFunc' [formGroup]="formGroup.get('registries')"
[viewOnly]='viewOnly' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [autoCompleteConfiguration]="registriesAutoCompleteConfiguration" [viewOnly]='viewOnly' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [autoCompleteConfiguration]="registriesAutoCompleteConfiguration"
(onItemChange)="registriesOnItemChange($event)"> (onItemChange)="registriesOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
<ng-template #registriesTemplate let-suggestion let-i="index" let-callback="function"> <ng-template #registriesTemplate let-suggestion let-i="index" let-callback="function">
<div class="col-md-2"> <div class="col-md-2">
<p> <p>
{{i+1}}) {{suggestion.get('label').value}} {{i+1}}) {{suggestion.get('label').value}}
</p> </p>
</div> </div>
<div class="col-md-10"> <div class="col-md-10">
<button mat-button (click)="callback(i)" *ngIf='!viewOnly'> <button mat-button (click)="callback(i)" *ngIf='!viewOnly'>
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>
</ng-template> </ng-template>
</mat-card> </mat-card>
<mat-card> <mat-card>
<mat-card-header> <mat-card-header>
<mat-card-title class="thick" *ngIf='!viewOnly'> <mat-card-title class="thick" *ngIf='!viewOnly'>
{{'DATASET-EDITOR.FIELDS.SERVICES' | translate}} {{'DATASET-EDITOR.FIELDS.SERVICES' | translate}}
<button mat-raised-button color="primary" (click)="addService()"> <button mat-raised-button color="primary" (click)="addService()">
{{'DATASET-EDITOR.FIELDS.CREATE'|translate}} {{'DATASET-EDITOR.FIELDS.CREATE'|translate}}
</button> </button>
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('services') && servicesTemplate && externalSourcesConfiguration" <app-external-item-listing *ngIf="formGroup.get('services') && servicesTemplate && externalSourcesConfiguration"
[options]="externalSourcesConfiguration.services" placeholder="{{'DATASET-EDITOR.FIELDS.SERVICES' | translate}}" [options]="externalSourcesConfiguration.services" placeholder="{{'DATASET-EDITOR.FIELDS.SERVICES' | translate}}"
[parentTemplate]='servicesTemplate' [displayFunction]='servicesDisplayFunc' [formGroup]="formGroup.get('services')" [parentTemplate]='servicesTemplate' [displayFunction]='servicesDisplayFunc' [formGroup]="formGroup.get('services')"
[viewOnly]='viewOnly' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [autoCompleteConfiguration]="servicesAutoCompleteConfiguration" [viewOnly]='viewOnly' [subtitleFunction]='dataRepositoryDisplaySubtitleFunc' [autoCompleteConfiguration]="servicesAutoCompleteConfiguration"
(onItemChange)="servicesOnItemChange($event)"> (onItemChange)="servicesOnItemChange($event)">
</app-external-item-listing> </app-external-item-listing>
<ng-template #servicesTemplate let-suggestion let-i="index" let-callback="function"> <ng-template #servicesTemplate let-suggestion let-i="index" let-callback="function">
<div class="col-md-2"> <div class="col-md-2">
<p> <p>
{{i+1}}) {{suggestion.get('label').value}} {{i+1}}) {{suggestion.get('label').value}}
</p> </p>
</div> </div>
<div class="col-md-10"> <div class="col-md-10">
<button mat-button (click)="callback(i)" *ngIf='!viewOnly'> <button mat-button (click)="callback(i)" *ngIf='!viewOnly'>
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>
</ng-template> </ng-template>
</mat-card> </mat-card>
<mat-card> <mat-card>
<mat-card-header> <mat-card-header>
<mat-card-title class="thick"> <mat-card-title class="thick">
{{'DATASET-EDITOR.FIELDS.TAGS' | translate}} {{'DATASET-EDITOR.FIELDS.TAGS' | translate}}
</mat-card-title> </mat-card-title>
</mat-card-header> </mat-card-header>
<app-external-item-listing *ngIf="formGroup.get('tags') && tagsTemplate && externalSourcesConfiguration" [options]="externalSourcesConfiguration.tags" <app-external-item-listing *ngIf="formGroup.get('tags') && tagsTemplate && externalSourcesConfiguration"
placeholder="{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}" [parentTemplate]='tagsTemplate' [displayFunction]='tagsDisplayFunc' [options]="externalSourcesConfiguration.tags" placeholder="{{'DATASET-EDITOR.FIELDS.TAGS' | translate}}"
[formGroup]="formGroup.get('tags')" [viewOnly]='viewOnly' [subtitleFunction]='tagsDisplaySubtitleFunc' [parentTemplate]='tagsTemplate' [displayFunction]='tagsDisplayFunc' [formGroup]="formGroup.get('tags')"
[autoCompleteConfiguration]="tagsAutoCompleteConfiguration" (onItemChange)="tagsOnItemChange($event)"> [viewOnly]='viewOnly' [subtitleFunction]='tagsDisplaySubtitleFunc' [autoCompleteConfiguration]="tagsAutoCompleteConfiguration"
</app-external-item-listing> (onItemChange)="tagsOnItemChange($event)">
</app-external-item-listing>
<ng-template #tagsTemplate let-suggestion let-i="index" let-callback="function"> <ng-template #tagsTemplate let-suggestion let-i="index" let-callback="function">
<div class="col-md-2"> <div class="col-md-2">
<p> <p>
{{i+1}}) {{suggestion.get('name').value}} {{i+1}}) {{suggestion.get('name').value}}
</p> </p>
</div> </div>
<div class="col-md-10"> <div class="col-md-10">
<button mat-button (click)="callback(i)" *ngIf='!viewOnly'> <button mat-button (click)="callback(i)" *ngIf='!viewOnly'>
<mat-icon>close</mat-icon> <mat-icon>close</mat-icon>
</button> </button>
</div> </div>
</ng-template> </ng-template>
</mat-card> </mat-card>
<div class="navigation-buttons-container"> <div class="navigation-buttons-container">
<button matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK' | translate}}</button> <button matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK' | translate}}</button>
<button matStepperNext mat-raised-button color="primary" style="float:right;" (click)="getDefinition()">{{'DATASET-WIZARD.ACTIONS.NEXT' <button matStepperNext mat-raised-button color="primary" style="float:right;" (click)="getDefinition()">{{'DATASET-WIZARD.ACTIONS.NEXT'
| translate}}</button> | translate}}</button>
</div> </div>
</form> </form>
</div>
</mat-step> </mat-step>
<mat-step> <mat-step>
<ng-template matStepLabel>{{'DATASET-WIZARD.THIRD-STEP.TITLE' | translate}}</ng-template> <div *ngIf="this.isActiveStep(2)">
<app-dynamic-form class="full-width" *ngIf="formGroup && datasetWizardModel && datasetWizardModel.datasetProfileDefinition" <ng-template matStepLabel>{{'DATASET-WIZARD.THIRD-STEP.TITLE' | translate}}</ng-template>
[form]="this.formGroup.get('datasetProfileDefinition')" [dataModel]="datasetWizardModel"></app-dynamic-form> <app-dynamic-form class="full-width" *ngIf="formGroup && datasetWizardModel && datasetWizardModel.datasetProfileDefinition"
<div class="navigation-buttons-container"> [form]="this.formGroup.get('datasetProfileDefinition')" [dataModel]="datasetWizardModel"></app-dynamic-form>
<button style="margin-top:10px;" matStepperPrevious mat-raised-button color="primary">{{'DATASET-WIZARD.ACTIONS.BACK' <div class="navigation-buttons-container">
| translate}}</button> <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> </div>
</mat-step> </mat-step>
</mat-horizontal-stepper> </mat-horizontal-stepper>

View File

@ -155,14 +155,55 @@ export class DatasetWizardComponent implements OnInit, AfterViewInit, IBreadCrum
loadDataOnStart: true loadDataOnStart: true
}; };
this.route.params.subscribe((params: Params) => { const params = this.route.snapshot.params;
this.itemId = params['id']; this.itemId = params['id'];
const dmpId = params['dmpId']; const dmpId = params['dmpId'];
if (this.itemId != null) { if (this.itemId != null) {
this.isNew = false; this.isNew = false;
this.datasetWizardService.getSingle(this.itemId).map(data => data as DatasetWizardModel) this.datasetWizardService.getSingle(this.itemId).map(data => data as DatasetWizardModel)
.subscribe(data => { .subscribe(data => {
this.datasetWizardModel = JsonSerializer.fromJSONObject(data, DatasetWizardModel); this.datasetWizardModel = JsonSerializer.fromJSONObject(data, DatasetWizardModel);
this.breadCrumbs = Observable.of([
{
parentComponentName: null,
label: 'Datasets',
url: '/datasets',
notFoundResolver: [
{
parentComponentName: null,
label: this.datasetWizardModel.dmp.project.label,
url: '/projects/edit/' + this.datasetWizardModel.dmp.project.id
},
{
parentComponentName: null,
label: this.datasetWizardModel.dmp.label,
url: '/dmps/edit/' + this.datasetWizardModel.dmp.id,
},
]
}]);
this.formGroup = this.datasetWizardModel.buildForm();
this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft;
if (this.datasetWizardModel.status === 1) {
this.formGroup.disable();
this.viewOnly = true;
}
if (this.viewOnly) { this.formGroup.disable(); }
this.loadDatasetProfiles();
});
} else if (dmpId != null) {
this.isNew = true;
this.dataManagementPlanService.getSingle(dmpId).map(data => data as DataManagementPlanModel)
.subscribe(data => {
this.datasetWizardModel = new DatasetWizardModel();
setTimeout(() => {
this.datasetWizardModel.dmp = data;
this.formGroup = this.datasetWizardModel.buildForm();
this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft;
if (this.datasetWizardModel.status === 1) {
this.formGroup.disable();
this.viewOnly = true;
}
this.loadDatasetProfiles();
this.breadCrumbs = Observable.of([ this.breadCrumbs = Observable.of([
{ {
parentComponentName: null, parentComponentName: null,
@ -178,65 +219,23 @@ export class DatasetWizardComponent implements OnInit, AfterViewInit, IBreadCrum
parentComponentName: null, parentComponentName: null,
label: this.datasetWizardModel.dmp.label, label: this.datasetWizardModel.dmp.label,
url: '/dmps/edit/' + this.datasetWizardModel.dmp.id, url: '/dmps/edit/' + this.datasetWizardModel.dmp.id,
}, }]
]
}]); }]);
this.formGroup = this.datasetWizardModel.buildForm();
this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft;
if (this.datasetWizardModel.status === 1) {
this.formGroup.disable();
this.viewOnly = true;
}
if (this.viewOnly) { this.formGroup.disable(); }
this.loadDatasetProfiles();
}); });
} else if (dmpId != null) {
this.isNew = true;
this.dataManagementPlanService.getSingle(dmpId).map(data => data as DataManagementPlanModel)
.subscribe(data => {
this.datasetWizardModel = new DatasetWizardModel();
setTimeout(() => {
this.datasetWizardModel.dmp = data;
this.formGroup = this.datasetWizardModel.buildForm();
this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft;
if (this.datasetWizardModel.status === 1) {
this.formGroup.disable();
this.viewOnly = true;
}
this.loadDatasetProfiles();
this.breadCrumbs = Observable.of([
{
parentComponentName: null,
label: 'Datasets',
url: '/datasets',
notFoundResolver: [
{
parentComponentName: null,
label: this.datasetWizardModel.dmp.project.label,
url: '/projects/edit/' + this.datasetWizardModel.dmp.project.id
},
{
parentComponentName: null,
label: this.datasetWizardModel.dmp.label,
url: '/dmps/edit/' + this.datasetWizardModel.dmp.id,
}]
}]);
});
});
} else {
this.datasetWizardModel = new DatasetWizardModel();
this.formGroup = this.datasetWizardModel.buildForm();
this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft;
if (this.datasetWizardModel.status === 1) {
this.formGroup.disable();
this.viewOnly = true;
}
if (this.viewOnly) { this.formGroup.disable(); }
this.formGroup.get('dmp').valueChanges.subscribe(x => {
this.loadDatasetProfiles();
}); });
} else {
this.datasetWizardModel = new DatasetWizardModel();
this.formGroup = this.datasetWizardModel.buildForm();
this.editMode = this.datasetWizardModel.status === DatasetStatus.Draft;
if (this.datasetWizardModel.status === 1) {
this.formGroup.disable();
this.viewOnly = true;
} }
}); if (this.viewOnly) { this.formGroup.disable(); }
this.formGroup.get('dmp').valueChanges.subscribe(x => {
this.loadDatasetProfiles();
});
}
} }
ngAfterViewInit() { ngAfterViewInit() {
@ -490,4 +489,8 @@ export class DatasetWizardComponent implements OnInit, AfterViewInit, IBreadCrum
this.viewOnly = true; this.viewOnly = true;
this.formGroup.disable(); 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" <textarea matInput formControlName="value" matTextareaAutosize matAutosizeMinRows="2" matAutosizeMaxRows="10"
[required]="field.validationRequired"> [required]="field.validationRequired">
</textarea> </textarea>
<button mat-button *ngIf="!form.get('value').disabled && form.get('value').value" matSuffix mat-icon-button <button mat-button *ngIf="!form.get('value').disabled && form.get('value').value" matSuffix mat-icon-button
aria-label="Clear" (click)="this.form.patchValue({'value': ''})"> 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 { export class DynamicFormFieldComponent implements OnInit, OnChanges, OnDestroy {
@Input() field: Field; @Input() field: Field;
form: FormGroup; form: FormGroup;
@Input() pathName: string;
@Input() path: string;
change: Subscription; change: Subscription;
trackByFn = (index, item) => item ? item['id'] : null; trackByFn = (index, item) => item ? item['id'] : null;
constructor(private route: ActivatedRoute, public visibilityRulesService: VisibilityRulesService) { constructor(private route: ActivatedRoute, public visibilityRulesService: VisibilityRulesService) {
} }

View File

@ -1,14 +1,20 @@
<div *ngIf="form" [id]="compositeField.id" [formGroup]="form"> <div *ngIf="form" [id]="compositeField.id" [formGroup]="form">
<div *ngIf="compositeField.fields.length == 1" class="fieldset-component"> <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"> <div class="content-left-margin">
<h5 *ngIf="compositeField.description">{{compositeField.description}}</h5> <h5 *ngIf="compositeField.description">{{compositeField.description}}</h5>
<h5 *ngIf="compositeField.extendedDescription" class="fieldset-extended-desc"> <h5 *ngIf="compositeField.extendedDescription" class="fieldset-extended-desc">
<i>{{compositeField.extendedDescription}}</i> <i>{{compositeField.extendedDescription}}</i>
</h5> </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>
</div> </div>
@ -28,13 +34,14 @@
</div> </div>
</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 *ngIf="field">
<div *ngFor="let multipleField of field.multiplicityItems; let j = index; trackBy: trackByFn"> <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>
</div> </div>
</div> </div>
</div> </div>

View File

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

View File

@ -1,20 +1,20 @@
<div *ngIf="form" class="group-component" [id]="group.id" [formGroup]="form"> <div *ngIf="form" class="group-component" [id]="group.id" [formGroup]="form">
<div class="content-left-margin"> <div class="content-left-margin">
<div *ngFor="let compositeField of group.compositeFields; let i = index; trackBy: trackByFn"> <div *ngFor="let compositeField of group.compositeFields; let i = index; trackBy: trackByFn">
<div> <div>
<div *ngIf="(compositeField?.multiplicity?.max - 1) > (compositeField?.multiplicityItems?.length)"> <div *ngIf="(compositeField?.multiplicity?.max - 1) > (compositeField?.multiplicityItems?.length)">
<a (click)="addMultipleField(i)" style="cursor: pointer"> <a (click)="addMultipleField(i)" style="cursor: pointer">
Add one more fieldset + Add one more fieldset +
</a> </a>
</div> </div>
</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 *ngIf="compositeField">
<div *ngFor="let multipleCompositeField of compositeField.multiplicityItems; let j = index; trackBy: trackByFn"> <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> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -18,16 +18,19 @@
Add one more fieldset + Add one more fieldset +
</a> </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 *ngIf="compositeField">
<div *ngFor="let multipleCompositeField of compositeField.multiplicityItems; let j = index; trackBy: trackByFn"> <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 *ngIf="compositeField.hasCommentField" [formGroup]="form.get('compositeFields').get(''+i)"> <div *ngIf="compositeField.hasCommentField" [formGroup]="form.get('compositeFields').get(''+i)">
<mat-form-field> <mat-form-field>
<input matInput formControlName="commentFieldValue" placeholder="comment"> <input matInput formControlName="commentFieldValue" placeholder="comment">
</mat-form-field> </mat-form-field>
</div> </div>
<button mat-icon-button type="button" (click)="next(compositeField)">
<mat-icon>expand_more</mat-icon>
</button>
</div> </div>
</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 { Component, Input, OnInit, ViewEncapsulation, ChangeDetectionStrategy, AfterViewInit } from '@angular/core';
import { CompositeField } from '../../models/CompositeField'; import { CompositeField } from '../../models/CompositeField';
import { Section } from '../../models/Section'; import { Section } from '../../models/Section';
import { FormFocusService } from '../../utilities/form-focus-service/form-focus.service';
@Component({ @Component({
@ -20,7 +21,10 @@ export class DynamicFormSectionComponent implements OnInit, AfterViewInit {
@Input() pathName: string; @Input() pathName: string;
@Input() path: string; @Input() path: string;
trackByFn = (index, item) => item ? item['id'] : null; trackByFn = (index, item) => item ? item['id'] : null;
constructor(public visibilityRulesService: VisibilityRulesService) { } constructor(
public visibilityRulesService: VisibilityRulesService,
private formFocusService: FormFocusService
) { }
ngOnInit() { ngOnInit() {
if (this.section) { if (this.section) {
@ -47,4 +51,8 @@ export class DynamicFormSectionComponent implements OnInit, AfterViewInit {
} }
return false; 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 { DatasetProfileAdmin } from '../services/datasetProfileAdmin/datasetProfileAfmin.service';
import { DatasetProfileService } from '../services/dataset-profile.service'; import { DatasetProfileService } from '../services/dataset-profile.service';
import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.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({ @NgModule({
@ -57,6 +60,7 @@ import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.
DynamicFormCompositeFieldComponent, DynamicFormCompositeFieldComponent,
DynamicFieldBooleanDecisionComponent, DynamicFieldBooleanDecisionComponent,
DynamicFieldRadioBoxComponent, DynamicFieldRadioBoxComponent,
DynamicFormPendingQuestionsDisplayComponent,
TableOfContentsComponent, TableOfContentsComponent,
TableOfContentsFieldSetComponent, TableOfContentsFieldSetComponent,
TableOfContentsGroupComponent, TableOfContentsGroupComponent,
@ -76,6 +80,7 @@ import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.
DynamicFormCompositeFieldComponent, DynamicFormCompositeFieldComponent,
DynamicFieldBooleanDecisionComponent, DynamicFieldBooleanDecisionComponent,
DynamicFieldRadioBoxComponent, DynamicFieldRadioBoxComponent,
DynamicFormPendingQuestionsDisplayComponent,
TableOfContentsComponent, TableOfContentsComponent,
TableOfContentsFieldSetComponent, TableOfContentsFieldSetComponent,
TableOfContentsGroupComponent, TableOfContentsGroupComponent,
@ -92,7 +97,9 @@ import { DatasetWizardService } from '../services/dataset-wizard/dataset-wizard.
PaginationService, PaginationService,
DatasetProfileService, DatasetProfileService,
DatasetProfileAdmin, 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 { VisibilityRulesService } from '../../utilities/visibility-rules/visibility-rules.service';
import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel'; import { DatasetProfileDefinitionModel } from '../../models/DatasetProfileDefinitionModel';
import { DatasetWizardModel } from '../../models/datasets/DatasetWizardModel'; 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 { FormGroup } from '@angular/forms';
import { Router, ActivatedRoute } from '@angular/router'; import { Router, ActivatedRoute } from '@angular/router';
import 'rxjs/add/operator/switchMap'; import 'rxjs/add/operator/switchMap';
import '../../utilities/enhancers/flatJoinOn';
import { Location } from '@angular/common'; 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({ @Component({
selector: 'app-dynamic-form', selector: 'app-dynamic-form',
@ -19,6 +25,7 @@ import { Location } from '@angular/common';
'./dynamic-form.component.scss' './dynamic-form.component.scss'
], ],
providers: [ providers: [
FormFocusService
], ],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
}) })
@ -31,6 +38,7 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
datasetProfileDefinitionModel: DatasetProfileDefinitionModel; datasetProfileDefinitionModel: DatasetProfileDefinitionModel;
private progressbar = false; private progressbar = false;
private currentPageIndex = 0; private currentPageIndex = 0;
@ViewChild('stepper') stepper: MatStepper;
@Input() dataModel: DatasetWizardModel = new DatasetWizardModel(); @Input() dataModel: DatasetWizardModel = new DatasetWizardModel();
@Input() path: string; @Input() path: string;
@ -43,11 +51,9 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
constructor( constructor(
private router: Router, private router: Router,
private _location: Location,
private route: ActivatedRoute, private route: ActivatedRoute,
private visibilityRulesService: VisibilityRulesService, private visibilityRulesService: VisibilityRulesService,
private http: BaseHttpService, private formFocusService: FormFocusService
private datasetWizardService: DatasetWizardService,
) { ) {
//this.datasetId = route.snapshot.params['id']; //this.datasetId = route.snapshot.params['id'];
} }
@ -64,14 +70,26 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
this.visibilityRulesService.buildVisibilityRules(rules); this.visibilityRulesService.buildVisibilityRules(rules);
this.datasetProfileDefinitionModel = this.dataModel.datasetProfileDefinition; this.datasetProfileDefinitionModel = this.dataModel.datasetProfileDefinition;
this.visibilityRulesService.setModel(this.datasetProfileDefinitionModel); this.visibilityRulesService.setModel(this.datasetProfileDefinitionModel);
this.createPagination(); this.createPagination();
this.progressbar = true; 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) => { this.route.fragment.subscribe((fragment: string) => {
const self = this; const self = this;
setTimeout(function () { self.scrollTo(fragment); }); setTimeout(function () { self.scrollTo(fragment); });
}); });
}
ngAfterViewInit() {
this.visibilityRulesService.triggerVisibilityEvaluation();
this.route.queryParams.subscribe((params) => { this.route.queryParams.subscribe((params) => {
if (params && 'page' in params) { if (params && 'page' in params) {
this.changeCurrentPage(params['page']); this.changeCurrentPage(params['page']);
@ -79,35 +97,17 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
}); });
} }
ngAfterViewInit() {
this.visibilityRulesService.triggerVisibilityEvaluation();
}
toggleSidebar() { toggleSidebar() {
this.visibleSidebar = !this.visibleSidebar; 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 { shouldDisplaySection(section: Section): Boolean {
return (section.page) === this.currentPageIndex; return (section.page) === this.currentPageIndex;
} }
createPagination() { createPagination() {
/*this.pages.forEach(item => {
this.stepperItems.push({
label: '',
})
});*/
} }
changePageIndex(index: any) { changePageIndex(index: any) {
@ -120,16 +120,14 @@ export class DynamicFormComponent implements OnInit, AfterViewInit {
if (!element) { return; } if (!element) { return; }
element.scrollIntoView(); element.scrollIntoView();
this.visibleSidebar = true; this.visibleSidebar = true;
const scrollElement = document.querySelector('.scrollableContent');
//scrollElement.scrollTop = topElement.offsetTop;
} }
changeCurrentPage(pageString: string) { changeCurrentPage(pageString: string) {
if (!pageString) { return; } //if (!pageString) { return; }
const page = parseInt(pageString); const page = parseInt(pageString);
if (isNaN(page)) { return; } /*if (isNaN(page)) { return; }
const pageIndex = this.pages.indexOf(page); const pageIndex = this.pages.indexOf(page);
if (pageIndex === -1) { return; } if (pageIndex === -1) { return; }*/
this.currentPageIndex = page; 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({ @Component({
selector: 'app-dynamic-form-pending-questions-display', selector: 'app-dynamic-form-pending-questions-display',
templateUrl: './dynamic-form-pending-questions-display.component.html', templateUrl: './dynamic-form-pending-questions-display.component.html',
@ -11,7 +21,32 @@ import { Component, ViewEncapsulation, OnInit } from '@angular/core';
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
}) })
export class DynamicFormPendingQuestionsDisplayComponent implements OnInit { 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 { 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 { 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>) { public buildVisibilityRules(item: Array<Rule>) {
@ -90,7 +90,7 @@ export class VisibilityRulesService {
parseValue(value: any) { parseValue(value: any) {
if (typeof value === 'string') { 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; } } else { return value; }
} }
@ -137,4 +137,12 @@ export class VisibilityRulesService {
} }
} }
} }
private translate(item: any) {
try {
return JSON.parse(item).value;
} catch (error) {
return item;
}
}
} }