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 5ce2abafb787a3c6bf8d748a877585bf7d3db2e3
Author: Vadim Ogievetsky <[email protected]>
AuthorDate: Wed Aug 14 14:19:09 2024 -0700

    add others
---
 .../_save/modules/pie-chart-echarts-module.ts      | 203 ---------------------
 web-console/src/modules/pie-chart-module.tsx       |  50 +++--
 web-console/src/utils/general.tsx                  |   6 +
 3 files changed, 41 insertions(+), 218 deletions(-)

diff --git a/web-console/_save/modules/pie-chart-echarts-module.ts 
b/web-console/_save/modules/pie-chart-echarts-module.ts
deleted file mode 100644
index d9aedb16082..00000000000
--- a/web-console/_save/modules/pie-chart-echarts-module.ts
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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 { C, SqlExpression } from '@druid-toolkit/query';
-import { typedVisualModule } from '@druid-toolkit/visuals-core';
-import * as echarts from 'echarts';
-
-import { highlightStore } from '../highlight-store/highlight-store';
-import { getInitQuery } from '../utils';
-
-/**
- * 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 };
-}
-
-export default typedVisualModule({
-  parameters: {
-    splitColumn: {
-      type: 'column',
-      control: {
-        label: 'Slice column',
-        // transferGroup: 'show',
-        required: true,
-      },
-    },
-    metric: {
-      type: 'aggregate',
-      default: { expression: SqlExpression.parse('COUNT(*)'), name: 'Count', 
sqlType: 'BIGINT' },
-      control: {
-        // transferGroup: 'show',
-        required: true,
-      },
-    },
-    limit: {
-      type: 'number',
-      default: 5,
-      control: {
-        label: 'Max slices to show',
-        required: true,
-      },
-    },
-    showOthers: {
-      type: 'boolean',
-      default: true,
-      control: { label: 'Show others' },
-    },
-  },
-  module: ({ container, host, updateWhere }) => {
-    const myChart = echarts.init(container, 'dark');
-
-    myChart.setOption({
-      tooltip: {
-        trigger: 'item',
-      },
-      legend: {
-        orient: 'vertical',
-        left: 'left',
-      },
-      series: [
-        {
-          type: 'pie',
-          id: 'hello',
-          radius: '50%',
-          data: [],
-          emphasis: {
-            itemStyle: {
-              shadowBlur: 10,
-              shadowOffsetX: 0,
-              shadowColor: 'rgba(0, 0, 0, 0.5)',
-            },
-          },
-        },
-      ],
-    });
-
-    return {
-      async update({ table, where, parameterValues }) {
-        const { splitColumn, metric, limit } = parameterValues;
-
-        if (!splitColumn) return;
-
-        myChart.off('click');
-
-        const result = await host.sqlQuery(
-          getInitQuery(table, where)
-            .addSelect(splitColumn.expression.as('name'), { addToGroupBy: 
'end' })
-            .addSelect(metric.expression.as('value'), {
-              addToOrderBy: 'end',
-              direction: 'DESC',
-            })
-            .changeLimitValue(limit),
-        );
-
-        const data = result.toObjectArray();
-
-        if (parameterValues.showOthers) {
-          const others = await host.sqlQuery(
-            getInitQuery(
-              table,
-              where.changeClauseInWhere(
-                C(splitColumn.name).notIn(result.getColumnByIndex(0)!),
-              ) as SqlExpression,
-            ).addSelect(metric.expression.as('value')),
-          );
-
-          data.push({ name: 'Others', value: others.rows[0][0], __isOthers: 
true });
-        }
-
-        myChart.setOption({
-          series: [
-            {
-              id: 'hello',
-              data,
-            },
-          ],
-        });
-
-        myChart.on('click', 'series', p => {
-          if (highlightStore.getState().highlight?.data.name === p.name) {
-            highlightStore.getState().dropHighlight();
-            return;
-          }
-
-          const centroid = getCentroid(myChart, p.dataIndex);
-
-          if (!centroid) return;
-
-          const { name, value, __isOthers } = p.data as any;
-
-          highlightStore.getState().setHighlight({
-            label: name + ': ' + value,
-            x: centroid.x,
-            y: centroid.y - 20,
-            data: { name, value, dataIndex: p.dataIndex },
-            onDrop: () => {
-              highlightStore.getState().dropHighlight();
-            },
-            onSave: __isOthers
-              ? undefined
-              : () => {
-                  
updateWhere(where.toggleClauseInWhere(C(splitColumn.name).equal(name)));
-                  highlightStore.getState().dropHighlight();
-                },
-          });
-        });
-      },
-
-      resize() {
-        myChart.resize();
-
-        // if there is a highlight, update its x position
-        // by calculating new pixel position from the highlight's data
-        const highlight = highlightStore.getState().highlight;
-        if (highlight) {
-          const { dataIndex } = highlight.data;
-
-          const centroid = getCentroid(myChart, dataIndex);
-
-          if (!centroid) return;
-
-          highlightStore.getState().updateHighlight({
-            x: centroid.x,
-            y: centroid.y - 20,
-          });
-        }
-      },
-
-      destroy() {
-        myChart.dispose();
-      },
-    };
-  },
-});
diff --git a/web-console/src/modules/pie-chart-module.tsx 
b/web-console/src/modules/pie-chart-module.tsx
index 7daa2742ec4..fdd32f2ee99 100644
--- a/web-console/src/modules/pie-chart-module.tsx
+++ b/web-console/src/modules/pie-chart-module.tsx
@@ -22,6 +22,7 @@ import * as echarts from 'echarts';
 import React, { useEffect, useMemo, useRef } from 'react';
 
 import { useQueryManager } from '../hooks';
+import { formatEmpty, formatNumber } from '../utils';
 import { highlightStore } from 
'../views/explore-view/highlight-store/highlight-store';
 
 import type { ExpressionMeta } from './models';
@@ -97,26 +98,42 @@ ModuleRepository.registerModule<PieChartParameterValues>({
     const { querySource, where, setWhere, parameterValues, stage, runSqlQuery 
} = props;
     const chartRef = useRef<ECharts>();
 
-    const { splitColumn, measure, limit } = parameterValues;
+    const { splitColumn, measure, limit, showOthers } = parameterValues;
 
-    const dataQuery = useMemo(() => {
+    const dataQueries = useMemo(() => {
       const source = querySource.query;
       const splitExpression = splitColumn ? splitColumn.expression : 
L(OVERALL_LABEL);
 
-      return SqlQuery.from(source)
-        .addWhere(where)
-        .addSelect(splitExpression.as('name'), { addToGroupBy: 'end' })
-        .addSelect(measure.expression.as('value'), {
-          addToOrderBy: 'end',
-          direction: 'DESC',
-        })
-        .changeLimitValue(limit);
-    }, [querySource, where, splitColumn, measure, limit]);
+      return {
+        mainQuery: SqlQuery.from(source)
+          .addWhere(where)
+          .addSelect(splitExpression.as('name'), { addToGroupBy: 'end' })
+          .addSelect(measure.expression.as('value'), {
+            addToOrderBy: 'end',
+            direction: 'DESC',
+          })
+          .changeLimitValue(limit),
+        splitExpression: splitColumn?.expression,
+        othersPartialQuery: showOthers
+          ? 
SqlQuery.from(source).addWhere(where).addSelect(measure.expression.as('value'))
+          : undefined,
+      };
+    }, [querySource, where, splitColumn, measure, limit, showOthers]);
 
     const [dataState] = useQueryManager({
-      query: dataQuery,
-      processQuery: async (query: SqlQuery) => {
-        return (await runSqlQuery(query)).toObjectArray();
+      query: dataQueries,
+      processQuery: async ({ mainQuery, splitExpression, othersPartialQuery }) 
=> {
+        const result = await runSqlQuery(mainQuery);
+        const data = result.toObjectArray();
+
+        if (splitExpression && othersPartialQuery) {
+          const othersResult = await runSqlQuery(
+            
othersPartialQuery.addWhere(splitExpression.notIn(result.getColumnByIndex(0)!)),
+          );
+          data.push({ name: 'Others', value: othersResult.rows[0][0], 
__isOthers: true });
+        }
+
+        return data;
       },
     });
 
@@ -144,6 +161,9 @@ ModuleRepository.registerModule<PieChartParameterValues>({
                 shadowColor: 'rgba(0, 0, 0, 0.5)',
               },
             },
+            label: {
+              formatter: (params: any) => formatEmpty(params.name),
+            },
           },
         ],
       });
@@ -188,7 +208,7 @@ ModuleRepository.registerModule<PieChartParameterValues>({
         const { name, value, __isOthers } = p.data as any;
 
         highlightStore.getState().setHighlight({
-          label: name + ': ' + value,
+          label: formatEmpty(name) + ': ' + formatNumber(value),
           x: centroid.x,
           y: centroid.y - 20,
           data: { name, value, dataIndex: p.dataIndex },
diff --git a/web-console/src/utils/general.tsx 
b/web-console/src/utils/general.tsx
index 6ccab1077b4..016cee28d34 100644
--- a/web-console/src/utils/general.tsx
+++ b/web-console/src/utils/general.tsx
@@ -259,6 +259,12 @@ export function uniq(array: readonly string[]): string[] {
 
 // ----------------------------
 
+export function formatEmpty(str: string): string {
+  return str === '' ? 'empty' : str;
+}
+
+// ----------------------------
+
 export function formatInteger(n: NumberLike): string {
   return numeral(n).format('0,0');
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to