@parca/profile 0.19.144 → 0.19.145
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 +4 -0
- package/dist/MatchersInput/SuggestionsList.d.ts.map +1 -1
- package/dist/MatchersInput/SuggestionsList.js +73 -63
- package/dist/MatchersInput/index.d.ts.map +1 -1
- package/dist/MatchersInput/index.js +4 -5
- package/dist/ProfileTypeSelector/index.d.ts.map +1 -1
- package/dist/ProfileTypeSelector/index.js +33 -52
- package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -1
- package/dist/ProfileView/components/ColorStackLegend.js +70 -118
- package/dist/ProfileView/components/ProfileFilters/index.d.ts.map +1 -1
- package/dist/ProfileView/components/ProfileFilters/index.js +0 -1
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +319 -123
- package/dist/SelectWithRefresh/index.js +38 -33
- package/dist/SimpleMatchers/Select.d.ts.map +1 -1
- package/dist/SimpleMatchers/Select.js +63 -68
- package/dist/SourceView/Highlighter.d.ts.map +1 -1
- package/dist/SourceView/Highlighter.js +1 -1
- package/package.json +3 -3
- package/src/MatchersInput/SuggestionsList.tsx +71 -86
- package/src/MatchersInput/index.tsx +61 -74
- package/src/ProfileTypeSelector/index.tsx +4 -7
- package/src/ProfileView/components/ColorStackLegend.tsx +15 -23
- package/src/ProfileView/components/ProfileFilters/index.tsx +8 -13
- package/src/ProfileView/components/Toolbars/TableColumnsDropdown.tsx +113 -115
- package/src/SelectWithRefresh/index.tsx +28 -28
- package/src/SimpleMatchers/Select.tsx +29 -37
- package/src/SourceView/Highlighter.tsx +2 -2
|
@@ -32,7 +32,7 @@ import { c as _c } from "react-compiler-runtime";
|
|
|
32
32
|
// See the License for the specific language governing permissions and
|
|
33
33
|
// limitations under the License.
|
|
34
34
|
|
|
35
|
-
import React, {
|
|
35
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
36
36
|
import { Icon } from '@iconify/react';
|
|
37
37
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
38
38
|
import cx from 'classnames';
|
|
@@ -41,6 +41,7 @@ import { Button, DividerWithLabel, RefreshButton, useParcaContext } from '@parca
|
|
|
41
41
|
import { TEST_IDS, testId } from '@parca/test-utils/dist/test-ids';
|
|
42
42
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
43
43
|
var CustomSelect = function CustomSelect(_ref) {
|
|
44
|
+
var _filteredItems$reduce, _filteredItems$reduce2;
|
|
44
45
|
var itemsProp = _ref.items,
|
|
45
46
|
selectedKey = _ref.selectedKey,
|
|
46
47
|
onSelection = _ref.onSelection,
|
|
@@ -92,29 +93,34 @@ var CustomSelect = function CustomSelect(_ref) {
|
|
|
92
93
|
var containerRef = useRef(null);
|
|
93
94
|
var optionsRef = useRef(null);
|
|
94
95
|
var searchInputRef = useRef(null);
|
|
95
|
-
var handleRefetch =
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
96
|
+
var handleRefetch = /*#__PURE__*/function () {
|
|
97
|
+
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
98
|
+
return _regenerator().w(function (_context) {
|
|
99
|
+
while (1) switch (_context.p = _context.n) {
|
|
100
|
+
case 0:
|
|
101
|
+
if (!(refetchValues == null || isRefetching)) {
|
|
102
|
+
_context.n = 1;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
return _context.a(2);
|
|
106
|
+
case 1:
|
|
107
|
+
setIsRefetching(true);
|
|
108
|
+
_context.p = 2;
|
|
109
|
+
_context.n = 3;
|
|
110
|
+
return refetchValues();
|
|
111
|
+
case 3:
|
|
112
|
+
_context.p = 3;
|
|
113
|
+
setIsRefetching(false);
|
|
114
|
+
return _context.f(3);
|
|
115
|
+
case 4:
|
|
116
|
+
return _context.a(2);
|
|
117
|
+
}
|
|
118
|
+
}, _callee, null, [[2,, 3, 4]]);
|
|
119
|
+
}));
|
|
120
|
+
return function handleRefetch() {
|
|
121
|
+
return _ref2.apply(this, arguments);
|
|
122
|
+
};
|
|
123
|
+
}();
|
|
118
124
|
useEffect(function () {
|
|
119
125
|
var timer = setTimeout(function () {
|
|
120
126
|
return setDebouncedSearchTerm(searchTerm);
|
|
@@ -123,23 +129,18 @@ var CustomSelect = function CustomSelect(_ref) {
|
|
|
123
129
|
return clearTimeout(timer);
|
|
124
130
|
};
|
|
125
131
|
}, [searchTerm]);
|
|
126
|
-
var items =
|
|
127
|
-
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
return _objectSpread(_objectSpread({}, v), {}, {
|
|
131
|
-
type: item.type
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
return itemsProp.map(function (item_0) {
|
|
137
|
-
return _objectSpread(_objectSpread({}, item_0), {}, {
|
|
138
|
-
type: ''
|
|
132
|
+
var items = itemsProp[0] != null && 'type' in itemsProp[0] ? itemsProp.flatMap(function (item) {
|
|
133
|
+
return item.values.map(function (v) {
|
|
134
|
+
return _objectSpread(_objectSpread({}, v), {}, {
|
|
135
|
+
type: item.type
|
|
139
136
|
});
|
|
140
137
|
});
|
|
141
|
-
}
|
|
142
|
-
|
|
138
|
+
}) : itemsProp.map(function (item_0) {
|
|
139
|
+
return _objectSpread(_objectSpread({}, item_0), {}, {
|
|
140
|
+
type: ''
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
var computeFilteredItems = function computeFilteredItems() {
|
|
143
144
|
if (!searchable) return items;
|
|
144
145
|
var lowerSearch = debouncedSearchTerm.toLowerCase();
|
|
145
146
|
var filtered = items.filter(function (item_1) {
|
|
@@ -153,7 +154,8 @@ var CustomSelect = function CustomSelect(_ref) {
|
|
|
153
154
|
return filtered.sort(function (a_0, b_0) {
|
|
154
155
|
return levenshtein.get(a_0.key, debouncedSearchTerm) - levenshtein.get(b_0.key, debouncedSearchTerm);
|
|
155
156
|
});
|
|
156
|
-
}
|
|
157
|
+
};
|
|
158
|
+
var filteredItems = computeFilteredItems();
|
|
157
159
|
var selection = editable ? selectedKey : items.find(function (v_0) {
|
|
158
160
|
return v_0.key === selectedKey;
|
|
159
161
|
});
|
|
@@ -252,29 +254,25 @@ var CustomSelect = function CustomSelect(_ref) {
|
|
|
252
254
|
e_0.target.value = '';
|
|
253
255
|
e_0.target.value = value_0;
|
|
254
256
|
};
|
|
255
|
-
var groupedFilteredItems =
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return g.type === item_2.type;
|
|
259
|
-
});
|
|
260
|
-
if (group != null) {
|
|
261
|
-
group.values.push(item_2);
|
|
262
|
-
} else {
|
|
263
|
-
acc.push({
|
|
264
|
-
type: item_2.type,
|
|
265
|
-
values: [item_2]
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
return acc;
|
|
269
|
-
}, []).sort(function (a_1, b_1) {
|
|
270
|
-
return a_1.values.length - b_1.values.length;
|
|
271
|
-
});
|
|
272
|
-
}, [filteredItems]);
|
|
273
|
-
var showHeaders = useMemo(function () {
|
|
274
|
-
return groupedFilteredItems.length > 1 && groupedFilteredItems.every(function (g_0) {
|
|
275
|
-
return g_0.type !== '';
|
|
257
|
+
var groupedFilteredItems = filteredItems.reduce(function (acc, item_2) {
|
|
258
|
+
var group = acc.find(function (g) {
|
|
259
|
+
return g.type === item_2.type;
|
|
276
260
|
});
|
|
277
|
-
|
|
261
|
+
if (group != null) {
|
|
262
|
+
group.values.push(item_2);
|
|
263
|
+
} else {
|
|
264
|
+
acc.push({
|
|
265
|
+
type: item_2.type,
|
|
266
|
+
values: [item_2]
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
return acc;
|
|
270
|
+
}, []).sort(function (a_1, b_1) {
|
|
271
|
+
return a_1.values.length - b_1.values.length;
|
|
272
|
+
});
|
|
273
|
+
var showHeaders = groupedFilteredItems.length > 1 && groupedFilteredItems.every(function (g_0) {
|
|
274
|
+
return g_0.type !== '';
|
|
275
|
+
});
|
|
278
276
|
var flatList = useMemo(function () {
|
|
279
277
|
var list = [];
|
|
280
278
|
var optionIndex = 0;
|
|
@@ -314,12 +312,9 @@ var CustomSelect = function CustomSelect(_ref) {
|
|
|
314
312
|
}
|
|
315
313
|
return list;
|
|
316
314
|
}, [groupedFilteredItems, showHeaders]);
|
|
317
|
-
var longestKey =
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return a_2.key.length > b_2.key.length ? a_2 : b_2;
|
|
321
|
-
}, filteredItems[0])) === null || _filteredItems$reduce2 === void 0 ? void 0 : _filteredItems$reduce2.key) !== null && _filteredItems$reduce !== void 0 ? _filteredItems$reduce : '';
|
|
322
|
-
}, [filteredItems]);
|
|
315
|
+
var longestKey = (_filteredItems$reduce = (_filteredItems$reduce2 = filteredItems.reduce(function (a_2, b_2) {
|
|
316
|
+
return a_2.key.length > b_2.key.length ? a_2 : b_2;
|
|
317
|
+
}, filteredItems[0])) === null || _filteredItems$reduce2 === void 0 ? void 0 : _filteredItems$reduce2.key) !== null && _filteredItems$reduce !== void 0 ? _filteredItems$reduce : '';
|
|
323
318
|
var rowVirtualizer = useVirtualizer({
|
|
324
319
|
count: flatList.length,
|
|
325
320
|
getScrollElement: function getScrollElement() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Highlighter.d.ts","sourceRoot":"","sources":["../../src/SourceView/Highlighter.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"Highlighter.d.ts","sourceRoot":"","sources":["../../src/SourceView/Highlighter.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,iBAAiB,EAAQ,MAAM,OAAO,CAAC;AAI/C,OAAO,EAAC,KAAK,kBAAkB,EAAC,MAAM,0BAA0B,CAAC;AAcjE,UAAU,aAAa;IAErB,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,UAAU,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAC7C,eAAe,EAAE,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;CACxD;AAED,KAAK,QAAQ,GAAG,CAAC,EAAC,IAAI,EAAE,UAAU,EAAE,eAAe,EAAC,EAAE,aAAa,KAAK,GAAG,CAAC,OAAO,CAAC;AAEpF,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAuED,MAAM,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,GAAG,SAAS,CAAC;AAEpG,eAAO,MAAM,oBAAoB,GAC/B,aAAa,cAAc,EAC3B,OAAO,MAAM,EACb,UAAU,MAAM,EAChB,eAAe,iBAAiB,CAAC,cAAc,CAAC,KAC/C,QAqEF,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,6BAA2B,gBAAgB,KAAG,GAAG,CAAC,OAyC7E,CAAC"}
|
|
@@ -12,7 +12,7 @@ import { c as _c } from "react-compiler-runtime";
|
|
|
12
12
|
// See the License for the specific language governing permissions and
|
|
13
13
|
// limitations under the License.
|
|
14
14
|
|
|
15
|
-
import { useId
|
|
15
|
+
import { useId } from 'react';
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import { scaleLinear } from 'd3-scale';
|
|
18
18
|
import createElement from 'react-syntax-highlighter/dist/cjs/create-element';
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.145",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@floating-ui/react": "^0.27.12",
|
|
7
7
|
"@headlessui/react": "^1.7.19",
|
|
8
8
|
"@iconify/react": "^4.0.0",
|
|
9
9
|
"@parca/client": "0.17.23",
|
|
10
|
-
"@parca/components": "0.16.
|
|
10
|
+
"@parca/components": "0.16.416",
|
|
11
11
|
"@parca/dynamicsize": "0.16.74",
|
|
12
12
|
"@parca/hooks": "0.0.125",
|
|
13
13
|
"@parca/icons": "0.16.82",
|
|
@@ -89,5 +89,5 @@
|
|
|
89
89
|
"access": "public",
|
|
90
90
|
"registry": "https://registry.npmjs.org/"
|
|
91
91
|
},
|
|
92
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "125dbac3accf1ebbac6df49dcd72a38c1e6b4d39"
|
|
93
93
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import React, {Fragment,
|
|
14
|
+
import React, {Fragment, useEffect, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {Transition} from '@headlessui/react';
|
|
17
17
|
import {usePopper} from 'react-popper';
|
|
@@ -90,7 +90,7 @@ const SuggestionsList = ({
|
|
|
90
90
|
const [isRefetchingValues, setIsRefetchingValues] = useState(false);
|
|
91
91
|
const [isRefetchingNames, setIsRefetchingNames] = useState(false);
|
|
92
92
|
|
|
93
|
-
const handleRefetchValues =
|
|
93
|
+
const handleRefetchValues = async (): Promise<void> => {
|
|
94
94
|
if (isRefetchingValues) return;
|
|
95
95
|
|
|
96
96
|
setIsRefetchingValues(true);
|
|
@@ -99,9 +99,9 @@ const SuggestionsList = ({
|
|
|
99
99
|
} finally {
|
|
100
100
|
setIsRefetchingValues(false);
|
|
101
101
|
}
|
|
102
|
-
}
|
|
102
|
+
};
|
|
103
103
|
|
|
104
|
-
const handleRefetchNames =
|
|
104
|
+
const handleRefetchNames = async (): Promise<void> => {
|
|
105
105
|
if (isRefetchingNames) return;
|
|
106
106
|
|
|
107
107
|
setIsRefetchingNames(true);
|
|
@@ -110,54 +110,45 @@ const SuggestionsList = ({
|
|
|
110
110
|
} finally {
|
|
111
111
|
setIsRefetchingNames(false);
|
|
112
112
|
}
|
|
113
|
-
}
|
|
113
|
+
};
|
|
114
114
|
|
|
115
115
|
const suggestionsLength =
|
|
116
116
|
suggestions.literals.length + suggestions.labelNames.length + suggestions.labelValues.length;
|
|
117
117
|
|
|
118
|
-
const getSuggestion =
|
|
119
|
-
(index
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
},
|
|
130
|
-
[suggestions]
|
|
131
|
-
);
|
|
118
|
+
const getSuggestion = (index: number): Suggestion => {
|
|
119
|
+
if (index < suggestions.labelNames.length) {
|
|
120
|
+
return suggestions.labelNames[index];
|
|
121
|
+
}
|
|
122
|
+
if (index < suggestions.labelNames.length + suggestions.literals.length) {
|
|
123
|
+
return suggestions.literals[index - suggestions.labelNames.length];
|
|
124
|
+
}
|
|
125
|
+
return suggestions.labelValues[
|
|
126
|
+
index - suggestions.labelNames.length - suggestions.literals.length
|
|
127
|
+
];
|
|
128
|
+
};
|
|
132
129
|
|
|
133
|
-
const resetHighlight =
|
|
134
|
-
(): void => setHighlightedSuggestionIndex(-1),
|
|
135
|
-
[setHighlightedSuggestionIndex]
|
|
136
|
-
);
|
|
130
|
+
const resetHighlight = (): void => setHighlightedSuggestionIndex(-1);
|
|
137
131
|
|
|
138
|
-
const applyHighlightedSuggestion =
|
|
132
|
+
const applyHighlightedSuggestion = (): void => {
|
|
139
133
|
applySuggestion(getSuggestion(highlightedSuggestionIndex));
|
|
140
134
|
resetHighlight();
|
|
141
|
-
}
|
|
135
|
+
};
|
|
142
136
|
|
|
143
|
-
const applySuggestionWithIndex =
|
|
144
|
-
(index
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
},
|
|
148
|
-
[resetHighlight, applySuggestion, getSuggestion]
|
|
149
|
-
);
|
|
137
|
+
const applySuggestionWithIndex = (index: number): void => {
|
|
138
|
+
applySuggestion(getSuggestion(index));
|
|
139
|
+
resetHighlight();
|
|
140
|
+
};
|
|
150
141
|
|
|
151
|
-
const highlightNext =
|
|
142
|
+
const highlightNext = (): void => {
|
|
152
143
|
const nextIndex = highlightedSuggestionIndex + 1;
|
|
153
144
|
if (nextIndex === suggestionsLength) {
|
|
154
145
|
resetHighlight();
|
|
155
146
|
return;
|
|
156
147
|
}
|
|
157
148
|
setHighlightedSuggestionIndex(nextIndex);
|
|
158
|
-
}
|
|
149
|
+
};
|
|
159
150
|
|
|
160
|
-
const highlightPrevious =
|
|
151
|
+
const highlightPrevious = (): void => {
|
|
161
152
|
if (highlightedSuggestionIndex === -1) {
|
|
162
153
|
// Didn't select anything, so starting at the bottom.
|
|
163
154
|
setHighlightedSuggestionIndex(suggestionsLength - 1);
|
|
@@ -165,66 +156,60 @@ const SuggestionsList = ({
|
|
|
165
156
|
}
|
|
166
157
|
|
|
167
158
|
setHighlightedSuggestionIndex(highlightedSuggestionIndex - 1);
|
|
168
|
-
}
|
|
159
|
+
};
|
|
169
160
|
|
|
170
|
-
const handleKeyPress =
|
|
171
|
-
(event
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// If no suggestions is highlighted and we hit enter, we run the query,
|
|
183
|
-
// and hide suggestions until another actions enables them again.
|
|
184
|
-
if (highlightedSuggestionIndex === -1 && event.key === 'Enter') {
|
|
185
|
-
setShowSuggest(false);
|
|
186
|
-
runQuery();
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
161
|
+
const handleKeyPress = (event: React.KeyboardEvent<HTMLTextAreaElement>): void => {
|
|
162
|
+
if (event.key === 'Enter') {
|
|
163
|
+
// Disable new line in the text area
|
|
164
|
+
event.preventDefault();
|
|
165
|
+
}
|
|
166
|
+
// If there is a highlighted suggestion and enter is hit, we complete
|
|
167
|
+
// with the highlighted suggestion.
|
|
168
|
+
if (highlightedSuggestionIndex >= 0 && event.key === 'Enter') {
|
|
169
|
+
applyHighlightedSuggestion();
|
|
170
|
+
}
|
|
189
171
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
172
|
+
// If no suggestions is highlighted and we hit enter, we run the query,
|
|
173
|
+
// and hide suggestions until another actions enables them again.
|
|
174
|
+
if (highlightedSuggestionIndex === -1 && event.key === 'Enter') {
|
|
175
|
+
setShowSuggest(false);
|
|
176
|
+
runQuery();
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
194
179
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
// Don't need to handle any key interactions if no suggestions there.
|
|
198
|
-
if (suggestionsLength === 0 || !['Tab', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
180
|
+
setShowSuggest(true);
|
|
181
|
+
};
|
|
201
182
|
|
|
202
|
-
|
|
183
|
+
const handleKeyDown = (event: KeyboardEvent): void => {
|
|
184
|
+
// Don't need to handle any key interactions if no suggestions there.
|
|
185
|
+
if (suggestionsLength === 0 || !['Tab', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
203
188
|
|
|
204
|
-
|
|
205
|
-
if (event.key === 'Tab' && suggestionsLength > 0) {
|
|
206
|
-
event.preventDefault();
|
|
207
|
-
if (event.shiftKey) {
|
|
208
|
-
// Shift + tab goes up.
|
|
209
|
-
highlightPrevious();
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// Just tab goes down.
|
|
213
|
-
highlightNext();
|
|
214
|
-
}
|
|
189
|
+
event.preventDefault();
|
|
215
190
|
|
|
216
|
-
|
|
217
|
-
|
|
191
|
+
// Handle tabbing through suggestions.
|
|
192
|
+
if (event.key === 'Tab' && suggestionsLength > 0) {
|
|
193
|
+
event.preventDefault();
|
|
194
|
+
if (event.shiftKey) {
|
|
195
|
+
// Shift + tab goes up.
|
|
218
196
|
highlightPrevious();
|
|
197
|
+
return;
|
|
219
198
|
}
|
|
199
|
+
// Just tab goes down.
|
|
200
|
+
highlightNext();
|
|
201
|
+
}
|
|
220
202
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
203
|
+
// Up arrow highlights previous suggestions.
|
|
204
|
+
if (event.key === 'ArrowUp') {
|
|
205
|
+
highlightPrevious();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Down arrow highlights next suggestions.
|
|
209
|
+
if (event.key === 'ArrowDown') {
|
|
210
|
+
highlightNext();
|
|
211
|
+
}
|
|
212
|
+
};
|
|
228
213
|
|
|
229
214
|
useEffect(() => {
|
|
230
215
|
const el = inputRef.current;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import React, {
|
|
14
|
+
import React, {useRef, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import TextareaAutosize from 'react-textarea-autosize';
|
|
@@ -48,91 +48,78 @@ const MatchersInput = ({setDraftMatchers, draftParsedQuery, commitDraft}: Props)
|
|
|
48
48
|
|
|
49
49
|
const value = draftParsedQuery != null ? draftParsedQuery.matchersString() : '';
|
|
50
50
|
|
|
51
|
-
const suggestionSections =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
51
|
+
const suggestionSections = new Suggestions();
|
|
52
|
+
Query.suggest(`${draftParsedQuery?.profileName() as string}{${value}`).forEach(function (s) {
|
|
53
|
+
// Skip suggestions that we just completed. This really only works,
|
|
54
|
+
// because we know the language is not repetitive. For a language that
|
|
55
|
+
// has a repeating word, this would not work.
|
|
56
|
+
if (lastCompleted !== null && lastCompleted.type === s.type) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
// Need to figure out if any literal suggestions make sense, but a
|
|
61
|
+
// closing bracket doesn't in the guided query experience because all
|
|
62
|
+
// we have the user do is type the matchers.
|
|
63
|
+
if (s.type === 'literal' && s.value !== '}') {
|
|
64
|
+
suggestionSections.literals.push({
|
|
65
|
+
type: s.type,
|
|
66
|
+
typeahead: s.typeahead,
|
|
67
|
+
value: s.value,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (s.type === 'labelName') {
|
|
71
|
+
const inputValue = s.typeahead.trim().toLowerCase();
|
|
72
|
+
const inputLength = inputValue.length;
|
|
73
|
+
const matches = labelNames.filter(function (label) {
|
|
74
|
+
return label.toLowerCase().slice(0, inputLength) === inputValue;
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
matches.forEach(m => {
|
|
78
|
+
const suggestion = {
|
|
66
79
|
type: s.type,
|
|
67
80
|
typeahead: s.typeahead,
|
|
68
|
-
value:
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (s.type === 'labelName') {
|
|
72
|
-
const inputValue = s.typeahead.trim().toLowerCase();
|
|
73
|
-
const inputLength = inputValue.length;
|
|
74
|
-
const matches = labelNames.filter(function (label) {
|
|
75
|
-
return label.toLowerCase().slice(0, inputLength) === inputValue;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
matches.forEach(m => {
|
|
79
|
-
const suggestion = {
|
|
80
|
-
type: s.type,
|
|
81
|
-
typeahead: s.typeahead,
|
|
82
|
-
value: m,
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
if (shouldHandlePrefixes) {
|
|
86
|
-
const mapping = labelNameMappings.find(l => l.displayName === m);
|
|
87
|
-
if (mapping != null) {
|
|
88
|
-
(suggestion as any).fullName = mapping.fullName;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
suggestionSections.labelNames.push(suggestion);
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
if (s.type === 'labelValue') {
|
|
97
|
-
let labelNameForQuery = s.labelName;
|
|
81
|
+
value: m,
|
|
82
|
+
};
|
|
98
83
|
|
|
99
84
|
if (shouldHandlePrefixes) {
|
|
100
|
-
const mapping = labelNameMappings.find(l => l.displayName ===
|
|
85
|
+
const mapping = labelNameMappings.find(l => l.displayName === m);
|
|
101
86
|
if (mapping != null) {
|
|
102
|
-
|
|
87
|
+
(suggestion as any).fullName = mapping.fullName;
|
|
103
88
|
}
|
|
104
89
|
}
|
|
105
90
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
91
|
+
suggestionSections.labelNames.push(suggestion);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (s.type === 'labelValue') {
|
|
96
|
+
let labelNameForQuery = s.labelName;
|
|
110
97
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
suggestionSections.labelValues.push({
|
|
116
|
-
type: s.type,
|
|
117
|
-
typeahead: s.typeahead,
|
|
118
|
-
value: v,
|
|
119
|
-
})
|
|
120
|
-
);
|
|
98
|
+
if (shouldHandlePrefixes) {
|
|
99
|
+
const mapping = labelNameMappings.find(l => l.displayName === s.labelName);
|
|
100
|
+
if (mapping != null) {
|
|
101
|
+
labelNameForQuery = mapping.fullName;
|
|
121
102
|
}
|
|
122
103
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
104
|
+
|
|
105
|
+
if (currentLabelName === null || labelNameForQuery !== currentLabelName) {
|
|
106
|
+
setCurrentLabelName(labelNameForQuery);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (labelValues !== null) {
|
|
111
|
+
labelValues
|
|
112
|
+
.filter(v => v.slice(0, s.typeahead.length) === s.typeahead)
|
|
113
|
+
.forEach(v =>
|
|
114
|
+
suggestionSections.labelValues.push({
|
|
115
|
+
type: s.type,
|
|
116
|
+
typeahead: s.typeahead,
|
|
117
|
+
value: v,
|
|
118
|
+
})
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
136
123
|
|
|
137
124
|
const resetLastCompleted = (): void => setLastCompleted(new Suggestion('', '', ''));
|
|
138
125
|
|
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {useMemo} from 'react';
|
|
15
|
-
|
|
16
14
|
import {RpcError} from '@protobuf-ts/runtime-rpc';
|
|
17
15
|
|
|
18
16
|
import {ProfileType, ProfileTypesResponse} from '@parca/client';
|
|
@@ -180,13 +178,12 @@ const ProfileTypeSelector = ({
|
|
|
180
178
|
flexibleKnownProfilesDetection = false,
|
|
181
179
|
disabled,
|
|
182
180
|
}: Props): JSX.Element => {
|
|
183
|
-
const profileNames =
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
181
|
+
const profileNames =
|
|
182
|
+
(error === undefined || error == null) &&
|
|
183
|
+
profileTypesData !== undefined &&
|
|
184
|
+
profileTypesData != null
|
|
187
185
|
? normalizeProfileTypesData(profileTypesData.types)
|
|
188
186
|
: [];
|
|
189
|
-
}, [profileTypesData, error]);
|
|
190
187
|
|
|
191
188
|
const profileLabels = (
|
|
192
189
|
profileNames.length > 0 ? profileNames : selectedKey != null ? [selectedKey] : []
|