@parca/profile 0.19.52 → 0.19.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/MatchersInput/index.js +3 -3
  3. package/dist/MetricsGraph/MetricsContextMenu/index.js +2 -2
  4. package/dist/MetricsGraph/MetricsTooltip/index.js +2 -2
  5. package/dist/MetricsGraph/index.js +2 -2
  6. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  7. package/dist/ProfileExplorer/ProfileExplorerCompare.js +2 -2
  8. package/dist/ProfileExplorer/index.js +3 -3
  9. package/dist/ProfileFlameGraph/index.js +2 -2
  10. package/dist/ProfileMetricsGraph/index.js +3 -3
  11. package/dist/ProfileSelector/QueryControls.js +6 -6
  12. package/dist/ProfileTypeSelector/index.js +2 -2
  13. package/dist/ProfileView/components/DashboardItems/index.d.ts +0 -2
  14. package/dist/ProfileView/components/DashboardItems/index.d.ts.map +1 -1
  15. package/dist/ProfileView/components/DiffLegend.js +2 -2
  16. package/dist/ProfileView/components/GroupByLabelsDropdown/index.js +3 -3
  17. package/dist/ProfileView/components/ProfileFilters/index.js +6 -6
  18. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.d.ts.map +1 -1
  19. package/dist/ProfileView/components/ProfileFilters/useProfileFilters.js +10 -4
  20. package/dist/ProfileView/components/Toolbars/index.js +2 -2
  21. package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts +2 -0
  22. package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts.map +1 -0
  23. package/dist/ProfileView/hooks/{useResetStateOnNewSearch.js → useResetFlameGraphState.js} +1 -1
  24. package/dist/ProfileView/hooks/useVisualizationState.d.ts +0 -2
  25. package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
  26. package/dist/ProfileView/hooks/useVisualizationState.js +5 -5
  27. package/dist/ProfileView/index.d.ts.map +1 -1
  28. package/dist/ProfileView/index.js +1 -3
  29. package/dist/ProfileViewWithData.js +1 -1
  30. package/dist/SimpleMatchers/index.js +3 -3
  31. package/dist/ViewMatchers/index.js +2 -2
  32. package/package.json +4 -4
  33. package/src/MatchersInput/index.tsx +3 -3
  34. package/src/MetricsGraph/MetricsContextMenu/index.tsx +2 -2
  35. package/src/MetricsGraph/MetricsTooltip/index.tsx +2 -2
  36. package/src/MetricsGraph/index.tsx +2 -2
  37. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +11 -5
  38. package/src/ProfileExplorer/index.tsx +3 -3
  39. package/src/ProfileFlameGraph/index.tsx +2 -2
  40. package/src/ProfileMetricsGraph/index.tsx +4 -4
  41. package/src/ProfileSelector/QueryControls.tsx +13 -13
  42. package/src/ProfileTypeSelector/index.tsx +2 -2
  43. package/src/ProfileView/components/DashboardItems/index.tsx +0 -2
  44. package/src/ProfileView/components/DiffLegend.tsx +2 -2
  45. package/src/ProfileView/components/GroupByLabelsDropdown/index.tsx +4 -4
  46. package/src/ProfileView/components/ProfileFilters/index.tsx +10 -10
  47. package/src/ProfileView/components/ProfileFilters/useProfileFilters.ts +10 -4
  48. package/src/ProfileView/components/Toolbars/index.tsx +2 -2
  49. package/src/ProfileView/hooks/{useResetStateOnNewSearch.ts → useResetFlameGraphState.ts} +1 -1
  50. package/src/ProfileView/hooks/useVisualizationState.ts +6 -7
  51. package/src/ProfileView/index.tsx +0 -4
  52. package/src/ProfileViewWithData.tsx +1 -1
  53. package/src/SimpleMatchers/index.tsx +9 -9
  54. package/src/ViewMatchers/index.tsx +2 -2
  55. package/dist/ProfileView/hooks/useResetStateOnNewSearch.d.ts +0 -2
  56. package/dist/ProfileView/hooks/useResetStateOnNewSearch.d.ts.map +0 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,16 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.19.54](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.53...@parca/profile@0.19.54) (2025-09-16)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.19.53](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.52...@parca/profile@0.19.53) (2025-09-15)
11
+
12
+ ## 0.24.2 (2025-09-10)
13
+
14
+ **Note:** Version bump only for package @parca/profile
15
+
6
16
  ## 0.19.52 (2025-09-15)
7
17
 
8
18
  ## 0.24.2 (2025-09-10)
@@ -17,7 +17,7 @@ import cx from 'classnames';
17
17
  import TextareaAutosize from 'react-textarea-autosize';
18
18
  import { useGrpcMetadata } from '@parca/components';
19
19
  import { Query } from '@parca/parser';
20
- import { testId } from '@parca/test-utils';
20
+ import { TEST_IDS, testId } from '@parca/test-utils';
21
21
  import { millisToProtoTimestamp, sanitizeLabelValue } from '@parca/utilities';
22
22
  import { LabelsProvider, useLabels } from '../contexts/MatchersInputLabelsContext';
23
23
  import useGrpcQuery from '../useGrpcQuery';
@@ -194,9 +194,9 @@ const MatchersInput = ({ setMatchersString, runQuery, currentQuery, }) => {
194
194
  setFocusedInput(false);
195
195
  };
196
196
  const profileSelected = currentQuery.profileName() === '';
