From a4ed8888e61d56bccc1f64936e3395fdb8881adc Mon Sep 17 00:00:00 2001 From: VLE2FE Date: Thu, 30 Jul 2020 11:33:56 +0200 Subject: [PATCH] implemented icon buttons, array input, reformatting, minor sample component improvements --- package-lock.json | 5 + package.json | 4 +- .../rb-array-input.component.ts | 70 +++++++-- .../rb-icon-button.component.ts | 1 - src/app/sample/sample.component.html | 119 ++++++++++----- src/app/sample/sample.component.spec.ts | 2 +- src/app/sample/sample.component.ts | 137 +++++++++--------- src/app/samples/samples.component.html | 78 ++++++---- src/app/samples/samples.component.spec.ts | 2 +- src/app/samples/samples.component.ts | 74 ++++++---- src/app/services/login.service.ts | 3 - src/app/templates/templates.component.html | 9 +- 12 files changed, 326 insertions(+), 178 deletions(-) diff --git a/package-lock.json b/package-lock.json index cde5a07..5f6e05a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12388,6 +12388,11 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, + "str-compare": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/str-compare/-/str-compare-0.1.2.tgz", + "integrity": "sha1-eOaGGlccGiKhnq4Q5wmWt9z9r0Y=" + }, "stream-browserify": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", diff --git a/package.json b/package.json index 96c6204..6c9df32 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "@angular/platform-browser-dynamic": "~9.1.7", "@angular/router": "~9.1.7", "@hapi/joi": "^17.1.1", - "@inst-iot/bosch-angular-ui-components": "file:../Bosch-UI-Components/bosch-angular-ui-components/dist-lib/inst-iot-bosch-angular-ui-components-0.6.0.tgz", + "@inst-iot/bosch-angular-ui-components": + "file:../Bosch-UI-Components/bosch-angular-ui-components/dist-lib/inst-iot-bosch-angular-ui-components-0.6.0.tgz", "angular-2-local-storage": "^3.0.2", "chart.js": "^2.9.3", "chartjs-plugin-datalabels": "^0.7.0", @@ -33,6 +34,7 @@ "ng2-charts": "^2.3.2", "quick-score": "0.0.8", "rxjs": "~6.5.5", + "str-compare": "^0.1.2", "tslib": "^1.10.0", "zone.js": "~0.10.2" }, diff --git a/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.ts b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.ts index e258217..82501eb 100644 --- a/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.ts +++ b/src/app/rb-custom-inputs/rb-array-input/rb-array-input.component.ts @@ -13,7 +13,6 @@ import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; import _ from 'lodash'; import {ArrayInputHelperService} from './array-input-helper.service'; -// TODO: implement everywhere @Directive({ // directive for template and input values // tslint:disable-next-line:directive-selector @@ -31,7 +30,7 @@ export class RbArrayInputItemDirective { export class RbArrayInputListenerDirective { @Input() rbArrayInputListener: string; - @Input() index: number; + @Input() index; constructor( private helperService: ArrayInputHelperService @@ -39,7 +38,6 @@ export class RbArrayInputListenerDirective { @HostListener('ngModelChange', ['$event']) onChange(event) { - console.log(event); this.helperService.newValue(this.rbArrayInputListener, this.index, event); } } @@ -54,8 +52,14 @@ export class RbArrayInputListenerDirective { }) export class RbArrayInputComponent implements ControlValueAccessor, OnInit, AfterViewInit { - @Input() pushTemplate: any; - @Input() pushPath: string; + pushTemplate: any = ''; + @Input('pushTemplate') set _pushTemplate(value) { + this.pushTemplate = value; + if (this.values.length) { + this.updateArray(); + } + } + @Input() pushPath: string = null; @ContentChild(RbArrayInputItemDirective) item: RbArrayInputItemDirective; @ContentChild(RbArrayInputListenerDirective) item2: RbArrayInputListenerDirective; @@ -76,24 +80,62 @@ export class RbArrayInputComponent implements ControlValueAccessor, OnInit, Afte ngAfterViewInit() { setTimeout(() => { // needed to find reference this.helperService.values(this.item2.rbArrayInputListener).subscribe(data => { // action on value change - this.values[data.index][this.pushPath] = data.value; - console.log(this.values); - if (this.values[this.values.length - 1][this.pushPath] === '' && this.values[this.values.length - 2][this.pushPath] === '') { // remove last element if last two are empty - this.values.pop(); + // assign value + if (this.pushPath) { + this.values[data.index][this.pushPath] = data.value; } - else if (this.values[this.values.length - 1][this.pushPath] !== '') { // add element if last one is filled - this.values.push(_.cloneDeep(this.pushTemplate)); + else { + this.values[data.index] = data.value; } - this.onChange(this.values.filter(e => e !== '')); // trigger ngModel with filled elements + console.log(111, this.values); + this.updateArray(); }); }, 0); } + updateArray() { + let res; + // adjust fields if pushTemplate is specified + if (this.pushTemplate !== null) { + if (this.pushPath) { + // remove last element if last two are empty + if (this.values[this.values.length - 1][this.pushPath] === '' && this.values[this.values.length - 2][this.pushPath] === '') { + this.values.pop(); + } + // add element if last all are filled + else if (this.values.filter(e => e[this.pushPath] !== '').length === this.values.length) { + this.values.push(_.cloneDeep(this.pushTemplate)); + } + res = this.values.filter(e => e[this.pushPath] !== ''); + } + else { + // remove last element if last two are empty + if (this.values[this.values.length - 1] === '' && this.values[this.values.length - 2] === '') { + this.values.pop(); + } + else if (this.values.filter(e => e !== '').length === this.values.length) { // add element if all are is filled + this.values.push(_.cloneDeep(this.pushTemplate)); + } + res = this.values.filter(e => e !== ''); + } + } + else { + this.values = [this.values[0]]; + res = this.values; + } + if (!res.length) { + res = ['']; + } + this.onChange(res); // trigger ngModel with filled elements + } + writeValue(obj: any) { // add empty value on init this.values = obj ? obj : []; if (this.values.length === 0 || this.values[0] !== '') { - console.log(this.values); - this.values.push(_.cloneDeep(this.pushTemplate)); + // add empty last field if pushTemplate is specified + if (this.pushTemplate !== null) { + this.values.push(_.cloneDeep(this.pushTemplate)); + } } } diff --git a/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.ts b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.ts index fb02b84..8896e99 100644 --- a/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.ts +++ b/src/app/rb-custom-inputs/rb-icon-button/rb-icon-button.component.ts @@ -1,6 +1,5 @@ import {Component, Input, OnInit} from '@angular/core'; -// TODO: apply everywhere @Component({ // tslint:disable-next-line:component-selector diff --git a/src/app/sample/sample.component.html b/src/app/sample/sample.component.html index 19306d6..5780178 100644 --- a/src/app/sample/sample.component.html +++ b/src/app/sample/sample.component.html @@ -6,28 +6,48 @@
- + Cannot be empty Unknown material, add properties for new material - + New material

