Merge pull request #21 in ~VLE2FE/definma-ui from development to master
* commit '9197e8a1875f5a696861e44cfec3547b8a5cccfa': started testing fixed type filter pwa, save sample view preferences added prediction prototype
@ -1,4 +1,4 @@
|
||||
# Digital fingerprint of plastics - UI
|
||||
# DeFinMa - UI
|
||||
|
||||
This is the Angular front end for the digital fingerprint of plastics web page hosted in the bic
|
||||
|
||||
|
26
angular.json
@ -3,7 +3,7 @@
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"UI": {
|
||||
"definma": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
@ -17,7 +17,7 @@
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/UI",
|
||||
"outputPath": "dist/definma",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
@ -30,7 +30,8 @@
|
||||
"glob": "**/*",
|
||||
"input": "./node_modules/@inst-iot/bosch-angular-ui-components/assets",
|
||||
"output": "./assets"
|
||||
}
|
||||
},
|
||||
"src/manifest.webmanifest"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
@ -64,26 +65,28 @@
|
||||
"maximumWarning": "6kb",
|
||||
"maximumError": "10kb"
|
||||
}
|
||||
]
|
||||
],
|
||||
"serviceWorker": true,
|
||||
"ngswConfigPath": "ngsw-config.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "UI:build",
|
||||
"browserTarget": "definma:build",
|
||||
"proxyConfig": "src/proxy.conf.json"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "UI:build:production"
|
||||
"browserTarget": "definma:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "UI:build"
|
||||
"browserTarget": "definma:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
@ -95,7 +98,8 @@
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
"src/assets",
|
||||
"src/manifest.webmanifest"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
@ -120,15 +124,15 @@
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "UI:serve"
|
||||
"devServerTarget": "definma:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "UI:serve:production"
|
||||
"devServerTarget": "definma:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}},
|
||||
"defaultProject": "UI"
|
||||
"defaultProject": "definma"
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
pushstate: enabled
|
||||
force_https: true
|
||||
root: UI
|
||||
root: definma
|
||||
location_include: ../../*.conf
|
||||
|
@ -13,10 +13,13 @@ module.exports = function (config) {
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
jasmine: {
|
||||
random: false
|
||||
}
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/UI'),
|
||||
dir: require('path').join(__dirname, './coverage/definma'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
|
29
ngsw-config.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
||||
"index": "/index.html",
|
||||
"assetGroups": [
|
||||
{
|
||||
"name": "app",
|
||||
"installMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/favicon.ico",
|
||||
"/index.html",
|
||||
"/manifest.webmanifest",
|
||||
"/*.css",
|
||||
"/*.js"
|
||||
]
|
||||
}
|
||||
}, {
|
||||
"name": "assets",
|
||||
"installMode": "lazy",
|
||||
"updateMode": "prefetch",
|
||||
"resources": {
|
||||
"files": [
|
||||
"/assets/**",
|
||||
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
9
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ui",
|
||||
"version": "0.0.0",
|
||||
"name": "definma",
|
||||
"version": "0.5.5",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -630,6 +630,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@angular/router/-/router-9.1.7.tgz",
|
||||
"integrity": "sha512-ycrkhkCbfOMCe9PngFjnyk8nH5jt0Kyb2NPtjmaGOtSCuZBZ0kOU0rQGmQnj3d2PiT0Yir59S8eEAf3Fh0iDuw=="
|
||||
},
|
||||
"@angular/service-worker": {
|
||||
"version": "9.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@angular/service-worker/-/service-worker-9.1.12.tgz",
|
||||
"integrity": "sha512-UsmhPfhIYq9LanuFT6V7Kmkr5Vjl2CMjKkL1gqhChkywNW4vavAYsBkuVji8P76ZKliq41TCG01z6xIAWji8QA=="
|
||||
},
|
||||
"@babel/code-frame": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"@angular/platform-browser": "~9.1.7",
|
||||
"@angular/platform-browser-dynamic": "~9.1.7",
|
||||
"@angular/router": "~9.1.7",
|
||||
"@angular/service-worker": "~9.1.7",
|
||||
"@hapi/joi": "^17.1.1",
|
||||
"@inst-iot/bosch-angular-ui-components": "^0.7.2",
|
||||
"angular-2-local-storage": "^3.0.2",
|
||||
|
@ -10,11 +10,13 @@ import {SettingsComponent} from './settings/settings.component';
|
||||
import {UsersComponent} from './users/users.component';
|
||||
import {ChangelogComponent} from './changelog/changelog.component';
|
||||
import {DocumentationDatabaseComponent} from './documentation-database/documentation-database.component';
|
||||
import {PredictionComponent} from './prediction/prediction.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{path: '', component: HomeComponent},
|
||||
{path: 'home', component: HomeComponent},
|
||||
{path: 'prediction', component: PredictionComponent},
|
||||
{path: 'samples', component: SamplesComponent, canActivate: [LoginService]},
|
||||
{path: 'samples/new', component: SampleComponent, canActivate: [LoginService]},
|
||||
{path: 'samples/edit/:id', component: SampleComponent, canActivate: [LoginService]},
|
||||
|
@ -1,6 +1,7 @@
|
||||
<rb-full-header id="top">
|
||||
<nav *rbMainNavItems>
|
||||
<a routerLink="/home" routerLinkActive="active" rbLoadingLink>Home</a>
|
||||
<a routerLink="/prediction" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.admin">Prediction</a>
|
||||
<a routerLink="/samples" routerLinkActive="active" rbLoadingLink *ngIf="login.isLoggedIn">Samples</a>
|
||||
<a routerLink="/templates" routerLinkActive="active" rbLoadingLink *ngIf="login.isLevel.dev">
|
||||
Templates
|
||||
|
@ -4,8 +4,13 @@ import {By} from '@angular/platform-browser';
|
||||
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {LoginService} from './services/login.service';
|
||||
import {Router} from '@angular/router';
|
||||
|
||||
// TODO
|
||||
|
||||
let loginServiceSpy: jasmine.SpyObj<LoginService>;
|
||||
let routerServiceSpy: jasmine.SpyObj<Router>;
|
||||
let windowServiceSpy: jasmine.SpyObj<Window>;
|
||||
|
||||
describe('AppComponent', () => {
|
||||
let component: AppComponent;
|
||||
@ -14,6 +19,8 @@ describe('AppComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
const loginSpy = jasmine.createSpyObj('LoginService', ['login', 'canActivate']);
|
||||
const routerSpy = jasmine.createSpyObj('Router', ['navigate', 'events']);
|
||||
const windowSpy = jasmine.createSpyObj('Window', ['location', 'innerWidth', 'innerHeight', 'scroll']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ AppComponent ],
|
||||
@ -22,10 +29,15 @@ describe('AppComponent', () => {
|
||||
RouterTestingModule
|
||||
],
|
||||
providers: [
|
||||
{provide: LoginService, useValue: loginSpy}
|
||||
{provide: LoginService, useValue: loginSpy},
|
||||
{provide: Router, useValue: routerSpy},
|
||||
{provide: Window, useValue: windowSpy}
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
loginServiceSpy = TestBed.inject(LoginService) as jasmine.SpyObj<LoginService>;
|
||||
routerServiceSpy = TestBed.inject(Router) as jasmine.SpyObj<Router>;
|
||||
windowServiceSpy = TestBed.inject(Window) as jasmine.SpyObj<Window>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -2,12 +2,6 @@ import { Component, isDevMode} from '@angular/core';
|
||||
import {LoginService} from './services/login.service';
|
||||
import {NavigationStart, Router} from '@angular/router';
|
||||
|
||||
// TODO: add multiple samples at once
|
||||
// TODO: validation: DPT: filename
|
||||
// TODO: filter by not completely filled/no measurements
|
||||
// TODO: validation of samples
|
||||
// TODO: centralize fetching of materials / templates, etc.
|
||||
// TODO: PWA
|
||||
|
||||
// TODO: get rid of chart.js (+moment.js)
|
||||
|
||||
@ -24,7 +18,8 @@ export class AppComponent {
|
||||
|
||||
constructor(
|
||||
public login: LoginService,
|
||||
public router: Router
|
||||
public router: Router,
|
||||
private window: Window
|
||||
) {
|
||||
this.devMode = isDevMode();
|
||||
this.router.events.subscribe(event => {
|
||||
@ -43,7 +38,7 @@ export class AppComponent {
|
||||
return `mailto:lukas.veit@de.bosch.com?subject=Bug report&body=Thanks for sending the report! Your bug will be (hopefully) fixed soon.
|
||||
%0D%0A%0D%0A--- REPORT DATA ---
|
||||
%0D%0A%0D%0ATime: ${new Date().toString()}%0D%0A
|
||||
URL: ${window.location}%0D%0A%0D%0AWhat did you do?%0D%0A${encodeURIComponent(this.bugReport.do)}
|
||||
URL: ${this.window.location}%0D%0A%0D%0AWhat did you do?%0D%0A${encodeURIComponent(this.bugReport.do)}
|
||||
%0D%0A%0D%0AWhat did not work?%0D%0A${encodeURIComponent(this.bugReport.work)}%0D%0A%0D%0ABrowser:%0D%0A
|
||||
%0D%0AappCodeName: ${navigator.appCodeName}
|
||||
%0D%0AappVersion: ${navigator.appVersion}
|
||||
@ -52,8 +47,8 @@ URL: ${window.location}%0D%0A%0D%0AWhat did you do?%0D%0A${encodeURIComponent(th
|
||||
%0D%0Aoscpu: ${navigator.oscpu}
|
||||
%0D%0Aplatform: ${navigator.platform}
|
||||
%0D%0AuserAgent: ${navigator.userAgent}
|
||||
%0D%0AinnerWidth: ${window.innerWidth}
|
||||
%0D%0AinnerHeight: ${window.innerHeight}`;
|
||||
%0D%0AinnerWidth: ${this.window.innerWidth}
|
||||
%0D%0AinnerHeight: ${this.window.innerHeight}`;
|
||||
}
|
||||
|
||||
closeBugReport(close) {
|
||||
@ -61,7 +56,7 @@ URL: ${window.location}%0D%0A%0D%0AWhat did you do?%0D%0A${encodeURIComponent(th
|
||||
}
|
||||
|
||||
toTheTop() {
|
||||
window.scroll(0, 0);
|
||||
this.window.scroll(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,9 @@ import { SettingsComponent } from './settings/settings.component';
|
||||
import { UsersComponent } from './users/users.component';
|
||||
import { ChangelogComponent } from './changelog/changelog.component';
|
||||
import { DocumentationDatabaseComponent } from './documentation-database/documentation-database.component';
|
||||
import { PredictionComponent } from './prediction/prediction.component';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { environment } from '../environments/environment';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -46,7 +49,8 @@ import { DocumentationDatabaseComponent } from './documentation-database/documen
|
||||
SettingsComponent,
|
||||
UsersComponent,
|
||||
ChangelogComponent,
|
||||
DocumentationDatabaseComponent
|
||||
DocumentationDatabaseComponent,
|
||||
PredictionComponent
|
||||
],
|
||||
imports: [
|
||||
LocalStorageModule.forRoot({
|
||||
@ -63,7 +67,8 @@ import { DocumentationDatabaseComponent } from './documentation-database/documen
|
||||
ReactiveFormsModule,
|
||||
FormFieldsModule,
|
||||
CommonModule,
|
||||
ChartsModule
|
||||
ChartsModule,
|
||||
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
|
||||
],
|
||||
providers: [
|
||||
ModalService,
|
||||
|
@ -1,21 +1,44 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ChangelogComponent } from './changelog.component';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {ModalService, RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ValidationService} from '../services/validation.service';
|
||||
import {DataService} from '../services/data.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
let modalServiceSpy: jasmine.SpyObj<ModalService>;
|
||||
|
||||
describe('ChangelogComponent', () => {
|
||||
let component: ChangelogComponent;
|
||||
let fixture: ComponentFixture<ChangelogComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['get']);
|
||||
const modalSpy = jasmine.createSpyObj('ModalService', ['open']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ChangelogComponent ]
|
||||
declarations: [ ChangelogComponent ],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
{provide: ApiService, useValue: apiSpy},
|
||||
{provide: ModalService, useValue: modalSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
modalServiceSpy = TestBed.inject(ModalService) as jasmine.SpyObj<ModalService>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ChangelogComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
<td>Automatically generated unique id</td>
|
||||
<td>'5f2e63c98d1c020f8cda6e06'</td>
|
||||
</tr>
|
||||
<!-- TODO: new names-->
|
||||
<tr>
|
||||
<td>type</td>
|
||||
<td>
|
||||
|
@ -2,6 +2,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DocumentationDatabaseComponent } from './documentation-database.component';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('DocumentationDatabaseComponent', () => {
|
||||
let component: DocumentationDatabaseComponent;
|
||||
let fixture: ComponentFixture<DocumentationDatabaseComponent>;
|
||||
@ -16,6 +18,7 @@ describe('DocumentationDatabaseComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DocumentationDatabaseComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DocumentationComponent } from './documentation.component';
|
||||
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {RbCustomInputsModule} from '../rb-custom-inputs/rb-custom-inputs.module';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('DocumentationComponent', () => {
|
||||
let component: DocumentationComponent;
|
||||
@ -8,7 +13,10 @@ describe('DocumentationComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DocumentationComponent ]
|
||||
declarations: [ DocumentationComponent ],
|
||||
imports: [
|
||||
RbCustomInputsModule
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
@ -16,6 +24,7 @@ describe('DocumentationComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DocumentationComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -4,6 +4,8 @@ import { ErrorComponent } from './error.component';
|
||||
import {ModalService, RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('ErrorComponent', () => {
|
||||
let component: ErrorComponent;
|
||||
let fixture: ComponentFixture<ErrorComponent>;
|
||||
@ -25,6 +27,7 @@ describe('ErrorComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ErrorComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
css = (selector) => fixture.debugElement.query(By.css(selector)).nativeElement;
|
||||
});
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { ExistsPipe } from './exists.pipe';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('ExistsPipe', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new ExistsPipe();
|
||||
|
@ -3,6 +3,8 @@ import { HomeComponent } from './home.component';
|
||||
import {Component} from '@angular/core';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
// TODO
|
||||
|
||||
@Component({selector: 'app-login', template: ''})
|
||||
class LoginStubComponent {}
|
||||
|
||||
@ -23,6 +25,7 @@ describe('HomeComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HomeComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -1,21 +1,40 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ImgMagnifierComponent } from './img-magnifier.component';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ValidationService} from '../services/validation.service';
|
||||
import {DataService} from '../services/data.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let windowServiceSpy: jasmine.SpyObj<Window>;
|
||||
|
||||
describe('ImgMagnifierComponent', () => {
|
||||
let component: ImgMagnifierComponent;
|
||||
let fixture: ComponentFixture<ImgMagnifierComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const windowSpy = jasmine.createSpyObj('Window', []);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ImgMagnifierComponent ]
|
||||
declarations: [ ImgMagnifierComponent ],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
{provide: Window, useValue: windowSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
windowServiceSpy = TestBed.inject(Window) as jasmine.SpyObj<Window>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ImgMagnifierComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -7,6 +7,8 @@ import {By} from '@angular/platform-browser';
|
||||
import {ValidateDirective} from '../validate.directive';
|
||||
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
|
||||
// TODO
|
||||
|
||||
let validationServiceSpy: jasmine.SpyObj<ValidationService>;
|
||||
let loginServiceSpy: jasmine.SpyObj<LoginService>;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { UserModel } from './user.model';
|
||||
|
||||
describe('User.Model', () => {
|
||||
describe('UserModel', () => {
|
||||
it('should create an instance', () => {
|
||||
expect(new UserModel()).toBeTruthy();
|
||||
});
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { ObjectPipe } from './object.pipe';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('ObjectPipe', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new ObjectPipe();
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { ParametersPipe } from './parameters.pipe';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('ParametersPipe', () => {
|
||||
it('create an instance', () => {
|
||||
const pipe = new ParametersPipe();
|
||||
|
20
src/app/prediction/prediction.component.html
Normal file
@ -0,0 +1,20 @@
|
||||
<h2>Prediction</h2>
|
||||
|
||||
<h4 *ngIf="result !== '' || loading" [@inOut]>
|
||||
Result: {{result}}<rb-loading-spinner *ngIf="loading"></rb-loading-spinner>
|
||||
</h4>
|
||||
|
||||
<rb-form-file name="spectrum-upload" label="spectrum file" maxSize="10000000" class="space-below"
|
||||
(ngModelChange)="fileToArray($event)" placeholder="Select file or drag and drop" dragDrop ngModel>
|
||||
</rb-form-file>
|
||||
|
||||
<div class="dpt-chart">
|
||||
<canvas baseChart
|
||||
class="dpt-chart"
|
||||
[datasets]="chart"
|
||||
[labels]="[]"
|
||||
[options]="chartOptions"
|
||||
[legend]="false"
|
||||
chartType="scatter">
|
||||
</canvas>
|
||||
</div>
|
4
src/app/prediction/prediction.component.scss
Normal file
@ -0,0 +1,4 @@
|
||||
.dpt-chart {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
44
src/app/prediction/prediction.component.spec.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PredictionComponent } from './prediction.component';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ValidationService} from '../services/validation.service';
|
||||
import {DataService} from '../services/data.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
|
||||
describe('PredictionComponent', () => {
|
||||
let component: PredictionComponent;
|
||||
let fixture: ComponentFixture<PredictionComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['post']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ PredictionComponent ],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
{provide: ApiService, useValue: apiSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PredictionComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
74
src/app/prediction/prediction.component.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {ChartOptions} from 'chart.js';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {animate, style, transition, trigger} from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
selector: 'app-prediction',
|
||||
templateUrl: './prediction.component.html',
|
||||
styleUrls: ['./prediction.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 PredictionComponent implements OnInit {
|
||||
|
||||
readonly predictionUrl = 'https://definma-model-test.apps.de1.bosch-iot-cloud.com/predict';
|
||||
result = '';
|
||||
loading = false;
|
||||
spectrum: string[][] = [[]];
|
||||
chart = [{
|
||||
data: [],
|
||||
label: 'Spectrum',
|
||||
showLine: true,
|
||||
fill: false,
|
||||
pointRadius: 0,
|
||||
borderColor: '#00a8b0',
|
||||
borderWidth: 2
|
||||
}];
|
||||
readonly chartOptions: ChartOptions = {
|
||||
scales: {
|
||||
xAxes: [{ticks: {min: 400, max: 4000, stepSize: 400, reverse: true}}],
|
||||
yAxes: [{ticks: {min: 0, max: 1}}]
|
||||
},
|
||||
responsive: true,
|
||||
tooltips: {enabled: false},
|
||||
hover: {mode: null},
|
||||
maintainAspectRatio: true,
|
||||
plugins: {datalabels: {display: false}}
|
||||
};
|
||||
|
||||
constructor(
|
||||
private api: ApiService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
fileToArray(files) {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = () => {
|
||||
this.spectrum = fileReader.result.toString().split('\r\n').map(e => e.split(','));
|
||||
this.loading = true;
|
||||
this.api.post<{result: string}>(this.predictionUrl, this.spectrum, data => {
|
||||
this.result = data.result;
|
||||
this.loading = false;
|
||||
});
|
||||
this.chart[0].data = this.spectrum.map(e => ({x: parseFloat(e[0]), y: parseFloat(e[1])}));
|
||||
console.log(this.chart);
|
||||
};
|
||||
fileReader.readAsText(files[0]);
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,8 @@ import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ArrayInputHelperService } from './array-input-helper.service';
|
||||
|
||||
// TOdo
|
||||
|
||||
describe('ArrayInputHelperService', () => {
|
||||
let service: ArrayInputHelperService;
|
||||
|
||||
|
@ -16,6 +16,7 @@ describe('RbArrayInputComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RbArrayInputComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -2,6 +2,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RbIconButtonComponent } from './rb-icon-button.component';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('RbIconButtonComponent', () => {
|
||||
let component: RbIconButtonComponent;
|
||||
let fixture: ComponentFixture<RbIconButtonComponent>;
|
||||
@ -16,6 +18,7 @@ describe('RbIconButtonComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RbIconButtonComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -34,5 +34,6 @@ table.ellipsis {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
max-width: 200px;
|
||||
//min-width: 100px;
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RbTableComponent } from './rb-table.component';
|
||||
|
||||
// TODO
|
||||
|
||||
describe('RbTableComponent', () => {
|
||||
let component: RbTableComponent;
|
||||
let fixture: ComponentFixture<RbTableComponent>;
|
||||
@ -16,6 +18,7 @@ describe('RbTableComponent', () => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RbTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
<script src="../models/template.model.ts"></script><h2>{{new ? 'Add new sample' : 'Edit sample ' + sample.number}}</h2>
|
||||
<h2>{{new ? 'Add new sample' : 'Edit sample ' + sample.number}}</h2>
|
||||
|
||||
<rb-loading-spinner *ngIf="loading"></rb-loading-spinner>
|
||||
|
||||
|
@ -1,27 +1,70 @@
|
||||
// import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
//
|
||||
// import { SampleComponent } from './sample.component';
|
||||
//
|
||||
// // TODO: tests
|
||||
//
|
||||
// describe('SampleComponent', () => {
|
||||
// let component: SampleComponent;
|
||||
// let fixture: ComponentFixture<SampleComponent>;
|
||||
//
|
||||
// beforeEach(async(() => {
|
||||
// TestBed.configureTestingModule({
|
||||
// declarations: [ SampleComponent ]
|
||||
// })
|
||||
// .compileComponents();
|
||||
// }));
|
||||
//
|
||||
// beforeEach(() => {
|
||||
// fixture = TestBed.createComponent(SampleComponent);
|
||||
// component = fixture.componentInstance;
|
||||
// fixture.detectChanges();
|
||||
// });
|
||||
//
|
||||
// it('should create', () => {
|
||||
// expect(component).toBeTruthy();
|
||||
// });
|
||||
// });
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SampleComponent } from './sample.component';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {ValidationService} from '../services/validation.service';
|
||||
import {DataService} from '../services/data.service';
|
||||
import {ModalService, RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {AutocompleteService} from '../services/autocomplete.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let routerServiceSpy: jasmine.SpyObj<Router>;
|
||||
let activatedRouteServiceSpy: jasmine.SpyObj<ActivatedRoute>;
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
let validationServiceSpy: jasmine.SpyObj<ValidationService>;
|
||||
let autocompleteServiceSpy: jasmine.SpyObj<AutocompleteService>;
|
||||
let modalServiceSpy: jasmine.SpyObj<ModalService>;
|
||||
let dataServiceSpy: jasmine.SpyObj<DataService>;
|
||||
|
||||
describe('SampleComponent', () => {
|
||||
let component: SampleComponent;
|
||||
let fixture: ComponentFixture<SampleComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
|
||||
const activatedRouteSpy = jasmine.createSpyObj('ActivatedRoute', ['snapshot']);
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['post', 'put']);
|
||||
const validationSpy = jasmine.createSpyObj('ValidationService', ['generate']);
|
||||
const autocompleteSpy = jasmine.createSpyObj('AutocompleteService', []);
|
||||
const modalSpy = jasmine.createSpyObj('ModalService', ['open']);
|
||||
const dataSpy = jasmine.createSpyObj('DataService', ['load', 'idReload']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SampleComponent ],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
{provide: Router, useValue: routerSpy},
|
||||
{provide: ActivatedRoute, useValue: activatedRouteSpy},
|
||||
{provide: ApiService, useValue: apiSpy},
|
||||
{provide: ValidationService, useValue: validationSpy},
|
||||
{provide: AutocompleteService, useValue: autocompleteSpy},
|
||||
{provide: ModalService, useValue: modalSpy},
|
||||
{provide: DataService, useValue: dataSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
routerServiceSpy = TestBed.inject(Router) as jasmine.SpyObj<Router>;
|
||||
activatedRouteServiceSpy = TestBed.inject(ActivatedRoute) as jasmine.SpyObj<ActivatedRoute>;
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
validationServiceSpy = TestBed.inject(ValidationService) as jasmine.SpyObj<ValidationService>;
|
||||
autocompleteServiceSpy = TestBed.inject(AutocompleteService) as jasmine.SpyObj<AutocompleteService>;
|
||||
modalServiceSpy = TestBed.inject(ModalService) as jasmine.SpyObj<ModalService>;
|
||||
dataServiceSpy = TestBed.inject(DataService) as jasmine.SpyObj<DataService>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SampleComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -22,10 +22,6 @@ import {Observable} from 'rxjs';
|
||||
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {DataService} from '../services/data.service';
|
||||
|
||||
// TODO: clean up this mess !!!
|
||||
|
||||
// TODO: only show condition (if not set) and measurements in edit sample dialog at first
|
||||
// TODO: multiple samples for base data, extend multiple measurements, conditions
|
||||
|
||||
@Component({
|
||||
selector: 'app-sample',
|
||||
|
@ -73,7 +73,7 @@
|
||||
(ngModelChange)="updateFilterFields(filter.field)">
|
||||
<ng-container *rbArrayInputItem="let item"
|
||||
[ngSwitch]="(filter.autocomplete.length ? 'autocomplete' : '') +
|
||||
(filter.field == 'added' ? 'date' : '')">
|
||||
(filter.field == 'added' ? 'date' : (filter.field == 'type' ? 'type' : ''))">
|
||||
<rb-form-date-input *ngSwitchCase="'date'" [rbArrayInputListener]="'filter-' + filter.field"
|
||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
||||
[label]="filter.label" [(ngModel)]="item.value"></rb-form-date-input>
|
||||
@ -86,6 +86,12 @@
|
||||
[rbDebounceTime]="0" (keydown)="preventDefault($event, 'Enter')"
|
||||
[rbFormInputAutocomplete]="autocomplete.bind(this, filter.autocomplete)"
|
||||
ngModel></rb-form-input>
|
||||
<rb-form-select *ngSwitchCase="'type'" [rbArrayInputListener]="'filter-' + filter.field"
|
||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
||||
[label]="filter.label" [(ngModel)]="item.value">
|
||||
<option value="as-delivered/raw">as-delivered/raw</option>
|
||||
<option value="processed">processed</option>
|
||||
</rb-form-select>
|
||||
</ng-container>
|
||||
</rb-array-input>
|
||||
</div>
|
||||
@ -132,17 +138,17 @@
|
||||
<th *ngIf="validation">
|
||||
<rb-form-checkbox name="validate-all" (change)="selectAll($event)">all</rb-form-checkbox>
|
||||
</th>
|
||||
<th *ngFor="let key of activeKeys">
|
||||
<th *ngFor="let key of activeKeys" [title]="key.label">
|
||||
<div class="sort-header">
|
||||
<span>{{key.label}}</span>
|
||||
<ng-container *ngIf="key.sortable">
|
||||
<div *ngIf="key.sortable">
|
||||
<span class="rb-ic rb-ic-up sort-arr-up" (click)="setSort(key.id + '-' + 'desc')">
|
||||
<span *ngIf="filters.sort === key.id + '-' + 'desc'"></span>
|
||||
</span>
|
||||
<span class="rb-ic rb-ic-down sort-arr-down" (click)="setSort(key.id + '-' + 'asc')">
|
||||
<span *ngIf="filters.sort === key.id + '-' + 'asc'"></span>
|
||||
</span>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</th>
|
||||
<th *ngIf="login.isLevel.write"></th>
|
||||
@ -165,6 +171,9 @@
|
||||
<td *ngIf="isActiveKey['type']">{{sample.type}}</td>
|
||||
<td *ngIf="isActiveKey['color']">{{sample.color}}</td>
|
||||
<td *ngIf="isActiveKey['batch']">{{sample.batch}}</td>
|
||||
<td *ngFor="let key of activeTemplateKeys.condition">
|
||||
{{sample.condition ? sample.condition[key[1]] : '' | exists}}
|
||||
</td>
|
||||
<td *ngIf="isActiveKey['notes']">{{sample.notes | object: ['_id', 'sample_references']}}</td>
|
||||
<td *ngFor="let key of activeTemplateKeys.measurements">{{sample[key[1]] | exists: key[2]}}</td>
|
||||
<td *ngIf="isActiveKey['status']">{{sample.status}}</td>
|
||||
@ -188,7 +197,7 @@
|
||||
<button class="rb-btn rb-link" type="button" (click)="loadPage(-1)" [disabled]="page === 1">
|
||||
<span class="rb-ic rb-ic-back-left"></span>
|
||||
</button>
|
||||
<rb-form-input label="page" (change)="loadPage({toPage: $event.target.value - page})" [ngModel]="page">
|
||||
<rb-form-input label="page" (ngModelChange)="loadPage($event - page)" [ngModel]="page">
|
||||
</rb-form-input>
|
||||
<span>
|
||||
of {{pages}} ({{totalSamples}} samples)
|
||||
|
@ -54,7 +54,7 @@ rb-table {
|
||||
.paging {
|
||||
height: 50px;
|
||||
rb-form-input {
|
||||
max-width: 50px;
|
||||
max-width: 65px;
|
||||
}
|
||||
|
||||
> * {
|
||||
@ -72,24 +72,35 @@ rb-table {
|
||||
}
|
||||
|
||||
.sort-header {
|
||||
display: inline-grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-column-gap: 5px;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
:first-child {
|
||||
grid-row: span 2;
|
||||
& > span:first-child {
|
||||
max-width: 180px;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
:nth-child(2) {
|
||||
div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
background: #FFF;
|
||||
|
||||
:nth-child(1) {
|
||||
margin-bottom: -3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:nth-child(3) {
|
||||
:nth-child(2) {
|
||||
margin-top: -3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sort-active-asc {
|
||||
|
@ -1,27 +1,72 @@
|
||||
// import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
//
|
||||
// import { SamplesComponent } from './samples.component';
|
||||
//
|
||||
// // TODO: tests
|
||||
//
|
||||
// describe('SamplesComponent', () => {
|
||||
// let component: SamplesComponent;
|
||||
// let fixture: ComponentFixture<SamplesComponent>;
|
||||
//
|
||||
// beforeEach(async(() => {
|
||||
// TestBed.configureTestingModule({
|
||||
// declarations: [ SamplesComponent ]
|
||||
// })
|
||||
// .compileComponents();
|
||||
// }));
|
||||
//
|
||||
// beforeEach(() => {
|
||||
// fixture = TestBed.createComponent(SamplesComponent);
|
||||
// component = fixture.componentInstance;
|
||||
// fixture.detectChanges();
|
||||
// });
|
||||
//
|
||||
// it('should create', () => {
|
||||
// expect(component).toBeTruthy();
|
||||
// });
|
||||
// });
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SamplesComponent } from './samples.component';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {AutocompleteService} from '../services/autocomplete.service';
|
||||
import {DataService} from '../services/data.service';
|
||||
import {LoginService} from '../services/login.service';
|
||||
import {LocalStorageService} from 'angular-2-local-storage';
|
||||
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {ValidationService} from '../services/validation.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
let autocompleteServiceSpy: jasmine.SpyObj<AutocompleteService>;
|
||||
let modalServiceSpy: jasmine.SpyObj<ModalService>;
|
||||
let dataServiceSpy: jasmine.SpyObj<DataService>;
|
||||
let loginServiceSpy: jasmine.SpyObj<LoginService>;
|
||||
let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
|
||||
let windowServiceSpy: jasmine.SpyObj<Window>;
|
||||
|
||||
|
||||
|
||||
describe('SamplesComponent', () => {
|
||||
let component: SamplesComponent;
|
||||
let fixture: ComponentFixture<SamplesComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['post', 'put']);
|
||||
const autocompleteSpy = jasmine.createSpyObj('AutocompleteService', []);
|
||||
const loginSpy = jasmine.createSpyObj('LoginService', ['login', 'canActivate']);
|
||||
const modalSpy = jasmine.createSpyObj('ModalService', ['open']);
|
||||
const dataSpy = jasmine.createSpyObj('DataService', ['load', 'idReload']);
|
||||
const localStorageSpy = jasmine.createSpyObj('LocalStorageService', ['set', 'remove']);
|
||||
const windowSpy = jasmine.createSpyObj('Window', []);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SamplesComponent ],
|
||||
imports: [
|
||||
],
|
||||
providers: [
|
||||
{provide: ApiService, useValue: apiSpy},
|
||||
{provide: AutocompleteService, useValue: autocompleteSpy},
|
||||
{provide: ModalService, useValue: modalSpy},
|
||||
{provide: DataService, useValue: dataSpy},
|
||||
{provide: LoginService, useValue: loginSpy},
|
||||
{provide: LocalStorageService, useValue: localStorageSpy},
|
||||
{provide: Window, useValue: windowSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
autocompleteServiceSpy = TestBed.inject(AutocompleteService) as jasmine.SpyObj<AutocompleteService>;
|
||||
modalServiceSpy = TestBed.inject(ModalService) as jasmine.SpyObj<ModalService>;
|
||||
dataServiceSpy = TestBed.inject(DataService) as jasmine.SpyObj<DataService>;
|
||||
loginServiceSpy = TestBed.inject(LoginService) as jasmine.SpyObj<LoginService>;
|
||||
localStorageServiceSpy = TestBed.inject(LocalStorageService) as jasmine.SpyObj<LocalStorageService>;
|
||||
windowServiceSpy = TestBed.inject(Window) as jasmine.SpyObj<Window>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SamplesComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
@ -8,6 +8,9 @@ import {SampleModel} from '../models/sample.model';
|
||||
import {LoginService} from '../services/login.service';
|
||||
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {DataService} from '../services/data.service';
|
||||
import {LocalStorageService} from 'angular-2-local-storage';
|
||||
|
||||
// TODO: turn off sort field
|
||||
|
||||
|
||||
interface LoadSamplesOptions {
|
||||
@ -28,8 +31,6 @@ interface KeyInterface {
|
||||
styleUrls: ['./samples.component.scss']
|
||||
})
|
||||
|
||||
// TODO: save last settings
|
||||
|
||||
export class SamplesComponent implements OnInit {
|
||||
|
||||
@ViewChild('pageSizeSelection') pageSizeSelection: ElementRef<HTMLElement>;
|
||||
@ -79,7 +80,7 @@ export class SamplesComponent implements OnInit {
|
||||
];
|
||||
isActiveKey: {[key: string]: boolean} = {};
|
||||
activeKeys: KeyInterface[] = [];
|
||||
activeTemplateKeys = {material: [], measurements: []};
|
||||
activeTemplateKeys = {material: [], condition: [], measurements: []};
|
||||
sampleDetailsSample: any = null;
|
||||
validation = false; // true to activate validation mode
|
||||
|
||||
@ -89,29 +90,41 @@ export class SamplesComponent implements OnInit {
|
||||
public autocomplete: AutocompleteService,
|
||||
public login: LoginService,
|
||||
private modalService: ModalService,
|
||||
public d: DataService
|
||||
public d: DataService,
|
||||
private storage: LocalStorageService,
|
||||
private window: Window
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
let loading = 8;
|
||||
const onLoad = () => {
|
||||
if ((--loading) <= 0) {
|
||||
this.loadSamples();
|
||||
}
|
||||
};
|
||||
|
||||
this.calcFieldSelectKeys();
|
||||
this.d.load('materials', () => {
|
||||
this.filters.filters.find(e => e.field === 'material.name').autocomplete = this.d.arr.materials.map(e => e.name);
|
||||
this.loadSamples();
|
||||
onLoad();
|
||||
});
|
||||
this.d.load('materialSuppliers', () => {
|
||||
this.filters.filters.find(e => e.field === 'material.supplier').autocomplete = this.d.arr.materialSuppliers;
|
||||
onLoad();
|
||||
});
|
||||
this.d.load('materialGroups', () => {
|
||||
this.filters.filters.find(e => e.field === 'material.group').autocomplete = this.d.arr.materialGroups;
|
||||
onLoad();
|
||||
});
|
||||
this.d.load('userKey');
|
||||
this.d.load('conditionTemplates');
|
||||
this.loadTemplateKeys('material', 'type');
|
||||
this.loadTemplateKeys('measurement', 'status');
|
||||
this.d.load('userKey', onLoad);
|
||||
this.d.load('conditionTemplates', onLoad);
|
||||
this.loadTemplateKeys('material', 'type', onLoad);
|
||||
this.loadTemplateKeys('condition', 'notes', onLoad);
|
||||
this.loadTemplateKeys('measurement', 'status', onLoad);
|
||||
}
|
||||
|
||||
loadTemplateKeys(collection, insertBefore) {
|
||||
loadTemplateKeys(collection, insertBefore, f) {
|
||||
this.d.load(collection + 'Templates', () => {
|
||||
const templateKeys = [];
|
||||
this.d.arr[collection + 'Templates'].forEach(item => {
|
||||
@ -119,15 +132,16 @@ export class SamplesComponent implements OnInit {
|
||||
const parameterName = encodeURIComponent(parameter.name);
|
||||
// exclude spectrum and duplicates
|
||||
if (parameter.name !== 'dpt' && !templateKeys.find(e => new RegExp('.' + parameterName + '$').test(e.id))) {
|
||||
const collectionNames = {material: 'material.properties', condition: 'condition', measurement: 'measurements.' + item.name};
|
||||
templateKeys.push({
|
||||
id: `${collection === 'material' ? 'material.properties' : collection + 's.' + item.name}.${parameterName}`,
|
||||
label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`,
|
||||
id: `${collectionNames[collection]}.${parameterName}`,
|
||||
label: `${this.ucFirst(item.name)} ${parameter.name}`,
|
||||
active: false,
|
||||
sortable: true
|
||||
});
|
||||
this.filters.filters.push({
|
||||
field: `${collection === 'material' ? 'material.properties' : collection + 's.' + item.name}.${parameterName}`,
|
||||
label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`,
|
||||
field: `${collectionNames[collection]}.${parameterName}`,
|
||||
label: `${this.ucFirst(item.name)} ${parameter.name}`,
|
||||
active: false,
|
||||
autocomplete: [],
|
||||
mode: 'eq',
|
||||
@ -138,12 +152,13 @@ export class SamplesComponent implements OnInit {
|
||||
});
|
||||
this.keys.splice(this.keys.findIndex(e => e.id === insertBefore), 0, ...templateKeys);
|
||||
this.keys = [...this.keys]; // complete overwrite array to invoke update in rb-multiselect
|
||||
this.updateActiveKeys();
|
||||
this.calcFieldSelectKeys();
|
||||
this.loadPreferences();
|
||||
f();
|
||||
});
|
||||
}
|
||||
|
||||
loadSamples(options: LoadSamplesOptions = {}, event = null) { // set toPage to null to reload first page, queues calls
|
||||
console.log(this.isActiveKey);
|
||||
if (event) { // adjust active keys
|
||||
this.keys.forEach(key => {
|
||||
if (event.hasOwnProperty(key.id)) {
|
||||
@ -156,10 +171,16 @@ export class SamplesComponent implements OnInit {
|
||||
if (this.loadSamplesQueue.length <= 1) { // nothing queued up
|
||||
this.sampleLoader(this.loadSamplesQueue[0]);
|
||||
}
|
||||
this.storePreferences();
|
||||
}
|
||||
|
||||
private sampleLoader(options: LoadSamplesOptions) { // actual loading of the sample, do not call directly
|
||||
this.api.get(this.sampleUrl({paging: true, pagingOptions: options}), (sData, ignore, headers) => {
|
||||
this.api.get(this.sampleUrl({paging: true, pagingOptions: options}), (sData, err, headers) => {
|
||||
if (err) {
|
||||
this.storage.remove('samplesPreferences');
|
||||
this.api.requestError(err);
|
||||
}
|
||||
else {
|
||||
if (!options.toPage && headers['x-total-items']) {
|
||||
this.totalSamples = headers['x-total-items'];
|
||||
}
|
||||
@ -169,6 +190,7 @@ export class SamplesComponent implements OnInit {
|
||||
if (this.loadSamplesQueue.length > 0) { // execute next queue item
|
||||
this.sampleLoader(this.loadSamplesQueue[0]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -206,7 +228,7 @@ export class SamplesComponent implements OnInit {
|
||||
}
|
||||
this.keys.forEach(key => {
|
||||
// do not load material properties for table
|
||||
if (key.active && (options.export || (!options.export && key.id.indexOf('material') < 0))) {
|
||||
if (key.active && (options.export || (!options.export && key.id.indexOf('material.') < 0))) {
|
||||
query.push('fields[]=' + key.id);
|
||||
}
|
||||
});
|
||||
@ -243,12 +265,13 @@ export class SamplesComponent implements OnInit {
|
||||
query.push('fields[]=condition');
|
||||
}
|
||||
}
|
||||
return (options.host && isDevMode() ? window.location.host : '') +
|
||||
return (options.host && isDevMode() ? this.window.location.host : '') +
|
||||
(options.export ? this.api.hostName : '') +
|
||||
'/samples?' + query.join('&');
|
||||
}
|
||||
|
||||
loadPage(delta) {
|
||||
console.log(delta);
|
||||
if (!/[0-9]+/.test(delta) || (this.page <= 1 && delta < 0)) { // invalid delta
|
||||
return;
|
||||
}
|
||||
@ -256,6 +279,38 @@ export class SamplesComponent implements OnInit {
|
||||
this.loadSamples({toPage: delta});
|
||||
}
|
||||
|
||||
storePreferences() {
|
||||
const store = {
|
||||
filters: {
|
||||
...pick(this.filters, ['status', 'pageSize', 'toPage', 'sort']),
|
||||
filters: this.filters.filters.map(e => pick(e, ['field', 'active', 'mode', 'values']))
|
||||
},
|
||||
keys: this.keys.map(e => pick(e, ['id', 'active']))
|
||||
};
|
||||
this.storage.set('samplesPreferences', store);
|
||||
}
|
||||
|
||||
loadPreferences() {
|
||||
const store: any = this.storage.get('samplesPreferences');
|
||||
if (store) {
|
||||
this.filters = {...this.filters, ...pick(store.filters, ['status', 'pageSize', 'toPage', 'sort'])};
|
||||
store.filters.filters.forEach(filter => {
|
||||
const filterIndex = this.filters.filters.findIndex(e => e.field === filter.field);
|
||||
if (filterIndex >= 0) {
|
||||
this.filters.filters[filterIndex] = {...this.filters.filters[filterIndex], ...filter};
|
||||
}
|
||||
});
|
||||
store.keys.forEach(key => {
|
||||
const keyIndex = this.keys.findIndex(e => e.id === key.id);
|
||||
if (keyIndex >= 0) {
|
||||
this.keys[keyIndex].active = key.active;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.calcFieldSelectKeys();
|
||||
this.updateActiveKeys();
|
||||
}
|
||||
|
||||
updateFilterFields(field) {
|
||||
const filter = this.filters.filters.find(e => e.field === field);
|
||||
filter.active = true;
|
||||
@ -271,10 +326,18 @@ export class SamplesComponent implements OnInit {
|
||||
|
||||
updateActiveKeys() { // array with all activeKeys
|
||||
this.activeKeys = this.keys.filter(e => e.active);
|
||||
this.filters.filters.forEach(filter => {
|
||||
if (!this.isActiveKey[filter.field]) {
|
||||
filter.active = false;
|
||||
}
|
||||
});
|
||||
this.activeTemplateKeys.material = this.keys
|
||||
.filter(e => e.id.indexOf('material.properties.') >= 0 && e.active)
|
||||
.map(e => e.id.split('.')
|
||||
.map(el => decodeURIComponent(el)));
|
||||
this.activeTemplateKeys.condition = this.keys.filter(e => e.id.indexOf('condition.') >= 0 && e.active)
|
||||
.map(e => e.id.split('.')
|
||||
.map(el => decodeURIComponent(el)));
|
||||
this.activeTemplateKeys.measurements = this.keys.filter(e => e.id.indexOf('measurements.') >= 0 && e.active)
|
||||
.map(e => e.id.split('.')
|
||||
.map(el => decodeURIComponent(el)));
|
||||
@ -390,4 +453,6 @@ export class SamplesComponent implements OnInit {
|
||||
ucFirst(string) {
|
||||
return string[0].toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ let httpClientSpy: jasmine.SpyObj<HttpClient>;
|
||||
let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
|
||||
let modalServiceSpy: jasmine.SpyObj<ModalService>;
|
||||
|
||||
// TODO
|
||||
// TODO: test options
|
||||
|
||||
describe('ApiService', () => {
|
||||
|
@ -25,29 +25,36 @@ export class ApiService {
|
||||
}
|
||||
|
||||
get<T>(url, f: (data?: T, err?, headers?) => void = () => {}) {
|
||||
this.requestErrorHandler<T>(this.http.get(this.host + url, this.options()), f);
|
||||
this.requestErrorHandler<T>(this.http.get(this.url(url), this.options()), f);
|
||||
}
|
||||
|
||||
post<T>(url, data = null, f: (data?: T, err?, headers?) => void = () => {}) {
|
||||
this.requestErrorHandler<T>(this.http.post(this.host + url, data, this.options()), f);
|
||||
this.requestErrorHandler<T>(this.http.post(this.url(url), data, this.options()), f);
|
||||
}
|
||||
|
||||
put<T>(url, data = null, f: (data?: T, err?, headers?) => void = () => {}) {
|
||||
this.requestErrorHandler<T>(this.http.put(this.host + url, data, this.options()), f);
|
||||
this.requestErrorHandler<T>(this.http.put(this.url(url), data, this.options()), f);
|
||||
}
|
||||
|
||||
delete<T>(url, f: (data?: T, err?, headers?) => void = () => {}) {
|
||||
this.requestErrorHandler<T>(this.http.delete(this.host + url, this.options()), f);
|
||||
this.requestErrorHandler<T>(this.http.delete(this.url(url), this.options()), f);
|
||||
}
|
||||
|
||||
private requestErrorHandler<T>(observable: Observable<any>, f: (data?: T, err?, headers?) => void) {
|
||||
observable.subscribe(data => {
|
||||
f(data.body, undefined, data.headers.keys().reduce((s, e) => {s[e.toLowerCase()] = data.headers.get(e); return s; }, {}));
|
||||
}, err => {
|
||||
if (f.length === 2) {
|
||||
f(undefined, err);
|
||||
console.log(f.length);
|
||||
if (f.length > 1) {
|
||||
f(undefined, err, undefined);
|
||||
}
|
||||
else {
|
||||
this.requestError(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
requestError(err) {
|
||||
const modalRef = this.modalService.openComponent(ErrorComponent);
|
||||
modalRef.instance.message = 'Network request failed!';
|
||||
const details = [err.error.status];
|
||||
@ -59,7 +66,14 @@ export class ApiService {
|
||||
this.window.location.reload();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
private url(url) {
|
||||
if (/http[s]?:\/\//.test(url)) {
|
||||
return url;
|
||||
}
|
||||
else {
|
||||
return this.host + url;
|
||||
}
|
||||
}
|
||||
|
||||
private options(): {headers: HttpHeaders, observe: 'body'} {
|
||||
|
@ -2,6 +2,8 @@ import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AutocompleteService } from './autocomplete.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let autocompleteService: AutocompleteService;
|
||||
|
||||
describe('AutocompleteService', () => {
|
||||
|
@ -1,13 +1,30 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DataService } from './data.service';
|
||||
import {ApiService} from './api.service';
|
||||
import {HttpClient} from '@angular/common/http';
|
||||
import {LocalStorageService} from 'angular-2-local-storage';
|
||||
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
|
||||
|
||||
// TODO
|
||||
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
|
||||
|
||||
describe('DataService', () => {
|
||||
let service: DataService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['post', 'put']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{provide: ApiService, useValue: apiSpy}
|
||||
]
|
||||
});
|
||||
service = TestBed.inject(DataService);
|
||||
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
|
@ -4,6 +4,8 @@ import { LoginService } from './login.service';
|
||||
import {LocalStorageService} from 'angular-2-local-storage';
|
||||
import {ApiService} from './api.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let loginService: LoginService;
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
let localStorageServiceSpy: jasmine.SpyObj<LocalStorageService>;
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { ValidationService } from './validation.service';
|
||||
|
||||
// TODO
|
||||
|
||||
let validationService: ValidationService;
|
||||
|
||||
describe('ValidationService', () => {
|
||||
|
@ -1,21 +1,45 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { SettingsComponent } from './settings.component';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {LoginService} from '../services/login.service';
|
||||
import {Router} from '@angular/router';
|
||||
|
||||
// TODO
|
||||
|
||||
let routerServiceSpy: jasmine.SpyObj<Router>;
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
let loginServiceSpy: jasmine.SpyObj<LoginService>;
|
||||
|
||||
|
||||
describe('SettingsComponent', () => {
|
||||
let component: SettingsComponent;
|
||||
let fixture: ComponentFixture<SettingsComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['post', 'put']);
|
||||
const loginSpy = jasmine.createSpyObj('LoginService', ['login', 'canActivate']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ SettingsComponent ]
|
||||
declarations: [ SettingsComponent ],
|
||||
providers: [
|
||||
{provide: Router, useValue: routerSpy},
|
||||
{provide: ApiService, useValue: apiSpy},
|
||||
{provide: LoginService, useValue: loginSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
routerServiceSpy = TestBed.inject(Router) as jasmine.SpyObj<Router>;
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
loginServiceSpy = TestBed.inject(LoginService) as jasmine.SpyObj<LoginService>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SettingsComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -1,21 +1,51 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TemplatesComponent } from './templates.component';
|
||||
import {LoginService} from '../services/login.service';
|
||||
import {ValidationService} from '../services/validation.service';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {DataService} from '../services/data.service';
|
||||
import {RbUiComponentsModule} from '@inst-iot/bosch-angular-ui-components';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
|
||||
// TODO
|
||||
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
let validationServiceSpy: jasmine.SpyObj<ValidationService>;
|
||||
let dataServiceSpy: jasmine.SpyObj<DataService>;
|
||||
|
||||
describe('TemplatesComponent', () => {
|
||||
let component: TemplatesComponent;
|
||||
let fixture: ComponentFixture<TemplatesComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['post', 'put']);
|
||||
const validationSpy = jasmine.createSpyObj('ValidationService', ['string', 'parameterName', 'parameterRange']);
|
||||
const dataSpy = jasmine.createSpyObj('DataService', ['load', 'idReload']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ TemplatesComponent ]
|
||||
declarations: [ TemplatesComponent ],
|
||||
imports: [
|
||||
RbUiComponentsModule,
|
||||
FormsModule
|
||||
],
|
||||
providers: [
|
||||
{provide: ApiService, useValue: apiSpy},
|
||||
{provide: ValidationService, useValue: validationSpy},
|
||||
{provide: DataService, useValue: dataSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
validationServiceSpy = TestBed.inject(ValidationService) as jasmine.SpyObj<ValidationService>;
|
||||
dataServiceSpy = TestBed.inject(DataService) as jasmine.SpyObj<DataService>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TemplatesComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -1,21 +1,45 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { UsersComponent } from './users.component';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {LoginService} from '../services/login.service';
|
||||
import {ModalService} from '@inst-iot/bosch-angular-ui-components';
|
||||
|
||||
// TODO
|
||||
|
||||
let apiServiceSpy: jasmine.SpyObj<ApiService>;
|
||||
let modalServiceSpy: jasmine.SpyObj<ModalService>;
|
||||
let loginServiceSpy: jasmine.SpyObj<LoginService>;
|
||||
|
||||
|
||||
describe('UsersComponent', () => {
|
||||
let component: UsersComponent;
|
||||
let fixture: ComponentFixture<UsersComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
const apiSpy = jasmine.createSpyObj('ApiService', ['post', 'put']);
|
||||
const modalSpy = jasmine.createSpyObj('ModalService', ['open']);
|
||||
const loginSpy = jasmine.createSpyObj('LoginService', ['login', 'canActivate']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ UsersComponent ]
|
||||
declarations: [ UsersComponent ],
|
||||
providers: [
|
||||
{provide: ApiService, useValue: apiSpy},
|
||||
{provide: ModalService, useValue: modalSpy},
|
||||
{provide: LoginService, useValue: loginSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
apiServiceSpy = TestBed.inject(ApiService) as jasmine.SpyObj<ApiService>;
|
||||
modalServiceSpy = TestBed.inject(ModalService) as jasmine.SpyObj<ModalService>;
|
||||
loginServiceSpy = TestBed.inject(LoginService) as jasmine.SpyObj<LoginService>;
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(UsersComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -1,8 +1,14 @@
|
||||
// import { ValidateDirective } from './validate.directive';
|
||||
// import {ValidationService} from './services/validation.service';
|
||||
//
|
||||
// // TODO
|
||||
//
|
||||
// const validationSpy = {test: () => {}};
|
||||
// const validationServiceSpy: jasmine.SpyObj<any> = spyOn(validationSpy, 'test');
|
||||
//
|
||||
// describe('ValidateDirective', () => {
|
||||
// it('should create an instance', () => {
|
||||
// const directive = new ValidateDirective();
|
||||
// const directive = new ValidateDirective(validationServiceSpy);
|
||||
// expect(directive).toBeTruthy();
|
||||
// });
|
||||
// });
|
||||
|
BIN
src/assets/icons/icon-128x128.png
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
src/assets/icons/icon-144x144.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
src/assets/icons/icon-152x152.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
src/assets/icons/icon-192x192.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
src/assets/icons/icon-384x384.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
src/assets/icons/icon-512x512.png
Normal file
After Width: | Height: | Size: 235 KiB |
BIN
src/assets/icons/icon-72x72.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
src/assets/icons/icon-96x96.png
Normal file
After Width: | Height: | Size: 16 KiB |
@ -6,8 +6,11 @@
|
||||
<base href="/">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="manifest" href="manifest.webmanifest">
|
||||
<meta name="theme-color" content="#1976d2">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
<noscript>Please enable JavaScript to continue using this application.</noscript>
|
||||
</body>
|
||||
</html>
|
||||
|
59
src/manifest.webmanifest
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"name": "definma",
|
||||
"short_name": "definma",
|
||||
"theme_color": "#1976d2",
|
||||
"background_color": "#fafafa",
|
||||
"display": "standalone",
|
||||
"scope": "./",
|
||||
"start_url": "./",
|
||||
"icons": [
|
||||
{
|
||||
"src": "assets/icons/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
},
|
||||
{
|
||||
"src": "assets/icons/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable any"
|
||||
}
|
||||
]
|
||||
}
|