refactor rent-duration to component
This commit is contained in:
parent
cdbf36fadb
commit
6d7c40ada6
@ -77,117 +77,12 @@
|
|||||||
</mat-card>
|
</mat-card>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container-table" fxFlex fxLayout="row" fxLayoutAlign="center">
|
<div class="container-table" fxFlex fxLayout="row" fxLayoutAlign="space-evenly center">
|
||||||
<div class="dashboard-table-to" fxFlex>
|
<app-table fxFlex></app-table>
|
||||||
<table [dataSource]="stationToSource" class="mat-elevation-z8" fxFill mat-table>
|
|
||||||
<ng-container matColumnDef="select">
|
|
||||||
<th *matHeaderCellDef mat-header-cell></th>
|
|
||||||
<td *matCellDef="let row" mat-cell>
|
|
||||||
<mat-checkbox [disabled]="isCheckBoxDisable(row)"
|
|
||||||
(change)="$event ? selectRow($event, row) : null" (click)="$event.stopPropagation()"
|
|
||||||
[checked]="selectionModel.isSelected(row)"
|
|
||||||
matTooltip="toggle to view marker on map"
|
|
||||||
matTooltipPosition="above">
|
|
||||||
</mat-checkbox>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="endStationName">
|
|
||||||
<th *matHeaderCellDef mat-header-cell> station of rental destination</th>
|
|
||||||
<td *matCellDef="let element" mat-cell><a
|
|
||||||
[routerLink]="['/dashboard/', element.stationId]">{{element.stationName}}</a></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 rental duration</th>
|
|
||||||
<td *matCellDef="let element" mat-cell> {{humanizeAvgDuration(element.avgDuration)}} </td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="marker">
|
|
||||||
<th *matHeaderCellDef mat-header-cell> icon on map</th>
|
|
||||||
<td *matCellDef="let element" mat-cell><img [src]="drawIconInTable(element)" alt="marker"></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>
|
|
||||||
<table [dataSource]="stationFromSource" class="mat-elevation-z9" fxFill mat-table>
|
|
||||||
<ng-container matColumnDef="select">
|
|
||||||
<th *matHeaderCellDef mat-header-cell></th>
|
|
||||||
<td *matCellDef="let row" mat-cell>
|
|
||||||
<mat-checkbox [disabled]="isCheckBoxDisable(row)"
|
|
||||||
(change)="$event ? selectRow($event, row) : null" (click)="$event.stopPropagation()"
|
|
||||||
[checked]="selectionModel.isSelected(row)"
|
|
||||||
matTooltip="toggle to view marker on map"
|
|
||||||
matTooltipPosition="above">
|
|
||||||
</mat-checkbox>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
<ng-container matColumnDef="startStationName">
|
|
||||||
<th *matHeaderCellDef mat-header-cell> station of rental origin</th>
|
|
||||||
<td *matCellDef="let element" mat-cell><a
|
|
||||||
[routerLink]="['/dashboard/', element.stationId]"> {{element.stationName}}</a></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 rental duration</th>
|
|
||||||
<td *matCellDef="let element" mat-cell> {{humanizeAvgDuration(element.avgDuration)}} </td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="marker">
|
|
||||||
<th *matHeaderCellDef mat-header-cell> icon on map</th>
|
|
||||||
<td *matCellDef="let element" mat-cell><img [src]="drawIconInTable(element)" alt="marker"></td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr *matHeaderRowDef="displayedColumnsFrom" mat-header-row></tr>
|
|
||||||
<tr *matRowDef="let row; columns: displayedColumnsFrom;" mat-row></tr>
|
|
||||||
</table>
|
|
||||||
<mat-card *ngIf="isLoading" style="display: flex; justify-content: center; align-items: center">
|
|
||||||
<mat-progress-spinner
|
|
||||||
color="primary"
|
|
||||||
mode="indeterminate">
|
|
||||||
</mat-progress-spinner>
|
|
||||||
</mat-card>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container-borrow-duration" fxLayout="row" fxLayoutAlign="center">
|
<div class="container-borrow-duration" fxLayout="row" fxLayoutAlign="center">
|
||||||
<mat-card fxFlex fxLayout="column">
|
<app-rent-duration-chart fxFlex></app-rent-duration-chart>
|
||||||
<mat-card-header>
|
|
||||||
<mat-card-title>Rental Duration</mat-card-title>
|
|
||||||
<mat-card-subtitle>
|
|
||||||
This chart shows the rent duration based on the currently selected station.
|
|
||||||
The time it takes for a rent which has the current station as origin is displayed here.
|
|
||||||
</mat-card-subtitle>
|
|
||||||
</mat-card-header>
|
|
||||||
<mat-card-content fxFlex fxLayout="row" fxLayoutAlign="center">
|
|
||||||
<div class="station-dashboard-borrow-duration" fxFlex="97%">
|
|
||||||
<apx-chart
|
|
||||||
[chart]="durationChartOptions.chart"
|
|
||||||
[colors]="durationChartOptions.colors"
|
|
||||||
[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>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container-borrow-time" fxLayout="row" fxLayoutAlign="center">
|
<div class="container-borrow-time" fxLayout="row" fxLayoutAlign="center">
|
||||||
|
@ -6,14 +6,6 @@ mat-sidenav-content {
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-back:hover, .button-wiki:hover {
|
.button-back:hover, .button-wiki:hover {
|
||||||
background: #086ed2;
|
background: #086ed2;
|
||||||
}
|
}
|
||||||
@ -53,7 +45,6 @@ img {
|
|||||||
margin-left: 39px;
|
margin-left: 39px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.container-map {
|
.container-map {
|
||||||
height: 40em;
|
height: 40em;
|
||||||
margin: 1em 2em;
|
margin: 1em 2em;
|
||||||
@ -64,14 +55,6 @@ img {
|
|||||||
margin: 1em 3em;
|
margin: 1em 3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-table-to {
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dashboard-table-from {
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container-borrow-duration {
|
.container-borrow-duration {
|
||||||
height: 41em;
|
height: 41em;
|
||||||
margin: 1em 2em;
|
margin: 1em 2em;
|
||||||
|
@ -2,10 +2,8 @@ import {ChangeDetectionStrategy, ChangeDetectorRef, Component, Injectable, OnIni
|
|||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
import {DashboardService} from '../service/dashboard.service';
|
import {DashboardService} from '../service/dashboard.service';
|
||||||
import {IDashboardCommonBikePoint} from '../service/domain/dashboard-common-bike-point';
|
import {IDashboardCommonBikePoint} from '../service/domain/dashboard-common-bike-point';
|
||||||
import {MatTableDataSource} from '@angular/material/table';
|
|
||||||
import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
|
import {FormBuilder, FormControl, FormGroup} from '@angular/forms';
|
||||||
import {MapService} from '../service/map.service';
|
import {MapService} from '../service/map.service';
|
||||||
import stht from 'seconds-to-human-time';
|
|
||||||
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -20,14 +18,13 @@ import {
|
|||||||
ApexTitleSubtitle,
|
ApexTitleSubtitle,
|
||||||
ApexTooltip,
|
ApexTooltip,
|
||||||
ApexXAxis,
|
ApexXAxis,
|
||||||
ApexYAxis,
|
ApexYAxis
|
||||||
ChartComponent
|
|
||||||
} from 'ng-apexcharts';
|
} from 'ng-apexcharts';
|
||||||
import {IMapBikePoint} from '../service/domain/map-bike-point';
|
import {IMapBikePoint} from '../service/domain/map-bike-point';
|
||||||
import {SelectionModel} from '@angular/cdk/collections';
|
|
||||||
import {MatCheckboxChange} from '@angular/material/checkbox';
|
|
||||||
import {DateAdapter, MAT_DATE_FORMATS, NativeDateAdapter} from '@angular/material/core';
|
import {DateAdapter, MAT_DATE_FORMATS, NativeDateAdapter} from '@angular/material/core';
|
||||||
import {formatDate} from '@angular/common';
|
import {formatDate} from '@angular/common';
|
||||||
|
import {TableComponent} from './table/table.component';
|
||||||
|
import {RentDurationChartComponent} from "./rent-duration-chart/rent-duration-chart.component";
|
||||||
|
|
||||||
export type ChartOptions = {
|
export type ChartOptions = {
|
||||||
title: ApexTitleSubtitle;
|
title: ApexTitleSubtitle;
|
||||||
@ -80,19 +77,12 @@ const chartHeight = 460;
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class DashboardComponent implements OnInit {
|
export class DashboardComponent implements OnInit {
|
||||||
@ViewChild('Station-Dashboard-Borrow-Duration') chart: ChartComponent;
|
@ViewChild(TableComponent) table: TableComponent;
|
||||||
|
@ViewChild(RentDurationChartComponent) durationChart: RentDurationChartComponent;
|
||||||
|
|
||||||
public durationChartOptions: Partial<ChartOptions>;
|
public durationChartOptions: Partial<ChartOptions>;
|
||||||
public timeChartOptions: Partial<ChartOptions>;
|
public timeChartOptions: Partial<ChartOptions>;
|
||||||
public bikePointChartOptions: Partial<ChartOptions>;
|
public bikePointChartOptions: Partial<ChartOptions>;
|
||||||
displayedColumnsTo: string[] = ['select', 'endStationName', 'number', 'avgDuration', 'marker'];
|
|
||||||
displayedColumnsFrom: string[] = ['select', 'startStationName', 'number', 'avgDuration', 'marker'];
|
|
||||||
stationToSource = new MatTableDataSource<IDashboardCommonBikePoint>();
|
|
||||||
iterableToSource: any[];
|
|
||||||
stationFromSource = new MatTableDataSource<IDashboardCommonBikePoint>();
|
|
||||||
iterableFromSource: any[];
|
|
||||||
selectionModel = new SelectionModel<IDashboardCommonBikePoint>(true, []);
|
|
||||||
colors = ['black', 'gray', 'green', 'orange', 'purple', 'red'];
|
|
||||||
isLoading: boolean;
|
|
||||||
|
|
||||||
station: IDashboardCommonBikePoint;
|
station: IDashboardCommonBikePoint;
|
||||||
maxStartDate: Date;
|
maxStartDate: Date;
|
||||||
@ -138,7 +128,6 @@ export class DashboardComponent implements OnInit {
|
|||||||
text: 'Loading...'
|
text: 'Loading...'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.isLoading = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -151,8 +140,6 @@ export class DashboardComponent implements OnInit {
|
|||||||
this.changeDetectorRefs.detectChanges();
|
this.changeDetectorRefs.detectChanges();
|
||||||
this.map.removeTableStationMarkerOnReload();
|
this.map.removeTableStationMarkerOnReload();
|
||||||
this.route.params.subscribe(params => {
|
this.route.params.subscribe(params => {
|
||||||
this.selectionModel.clear();
|
|
||||||
this.colors = ['black', 'gray', 'green', 'orange', 'purple', 'red'];
|
|
||||||
this.service.fetchDashboardInit(params.id).then(data => {
|
this.service.fetchDashboardInit(params.id).then(data => {
|
||||||
this.station = data;
|
this.station = data;
|
||||||
this.maxStartDate = new Date(data.maxStartDate);
|
this.maxStartDate = new Date(data.maxStartDate);
|
||||||
@ -254,18 +241,6 @@ export class DashboardComponent implements OnInit {
|
|||||||
const initDate = this.maxEndDate.toISOString().substring(0, 10);
|
const initDate = this.maxEndDate.toISOString().substring(0, 10);
|
||||||
this.form.get('daterange').get('start').setValue(initDate);
|
this.form.get('daterange').get('start').setValue(initDate);
|
||||||
this.form.get('daterange').get('end').setValue(initDate);
|
this.form.get('daterange').get('end').setValue(initDate);
|
||||||
await this.service.fetchDashboardStationTo(this.station.id, initDate, initDate).then((source) => {
|
|
||||||
this.stationToSource = this.setBikePointColorToSource(source);
|
|
||||||
this.iterableToSource = source;
|
|
||||||
this.isLoading = false;
|
|
||||||
this.changeDetectorRefs.detectChanges();
|
|
||||||
});
|
|
||||||
await this.service.fetchDashboardStationFrom(this.station.id, initDate, initDate).then((source) => {
|
|
||||||
this.stationFromSource = this.setBikePointColorFromSource(source);
|
|
||||||
this.iterableFromSource = source;
|
|
||||||
this.isLoading = false;
|
|
||||||
this.changeDetectorRefs.detectChanges();
|
|
||||||
});
|
|
||||||
this.service.fetchDashboardStationCharts(this.station.id, initDate, initDate, 'duration').then((source) => {
|
this.service.fetchDashboardStationCharts(this.station.id, initDate, initDate, 'duration').then((source) => {
|
||||||
const numbers = [];
|
const numbers = [];
|
||||||
const minutesGroup = [];
|
const minutesGroup = [];
|
||||||
@ -404,232 +379,17 @@ export class DashboardComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onSubmit(): Promise<any> {
|
async onSubmit(): Promise<any> {
|
||||||
this.isLoading = false;
|
|
||||||
this.actualStartDate = this.form.get('daterange').value.start;
|
this.actualStartDate = this.form.get('daterange').value.start;
|
||||||
this.actualEndDate = this.form.get('daterange').value.end;
|
this.actualEndDate = this.form.get('daterange').value.end;
|
||||||
this.map.removeTableStationMarkerOnReload();
|
this.table.onSubmit(
|
||||||
this.selectionModel.clear();
|
|
||||||
await this.service.fetchDashboardStationTo(
|
|
||||||
this.station.id,
|
|
||||||
this.actualStartDate.toISOString().substring(0, 10),
|
this.actualStartDate.toISOString().substring(0, 10),
|
||||||
this.actualEndDate.toISOString().substring(0, 10)
|
this.actualEndDate.toISOString().substring(0, 10)
|
||||||
).then((source) => {
|
);
|
||||||
this.colors = ['black', 'gray', 'green', 'orange', 'purple', 'red'];
|
this.durationChart.onSubmit(
|
||||||
this.stationToSource = this.setBikePointColorToSource(source);
|
|
||||||
this.iterableToSource = source;
|
|
||||||
this.isLoading = false;
|
|
||||||
this.changeDetectorRefs.detectChanges();
|
|
||||||
});
|
|
||||||
await this.service.fetchDashboardStationFrom(
|
|
||||||
this.station.id,
|
|
||||||
this.actualStartDate.toISOString().substring(0, 10),
|
this.actualStartDate.toISOString().substring(0, 10),
|
||||||
this.actualEndDate.toISOString().substring(0, 10)
|
this.actualEndDate.toISOString().substring(0, 10)
|
||||||
).then((source) => {
|
);
|
||||||
this.stationFromSource = this.setBikePointColorFromSource(source);
|
|
||||||
this.iterableFromSource = source;
|
|
||||||
this.isLoading = false;
|
|
||||||
this.changeDetectorRefs.detectChanges();
|
|
||||||
});
|
|
||||||
this.service.fetchDashboardStationCharts(
|
|
||||||
this.station.id,
|
|
||||||
this.actualStartDate.toISOString().substring(0, 10),
|
|
||||||
this.actualEndDate.toISOString().substring(0, 10),
|
|
||||||
'duration'
|
|
||||||
).then((source) => {
|
|
||||||
const numbers = [];
|
|
||||||
const minutesGroup = [];
|
|
||||||
source.forEach(value => {
|
|
||||||
numbers.push(value.number);
|
|
||||||
minutesGroup.push(value.minutesGroup);
|
|
||||||
});
|
|
||||||
this.durationChartOptions = {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'amount of drives for given borrow duration',
|
|
||||||
data: numbers
|
|
||||||
}
|
|
||||||
],
|
|
||||||
chart: {
|
|
||||||
type: 'bar',
|
|
||||||
height: chartHeight
|
|
||||||
},
|
|
||||||
colors: ['#017bfe'],
|
|
||||||
plotOptions: {
|
|
||||||
bar: {
|
|
||||||
horizontal: false,
|
|
||||||
columnWidth: '55%',
|
|
||||||
endingShape: 'flat'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dataLabels: {
|
|
||||||
enabled: false
|
|
||||||
},
|
|
||||||
stroke: {
|
|
||||||
show: true,
|
|
||||||
width: 2,
|
|
||||||
colors: ['transparent']
|
|
||||||
},
|
|
||||||
xaxis: {
|
|
||||||
title: {
|
|
||||||
text: 'average rental duration'
|
|
||||||
},
|
|
||||||
categories: minutesGroup,
|
|
||||||
labels: {
|
|
||||||
formatter: value => {
|
|
||||||
return value + ' min';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
yaxis: {
|
|
||||||
title: {
|
|
||||||
text: 'amount of drives'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fill: {
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
this.service.fetchDashboardStationCharts(
|
|
||||||
this.station.id,
|
|
||||||
this.actualStartDate.toISOString().substring(0, 10),
|
|
||||||
this.actualEndDate.toISOString().substring(0, 10),
|
|
||||||
'time'
|
|
||||||
).then((source) => {
|
|
||||||
const timeFrame = [];
|
|
||||||
const numbers = [];
|
|
||||||
const avgDuration = [];
|
|
||||||
source.forEach(value => {
|
|
||||||
timeFrame.push(value.timeFrame);
|
|
||||||
numbers.push(value.number);
|
|
||||||
avgDuration.push(Math.round(value.avgDuration / 60));
|
|
||||||
});
|
|
||||||
this.timeChartOptions = {
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: 'amount of drives',
|
|
||||||
type: 'bar',
|
|
||||||
data: numbers
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'average rental duration',
|
|
||||||
type: 'line',
|
|
||||||
data: avgDuration
|
|
||||||
}
|
|
||||||
],
|
|
||||||
chart: {
|
|
||||||
toolbar: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
type: 'line',
|
|
||||||
height: chartHeight,
|
|
||||||
zoom: {
|
|
||||||
enabled: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
colors: ['#017bfe', '#51ca49'],
|
|
||||||
dataLabels: {
|
|
||||||
enabled: false
|
|
||||||
},
|
|
||||||
stroke: {
|
|
||||||
curve: 'straight'
|
|
||||||
},
|
|
||||||
xaxis: {
|
|
||||||
title: {
|
|
||||||
text: 'time of the day'
|
|
||||||
},
|
|
||||||
categories: timeFrame,
|
|
||||||
tickAmount: 24,
|
|
||||||
tickPlacement: 'between'
|
|
||||||
},
|
|
||||||
yaxis: [{
|
|
||||||
title: {
|
|
||||||
text: 'amount of drives',
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
opposite: true,
|
|
||||||
title: {
|
|
||||||
text: 'average rental duration'
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
formatter: (val: number): string => {
|
|
||||||
return val + ' min';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}],
|
|
||||||
legend: {
|
|
||||||
horizontalAlign: 'left'
|
|
||||||
},
|
|
||||||
fill: {
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
humanizeAvgDuration(avgDuration: number): string {
|
|
||||||
return stht(avgDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectRow(selection: MatCheckboxChange, row): void {
|
|
||||||
const markerToDisplay = [];
|
|
||||||
this.iterableToSource.forEach(point => {
|
|
||||||
if (point.stationId === row.stationId) {
|
|
||||||
this.selectionModel.toggle(point);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.iterableFromSource.forEach(point => {
|
|
||||||
if (point.stationId === row.stationId) {
|
|
||||||
this.selectionModel.toggle(point);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.selectionModel.selected.forEach(point => {
|
|
||||||
markerToDisplay.push(point);
|
|
||||||
});
|
|
||||||
this.map.drawTableStationMarker(markerToDisplay);
|
|
||||||
}
|
|
||||||
|
|
||||||
public drawIconInTable(bikePoint: any): string {
|
|
||||||
return `../../assets/bike-point-${bikePoint.color}.png`;
|
|
||||||
}
|
|
||||||
|
|
||||||
setBikePointColorToSource(source): any {
|
|
||||||
for (const station of source) {
|
|
||||||
if (station.stationId === this.station.id) {
|
|
||||||
station.color = 'blue';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
station.color = this.getRandomColor();
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
setBikePointColorFromSource(source): any {
|
|
||||||
for (const station of source) {
|
|
||||||
if (station.stationId === this.station.id) {
|
|
||||||
station.color = 'blue';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const to of this.iterableToSource) {
|
|
||||||
if (station.stationId === to.stationId) {
|
|
||||||
station.color = to.color;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!station.color) {
|
|
||||||
station.color = this.getRandomColor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
getRandomColor(): string {
|
|
||||||
const color = this.colors[Math.floor(Math.random() * this.colors.length)];
|
|
||||||
this.colors = this.colors.filter(c => c !== color);
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
isCheckBoxDisable(row): boolean {
|
|
||||||
return row.stationId === this.station.id;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
<mat-card fxFlex fxLayout="column">
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title>Rental Duration</mat-card-title>
|
||||||
|
<mat-card-subtitle>
|
||||||
|
This chart shows the rent duration based on the currently selected station.
|
||||||
|
The time it takes for a rent which has the current station as origin is displayed here.
|
||||||
|
</mat-card-subtitle>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content fxFlex fxLayout="row" fxLayoutAlign="center">
|
||||||
|
<div class="station-dashboard-borrow-duration" fxFlex>
|
||||||
|
<apx-chart
|
||||||
|
[chart]="chartOptions.chart"
|
||||||
|
[colors]="chartOptions.colors"
|
||||||
|
[dataLabels]="chartOptions.dataLabels"
|
||||||
|
[fill]="chartOptions.fill"
|
||||||
|
[legend]="chartOptions.legend"
|
||||||
|
[plotOptions]="chartOptions.plotOptions"
|
||||||
|
[series]="chartOptions.series"
|
||||||
|
[stroke]="chartOptions.stroke"
|
||||||
|
[xaxis]="chartOptions.xaxis"
|
||||||
|
[yaxis]="chartOptions.yaxis"></apx-chart>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
@ -0,0 +1,17 @@
|
|||||||
|
.station-dashboard-borrow-duration {
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-card {
|
||||||
|
padding: 1px 1px 1px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-card-title {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-card-subtitle {
|
||||||
|
margin-left: 39px;
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { RentDurationChartComponent } from './rent-duration-chart.component';
|
||||||
|
|
||||||
|
describe('RentDurationChartComponent', () => {
|
||||||
|
let component: RentDurationChartComponent;
|
||||||
|
let fixture: ComponentFixture<RentDurationChartComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ RentDurationChartComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(RentDurationChartComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,149 @@
|
|||||||
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
|
import {
|
||||||
|
ApexAxisChartSeries,
|
||||||
|
ApexChart,
|
||||||
|
ApexDataLabels,
|
||||||
|
ApexFill,
|
||||||
|
ApexLegend,
|
||||||
|
ApexNoData,
|
||||||
|
ApexPlotOptions,
|
||||||
|
ApexStroke,
|
||||||
|
ApexTitleSubtitle,
|
||||||
|
ApexTooltip,
|
||||||
|
ApexXAxis,
|
||||||
|
ApexYAxis,
|
||||||
|
ChartComponent
|
||||||
|
} from 'ng-apexcharts';
|
||||||
|
import {ActivatedRoute} from '@angular/router';
|
||||||
|
import {DashboardService} from '../../service/dashboard.service';
|
||||||
|
import {IDashboardCommonBikePoint} from '../../service/domain/dashboard-common-bike-point';
|
||||||
|
|
||||||
|
export type ChartOptions = {
|
||||||
|
title: ApexTitleSubtitle;
|
||||||
|
subtitle: ApexTitleSubtitle;
|
||||||
|
series: ApexAxisChartSeries;
|
||||||
|
chart: ApexChart;
|
||||||
|
colors: string[];
|
||||||
|
dataLabels: ApexDataLabels;
|
||||||
|
plotOptions: ApexPlotOptions;
|
||||||
|
yaxis: ApexYAxis;
|
||||||
|
xaxis: ApexXAxis;
|
||||||
|
fill: ApexFill;
|
||||||
|
tooltip: ApexTooltip;
|
||||||
|
stroke: ApexStroke;
|
||||||
|
legend: ApexLegend;
|
||||||
|
noData: ApexNoData;
|
||||||
|
};
|
||||||
|
|
||||||
|
const chartType = 'duration';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-rent-duration-chart',
|
||||||
|
templateUrl: './rent-duration-chart.component.html',
|
||||||
|
styleUrls: ['./rent-duration-chart.component.scss']
|
||||||
|
})
|
||||||
|
export class RentDurationChartComponent implements OnInit {
|
||||||
|
@ViewChild(ChartComponent) chart: ChartComponent;
|
||||||
|
chartOptions: Partial<ChartOptions>;
|
||||||
|
|
||||||
|
bikePoint: IDashboardCommonBikePoint;
|
||||||
|
maxStartDate: Date;
|
||||||
|
maxEndDate: Date;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private service: DashboardService,
|
||||||
|
) {
|
||||||
|
this.chartOptions = {
|
||||||
|
series: [],
|
||||||
|
chart: {
|
||||||
|
type: 'bar'
|
||||||
|
},
|
||||||
|
noData: {
|
||||||
|
text: 'Loading...'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.route.params.subscribe(params => {
|
||||||
|
this.service.fetchDashboardInit(params.id).then(data => {
|
||||||
|
this.bikePoint = data;
|
||||||
|
this.maxStartDate = new Date(data.maxStartDate);
|
||||||
|
this.maxEndDate = new Date(data.maxEndDate);
|
||||||
|
this.initChart();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async initChart(): Promise<void> {
|
||||||
|
const initDate = this.maxEndDate.toISOString().substring(0, 10);
|
||||||
|
await this.service.fetchDashboardStationCharts(this.bikePoint.id, initDate, initDate, chartType).then(source => {
|
||||||
|
this.chartOptions = {
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'amount of drives',
|
||||||
|
data: source.map(value => value.number)
|
||||||
|
}
|
||||||
|
],
|
||||||
|
chart: {
|
||||||
|
type: 'bar',
|
||||||
|
height: '460'
|
||||||
|
},
|
||||||
|
colors: ['#017bfe'],
|
||||||
|
plotOptions: {
|
||||||
|
bar: {
|
||||||
|
horizontal: false,
|
||||||
|
columnWidth: '55%',
|
||||||
|
endingShape: 'flat'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataLabels: {
|
||||||
|
enabled: false
|
||||||
|
},
|
||||||
|
stroke: {
|
||||||
|
show: true,
|
||||||
|
width: 2,
|
||||||
|
colors: ['transparent']
|
||||||
|
},
|
||||||
|
xaxis: {
|
||||||
|
title: {
|
||||||
|
text: 'average rental duration'
|
||||||
|
},
|
||||||
|
categories: source.map(value => value.minutesGroup),
|
||||||
|
labels: {
|
||||||
|
formatter: value => {
|
||||||
|
return value + ' min';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yaxis: {
|
||||||
|
title: {
|
||||||
|
text: 'amount of drives'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
noData: {
|
||||||
|
text: 'loading'
|
||||||
|
},
|
||||||
|
fill: {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.chart.updateOptions(this.chartOptions);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onSubmit(actualStartDate: string, actualEndDate: string): Promise<void> {
|
||||||
|
await this.service.fetchDashboardStationCharts(
|
||||||
|
this.bikePoint.id,
|
||||||
|
actualStartDate,
|
||||||
|
actualEndDate,
|
||||||
|
chartType
|
||||||
|
).then(source => {
|
||||||
|
this.chart.updateSeries([{
|
||||||
|
data: source.map(value => value.number)
|
||||||
|
}]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user