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 7e8003112ccdccef2997844449c9e42be7de8fc2
Author: Vadim Ogievetsky <[email protected]>
AuthorDate: Fri Nov 1 11:40:41 2024 -0700

    fixes
---
 .../segment-timeline/segment-bar-chart-render.scss |  7 +-
 .../segment-timeline/segment-bar-chart-render.tsx  | 77 ++++++++++++++--------
 .../segment-timeline/segment-timeline.tsx          | 56 ++++++++++++++--
 .../components/source-pane/source-pane.tsx         |  4 +-
 4 files changed, 105 insertions(+), 39 deletions(-)

diff --git 
a/web-console/src/components/segment-timeline/segment-bar-chart-render.scss 
b/web-console/src/components/segment-timeline/segment-bar-chart-render.scss
index 90a6bcbe8d6..c036c313cf3 100644
--- a/web-console/src/components/segment-timeline/segment-bar-chart-render.scss
+++ b/web-console/src/components/segment-timeline/segment-bar-chart-render.scss
@@ -29,8 +29,13 @@
       user-select: none;
     }
 
+    .hover-highlight {
+      fill: white;
+      fill-opacity: 0.1;
+    }
+
     .hovered-bar {
-      fill: transparent;
+      fill: none;
       stroke: #ffffff;
       stroke-width: 1.5px;
     }
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 026b6e7d0d8..edb3a90e655 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
@@ -37,6 +37,7 @@ import {
   formatInteger,
   formatNumber,
   groupBy,
+  month,
   prettyFormatIsoDate,
   TZ_UTC,
 } from '../../utils';
@@ -49,7 +50,7 @@ import { aggregateSegmentStats } from './common';
 
 import './segment-bar-chart-render.scss';
 
