diff --git a/web-console/src/bootstrap/react-table-defaults.tsx b/web-console/src/bootstrap/react-table-defaults.tsx
index 42039b36da8..531bc8127bc 100644
--- a/web-console/src/bootstrap/react-table-defaults.tsx
+++ b/web-console/src/bootstrap/react-table-defaults.tsx
@@ -40,7 +40,12 @@ export function bootstrapReactTable() {
className: DEFAULT_TABLE_CLASS_NAME,
defaultFilterMethod: (filter: Filter, row: any) => {
const id = filter.pivotId || filter.id;
- return booleanCustomTableFilter(filter, row[id]);
+ const subRows = row._subRows;
+ if (Array.isArray(subRows)) {
+ return subRows.some(r => booleanCustomTableFilter(filter, r[id]));
+ } else {
+ return booleanCustomTableFilter(filter, row[id]);
+ }
},
LoadingComponent: Loader,
loadingText: '',
diff --git a/web-console/src/components/segment-timeline/segment-timeline.tsx b/web-console/src/components/segment-timeline/segment-timeline.tsx
index 150e94f2abe..3fc9e1ad87f 100644
--- a/web-console/src/components/segment-timeline/segment-timeline.tsx
+++ b/web-console/src/components/segment-timeline/segment-timeline.tsx
@@ -16,7 +16,6 @@
* limitations under the License.
*/
-import type { IResizeEntry } from '@blueprintjs/core';
import { FormGroup, HTMLSelect, Radio, RadioGroup, ResizeSensor } from '@blueprintjs/core';
import type { AxisScale } from 'd3-axis';
import { scaleLinear, scaleUtc } from 'd3-scale';
@@ -428,7 +427,7 @@ ORDER BY "start" DESC`;
}
};
- private readonly handleResize = (entries: IResizeEntry[]) => {
+ private readonly handleResize = (entries: ResizeObserverEntry[]) => {
const chartRect = entries[0].contentRect;
this.setState({
chartWidth: chartRect.width,
diff --git a/web-console/src/react-table/react-table-utils.ts b/web-console/src/react-table/react-table-utils.ts
index e1ae5b9b151..91248c55209 100644
--- a/web-console/src/react-table/react-table-utils.ts
+++ b/web-console/src/react-table/react-table-utils.ts
@@ -107,7 +107,7 @@ export function addOrUpdateFilter(filters: readonly Filter[], filter: Filter): F
return addOrUpdate(filters, filter, f => f.id);
}
-export function booleanCustomTableFilter(filter: Filter, value: any): boolean {
+export function booleanCustomTableFilter(filter: Filter, value: unknown): boolean {
if (value == null) return false;
const modeAndNeedle = parseFilterModeAndNeedle(filter);
if (!modeAndNeedle) return true;
diff --git a/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap b/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap
index f1ed7216981..93e3c83d041 100644
--- a/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap
+++ b/web-console/src/views/workbench-view/column-tree/__snapshots__/column-tree.spec.tsx.snap
@@ -32,7 +32,13 @@ exports[`ColumnTree matches snapshot 1`] = `
Object {
"childNodes": Array [
Object {
- "icon": "time",
+ "icon": ,
"id": "__time",
"label": ,
},
Object {
- "icon": "numerical",
+ "icon": ,
"id": "added",
"label": ,
},
Object {
- "icon": "floating-point",
+ "icon": ,
"id": "addedBy10",
"label":
+
+
+`;
diff --git a/web-console/src/views/workbench-view/column-tree/column-tree-menu/complex-menu-items/complex-menu-items.spec.tsx b/web-console/src/views/workbench-view/column-tree/column-tree-menu/complex-menu-items/complex-menu-items.spec.tsx
new file mode 100644
index 00000000000..a7d7fdcf2c8
--- /dev/null
+++ b/web-console/src/views/workbench-view/column-tree/column-tree-menu/complex-menu-items/complex-menu-items.spec.tsx
@@ -0,0 +1,41 @@
+/*
+ * 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 { SqlQuery } from '@druid-toolkit/query';
+import { render } from '@testing-library/react';
+import React from 'react';
+
+import { ComplexMenuItems } from './complex-menu-items';
+
+describe('ComplexMenuItems', () => {
+ it('matches snapshot when menu is opened for column not inside group by', () => {
+ const numberMenu = (
+ {}}
+ />
+ );
+
+ const { container } = render(numberMenu);
+ expect(container).toMatchSnapshot();
+ });
+});
diff --git a/web-console/src/views/workbench-view/column-tree/column-tree-menu/complex-menu-items/complex-menu-items.tsx b/web-console/src/views/workbench-view/column-tree/column-tree-menu/complex-menu-items/complex-menu-items.tsx
new file mode 100644
index 00000000000..fa172262f07
--- /dev/null
+++ b/web-console/src/views/workbench-view/column-tree/column-tree-menu/complex-menu-items/complex-menu-items.tsx
@@ -0,0 +1,83 @@
+/*
+ * 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 { MenuItem } from '@blueprintjs/core';
+import { IconNames } from '@blueprintjs/icons';
+import type { SqlExpression, SqlQuery } from '@druid-toolkit/query';
+import { C, F } from '@druid-toolkit/query';
+import type { JSX } from 'react';
+import React from 'react';
+
+import { prettyPrintSql } from '../../../../../utils';
+
+const UNIQUE_FUNCTIONS: Record = {
+ 'COMPLEX': 'APPROX_COUNT_DISTINCT_BUILTIN',
+ 'COMPLEX': 'APPROX_COUNT_DISTINCT_DS_THETA',
+ 'COMPLEX': 'APPROX_COUNT_DISTINCT_DS_HLL',
+};
+
+const QUANTILE_FUNCTIONS: Record = {
+ 'COMPLEX': 'APPROX_QUANTILE_DS',
+};
+
+export interface ComplexMenuItemsProps {
+ table: string;
+ schema: string;
+ columnName: string;
+ columnType: string;
+ parsedQuery: SqlQuery;
+ onQueryChange: (query: SqlQuery, run?: boolean) => void;
+}
+
+export const ComplexMenuItems = React.memo(function ComplexMenuItems(props: ComplexMenuItemsProps) {
+ const { columnName, columnType, parsedQuery, onQueryChange } = props;
+ const column = C(columnName);
+
+ function renderAggregateMenu(): JSX.Element | undefined {
+ if (!parsedQuery.hasGroupBy()) return;
+
+ function aggregateMenuItem(ex: SqlExpression, alias: string) {
+ return (
+