@parca/profile 0.16.92 → 0.16.93

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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
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.16.93](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.92...@parca/profile@0.16.93) (2023-01-11)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
6
10
  ## [0.16.92](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.89...@parca/profile@0.16.92) (2023-01-11)
7
11
 
8
12
  **Note:** Version bump only for package @parca/profile
@@ -64,8 +64,7 @@ import * as d3 from 'd3';
64
64
  import { Stage, Layer, Rect, Arrow, Text, Label } from 'react-konva';
65
65
  import { Button } from '@parca/components';
66
66
  import { jsonToDot, getCurvePoints } from './utils';
67
- import { useAppSelector, selectSearchNodeString } from '@parca/store';
68
- import { isSearchMatch } from '@parca/functions';
67
+ import { isSearchMatch, selectQueryParam } from '@parca/functions';
69
68
  import Tooltip from '../GraphTooltip';
70
69
  import { DEFAULT_NODE_HEIGHT, GRAPH_MARGIN } from './constants';
71
70
  var Node = function (_a) {
@@ -97,18 +96,18 @@ var Edge = function (_a) {
97
96
  return (_jsx(Arrow, { points: points, bezier: true, stroke: color, strokeWidth: 3, pointerLength: 10, pointerWidth: 10, fill: color, opacity: isCurrentSearchMatch ? Number(opacity) : 0 }));
98
97
  };
99
98
  var Callgraph = function (_a) {
100
- var _b, _c;
99
+ var _b, _c, _d;
101
100
  var graph = _a.graph, sampleUnit = _a.sampleUnit, width = _a.width, colorRange = _a.colorRange;
102
101
  var containerRef = useRef(null);
103
- var _d = useState(null), graphData = _d[0], setGraphData = _d[1];
104
- var _e = useState(null), hoveredNode = _e[0], setHoveredNode = _e[1];
105
- var _f = useState({
102
+ var _e = useState(null), graphData = _e[0], setGraphData = _e[1];
103
+ var _f = useState(null), hoveredNode = _f[0], setHoveredNode = _f[1];
104
+ var _g = useState({
106
105
  scale: { x: 1, y: 1 },
107
106
  x: 0,
108
107
  y: 0,
109
- }), stage = _f[0], setStage = _f[1];
108
+ }), stage = _g[0], setStage = _g[1];
110
109
  var rawNodes = graph.nodes, total = graph.cumulative;
111
- var currentSearchString = useAppSelector(selectSearchNodeString);
110
+ var currentSearchString = (_b = selectQueryParam('search_string')) !== null && _b !== void 0 ? _b : '';
112
111
  var isSearchEmpty = currentSearchString === undefined || currentSearchString === '';
113
112
  useEffect(function () {
114
113
  var getDataWithPositions = function () { return __awaiter(void 0, void 0, void 0, function () {
@@ -139,7 +138,9 @@ var Callgraph = function (_a) {
139
138
  // 3. Render the graph with calculated layout in Canvas container
140
139
  if (width == null || graphData == null)
141
140
  return _jsx(_Fragment, {});
142
- var _g = JSON.parse(graphData), gvizNodes = _g.objects, edges = _g.edges, boundingBox = _g.bb;
141
+ var _h = JSON.parse(graphData), gvizNodes = _h.objects, edges = _h.edges, boundingBox = _h.bb;
142
+ if (gvizNodes.length < 1)
143
+ return _jsx(_Fragment, { children: "Profile has no samples" });
143
144
  var graphBB = boundingBox.split(',');
144
145
  var bbWidth = Number(graphBB[2]);
145
146
  var bbHeight = Number(graphBB[3]);
@@ -217,6 +218,6 @@ var Callgraph = function (_a) {
217
218
  ? true
218
219
  : isSearchMatch(currentSearchString, node.functionName);
219
220
  return (_jsx(Node, { node: node, hoveredNode: hoveredNode, setHoveredNode: setHoveredNode, isCurrentSearchMatch: isCurrentSearchMatch }, "node-".concat(node._gvid)));
220
- })] })) })), _jsx(Tooltip, { hoveringNode: rawNodes.find(function (n) { return n.id === (hoveredNode === null || hoveredNode === void 0 ? void 0 : hoveredNode.data.id); }), unit: sampleUnit, total: +total, isFixed: false, x: (_b = hoveredNode === null || hoveredNode === void 0 ? void 0 : hoveredNode.mouseX) !== null && _b !== void 0 ? _b : 0, y: (_c = hoveredNode === null || hoveredNode === void 0 ? void 0 : hoveredNode.mouseY) !== null && _c !== void 0 ? _c : 0, contextElement: containerRef.current }), stage.scale.x !== 1 && (_jsx(Button, __assign({ className: "w-auto !absolute top-0 right-0", variant: "neutral", onClick: resetZoom }, { children: "Reset Zoom" })))] })) })));
221
+ })] })) })), _jsx(Tooltip, { hoveringNode: rawNodes.find(function (n) { return n.id === (hoveredNode === null || hoveredNode === void 0 ? void 0 : hoveredNode.data.id); }), unit: sampleUnit, total: +total, isFixed: false, x: (_c = hoveredNode === null || hoveredNode === void 0 ? void 0 : hoveredNode.mouseX) !== null && _c !== void 0 ? _c : 0, y: (_d = hoveredNode === null || hoveredNode === void 0 ? void 0 : hoveredNode.mouseY) !== null && _d !== void 0 ? _d : 0, contextElement: containerRef.current }), stage.scale.x !== 1 && (_jsx(Button, __assign({ className: "w-auto !absolute top-0 left-0", variant: "neutral", onClick: resetZoom }, { children: "Reset Zoom" })))] })) })));
221
222
  };
