diff --git a/src/lib/components/AgGrid.react.js b/src/lib/components/AgGrid.react.js index ce2e1c3a..3bec49b2 100644 --- a/src/lib/components/AgGrid.react.js +++ b/src/lib/components/AgGrid.react.js @@ -10,8 +10,8 @@ ModuleRegistry.registerModules([AllCommunityModule]); const RealAgGrid = lazy(LazyLoader.agGrid); const RealAgGridEnterprise = lazy(LazyLoader.agGridEnterprise); -function getGrid(enable) { - return enable ? RealAgGridEnterprise : RealAgGrid; +function getGrid(enableEnterpriseModules) { + return enableEnterpriseModules ? RealAgGridEnterprise : RealAgGrid; } export const defaultProps = { @@ -21,6 +21,7 @@ export const defaultProps = { selectAll: false, deselectAll: false, enableEnterpriseModules: false, + dashEnableCharts: false, updateColumnState: false, persisted_props: ['selectedRows'], persistence_type: 'local', @@ -64,12 +65,62 @@ function DashAgGrid(props) { } }, [props.rowTransaction, state.mounted, buildArray]); - const {enableEnterpriseModules} = props; + const { + enableEnterpriseModules, + dashEnableCharts, + dashGridOptions = {}, + } = props; + const normalizedDashEnableCharts = + typeof dashEnableCharts === 'undefined' || dashEnableCharts === null + ? false + : dashEnableCharts; + const validDashEnableCharts = [ + false, + true, + 'enterprise', + 'community', + ].includes(normalizedDashEnableCharts); + const hasConflictingEnableChartsSetting = + normalizedDashEnableCharts && dashGridOptions.enableCharts === false; + const gridDashOptions = normalizedDashEnableCharts + ? {...dashGridOptions, enableCharts: true} + : dashGridOptions; + const hasEnableCharts = gridDashOptions.enableCharts; + + if (!validDashEnableCharts) { + throw new Error( + "dashEnableCharts must be one of: false, true, 'enterprise', 'community'." + ); + } + + if (normalizedDashEnableCharts && !enableEnterpriseModules) { + throw new Error( + 'dashEnableCharts is only supported when enableEnterpriseModules is true.' + ); + } + + if (hasConflictingEnableChartsSetting) { + throw new Error( + 'dashEnableCharts cannot be combined with dashGridOptions.enableCharts=false.' + ); + } + + if (hasEnableCharts && !normalizedDashEnableCharts) { + throw new Error( + "enableCharts is set, but chart modules are not loaded. Set enableEnterpriseModules=true and dashEnableCharts=true, 'community', or 'enterprise'." + ); + } + const RealComponent = getGrid(enableEnterpriseModules); return ( - + ); } @@ -494,11 +545,26 @@ DashAgGrid.propTypes = { */ licenseKey: PropTypes.string, + /** + * License key for AG Charts Enterprise when dashEnableCharts is "enterprise". + * If not provided, licenseKey is used. + */ + chartsLicenseKey: PropTypes.string, + /** * If True, enable ag-grid Enterprise modules. Recommended to use with licenseKey. */ enableEnterpriseModules: PropTypes.bool, + /** + * Load enterprise AG Charts modules for integrated charts. + * true and "community" are equivalent and set dashGridOptions.enableCharts=true. + */ + dashEnableCharts: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.oneOf(['community', 'enterprise']), + ]), + /** * The rowData in the grid after inline filters are applied. */ diff --git a/src/lib/fragments/AgGridEnterprise.react.js b/src/lib/fragments/AgGridEnterprise.react.js index fa847e63..a50c6368 100644 --- a/src/lib/fragments/AgGridEnterprise.react.js +++ b/src/lib/fragments/AgGridEnterprise.react.js @@ -2,10 +2,15 @@ import React from 'react'; import {ModuleRegistry} from 'ag-grid-community'; import { AllEnterpriseModule, + IntegratedChartsModule, LicenseManager, SparklinesModule, } from 'ag-grid-enterprise'; -import {AgChartsEnterpriseModule} from 'ag-charts-enterprise'; +import {AgChartsCommunityModule} from 'ag-charts-community'; +import { + AgChartsEnterpriseModule, + LicenseManager as AgChartsLicenseManager, +} from 'ag-charts-enterprise'; import MemoizedAgGrid, {propTypes} from './AgGrid.react'; // Register all enterprise features @@ -15,10 +20,25 @@ ModuleRegistry.registerModules([ ]); export default function DashAgGridEnterprise(props) { - const {licenseKey} = props; + const {licenseKey, chartsLicenseKey, dashEnableCharts} = props; if (licenseKey) { LicenseManager.setLicenseKey(licenseKey); } + if (dashEnableCharts) { + if (dashEnableCharts === 'enterprise') { + const effectiveChartsLicenseKey = chartsLicenseKey || licenseKey; + if (effectiveChartsLicenseKey) { + AgChartsLicenseManager.setLicenseKey(effectiveChartsLicenseKey); + } + ModuleRegistry.registerModules([ + IntegratedChartsModule.with(AgChartsEnterpriseModule), + ]); + } else { + ModuleRegistry.registerModules([ + IntegratedChartsModule.with(AgChartsCommunityModule), + ]); + } + } return ; } diff --git a/src/lib/utils/propCategories.js b/src/lib/utils/propCategories.js index 74f0e781..4a7c9909 100644 --- a/src/lib/utils/propCategories.js +++ b/src/lib/utils/propCategories.js @@ -342,6 +342,7 @@ export const PROPS_NOT_FOR_AG_GRID = [ 'setProps', 'loading_state', 'enableEnterpriseModules', + 'dashEnableCharts', 'parentState', 'persistence', 'persisted_props', diff --git a/tests/test_charts.py b/tests/test_charts.py new file mode 100644 index 00000000..67b3d601 --- /dev/null +++ b/tests/test_charts.py @@ -0,0 +1,146 @@ +import dash_ag_grid as dag +from dash import Dash, html +from . import utils + + +def _make_chart_grid(**extra_props): + return dag.AgGrid( + id="grid", + columnDefs=[{"field": "make"}, {"field": "model"}, {"field": "price"}], + rowData=[ + {"make": "Toyota", "model": "Celica", "price": 35000}, + {"make": "Ford", "model": "Mondeo", "price": 32000}, + {"make": "Porsche", "model": "Boxster", "price": 72000}, + ], + **extra_props, + ) + + +def _make_basic_grid(**extra_props): + return dag.AgGrid( + id="grid", + columnDefs=[{"field": "make"}, {"field": "model"}, {"field": "price"}], + rowData=[ + {"make": "Toyota", "model": "Celica", "price": 35000}, + {"make": "Ford", "model": "Mondeo", "price": 32000}, + {"make": "Porsche", "model": "Boxster", "price": 72000}, + ], + **extra_props, + ) + + +def test_charts001_enables_enterprise_charts_modules_with_true(dash_duo): + app = Dash(__name__) + app.layout = html.Div( + [_make_chart_grid(enableEnterpriseModules=True, dashEnableCharts=True)] + ) + + dash_duo.start_server(app) + + grid = utils.Grid(dash_duo, "grid") + grid.wait_for_cell_text(0, 0, "Toyota") + + assert not any( + "AG Grid: error #200" in entry.get("message", "") + for entry in dash_duo.get_logs() + ) + + +def test_charts002_enables_enterprise_charts_modules(dash_duo): + app = Dash(__name__) + app.layout = html.Div( + [ + _make_chart_grid( + enableEnterpriseModules=True, + dashEnableCharts="enterprise", + ) + ] + ) + + dash_duo.start_server(app) + + grid = utils.Grid(dash_duo, "grid") + grid.wait_for_cell_text(0, 0, "Toyota") + + assert not any( + "AG Grid: error #200" in entry.get("message", "") + for entry in dash_duo.get_logs() + ) + + +def test_charts003_keeps_enterprise_grid_without_charts(dash_duo): + app = Dash(__name__) + app.layout = html.Div([_make_basic_grid(enableEnterpriseModules=True)]) + + dash_duo.start_server(app) + + grid = utils.Grid(dash_duo, "grid") + grid.wait_for_cell_text(0, 0, "Toyota") + + +def test_charts004_rejects_charts_on_community_grid(dash_duo): + app = Dash(__name__) + app.layout = html.Div([_make_chart_grid(dashEnableCharts=True)]) + + dash_duo.start_server(app) + + assert any( + "dashEnableCharts is only supported when enableEnterpriseModules is true." + in entry.get("message", "") + for entry in dash_duo.get_logs() + ) + + +def test_charts005_rejects_enablecharts_without_dashenablecharts(dash_duo): + app = Dash(__name__) + app.layout = html.Div( + [_make_chart_grid(dashGridOptions={"enableCharts": True})] + ) + + dash_duo.start_server(app) + + assert any( + "enableCharts is set, but chart modules are not loaded." + in entry.get("message", "") + for entry in dash_duo.get_logs() + ) + + +def test_charts006_rejects_conflicting_enablecharts_false(dash_duo): + app = Dash(__name__) + app.layout = html.Div( + [ + _make_chart_grid( + enableEnterpriseModules=True, + dashEnableCharts=True, + dashGridOptions={"enableCharts": False}, + ) + ] + ) + + dash_duo.start_server(app) + + assert any( + "dashEnableCharts cannot be combined with dashGridOptions.enableCharts=false." + in entry.get("message", "") + for entry in dash_duo.get_logs() + ) + + +def test_charts007_accepts_charts_license_key_prop(dash_duo): + app = Dash(__name__) + app.layout = html.Div( + [ + _make_chart_grid( + enableEnterpriseModules=True, + dashEnableCharts="enterprise", + licenseKey="grid-key", + chartsLicenseKey="charts-key", + ) + ] + ) + + dash_duo.start_server(app) + + grid = utils.Grid(dash_duo, "grid") + grid.wait_for_cell_text(0, 0, "Toyota")