Merge pull request #52 in DEFINMA/definma-ui from f/prediction-delta to master
* commit 'f7f351d6a303899fd86628d142e8585e03809636': Add very simple prediction delta UI Allow viscosity number predictions to be saved
This commit is contained in:
		@@ -11,6 +11,7 @@ import {UsersComponent} from './users/users.component';
 | 
				
			|||||||
import {ChangelogComponent} from './changelog/changelog.component';
 | 
					import {ChangelogComponent} from './changelog/changelog.component';
 | 
				
			||||||
import {DocumentationDatabaseComponent} from './documentation/documentation-database/documentation-database.component';
 | 
					import {DocumentationDatabaseComponent} from './documentation/documentation-database/documentation-database.component';
 | 
				
			||||||
import {PredictionComponent} from './prediction/prediction.component';
 | 
					import {PredictionComponent} from './prediction/prediction.component';
 | 
				
			||||||
 | 
					import {PredictionDeltaComponent} from './prediction-delta/prediction-delta.component';
 | 
				
			||||||
import {ModelTemplatesComponent} from './model-templates/model-templates.component';
 | 
					import {ModelTemplatesComponent} from './model-templates/model-templates.component';
 | 
				
			||||||
import {DocumentationArchitectureComponent} from
 | 
					import {DocumentationArchitectureComponent} from
 | 
				
			||||||
'./documentation/documentation-architecture/documentation-architecture.component';
 | 
					'./documentation/documentation-architecture/documentation-architecture.component';
 | 
				
			||||||
