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

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

commit 91af28e729930a8d86b58df3c4732a281a5cd509
Author: Vadim Ogievetsky <[email protected]>
AuthorDate: Mon Nov 4 15:55:57 2024 -0800

    more fixes
---
 .../src/components/segment-timeline/common.ts      |  18 +++
 .../segment-timeline/segment-timeline.scss         |   4 +-
 .../segment-timeline/segment-timeline.tsx          | 129 +++++++++------------
 3 files changed, 78 insertions(+), 73 deletions(-)

diff --git a/web-console/src/components/segment-timeline/common.ts 
b/web-console/src/components/segment-timeline/common.ts
index efd2a0b1b45..7371aada27f 100644
--- a/web-console/src/components/segment-timeline/common.ts
+++ b/web-console/src/components/segment-timeline/common.ts
@@ -22,6 +22,24 @@ import type { Duration } from '../../utils';
 
 export type IntervalStat = 'segments' | 'size' | 'rows';
 
+export const INTERVAL_STATS: IntervalStat[] = ['segments', 'size', 'rows'];
+
+export function getIntervalStatTitle(intervalStat: IntervalStat): string {
+  switch (intervalStat) {
+    case 'segments':
+      return 'Num. segments';
+
+    case 'size':
+      return 'Size';
+
+    case 'rows':
+      return 'Rows';
+
+    default:
+      return intervalStat;
+  }
+}
+
 export function aggregateSegmentStats(
   xs: readonly Record<IntervalStat, number>[],
 ): Record<IntervalStat, number> {
diff --git a/web-console/src/components/segment-timeline/segment-timeline.scss 
b/web-console/src/components/segment-timeline/segment-timeline.scss
index 6582394869e..b1844016041 100644
--- a/web-console/src/components/segment-timeline/segment-timeline.scss
+++ b/web-console/src/components/segment-timeline/segment-timeline.scss
@@ -21,7 +21,7 @@
 .segment-timeline {
   .control-bar {
     @include card-like;
-    height: 40px;
+    height: 34px;
     display: flex;
     align-items: start;
     padding: 5px;
@@ -37,7 +37,7 @@
 
   .chart-container {
     position: absolute;
-    top: 40px;
+    top: 34px;
     width: 100%;
     bottom: 0;
     overflow: hidden;
diff --git a/web-console/src/components/segment-timeline/segment-timeline.tsx 
b/web-console/src/components/segment-timeline/segment-timeline.tsx
index 92761368d53..81b26c04d8b 100644
--- a/web-console/src/components/segment-timeline/segment-timeline.tsx
+++ b/web-console/src/components/segment-timeline/segment-timeline.tsx
@@ -16,25 +16,17 @@
  * limitations under the License.
  */
 
-import {
-  Button,
-  ButtonGroup,
-  FormGroup,
-  MenuItem,
-  Popover,
-  ResizeSensor,
-  SegmentedControl,
-} from '@blueprintjs/core';
+import { Button, ButtonGroup, Menu, MenuItem, Popover, ResizeSensor } from 
'@blueprintjs/core';
 import type { NonNullDateRange } from '@blueprintjs/datetime';
 import { DateRangePicker3 } from '@blueprintjs/datetime2';
 import { IconNames } from '@blueprintjs/icons';
 import { Select } from '@blueprintjs/select';
-import type React from 'react';
 import { useState } from 'react';
 
 import type { Capabilities } from '../../helpers';
 import { useQueryManager } from '../../hooks';
 import {
+  checkedCircleIcon,
   day,
   Duration,
   getApiArray,
@@ -48,6 +40,7 @@ import {
 import { Stage } from '../../utils/stage';
 
 import type { IntervalStat } from './common';
+import { getIntervalStatTitle, INTERVAL_STATS } from './common';
 import { SegmentBarChart } from './segment-bar-chart';
 
 import './segment-timeline.scss';
@@ -102,45 +95,6 @@ export const SegmentTimeline = function 
SegmentTimeline(props: SegmentTimelinePr
     },
   });
 
-  const DatasourceSelect: React.FC = () => {
-    const datasourcesWzAll = [SHOW_ALL].concat(datasourcesState.data || []);
-    return (
-      <Select<string>
-        items={datasourcesWzAll}
-        onItemSelect={(selectedItem: string) => {
-          setFocusDatasource(selectedItem === SHOW_ALL ? undefined : 
selectedItem);
-        }}
-        itemRenderer={(val, { handleClick, handleFocus, modifiers }) => {
-          if (!modifiers.matchesPredicate) return null;
-          return (
-            <MenuItem
-              key={val}
-              disabled={modifiers.disabled}
-              active={modifiers.active}
-              onClick={handleClick}
-              onFocus={handleFocus}
-              roleStructure="listoption"
-              text={val}
-            />
-          );
-        }}
-        noResults={<MenuItem disabled text="No results" 
roleStructure="listoption" />}
-        itemPredicate={(query, val, _index, exactMatch) => {
-          const normalizedTitle = val.toLowerCase();
-          const normalizedQuery = query.toLowerCase();
-
-          if (exactMatch) {
-            return normalizedTitle === normalizedQuery;
-          } else {
-            return normalizedTitle.includes(normalizedQuery);
-          }
-        }}
-      >
-        <Button text={focusDatasource ?? SHOW_ALL} 
rightIcon={IconNames.CARET_DOWN} />
-      </Select>
-    );
-  };
-
   return (
     <div className="segment-timeline">
       <div className="control-bar">
@@ -208,30 +162,63 @@ export const SegmentTimeline = function 
SegmentTimeline(props: SegmentTimelinePr
             />
           </Popover>
         </ButtonGroup>
-        <FormGroup label="Show" inline>
-          <SegmentedControl
-            value={activeSegmentStat}
-            onValueChange={s => setActiveSegmentStat(s as IntervalStat)}
+        <Popover
+          content={
+            <Menu>
+              {INTERVAL_STATS.map(stat => (
+                <MenuItem
+                  key={stat}
+                  icon={checkedCircleIcon(stat === activeSegmentStat)}
+                  text={getIntervalStatTitle(stat)}
+                  onClick={() => setActiveSegmentStat(stat)}
+                />
+              ))}
+            </Menu>
+          }
+        >
+          <Button
+            text={`Stat: ${getIntervalStatTitle(activeSegmentStat)}`}
+            small
+            rightIcon={IconNames.CARET_DOWN}
+          />
+        </Popover>
+        <Select<string>
+          items={[SHOW_ALL].concat(datasourcesState.data || [])}
+          onItemSelect={(selectedItem: string) => {
+            setFocusDatasource(selectedItem === SHOW_ALL ? undefined : 
selectedItem);
+          }}
+          itemRenderer={(val, { handleClick, handleFocus, modifiers }) => {
+            if (!modifiers.matchesPredicate) return null;
+            return (
+              <MenuItem
+                key={val}
+                disabled={modifiers.disabled}
+                active={modifiers.active}
+                onClick={handleClick}
+                onFocus={handleFocus}
+                roleStructure="listoption"
+                text={val}
+              />
+            );
+          }}
+          noResults={<MenuItem disabled text="No results" 
roleStructure="listoption" />}
+          itemPredicate={(query, val, _index, exactMatch) => {
+            const normalizedTitle = val.toLowerCase();
+            const normalizedQuery = query.toLowerCase();
+
+            if (exactMatch) {
+              return normalizedTitle === normalizedQuery;
+            } else {
+              return normalizedTitle.includes(normalizedQuery);
+            }
+          }}
+        >
+          <Button
+            text={`Datasource: ${focusDatasource ?? 'all'}`}
             small
-            options={[
-              {
-                label: 'Size',
-                value: 'size',
-              },
-              {
-                label: 'Num. rows',
-                value: 'rows',
-              },
-              {
-                label: 'Num. segments',
-                value: 'segments',
-              },
-            ]}
+            rightIcon={IconNames.CARET_DOWN}
           />
-        </FormGroup>
-        <FormGroup label="Datasource" inline>
-          <DatasourceSelect />
-        </FormGroup>
+        </Select>
       </div>
       <ResizeSensor
         onResize={(entries: ResizeObserverEntry[]) => {


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

Reply via email to