Apply sample page fix
This commit is contained in:
parent
ad20fdb1bb
commit
5232c4d4e4
@ -1,3 +1,23 @@
|
||||
<app-login *ngIf="!login.isLoggedIn"></app-login>
|
||||
<div *ngIf="!login.isLoggedIn">
|
||||
<app-login></app-login>
|
||||
<img src="/assets/imgs/key-visual.png" alt="" class="key-visual">
|
||||
</div>
|
||||
|
||||
<img src="/assets/imgs/key-visual.png" alt="" class="key-visual">
|
||||
|
||||
<div *ngIf="login.isLoggedIn">
|
||||
<rb-form-multi-select name="groupSelect" idField="id" [items]="keys" [(ngModel)]="isActiveKey" label="Groups"
|
||||
class="selection" (ngModelChange)="updateGroups($event)">
|
||||
<span *rbFormMultiSelectOption="let key">{{key.id}}</span>
|
||||
</rb-form-multi-select>
|
||||
|
||||
<!--
|
||||
<rb-icon-button icon="forward-right" mode="primary" (click)="updateGroups()">
|
||||
Apply groups
|
||||
</rb-icon-button>
|
||||
-->
|
||||
|
||||
<div id="divChart">
|
||||
<canvas id="myChart">
|
||||
</canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {LoginService} from '../services/login.service';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import {Chart} from 'chart.js';
|
||||
|
||||
|
||||
|
||||
interface KeyInterface {
|
||||
id: string;
|
||||
count: number;
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
@ -8,11 +18,121 @@ import {LoginService} from '../services/login.service';
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
|
||||
keys: KeyInterface[] = [];
|
||||
isActiveKey: { [key: string]: boolean } = {}; // object to check if key is currently active
|
||||
myChart: Chart;
|
||||
|
||||
constructor(
|
||||
public login: LoginService
|
||||
public login: LoginService,
|
||||
public api: ApiService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
// fetch all available groups
|
||||
this.fetchData('/material/groups', data => this.createGroup(data));
|
||||
//this.initChart();
|
||||
console.log(this.login.username);
|
||||
}
|
||||
|
||||
// api access with callback
|
||||
async fetchData(URL: string, processor: any) {
|
||||
this.api.get(URL, (sData, err, headers) => {
|
||||
processor(sData);
|
||||
});
|
||||
}
|
||||
|
||||
// Fill interface with data
|
||||
createGroup(data: any) {
|
||||
let temp: KeyInterface[] = [];
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
temp.push({ id: data[i], count: 0, active: false });
|
||||
}
|
||||
this.keys = temp; // invoke update in rb-multiselect
|
||||
this.calcFieldSelectKeys();
|
||||
// fetch all samples populated with according group
|
||||
this.fetchData('/samples?status%5B%5D=validated&status=new&page-size=10&sort=_id-asc&fields%5B%5D=material.group', data => this.countSamples(data));
|
||||
}
|
||||
|
||||
// loop through samples and count
|
||||
countSamples(data: any) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
this.keys.forEach(key => {
|
||||
if (key.id === data[i].material.group) {
|
||||
key.count += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.initChart();
|
||||
}
|
||||
|
||||
// preset select
|
||||
calcFieldSelectKeys() {
|
||||
this.keys.forEach(key => {
|
||||
this.isActiveKey[key.id] = key.active;
|
||||
});
|
||||
}
|
||||
|
||||
// update keys based on select
|
||||
updateGroups(event: any) {
|
||||
this.keys.forEach(key => {
|
||||
if (event.hasOwnProperty(key.id)) {
|
||||
key.active = event[key.id];
|
||||
}
|
||||
});
|
||||
this.myChart.destroy();
|
||||
this.initChart();
|
||||
}
|
||||
|
||||
// get data for graph based on active keys
|
||||
async getData() {
|
||||
let nameList: string[] = [];
|
||||
let dataList: number[] = [];
|
||||
|
||||
this.keys.forEach(key => {
|
||||
if (key.active) {
|
||||
nameList.push(key.id);
|
||||
dataList.push(key.count);
|
||||
}
|
||||
})
|
||||
return { names: nameList, data: dataList };
|
||||
}
|
||||
|
||||
// draw graph
|
||||
async initChart() {
|
||||
const data = await this.getData();
|
||||
|
||||
const canvas = document.getElementById('myChart') as HTMLCanvasElement;
|
||||
const width = canvas.clientWidth;
|
||||
const height = canvas.clientHeight;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
var img = new Image(width, height);
|
||||
img.src = "/assets/imgs/supergraphic.svg";
|
||||
img.onload = () => {
|
||||
const fillPattern = ctx.createPattern(img, 'no-repeat');
|
||||
|
||||
this.myChart = new Chart("myChart", {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: data.names,
|
||||
datasets: [{
|
||||
label: 'Number of samples per group',
|
||||
data: data.data,
|
||||
backgroundColor: fillPattern,
|
||||
borderWidth: 2
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,22 @@
|
||||
import {Component, ElementRef, isDevMode, OnInit, TemplateRef, ViewChild} from '@angular/core';
|
||||
import {ApiService} from '../services/api.service';
|
||||
import {AutocompleteService} from '../services/autocomplete.service';
|
||||
import { Component, ElementRef, isDevMode, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { ApiService } from '../services/api.service';
|
||||
import { AutocompleteService } from '../services/autocomplete.service';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import pick from 'lodash/pick';
|
||||
import omit from 'lodash/omit';
|
||||
import {SampleModel} from '../models/sample.model';
|
||||
import {LoginService} from '../services/login.service';
|
||||
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 { SampleModel } from '../models/sample.model';
|
||||
import { LoginService } from '../services/login.service';
|
||||
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';
|
||||
|
||||
interface LoadSamplesOptions {
|
||||
toPage?: number;
|
||||
event?: Event;
|
||||
firstPage?: boolean;
|
||||
}
|
||||
|
||||
interface KeyInterface {
|
||||
id: string;
|
||||
label: string;
|
||||
@ -43,46 +42,46 @@ export class SamplesComponent implements OnInit {
|
||||
totalSamples = 0; // total number of samples
|
||||
csvUrl = ''; // store url separate so it only has to be generated when clicking the download button
|
||||
filters = {
|
||||
status: {new: true, validated: true, deleted: false},
|
||||
status: { new: true, validated: true, deleted: false },
|
||||
pageSize: 25,
|
||||
toPage: 0,
|
||||
sort: 'added-asc',
|
||||
no: {condition: false, measurements: false},
|
||||
no: { condition: false, measurements: false },
|
||||
filters: [
|
||||
{field: 'number', label: 'Number', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'material.name', label: 'Product name', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'material.supplier', label: 'Supplier', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'material.group', label: 'Material', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'material.glass_fiber', label: 'GF', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'material.carbon_fiber', label: 'CF', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'material.mineral', label: 'M', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'type', label: 'Type', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'color', label: 'Color', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'batch', label: 'Batch', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'notes.comment', label: 'Comment', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'added', label: 'Added', active: false, autocomplete: [], mode: 'eq', values: ['']}
|
||||
{ field: 'number', label: 'Number', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'material.name', label: 'Product name', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'material.supplier', label: 'Supplier', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'material.group', label: 'Material', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'material.glass_fiber', label: 'GF', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'material.carbon_fiber', label: 'CF', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'material.mineral', label: 'M', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'type', label: 'Type', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'color', label: 'Color', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'batch', label: 'Batch', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'notes.comment', label: 'Comment', active: false, autocomplete: [], mode: 'eq', values: [''] },
|
||||
{ field: 'added', label: 'Added', active: false, autocomplete: [], mode: 'eq', values: [''] }
|
||||
]
|
||||
};
|
||||
page = 1; // current page
|
||||
pages = 1; // total number of pages
|
||||
loadSamplesQueue = []; // arguments of queued up loadSamples() calls
|
||||
keys: 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', label: 'Notes', active: false, sortable: false},
|
||||
{id: 'status', label: 'Status', active: false, sortable: true},
|
||||
{id: 'added', label: 'Added', active: true, sortable: true}
|
||||
{ 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', label: 'Notes', active: false, sortable: false },
|
||||
{ id: 'status', label: 'Status', active: false, sortable: true },
|
||||
{ id: 'added', label: 'Added', active: true, sortable: true }
|
||||
];
|
||||
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
|
||||
activeTemplateKeys = {material: [], condition: [], measurements: []};
|
||||
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
|
||||
@ -126,10 +125,6 @@ export class SamplesComponent implements OnInit {
|
||||
this.loadTemplateKeys('material', 'type', onLoad);
|
||||
this.loadTemplateKeys('condition', 'notes.comment', onLoad);
|
||||
this.loadTemplateKeys('measurement', 'status', onLoad);
|
||||
|
||||
if("currentPage" in localStorage){
|
||||
this.page = Number(localStorage.getItem("currentPage"));
|
||||
}
|
||||
}
|
||||
|
||||
loadTemplateKeys(collection, insertBefore, f) {
|
||||
@ -172,6 +167,7 @@ export class SamplesComponent implements OnInit {
|
||||
// set toPage to null to reload first page, queues calls
|
||||
loadSamples(options: LoadSamplesOptions = {}, event = null) {
|
||||
if (event) { // adjust active keys
|
||||
console.log(event);
|
||||
this.keys.forEach(key => {
|
||||
if (event.hasOwnProperty(key.id)) {
|
||||
key.active = event[key.id];
|
||||
@ -183,6 +179,9 @@ export class SamplesComponent implements OnInit {
|
||||
}
|
||||
this.updateActiveKeys();
|
||||
}
|
||||
if(options.firstPage){
|
||||
this.storage.set('currentPage', 1);
|
||||
}
|
||||
this.loadSamplesQueue.push(options);
|
||||
if (this.loadSamplesQueue.length <= 1) { // nothing queued up
|
||||
this.sampleLoader(this.loadSamplesQueue[0]);
|
||||
@ -191,9 +190,9 @@ export class SamplesComponent implements OnInit {
|
||||
}
|
||||
|
||||
private sampleLoader(options: LoadSamplesOptions) { // actual loading of the sample, do not call directly
|
||||
this.loading ++;
|
||||
this.api.get(this.sampleUrl({paging: true, pagingOptions: options}), (sData, err, headers) => {
|
||||
this.loading --;
|
||||
this.loading++;
|
||||
this.api.get(this.sampleUrl({ paging: true, pagingOptions: options }), (sData, err, headers) => {
|
||||
this.loading--;
|
||||
if (err) { // remove stored options on error to avoid loop
|
||||
this.storage.remove('samplesPreferences');
|
||||
this.api.requestError(err);
|
||||
@ -210,6 +209,9 @@ export class SamplesComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
});
|
||||
if(this.storage.get('currentPage') !== this.page){
|
||||
this.loadPage(Number(this.storage.get('currentPage')) - this.page);
|
||||
}
|
||||
}
|
||||
|
||||
sampleUrl(options: {
|
||||
@ -270,17 +272,17 @@ export class SamplesComponent implements OnInit {
|
||||
.map(e => 'filters[]=' + encodeURIComponent(JSON.stringify(pick(e, ['mode', 'field', 'values']))))
|
||||
);
|
||||
if (this.filters.no.condition) {
|
||||
query.push('filters[]=' + encodeURIComponent( JSON.stringify({mode: 'eq', field: 'condition', values: [{}]})));
|
||||
query.push('filters[]=' + encodeURIComponent(JSON.stringify({ mode: 'eq', field: 'condition', values: [{}] })));
|
||||
}
|
||||
if (this.filters.no.measurements) {
|
||||
query.push('filters[]=' +
|
||||
encodeURIComponent( JSON.stringify( {mode: 'eq', field: 'measurements', values: [null]})));
|
||||
encodeURIComponent(JSON.stringify({ mode: 'eq', field: 'measurements', values: [null] })));
|
||||
}
|
||||
if (!options.export) {
|
||||
additionalTableKeys.forEach(key => {
|
||||
if (query.indexOf('fields[]=' + key) < 0) { // add key if not already added
|
||||
query.push('fields[]=' + key);
|
||||
}
|
||||
if (query.indexOf('fields[]=' + key) < 0) { // add key if not already added
|
||||
query.push('fields[]=' + key);
|
||||
}
|
||||
});
|
||||
}
|
||||
else { // export options
|
||||
@ -303,12 +305,12 @@ export class SamplesComponent implements OnInit {
|
||||
}
|
||||
|
||||
loadPage(delta) {
|
||||
if (!/[0-9]+/.test(delta) || this.page + delta < 1 || this.page + delta > this.pages) { // invalid delta
|
||||
if (!/[0-9]+/.test(delta) || this.page + delta < 1) { // invalid delta
|
||||
return;
|
||||
}
|
||||
this.page += delta;
|
||||
localStorage.setItem("currentPage", this.page.toString());
|
||||
this.loadSamples({toPage: delta});
|
||||
this.storage.set('currentPage', this.page);
|
||||
this.loadSamples({ toPage: delta });
|
||||
}
|
||||
|
||||
storePreferences() {
|
||||
@ -325,11 +327,11 @@ export class SamplesComponent implements OnInit {
|
||||
loadPreferences() {
|
||||
const store: any = this.storage.get('samplesPreferences');
|
||||
if (store) {
|
||||
this.filters = {...this.filters, ...pick(store.filters, ['status', 'pageSize', 'toPage', 'sort'])};
|
||||
this.filters = { ...this.filters, ...pick(store.filters, ['status', 'pageSize', 'toPage', 'sort']) };
|
||||
store.filters.filters.forEach(filter => {
|
||||
const filterIndex = this.filters.filters.findIndex(e => e.field === filter.field);
|
||||
if (filterIndex >= 0) {
|
||||
this.filters.filters[filterIndex] = {...this.filters.filters[filterIndex], ...filter};
|
||||
this.filters.filters[filterIndex] = { ...this.filters.filters[filterIndex], ...filter };
|
||||
}
|
||||
});
|
||||
store.keys.forEach(key => {
|
||||
@ -355,7 +357,7 @@ export class SamplesComponent implements OnInit {
|
||||
|
||||
setSort(string) {
|
||||
this.filters.sort = string;
|
||||
this.loadSamples({firstPage: true});
|
||||
this.loadSamples({ firstPage: true });
|
||||
}
|
||||
|
||||
updateActiveKeys() { // array with all activeKeys
|
||||
@ -397,12 +399,12 @@ export class SamplesComponent implements OnInit {
|
||||
if (Object.keys(data.condition).length) { // convert condition
|
||||
this.sampleDetailsSample.condition_entries =
|
||||
Object.entries(omit(this.sampleDetailsSample.condition, ['condition_template']))
|
||||
.map(e => {
|
||||
e[0] = `${this.ucFirst(
|
||||
this.d.id.conditionTemplates[this.sampleDetailsSample.condition.condition_template].name
|
||||
)} ${e[0]}`;
|
||||
return e;
|
||||
});
|
||||
.map(e => {
|
||||
e[0] = `${this.ucFirst(
|
||||
this.d.id.conditionTemplates[this.sampleDetailsSample.condition.condition_template].name
|
||||
)} ${e[0]}`;
|
||||
return e;
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.sampleDetailsSample.condition_entries = [];
|
||||
@ -413,7 +415,7 @@ export class SamplesComponent implements OnInit {
|
||||
const name = this.d.id.measurementTemplates[measurement.measurement_template].name;
|
||||
this.sampleDetailsSample.measurement_entries
|
||||
.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 => {
|
||||
if (data.notes.sample_references.length) { // load referenced samples if available
|
||||
@ -421,7 +423,7 @@ export class SamplesComponent implements OnInit {
|
||||
this.sampleDetailsSample.notes.sample_references.forEach(reference => {
|
||||
this.api.get<SampleModel>('/sample/' + reference.sample_id, rData => {
|
||||
reference.number = rData.number;
|
||||
loadingCounter --;
|
||||
loadingCounter--;
|
||||
if (!loadingCounter) {
|
||||
resolve();
|
||||
}
|
||||
@ -432,7 +434,7 @@ export class SamplesComponent implements OnInit {
|
||||
resolve();
|
||||
}
|
||||
}).then(() => {
|
||||
this.modalService.open(modal).then(() => {});
|
||||
this.modalService.open(modal).then(() => { });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user