This is an automated email from the ASF dual-hosted git repository.

vogievetsky pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 2e324702f06 Web console: add suggestions for table status filtering. 
(#17765)
2e324702f06 is described below

commit 2e324702f06fa072f3c546f4516629e0a4ac75e6
Author: Vadim Ogievetsky <[email protected]>
AuthorDate: Wed Mar 5 13:12:29 2025 -0800

    Web console: add suggestions for table status filtering. (#17765)
    
    * suggest filter values when known
    
    * update snapshots
    
    * add more d
    
    * fix load rule clamp
    
    * better segment timeline init
---
 .../src/components/menu-boolean/menu-boolean.tsx   |  6 +--
 .../segment-timeline/segment-bar-chart-render.tsx  |  4 +-
 web-console/src/react-table/react-table-inputs.tsx | 53 ++++++++++++++++++++
 web-console/src/react-table/react-table-utils.ts   | 56 ++++++++++++----------
 web-console/src/utils/general.tsx                  |  5 ++
 .../views/datasources-view/datasources-view.tsx    | 14 +++++-
 .../values-filter-control.tsx                      |  3 +-
 .../components/helper-table/helper-table.tsx       |  3 +-
 .../nested-column-dialog/nested-column-dialog.tsx  |  9 +++-
 web-console/src/views/explore-view/utils/misc.ts   |  5 --
 .../src/views/segments-view/segments-view.tsx      | 14 +++++-
 .../__snapshots__/services-view.spec.tsx.snap      |  1 +
 .../src/views/services-view/services-view.tsx      | 16 ++++++-
 .../schema-step/schema-step.tsx                    |  4 +-
 .../__snapshots__/supervisors-view.spec.tsx.snap   |  1 +
 .../views/supervisors-view/supervisors-view.tsx    | 15 ++++++
 .../__snapshots__/tasks-view.spec.tsx.snap         |  1 +
 web-console/src/views/tasks-view/tasks-view.tsx    | 14 +++++-
 .../views/workbench-view/run-panel/run-panel.tsx   | 18 +++----
 19 files changed, 186 insertions(+), 56 deletions(-)

diff --git a/web-console/src/components/menu-boolean/menu-boolean.tsx 
b/web-console/src/components/menu-boolean/menu-boolean.tsx
index 0d77d7e315e..2457f848643 100644
--- a/web-console/src/components/menu-boolean/menu-boolean.tsx
+++ b/web-console/src/components/menu-boolean/menu-boolean.tsx
@@ -31,9 +31,9 @@ function toKey(value: boolean | undefined) {
 
 const DEFAULT_OPTIONS_TEXT: Partial<Record<TrueFalseUndefined, string>> = { 
undefined: 'Auto' };
 
-export const ENABLE_DISABLE_OPTIONS_TEXT: Partial<Record<TrueFalseUndefined, 
string>> = {
-  true: 'Enable',
-  false: 'Disable',
+export const ENABLED_DISABLED_OPTIONS_TEXT: Partial<Record<TrueFalseUndefined, 
string>> = {
+  true: 'Enabled',
+  false: 'Disabled',
   undefined: 'Auto',
 };
 
diff --git 
a/web-console/src/components/segment-timeline/segment-bar-chart-render.tsx 
b/web-console/src/components/segment-timeline/segment-bar-chart-render.tsx
index bb04259b53d..630dc423149 100644
--- a/web-console/src/components/segment-timeline/segment-bar-chart-render.tsx
+++ b/web-console/src/components/segment-timeline/segment-bar-chart-render.tsx
@@ -644,8 +644,8 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
         className={classNames('load-rule', loadRuleToBaseType(loadRule))}
         data-tooltip={title}
         style={{
-          left: xWidth.x,
-          width: xWidth.width,
+          left: clamp(xWidth.x, 0, innerStage.width),
+          width: clamp(xWidth.width, 0, innerStage.width),
         }}
       >
         {title}
diff --git a/web-console/src/react-table/react-table-inputs.tsx 
b/web-console/src/react-table/react-table-inputs.tsx
index 22ff5f64bd2..79932b490e4 100644
--- a/web-console/src/react-table/react-table-inputs.tsx
+++ b/web-console/src/react-table/react-table-inputs.tsx
@@ -22,6 +22,8 @@ import classNames from 'classnames';
 import { useEffect, useState } from 'react';
 import type { Column, ReactTableFunction } from 'react-table';
 
+import { filterMap, toggle } from '../utils';
+
 import {
   combineModeAndNeedle,
   FILTER_MODES,
@@ -113,6 +115,57 @@ export function GenericFilterInput({ column, filter, 
onChange, key }: FilterRend
   );
 }
 
+export function suggestibleFilterInput(suggestions: string[]) {
+  return function SuggestibleFilterInput({ filter, onChange, key, ...rest }: 
FilterRendererProps) {
+    let valuesFilteredOn: string[] | undefined;
+    if (filter) {
+      const modeAndNeedle = parseFilterModeAndNeedle(filter, true);
+      if (modeAndNeedle && modeAndNeedle.mode === '=') {
+        valuesFilteredOn = modeAndNeedle.needleParts;
+      }
+    }
+    return (
+      <Popover
+        key={key}
+        placement="bottom-start"
+        minimal
+        content={
+          <Menu>
+            {filterMap(suggestions, (suggestion, i) => {
+              return (
+                <MenuItem
+                  key={i}
+                  icon={
+                    valuesFilteredOn
+                      ? valuesFilteredOn.includes(suggestion)
+                        ? IconNames.MINUS
+                        : IconNames.PLUS
+                      : IconNames.EQUALS
+                  }
+                  text={suggestion}
+                  onClick={() =>
+                    onChange(
+                      combineModeAndNeedle(
+                        '=',
+                        valuesFilteredOn
+                          ? toggle(valuesFilteredOn, suggestion).join('|')
+                          : suggestion,
+                        true,
+                      ),
+                    )
+                  }
+                />
+              );
+            })}
+          </Menu>
+        }
+      >
+        <GenericFilterInput filter={filter} onChange={onChange} {...rest} />
+      </Popover>
+    );
+  };
+}
+
 export function BooleanFilterInput({ filter, onChange, key }: 
FilterRendererProps) {
   return (
     <HTMLSelect
diff --git a/web-console/src/react-table/react-table-utils.ts 
b/web-console/src/react-table/react-table-utils.ts
index 7732c90b231..bb19dddae2d 100644
--- a/web-console/src/react-table/react-table-utils.ts
+++ b/web-console/src/react-table/react-table-utils.ts
@@ -81,6 +81,7 @@ export function filterModeToTitle(mode: FilterMode): string {
 interface FilterModeAndNeedle {
   mode: FilterMode;
   needle: string;
+  needleParts: string[];
 }
 
 export function addFilter(
@@ -100,13 +101,16 @@ export function parseFilterModeAndNeedle(
   if (!m) return;
   if (!loose && !m[2]) return;
   const mode = (m[1] as FilterMode) || '~';
+  const needle = m[2] || '';
   return {
     mode,
-    needle: m[2] || '',
+    needle,
+    needleParts: needle.split('|'),
   };
 }
 
-export function combineModeAndNeedle(mode: FilterMode, needle: string): string 
{
+export function combineModeAndNeedle(mode: FilterMode, needle: string, cleanup 
= false): string {
+  if (cleanup && needle === '') return '';
   return `${mode}${needle}`;
 }
 
@@ -116,60 +120,64 @@ export function addOrUpdateFilter(filters: readonly 
Filter[], filter: Filter): F
 
 export function booleanCustomTableFilter(filter: Filter, value: unknown): 
boolean {
   if (value == null) return false;
-  const modeAndNeedle = parseFilterModeAndNeedle(filter);
-  if (!modeAndNeedle) return true;
-  const { mode, needle } = modeAndNeedle;
+  const modeAndNeedles = parseFilterModeAndNeedle(filter);
+  if (!modeAndNeedles) return true;
+  const { mode, needleParts } = modeAndNeedles;
   const strValue = String(value);
   switch (mode) {
     case '=':
-      return strValue === needle;
+      return needleParts.some(needle => strValue === needle);
 
     case '!=':
-      return strValue !== needle;
+      return needleParts.every(needle => strValue !== needle);
 
     case '<':
-      return strValue < needle;
+      return needleParts.some(needle => strValue < needle);
 
     case '<=':
-      return strValue <= needle;
+      return needleParts.some(needle => strValue <= needle);
 
     case '>':
-      return strValue > needle;
+      return needleParts.some(needle => strValue > needle);
 
     case '>=':
-      return strValue >= needle;
+      return needleParts.some(needle => strValue >= needle);
 
     default:
-      return caseInsensitiveContains(strValue, needle);
+      return needleParts.some(needle => caseInsensitiveContains(strValue, 
needle));
   }
 }
 
 export function sqlQueryCustomTableFilter(filter: Filter): SqlExpression | 
undefined {
-  const modeAndNeedle = parseFilterModeAndNeedle(filter);
-  if (!modeAndNeedle) return;
-  const { mode, needle } = modeAndNeedle;
+  const modeAndNeedles = parseFilterModeAndNeedle(filter);
+  if (!modeAndNeedles) return;
+  const { mode, needleParts } = modeAndNeedles;
   const column = C(filter.id);
   switch (mode) {
-    case '=':
-      return column.equal(needle);
+    case '=': {
+      return SqlExpression.or(...needleParts.map(needle => 
column.equal(needle)));
+    }
 
-    case '!=':
-      return column.unequal(needle);
+    case '!=': {
+      return SqlExpression.and(...needleParts.map(needle => 
column.unequal(needle)));
+    }
 
     case '<':
-      return column.lessThan(needle);
+      return SqlExpression.or(...needleParts.map(needle => 
column.lessThan(needle)));
 
     case '<=':
-      return column.lessThanOrEqual(needle);
+      return SqlExpression.or(...needleParts.map(needle => 
column.lessThanOrEqual(needle)));
 
     case '>':
-      return column.greaterThan(needle);
+      return SqlExpression.or(...needleParts.map(needle => 
column.greaterThan(needle)));
 
     case '>=':
-      return column.greaterThanOrEqual(needle);
+      return SqlExpression.or(...needleParts.map(needle => 
column.greaterThanOrEqual(needle)));
 
     default:
-      return F('LOWER', column).like(`%${needle.toLowerCase()}%`);
+      return SqlExpression.or(
+        ...needleParts.map(needle => F('LOWER', 
column).like(`%${needle.toLowerCase()}%`)),
+      );
   }
 }
 
diff --git a/web-console/src/utils/general.tsx 
b/web-console/src/utils/general.tsx
index 9aefb5631f7..8af818664fd 100644
--- a/web-console/src/utils/general.tsx
+++ b/web-console/src/utils/general.tsx
@@ -686,3 +686,8 @@ export function offsetToRowColumn(str: string, offset: 
number): RowColumn | unde
 export function xor(a: unknown, b: unknown): boolean {
   return Boolean(a ? !b : b);
 }
+
+export function toggle<T>(xs: readonly T[], x: T, eq?: (a: T, b: T) => 
boolean): T[] {
+  const e = eq || ((a, b) => a === b);
+  return xs.find(_ => e(_, x)) ? xs.filter(d => !e(d, x)) : xs.concat([x]);
+}
diff --git a/web-console/src/views/datasources-view/datasources-view.tsx 
b/web-console/src/views/datasources-view/datasources-view.tsx
index f4f652befed..4921027100a 100644
--- a/web-console/src/views/datasources-view/datasources-view.tsx
+++ b/web-console/src/views/datasources-view/datasources-view.tsx
@@ -70,6 +70,7 @@ import {
   compact,
   countBy,
   deepGet,
+  findMap,
   formatBytes,
   formatInteger,
   formatMillions,
@@ -1709,7 +1710,7 @@ GROUP BY 1, 2`;
   }
 
   render() {
-    const { capabilities, goToSegments } = this.props;
+    const { capabilities, filters, goToSegments } = this.props;
     const {
       showUnused,
       visibleColumns,
@@ -1737,7 +1738,16 @@ GROUP BY 1, 2`;
             label="Show segment timeline"
             onChange={() =>
               this.setState({
-                showSegmentTimeline: showSegmentTimeline ? undefined : { 
capabilities },
+                showSegmentTimeline: showSegmentTimeline
+                  ? undefined
+                  : {
+                      capabilities,
+                      datasource: findMap(filters, filter =>
+                        filter.id === 'datasource' && 
/^=[^=|]+$/.exec(String(filter.value))
+                          ? filter.value.slice(1)
+                          : undefined,
+                      ),
+                    },
               })
             }
             disabled={!capabilities.hasSqlOrCoordinatorAccess()}
diff --git 
a/web-console/src/views/explore-view/components/filter-pane/filter-menu/values-filter-control/values-filter-control.tsx
 
b/web-console/src/views/explore-view/components/filter-pane/filter-menu/values-filter-control/values-filter-control.tsx
index 93304f628ae..f14851f081f 100644
--- 
a/web-console/src/views/explore-view/components/filter-pane/filter-menu/values-filter-control/values-filter-control.tsx
+++ 
b/web-console/src/views/explore-view/components/filter-pane/filter-menu/values-filter-control/values-filter-control.tsx
@@ -25,9 +25,8 @@ import React, { useMemo, useState } from 'react';
 
 import { ClearableInput } from '../../../../../../components';
 import { useQueryManager } from '../../../../../../hooks';
-import { caseInsensitiveContains, filterMap } from '../../../../../../utils';
+import { caseInsensitiveContains, filterMap, toggle } from 
'../../../../../../utils';
 import type { QuerySource } from '../../../../models';
-import { toggle } from '../../../../utils';
 import { ColumnValue } from '../../../column-value/column-value';
 
 import './values-filter-control.scss';
diff --git 
a/web-console/src/views/explore-view/components/helper-table/helper-table.tsx 
b/web-console/src/views/explore-view/components/helper-table/helper-table.tsx
index 42ad3ae45d7..2f6ee09153c 100644
--- 
a/web-console/src/views/explore-view/components/helper-table/helper-table.tsx
+++ 
b/web-console/src/views/explore-view/components/helper-table/helper-table.tsx
@@ -37,11 +37,12 @@ import {
   checkedCircleIcon,
   filterMap,
   formatNumber,
+  toggle,
   without,
   xor,
 } from '../../../../utils';
 import type { ExpressionMeta, QuerySource } from '../../models';
-import { addOrUpdatePattern, toggle } from '../../utils';
+import { addOrUpdatePattern } from '../../utils';
 import { ColumnValue } from '../column-value/column-value';
 
 import './helper-table.scss';
diff --git 
a/web-console/src/views/explore-view/components/resource-pane/nested-column-dialog/nested-column-dialog.tsx
 
b/web-console/src/views/explore-view/components/resource-pane/nested-column-dialog/nested-column-dialog.tsx
index acb2e2c4775..133661c564b 100644
--- 
a/web-console/src/views/explore-view/components/resource-pane/nested-column-dialog/nested-column-dialog.tsx
+++ 
b/web-console/src/views/explore-view/components/resource-pane/nested-column-dialog/nested-column-dialog.tsx
@@ -33,10 +33,15 @@ import React, { useState } from 'react';
 
 import { ClearableInput, Loader, MenuCheckbox } from 
'../../../../../components';
 import { useQueryManager } from '../../../../../hooks';
-import { caseInsensitiveContains, filterMap, pluralIfNeeded, wait } from 
'../../../../../utils';
+import {
+  caseInsensitiveContains,
+  filterMap,
+  pluralIfNeeded,
+  toggle,
+  wait,
+} from '../../../../../utils';
 import type { QuerySource } from '../../../models';
 import { ExpressionMeta } from '../../../models';
-import { toggle } from '../../../utils';
 
 import './nested-column-dialog.scss';
 
diff --git a/web-console/src/views/explore-view/utils/misc.ts 
b/web-console/src/views/explore-view/utils/misc.ts
index 3f461b1d6c8..8b0c917c87a 100644
--- a/web-console/src/views/explore-view/utils/misc.ts
+++ b/web-console/src/views/explore-view/utils/misc.ts
@@ -19,11 +19,6 @@
 import { nonEmptyArray } from '../../../utils';
 import type { ParameterDefinition } from '../models';
 
-export function toggle<T>(xs: readonly T[], x: T, eq?: (a: T, b: T) => 
boolean): T[] {
-  const e = eq || ((a, b) => a === b);
-  return xs.find(_ => e(_, x)) ? xs.filter(d => !e(d, x)) : xs.concat([x]);
-}
-
 export function normalizeType(paramType: ParameterDefinition['type']): 
ParameterDefinition['type'] {
   switch (paramType) {
     case 'expressions':
diff --git a/web-console/src/views/segments-view/segments-view.tsx 
b/web-console/src/views/segments-view/segments-view.tsx
index 5ac84089aa1..ff3b0f76d8b 100644
--- a/web-console/src/views/segments-view/segments-view.tsx
+++ b/web-console/src/views/segments-view/segments-view.tsx
@@ -62,6 +62,7 @@ import {
   compact,
   countBy,
   filterMap,
+  findMap,
   formatBytes,
   formatInteger,
   getApiArray,
@@ -1004,7 +1005,7 @@ export class SegmentsView extends 
React.PureComponent<SegmentsViewProps, Segment
   }
 
   render() {
-    const { capabilities, onFiltersChange } = this.props;
+    const { capabilities, filters, onFiltersChange } = this.props;
     const {
       segmentTableActionDialogId,
       datasourceTableActionDialogId,
@@ -1047,7 +1048,16 @@ export class SegmentsView extends 
React.PureComponent<SegmentsViewProps, Segment
             label="Show segment timeline"
             onChange={() =>
               this.setState({
-                showSegmentTimeline: showSegmentTimeline ? undefined : { 
capabilities },
+                showSegmentTimeline: showSegmentTimeline
+                  ? undefined
+                  : {
+                      capabilities,
+                      datasource: findMap(filters, filter =>
+                        filter.id === 'datasource' && 
/^=[^=|]+$/.exec(String(filter.value))
+                          ? filter.value.slice(1)
+                          : undefined,
+                      ),
+                    },
               })
             }
             disabled={!capabilities.hasSqlOrCoordinatorAccess()}
diff --git 
a/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap 
b/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap
index 3e4e05a451f..b304833a8cc 100644
--- 
a/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap
+++ 
b/web-console/src/views/services-view/__snapshots__/services-view.spec.tsx.snap
@@ -132,6 +132,7 @@ exports[`ServicesView renders data 1`] = `
         },
         {
           "Cell": [Function],
+          "Filter": [Function],
           "Header": "Type",
           "accessor": "service_type",
           "show": true,
diff --git a/web-console/src/views/services-view/services-view.tsx 
b/web-console/src/views/services-view/services-view.tsx
index e658d935594..2a68eaed1cd 100644
--- a/web-console/src/views/services-view/services-view.tsx
+++ b/web-console/src/views/services-view/services-view.tsx
@@ -38,7 +38,11 @@ import {
 import { AsyncActionDialog } from '../../dialogs';
 import type { QueryWithContext } from '../../druid-models';
 import type { Capabilities, CapabilitiesMode } from '../../helpers';
-import { STANDARD_TABLE_PAGE_SIZE, STANDARD_TABLE_PAGE_SIZE_OPTIONS } from 
'../../react-table';
+import {
+  STANDARD_TABLE_PAGE_SIZE,
+  STANDARD_TABLE_PAGE_SIZE_OPTIONS,
+  suggestibleFilterInput,
+} from '../../react-table';
 import { Api, AppToaster } from '../../singletons';
 import type { AuxiliaryQueryFn, NumberLike } from '../../utils';
 import {
@@ -417,6 +421,16 @@ ORDER BY
           {
             Header: 'Type',
             show: visibleColumns.shown('Type'),
+            Filter: suggestibleFilterInput([
+              'coordinator',
+              'overlord',
+              'router',
+              'broker',
+              'historical',
+              'indexer',
+              'middle_manager',
+              'peon',
+            ]),
             accessor: 'service_type',
             width: 150,
             Cell: this.renderFilterableCell('service_type'),
diff --git 
a/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx 
b/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
index 27b24a8350a..232c6635361 100644
--- a/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
+++ b/web-console/src/views/sql-data-loader-view/schema-step/schema-step.tsx
@@ -48,7 +48,7 @@ import { useCallback, useEffect, useLayoutEffect, useMemo, 
useRef, useState } fr
 
 import {
   ClearableInput,
-  ENABLE_DISABLE_OPTIONS_TEXT,
+  ENABLED_DISABLED_OPTIONS_TEXT,
   LearnMore,
   Loader,
   MenuBoolean,
@@ -694,7 +694,7 @@ export const SchemaStep = function SchemaStep(props: 
SchemaStepProps) {
                     text="Force segment sort by time"
                     value={forceSegmentSortByTime}
                     onValueChange={v => 
changeForceSegmentSortByTime(Boolean(v))}
-                    optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                    optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                     optionsLabelElement={{ false: EXPERIMENTAL_ICON }}
                   />
                 </Menu>
diff --git 
a/web-console/src/views/supervisors-view/__snapshots__/supervisors-view.spec.tsx.snap
 
b/web-console/src/views/supervisors-view/__snapshots__/supervisors-view.spec.tsx.snap
index f9a450468e7..273fa44d9db 100644
--- 
a/web-console/src/views/supervisors-view/__snapshots__/supervisors-view.spec.tsx.snap
+++ 
b/web-console/src/views/supervisors-view/__snapshots__/supervisors-view.spec.tsx.snap
@@ -183,6 +183,7 @@ exports[`SupervisorsView matches snapshot 1`] = `
         },
         {
           "Cell": [Function],
+          "Filter": [Function],
           "Header": "Status",
           "accessor": "detailed_state",
           "id": "detailed_state",
diff --git a/web-console/src/views/supervisors-view/supervisors-view.tsx 
b/web-console/src/views/supervisors-view/supervisors-view.tsx
index 0b1bd9a19d2..89ad8ebfcb9 100644
--- a/web-console/src/views/supervisors-view/supervisors-view.tsx
+++ b/web-console/src/views/supervisors-view/supervisors-view.tsx
@@ -58,6 +58,7 @@ import {
   SMALL_TABLE_PAGE_SIZE,
   SMALL_TABLE_PAGE_SIZE_OPTIONS,
   sqlQueryCustomTableFilters,
+  suggestibleFilterInput,
 } from '../../react-table';
 import { Api, AppToaster } from '../../singletons';
 import type { AuxiliaryQueryFn, TableState } from '../../utils';
@@ -741,6 +742,20 @@ export class SupervisorsView extends React.PureComponent<
             Header: 'Status',
             id: 'detailed_state',
             width: 150,
+            Filter: suggestibleFilterInput([
+              'CONNECTING_TO_STREAM',
+              'CREATING_TASKS',
+              'DISCOVERING_INITIAL_TASKS',
+              'IDLE',
+              'LOST_CONTACT_WITH_STREAM',
+              'PENDING',
+              'RUNNING',
+              'STOPPING',
+              'SUSPENDED',
+              'UNABLE_TO_CONNECT_TO_STREAM',
+              'UNHEALTHY_SUPERVISOR',
+              'UNHEALTHY_TASKS',
+            ]),
             accessor: 'detailed_state',
             Cell: ({ value }) => (
               <TableFilterableCell
diff --git 
a/web-console/src/views/tasks-view/__snapshots__/tasks-view.spec.tsx.snap 
b/web-console/src/views/tasks-view/__snapshots__/tasks-view.spec.tsx.snap
index b3927f64e9a..3e702f91d45 100644
--- a/web-console/src/views/tasks-view/__snapshots__/tasks-view.spec.tsx.snap
+++ b/web-console/src/views/tasks-view/__snapshots__/tasks-view.spec.tsx.snap
@@ -174,6 +174,7 @@ exports[`TasksView matches snapshot 1`] = `
         },
         {
           "Cell": [Function],
+          "Filter": [Function],
           "Header": "Status",
           "accessor": [Function],
           "id": "status",
diff --git a/web-console/src/views/tasks-view/tasks-view.tsx 
b/web-console/src/views/tasks-view/tasks-view.tsx
index f968b7d4925..7dc9b2ab5b0 100644
--- a/web-console/src/views/tasks-view/tasks-view.tsx
+++ b/web-console/src/views/tasks-view/tasks-view.tsx
@@ -38,7 +38,11 @@ import { AlertDialog, AsyncActionDialog, SpecDialog, 
TaskTableActionDialog } fro
 import type { QueryWithContext } from '../../druid-models';
 import { TASK_CANCELED_ERROR_MESSAGES, TASK_CANCELED_PREDICATE } from 
'../../druid-models';
 import type { Capabilities } from '../../helpers';
-import { SMALL_TABLE_PAGE_SIZE, SMALL_TABLE_PAGE_SIZE_OPTIONS } from 
'../../react-table';
+import {
+  SMALL_TABLE_PAGE_SIZE,
+  SMALL_TABLE_PAGE_SIZE_OPTIONS,
+  suggestibleFilterInput,
+} from '../../react-table';
 import { Api, AppToaster } from '../../singletons';
 import {
   formatDuration,
@@ -408,6 +412,14 @@ ORDER BY
             Header: 'Status',
             id: 'status',
             width: 110,
+            Filter: suggestibleFilterInput([
+              'CANCELED',
+              'FAILED',
+              'PENDING',
+              'RUNNING',
+              'SUCCESS',
+              'WAITING',
+            ]),
             accessor: row => ({
               status: row.status,
               created_time: row.created_time,
diff --git a/web-console/src/views/workbench-view/run-panel/run-panel.tsx 
b/web-console/src/views/workbench-view/run-panel/run-panel.tsx
index a3a7548856e..9ca4f300402 100644
--- a/web-console/src/views/workbench-view/run-panel/run-panel.tsx
+++ b/web-console/src/views/workbench-view/run-panel/run-panel.tsx
@@ -34,7 +34,7 @@ import type { JSX } from 'react';
 import React, { useCallback, useMemo, useState } from 'react';
 
 import {
-  ENABLE_DISABLE_OPTIONS_TEXT,
+  ENABLED_DISABLED_OPTIONS_TEXT,
   MenuBoolean,
   MenuCheckbox,
   TimezoneMenuItems,
@@ -414,7 +414,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                         useApproximateCountDistinct,
                       })
                     }
-                    optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                    optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                   />
                 )}
                 {show('approximate-top-n') && (
@@ -428,7 +428,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                         useApproximateTopN,
                       })
                     }
-                    optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                    optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                   />
                 )}
                 {show('join-algorithm') && (
@@ -465,7 +465,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                       onValueChange={failOnEmptyInsert =>
                         changeQueryContext({ ...queryContext, 
failOnEmptyInsert })
                       }
-                      optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                      optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                     />
                     <MenuBoolean
                       text="Wait until segments have loaded"
@@ -475,7 +475,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                       onValueChange={waitUntilSegmentsLoad =>
                         changeQueryContext({ ...queryContext, 
waitUntilSegmentsLoad })
                       }
-                      optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                      optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                     />
                     <MenuItem text="Max parse exceptions" 
label={String(maxParseExceptions)}>
                       {[0, 1, 5, 10, 1000, 10000, -1].map(v => (
@@ -511,7 +511,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                     onValueChange={finalizeAggregations =>
                       changeQueryContext({ ...queryContext, 
finalizeAggregations })
                     }
-                    optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                    optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                   />
                 )}
                 {show('group-by-enable-multi-value-unnesting') && (
@@ -524,7 +524,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                     onValueChange={groupByEnableMultiValueUnnesting =>
                       changeQueryContext({ ...queryContext, 
groupByEnableMultiValueUnnesting })
                     }
-                    optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                    optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                   />
                 )}
 
@@ -540,7 +540,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                         populateCache: useCache,
                       })
                     }
-                    optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                    optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                   />
                 )}
                 {show('limit-inline-results') && (
@@ -568,7 +568,7 @@ export const RunPanel = React.memo(function RunPanel(props: 
RunPanelProps) {
                         durableShuffleStorage,
                       })
                     }
-                    optionsText={ENABLE_DISABLE_OPTIONS_TEXT}
+                    optionsText={ENABLED_DISABLED_OPTIONS_TEXT}
                   />
                 )}
                 {show('select-destination') && (


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

Reply via email to