Browse Source

fix(client): implement custom tooltip positioner with type safety

pull/6264/head
KenTandrian 1 week ago
parent
commit
15b2b78ce9
  1. 8
      apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts
  2. 8
      apps/client/src/app/components/investment-chart/investment-chart.component.ts
  3. 3
      apps/client/src/main.ts
  4. 4
      libs/common/src/lib/chart-helper.ts
  5. 19
      libs/ui/src/lib/chart/chart.registry.ts
  6. 1
      libs/ui/src/lib/chart/index.ts
  7. 8
      libs/ui/src/lib/line-chart/line-chart.component.ts

8
apps/client/src/app/components/benchmark-comparator/benchmark-comparator.component.ts

@ -1,6 +1,5 @@
import { import {
getTooltipOptions, getTooltipOptions,
getTooltipPositionerMapTop,
getVerticalHoverLinePlugin getVerticalHoverLinePlugin
} from '@ghostfolio/common/chart-helper'; } from '@ghostfolio/common/chart-helper';
import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config'; import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config';
@ -43,8 +42,7 @@ import {
PointElement, PointElement,
TimeScale, TimeScale,
Tooltip, Tooltip,
type TooltipOptions, type TooltipOptions
type TooltipPosition
} from 'chart.js'; } from 'chart.js';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import annotationPlugin from 'chartjs-plugin-annotation'; import annotationPlugin from 'chartjs-plugin-annotation';
@ -98,9 +96,6 @@ export class GfBenchmarkComparatorComponent implements OnChanges, OnDestroy {
Tooltip Tooltip
); );
Tooltip.positioners['top'] = (_elements, position: TooltipPosition) =>
getTooltipPositionerMapTop(this.chart, position);
addIcons({ arrowForwardOutline }); addIcons({ arrowForwardOutline });
} }
@ -264,7 +259,6 @@ export class GfBenchmarkComparatorComponent implements OnChanges, OnDestroy {
unit: '%' unit: '%'
}), }),
mode: 'index', mode: 'index',
// @ts-ignore
position: 'top', position: 'top',
xAlign: 'center', xAlign: 'center',
yAlign: 'bottom' yAlign: 'bottom'

8
apps/client/src/app/components/investment-chart/investment-chart.component.ts

@ -1,6 +1,5 @@
import { import {
getTooltipOptions, getTooltipOptions,
getTooltipPositionerMapTop,
getVerticalHoverLinePlugin, getVerticalHoverLinePlugin,
transformTickToAbbreviation transformTickToAbbreviation
} from '@ghostfolio/common/chart-helper'; } from '@ghostfolio/common/chart-helper';
@ -37,8 +36,7 @@ import {
PointElement, PointElement,
TimeScale, TimeScale,
Tooltip, Tooltip,
type TooltipOptions, type TooltipOptions
type TooltipPosition
} from 'chart.js'; } from 'chart.js';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import annotationPlugin from 'chartjs-plugin-annotation'; import annotationPlugin from 'chartjs-plugin-annotation';
@ -82,9 +80,6 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
TimeScale, TimeScale,
Tooltip Tooltip
); );
Tooltip.positioners['top'] = (_elements, position: TooltipPosition) =>
getTooltipPositionerMapTop(this.chart, position);
} }
public ngOnChanges() { public ngOnChanges() {
@ -301,7 +296,6 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
unit: this.isInPercent ? '%' : undefined unit: this.isInPercent ? '%' : undefined
}), }),
mode: 'index', mode: 'index',
// @ts-ignore
position: 'top', position: 'top',
xAlign: 'center', xAlign: 'center',
yAlign: 'bottom' yAlign: 'bottom'

3
apps/client/src/main.ts

@ -1,5 +1,6 @@
import { InfoResponse } from '@ghostfolio/common/interfaces'; import { InfoResponse } from '@ghostfolio/common/interfaces';
import { filterGlobalPermissions } from '@ghostfolio/common/permissions'; import { filterGlobalPermissions } from '@ghostfolio/common/permissions';
import { registerChartConfiguration } from '@ghostfolio/ui/chart';
import { GF_ENVIRONMENT } from '@ghostfolio/ui/environment'; import { GF_ENVIRONMENT } from '@ghostfolio/ui/environment';
import { GfNotificationModule } from '@ghostfolio/ui/notifications'; import { GfNotificationModule } from '@ghostfolio/ui/notifications';
@ -58,6 +59,8 @@ import { environment } from './environments/environment';
enableProdMode(); enableProdMode();
} }
registerChartConfiguration();
await bootstrapApplication(GfAppComponent, { await bootstrapApplication(GfAppComponent, {
providers: [ providers: [
authInterceptorProviders, authInterceptorProviders,

4
libs/common/src/lib/chart-helper.ts

@ -92,8 +92,8 @@ export function getTooltipOptions({
}; };
} }
export function getTooltipPositionerMapTop<T extends 'line' | 'bar'>( export function getTooltipPositionerMapTop(
chart: Chart<T>, chart: Chart,
position: TooltipPosition position: TooltipPosition
) { ) {
if (!position || !chart?.chartArea) { if (!position || !chart?.chartArea) {

19
libs/ui/src/lib/chart/chart.registry.ts

@ -0,0 +1,19 @@
import { getTooltipPositionerMapTop } from '@ghostfolio/common/chart-helper';
import { Tooltip, TooltipPositionerFunction, ChartType } from 'chart.js';
declare module 'chart.js' {
interface TooltipPositionerMap {
top: TooltipPositionerFunction<ChartType>;
}
}
export function registerChartConfiguration() {
if (Tooltip.positioners['top']) {
return;
}
Tooltip.positioners.top = function (_elements, eventPosition) {
return getTooltipPositionerMapTop(this.chart, eventPosition);
};
}

1
libs/ui/src/lib/chart/index.ts

@ -0,0 +1 @@
export * from './chart.registry';

8
libs/ui/src/lib/line-chart/line-chart.component.ts

@ -1,6 +1,5 @@
import { import {
getTooltipOptions, getTooltipOptions,
getTooltipPositionerMapTop,
getVerticalHoverLinePlugin getVerticalHoverLinePlugin
} from '@ghostfolio/common/chart-helper'; } from '@ghostfolio/common/chart-helper';
import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config'; import { primaryColorRgb, secondaryColorRgb } from '@ghostfolio/common/config';
@ -35,8 +34,7 @@ import {
PointElement, PointElement,
TimeScale, TimeScale,
Tooltip, Tooltip,
type TooltipOptions, type TooltipOptions
type TooltipPosition
} from 'chart.js'; } from 'chart.js';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader'; import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
@ -87,9 +85,6 @@ export class GfLineChartComponent
TimeScale, TimeScale,
Tooltip Tooltip
); );
Tooltip.positioners['top'] = (_elements, position: TooltipPosition) =>
getTooltipPositionerMapTop(this.chart, position);
} }
public ngAfterViewInit() { public ngAfterViewInit() {
@ -337,7 +332,6 @@ export class GfLineChartComponent
unit: this.unit unit: this.unit
}), }),
mode: 'index', mode: 'index',
// @ts-ignore
position: 'top', position: 'top',
xAlign: 'center', xAlign: 'center',
yAlign: 'bottom' yAlign: 'bottom'

Loading…
Cancel
Save