implemented icon buttons, array input, reformatting, minor sample component improvements
This commit is contained in:
@ -2,7 +2,7 @@
|
||||
<div class="header-addnew">
|
||||
<h2>Samples</h2>
|
||||
<a routerLink="/samples/new">
|
||||
<button class="rb-btn rb-primary"><span class="rb-ic rb-ic-add"></span> New sample</button>
|
||||
<rb-icon-button icon="add" mode="primary">New sample</rb-icon-button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@ -12,14 +12,17 @@
|
||||
<form class="filters">
|
||||
<div class="status-selection">
|
||||
<label class="label">Status</label>
|
||||
<rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated" [disabled]="!filters.status.new" (ngModelChange)="loadSamples({firstPage: true})">
|
||||
<rb-form-checkbox name="status-validated" [(ngModel)]="filters.status.validated"
|
||||
[disabled]="!filters.status.new" (ngModelChange)="loadSamples({firstPage: true})">
|
||||
validated
|
||||
</rb-form-checkbox>
|
||||
<rb-form-checkbox name="status-new" [(ngModel)]="filters.status.new" [disabled]="!filters.status.validated" (ngModelChange)="loadSamples({firstPage: true})">
|
||||
<rb-form-checkbox name="status-new" [(ngModel)]="filters.status.new" [disabled]="!filters.status.validated"
|
||||
(ngModelChange)="loadSamples({firstPage: true})">
|
||||
new
|
||||
</rb-form-checkbox>
|
||||
</div>
|
||||
<rb-form-select name="pageSizeSelection" label="page size" [(ngModel)]="filters.pageSize" class="selection" (ngModelChange)="loadSamples({firstPage: true})" #pageSizeSelection>
|
||||
<rb-form-select name="pageSizeSelection" label="page size" [(ngModel)]="filters.pageSize" class="selection"
|
||||
(ngModelChange)="loadSamples({firstPage: true})" #pageSizeSelection>
|
||||
<option value="3">3</option>
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
@ -29,15 +32,18 @@
|
||||
<option value="500">500</option>
|
||||
</rb-form-select>
|
||||
|
||||
<rb-form-multi-select name="fieldSelect" idField="id" [items]="keys" [(ngModel)]="isActiveKey" label="Fields" class="selection" (ngModelChange)="loadSamples({}, $event)">
|
||||
<rb-form-multi-select name="fieldSelect" idField="id" [items]="keys" [(ngModel)]="isActiveKey" label="Fields"
|
||||
class="selection" (ngModelChange)="loadSamples({}, $event)">
|
||||
<span *rbFormMultiSelectOption="let item" class="load-first-page">{{item.label}}</span>
|
||||
</rb-form-multi-select>
|
||||
|
||||
<div class="fieldfilters">
|
||||
<div *ngFor="let filter of filters.filters">
|
||||
<ng-container *ngIf="isActiveKey[filter.field]">
|
||||
<rb-form-checkbox [name]="'filteractive-' + filter.field" [(ngModel)]="filter.active" (ngModelChange)="loadSamples({firstPage: true})"></rb-form-checkbox>
|
||||
<rb-form-select [name]="'filtermode-' + filter.field" class="filtermode" [(ngModel)]="filter.mode" (ngModelChange)="updateFilterFields(filter.field)">
|
||||
<rb-form-checkbox [name]="'filteractive-' + filter.field" [(ngModel)]="filter.active"
|
||||
(ngModelChange)="loadSamples({firstPage: true})"></rb-form-checkbox>
|
||||
<rb-form-select [name]="'filtermode-' + filter.field" class="filtermode" [(ngModel)]="filter.mode"
|
||||
(ngModelChange)="updateFilterFields(filter.field)">
|
||||
<option value="eq" title="field is 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>
|
||||
@ -49,13 +55,26 @@
|
||||
<option value="nin" title="field is not one of the values">∉</option>
|
||||
</rb-form-select>
|
||||
<div class="filter-inputs">
|
||||
<ng-container *ngFor="let ignore of [].constructor(filter.values.length); index as i">
|
||||
<rb-form-date-input *ngIf="filter.field === 'added'; else noDate" [name]="'filter-' + filter.field + i" [label]="filter.label" [(ngModel)]="filter.values[i]" (ngModelChange)="updateFilterFields(filter.field)"></rb-form-date-input>
|
||||
<ng-template #noDate>
|
||||
<rb-form-input *ngIf="!filter.autocomplete.length" [name]="'filter-' + filter.field + i" [label]="filter.label" [(ngModel)]="filter.values[i]" (ngModelChange)="updateFilterFields(filter.field)"></rb-form-input>
|
||||
<rb-form-input *ngIf="filter.autocomplete.length" [name]="'filter-' + filter.field + i" [label]="filter.label" [rbFormInputAutocomplete]="autocomplete.bind(this, filter.autocomplete)" [rbDebounceTime]="0" (keydown)="preventDefault($event, 'Enter')" [(ngModel)]="filter.values[i]" (ngModelChange)="updateFilterFields(filter.field)" ngModel></rb-form-input>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
<rb-array-input [(ngModel)]="filter.values" [name]="'filter-' + filter.field"
|
||||
[pushTemplate]="!(filter.mode === 'in' || filter.mode === 'nin') ? null :''"
|
||||
(ngModelChange)="updateFilterFields(filter.field)">
|
||||
<ng-container *rbArrayInputItem="let item"
|
||||
[ngSwitch]="(filter.autocomplete.length ? 'autocomplete' : '') +
|
||||
(filter.field == 'added' ? 'date' : '')">
|
||||
<rb-form-date-input *ngSwitchCase="'date'" [rbArrayInputListener]="'filter-' + filter.field"
|
||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
||||
[label]="filter.label" [(ngModel)]="item.value"></rb-form-date-input>
|
||||
<rb-form-input *ngSwitchCase="''" [rbArrayInputListener]="'filter-' + filter.field"
|
||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
||||
[label]="filter.label" [(ngModel)]="item.value"></rb-form-input>
|
||||
<rb-form-input *ngSwitchCase="'autocomplete'" [rbArrayInputListener]="'filter-' + filter.field"
|
||||
[name]="'filter-' + filter.field + item.i" [index]="item.i"
|
||||
[label]="filter.label" [(ngModel)]="item.value"
|
||||
[rbDebounceTime]="0" (keydown)="preventDefault($event, 'Enter')"
|
||||
[rbFormInputAutocomplete]="autocomplete.bind(this, filter.autocomplete)"
|
||||
ngModel></rb-form-input>
|
||||
</ng-container>
|
||||
</rb-array-input>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
@ -68,18 +87,20 @@
|
||||
<ng-container *ngTemplateOutlet="paging"></ng-container>
|
||||
|
||||
<div class="download">
|
||||
<button class="rb-btn rb-secondary" type="button" [rbModal]="linkModal" ><span class="rb-ic rb-ic-download"></span> JSON download link
|
||||
</button>
|
||||
<ng-template #linkModal let-close="close">
|
||||
URL for JSON download:
|
||||
<textarea class="linkmodal" #linkarea [value]="sampleUrl({export: true, host: true})" (keydown)="preventDefault($event)"></textarea>
|
||||
<rb-icon-button icon="download" mode="secondary" [rbModal]="linkModal">JSON download link</rb-icon-button>
|
||||
<ng-template #linkModal>
|
||||
<label for="jsonUrl">URL for JSON download</label>
|
||||
<textarea class="linkmodal" id="jsonUrl" #linkarea [value]="sampleUrl({export: true, host: true})"
|
||||
(keydown)="preventDefault($event)"></textarea>
|
||||
<rb-form-checkbox name="download-csv" [(ngModel)]="downloadCsv">
|
||||
add spectra
|
||||
</rb-form-checkbox>
|
||||
<button class="rb-btn rb-secondary" type="button" (click)="clipboard()"><span class="rb-ic rb-ic-clipboard"></span> Copy to clipboard</button>
|
||||
<rb-icon-button icon="clipboard" mode="secondary" (click)="clipboard()">Copy to clipboard</rb-icon-button>
|
||||
</ng-template>
|
||||
<a [href]="csvUrl" download="samples.csv">
|
||||
<button class="rb-btn rb-secondary" type="button" (mousedown)="csvUrl = sampleUrl({csv: true, export: true})"><span class="rb-ic rb-ic-download"></span> Download result as CSV</button>
|
||||
<rb-icon-button icon="download" mode="secondary" (mousedown)="csvUrl = sampleUrl({csv: true, export: true})">
|
||||
Download result as CSV
|
||||
</rb-icon-button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@ -89,8 +110,12 @@
|
||||
<div class="sort-header">
|
||||
<span>{{key.label}}</span>
|
||||
<ng-container *ngIf="key.sortable">
|
||||
<span class="rb-ic rb-ic-up sort-arr-up" (click)="setSort(key.id + '-' + 'desc')"><span *ngIf="filters.sort === key.id + '-' + 'desc'"></span></span>
|
||||
<span class="rb-ic rb-ic-down sort-arr-down" (click)="setSort(key.id + '-' + 'asc')"><span *ngIf="filters.sort === key.id + '-' + 'asc'"></span></span>
|
||||
<span class="rb-ic rb-ic-up sort-arr-up" (click)="setSort(key.id + '-' + 'desc')">
|
||||
<span *ngIf="filters.sort === key.id + '-' + 'desc'"></span>
|
||||
</span>
|
||||
<span class="rb-ic rb-ic-down sort-arr-down" (click)="setSort(key.id + '-' + 'asc')">
|
||||
<span *ngIf="filters.sort === key.id + '-' + 'asc'"></span>
|
||||
</span>
|
||||
</ng-container>
|
||||
</div>
|
||||
</th>
|
||||
@ -103,7 +128,9 @@
|
||||
<td *ngIf="isActiveKey['material.name']">{{materials[sample.material_id].name}}</td>
|
||||
<td *ngIf="isActiveKey['material.supplier']">{{materials[sample.material_id].supplier}}</td>
|
||||
<td *ngIf="isActiveKey['material.group']">{{materials[sample.material_id].group}}</td>
|
||||
<td *ngFor="let key of activeTemplateKeys.material">{{materials[sample.material_id].properties[key[2]] | exists}}</td>
|
||||
<td *ngFor="let key of activeTemplateKeys.material">
|
||||
{{materials[sample.material_id].properties[key[2]] | exists}}
|
||||
</td>
|
||||
<td *ngIf="isActiveKey['type']">{{sample.type}}</td>
|
||||
<td *ngIf="isActiveKey['color']">{{sample.color}}</td>
|
||||
<td *ngIf="isActiveKey['batch']">{{sample.batch}}</td>
|
||||
@ -121,7 +148,8 @@
|
||||
<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>
|
||||
<rb-form-input label="page" (change)="loadPage({toPage: $event.target.value - page})" [ngModel]="page">
|
||||
</rb-form-input>
|
||||
<span>
|
||||
of {{pages}} ({{totalSamples}} samples)
|
||||
</span>
|
||||
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// import { SamplesComponent } from './samples.component';
|
||||
//
|
||||
// // TODO
|
||||
// // TODO: tests
|
||||
//
|
||||
// describe('SamplesComponent', () => {
|
||||
// let component: SamplesComponent;
|
||||
|
@ -54,7 +54,7 @@ export class SamplesComponent implements OnInit {
|
||||
{field: 'color', label: 'Color', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'batch', label: 'Batch', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'notes', label: 'Notes', active: false, autocomplete: [], mode: 'eq', values: ['']},
|
||||
{field: 'added', label: 'Added', active: false, autocomplete: [], mode: 'eq', values: [new Date()]}
|
||||
{field: 'added', label: 'Added', active: false, autocomplete: [], mode: 'eq', values: ['']}
|
||||
]
|
||||
};
|
||||
page = 1;
|
||||
@ -92,7 +92,8 @@ export class SamplesComponent implements OnInit {
|
||||
this.materials[material._id] = material;
|
||||
});
|
||||
this.filters.filters.find(e => e.field === 'material.name').autocomplete = mData.map(e => e.name);
|
||||
this.filters.filters.find(e => e.field === 'color').autocomplete = [...new Set(mData.reduce((s, e) => {s.push(...e.numbers.map(el => el.color)); return s; }, []))];
|
||||
this.filters.filters.find(e => e.field === 'color').autocomplete =
|
||||
[...new Set(mData.reduce((s, e) => {s.push(...e.numbers.map(el => el.color)); return s; }, []))];
|
||||
this.loadSamples();
|
||||
});
|
||||
this.api.get('/user/key', (data: {key: string}) => {
|
||||
@ -114,9 +115,22 @@ export class SamplesComponent implements OnInit {
|
||||
data.forEach(item => {
|
||||
item.parameters.forEach(parameter => {
|
||||
const parameterName = encodeURIComponent(parameter.name);
|
||||
if (parameter.name !== 'dpt' && !templateKeys.find(e => new RegExp('.' + parameterName + '$').test(e.id))) { // exclude spectrum
|
||||
templateKeys.push({id: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`, label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`, active: false, sortable: true});
|
||||
this.filters.filters.push({field: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`, label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`, active: false, autocomplete: [], mode: 'eq', values: ['']});
|
||||
// exclude spectrum
|
||||
if (parameter.name !== 'dpt' && !templateKeys.find(e => new RegExp('.' + parameterName + '$').test(e.id))) {
|
||||
templateKeys.push({
|
||||
id: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`,
|
||||
label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`,
|
||||
active: false,
|
||||
sortable: true
|
||||
});
|
||||
this.filters.filters.push({
|
||||
field: `${collection === 'materials' ? 'material.properties' : collection + '.' + item.name}.${parameterName}`,
|
||||
label: `${this.ucFirst(item.name)} ${this.ucFirst(parameter.name)}`,
|
||||
active: false,
|
||||
autocomplete: [],
|
||||
mode: 'eq',
|
||||
values: ['']
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -156,10 +170,22 @@ export class SamplesComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
sampleUrl(options: {paging?: boolean, pagingOptions?: {firstPage?: boolean, toPage?: number, event?: Event}, csv?: boolean, export?: boolean, host?: boolean}) { // return url to fetch samples
|
||||
sampleUrl(options: {
|
||||
paging?: boolean,
|
||||
pagingOptions?: {
|
||||
firstPage?: boolean,
|
||||
toPage?: number,
|
||||
event?: Event
|
||||
},
|
||||
csv?: boolean,
|
||||
export?: boolean,
|
||||
host?: boolean
|
||||
}) { // return url to fetch samples
|
||||
const additionalTableKeys = ['material_id', '_id']; // keys which should always be added if export = false
|
||||
const query: string[] = [];
|
||||
query.push('status=' + (this.filters.status.new && this.filters.status.validated ? 'all' : (this.filters.status.new ? 'new' : 'validated')));
|
||||
query.push(
|
||||
'status=' + (this.filters.status.new && this.filters.status.validated ? 'all' : (this.filters.status.new ? 'new' : 'validated'))
|
||||
);
|
||||
if (options.paging) {
|
||||
if (this.samples[0]) { // do not include from-id when page size was changed
|
||||
if (!options.pagingOptions.firstPage) {
|
||||
@ -182,11 +208,11 @@ export class SamplesComponent implements OnInit {
|
||||
query.push('key=' + this.apiKey);
|
||||
}
|
||||
this.keys.forEach(key => {
|
||||
if (key.active && (options.export || (!options.export && key.id.indexOf('material') < 0))) { // do not load material properties for table
|
||||
// do not load material properties for table
|
||||
if (key.active && (options.export || (!options.export && key.id.indexOf('material') < 0))) {
|
||||
query.push('fields[]=' + key.id);
|
||||
}
|
||||
});
|
||||
console.log(this.filters.filters);
|
||||
|
||||
query.push(..._.cloneDeep(this.filters.filters)
|
||||
.map(e => {
|
||||
@ -199,7 +225,6 @@ export class SamplesComponent implements OnInit {
|
||||
.filter(e => e.active && e.values.length > 0)
|
||||
.map(e => 'filters[]=' + encodeURIComponent(JSON.stringify(_.pick(e, ['mode', 'field', 'values']))))
|
||||
);
|
||||
console.log(this.filters);
|
||||
if (!options.export) {
|
||||
additionalTableKeys.forEach(key => {
|
||||
if (query.indexOf('fields[]=' + key) < 0) { // add key if not already added
|
||||
@ -210,8 +235,9 @@ export class SamplesComponent implements OnInit {
|
||||
else if (this.downloadCsv) {
|
||||
query.push('fields[]=measurements.spectrum.dpt');
|
||||
}
|
||||
console.log('/samples?' + query.join('&'));
|
||||
return (options.host && isDevMode() ? window.location.host : '') + (options.export ? this.api.hostName : '') + '/samples?' + query.join('&');
|
||||
return (options.host && isDevMode() ? window.location.host : '') +
|
||||
(options.export ? this.api.hostName : '') +
|
||||
'/samples?' + query.join('&');
|
||||
}
|
||||
|
||||
loadPage(delta) {
|
||||
@ -225,17 +251,6 @@ export class SamplesComponent implements OnInit {
|
||||
updateFilterFields(field) {
|
||||
const filter = this.filters.filters.find(e => e.field === field);
|
||||
filter.active = true;
|
||||
if (filter.mode === 'in' || filter.mode === 'nin') {
|
||||
if (filter.values[filter.values.length - 1] === '' && filter.values[filter.values.length - 2] === '') {
|
||||
filter.values.pop();
|
||||
}
|
||||
else if (filter.values[filter.values.length - 1] !== '') {
|
||||
filter.values.push((filter.field === 'added' ? new Date() : '') as string & Date);
|
||||
}
|
||||
}
|
||||
else {
|
||||
filter.values = [filter.values[0] as string & Date];
|
||||
}
|
||||
if (filter.active) {
|
||||
this.loadSamples({firstPage: true});
|
||||
}
|
||||
@ -248,15 +263,16 @@ export class SamplesComponent implements OnInit {
|
||||
|
||||
updateActiveKeys() { // array with all activeKeys
|
||||
this.activeKeys = this.keys.filter(e => e.active);
|
||||
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.measurements = this.keys.filter(e => e.id.indexOf('measurements.') >= 0 && e.active).map(e => e.id.split('.').map(el => decodeURIComponent(el)));
|
||||
console.log(this.activeTemplateKeys);
|
||||
console.log(this.keys); // TODO: glass fiber filter not working
|
||||
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.measurements = this.keys.filter(e => e.id.indexOf('measurements.') >= 0 && e.active)
|
||||
.map(e => e.id.split('.')
|
||||
.map(el => decodeURIComponent(el))); // TODO: glass fiber filter not working
|
||||
}
|
||||
|
||||
calcFieldSelectKeys() {
|
||||
console.log('CALC');
|
||||
console.log(this.keys);
|
||||
this.keys.forEach(key => {
|
||||
this.isActiveKey[key.id] = key.active;
|
||||
});
|
||||
|
Reference in New Issue
Block a user