sorting implemented
This commit is contained in:
parent
09598c4ba7
commit
81621e77cc
@ -13,7 +13,7 @@ export class SampleModel extends BaseModel {
|
||||
condition: {condition_template: string, [prop: string]: string} | {} = {};
|
||||
material_id: IdModel = null;
|
||||
material: MaterialModel;
|
||||
measurements: MeasurementModel[];
|
||||
measurements: MeasurementModel[] = [];
|
||||
note_id: IdModel = null;
|
||||
user_id: IdModel = null;
|
||||
notes: {comment: string, sample_references: {sample_id: IdModel, relation: string}[], custom_fields: {[prop: string]: string}} = {comment: '', sample_references: [], custom_fields: {}};
|
||||
|
@ -19,6 +19,9 @@ import {MeasurementModel} from '../models/measurement.model';
|
||||
// TODO: confirmation for new group/supplier
|
||||
// TODO: DPT preview
|
||||
// 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, drag and drop
|
||||
// TODO: multiple samples for base data, extend multiple measurements, conditions
|
||||
|
||||
|
||||
|
||||
|
@ -6,48 +6,77 @@
|
||||
</div>
|
||||
|
||||
<rb-accordion>
|
||||
<rb-accordion-title><span class="rb-ic rb-ic-filter"></span> Filter</rb-accordion-title>
|
||||
<rb-accordion-title [open]="true"><span class="rb-ic rb-ic-filter"></span> Filter</rb-accordion-title>
|
||||
<rb-accordion-body>
|
||||
<form>
|
||||
<rb-form-select name="statusSelect" label="Status" [(ngModel)]="filters.status">
|
||||
<option value="validated">validated</option>
|
||||
<option value="new">new</option>
|
||||
<option value="all">all</option>
|
||||
<form (change)="loadSamples({event: $event})">
|
||||
<div class="status-selection">
|
||||
<label class="label">Status</label>
|
||||
<rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated" [disabled]="!filters.status.new">
|
||||
validated
|
||||
</rb-form-checkbox>
|
||||
<rb-form-checkbox name="status-new" [(ngModel)]="filters.status.new" [disabled]="!filters.status.validated">
|
||||
new
|
||||
</rb-form-checkbox>
|
||||
</div>
|
||||
<rb-form-select name="pageSizeSelection" label="page size" [(ngModel)]="filters.pageSize" class="page-size-selection" #pageSizeSelection>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
<option value="250">250</option>
|
||||
<option value="500">500</option>
|
||||
</rb-form-select>
|
||||
|
||||
<button class="rb-btn rb-secondary" (click)="loadSamples()">Apply filters</button>
|
||||
<!-- <button class="rb-btn rb-secondary" (click)="loadSamples()">Apply filters</button>-->
|
||||
</form>
|
||||
</rb-accordion-body>
|
||||
</rb-accordion>
|
||||
|
||||
<ng-container *ngTemplateOutlet="paging"></ng-container>
|
||||
|
||||
<rb-table>
|
||||
<tr>
|
||||
<th>Number</th>
|
||||
<th>Material number</th>
|
||||
<th>Material name</th>
|
||||
<th>Supplier</th>
|
||||
<th>Material</th>
|
||||
<th>GF</th>
|
||||
<th>CF</th>
|
||||
<th>M</th>
|
||||
<th>type</th>
|
||||
<th>Color</th>
|
||||
<th>Batch</th>
|
||||
<th *ngFor="let key of activeKeys">
|
||||
<div class="sort-header">
|
||||
<span>{{key.name}}</span>
|
||||
<span class="rb-ic rb-ic-up" [ngClass]="{'sort-active-desc': filters.sort === key.key + '-' + 'desc'}" (click)="setSort(key.key + '-' + 'desc')"></span>
|
||||
<span class="rb-ic rb-ic-down" [ngClass]="{'sort-active-asc': filters.sort === key.key + '-' + 'asc'}" (click)="setSort(key.key + '-' + 'asc')"></span>
|
||||
</div>
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
<tr *ngFor="let sample of samples">
|
||||
<td>{{sample.number}}</td>
|
||||
<td>{{sample.material_number}}</td>
|
||||
<!-- <td>{{sample.material_number}}</td>-->
|
||||
<td>{{materials[sample.material_id].name}}</td>
|
||||
<td>{{materials[sample.material_id].supplier}}</td>
|
||||
<td>{{materials[sample.material_id].group}}</td>
|
||||
<td>{{materials[sample.material_id].glass_fiber}}</td>
|
||||
<td>{{materials[sample.material_id].carbon_fiber}}</td>
|
||||
<td>{{materials[sample.material_id].mineral}}</td>
|
||||
<!-- <td>{{materials[sample.material_id].group}}</td>-->
|
||||
<!-- <td>{{materials[sample.material_id].glass_fiber}}</td>-->
|
||||
<!-- <td>{{materials[sample.material_id].carbon_fiber}}</td>-->
|
||||
<!-- <td>{{materials[sample.material_id].mineral}}</td>-->
|
||||
<td>{{sample.type}}</td>
|
||||
<td>{{sample.color}}</td>
|
||||
<td>{{sample.batch}}</td>
|
||||
<td>{{sample.added | date}}</td>
|
||||
<td><a [routerLink]="'/samples/edit/' + sample._id"><span class="rb-ic rb-ic-edit"></span></a></td>
|
||||
</tr>
|
||||
</rb-table>
|
||||
|
||||
<ng-container *ngTemplateOutlet="paging"></ng-container>
|
||||
|
||||
<ng-template #paging>
|
||||
<div class="paging">
|
||||
<button class="rb-btn rb-link" type="button" (click)="loadPage(-1)" [disabled]="page === 1">
|
||||
<span class="rb-ic rb-ic-back-left"></span>
|
||||
</button>
|
||||
<rb-form-input label="page" (change)="loadPage({toPage: $event.target.value - page})" [ngModel]="page"></rb-form-input>
|
||||
<span>
|
||||
of {{pages()}}
|
||||
</span>
|
||||
<button class="rb-btn rb-link" type="button" (click)="loadPage(1)" [disabled]="page >= pages()">
|
||||
<span class="rb-ic rb-ic-forward-right"></span>
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
|
@ -22,3 +22,83 @@
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.status-selection {
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
font-weight: 700;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
rb-form-checkbox {
|
||||
float: left;
|
||||
margin-right: 10px;
|
||||
margin-top: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
.page-size-selection {
|
||||
max-width: 125px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.paging {
|
||||
rb-form-input {
|
||||
max-width: 50px;
|
||||
}
|
||||
|
||||
> * {
|
||||
float: left;
|
||||
}
|
||||
|
||||
> button {
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
> span {
|
||||
margin-top: 20px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.sort-header {
|
||||
display: inline-grid;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-column-gap: 5px;
|
||||
width: 100%;
|
||||
|
||||
:first-child {
|
||||
grid-row: span 2;
|
||||
}
|
||||
|
||||
:nth-child(2) {
|
||||
margin-bottom: -3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:nth-child(3) {
|
||||
margin-top: -3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.sort-active-asc {
|
||||
color: $color-bosch-dark-blue;
|
||||
background: linear-gradient(to bottom, #FFF 17%, $color-bosch-light-blue-w50 17%);;
|
||||
border-radius: 0 0 8px 8px;
|
||||
}
|
||||
|
||||
.sort-active-desc {
|
||||
color: $color-bosch-dark-blue;
|
||||
background: linear-gradient(to top, #FFF 17%, $color-bosch-light-blue-w50 17%);;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
@ -1,16 +1,46 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {ApiService} from '../services/api.service';
|
||||
|
||||
|
||||
|
||||
interface LoadSamplesOptions {
|
||||
toPage?: number;
|
||||
event?: Event;
|
||||
firstPage?: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-samples',
|
||||
templateUrl: './samples.component.html',
|
||||
styleUrls: ['./samples.component.scss']
|
||||
})
|
||||
|
||||
// TODO: always show first page on sort change
|
||||
|
||||
export class SamplesComponent implements OnInit { // TODO: implement paging
|
||||
|
||||
@ViewChild('pageSizeSelection') pageSizeSelection: HTMLElement;
|
||||
|
||||
materials = {};
|
||||
samples = [];
|
||||
filters = {status: 'validated'};
|
||||
totalSamples = 0; // total number of samples
|
||||
filters = {status: {new: true, validated: true}, pageSize: 25, toPage: 0, sort: 'added-asc'};
|
||||
page = 1;
|
||||
loadSamplesQueue = []; // arguments of queued up loadSamples() calls
|
||||
activeKeys = [
|
||||
{name: 'Number', key: 'number'},
|
||||
// {name: 'Material number', key: ''},
|
||||
{name: 'Material name', key: ''},
|
||||
{name: 'Supplier', key: ''},
|
||||
// {name: 'Material', key: ''},
|
||||
// {name: 'GF', key: ''},
|
||||
// {name: 'CF', key: ''},
|
||||
// {name: 'M', key: ''},
|
||||
{name: 'Type', key: 'type'},
|
||||
{name: 'Color', key: 'color'},
|
||||
{name: 'Batch', key: 'batch'},
|
||||
{name: 'Added', key: 'added'},
|
||||
];
|
||||
|
||||
constructor(
|
||||
private api: ApiService
|
||||
@ -24,15 +54,61 @@ export class SamplesComponent implements OnInit { // TODO: implement paging
|
||||
});
|
||||
this.loadSamples();
|
||||
});
|
||||
this.api.get('/samples/count', (data: {count: number}) => {
|
||||
this.totalSamples = data.count;
|
||||
});
|
||||
}
|
||||
|
||||
loadSamples() {
|
||||
this.api.get(`/samples?status=${this.filters.status}`, sData => {
|
||||
loadSamples(options: LoadSamplesOptions = {}) { // set toPage to null to reload first page, queues calls
|
||||
this.loadSamplesQueue.push(options);
|
||||
if (this.loadSamplesQueue.length <= 1) { // nothing queued up
|
||||
this.sampleLoader(this.loadSamplesQueue[0]);
|
||||
}
|
||||
}
|
||||
|
||||
private sampleLoader(options: LoadSamplesOptions) { // actual loading of the sample, do not call directly
|
||||
const query: string[] = [];
|
||||
query.push('status=' + (this.filters.status.new && this.filters.status.validated ? 'all' : (this.filters.status.new ? 'new' : 'validated')));
|
||||
if (this.samples[0]) { // do not include from-id when page size was changed
|
||||
if (!options.firstPage && (!options.event || ((options.event.target as HTMLElement).id.indexOf(this.pageSizeSelection.id) < 0))) {
|
||||
query.push('from-id=' + this.samples[0]._id);
|
||||
}
|
||||
else {
|
||||
this.page = 1;
|
||||
}
|
||||
}
|
||||
if (options.toPage) {
|
||||
query.push('to-page=' + options.toPage);
|
||||
}
|
||||
query.push('page-size=' + this.filters.pageSize);
|
||||
query.push('sort=' + this.filters.sort);
|
||||
|
||||
this.api.get('/samples?' + query.join('&'), sData => {
|
||||
this.samples = sData as any;
|
||||
this.samples.forEach(sample => {
|
||||
sample.material_number = this.materials[sample.material_id].numbers.find(e => sample.color === e.color).number;
|
||||
});
|
||||
this.loadSamplesQueue.shift();
|
||||
if (this.loadSamplesQueue.length > 0) { // execute next queue item
|
||||
this.sampleLoader(this.loadSamplesQueue[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadPage(delta) {
|
||||
if (!/[0-9]+/.test(delta) || (this.page <= 1 && delta < 0)) { // invalid delta
|
||||
return;
|
||||
}
|
||||
this.page += delta;
|
||||
this.loadSamples({toPage: delta});
|
||||
}
|
||||
|
||||
pages() {
|
||||
return Math.ceil(this.totalSamples / this.filters.pageSize);
|
||||
}
|
||||
|
||||
setSort(string) {
|
||||
this.filters.sort = string;
|
||||
this.loadSamples({firstPage: true});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user