Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions packages/app/src/components/DBDeltaChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import {
Filter,
} from '@hyperdx/common-utils/dist/types';
import {
ActionIcon,
Box,
Code,
Container,
Divider,
Flex,
Pagination,
Text,
Tooltip,
} from '@mantine/core';
import { useElementSize } from '@mantine/hooks';
import { IconX } from '@tabler/icons-react';

import { isAggregateFunction } from '@/ChartUtils';
import { useQueriedChartConfig } from '@/hooks/useChartConfig';
Expand Down Expand Up @@ -52,6 +55,7 @@ export default function DBDeltaChart({
yMin: rawYMin,
yMax: rawYMax,
onAddFilter,
onClearSelection,
spanIdExpression,
legendPrefix,
}: {
Expand All @@ -62,6 +66,7 @@ export default function DBDeltaChart({
yMin?: number | null;
yMax?: number | null;
onAddFilter?: AddFilterFn;
onClearSelection?: () => void;
spanIdExpression?: string;
legendPrefix?: React.ReactNode;
}) {
Expand Down Expand Up @@ -516,6 +521,18 @@ export default function DBDeltaChart({
Background
</Text>
</Flex>
{onClearSelection && (
<Tooltip label="Clear selection">
<ActionIcon
variant="secondary"
size="xs"
aria-label="Clear heatmap selection"
onClick={onClearSelection}
>
<IconX size={14} />
</ActionIcon>
</Tooltip>
)}
</>
) : (
<>
Expand Down
25 changes: 24 additions & 1 deletion packages/app/src/components/DBHeatmapChart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useMemo, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import dynamic from 'next/dynamic';
import type { Plugin } from 'uplot';
import uPlot from 'uplot';
Expand Down Expand Up @@ -341,6 +341,7 @@ function HeatmapContainer({
config,
enabled = true,
onFilter,
clearSelectionVersion = 0,
title,
toolbarPrefix,
toolbarSuffix,
Expand All @@ -349,6 +350,7 @@ function HeatmapContainer({
config: HeatmapChartConfig;
enabled?: boolean;
onFilter?: (xMin: number, xMax: number, yMin: number, yMax: number) => void;
clearSelectionVersion?: number;
title?: React.ReactNode;
toolbarPrefix?: React.ReactNode[];
toolbarSuffix?: React.ReactNode[];
Expand Down Expand Up @@ -661,6 +663,7 @@ function HeatmapContainer({
key={JSON.stringify(config)}
data={[time, bucket, count]}
numberFormat={config.numberFormat}
clearSelectionVersion={clearSelectionVersion}
onFilter={
onFilter
? (xMin, xMax, yMin, yMax) => {
Expand Down Expand Up @@ -791,12 +794,14 @@ function Heatmap({
data,
numberFormat,
onFilter,
clearSelectionVersion = 0,
scaleType = 'linear',
palette,
}: {
data: Mode2DataArray;
numberFormat?: NumberFormat;
onFilter?: (xMin: number, xMax: number, yMin: number, yMax: number) => void;
clearSelectionVersion?: number;
scaleType?: HeatmapScaleType;
palette: string[];
}) {
Expand Down Expand Up @@ -834,9 +839,21 @@ function Heatmap({
// Gate tooltip display on actual mouse interaction. uPlot fires setCursor
// on init (before user hovers), which would show the tooltip on page load.
const mouseInsideRef = useRef(false);
const uplotRef = useRef<uPlot | null>(null);

const { ref, width, height } = useElementSize();

useEffect(() => {
setSelectingInfo(undefined);
if (uplotRef.current != null) {
// Clear persisted uPlot drag rectangle when parent resets selection.
uplotRef.current.setSelect(
{ left: 0, top: 0, width: 0, height: 0 },
false,
);
}
}, [clearSelectionVersion]);

const tickFormatter = useCallback(
(value: number) => {
// y-values are stored in log space for log scale; exponentiate back
Expand Down Expand Up @@ -1048,6 +1065,12 @@ function Heatmap({
// @ts-expect-error TODO: uPlot types are wrong for mode 2 data
data={[[], data]}
resetScales={true}
onCreate={chart => {
uplotRef.current = chart;
}}
onDelete={() => {
uplotRef.current = null;
}}
/>
{highlightedPoint != null && (
<>
Expand Down
11 changes: 9 additions & 2 deletions packages/app/src/components/Search/DBSearchHeatmapChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export function DBSearchHeatmapChart({
yMax: parseAsFloat,
});
const [container, setContainer] = useState<HTMLElement | null>(null);
const [clearSelectionVersion, setClearSelectionVersion] = useState(0);
const scaleType = (fields.scaleType ?? 'log') as HeatmapScaleType;
const setScaleType = useCallback(
(v: HeatmapScaleType) => {
Expand All @@ -79,17 +80,21 @@ export function DBSearchHeatmapChart({
const [settingsOpened, settingsHandlers] = useDisclosure(false);
const { colorScheme } = useMantineColorScheme();
const palette = colorScheme === 'light' ? lightPalette : darkPalette;
const clearSelection = useCallback(() => {
setFields({ xMin: null, xMax: null, yMin: null, yMax: null });
setClearSelectionVersion(version => version + 1);
}, [setFields]);

// After applying a filter, clear the heatmap selection so the delta chart
// resets instead of staying in comparison mode.
const handleAddFilterAndClearSelection = useCallback<
NonNullable<AddFilterFn>
>(
(property, value, action) => {
setFields({ xMin: null, xMax: null, yMin: null, yMax: null });
clearSelection();
onAddFilter?.(property, value, action);
},
[onAddFilter, setFields],
[clearSelection, onAddFilter],
);

return (
Expand Down Expand Up @@ -125,6 +130,7 @@ export function DBSearchHeatmapChart({
: undefined,
}}
enabled={isReady}
clearSelectionVersion={clearSelectionVersion}
scaleType={scaleType}
onFilter={(xMin, xMax, yMin, yMax) => {
setFields({ xMin, xMax, yMin, yMax });
Expand Down Expand Up @@ -180,6 +186,7 @@ export function DBSearchHeatmapChart({
onAddFilter={
onAddFilter ? handleAddFilterAndClearSelection : undefined
}
onClearSelection={clearSelection}
spanIdExpression={source.spanIdExpression}
legendPrefix={<ColorLegend colors={palette} />}
/>
Expand Down
Loading