-const CHART_MARGIN: Margin = { top: 40, right: 10, bottom: 25, left: 80 };
+const CHART_MARGIN: Margin = { top: 40, right: 0, bottom: 25, left: 70 };
 const MIN_BAR_WIDTH = 2;
 const POSSIBLE_GRANULARITIES = [
   new Duration('PT15M'),
@@ -60,7 +61,6 @@ const POSSIBLE_GRANULARITIES = [
   new Duration('P1Y'),
 ];
 
-const EXTEND_DATE_RANGE_BY = 0;
 const EXTEND_X_SCALE_DOMAIN_BY = 10;
 
 function offsetDateRange(dateRange: NonNullDateRange, offset: number): 
NonNullDateRange {
@@ -124,22 +124,17 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
   const [dragging, setDragging] = useState<NonNullDateRange | undefined>();
   const [shiftOffset, setShiftOffset] = useState<number | undefined>();
   const [bubbleOpenOn, setBubbleOpenOn] = useState<
-    { x: number; y: number; text: string } | undefined
+    { start: Date; end: Date; x: number; y: number; text: string } | undefined
   >();
   const svgRef = useRef<SVGSVGElement | null>(null);
 
-  const expandedDateRange: NonNullDateRange = useMemo(() => {
-    const extend = (dateRange[1].valueOf() - dateRange[0].valueOf()) * 
EXTEND_DATE_RANGE_BY;
-    return [new Date(dateRange[0].valueOf() - extend), new 
Date(dateRange[1].valueOf() + extend)];
-  }, [dateRange]);
-
   const trimGranularity = useMemo(() => {
     return Duration.pickSmallestGranularityThatFits(
       POSSIBLE_GRANULARITIES,
-      expandedDateRange[1].valueOf() - expandedDateRange[0].valueOf(),
+      dateRange[1].valueOf() - dateRange[0].valueOf(),
       Math.floor(stage.width / MIN_BAR_WIDTH),
     ).toString();
-  }, [expandedDateRange, stage.width]);
+  }, [dateRange, stage.width]);
 
   const intervalBars = useMemo(() => {
     const trimDuration = new Duration(trimGranularity);
@@ -186,11 +181,11 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
   const innerStage = stage.applyMargin(CHART_MARGIN);
 
   const baseTimeScale = scaleUtc()
-    .domain(expandedDateRange)
+    .domain(dateRange)
     .range([EXTEND_X_SCALE_DOMAIN_BY, innerStage.width - 
EXTEND_X_SCALE_DOMAIN_BY]);
 
   const timeScale = shiftOffset
-    ? baseTimeScale.copy().domain(offsetDateRange(expandedDateRange, 
shiftOffset))
+    ? baseTimeScale.copy().domain(offsetDateRange(dateRange, shiftOffset))
     : baseTimeScale;
 
   const maxNormalizedStat = max(
@@ -233,10 +228,16 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
     const rect = svg.getBoundingClientRect();
     const x = e.clientX - rect.x - CHART_MARGIN.left;
     const y = e.clientY - rect.y - CHART_MARGIN.top;
+    const time = baseTimeScale.invert(x);
+    const action = y > innerStage.height || e.shiftKey ? 'shift' : 'select';
+    setBubbleOpenOn(undefined);
     setMouseDownAt({
-      time: baseTimeScale.invert(x),
-      action: y > innerStage.height ? 'shift' : 'select',
+      time,
+      action,
     });
+    if (action === 'select') {
+      setDragging([day.floor(time, TZ_UTC), day.ceil(time, TZ_UTC)]);
+    }
   }
 
   useGlobalEventListener('mousemove', (e: MouseEvent) => {
@@ -248,16 +249,19 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
 
     if (!mouseDownAt) {
       if (0 <= x && x <= innerStage.width && 0 <= y && y <= innerStage.height) 
{
+        const shifter =
+          new Duration(trimGranularity).getCanonicalLength() > 
day.canonicalLength * 25
+            ? month
+            : day;
         const time = baseTimeScale.invert(x);
-        const granStart = day.floor(time, TZ_UTC);
-        const granEnd = day.ceil(time, TZ_UTC);
+        const start = shifter.floor(time, TZ_UTC);
+        const end = shifter.ceil(time, TZ_UTC);
         setBubbleOpenOn({
-          x:
-            rect.x +
-            CHART_MARGIN.left +
-            baseTimeScale((granStart.valueOf() + granEnd.valueOf()) / 2),
+          start,
+          end,
+          x: rect.x + CHART_MARGIN.left + baseTimeScale((start.valueOf() + 
end.valueOf()) / 2),
           y: rect.y + CHART_MARGIN.top + innerStage.height + 10,
-          text: granStart.toISOString().slice(0, 10),
+          text: start.toISOString().slice(0, shifter === day ? 10 : 7),
         });
       } else {
         setBubbleOpenOn(undefined);
@@ -298,23 +302,30 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
     }
   });
 
+  function startEndToXWidth({ start, end }: { start: Date; end: Date }) {
+    const xStart = clamp(timeScale(start), 0, innerStage.width);
+    const xEnd = clamp(timeScale(end), 0, innerStage.width);
+
+    return {
+      x: xStart,
+      width: Math.max(xEnd - xStart - 1, 1),
+    };
+  }
+
   function segmentBarToRect(intervalBar: IntervalBar) {
-    const xStart = clamp(timeScale(intervalBar.start), 0, innerStage.width);
-    const xEnd = clamp(timeScale(intervalBar.end), 0, innerStage.width);
     const y0 = statScale(intervalBar.offset[shownIntervalStat]);
     const y = statScale(
       intervalBar.normalized[shownIntervalStat] + 
intervalBar.offset[shownIntervalStat],
     );
 
     return {
-      x: xStart,
+      ...startEndToXWidth(intervalBar),
       y: y,
-      width: Math.max(xEnd - xStart - 1, 1),
       height: Math.abs(y0 - y),
     };
   }
 
-  console.log('here');
+  console.log('Bar chart render');
 
   return (
     <div className="segment-bar-chart-render">
@@ -360,6 +371,14 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
               .tickFormat(e => formatTickRate(e.valueOf()))}
           />
           <g className="bar-group">
+            {bubbleOpenOn && (
+              <rect
+                className="hover-highlight"
+                {...startEndToXWidth(bubbleOpenOn)}
+                y={0}
+                height={innerStage.height}
+              />
+            )}
             {intervalBars.map((intervalBar, i) => {
               return (
                 <rect
@@ -397,13 +416,13 @@ export const SegmentBarChartRender = function 
SegmentBarChartRender(
             {!!shiftOffset && (
               <rect
                 className="shifter"
-                x={shiftOffset > 0 ? timeScale(expandedDateRange[1]) : 0}
+                x={shiftOffset > 0 ? timeScale(dateRange[1]) : 0}
                 y={0}
                 height={innerStage.height}
                 width={
                   shiftOffset > 0
-                    ? innerStage.width - timeScale(expandedDateRange[1])
-                    : timeScale(expandedDateRange[0])
+                    ? innerStage.width - timeScale(dateRange[1])
+                    : timeScale(dateRange[0])
                 }
               />
             )}
diff --git a/web-console/src/components/segment-timeline/segment-timeline.tsx 
b/web-console/src/components/segment-timeline/segment-timeline.tsx
index e113fdea571..5fbc2587ea2 100644
--- a/web-console/src/components/segment-timeline/segment-timeline.tsx
+++ b/web-console/src/components/segment-timeline/segment-timeline.tsx
@@ -33,12 +33,15 @@ import type React from 'react';
 import { useState } from 'react';
 
 import type { Capabilities } from '../../helpers';
+import { useQueryManager } from '../../hooks';
+import { Api } from '../../singletons';
 import {
   day,
   Duration,
   isNonNullRange,
   localToUtcDateRange,
   prettyFormatIsoDate,
+  queryDruidSql,
   TZ_UTC,
   utcToLocalDateRange,
 } from '../../utils';
@@ -79,11 +82,27 @@ export const SegmentTimeline = function 
SegmentTimeline(props: SegmentTimelinePr
   );
   const [showCustomDatePicker, setShowCustomDatePicker] = useState(false);
 
-  const datasources: string[] = ['wiki', 'kttm']; // ToDo
+  const [datasourcesState] = useQueryManager<Capabilities, string[]>({
+    initQuery: capabilities,
+    processQuery: async (capabilities, cancelToken) => {
+      if (capabilities.hasSql()) {
+        const tables = await queryDruidSql<{ TABLE_NAME: string }>(
+          {
+            query: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE 
TABLE_TYPE = 'TABLE'`,
+          },
+          cancelToken,
+        );
+
+        return tables.map(d => d.TABLE_NAME);
+      } else {
+        return (await Api.instance.get(`/druid/coordinator/v1/datasources`, { 
cancelToken })).data;
+      }
+    },
+  });
 
   const DatasourceSelect: React.FC = () => {
     const showAll = 'Show all';
-    const datasourcesWzAll = [showAll].concat(datasources);
+    const datasourcesWzAll = [showAll].concat(datasourcesState.data || []);
     return (
       <Select<string>
         items={datasourcesWzAll}
@@ -116,11 +135,7 @@ export const SegmentTimeline = function 
SegmentTimeline(props: SegmentTimelinePr
           }
         }}
       >
-        <Button
-          text={focusDatasource === null ? showAll : focusDatasource}
-          fill
-          rightIcon={IconNames.CARET_DOWN}
-        />
+        <Button text={focusDatasource ?? showAll} 
rightIcon={IconNames.CARET_DOWN} />
       </Select>
     );
   };
@@ -128,6 +143,32 @@ export const SegmentTimeline = function 
SegmentTimeline(props: SegmentTimelinePr
   return (
     <div className="segment-timeline">
       <div className="control-bar">
+        <ButtonGroup>
+          <Button
+            icon={IconNames.CARET_LEFT}
+            small
+            onClick={() => {
+              const d = Duration.fromRange(dateRange[0], dateRange[1], TZ_UTC);
+              setDateRange([d.shift(dateRange[0], TZ_UTC, -1), dateRange[0]]);
+            }}
+          />
+          <Button
+            icon={IconNames.ZOOM_OUT}
+            small
+            onClick={() => {
+              const d = Duration.fromRange(dateRange[0], dateRange[1], TZ_UTC);
+              setDateRange([d.shift(dateRange[0], TZ_UTC, -1), dateRange[1]]);
+            }}
+          />
+          <Button
+            icon={IconNames.CARET_RIGHT}
+            small
+            onClick={() => {
+              const d = Duration.fromRange(dateRange[0], dateRange[1], TZ_UTC);
+              setDateRange([dateRange[1], d.shift(dateRange[1], TZ_UTC, 1)]);
+            }}
+          />
+        </ButtonGroup>
         <ButtonGroup>
           {SHOWN_DURATION_OPTIONS.map((d, i) => (
             <Button
@@ -159,6 +200,7 @@ export const SegmentTimeline = function 
SegmentTimeline(props: SegmentTimelinePr
           >
             <Button
               icon={IconNames.CALENDAR}
+              small
               data-tooltip={`Select a custom date range\nCurrent range: 
${prettyFormatIsoDate(
                 dateRange[0],
               )} - ${prettyFormatIsoDate(dateRange[1])}`}
diff --git 
a/web-console/src/views/explore-view/components/source-pane/source-pane.tsx 
b/web-console/src/views/explore-view/components/source-pane/source-pane.tsx
index c97f736d9bc..5922152360b 100644
--- a/web-console/src/views/explore-view/components/source-pane/source-pane.tsx
+++ b/web-console/src/views/explore-view/components/source-pane/source-pane.tsx
@@ -53,8 +53,8 @@ export interface SourcePaneProps {
 export const SourcePane = React.memo(function SourcePane(props: 
SourcePaneProps) {
   const { selectedSource, onSelectTable, onShowSourceQuery, fill, minimal, 
disabled } = props;
 
-  const [tables] = useQueryManager<string, string[]>({
-    initQuery: '',
+  const [tables] = useQueryManager<null, string[]>({
+    initQuery: null,
     processQuery: async () => {
       const tables = await queryDruidSql<{ TABLE_NAME: string }>({
         query: `SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE 
TABLE_TYPE = 'TABLE'`,


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

Reply via email to