sorting implemented

This commit is contained in:
VLE2FE 2020-06-26 11:09:59 +02:00
parent 09598c4ba7
commit 81621e77cc
5 changed files with 216 additions and 28 deletions

View File

@ -13,7 +13,7 @@ export class SampleModel extends BaseModel {
condition: {condition_template: string, [prop: string]: string} | {} = {}; condition: {condition_template: string, [prop: string]: string} | {} = {};
material_id: IdModel = null; material_id: IdModel = null;
material: MaterialModel; material: MaterialModel;
measurements: MeasurementModel[]; measurements: MeasurementModel[] = [];
note_id: IdModel = null; note_id: IdModel = null;
user_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: {}}; notes: {comment: string, sample_references: {sample_id: IdModel, relation: string}[], custom_fields: {[prop: string]: string}} = {comment: '', sample_references: [], custom_fields: {}};

View File

@ -19,6 +19,9 @@ import {MeasurementModel} from '../models/measurement.model';
// TODO: confirmation for new group/supplier // TODO: confirmation for new group/supplier
// TODO: DPT preview // TODO: DPT preview
// TODO: work on better recognition for file input // 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

View File

@ -6,48 +6,77 @@
</div> </div>
<rb-accordion> <rb-accordion>
<rb-accordion-title><span class="rb-ic rb-ic-filter"></span>&nbsp; Filter</rb-accordion-title> <rb-accordion-title [open]="true"><span class="rb-ic rb-ic-filter"></span>&nbsp; Filter</rb-accordion-title>
<rb-accordion-body> <rb-accordion-body>
<form> <form (change)="loadSamples({event: $event})">
<rb-form-select name="statusSelect" label="Status" [(ngModel)]="filters.status"> <div class="status-selection">
<option value="validated">validated</option> <label class="label">Status</label>
<option value="new">new</option> <rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated" [disabled]="!filters.status.new">
<option value="all">all</option> 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> </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> </form>
</rb-accordion-body> </rb-accordion-body>
</rb-accordion> </rb-accordion>
<ng-container *ngTemplateOutlet="paging"></ng-container>
<rb-table> <rb-table>
<tr> <tr>
<th>Number</th> <th *ngFor="let key of activeKeys">
<th>Material number</th> <div class="sort-header">
<th>Material name</th> <span>{{key.name}}</span>
<th>Supplier</th> <span class="rb-ic rb-ic-up" [ngClass]="{'sort-active-desc': filters.sort === key.key + '-' + 'desc'}" (click)="setSort(key.key + '-' + 'desc')"></span>
<th>Material</th> <span class="rb-ic rb-ic-down" [ngClass]="{'sort-active-asc': filters.sort === key.key + '-' + 'asc'}" (click)="setSort(key.key + '-' + 'asc')"></span>
<th>GF</th> </div>
<th>CF</th> </th>
<th>M</th>
<th>type</th>
<th>Color</th>
<th>Batch</th>
<th></th> <th></th>
</tr> </tr>
<tr *ngFor="let sample of samples"> <tr *ngFor="let sample of samples">
<td>{{sample.number}}</td> <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].name}}</td>
<td>{{materials[sample.material_id].supplier}}</td> <td>{{materials[sample.material_id].supplier}}</td>
<td>{{materials[sample.material_id].group}}</td> <!-- <td>{{materials[sample.material_id].group}}</td>-->
<td>{{materials[sample.material_id].glass_fiber}}</td> <!-- <td>{{materials[sample.material_id].glass_fiber}}</td>-->
<td>{{materials[sample.material_id].carbon_fiber}}</td> <!-- <td>{{materials[sample.material_id].carbon_fiber}}</td>-->
<td>{{materials[sample.material_id].mineral}}</td> <!-- <td>{{materials[sample.material_id].mineral}}</td>-->
<td>{{sample.type}}</td> <td>{{sample.type}}</td>
<td>{{sample.color}}</td> <td>{{sample.color}}</td>
<td>{{sample.batch}}</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> <td><a [routerLink]="'/samples/edit/' + sample._id"><span class="rb-ic rb-ic-edit"></span></a></td>
</tr> </tr>
</rb-table> </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>

View File

@ -22,3 +22,83 @@
color: #000; 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;
}

View File

@ -1,16 +1,46 @@
import { Component, OnInit } from '@angular/core'; import {Component, OnInit, ViewChild} from '@angular/core';
import {ApiService} from '../services/api.service'; import {ApiService} from '../services/api.service';
interface LoadSamplesOptions {
toPage?: number;
event?: Event;
firstPage?: boolean;
}
@Component({ @Component({
selector: 'app-samples', selector: 'app-samples',
templateUrl: './samples.component.html', templateUrl: './samples.component.html',
styleUrls: ['./samples.component.scss'] styleUrls: ['./samples.component.scss']
}) })
// TODO: always show first page on sort change
export class SamplesComponent implements OnInit { // TODO: implement paging export class SamplesComponent implements OnInit { // TODO: implement paging
@ViewChild('pageSizeSelection') pageSizeSelection: HTMLElement;
materials = {}; materials = {};
samples = []; 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( constructor(
private api: ApiService private api: ApiService
@ -24,15 +54,61 @@ export class SamplesComponent implements OnInit { // TODO: implement paging
}); });
this.loadSamples(); this.loadSamples();
}); });
this.api.get('/samples/count', (data: {count: number}) => {
this.totalSamples = data.count;
});
} }
loadSamples() { loadSamples(options: LoadSamplesOptions = {}) { // set toPage to null to reload first page, queues calls
this.api.get(`/samples?status=${this.filters.status}`, sData => { 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 = sData as any;
this.samples.forEach(sample => { this.samples.forEach(sample => {
sample.material_number = this.materials[sample.material_id].numbers.find(e => sample.color === e.color).number; 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});
}
} }