dashboard #1

Merged
andi merged 118 commits from dashboard into master 2024-09-29 06:47:35 +00:00
19 changed files with 114 additions and 55 deletions
Showing only changes of commit fb5c8ea019 - Show all commits

View File

@@ -1,13 +1,7 @@
<div id="main-toolbar"> <div id="main-toolbar">
<!-- <button mat-button [routerLink]="['/']"><img src="assets/img/scatter-chart2.svg" aria-hidden="false" aria-label="go to home page" /> Plotilio</button>
<a href="/">Home</a>
<a href="/"><img src="assets/img/home.svg" aria-hidden="false" aria-label="go to home page" /></a>
<a href="/vis" aria-label="go to visualization page">Visualization</a>
<a href="/dashboard" aria-label="go to dashboard page">Dashboards</a>
-->
<button mat-button [routerLink]="['/']"><img src="assets/img/home.svg" aria-hidden="false" aria-label="go to home page" /></button>
<button mat-button [routerLink]="['/vis']">Visualization</button> <button mat-button [routerLink]="['/vis']">Visualization</button>
<button mat-button [routerLink]="['/dashboard']">Dashboards</button> <button mat-button [routerLink]="['/dashboard']">Dashboards</button>
</div> </div>

View File

@@ -37,6 +37,7 @@ import { DashboardComponent } from './dashboard-page/dashboard/dashboard.compone
import { AddTextDialogComponent } from './dashboard-page/dashboard/add-text-dialog/add-text-dialog.component'; import { AddTextDialogComponent } from './dashboard-page/dashboard/add-text-dialog/add-text-dialog.component';
import { TextWidgetComponent } from './dashboard-page/dashboard/text-widget/text-widget.component'; import { TextWidgetComponent } from './dashboard-page/dashboard/text-widget/text-widget.component';
import { AddPlotDialogComponent } from './dashboard-page/dashboard/add-plot-dialog/add-plot-dialog.component'; import { AddPlotDialogComponent } from './dashboard-page/dashboard/add-plot-dialog/add-plot-dialog.component';
import { PlotWidgetComponent } from './dashboard-page/dashboard/plot-widget/plot-widget.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
@@ -59,7 +60,8 @@ import { AddPlotDialogComponent } from './dashboard-page/dashboard/add-plot-dial
DashboardComponent, DashboardComponent,
AddTextDialogComponent, AddTextDialogComponent,
TextWidgetComponent, TextWidgetComponent,
AddPlotDialogComponent AddPlotDialogComponent,
PlotWidgetComponent
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@@ -14,7 +14,7 @@
</style> </style>
<h1 mat-dialog-title>Add Plot</h1> <h1 mat-dialog-title>Add Plot</h1>
<pdb-visualization-page mat-dialog-content></pdb-visualization-page> <pdb-visualization-page mat-dialog-content #plot></pdb-visualization-page>
<div mat-dialog-actions align="end"> <div mat-dialog-actions align="end">
<button mat-button mat-dialog-close>Cancel</button> <button mat-button mat-dialog-close>Cancel</button>

View File

@@ -1,5 +1,6 @@
import { Component, ElementRef, ViewChild } from '@angular/core'; import { Component, ElementRef, ViewChild } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog'; import { MatDialogRef } from '@angular/material/dialog';
import { VisualizationPageComponent } from 'src/app/visualization-page/visualization-page.component';
@Component({ @Component({
selector: 'app-add-plot-dialog', selector: 'app-add-plot-dialog',
@@ -8,10 +9,13 @@ import { MatDialogRef } from '@angular/material/dialog';
}) })
export class AddPlotDialogComponent { export class AddPlotDialogComponent {
@ViewChild("plot") plotElement! :VisualizationPageComponent;
constructor(public dialogRef: MatDialogRef<string>){ constructor(public dialogRef: MatDialogRef<string>){
} }
onSaveClick(): void { onSaveClick(): void {
this.dialogRef.close("todo"); const config = this.plotElement.createPlotConfig();
this.dialogRef.close(config);
} }
} }

View File

@@ -1,3 +1,20 @@
<style>
:host {
width: 100%;
height: 100%;
}
.spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.content {
padding: 0.5em;
}
</style>
<div *ngIf="dashboard === undefined" class="spinner"> <div *ngIf="dashboard === undefined" class="spinner">
<mat-spinner></mat-spinner> <mat-spinner></mat-spinner>
</div> </div>
@@ -11,4 +28,5 @@
<p>{{dashboard.description}}</p> <p>{{dashboard.description}}</p>
<app-text-widget *ngFor="let textWidget of dashboard.texts" [text]="textWidget.text"></app-text-widget> <app-text-widget *ngFor="let textWidget of dashboard.texts" [text]="textWidget.text"></app-text-widget>
<app-plot-widget *ngFor="let plotWidget of dashboard.plots" [data]="plotWidget"></app-plot-widget>
</div> </div>

View File

