-
Notifications
You must be signed in to change notification settings - Fork 15.4k
feat(plugin-chart-echarts): add Gantt Chart plugin #33716
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
Merged
+1,845
−108
Merged
Changes from 1 commit
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
64ab9ff
feat(viz): add Timeline Chart
Quatters 81562cc
Merge branch 'master' of https://github.com/Quatters/superset into ec…
Quatters 6fbfcce
Add missing license headers
Quatters f62b581
Refactor
Quatters 07a7c42
Fix test
Quatters c05a722
Merge branch 'master' of https://github.com/Quatters/superset into ec…
Quatters aaa585c
Add encode.x to properly show x-axis
Quatters 4369839
Rename Timeline Chart -> Gantt Chart
Quatters bc9aa33
Add missing word
Quatters 6bc3df8
Use all titleControls except of y_axis_title_position
Quatters e3d3f1a
Merge branch 'master' of https://github.com/Quatters/superset into ec…
Quatters ab7f19a
Fix import
Quatters cf42ed2
Add chart to Featured charts dashboard, small fixes
Quatters 7339ee6
Fix query for 'Features charts' dashboard
Quatters File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/EchartsTimeline.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import { useEffect, useRef, useState } from 'react'; | ||
import { sharedControlComponents } from '@superset-ui/chart-controls'; | ||
import { t } from '@superset-ui/core'; | ||
import Echart from '../components/Echart'; | ||
import { EchartsTimelineChartTransformedProps } from './types'; | ||
import { EventHandlers } from '../types'; | ||
|
||
const { RadioButtonControl } = sharedControlComponents; | ||
|
||
export default function EchartsTimeline( | ||
props: EchartsTimelineChartTransformedProps, | ||
) { | ||
const { | ||
height, | ||
width, | ||
echartOptions, | ||
selectedValues, | ||
refs, | ||
formData, | ||
setControlValue, | ||
onLegendStateChanged, | ||
} = props; | ||
const extraControlRef = useRef<HTMLDivElement>(null); | ||
const [extraHeight, setExtraHeight] = useState(0); | ||
|
||
useEffect(() => { | ||
const updatedHeight = extraControlRef.current?.offsetHeight ?? 0; | ||
setExtraHeight(updatedHeight); | ||
}, [formData.showExtraControls]); | ||
|
||
const eventHandlers: EventHandlers = { | ||
legendselectchanged: payload => { | ||
requestAnimationFrame(() => { | ||
onLegendStateChanged?.(payload.selected); | ||
}); | ||
}, | ||
legendselectall: payload => { | ||
requestAnimationFrame(() => { | ||
onLegendStateChanged?.(payload.selected); | ||
}); | ||
}, | ||
legendinverseselect: payload => { | ||
requestAnimationFrame(() => { | ||
onLegendStateChanged?.(payload.selected); | ||
}); | ||
}, | ||
}; | ||
|
||
return ( | ||
<> | ||
<div ref={extraControlRef} css={{ textAlign: 'center' }}> | ||
{formData.showExtraControls ? ( | ||
<RadioButtonControl | ||
options={[ | ||
[false, t('Plain')], | ||
[true, t('Subcategories')], | ||
]} | ||
value={formData.subcategories} | ||
onChange={v => setControlValue?.('subcategories', v)} | ||
/> | ||
) : null} | ||
</div> | ||
<Echart | ||
refs={refs} | ||
height={height - extraHeight} | ||
width={width} | ||
echartOptions={echartOptions} | ||
selectedValues={selectedValues} | ||
eventHandlers={eventHandlers} | ||
/> | ||
</> | ||
); | ||
} |
43 changes: 43 additions & 0 deletions
43
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/buildQuery.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { | ||
QueryFormData, | ||
QueryObject, | ||
buildQueryContext, | ||
ensureIsArray, | ||
} from '@superset-ui/core'; | ||
|
||
export default function buildQuery(formData: QueryFormData) { | ||
const { | ||
start_time, | ||
end_time, | ||
y_axis, | ||
series, | ||
tooltip_columns, | ||
tooltip_metrics, | ||
order_by_cols, | ||
} = formData; | ||
|
||
const groupBy = ensureIsArray(series); | ||
const orderby = ensureIsArray(order_by_cols).map( | ||
expr => JSON.parse(expr) as [string, boolean], | ||
); | ||
const columns = Array.from( | ||
new Set([ | ||
start_time, | ||
end_time, | ||
y_axis, | ||
...groupBy, | ||
...ensureIsArray(tooltip_columns), | ||
...orderby.map(v => v[0]), | ||
]), | ||
); | ||
|
||
return buildQueryContext(formData, (baseQueryObject: QueryObject) => [ | ||
{ | ||
...baseQueryObject, | ||
columns, | ||
metrics: ensureIsArray(tooltip_metrics), | ||
orderby, | ||
series_columns: groupBy, | ||
}, | ||
]); | ||
} |
8 changes: 8 additions & 0 deletions
8
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/constants.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export const ELEMENT_HEIGHT_SCALE = 0.85 as const; | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export enum Dimension { | ||
StartTime = 'start_time', | ||
EndTime = 'end_time', | ||
Index = 'index', | ||
SeriesCount = 'series_count', | ||
} | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
133 changes: 133 additions & 0 deletions
133
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/controlPanel.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { | ||
ControlPanelConfig, | ||
ControlSubSectionHeader, | ||
sections, | ||
sharedControls, | ||
} from '@superset-ui/chart-controls'; | ||
import { GenericDataType, t } from '@superset-ui/core'; | ||
import { | ||
legendSection, | ||
showExtraControls, | ||
tooltipTimeFormatControl, | ||
tooltipValuesFormatControl, | ||
} from '../controls'; | ||
|
||
const config: ControlPanelConfig = { | ||
controlPanelSections: [ | ||
{ | ||
label: t('Query'), | ||
expanded: true, | ||
controlSetRows: [ | ||
[ | ||
{ | ||
name: 'start_time', | ||
config: { | ||
...sharedControls.entity, | ||
label: t('Start Time'), | ||
description: undefined, | ||
allowedDataTypes: [GenericDataType.Temporal], | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
name: 'end_time', | ||
config: { | ||
...sharedControls.entity, | ||
label: t('End Time'), | ||
description: undefined, | ||
allowedDataTypes: [GenericDataType.Temporal], | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
name: 'y_axis', | ||
config: { | ||
...sharedControls.x_axis, | ||
label: t('Y-axis'), | ||
description: t('Dimension to use on y-axis.'), | ||
initialValue: () => undefined, | ||
}, | ||
}, | ||
], | ||
['series'], | ||
[ | ||
{ | ||
name: 'subcategories', | ||
config: { | ||
type: 'CheckboxControl', | ||
label: t('Subcategories'), | ||
description: t( | ||
'Divides each category into subcategories based on the values in ' + | ||
'the dimension. It can be used to exclude intersections.', | ||
), | ||
renderTrigger: true, | ||
default: false, | ||
visibility: ({ controls }) => !!controls?.series?.value, | ||
}, | ||
}, | ||
], | ||
['tooltip_metrics'], | ||
['tooltip_columns'], | ||
['adhoc_filters'], | ||
['order_by_cols'], | ||
['row_limit'], | ||
], | ||
}, | ||
{ | ||
label: t('Chart Options'), | ||
expanded: true, | ||
tabOverride: 'customize', | ||
controlSetRows: [ | ||
['color_scheme'], | ||
...legendSection, | ||
['zoomable'], | ||
[showExtraControls], | ||
[<ControlSubSectionHeader>{t('X Axis')}</ControlSubSectionHeader>], | ||
[ | ||
{ | ||
name: 'x_axis_time_bounds', | ||
config: { | ||
type: 'TimeRangeControl', | ||
label: t('Bounds'), | ||
description: t( | ||
'Bounds for the X-axis. Selected time merges with ' + | ||
'min/max date of the data. When left empty, bounds ' + | ||
'dynamically defined based on the min/max of the data.', | ||
), | ||
renderTrigger: true, | ||
allowClear: true, | ||
allowEmpty: [true, true], | ||
}, | ||
}, | ||
], | ||
[ | ||
{ | ||
name: sections.xAxisTitleMarginControl.name, | ||
config: { | ||
...sections.xAxisTitleMarginControl.config, | ||
default: 0, | ||
}, | ||
}, | ||
], | ||
['x_axis_time_format'], | ||
[<ControlSubSectionHeader>{t('Y Axis')}</ControlSubSectionHeader>], | ||
[ | ||
{ | ||
name: sections.yAxisTitleMarginControl.name, | ||
config: { | ||
...sections.yAxisTitleMarginControl.config, | ||
default: 30, | ||
}, | ||
}, | ||
], | ||
[<ControlSubSectionHeader>{t('Tooltip')}</ControlSubSectionHeader>], | ||
[tooltipTimeFormatControl], | ||
[tooltipValuesFormatControl], | ||
], | ||
}, | ||
], | ||
}; | ||
|
||
export default config; |
Binary file added
BIN
+87.2 KB
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/images/example1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+87.3 KB
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/images/example2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+55 KB
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/images/thumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions
36
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/index.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { Behavior, t } from '@superset-ui/core'; | ||
import transformProps from './transformProps'; | ||
import controlPanel from './controlPanel'; | ||
import buildQuery from './buildQuery'; | ||
import { EchartsChartPlugin } from '../types'; | ||
import thumbnail from './images/thumbnail.png'; | ||
import example1 from './images/example1.png'; | ||
import example2 from './images/example2.png'; | ||
|
||
export default class EchartsTimelineChartPlugin extends EchartsChartPlugin { | ||
constructor() { | ||
super({ | ||
buildQuery, | ||
controlPanel, | ||
loadChart: () => import('./EchartsTimeline'), | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
metadata: { | ||
behaviors: [ | ||
Behavior.InteractiveChart, | ||
Behavior.DrillToDetail, | ||
Behavior.DrillBy, | ||
], | ||
credits: ['https://echarts.apache.org'], | ||
name: t('Timeline'), | ||
description: t( | ||
'Timeline chart visualizes important events over a time span. ' + | ||
'Every data point displayed as a separate event along a ' + | ||
'horizontal line.', | ||
), | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
tags: [t('ECharts'), t('Time'), t('Featured')], | ||
thumbnail, | ||
exampleGallery: [{ url: example1 }, { url: example2 }], | ||
}, | ||
transformProps, | ||
}); | ||
} | ||
} |
404 changes: 404 additions & 0 deletions
404
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/transformProps.ts
Large diffs are not rendered by default.
Oops, something went wrong.
50 changes: 50 additions & 0 deletions
50
superset-frontend/plugins/plugin-chart-echarts/src/Timeline/types.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { | ||
ChartDataResponseResult, | ||
ChartProps, | ||
QueryFormColumn, | ||
QueryFormData, | ||
QueryFormMetric, | ||
} from '@superset-ui/core'; | ||
import { | ||
BaseTransformedProps, | ||
CrossFilterTransformedProps, | ||
LegendFormData, | ||
} from '../types'; | ||
|
||
export type EchartsTimelineChartTransformedProps = | ||
BaseTransformedProps<EchartsTimelineFormData> & CrossFilterTransformedProps; | ||
|
||
export type EchartsTimelineFormData = QueryFormData & | ||
LegendFormData & { | ||
viz_type: 'echarts_timeline'; | ||
startTime: QueryFormColumn; | ||
endTime: QueryFormColumn; | ||
yAxis: QueryFormColumn; | ||
tooltipMetrics: QueryFormMetric[]; | ||
tooltipColumns: QueryFormColumn[]; | ||
series?: QueryFormColumn; | ||
xAxisTimeFormat?: string; | ||
tooltipTimeFormat?: string; | ||
tooltipValuesFormat?: string; | ||
colorScheme?: string; | ||
zoomable?: boolean; | ||
xAxisTitleMargin?: number; | ||
yAxisTitleMargin?: number; | ||
xAxisTimeBounds?: [string | null, string | null]; | ||
subcategories?: boolean; | ||
showExtraControls?: boolean; | ||
}; | ||
|
||
export interface EchartsTimelineChartProps | ||
extends ChartProps<EchartsTimelineFormData> { | ||
formData: EchartsTimelineFormData; | ||
queriesData: ChartDataResponseResult[]; | ||
} | ||
|
||
export interface Cartesian2dCoordSys { | ||
type: 'cartesian2d'; | ||
x: number; | ||
y: number; | ||
width: number; | ||
height: number; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
superset-frontend/plugins/plugin-chart-echarts/test/Timeline/buildQuery.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { QueryFormData } from '@superset-ui/core'; | ||
import buildQuery from '../../src/Timeline/buildQuery'; | ||
|
||
describe('Timeline buildQuery', () => { | ||
const formData: QueryFormData = { | ||
datasource: '1__table', | ||
viz_type: 'echarts_timeline', | ||
start_time: 'start_time', | ||
end_time: 'end_time', | ||
y_axis: { | ||
label: 'Y Axis', | ||
sqlExpression: 'SELECT 1', | ||
expressionType: 'SQL', | ||
}, | ||
series: 'series', | ||
tooltip_metrics: ['tooltip_metric'], | ||
tooltip_columns: ['tooltip_column'], | ||
order_by_cols: [ | ||
JSON.stringify(['start_time', true]), | ||
JSON.stringify(['order_col', false]), | ||
], | ||
}; | ||
|
||
it('should build query', () => { | ||
const queryContext = buildQuery(formData); | ||
const [query] = queryContext.queries; | ||
expect(query.metrics).toStrictEqual(['tooltip_metric']); | ||
expect(query.columns).toStrictEqual([ | ||
'start_time', | ||
'end_time', | ||
{ | ||
label: 'Y Axis', | ||
sqlExpression: 'SELECT 1', | ||
expressionType: 'SQL', | ||
}, | ||
'series', | ||
'tooltip_column', | ||
'order_col', | ||
]); | ||
expect(query.series_columns).toStrictEqual(['series']); | ||
expect(query.orderby).toStrictEqual([ | ||
['start_time', true], | ||
['order_col', false], | ||
]); | ||
}); | ||
}); |
238 changes: 238 additions & 0 deletions
238
superset-frontend/plugins/plugin-chart-echarts/test/Timeline/transformProps.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
import { AxisType, ChartProps, supersetTheme } from '@superset-ui/core'; | ||
import { | ||
LegendOrientation, | ||
LegendType, | ||
} from '@superset-ui/plugin-chart-echarts'; | ||
import transformProps from '../../src/Timeline/transformProps'; | ||
import { | ||
EchartsTimelineChartProps, | ||
EchartsTimelineFormData, | ||
} from '../../src/Timeline/types'; | ||
|
||
describe('Timeline transformProps', () => { | ||
const formData: EchartsTimelineFormData = { | ||
viz_type: 'echarts_timeline', | ||
datasource: '1__table', | ||
|
||
startTime: 'startTime', | ||
endTime: 'endTime', | ||
yAxis: { | ||
label: 'Y Axis', | ||
sqlExpression: 'y_axis', | ||
expressionType: 'SQL', | ||
}, | ||
tooltipMetrics: ['tooltip_metric'], | ||
tooltipColumns: ['tooltip_column'], | ||
series: 'series', | ||
xAxisTimeFormat: '%H:%M', | ||
tooltipTimeFormat: '%H:%M', | ||
tooltipValuesFormat: 'DURATION_SEC', | ||
colorScheme: 'bnbColors', | ||
zoomable: true, | ||
xAxisTitleMargin: undefined, | ||
yAxisTitleMargin: undefined, | ||
xAxisTimeBounds: [null, '19:00:00'], | ||
subcategories: true, | ||
legendMargin: 0, | ||
legendOrientation: LegendOrientation.Top, | ||
legendType: LegendType.Scroll, | ||
showLegend: true, | ||
sortSeriesAscending: true, | ||
}; | ||
const queriesData = [ | ||
{ | ||
data: [ | ||
{ | ||
startTime: Date.UTC(2025, 1, 1, 13, 0, 0), | ||
endTime: Date.UTC(2025, 1, 1, 14, 0, 0), | ||
'Y Axis': 'first', | ||
tooltip_column: 'tooltip value 1', | ||
series: 'series value 1', | ||
}, | ||
{ | ||
startTime: Date.UTC(2025, 1, 1, 18, 0, 0), | ||
endTime: Date.UTC(2025, 1, 1, 20, 0, 0), | ||
'Y Axis': 'second', | ||
tooltip_column: 'tooltip value 2', | ||
series: 'series value 2', | ||
}, | ||
], | ||
colnames: ['startTime', 'endTime', 'Y Axis', 'tooltip_column', 'series'], | ||
}, | ||
]; | ||
const chartPropsConfig = { | ||
formData, | ||
queriesData, | ||
theme: supersetTheme, | ||
}; | ||
|
||
it('should transform chart props', () => { | ||
const chartProps = new ChartProps(chartPropsConfig); | ||
const transformedProps = transformProps( | ||
chartProps as EchartsTimelineChartProps, | ||
); | ||
|
||
expect(transformedProps.echartOptions.series).toHaveLength(4); | ||
const series = transformedProps.echartOptions.series as any[]; | ||
const series0 = series[0]; | ||
const series1 = series[1]; | ||
|
||
// exclude renderItem because it can't be serialized | ||
expect(typeof series0.renderItem).toBe('function'); | ||
delete series0.renderItem; | ||
expect(typeof series1.renderItem).toBe('function'); | ||
delete series1.renderItem; | ||
delete transformedProps.echartOptions.series; | ||
|
||
expect(transformedProps).toEqual( | ||
expect.objectContaining({ | ||
echartOptions: expect.objectContaining({ | ||
useUTC: true, | ||
xAxis: { | ||
max: Date.UTC(2025, 1, 1, 19, 0, 0), | ||
min: undefined, | ||
type: AxisType.Time, | ||
nameGap: 0, | ||
nameLocation: 'middle', | ||
axisLabel: { | ||
hideOverlap: true, | ||
formatter: expect.anything(), | ||
}, | ||
}, | ||
yAxis: { | ||
type: AxisType.Value, | ||
// always 0 | ||
min: 0, | ||
// equals unique categories count | ||
max: 2, | ||
// always disabled because markLines are used instead | ||
show: false, | ||
nameGap: 0, | ||
}, | ||
legend: expect.objectContaining({ | ||
show: true, | ||
type: 'scroll', | ||
selector: ['all', 'inverse'], | ||
}), | ||
tooltip: { | ||
formatter: expect.anything(), | ||
}, | ||
dataZoom: [ | ||
expect.objectContaining({ | ||
type: 'slider', | ||
filterMode: 'none', | ||
}), | ||
], | ||
}), | ||
}), | ||
); | ||
|
||
expect(series0).toEqual({ | ||
name: 'series value 1', | ||
type: 'custom', | ||
progressive: 0, | ||
itemStyle: { | ||
color: expect.anything(), | ||
}, | ||
data: [ | ||
{ | ||
value: [ | ||
Date.UTC(2025, 1, 1, 13, 0, 0), | ||
Date.UTC(2025, 1, 1, 14, 0, 0), | ||
0, | ||
2, | ||
Date.UTC(2025, 1, 1, 13, 0, 0), | ||
Date.UTC(2025, 1, 1, 14, 0, 0), | ||
'first', | ||
'tooltip value 1', | ||
'series value 1', | ||
], | ||
}, | ||
], | ||
dimensions: [ | ||
'start_time', | ||
'end_time', | ||
'index', | ||
'series_count', | ||
'startTime', | ||
'endTime', | ||
'Y Axis', | ||
'tooltip_column', | ||
'series', | ||
], | ||
}); | ||
|
||
expect(series1).toEqual({ | ||
name: 'series value 2', | ||
type: 'custom', | ||
progressive: 0, | ||
itemStyle: { | ||
color: expect.anything(), | ||
}, | ||
data: [ | ||
{ | ||
value: [ | ||
Date.UTC(2025, 1, 1, 18, 0, 0), | ||
Date.UTC(2025, 1, 1, 20, 0, 0), | ||
1, | ||
2, | ||
Date.UTC(2025, 1, 1, 18, 0, 0), | ||
Date.UTC(2025, 1, 1, 20, 0, 0), | ||
'second', | ||
'tooltip value 2', | ||
'series value 2', | ||
], | ||
}, | ||
], | ||
dimensions: [ | ||
'start_time', | ||
'end_time', | ||
'index', | ||
'series_count', | ||
'startTime', | ||
'endTime', | ||
'Y Axis', | ||
'tooltip_column', | ||
'series', | ||
], | ||
}); | ||
expect(series[2]).toEqual({ | ||
// just for markLines | ||
type: 'line', | ||
animation: false, | ||
markLine: { | ||
data: [{ yAxis: 1 }, { yAxis: 0 }], | ||
label: { | ||
show: false, | ||
}, | ||
silent: true, | ||
symbol: ['none', 'none'], | ||
lineStyle: { | ||
type: 'dashed', | ||
color: '#dbe0ea', | ||
}, | ||
}, | ||
}); | ||
expect(series[3]).toEqual({ | ||
type: 'line', | ||
animation: false, | ||
markLine: { | ||
data: [ | ||
{ yAxis: 1.5, name: 'first' }, | ||
{ yAxis: 0.5, name: 'second' }, | ||
], | ||
label: { | ||
show: true, | ||
position: 'start', | ||
formatter: '{b}', | ||
}, | ||
lineStyle: expect.objectContaining({ | ||
color: '#00000000', | ||
type: 'solid', | ||
}), | ||
silent: true, | ||
symbol: ['none', 'none'], | ||
}, | ||
}); | ||
}); | ||
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
import { | ||
TimePicker as AntdTimePicker, | ||
TimePickerProps, | ||
TimeRangePickerProps, | ||
} from 'antd-v5'; | ||
|
||
export const TimePicker = (props: TimePickerProps) => ( | ||
<AntdTimePicker css={{ width: '100%' }} {...props} /> | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export const TimeRangePicker = (props: TimeRangePickerProps) => ( | ||
<AntdTimePicker.RangePicker css={{ width: '100%' }} {...props} /> | ||
); |
47 changes: 47 additions & 0 deletions
47
superset-frontend/src/explore/components/controls/TimeRangeControl/index.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { useMemo } from 'react'; | ||
import dayjs from 'dayjs'; | ||
import { TimeRangePicker } from 'src/components/TimePicker'; | ||
import ControlHeader, { ControlHeaderProps } from '../../ControlHeader'; | ||
|
||
type TimeRangeValueType = [string, string]; | ||
|
||
export interface TimeRangeControlProps extends ControlHeaderProps { | ||
value?: TimeRangeValueType; | ||
onChange?: (value: TimeRangeValueType, errors: any) => void; | ||
allowClear?: boolean; | ||
showNow?: boolean; | ||
allowEmpty?: [boolean, boolean]; | ||
} | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export default function TimeRangeControl({ | ||
value: stringValue, | ||
onChange, | ||
allowClear, | ||
showNow, | ||
allowEmpty, | ||
...rest | ||
}: TimeRangeControlProps) { | ||
const dayjsValue = useMemo(() => { | ||
const ret: [dayjs.Dayjs | null, dayjs.Dayjs | null] = [null, null]; | ||
if (stringValue?.[0]) { | ||
ret[0] = dayjs.utc(stringValue[0], 'HH:mm:ss'); | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
if (stringValue?.[1]) { | ||
ret[1] = dayjs.utc(stringValue[1], 'HH:mm:ss'); | ||
} | ||
return ret; | ||
}, [stringValue]); | ||
Quatters marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return ( | ||
<div> | ||
<ControlHeader {...rest} /> | ||
<TimeRangePicker | ||
value={dayjsValue} | ||
onChange={(_, stringValue) => onChange?.(stringValue, null)} | ||
allowClear={allowClear} | ||
showNow={showNow} | ||
allowEmpty={allowEmpty} | ||
/> | ||
</div> | ||
); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
for consistency with other charts, should you just bring the entire
titleControls
section here?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.
There are several reasons why I chose to use only margin controls:
However, I played around with these controls and found that all of them worked except for the last one (
y_axis_title_position
). When the value is set toTop
, the padding for the y-axis applies to the top, rather than to the left, using the standardgetPadding
function. This contradicts (2).If I manually apply padding to the left, then the title behaves weird: the more padding there is on the left, the more it moves to the top. So, I ended up using the entire
titleControls
section except for they_axis_title_position
control (6bc3df8).P.S.: sorry for the long delay