render gallery items
This commit is contained in:
@@ -22,7 +22,7 @@ import { YAxisRangeComponent } from './y-axis-range/y-axis-range.component';
|
|||||||
import { QueryAutocompleteComponent } from './query-autocomplete/query-autocomplete.component';
|
import { QueryAutocompleteComponent } from './query-autocomplete/query-autocomplete.component';
|
||||||
import { LimitByComponent } from './limit-by/limit-by.component';
|
import { LimitByComponent } from './limit-by/limit-by.component';
|
||||||
import { PlotViewComponent } from './plot-view/plot-view.component';
|
import { PlotViewComponent } from './plot-view/plot-view.component';
|
||||||
import { GalleryViewComponent } from './gallery-view/gallery-view.component';
|
import { GalleryViewComponent, GalleryItemView } from './gallery-view/gallery-view.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -35,6 +35,8 @@ import { GalleryViewComponent } from './gallery-view/gallery-view.component';
|
|||||||
QueryAutocompleteComponent,
|
QueryAutocompleteComponent,
|
||||||
LimitByComponent,
|
LimitByComponent,
|
||||||
PlotViewComponent,
|
PlotViewComponent,
|
||||||
|
GalleryViewComponent,
|
||||||
|
GalleryItemView
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
13
pdb-js/src/app/gallery-view/gallery-item-view.component.html
Normal file
13
pdb-js/src/app/gallery-view/gallery-item-view.component.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<div class="gallery-item">
|
||||||
|
<div class="gallery-item">
|
||||||
|
<a href="{{data.imageUrl}}"><img src="{{data.thumbnailUrl}}" class="clickable"></a>
|
||||||
|
|
||||||
|
<div class="fieldValue">{{data.splitByValue}}</div>
|
||||||
|
<div class="fieldStatsValue">Values:
|
||||||
|
<span *ngIf="data.stats.plottedValues != data.stats.values" title="plotted values, some values might be missing due to y-axis range limits">{{data.stats.plottedValues}}/</span>
|
||||||
|
<span title="total number of values in the plot">{{data.stats.values}}</span>
|
||||||
|
</div>
|
||||||
|
<div class="fieldStatsMaxValue">Max value: <span class="time">{{ formatMs(data.stats.maxValue) }}</span></div>
|
||||||
|
<div class="fieldStatsAverage">Average: <span class="time">{{ formatMs(data.stats.average) }}</span></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
14
pdb-js/src/app/gallery-view/gallery-item-view.component.scss
Normal file
14
pdb-js/src/app/gallery-view/gallery-item-view.component.scss
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
.gallery-item {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
background: white;
|
||||||
|
box-shadow: 5px 5px 10px 0px #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-item a {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-item .fieldValue{
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
5
pdb-js/src/app/gallery-view/gallery-view.component.html
Normal file
5
pdb-js/src/app/gallery-view/gallery-view.component.html
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<div id="gallery" class="card-grid-300">
|
||||||
|
<pdb-gallery-item-view
|
||||||
|
*ngFor="let galleryItem of galleryItems" [data]="galleryItem">
|
||||||
|
</pdb-gallery-item-view>
|
||||||
|
</div>
|
||||||
7
pdb-js/src/app/gallery-view/gallery-view.component.scss
Normal file
7
pdb-js/src/app/gallery-view/gallery-view.component.scss
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.card-grid-300 {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 300px));
|
||||||
|
grid-gap: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
25
pdb-js/src/app/gallery-view/gallery-view.component.spec.ts
Normal file
25
pdb-js/src/app/gallery-view/gallery-view.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { GalleryViewComponent } from './gallery-view.component';
|
||||||
|
|
||||||
|
describe('GalleryViewComponent', () => {
|
||||||
|
let component: GalleryViewComponent;
|
||||||
|
let fixture: ComponentFixture<GalleryViewComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ GalleryViewComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(GalleryViewComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
123
pdb-js/src/app/gallery-view/gallery-view.component.ts
Normal file
123
pdb-js/src/app/gallery-view/gallery-view.component.ts
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { PlotService, PlotRequest, PlotResponse, PlotResponseStats } from '../plot.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'pdb-gallery-view',
|
||||||
|
templateUrl: './gallery-view.component.html',
|
||||||
|
styleUrls: ['./gallery-view.component.scss']
|
||||||
|
})
|
||||||
|
export class GalleryViewComponent implements OnInit {
|
||||||
|
|
||||||
|
|
||||||
|
galleryItems: Array<GalleryItem> = new Array<GalleryItem>();
|
||||||
|
|
||||||
|
splitByValuesQueue = new Array<string>();
|
||||||
|
|
||||||
|
constructor(private plotService: PlotService, private snackBar: MatSnackBar) {
|
||||||
|
}
|
||||||
|
|
||||||
|
showError(message) {
|
||||||
|
this.snackBar.open(message, "", {
|
||||||
|
duration: 5000,
|
||||||
|
verticalPosition: 'top'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
renderGallery(request: PlotRequest, splitByField: string) {
|
||||||
|
const that=this;
|
||||||
|
|
||||||
|
this.galleryItems.length = 0;
|
||||||
|
this.splitByValuesQueue.length = 0;
|
||||||
|
|
||||||
|
request.generateThumbnail = true;
|
||||||
|
|
||||||
|
this.plotService.splitQuery(request.query, splitByField).subscribe(function(valuesForSplitBy){
|
||||||
|
console.log("valuesForSplitBy: " + JSON.stringify(valuesForSplitBy));
|
||||||
|
that.splitByValuesQueue = valuesForSplitBy;
|
||||||
|
that.renderGalleryRecursively(request, splitByField);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
that.showError(error.error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderGalleryRecursively(masterRequest: PlotRequest, splitByField: string){
|
||||||
|
const that = this;
|
||||||
|
|
||||||
|
if (this.splitByValuesQueue.length == 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const splitByValue = this.splitByValuesQueue.pop();
|
||||||
|
|
||||||
|
let request = masterRequest.copy();
|
||||||
|
request.query = "("+request.query+") and " + splitByField+"="+ splitByValue;
|
||||||
|
|
||||||
|
this.plotService.sendPlotRequest(request).subscribe(function(plotResponse : PlotResponse){
|
||||||
|
console.log("response: " + JSON.stringify(plotResponse));
|
||||||
|
|
||||||
|
plotResponse.thumbnailUrl = "http://"+window.location.hostname+':8080/'+plotResponse.thumbnailUrl;
|
||||||
|
plotResponse.imageUrl = "http://"+window.location.hostname+':8080/'+plotResponse.imageUrl;
|
||||||
|
let galleryItem = new GalleryItem(splitByValue, plotResponse);
|
||||||
|
that.galleryItems.push(galleryItem);
|
||||||
|
that.renderGalleryRecursively(masterRequest, splitByField);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
that.showError(error.error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'pdb-gallery-item-view',
|
||||||
|
templateUrl: './gallery-item-view.component.html',
|
||||||
|
styleUrls: ['./gallery-item-view.component.scss']
|
||||||
|
})
|
||||||
|
export class GalleryItemView {
|
||||||
|
@Input()
|
||||||
|
data: GalleryItem;
|
||||||
|
|
||||||
|
|
||||||
|
formatMs(valueInMs):string {
|
||||||
|
const ms = Math.floor(valueInMs % 1000);
|
||||||
|
const s = Math.floor((valueInMs / 1000) % 60);
|
||||||
|
const m = Math.floor((valueInMs / (60*1000)) % 60);
|
||||||
|
const h = Math.floor(valueInMs / (3600*1000));
|
||||||
|
|
||||||
|
var result = "";
|
||||||
|
if (h != 0) {
|
||||||
|
result += h+"h ";
|
||||||
|
}
|
||||||
|
if (h!= 0 || m != 0) {
|
||||||
|
result += m+"m ";
|
||||||
|
}
|
||||||
|
if (h!= 0 || m != 0 || s != 0) {
|
||||||
|
result += s+"s ";
|
||||||
|
result += ms+"ms";
|
||||||
|
} else {
|
||||||
|
result += ms+"ms";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export class GalleryItem {
|
||||||
|
thumbnailUrl: string;
|
||||||
|
imageUrl: string;
|
||||||
|
stats: PlotResponseStats;
|
||||||
|
splitByValue : string;
|
||||||
|
|
||||||
|
constructor(splitByValue: string, plotResponse: PlotResponse){
|
||||||
|
this.thumbnailUrl = plotResponse.thumbnailUrl;
|
||||||
|
this.imageUrl = plotResponse.imageUrl;
|
||||||
|
this.splitByValue = splitByValue;
|
||||||
|
this.stats = plotResponse.stats;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -156,6 +156,10 @@ export class PlotRequest {
|
|||||||
yRangeUnit : string;
|
yRangeUnit : string;
|
||||||
keyOutside : boolean = false;
|
keyOutside : boolean = false;
|
||||||
generateThumbnail : boolean;
|
generateThumbnail : boolean;
|
||||||
|
|
||||||
|
copy(): PlotRequest {
|
||||||
|
return JSON.parse(JSON.stringify(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PlotResponse {
|
export class PlotResponse {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
grid:
|
grid:
|
||||||
"query-box query-box date-box" auto
|
"query-box query-box date-box" auto
|
||||||
"filters results results" 1fr
|
"filters results results" 1fr
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
#visualization {
|
#visualization {
|
||||||
display: grid;
|
display: grid;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
grid:
|
grid:
|
||||||
"query-box" auto
|
"query-box" auto
|
||||||
"date-box" auto
|
"date-box" auto
|
||||||
@@ -57,8 +59,8 @@
|
|||||||
#results {
|
#results {
|
||||||
grid-area: results;
|
grid-area: results;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin-right: 0.5em;
|
|
||||||
position:relative; /* ??? */
|
position:relative; /* ??? */
|
||||||
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
#plot-button-bar {
|
#plot-button-bar {
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
@ViewChild(PlotViewComponent, {static: false})
|
@ViewChild(PlotViewComponent, {static: false})
|
||||||
plotView: PlotViewComponent;
|
plotView: PlotViewComponent;
|
||||||
|
|
||||||
|
@ViewChild(GalleryViewComponent, {static: false})
|
||||||
|
galleryView: GalleryViewComponent;
|
||||||
|
|
||||||
enableGallery = false;
|
enableGallery = false;
|
||||||
splitBy = null;
|
splitBy = null;
|
||||||
|
|
||||||
@@ -108,13 +111,9 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
|
|
||||||
gallery(){
|
gallery(){
|
||||||
const that = this;
|
const that = this;
|
||||||
this.plotService.splitQuery(this.query.query, this.splitBy.name).subscribe(function(valuesForSplitBy){
|
this.plotView.imageUrl = '';
|
||||||
console.log("valuesForSplitBy: " + JSON.stringify(valuesForSplitBy));
|
const request = this.createPlotRequest();
|
||||||
},
|
this.galleryView.renderGallery(request, this.splitBy.name);
|
||||||
error => {
|
|
||||||
that.plotView.imageUrl = '';
|
|
||||||
that.showError(error.error.message);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
plot(){
|
plot(){
|
||||||
@@ -122,7 +121,19 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
|
|
||||||
that.plotView.imageUrl = '';
|
that.plotView.imageUrl = '';
|
||||||
|
|
||||||
|
const request = this.createPlotRequest();
|
||||||
|
|
||||||
|
this.plotService.sendPlotRequest(request).subscribe(function(plotResponse){
|
||||||
|
console.log("response: " + JSON.stringify(plotResponse));
|
||||||
|
that.plotView.imageUrl = "http://"+window.location.hostname+':8080/'+plotResponse.imageUrl;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
that.plotView.imageUrl = '';
|
||||||
|
that.showError(error.error.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createPlotRequest(): PlotRequest {
|
||||||
const aggregates = [];
|
const aggregates = [];
|
||||||
aggregates.push(this.selectedPlotType.value.id);
|
aggregates.push(this.selectedPlotType.value.id);
|
||||||
if (this.selectedCombinePlotType.value){
|
if (this.selectedCombinePlotType.value){
|
||||||
@@ -144,16 +155,7 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
request.yRangeMin = this.yAxisRangeComponent.minYValue;
|
request.yRangeMin = this.yAxisRangeComponent.minYValue;
|
||||||
request.yRangeMax = this.yAxisRangeComponent.maxYValue;
|
request.yRangeMax = this.yAxisRangeComponent.maxYValue;
|
||||||
request.yRangeUnit = this.yAxisRangeComponent.yAxisUnit;
|
request.yRangeUnit = this.yAxisRangeComponent.yAxisUnit;
|
||||||
|
return request;
|
||||||
|
|
||||||
this.plotService.sendPlotRequest(request).subscribe(function(plotResponse){
|
|
||||||
console.log("response: " + JSON.stringify(plotResponse));
|
|
||||||
that.plotView.imageUrl = "http://"+window.location.hostname+':8080/'+plotResponse.imageUrl;
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
that.plotView.imageUrl = '';
|
|
||||||
that.showError(error.error.message);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ a.external-link:after {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
body .mat-select-panel, body .mat-autocomplete-panel {
|
body .mat-select-panel, body .mat-autocomplete-panel {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user