working on dashboard
* borrow-duration is fix * to and from is fix * map-load with marker is fix missing: dashboard-chart-borrow-time
This commit is contained in:
parent
8dd31f3703
commit
678272ef8a
@ -18,23 +18,40 @@
|
||||
</mat-toolbar>
|
||||
<mat-sidenav-container class="sidenav-container">
|
||||
<mat-sidenav #sidenav class="sidenav" mode="side" opened role="region">
|
||||
<mat-form-field appearance="fill" class="datepicker-start" fxLayout="column" fxLayoutAlign="center center">
|
||||
<mat-label>Start der Zeitmessung</mat-label>
|
||||
<input (dateChange)="addStartDate('input', $event)"
|
||||
[matDatepicker]="picker" [max]="maxEndDate"
|
||||
[min]="maxStartDate" matInput>
|
||||
<form [formGroup]="form">
|
||||
<mat-form-field appearance="fill" class="datepicker" fxLayout="column" fxLayoutAlign="center center">
|
||||
<mat-label>Enter a range</mat-label>
|
||||
<mat-date-range-input [max]="maxEndDate" [min]="maxStartDate" [rangePicker]="picker" formGroupName="daterange">
|
||||
<input formControlName="start" matStartDate placeholder="Start date">
|
||||
<input formControlName="end" matEndDate placeholder="End date">
|
||||
</mat-date-range-input>
|
||||
<mat-datepicker-toggle [for]="picker" matSuffix></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="fill" class="datepicker-end" fxLayout="column" fxLayoutAlign="center center">
|
||||
<mat-label>Ende der Zeitmessung</mat-label>
|
||||
<input (dateChange)="addEndDate('input', $event)"
|
||||
[matDatepicker]="picker1" [max]="maxEndDate" [min]="maxStartDate" matInput>
|
||||
<mat-datepicker-toggle [for]="picker1" matSuffix></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker1></mat-datepicker>
|
||||
<mat-date-range-picker #picker></mat-date-range-picker>
|
||||
</mat-form-field>
|
||||
</form>
|
||||
<div class="submit-date" fxLayout="row" fxLayoutAlign="center">
|
||||
<button (click)="onSubmit()" color="primary" mat-raised-button>
|
||||
<mat-icon>dashboard</mat-icon>
|
||||
<span id="submit-date-span"> reload dashboard</span>
|
||||
</button>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content>
|
||||
<div class="container containter-map"
|
||||
fxLayout
|
||||
fxLayout.xs="column"
|
||||
fxLayoutAlign="center"
|
||||
fxLayoutGap="10px"
|
||||
fxLayoutGap.xs="0"
|
||||
>
|
||||
<div class="mini-map"
|
||||
fxFlex
|
||||
>
|
||||
<div class="map-frame" fxFlex>
|
||||
<div fxFill id="map"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container container-top"
|
||||
fxLayout
|
||||
fxLayout.xs="column"
|
||||
@ -43,32 +60,76 @@
|
||||
fxLayoutGap.xs="0"
|
||||
>
|
||||
<div class="dashboard-table-to"
|
||||
fxFlex="35%"
|
||||
fxFlex="40%"
|
||||
>
|
||||
<table [dataSource]="stationToSource" class="mat-elevation-z8" fxFill mat-table>
|
||||
<ng-container matColumnDef="endStationName">
|
||||
<th *matHeaderCellDef mat-header-cell> station of lend destination</th>
|
||||
<td *matCellDef="let element" mat-cell> {{element.endStationName}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="number">
|
||||
<th *matHeaderCellDef mat-header-cell> number of drives</th>
|
||||
<td *matCellDef="let element" mat-cell> {{element.number}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="avgDuration">
|
||||
<th *matHeaderCellDef mat-header-cell> average Lend duration</th>
|
||||
<td *matCellDef="let element" mat-cell> {{element.avgDuration}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr *matHeaderRowDef="displayedColumnsTo" mat-header-row></tr>
|
||||
<tr *matRowDef="let row; columns: displayedColumnsTo;" mat-row></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="dashboard-table-from"
|
||||
fxFlex="35%"
|
||||
fxFlex="40%"
|
||||
>
|
||||
dashboard-table-from
|
||||
</div>
|
||||
<div class="mini-map"
|
||||
fxFlex
|
||||
>
|
||||
mini-map
|
||||
<table [dataSource]="stationFromSource" class="mat-elevation-z9" fxFill mat-table>
|
||||
<ng-container matColumnDef="startStationName">
|
||||
<th *matHeaderCellDef mat-header-cell> station of lend origin</th>
|
||||
<td *matCellDef="let element" mat-cell> {{element.startStationName}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="number">
|
||||
<th *matHeaderCellDef mat-header-cell> number of drives</th>
|
||||
<td *matCellDef="let element" mat-cell> {{element.number}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="avgDuration">
|
||||
<th *matHeaderCellDef mat-header-cell> average lend duration</th>
|
||||
<td *matCellDef="let element" mat-cell> {{element.avgDuration}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr *matHeaderRowDef="displayedColumnsFrom" mat-header-row></tr>
|
||||
<tr *matRowDef="let row; columns: displayedColumnsFrom;" mat-row></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="container container-middle"
|
||||
fxLayout
|
||||
fxLayout.xs="column"
|
||||
fxLayoutAlign="center"
|
||||
fxLayoutAlign="center center"
|
||||
fxLayoutGap="10px"
|
||||
fxLayoutGap.xs="0"
|
||||
>
|
||||
<div class="dashboard-chart-borrow-duration"
|
||||
fxFlex
|
||||
fxFlex="80%"
|
||||
>
|
||||
dashboard-chart-borrow-duration
|
||||
<div id="Station-Dashboard-Borrow-Duration">
|
||||
<apx-chart
|
||||
[chart]="durationChartOptions.chart"
|
||||
[dataLabels]="durationChartOptions.dataLabels"
|
||||
[fill]="durationChartOptions.fill"
|
||||
[legend]="durationChartOptions.legend"
|
||||
[plotOptions]="durationChartOptions.plotOptions"
|
||||
[series]="durationChartOptions.series"
|
||||
[stroke]="durationChartOptions.stroke"
|
||||
[xaxis]="durationChartOptions.xaxis"
|
||||
[yaxis]="durationChartOptions.yaxis"
|
||||
></apx-chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container container-bottom"
|
||||
|
@ -16,26 +16,28 @@ mat-sidenav-container, mat-sidenav-content, mat-sidenav {
|
||||
background: #5a34a0;
|
||||
}
|
||||
|
||||
#submit-date-span {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.button-wiki:hover {
|
||||
background: #5a34a0;
|
||||
}
|
||||
|
||||
.datepicker-start {
|
||||
margin: 5px;
|
||||
margin-top: 50px;
|
||||
.datepicker {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
.datepicker-end {
|
||||
margin: 5px;
|
||||
margin-top: 20px;
|
||||
.containter-map {
|
||||
height: 40vh;
|
||||
}
|
||||
|
||||
.container-top {
|
||||
height: 30vh;
|
||||
height: 20vh;
|
||||
}
|
||||
|
||||
.container-middle {
|
||||
height: 30vh
|
||||
height: 40vh
|
||||
}
|
||||
|
||||
.container-bottom {
|
||||
@ -44,22 +46,18 @@ mat-sidenav-container, mat-sidenav-content, mat-sidenav {
|
||||
|
||||
.dashboard-table-to {
|
||||
margin: 5px;
|
||||
background: gray;
|
||||
}
|
||||
|
||||
.dashboard-table-from {
|
||||
margin: 5px;
|
||||
background: aquamarine;
|
||||
}
|
||||
|
||||
.mini-map {
|
||||
margin: 5px;
|
||||
background: blueviolet;
|
||||
}
|
||||
|
||||
.dashboard-chart-borrow-duration {
|
||||
margin: 5px;
|
||||
background: blue;
|
||||
}
|
||||
|
||||
.dashboard-chart-borrow-time {
|
||||
|
@ -1,45 +1,218 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {DashboardService} from '../service/dashboard.service';
|
||||
import {IDashboardCommonBikePoint} from '../service/domain/dashboard-common-bike-point';
|
||||
import {MatDatepickerInputEvent} from '@angular/material/datepicker';
|
||||
import {MatTableDataSource} from '@angular/material/table';
|
||||
import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
|
||||
import {MapService} from '../service/map.service';
|
||||
|
||||
import {
|
||||
ApexAxisChartSeries,
|
||||
ApexChart,
|
||||
ApexDataLabels,
|
||||
ApexFill,
|
||||
ApexLegend,
|
||||
ApexNoData,
|
||||
ApexPlotOptions,
|
||||
ApexStroke,
|
||||
ApexTooltip,
|
||||
ApexXAxis,
|
||||
ApexYAxis,
|
||||
ChartComponent
|
||||
} from 'ng-apexcharts';
|
||||
|
||||
export type ChartOptions = {
|
||||
series: ApexAxisChartSeries;
|
||||
chart: ApexChart;
|
||||
dataLabels: ApexDataLabels;
|
||||
plotOptions: ApexPlotOptions;
|
||||
yaxis: ApexYAxis;
|
||||
xaxis: ApexXAxis;
|
||||
fill: ApexFill;
|
||||
tooltip: ApexTooltip;
|
||||
stroke: ApexStroke;
|
||||
legend: ApexLegend;
|
||||
noData: ApexNoData;
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.scss']
|
||||
styleUrls: ['./dashboard.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.Default
|
||||
})
|
||||
export class DashboardComponent implements OnInit {
|
||||
@ViewChild('Station-Dashboard-Borrow-Duration') chart: ChartComponent;
|
||||
public durationChartOptions: Partial<ChartOptions>;
|
||||
displayedColumnsTo: string[] = ['endStationName', 'number', 'avgDuration'];
|
||||
displayedColumnsFrom: string[] = ['startStationName', 'number', 'avgDuration'];
|
||||
stationToSource = new MatTableDataSource<any>();
|
||||
stationFromSource = new MatTableDataSource<any>();
|
||||
|
||||
|
||||
station: IDashboardCommonBikePoint;
|
||||
maxStartDate: Date;
|
||||
maxEndDate: Date;
|
||||
actualStartDate: Date;
|
||||
actualEndDate: Date;
|
||||
form: FormGroup;
|
||||
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
public service: DashboardService
|
||||
private service: DashboardService,
|
||||
private map: MapService,
|
||||
private changeDetectorRefs: ChangeDetectorRef,
|
||||
private fb: FormBuilder
|
||||
) {
|
||||
this.durationChartOptions = {
|
||||
series: [],
|
||||
chart: {
|
||||
type: 'bar'
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
noData: {
|
||||
text: 'Loading...'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.service.initialDashboardStationFetch(this.route.snapshot.paramMap.get('id')).then(data => {
|
||||
this.service.fetch_dashboard_init(this.route.snapshot.paramMap.get('id')).then(data => {
|
||||
this.station = data;
|
||||
this.maxStartDate = new Date(data.maxStartDate);
|
||||
this.maxEndDate = new Date(data.maxEndDate);
|
||||
console.log(data);
|
||||
this.init_dashboard();
|
||||
});
|
||||
|
||||
this.form = this.fb.group({
|
||||
daterange: new FormGroup({
|
||||
start: new FormControl(),
|
||||
end: new FormControl()
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
addStartDate(type: string, event: MatDatepickerInputEvent<Date>): void {
|
||||
this.actualStartDate = event.value;
|
||||
console.log(this.actualStartDate);
|
||||
init_dashboard(): void {
|
||||
const initDate = this.maxEndDate.toISOString().substring(0, 10);
|
||||
this.service.fetch_dashboard_station_to(this.station.id, initDate, initDate).then((source) => {
|
||||
this.stationToSource = source;
|
||||
this.changeDetectorRefs.detectChanges();
|
||||
});
|
||||
this.service.fetch_dashboard_station_from(this.station.id, initDate, initDate).then((source) => {
|
||||
this.stationFromSource = source;
|
||||
this.changeDetectorRefs.detectChanges();
|
||||
});
|
||||
this.service.fetch_dashboard_station_duration(this.station.id, initDate, initDate).then((source) => {
|
||||
const numbers = [];
|
||||
const minutesGroup = [];
|
||||
source.forEach(value => {
|
||||
numbers.push(value.number);
|
||||
minutesGroup.push(value.minutesGroup);
|
||||
});
|
||||
|
||||
this.durationChartOptions = {
|
||||
series: [
|
||||
{
|
||||
name: 'borrow-duration',
|
||||
data: [...numbers]
|
||||
}
|
||||
],
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 450
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '55%',
|
||||
endingShape: 'rounded'
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
stroke: {
|
||||
show: true,
|
||||
width: 2,
|
||||
colors: ['transparent']
|
||||
},
|
||||
xaxis: {
|
||||
categories: [...minutesGroup]
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: 'minutes'
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
}
|
||||
};
|
||||
});
|
||||
this.map.init_map(this.station.lat, this.station.lon, 17);
|
||||
this.map.draw_dashboard_station_marker(this.station.lat, this.station.lon);
|
||||
}
|
||||
|
||||
addEndDate(type: string, event: MatDatepickerInputEvent<Date>): void {
|
||||
this.actualEndDate = event.value;
|
||||
console.log(this.actualEndDate);
|
||||
}
|
||||
onSubmit(): void {
|
||||
this.actualStartDate = this.form.get('daterange').value.start;
|
||||
this.actualEndDate = this.form.get('daterange').value.end;
|
||||
this.service.fetch_dashboard_station_to(this.station.id, this.actualStartDate.toISOString().substring(0, 10), this.actualEndDate.toISOString().substring(0, 10)).then((source) => {
|
||||
this.stationToSource = source;
|
||||
this.changeDetectorRefs.detectChanges();
|
||||
});
|
||||
this.service.fetch_dashboard_station_from(this.station.id, this.actualStartDate.toISOString().substring(0, 10), this.actualStartDate.toISOString().substring(0, 10)).then((source) => {
|
||||
this.stationFromSource = source;
|
||||
this.changeDetectorRefs.detectChanges();
|
||||
});
|
||||
this.service.fetch_dashboard_station_duration(this.station.id, this.actualStartDate.toISOString().substring(0, 10), this.actualStartDate.toISOString().substring(0, 10)).then((source) => {
|
||||
const numbers = [];
|
||||
const minutesGroup = [];
|
||||
source.forEach(value => {
|
||||
numbers.push(value.number);
|
||||
minutesGroup.push(value.minutesGroup);
|
||||
});
|
||||
|
||||
this.durationChartOptions = {
|
||||
series: [
|
||||
{
|
||||
name: 'borrow-duration',
|
||||
data: [...numbers]
|
||||
}
|
||||
],
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 450
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '55%',
|
||||
endingShape: 'rounded'
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
stroke: {
|
||||
show: true,
|
||||
width: 2,
|
||||
colors: ['transparent']
|
||||
},
|
||||
xaxis: {
|
||||
categories: [...minutesGroup]
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: 'minutes'
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ export class MapComponent implements AfterViewInit {
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.service.initMap();
|
||||
this.service.makeStationMarkers();
|
||||
this.service.init_map(51.509865, -0.118092, 14);
|
||||
this.service.make_station_markers();
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,7 +10,19 @@ export class DashboardService {
|
||||
constructor(private client: HttpClient) {
|
||||
}
|
||||
|
||||
public async initialDashboardStationFetch(id: string): Promise<any> {
|
||||
return await this.client.get(environment.apiUrl + 'latest/dashboard/' + id + '/').toPromise();
|
||||
public async fetch_dashboard_init(id: string): Promise<any> {
|
||||
return await this.client.get(environment.apiUrl + `latest/dashboard/${id}/`).toPromise();
|
||||
}
|
||||
|
||||
public async fetch_dashboard_station_to(id: string, startDate: string, endDate: string): Promise<any> {
|
||||
return await this.client.get(environment.apiUrl + `latest/dashboard/${id}/to?start_date=${startDate}&end_date=${endDate}`).toPromise();
|
||||
}
|
||||
|
||||
public async fetch_dashboard_station_from(id: string, startDate: string, endDate: string): Promise<any> {
|
||||
return await this.client.get(environment.apiUrl + `latest/dashboard/${id}/from?start_date=${startDate}&end_date=${endDate}`).toPromise();
|
||||
}
|
||||
|
||||
public async fetch_dashboard_station_duration(id: string, startDate: string, endDate: string): Promise<any> {
|
||||
return await this.client.get(environment.apiUrl + `latest/dashboard/${id}/duration?start_date=${startDate}&end_date=${endDate}`).toPromise();
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
export interface IDashboardStationTo {
|
||||
startStationName?: string;
|
||||
endStationName?: string;
|
||||
stationNumber?: number;
|
||||
avgDuration?: number;
|
||||
}
|
||||
|
||||
export class DashboardStationTo implements IDashboardStationTo {
|
||||
constructor(
|
||||
public startStationName?: string,
|
||||
public endStationName?: string,
|
||||
public stationNumber?: number,
|
||||
public avgDuration?: number
|
||||
) {
|
||||
}
|
||||
}
|
@ -25,8 +25,8 @@ export class MapService {
|
||||
) {
|
||||
}
|
||||
|
||||
public initMap(): void {
|
||||
this.map = L.map('map').setView([51.509865, -0.118092], 14);
|
||||
public init_map(lat: number, lon: number, zoom: number): void {
|
||||
this.map = L.map('map').setView([lat, lon], zoom);
|
||||
this.map.addLayer(new L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: 'Map data <a href="https://openstreetmap.org">OpenStreetMap</a> contributors',
|
||||
minZoom: 0,
|
||||
@ -34,8 +34,8 @@ export class MapService {
|
||||
}));
|
||||
}
|
||||
|
||||
public makeStationMarkers(): void {
|
||||
this.fetchStationGeoData().then((data) => {
|
||||
public make_station_markers(): void {
|
||||
this.fetch_station_geo_data().then((data) => {
|
||||
const markerClusters = L.markerClusterGroup({
|
||||
spiderflyOnMaxZoom: true,
|
||||
showCoverageOnHover: true,
|
||||
@ -56,8 +56,12 @@ export class MapService {
|
||||
});
|
||||
}
|
||||
|
||||
public draw_dashboard_station_marker(lat: number, lon: number): void {
|
||||
L.marker([lat, lon], {icon: createIcon}).addTo(this.map);
|
||||
}
|
||||
|
||||
private async fetchStationGeoData(): Promise<any> {
|
||||
|
||||
private async fetch_station_geo_data(): Promise<any> {
|
||||
return await this.client.get(environment.apiUrl + 'latest/bikepoints/').toPromise();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user