diff --git a/README.md b/README.md
index 00b887f..b098ff9 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/angular.json b/angular.json
index 023e2a4..5917785 100644
--- a/angular.json
+++ b/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"
}
diff --git a/cf_config/Staticfile b/cf_config/Staticfile
index 9357ba4..aceedb5 100644
--- a/cf_config/Staticfile
+++ b/cf_config/Staticfile
@@ -1,4 +1,4 @@
pushstate: enabled
force_https: true
-root: UI
+root: definma
location_include: ../../*.conf
diff --git a/karma.conf.js b/karma.conf.js
index 09aabe9..6df3baf 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -16,7 +16,7 @@ module.exports = function (config) {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
- dir: require('path').join(__dirname, './coverage/UI'),
+ dir: require('path').join(__dirname, './coverage/definma'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
diff --git a/ngsw-config.json b/ngsw-config.json
new file mode 100644
index 0000000..4ddf1a7
--- /dev/null
+++ b/ngsw-config.json
@@ -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)"
+ ]
+ }
+ }
+ ]
+}
diff --git a/package-lock.json b/package-lock.json
index 352f42d..79fc0f9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -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",
diff --git a/package.json b/package.json
index fe7f7ab..2b41b23 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 9946350..320f25c 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -2,12 +2,7 @@ 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)
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 779a576..44f4513 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -28,6 +28,8 @@ 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: [
@@ -65,7 +67,8 @@ import { PredictionComponent } from './prediction/prediction.component';
ReactiveFormsModule,
FormFieldsModule,
CommonModule,
- ChartsModule
+ ChartsModule,
+ ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
],
providers: [
ModalService,
diff --git a/src/app/documentation-database/documentation-database.component.html b/src/app/documentation-database/documentation-database.component.html
index d957144..32296bc 100644
--- a/src/app/documentation-database/documentation-database.component.html
+++ b/src/app/documentation-database/documentation-database.component.html
@@ -18,7 +18,6 @@
Automatically generated unique id |
'5f2e63c98d1c020f8cda6e06' |
-
type |
diff --git a/src/app/sample/sample.component.ts b/src/app/sample/sample.component.ts
index 67c2b85..57cf409 100644
--- a/src/app/sample/sample.component.ts
+++ b/src/app/sample/sample.component.ts
@@ -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',
diff --git a/src/app/samples/samples.component.ts b/src/app/samples/samples.component.ts
index 51f3fbb..cf0aa27 100644
--- a/src/app/samples/samples.component.ts
+++ b/src/app/samples/samples.component.ts
@@ -8,6 +8,7 @@ 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';
interface LoadSamplesOptions {
@@ -28,8 +29,6 @@ interface KeyInterface {
styleUrls: ['./samples.component.scss']
})
-// TODO: save last settings
-
export class SamplesComponent implements OnInit {
@ViewChild('pageSizeSelection') pageSizeSelection: ElementRef;
@@ -89,29 +88,39 @@ export class SamplesComponent implements OnInit {
public autocomplete: AutocompleteService,
public login: LoginService,
private modalService: ModalService,
- public d: DataService
+ public d: DataService,
+ private storage: LocalStorageService
) {
}
ngOnInit(): void {
+ let loading = 7;
+ 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('measurement', 'status', onLoad);
}
- loadTemplateKeys(collection, insertBefore) {
+ loadTemplateKeys(collection, insertBefore, f) {
this.d.load(collection + 'Templates', () => {
const templateKeys = [];
this.d.arr[collection + 'Templates'].forEach(item => {
@@ -138,8 +147,8 @@ 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();
});
}
@@ -156,6 +165,7 @@ 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
@@ -256,6 +266,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;
@@ -390,4 +432,6 @@ export class SamplesComponent implements OnInit {
ucFirst(string) {
return string[0].toUpperCase() + string.slice(1);
}
+
+
}
diff --git a/src/assets/icons/icon-128x128.png b/src/assets/icons/icon-128x128.png
new file mode 100644
index 0000000..01e3730
Binary files /dev/null and b/src/assets/icons/icon-128x128.png differ
diff --git a/src/assets/icons/icon-144x144.png b/src/assets/icons/icon-144x144.png
new file mode 100644
index 0000000..25da7aa
Binary files /dev/null and b/src/assets/icons/icon-144x144.png differ
diff --git a/src/assets/icons/icon-152x152.png b/src/assets/icons/icon-152x152.png
new file mode 100644
index 0000000..65b360e
Binary files /dev/null and b/src/assets/icons/icon-152x152.png differ
diff --git a/src/assets/icons/icon-192x192.png b/src/assets/icons/icon-192x192.png
new file mode 100644
index 0000000..10f939c
Binary files /dev/null and b/src/assets/icons/icon-192x192.png differ
diff --git a/src/assets/icons/icon-384x384.png b/src/assets/icons/icon-384x384.png
new file mode 100644
index 0000000..6f4c7bb
Binary files /dev/null and b/src/assets/icons/icon-384x384.png differ
diff --git a/src/assets/icons/icon-512x512.png b/src/assets/icons/icon-512x512.png
new file mode 100644
index 0000000..45bd462
Binary files /dev/null and b/src/assets/icons/icon-512x512.png differ
diff --git a/src/assets/icons/icon-72x72.png b/src/assets/icons/icon-72x72.png
new file mode 100644
index 0000000..d504761
Binary files /dev/null and b/src/assets/icons/icon-72x72.png differ
diff --git a/src/assets/icons/icon-96x96.png b/src/assets/icons/icon-96x96.png
new file mode 100644
index 0000000..28f4640
Binary files /dev/null and b/src/assets/icons/icon-96x96.png differ
diff --git a/src/index.html b/src/index.html
index bc0c164..173237a 100644
--- a/src/index.html
+++ b/src/index.html
@@ -6,8 +6,11 @@
+
+
+
|