197
- return (_jsxs("div", { className: "w-full min-w-[300px] flex-1 font-mono relative", ...testId('MATCHERS_INPUT_CONTAINER'), children: [_jsx(TextareaAutosize, { ref: inputRef, className: cx('block h-[38px] w-full flex-1 rounded-md border bg-white px-2 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900', profileSelected && 'cursor-not-allowed'), placeholder: profileSelected
197
+ return (_jsxs("div", { className: "w-full min-w-[300px] flex-1 font-mono relative", ...testId(TEST_IDS.MATCHERS_INPUT_CONTAINER), children: [_jsx(TextareaAutosize, { ref: inputRef, className: cx('block h-[38px] w-full flex-1 rounded-md border bg-white px-2 py-2 text-sm shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900', profileSelected && 'cursor-not-allowed'), placeholder: profileSelected
198
198
  ? 'Select a profile first to enter a filter...'
199
- : 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, ...testId('MATCHERS_TEXTAREA'), onFocus: focus, disabled: profileSelected, title: profileSelected
199
+ : 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, ...testId(TEST_IDS.MATCHERS_TEXTAREA), onFocus: focus, disabled: profileSelected, title: profileSelected
200
200
  ? 'Select a profile first to enter a filter...'
201
201
  : 'filter profiles... eg. node="test"', id: "matchers-input" }), _jsx(SuggestionsList, { isLabelNamesLoading: isLabelNamesLoading, suggestions: suggestionSections, applySuggestion: applySuggestion, inputRef: inputRef.current, runQuery: runQuery, focusedInput: focusedInput, isLabelValuesLoading: isLabelValuesLoading && lastCompleted.type === 'literal', shouldTrimPrefix: shouldHandlePrefixes })] }));
202
202
  };
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  import { Icon } from '@iconify/react';
15
15
  import { Item, Menu, Submenu } from 'react-contexify';
16
16
  import { useParcaContext } from '@parca/components';
17
- import { testId } from '@parca/test-utils';
17
+ import { TEST_IDS, testId } from '@parca/test-utils';
18
18
  const MetricsContextMenu = ({ menuId, closestPoint, series, trackVisibility, menuItems, }) => {
19
19
  const { isDarkMode } = useParcaContext();
20
20
  const renderMenuItem = (item) => {
@@ -32,6 +32,6 @@ const MetricsContextMenu = ({ menuId, closestPoint, series, trackVisibility, men
32
32
  return (_jsx(Item, { id: menuItem.id, onClick: () => menuItem.onClick(closestPoint, series), disabled: menuItem.disabled?.(closestPoint, series) ?? false, children: _jsxs("div", { className: "flex w-full items-center gap-2", children: [menuItem.icon != null && menuItem.icon !== '' && _jsx(Icon, { icon: menuItem.icon }), _jsx("div", { children: menuItem.label })] }) }, menuItem.id));
33
33
  }
34
34
  };
35
- return (_jsx(Menu, { id: menuId, onVisibilityChange: trackVisibility, theme: isDarkMode ? 'dark' : '', ...testId('METRICS_GRAPH_CONTEXT_MENU'), children: menuItems.map(renderMenuItem) }));
35
+ return (_jsx(Menu, { id: menuId, onVisibilityChange: trackVisibility, theme: isDarkMode ? 'dark' : '', ...testId(TEST_IDS.METRICS_GRAPH_CONTEXT_MENU), children: menuItems.map(renderMenuItem) }));
36
36
  };
37
37
  export default MetricsContextMenu;
@@ -13,7 +13,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
13
13
  // limitations under the License.
14
14
  import { useEffect, useMemo, useState } from 'react';
15
15
  import { usePopper } from 'react-popper';
16
- import { testId } from '@parca/test-utils';
16
+ import { TEST_IDS, testId } from '@parca/test-utils';
17
17
  const virtualElement = {
18
18
  getBoundingClientRect: () => {
19
19
  const emptyRect = {
@@ -87,6 +87,6 @@ const MetricsTooltip = ({ x, y, contextElement, content }) => {
87
87
  if (content == null) {
88
88
  return _jsx(_Fragment, {});
89
89
  }
90
- return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, ...testId('METRICS_GRAPH_TOOLTIP'), className: "z-50", children: _jsx("div", { className: "flex max-w-lg", children: _jsx("div", { className: "m-auto", children: _jsx("div", { className: "border border-gray-300 bg-gray-50 dark:border-gray-500 dark:bg-gray-900 rounded-lg shadow-lg px-3 py-2", children: content }) }) }) }));
90
+ return (_jsx("div", { ref: setPopperElement, style: styles.popper, ...attributes.popper, ...testId(TEST_IDS.METRICS_GRAPH_TOOLTIP), className: "z-50", children: _jsx("div", { className: "flex max-w-lg", children: _jsx("div", { className: "m-auto", children: _jsx("div", { className: "border border-gray-300 bg-gray-50 dark:border-gray-500 dark:bg-gray-900 rounded-lg shadow-lg px-3 py-2", children: content }) }) }) }));
91
91
  };
92
92
  export default MetricsTooltip;
@@ -17,7 +17,7 @@ import { pointer } from 'd3-selection';
17
17
  import throttle from 'lodash.throttle';
18
18
  import { useContextMenu } from 'react-contexify';
19
19
  import { DateTimeRange, useParcaContext } from '@parca/components';
20
- import { testId } from '@parca/test-utils';
20
+ import { TEST_IDS, testId } from '@parca/test-utils';
21
21
  import { formatDate, formatForTimespan, getPrecision, valueFormatter } from '@parca/utilities';
22
22
  import MetricsCircle from '../MetricsCircle';
23
23
  import MetricsSeries from '../MetricsSeries';
@@ -26,7 +26,7 @@ import MetricsInfoPanel from './MetricsInfoPanel';
26
26
  import MetricsTooltip from './MetricsTooltip';
27
27
  const MetricsGraph = ({ data, from, to, onSampleClick, setTimeRange, yAxisLabel, yAxisUnit, width = 0, height = 0, margin = 0, selectedPoint, contextMenuItems, renderTooltipContent, }) => {
28
28
  const [isInfoPanelOpen, setIsInfoPanelOpen] = useState(false);
29
- return (_jsxs("div", { className: "relative", ...testId('METRICS_GRAPH'), onClick: () => isInfoPanelOpen && setIsInfoPanelOpen(false), children: [_jsx("div", { className: "absolute right-0 top-0", children: _jsx(MetricsInfoPanel, { isInfoPanelOpen: isInfoPanelOpen, onInfoIconClick: () => setIsInfoPanelOpen(true) }) }), _jsx(RawMetricsGraph, { data: data, from: from, to: to, onSampleClick: onSampleClick, setTimeRange: setTimeRange, yAxisLabel: yAxisLabel, yAxisUnit: yAxisUnit, width: width, height: height, margin: margin, selectedPoint: selectedPoint, contextMenuItems: contextMenuItems, renderTooltipContent: renderTooltipContent })] }));
29
+ return (_jsxs("div", { className: "relative", ...testId(TEST_IDS.METRICS_GRAPH), onClick: () => isInfoPanelOpen && setIsInfoPanelOpen(false), children: [_jsx("div", { className: "absolute right-0 top-0", children: _jsx(MetricsInfoPanel, { isInfoPanelOpen: isInfoPanelOpen, onInfoIconClick: () => setIsInfoPanelOpen(true) }) }), _jsx(RawMetricsGraph, { data: data, from: from, to: to, onSampleClick: onSampleClick, setTimeRange: setTimeRange, yAxisLabel: yAxisLabel, yAxisUnit: yAxisUnit, width: width, height: height, margin: margin, selectedPoint: selectedPoint, contextMenuItems: contextMenuItems, renderTooltipContent: renderTooltipContent })] }));
30
30
  };
31
31
  export default MetricsGraph;
32
32
  export const parseValue = (value) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAoB,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AAC5E,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAEhC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,GAAI,4IAY7B,2BAA2B,KAAG,GAAG,CAAC,OAyEpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAoB,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AAC5E,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAEhC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,GAAI,4IAY7B,2BAA2B,KAAG,GAAG,CAAC,OA+EpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
14
  import { useState } from 'react';
15
15
  import { useURLState } from '@parca/components';
16
16
  import { Query } from '@parca/parser';
17
- import { testId } from '@parca/test-utils';
17
+ import { TEST_IDS, testId } from '@parca/test-utils';
18
18
  import { ProfileDiffSource, ProfileViewWithData } from '..';
19
19
  import ProfileSelector from '../ProfileSelector';
20
20
  const ProfileExplorerCompare = ({ queryClient, queryA, queryB, profileA, profileB, selectQueryA, selectQueryB, selectProfileA, selectProfileB, closeProfile, navigateTo, }) => {
@@ -26,6 +26,6 @@ const ProfileExplorerCompare = ({ queryClient, queryA, queryB, profileA, profile
26
26
  closeProfile('B');
27
27
  };
28
28
  const [compareAbsolute] = useURLState('compare_absolute');
29
- return (_jsxs("div", { ...testId('COMPARE_CONTAINER'), children: [_jsxs("div", { className: "flex justify-between gap-2 relative mb-2", children: [_jsx("div", { className: "flex-column flex-1 p-2 shadow-md rounded-md", ...testId('COMPARE_SIDE_A'), children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryA, profileSelection: profileA, selectProfile: selectProfileA, selectQuery: selectQueryA, closeProfile: closeProfileA, enforcedProfileName: '', comparing: true, navigateTo: navigateTo, suffix: "_a", showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setShowMetricsGraph }) }), _jsx("div", { className: "flex-column flex-1 p-2 shadow-md rounded-md", ...testId('COMPARE_SIDE_B'), children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryB, profileSelection: profileB, selectProfile: selectProfileB, selectQuery: selectQueryB, closeProfile: closeProfileB, enforcedProfileName: Query.parse(queryA.expression).profileName(), comparing: true, navigateTo: navigateTo, suffix: "_b", showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setShowMetricsGraph }) })] }), _jsx("div", { className: "grid grid-cols-1", children: profileA != null && profileB != null ? (_jsx("div", { ...testId('COMPARE_PROFILE_VIEW'), children: _jsx(ProfileViewWithData, { queryClient: queryClient, profileSource: new ProfileDiffSource(profileA.ProfileSource(), profileB.ProfileSource(), compareAbsolute === 'true') }) })) : (_jsx("div", { children: _jsx("div", { className: "my-20 text-center", children: _jsx("p", { children: "Select a profile on both sides." }) }) })) })] }));
29
+ return (_jsxs("div", { ...testId(TEST_IDS.COMPARE_CONTAINER), children: [_jsxs("div", { className: "flex justify-between gap-2 relative mb-2", children: [_jsx("div", { className: "flex-column flex-1 p-2 shadow-md rounded-md", ...testId(TEST_IDS.COMPARE_SIDE_A), children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryA, profileSelection: profileA, selectProfile: selectProfileA, selectQuery: selectQueryA, closeProfile: closeProfileA, enforcedProfileName: '', comparing: true, navigateTo: navigateTo, suffix: "_a", showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setShowMetricsGraph }) }), _jsx("div", { className: "flex-column flex-1 p-2 shadow-md rounded-md", ...testId(TEST_IDS.COMPARE_SIDE_B), children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryB, profileSelection: profileB, selectProfile: selectProfileB, selectQuery: selectQueryB, closeProfile: closeProfileB, enforcedProfileName: Query.parse(queryA.expression).profileName(), comparing: true, navigateTo: navigateTo, suffix: "_b", showMetricsGraph: showMetricsGraph, setDisplayHideMetricsGraphButton: setShowMetricsGraph }) })] }), _jsx("div", { className: "grid grid-cols-1", children: profileA != null && profileB != null ? (_jsx("div", { ...testId(TEST_IDS.COMPARE_PROFILE_VIEW), children: _jsx(ProfileViewWithData, { queryClient: queryClient, profileSource: new ProfileDiffSource(profileA.ProfileSource(), profileB.ProfileSource(), compareAbsolute === 'true') }) })) : (_jsx("div", { children: _jsx("div", { className: "my-20 text-center", children: _jsx("p", { children: "Select a profile on both sides." }) }) })) })] }));
30
30
  };
