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 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
ef3b92b
feat: add HighchartsChartProvider
HendrikThePendric Jul 9, 2024
5c79c2f
feat: replace chart in redux store with chart provider
HendrikThePendric Jul 9, 2024
f91f4a3
chore: implement client side download WIP
HendrikThePendric Jul 9, 2024
d7fa2f6
chore: add noto base font
HendrikThePendric Jul 11, 2024
cfa9a64
fix: add db locale to user settings provider
HendrikThePendric Jul 15, 2024
702a5a2
chore: add noto fonts for pdf generation
HendrikThePendric Jul 15, 2024
c2d5ab6
fix: serve suitable noto font bundle per script or language
HendrikThePendric Jul 15, 2024
e1e34f1
chore: fix typo
HendrikThePendric Jul 15, 2024
e927dcd
chore: add additional fonts and mappings
HendrikThePendric Jul 16, 2024
f4f9870
chore: include newly added fonts in comment
HendrikThePendric Jul 16, 2024
612d55a
chore: tweak test config
HendrikThePendric Jul 16, 2024
b18eb66
chore: tweak jest config so it only reports to portal when on CI
HendrikThePendric Jul 16, 2024
bb0fbdd
chore: disable report-portal debug logging
HendrikThePendric Jul 16, 2024
910f025
chore: remove reference to maps app
HendrikThePendric Jul 16, 2024
281ce39
chore: fix failing tests
HendrikThePendric Jul 16, 2024
332697a
feat: add HighchartsChartProvider
HendrikThePendric Jul 9, 2024
68ee53e
feat: replace chart in redux store with chart provider
HendrikThePendric Jul 9, 2024
579db2f
chore: implement client side download WIP
HendrikThePendric Jul 9, 2024
d72311c
fix: add db locale to user settings provider
HendrikThePendric Jul 15, 2024
1d8484a
fix: serve suitable noto font bundle per script or language
HendrikThePendric Jul 15, 2024
be0c6fc
chore: fix typo
HendrikThePendric Jul 15, 2024
d15ee9e
chore: add additional fonts and mappings
HendrikThePendric Jul 16, 2024
850b782
chore: include newly added fonts in comment
HendrikThePendric Jul 16, 2024
9a9bd9f
chore: tweak test config
HendrikThePendric Jul 16, 2024
7ec3650
chore: tweak jest config so it only reports to portal when on CI
HendrikThePendric Jul 16, 2024
fc8d849
chore: disable report-portal debug logging
HendrikThePendric Jul 16, 2024
e43760f
chore: remove reference to maps app
HendrikThePendric Jul 16, 2024
7448a96
chore: fix failing tests
HendrikThePendric Jul 16, 2024
382aca9
chore: deduplicate dependencies
HendrikThePendric Sep 23, 2024
e57ed18
chore: remove logic for differentiating between single value and others
HendrikThePendric Sep 23, 2024
eeadab0
fix: don't run getNotoFontVariantsForLocale for png downloads
HendrikThePendric Sep 24, 2024
233efdc
chore: remove single value specific test code because it is now a hig…
HendrikThePendric Sep 24, 2024
8653d79
chore: remove stray log
HendrikThePendric Sep 24, 2024
e7320d5
chore: deduplicate dependencies
HendrikThePendric Sep 24, 2024
be2a805
chore: remove unused vars
HendrikThePendric Sep 24, 2024
1fc240a
chore: set contextTypes during Jest test run only
HendrikThePendric Sep 24, 2024
aa73b6f
fix: inform SingleValue render process about export MIME type
HendrikThePendric Oct 10, 2024
ed13528
fix: set default locale to 'en'
HendrikThePendric Oct 15, 2024
01e168b
refactor: clean up pdf font computations
HendrikThePendric Oct 16, 2024
e992a80
chore: adjust comment for clarity
HendrikThePendric Oct 16, 2024
8d495b6
test: fix open e2e test because single value is no long a nonHighchar…
HendrikThePendric Oct 16, 2024
16335d2
test: fix new e2e test because single value now is a highcharts chart
HendrikThePendric Oct 16, 2024
18f9c18
test: adjust legend test to new single value implementation
HendrikThePendric Oct 17, 2024
c2451ba
fix: handle missing icon file more gracefully
HendrikThePendric Oct 17, 2024
26d7c91
fix: include credentials when fetching the icon
HendrikThePendric Oct 21, 2024
2693d95
Merge branch 'master' into feat/use-highcharts-clientside-downloads-D…
HendrikThePendric Oct 21, 2024
45ecaef
chore: use analytics feature branch
HendrikThePendric Oct 21, 2024
542d14f
chore: delete import of removed function
HendrikThePendric Oct 21, 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": "git+https://github.com/d2-ci/analytics.git#feat/single-value-as-highcharts-chart-DHIS2-17928",
"@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