@@ -23,6 +24,7 @@ const routes: Routes = [
 | 
				
			|||||||
	{path: '', component: HomeComponent},
 | 
						{path: '', component: HomeComponent},
 | 
				
			||||||
	{path: 'home', component: HomeComponent},
 | 
						{path: 'home', component: HomeComponent},
 | 
				
			||||||
	{path: 'prediction', component: PredictionComponent},
 | 
						{path: 'prediction', component: PredictionComponent},
 | 
				
			||||||
 | 
						{path: 'prediction-delta', component: PredictionDeltaComponent},
 | 
				
			||||||
	{path: 'models', component: ModelTemplatesComponent},
 | 
						{path: 'models', component: ModelTemplatesComponent},
 | 
				
			||||||
	{path: 'samples', component: SamplesComponent, canActivate: [LoginService]},
 | 
						{path: 'samples', component: SamplesComponent, canActivate: [LoginService]},
 | 
				
			||||||
	{path: 'samples/new', component: SampleComponent, canActivate: [LoginService]},
 | 
						{path: 'samples/new', component: SampleComponent, canActivate: [LoginService]},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
	<nav *rbMainNavItems>
 | 
						<nav *rbMainNavItems>
 | 
				
			||||||
		<a routerLink="/home" routerLinkActive="active" rbLoadingLink>Home</a>
 | 
							<a routerLink="/home" routerLinkActive="active" rbLoadingLink>Home</a>
 | 
				
			||||||
		<a routerLink="/prediction" routerLinkActive="active" rbLoadingLink *ngIf="login.hasPrediction">Prediction</a>
 | 
							<a routerLink="/prediction" routerLinkActive="active" rbLoadingLink *ngIf="login.hasPrediction">Prediction</a>
 | 
				
			||||||
 | 
							<a routerLink="/prediction-delta" routerLinkActive="active" rbLoadingLink *ngIf="login.hasPrediction">Prediction Delta</a>
 | 
				
			||||||
		<a routerLink="/models" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.dev">Models</a>
 | 
							<a routerLink="/models" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.dev">Models</a>
 | 
				
			||||||
		<a routerLink="/samples" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.read">Samples</a>
 | 
							<a routerLink="/samples" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.read">Samples</a>
 | 
				
			||||||
		<a routerLink="/materials" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.dev">Materials</a>
 | 
							<a routerLink="/materials" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.dev">Materials</a>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -37,6 +37,7 @@ import { DocumentationArchitectureComponent } from
 | 
				
			|||||||
import { MaterialsComponent } from './materials/materials.component';
 | 
					import { MaterialsComponent } from './materials/materials.component';
 | 
				
			||||||
import { MaterialComponent } from './material/material.component';
 | 
					import { MaterialComponent } from './material/material.component';
 | 
				
			||||||
import { DocumentationModelsComponent } from './documentation/documentation-models/documentation-models.component';
 | 
					import { DocumentationModelsComponent } from './documentation/documentation-models/documentation-models.component';
 | 
				
			||||||
 | 
					import { PredictionDeltaComponent } from './prediction-delta/prediction-delta.component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@NgModule({
 | 
					@NgModule({
 | 
				
			||||||
	declarations: [
 | 
						declarations: [
 | 
				
			||||||
@@ -64,7 +65,8 @@ import { DocumentationModelsComponent } from './documentation/documentation-mode
 | 
				
			|||||||
		DocumentationArchitectureComponent,
 | 
							DocumentationArchitectureComponent,
 | 
				
			||||||
		MaterialsComponent,
 | 
							MaterialsComponent,
 | 
				
			||||||
		MaterialComponent,
 | 
							MaterialComponent,
 | 
				
			||||||
		DocumentationModelsComponent
 | 
							DocumentationModelsComponent,
 | 
				
			||||||
 | 
							PredictionDeltaComponent
 | 
				
			||||||
	],
 | 
						],
 | 
				
			||||||
	imports: [
 | 
						imports: [
 | 
				
			||||||
		LocalStorageModule.forRoot({
 | 
							LocalStorageModule.forRoot({
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								src/app/prediction-delta/prediction-delta.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/app/prediction-delta/prediction-delta.component.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					<h4>Enter the names of two predictions to compare</h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<rb-form-input label="Prediction A" [(ngModel)]="nameA"></rb-form-input>
 | 
				
			||||||
 | 
					<rb-form-input label="Prediction B" [(ngModel)]="nameB"></rb-form-input>
 | 
				
			||||||
 | 
					<p *ngIf="delta">
 | 
				
			||||||
 | 
						The result is {{ delta }}.
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
 | 
					<rb-icon-button icon="forward-right" mode="primary" (click)="compare()">
 | 
				
			||||||
 | 
						Compare Predictions
 | 
				
			||||||
 | 
					</rb-icon-button>
 | 
				
			||||||
							
								
								
									
										25
									
								
								src/app/prediction-delta/prediction-delta.component.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/app/prediction-delta/prediction-delta.component.spec.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import { PredictionDeltaComponent } from './prediction-delta.component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					describe('PredictionDeltaComponent', () => {
 | 
				
			||||||
 | 
					  let component: PredictionDeltaComponent;
 | 
				
			||||||
 | 
					  let fixture: ComponentFixture<PredictionDeltaComponent>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(async(() => {
 | 
				
			||||||
 | 
					    TestBed.configureTestingModule({
 | 
				
			||||||
 | 
					      declarations: [ PredictionDeltaComponent ]
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    .compileComponents();
 | 
				
			||||||
 | 
					  }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  beforeEach(() => {
 | 
				
			||||||
 | 
					    fixture = TestBed.createComponent(PredictionDeltaComponent);
 | 
				
			||||||
 | 
					    component = fixture.componentInstance;
 | 
				
			||||||
 | 
					    fixture.detectChanges();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  it('should create', () => {
 | 
				
			||||||
 | 
					    expect(component).toBeTruthy();
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										41
									
								
								src/app/prediction-delta/prediction-delta.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/app/prediction-delta/prediction-delta.component.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					import { Component } from '@angular/core';
 | 
				
			||||||
 | 
					import { animate, style, transition, trigger } from '@angular/animations';
 | 
				
			||||||
 | 
					import { ApiService } from '../services/api.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
						selector: 'app-prediction-delta',
 | 
				
			||||||
 | 
						templateUrl: './prediction-delta.component.html',
 | 
				
			||||||
 | 
						styleUrls: ['./prediction-delta.component.scss'],
 | 
				
			||||||
 | 
						animations: [
 | 
				
			||||||
 | 
							trigger(
 | 
				
			||||||
 | 
								'inOut', [
 | 
				
			||||||
 | 
									transition(':enter', [
 | 
				
			||||||
 | 
										style({height: 0, opacity: 0}),
 | 
				
			||||||
 | 
										animate('0.5s ease-out', style({height: '*', opacity: 1}))
 | 
				
			||||||
 | 
									]),
 | 
				
			||||||
 | 
									transition(':leave', [
 | 
				
			||||||
 | 
										style({height: '*', opacity: 1}),
 | 
				
			||||||
 | 
										animate('0.5s ease-in', style({height: 0, opacity: 0}))
 | 
				
			||||||
 | 
									])
 | 
				
			||||||
 | 
								]
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						]
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class PredictionDeltaComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nameA: String;
 | 
				
			||||||
 | 
						nameB: String;
 | 
				
			||||||
 | 
						delta: Number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						constructor(
 | 
				
			||||||
 | 
							private api: ApiService,
 | 
				
			||||||
 | 
						) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Compares the two predictions
 | 
				
			||||||
 | 
						compare() {
 | 
				
			||||||
 | 
							let data = { nameA: this.nameA, nameB: this.nameB };
 | 
				
			||||||
 | 
							this.api.post<Number>('/prediction/compare', data, result => {
 | 
				
			||||||
 | 
								this.delta = result;
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -40,7 +40,7 @@
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="file-input space-below">
 | 
					<div class="file-input space-below">
 | 
				
			||||||
	<rb-form-file name="spectrum-upload" label="spectrum file" maxSize="10000000" class="space-below" multiple
 | 
						<rb-form-file name="spectrum-upload" label="Spectrum File" maxSize="10000000" class="space-below" multiple
 | 
				
			||||||
		(ngModelChange)="fileToArray($event)" placeholder="Select file or drag and drop" dragDrop ngModel>
 | 
							(ngModelChange)="fileToArray($event)" placeholder="Select file or drag and drop" dragDrop ngModel>
 | 
				
			||||||
	</rb-form-file>
 | 
						</rb-form-file>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -72,6 +72,20 @@
 | 
				
			|||||||
	Export to PDF
 | 
						Export to PDF
 | 
				
			||||||
</rb-icon-button>
 | 
					</rb-icon-button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- Save Prediction -->
 | 
				
			||||||
 | 
					<!-- Only available for single sample viscosity number predictions -->
 | 
				
			||||||
 | 
					<div *ngIf="spectrumNames.length && !multipleSamples && activeGroup.group === 'Viscosity Number'">
 | 
				
			||||||
 | 
					<rb-form-input name="prediction-name" label="Prediction Name" [(ngModel)]="predictionName"></rb-form-input>
 | 
				
			||||||
 | 
					<rb-icon-button icon="forward-right" mode="secondary" (click)="savePrediction()" [rbModal]="modalSuccess">
 | 
				
			||||||
 | 
						Save Prediction
 | 
				
			||||||
 | 
					</rb-icon-button>
 | 
				
			||||||
 | 
					<ng-template #modalSuccess>
 | 
				
			||||||
 | 
						<rb-alert alertTitle="Success" type="success" okBtnLabel="Got it">
 | 
				
			||||||
 | 
							Prediction saved!
 | 
				
			||||||
 | 
						</rb-alert>
 | 
				
			||||||
 | 
					</ng-template>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="dpt-chart space-below">
 | 
					<div class="dpt-chart space-below">
 | 
				
			||||||
	<canvas baseChart
 | 
						<canvas baseChart
 | 
				
			||||||
		class="dpt-chart"
 | 
							class="dpt-chart"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,8 +39,11 @@ export class PredictionComponent implements OnInit {
 | 
				
			|||||||
	loading = false;
 | 
						loading = false;
 | 
				
			||||||
	activeGroup: ModelItemModel = new ModelItemModel();
 | 
						activeGroup: ModelItemModel = new ModelItemModel();
 | 
				
			||||||
	activeModelIndex = 0;
 | 
						activeModelIndex = 0;
 | 
				
			||||||
 | 
						predictionName: String;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If true, spectra belong to different samples, otherwise multiple spectra from the same sample are given
 | 
						// If true, spectra belong to different samples, otherwise multiple spectra from the same sample are given
 | 
				
			||||||
	multipleSamples = false;
 | 
						multipleSamples = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spectrumNames: string[] = [];
 | 
						spectrumNames: string[] = [];
 | 
				
			||||||
	spectrum: string[][] = [[]];
 | 
						spectrum: string[][] = [[]];
 | 
				
			||||||
	flattenedSpectra = [];
 | 
						flattenedSpectra = [];
 | 
				
			||||||
@@ -122,12 +125,20 @@ export class PredictionComponent implements OnInit {
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	groupChange(index) {  // Group was changed
 | 
						// Group was changed
 | 
				
			||||||
 | 
						groupChange(index) {
 | 
				
			||||||
		this.activeGroup = this.d.arr.modelGroups[index];
 | 
							this.activeGroup = this.d.arr.modelGroups[index];
 | 
				
			||||||
		this.activeModelIndex = 0;
 | 
							this.activeModelIndex = 0;
 | 
				
			||||||
		this.result = undefined;
 | 
							this.result = undefined;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Save prediction to database
 | 
				
			||||||
 | 
						// This is not suited for multiple samples
 | 
				
			||||||
 | 
						savePrediction() {
 | 
				
			||||||
 | 
							let prediction = { name: this.predictionName, value: this.result.mean[0].value };
 | 
				
			||||||
 | 
							this.api.post<any>('/prediction/new', prediction);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Aggregates spectrum names and prediction values into an associative array
 | 
						// Aggregates spectrum names and prediction values into an associative array
 | 
				
			||||||
	prepareExport() {
 | 
						prepareExport() {
 | 
				
			||||||
		const zip = (a, b) => a.map((k, i) => [k, b[i]]);
 | 
							const zip = (a, b) => a.map((k, i) => [k, b[i]]);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user