extract plot detail view into its own component
This commit is contained in:
@@ -24,6 +24,7 @@ import {MatTooltipModule} from '@angular/material/tooltip';
|
||||
import { YAxisDefinitionComponent } from './y-axis-definition/y-axis-definition.component';
|
||||
import { QueryAutocompleteComponent } from './query-autocomplete/query-autocomplete.component';
|
||||
import { LimitByComponent } from './limit-by/limit-by.component';
|
||||
import { PlotDetailsComponent } from './plot-details/plot-details.component';
|
||||
import { PlotViewComponent } from './plot-view/plot-view.component';
|
||||
import { GalleryViewComponent, GalleryItemView, GalleryFilterView } from './gallery-view/gallery-view.component';
|
||||
import { ImageToggleComponent } from './image-toggle/image-toggle.component';
|
||||
@@ -38,6 +39,7 @@ import { ImageToggleComponent } from './image-toggle/image-toggle.component';
|
||||
YAxisDefinitionComponent,
|
||||
QueryAutocompleteComponent,
|
||||
LimitByComponent,
|
||||
PlotDetailsComponent,
|
||||
PlotViewComponent,
|
||||
GalleryViewComponent,
|
||||
GalleryItemView,
|
||||
|
||||
@@ -8,47 +8,18 @@
|
||||
<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 class="fieldStatsMaxValue">Max value: <span class="time">{{ utils.formatMs(data.stats.maxValue) }}</span></div>
|
||||
<div class="fieldStatsAverage">Average: <span class="time">{{ utils.formatMs(data.stats.average) }}</span></div>
|
||||
</div>
|
||||
<table *ngIf="showDetails" class="gallery-item-details">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Values</th>
|
||||
<th>Avg</th>
|
||||
</tr>
|
||||
<tr *ngFor="let stats of data.stats.dataSeriesStats">
|
||||
<td>{{ stats.name }}</td>
|
||||
<td><div class="{{ pointTypeClass(stats.dashTypeAndColor) }}" title="{{ stats.name }}"></div></td>
|
||||
<td>{{ stats.values }}</td>
|
||||
<td>{{ formatMs(stats.average) }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table *ngIf="showDetails" class="gallery-item-details-matrix">
|
||||
<tr>
|
||||
<th></th>
|
||||
<td *ngFor="let statsCol of data.stats.dataSeriesStats">
|
||||
<div class="{{ pointTypeClass(statsCol.dashTypeAndColor) }}" title="{{ statsCol.name }}"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr *ngFor="let statsRow of data.stats.dataSeriesStats">
|
||||
<td><div class="{{ pointTypeClass(statsRow.dashTypeAndColor) }}" title="{{ statsRow.name }}"></div></td>
|
||||
<td *ngFor="let statsCol of data.stats.dataSeriesStats">
|
||||
{{ toPercent(statsRow.average / statsCol.average) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<pdb-plot-details *ngIf="showDetails" [stats]="data.stats"></pdb-plot-details>
|
||||
<div
|
||||
*ngIf="showImage"
|
||||
class="gallery-item-big-image-container"
|
||||
>
|
||||
<img src="{{data.imageUrl}}" />
|
||||
<div
|
||||
class="gallery-item-big-image-close clickable"
|
||||
(click)="closeImage()"
|
||||
title="Close"
|
||||
><img src="assets/img/close.svg" class="icon-small" />
|
||||
<div class="top-right">
|
||||
<!--<img class="icon-small clickable" src="assets/img/exclamation-round.svg" title="show details"/>-->
|
||||
<img src="assets/img/close.svg" class="icon-small clickable" (click)="closeImage()" title="close" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -45,33 +45,4 @@
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.gallery-item-plotType {
|
||||
background-image: url(/assets/img/pointTypes.png);
|
||||
width: 9px;
|
||||
height: 7px;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
|
||||
.gallery-item-plotType_0 {background-position-x: 0px;}
|
||||
.gallery-item-plotType_1 {background-position-x: -10px;}
|
||||
.gallery-item-plotType_2 {background-position-x: -20px;}
|
||||
.gallery-item-plotType_3 {background-position-x: -30px;}
|
||||
.gallery-item-plotType_4 {background-position-x: -40px;}
|
||||
.gallery-item-plotType_5 {background-position-x: -50px;}
|
||||
.gallery-item-plotType_6 {background-position-x: -60px;}
|
||||
.gallery-item-plotType_7 {background-position-x: -70px;}
|
||||
.gallery-item-plotType_8 {background-position-x: -80px;}
|
||||
.gallery-item-plotType_9 {background-position-x: -90px;}
|
||||
.gallery-item-plotType_10 {background-position-x:-100px;}
|
||||
.gallery-item-plotType_11 {background-position-x:-110px;}
|
||||
.gallery-item-plotType_12 {background-position-x:-120px;}
|
||||
|
||||
.gallery-item-plotType_0051c2 {background-position-y: 0px;}
|
||||
.gallery-item-plotType_bf8300 {background-position-y: -8px;}
|
||||
.gallery-item-plotType_9400d3 {background-position-y: -16px;}
|
||||
.gallery-item-plotType_00c254 {background-position-y: -24px;}
|
||||
.gallery-item-plotType_e6e600 {background-position-y: -32px;}
|
||||
.gallery-item-plotType_e51e10 {background-position-y: -40px;}
|
||||
.gallery-item-plotType_57a1c2 {background-position-y: -48px;}
|
||||
.gallery-item-plotType_bd36c2 {background-position-y: -56px;}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component, OnInit, Input, Output, ViewChild, EventEmitter } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { PlotService, PlotRequest, PlotResponse, PlotResponseStats, DashTypeAndColor } from '../plot.service';
|
||||
import { UtilService } from '../utils.service';
|
||||
|
||||
export class GalleryFilterData {
|
||||
filterBy :string;
|
||||
@@ -312,37 +313,7 @@ export class GalleryItemView {
|
||||
|
||||
showImage: boolean= false;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
pointTypeClass(typeAndColor: DashTypeAndColor): string {
|
||||
return "gallery-item-plotType gallery-item-plotType_"+typeAndColor.pointType+" gallery-item-plotType_"+typeAndColor.color.toLocaleLowerCase();
|
||||
}
|
||||
|
||||
toPercent(percentage: number) : string{
|
||||
return (Math.round(percentage * 10000) / 100)+"%";
|
||||
}
|
||||
constructor(public utils: UtilService){}
|
||||
|
||||
openImage() {
|
||||
this.showImage=true;
|
||||
|
||||
28
pdb-js/src/app/plot-details/plot-details.component.html
Normal file
28
pdb-js/src/app/plot-details/plot-details.component.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<table class="gallery-item-details">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Values</th>
|
||||
<th>Avg</th>
|
||||
</tr>
|
||||
<tr *ngFor="let stat of stats.dataSeriesStats">
|
||||
<td>{{ stat.name }}</td>
|
||||
<td><div class="{{ pointTypeClass(stat.dashTypeAndColor) }}" title="{{ stat.name }}"></div></td>
|
||||
<td>{{ stat.values }}</td>
|
||||
<td>{{ utils.formatMs(stats.average) }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table class="gallery-item-details-matrix">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th *ngFor="let statsCol of stats.dataSeriesStats">
|
||||
<div class="{{ pointTypeClass(statsCol.dashTypeAndColor) }}" title="{{ statsCol.name }}"></div>
|
||||
</th>
|
||||
</tr>
|
||||
<tr *ngFor="let statsRow of stats.dataSeriesStats">
|
||||
<td><div class="{{ pointTypeClass(statsRow.dashTypeAndColor) }}" title="{{ statsRow.name }}"></div></td>
|
||||
<td *ngFor="let statsCol of stats.dataSeriesStats">
|
||||
{{ utils.toPercent(statsRow.average / statsCol.average) }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
30
pdb-js/src/app/plot-details/plot-details.component.scss
Normal file
30
pdb-js/src/app/plot-details/plot-details.component.scss
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
.plot-details-plotType {
|
||||
background-image: url(/assets/img/pointTypes.png);
|
||||
width: 9px;
|
||||
height: 7px;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
|
||||
.plot-details-plotType_0 {background-position-x: 0px;}
|
||||
.plot-details-plotType_1 {background-position-x: -10px;}
|
||||
.plot-details-plotType_2 {background-position-x: -20px;}
|
||||
.plot-details-plotType_3 {background-position-x: -30px;}
|
||||
.plot-details-plotType_4 {background-position-x: -40px;}
|
||||
.plot-details-plotType_5 {background-position-x: -50px;}
|
||||
.plot-details-plotType_6 {background-position-x: -60px;}
|
||||
.plot-details-plotType_7 {background-position-x: -70px;}
|
||||
.plot-details-plotType_8 {background-position-x: -80px;}
|
||||
.plot-details-plotType_9 {background-position-x: -90px;}
|
||||
.plot-details-plotType_10 {background-position-x:-100px;}
|
||||
.plot-details-plotType_11 {background-position-x:-110px;}
|
||||
.plot-details-plotType_12 {background-position-x:-120px;}
|
||||
|
||||
.plot-details-plotType_0051c2 {background-position-y: 0px;}
|
||||
.plot-details-plotType_bf8300 {background-position-y: -8px;}
|
||||
.plot-details-plotType_9400d3 {background-position-y: -16px;}
|
||||
.plot-details-plotType_00c254 {background-position-y: -24px;}
|
||||
.plot-details-plotType_e6e600 {background-position-y: -32px;}
|
||||
.plot-details-plotType_e51e10 {background-position-y: -40px;}
|
||||
.plot-details-plotType_57a1c2 {background-position-y: -48px;}
|
||||
.plot-details-plotType_bd36c2 {background-position-y: -56px;}
|
||||
24
pdb-js/src/app/plot-details/plot-details.component.ts
Normal file
24
pdb-js/src/app/plot-details/plot-details.component.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Component, OnInit, Input, Output, ViewChild, EventEmitter, ɵpublishDefaultGlobalUtils } from '@angular/core';
|
||||
import { DashTypeAndColor, PlotResponseStats } from '../plot.service';
|
||||
import { UtilService } from '../utils.service';
|
||||
|
||||
@Component({
|
||||
selector: 'pdb-plot-details',
|
||||
templateUrl: './plot-details.component.html',
|
||||
styleUrls: ['./plot-details.component.scss']
|
||||
})
|
||||
export class PlotDetailsComponent {
|
||||
|
||||
@Input()
|
||||
stats: PlotResponseStats;
|
||||
|
||||
constructor(public utils: UtilService){
|
||||
|
||||
}
|
||||
|
||||
pointTypeClass(typeAndColor: DashTypeAndColor): string {
|
||||
return "plot-details-plotType"
|
||||
+" plot-details-plotType_"+typeAndColor.pointType
|
||||
+" plot-details-plotType_"+typeAndColor.color.toLocaleLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,42 @@
|
||||
<div
|
||||
*ngIf="imageUrl"
|
||||
[style.cursor]="imageCursor"
|
||||
(mousedown)="dragStart($event)"
|
||||
(mousemove)="dragging($event)"
|
||||
(mouseup)="dragStop($event)"
|
||||
(mouseout)="dragAbort($event)"
|
||||
(wheel)="zoomByScroll($event)">
|
||||
<img
|
||||
*ngIf="imageUrl">
|
||||
<div
|
||||
*ngIf="!showStats"
|
||||
[style.cursor]="imageCursor"
|
||||
(mousedown)="dragStart($event)"
|
||||
(mousemove)="dragging($event)"
|
||||
(mouseup)="dragStop($event)"
|
||||
(mouseout)="dragAbort($event)"
|
||||
(wheel)="zoomByScroll($event)">
|
||||
<img
|
||||
id="result-image"
|
||||
src="{{imageUrl}}"
|
||||
/>
|
||||
<div
|
||||
id="zoom-in-slider"
|
||||
[style.display]="zoomInSliderStyleDisplay"
|
||||
[style.top]="zoomInSliderStyleTopMargin"
|
||||
[style.bottom]="zoomInSliderStyleBottomMargin"
|
||||
[style.left]="zoomInSliderStyleLeft"
|
||||
[style.width]="zoomInSliderStyleWidth"
|
||||
></div>
|
||||
/>
|
||||
<div class="top-right">
|
||||
<img
|
||||
id="plot-view-info"
|
||||
class="icon-small clickable"
|
||||
(click)="showDetails()"
|
||||
src="assets/img/exclamation-round.svg"
|
||||
title="show details" />
|
||||
</div>
|
||||
<div
|
||||
id="zoom-in-slider"
|
||||
[style.display]="zoomInSliderStyleDisplay"
|
||||
[style.top]="zoomInSliderStyleTopMargin"
|
||||
[style.bottom]="zoomInSliderStyleBottomMargin"
|
||||
[style.left]="zoomInSliderStyleLeft"
|
||||
[style.width]="zoomInSliderStyleWidth"
|
||||
></div>
|
||||
</div>
|
||||
<div *ngIf="showStats" class="plot-view-overlay">
|
||||
<pdb-plot-details [stats]="stats"></pdb-plot-details>
|
||||
<div class="top-right">
|
||||
<img
|
||||
class="icon-small clickable"
|
||||
(click)="hideDetails()"
|
||||
src="assets/img/close.svg"
|
||||
title="close" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,4 +8,15 @@ img {
|
||||
position: absolute;
|
||||
background: #ccc;
|
||||
opacity:0.4;
|
||||
}
|
||||
|
||||
|
||||
.plot-view-overlay {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 5px;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
background-color: white;
|
||||
box-shadow: 5px 5px 10px 0px #e0e0e0;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
|
||||
import { DataType, AxesTypes } from '../plot.service';
|
||||
import { DataType, AxesTypes, PlotResponseStats } from '../plot.service';
|
||||
|
||||
@Component({
|
||||
selector: 'pdb-plot-view',
|
||||
@@ -16,6 +16,7 @@ export class PlotViewComponent implements OnInit {
|
||||
|
||||
|
||||
imageUrl : string;
|
||||
stats : PlotResponseStats;
|
||||
|
||||
axes: AxesTypes;
|
||||
|
||||
@@ -38,6 +39,8 @@ export class PlotViewComponent implements OnInit {
|
||||
zoomInSliderStyleLeft = "0";
|
||||
zoomInSliderStyleWidth = "0";
|
||||
|
||||
showStats = false;
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
@@ -175,6 +178,14 @@ export class PlotViewComponent implements OnInit {
|
||||
this.zoomWithDateAnchor.emit(new DateAnchor(cursorPercentOfDateRange, zoomFactor));
|
||||
}
|
||||
}
|
||||
|
||||
showDetails() {
|
||||
this.showStats = true;
|
||||
}
|
||||
|
||||
hideDetails() {
|
||||
this.showStats = false;
|
||||
}
|
||||
}
|
||||
|
||||
export class SelectionRange {
|
||||
|
||||
@@ -30,11 +30,7 @@ export class PlotService {
|
||||
this.plotTypes.push(new PlotType("LAG", "Lag", "lag-plot", false, DataType.Other, DataType.Other));
|
||||
this.plotTypes.push(new PlotType("ACF", "ACF", "acf-plot", false, DataType.Other, DataType.Other));
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
}
|
||||
|
||||
getPlotTypes(): Array<PlotType> {
|
||||
return this.plotTypes.filter(plotType => plotType.active);
|
||||
}
|
||||
|
||||
38
pdb-js/src/app/utils.service.ts
Normal file
38
pdb-js/src/app/utils.service.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class UtilService {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
toPercent(percentage: number) : string{
|
||||
return (Math.round(percentage * 10000) / 100)+"%";
|
||||
}
|
||||
}
|
||||
@@ -65,4 +65,3 @@
|
||||
#plot-button-bar {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ export class VisualizationPageComponent implements OnInit {
|
||||
gallery(){
|
||||
const that = this;
|
||||
this.plotView.imageUrl = '';
|
||||
that.plotView.stats = null;
|
||||
that.galleryView.show=true;
|
||||
const request = this.createPlotRequest();
|
||||
this.galleryView.renderGallery(request, this.splitBy.name);
|
||||
@@ -132,6 +133,7 @@ export class VisualizationPageComponent implements OnInit {
|
||||
const that = this;
|
||||
|
||||
that.plotView.imageUrl = '';
|
||||
that.plotView.stats = null;
|
||||
this.plotView.axes = this.getAxes();
|
||||
console.log(JSON.stringify(this.getAxes()));
|
||||
that.galleryView.show=false;
|
||||
@@ -142,10 +144,12 @@ export class VisualizationPageComponent implements OnInit {
|
||||
this.plotService.sendPlotRequest(request).subscribe(function(plotResponse){
|
||||
console.log("response: " + JSON.stringify(plotResponse));
|
||||
that.plotView.imageUrl = "http://"+window.location.hostname+':'+window.location.port+'/'+plotResponse.imageUrl;
|
||||
that.plotView.stats = plotResponse.stats;
|
||||
document.dispatchEvent(new Event("invadersPause", {}));
|
||||
},
|
||||
error => {
|
||||
that.plotView.imageUrl = '';
|
||||
that.plotView.stats = null;
|
||||
that.showError(error.error.message);
|
||||
document.dispatchEvent(new Event("invadersPause", {}));
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user