This is an automated email from the ASF dual-hosted git repository. vogievetsky pushed a commit to branch explore_source in repository https://gitbox.apache.org/repos/asf/druid.git
commit 442589145a708b4f6e67f6d68fb2c2652bcf6f13 Author: Vadim Ogievetsky <[email protected]> AuthorDate: Wed Aug 14 08:00:03 2024 -0700 init pie --- web-console/src/modules/bar-chart-module.tsx | 4 +- web-console/src/modules/index.ts | 1 + .../{bar-chart-module.tsx => pie-chart-module.tsx} | 148 ++++++++++++--------- .../src/views/explore-view/explore-view.tsx | 1 + 4 files changed, 88 insertions(+), 66 deletions(-) diff --git a/web-console/src/modules/bar-chart-module.tsx b/web-console/src/modules/bar-chart-module.tsx index 2e07d863b49..585f85a172c 100644 --- a/web-console/src/modules/bar-chart-module.tsx +++ b/web-console/src/modules/bar-chart-module.tsx @@ -31,14 +31,14 @@ import './record-table-module.scss'; const OVERALL_LABEL = 'Overall'; -interface RecordTableParameterValues { +interface BarChartParameterValues { splitColumn: ExpressionMeta; measure: ExpressionMeta; measureToSort: ExpressionMeta; limit: number; } -ModuleRepository.registerModule<RecordTableParameterValues>({ +ModuleRepository.registerModule<BarChartParameterValues>({ id: 'bar-chart', title: 'Bar chart', description: 'An echarts bar chart', diff --git a/web-console/src/modules/index.ts b/web-console/src/modules/index.ts index 932c43137e4..1ce08c91970 100644 --- a/web-console/src/modules/index.ts +++ b/web-console/src/modules/index.ts @@ -19,6 +19,7 @@ import './grouping-table-module'; import './record-table-module'; import './bar-chart-module'; +import './pie-chart-module'; import './overall-module'; import './timeline-module'; diff --git a/web-console/src/modules/bar-chart-module.tsx b/web-console/src/modules/pie-chart-module.tsx similarity index 57% copy from web-console/src/modules/bar-chart-module.tsx copy to web-console/src/modules/pie-chart-module.tsx index 2e07d863b49..7daa2742ec4 100644 --- a/web-console/src/modules/bar-chart-module.tsx +++ b/web-console/src/modules/pie-chart-module.tsx @@ -16,7 +16,7 @@ * limitations under the License. */ -import { L, SqlExpression, SqlQuery } from '@druid-toolkit/query'; +import { C, L, SqlExpression, SqlQuery } from '@druid-toolkit/query'; import type { ECharts } from 'echarts'; import * as echarts from 'echarts'; import React, { useEffect, useMemo, useRef } from 'react'; @@ -31,22 +31,42 @@ import './record-table-module.scss'; const OVERALL_LABEL = 'Overall'; -interface RecordTableParameterValues { +/** + * Returns the cartesian coordinates of a pie slice external centroid + */ +function getCentroid(chart: echarts.ECharts, dataIndex: number) { + // see these underscores everywhere? that's because those are private properties + // I have no real choice but to use them, because there is no public API for this (on pie charts) + // #no_ragrets + const layout = (chart as any)._chartsViews?.[0]?._data?._itemLayouts?.[dataIndex]; + + if (!layout) return; + + const { cx, cy, startAngle, endAngle, r } = layout; + const angle = (startAngle + endAngle) / 2; + + const x = cx + Math.cos(angle) * r; + const y = cy + Math.sin(angle) * r; + + return { x, y }; +} + +interface PieChartParameterValues { splitColumn: ExpressionMeta; measure: ExpressionMeta; - measureToSort: ExpressionMeta; limit: number; + showOthers: boolean; } -ModuleRepository.registerModule<RecordTableParameterValues>({ - id: 'bar-chart', - title: 'Bar chart', - description: 'An echarts bar chart', +ModuleRepository.registerModule<PieChartParameterValues>({ + id: 'pie-chart', + title: 'Pie chart', + description: 'An echarts pie chart', parameters: { splitColumn: { type: 'expression', control: { - label: 'Bar column', + label: 'Slice column', // transferGroup: 'show', required: true, }, @@ -55,31 +75,29 @@ ModuleRepository.registerModule<RecordTableParameterValues>({ type: 'aggregate', default: { expression: SqlExpression.parse('COUNT(*)'), name: 'Count', sqlType: 'BIGINT' }, control: { - label: 'Measure to show', - // transferGroup: 'show-agg', + // transferGroup: 'show', required: true, }, }, - measureToSort: { - type: 'aggregate', - control: { - label: 'Measure to sort (default to shown)', - }, - }, limit: { type: 'number', default: 5, control: { - label: 'Max bars to show', + label: 'Max slices to show', required: true, }, }, + showOthers: { + type: 'boolean', + default: true, + control: { label: 'Show others' }, + }, }, - component: function BarChartModule(props) { + component: function PieChartModule(props) { const { querySource, where, setWhere, parameterValues, stage, runSqlQuery } = props; const chartRef = useRef<ECharts>(); - const { splitColumn, measure, measureToSort, limit } = parameterValues; + const { splitColumn, measure, limit } = parameterValues; const dataQuery = useMemo(() => { const source = querySource.query; @@ -87,16 +105,13 @@ ModuleRepository.registerModule<RecordTableParameterValues>({ return SqlQuery.from(source) .addWhere(where) - .addSelect(splitExpression.as('dim'), { addToGroupBy: 'end' }) - .addSelect(measure.expression.as('met'), { - addToOrderBy: measureToSort ? undefined : 'end', + .addSelect(splitExpression.as('name'), { addToGroupBy: 'end' }) + .addSelect(measure.expression.as('value'), { + addToOrderBy: 'end', direction: 'DESC', }) - .applyIf(measureToSort, q => - q.addOrderBy(measureToSort.expression.toOrderByExpression('DESC')), - ) .changeLimitValue(limit); - }, [querySource, where, splitColumn, measure, measureToSort, limit]); + }, [querySource, where, splitColumn, measure, limit]); const [dataState] = useQueryManager({ query: dataQuery, @@ -109,23 +124,25 @@ ModuleRepository.registerModule<RecordTableParameterValues>({ const myChart = echarts.init(container, 'dark'); myChart.setOption({ - tooltip: {}, - dataset: { - sourceHeader: false, - dimensions: ['dim', 'met'], - source: [], + tooltip: { + trigger: 'item', }, - xAxis: { - type: 'category', - axisLabel: { interval: 0, rotate: -30 }, + legend: { + orient: 'vertical', + left: 'left', }, - yAxis: {}, series: [ { - type: 'bar', - encode: { - x: 'dim', - y: 'met', + type: 'pie', + id: 'hello', + radius: '50%', + data: [], + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)', + }, }, }, ], @@ -150,39 +167,42 @@ ModuleRepository.registerModule<RecordTableParameterValues>({ myChart.off('click'); myChart.setOption({ - dataset: { - source: data, - }, + series: [ + { + id: 'hello', + data, + }, + ], }); myChart.on('click', 'series', p => { - const label = p.name; - const { dim, met } = p.data as any; + if (highlightStore.getState().highlight?.data.name === p.name) { + highlightStore.getState().dropHighlight(); + return; + } + + const centroid = getCentroid(myChart, p.dataIndex); + + if (!centroid) return; - const [x, y] = myChart.convertToPixel({ seriesIndex: 0 }, [dim, met]); + const { name, value, __isOthers } = p.data as any; highlightStore.getState().setHighlight({ - label, - x, - y: y - 20, - data: [dim, met], + label: name + ': ' + value, + x: centroid.x, + y: centroid.y - 20, + data: { name, value, dataIndex: p.dataIndex }, onDrop: () => { highlightStore.getState().dropHighlight(); }, - onSave: - label !== OVERALL_LABEL - ? () => { - if (splitColumn) { - setWhere( - SqlExpression.parse( - // ToDo: remove SqlExpression.parse - where.toggleClauseInWhere(splitColumn.expression.equal(label)), - ), - ); - } - highlightStore.getState().dropHighlight(); - } - : undefined, + onSave: __isOthers + ? undefined + : () => { + setWhere( + SqlExpression.parse(where.toggleClauseInWhere(C(splitColumn.name).equal(name))), + ); + highlightStore.getState().dropHighlight(); + }, }); }); }, [dataState.data]); @@ -195,7 +215,7 @@ ModuleRepository.registerModule<RecordTableParameterValues>({ return ( <div - className="bar-chart-module module" + className="pie-chart-module module" ref={container => { if (chartRef.current || !container) return; chartRef.current = setupChart(container); diff --git a/web-console/src/views/explore-view/explore-view.tsx b/web-console/src/views/explore-view/explore-view.tsx index 3178b601b6f..ef88b8a2d73 100644 --- a/web-console/src/views/explore-view/explore-view.tsx +++ b/web-console/src/views/explore-view/explore-view.tsx @@ -293,6 +293,7 @@ export const ExploreView = React.memo(function ExploreView() { { id: 'record-table', icon: IconNames.PIVOT_TABLE, label: 'Record table' }, { id: 'timeline', icon: IconNames.FLOW_LINEAR, label: 'Timeline' }, { id: 'bar-chart', icon: IconNames.VERTICAL_BAR_CHART_DESC, label: 'Bar chart' }, + { id: 'pie-chart', icon: IconNames.PIE_CHART, label: 'Pie chart' }, ]} selectedModuleId={moduleId} onSelectedModuleIdChange={id => { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
