-
Notifications
You must be signed in to change notification settings - Fork 16.3k
feat: add timeseries range selection #36689
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
base: master
Are you sure you want to change the base?
feat: add timeseries range selection #36689
Conversation
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
524454f to
ea3d247
Compare
Nitpicks 🔍
|
| xValueFormatter, | ||
| xAxis, | ||
| refs, | ||
| emitCrossFilters, | ||
| coltypeMapping, | ||
| onLegendScroll, | ||
| isHorizontal, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: The newly added isHorizontal prop is never used; leaving an unused prop in the function signature may trigger linter warnings and is misleading—rename it to _isHorizontal (or remove it) to signal it's intentionally unused. [possible bug]
Severity Level: Critical 🚨
| isHorizontal, | |
| _isHorizontal, |
Why it matters? ⭐
The prop isHorizontal is indeed declared in the destructured props but never referenced anywhere in the component. Renaming to _isHorizontal (or removing it) is a small, correct change that avoids linter warnings and clarifies intent. This is a harmless, localized cleanup.
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx
**Line:** 57:57
**Comment:**
*Possible Bug: The newly added `isHorizontal` prop is never used; leaving an unused prop in the function signature may trigger linter warnings and is misleading—rename it to `_isHorizontal` (or remove it) to signal it's intentionally unused.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.|
|
||
| // Disable brush selection on touch devices to avoid interfering with scrolling | ||
| const isTouchDevice = | ||
| 'ontouchstart' in window || navigator.maxTouchPoints > 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Accessing window and navigator directly will throw during server-side rendering (when window/navigator is undefined). Add guards using typeof window !== 'undefined' and typeof navigator !== 'undefined' before checking ontouchstart or maxTouchPoints. [possible bug]
Severity Level: Critical 🚨
| 'ontouchstart' in window || navigator.maxTouchPoints > 0; | |
| (typeof window !== 'undefined' && 'ontouchstart' in window) || | |
| (typeof navigator !== 'undefined' && navigator.maxTouchPoints > 0); |
Why it matters? ⭐
The handler reads global browser APIs; while this code runs only when the brush event fires in the browser, guarding with typeof window !== 'undefined' and typeof navigator !== 'undefined' is a robust defensive change that prevents potential ReferenceErrors in non-browser environments (SSR/test runners). The suggested improved code is sensible and low-risk.
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/EchartsTimeseries.tsx
**Line:** 177:177
**Comment:**
*Possible Bug: Accessing `window` and `navigator` directly will throw during server-side rendering (when `window`/`navigator` is undefined). Add guards using `typeof window !== 'undefined'` and `typeof navigator !== 'undefined'` before checking `ontouchstart` or `maxTouchPoints`.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.| brush: | ||
| xAxisType === AxisType.time | ||
| ? { | ||
| toolbox: [], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Configuration risk: brush.toolbox was set to an empty array ([]), but the ECharts brush toolbox option expects an object (or to be omitted) — using an invalid type can lead to runtime errors in some ECharts versions; remove or set it to an object/undefined to avoid invalid configuration. [possible bug]
Severity Level: Critical 🚨
| toolbox: [], | |
| toolbox: undefined, |
Why it matters? ⭐
The brush.toolbox in ECharts expects an object (or omitted/undefined). Passing an array is likely an invalid config and can cause runtime warnings or errors. Replacing it with undefined (or a proper object) is a safe, small fix that prevents malformed options from being passed to ECharts.
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/plugins/plugin-chart-echarts/src/Timeseries/transformProps.ts
**Line:** 540:540
**Comment:**
*Possible Bug: Configuration risk: `brush.toolbox` was set to an empty array (`[]`), but the ECharts brush `toolbox` option expects an object (or to be omitted) — using an invalid type can lead to runtime errors in some ECharts versions; remove or set it to an object/undefined to avoid invalid configuration.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.| const baseXAxis = { | ||
| label: '__timestamp', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: The test uses the string literal '__timestamp' in multiple places which duplicates the real code's DTTM alias; define and use a single local constant DTTM_ALIAS so the test stays correct if the alias is ever refactored and to avoid divergence between test and implementation. [logic error]
Severity Level: Minor
| const baseXAxis = { | |
| label: '__timestamp', | |
| const DTTM_ALIAS = '__timestamp'; | |
| const baseXAxis = { | |
| label: DTTM_ALIAS, |
Why it matters? ⭐
Good, harmless suggestion. Centralizing the DTTM alias in a test reduces duplication and the risk of the test diverging from the implementation constant. It doesn't fix a bug but improves maintainability and makes future refactors simpler.
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/EchartsTimeseries.test.tsx
**Line:** 30:31
**Comment:**
*Logic Error: The test uses the string literal '__timestamp' in multiple places which duplicates the real code's DTTM alias; define and use a single local constant `DTTM_ALIAS` so the test stays correct if the alias is ever refactored and to avoid divergence between test and implementation.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.| const startFormatted = xValueFormatter(startValue); | ||
| const endFormatted = xValueFormatter(endValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: xValueFormatter is typed to accept a number but coordRange values may arrive as strings from the chart; coerce startValue and endValue to numbers before passing to the formatter to avoid type errors or unexpected formatting results. [type error]
Severity Level: Minor
| const startFormatted = xValueFormatter(startValue); | |
| const endFormatted = xValueFormatter(endValue); | |
| const startFormatted = xValueFormatter(Number(startValue)); | |
| const endFormatted = xValueFormatter(Number(endValue)); |
Why it matters? ⭐
Coercing to Number before calling a formatter typed for numbers is reasonable defensive coding — it avoids a runtime type mismatch if coordRange can sometimes be strings. It's harmless in tests and can catch cases where the chart library emits strings. Note this diverges slightly from the production handler which doesn't coerce; if you want exact parity you could also update production code, but as a test hardening it's acceptable.
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** superset-frontend/plugins/plugin-chart-echarts/test/Timeseries/EchartsTimeseries.test.tsx
**Line:** 84:85
**Comment:**
*Type Error: `xValueFormatter` is typed to accept a number but `coordRange` values may arrive as strings from the chart; coerce `startValue` and `endValue` to numbers before passing to the formatter to avoid type errors or unexpected formatting results.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.|
CodeAnt AI finished reviewing your PR. |
Add click-and-drag time range selection to timeseries charts. When enabled, users can select a time range on the chart which automatically applies a time filter. This works for individual charts and integrates with dashboard filters. Changes: - Add timeRangeSelection form data option and default (false) - Add ECharts brush configuration for horizontal range selection - Add brushSelected event handler to capture selection and apply filter - Add "Time Range Filter Selection" checkbox to all timeseries chart control panels (Line, Area, Bar, Scatter, SmoothLine, Step) - Support both vertical and horizontal chart orientations
Add comprehensive tests for the time range brush selection feature: transformProps.test.ts: - Test brush configuration is enabled when x-axis type is time - Test brush has correct style properties - Test brush is NOT enabled when x-axis type is category - Test isHorizontal prop is correctly set EchartsTimeseries.test.tsx: - Test brush events are ignored for non-time axis charts - Test brush events are ignored on touch devices - Test filter is reset when brush selection is cleared - Test time range filter is created with correct format - Test custom time column is used when x-axis label is not __timestamp - Test range operators (>= and <=) are used correctly - Test label is formatted using xValueFormatter
- Remove unused isHorizontal prop from component destructuring - Add SSR safety guards for window and navigator access
SUMMARY
This PR adds a click-and-drag time range selection feature to all timeseries chart types (Line, Area, Bar, Scatter, SmoothLine, Step). Users can draw a rectangle on the chart to select a time range, which automatically applies as a cross-filter.
Key features:
Automatic enablement: The brush selection is automatically enabled for charts with a time-based x-axis. No configuration required.
Rectangle selection: Users draw a rectangle to select a time range (vertical extent is ignored for filtering but provides visual flexibility).
Cross-filter integration: Selected time range creates a cross-filter with >= and <= operators, affecting other charts on the dashboard.
Touch device handling: Disabled on touch devices to avoid interfering with scrolling gestures.
Visual feedback: Selection area has a semi-transparent blue overlay with a subtle border.
Technical implementation:
Uses ECharts' brush component with brushType: 'rect'
Brush configuration is conditionally added when xAxisType === AxisType.time
brushSelected event handler extracts time range from coordRange and calls setDataMask
Filter label displays formatted time range (e.g., "Jan 1, 2024 - Mar 15, 2024")
BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
Before: Users had no way to directly select a time range on timeseries charts.
After: Users can click and drag to draw a rectangle, creating a time range cross-filter.
TESTING INSTRUCTIONS
Create a dashboard with a timeseries chart (Line, Area, Bar, etc.) using a time-based x-axis
Add another chart to the dashboard that shares the same time column
Click and drag on the timeseries chart to draw a rectangle selection
Verify:
A blue selection rectangle appears while dragging
After releasing, a cross-filter badge appears on the chart
Other charts on the dashboard are filtered to the selected time range
The filter label shows the formatted time range
Click elsewhere on the chart to clear the selection
Test on a mobile device or emulator to verify the feature is disabled (no brush on touch)
Test with a category x-axis to verify brush is not enabled (only for time axis)
ADDITIONAL INFORMATION