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]

Reply via email to