Feature/add story for line chart component (#385)
* Add story for line chart component * Update changelog
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
export interface LineChartItem {
|
||||
date: string;
|
||||
value: number;
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
<ngx-skeleton-loader
|
||||
*ngIf="isLoading && showLoader"
|
||||
animation="pulse"
|
||||
[theme]="{
|
||||
height: '100%',
|
||||
width: '100%'
|
||||
}"
|
||||
></ngx-skeleton-loader>
|
||||
<canvas
|
||||
#chartCanvas
|
||||
class="h-100"
|
||||
[ngStyle]="{ display: isLoading ? 'none' : 'block' }"
|
||||
></canvas>
|
@@ -1,7 +0,0 @@
|
||||
:host {
|
||||
display: block;
|
||||
|
||||
ngx-skeleton-loader {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
@@ -1,189 +0,0 @@
|
||||
import 'chartjs-adapter-date-fns';
|
||||
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewChild
|
||||
} from '@angular/core';
|
||||
import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config';
|
||||
import { getBackgroundColor } from '@ghostfolio/common/helper';
|
||||
import {
|
||||
Chart,
|
||||
Filler,
|
||||
LineController,
|
||||
LineElement,
|
||||
LinearScale,
|
||||
PointElement,
|
||||
TimeScale
|
||||
} from 'chart.js';
|
||||
|
||||
import { LineChartItem } from './interfaces/line-chart.interface';
|
||||
|
||||
@Component({
|
||||
selector: 'gf-line-chart',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: './line-chart.component.html',
|
||||
styleUrls: ['./line-chart.component.scss']
|
||||
})
|
||||
export class LineChartComponent implements OnChanges, OnDestroy, OnInit {
|
||||
@Input() benchmarkDataItems: LineChartItem[] = [];
|
||||
@Input() benchmarkLabel = '';
|
||||
@Input() historicalDataItems: LineChartItem[];
|
||||
@Input() showLegend: boolean;
|
||||
@Input() showLoader = true;
|
||||
@Input() showXAxis: boolean;
|
||||
@Input() showYAxis: boolean;
|
||||
@Input() symbol: string;
|
||||
|
||||
@ViewChild('chartCanvas') chartCanvas;
|
||||
|
||||
public chart: Chart;
|
||||
public isLoading = true;
|
||||
|
||||
public constructor(private changeDetectorRef: ChangeDetectorRef) {
|
||||
Chart.register(
|
||||
Filler,
|
||||
LineController,
|
||||
LineElement,
|
||||
PointElement,
|
||||
LinearScale,
|
||||
TimeScale
|
||||
);
|
||||
}
|
||||
|
||||
public ngOnInit() {}
|
||||
|
||||
public ngOnChanges() {
|
||||
if (this.historicalDataItems) {
|
||||
setTimeout(() => {
|
||||
// Wait for the chartCanvas
|
||||
this.initialize();
|
||||
|
||||
this.changeDetectorRef.markForCheck();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public ngOnDestroy() {
|
||||
this.chart?.destroy();
|
||||
}
|
||||
|
||||
private initialize() {
|
||||
this.isLoading = true;
|
||||
const benchmarkPrices = [];
|
||||
const labels = [];
|
||||
const marketPrices = [];
|
||||
|
||||
this.historicalDataItems?.forEach((historicalDataItem, index) => {
|
||||
benchmarkPrices.push(this.benchmarkDataItems?.[index]?.value);
|
||||
labels.push(historicalDataItem.date);
|
||||
marketPrices.push(historicalDataItem.value);
|
||||
});
|
||||
|
||||
const gradient = this.chartCanvas?.nativeElement
|
||||
?.getContext('2d')
|
||||
.createLinearGradient(
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(this.chartCanvas.nativeElement.parentNode.offsetHeight * 4) / 5
|
||||
);
|
||||
|
||||
if (gradient) {
|
||||
gradient.addColorStop(
|
||||
0,
|
||||
`rgba(${primaryColorRgb.r}, ${primaryColorRgb.g}, ${primaryColorRgb.b}, 0.01)`
|
||||
);
|
||||
gradient.addColorStop(1, getBackgroundColor());
|
||||
}
|
||||
|
||||
const data = {
|
||||
labels,
|
||||
datasets: [
|
||||
{
|
||||
borderColor: `rgb(${secondaryColorRgb.r}, ${secondaryColorRgb.g}, ${secondaryColorRgb.b})`,
|
||||
borderWidth: 1,
|
||||
data: benchmarkPrices,
|
||||
fill: false,
|
||||
label: this.benchmarkLabel,
|
||||
pointRadius: 0
|
||||
},
|
||||
{
|
||||
backgroundColor: gradient,
|
||||
borderColor: `rgb(${primaryColorRgb.r}, ${primaryColorRgb.g}, ${primaryColorRgb.b})`,
|
||||
borderWidth: 2,
|
||||
data: marketPrices,
|
||||
fill: true,
|
||||
label: this.symbol,
|
||||
pointRadius: 0
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
if (this.chartCanvas) {
|
||||
if (this.chart) {
|
||||
this.chart.data = data;
|
||||
this.chart.update();
|
||||
} else {
|
||||
this.chart = new Chart(this.chartCanvas.nativeElement, {
|
||||
data,
|
||||
options: {
|
||||
animation: false,
|
||||
plugins: {
|
||||
legend: {
|
||||
align: 'start',
|
||||
display: this.showLegend,
|
||||
position: 'bottom'
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: this.showXAxis,
|
||||
grid: {
|
||||
display: false
|
||||
},
|
||||
time: {
|
||||
unit: 'year'
|
||||
},
|
||||
type: 'time'
|
||||
},
|
||||
y: {
|
||||
display: this.showYAxis,
|
||||
grid: {
|
||||
display: false
|
||||
},
|
||||
ticks: {
|
||||
display: this.showYAxis,
|
||||
callback: function (tickValue, index, ticks) {
|
||||
if (index === 0 || index === ticks.length - 1) {
|
||||
// Only print last and first legend entry
|
||||
if (typeof tickValue === 'number') {
|
||||
return tickValue.toFixed(2);
|
||||
}
|
||||
|
||||
return tickValue;
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
mirror: true,
|
||||
z: 1
|
||||
},
|
||||
type: 'linear'
|
||||
}
|
||||
},
|
||||
spanGaps: true
|
||||
},
|
||||
type: 'line'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
}
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
|
||||
import { LineChartComponent } from './line-chart.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [LineChartComponent],
|
||||
exports: [LineChartComponent],
|
||||
imports: [CommonModule, NgxSkeletonLoaderModule],
|
||||
providers: []
|
||||
})
|
||||
export class GfLineChartModule {}
|
@@ -1,4 +1,4 @@
|
||||
import { LineChartItem } from '../../line-chart/interfaces/line-chart.interface';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
|
||||
export interface PositionDetailDialogParams {
|
||||
deviceType: string;
|
||||
|
@@ -7,11 +7,11 @@ import {
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
import { isToday, parse } from 'date-fns';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
import { LineChartItem } from '../line-chart/interfaces/line-chart.interface';
|
||||
import { PositionDetailDialogParams } from './interfaces/interfaces';
|
||||
|
||||
@Component({
|
||||
|
@@ -13,6 +13,7 @@
|
||||
[benchmarkDataItems]="benchmarkDataItems"
|
||||
[benchmarkLabel]="benchmarkLabel"
|
||||
[historicalDataItems]="historicalDataItems"
|
||||
[showGradient]="true"
|
||||
[showLegend]="true"
|
||||
[showXAxis]="true"
|
||||
[showYAxis]="false"
|
||||
|
@@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { GfLineChartModule } from '@ghostfolio/client/components/line-chart/line-chart.module';
|
||||
import { GfLineChartModule } from '@ghostfolio/ui/line-chart/line-chart.module';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
|
||||
|
@@ -8,11 +8,11 @@ import {
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { DATE_FORMAT } from '@ghostfolio/common/helper';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
import { format, isSameMonth, isToday, parseISO } from 'date-fns';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
||||
import { LineChartItem } from '../../line-chart/interfaces/line-chart.interface';
|
||||
import { PositionDetailDialogParams } from './interfaces/interfaces';
|
||||
|
||||
@Component({
|
||||
|
@@ -12,6 +12,7 @@
|
||||
benchmarkLabel="Buy Price"
|
||||
[benchmarkDataItems]="benchmarkDataItems"
|
||||
[historicalDataItems]="historicalDataItems"
|
||||
[showGradient]="true"
|
||||
[showXAxis]="true"
|
||||
[showYAxis]="true"
|
||||
[symbol]="data.symbol"
|
||||
|
@@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { GfLineChartModule } from '@ghostfolio/client/components/line-chart/line-chart.module';
|
||||
import { GfLineChartModule } from '@ghostfolio/ui/line-chart/line-chart.module';
|
||||
import { GfValueModule } from '@ghostfolio/ui/value';
|
||||
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
|
||||
|
||||
|
@@ -10,7 +10,6 @@ import {
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatTabChangeEvent } from '@angular/material/tabs';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { LineChartItem } from '@ghostfolio/client/components/line-chart/interfaces/line-chart.interface';
|
||||
import { PerformanceChartDialog } from '@ghostfolio/client/components/performance-chart-dialog/performance-chart-dialog.component';
|
||||
import { ToggleOption } from '@ghostfolio/client/components/toggle/interfaces/toggle-option.type';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
@@ -29,6 +28,7 @@ import {
|
||||
} from '@ghostfolio/common/interfaces';
|
||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||
import { DateRange } from '@ghostfolio/common/types';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
import { DataSource } from '@prisma/client';
|
||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
|
@@ -33,6 +33,7 @@
|
||||
class="mr-3"
|
||||
symbol="Performance"
|
||||
[historicalDataItems]="historicalDataItems"
|
||||
[showGradient]="true"
|
||||
[showLoader]="false"
|
||||
[showXAxis]="false"
|
||||
[showYAxis]="false"
|
||||
|
@@ -4,12 +4,12 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfLineChartModule } from '@ghostfolio/client/components/line-chart/line-chart.module';
|
||||
import { GfPerformanceChartDialogModule } from '@ghostfolio/client/components/performance-chart-dialog/performance-chart-dialog.module';
|
||||
import { GfPortfolioPerformanceModule } from '@ghostfolio/client/components/portfolio-performance/portfolio-performance.module';
|
||||
import { GfPortfolioSummaryModule } from '@ghostfolio/client/components/portfolio-summary/portfolio-summary.module';
|
||||
import { GfPositionsModule } from '@ghostfolio/client/components/positions/positions.module';
|
||||
import { GfToggleModule } from '@ghostfolio/client/components/toggle/toggle.module';
|
||||
import { GfLineChartModule } from '@ghostfolio/ui/line-chart/line-chart.module';
|
||||
import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info';
|
||||
|
||||
import { HomePageRoutingModule } from './home-page-routing.module';
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { LineChartItem } from '@ghostfolio/client/components/line-chart/interfaces/line-chart.interface';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
import { format } from 'date-fns';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
|
@@ -50,6 +50,7 @@
|
||||
class="position-absolute"
|
||||
symbol="Performance"
|
||||
[historicalDataItems]="historicalDataItems"
|
||||
[showGradient]="true"
|
||||
[showLoader]="false"
|
||||
[showXAxis]="false"
|
||||
[showYAxis]="false"
|
||||
|
@@ -2,7 +2,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfLineChartModule } from '@ghostfolio/client/components/line-chart/line-chart.module';
|
||||
import { GfLineChartModule } from '@ghostfolio/ui/line-chart/line-chart.module';
|
||||
import { GfLogoModule } from '@ghostfolio/ui/logo';
|
||||
|
||||
import { LandingPageRoutingModule } from './landing-page-routing.module';
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { Router } from '@angular/router';
|
||||
import { LineChartItem } from '@ghostfolio/client/components/line-chart/interfaces/line-chart.interface';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
|
||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
import { format } from 'date-fns';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
|
@@ -10,7 +10,6 @@ import {
|
||||
} from '@angular/core';
|
||||
import { MatTabChangeEvent } from '@angular/material/tabs';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { LineChartItem } from '@ghostfolio/client/components/line-chart/interfaces/line-chart.interface';
|
||||
import { DataService } from '@ghostfolio/client/services/data.service';
|
||||
import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
|
||||
import { UserService } from '@ghostfolio/client/services/user/user.service';
|
||||
@@ -21,6 +20,7 @@ import {
|
||||
} from '@ghostfolio/common/interfaces';
|
||||
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
|
||||
import { DateRange } from '@ghostfolio/common/types';
|
||||
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
|
||||
import { DeviceDetectorService } from 'ngx-device-detector';
|
||||
import { Subject } from 'rxjs';
|
||||
import { first, takeUntil } from 'rxjs/operators';
|
||||
|
@@ -29,6 +29,7 @@
|
||||
class="mr-3"
|
||||
symbol="Performance"
|
||||
[historicalDataItems]="historicalDataItems"
|
||||
[showGradient]="true"
|
||||
[showLoader]="false"
|
||||
[showXAxis]="false"
|
||||
[showYAxis]="false"
|
||||
|
@@ -4,9 +4,9 @@ import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { GfLineChartModule } from '@ghostfolio/client/components/line-chart/line-chart.module';
|
||||
import { GfPortfolioPerformanceModule } from '@ghostfolio/client/components/portfolio-performance/portfolio-performance.module';
|
||||
import { GfPositionsModule } from '@ghostfolio/client/components/positions/positions.module';
|
||||
import { GfLineChartModule } from '@ghostfolio/ui/line-chart/line-chart.module';
|
||||
import { GfNoTransactionsInfoModule } from '@ghostfolio/ui/no-transactions-info';
|
||||
|
||||
import { ZenPageRoutingModule } from './zen-page-routing.module';
|
||||
|
Reference in New Issue
Block a user