222
223
  export default Callgraph;
@@ -27,9 +27,10 @@ import { throttle } from 'lodash';
27
27
  import { pointer } from 'd3-selection';
28
28
  import { scaleLinear } from 'd3-scale';
29
29
  import GraphTooltip from './GraphTooltip';
30
- import { diffColor, getLastItem, isSearchMatch } from '@parca/functions';
31
- import { selectDarkMode, selectSearchNodeString, useAppSelector } from '@parca/store';
30
+ import { diffColor, getLastItem, isSearchMatch, selectQueryParam } from '@parca/functions';
31
+ import { selectDarkMode, useAppSelector } from '@parca/store';
32
32
  import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
33
+ import { Button } from '@parca/components';
33
34
  import { hexifyAddress } from './utils';
34
35
  var RowHeight = 26;
35
36
  var icicleRectStyles = {
@@ -42,8 +43,9 @@ var fadedIcicleRectStyles = {
42
43
  opacity: '0.5',
43
44
  };
44
45
  function IcicleRect(_a) {
46
+ var _b;
45
47
  var x = _a.x, y = _a.y, width = _a.width, height = _a.height, color = _a.color, name = _a.name, onMouseEnter = _a.onMouseEnter, onMouseLeave = _a.onMouseLeave, onClick = _a.onClick, curPath = _a.curPath;
46
- var currentSearchString = useAppSelector(selectSearchNodeString);
48
+ var currentSearchString = (_b = selectQueryParam('search_string')) !== null && _b !== void 0 ? _b : '';
47
49
  var isFaded = curPath.length > 0 && name !== curPath[curPath.length - 1];
48
50
  var styles = isFaded ? fadedIcicleRectStyles : icicleRectStyles;
49
51
  return (_jsxs("g", __assign({ transform: "translate(".concat(x + 1, ", ").concat(y + 1, ")"), style: styles, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onClick: onClick }, { children: [_jsx("rect", { x: 0, y: 0, width: width - 1, height: height - 1, style: {
@@ -169,5 +171,5 @@ export default function IcicleGraph(_a) {
169
171
  var rel = pointer(e);
170
172
  throttledSetPos([rel[0], rel[1]]);
171
173
  };
172
- return (_jsxs("div", __assign({ onMouseLeave: function () { return setHoveringNode(undefined); } }, { children: [_jsx(GraphTooltip, { unit: sampleUnit, total: total, x: pos[0], y: pos[1], hoveringNode: hoveringNode, contextElement: svg.current, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function }), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height, onMouseMove: onMouseMove, preserveAspectRatio: "xMinYMid", ref: svg }, { children: _jsx("g", __assign({ ref: ref }, { children: _jsx(MemoizedIcicleGraphRootNode, { node: graph.root, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function, setHoveringNode: setHoveringNode, curPath: curPath, setCurPath: setCurPath, xScale: xScale, total: total, totalWidth: width }) })) }))] })));
174
+ return (_jsxs("div", __assign({ onMouseLeave: function () { return setHoveringNode(undefined); } }, { children: [_jsx(GraphTooltip, { unit: sampleUnit, total: total, x: pos[0], y: pos[1], hoveringNode: hoveringNode, contextElement: svg.current, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function }), _jsx("div", __assign({ className: "w-full flex justify-start" }, { children: _jsx(Button, __assign({ color: "neutral", onClick: function () { return setCurPath([]); }, disabled: curPath.length === 0, className: "w-auto", variant: "neutral" }, { children: "Reset zoom" })) })), _jsx("svg", __assign({ className: "font-robotoMono", width: width, height: height, onMouseMove: onMouseMove, preserveAspectRatio: "xMinYMid", ref: svg }, { children: _jsx("g", __assign({ ref: ref }, { children: _jsx(MemoizedIcicleGraphRootNode, { node: graph.root, strings: graph.stringTable, mappings: graph.mapping, locations: graph.locations, functions: graph.function, setHoveringNode: setHoveringNode, curPath: curPath, setCurPath: setCurPath, xScale: xScale, total: total, totalWidth: width }) })) }))] })));
173
175
  }
@@ -1,6 +1,7 @@
1
1
  /// <reference types="react" />
2
- import { ProfileSelection, NavigateFunction } from '..';
2
+ import { NavigateFunction } from '@parca/functions';
3
3
  import { QueryServiceClient } from '@parca/client';
4
+ import { ProfileSelection } from '..';
4
5
  import { QuerySelection } from '../ProfileSelector';
5
6
  interface ProfileExplorerCompareProps {
6
7
  queryClient: QueryServiceClient;
@@ -10,20 +10,8 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
- // Copyright 2022 The Parca Authors
14
- // Licensed under the Apache License, Version 2.0 (the "License");
15
- // you may not use this file except in compliance with the License.
16
- // You may obtain a copy of the License at
17
- //
18
- // http://www.apache.org/licenses/LICENSE-2.0
19
- //
20
- // Unless required by applicable law or agreed to in writing, software
21
- // distributed under the License is distributed on an "AS IS" BASIS,
22
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
- // See the License for the specific language governing permissions and
24
- // limitations under the License.
25
- import { ProfileDiffSource, ProfileViewWithData } from '..';
26
13
  import { Query } from '@parca/parser';
14
+ import { ProfileDiffSource, ProfileViewWithData } from '..';
27
15
  import ProfileSelector from '../ProfileSelector';
28
16
  var ProfileExplorerCompare = function (_a) {
29
17
  var queryClient = _a.queryClient, queryA = _a.queryA, queryB = _a.queryB, profileA = _a.profileA, profileB = _a.profileB, selectQueryA = _a.selectQueryA, selectQueryB = _a.selectQueryB, selectProfileA = _a.selectProfileA, selectProfileB = _a.selectProfileB, closeProfile = _a.closeProfile, navigateTo = _a.navigateTo;
@@ -1,6 +1,7 @@
1
1
  /// <reference types="react" />
2
+ import { NavigateFunction } from '@parca/functions';
2
3
  import { QueryServiceClient } from '@parca/client';
3
- import { ProfileSelection, NavigateFunction } from '..';
4
+ import { ProfileSelection } from '..';
4
5
  import { QuerySelection } from '../ProfileSelector';
5
6
  interface ProfileExplorerSingleProps {
6
7
  queryClient: QueryServiceClient;
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
- import { NavigateFunction } from '..';
3
2
  import { QueryServiceClient } from '@parca/client';
3
+ import { NavigateFunction } from '@parca/functions';
4
4
  interface ProfileExplorerProps {
5
5
  queryClient: QueryServiceClient;
6
6
  queryParams: any;
@@ -13,14 +13,14 @@ import { jsx as _jsx } from "react/jsx-runtime";
13
13
  import { ProfileSelectionFromParams, SuffixParams } from '..';
14
14
  import ProfileExplorerSingle from './ProfileExplorerSingle';
15
15
  import ProfileExplorerCompare from './ProfileExplorerCompare';
16
- import { useAppSelector, useAppDispatch, setCompare, selectCompareMode, setSearchNodeString, store, selectFilterByFunction, } from '@parca/store';
17
- import { Provider, batch } from 'react-redux';
16
+ import { store } from '@parca/store';
17
+ import { Provider } from 'react-redux';
18
18
  import { DateTimeRange } from '@parca/components';
19
- import { useEffect } from 'react';
20
19
  var getExpressionAsAString = function (expression) {
21
20
  var x = Array.isArray(expression) ? expression.join() : expression;
22
21
  return x;
23
22
  };
23
+ var DEFAULT_DASHBOARD_ITEMS = ['icicle'];
24
24
  /* eslint-disable @typescript-eslint/naming-convention */
25
25
  var sanitizeDateRange = function (time_selection_a, from_a, to_a) {
26
26
  var range = DateTimeRange.fromRangeKey(time_selection_a);
@@ -49,12 +49,9 @@ var swapQueryParameters = function (o) {
49
49
  var ProfileExplorerApp = function (_a) {
50
50
  var _b, _c;
51
51
  var queryClient = _a.queryClient, queryParams = _a.queryParams, navigateTo = _a.navigateTo;
52
- var dispatch = useAppDispatch();
53
- var compareMode = useAppSelector(selectCompareMode);
54
52
  /* eslint-disable @typescript-eslint/naming-convention */
55
- var from_a = queryParams.from_a, to_a = queryParams.to_a, merge_a = queryParams.merge_a, profile_name_a = queryParams.profile_name_a, labels_a = queryParams.labels_a, time_a = queryParams.time_a, time_selection_a = queryParams.time_selection_a, compare_a = queryParams.compare_a, from_b = queryParams.from_b, to_b = queryParams.to_b, merge_b = queryParams.merge_b, profile_name_b = queryParams.profile_name_b, labels_b = queryParams.labels_b, time_b = queryParams.time_b, time_selection_b = queryParams.time_selection_b, compare_b = queryParams.compare_b;
53
+ var from_a = queryParams.from_a, to_a = queryParams.to_a, merge_a = queryParams.merge_a, profile_name_a = queryParams.profile_name_a, labels_a = queryParams.labels_a, time_a = queryParams.time_a, time_selection_a = queryParams.time_selection_a, compare_a = queryParams.compare_a, from_b = queryParams.from_b, to_b = queryParams.to_b, merge_b = queryParams.merge_b, profile_name_b = queryParams.profile_name_b, labels_b = queryParams.labels_b, time_b = queryParams.time_b, time_selection_b = queryParams.time_selection_b, compare_b = queryParams.compare_b, filter_by_function = queryParams.filter_by_function, dashboard_items = queryParams.dashboard_items;
56
54
  /* eslint-enable @typescript-eslint/naming-convention */
57
- var filterByFunction = useAppSelector(selectFilterByFunction);
58
55
  var sanitizedRange = sanitizeDateRange(time_selection_a, from_a, to_a);
59
56
  time_selection_a = sanitizedRange.time_selection_a;
60
57
  from_a = sanitizedRange.from_a;
@@ -67,18 +64,10 @@ var ProfileExplorerApp = function (_a) {
67
64
  queryParams.expression_a = expression_a;
68
65
  if (((_c = queryParams === null || queryParams === void 0 ? void 0 : queryParams.expression_b) !== null && _c !== void 0 ? _c : '') !== '')
69
66
  queryParams.expression_b = expression_b;
70
- useEffect(function () {
71
- if (compare_a === 'true' && compare_b === 'true') {
72
- dispatch(setCompare(true));
73
- }
74
- else {
75
- dispatch(setCompare(false));
76
- }
77
- }, [dispatch, compare_a, compare_b]);
78
67
  var selectProfile = function (p, suffix) {
79
68
  queryParams.expression_a = encodeURIComponent(queryParams.expression_a);
80
69
  queryParams.expression_b = encodeURIComponent(queryParams.expression_b);
81
- return navigateTo('/', __assign(__assign({}, queryParams), SuffixParams(p.HistoryParams(), suffix)));
70
+ return navigateTo('/', __assign(__assign(__assign({}, queryParams), SuffixParams(p.HistoryParams(), suffix)), { dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }));
82
71
  };
83
72
  var selectProfileA = function (p) {
84
73
  return selectProfile(p, '_a');
@@ -96,7 +85,7 @@ var ProfileExplorerApp = function (_a) {
96
85
  profile_name: profile_name_a,
97
86
  timeSelection: time_selection_a,
98
87
  };
99
- var profile_1 = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a, filterByFunction);
88
+ var profile_1 = ProfileSelectionFromParams(expression_a, from_a, to_a, merge_a, labels_a, profile_name_a, time_a, filter_by_function);
100
89
  var selectQuery = function (q) {
101
90
  return navigateTo('/', __assign(__assign({}, filterSuffix(queryParams, '_a')), {
102
91
  expression_a: encodeURIComponent(q.expression),
@@ -104,12 +93,12 @@ var ProfileExplorerApp = function (_a) {
104
93
  to_a: q.to.toString(),
105
94
  merge_a: q.merge,
106
95
  time_selection_a: q.timeSelection,
107
- currentProfileView: 'icicle',
96
+ dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
108
97
  }));
109
98
  };
110
99
  var selectProfile_1 = function (p) {
111
100
  queryParams.expression_a = encodeURIComponent(queryParams.expression_a);
112
- return navigateTo('/', __assign(__assign({}, queryParams), SuffixParams(p.HistoryParams(), '_a')));
101
+ return navigateTo('/', __assign(__assign(__assign({}, queryParams), SuffixParams(p.HistoryParams(), '_a')), { dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }));
113
102
  };
114
103
  var compareProfile = function () {
115
104
  var compareQuery = {
@@ -131,14 +120,7 @@ var ProfileExplorerApp = function (_a) {
131
120
  if (profile_1 != null) {
132
121
  compareQuery = __assign(__assign({}, SuffixParams(profile_1.HistoryParams(), '_a')), compareQuery);
133
122
  }
134
- compareQuery = __assign(__assign({}, compareQuery), {
135
- currentProfileView: 'icicle',
136
- });
137
- batch(function () {
138
- dispatch(setCompare(!compareMode));
139
- dispatch(setSearchNodeString(undefined));
140
- });
141
- void navigateTo('/', compareQuery);
123
+ void navigateTo('/', __assign(__assign({}, compareQuery), { search_string: '', dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS }));
142
124
  };
143
125
  return (_jsx(ProfileExplorerSingle, { queryClient: queryClient, query: query_1, profile: profile_1, selectQuery: selectQuery, selectProfile: selectProfile_1, compareProfile: compareProfile, navigateTo: navigateTo }));
144
126
  }
@@ -169,7 +151,8 @@ var ProfileExplorerApp = function (_a) {
169
151
  to_a: q.to.toString(),
170
152
  merge_a: q.merge,
171
153
  time_selection_a: q.timeSelection,
172
- filterByFunction: filterByFunction,
154
+ filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '',
155
+ dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
173
156
  }));
174
157
  };
175
158
  var selectQueryB = function (q) {
@@ -181,7 +164,8 @@ var ProfileExplorerApp = function (_a) {
181
164
  to_b: q.to.toString(),
182
165
  merge_b: q.merge,
183
166
  time_selection_b: q.timeSelection,
184
- filterByFunction: filterByFunction,
167
+ filter_by_function: filter_by_function !== null && filter_by_function !== void 0 ? filter_by_function : '',
168
+ dashboard_items: dashboard_items !== null && dashboard_items !== void 0 ? dashboard_items : DEFAULT_DASHBOARD_ITEMS,
185
169
  }));
186
170
  };
187
171
  var closeProfile = function (card) {
@@ -189,12 +173,10 @@ var ProfileExplorerApp = function (_a) {
189
173
  if (card === 'A') {
190
174
  newQueryParameters = swapQueryParameters(queryParams);
191
175
  }
192
- batch(function () {
193
- dispatch(setCompare(!compareMode));
194
- dispatch(setSearchNodeString(undefined));
195
- });
196
176
  return navigateTo('/', __assign(__assign({}, filterSuffix(newQueryParameters, '_b')), {
197
177
  compare_a: 'false',
178
+ compare_b: 'false',
179
+ search_string: '',
198
180
  }));
199
181
  };
200
182
  return (_jsx(ProfileExplorerCompare, { queryClient: queryClient, queryA: queryA, queryB: queryB, profileA: profileA, profileB: profileB, selectQueryA: selectQueryA, selectQueryB: selectQueryB, selectProfileA: selectProfileA, selectProfileB: selectProfileB, closeProfile: closeProfile, navigateTo: navigateTo }));
@@ -10,15 +10,15 @@ var __assign = (this && this.__assign) || function () {
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
12
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { useAppSelector, selectCompareMode } from '@parca/store';
14
13
  import { useContainerDimensions } from '@parca/dynamicsize';
15
14
  import DiffLegend from '../components/DiffLegend';
16
15
  import IcicleGraph from '../IcicleGraph';
16
+ import { selectQueryParam } from '@parca/functions';
17
17
  import { useEffect, useMemo } from 'react';
18
18
  var numberFormatter = new Intl.NumberFormat('en-US');
19
19
  var ProfileIcicleGraph = function (_a) {
20
20
  var graph = _a.graph, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit, onContainerResize = _a.onContainerResize;
21
- var compareMode = useAppSelector(selectCompareMode);
21
+ var compareMode = Boolean(selectQueryParam('compare_a')) && Boolean(selectQueryParam('compare_b'));
22
22
  var _b = useContainerDimensions(), ref = _b.ref, dimensions = _b.dimensions;
23
23
  useEffect(function () {
24
24
  if (dimensions === undefined)
@@ -1,3 +1,6 @@
1
1
  /// <reference types="react" />
2
- declare const FilterByFunctionButton: () => JSX.Element;
2
+ import { NavigateFunction } from '@parca/functions';
3
+ declare const FilterByFunctionButton: ({ navigateTo, }: {
4
+ navigateTo: NavigateFunction | undefined;
5
+ }) => JSX.Element;
3
6
  export default FilterByFunctionButton;
@@ -12,22 +12,25 @@ import { jsx as _jsx } 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 { Input } from '@parca/components';
15
- import { selectFilterByFunction, setFilterByFunction, useAppDispatch, useAppSelector, } from '@parca/store';
15
+ import { useURLState } from '@parca/functions';
16
16
  import { Icon } from '@iconify/react';
17
17
  import { useCallback, useMemo, useState } from 'react';
18
- var FilterByFunctionButton = function () {
19
- var dispatch = useAppDispatch();
20
- var storeVal = useAppSelector(selectFilterByFunction);
21
- var _a = useState(storeVal !== null && storeVal !== void 0 ? storeVal : ''), value = _a[0], setValue = _a[1];
18
+ var FilterByFunctionButton = function (_a) {
19
+ var navigateTo = _a.navigateTo;
20
+ var _b = useURLState({ param: 'filter_by_function', navigateTo: navigateTo }), storeValue = _b[0], setStoreValue = _b[1];
21
+ var _c = useState(storeValue), localValue = _c[0], setLocalValue = _c[1];
22
22
  var isClearAction = useMemo(function () {
23
- return value === storeVal && value != null;
24
- }, [value, storeVal]);
23
+ return localValue === storeValue && localValue != null && localValue !== '';
24
+ }, [localValue, storeValue]);
25
25
  var onAction = useCallback(function () {
26
- dispatch(setFilterByFunction(isClearAction ? undefined : value));
27
26
  if (isClearAction) {
28
- setValue('');
27
+ setLocalValue('');
28
+ setStoreValue('');
29
29
  }
30
- }, [dispatch, isClearAction, value]);
31
- return (_jsx(Input, { placeholder: "Filter by function", className: "text-sm", onAction: onAction, onChange: function (e) { return setValue(e.target.value); }, value: value, onBlur: function () { return setValue(storeVal !== null && storeVal !== void 0 ? storeVal : ''); }, actionIcon: isClearAction ? _jsx(Icon, { icon: "ep:circle-close" }) : _jsx(Icon, { icon: "ep:arrow-right" }) }));
30
+ else {
31
+ setStoreValue(localValue);
32
+ }
33
+ }, [localValue, isClearAction, setStoreValue]);
34
+ return (_jsx(Input, { placeholder: "Filter by function", className: "text-sm", onAction: onAction, onChange: function (e) { return setLocalValue(e.target.value); }, value: localValue !== null && localValue !== void 0 ? localValue : '', onBlur: function () { return setLocalValue(storeValue); }, actionIcon: isClearAction ? _jsx(Icon, { icon: "ep:circle-close" }) : _jsx(Icon, { icon: "ep:arrow-right" }) }));
32
35
  };
33
36
  export default FilterByFunctionButton;
@@ -0,0 +1,13 @@
1
+ /// <reference types="react" />
2
+ import { NavigateFunction } from '@parca/functions';
3
+ interface Props {
4
+ position: number;
5
+ defaultValue: string;
6
+ navigateTo?: NavigateFunction;
7
+ placeholderText?: string;
8
+ primary?: boolean;
9
+ addView?: boolean;
10
+ disabled?: boolean;
11
+ }
12
+ declare const ViewSelector: ({ defaultValue, navigateTo, position, placeholderText, primary, addView, disabled, }: Props) => JSX.Element;
13
+ export default ViewSelector;
@@ -0,0 +1,80 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ // Copyright 2022 The Parca Authors
14
+ // Licensed under the Apache License, Version 2.0 (the "License");
15
+ // you may not use this file except in compliance with the License.
16
+ // You may obtain a copy of the License at
17
+ //
18
+ // http://www.apache.org/licenses/LICENSE-2.0
19
+ //
20
+ // Unless required by applicable law or agreed to in writing, software
21
+ // distributed under the License is distributed on an "AS IS" BASIS,
22
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
+ // See the License for the specific language governing permissions and
24
+ // limitations under the License.
25
+ import { Select } from '@parca/components';
26
+ import { useURLState } from '@parca/functions';
27
+ import useUIFeatureFlag from '@parca/functions/useUIFeatureFlag';
28
+ var ViewSelector = function (_a) {
29
+ var defaultValue = _a.defaultValue, navigateTo = _a.navigateTo, position = _a.position, placeholderText = _a.placeholderText, _b = _a.primary, primary = _b === void 0 ? false : _b, _c = _a.addView, addView = _c === void 0 ? false : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d;
30
+ var callgraphEnabled = useUIFeatureFlag('callgraph')[0];
31
+ var _e = useURLState({
32
+ param: 'dashboard_items',
33
+ navigateTo: navigateTo,
34
+ }), dashboardItems = _e[0], setDashboardItems = _e[1];
35
+ var allItems = [
36
+ { key: 'table', canBeSelected: !dashboardItems.includes('table') },
37
+ { key: 'icicle', canBeSelected: !dashboardItems.includes('icicle') },
38
+ ];
39
+ if (callgraphEnabled) {
40
+ allItems.push({
41
+ key: 'callgraph',
42
+ canBeSelected: !dashboardItems.includes('callgraph'),
43
+ });
44
+ }
45
+ var getOption = function (_a) {
46
+ var key = _a.key, supportingText = _a.supportingText;
47
+ var capitalizeFirstLetter = function (string) {
48
+ return "".concat(string.charAt(0).toUpperCase()).concat(string.slice(1));
49
+ };
50
+ var title = capitalizeFirstLetter(key);
51
+ return {
52
+ active: _jsx(_Fragment, { children: title }),
53
+ expanded: (_jsxs(_Fragment, { children: [_jsx("span", { children: title }), supportingText !== null && _jsx("span", __assign({ className: "text-xs" }, { children: supportingText }))] })),
54
+ };
55
+ };
56
+ var items = allItems.map(function (item) { return ({
57
+ key: item.key,
58
+ disabled: !item.canBeSelected,
59
+ element: getOption(item),
60
+ }); });
61
+ var onSelection = function (value) {
62
+ if (addView) {
63
+ setDashboardItems([dashboardItems[0], value]);
64
+ return;
65
+ }
66
+ var isOnlyChart = dashboardItems.length === 1;
67
+ if (isOnlyChart) {
68
+ setDashboardItems([value]);
69
+ return;
70
+ }
71
+ // Note: this will need to be updated if we ever have more more than 2 panels
72
+ var isFirstChart = position === 0;
73
+ var newDashboardItems = isFirstChart
74
+ ? [value, dashboardItems[1]]
75
+ : [dashboardItems[0], value];
76
+ setDashboardItems(newDashboardItems);
77
+ };
78
+ return (_jsx(Select, { items: items, selectedKey: defaultValue, onSelection: onSelection, placeholder: placeholderText !== null && placeholderText !== void 0 ? placeholderText : 'Select view type...', primary: primary, disabled: disabled }));
79
+ };
80
+ export default ViewSelector;
@@ -3,7 +3,9 @@ import { QueryServiceClient, Flamegraph, Top, Callgraph as CallgraphType } from
3
3
  import { ResizeHandler } from '../ProfileIcicleGraph';
4
4
  import { ProfileSource } from '../ProfileSource';
5
5
  import '../ProfileView.styles.css';
6
- type NavigateFunction = (path: string, queryParams: any) => void;
6
+ type NavigateFunction = (path: string, queryParams: any, options?: {
7
+ replace?: boolean;
8
+ }) => void;
7
9
  export interface FlamegraphData {
8
10
  loading: boolean;
9
11
  data?: Flamegraph;
@@ -19,17 +21,11 @@ interface CallgraphData {
19
21
  data?: CallgraphType;
20
22
  error?: any;
21
23
  }
22
- export type VisualizationType = 'icicle' | 'table' | 'callgraph' | 'both';
23
- export interface ProfileVisState {
24
- currentView: VisualizationType;
25
- setCurrentView: (view: VisualizationType) => void;
26
- }
27
24
  export interface ProfileViewProps {
28
25
  flamegraphData?: FlamegraphData;
29
26
  topTableData?: TopTableData;
30
27
  callgraphData?: CallgraphData;
31
28
  sampleUnit: string;
32
- profileVisState: ProfileVisState;
33
29
  profileSource?: ProfileSource;
34
30
  queryClient?: QueryServiceClient;
35
31
  navigateTo?: NavigateFunction;
@@ -37,6 +33,5 @@ export interface ProfileViewProps {
37
33
  onDownloadPProf: () => void;
38
34
  onFlamegraphContainerResize?: ResizeHandler;
39
35
  }
40
- export declare const useProfileVisState: () => ProfileVisState;
41
- export declare const ProfileView: ({ flamegraphData, topTableData, callgraphData, sampleUnit, profileSource, queryClient, navigateTo, profileVisState, onDownloadPProf, onFlamegraphContainerResize, }: ProfileViewProps) => JSX.Element;
36
+ export declare const ProfileView: ({ flamegraphData, topTableData, callgraphData, sampleUnit, profileSource, queryClient, navigateTo, onDownloadPProf, onFlamegraphContainerResize, }: ProfileViewProps) => JSX.Element;
42
37
  export {};