From 4908045fc37744a5a12cb8792e70646b01784009 Mon Sep 17 00:00:00 2001 From: Andrej Ocenas Date: Thu, 25 May 2023 18:26:14 +0200 Subject: [PATCH] FlameGraph: Simplify the data needed for context menu and item focusing (#69006) --- .../components/FlameGraph/FlameGraph.test.tsx | 30 ++++--- .../components/FlameGraph/FlameGraph.tsx | 89 ++++++++----------- .../FlameGraph/FlameGraphContextMenu.tsx | 67 ++++---------- .../FlameGraph/FlameGraphMetadata.test.ts | 10 +-- .../FlameGraph/FlameGraphMetadata.tsx | 22 ++--- .../components/FlameGraph/rendering.test.ts | 31 +++++-- .../components/FlameGraph/rendering.ts | 2 + .../components/FlameGraphContainer.tsx | 45 +++++----- .../components/FlameGraphHeader.test.tsx | 7 +- .../components/FlameGraphHeader.tsx | 31 +++---- .../FlameGraphTopTableContainer.test.tsx | 14 +-- .../TopTable/FlameGraphTopTableContainer.tsx | 40 +-------- .../panel/flamegraph/components/types.ts | 10 ++- 13 files changed, 161 insertions(+), 237 deletions(-) diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.test.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.test.tsx index b90b4353919..49425085941 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.test.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.test.tsx @@ -1,7 +1,7 @@ import { fireEvent, render, screen } from '@testing-library/react'; import React, { useState } from 'react'; -import { CoreApp, createDataFrame } from '@grafana/data'; +import { createDataFrame } from '@grafana/data'; import { SelectedView } from '../types'; @@ -11,17 +11,20 @@ import { data } from './testData/dataNestedSet'; import 'jest-canvas-mock'; -jest.mock('react-use', () => ({ - useMeasure: () => { - const ref = React.useRef(); - return [ref, { width: 1600 }]; - }, -})); +jest.mock('react-use', () => { + const reactUse = jest.requireActual('react-use'); + return { + ...reactUse, + useMeasure: () => { + const ref = React.useRef(); + return [ref, { width: 1600 }]; + }, + }; +}); describe('FlameGraph', () => { const FlameGraphWithProps = () => { - const [topLevelIndex, setTopLevelIndex] = useState(0); - const [selectedBarIndex, setSelectedBarIndex] = useState(0); + const [focusedItemIndex, setFocusedItemIndex] = useState(); const [rangeMin, setRangeMin] = useState(0); const [rangeMax, setRangeMax] = useState(1); const [search] = useState(''); @@ -34,18 +37,17 @@ describe('FlameGraph', () => { return ( { + setFocusedItemIndex(itemIndex); + }} + focusedItemIndex={focusedItemIndex} textAlign={'left'} /> ); diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx index c2c9f5d4331..b4fc39e48f5 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx @@ -21,11 +21,10 @@ import uFuzzy from '@leeoniya/ufuzzy'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { useMeasure } from 'react-use'; -import { CoreApp } from '@grafana/data'; import { useStyles2 } from '@grafana/ui'; import { PIXELS_PER_LEVEL } from '../../constants'; -import { SelectedView, ContextMenuData, TextAlign } from '../types'; +import { SelectedView, ClickedItemData, TextAlign } from '../types'; import FlameGraphContextMenu from './FlameGraphContextMenu'; import FlameGraphMetadata from './FlameGraphMetadata'; @@ -35,36 +34,30 @@ import { getBarX, getRectDimensionsForLevel, renderRect } from './rendering'; type Props = { data: FlameGraphDataContainer; - app: CoreApp; levels: LevelItem[][]; - topLevelIndex: number; - selectedBarIndex: number; rangeMin: number; rangeMax: number; search: string; - setTopLevelIndex: (level: number) => void; - setSelectedBarIndex: (bar: number) => void; setRangeMin: (range: number) => void; setRangeMax: (range: number) => void; selectedView: SelectedView; style?: React.CSSProperties; + onItemFocused: (itemIndex: number) => void; + focusedItemIndex?: number; textAlign: TextAlign; }; const FlameGraph = ({ data, - app, levels, - topLevelIndex, - selectedBarIndex, rangeMin, rangeMax, search, - setTopLevelIndex, - setSelectedBarIndex, setRangeMin, setRangeMax, selectedView, + onItemFocused, + focusedItemIndex, textAlign, }: Props) => { const styles = useStyles2(getStyles); @@ -74,7 +67,8 @@ const FlameGraph = ({ const graphRef = useRef(null); const tooltipRef = useRef(null); const [tooltipItem, setTooltipItem] = useState(); - const [contextMenuData, setContextMenuData] = useState(); + + const [clickedItemData, setClickedItemData] = useState(); const [ufuzzy] = useState(() => { return new uFuzzy(); @@ -120,22 +114,12 @@ const FlameGraph = ({ // sometimes we collapse multiple bars into single rect. const dimensions = getRectDimensionsForLevel(data, level, levelIndex, totalTicks, rangeMin, pixelsPerTick); for (const rect of dimensions) { + const focusedLevel = focusedItemIndex ? data.getLevel(focusedItemIndex) : 0; // Render each rectangle based on the computed dimensions - renderRect( - ctx, - rect, - totalTicks, - rangeMin, - rangeMax, - search, - levelIndex, - topLevelIndex, - foundLabels, - textAlign - ); + renderRect(ctx, rect, totalTicks, rangeMin, rangeMax, search, levelIndex, focusedLevel, foundLabels, textAlign); } } - }, [data, levels, wrapperWidth, totalTicks, rangeMin, rangeMax, search, topLevelIndex, foundLabels, textAlign]); + }, [data, levels, wrapperWidth, totalTicks, rangeMin, rangeMax, search, focusedItemIndex, foundLabels, textAlign]); useEffect(() => { if (graphRef.current) { @@ -153,15 +137,22 @@ const FlameGraph = ({ // if clicking on a block in the canvas if (barIndex !== -1 && !isNaN(levelIndex) && !isNaN(barIndex)) { - setContextMenuData({ e, levelIndex, barIndex }); + const item = levels[levelIndex][barIndex]; + setClickedItemData({ + posY: e.clientY, + posX: e.clientX, + itemIndex: item.itemIndex, + label: data.getLabel(item.itemIndex), + start: item.start, + }); } else { // if clicking on the canvas but there is no block beneath the cursor - setContextMenuData(undefined); + setClickedItemData(undefined); } }; graphRef.current!.onmousemove = (e) => { - if (tooltipRef.current && contextMenuData === undefined) { + if (tooltipRef.current && clickedItemData === undefined) { setTooltipItem(undefined); const pixelsPerTick = graphRef.current!.clientWidth / totalTicks / (rangeMax - rangeMin); const { levelIndex, barIndex } = convertPixelCoordinatesToBarCoordinates( @@ -197,16 +188,13 @@ const FlameGraph = ({ levels, rangeMin, rangeMax, - topLevelIndex, totalTicks, wrapperWidth, - setTopLevelIndex, setRangeMin, setRangeMax, selectedView, - setSelectedBarIndex, - setContextMenuData, - contextMenuData, + setClickedItemData, + clickedItemData, ]); // hide context menu if outside the flame graph canvas is clicked @@ -214,38 +202,31 @@ const FlameGraph = ({ const handleOnClick = (e: MouseEvent) => { // eslint-disable-next-line @typescript-eslint/consistent-type-assertions if ((e.target as HTMLElement).parentElement?.id !== 'flameGraphCanvasContainer') { - setContextMenuData(undefined); + setClickedItemData(undefined); } }; window.addEventListener('click', handleOnClick); return () => window.removeEventListener('click', handleOnClick); - }, [setContextMenuData]); + }, [setClickedItemData]); return (
- +
- {contextMenuData && ( + {clickedItemData && ( { + setClickedItemData(undefined); + }} + onItemFocus={(itemIndex) => { + setRangeMin(clickedItemData.start / totalTicks); + setRangeMax((clickedItemData.start + data.getValue(clickedItemData.itemIndex)) / totalTicks); + onItemFocused(itemIndex); + }} /> )}
diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphContextMenu.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphContextMenu.tsx index 886803bcac2..7a5455b4f42 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphContextMenu.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphContextMenu.tsx @@ -2,78 +2,47 @@ import React from 'react'; import { MenuItem, ContextMenu } from '@grafana/ui'; -import { ContextMenuData } from '../types'; - -import { FlameGraphDataContainer, LevelItem } from './dataTransform'; +import { ClickedItemData } from '../types'; type Props = { - contextMenuData: ContextMenuData; - data: FlameGraphDataContainer; - levels: LevelItem[][]; - totalTicks: number; - graphRef: React.RefObject; - setContextMenuData: (event: ContextMenuData | undefined) => void; - setTopLevelIndex: (level: number) => void; - setSelectedBarIndex: (bar: number) => void; - setRangeMin: (range: number) => void; - setRangeMax: (range: number) => void; + itemData: ClickedItemData; + onMenuItemClick: () => void; + onItemFocus: (itemIndex: number) => void; }; -const FlameGraphContextMenu = ({ - contextMenuData, - graphRef, - totalTicks, - levels, - setContextMenuData, - setTopLevelIndex, - setSelectedBarIndex, - setRangeMin, - setRangeMax, - data, -}: Props) => { - const clickedItem = levels[contextMenuData.levelIndex][contextMenuData.barIndex]; - - const renderMenuItems = () => { +const FlameGraphContextMenu = ({ itemData, onMenuItemClick, onItemFocus }: Props) => { + function renderItems() { return ( <> { - if (graphRef.current && contextMenuData) { - setTopLevelIndex(contextMenuData.levelIndex); - setSelectedBarIndex(contextMenuData.barIndex); - setRangeMin(clickedItem.start / totalTicks); - setRangeMax((clickedItem.start + data.getValue(clickedItem.itemIndex)) / totalTicks); - setContextMenuData(undefined); - } + onItemFocus(itemData.itemIndex); + onMenuItemClick(); }} /> { - if (graphRef.current && contextMenuData) { - navigator.clipboard.writeText(data.getLabel(clickedItem.itemIndex)).then(() => { - setContextMenuData(undefined); - }); - } + navigator.clipboard.writeText(itemData.label).then(() => { + onMenuItemClick(); + }); }} /> ); - }; + } return (
- {contextMenuData.e.clientX && contextMenuData.e.clientY && ( - renderMenuItems()} - x={contextMenuData.e.clientX + 10} - y={contextMenuData.e.clientY} - focusOnOpen={false} - > - )} +
); }; diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.test.ts b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.test.ts index 482a7c4b637..757b2c39add 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.test.ts +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.test.ts @@ -22,7 +22,7 @@ describe('should get metadata correctly', () => { const container = new FlameGraphDataContainer( makeDataFrame({ value: [1_624_078_250], level: [1], label: ['1'], self: [0] }, 'bytes') ); - const metadata = getMetadata(container, { itemIndex: 0, start: 0 }, 8_624_078_250); + const metadata = getMetadata(container, 0, 8_624_078_250); expect(metadata).toEqual({ percentValue: 18.83, unitTitle: 'RAM', @@ -35,7 +35,7 @@ describe('should get metadata correctly', () => { const container = new FlameGraphDataContainer( makeDataFrame({ value: [1_624_078_250], level: [1], label: ['1'], self: [0] }, 'none') ); - const metadata = getMetadata(container, { itemIndex: 0, start: 0 }, 8_624_078_250); + const metadata = getMetadata(container, 0, 8_624_078_250); expect(metadata).toEqual({ percentValue: 18.83, unitTitle: 'Count', @@ -48,7 +48,7 @@ describe('should get metadata correctly', () => { const container = new FlameGraphDataContainer( makeDataFrame({ value: [1_624_078_250], level: [1], label: ['1'], self: [0] }) ); - const metadata = getMetadata(container, { itemIndex: 0, start: 0 }, 8_624_078_250); + const metadata = getMetadata(container, 0, 8_624_078_250); expect(metadata).toEqual({ percentValue: 18.83, unitTitle: 'Count', @@ -61,7 +61,7 @@ describe('should get metadata correctly', () => { const container = new FlameGraphDataContainer( makeDataFrame({ value: [1_624_078_250], level: [1], label: ['1'], self: [0] }, 'short') ); - const metadata = getMetadata(container, { itemIndex: 0, start: 0 }, 8_624_078_250); + const metadata = getMetadata(container, 0, 8_624_078_250); expect(metadata).toEqual({ percentValue: 18.83, unitTitle: 'Count', @@ -74,7 +74,7 @@ describe('should get metadata correctly', () => { const container = new FlameGraphDataContainer( makeDataFrame({ value: [1_624_078_250], level: [1], label: ['1'], self: [0] }, 'ns') ); - const metadata = getMetadata(container, { itemIndex: 0, start: 0 }, 8_624_078_250); + const metadata = getMetadata(container, 0, 8_624_078_250); expect(metadata).toEqual({ percentValue: 18.83, unitTitle: 'Time', diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.tsx index 6569db110ae..26658e187a2 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraphMetadata.tsx @@ -5,29 +5,23 @@ import { useStyles2 } from '@grafana/ui'; import { Metadata } from '../types'; -import { FlameGraphDataContainer, LevelItem } from './dataTransform'; +import { FlameGraphDataContainer } from './dataTransform'; type Props = { data: FlameGraphDataContainer; - levels: LevelItem[][]; - topLevelIndex: number; - selectedBarIndex: number; totalTicks: number; + focusedItemIndex?: number; }; -const FlameGraphMetadata = React.memo(({ data, levels, topLevelIndex, selectedBarIndex, totalTicks }: Props) => { +const FlameGraphMetadata = React.memo(({ data, focusedItemIndex, totalTicks }: Props) => { const styles = useStyles2(getStyles); - if (levels[topLevelIndex] && levels[topLevelIndex][selectedBarIndex]) { - const bar = levels[topLevelIndex][selectedBarIndex]; - const metadata = getMetadata(data, bar, totalTicks); - const metadataText = `${metadata?.unitValue} (${metadata?.percentValue}%) of ${metadata?.samples} total samples (${metadata?.unitTitle})`; - return <>{
{metadataText}
}; - } - return <>; + const metadata = getMetadata(data, focusedItemIndex || 0, totalTicks); + const metadataText = `${metadata?.unitValue} (${metadata?.percentValue}%) of ${metadata?.samples} total samples (${metadata?.unitTitle})`; + return <>{
{metadataText}
}; }); -export const getMetadata = (data: FlameGraphDataContainer, bar: LevelItem, totalTicks: number): Metadata => { - const displayValue = data.getValueDisplay(bar.itemIndex); +export const getMetadata = (data: FlameGraphDataContainer, itemIndex: number, totalTicks: number): Metadata => { + const displayValue = data.getValueDisplay(itemIndex); const percentValue = Math.round(10000 * (displayValue.numeric / totalTicks)) / 100; let unitValue = displayValue.text + displayValue.suffix; diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.test.ts b/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.test.ts index 3489e2f5378..2b4c09d36ff 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.test.ts +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.test.ts @@ -21,6 +21,7 @@ describe('getRectDimensionsForLevel', () => { { width: 999, height: 22, + itemIndex: 0, x: 0, y: 22, collapsed: false, @@ -42,9 +43,29 @@ describe('getRectDimensionsForLevel', () => { ); const result = getRectDimensionsForLevel(container, level, 2, 100, 0, 10); expect(result).toEqual([ - { width: 999, height: 22, x: 0, y: 44, collapsed: false, ticks: 100, label: '1', unitLabel: '100' }, - { width: 499, height: 22, x: 1000, y: 44, collapsed: false, ticks: 50, label: '2', unitLabel: '50' }, - { width: 499, height: 22, x: 1500, y: 44, collapsed: false, ticks: 50, label: '3', unitLabel: '50' }, + { width: 999, height: 22, x: 0, y: 44, collapsed: false, ticks: 100, label: '1', unitLabel: '100', itemIndex: 0 }, + { + width: 499, + height: 22, + x: 1000, + y: 44, + collapsed: false, + ticks: 50, + label: '2', + unitLabel: '50', + itemIndex: 1, + }, + { + width: 499, + height: 22, + x: 1500, + y: 44, + collapsed: false, + ticks: 50, + label: '3', + unitLabel: '50', + itemIndex: 2, + }, ]); }); @@ -59,8 +80,8 @@ describe('getRectDimensionsForLevel', () => { ); const result = getRectDimensionsForLevel(container, level, 2, 100, 0, 1); expect(result).toEqual([ - { width: 99, height: 22, x: 0, y: 44, collapsed: false, ticks: 100, label: '1', unitLabel: '100' }, - { width: 3, height: 22, x: 100, y: 44, collapsed: true, ticks: 3, label: '2', unitLabel: '2' }, + { width: 99, height: 22, x: 0, y: 44, collapsed: false, ticks: 100, label: '1', unitLabel: '100', itemIndex: 0 }, + { width: 3, height: 22, x: 100, y: 44, collapsed: true, ticks: 3, label: '2', unitLabel: '2', itemIndex: 1 }, ]); }); }); diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.ts b/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.ts index 62cbf2e6dd2..7a805409193 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.ts +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/rendering.ts @@ -21,6 +21,7 @@ type RectData = { ticks: number; label: string; unitLabel: string; + itemIndex: number; }; /** @@ -67,6 +68,7 @@ export function getRectDimensionsForLevel( ticks: curBarTicks, label: data.getLabel(item.itemIndex), unitLabel: unit, + itemIndex: item.itemIndex, }); } return coordinatesLevel; diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraphContainer.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraphContainer.tsx index 04538da8b23..97dbc0dc0f4 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraphContainer.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraphContainer.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { useMeasure } from 'react-use'; import { DataFrame, CoreApp, GrafanaTheme2 } from '@grafana/data'; +import { config, reportInteraction } from '@grafana/runtime'; import { useStyles2, useTheme2 } from '@grafana/ui'; import { MIN_WIDTH_TO_SHOW_BOTH_TOPTABLE_AND_FLAMEGRAPH } from '../constants'; @@ -19,8 +20,8 @@ type Props = { }; const FlameGraphContainer = (props: Props) => { - const [topLevelIndex, setTopLevelIndex] = useState(0); - const [selectedBarIndex, setSelectedBarIndex] = useState(0); + const [focusedItemIndex, setFocusedItemIndex] = useState(); + const [rangeMin, setRangeMin] = useState(0); const [rangeMax, setRangeMax] = useState(1); const [search, setSearch] = useState(''); @@ -56,8 +57,7 @@ const FlameGraphContainer = (props: Props) => { }, [selectedView, setSelectedView, containerWidth]); useEffect(() => { - setTopLevelIndex(0); - setSelectedBarIndex(0); + setFocusedItemIndex(undefined); setRangeMin(0); setRangeMax(1); }, [props.data]); @@ -68,15 +68,16 @@ const FlameGraphContainer = (props: Props) => {
{ + setRangeMin(0); + setRangeMax(1); + setFocusedItemIndex(undefined); + }} textAlign={textAlign} onTextAlignChange={setTextAlign} /> @@ -87,31 +88,35 @@ const FlameGraphContainer = (props: Props) => { data={dataContainer} app={props.app} totalLevels={levels.length} - selectedView={selectedView} - search={search} - setSearch={setSearch} - setTopLevelIndex={setTopLevelIndex} - setSelectedBarIndex={setSelectedBarIndex} - setRangeMin={setRangeMin} - setRangeMax={setRangeMax} + onSymbolClick={(symbol) => { + if (search === symbol) { + setSearch(''); + } else { + reportInteraction('grafana_flamegraph_table_item_selected', { + app: props.app, + grafana_version: config.buildInfo.version, + }); + setSearch(symbol); + // Reset selected level in flamegraph when selecting row in top table + setRangeMin(0); + setRangeMax(1); + } + }} /> )} {selectedView !== SelectedView.TopTable && ( setFocusedItemIndex(itemIndex)} + focusedItemIndex={focusedItemIndex} textAlign={textAlign} /> )} diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx index 2fd327ef0d4..a576a1dc063 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.test.tsx @@ -18,13 +18,12 @@ describe('FlameGraphHeader', () => { app={CoreApp.Explore} search={search} setSearch={setSearch} - setTopLevelIndex={jest.fn()} - setSelectedBarIndex={jest.fn()} - setRangeMin={jest.fn()} - setRangeMax={jest.fn()} selectedView={selectedView} setSelectedView={setSelectedView} containerWidth={1600} + onReset={() => { + setSearch(''); + }} onTextAlignChange={jest.fn()} textAlign={'left'} /> diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.tsx index ad2fc2dc23b..3dd0d068260 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraphHeader.tsx @@ -15,14 +15,11 @@ import { SelectedView, TextAlign } from './types'; type Props = { app: CoreApp; search: string; - setTopLevelIndex: (level: number) => void; - setSelectedBarIndex: (bar: number) => void; - setRangeMin: (range: number) => void; - setRangeMax: (range: number) => void; setSearch: (search: string) => void; selectedView: SelectedView; setSelectedView: (view: SelectedView) => void; containerWidth: number; + onReset: () => void; textAlign: TextAlign; onTextAlignChange: (align: TextAlign) => void; }; @@ -30,14 +27,11 @@ type Props = { const FlameGraphHeader = ({ app, search, - setTopLevelIndex, - setSelectedBarIndex, - setRangeMin, - setRangeMax, setSearch, selectedView, setSelectedView, containerWidth, + onReset, textAlign, onTextAlignChange, }: Props) => { @@ -50,16 +44,6 @@ const FlameGraphHeader = ({ }); } - const onResetView = () => { - setTopLevelIndex(0); - setSelectedBarIndex(0); - setRangeMin(0); - setRangeMax(1); - // We could set only one and wait them to sync but there is no need to debounce this. - setSearch(''); - setLocalSearch(''); - }; - const [localSearch, setLocalSearch] = useSearchInput(search, setSearch); return ( @@ -75,7 +59,16 @@ const FlameGraphHeader = ({ width={44} />
- diff --git a/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.test.tsx b/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.test.tsx index b222b1964c9..c8ce892503b 100644 --- a/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.test.tsx +++ b/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.test.tsx @@ -1,19 +1,15 @@ import { render, screen } from '@testing-library/react'; -import React, { useState } from 'react'; +import React from 'react'; import { CoreApp, createDataFrame } from '@grafana/data'; import { FlameGraphDataContainer, nestedSetToLevels } from '../FlameGraph/dataTransform'; import { data } from '../FlameGraph/testData/dataNestedSet'; -import { SelectedView } from '../types'; import FlameGraphTopTableContainer from './FlameGraphTopTableContainer'; describe('FlameGraphTopTableContainer', () => { const FlameGraphTopTableContainerWithProps = () => { - const [search, setSearch] = useState(''); - const [selectedView, _] = useState(SelectedView.Both); - const flameGraphData = createDataFrame(data); const container = new FlameGraphDataContainer(flameGraphData); const levels = nestedSetToLevels(container); @@ -23,13 +19,7 @@ describe('FlameGraphTopTableContainer', () => { data={container} app={CoreApp.Explore} totalLevels={levels.length} - selectedView={selectedView} - search={search} - setSearch={setSearch} - setTopLevelIndex={jest.fn()} - setSelectedBarIndex={jest.fn()} - setRangeMin={jest.fn()} - setRangeMax={jest.fn()} + onSymbolClick={jest.fn()} /> ); }; diff --git a/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx b/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx index 4724356e0bd..6b8bf1e354c 100644 --- a/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx +++ b/public/app/plugins/panel/flamegraph/components/TopTable/FlameGraphTopTableContainer.tsx @@ -8,52 +8,18 @@ import { Table, TableSortByFieldState, useStyles2 } from '@grafana/ui'; import { PIXELS_PER_LEVEL, TOP_TABLE_COLUMN_WIDTH } from '../../constants'; import { FlameGraphDataContainer } from '../FlameGraph/dataTransform'; -import { SelectedView, TableData } from '../types'; +import { TableData } from '../types'; type Props = { data: FlameGraphDataContainer; app: CoreApp; totalLevels: number; - selectedView: SelectedView; - search: string; - setSearch: (search: string) => void; - setTopLevelIndex: (level: number) => void; - setSelectedBarIndex: (bar: number) => void; - setRangeMin: (range: number) => void; - setRangeMax: (range: number) => void; + onSymbolClick: (symbol: string) => void; }; -const FlameGraphTopTableContainer = ({ - data, - app, - totalLevels, - selectedView, - search, - setSearch, - setTopLevelIndex, - setSelectedBarIndex, - setRangeMin, - setRangeMax, -}: Props) => { +const FlameGraphTopTableContainer = ({ data, app, totalLevels, onSymbolClick }: Props) => { const styles = useStyles2(getStyles); - const onSymbolClick = (symbol: string) => { - if (search === symbol) { - setSearch(''); - } else { - reportInteraction('grafana_flamegraph_table_item_selected', { - app, - grafana_version: config.buildInfo.version, - }); - setSearch(symbol); - // Reset selected level in flamegraph when selecting row in top table - setTopLevelIndex(0); - setSelectedBarIndex(0); - setRangeMin(0); - setRangeMax(1); - } - }; - const [sort, setSort] = useState([{ displayName: 'Self', desc: true }]); return ( diff --git a/public/app/plugins/panel/flamegraph/components/types.ts b/public/app/plugins/panel/flamegraph/components/types.ts index b13c0bc5c83..f36772c1fce 100644 --- a/public/app/plugins/panel/flamegraph/components/types.ts +++ b/public/app/plugins/panel/flamegraph/components/types.ts @@ -1,7 +1,9 @@ -export type ContextMenuData = { - e: MouseEvent; - levelIndex: number; - barIndex: number; +export type ClickedItemData = { + posX: number; + posY: number; + itemIndex: number; + label: string; + start: number; }; export type Metadata = {