31
31
  export default ProfileExplorerCompare;
@@ -19,7 +19,7 @@ import { createStore } from '@parca/store';
19
19
  import { capitalizeOnlyFirstLetter, safeDecode } from '@parca/utilities';
20
20
  import { ProfileSelectionFromParams, SuffixParams } from '..';
21
21
  import { useProfileTypes } from '../ProfileSelector';
22
- import { useResetStateOnNewSearch } from '../ProfileView/hooks/useResetStateOnNewSearch';
22
+ import { useResetFlameGraphState } from '../ProfileView/hooks/useResetFlameGraphState';
23
23
  import { useResetStateOnProfileTypeChange } from '../ProfileView/hooks/useResetStateOnProfileTypeChange';
24
24
  import { sumByToParam, useSumByFromParams } from '../useSumBy';
25
25
  import ProfileExplorerCompare from './ProfileExplorerCompare';
@@ -89,7 +89,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
89
89
  const [profileA, setProfileA] = useState(null);
90
90
  const [profileB, setProfileB] = useState(null);
91
91
  const resetStateOnProfileTypeChange = useResetStateOnProfileTypeChange();
92
- const resetStateOnNewSearch = useResetStateOnNewSearch();
92
+ const resetFlameGraphState = useResetFlameGraphState();
93
93
  const sumByA = useSumByFromParams(sum_by_a);
94
94
  const sumByB = useSumByFromParams(sum_by_b);
95
95
  useEffect(() => {
@@ -156,7 +156,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
156
156
  }
157
157
  else {
158
158
  // Reset the state when a new search is performed.
159
- resetStateOnNewSearch();
159
+ resetFlameGraphState();
160
160
  }
161
161
  }
162
162
  const mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
@@ -16,7 +16,7 @@ import cx from 'classnames';
16
16
  import { AnimatePresence, motion } from 'framer-motion';
17
17
  import { useMeasure } from 'react-use';
18
18
  import { FlameGraphSkeleton, SandwichFlameGraphSkeleton, useParcaContext, useURLState, } from '@parca/components';
19
- import { testId } from '@parca/test-utils';
19
+ import { TEST_IDS, testId } from '@parca/test-utils';
20
20
  import { capitalizeOnlyFirstLetter, divide } from '@parca/utilities';
21
21
  import DiffLegend from '../ProfileView/components/DiffLegend';
22
22
  import { useProfileViewContext } from '../ProfileView/context/ProfileViewContext';
@@ -173,6 +173,6 @@ const ProfileFlameGraph = function ProfileFlameGraphNonMemo({ arrow, total, filt
173
173
  }
174
174
  return (_jsx(ErrorContent, { errorMessage: _jsxs(_Fragment, { children: [_jsx("span", { children: capitalizeOnlyFirstLetter(error.message) }), isFlameChart ? flamechartHelpText ?? null : null] }) }));
175
175
  }
176
- return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "relative h-full w-full", initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.5 }, children: [compareMode ? _jsx(DiffLegend, {}) : null, _jsx("div", { className: cx(!isInSandwichView ? 'min-h-48' : ''), id: "h-flame-graph", ...testId('FLAMEGRAPH_CONTAINER'), children: _jsx(_Fragment, { children: flameGraph }) }), !isInSandwichView && (_jsxs("p", { className: "my-2 text-xs", children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] }))] }, "flame-graph-loaded") }));
176
+ return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "relative h-full w-full", initial: { opacity: 0 }, animate: { opacity: 1 }, transition: { duration: 0.5 }, children: [compareMode ? _jsx(DiffLegend, {}) : null, _jsx("div", { className: cx(!isInSandwichView ? 'min-h-48' : ''), id: "h-flame-graph", ...testId(TEST_IDS.FLAMEGRAPH_CONTAINER), children: _jsx(_Fragment, { children: flameGraph }) }), !isInSandwichView && (_jsxs("p", { className: "my-2 text-xs", children: ["Showing ", totalFormatted, ' ', isFiltered ? (_jsxs("span", { children: ["(", filteredPercentage, "%) filtered of ", totalUnfilteredFormatted, ' '] })) : (_jsx(_Fragment, {})), "values.", ' '] }))] }, "flame-graph-loaded") }));
177
177
  };
178
178
  export default ProfileFlameGraph;
@@ -16,7 +16,7 @@ import { Icon } from '@iconify/react';
16
16
  import { AnimatePresence, motion } from 'framer-motion';
17
17
  import { MetricsGraphSkeleton, TextWithTooltip, useParcaContext, } from '@parca/components';
18
18
  import { Query } from '@parca/parser';
19
- import { testId } from '@parca/test-utils';
19
+ import { TEST_IDS, testId } from '@parca/test-utils';
20
20
  import { capitalizeOnlyFirstLetter, formatDate, timePattern, valueFormatter } from '@parca/utilities';
21
21
  import { MergedProfileSelection } from '..';
22
22
  import MetricsGraph from '../MetricsGraph';
