Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use highchart offline export for downloads #3135

Open
wants to merge 49 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
9a94bb2
feat: add HighchartsChartProvider
HendrikThePendric Jul 9, 2024
174bd62
feat: replace chart in redux store with chart provider
HendrikThePendric Jul 9, 2024
bf8e09a
chore: implement client side download WIP
HendrikThePendric Jul 9, 2024
a92a4ca
chore: add noto base font
HendrikThePendric Jul 11, 2024
e916a9a
fix: add db locale to user settings provider
HendrikThePendric Jul 15, 2024
15a9f26
chore: add noto fonts for pdf generation
HendrikThePendric Jul 15, 2024
159a8b6
fix: serve suitable noto font bundle per script or language
HendrikThePendric Jul 15, 2024
60cdf00
chore: fix typo
HendrikThePendric Jul 15, 2024
904befd
chore: add additional fonts and mappings
HendrikThePendric Jul 16, 2024
dc614a2
chore: include newly added fonts in comment
HendrikThePendric Jul 16, 2024
d54eeea
chore: tweak test config
HendrikThePendric Jul 16, 2024
304e44f
chore: tweak jest config so it only reports to portal when on CI
HendrikThePendric Jul 16, 2024
1619321
chore: disable report-portal debug logging
HendrikThePendric Jul 16, 2024
a4a5e95
chore: remove reference to maps app
HendrikThePendric Jul 16, 2024
05a00e8
chore: fix failing tests
HendrikThePendric Jul 16, 2024
77ad86c
feat: add HighchartsChartProvider
HendrikThePendric Jul 9, 2024
b84588a
feat: replace chart in redux store with chart provider
HendrikThePendric Jul 9, 2024
b456982
chore: implement client side download WIP
HendrikThePendric Jul 9, 2024
ed8b79b
fix: add db locale to user settings provider
HendrikThePendric Jul 15, 2024
bd45555
fix: serve suitable noto font bundle per script or language
HendrikThePendric Jul 15, 2024
7318a08
chore: fix typo
HendrikThePendric Jul 15, 2024
53c11a3
chore: add additional fonts and mappings
HendrikThePendric Jul 16, 2024
aec2b35
chore: include newly added fonts in comment
HendrikThePendric Jul 16, 2024
d1595d8
chore: tweak test config
HendrikThePendric Jul 16, 2024
862a07f
chore: tweak jest config so it only reports to portal when on CI
HendrikThePendric Jul 16, 2024
e7897aa
chore: disable report-portal debug logging
HendrikThePendric Jul 16, 2024
8a14b36
chore: remove reference to maps app
HendrikThePendric Jul 16, 2024
18d5e96
chore: fix failing tests
HendrikThePendric Jul 16, 2024
44fcbbd
chore: deduplicate dependencies
HendrikThePendric Sep 23, 2024
19559ab
chore: remove logic for differentiating between single value and others
HendrikThePendric Sep 23, 2024
6a2d9d8
fix: don't run getNotoFontVariantsForLocale for png downloads
HendrikThePendric Sep 24, 2024
43499ef
chore: remove single value specific test code because it is now a hig…
HendrikThePendric Sep 24, 2024
aaa8ab3
chore: remove stray log
HendrikThePendric Sep 24, 2024
d6446ac
chore: deduplicate dependencies
HendrikThePendric Sep 24, 2024
ecdcf72
chore: remove unused vars
HendrikThePendric Sep 24, 2024
083e774
chore: set contextTypes during Jest test run only
HendrikThePendric Sep 24, 2024
1dda633
fix: inform SingleValue render process about export MIME type
HendrikThePendric Oct 10, 2024
2283788
fix: set default locale to 'en'
HendrikThePendric Oct 15, 2024
508b2bb
refactor: clean up pdf font computations
HendrikThePendric Oct 16, 2024
f68bd68
chore: adjust comment for clarity
HendrikThePendric Oct 16, 2024
ff615bf
test: fix open e2e test because single value is no long a nonHighchar…
HendrikThePendric Oct 16, 2024
4865ca6
test: fix new e2e test because single value now is a highcharts chart
HendrikThePendric Oct 16, 2024
9b00103
test: adjust legend test to new single value implementation
HendrikThePendric Oct 17, 2024
f6c5608
chore: use analytics feature branch
HendrikThePendric Oct 21, 2024
144cfea
chore: delete import of removed function
HendrikThePendric Oct 21, 2024
b219a9d
chore: update analytics dep after its feat branch was rebased onto ma…
HendrikThePendric Oct 22, 2024
1992e1f
chore: update analytics to get no data changes
HendrikThePendric Oct 22, 2024
2e2120f
chore: update analytics dep
HendrikThePendric Oct 22, 2024
5e362e0
Merge branch 'master' into feat/use-highcharts-clientside-downloads-D…
HendrikThePendric Nov 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 4 additions & 15 deletions cypress/elements/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import {
} from '@dhis2/analytics'

