add limit by
This commit is contained in:
@@ -10,12 +10,16 @@ import { MainPageComponent } from './main-page/main-page.component';
|
|||||||
import { HelpPageComponent } from './help-page/help-page.component';
|
import { HelpPageComponent } from './help-page/help-page.component';
|
||||||
import { UploadPageComponent } from './upload-page/upload-page.component';
|
import { UploadPageComponent } from './upload-page/upload-page.component';
|
||||||
import { VisualizationPageComponent } from './visualization-page/visualization-page.component';
|
import { VisualizationPageComponent } from './visualization-page/visualization-page.component';
|
||||||
|
|
||||||
|
import {MatAutocompleteModule} from '@angular/material/autocomplete';
|
||||||
|
import {MatButtonModule} from '@angular/material/button';
|
||||||
|
import {MatCheckboxModule} from '@angular/material/checkbox';
|
||||||
import {MatSelectModule} from '@angular/material/select';
|
import {MatSelectModule} from '@angular/material/select';
|
||||||
import {MatAutocompleteModule} from '@angular/material/autocomplete';
|
|
||||||
import {MatFormFieldModule, MatInputModule} from '@angular/material';
|
import {MatFormFieldModule, MatInputModule} from '@angular/material';
|
||||||
|
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||||
import { YAxisRangeComponent } from './y-axis-range/y-axis-range.component';
|
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';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -26,14 +30,20 @@ import { QueryAutocompleteComponent } from './query-autocomplete/query-autocompl
|
|||||||
VisualizationPageComponent,
|
VisualizationPageComponent,
|
||||||
YAxisRangeComponent,
|
YAxisRangeComponent,
|
||||||
QueryAutocompleteComponent,
|
QueryAutocompleteComponent,
|
||||||
|
LimitByComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatSelectModule,MatFormFieldModule, MatInputModule,
|
|
||||||
MatAutocompleteModule,
|
MatAutocompleteModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatCheckboxModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatSelectModule,
|
||||||
|
MatTooltipModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
HttpClientModule
|
HttpClientModule
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -13,14 +13,37 @@ This page describes how to use this tool.
|
|||||||
|
|
||||||
<h2>Why not use one of the existing monitoring tools?</h2>
|
<h2>Why not use one of the existing monitoring tools?</h2>
|
||||||
<p>
|
<p>
|
||||||
There are many tools out there that do monitoring in one way or the other. Here are a few:
|
There are many tools out there that do monitoring in one way or the other. There are complete closed source solutions like
|
||||||
<a href="https://newrelic.com" target="_blank" rel="nofollow" class="external-link">New Relic</a>,
|
<a href="https://newrelic.com" target="_blank" rel="nofollow" class="external-link">New Relic</a>,
|
||||||
<a href="https://www.splunk.com" target="_blank" rel="nofollow" class="external-link">Splunk</a>,
|
<a href="https://www.splunk.com" target="_blank" rel="nofollow" class="external-link">Splunk</a>,
|
||||||
|
and <a href="https://www.appdynamics.com/" target="_blank" rel="nofollow" class="external-link">App Dynamics</a>.
|
||||||
|
They bring everything you need, a tool to collect logs or metrics, a database, a UI with dashboards and alerting.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The OSS community likes to break them down into separate tools.
|
||||||
|
For example the <a href="https://www.elastic.co/products/elastic-stack" target="_blank" rel="nofollow" class="external-link">ELK</a>-stack
|
||||||
|
consists of <a href="https://www.elastic.co/products/elasticsearch" target="_blank" rel="nofollow" class="external-link">Elasticsearch</a>
|
||||||
|
as database, and <a href="https://www.elastic.co/products/kibana" target="_blank" rel="nofollow" class="external-link">Kibana</a>
|
||||||
|
as the UI. It is usually combined with <a href="https://www.elastic.co/products/logstash" target="_blank" rel="nofollow" class="external-link">Logstash</a>
|
||||||
|
for logfile collection.<br/>
|
||||||
|
Another popular UI is <a href="https://grafana.com/" target="_blank" rel="nofollow" class="external-link">Grafana</a>
|
||||||
|
which can be combined with
|
||||||
|
<a href="https://grafana.com/oss/loki/" target="_blank" rel="nofollow" class="external-link">Loki</a>,
|
||||||
|
<a href="https://prometheus.io/" target="_blank" rel="nofollow" class="external-link">Prometheus</a>,
|
||||||
|
<a href="https://graphiteapp.org/" target="_blank" rel="nofollow" class="external-link">Graphite</a> or
|
||||||
|
<a href="https://grafana.com/oss/metrictank/" target="_blank" rel="nofollow" class="external-link">Metrictank</a> (which is an engine for Graphite).
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/><br/>
|
||||||
<a href="https://www.elastic.co/products/kibana" target="_blank" rel="nofollow" class="external-link">Kibana</a> (<a href="https://www.elastic.co/products/elastic-stack" target="_blank" rel="nofollow" class="external-link">ELK</a>),
|
<a href="https://www.elastic.co/products/kibana" target="_blank" rel="nofollow" class="external-link">Kibana</a> (<a href="https://www.elastic.co/products/elastic-stack" target="_blank" rel="nofollow" class="external-link">ELK</a>),
|
||||||
<a href="https://www.appdynamics.com/" target="_blank" rel="nofollow" class="external-link">App Dynamics</a>,
|
<a href="https://www.appdynamics.com/" target="_blank" rel="nofollow" class="external-link">App Dynamics</a>,
|
||||||
<a href="https://graphiteapp.org/" target="_blank" rel="nofollow" class="external-link">Graphite</a>,
|
<a href="https://graphiteapp.org/" target="_blank" rel="nofollow" class="external-link">Graphite</a>
|
||||||
<a href="https://prometheus.io/" target="_blank" rel="nofollow" class="external-link">Prometheus</a>
|
(<a href="https://grafana.com/oss/metrictank/" target="_blank" rel="nofollow" class="external-link">Metrictank</a>),
|
||||||
+ <a href="https://grafana.com/" target="_blank" rel="nofollow" class="external-link">Grafana</a>,
|
<a href="https://prometheus.io/" target="_blank" rel="nofollow" class="external-link">Prometheus</a>,
|
||||||
|
<a href="https://grafana.com/oss/loki/" target="_blank" rel="nofollow" class="external-link">Loki</a>,
|
||||||
|
<a href="https://grafana.com/" target="_blank" rel="nofollow" class="external-link">Grafana</a>,
|
||||||
|
|
||||||
|
|
||||||
<a href="https://github.com/Netflix/atlas" target="_blank" rel="nofollow" class="external-link">Netflix Atlas</a>,
|
<a href="https://github.com/Netflix/atlas" target="_blank" rel="nofollow" class="external-link">Netflix Atlas</a>,
|
||||||
<a href="https://oss.oetiker.ch/rrdtool/" target="_blank" rel="nofollow" class="external-link">RRDtool</a>,
|
<a href="https://oss.oetiker.ch/rrdtool/" target="_blank" rel="nofollow" class="external-link">RRDtool</a>,
|
||||||
<a href="http://ganglia.sourceforge.net/" target="_blank" rel="nofollow" class="external-link">Ganglia</a>,
|
<a href="http://ganglia.sourceforge.net/" target="_blank" rel="nofollow" class="external-link">Ganglia</a>,
|
||||||
@@ -37,7 +60,8 @@ There are many tools out there that do monitoring in one way or the other. Here
|
|||||||
<a href="https://bleemeo.com/" target="_blank" rel="nofollow" class="external-link">Bleemo</a>,
|
<a href="https://bleemeo.com/" target="_blank" rel="nofollow" class="external-link">Bleemo</a>,
|
||||||
<a href="https://www.site24x7.com/" target="_blank" rel="nofollow" class="external-link">Site24x7</a>,
|
<a href="https://www.site24x7.com/" target="_blank" rel="nofollow" class="external-link">Site24x7</a>,
|
||||||
<a href="https://www.datadoghq.com/" target="_blank" rel="nofollow" class="external-link">Datadog</a>,
|
<a href="https://www.datadoghq.com/" target="_blank" rel="nofollow" class="external-link">Datadog</a>,
|
||||||
<a href="https://www.microfocus.com/en-us/products/sitescope-application-monitoring/overview" target="_blank" rel="nofollow" class="external-link">Sitescope</a>,
|
<a href="https://www.microfocus.com/en-us/products/sitescope-application-monitoring/overview" target="_blank" rel="nofollow" class="external-link">Sitescope</a>,
|
||||||
|
<a href="https://www.signalfx.com/" target="_blank" rel="nofollow" class="external-link">SignalFX</a>,
|
||||||
and many more. None of them provides the visualizations we had in mind. We wanted to plot each value of the time series data individually, so that we can identify the
|
and many more. None of them provides the visualizations we had in mind. We wanted to plot each value of the time series data individually, so that we can identify the
|
||||||
response times of a single request. But tools like Splunk, Kibana, Chronograf or Grafana only plot aggregated data (average, min/max, percentiles).
|
response times of a single request. But tools like Splunk, Kibana, Chronograf or Grafana only plot aggregated data (average, min/max, percentiles).
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
22
pdb-js/src/app/limit-by/limit-by.component.html
Normal file
22
pdb-js/src/app/limit-by/limit-by.component.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<mat-form-field id="limitBy">
|
||||||
|
<mat-label>Limit By:</mat-label>
|
||||||
|
<mat-select [(value)]="limitBy">
|
||||||
|
<mat-option value="NO_LIMIT">no limit</mat-option>
|
||||||
|
<mat-option value="MOST_VALUES">most values</mat-option>
|
||||||
|
<mat-option value="FEWEST_VALUES">fewest values</mat-option>
|
||||||
|
<mat-option value="MAX_VALUE">max value</mat-option>
|
||||||
|
<mat-option value="MIN_VALUE">min value</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field id="limit"
|
||||||
|
*ngIf="limitBy !== 'NO_LIMIT'">
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
type="number"
|
||||||
|
placeholder="Limit"
|
||||||
|
min="1"
|
||||||
|
value="{{limit}}"
|
||||||
|
|
||||||
|
>
|
||||||
|
</mat-form-field>
|
||||||
9
pdb-js/src/app/limit-by/limit-by.component.scss
Normal file
9
pdb-js/src/app/limit-by/limit-by.component.scss
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#limitBy {
|
||||||
|
width: 10em;
|
||||||
|
margin-right: 1ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#limit {
|
||||||
|
width: 5em;
|
||||||
|
margin-right: 0ex;
|
||||||
|
}
|
||||||
25
pdb-js/src/app/limit-by/limit-by.component.spec.ts
Normal file
25
pdb-js/src/app/limit-by/limit-by.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { LimitByComponent } from './limit-by.component';
|
||||||
|
|
||||||
|
describe('LimitByComponent', () => {
|
||||||
|
let component: LimitByComponent;
|
||||||
|
let fixture: ComponentFixture<LimitByComponent>;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ LimitByComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(LimitByComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
18
pdb-js/src/app/limit-by/limit-by.component.ts
Normal file
18
pdb-js/src/app/limit-by/limit-by.component.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Component, OnInit, Input} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'pdb-limit-by',
|
||||||
|
templateUrl: './limit-by.component.html',
|
||||||
|
styleUrls: ['./limit-by.component.scss']
|
||||||
|
})
|
||||||
|
export class LimitByComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() limit: number;
|
||||||
|
|
||||||
|
@Input() limitBy: string;
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,6 @@ export class PlotService {
|
|||||||
this.plotTypes.push(new PlotType("Bar", "bar-chart", false, DataType.Other, DataType.Other));
|
this.plotTypes.push(new PlotType("Bar", "bar-chart", false, DataType.Other, DataType.Other));
|
||||||
|
|
||||||
this.tagFields = new Array<TagField>();
|
this.tagFields = new Array<TagField>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
placeholder="Query"
|
placeholder="Query"
|
||||||
[formControl]="query"
|
[formControl]="query"
|
||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
(keyup)="onKey($event)"/>
|
(keyup)="onKey($event)"
|
||||||
|
(focus)="onKey($event)"/>
|
||||||
<mat-autocomplete
|
<mat-autocomplete
|
||||||
#auto="matAutocomplete"
|
#auto="matAutocomplete"
|
||||||
[displayWith]="displaySuggestion"
|
[displayWith]="displaySuggestion"
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
.mat-option {
|
||||||
|
/*height: 1.5em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
/**/
|
||||||
|
}
|
||||||
|
|
||||||
|
#query-autocomplete-input {
|
||||||
|
border: solid 1px #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import { PlotService, PlotType, AutocompleteResult, Suggestion } from '../plot.s
|
|||||||
})
|
})
|
||||||
export class QueryAutocompleteComponent implements OnInit {
|
export class QueryAutocompleteComponent implements OnInit {
|
||||||
|
|
||||||
@Input() query = new FormControl();
|
@Input() query = new FormControl('');
|
||||||
|
|
||||||
suggestions = new FormControl();
|
suggestions = new FormControl();
|
||||||
|
|
||||||
|
|||||||
@@ -1,80 +1,92 @@
|
|||||||
<style>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="visualization">
|
<div id="visualization">
|
||||||
<div id="query-box">
|
<div id="query-box">
|
||||||
<!-- [query]="query"-->
|
|
||||||
<pdb-query-autocomplete ></pdb-query-autocomplete>
|
<pdb-query-autocomplete ></pdb-query-autocomplete>
|
||||||
</div>
|
</div>
|
||||||
<div id="filters">
|
<div id="filters">
|
||||||
<mat-form-field class="mat-field-full-width">
|
<div id="filterpanel">
|
||||||
<mat-label>Date Range:</mat-label>
|
<mat-form-field class="mat-field-full-width">
|
||||||
<input matInput [formControl]="dateRange" name="dates" />
|
<mat-label>Date Range:</mat-label>
|
||||||
</mat-form-field>
|
<input matInput [formControl]="dateRange" name="dates" />
|
||||||
|
</mat-form-field>
|
||||||
<mat-form-field class="mat-field-full-width">
|
|
||||||
<mat-label>Type:</mat-label>
|
|
||||||
<mat-select [formControl]="selectedPlotType">
|
|
||||||
<mat-option *ngFor="let plotType of plotTypes" [value]="plotType.name">
|
|
||||||
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field>
|
|
||||||
<mat-label>Combine with:</mat-label>
|
|
||||||
<mat-select [(value)]="selectedCombinePlotType">
|
|
||||||
<mat-option>-</mat-option>
|
|
||||||
<mat-option *ngFor="let plotType of combinePlotTypes" [value]="plotType.name">
|
|
||||||
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field>
|
|
||||||
<mat-label>Group By:</mat-label>
|
|
||||||
<mat-select multiple>
|
|
||||||
<mat-option *ngFor="let tagField of tagFields" [value]="tagField">{{tagField.name}}</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field class="mat-field-full-width">
|
||||||
<mat-label>Split By:</mat-label>
|
<mat-label>Type:</mat-label>
|
||||||
<mat-select>
|
<mat-select [formControl]="selectedPlotType">
|
||||||
<mat-option>-</mat-option>
|
<mat-option *ngFor="let plotType of plotTypes" [value]="plotType.name">
|
||||||
<mat-option *ngFor="let tagField of tagFields" [value]="tagField">{{tagField.name}}</mat-option>
|
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
|
||||||
</mat-select>
|
</mat-option>
|
||||||
</mat-form-field>
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-label>Y-Axis:</mat-label>
|
<mat-label>Combine with:</mat-label>
|
||||||
<mat-select [(value)]="yAxis">
|
<mat-select [(value)]="selectedCombinePlotType">
|
||||||
<mat-option value="log">Logarithm</mat-option>
|
<mat-option>-</mat-option>
|
||||||
<mat-option value="linear">Linear</mat-option>
|
<mat-option *ngFor="let plotType of combinePlotTypes" [value]="plotType.name">
|
||||||
</mat-select>
|
<img src="assets/img/{{plotType.icon}}.svg" class="icon-select" /> {{plotType.name}}
|
||||||
</mat-form-field>
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
<pdb-y-axis-range
|
</mat-form-field>
|
||||||
[(yAxisUnit)]="yAxisUnit"
|
|
||||||
[(minYValue)]="minYValue"
|
|
||||||
[(maxYValue)]="maxYValue"
|
|
||||||
></pdb-y-axis-range>
|
|
||||||
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button mat-button (click)="plot()">
|
|
||||||
<img src="assets/img/scatter-chart2.svg" class="icon-inline" aria-hidden="true" title="create plot" />
|
|
||||||
Plot
|
|
||||||
</button>
|
|
||||||
<!--
|
|
||||||
<button mat-button (click)="gallery()">
|
|
||||||
<img src="assets/img/four-squares-line.svg" class="icon-inline" aria-hidden="true" title="Create Gallery (only active if 'Split' is set)" />
|
|
||||||
Gallery
|
|
||||||
</button>
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Group By:</mat-label>
|
||||||
|
<mat-select multiple [(value)]="groupBy">
|
||||||
|
<mat-option *ngFor="let tagField of tagFields" [value]="tagField">{{tagField.name}}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<pdb-limit-by
|
||||||
|
[(limitBy)]="limitBy"
|
||||||
|
[limit]="limit"
|
||||||
|
></pdb-limit-by>
|
||||||
|
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Y-Axis:</mat-label>
|
||||||
|
<mat-select [(value)]="yAxis">
|
||||||
|
<mat-option value="log">Logarithm</mat-option>
|
||||||
|
<mat-option value="linear">Linear</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<pdb-y-axis-range
|
||||||
|
[(yAxisUnit)]="yAxisUnit"
|
||||||
|
[(minYValue)]="minYValue"
|
||||||
|
[(maxYValue)]="maxYValue"
|
||||||
|
></pdb-y-axis-range>
|
||||||
|
|
||||||
|
|
||||||
|
<mat-checkbox [(ngModel)]="enableGallery">Gallery</mat-checkbox>
|
||||||
|
|
||||||
|
<mat-form-field *ngIf="enableGallery">
|
||||||
|
<mat-label>Split By:</mat-label>
|
||||||
|
<mat-select [(value)]="splitBy">
|
||||||
|
<mat-option *ngFor="let tagField of tagFields" [value]="tagField">{{tagField.name}}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
<mat-error *ngIf="splitBy == null || true">
|
||||||
|
Please select a value!
|
||||||
|
</mat-error>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="plot-button-bar">
|
||||||
|
<button
|
||||||
|
*ngIf="!enableGallery"
|
||||||
|
mat-button
|
||||||
|
matTooltip="Create Plot"
|
||||||
|
(click)="plot()">
|
||||||
|
<img src="assets/img/scatter-chart2.svg" class="icon-inline" aria-hidden="true" title="create plot" />
|
||||||
|
Plot
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
*ngIf="enableGallery"
|
||||||
|
mat-button
|
||||||
|
matTooltip="Create Gallery"
|
||||||
|
(click)="plot()"
|
||||||
|
[disabled]="this.splitBy == null">
|
||||||
|
<img src="assets/img/four-squares-line.svg" class="icon-inline" aria-hidden="true" title="Create Gallery (only active if 'Split' is set)" />
|
||||||
|
Gallery
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="results"></div>
|
<div id="results"></div>
|
||||||
|
|||||||
@@ -14,14 +14,13 @@
|
|||||||
grid:
|
grid:
|
||||||
"query-box query-box" auto
|
"query-box query-box" auto
|
||||||
"filters results" 1fr
|
"filters results" 1fr
|
||||||
/ 23em 3fr;
|
/ 25em 3fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 800px) {
|
@media screen and (max-width: 1000px) {
|
||||||
#visualization {
|
#visualization {
|
||||||
display: grid;
|
display: grid;
|
||||||
height: 100%;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
grid:
|
grid:
|
||||||
"query-box" auto
|
"query-box" auto
|
||||||
@@ -29,22 +28,31 @@
|
|||||||
"results" 1fr
|
"results" 1fr
|
||||||
/ 1fr;
|
/ 1fr;
|
||||||
}
|
}
|
||||||
|
#results {
|
||||||
|
height: 600px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#query-box {
|
#query-box {
|
||||||
grid-area: query-box;
|
grid-area: query-box;
|
||||||
padding: 2px;
|
margin: 1em;
|
||||||
border-bottom: 1px solid black;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#filters {
|
#filters {
|
||||||
grid-area: filters;
|
grid-area: filters;
|
||||||
background-color: #fafafa;
|
}
|
||||||
|
#filterpanel {
|
||||||
|
background-color: #f8f8f8;/*#fafafa;*/
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
margin: 0 1em 1em 1em;
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#results {
|
#results {
|
||||||
grid-area: results;
|
grid-area: results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#plot-button-bar {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { PlotService, PlotType } from '../plot.service';
|
import { PlotService, PlotType } from '../plot.service';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { FormControl } from '@angular/forms';
|
import { FormControl, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pdb-visualization-page',
|
selector: 'pdb-visualization-page',
|
||||||
@@ -22,12 +23,22 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
|
|
||||||
tagFields: Array<any>;
|
tagFields: Array<any>;
|
||||||
|
|
||||||
|
groupBy: Array<any> = [];
|
||||||
|
limitBy: string = "NO_LIMIT";
|
||||||
|
limit = 10;
|
||||||
|
|
||||||
yAxis: string;
|
yAxis: string;
|
||||||
yAxisUnit: string;
|
yAxisUnit: string;
|
||||||
minYValue: number;
|
minYValue: number;
|
||||||
maxYValue: number;
|
maxYValue: number;
|
||||||
|
|
||||||
query: string;
|
query: string;
|
||||||
|
|
||||||
|
|
||||||
|
enableGallery = true;
|
||||||
|
splitBy = new FormControl(null, [
|
||||||
|
Validators.required
|
||||||
|
]);
|
||||||
|
|
||||||
constructor(private plotService: PlotService) {
|
constructor(private plotService: PlotService) {
|
||||||
}
|
}
|
||||||
@@ -47,24 +58,38 @@ export class VisualizationPageComponent implements OnInit {
|
|||||||
this.yAxisUnit = "MINUTES";
|
this.yAxisUnit = "MINUTES";
|
||||||
this.minYValue = 0;
|
this.minYValue = 0;
|
||||||
this.maxYValue = 120;
|
this.maxYValue = 120;
|
||||||
|
|
||||||
|
|
||||||
this.selectedPlotType.valueChanges.subscribe(function(selectedMainPlotType){
|
this.selectedPlotType.valueChanges.subscribe(function(selectedMainPlotType){
|
||||||
that.combinePlotTypes = that.getCombinablePlotTypes(selectedMainPlotType);
|
that.combinePlotTypes = that.getCombinablePlotTypes(selectedMainPlotType);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getCombinablePlotTypes(selectedMainPlotType) : Array<any>{
|
getCombinablePlotTypes(selectedMainPlotType) : Array<any>{
|
||||||
// get compatible plot types
|
|
||||||
const mainPlotType = this.availablePlotTypes[selectedMainPlotType];
|
const mainPlotType = this.availablePlotTypes[selectedMainPlotType];
|
||||||
|
|
||||||
const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(mainPlotType));
|
const compatiblePlotTypes = this.plotTypes.filter(pt => pt.compatible(mainPlotType));
|
||||||
console.log(compatiblePlotTypes);
|
|
||||||
return compatiblePlotTypes;
|
return compatiblePlotTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
plot(){
|
plot(){
|
||||||
console.log("plot clicked");
|
|
||||||
|
var request = {};
|
||||||
|
request['query'] = this.query;
|
||||||
|
request['height'] = document.getElementById("results").offsetHeight;
|
||||||
|
request['width'] = document.getElementById("results").offsetWidth;
|
||||||
|
request['groupBy'] = this.groupBy.map(o => o.name);
|
||||||
|
request['limitBy'] = this.limitBy;
|
||||||
|
request['limit'] = this.limit;
|
||||||
|
request['dateRange'] = this.dateRange.value;
|
||||||
|
request['axisScale'] = this.yAxis;
|
||||||
|
request['aggregate'] = this.selectedCombinePlotType.value;
|
||||||
|
request['keyOutside'] = false;
|
||||||
|
request['generateThumbnail'] = this.enableGallery;
|
||||||
|
request['yRangeMin'] = this.minYValue;
|
||||||
|
request['yRangeMax'] = this.maxYValue;
|
||||||
|
request['yRangeUnit'] = this.yAxisUnit;
|
||||||
|
|
||||||
|
console.log("plot clicked: "+ JSON.stringify(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
<mat-form-field>
|
<div>
|
||||||
<input matInput type="number" placeholder="Min Y-Value" min="0" value="{{minYValue}}">
|
<mat-form-field>
|
||||||
</mat-form-field>
|
<input matInput type="number" placeholder="Min Y-Value" min="0" value="{{minYValue}}">
|
||||||
<mat-form-field>
|
</mat-form-field>
|
||||||
<input matInput type="number" placeholder="Max Y-Value" min="0" value="{{maxYValue}}">
|
<mat-form-field>
|
||||||
</mat-form-field>
|
<input matInput type="number" placeholder="Max Y-Value" min="0" value="{{maxYValue}}">
|
||||||
<mat-form-field class="yAxisUnit">
|
</mat-form-field>
|
||||||
<mat-label>Unit:</mat-label>
|
<mat-form-field class="yAxisUnit">
|
||||||
<mat-select [(value)]="yAxisUnit">
|
<mat-label>Unit:</mat-label>
|
||||||
<mat-option value="AUTOMATIC">automatic</mat-option>
|
<mat-select [(value)]="yAxisUnit">
|
||||||
<mat-option value="MILLISECONDS">milli seconds</mat-option>
|
<mat-option value="AUTOMATIC">automatic</mat-option>
|
||||||
<mat-option value="SECONDS">seconds</mat-option>
|
<mat-option value="MILLISECONDS">milli seconds</mat-option>
|
||||||
<mat-option value="MINUTES">minutes</mat-option>
|
<mat-option value="SECONDS">seconds</mat-option>
|
||||||
<mat-option value="HOURS">hours</mat-option>
|
<mat-option value="MINUTES">minutes</mat-option>
|
||||||
<mat-option value="DAYS">days</mat-option>
|
<mat-option value="HOURS">hours</mat-option>
|
||||||
</mat-select>
|
<mat-option value="DAYS">days</mat-option>
|
||||||
</mat-form-field>
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ body {
|
|||||||
vertical-align: text-bottom;
|
vertical-align: text-bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button[disabled] .icon-inline {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-small {
|
.icon-small {
|
||||||
width: 1.5em;
|
width: 1.5em;
|
||||||
height: 1.5em;
|
height: 1.5em;
|
||||||
@@ -65,6 +69,9 @@ a.external-link:after {
|
|||||||
content: "";
|
content: "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inline {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
body .mat-select-panel {
|
body .mat-select-panel {
|
||||||
@@ -78,3 +85,5 @@ body .mat-select-panel {
|
|||||||
mat-form-field {
|
mat-form-field {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user