diff --git a/pdb-js/src/app/app.module.ts b/pdb-js/src/app/app.module.ts
index e8aaf6d..934f729 100644
--- a/pdb-js/src/app/app.module.ts
+++ b/pdb-js/src/app/app.module.ts
@@ -22,7 +22,7 @@ import { YAxisRangeComponent } from './y-axis-range/y-axis-range.component';
import { QueryAutocompleteComponent } from './query-autocomplete/query-autocomplete.component';
import { LimitByComponent } from './limit-by/limit-by.component';
import { PlotViewComponent } from './plot-view/plot-view.component';
-import { GalleryViewComponent, GalleryItemView } from './gallery-view/gallery-view.component';
+import { GalleryViewComponent, GalleryItemView, GalleryFilterView } from './gallery-view/gallery-view.component';
import { ImageToggleComponent } from './image-toggle/image-toggle.component';
@NgModule({
@@ -38,6 +38,7 @@ import { ImageToggleComponent } from './image-toggle/image-toggle.component';
PlotViewComponent,
GalleryViewComponent,
GalleryItemView,
+ GalleryFilterView,
ImageToggleComponent
],
imports: [
diff --git a/pdb-js/src/app/gallery-view/gallery-filter-view.component.html b/pdb-js/src/app/gallery-view/gallery-filter-view.component.html
new file mode 100644
index 0000000..098f522
--- /dev/null
+++ b/pdb-js/src/app/gallery-view/gallery-filter-view.component.html
@@ -0,0 +1,26 @@
+
+ Filter By:
+
+ none
+ max value
+ average
+ #values
+ #plotted values
+
+
+
+
+
+
+
+
+
+
+
+ millis
+ seconds
+ minutes
+ hours
+ days
+
+
\ No newline at end of file
diff --git a/pdb-js/src/app/gallery-view/gallery-filter-view.component.scss b/pdb-js/src/app/gallery-view/gallery-filter-view.component.scss
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/pdb-js/src/app/gallery-view/gallery-filter-view.component.scss
@@ -0,0 +1 @@
+
diff --git a/pdb-js/src/app/gallery-view/gallery-view.component.html b/pdb-js/src/app/gallery-view/gallery-view.component.html
index b68101e..23d404c 100644
--- a/pdb-js/src/app/gallery-view/gallery-view.component.html
+++ b/pdb-js/src/app/gallery-view/gallery-view.component.html
@@ -13,9 +13,11 @@
-
+
+
+
+
+
+ *ngFor="let galleryItem of filteredSortedGalleryItems()" [data]="galleryItem">
diff --git a/pdb-js/src/app/gallery-view/gallery-view.component.ts b/pdb-js/src/app/gallery-view/gallery-view.component.ts
index 0e4c104..9f4a535 100644
--- a/pdb-js/src/app/gallery-view/gallery-view.component.ts
+++ b/pdb-js/src/app/gallery-view/gallery-view.component.ts
@@ -1,7 +1,93 @@
-import { Component, OnInit, Input } from '@angular/core';
+import { Component, OnInit, Input, Output, ViewChild, EventEmitter } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { PlotService, PlotRequest, PlotResponse, PlotResponseStats } from '../plot.service';
+export class GalleryFilterData {
+ filterBy :string;
+ comparator :string;
+ value : number;
+ unit: string;
+ constructor(filterBy :string, comparator :string, value : number, unit: string){
+ this.filterBy = filterBy;
+ this.comparator = comparator;
+ this.value = value;
+ this.unit = unit;
+ }
+}
+
+@Component({
+ selector: 'pdb-gallery-filter-view',
+ templateUrl: './gallery-filter-view.component.html',
+ styleUrls: ['./gallery-filter-view.component.scss']
+})
+export class GalleryFilterView {
+ compareImages = JSON.stringify([
+ {
+ value: 'GREATER_EQUAL',
+ text: '≥',
+ title: 'greater or equal'
+ },
+ {
+ value: 'LESS_EQUAL',
+ text: '≤',
+ title: 'less or equal'
+ }
+ ]);
+
+ _filterBy = 'MAX_VALUE';
+
+ _comparator = 'GREATER_EQUAL';
+
+ _value : number = 0;
+
+ _unit: string = 'SECONDS';
+
+ @Output()
+ valueChanged : EventEmitter = new EventEmitter();
+
+ comparatorChanged(newComparator: string){
+ this._comparator = newComparator;
+ this.valueChanged.emit(undefined);
+ }
+
+ set filterBy(filterBy: string){
+ this._filterBy = filterBy;
+ this.valueChanged.emit(undefined);
+ }
+
+ get filterBy() : string{
+ return this._filterBy;
+ }
+ set unit(unit: string){
+ this._unit = unit;
+ this.valueChanged.emit(undefined);
+ }
+
+ get unit() : string{
+ return this._unit;
+ }
+
+ set comparator(comparator: string){
+ this._comparator = comparator;
+ this.valueChanged.emit(undefined);
+ }
+
+ get comparator() : string{
+ return this._comparator;
+ }
+
+ set value(value: number){
+ this._value = value;
+ this.valueChanged.emit(undefined);
+ }
+
+ get value() : number{
+ return this._value;
+ }
+}
+
+
+
@Component({
selector: 'pdb-gallery-view',
templateUrl: './gallery-view.component.html',
@@ -12,20 +98,26 @@ export class GalleryViewComponent implements OnInit {
galleryItems: Array = new Array();
+
show = false;
splitByValuesQueue = new Array();
_sortBy= "NAME";
- sortOrder = 0;
+ sortOrder = 'ASC';
+
+ @ViewChild(GalleryFilterView, {static: false})
+ filter : GalleryFilterView;
ascDescImages = JSON.stringify([
{
+ value: 'ASC',
imageUrl: 'assets/img/ascending-filter.svg',
title: 'ascending'
},
{
+ value: 'DESC',
imageUrl: 'assets/img/descending-filter.svg',
title: 'descending'
}
@@ -44,8 +136,17 @@ export class GalleryViewComponent implements OnInit {
ngOnInit() {
}
+ filteredSortedGalleryItems(): Array {
+ return this.galleryItems.filter(item => item.show);
+ }
+
+ sortAndFilterGallery(){
+ this.filterGallery();
+ this.sortGallery();
+ }
+
sortGallery() {
- const orderFactor = this.sortOrder == 0 ? 1 : -1; // ASC=1, DESC=-1
+ const orderFactor = this.sortOrder == 'ASC' ? 1 : -1;
switch (this._sortBy) {
case "NAME":
@@ -66,6 +167,52 @@ export class GalleryViewComponent implements OnInit {
}
}
+ filterGallery(){
+ const that = this;
+ this.galleryItems.forEach(function(item){
+ const show = that.filterPredicate(item);
+ item.show = show;
+ });
+ }
+
+ filterPredicate(galleryItem: GalleryItem){
+ const predicate = this.filter.comparator == 'LESS_EQUAL'
+ ? function(a, b) { return a <= b; }
+ : function(a, b) { return a >= b; };
+ const millis = this.timeUnitToMillis(this.filter.value, this.filter.unit);
+ switch(this.filter.filterBy){
+ case 'NONE':
+ case undefined:
+ return true;
+ case 'MAX_VALUE':
+ return predicate(galleryItem.stats.maxValue, millis);
+ case 'AVERAGE':
+ return predicate(galleryItem.stats.average, millis);
+ case 'VALUES':
+ return predicate(galleryItem.stats.values, this.filter.value);
+ case 'PLOTTED_VALUES':
+ return predicate(galleryItem.stats.plottedValues, this.filter.value);
+ }
+ throw "unhandled option: " + this.filter.filterBy;
+ }
+
+ timeUnitToMillis(value, unit)
+ {
+ switch(unit){
+ case 'MILLISECONDS':
+ return value;
+ case 'SECONDS':
+ return value*1000;
+ case 'MINUTES':
+ return value*1000*60;
+ case 'HOURS':
+ return value*1000*60*60;
+ case 'DAYS':
+ return value*1000*60*60*24;
+ }
+ throw "unknown unit: " + unit;
+ }
+
renderGallery(request: PlotRequest, splitByField: string) {
const that=this;
@@ -103,7 +250,7 @@ export class GalleryViewComponent implements OnInit {
plotResponse.imageUrl = "http://"+window.location.hostname+':8080/'+plotResponse.imageUrl;
let galleryItem = new GalleryItem(splitByValue, plotResponse);
that.galleryItems.push(galleryItem);
- that.sortGallery();
+ that.sortAndFilterGallery();
that.renderGalleryRecursively(masterRequest, splitByField);
},
error => {
@@ -113,14 +260,18 @@ export class GalleryViewComponent implements OnInit {
set sortBy(name: string) {
this._sortBy = name;
- this.sortGallery();
+ this.sortAndFilterGallery();
}
get sortBy(): string { return this._sortBy; }
sortOrderChanged(event){
this.sortOrder = event;
- this.sortGallery();
+ this.sortAndFilterGallery();
+ }
+
+ filterChanged(event){
+ this.sortAndFilterGallery();
}
}
@@ -160,11 +311,13 @@ export class GalleryItemView {
}
+
export class GalleryItem {
thumbnailUrl: string;
imageUrl: string;
stats: PlotResponseStats;
splitByValue : string;
+ show : boolean;
constructor(splitByValue: string, plotResponse: PlotResponse){
this.thumbnailUrl = plotResponse.thumbnailUrl;
diff --git a/pdb-js/src/app/image-toggle/image-toggle.component.html b/pdb-js/src/app/image-toggle/image-toggle.component.html
index 1738d6f..3c9e4c6 100644
--- a/pdb-js/src/app/image-toggle/image-toggle.component.html
+++ b/pdb-js/src/app/image-toggle/image-toggle.component.html
@@ -1 +1,10 @@
-
+
+{{text}}
\ No newline at end of file
diff --git a/pdb-js/src/app/image-toggle/image-toggle.component.scss b/pdb-js/src/app/image-toggle/image-toggle.component.scss
index e69de29..137d553 100644
--- a/pdb-js/src/app/image-toggle/image-toggle.component.scss
+++ b/pdb-js/src/app/image-toggle/image-toggle.component.scss
@@ -0,0 +1,11 @@
+:host{
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 1ex;
+}
+
+.image-toggle-text{
+ font-size: 1.5em;
+ font-weight: normal;
+}
diff --git a/pdb-js/src/app/image-toggle/image-toggle.component.ts b/pdb-js/src/app/image-toggle/image-toggle.component.ts
index 65d0c49..93c7035 100644
--- a/pdb-js/src/app/image-toggle/image-toggle.component.ts
+++ b/pdb-js/src/app/image-toggle/image-toggle.component.ts
@@ -10,29 +10,33 @@ export class ImageToggleComponent implements OnInit {
@Input()
images : string = "";
- value: number = 0;
+ index: number = 0;
@Output()
valueChanged : EventEmitter = new EventEmitter();
+ text = undefined;
+
_states : Array;
constructor() { }
ngOnInit() {
this._states = JSON.parse(this.images);
+ this.text = this._states[this.index].text;
}
imageUrl() : string {
- return this._states[this.value].imageUrl;
+ return this._states[this.index].imageUrl;
}
title() : string {
- return this._states[this.value].title;
+ return this._states[this.index].title;
}
toggle(event){
- this.value = (this.value+1) % this._states.length;
- this.valueChanged.emit(this.value);
+ this.index = (this.index+1) % this._states.length;
+ this.text = this._states[this.index].text;
+ this.valueChanged.emit(this._states[this.index].value);
}
}
diff --git a/pdb-js/src/styles.scss b/pdb-js/src/styles.scss
index 4c24d1f..b725766 100644
--- a/pdb-js/src/styles.scss
+++ b/pdb-js/src/styles.scss
@@ -93,6 +93,9 @@ mat-form-field:last-child {
mat-form-field.pdb-form-number {
width: 3.5em;
}
+mat-form-field.pdb-form-number-long {
+ width: 7em;
+}
.pdb-form-icon-small {
display: inline-block;
width: 2em;