const visualizationContainerEl = 'visualization-container'
const visualizationTitleEl = 'visualization-title'
const visualizationSubtitleEl = 'visualization-subtitle'
const chartContainerEl = '.highcharts-container'
const highchartsLegendEl = '.highcharts-legend'
const highchartsTitleEl = '.highcharts-title'
Expand All @@ -24,11 +22,7 @@ const AOTitleDirtyEl = 'titlebar-dirty'
const timeout = {
timeout: 40000,
}
const nonHighchartsTypes = [
VIS_TYPE_OUTLIER_TABLE,
VIS_TYPE_PIVOT_TABLE,
VIS_TYPE_SINGLE_VALUE,
]
const nonHighchartsTypes = [VIS_TYPE_OUTLIER_TABLE, VIS_TYPE_PIVOT_TABLE]

export const expectVisualizationToBeVisible = (visType = VIS_TYPE_COLUMN) =>
nonHighchartsTypes.includes(visType)
Expand Down Expand Up @@ -64,13 +58,11 @@ export const expectChartToContainDimensionItem = (visType, itemName) => {
case VIS_TYPE_GAUGE:
case VIS_TYPE_YEAR_OVER_YEAR_COLUMN:
case VIS_TYPE_YEAR_OVER_YEAR_LINE:
case VIS_TYPE_SINGLE_VALUE:
cy.get(highchartsTitleEl)
.should('be.visible')
.and('contain', itemName)
break
case VIS_TYPE_SINGLE_VALUE:
cy.getBySel(visualizationTitleEl).should('contain', itemName)
break
case VIS_TYPE_PIVOT_TABLE:
cy.getBySel('visualization-column-header')
.contains(itemName)
Expand Down Expand Up @@ -119,10 +111,7 @@ export const expectChartItemsToHaveLength = (length) =>
cy.get(highchartsChartItemEl).children().should('have.length', length)

export const expectSVTitleToHaveColor = (color) =>
cy.getBySel(visualizationTitleEl).invoke('attr', 'fill').should('eq', color)
cy.get('text.highcharts-title').should('have.css', 'color', color)

export const expectSVSubtitleToHaveColor = (color) =>
cy
.getBySel(visualizationSubtitleEl)
.invoke('attr', 'fill')
.should('eq', color)
cy.get('text.highcharts-subtitle').should('have.css', 'color', color)
1 change: 0 additions & 1 deletion cypress/elements/optionsModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ export {
expectLegendDisplayStyleToBeText,
expectLegendDisplayStyleToBeFill,
expectSingleValueToHaveTextColor,
expectSingleValueToNotHaveBackgroundColor,
expectSingleValueToHaveBackgroundColor,
toggleLegendKeyOption,
expectLegendKeyOptionToBeEnabled,
Expand Down
11 changes: 2 additions & 9 deletions cypress/elements/optionsModal/legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const legendKeyContainerEl = 'legend-key-container'
const legendKeyItemEl = 'legend-key-item'
const singleValueTextEl = 'visualization-primary-value'
const singleValueIconEl = 'visualization-icon'
const singleValueOutputEl = 'visualization-container'
const legendDisplayStrategyByDataItemEl = 'legend-display-strategy-BY_DATA_ITEM'
const legendDisplayStrategyFixedEl = 'legend-display-strategy-FIXED'
const legendDisplayStyleOptionTextEl = 'legend-display-style-option-TEXT'
Expand Down Expand Up @@ -76,16 +75,10 @@ export const expectFixedLegendSetToBe = (legendSetName) =>
cy.getBySel(fixedLegendSetSelectEl).should('contain', legendSetName)

export const expectSingleValueToHaveTextColor = (color) =>
cy.getBySel(singleValueTextEl).invoke('attr', 'fill').should('eq', color)

export const expectSingleValueToNotHaveBackgroundColor = () =>
cy.getBySel(singleValueOutputEl).should('not.have.attr', 'style')
cy.getBySel(singleValueTextEl).should('have.css', 'color', color)

export const expectSingleValueToHaveBackgroundColor = (color) =>
cy
.getBySel(singleValueOutputEl)
.invoke('attr', 'style')
.should('contain', `background-color: ${color}`)
cy.get('rect.highcharts-background').should('have.attr', 'fill', color)

export const expectSingleValueToHaveIconColor = (color) =>
cy
Expand Down
49 changes: 25 additions & 24 deletions cypress/integration/options/legend.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ import {
setItemToType,
clickOptionsModalHideButton,
expectSingleValueToHaveBackgroundColor,
expectSingleValueToNotHaveBackgroundColor,
changeDisplayStyleToFill,
changeColor,
OPTIONS_TAB_STYLE,
Expand Down Expand Up @@ -156,17 +155,19 @@ describe('Options - Legend', () => {

it('applies different styles of legend to a Single Value chart', () => {
const TEST_ITEM = TEST_ITEMS[0]
const EXPECTED_STANDARD_TEXT_COLOR = '#212934'
const EXPECTED_CONTRAST_TEXT_COLOR = '#ffffff'
const EXPECTED_STANDARD_TEXT_COLOR = 'rgb(33, 41, 52)'
const EXPECTED_CONTRAST_TEXT_COLOR = 'rgb(255, 255, 255)'
const EXPECTED_BACKGROUND_COLOR_1 = '#FFFFB2'
const EXPECTED_TEXT_COLOR_1 = '#FFFFB2'
const EXPECTED_TEXT_COLOR_1 = 'rgb(255, 255, 178)'
const EXPECTED_BACKGROUND_COLOR_2 = '#B3402B'
const EXPECTED_TEXT_COLOR_2 = '#B3402B'
const EXPECTED_TEXT_COLOR_2 = 'rgb(179, 64, 43)'
const EXPECTED_CUSTOM_TITLE_COLOR = '#ff7700'
const EXPECTED_CUSTOM_TITLE_COLOR_RGB = 'rgb(255, 119, 0)'
const EXPECTED_CUSTOM_SUBTITLE_COLOR = '#ffaa00'
const EXPECTED_CUSTOM_SUBTITLE_COLOR_RGB = 'rgb(255, 170, 0)'
const TEST_LEGEND_SET_WITH_CONTRAST = 'Age 15y interval'
const EXPECTED_STANDARD_TITLE_COLOR = '#212934'
const EXPECTED_STANDARD_SUBTITLE_COLOR = '#4a5768'
const EXPECTED_STANDARD_TITLE_COLOR = 'rgb(33, 41, 52)'
const EXPECTED_STANDARD_SUBTITLE_COLOR = 'rgb(74, 87, 104)'

cy.log('navigates to the start page and adds data items')
goToStartPage()
Expand All @@ -176,7 +177,7 @@ describe('Options - Legend', () => {
clickDimensionModalUpdateButton()
expectVisualizationToBeVisible(VIS_TYPE_SINGLE_VALUE)
expectSingleValueToHaveTextColor(EXPECTED_STANDARD_TEXT_COLOR)
expectSingleValueToNotHaveBackgroundColor()
expectSingleValueToHaveBackgroundColor('transparent')

cy.log('enables legend')
openOptionsModal(OPTIONS_TAB_LEGEND)
Expand Down Expand Up @@ -206,7 +207,7 @@ describe('Options - Legend', () => {
// Legend on text, no contrast, no custom title colors
cy.log('verifies text color legend is applied')
expectSingleValueToHaveTextColor(EXPECTED_TEXT_COLOR_1)
expectSingleValueToNotHaveBackgroundColor()
expectSingleValueToHaveBackgroundColor('transparent')
expectSVTitleToHaveColor(EXPECTED_STANDARD_TITLE_COLOR)
expectSVSubtitleToHaveColor(EXPECTED_STANDARD_SUBTITLE_COLOR)

Expand All @@ -225,11 +226,11 @@ describe('Options - Legend', () => {
// Legend on text, with contrast (N/, no custom title colors
cy.log('verifies text color legend is applied')
expectSingleValueToHaveTextColor(EXPECTED_TEXT_COLOR_2)
expectSingleValueToNotHaveBackgroundColor()
expectSingleValueToHaveBackgroundColor('transparent')
expectSVTitleToHaveColor(EXPECTED_STANDARD_TITLE_COLOR)
expectSVSubtitleToHaveColor(EXPECTED_STANDARD_SUBTITLE_COLOR)

cy.log('changees legend display style to background color')
cy.log('changes legend display style to background color')
openOptionsModal(OPTIONS_TAB_LEGEND)
expectLegendDisplayStrategyToBeFixed()
expectLegendDisplayStyleToBeText()
Expand Down Expand Up @@ -259,8 +260,8 @@ describe('Options - Legend', () => {
)
expectSingleValueToHaveTextColor(EXPECTED_CONTRAST_TEXT_COLOR)
expectSingleValueToHaveBackgroundColor(EXPECTED_BACKGROUND_COLOR_2)
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR)
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR_RGB)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR_RGB)

cy.log('changes legend display style to text color')
openOptionsModal(OPTIONS_TAB_LEGEND)
Expand All @@ -271,12 +272,12 @@ describe('Options - Legend', () => {
clickOptionsModalUpdateButton()
expectVisualizationToBeVisible(VIS_TYPE_SINGLE_VALUE)

// Legend on text, with contrast, with custom title colo
// Legend on text, with contrast, with custom title colors
cy.log('verifies text color legend and custom title colors are applied')
expectSingleValueToHaveTextColor(EXPECTED_TEXT_COLOR_2)
expectSingleValueToNotHaveBackgroundColor()
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR)
expectSingleValueToHaveBackgroundColor('transparent')
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR_RGB)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR_RGB)

cy.log('changes legend display strategy to by data item')
openOptionsModal(OPTIONS_TAB_LEGEND)
Expand All @@ -287,12 +288,12 @@ describe('Options - Legend', () => {
clickOptionsModalUpdateButton()
expectVisualizationToBeVisible(VIS_TYPE_SINGLE_VALUE)

// Legend on text, no contrast, with custom title colo
// Legend on text, no contrast, with custom title colors
cy.log('verifies text color legend and custom title colors are applied')
expectSingleValueToHaveTextColor(EXPECTED_TEXT_COLOR_1)
expectSingleValueToNotHaveBackgroundColor()
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR)
expectSingleValueToHaveBackgroundColor('transparent')
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR_RGB)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR_RGB)

cy.log('changes legend display style to background color')
openOptionsModal(OPTIONS_TAB_LEGEND)
Expand All @@ -309,8 +310,8 @@ describe('Options - Legend', () => {
)
expectSingleValueToHaveTextColor(EXPECTED_STANDARD_TEXT_COLOR)
expectSingleValueToHaveBackgroundColor(EXPECTED_BACKGROUND_COLOR_1)
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR)
expectSVTitleToHaveColor(EXPECTED_CUSTOM_TITLE_COLOR_RGB)
expectSVSubtitleToHaveColor(EXPECTED_CUSTOM_SUBTITLE_COLOR_RGB)

cy.log('verifies legend key is hidden')
expectLegendKeyToBeHidden()
Expand Down Expand Up @@ -605,7 +606,7 @@ describe('Options - Legend', () => {
const TEST_ITEM = TEST_ITEMS[0]
const EXPECTED_FIXED_COLOR = '#c7e9c0'
const valueCellEl = 'visualization-value-cell'
const EXPECTED_SV_STANDARD_TEXT_COLOR = '#212934'
const EXPECTED_SV_STANDARD_TEXT_COLOR = 'rgb(33, 41, 52)'
const EXPECTED_PT_STANDARD_TEXT_COLOR = 'color: rgb(33, 41, 52)'

cy.log('navigates to the start page and adds data items')
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"typescript": "^4.8.4"
},
"dependencies": {
"@dhis2/analytics": "^26.8.7",
"@dhis2/analytics": "^26.9.0",
"@dhis2/app-runtime": "^3.10.4",
"@dhis2/app-runtime-adapter-d2": "^1.1.0",
"@dhis2/app-service-datastore": "^1.0.0-beta.3",
Expand Down
Binary file added public/fonts/NotoSans-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSans-BoldItalic.ttf
Binary file not shown.
Binary file added public/fonts/NotoSans-Italic.ttf
Binary file not shown.
Binary file added public/fonts/NotoSans-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansArabic-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansArabic-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansBengali-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansBengali-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansEthiopic-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansEthiopic-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansHebrew-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansHebrew-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansJP-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansJP-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansKR-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansKR-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansKhmer-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansKhmer-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansLao-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansLao-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansMyanmar-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansMyanmar-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansOriya-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansOriya-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansSC-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansSC-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansSinhala-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansSinhala-Regular.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansThai-Bold.ttf
Binary file not shown.
Binary file added public/fonts/NotoSansThai-Regular.ttf
Binary file not shown.
69 changes: 38 additions & 31 deletions src/AppWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React from 'react'
import { Provider as ReduxProvider } from 'react-redux'
import thunk from 'redux-thunk'
import { App } from './components/App.js'
import { ChartProvider } from './components/ChartProvider.js'
import UserSettingsProvider, {
UserSettingsCtx,
} from './components/UserSettingsProvider.js'
Expand Down Expand Up @@ -33,37 +34,43 @@ const AppWrapper = () => {

return (
<ReduxProvider store={store}>
<DataStoreProvider namespace={USER_DATASTORE_NAMESPACE}>
<UserSettingsProvider>
<UserSettingsCtx.Consumer>
{({ userSettings }) => {
return userSettings?.uiLocale ? (
<D2Shim
d2Config={d2Config}
locale={userSettings.uiLocale}
>
{({ d2 }) => {
if (!d2) {
// TODO: Handle errors in d2 initialization
return null
} else {
return (
<App
d2={d2}
location={history.location}
baseUrl={baseUrl}
dataEngine={engine}
userSettings={userSettings}
/>
)
}
}}
</D2Shim>
) : null
}}
</UserSettingsCtx.Consumer>
</UserSettingsProvider>
</DataStoreProvider>
<ChartProvider>
<DataStoreProvider namespace={USER_DATASTORE_NAMESPACE}>
<UserSettingsProvider>
<UserSettingsCtx.Consumer>
{(userSettings) => {
return userSettings?.uiLocale ? (
<D2Shim
d2Config={d2Config}
locale={userSettings.uiLocale}
>
{({ d2 }) => {
if (!d2) {
// TODO: Handle errors in d2 initialization
return null
} else {
return (
<App
d2={d2}
location={
history.location
}
baseUrl={baseUrl}
dataEngine={engine}
userSettings={
userSettings
}
/>
)
}
}}
</D2Shim>
) : null
}}
</UserSettingsCtx.Consumer>
</UserSettingsProvider>
</DataStoreProvider>
</ChartProvider>
</ReduxProvider>
)
}
Expand Down
6 changes: 0 additions & 6 deletions src/actions/chart.js

This file was deleted.

2 changes: 0 additions & 2 deletions src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {
sGetSettingsDigitGroupSeparator,
} from '../reducers/settings.js'
import { sGetVisualization } from '../reducers/visualization.js'
import * as fromChart from './chart.js'
import * as fromCurrent from './current.js'
import * as fromDimensions from './dimensions.js'
import * as fromLoader from './loader.js'
Expand All @@ -49,7 +48,6 @@ export {
fromMetadata,
fromSettings,
fromUser,
fromChart,
fromSnackbar,
fromLoader,
}
Expand Down
31 changes: 31 additions & 0 deletions src/components/ChartProvider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import PropTypes from 'prop-types'
import React, { createContext, useCallback, useContext, useRef } from 'react'

const throwIfNotInitialized = () => {
throw new Error('ChartContext not yet initialized')
}

export const ChartContext = createContext({
getChart: throwIfNotInitialized,
setChart: throwIfNotInitialized,
})

export const useChartContext = () => useContext(ChartContext)

export const ChartProvider = ({ children }) => {
const chartRef = useRef(null)
const getChart = useCallback(() => chartRef.current, [])
const setChart = useCallback((chart = null) => {
chartRef.current = chart
}, [])

return (
<ChartContext.Provider value={{ getChart, setChart }}>
{children}
</ChartContext.Provider>
)
}

ChartProvider.propTypes = {
children: PropTypes.node,
}
Loading
Loading