@@ -1,15 +0,0 @@
:host {
width: 100%;
height: 100%;
}
.spinner {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.content {
padding: 0.5em;
}

View File

@@ -2,14 +2,14 @@ import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'; import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Dashboard, DashboardService, TextWidget } from 'src/app/dashboard.service'; import { Dashboard, DashboardService, PlotWidget, TextWidget } from 'src/app/dashboard.service';
import { PlotConfig } from 'src/app/plot.service';
import { AddPlotDialogComponent } from './add-plot-dialog/add-plot-dialog.component'; import { AddPlotDialogComponent } from './add-plot-dialog/add-plot-dialog.component';
import { AddTextDialogComponent } from './add-text-dialog/add-text-dialog.component'; import { AddTextDialogComponent } from './add-text-dialog/add-text-dialog.component';
@Component({ @Component({
selector: 'app-dashboard', selector: 'app-dashboard',
templateUrl: './dashboard.component.html', templateUrl: './dashboard.component.html'
styleUrls: ['./dashboard.component.scss']
}) })
export class DashboardComponent implements OnInit { export class DashboardComponent implements OnInit {
@@ -34,9 +34,9 @@ export class DashboardComponent implements OnInit {
addPlot() { addPlot() {
this.dialog.open(AddPlotDialogComponent,{ this.dialog.open(AddPlotDialogComponent,{
width: 'calc(100% - 1em)', width: 'calc(100% - 1em)',
//height: 'calc(100% - 1em)' height: 'calc(100% - 1em)'
}).afterClosed().subscribe((text: string) => { }).afterClosed().subscribe((config: PlotConfig) => {
//this.dashboard!.texts.push(new TextWidget('MEDIUM', text)); this.dashboard!.plots.push(new PlotWidget('MEDIUM', config));
}); });
} }

View File

@@ -0,0 +1,4 @@
<style>
</style>
<p>{{data.config.query}}</p>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PlotWidgetComponent } from './plot-widget.component';
describe('PlotWidgetComponent', () => {
let component: PlotWidgetComponent;
let fixture: ComponentFixture<PlotWidgetComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ PlotWidgetComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(PlotWidgetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,13 @@
import { Component, Input } from '@angular/core';
import { PlotWidget } from 'src/app/dashboard.service';
@Component({
selector: 'app-plot-widget',
templateUrl: './plot-widget.component.html'
})
export class PlotWidgetComponent {
@Input("data")
data!: PlotWidget;
}

View File

@@ -1,6 +1,7 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { PlotConfig } from './plot.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -32,7 +33,7 @@ export class DashboardCreationData{
} }
export class Dashboard{ export class Dashboard{
constructor(public id: string, public name: string, public description: string, public texts: [TextWidget]){} constructor(public id: string, public name: string, public description: string, public texts: TextWidget[], public plots: PlotWidget[]){}
} }
export class DashboardList{ export class DashboardList{
@@ -49,7 +50,7 @@ export class TextWidget extends BaseWidget {
} }
} }
export class PlotWidget extends BaseWidget { export class PlotWidget extends BaseWidget {
constructor(override size: 'SMALL'|'MEDIUM'|'LARGE') { constructor(override size: 'SMALL'|'MEDIUM'|'LARGE', public config: PlotConfig) {
super('PLOT', size); super('PLOT', size);
} }
} }

View File

@@ -1,7 +1,7 @@
:host{ :host{
font-weight: bold; font-weight: bold;
width: 100%; width: 100%;
height: calc(100% - 29px); height: calc(100% - 43px);
position: absolute; position: absolute;
display: grid; display: grid;
} }

View File

@@ -181,13 +181,12 @@ export class VisualizationPageComponent implements OnInit {
}); });
} }
createPlotRequest(): PlotRequest { createPlotConfig(): PlotConfig {
const aggregates = new Array<string>(); const aggregates = new Array<string>();
this.selectedPlotType.forEach(a => aggregates.push(a.id)); this.selectedPlotType.forEach(a => aggregates.push(a.id));
const y1 = this.y1AxisDefinitionComponent.getAxisDefinition(); const y1 = this.y1AxisDefinitionComponent.getAxisDefinition();
const y2 = this.y2AxisDefinitionComponent ? this.y2AxisDefinitionComponent.getAxisDefinition() : undefined; const y2 = this.y2AxisDefinitionComponent ? this.y2AxisDefinitionComponent.getAxisDefinition() : undefined;
const results = document.getElementById("results");
const config = new PlotConfig( const config = new PlotConfig(
this.query.query, this.query.query,
@@ -202,6 +201,13 @@ export class VisualizationPageComponent implements OnInit {
this.intervalValue, this.intervalValue,
this.renderBarChartTickLabels, this.renderBarChartTickLabels,
); );
return config;
}
createPlotRequest(): PlotRequest {
const results = document.getElementById("results");
const config = this.createPlotConfig();
const request = new PlotRequest( const request = new PlotRequest(
results != null ? results.offsetHeight-1: 1024, results != null ? results.offsetHeight-1: 1024,

View File

@@ -45,8 +45,8 @@ public class ScatterAggregator implements CustomAggregator {
final YAxisDefinition yAxisDefinition = plotSettings.getyAxisDefinition(yAxis); final YAxisDefinition yAxisDefinition = plotSettings.getyAxisDefinition(yAxis);
final boolean automaticRange = yAxisDefinition.getRangeUnit().isAutomatic(); final boolean automaticRange = yAxisDefinition.getRangeUnit().isAutomatic();
minValue = automaticRange ? 0 : yAxisDefinition.getRangeMinForUnit(); minValue = automaticRange ? 0 : yAxisDefinition.rangeMinForUnit();
maxValue = automaticRange ? Long.MAX_VALUE : yAxisDefinition.getRangeMaxForUnit(); maxValue = automaticRange ? Long.MAX_VALUE : yAxisDefinition.rangeMaxForUnit();
valuesPerPixel = yAxisDefinition.getAxisScale() == AxisScale.LINEAR && !automaticRange valuesPerPixel = yAxisDefinition.getAxisScale() == AxisScale.LINEAR && !automaticRange
? Math.max(1, (maxValue - minValue) / plotAreaHeightInPx) ? Math.max(1, (maxValue - minValue) / plotAreaHeightInPx)
: 1; : 1;

View File

@@ -15,11 +15,11 @@ public class YAxisDefinition {
this.axisScale = axisScale; this.axisScale = axisScale;
} }
public long getRangeMinForUnit() { public long rangeMinForUnit() {
return rangeUnit.valueForUnit(rangeMin); return rangeUnit.valueForUnit(rangeMin);
} }
public long getRangeMaxForUnit() { public long rangeMaxForUnit() {
return rangeUnit.valueForUnit(rangeMax); return rangeUnit.valueForUnit(rangeMax);
} }
@@ -51,8 +51,4 @@ public class YAxisDefinition {
this.rangeUnit = rangeUnit; this.rangeUnit = rangeUnit;
} }
public boolean isLogscale() {
return axisScale == AxisScale.LOG10;
}
} }

View File

@@ -52,15 +52,15 @@ public class AxisTime {
final int graphOffset = yAxisDefinition.getAxisScale() == AxisScale.LINEAR ? 0 : 1; final int graphOffset = yAxisDefinition.getAxisScale() == AxisScale.LINEAR ? 0 : 1;
if (yAxisDefinition.hasRange()) { if (yAxisDefinition.hasRange()) {
final long min = Math.max(yAxisDefinition.getRangeMinForUnit(), graphOffset); final long min = Math.max(yAxisDefinition.rangeMinForUnit(), graphOffset);
final long max = yAxisDefinition.getRangeMaxForUnit(); final long max = yAxisDefinition.rangeMaxForUnit();
result.setFrom(String.valueOf(min)); result.setFrom(String.valueOf(min));
result.setTo(String.valueOf(max)); result.setTo(String.valueOf(max));
} else { } else {
result.setFrom(String.valueOf(graphOffset)); result.setFrom(String.valueOf(graphOffset));
} }
result.setLogscale(yAxisDefinition.isLogscale()); result.setLogscale(yAxisDefinition.getAxisScale() == AxisScale.LOG10);
result.setTics(YAxisTicks.computeYTicks(settings, yAxis, dataSeries)); result.setTics(YAxisTicks.computeYTicks(settings, yAxis, dataSeries));
result.setShowGrid(yAxis == GnuplotAxis.Y1); result.setShowGrid(yAxis == GnuplotAxis.Y1);

View File

@@ -25,8 +25,8 @@ class YAxisTicks {
final long yRangeMax; final long yRangeMax;
final long yRangeMin; final long yRangeMin;
if (yAxisDefinition.hasRange()) { if (yAxisDefinition.hasRange()) {
yRangeMin = yAxisDefinition.getRangeMinForUnit(); yRangeMin = yAxisDefinition.rangeMinForUnit();
yRangeMax = yAxisDefinition.getRangeMaxForUnit(); yRangeMax = yAxisDefinition.rangeMaxForUnit();
} else { } else {
yRangeMin = 0; yRangeMin = 0;
yRangeMax = DataSeries.maxValue(dataSeries); yRangeMax = DataSeries.maxValue(dataSeries);

View File

@@ -22,6 +22,8 @@ public class Dashboard {
private List<TextWidget> texts = new ArrayList<>(); private List<TextWidget> texts = new ArrayList<>();
private List<PlotWidget> plots = new ArrayList<>();
public Dashboard() { public Dashboard() {
super(); super();
@@ -68,4 +70,11 @@ public class Dashboard {
this.texts = texts; this.texts = texts;
} }
public void setPlots(final List<PlotWidget> plots) {
this.plots = plots;
}
public List<PlotWidget> getPlots() {
return plots;
}
} }

View File

@@ -1,12 +1,16 @@
package org.lucares.pdbui.dashboard; package org.lucares.pdbui.dashboard;
import org.lucares.pdbui.domain.PlotConfig;
public class PlotWidget extends BaseDashboardWidget { public class PlotWidget extends BaseDashboardWidget {
public PlotWidget() { private PlotConfig config;
super();
public PlotConfig getConfig() {
return config;
} }
public PlotWidget(final DashboardWidgetSize size) { public void setConfig(final PlotConfig config) {
super(DashboardWidgetType.PLOT, size); this.config = config;
} }
} }