+ (keydown)="preventDefault($event)">
add spectra
@@ -161,7 +158,7 @@
-
+ |
|
@@ -184,39 +181,22 @@
-
-
+
+ (click)="restoreSample(sample._id, restoreConfirm, $event)">
|
-
+ |
+ [(ngModel)]="sample.selected">
|
- {{sample.number}} |
- {{d.id.materials[sample.material_id].numbers}} |
- {{d.id.materials[sample.material_id].name}} |
- {{d.id.materials[sample.material_id].supplier}} |
- {{d.id.materials[sample.material_id].group}} |
-
- {{d.id.materials[sample.material_id].properties[key[2]] | exists}}
+ |
+ {{data[i].data[j]}}
|
- {{sample.type}} |
- {{sample.color}} |
- {{sample.batch}} |
-
- {{sample.condition ? sample.condition[key[1]] : '' | exists}}
- |
- {{sample.notes | exists: 'comment'}} |
- {{sample.notes | object: ['_id', 'sample_references']}} |
- {{sample[key[1]] | exists: key[2]}} |
- {{sample.status}} |
- {{sample.added | date:'dd/MM/yy'}} |
@@ -245,13 +225,34 @@
{{sampleDetailsSample.number}}
- Material | {{sampleDetailsSample.material.name}} |
- Supplier | {{sampleDetailsSample.material.supplier}} |
- Group | {{sampleDetailsSample.material.group}} |
- Type | {{sampleDetailsSample.type}} |
- color | {{sampleDetailsSample.color}} |
- Batch | {{sampleDetailsSample.batch}} |
- Comment | {{sampleDetailsSample.notes.comment | exists}} |
+
+ Material |
+ {{sampleDetailsSample.material.name}} |
+
+
+ Supplier |
+ {{sampleDetailsSample.material.supplier}} |
+
+
+ Group |
+ {{sampleDetailsSample.material.group}} |
+
+
+ Type |
+ {{sampleDetailsSample.type}} |
+
+
+ color |
+ {{sampleDetailsSample.color}} |
+
+
+ Batch |
+ {{sampleDetailsSample.batch}} |
+
+
+ Comment |
+ {{sampleDetailsSample.notes.comment | exists}} |
+
{{customField[0]}} |
{{customField[1]}} |
@@ -272,8 +273,14 @@
{{measurement.name}} |
{{measurement.value}} |
- User | {{sampleDetailsSample.user}} |
- Status | {{sampleDetailsSample.status}} |
+
+ User |
+ {{sampleDetailsSample.user}} |
+
+
+ Status |
+ {{sampleDetailsSample.status}} |
+
@@ -282,4 +289,4 @@
Do you really want to restore this sample?
-
+
\ No newline at end of file
diff --git a/src/app/samples/samples.component.scss b/src/app/samples/samples.component.scss
index 7b92037..a710bcf 100644
--- a/src/app/samples/samples.component.scss
+++ b/src/app/samples/samples.component.scss
@@ -28,6 +28,10 @@ rb-table {
}
}
+rb-form-multi-select{
+ min-width: 9rem;
+}
+
.status-selection {
overflow: hidden;
margin-bottom: 10px;
diff --git a/src/app/samples/samples.component.ts b/src/app/samples/samples.component.ts
index c8f598e..c54d123 100644
--- a/src/app/samples/samples.component.ts
+++ b/src/app/samples/samples.component.ts
@@ -10,6 +10,7 @@ import { ModalService } from '@inst-iot/bosch-angular-ui-components';
import { DataService } from '../services/data.service';
import { LocalStorageService } from 'angular-2-local-storage';
import { Router } from '@angular/router';
+import { KeyValue } from '@angular/common';
interface LoadSamplesOptions {
toPage?: number;
@@ -24,6 +25,11 @@ interface KeyInterface {
sortable: boolean;
}
+interface Data {
+ id: string;
+ data: any[];
+}
+
@Component({
selector: 'app-samples',
templateUrl: './samples.component.html',
@@ -39,6 +45,7 @@ export class SamplesComponent implements OnInit {
downloadCondition = false;
downloadFlatten = true;
samples: SampleModel[] = []; // all samples to display
+ data: Data[] = [];
totalSamples = 0; // total number of samples
csvUrl = ''; // store url separate so it only has to be generated when clicking the download button
filters = {
@@ -65,27 +72,44 @@ export class SamplesComponent implements OnInit {
page = 1; // current page
pages = 1; // total number of pages
loadSamplesQueue = []; // arguments of queued up loadSamples() calls
- keys: KeyInterface[] = [
+ materialKeys: KeyInterface[] = [
{ id: 'number', label: 'Number', active: true, sortable: true },
{ id: 'material.numbers', label: 'Material numbers', active: false, sortable: false },
- { id: 'material.name', label: 'Product name', active: true, sortable: true },
{ id: 'material.supplier', label: 'Supplier', active: false, sortable: true },
{ id: 'material.group', label: 'Material', active: true, sortable: true },
{ id: 'type', label: 'Type', active: true, sortable: true },
{ id: 'color', label: 'Color', active: false, sortable: true },
{ id: 'batch', label: 'Batch', active: true, sortable: true },
- { id: 'notes.comment', label: 'Comment', active: false, sortable: false },
+ { id: 'notes.comment', label: 'Comment', active: false, sortable: false }
+ ];
+ conditionKeys: KeyInterface[] = [
{ id: 'notes', label: 'Notes', active: false, sortable: false },
+ ];
+ measurementKeys: KeyInterface[] = [
+ { id: 'material.name', label: 'Product name', active: true, sortable: true },
{ id: 'status', label: 'Status', active: false, sortable: true },
{ id: 'added', label: 'Added', active: true, sortable: true }
];
+
+ // combines the 3 different categories
+ categories = {
+ material: this.materialKeys,
+ condition: this.conditionKeys,
+ measurement: this.measurementKeys
+ };
+
isActiveKey: { [key: string]: boolean } = {}; // object to check if key is currently active
activeKeys: KeyInterface[] = []; // list of active keys
- activeTemplateKeys = { material: [], condition: [], measurements: [] };
sampleDetailsSample: any = null; // sample for the sample details dialog
sampleSelect = 0; // modes: 0 - no selection, 1 - sample edit selection, 2 - validation selection
loading = 0; // number of loading instances
+ // change the way values are displayed
+ valueConverters = {
+ 'added': (v: string, _sample) => new Date(v).toLocaleDateString(),
+ 'notes': (v: any, _sample: any) => v.sample_references.length > 0 ? Object.keys(v.sample_references).map(r => v.sample_references[r].relation).join(", ") : "",
+ 'notes.comment': (v: any, sample: any) => sample['notes']['comment']
+ }
constructor(
private api: ApiService,
@@ -96,8 +120,7 @@ export class SamplesComponent implements OnInit {
private storage: LocalStorageService,
private window: Window,
private router: Router
- ) {
- }
+ ) {}
ngOnInit(): void {
this.loading = 8;
@@ -123,7 +146,7 @@ export class SamplesComponent implements OnInit {
this.d.load('userKey', onLoad);
this.d.load('conditionTemplates', onLoad);
this.loadTemplateKeys('material', 'type', onLoad);
- this.loadTemplateKeys('condition', 'notes.comment', onLoad);
+ this.loadTemplateKeys('condition', 'notes', onLoad);
this.loadTemplateKeys('measurement', 'status', onLoad);
}
@@ -157,18 +180,17 @@ 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.categories[collection].splice(this.categories[collection].findIndex(e => e.id === insertBefore), 0, ...templateKeys);
+ this.categories[collection] = [...this.categories[collection]]; // complete overwrite array to invoke update in rb-multiselect
this.loadPreferences();
f();
});
}
// set toPage to null to reload first page, queues calls
- loadSamples(options: LoadSamplesOptions = {}, event = null) {
+ loadSamples(options: LoadSamplesOptions = {}, event = null, category?) {
if (event) { // adjust active keys
- console.log(event);
- this.keys.forEach(key => {
+ this.categories[category].forEach(key => {
if (event.hasOwnProperty(key.id)) {
key.active = event[key.id];
}
@@ -179,7 +201,7 @@ export class SamplesComponent implements OnInit {
}
this.updateActiveKeys();
}
- if(options.firstPage){
+ if (options.firstPage) {
this.storage.set('currentPage', 1);
}
this.loadSamplesQueue.push(options);
@@ -203,13 +225,14 @@ export class SamplesComponent implements OnInit {
}
this.pages = Math.ceil(this.totalSamples / this.filters.pageSize);
this.samples = sData as any;
+ this.storeData();
this.loadSamplesQueue.shift();
if (this.loadSamplesQueue.length > 0) { // execute next queue item
this.sampleLoader(this.loadSamplesQueue[0]);
}
}
});
- if(this.storage.get('currentPage') !== this.page){
+ if (this.storage.get('currentPage') !== this.page) {
this.loadPage(Number(this.storage.get('currentPage')) - this.page);
}
}
@@ -247,13 +270,14 @@ export class SamplesComponent implements OnInit {
if (options.export) { // append API key on export
query.push('key=' + this.d.d.userKey.key);
}
- this.keys.forEach(key => {
- // do not load material properties for table
- if (key.active && (options.export || (!options.export && key.id.indexOf('material.') < 0))) {
- query.push('fields[]=' + key.id);
- }
- });
+ for (let category in this.categories) {
+ this.categories[category].forEach(key => {
+ if (key.active && (options.export || (!options.export && key.id.indexOf('material.') < 0))) {
+ query.push('fields[]=' + key.id);
+ }
+ });
+ }
query.push(...cloneDeep(this.filters.filters)
.map(e => {
e.values = e.values.filter(el => el !== ''); // do not include empty values
@@ -314,14 +338,20 @@ export class SamplesComponent implements OnInit {
}
storePreferences() {
+ let keys = [];
+ for (let category in this.categories) {
+ keys.push(...this.categories[category].map(e => pick(e, ['id', 'active'])));
+ }
+
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']))
+ keys: keys
};
this.storage.set('samplesPreferences', store);
+ this.calcFieldSelectKeys();
}
loadPreferences() {
@@ -334,10 +364,13 @@ export class SamplesComponent implements OnInit {
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;
+ for (let category in this.categories) {
+ const keyIndex = this.categories[category].findIndex(e => e.id === key.id);
+ if (keyIndex >= 0) {
+ this.categories[category][keyIndex].active = key.active;
+ }
}
});
}
@@ -361,28 +394,23 @@ export class SamplesComponent implements OnInit {
}
updateActiveKeys() { // array with all activeKeys
- this.activeKeys = this.keys.filter(e => e.active);
- this.filters.filters.forEach(filter => { // disable filters of fields not displayed
- 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)));
+ this.activeKeys = [];
+ for (let category in this.categories) {
+ this.activeKeys.push(...this.categories[category].filter(e => e.active));
+ this.filters.filters.forEach(filter => { // disable filters of fields not displayed
+ if (!this.isActiveKey[filter.field]) {
+ filter.active = false;
+ }
+ });
+ }
}
calcFieldSelectKeys() {
- this.keys.forEach(key => {
- this.isActiveKey[key.id] = key.active;
- });
+ for (let category in this.categories) {
+ this.categories[category].forEach(key => {
+ this.isActiveKey[key.id] = key.active;
+ });
+ }
}
sampleDetails(id: string, modal: TemplateRef
) { // show sample details
@@ -417,7 +445,7 @@ export class SamplesComponent implements OnInit {
.push(...Object.entries(measurement.values).filter(e => e[0] !== 'dpt')
.map(e => ({ name: this.ucFirst(name) + ' ' + e[0], value: e[1] })));
});
- new Promise(resolve => {
+ new Promise(resolve => {
if (data.notes.sample_references.length) { // load referenced samples if available
let loadingCounter = data.notes.sample_references.length;
this.sampleDetailsSample.notes.sample_references.forEach(reference => {
@@ -505,4 +533,28 @@ export class SamplesComponent implements OnInit {
ucFirst(string) { // convert first character of string to uppercase
return string[0].toUpperCase() + string.slice(1);
}
+
+ refreshMultiSelect() {
+ for (let collection in this.categories) {
+ this.categories[collection] = [...this.categories[collection]];
+ }
+ }
+
+ // stores data in a unified way
+ storeData() {
+ this.data = [];
+ this.samples.forEach(sample => {
+ let value = [];
+ this.activeKeys.forEach(key => {
+ let id = key.id.split('material.')[1];
+ let tmpValue = id ? this.d.id.materials[sample.material_id][id] : sample[key.id];
+ value.push(this.valueConverters[key.id] ? this.valueConverters[key.id](tmpValue, sample) : tmpValue);
+ });
+ this.data.push({ id: sample._id, data: value });
+ });
+ }
+
+ originalOrder = (a: KeyValue, b: KeyValue): number => {
+ return 0;
+ }
}