Merge pull request #44 in DEFINMA/definma-ui from f/filter-separation to master
* commit '2aad393c0d6f4fa24df2c888ff9e81cac12d89b3': Fix a typo Performance updates Added value converter to correctly display values Seperate the fields into 3 categories
This commit is contained in:
commit
bdce691210
@ -10,12 +10,6 @@
|
|||||||
<span *rbFormMultiSelectOption="let key">{{key.id}}</span>
|
<span *rbFormMultiSelectOption="let key">{{key.id}}</span>
|
||||||
</rb-form-multi-select>
|
</rb-form-multi-select>
|
||||||
|
|
||||||
<!--
|
|
||||||
<rb-icon-button icon="forward-right" mode="primary" (click)="updateGroups()">
|
|
||||||
Apply groups
|
|
||||||
</rb-icon-button>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<div id="divChart">
|
<div id="divChart">
|
||||||
<canvas id="myChart">
|
<canvas id="myChart">
|
||||||
</canvas>
|
</canvas>
|
||||||
|
@ -6,3 +6,7 @@ app-login {
|
|||||||
width: 70%;
|
width: 70%;
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb-form-multi-select {
|
||||||
|
width: 20%;
|
||||||
|
}
|
||||||
|
@ -120,7 +120,8 @@ export class HomeComponent implements OnInit {
|
|||||||
label: 'Number of samples per group',
|
label: 'Number of samples per group',
|
||||||
data: data.data,
|
data: data.data,
|
||||||
backgroundColor: fillPattern,
|
backgroundColor: fillPattern,
|
||||||
borderWidth: 2
|
pointRadius: 4,
|
||||||
|
pointHoverRadius: 7
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
|
@ -3,9 +3,9 @@
|
|||||||
<rb-icon-button icon="add" mode="primary" class="space-left">New sample</rb-icon-button>
|
<rb-icon-button icon="add" mode="primary" class="space-left">New sample</rb-icon-button>
|
||||||
</a>
|
</a>
|
||||||
<rb-icon-button *ngIf="sampleSelect === 2" mode="secondary" icon="close" (click)="sampleSelect = 0"
|
<rb-icon-button *ngIf="sampleSelect === 2" mode="secondary" icon="close" (click)="sampleSelect = 0"
|
||||||
class="validation-close" iconOnly></rb-icon-button>
|
class="validation-close" iconOnly></rb-icon-button>
|
||||||
<rb-icon-button *ngIf="login.isLevel.dev" [icon]="sampleSelect === 2 ? 'checkmark' : 'clear-all'"
|
<rb-icon-button *ngIf="login.isLevel.dev" [icon]="sampleSelect === 2 ? 'checkmark' : 'clear-all'" mode="secondary"
|
||||||
mode="secondary" (click)="validate()">
|
(click)="validate()">
|
||||||
{{sampleSelect === 2 ? 'Validate' : 'Validation'}}
|
{{sampleSelect === 2 ? 'Validate' : 'Validation'}}
|
||||||
</rb-icon-button>
|
</rb-icon-button>
|
||||||
</div>
|
</div>
|
||||||
@ -19,23 +19,22 @@
|
|||||||
<div class="status-selection">
|
<div class="status-selection">
|
||||||
<label class="label">Status</label>
|
<label class="label">Status</label>
|
||||||
<rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated"
|
<rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated"
|
||||||
[disabled]="!filters.status.new && !filters.status.deleted"
|
[disabled]="!filters.status.new && !filters.status.deleted" (ngModelChange)="loadSamples({firstPage: true})">
|
||||||
(ngModelChange)="loadSamples({firstPage: true})">
|
|
||||||
validated
|
validated
|
||||||
</rb-form-checkbox>
|
</rb-form-checkbox>
|
||||||
<rb-form-checkbox name="status-new" [(ngModel)]="filters.status.new"
|
<rb-form-checkbox name="status-new" [(ngModel)]="filters.status.new"
|
||||||
[disabled]="!filters.status.validated && !filters.status.deleted"
|
[disabled]="!filters.status.validated && !filters.status.deleted"
|
||||||
(ngModelChange)="loadSamples({firstPage: true})">
|
(ngModelChange)="loadSamples({firstPage: true})">
|
||||||
new
|
new
|
||||||
</rb-form-checkbox>
|
</rb-form-checkbox>
|
||||||
<rb-form-checkbox name="status-deleted" [(ngModel)]="filters.status.deleted"
|
<rb-form-checkbox name="status-deleted" [(ngModel)]="filters.status.deleted"
|
||||||
[disabled]="!filters.status.validated && !filters.status.new"
|
[disabled]="!filters.status.validated && !filters.status.new" (ngModelChange)="loadSamples({firstPage: true})"
|
||||||
(ngModelChange)="loadSamples({firstPage: true})" *ngIf="login.isLevel.dev">
|
*ngIf="login.isLevel.dev">
|
||||||
deleted
|
deleted
|
||||||
</rb-form-checkbox>
|
</rb-form-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<rb-form-select name="pageSizeSelection" label="page size" [(ngModel)]="filters.pageSize" class="selection"
|
<rb-form-select name="pageSizeSelection" label="page size" [(ngModel)]="filters.pageSize" class="selection"
|
||||||
(ngModelChange)="loadSamples({firstPage: true})" #pageSizeSelection>
|
(ngModelChange)="loadSamples({firstPage: true})" #pageSizeSelection>
|
||||||
<option value="3">3</option>
|
<option value="3">3</option>
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
<option value="25">25</option>
|
<option value="25">25</option>
|
||||||
@ -45,10 +44,13 @@
|
|||||||
<option value="500">500</option>
|
<option value="500">500</option>
|
||||||
</rb-form-select>
|
</rb-form-select>
|
||||||
|
|
||||||
<rb-form-multi-select name="fieldSelect" idField="id" [items]="keys" [(ngModel)]="isActiveKey" label="Fields"
|
<div id="multi">
|
||||||
class="selection" (ngModelChange)="loadSamples({}, $event)">
|
<rb-form-multi-select *ngFor="let item of categories | keyvalue: originalOrder" name="fieldSelect" idField="id"
|
||||||
<span *rbFormMultiSelectOption="let item" class="load-first-page">{{item.label}}</span>
|
[items]="item.value" [(ngModel)]="isActiveKey" [label]="item.key" class="selection"
|
||||||
</rb-form-multi-select>
|
(ngModelChange)="loadSamples({}, $event, item.key)">
|
||||||
|
<span *rbFormMultiSelectOption="let item" class="load-first-page">{{item.label}}</span>
|
||||||
|
</rb-form-multi-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<rb-icon-button icon="reset" mode="secondary" (click)="resetPreferences()" class="reset-preferences">
|
<rb-icon-button icon="reset" mode="secondary" (click)="resetPreferences()" class="reset-preferences">
|
||||||
Reset to default
|
Reset to default
|
||||||
@ -59,7 +61,7 @@
|
|||||||
<ng-container *ngIf="isActiveKey[filter.field]">
|
<ng-container *ngIf="isActiveKey[filter.field]">
|
||||||
<rb-form-checkbox [name]="'filteractive-' + filter.field" [(ngModel)]="filter.active"></rb-form-checkbox>
|
<rb-form-checkbox [name]="'filteractive-' + filter.field" [(ngModel)]="filter.active"></rb-form-checkbox>
|
||||||
<rb-form-select [name]="'filtermode-' + filter.field" class="filtermode" [(ngModel)]="filter.mode"
|
<rb-form-select [name]="'filtermode-' + filter.field" class="filtermode" [(ngModel)]="filter.mode"
|
||||||
(ngModelChange)="updateFilterFields(filter.field)">
|
(ngModelChange)="updateFilterFields(filter.field)">
|
||||||
<option value="eq" title="field is equal to value">=</option>
|
<option value="eq" title="field is equal to value">=</option>
|
||||||
<option value="ne" title="field is not equal to value">≠</option>
|
<option value="ne" title="field is not equal to value">≠</option>
|
||||||
<option value="lt" title="field is lower than value"><</option>
|
<option value="lt" title="field is lower than value"><</option>
|
||||||
@ -73,29 +75,25 @@
|
|||||||
</rb-form-select>
|
</rb-form-select>
|
||||||
<div class="filter-inputs">
|
<div class="filter-inputs">
|
||||||
<rb-array-input [(ngModel)]="filter.values" [name]="'filter-' + filter.field"
|
<rb-array-input [(ngModel)]="filter.values" [name]="'filter-' + filter.field"
|
||||||
[pushTemplate]="!(filter.mode === 'in' || filter.mode === 'nin') ? null :''"
|
[pushTemplate]="!(filter.mode === 'in' || filter.mode === 'nin') ? null :''"
|
||||||
(ngModelChange)="updateFilterFields(filter.field)">
|
(ngModelChange)="updateFilterFields(filter.field)">
|
||||||
<ng-container *rbArrayInputItem="let item"
|
<ng-container *rbArrayInputItem="let item" [ngSwitch]="(filter.autocomplete.length ? 'autocomplete' : '') +
|
||||||
[ngSwitch]="(filter.autocomplete.length ? 'autocomplete' : '') +
|
|
||||||
(filter.field == 'added' ? 'date' : (filter.field == 'type' ? 'type' : ''))">
|
(filter.field == 'added' ? 'date' : (filter.field == 'type' ? 'type' : ''))">
|
||||||
<rb-form-date-input *ngSwitchCase="'date'" [rbArrayInputListener]="'filter-' + filter.field"
|
<rb-form-date-input *ngSwitchCase="'date'" [rbArrayInputListener]="'filter-' + filter.field"
|
||||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
[name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
|
||||||
[label]="filter.label" [(ngModel)]="item.value"
|
[(ngModel)]="item.value" [disabled]="filter.mode === 'null'"></rb-form-date-input>
|
||||||
[disabled]="filter.mode === 'null'"></rb-form-date-input>
|
|
||||||
<rb-form-input *ngSwitchCase="''" [rbArrayInputListener]="'filter-' + filter.field"
|
<rb-form-input *ngSwitchCase="''" [rbArrayInputListener]="'filter-' + filter.field"
|
||||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
[name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
|
||||||
[label]="filter.label" [(ngModel)]="item.value" [disabled]="filter.mode === 'null'">
|
[(ngModel)]="item.value" [disabled]="filter.mode === 'null'">
|
||||||
</rb-form-input>
|
</rb-form-input>
|
||||||
<rb-form-input *ngSwitchCase="'autocomplete'" [rbArrayInputListener]="'filter-' + filter.field"
|
<rb-form-input *ngSwitchCase="'autocomplete'" [rbArrayInputListener]="'filter-' + filter.field"
|
||||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
[name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
|
||||||
[label]="filter.label" [(ngModel)]="item.value"
|
[(ngModel)]="item.value" [rbDebounceTime]="0" (keydown)="preventDefault($event, 'Enter')"
|
||||||
[rbDebounceTime]="0" (keydown)="preventDefault($event, 'Enter')"
|
[rbFormInputAutocomplete]="autocomplete.bind(this, filter.autocomplete)"
|
||||||
[rbFormInputAutocomplete]="autocomplete.bind(this, filter.autocomplete)"
|
[disabled]="filter.mode === 'null'" ngModel></rb-form-input>
|
||||||
[disabled]="filter.mode === 'null'"
|
|
||||||
ngModel></rb-form-input>
|
|
||||||
<rb-form-select *ngSwitchCase="'type'" [rbArrayInputListener]="'filter-' + filter.field"
|
<rb-form-select *ngSwitchCase="'type'" [rbArrayInputListener]="'filter-' + filter.field"
|
||||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
[name]="'filter-' + filter.field + item.i" [index]="item.i" [label]="filter.label"
|
||||||
[label]="filter.label" [(ngModel)]="item.value">
|
[(ngModel)]="item.value">
|
||||||
<option value="as-delivered/raw">as-delivered/raw</option>
|
<option value="as-delivered/raw">as-delivered/raw</option>
|
||||||
<option value="processed">processed</option>
|
<option value="processed">processed</option>
|
||||||
</rb-form-select>
|
</rb-form-select>
|
||||||
@ -119,7 +117,6 @@
|
|||||||
</rb-accordion-body>
|
</rb-accordion-body>
|
||||||
</rb-accordion>
|
</rb-accordion>
|
||||||
|
|
||||||
|
|
||||||
<ng-container *ngTemplateOutlet="paging"></ng-container>
|
<ng-container *ngTemplateOutlet="paging"></ng-container>
|
||||||
|
|
||||||
<div class="samples-loading" *ngIf="loading">
|
<div class="samples-loading" *ngIf="loading">
|
||||||
@ -137,7 +134,7 @@
|
|||||||
<div class="link-dialog">
|
<div class="link-dialog">
|
||||||
<label for="jsonUrl">URL for JSON download</label>
|
<label for="jsonUrl">URL for JSON download</label>
|
||||||
<textarea class="linkmodal" id="jsonUrl" #linkarea [value]="sampleUrl({export: true, host: true})"
|
<textarea class="linkmodal" id="jsonUrl" #linkarea [value]="sampleUrl({export: true, host: true})"
|
||||||
(keydown)="preventDefault($event)"></textarea>
|
(keydown)="preventDefault($event)"></textarea>
|
||||||
<rb-form-checkbox class="space-right" name="download-spectra" [(ngModel)]="downloadSpectra">
|
<rb-form-checkbox class="space-right" name="download-spectra" [(ngModel)]="downloadSpectra">
|
||||||
add spectra
|
add spectra
|
||||||
</rb-form-checkbox>
|
</rb-form-checkbox>
|
||||||
@ -161,7 +158,7 @@
|
|||||||
|
|
||||||
<rb-table class="samples-table" scrollTop ellipsis>
|
<rb-table class="samples-table" scrollTop ellipsis>
|
||||||
<tr>
|
<tr>
|
||||||
<th *ngIf="login.isLevel.write">
|
<th *ngIf="login.isLevel.write">
|
||||||
<span class="rb-ic rb-ic-edit clickable" *ngIf="login.isLevel.dev" (click)="batchEdit()"></span>
|
<span class="rb-ic rb-ic-edit clickable" *ngIf="login.isLevel.dev" (click)="batchEdit()"></span>
|
||||||
<span class="rb-ic rb-ic-close clickable" *ngIf="sampleSelect === 1" (click)="sampleSelect = 0"></span>
|
<span class="rb-ic rb-ic-close clickable" *ngIf="sampleSelect === 1" (click)="sampleSelect = 0"></span>
|
||||||
</th>
|
</th>
|
||||||
@ -184,39 +181,22 @@
|
|||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr *ngFor="let sample of samples; index as i" class="clickable" (click)="sampleDetails(sample._id, sampleModal)">
|
<tr *ngFor="let sample of samples; index as i" class="clickable" (click)="sampleDetails(sample._id, sampleModal)">
|
||||||
<td *ngIf="login.isLevel.write">
|
<td *ngIf="login.isLevel.write">
|
||||||
<a [routerLink]="'/samples/edit/' + sample._id"
|
<a [routerLink]="'/samples/edit/' + sample._id" *ngIf="sample.status !== 'deleted' &&
|
||||||
*ngIf="sample.status !== 'deleted' &&
|
|
||||||
(login.isLevel.dev || (login.isLevel.write && sample.user_id === login.userId))">
|
(login.isLevel.dev || (login.isLevel.write && sample.user_id === login.userId))">
|
||||||
<span class="rb-ic rb-ic-edit clickable"></span>
|
<span class="rb-ic rb-ic-edit clickable"></span>
|
||||||
</a>
|
</a>
|
||||||
<span class="rb-ic rb-ic-undo clickable" *ngIf="sample.status === 'deleted' && login.isLevel.dev"
|
<span class="rb-ic rb-ic-undo clickable" *ngIf="sample.status === 'deleted' && login.isLevel.dev"
|
||||||
(click)="restoreSample(sample._id, restoreConfirm, $event)"></span>
|
(click)="restoreSample(sample._id, restoreConfirm, $event)"></span>
|
||||||
</td>
|
</td>
|
||||||
<td *ngIf="sampleSelect">
|
<td *ngIf="sampleSelect">
|
||||||
<rb-form-checkbox *ngIf="sample.status !== 'deleted'" [name]="'validate-' + i" (click)="stopPropagation($event)"
|
<rb-form-checkbox *ngIf="sample.status !== 'deleted'" [name]="'validate-' + i" (click)="stopPropagation($event)"
|
||||||
[(ngModel)]="sample.selected">
|
[(ngModel)]="sample.selected">
|
||||||
</rb-form-checkbox>
|
</rb-form-checkbox>
|
||||||
</td>
|
</td>
|
||||||
<td *ngIf="isActiveKey['number']">{{sample.number}}</td>
|
<td *ngFor="let item of activeKeys; index as j">
|
||||||
<td *ngIf="isActiveKey['material.numbers']">{{d.id.materials[sample.material_id].numbers}}</td>
|
{{data[i].data[j]}}
|
||||||
<td *ngIf="isActiveKey['material.name']">{{d.id.materials[sample.material_id].name}}</td>
|
|
||||||
<td *ngIf="isActiveKey['material.supplier']">{{d.id.materials[sample.material_id].supplier}}</td>
|
|
||||||
<td *ngIf="isActiveKey['material.group']">{{d.id.materials[sample.material_id].group}}</td>
|
|
||||||
<td *ngFor="let key of activeTemplateKeys.material">
|
|
||||||
{{d.id.materials[sample.material_id].properties[key[2]] | exists}}
|
|
||||||
</td>
|
</td>
|
||||||
<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.comment']">{{sample.notes | exists: 'comment'}}</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>
|
|
||||||
<td *ngIf="isActiveKey['added']">{{sample.added | date:'dd/MM/yy'}}</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</rb-table>
|
</rb-table>
|
||||||
|
|
||||||
@ -245,13 +225,34 @@
|
|||||||
<ng-template #sampleDetailsTemplate>
|
<ng-template #sampleDetailsTemplate>
|
||||||
<h3>{{sampleDetailsSample.number}}</h3>
|
<h3>{{sampleDetailsSample.number}}</h3>
|
||||||
<rb-table class="sample-details-table">
|
<rb-table class="sample-details-table">
|
||||||
<tr><th>Material</th><td>{{sampleDetailsSample.material.name}}</td></tr>
|
<tr>
|
||||||
<tr><th>Supplier</th><td>{{sampleDetailsSample.material.supplier}}</td></tr>
|
<th>Material</th>
|
||||||
<tr><th>Group</th><td>{{sampleDetailsSample.material.group}}</td></tr>
|
<td>{{sampleDetailsSample.material.name}}</td>
|
||||||
<tr><th>Type</th><td>{{sampleDetailsSample.type}}</td></tr>
|
</tr>
|
||||||
<tr><th>color</th><td>{{sampleDetailsSample.color}}</td></tr>
|
<tr>
|
||||||
<tr><th>Batch</th><td>{{sampleDetailsSample.batch}}</td></tr>
|
<th>Supplier</th>
|
||||||
<tr><th>Comment</th><td>{{sampleDetailsSample.notes.comment | exists}}</td></tr>
|
<td>{{sampleDetailsSample.material.supplier}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Group</th>
|
||||||
|
<td>{{sampleDetailsSample.material.group}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Type</th>
|
||||||
|
<td>{{sampleDetailsSample.type}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>color</th>
|
||||||
|
<td>{{sampleDetailsSample.color}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Batch</th>
|
||||||
|
<td>{{sampleDetailsSample.batch}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Comment</th>
|
||||||
|
<td>{{sampleDetailsSample.notes.comment | exists}}</td>
|
||||||
|
</tr>
|
||||||
<tr *ngFor="let customField of sampleDetailsSample.notes.custom_fields_entries">
|
<tr *ngFor="let customField of sampleDetailsSample.notes.custom_fields_entries">
|
||||||
<th>{{customField[0]}}</th>
|
<th>{{customField[0]}}</th>
|
||||||
<td>{{customField[1]}}</td>
|
<td>{{customField[1]}}</td>
|
||||||
@ -272,8 +273,14 @@
|
|||||||
<th>{{measurement.name}}</th>
|
<th>{{measurement.name}}</th>
|
||||||
<td>{{measurement.value}}</td>
|
<td>{{measurement.value}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr><th>User</th><td>{{sampleDetailsSample.user}}</td></tr>
|
<tr>
|
||||||
<tr><th>Status</th><td>{{sampleDetailsSample.status}}</td></tr>
|
<th>User</th>
|
||||||
|
<td>{{sampleDetailsSample.user}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Status</th>
|
||||||
|
<td>{{sampleDetailsSample.status}}</td>
|
||||||
|
</tr>
|
||||||
</rb-table>
|
</rb-table>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
@ -282,4 +289,4 @@
|
|||||||
<rb-dialog dialogTitle="Restore sample">
|
<rb-dialog dialogTitle="Restore sample">
|
||||||
Do you really want to restore this sample?
|
Do you really want to restore this sample?
|
||||||
</rb-dialog>
|
</rb-dialog>
|
||||||
</ng-template>
|
</ng-template>
|
@ -28,6 +28,10 @@ rb-table {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb-form-multi-select{
|
||||||
|
min-width: 9rem;
|
||||||
|
}
|
||||||
|
|
||||||
.status-selection {
|
.status-selection {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
@ -10,6 +10,7 @@ import { ModalService } from '@inst-iot/bosch-angular-ui-components';
|
|||||||
import { DataService } from '../services/data.service';
|
import { DataService } from '../services/data.service';
|
||||||
import { LocalStorageService } from 'angular-2-local-storage';
|
import { LocalStorageService } from 'angular-2-local-storage';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
import { KeyValue } from '@angular/common';
|
||||||
|
|
||||||
interface LoadSamplesOptions {
|
interface LoadSamplesOptions {
|
||||||
toPage?: number;
|
toPage?: number;
|
||||||
@ -24,6 +25,11 @@ interface KeyInterface {
|
|||||||
sortable: boolean;
|
sortable: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
id: string;
|
||||||
|
data: any[];
|
||||||
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-samples',
|
selector: 'app-samples',
|
||||||
templateUrl: './samples.component.html',
|
templateUrl: './samples.component.html',
|
||||||
@ -39,6 +45,7 @@ export class SamplesComponent implements OnInit {
|
|||||||
downloadCondition = false;
|
downloadCondition = false;
|
||||||
downloadFlatten = true;
|
downloadFlatten = true;
|
||||||
samples: SampleModel[] = []; // all samples to display
|
samples: SampleModel[] = []; // all samples to display
|
||||||
|
data: Data[] = [];
|
||||||
totalSamples = 0; // total number of samples
|
totalSamples = 0; // total number of samples
|
||||||
csvUrl = ''; // store url separate so it only has to be generated when clicking the download button
|
csvUrl = ''; // store url separate so it only has to be generated when clicking the download button
|
||||||
filters = {
|
filters = {
|
||||||
@ -65,27 +72,44 @@ export class SamplesComponent implements OnInit {
|
|||||||
page = 1; // current page
|
page = 1; // current page
|
||||||
pages = 1; // total number of pages
|
pages = 1; // total number of pages
|
||||||
loadSamplesQueue = []; // arguments of queued up loadSamples() calls
|
loadSamplesQueue = []; // arguments of queued up loadSamples() calls
|
||||||
keys: KeyInterface[] = [
|
materialKeys: KeyInterface[] = [
|
||||||
{ id: 'number', label: 'Number', active: true, sortable: true },
|
{ id: 'number', label: 'Number', active: true, sortable: true },
|
||||||
{ id: 'material.numbers', label: 'Material numbers', active: false, sortable: false },
|
{ 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.supplier', label: 'Supplier', active: false, sortable: true },
|
||||||
{ id: 'material.group', label: 'Material', active: true, sortable: true },
|
{ id: 'material.group', label: 'Material', active: true, sortable: true },
|
||||||
{ id: 'type', label: 'Type', active: true, sortable: true },
|
{ id: 'type', label: 'Type', active: true, sortable: true },
|
||||||
{ id: 'color', label: 'Color', active: false, sortable: true },
|
{ id: 'color', label: 'Color', active: false, sortable: true },
|
||||||
{ id: 'batch', label: 'Batch', active: true, 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 },
|
{ 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: 'status', label: 'Status', active: false, sortable: true },
|
||||||
{ id: 'added', label: 'Added', active: true, 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
|
isActiveKey: { [key: string]: boolean } = {}; // object to check if key is currently active
|
||||||
activeKeys: KeyInterface[] = []; // list of active keys
|
activeKeys: KeyInterface[] = []; // list of active keys
|
||||||
activeTemplateKeys = { material: [], condition: [], measurements: [] };
|
|
||||||
sampleDetailsSample: any = null; // sample for the sample details dialog
|
sampleDetailsSample: any = null; // sample for the sample details dialog
|
||||||
sampleSelect = 0; // modes: 0 - no selection, 1 - sample edit selection, 2 - validation selection
|
sampleSelect = 0; // modes: 0 - no selection, 1 - sample edit selection, 2 - validation selection
|
||||||
loading = 0; // number of loading instances
|
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(
|
constructor(
|
||||||
private api: ApiService,
|
private api: ApiService,
|
||||||
@ -96,8 +120,7 @@ export class SamplesComponent implements OnInit {
|
|||||||
private storage: LocalStorageService,
|
private storage: LocalStorageService,
|
||||||
private window: Window,
|
private window: Window,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {
|
) {}
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loading = 8;
|
this.loading = 8;
|
||||||
@ -123,7 +146,7 @@ export class SamplesComponent implements OnInit {
|
|||||||
this.d.load('userKey', onLoad);
|
this.d.load('userKey', onLoad);
|
||||||
this.d.load('conditionTemplates', onLoad);
|
this.d.load('conditionTemplates', onLoad);
|
||||||
this.loadTemplateKeys('material', 'type', onLoad);
|
this.loadTemplateKeys('material', 'type', onLoad);
|
||||||
this.loadTemplateKeys('condition', 'notes.comment', onLoad);
|
this.loadTemplateKeys('condition', 'notes', onLoad);
|
||||||
this.loadTemplateKeys('measurement', 'status', 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.categories[collection].splice(this.categories[collection].findIndex(e => e.id === insertBefore), 0, ...templateKeys);
|
||||||
this.keys = [...this.keys]; // complete overwrite array to invoke update in rb-multiselect
|
this.categories[collection] = [...this.categories[collection]]; // complete overwrite array to invoke update in rb-multiselect
|
||||||
this.loadPreferences();
|
this.loadPreferences();
|
||||||
f();
|
f();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// set toPage to null to reload first page, queues calls
|
// 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
|
if (event) { // adjust active keys
|
||||||
console.log(event);
|
this.categories[category].forEach(key => {
|
||||||
this.keys.forEach(key => {
|
|
||||||
if (event.hasOwnProperty(key.id)) {
|
if (event.hasOwnProperty(key.id)) {
|
||||||
key.active = event[key.id];
|
key.active = event[key.id];
|
||||||
}
|
}
|
||||||
@ -179,7 +201,7 @@ export class SamplesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
this.updateActiveKeys();
|
this.updateActiveKeys();
|
||||||
}
|
}
|
||||||
if(options.firstPage){
|
if (options.firstPage) {
|
||||||
this.storage.set('currentPage', 1);
|
this.storage.set('currentPage', 1);
|
||||||
}
|
}
|
||||||
this.loadSamplesQueue.push(options);
|
this.loadSamplesQueue.push(options);
|
||||||
@ -203,13 +225,14 @@ export class SamplesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
this.pages = Math.ceil(this.totalSamples / this.filters.pageSize);
|
this.pages = Math.ceil(this.totalSamples / this.filters.pageSize);
|
||||||
this.samples = sData as any;
|
this.samples = sData as any;
|
||||||
|
this.storeData();
|
||||||
this.loadSamplesQueue.shift();
|
this.loadSamplesQueue.shift();
|
||||||
if (this.loadSamplesQueue.length > 0) { // execute next queue item
|
if (this.loadSamplesQueue.length > 0) { // execute next queue item
|
||||||
this.sampleLoader(this.loadSamplesQueue[0]);
|
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);
|
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
|
if (options.export) { // append API key on export
|
||||||
query.push('key=' + this.d.d.userKey.key);
|
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)
|
query.push(...cloneDeep(this.filters.filters)
|
||||||
.map(e => {
|
.map(e => {
|
||||||
e.values = e.values.filter(el => el !== ''); // do not include empty values
|
e.values = e.values.filter(el => el !== ''); // do not include empty values
|
||||||
@ -314,14 +338,20 @@ export class SamplesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
storePreferences() {
|
storePreferences() {
|
||||||
|
let keys = [];
|
||||||
|
for (let category in this.categories) {
|
||||||
|
keys.push(...this.categories[category].map(e => pick(e, ['id', 'active'])));
|
||||||
|
}
|
||||||
|
|
||||||
const store = {
|
const store = {
|
||||||
filters: {
|
filters: {
|
||||||
...pick(this.filters, ['status', 'pageSize', 'toPage', 'sort']),
|
...pick(this.filters, ['status', 'pageSize', 'toPage', 'sort']),
|
||||||
filters: this.filters.filters.map(e => pick(e, ['field', 'active', 'mode', 'values']))
|
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.storage.set('samplesPreferences', store);
|
||||||
|
this.calcFieldSelectKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadPreferences() {
|
loadPreferences() {
|
||||||
@ -334,10 +364,13 @@ export class SamplesComponent implements OnInit {
|
|||||||
this.filters.filters[filterIndex] = { ...this.filters.filters[filterIndex], ...filter };
|
this.filters.filters[filterIndex] = { ...this.filters.filters[filterIndex], ...filter };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
store.keys.forEach(key => {
|
store.keys.forEach(key => {
|
||||||
const keyIndex = this.keys.findIndex(e => e.id === key.id);
|
for (let category in this.categories) {
|
||||||
if (keyIndex >= 0) {
|
const keyIndex = this.categories[category].findIndex(e => e.id === key.id);
|
||||||
this.keys[keyIndex].active = key.active;
|
if (keyIndex >= 0) {
|
||||||
|
this.categories[category][keyIndex].active = key.active;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -361,28 +394,23 @@ export class SamplesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateActiveKeys() { // array with all activeKeys
|
updateActiveKeys() { // array with all activeKeys
|
||||||
this.activeKeys = this.keys.filter(e => e.active);
|
this.activeKeys = [];
|
||||||
this.filters.filters.forEach(filter => { // disable filters of fields not displayed
|
for (let category in this.categories) {
|
||||||
if (!this.isActiveKey[filter.field]) {
|
this.activeKeys.push(...this.categories[category].filter(e => e.active));
|
||||||
filter.active = false;
|
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)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
calcFieldSelectKeys() {
|
calcFieldSelectKeys() {
|
||||||
this.keys.forEach(key => {
|
for (let category in this.categories) {
|
||||||
this.isActiveKey[key.id] = key.active;
|
this.categories[category].forEach(key => {
|
||||||
});
|
this.isActiveKey[key.id] = key.active;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sampleDetails(id: string, modal: TemplateRef<any>) { // show sample details
|
sampleDetails(id: string, modal: TemplateRef<any>) { // show sample details
|
||||||
@ -417,7 +445,7 @@ export class SamplesComponent implements OnInit {
|
|||||||
.push(...Object.entries(measurement.values).filter(e => e[0] !== 'dpt')
|
.push(...Object.entries(measurement.values).filter(e => e[0] !== 'dpt')
|
||||||
.map(e => ({ name: this.ucFirst(name) + ' ' + e[0], value: e[1] })));
|
.map(e => ({ name: this.ucFirst(name) + ' ' + e[0], value: e[1] })));
|
||||||
});
|
});
|
||||||
new Promise(resolve => {
|
new Promise<void>(resolve => {
|
||||||
if (data.notes.sample_references.length) { // load referenced samples if available
|
if (data.notes.sample_references.length) { // load referenced samples if available
|
||||||
let loadingCounter = data.notes.sample_references.length;
|
let loadingCounter = data.notes.sample_references.length;
|
||||||
this.sampleDetailsSample.notes.sample_references.forEach(reference => {
|
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
|
ucFirst(string) { // convert first character of string to uppercase
|
||||||
return string[0].toUpperCase() + string.slice(1);
|
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<number, string>, b: KeyValue<number, string>): number => {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user