@@ -268,9 +268,9 @@ const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to,
268
268
  return (_jsx("div", { className: "flex flex-row", children: _jsxs("div", { className: "ml-2 mr-6", children: [_jsx("span", { className: "font-semibold", children: highlightedNameLabel.value }), _jsx("span", { className: "my-2 block text-gray-700 dark:text-gray-300", children: _jsx("table", { className: "table-auto", children: _jsxs("tbody", { children: [isDeltaType ? (_jsxs(_Fragment, { children: [_jsxs("tr", { children: [_jsx("td", { className: "w-1/4 pr-3", children: "Per\u00A0Second" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.valuePerSecond, sampleUnit === 'nanoseconds' && sampleType === 'cpu'
269
269
  ? 'CPU Cores'
270
270
  : sampleUnit, 5) })] }), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Total" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.value ?? 0, sampleUnit, 2) })] })] })) : (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Value" }), _jsx("td", { className: "w-3/4", children: valueFormatter(originalPoint.valuePerSecond, sampleUnit, 5) })] })), originalPoint.duration != null &&
271
- Number(originalPoint.duration) > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(Number(originalPoint.duration.toString()), 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(new Date(timestampMs), timePattern(timezone), timezone) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: utilizationMetrics ? (_jsxs(_Fragment, { children: [Object.keys(attributesResourceMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Resource Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesResourceMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId('TOOLTIP_LABEL'), children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesResourceMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesResourceMap[name]}` }) }, name))) }), Object.keys(attributesMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId('TOOLTIP_LABEL'), children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesMap[name]}` }) }, name))) })] })) : (_jsx(_Fragment, { children: labels
271
+ Number(originalPoint.duration) > 0 && (_jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "Duration" }), _jsx("td", { className: "w-3/4", children: valueFormatter(Number(originalPoint.duration.toString()), 'nanoseconds', 2) })] })), _jsxs("tr", { children: [_jsx("td", { className: "w-1/4", children: "At" }), _jsx("td", { className: "w-3/4", children: formatDate(new Date(timestampMs), timePattern(timezone), timezone) })] })] }) }) }), _jsx("span", { className: "my-2 block text-gray-500", children: utilizationMetrics ? (_jsxs(_Fragment, { children: [Object.keys(attributesResourceMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Resource Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesResourceMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(TEST_IDS.TOOLTIP_LABEL), children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesResourceMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesResourceMap[name]}` }) }, name))) }), Object.keys(attributesMap).length > 0 && (_jsx("span", { className: "text-sm font-bold text-gray-700 dark:text-white", children: "Attributes" })), _jsx("span", { className: "my-2 block text-gray-500", children: Object.keys(attributesMap).map(name => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(TEST_IDS.TOOLTIP_LABEL), children: _jsx(TextWithTooltip, { text: `${name.replace('attributes.', '')}="${attributesMap[name]}"`, maxTextLength: 48, id: `tooltip-${name}-${attributesMap[name]}` }) }, name))) })] })) : (_jsx(_Fragment, { children: labels
272
272
  .filter((label) => label.name !== '__name__')
273
- .map((label) => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId('TOOLTIP_LABEL'), children: _jsx(TextWithTooltip, { text: `${label.name}="${label.value}"`, maxTextLength: 37, id: `tooltip-${label.name}` }) }, label.name))) })) }), _jsxs("div", { className: "flex w-full items-center gap-1 text-xs text-gray-500", children: [_jsx(Icon, { icon: "iconoir:mouse-button-right" }), _jsx("div", { children: "Right click to add labels to query." })] })] }) }));
273
+ .map((label) => (_jsx("div", { className: "mr-3 inline-block rounded-lg bg-gray-200 px-2 py-1 text-xs font-bold text-gray-700 dark:bg-gray-700 dark:text-gray-400", ...testId(TEST_IDS.TOOLTIP_LABEL), children: _jsx(TextWithTooltip, { text: `${label.name}="${label.value}"`, maxTextLength: 37, id: `tooltip-${label.name}` }) }, label.name))) })) }), _jsxs("div", { className: "flex w-full items-center gap-1 text-xs text-gray-500", children: [_jsx(Icon, { icon: "iconoir:mouse-button-right" }), _jsx("div", { children: "Right click to add labels to query." })] })] }) }));
274
274
  }
275
275
  }
276
276
  return null;
@@ -14,19 +14,19 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
14
14
  import { Switch } from '@headlessui/react';
15
15
  import Select from 'react-select';
16
16
  import { Button, DateTimeRangePicker, useParcaContext } from '@parca/components';
17
- import { testId } from '@parca/test-utils';
17
+ import { TEST_IDS, testId } from '@parca/test-utils';
18
18
  import MatchersInput from '../MatchersInput';
19
19
  import ProfileTypeSelector from '../ProfileTypeSelector';
20
20
  import SimpleMatchers from '../SimpleMatchers';
21
21
  import ViewMatchers from '../ViewMatchers';
22
22
  export function QueryControls({ showProfileTypeSelector, profileTypesData, profileTypesLoading, selectedProfileName, setProfileName, viewComponent, setQueryBrowserMode, advancedModeForQueryBrowser, setAdvancedModeForQueryBrowser, setMatchersString, setQueryExpression, query, queryBrowserRef, timeRangeSelection, setTimeRangeSelection, searchDisabled, queryClient, labels, sumBySelection, sumBySelectionLoading, setUserSumBySelection, sumByRef, profileType, showSumBySelector, profileTypesError, }) {
23
23
  const { timezone } = useParcaContext();
24
- return (_jsxs("div", { className: "flex w-full flex-wrap items-start gap-2", ...testId('QUERY_CONTROLS_CONTAINER'), children: [showProfileTypeSelector && (_jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId('PROFILE_TYPE_LABEL'), children: "Profile type" }), _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: profileTypesError, disabled: viewComponent?.disableProfileTypesDropdown })] })), _jsxs("div", { className: "w-full flex-1 flex flex-col gap-1 mt-auto", ref: queryBrowserRef, ...testId('QUERY_BROWSER_CONTAINER'), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("label", { className: "text-xs", ...testId('QUERY_LABEL'), children: "Query" }), viewComponent?.disableExplorativeQuerying !== true && (_jsxs(_Fragment, { children: [_jsxs(Switch, { checked: advancedModeForQueryBrowser, onChange: () => {
24
+ return (_jsxs("div", { className: "flex w-full flex-wrap items-start gap-2", ...testId(TEST_IDS.QUERY_CONTROLS_CONTAINER), children: [showProfileTypeSelector && (_jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId(TEST_IDS.PROFILE_TYPE_LABEL), children: "Profile type" }), _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: profileTypesError, disabled: viewComponent?.disableProfileTypesDropdown })] })), _jsxs("div", { className: "w-full flex-1 flex flex-col gap-1 mt-auto", ref: queryBrowserRef, ...testId(TEST_IDS.QUERY_BROWSER_CONTAINER), children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("label", { className: "text-xs", ...testId(TEST_IDS.QUERY_LABEL), children: "Query" }), viewComponent?.disableExplorativeQuerying !== true && (_jsxs(_Fragment, { children: [_jsxs(Switch, { checked: advancedModeForQueryBrowser, onChange: () => {
25
25
  setAdvancedModeForQueryBrowser(!advancedModeForQueryBrowser);
26
26
  setQueryBrowserMode(advancedModeForQueryBrowser ? 'simple' : 'advanced');
27
- }, className: `${advancedModeForQueryBrowser ? 'bg-indigo-600' : 'bg-gray-400 dark:bg-gray-800'} relative inline-flex h-[20px] w-[44px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75`, ...testId('ADVANCED_MODE_SWITCH'), children: [_jsx("span", { className: "sr-only", children: "Use setting" }), _jsx("span", { "aria-hidden": "true", className: `${advancedModeForQueryBrowser ? 'translate-x-6' : 'translate-x-0'} pointer-events-none inline-block h-[16px] w-[16px] transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out` })] }), _jsx("label", { className: "text-xs", ...testId('QUERY_MODE_LABEL'), children: "Advanced Mode" })] }))] }), viewComponent?.createViewComponent] }), viewComponent?.disableExplorativeQuerying === true &&
27
+ }, className: `${advancedModeForQueryBrowser ? 'bg-indigo-600' : 'bg-gray-400 dark:bg-gray-800'} relative inline-flex h-[20px] w-[44px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75`, ...testId(TEST_IDS.ADVANCED_MODE_SWITCH), children: [_jsx("span", { className: "sr-only", children: "Use setting" }), _jsx("span", { "aria-hidden": "true", className: `${advancedModeForQueryBrowser ? 'translate-x-6' : 'translate-x-0'} pointer-events-none inline-block h-[16px] w-[16px] transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out` })] }), _jsx("label", { className: "text-xs", ...testId(TEST_IDS.QUERY_MODE_LABEL), children: "Advanced Mode" })] }))] }), viewComponent?.createViewComponent] }), viewComponent?.disableExplorativeQuerying === true &&
28
28
  viewComponent?.labelnames !== undefined &&
29
- viewComponent?.labelnames.length >= 1 ? (_jsx(ViewMatchers, { labelNames: viewComponent.labelnames, setMatchersString: setMatchersString, profileType: selectedProfileName, runQuery: setQueryExpression, currentQuery: query, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : advancedModeForQueryBrowser ? (_jsx(MatchersInput, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : (_jsx(SimpleMatchers, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryBrowserRef: queryBrowserRef, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() }, query.toString()))] }), showSumBySelector && (_jsxs("div", { ...testId('SUM_BY_CONTAINER'), children: [_jsx("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: _jsx("label", { className: "text-xs", ...testId('SUM_BY_LABEL'), children: "Sum by" }) }), _jsx(Select, { id: "h-sum-by-selector", "data-testid": testId('SUM_BY_SELECT')['data-testid'], defaultValue: [], isMulti: true, isClearable: false, name: "colors", options: labels.map(label => ({ label, value: label })), className: "parca-select-container text-sm w-full max-w-80", classNamePrefix: "parca-select", value: (sumBySelection ?? []).map(sumBy => ({ label: sumBy, value: sumBy })), onChange: newValue => {
29
+ viewComponent?.labelnames.length >= 1 ? (_jsx(ViewMatchers, { labelNames: viewComponent.labelnames, setMatchersString: setMatchersString, profileType: selectedProfileName, runQuery: setQueryExpression, currentQuery: query, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : advancedModeForQueryBrowser ? (_jsx(MatchersInput, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() })) : (_jsx(SimpleMatchers, { setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName, queryBrowserRef: queryBrowserRef, queryClient: queryClient, start: timeRangeSelection.getFromMs(), end: timeRangeSelection.getToMs() }, query.toString()))] }), showSumBySelector && (_jsxs("div", { ...testId(TEST_IDS.SUM_BY_CONTAINER), children: [_jsx("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: _jsx("label", { className: "text-xs", ...testId(TEST_IDS.SUM_BY_LABEL), children: "Sum by" }) }), _jsx(Select, { id: "h-sum-by-selector", "data-testid": testId(TEST_IDS.SUM_BY_SELECT)['data-testid'], defaultValue: [], isMulti: true, isClearable: false, name: "colors", options: labels.map(label => ({ label, value: label })), className: "parca-select-container text-sm w-full max-w-80", classNamePrefix: "parca-select", value: (sumBySelection ?? []).map(sumBy => ({ label: sumBy, value: sumBy })), onChange: newValue => {
30
30
  setUserSumBySelection(newValue.map(option => option.value));
31
31
  }, placeholder: "Labels...", styles: {
32
32
  indicatorSeparator: () => ({ display: 'none' }),
@@ -49,8 +49,8 @@ export function QueryControls({ showProfileTypeSelector, profileTypesData, profi
49
49
  setQueryExpression(true);
50
50
  currentRef.blur();
51
51
  }
52
- } })] })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection, timezone: timezone, ...testId('DATE_TIME_RANGE_PICKER') }), _jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId('SEARCH_BUTTON_LABEL'), children: "\u00A0" }), _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
52
+ } })] })), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection, timezone: timezone, ...testId(TEST_IDS.DATE_TIME_RANGE_PICKER) }), _jsxs("div", { children: [_jsx("label", { className: "text-xs", ...testId(TEST_IDS.SEARCH_BUTTON_LABEL), children: "\u00A0" }), _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
53
53
  e.preventDefault();
54
54
  setQueryExpression(true);
55
- }, id: "h-matcher-search-button", ...testId('SEARCH_BUTTON'), children: "Search" })] })] }));
55
+ }, id: "h-matcher-search-button", ...testId(TEST_IDS.SEARCH_BUTTON), children: "Search" })] })] }));
56
56
  }
@@ -13,7 +13,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
13
13
  // limitations under the License.
14
14
  import { useMemo } from 'react';
15
15
  import { Select } from '@parca/components';
16
- import { testId } from '@parca/test-utils';
16
+ import { TEST_IDS, testId } from '@parca/test-utils';
17
17
  export const wellKnownProfiles = {
18
18
  'block:contentions:count:contentions:count': {
19
19
  name: 'Block Contentions Total',
@@ -139,6 +139,6 @@ const ProfileTypeSelector = ({ profileTypesData, loading = false, error, selecte
139
139
  key: name,
140
140
  element: profileSelectElement(name, flexibleKnownProfilesDetection),
141
141
  }));
142
- return (_jsx(Select, { items: profileLabels, selectedKey: selectedKey, onSelection: onSelection, placeholder: "Select profile type...", loading: loading, className: "bg-white h-profile-type-dropdown", disabled: disabled, ...testId('PROFILE_TYPE_SELECTOR') }));
142
+ return (_jsx(Select, { items: profileLabels, selectedKey: selectedKey, onSelection: onSelection, placeholder: "Select profile type...", loading: loading, className: "bg-white h-profile-type-dropdown", disabled: disabled, ...testId(TEST_IDS.PROFILE_TYPE_SELECTOR) }));
143
143
  };
144
144
  export default ProfileTypeSelector;
@@ -15,8 +15,6 @@ interface GetDashboardItemProps {
15
15
  profileSource: ProfileSource;
16
16
  total: bigint;
17
17
  filtered: bigint;
18
- curPath: string[];
19
- setNewCurPath: (path: string[]) => void;
20
18
  curPathArrow: CurrentPathFrame[];
21
19
  setNewCurPathArrow: (path: CurrentPathFrame[]) => void;
22
20
  perf?: {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACxC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAAI,qLAe9B,qBAAqB,KAAG,GAAG,CAAC,OA+F9B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/DashboardItems/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAW,wBAAwB,EAAC,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,EAAC,gBAAgB,EAAC,MAAM,kDAAkD,CAAC;AAClF,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAIrD,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,qBAAqB;IAC7B,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,aAAa,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,kBAAkB,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACvD,IAAI,CAAC,EAAE;QACL,QAAQ,CAAC,EAAE,wBAAwB,CAAC;KACrC,CAAC;IACF,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,eAAO,MAAM,gBAAgB,GAAI,qLAe9B,qBAAqB,KAAG,GAAG,CAAC,OA+F9B,CAAC"}
@@ -15,7 +15,7 @@ import { Fragment, useState } from 'react';
15
15
  import { Popover, Transition } from '@headlessui/react';
16
16
  import { usePopper } from 'react-popper';
17
17
  import { selectDarkMode, useAppSelector } from '@parca/store';
18
- import { testId } from '@parca/test-utils';
18
+ import { TEST_IDS, testId } from '@parca/test-utils';
19
19
  import { getIncreasedSpanColor, getNewSpanColor, getReducedSpanColor } from '@parca/utilities';
20
20
  const transparencyValues = [-100, -80, -60, -40, -20, 0, 20, 40, 60, 80, 100];
21
21
  const DiffLegendBar = ({ onMouseEnter, onMouseLeave, }) => {
@@ -46,6 +46,6 @@ const DiffLegend = () => {
46
46
  const handleMouseLeave = () => {
47
47
  setShowLegendTooltip(false);
48
48
  };
49
- return (_jsxs("div", { className: "mt-1 mb-2 hidden md:block", id: "h-diff-legend", ...testId('DIFF_LEGEND'), children: [_jsxs("div", { ref: setReferenceElement, className: "flex items-center justify-center", children: [_jsx("span", { children: "Better" }), _jsx(DiffLegendBar, { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }), _jsx("span", { children: "Worse" })] }), _jsx(Popover, { className: "relative", children: () => (_jsx(Transition, { show: showLegendTooltip, as: Fragment, enter: "transition ease-out duration-200", enterFrom: "opacity-0 translate-y-1", enterTo: "opacity-100 translate-y-0", leave: "transition ease-in duration-150", leaveFrom: "opacity-100 translate-y-0", leaveTo: "opacity-0 translate-y-1", children: _jsx(Popover.Panel, { ref: setPopperElement, style: styles.popper, ...attributes.popper, children: _jsx("div", { className: "overflow-hidden rounded-lg shadow-lg ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "bg-gray-50 p-4 dark:bg-gray-800", children: [_jsx("div", { className: "flex items-center justify-center" }), _jsx("span", { className: "block text-sm text-gray-500 dark:text-gray-50", children: "This is a differential flame graph, where a purple-colored node means unchanged, and the darker the red, the worse the node got, and the darker the green, the better the node got." })] }) }) }) })) })] }));
49
+ return (_jsxs("div", { className: "mt-1 mb-2 hidden md:block", id: "h-diff-legend", ...testId(TEST_IDS.DIFF_LEGEND), children: [_jsxs("div", { ref: setReferenceElement, className: "flex items-center justify-center", children: [_jsx("span", { children: "Better" }), _jsx(DiffLegendBar, { onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave }), _jsx("span", { children: "Worse" })] }), _jsx(Popover, { className: "relative", children: () => (_jsx(Transition, { show: showLegendTooltip, as: Fragment, enter: "transition ease-out duration-200", enterFrom: "opacity-0 translate-y-1", enterTo: "opacity-100 translate-y-0", leave: "transition ease-in duration-150", leaveFrom: "opacity-100 translate-y-0", leaveTo: "opacity-0 translate-y-1", children: _jsx(Popover.Panel, { ref: setPopperElement, style: styles.popper, ...attributes.popper, children: _jsx("div", { className: "overflow-hidden rounded-lg shadow-lg ring-1 ring-black ring-opacity-5", children: _jsxs("div", { className: "bg-gray-50 p-4 dark:bg-gray-800", children: [_jsx("div", { className: "flex items-center justify-center" }), _jsx("span", { className: "block text-sm text-gray-500 dark:text-gray-50", children: "This is a differential flame graph, where a purple-colored node means unchanged, and the darker the red, the worse the node got, and the darker the green, the better the node got." })] }) }) }) })) })] }));
50
50
  };
51
51
  export default DiffLegend;
@@ -12,12 +12,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
14
  import Select from 'react-select';
15
- import { testId } from '@parca/test-utils';
15
+ import { TEST_IDS, testId } from '@parca/test-utils';
16
16
  import { FIELD_LABELS } from '../../../ProfileFlameGraph/FlameGraphArrow';
17
17
  const GroupByLabelsDropdown = ({ labels, groupBy, setGroupByLabels }) => {
18
- return (_jsxs("div", { className: "flex flex-col relative", ...testId('GROUP_BY_CONTAINER'), children: [_jsx("div", { className: "flex items-center justify-between", children: _jsx("label", { className: "text-sm", ...testId('GROUP_BY_LABEL'), children: "Group by" }) }), _jsx(Select, { isMulti: true, defaultMenuIsOpen: false, defaultValue: undefined, name: "labels", options: labels.map(label => ({ label, value: `${FIELD_LABELS}.${label}` })), className: "parca-select-container text-sm rounded-md bg-white", classNamePrefix: "parca-select", components: {
18
+ return (_jsxs("div", { className: "flex flex-col relative", ...testId(TEST_IDS.GROUP_BY_CONTAINER), children: [_jsx("div", { className: "flex items-center justify-between", children: _jsx("label", { className: "text-sm", ...testId(TEST_IDS.GROUP_BY_LABEL), children: "Group by" }) }), _jsx(Select, { isMulti: true, defaultMenuIsOpen: false, defaultValue: undefined, name: "labels", options: labels.map(label => ({ label, value: `${FIELD_LABELS}.${label}` })), className: "parca-select-container text-sm rounded-md bg-white", classNamePrefix: "parca-select", components: {
19
19
  // eslint-disable-next-line react/prop-types
20
- MenuList: ({ children, innerProps }) => (_jsx("div", { className: "overflow-y-auto", ...testId('GROUP_BY_SELECT_FLYOUT'), ...innerProps,
20
+ MenuList: ({ children, innerProps }) => (_jsx("div", { className: "overflow-y-auto", ...testId(TEST_IDS.GROUP_BY_SELECT_FLYOUT), ...innerProps,
21
21
  // eslint-disable-next-line react/prop-types
22
22
  style: { ...innerProps.style, height: '332px', maxHeight: '332px', fontSize: '14px' }, children: children })),
23
23
  }, value: groupBy
@@ -15,7 +15,7 @@ import { useCallback } from 'react';
15
15
  import { Icon } from '@iconify/react';
16
16
  import cx from 'classnames';
17
17
  import { Button, Input, Select } from '@parca/components';
18
- import { testId } from '@parca/test-utils';
18
+ import { TEST_IDS, testId } from '@parca/test-utils';
19
19
  import { useProfileViewContext } from '../../context/ProfileViewContext';
20
20
  import { getPresetByKey, getPresetsForProfileType, isPresetKey } from './filterPresets';
21
21
  import { useProfileFilters } from './useProfileFilters';
@@ -155,11 +155,11 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
155
155
  }
156
156
  }, [onApplyFilters]);
157
157
  const filtersToRender = localFilters.length > 0 ? localFilters : appliedFilters ?? [];
158
- return (_jsxs("div", { className: "flex gap-2 w-full items-start", ...testId('PROFILE_FILTERS_CONTAINER'), children: [_jsxs("div", { className: "flex-1 flex flex-wrap gap-2", children: [filtersToRender.map(filter => {
158
+ return (_jsxs("div", { className: "flex gap-2 w-full items-start", ...testId(TEST_IDS.PROFILE_FILTERS_CONTAINER), children: [_jsxs("div", { className: "flex-1 flex flex-wrap gap-2", children: [filtersToRender.map(filter => {
159
159
  const isNumberField = filter.field === 'address' || filter.field === 'line_number';
160
160
  const matchTypeItems = isNumberField ? numberMatchTypeItems : stringMatchTypeItems;
161
161
  const isPresetFilter = filter.type != null && isPresetKey(filter.type);
162
- return (_jsxs("div", { className: "flex items-center gap-0", children: [_jsx(Select, { items: filterTypeItems, selectedKey: filter.type, placeholder: "Select Filter", disabled: readOnly, ...testId('FILTER_TYPE_SELECT'), flyoutTestId: "filter-type-select-flyout", onSelection: key => {
162
+ return (_jsxs("div", { className: "flex items-center gap-0", children: [_jsx(Select, { items: filterTypeItems, selectedKey: filter.type, placeholder: "Select Filter", disabled: readOnly, ...testId(TEST_IDS.FILTER_TYPE_SELECT), flyoutTestId: "filter-type-select-flyout", onSelection: key => {
163
163
  // Check if this is a preset selection
164
164
  if (isPresetKey(key)) {
165
165
  const preset = getPresetByKey(key);
@@ -191,7 +191,7 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
191
191
  });
192
192
  }
193
193
  }
194
- }, className: cx('gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1', readOnly && isPresetFilter ? 'rounded-md' : 'rounded-l-md rounded-r-none', !readOnly && (isPresetFilter ? 'rounded-r-none border-r-0' : 'rounded-r-none'), readOnly ? 'w-auto' : filter.type != null ? 'border-r-0 w-auto' : 'w-32'), hideCaretDropdown: readOnly }), filter.type != null && !isPresetFilter && (_jsxs(_Fragment, { children: [_jsx(Select, { items: fieldItems, selectedKey: filter.field ?? '', disabled: readOnly, ...testId('FILTER_FIELD_SELECT'), flyoutTestId: "filter-field-select-flyout", onSelection: key => {
194
+ }, className: cx('gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1', readOnly && isPresetFilter ? 'rounded-md' : 'rounded-l-md rounded-r-none', !readOnly && (isPresetFilter ? 'rounded-r-none border-r-0' : 'rounded-r-none'), readOnly ? 'w-auto' : filter.type != null ? 'border-r-0 w-auto' : 'w-32'), hideCaretDropdown: readOnly }), filter.type != null && !isPresetFilter && (_jsxs(_Fragment, { children: [_jsx(Select, { items: fieldItems, selectedKey: filter.field ?? '', disabled: readOnly, ...testId(TEST_IDS.FILTER_FIELD_SELECT), flyoutTestId: "filter-field-select-flyout", onSelection: key => {
195
195
  const newField = key;
196
196
  const isNewFieldNumber = newField === 'address' || newField === 'line_number';
197
197
  const isCurrentFieldNumber = filter.field === 'address' || filter.field === 'line_number';
@@ -204,7 +204,7 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
204
204
  else {
205
205
  updateFilter(filter.id, { field: newField });
206
206
  }
207
- }, className: cx('rounded-none border-r-0 w-32 gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1'), hideCaretDropdown: readOnly }), _jsx(Select, { items: matchTypeItems, selectedKey: filter.matchType ?? '', disabled: readOnly, ...testId('FILTER_MATCH_TYPE_SELECT'), flyoutTestId: "filter-match-type-select-flyout", onSelection: key => updateFilter(filter.id, { matchType: key }), className: cx('rounded-none border-r-0 gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1'), hideCaretDropdown: readOnly }), _jsx(Input, { placeholder: "Value", value: filter.value, disabled: readOnly, onChange: e => updateFilter(filter.id, { value: e.target.value }), onKeyDown: handleKeyDown, className: "rounded-none w-36 text-sm focus:outline-1", ...testId('FILTER_VALUE_INPUT') })] })), !readOnly && (_jsx(Button, { variant: "neutral", ...testId('FILTER_REMOVE_BUTTON'), onClick: () => {
207
+ }, className: cx('rounded-none border-r-0 w-32 gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1'), hideCaretDropdown: readOnly }), _jsx(Select, { items: matchTypeItems, selectedKey: filter.matchType ?? '', disabled: readOnly, ...testId(TEST_IDS.FILTER_MATCH_TYPE_SELECT), flyoutTestId: "filter-match-type-select-flyout", onSelection: key => updateFilter(filter.id, { matchType: key }), className: cx('rounded-none border-r-0 gap-0 focus:z-50 focus:relative focus:outline-1', readOnly ? '' : 'pr-1'), hideCaretDropdown: readOnly }), _jsx(Input, { placeholder: "Value", value: filter.value, disabled: readOnly, onChange: e => updateFilter(filter.id, { value: e.target.value }), onKeyDown: handleKeyDown, className: "rounded-none w-36 text-sm focus:outline-1", ...testId(TEST_IDS.FILTER_VALUE_INPUT) })] })), !readOnly && (_jsx(Button, { variant: "neutral", ...testId(TEST_IDS.FILTER_REMOVE_BUTTON), onClick: () => {
208
208
  // If we're displaying local filters and this is the last one, reset everything
209
209
  if (localFilters.length > 0 && localFilters.length === 1) {
210
210
  resetFilters();
@@ -220,6 +220,6 @@ const ProfileFilters = ({ readOnly = false } = {}) => {
220
220
  }, className: cx('h-[38px] p-3', filter.type != null
221
221
  ? 'rounded-none rounded-r-md'
222
222
  : 'rounded-l-none rounded-r-md'), children: _jsx(Icon, { icon: "mdi:close", className: "h-4 w-4" }) }))] }, filter.id));
223
- }), !readOnly && localFilters.length > 0 && (_jsx(Button, { variant: "neutral", onClick: addFilter, className: "p-3 h-[38px]", ...testId('ADD_FILTER_BUTTON'), children: _jsx(Icon, { icon: "mdi:filter-plus-outline", className: "h-4 w-4" }) })), !readOnly && localFilters.length === 0 && (appliedFilters?.length ?? 0) === 0 && (_jsxs(Button, { variant: "neutral", onClick: addFilter, className: "flex items-center gap-2", ...testId('ADD_FILTER_BUTTON'), children: [_jsx(Icon, { icon: "mdi:filter-outline", className: "h-4 w-4" }), _jsx("span", { children: "Filter" })] }))] }), !readOnly && localFilters.length > 0 && (_jsx(Button, { variant: "primary", onClick: onApplyFilters, disabled: !hasUnsavedChanges || !localFilters.some(isFilterComplete), className: cx('flex items-center gap-2 sticky top-0'), ...testId('APPLY_FILTERS_BUTTON'), children: _jsx("span", { children: "Apply" }) }))] }));
223
+ }), !readOnly && localFilters.length > 0 && (_jsx(Button, { variant: "neutral", onClick: addFilter, className: "p-3 h-[38px]", ...testId(TEST_IDS.ADD_FILTER_BUTTON), children: _jsx(Icon, { icon: "mdi:filter-plus-outline", className: "h-4 w-4" }) })), !readOnly && localFilters.length === 0 && (appliedFilters?.length ?? 0) === 0 && (_jsxs(Button, { variant: "neutral", onClick: addFilter, className: "flex items-center gap-2", ...testId(TEST_IDS.ADD_FILTER_BUTTON), children: [_jsx(Icon, { icon: "mdi:filter-outline", className: "h-4 w-4" }), _jsx("span", { children: "Filter" })] }))] }), !readOnly && localFilters.length > 0 && (_jsx(Button, { variant: "primary", onClick: onApplyFilters, disabled: !hasUnsavedChanges || !localFilters.some(isFilterComplete), className: cx('flex items-center gap-2 sticky top-0'), ...testId(TEST_IDS.APPLY_FILTERS_BUTTON), children: _jsx("span", { children: "Apply" }) }))] }));
224
224
  };
225
225
  export default ProfileFilters;
@@ -1 +1 @@
1
- {"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAA6C,MAAM,eAAe,CAAC;AAKtF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,eAAe,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;IAC5F,SAAS,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IAChE,KAAK,EAAE,MAAM,CAAC;CACf;AAqBD,eAAO,MAAM,uBAAuB,GAAI,cAAc,MAAM,EAAE,KAAG,aAAa,EA+E7E,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,gBAAgB,aAAa,EAAE,KAAG,MAAM,EAmF7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO;IACnC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,MAAM,IAAI,CAAC;CAsL1B,CAAC"}
1
+ {"version":3,"file":"useProfileFilters.d.ts","sourceRoot":"","sources":["../../../../src/ProfileView/components/ProfileFilters/useProfileFilters.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,KAAK,MAAM,EAA6C,MAAM,eAAe,CAAC;AAMtF,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,eAAe,GAAG,QAAQ,GAAG,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,aAAa,CAAC;IAC5F,SAAS,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,CAAC;IAChE,KAAK,EAAE,MAAM,CAAC;CACf;AAqBD,eAAO,MAAM,uBAAuB,GAAI,cAAc,MAAM,EAAE,KAAG,aAAa,EA+E7E,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,gBAAgB,aAAa,EAAE,KAAG,MAAM,EAmF7E,CAAC;AAEF,eAAO,MAAM,iBAAiB,QAAO;IACnC,YAAY,EAAE,aAAa,EAAE,CAAC;IAC9B,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC;IACpE,YAAY,EAAE,MAAM,IAAI,CAAC;CA2L1B,CAAC"}
@@ -11,6 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
14
+ import { useResetFlameGraphState } from '../../hooks/useResetFlameGraphState';
14
15
  import { getPresetByKey, isPresetKey } from './filterPresets';
15
16
  import { useProfileFiltersUrlState } from './useProfileFiltersUrlState';
16
17
  const createStringCondition = (matchType, value) => ({
@@ -182,6 +183,7 @@ export const convertToProtoFilters = (profileFilters) => {
182
183
  };
183
184
  export const useProfileFilters = () => {
184
185
  const { appliedFilters, setAppliedFilters } = useProfileFiltersUrlState();
186
+ const resetFlameGraphState = useResetFlameGraphState();
185
187
  const [localFilters, setLocalFilters] = useState(appliedFilters ?? []);
186
188
  const lastAppliedFiltersRef = useRef([]);
187
189
  const localFiltersRef = useRef(localFilters);
@@ -259,9 +261,10 @@ export const useProfileFilters = () => {
259
261
  // Auto-apply the filter since it has a value
260
262
  const filtersToApply = [...(appliedFilters ?? []), newFilter];
261
263
  setAppliedFilters(filtersToApply);
264
+ resetFlameGraphState();
262
265
  },
263
266
  // eslint-disable-next-line react-hooks/exhaustive-deps
264
- [setAppliedFilters]);
267
+ [setAppliedFilters, resetFlameGraphState]);
265
268
  const removeExcludeBinary = useCallback((binaryName) => {
266
269
  // Search for the exclude filter (not_contains) for this binary
267
270
  const filterToRemove = (appliedFilters ?? []).find(f => f.type === 'frame' &&
@@ -272,10 +275,11 @@ export const useProfileFilters = () => {
272
275
  // Remove the filter from applied filters
273
276
  const updatedAppliedFilters = (appliedFilters ?? []).filter(f => f.id !== filterToRemove.id);
274
277
  setAppliedFilters(updatedAppliedFilters);
278
+ resetFlameGraphState();
275
279
  // Also remove from local filters
276
280
  setLocalFilters(localFiltersRef.current.filter(f => f.id !== filterToRemove.id));
277
281
  }
278
- }, [appliedFilters, setAppliedFilters]);
282
+ }, [appliedFilters, setAppliedFilters, resetFlameGraphState]);
279
283
  const removeFilter = useCallback((id) => {
280
284
  setLocalFilters(localFiltersRef.current.filter(f => f.id !== id));
281
285
  }, []);
@@ -285,7 +289,8 @@ export const useProfileFilters = () => {
285
289
  const resetFilters = useCallback(() => {
286
290
  setLocalFilters([]);
287
291
  setAppliedFilters([]);
288
- }, [setAppliedFilters]);
292
+ resetFlameGraphState();
293
+ }, [setAppliedFilters, resetFlameGraphState]);
289
294
  const onApplyFilters = useCallback(() => {
290
295
  const validFilters = localFiltersRef.current.filter(f => {
291
296
  // For preset filters, only need type and value
@@ -300,7 +305,8 @@ export const useProfileFilters = () => {
300
305
  id: `filter-${Date.now()}-${index}`,
301
306
  }));
302
307
  setAppliedFilters(filtersToApply);
303
- }, [setAppliedFilters]);
308
+ resetFlameGraphState();
309
+ }, [setAppliedFilters, resetFlameGraphState]);
304
310
  const protoFilters = useMemo(() => {
305
311
  return convertToProtoFilters(appliedFilters ?? []);
306
312
  }, [appliedFilters]);
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Icon } from '@iconify/react';
3
3
  import { Button } from '@parca/components';
4
- import { testId } from '@parca/test-utils';
4
+ import { TEST_IDS, testId } from '@parca/test-utils';
5
5
  import { useDashboard } from '../../context/DashboardContext';
6
6
  import GroupByDropdown from '../ActionButtons/GroupByDropdown';
7
7
  import InvertCallStack from '../InvertCallStack';
@@ -14,7 +14,7 @@ export const TableToolbar = ({ profileType, total, filtered }) => {
14
14
  return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end", children: _jsx(TableColumnsDropdown, { profileType: profileType, total: total, filtered: filtered }) }) }));
15
15
  };
16
16
  export const FlameGraphToolbar = ({ curPath, setNewCurPath }) => {
17
- return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end", children: _jsxs(Button, { variant: "neutral", className: "gap-2 w-max h-fit", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, id: "h-reset-graph", ...testId('FLAMEGRAPH_RESET_BUTTON'), children: ["Reset graph", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }) }) }));
17
+ return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end", children: _jsxs(Button, { variant: "neutral", className: "gap-2 w-max h-fit", onClick: () => setNewCurPath([]), disabled: curPath.length === 0, id: "h-reset-graph", ...testId(TEST_IDS.FLAMEGRAPH_RESET_BUTTON), children: ["Reset graph", _jsx(Icon, { icon: "system-uicons:reset", width: 20 })] }) }) }));
18
18
  };
19
19
  export const SandwichFlameGraphToolbar = ({ resetSandwichFunctionName, sandwichFunctionName, }) => {
20
20
  return (_jsx(_Fragment, { children: _jsx("div", { className: "flex w-full gap-2 items-end justify-between", children: _jsx(Button, { color: "neutral", onClick: () => resetSandwichFunctionName(), className: "w-auto", variant: "neutral", disabled: sandwichFunctionName === undefined || sandwichFunctionName.length === 0, children: "Reset view" }) }) }));
@@ -0,0 +1,2 @@
1
+ export declare const useResetFlameGraphState: () => (() => void);
2
+ //# sourceMappingURL=useResetFlameGraphState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useResetFlameGraphState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useResetFlameGraphState.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,uBAAuB,QAAO,CAAC,MAAM,IAAI,CAWrD,CAAC"}
@@ -11,7 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { useURLState } from '@parca/components';
14
- export const useResetStateOnNewSearch = () => {
14
+ export const useResetFlameGraphState = () => {
15
15
  const [val, setCurPath] = useURLState('cur_path');
16
16
  return () => {
17
17
  setTimeout(() => {
@@ -1,7 +1,5 @@
1
1
  import { CurrentPathFrame } from '../../ProfileFlameGraph/FlameGraphArrow/utils';
2
2
  export declare const useVisualizationState: () => {
3
- curPath: string[];
4
- setCurPath: (path: string[]) => void;
5
3
  curPathArrow: CurrentPathFrame[];
6
4
  setCurPathArrow: (path: CurrentPathFrame[]) => void;
7
5
  colorStackLegend: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"useVisualizationState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useVisualizationState.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAC,gBAAgB,EAAC,MAAM,+CAA+C,CAAC;AAE/E,eAAO,MAAM,qBAAqB,QAAO;IACvC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACpD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,uBAAuB,EAAE,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC5E,yBAAyB,EAAE,MAAM,IAAI,CAAC;CA0EvC,CAAC"}
1
+ {"version":3,"file":"useVisualizationState.d.ts","sourceRoot":"","sources":["../../../src/ProfileView/hooks/useVisualizationState.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAC,gBAAgB,EAAC,MAAM,+CAA+C,CAAC;AAG/E,eAAO,MAAM,qBAAqB,QAAO;IACvC,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,IAAI,CAAC;IACpD,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,gBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,uBAAuB,EAAE,CAAC,oBAAoB,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAC5E,yBAAyB,EAAE,MAAM,IAAI,CAAC;CA0EvC,CAAC"}
@@ -10,11 +10,11 @@
10
10
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
- import { useCallback, useMemo, useState } from 'react';
13
+ import { useCallback, useMemo } from 'react';
14
14
  import { JSONParser, JSONSerializer, useURLState, useURLStateCustom } from '@parca/components';
15
15
  import { FIELD_FUNCTION_FILE_NAME, FIELD_FUNCTION_NAME, FIELD_LABELS, FIELD_LOCATION_ADDRESS, FIELD_MAPPING_FILE, } from '../../ProfileFlameGraph/FlameGraphArrow';
16
+ import { useResetFlameGraphState } from './useResetFlameGraphState';
16
17
  export const useVisualizationState = () => {
17
- const [curPath, setCurPath] = useState([]);
18
18
  const [curPathArrow, setCurPathArrow] = useURLStateCustom('cur_path', {
19
19
  parse: (JSONParser),
20
20
  stringify: JSONSerializer,
@@ -27,6 +27,7 @@ export const useVisualizationState = () => {
27
27
  alwaysReturnArray: true,
28
28
  });
29
29
  const [sandwichFunctionName, setSandwichFunctionName] = useURLState('sandwich_function_name');
30
+ const resetFlameGraphState = useResetFlameGraphState();
30
31
  const levelsOfProfiling = useMemo(() => [
31
32
  FIELD_FUNCTION_NAME,
32
33
  FIELD_FUNCTION_FILE_NAME,
@@ -44,7 +45,8 @@ export const useVisualizationState = () => {
44
45
  const filteredGroupBy = groupBy.filter(item => !levelsOfProfiling.includes(item));
45
46
  setGroupBy([...filteredGroupBy, key]); // add
46
47
  }
47
- }, [groupBy, setGroupBy, levelsOfProfiling]);
48
+ resetFlameGraphState();
49
+ }, [groupBy, setGroupBy, levelsOfProfiling, resetFlameGraphState]);
48
50
  const setGroupByLabels = useCallback((labels) => {
49
51
  setGroupBy(groupBy.filter(l => !l.startsWith(`${FIELD_LABELS}.`)).concat(labels));
50
52
  }, [groupBy, setGroupBy]);
@@ -52,8 +54,6 @@ export const useVisualizationState = () => {
52
54
  setSandwichFunctionName(undefined);
53
55
  }, [setSandwichFunctionName]);
54
56
  return {
55
- curPath,
56
- setCurPath,
57
57
  curPathArrow,
58
58
  setCurPathArrow,
59
59
  colorStackLegend,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,iMAczB,gBAAgB,KAAG,GAAG,CAAC,OA+HzB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileView/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAC,gBAAgB,EAAoB,MAAM,uBAAuB,CAAC;AAE/E,eAAO,MAAM,WAAW,GAAI,iMAczB,gBAAgB,KAAG,GAAG,CAAC,OA2HzB,CAAC"}