Material properties

- + {{supplierInput.errors.failure}} - + {{groupInput.errors.failure}} -
- -
- + + + The specified {{modalText.list}} could not be found in the list.
+ Did you mean {{modalText.suggestion}}? +
+
+ + + + - + {{parameterInput.errors.failure}} Cannot be empty @@ -36,11 +56,13 @@  
- + {{typeInput.errors.failure}} Cannot be empty - + {{colorInput.errors.failure}} Cannot be empty @@ -51,31 +73,43 @@
- + {{commentInput.errors.failure}}
Sample references
- + Unknown sample number
- + Cannot be empty
Additional properties
-
-
- - {{keyInput.errors.failure}} + + +
+ + {{keyInput.errors.failure}} + +
+ + Cannot be empty -
- - Cannot be empty - -
+ +
  @@ -83,14 +117,18 @@

Condition - +

- + - + {{parameterInput.errors.failure}} Cannot be empty @@ -102,16 +140,23 @@

Measurements

- + -
- +
+ {{parameterInput.errors.failure}} Cannot be empty - + Cannot be empty
- - + + Delete measurement +
 
- + + New measurement +
- +
diff --git a/src/app/sample/sample.component.spec.ts b/src/app/sample/sample.component.spec.ts index c32c4c1..85ea267 100644 --- a/src/app/sample/sample.component.spec.ts +++ b/src/app/sample/sample.component.spec.ts @@ -2,7 +2,7 @@ // // import { SampleComponent } from './sample.component'; // -// // TODO +// // TODO: tests // // describe('SampleComponent', () => { // let component: SampleComponent; diff --git a/src/app/sample/sample.component.ts b/src/app/sample/sample.component.ts index 985ea69..c03ab0f 100644 --- a/src/app/sample/sample.component.ts +++ b/src/app/sample/sample.component.ts @@ -1,8 +1,9 @@ import _ from 'lodash'; +import strCompare from 'str-compare'; import { AfterContentChecked, Component, - OnInit, + OnInit, TemplateRef, ViewChild } from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; @@ -17,18 +18,14 @@ import {MeasurementModel} from '../models/measurement.model'; import { ChartOptions } from 'chart.js'; import {animate, style, transition, trigger} from '@angular/animations'; import {Observable} from 'rxjs'; +import {ModalService} from '@inst-iot/bosch-angular-ui-components'; +import {UserModel} from '../models/user.model'; + -// TODO: tests -// TODO: confirmation for new group/supplier // TODO: work on better recognition for file input // TODO: only show condition (if not set) and measurements in edit sample dialog at first -// TODO: multiple spectra // TODO: multiple samples for base data, extend multiple measurements, conditions -// TODO: material properties, color (in material and sample (not required)) - -// TODO: device autocomplete - @Component({ selector: 'app-sample', templateUrl: './sample.component.html', @@ -55,16 +52,18 @@ export class SampleComponent implements OnInit, AfterContentChecked { new; // true if new sample should be created newMaterial = false; // true if new material should be created materials: MaterialModel[] = []; // all materials - suppliers: string[] = []; // all suppliers - groups: string[] = []; // all groups + ac: {[group: string]: string[]} = { // autocomplete data + supplier: [], + group: [], + materialName: [] + }; conditionTemplates: TemplateModel[]; // all conditions condition: TemplateModel | null = null; // selected condition materialTemplates: TemplateModel[]; // all material templates materialTemplate: TemplateModel | null = null; // selected material template - materialNames = []; // names of all materials material = new MaterialModel(); // object of current selected material sample = new SampleModel(); - customFields: [string, string][] = [['', '']]; + customFields: [string, string][]; sampleReferences: [string, string, string][] = [['', '', '']]; sampleReferenceFinds: {_id: string, number: string}[] = []; // raw sample reference data from db currentSRIndex = 0; // index of last entered sample reference @@ -74,7 +73,9 @@ export class SampleComponent implements OnInit, AfterContentChecked { measurementTemplates: TemplateModel[]; loading = 0; // number of currently loading instances checkFormAfterInit = false; - charts = []; // chart data for spectrums + modalText = {list: '', suggestion: ''}; + charts = []; // chart data for spectra + defaultDevice = ''; readonly chartInit = [{ data: [], label: 'Spectrum', @@ -101,7 +102,8 @@ export class SampleComponent implements OnInit, AfterContentChecked { private route: ActivatedRoute, private api: ApiService, private validation: ValidationService, - public autocomplete: AutocompleteService + public autocomplete: AutocompleteService, + private modal: ModalService ) { } ngOnInit(): void { @@ -109,15 +111,15 @@ export class SampleComponent implements OnInit, AfterContentChecked { this.loading = 7; this.api.get('/materials?status=all', (data: any) => { this.materials = data.map(e => new MaterialModel().deserialize(e)); - this.materialNames = data.map(e => e.name); + this.ac.materialName = data.map(e => e.name); this.loading--; }); this.api.get('/material/suppliers', (data: any) => { - this.suppliers = data; + this.ac.supplier = data; this.loading--; }); this.api.get('/material/groups', (data: any) => { - this.groups = data; + this.ac.mgroup = data; this.loading--; }); this.api.get('/template/conditions', data => { @@ -129,6 +131,9 @@ export class SampleComponent implements OnInit, AfterContentChecked { this.selectMaterialTemplate(this.materialTemplates[0]._id); this.loading--; }); + this.api.get('/user', data => { + this.defaultDevice = data.device_name; + }); this.api.get('/template/measurements', data => { this.measurementTemplates = data.map(e => new TemplateModel().deserialize(e)); if (!this.new) { @@ -149,7 +154,8 @@ export class SampleComponent implements OnInit, AfterContentChecked { } }); this.material = sData.material; - this.customFields = this.sample.notes.custom_fields && this.sample.notes.custom_fields !== {} ? Object.keys(this.sample.notes.custom_fields).map(e => [e, this.sample.notes.custom_fields[e]]) : [['', '']]; + this.customFields = this.sample.notes.custom_fields && this.sample.notes.custom_fields !== {} ? + Object.keys(this.sample.notes.custom_fields).map(e => [e, this.sample.notes.custom_fields[e]]) : [['', '']]; if (this.sample.notes.sample_references.length) { this.sampleReferences = []; this.sampleReferenceAutocomplete = []; @@ -185,7 +191,8 @@ export class SampleComponent implements OnInit, AfterContentChecked { ngAfterContentChecked() { // attach validators to dynamic condition fields when all values are available and template was fully created - if (this.condition && this.condition.hasOwnProperty('parameters') && this.condition.parameters.length > 0 && this.condition.parameters[0].hasOwnProperty('range') && this.sampleForm && this.sampleForm.form.get('conditionParameter0')) { + if (this.condition && this.condition.hasOwnProperty('parameters') && this.condition.parameters.length > 0 && + this.condition.parameters[0].hasOwnProperty('range') && this.sampleForm && this.sampleForm.form.get('conditionParameter0')) { for (const i in this.condition.parameters) { if (this.condition.parameters[i]) { this.attachValidator('conditionParameter' + i, this.condition.parameters[i].range, true); @@ -194,7 +201,8 @@ export class SampleComponent implements OnInit, AfterContentChecked { } // attach validators to dynamic material fields when all values are available and template was fully created - if (this.materialTemplate && this.materialTemplate.hasOwnProperty('parameters') && this.materialTemplate.parameters.length > 0 && this.materialTemplate.parameters[0].hasOwnProperty('range') && this.sampleForm && this.sampleForm.form.get('materialParameter0')) { + if (this.materialTemplate && this.materialTemplate.hasOwnProperty('parameters') && this.materialTemplate.parameters.length > 0 && + this.materialTemplate.parameters[0].hasOwnProperty('range') && this.sampleForm && this.sampleForm.form.get('materialParameter0')) { for (const i in this.materialTemplate.parameters) { if (this.materialTemplate.parameters[i]) { this.attachValidator('materialParameter' + i, this.materialTemplate.parameters[i].range, true); @@ -250,7 +258,6 @@ export class SampleComponent implements OnInit, AfterContentChecked { saveSample() { new Promise(resolve => { if (this.newMaterial) { // save material first if new one exists - this.material.numbers = this.material.numbers.filter(e => e !== ''); this.api.post('/material/new', this.material.sendFormat(), data => { this.materials.push(data); // add material to data this.material = data; @@ -268,7 +275,9 @@ export class SampleComponent implements OnInit, AfterContentChecked { this.sample.notes.custom_fields[element[0]] = element[1]; } }); - this.sample.notes.sample_references = this.sampleReferences.filter(e => e[0] && e[1] && e[2]).map(e => ({sample_id: e[2], relation: e[1]})); + this.sample.notes.sample_references = this.sampleReferences + .filter(e => e[0] && e[1] && e[2]) + .map(e => ({sample_id: e[2], relation: e[1]})); new Promise(resolve => { if (this.new) { this.api.post('/sample/new', this.sample.sendFormat(), resolve); @@ -289,7 +298,8 @@ export class SampleComponent implements OnInit, AfterContentChecked { this.api.post('/measurement/new', measurement.sendFormat()); } else { // update measurement - this.api.put('/measurement/' + measurement._id, measurement.sendFormat(['sample_id', 'measurement_template'])); + this.api.put('/measurement/' + measurement._id, + measurement.sendFormat(['sample_id', 'measurement_template'])); } } else if (measurement._id !== null) { // existing measurement was left empty to delete @@ -321,7 +331,6 @@ export class SampleComponent implements OnInit, AfterContentChecked { } } - // TODO: rework later setNewMaterial(value = null) { if (value === null) { this.newMaterial = !this.sample.material_id; @@ -333,24 +342,12 @@ export class SampleComponent implements OnInit, AfterContentChecked { this.sampleForm.form.get('materialname').setValidators([Validators.required]); } else { - this.sampleForm.form.get('materialname').setValidators([Validators.required, this.validation.generate('stringOf', [this.materialNames])]); + this.sampleForm.form.get('materialname') + .setValidators([Validators.required, this.validation.generate('stringOf', [this.ac.materialName])]); } this.sampleForm.form.get('materialname').updateValueAndValidity(); } - handleMaterialNumbers() { - const fieldNo = this.material.numbers.length; - const filledFields = this.material.numbers.filter(e => e !== '').length; - // append new field - if (filledFields === fieldNo) { - this.material.numbers.push(''); - } - // remove if two end fields are empty - if (fieldNo > 1 && this.material.numbers[fieldNo - 1] === '' && this.material.numbers[fieldNo - 2] === '') { - this.material.numbers.pop(); - } - } - selectCondition(id) { this.condition = this.conditionTemplates.find(e => e._id === id); console.log(this.condition); @@ -372,7 +369,8 @@ export class SampleComponent implements OnInit, AfterContentChecked { } addMeasurement() { - this.sample.measurements.push(new MeasurementModel(this.measurementTemplates[0]._id)); + this.sample.measurements.push(new MeasurementModel(this.measurementTemplates.filter(e => e.name === 'spectrum').reverse()[0]._id)); + this.sample.measurements[this.sample.measurements.length - 1].values.device = this.defaultDevice; this.charts.push(_.cloneDeep(this.chartInit)); } @@ -389,12 +387,22 @@ export class SampleComponent implements OnInit, AfterContentChecked { } fileToArray(files, mIndex, parameter) { - const fileReader = new FileReader(); - fileReader.onload = () => { - this.sample.measurements[mIndex].values[parameter] = fileReader.result.toString().split('\r\n').map(e => e.split(',')); - this.generateChart(this.sample.measurements[mIndex].values[parameter], mIndex); - }; - fileReader.readAsText(files[0]); + for (const i in files) { + if (files.hasOwnProperty(i)) { + const fileReader = new FileReader(); + fileReader.onload = () => { + let index: number = mIndex; + if (Number(i) > 0) { // append further spectra + this.addMeasurement(); + index = this.sample.measurements.length - 1; + } + this.sample.measurements[index].values[parameter] = + fileReader.result.toString().split('\r\n').map(e => e.split(',')); + this.generateChart(this.sample.measurements[index].values[parameter], index); + }; + fileReader.readAsText(files[i]); + } + } } generateChart(spectrum, index) { @@ -411,22 +419,17 @@ export class SampleComponent implements OnInit, AfterContentChecked { } } - adjustCustomFields(value, index) { - this.customFields[index][0] = value; - const fieldNo = this.customFields.length; - let filledFields = 0; - this.customFields.forEach(field => { - if (field[0] !== '') { - filledFields ++; - } - }); - // append new field - if (filledFields === fieldNo) { - this.customFields.push(['', '']); - } - // remove if two end fields are empty - if (fieldNo > 1 && this.customFields[fieldNo - 1][0] === '' && this.customFields[fieldNo - 2][0] === '') { - this.customFields.pop(); + checkTypo(list, modal: TemplateRef) { + if (this.ac[list].indexOf(this.material[list]) < 0) { // entry is not in lise + this.modalText.list = list; + this.modalText.suggestion = this.ac[list] // find possible entry from list + .map(e => ({v: e, s: strCompare.sorensenDice(e, this.material[list])})) + .sort((a, b) => b.s - a.s)[0].v; + this.modal.open(modal).then(result => { + if (result) { // use suggestion + this.material[list] = this.modalText.suggestion; + } + }); } } @@ -457,7 +460,9 @@ export class SampleComponent implements OnInit, AfterContentChecked { sampleReferenceList(value) { return new Observable(observer => { - this.api.get<{_id: string, number: string}[]>('/samples?status=all&page-size=25&sort=number-asc&fields[]=number&fields[]=_id&filters[]=%7B%22mode%22%3A%22stringin%22%2C%22field%22%3A%22number%22%2C%22values%22%3A%5B%22' + value + '%22%5D%7D', data => { + this.api.get<{_id: string, number: string}[]>( + '/samples?status=all&page-size=25&sort=number-asc&fields[]=number&fields[]=_id&' + + 'filters[]=%7B%22mode%22%3A%22stringin%22%2C%22field%22%3A%22number%22%2C%22values%22%3A%5B%22' + value + '%22%5D%7D', data => { console.log(data); this.sampleReferenceAutocomplete[this.currentSRIndex] = data.map(e => e.number); this.sampleReferenceFinds = data; @@ -483,12 +488,14 @@ export class SampleComponent implements OnInit, AfterContentChecked { } uniqueCfValues(index) { // returns all names until index for unique check - return this.customFields.slice(0, index).map(e => e[0]); + return this.customFields ? this.customFields.slice(0, index).map(e => e[0]) : []; } } -// 1. ngAfterViewInit wird ja jedes mal nach einem ngOnChanges aufgerufen, also zB wenn sich dein ngFor aufbaut. Du könntest also in der Methode prüfen, ob die Daten schon da sind und dann dementsprechend handeln. Das wäre die Eleganteste Variante +// 1. ngAfterViewInit wird ja jedes mal nach einem ngOnChanges aufgerufen, also zB wenn sich dein ngFor aufbaut. Du könntest also in der +// Methode prüfen, ob die Daten schon da sind und dann dementsprechend handeln. Das wäre die Eleganteste Variante // 2. Der state "dirty" soll eigentlich anzeigen, wenn ein Form-Field vom User geändert wurde; damit missbrauchst du es hier etwas -// 3. Die Dirty-Variante: Pack in deine ngFor ein {{ onFirstLoad(data) }} rein, das einfach ausgeführt wird. müsstest dann natürlich abfangen, dass das nicht nach jedem view-cycle neu getriggert wird. Schön ist das nicht, aber besser als mit Timeouts^^ +// 3. Die Dirty-Variante: Pack in deine ngFor ein {{ onFirstLoad(data) }} rein, das einfach ausgeführt wird. müsstest dann natürlich +// abfangen, dass das nicht nach jedem view-cycle neu getriggert wird. Schön ist das nicht, aber besser als mit Timeouts^^ diff --git a/src/app/samples/samples.component.html b/src/app/samples/samples.component.html index 4056ef8..24f665b 100644 --- a/src/app/samples/samples.component.html +++ b/src/app/samples/samples.component.html @@ -2,7 +2,7 @@ @@ -12,14 +12,17 @@
- + validated - + new
- + @@ -29,15 +32,18 @@ - + {{item.label}}
- - + + @@ -49,13 +55,26 @@
- - - - - - - + + + + + + +
@@ -68,18 +87,20 @@
- - - URL for JSON download: - + JSON download link + + + add spectra - + Copy to clipboard - + + Download result as CSV +
@@ -89,8 +110,12 @@
{{key.label}} - - + + + + + +
@@ -103,7 +128,9 @@ {{materials[sample.material_id].name}} {{materials[sample.material_id].supplier}} {{materials[sample.material_id].group}} - {{materials[sample.material_id].properties[key[2]] | exists}} + + {{materials[sample.material_id].properties[key[2]] | exists}} + {{sample.type}} {{sample.color}} {{sample.batch}} @@ -121,7 +148,8 @@ - + + of {{pages}} ({{totalSamples}} samples) diff --git a/src/app/samples/samples.component.spec.ts b/src/app/samples/samples.component.spec.ts index 1964449..d3ec677 100644 --- a/src/app/samples/samples.component.spec.ts +++ b/src/app/samples/samples.component.spec.ts @@ -2,7 +2,7 @@ // // import { SamplesComponent } from './samples.component'; // -// // TODO +// // TODO: tests // // describe('SamplesComponent', () => { // let component: SamplesComponent; diff --git a/src/app/samples/samples.component.ts b/src/app/samples/samples.component.ts index c4f6195..3523e14 100644 --- a/src/app/samples/samples.component.ts +++ b/src/app/samples/samples.component.ts @@ -54,7 +54,7 @@ export class SamplesComponent implements OnInit { {field: 'color', label: 'Color', active: false, autocomplete: [], mode: 'eq', values: ['']}, {field: 'batch', label: 'Batch', active: false, autocomplete: [], mode: 'eq', values: ['']}, {field: 'notes', label: 'Notes', active: false, autocomplete: [], mode: 'eq', values: ['']}, - {field: 'added', label: 'Added', active: false, autocomplete: [], mode: 'eq', values: [new Date()]} + {field: 'added', label: 'Added', active: false, autocomplete: [], mode: 'eq', values: ['']} ] }; page = 1; @@ -92,7 +92,8 @@ export class SamplesComponent implements OnInit { this.materials[material._id] = material; }); this.filters.filters.find(e => e.field === 'material.name').autocomplete = mData.map(e => e.name); - this.filters.filters.find(e => e.field === 'color').autocomplete = [...new Set(mData.reduce((s, e) => {s.push(...e.numbers.map(el => el.color)); return s; }, []))]; + this.filters.filters.find(e => e.field === 'color').autocomplete = + [...new Set(mData.reduce((s, e) => {s.push(...e.numbers.map(el => el.color)); return s; }, []))]; this.loadSamples(); }); this.api.get('/user/key', (data: {key: string}) => { @@ -114,9 +115,22 @@ export class SamplesComponent implements OnInit { data.forEach(item => { item.parameters.forEach(parameter => { const parameterName = encodeURIComponent(parameter.name); - if (parameter.name !== 'dpt' && !templateKeys.find(e => new RegExp('.' + parameterName + '$').test(e.id))) { // exclude spectrum - templateKeys.push({id: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`, label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`, active: false, sortable: true}); - this.filters.filters.push({field: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`, label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`, active: false, autocomplete: [], mode: 'eq', values: ['']}); + // exclude spectrum + if (parameter.name !== 'dpt' && !templateKeys.find(e => new RegExp('.' + parameterName + '$').test(e.id))) { + templateKeys.push({ + id: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`, + label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`, + active: false, + sortable: true + }); + this.filters.filters.push({ + field: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`, + label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`, + active: false, + autocomplete: [], + mode: 'eq', + values: [''] + }); } }); }); @@ -156,10 +170,22 @@ export class SamplesComponent implements OnInit { }); } - sampleUrl(options: {paging?: boolean, pagingOptions?: {firstPage?: boolean, toPage?: number, event?: Event}, csv?: boolean, export?: boolean, host?: boolean}) { // return url to fetch samples + sampleUrl(options: { + paging?: boolean, + pagingOptions?: { + firstPage?: boolean, + toPage?: number, + event?: Event + }, + csv?: boolean, + export?: boolean, + host?: boolean + }) { // return url to fetch samples const additionalTableKeys = ['material_id', '_id']; // keys which should always be added if export = false const query: string[] = []; - query.push('status=' + (this.filters.status.new && this.filters.status.validated ? 'all' : (this.filters.status.new ? 'new' : 'validated'))); + query.push( + 'status=' + (this.filters.status.new && this.filters.status.validated ? 'all' : (this.filters.status.new ? 'new' : 'validated')) + ); if (options.paging) { if (this.samples[0]) { // do not include from-id when page size was changed if (!options.pagingOptions.firstPage) { @@ -182,11 +208,11 @@ export class SamplesComponent implements OnInit { query.push('key=' + this.apiKey); } this.keys.forEach(key => { - if (key.active && (options.export || (!options.export && key.id.indexOf('material') < 0))) { // do not load material properties for table + // do not load material properties for table + if (key.active && (options.export || (!options.export && key.id.indexOf('material') < 0))) { query.push('fields[]=' + key.id); } }); - console.log(this.filters.filters); query.push(..._.cloneDeep(this.filters.filters) .map(e => { @@ -199,7 +225,6 @@ export class SamplesComponent implements OnInit { .filter(e => e.active && e.values.length > 0) .map(e => 'filters[]=' + encodeURIComponent(JSON.stringify(_.pick(e, ['mode', 'field', 'values'])))) ); - console.log(this.filters); if (!options.export) { additionalTableKeys.forEach(key => { if (query.indexOf('fields[]=' + key) < 0) { // add key if not already added @@ -210,8 +235,9 @@ export class SamplesComponent implements OnInit { else if (this.downloadCsv) { query.push('fields[]=measurements.spectrum.dpt'); } - console.log('/samples?' + query.join('&')); - return (options.host && isDevMode() ? window.location.host : '') + (options.export ? this.api.hostName : '') + '/samples?' + query.join('&'); + return (options.host && isDevMode() ? window.location.host : '') + + (options.export ? this.api.hostName : '') + + '/samples?' + query.join('&'); } loadPage(delta) { @@ -225,17 +251,6 @@ export class SamplesComponent implements OnInit { updateFilterFields(field) { const filter = this.filters.filters.find(e => e.field === field); filter.active = true; - if (filter.mode === 'in' || filter.mode === 'nin') { - if (filter.values[filter.values.length - 1] === '' && filter.values[filter.values.length - 2] === '') { - filter.values.pop(); - } - else if (filter.values[filter.values.length - 1] !== '') { - filter.values.push((filter.field === 'added' ? new Date() : '') as string & Date); - } - } - else { - filter.values = [filter.values[0] as string & Date]; - } if (filter.active) { this.loadSamples({firstPage: true}); } @@ -248,15 +263,16 @@ export class SamplesComponent implements OnInit { updateActiveKeys() { // array with all activeKeys this.activeKeys = this.keys.filter(e => e.active); - 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.measurements = this.keys.filter(e => e.id.indexOf('measurements.') >= 0 && e.active).map(e => e.id.split('.').map(el => decodeURIComponent(el))); - console.log(this.activeTemplateKeys); - console.log(this.keys); // TODO: glass fiber filter not working + 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.measurements = this.keys.filter(e => e.id.indexOf('measurements.') >= 0 && e.active) + .map(e => e.id.split('.') + .map(el => decodeURIComponent(el))); // TODO: glass fiber filter not working } calcFieldSelectKeys() { - console.log('CALC'); - console.log(this.keys); this.keys.forEach(key => { this.isActiveKey[key.id] = key.active; }); diff --git a/src/app/services/login.service.ts b/src/app/services/login.service.ts index 6f66d51..f4816bc 100644 --- a/src/app/services/login.service.ts +++ b/src/app/services/login.service.ts @@ -33,8 +33,6 @@ export class LoginService implements CanActivate { login(username = '', password = '') { return new Promise(resolve => { - console.log(username); - console.log(password); if (username !== '' || password !== '') { // some credentials given let credentials: string[]; const credentialString: string = this.storage.get('basicAuth'); @@ -54,7 +52,6 @@ export class LoginService implements CanActivate { this.storage.set('basicAuth', btoa(credentials[0] + ':' + password)); } } - console.log(this.storage.get('basicAuth')); this.api.get('/authorized', (data: any, error) => { if (!error) { if (data.status === 'Authorization successful') { diff --git a/src/app/templates/templates.component.html b/src/app/templates/templates.component.html index 7169c51..6d71ebc 100644 --- a/src/app/templates/templates.component.html +++ b/src/app/templates/templates.component.html @@ -40,12 +40,13 @@ class="parameters"> + [index]="item.i" [name]="'parameter-name-' + group.name + item.i" + label="parameter name" [ngModel]="item.value.name" #parameterName="ngModel"> {{parameterName.errors.failure}} - + {{parameterRange.errors.failure}}