diff --git a/.gitignore b/.gitignore index 347fe43c..8f0b19b6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ # Build artifacts dash_ag_grid/* !dash_ag_grid/__init__.py +!dash_ag_grid/_version.py +!dash_ag_grid/themes.py R/ deps/ man/ diff --git a/dash_ag_grid/__init__.py b/dash_ag_grid/__init__.py index f4ce3715..d2eda1b6 100644 --- a/dash_ag_grid/__init__.py +++ b/dash_ag_grid/__init__.py @@ -9,6 +9,7 @@ # noinspection PyUnresolvedReferences from ._imports_ import * from ._imports_ import __all__ +from dash_ag_grid import themes if not hasattr(_dash, '__plotly_dash') and not hasattr(_dash, 'development'): print('Dash was not successfully imported. ' @@ -16,14 +17,10 @@ 'named \n"dash.py" in your current directory.', file=_sys.stderr) _sys.exit(1) -_basepath = _os.path.dirname(__file__) -_filepath = _os.path.abspath(_os.path.join(_basepath, 'package-info.json')) -with open(_filepath) as f: - package = json.load(f) +from ._version import __version__, grid_version, get_package_info +package = get_package_info() package_name = package['name'].replace(' ', '_').replace('-', '_') -__version__ = package['version'] -grid_version = package['dependencies']['ag-grid-community'] _current_path = _os.path.dirname(_os.path.abspath(__file__)) diff --git a/dash_ag_grid/_version.py b/dash_ag_grid/_version.py new file mode 100644 index 00000000..bc31e78e --- /dev/null +++ b/dash_ag_grid/_version.py @@ -0,0 +1,12 @@ +import json +import os + +def get_package_info(): + basepath = os.path.dirname(__file__) + filepath = os.path.abspath(os.path.join(basepath, 'package-info.json')) + with open(filepath) as f: + return json.load(f) + +package = get_package_info() +__version__ = package['version'] +grid_version = package['dependencies']['ag-grid-community'] \ No newline at end of file diff --git a/dash_ag_grid/themes.py b/dash_ag_grid/themes.py new file mode 100644 index 00000000..85a7e5be --- /dev/null +++ b/dash_ag_grid/themes.py @@ -0,0 +1,9 @@ +from ._version import grid_version + +_base_url = f"https://cdn.jsdelivr.net/npm/ag-grid-community@{grid_version}/styles" + +BASE = f"{_base_url}/ag-grid.min.css" +ALPINE = f"{_base_url}/ag-theme-alpine.min.css" +BALHAM = f"{_base_url}/ag-theme-balham.min.css" +MATERIAL = f"{_base_url}/ag-theme-material.min.css" +QUARTZ = f"{_base_url}/ag-theme-quartz.min.css" diff --git a/package-lock.json b/package-lock.json index 8a578a5f..d3d3008b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,21 @@ { "name": "dash-ag-grid", - "version": "32.3.0", + "version": "33.3.2rc0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dash-ag-grid", - "version": "32.3.0", + "version": "33.3.2rc0", "license": "MIT", "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.15.7", "@mui/material": "^5.15.7", - "ag-grid-community": "32.3.4", - "ag-grid-enterprise": "32.3.4", - "ag-grid-react": "32.3.4", + "ag-grid-community": "33.3.2", + "ag-grid-enterprise": "33.3.2", + "ag-grid-react": "33.3.2", "d3-format": "^3.1.0", "d3-time": "^3.1.0", "d3-time-format": "^4.1.0", @@ -3426,53 +3426,80 @@ } }, "node_modules/ag-charts-community": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/ag-charts-community/-/ag-charts-community-10.3.4.tgz", - "integrity": "sha512-Acm4KNaS2khHH1Q1J96xtXclhqU2ku10amYRcpsVPdKL9dz9MmMbE6ja9DSGJuz3Zl8pwXlcT4GaQjNnaLKUFw==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-community/-/ag-charts-community-11.3.2.tgz", + "integrity": "sha512-4ZshRqfeCoQKgJ8WNxLfgkKtLszIxEF9WWOSuT2Uvyyy3x0rUUPQbl98+kVh+sRyGGQ6Qj8uoStqHAhwPwgTOQ==", "license": "MIT", + "optional": true, "dependencies": { - "ag-charts-locale": "10.3.4", - "ag-charts-types": "10.3.4" + "ag-charts-core": "11.3.2", + "ag-charts-locale": "11.3.2", + "ag-charts-types": "11.3.2" + } + }, + "node_modules/ag-charts-core": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-core/-/ag-charts-core-11.3.2.tgz", + "integrity": "sha512-D66lTBVXRDI6vFTcmL91KeBghOx63MmWrgDSJEEhsrK1ioWeYnFcRXStX0msx60D12i+Ba+uhM9xrxgRmqzM5w==", + "license": "MIT", + "optional": true, + "dependencies": { + "ag-charts-types": "11.3.2" + } + }, + "node_modules/ag-charts-enterprise": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-enterprise/-/ag-charts-enterprise-11.3.2.tgz", + "integrity": "sha512-5HRfEI2w0IxfyWy6bpu9Db2UVPxPyxYihSHJdlJLmmCCgPNoyUqnghZqr7vnRSrh/mVSeSo2WBzxZuuphr+Wtg==", + "license": "Commercial", + "optional": true, + "dependencies": { + "ag-charts-community": "11.3.2", + "ag-charts-core": "11.3.2" } }, "node_modules/ag-charts-locale": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/ag-charts-locale/-/ag-charts-locale-10.3.4.tgz", - "integrity": "sha512-b2DiNzkzJpyAM+YXv7qapApHRCmyJdn1qPWGDnFD8NqoMatMbvxpbjkbD8nmR9rECsI3l5uw9lvH1uxDks5lLA==", - "license": "MIT" + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-locale/-/ag-charts-locale-11.3.2.tgz", + "integrity": "sha512-6DrHD53PfdVNqFAlmNkHTnlQ9QY9EzME0vvaiotUpO8boKflGivgqmfx/uNTp6AsvOrsnRBBZW4b4XSg0LKG2w==", + "license": "MIT", + "optional": true }, "node_modules/ag-charts-types": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/ag-charts-types/-/ag-charts-types-10.3.4.tgz", - "integrity": "sha512-MU+3gvKn1jEyLlMHS0Vu0nHmIQxiVJAnA6ftUatLZvV0c7hOWap4VWghqZ0cVZUJsCdMI59Iuq1u3xquKv4LOQ==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-types/-/ag-charts-types-11.3.2.tgz", + "integrity": "sha512-trPGqgGYiTeLgtf9nLuztDYOPOFOLbqHn1g2D99phf7QowcwdX0TPx0wfWG8Hm90LjB8IH+G2s3AZe2vrdAtMQ==", "license": "MIT" }, "node_modules/ag-grid-community": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-32.3.4.tgz", - "integrity": "sha512-iYQYFapKkqtCml1BvIX/nyNO6SvZYe/Z/1hLa7/7Dpzj2uqABJZIPGgW/ZTOc+/YiM9JYJWMkD7c+5E23GzkAw==", + "version": "33.3.2", + "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-33.3.2.tgz", + "integrity": "sha512-9bx0e/+ykOyLvUxHqmdy0cRVANH6JAtv0yZdnBZEXYYqBAwN+G5a4NY+2I1KvoOCYzbk8SnStG7y4hCdVAAWOQ==", "license": "MIT", "dependencies": { - "ag-charts-types": "10.3.4" + "ag-charts-types": "11.3.2" } }, "node_modules/ag-grid-enterprise": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-32.3.4.tgz", - "integrity": "sha512-IgOw87Wg65x/fxKIhGHKgKL21Acht6P5kN1LHxzrV+PUn3Q13+52qhbLq+9Ck1FTxPqd2PgKrtLrZiQJWneYTA==", + "version": "33.3.2", + "resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-33.3.2.tgz", + "integrity": "sha512-wf1JMDdAk9GhWbB0WF5RIOYp4p/y6h7zJoscFsymEeFV7325Zyx0ZBQ/kQQ9R9MqnhIYp5xjpjYJ4r2rpIXH+A==", "license": "Commercial", "dependencies": { - "ag-charts-community": "10.3.4", - "ag-grid-community": "32.3.4" + "ag-grid-community": "33.3.2" + }, + "optionalDependencies": { + "ag-charts-community": "11.3.2", + "ag-charts-enterprise": "11.3.2" } }, "node_modules/ag-grid-react": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-32.3.4.tgz", - "integrity": "sha512-JuIum0etQnWUxWt4EbCXkLGa2lNLgFXNK0nR/rr2+WcOHZSIo1wXe5DPySnL725BK+yPqfB6XZmZcETpEDT+bQ==", + "version": "33.3.2", + "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-33.3.2.tgz", + "integrity": "sha512-5bv4JIJvGov23sduIUIyQTqpa/qhoQrRkQm5pFOQb7RMwusfx6xBPrkLwIIlCJiQ8g0OOinxWzZ2kQ2Zml6tLw==", "license": "MIT", "dependencies": { - "ag-grid-community": "32.3.4", + "ag-grid-community": "33.3.2", "prop-types": "^15.8.1" }, "peerDependencies": { @@ -14713,47 +14740,70 @@ "dev": true }, "ag-charts-community": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/ag-charts-community/-/ag-charts-community-10.3.4.tgz", - "integrity": "sha512-Acm4KNaS2khHH1Q1J96xtXclhqU2ku10amYRcpsVPdKL9dz9MmMbE6ja9DSGJuz3Zl8pwXlcT4GaQjNnaLKUFw==", + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-community/-/ag-charts-community-11.3.2.tgz", + "integrity": "sha512-4ZshRqfeCoQKgJ8WNxLfgkKtLszIxEF9WWOSuT2Uvyyy3x0rUUPQbl98+kVh+sRyGGQ6Qj8uoStqHAhwPwgTOQ==", + "optional": true, "requires": { - "ag-charts-locale": "10.3.4", - "ag-charts-types": "10.3.4" + "ag-charts-core": "11.3.2", + "ag-charts-locale": "11.3.2", + "ag-charts-types": "11.3.2" + } + }, + "ag-charts-core": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-core/-/ag-charts-core-11.3.2.tgz", + "integrity": "sha512-D66lTBVXRDI6vFTcmL91KeBghOx63MmWrgDSJEEhsrK1ioWeYnFcRXStX0msx60D12i+Ba+uhM9xrxgRmqzM5w==", + "optional": true, + "requires": { + "ag-charts-types": "11.3.2" + } + }, + "ag-charts-enterprise": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-enterprise/-/ag-charts-enterprise-11.3.2.tgz", + "integrity": "sha512-5HRfEI2w0IxfyWy6bpu9Db2UVPxPyxYihSHJdlJLmmCCgPNoyUqnghZqr7vnRSrh/mVSeSo2WBzxZuuphr+Wtg==", + "optional": true, + "requires": { + "ag-charts-community": "11.3.2", + "ag-charts-core": "11.3.2" } }, "ag-charts-locale": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/ag-charts-locale/-/ag-charts-locale-10.3.4.tgz", - "integrity": "sha512-b2DiNzkzJpyAM+YXv7qapApHRCmyJdn1qPWGDnFD8NqoMatMbvxpbjkbD8nmR9rECsI3l5uw9lvH1uxDks5lLA==" + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-locale/-/ag-charts-locale-11.3.2.tgz", + "integrity": "sha512-6DrHD53PfdVNqFAlmNkHTnlQ9QY9EzME0vvaiotUpO8boKflGivgqmfx/uNTp6AsvOrsnRBBZW4b4XSg0LKG2w==", + "optional": true }, "ag-charts-types": { - "version": "10.3.4", - "resolved": "https://registry.npmjs.org/ag-charts-types/-/ag-charts-types-10.3.4.tgz", - "integrity": "sha512-MU+3gvKn1jEyLlMHS0Vu0nHmIQxiVJAnA6ftUatLZvV0c7hOWap4VWghqZ0cVZUJsCdMI59Iuq1u3xquKv4LOQ==" + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/ag-charts-types/-/ag-charts-types-11.3.2.tgz", + "integrity": "sha512-trPGqgGYiTeLgtf9nLuztDYOPOFOLbqHn1g2D99phf7QowcwdX0TPx0wfWG8Hm90LjB8IH+G2s3AZe2vrdAtMQ==" }, "ag-grid-community": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-32.3.4.tgz", - "integrity": "sha512-iYQYFapKkqtCml1BvIX/nyNO6SvZYe/Z/1hLa7/7Dpzj2uqABJZIPGgW/ZTOc+/YiM9JYJWMkD7c+5E23GzkAw==", + "version": "33.3.2", + "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-33.3.2.tgz", + "integrity": "sha512-9bx0e/+ykOyLvUxHqmdy0cRVANH6JAtv0yZdnBZEXYYqBAwN+G5a4NY+2I1KvoOCYzbk8SnStG7y4hCdVAAWOQ==", "requires": { - "ag-charts-types": "10.3.4" + "ag-charts-types": "11.3.2" } }, "ag-grid-enterprise": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-32.3.4.tgz", - "integrity": "sha512-IgOw87Wg65x/fxKIhGHKgKL21Acht6P5kN1LHxzrV+PUn3Q13+52qhbLq+9Ck1FTxPqd2PgKrtLrZiQJWneYTA==", + "version": "33.3.2", + "resolved": "https://registry.npmjs.org/ag-grid-enterprise/-/ag-grid-enterprise-33.3.2.tgz", + "integrity": "sha512-wf1JMDdAk9GhWbB0WF5RIOYp4p/y6h7zJoscFsymEeFV7325Zyx0ZBQ/kQQ9R9MqnhIYp5xjpjYJ4r2rpIXH+A==", "requires": { - "ag-charts-community": "10.3.4", - "ag-grid-community": "32.3.4" + "ag-charts-community": "11.3.2", + "ag-charts-enterprise": "11.3.2", + "ag-grid-community": "33.3.2" } }, "ag-grid-react": { - "version": "32.3.4", - "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-32.3.4.tgz", - "integrity": "sha512-JuIum0etQnWUxWt4EbCXkLGa2lNLgFXNK0nR/rr2+WcOHZSIo1wXe5DPySnL725BK+yPqfB6XZmZcETpEDT+bQ==", + "version": "33.3.2", + "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-33.3.2.tgz", + "integrity": "sha512-5bv4JIJvGov23sduIUIyQTqpa/qhoQrRkQm5pFOQb7RMwusfx6xBPrkLwIIlCJiQ8g0OOinxWzZ2kQ2Zml6tLw==", "requires": { - "ag-grid-community": "32.3.4", + "ag-grid-community": "33.3.2", "prop-types": "^15.8.1" } }, diff --git a/package.json b/package.json index 43d85e61..be055b9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dash-ag-grid", - "version": "32.3.0", + "version": "33.3.2rc0", "description": "Dash wrapper around AG Grid, the best interactive data grid for the web.", "repository": { "type": "git", @@ -32,11 +32,11 @@ "dependencies": { "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", - "ag-grid-community": "32.3.4", - "ag-grid-enterprise": "32.3.4", - "ag-grid-react": "32.3.4", "@mui/icons-material": "^5.15.7", "@mui/material": "^5.15.7", + "ag-grid-community": "33.3.2", + "ag-grid-enterprise": "33.3.2", + "ag-grid-react": "33.3.2", "d3-format": "^3.1.0", "d3-time": "^3.1.0", "d3-time-format": "^4.1.0", diff --git a/src/lib/components/AgGrid.react.js b/src/lib/components/AgGrid.react.js index 5813dd3b..829f23b7 100644 --- a/src/lib/components/AgGrid.react.js +++ b/src/lib/components/AgGrid.react.js @@ -1,6 +1,10 @@ import PropTypes from 'prop-types'; import LazyLoader from '../LazyLoader'; import React, {lazy, Suspense, useState, useCallback, useEffect} from 'react'; +import {AllCommunityModule, ModuleRegistry} from 'ag-grid-community'; + +// Register all community features +ModuleRegistry.registerModules([AllCommunityModule]); const RealAgGrid = lazy(LazyLoader.agGrid); const RealAgGridEnterprise = lazy(LazyLoader.agGridEnterprise); @@ -53,7 +57,7 @@ function DashAgGrid(props) { DashAgGrid.dashRenderType = true; DashAgGrid.defaultProps = { - className: 'ag-theme-alpine', + className: '', resetColumnState: false, exportDataAsCsv: false, selectAll: false, diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 7250339f..c3a4cafc 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -46,12 +46,13 @@ import RowMenuRenderer from '../renderers/rowMenuRenderer'; import {customFunctions} from '../renderers/customFunctions'; import {AgGridReact, useGridFilter} from 'ag-grid-react'; - -import 'ag-grid-community/styles/ag-grid.css'; -import 'ag-grid-community/styles/ag-theme-alpine.css'; -import 'ag-grid-community/styles/ag-theme-balham.css'; -import 'ag-grid-community/styles/ag-theme-material.css'; -import 'ag-grid-community/styles/ag-theme-quartz.css'; +import { + themeAlpine, + themeBalham, + themeMaterial, + themeQuartz, +} from 'ag-grid-community'; +const themes = {themeAlpine, themeBalham, themeMaterial, themeQuartz}; // d3 imports import * as d3Format from 'd3-format'; @@ -159,6 +160,7 @@ export function DashAgGrid(props) { const parsedCondition = esprima.parse(funcString).body[0].expression; const context = { + ...themes, d3, dash_clientside, ...customFunctions, @@ -176,6 +178,7 @@ export function DashAgGrid(props) { const parsedCondition = esprima.parse(funcString).body[0].expression; const context = { + ...themes, d3, dash_clientside, ...customFunctions, @@ -195,6 +198,7 @@ export function DashAgGrid(props) { const parsedCondition = esprima.parse(funcString).body[0].expression; const context = { + ...themes, d3, ...customFunctions, ...window.dashAgGridFunctions, @@ -1532,6 +1536,14 @@ export function DashAgGrid(props) { omit(NO_CONVERT_PROPS, {...dashGridOptions, ...restProps}) ); + if ('theme' in convertedProps) { + if (typeof convertedProps.theme === 'function') { + convertedProps.theme = convertedProps.theme(); + } else if (convertedProps.theme in themes) { + convertedProps.theme = themes[convertedProps.theme]; + } + } + let alignedGrids; if (dashGridOptions) { if ('alignedGrids' in dashGridOptions) { diff --git a/src/lib/fragments/AgGridEnterprise.react.js b/src/lib/fragments/AgGridEnterprise.react.js index 3df1e599..fa847e63 100644 --- a/src/lib/fragments/AgGridEnterprise.react.js +++ b/src/lib/fragments/AgGridEnterprise.react.js @@ -1,7 +1,19 @@ import React from 'react'; -import {LicenseManager} from 'ag-grid-enterprise'; +import {ModuleRegistry} from 'ag-grid-community'; +import { + AllEnterpriseModule, + LicenseManager, + SparklinesModule, +} from 'ag-grid-enterprise'; +import {AgChartsEnterpriseModule} from 'ag-charts-enterprise'; import MemoizedAgGrid, {propTypes} from './AgGrid.react'; +// Register all enterprise features +ModuleRegistry.registerModules([ + AllEnterpriseModule, + SparklinesModule.with(AgChartsEnterpriseModule), +]); + export default function DashAgGridEnterprise(props) { const {licenseKey} = props; if (licenseKey) { diff --git a/src/lib/utils/propCategories.js b/src/lib/utils/propCategories.js index 20ef56d0..4a8f3008 100644 --- a/src/lib/utils/propCategories.js +++ b/src/lib/utils/propCategories.js @@ -142,6 +142,9 @@ export const GRID_MAYBE_FUNCTIONS_NO_PARAMS = { setPopupParent: 1, popupParent: 1, quickFilterMatcher: 1, + + // Themeing + theme: 1, }; /** diff --git a/tests/examples/themes.py b/tests/examples/themes.py new file mode 100644 index 00000000..b23febee --- /dev/null +++ b/tests/examples/themes.py @@ -0,0 +1,78 @@ +import dash_ag_grid as dag +from dash import Dash, Input, Output, State, dcc, html +import json + +app = Dash(__name__) + +rowData = [ + {"weight": 0.074657, "date": "01/01/2024"}, + {"weight": 0.06948567, "date": "02/01/2024"}, + {"weight": 0.02730574, "date": "03/01/2024"}, + {"weight": 0.0182345, "date": "04/01/2024"}, +] + +columnDefs = [ + {"field": "weight", "cellDataType": "percentage"}, + {"field": "date", "cellDataType": "dateString"}, +] + +dataTypeDefinitions = { + "percentage": { + "baseDataType": "number", + "extendsDataType": "number", + "valueFormatter": { + "function": "params.value == null ? '' : d3.format(',.1%')(params.value)" + }, + }, + "dateString": { + "baseDataType": 'dateString', + "extendsDataType": 'dateString', + "valueParser": { + "function": r"params.newValue != null && !!params.newValue.match(/\d{2}\/\d{2}\/\d{4}/) ? params.newValue : null" + }, + "valueFormatter": {"function": "params.value == null ? '' : params.value"}, + "dataTypeMatcher": {"function": r"params != null && !!params.match(/\d{2}\/\d{2}\/\d{4}/)"}, + "dateParser": {"function": "dateParser(params)"}, + "dateFormatter": {"function": "dateFormatter(params)"}, + }, +} + +app.layout = html.Div( + [ + dcc.Dropdown(options=[ + {"label": "Quartz", "value": "themeQuartz"}, + {"label": "Balham", "value": "themeBalham"}, + {"label": "Material", "value": "themeMaterial"}, + {"label": "Alpine", "value": "themeAlpine"}, + {"label": "Custom Balham with red accent", "value": '{ "function": "themeBalham.withParams({ accentColor: \'red\' })"}'}, + {"label": "Invalid theme name", "value": "invalidTheme"}, + ], value="themeQuartz", id="themeSelector"), + dag.AgGrid( + id="grid", + columnDefs=columnDefs, + rowData=rowData, + defaultColDef={"filter": True, "editable": True}, + dashGridOptions={"dataTypeDefinitions": dataTypeDefinitions}, + ), + ], +) + +@app.callback( + Output("grid", "dashGridOptions"), + Input("themeSelector", "value"), + State("grid", "dashGridOptions"), +) +def addGrid(selected_theme, dash_grid_options): + try: + selected_theme = json.loads(selected_theme) + except json.JSONDecodeError: + ... + + if not dash_grid_options: + dash_grid_options = {} + + dash_grid_options["theme"] = selected_theme + return dash_grid_options + +if __name__ == "__main__": + app.run(debug=True) diff --git a/tests/examples/themes_legacy.py b/tests/examples/themes_legacy.py new file mode 100644 index 00000000..f52bc88c --- /dev/null +++ b/tests/examples/themes_legacy.py @@ -0,0 +1,38 @@ +import dash_ag_grid as dag +from dash import Dash, Input, Output, State, dcc, html + +""" +Note the custom assets_folder in this app! +Change the `className` theme to one of the options in that folder to see the +legacy theme in action. +""" + +app = Dash(__name__, external_stylesheets=[dag.themes.BASE, dag.themes.MATERIAL]) + +rowData = [ + {"weight": 0.074657, "date": "01/01/2024"}, + {"weight": 0.06948567, "date": "02/01/2024"}, + {"weight": 0.02730574, "date": "03/01/2024"}, + {"weight": 0.0182345, "date": "04/01/2024"}, +] + +columnDefs = [ + {"field": "weight"}, + {"field": "date"}, +] + +app.layout = html.Div( + [ + dag.AgGrid( + id="grid", + columnDefs=columnDefs, + rowData=rowData, + defaultColDef={"filter": True, "editable": True}, + dashGridOptions={"theme": "legacy"}, + className="ag-theme-material", + ), + ], +) + +if __name__ == "__main__": + app.run(debug=True) diff --git a/tests/test_cell_value_changed.py b/tests/test_cell_value_changed.py index dabde15d..5a8387b4 100644 --- a/tests/test_cell_value_changed.py +++ b/tests/test_cell_value_changed.py @@ -31,6 +31,11 @@ def test_cv001_cell_value_changed(dash_duo): columnDefs=[{"field": "Key", "checkboxSelection": True}] + [{"field": i} for i in ["Column", "OldValue", "NewValue"]], rowData=[], + dashGridOptions={ + "rowSelection": { + "mode": 'singleRow' + }, + } ), ], style={"margin": 20}, @@ -50,7 +55,7 @@ def test_cv001_cell_value_changed(dash_duo): data = changes[i]; reloadData = {...data.data}; reloadData[data.colId] = data.oldValue; - newData.push({Key: data.rowId, Column: data.colId, OldValue: data.oldValue, + newData.push({Key: data.rowId, Column: data.colId, OldValue: data.oldValue, NewValue: data.value, reloadData}); } return {'add': newData} diff --git a/tests/test_grid_apis.py b/tests/test_grid_apis.py index 3f348a92..4b771fb9 100644 --- a/tests/test_grid_apis.py +++ b/tests/test_grid_apis.py @@ -100,7 +100,7 @@ def test_ga001_grid_apis(dash_duo): app.clientside_callback( """function (n) { if (n) { - dash_ag_grid.getApi('grid').setColumnVisible("price", false) + dash_ag_grid.getApi('grid').setColumnsVisible(["price"], false) } return dash_clientside.no_update }""", diff --git a/tests/test_user_style.py b/tests/test_user_style.py index 5276b74c..8c66d716 100644 --- a/tests/test_user_style.py +++ b/tests/test_user_style.py @@ -2,6 +2,7 @@ import dash_ag_grid as dag import plotly.express as px import json +import pytest from . import utils from dash.testing.wait import until @@ -41,6 +42,7 @@ def test_us001_user_style(dash_duo): defaultColDef=defaultColDef, rowData=rowData, style={"height": "500px", "width": "500px"}, + className="ag-theme-alpine", ), ] ) @@ -60,3 +62,58 @@ def test_us001_user_style(dash_duo): in dash_duo.find_element("div.ag-theme-alpine").get_attribute("style"), timeout=3, ) + + +@pytest.mark.parametrize("theme", ["alpine", "balham", "material", "quartz"]) +def test_us002_legacy_themes(dash_duo, theme): + app = Dash( + __name__, + external_stylesheets=[ + dag.themes.BASE, + dag.themes.ALPINE, + dag.themes.BALHAM, + dag.themes.MATERIAL, + dag.themes.QUARTZ, + ], + ) + + columnDefs = [ + {"field": "name", "width": "500"}, + ] + + rowData = [ + {"name": "a"}, + {"name": "b"}, + {"name": "c"}, + ] + + app.layout = html.Div( + [ + dag.AgGrid( + id="grid", + columnDefs=columnDefs, + rowData=rowData, + dashGridOptions={"theme": "legacy"}, + className=f"ag-theme-{theme}", + ), + ] + ) + + dash_duo.start_server(app) + + grid = utils.Grid(dash_duo, "grid") + + grid.wait_for_cell_text(0, 0, "a") + + # Test that the CSS files are actually loaded and applied + + # Base styles: assert that the grid height is <= 400px because an unstyled + # grid is very "tall" + root_wrapper = dash_duo.find_element(".ag-root-wrapper") + wrapper_height = root_wrapper.size["height"] + assert wrapper_height <= 400, f"Grid appears to be unstyled: height is too tall ({wrapper_height}px)" + + # Specific themes: Assert that cell headers are bold + header_cell_text = dash_duo.find_element(".ag-header-cell-text") + font_weight = header_cell_text.value_of_css_property("font-weight") + assert font_weight in ["bold", "700", "600", "500",], "Grid appears to be unstyled: cell headers are not bold"