@parca/profile 0.19.62 → 0.19.64
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 +8 -0
- package/dist/MatchersInput/SuggestionsList.d.ts +2 -1
- package/dist/MatchersInput/SuggestionsList.d.ts.map +1 -1
- package/dist/MatchersInput/SuggestionsList.js +42 -17
- package/dist/MatchersInput/index.d.ts +1 -0
- package/dist/MatchersInput/index.d.ts.map +1 -1
- package/dist/MatchersInput/index.js +12 -4
- package/dist/SimpleMatchers/Select.d.ts +2 -3
- package/dist/SimpleMatchers/Select.d.ts.map +1 -1
- package/dist/SimpleMatchers/Select.js +12 -11
- package/dist/SimpleMatchers/index.d.ts.map +1 -1
- package/dist/SimpleMatchers/index.js +4 -3
- package/dist/contexts/MatchersInputLabelsContext.d.ts +1 -0
- package/dist/contexts/MatchersInputLabelsContext.d.ts.map +1 -1
- package/dist/contexts/MatchersInputLabelsContext.js +3 -1
- package/dist/contexts/SimpleMatchersLabelContext.d.ts +2 -1
- package/dist/contexts/SimpleMatchersLabelContext.d.ts.map +1 -1
- package/dist/contexts/SimpleMatchersLabelContext.js +15 -5
- package/dist/styles.css +1 -1
- package/package.json +2 -2
- package/src/MatchersInput/SuggestionsList.tsx +109 -39
- package/src/MatchersInput/index.tsx +18 -3
- package/src/SimpleMatchers/Select.tsx +54 -48
- package/src/SimpleMatchers/index.tsx +9 -3
- package/src/contexts/MatchersInputLabelsContext.tsx +8 -6
- package/src/contexts/SimpleMatchersLabelContext.tsx +36 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
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.64](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.63...@parca/profile@0.19.64) (2025-10-13)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.19.63](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.62...@parca/profile@0.19.63) (2025-10-10)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.19.62](https://github.com/parca-dev/parca/compare/@parca/profile@0.19.61...@parca/profile@0.19.62) (2025-10-08)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -20,7 +20,8 @@ interface Props {
|
|
|
20
20
|
isLabelValuesLoading: boolean;
|
|
21
21
|
shouldTrimPrefix: boolean;
|
|
22
22
|
refetchLabelValues: () => void;
|
|
23
|
+
refetchLabelNames: () => void;
|
|
23
24
|
}
|
|
24
|
-
declare const SuggestionsList: ({ suggestions, applySuggestion, inputRef, runQuery, focusedInput, isLabelNamesLoading, isLabelValuesLoading, shouldTrimPrefix, refetchLabelValues, }: Props) => JSX.Element;
|
|
25
|
+
declare const SuggestionsList: ({ suggestions, applySuggestion, inputRef, runQuery, focusedInput, isLabelNamesLoading, isLabelValuesLoading, shouldTrimPrefix, refetchLabelValues, refetchLabelNames, }: Props) => JSX.Element;
|
|
25
26
|
export default SuggestionsList;
|
|
26
27
|
//# sourceMappingURL=SuggestionsList.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SuggestionsList.d.ts","sourceRoot":"","sources":["../../src/MatchersInput/SuggestionsList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SuggestionsList.d.ts","sourceRoot":"","sources":["../../src/MatchersInput/SuggestionsList.tsx"],"names":[],"mappings":"AAyBA,qBAAa,UAAU;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;gBAEF,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAK3D;AAED,qBAAa,WAAW;IACtB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,UAAU,EAAE,UAAU,EAAE,CAAC;IACzB,WAAW,EAAE,UAAU,EAAE,CAAC;;CAO3B;AAED,UAAU,KAAK;IACb,WAAW,EAAE,WAAW,CAAC;IACzB,eAAe,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAClD,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,IAAI,CAAC;CAC/B;AAkDD,QAAA,MAAM,eAAe,GAAI,yKAWtB,KAAK,KAAG,GAAG,CAAC,OAsUd,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx,
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
// Copyright 2022 The Parca Authors
|
|
3
3
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
4
|
// you may not use this file except in compliance with the License.
|
|
@@ -17,6 +17,7 @@ import { Icon } from '@iconify/react';
|
|
|
17
17
|
import cx from 'classnames';
|
|
18
18
|
import { usePopper } from 'react-popper';
|
|
19
19
|
import { useParcaContext } from '@parca/components';
|
|
20
|
+
import { TEST_IDS, testId } from '@parca/test-utils';
|
|
20
21
|
import SuggestionItem from './SuggestionItem';
|
|
21
22
|
export class Suggestion {
|
|
22
23
|
constructor(type, typeahead, value) {
|
|
@@ -36,29 +37,50 @@ const LoadingSpinner = () => {
|
|
|
36
37
|
const { loader: Spinner } = useParcaContext();
|
|
37
38
|
return _jsx("div", { className: "pt-2 pb-4", children: Spinner });
|
|
38
39
|
};
|
|
40
|
+
const RefreshButton = ({ onClick, disabled, title, testId }) => {
|
|
41
|
+
return (_jsx("div", { className: "sticky bottom-0 w-full flex items-center justify-center px-3 py-2 bg-gray-50 dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 z-20", children: _jsxs("button", { onClick: e => {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
e.stopPropagation();
|
|
44
|
+
onClick();
|
|
45
|
+
}, disabled: disabled, className: cx('py-1 px-2 flex items-center gap-1 rounded-full transition-all duration-200 w-auto justify-center', disabled
|
|
46
|
+
? 'cursor-wait opacity-50'
|
|
47
|
+
: 'hover:bg-gray-200 dark:hover:bg-gray-700 cursor-pointer'), title: title, type: "button", "data-testid": testId, children: [_jsx(Icon, { icon: "system-uicons:reset", className: cx('w-3 h-3 text-gray-500 dark:text-gray-400', disabled && 'animate-spin') }), _jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Refresh results" })] }) }));
|
|
48
|
+
};
|
|
39
49
|
const transformLabelsForSuggestions = (labelNames, shouldTrimPrefix = false) => {
|
|
40
50
|
const trimmedLabel = shouldTrimPrefix ? labelNames.split('.').pop() ?? labelNames : labelNames;
|
|
41
51
|
return trimmedLabel;
|
|
42
52
|
};
|
|
43
|
-
const SuggestionsList = ({ suggestions, applySuggestion, inputRef, runQuery, focusedInput, isLabelNamesLoading, isLabelValuesLoading, shouldTrimPrefix = false, refetchLabelValues, }) => {
|
|
53
|
+
const SuggestionsList = ({ suggestions, applySuggestion, inputRef, runQuery, focusedInput, isLabelNamesLoading, isLabelValuesLoading, shouldTrimPrefix = false, refetchLabelValues, refetchLabelNames, }) => {
|
|
44
54
|
const [popperElement, setPopperElement] = useState(null);
|
|
45
55
|
const { styles, attributes } = usePopper(inputRef, popperElement, {
|
|
46
56
|
placement: 'bottom-start',
|
|
47
57
|
});
|
|
48
58
|
const [highlightedSuggestionIndex, setHighlightedSuggestionIndex] = useState(-1);
|
|
49
59
|
const [showSuggest, setShowSuggest] = useState(true);
|
|
50
|
-
const [
|
|
51
|
-
const
|
|
52
|
-
|
|
60
|
+
const [isRefetchingValues, setIsRefetchingValues] = useState(false);
|
|
61
|
+
const [isRefetchingNames, setIsRefetchingNames] = useState(false);
|
|
62
|
+
const handleRefetchValues = useCallback(async () => {
|
|
63
|
+
if (isRefetchingValues)
|
|
53
64
|
return;
|
|
54
|
-
|
|
65
|
+
setIsRefetchingValues(true);
|
|
55
66
|
try {
|
|
56
67
|
await refetchLabelValues();
|
|
57
68
|
}
|
|
58
69
|
finally {
|
|
59
|
-
|
|
70
|
+
setIsRefetchingValues(false);
|
|
71
|
+
}
|
|
72
|
+
}, [refetchLabelValues, isRefetchingValues]);
|
|
73
|
+
const handleRefetchNames = useCallback(async () => {
|
|
74
|
+
if (isRefetchingNames)
|
|
75
|
+
return;
|
|
76
|
+
setIsRefetchingNames(true);
|
|
77
|
+
try {
|
|
78
|
+
await refetchLabelNames();
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
setIsRefetchingNames(false);
|
|
60
82
|
}
|
|
61
|
-
}, [
|
|
83
|
+
}, [refetchLabelNames, isRefetchingNames]);
|
|
62
84
|
const suggestionsLength = suggestions.literals.length + suggestions.labelNames.length + suggestions.labelValues.length;
|
|
63
85
|
const getSuggestion = useCallback((index) => {
|
|
64
86
|
if (index < suggestions.labelNames.length) {
|
|
@@ -150,14 +172,17 @@ const SuggestionsList = ({ suggestions, applySuggestion, inputRef, runQuery, foc
|
|
|
150
172
|
inputRef.removeEventListener('keypress', handleKeyPress);
|
|
151
173
|
};
|
|
152
174
|
}, [inputRef, highlightedSuggestionIndex, suggestions, handleKeyPress, handleKeyDown]);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
if (suggestionsLength > 0 && focusedInput) {
|
|
177
|
+
setShowSuggest(true);
|
|
178
|
+
}
|
|
179
|
+
}, [suggestionsLength, focusedInput]);
|
|
180
|
+
return (_jsx(_Fragment, { children: suggestionsLength > 0 && (_jsx("div", { ref: setPopperElement, style: { ...styles.popper, marginLeft: 0 }, ...attributes.popper, className: "z-50", children: _jsx(Transition, { show: focusedInput && showSuggest, as: Fragment, leave: "transition ease-in duration-100", leaveFrom: "opacity-100", leaveTo: "opacity-0", children: _jsxs("div", { style: { width: inputRef?.offsetWidth }, className: "absolute z-10 mt-1 max-h-[400px] overflow-auto rounded-md bg-gray-50 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-900 sm:text-sm flex flex-col", children: [_jsxs("div", { className: "flex-1 min-h-0", children: [isLabelNamesLoading ? (_jsx(LoadingSpinner, {})) : suggestions.literals.length === 0 && suggestions.labelValues.length === 0 ? (_jsx(_Fragment, { children: suggestions.labelNames.length === 0 ? (_jsx("div", { className: "px-4 py-3 text-sm text-gray-500 dark:text-gray-400 text-center", ...testId(TEST_IDS.SUGGESTIONS_NO_RESULTS), children: "No label names found" })) : (suggestions.labelNames.map((l, i) => (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex === i, onHighlight: () => setHighlightedSuggestionIndex(i), onApplySuggestion: () => applySuggestionWithIndex(i), onResetHighlight: () => resetHighlight(), value: transformLabelsForSuggestions(l.value, shouldTrimPrefix) }, transformLabelsForSuggestions(l.value, shouldTrimPrefix))))) })) : (_jsx(_Fragment, { children: suggestions.labelNames.map((l, i) => (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex === i, onHighlight: () => setHighlightedSuggestionIndex(i), onApplySuggestion: () => applySuggestionWithIndex(i), onResetHighlight: () => resetHighlight(), value: transformLabelsForSuggestions(l.value, shouldTrimPrefix) }, transformLabelsForSuggestions(l.value, shouldTrimPrefix)))) })), suggestions.literals.map((l, i) => (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex === i + suggestions.labelNames.length, onHighlight: () => setHighlightedSuggestionIndex(i + suggestions.labelNames.length), onApplySuggestion: () => applySuggestionWithIndex(i + suggestions.labelNames.length), onResetHighlight: () => resetHighlight(), value: l.value }, l.value))), isLabelValuesLoading ? (_jsx(LoadingSpinner, {})) : suggestions.labelNames.length === 0 && suggestions.literals.length === 0 ? (_jsx(_Fragment, { children: suggestions.labelValues.length === 0 ? (_jsx("div", { className: "px-4 py-3 text-sm text-gray-500 dark:text-gray-400 text-center", ...testId(TEST_IDS.SUGGESTIONS_NO_RESULTS), children: "No label values found" })) : (suggestions.labelValues.map((l, i) => (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex ===
|
|
181
|
+
i + suggestions.labelNames.length + suggestions.literals.length, onHighlight: () => setHighlightedSuggestionIndex(i + suggestions.labelNames.length + suggestions.literals.length), onApplySuggestion: () => applySuggestionWithIndex(i + suggestions.labelNames.length + suggestions.literals.length), onResetHighlight: () => resetHighlight(), value: l.value }, l.value)))) })) : (suggestions.labelValues.map((l, i) => (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex ===
|
|
182
|
+
i + suggestions.labelNames.length + suggestions.literals.length, onHighlight: () => setHighlightedSuggestionIndex(i + suggestions.labelNames.length + suggestions.literals.length), onApplySuggestion: () => applySuggestionWithIndex(i + suggestions.labelNames.length + suggestions.literals.length), onResetHighlight: () => resetHighlight(), value: l.value }, l.value))))] }), suggestions.literals.length === 0 &&
|
|
183
|
+
suggestions.labelValues.length === 0 &&
|
|
184
|
+
!isLabelNamesLoading && (_jsx(RefreshButton, { onClick: () => void handleRefetchNames(), disabled: isRefetchingNames, title: "Refresh label names", testId: "suggestions-refresh-names-button" })), suggestions.labelNames.length === 0 &&
|
|
185
|
+
suggestions.literals.length === 0 &&
|
|
186
|
+
!isLabelValuesLoading && (_jsx(RefreshButton, { onClick: () => void handleRefetchValues(), disabled: isRefetchingValues, title: "Refresh label values", testId: "suggestions-refresh-values-button" }))] }) }) })) }));
|
|
162
187
|
};
|
|
163
188
|
export default SuggestionsList;
|
|
@@ -17,6 +17,7 @@ export interface ILabelNamesResult {
|
|
|
17
17
|
interface UseLabelNames {
|
|
18
18
|
result: ILabelNamesResult;
|
|
19
19
|
loading: boolean;
|
|
20
|
+
refetch: () => void;
|
|
20
21
|
}
|
|
21
22
|
export declare const useLabelNames: (client: QueryServiceClient, profileType: string, start?: number, end?: number, match?: string[]) => UseLabelNames;
|
|
22
23
|
interface UseLabelValues {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MatchersInput/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAgB,cAAc,EAAE,kBAAkB,EAAgB,MAAM,eAAe,CAAC;AAE/F,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAIpC,OAAO,EAAC,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAKrD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,UAAU,aAAa;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/MatchersInput/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAgB,cAAc,EAAE,kBAAkB,EAAgB,MAAM,eAAe,CAAC;AAE/F,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAIpC,OAAO,EAAC,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAKrD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,UAAU,aAAa;IACrB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,aAAa,GACxB,QAAQ,kBAAkB,EAC1B,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,MAAM,MAAM,EACZ,QAAQ,MAAM,EAAE,KACf,aAgCF,CAAC;AAEF,UAAU,cAAc;IACtB,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,KAAK,CAAC,EAAE,KAAK,CAAC;KACf,CAAC;IACF,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,GACzB,QAAQ,kBAAkB,EAC1B,WAAW,MAAM,EACjB,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,MAAM,MAAM,KACX,cAiCF,CAAC;AAEF,eAAO,MAAM,8BAA8B,GACzC,WAAW,MAAM,EACjB,oBAAoB,iBAAiB,KACpC,MAAM,EAWR,CAAC;AA2MF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAWxF"}
|
|
@@ -24,7 +24,7 @@ import useGrpcQuery from '../useGrpcQuery';
|
|
|
24
24
|
import SuggestionsList, { Suggestion, Suggestions } from './SuggestionsList';
|
|
25
25
|
export const useLabelNames = (client, profileType, start, end, match) => {
|
|
26
26
|
const metadata = useGrpcMetadata();
|
|
27
|
-
const { data, isLoading, error } = useGrpcQuery({
|
|
27
|
+
const { data, isLoading, error, refetch } = useGrpcQuery({
|
|
28
28
|
key: ['labelNames', profileType, match?.join(','), start, end],
|
|
29
29
|
queryFn: async (signal) => {
|
|
30
30
|
const request = { match: match !== undefined ? match : [] };
|
|
@@ -43,7 +43,14 @@ export const useLabelNames = (client, profileType, start, end, match) => {
|
|
|
43
43
|
keepPreviousData: false,
|
|
44
44
|
},
|
|
45
45
|
});
|
|
46
|
-
|
|
46
|
+
console.log('Label names query result:', { data, error, isLoading });
|
|
47
|
+
return {
|
|
48
|
+
result: { response: data, error: error },
|
|
49
|
+
loading: isLoading,
|
|
50
|
+
refetch: () => {
|
|
51
|
+
void refetch();
|
|
52
|
+
},
|
|
53
|
+
};
|
|
47
54
|
};
|
|
48
55
|
export const useLabelValues = (client, labelName, profileType, start, end) => {
|
|
49
56
|
const metadata = useGrpcMetadata();
|
|
@@ -66,6 +73,7 @@ export const useLabelValues = (client, labelName, profileType, start, end) => {
|
|
|
66
73
|
keepPreviousData: false,
|
|
67
74
|
},
|
|
68
75
|
});
|
|
76
|
+
console.log('Label values query result:', { data, error, isLoading, labelName });
|
|
69
77
|
return {
|
|
70
78
|
result: { response: data ?? [], error: error },
|
|
71
79
|
loading: isLoading,
|
|
@@ -89,7 +97,7 @@ const MatchersInput = ({ setMatchersString, runQuery, currentQuery, }) => {
|
|
|
89
97
|
const inputRef = useRef(null);
|
|
90
98
|
const [focusedInput, setFocusedInput] = useState(false);
|
|
91
99
|
const [lastCompleted, setLastCompleted] = useState(new Suggestion('', '', ''));
|
|
92
|
-
const { labelNames, labelValues, labelNameMappings, isLabelNamesLoading, isLabelValuesLoading, currentLabelName, setCurrentLabelName, shouldHandlePrefixes, refetchLabelValues, } = useLabels();
|
|
100
|
+
const { labelNames, labelValues, labelNameMappings, isLabelNamesLoading, isLabelValuesLoading, currentLabelName, setCurrentLabelName, shouldHandlePrefixes, refetchLabelValues, refetchLabelNames, } = useLabels();
|
|
93
101
|
const value = currentQuery.matchersString();
|
|
94
102
|
const suggestionSections = useMemo(() => {
|
|
95
103
|
const suggestionSections = new Suggestions();
|
|
@@ -204,7 +212,7 @@ const MatchersInput = ({ setMatchersString, runQuery, currentQuery, }) => {
|
|
|
204
212
|
? 'Select a profile first to enter a filter...'
|
|
205
213
|
: 'filter profiles... eg. node="test"', onChange: onChange, value: value, onBlur: unfocus, ...testId(TEST_IDS.MATCHERS_TEXTAREA), onFocus: focus, disabled: profileSelected, title: profileSelected
|
|
206
214
|
? 'Select a profile first to enter a filter...'
|
|
207
|
-
: '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, refetchLabelValues: refetchLabelValues })] }));
|
|
215
|
+
: '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' && lastCompleted.value !== ',', shouldTrimPrefix: shouldHandlePrefixes, refetchLabelValues: refetchLabelValues, refetchLabelNames: refetchLabelNames })] }));
|
|
208
216
|
};
|
|
209
217
|
export default function MatchersInputWithProvider(props) {
|
|
210
218
|
return (_jsx(LabelsProvider, { queryClient: props.queryClient, profileType: props.profileType, start: props.start, end: props.end, children: _jsx(MatchersInput, { ...props }) }));
|
|
@@ -31,10 +31,9 @@ interface CustomSelectProps {
|
|
|
31
31
|
searchable?: boolean;
|
|
32
32
|
onButtonClick?: () => void;
|
|
33
33
|
editable?: boolean;
|
|
34
|
-
|
|
34
|
+
refetchValues?: () => void;
|
|
35
35
|
showLoadingInButton?: boolean;
|
|
36
|
-
hasRefreshButton?: boolean;
|
|
37
36
|
}
|
|
38
|
-
declare const CustomSelect: React.FC<CustomSelectProps
|
|
37
|
+
declare const CustomSelect: React.FC<CustomSelectProps & Record<string, any>>;
|
|
39
38
|
export default CustomSelect;
|
|
40
39
|
//# sourceMappingURL=Select.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/Select.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiD,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/Select.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAiD,MAAM,OAAO,CAAC;AAStE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC;IACpB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,eAAgB,SAAQ,UAAU;IACjD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,UAAU,iBAAiB;IACzB,KAAK,EAAE,iBAAiB,EAAE,GAAG,UAAU,EAAE,CAAC;IAC1C,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CA4VnE,CAAC;AAkDF,eAAe,YAAY,CAAC"}
|
|
@@ -16,7 +16,8 @@ import { Icon } from '@iconify/react';
|
|
|
16
16
|
import cx from 'classnames';
|
|
17
17
|
import levenshtein from 'fast-levenshtein';
|
|
18
18
|
import { Button, DividerWithLabel, useParcaContext } from '@parca/components';
|
|
19
|
-
|
|
19
|
+
import { TEST_IDS, testId } from '@parca/test-utils/dist/test-ids';
|
|
20
|
+
const CustomSelect = ({ items: itemsProp, selectedKey, onSelection, placeholder = 'Select an item', width, className = '', loading, primary = false, disabled = false, icon, id, optionsClassname = '', searchable = false, onButtonClick, editable = false, refetchValues, showLoadingInButton = false, ...restProps }) => {
|
|
20
21
|
const { loader } = useParcaContext();
|
|
21
22
|
const [isOpen, setIsOpen] = useState(false);
|
|
22
23
|
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
@@ -27,16 +28,16 @@ const CustomSelect = ({ items: itemsProp, selectedKey, onSelection, placeholder
|
|
|
27
28
|
const searchInputRef = useRef(null);
|
|
28
29
|
const optionRefs = useRef([]);
|
|
29
30
|
const handleRefetch = useCallback(async () => {
|
|
30
|
-
if (
|
|
31
|
+
if (refetchValues == null || isRefetching)
|
|
31
32
|
return;
|
|
32
33
|
setIsRefetching(true);
|
|
33
34
|
try {
|
|
34
|
-
await
|
|
35
|
+
await refetchValues();
|
|
35
36
|
}
|
|
36
37
|
finally {
|
|
37
38
|
setIsRefetching(false);
|
|
38
39
|
}
|
|
39
|
-
}, [
|
|
40
|
+
}, [refetchValues, isRefetching]);
|
|
40
41
|
let items = [];
|
|
41
42
|
if (itemsProp[0] != null && 'type' in itemsProp[0]) {
|
|
42
43
|
items = itemsProp.flatMap(item => item.values.map(v => ({ ...v, type: item.type })));
|
|
@@ -137,7 +138,7 @@ const CustomSelect = ({ items: itemsProp, selectedKey, onSelection, placeholder
|
|
|
137
138
|
const primaryStyles = 'text-gray-100 dark:gray-900 bg-indigo-600 border-indigo-500 font-medium py-2 px-4';
|
|
138
139
|
const renderSelection = (selection) => {
|
|
139
140
|
if (showLoadingInButton && loading === true && selectedKey === '') {
|
|
140
|
-
return (_jsxs("span", { className: "flex items-center gap-2",
|
|
141
|
+
return (_jsxs("span", { className: "flex items-center gap-2", ...testId(TEST_IDS.LABEL_VALUE_LOADING_INDICATOR), children: [_jsx(Icon, { icon: "svg-spinners:ring-resize", className: "w-4 h-4" }), _jsx("span", { children: "Loading..." })] }));
|
|
141
142
|
}
|
|
142
143
|
if (editable) {
|
|
143
144
|
return typeof selection === 'string' && selection.length > 0 ? selection : placeholder;
|
|
@@ -173,18 +174,18 @@ const CustomSelect = ({ items: itemsProp, selectedKey, onSelection, placeholder
|
|
|
173
174
|
return acc;
|
|
174
175
|
}, [])
|
|
175
176
|
.sort((a, b) => a.values.length - b.values.length);
|
|
176
|
-
return (_jsxs("div", { ref: containerRef, className: "relative", onKeyDown: handleKeyDown, onClick: onButtonClick, children: [_jsxs("div", { id: id, onClick: () => !disabled && setIsOpen(!isOpen), className: cx(styles, width !== undefined ? `w-${width}` : 'w-full', disabled ? 'cursor-not-allowed opacity-50 pointer-events-none' : '', primary ? primaryStyles : defaultStyles, { [className]: className.length > 0 }), tabIndex: 0, role: "button", "aria-haspopup": "listbox", "aria-expanded": isOpen, children: [_jsx("div", { className: cx(icon != null ? '' : 'block overflow-x-hidden text-ellipsis whitespace-nowrap'), children: renderSelection(selection) }), _jsx("div", { className: cx(icon != null ? '' : 'pointer-events-none text-gray-400'), children: icon ?? _jsx(Icon, { icon: "heroicons:chevron-up-down-20-solid", "aria-hidden": "true" }) })] }), isOpen && (_jsx("div", { ref: optionsRef, className: cx('absolute z-50 mt-1
|
|
177
|
+
return (_jsxs("div", { ref: containerRef, className: "relative", onKeyDown: handleKeyDown, onClick: onButtonClick, children: [_jsxs("div", { id: id, onClick: () => !disabled && setIsOpen(!isOpen), className: cx(styles, width !== undefined ? `w-${width}` : 'w-full', disabled ? 'cursor-not-allowed opacity-50 pointer-events-none' : '', primary ? primaryStyles : defaultStyles, { [className]: className.length > 0 }), tabIndex: 0, role: "button", "aria-haspopup": "listbox", "aria-expanded": isOpen, ...restProps, children: [_jsx("div", { className: cx(icon != null ? '' : 'block overflow-x-hidden text-ellipsis whitespace-nowrap'), children: renderSelection(selection) }), _jsx("div", { className: cx(icon != null ? '' : 'pointer-events-none text-gray-400'), children: icon ?? _jsx(Icon, { icon: "heroicons:chevron-up-down-20-solid", "aria-hidden": "true" }) })] }), isOpen && (_jsx("div", { ref: optionsRef, className: cx('absolute z-50 mt-1 max-h-[50vh] w-max overflow-auto rounded-md bg-gray-50 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:border-gray-600 dark:bg-gray-900 dark:ring-white dark:ring-opacity-20 sm:text-sm', { [optionsClassname]: optionsClassname.length > 0 }), role: "listbox", children: _jsxs("div", { className: "relative flex flex-col", children: [searchable && (_jsx("div", { className: "sticky z-10 top-[-5px] w-auto max-w-full", children: _jsx("div", { className: "flex flex-col", children: editable ? (_jsxs(_Fragment, { children: [_jsx("textarea", { ref: searchInputRef, className: "w-full px-4 py-2 text-sm border-b border-gray-200 rounded-none ring-0 outline-none bg-gray-50 dark:bg-gray-800 dark:text-white min-h-[50px]", placeholder: "Type a RegEx to add", value: searchTerm, onChange: e => setSearchTerm(e.target.value), onFocus: e => moveCaretToEnd(e) }), editable && searchTerm.length > 0 && (_jsx("div", { className: "p-2 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800", children: _jsx(Button, { variant: "primary", className: "w-full h-[30px]", onClick: () => {
|
|
177
178
|
onSelection(searchTerm);
|
|
178
179
|
setIsOpen(false);
|
|
179
|
-
}, children: "Add" }) }))] })) : (_jsx("input", { ref: searchInputRef, type: "text", className: "w-full px-4 h-[45px] text-sm border-none rounded-none ring-0 outline-none bg-gray-50 dark:bg-gray-800 dark:text-white", placeholder: "Search...", value: searchTerm, onChange: e => setSearchTerm(e.target.value) })) }) })),
|
|
180
|
+
}, children: "Add" }) }))] })) : (_jsx("input", { ref: searchInputRef, type: "text", className: "w-full px-4 h-[45px] text-sm border-none rounded-none ring-0 outline-none bg-gray-50 dark:bg-gray-800 dark:text-white", placeholder: "Search...", value: searchTerm, onChange: e => setSearchTerm(e.target.value) })) }) })), _jsx("div", { className: "flex-1 min-h-0", children: loading === true ? (_jsx("div", { className: "w-[270px]", children: loader })) : groupedFilteredItems.length === 0 ? (_jsx("div", { className: "px-4 py-3 text-sm text-gray-500 dark:text-gray-400 text-center", ...testId(TEST_IDS.LABEL_VALUE_NO_RESULTS), children: "No values found" })) : (groupedFilteredItems.map(group => (_jsxs(_Fragment, { children: [groupedFilteredItems.length > 1 &&
|
|
181
|
+
groupedFilteredItems.every(g => g.type !== '') &&
|
|
182
|
+
group.type !== '' ? (_jsx("div", { className: "pl-2", children: _jsx(DividerWithLabel, { label: group.type }) })) : null, group.values.map((item, index) => (_jsx(OptionItem, { item: item, index: index, optionRefs: optionRefs, focusedIndex: focusedIndex, selectedKey: selectedKey, handleSelection: handleSelection }, item.key)))] })))) }), refetchValues !== undefined && loading !== true && (_jsx("div", { className: "sticky bottom-0 w-full flex items-center justify-center px-3 py-2 bg-gray-50 dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 z-20 mt-auto", children: _jsxs("button", { onClick: e => {
|
|
180
183
|
e.preventDefault();
|
|
181
184
|
e.stopPropagation();
|
|
182
185
|
void handleRefetch();
|
|
183
|
-
}, disabled: isRefetching, className: cx('
|
|
186
|
+
}, disabled: isRefetching, className: cx('py-1 px-2 flex items-center gap-1 rounded-full transition-all duration-200 w-auto justify-center', isRefetching
|
|
184
187
|
? 'cursor-wait opacity-50'
|
|
185
|
-
: 'hover:bg-gray-200 dark:hover:bg-gray-700 cursor-pointer'), title: "Refresh label values", type: "button",
|
|
186
|
-
groupedFilteredItems.every(g => g.type !== '') &&
|
|
187
|
-
group.type !== '' ? (_jsx("div", { className: "pl-2", children: _jsx(DividerWithLabel, { label: group.type }) })) : null, group.values.map((item, index) => (_jsx(OptionItem, { item: item, index: index, optionRefs: optionRefs, focusedIndex: focusedIndex, selectedKey: selectedKey, handleSelection: handleSelection }, item.key)))] }))))] }) }))] }));
|
|
188
|
+
: 'hover:bg-gray-200 dark:hover:bg-gray-700 cursor-pointer'), title: "Refresh label values", type: "button", ...testId(TEST_IDS.LABEL_VALUE_REFRESH_BUTTON), children: [_jsx(Icon, { icon: "system-uicons:reset", className: cx('w-3 h-3 text-gray-500 dark:text-gray-400', isRefetching && 'animate-spin') }), _jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: "Refresh results" })] }) }))] }) }))] }));
|
|
188
189
|
};
|
|
189
190
|
const OptionItem = ({ item, optionRefs, index, focusedIndex, selectedKey, handleSelection, }) => {
|
|
190
191
|
return (_jsxs("div", { ref: el => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAMpC,OAAe,EAAC,KAAK,UAAU,EAAC,MAAM,UAAU,CAAC;AAEjD,UAAU,KAAK;IACb,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAoBD,eAAO,MAAM,wBAAwB,GAAI,YAAY,MAAM,EAAE,KAAG,UAAU,EAQzE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/SimpleMatchers/index.tsx"],"names":[],"mappings":"AAmBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AAMpC,OAAe,EAAC,KAAK,UAAU,EAAC,MAAM,UAAU,CAAC;AAEjD,UAAU,KAAK;IACb,WAAW,EAAE,kBAAkB,CAAC;IAChC,iBAAiB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,EAAE,KAAK,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC;AAoBD,eAAO,MAAM,wBAAwB,GAAI,YAAY,MAAM,EAAE,KAAG,UAAU,EAQzE,CAAC;AAidF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAoB3E"}
|
|
@@ -106,6 +106,7 @@ const SimpleMatchers = ({ queryClient, setMatchersString, currentQuery, profileT
|
|
|
106
106
|
}
|
|
107
107
|
: {}),
|
|
108
108
|
}, { meta: metadata }).response;
|
|
109
|
+
console.log('Fetched label values:', response.labelValues);
|
|
109
110
|
const sanitizedValues = sanitizeLabelValue(response.labelValues);
|
|
110
111
|
return sanitizedValues;
|
|
111
112
|
});
|
|
@@ -126,7 +127,7 @@ const SimpleMatchers = ({ queryClient, setMatchersString, currentQuery, profileT
|
|
|
126
127
|
.join(',');
|
|
127
128
|
setMatchersString(matcherString);
|
|
128
129
|
}, [setMatchersString]);
|
|
129
|
-
const { labelNameOptions, isLoading: labelNamesLoading, refetchLabelValues } = useLabels();
|
|
130
|
+
const { labelNameOptions, isLoading: labelNamesLoading, refetchLabelValues, refetchLabelNames, } = useLabels();
|
|
130
131
|
// Helper to ensure selected label name is in the options (for page load before API returns)
|
|
131
132
|
const getLabelNameOptionsWithSelected = useCallback((selectedLabelName) => {
|
|
132
133
|
if (selectedLabelName === '')
|
|
@@ -313,11 +314,11 @@ const SimpleMatchers = ({ queryClient, setMatchersString, currentQuery, profileT
|
|
|
313
314
|
};
|
|
314
315
|
}, [queryRows, fetchLabelValuesUnified]);
|
|
315
316
|
const isRowRegex = (row) => row.operator === '=~' || row.operator === '!~';
|
|
316
|
-
return (_jsxs("div", { className: `flex items-center gap-3 ${maxWidthInPixels} w-full flex-wrap`, id: "simple-matchers", ...testId(TEST_IDS.SIMPLE_MATCHERS_CONTAINER), children: [visibleRows.map((row, index) => (_jsxs("div", { className: "flex items-center", ...testId(TEST_IDS.SIMPLE_MATCHER_ROW), children: [_jsx(Select, { items: getLabelNameOptionsWithSelected(row.labelName), onSelection: value => handleUpdateRow(index, 'labelName', value), placeholder: "Select label name", selectedKey: row.labelName, className: "rounded-tr-none rounded-br-none ring-0 focus:ring-0 outline-none", loading: labelNamesLoading, searchable: true, ...testId(TEST_IDS.LABEL_NAME_SELECT) }), _jsx(Select, { items: operatorOptions, onSelection: value => handleUpdateRow(index, 'operator', value), selectedKey: row.operator, className: "rounded-none ring-0 focus:ring-0 outline-none", ...testId(TEST_IDS.OPERATOR_SELECT) }), _jsx(Select, { items: transformLabelsForSelect(row.labelValue !== '' && !row.labelValues.includes(row.labelValue)
|
|
317
|
+
return (_jsxs("div", { className: `flex items-center gap-3 ${maxWidthInPixels} w-full flex-wrap`, id: "simple-matchers", ...testId(TEST_IDS.SIMPLE_MATCHERS_CONTAINER), children: [visibleRows.map((row, index) => (_jsxs("div", { className: "flex items-center", ...testId(TEST_IDS.SIMPLE_MATCHER_ROW), children: [_jsx(Select, { items: getLabelNameOptionsWithSelected(row.labelName), onSelection: value => handleUpdateRow(index, 'labelName', value), placeholder: "Select label name", selectedKey: row.labelName, className: "rounded-tr-none rounded-br-none ring-0 focus:ring-0 outline-none", loading: labelNamesLoading, searchable: true, ...testId(TEST_IDS.LABEL_NAME_SELECT), refetchValues: refetchLabelNames }), _jsx(Select, { items: operatorOptions, onSelection: value => handleUpdateRow(index, 'operator', value), selectedKey: row.operator, className: "rounded-none ring-0 focus:ring-0 outline-none", ...testId(TEST_IDS.OPERATOR_SELECT) }), _jsx(Select, { items: transformLabelsForSelect(row.labelValue !== '' && !row.labelValues.includes(row.labelValue)
|
|
317
318
|
? [...row.labelValues, row.labelValue]
|
|
318
319
|
: row.labelValues), onSelection: value => handleUpdateRow(index, 'labelValue', value), placeholder: "Select label value", selectedKey: row.labelValue, className: "rounded-none ring-0 focus:ring-0 outline-none max-w-48", optionsClassname: cx('max-w-[600px]', {
|
|
319
320
|
'w-[300px]': isRowRegex(row),
|
|
320
|
-
}), searchable: true, disabled: row.labelName === '', loading: row.isLoading, onButtonClick: () => handleLabelValueClick(index), editable: isRowRegex(row), ...testId(TEST_IDS.LABEL_VALUE_SELECT),
|
|
321
|
+
}), searchable: true, disabled: row.labelName === '', loading: row.isLoading, onButtonClick: () => handleLabelValueClick(index), editable: isRowRegex(row), ...testId(TEST_IDS.LABEL_VALUE_SELECT), refetchValues: () => refetchLabelValues(row.labelName), showLoadingInButton: true }), _jsx("button", { onClick: () => removeRow(index), className: cx('p-2 border-gray-200 border rounded rounded-tl-none rounded-bl-none focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:border-gray-600 dark:bg-gray-900'), ...testId(TEST_IDS.REMOVE_MATCHER_BUTTON), children: _jsx(Icon, { icon: "carbon:close", className: "h-5 w-5 text-gray-400", "aria-hidden": "true" }) })] }, index))), queryRows.length > 3 && !isActivelyEditing && (_jsx("button", { onClick: () => {
|
|
321
322
|
if (showAll) {
|
|
322
323
|
// Clicking "Show less" - collapse and stop editing mode
|
|
323
324
|
setShowAll(false);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MatchersInputLabelsContext.d.ts","sourceRoot":"","sources":["../../src/contexts/MatchersInputLabelsContext.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAKjD,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"MatchersInputLabelsContext.d.ts","sourceRoot":"","sources":["../../src/contexts/MatchersInputLabelsContext.tsx"],"names":[],"mappings":"AAaA,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAKjD,UAAU,gBAAgB;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,iBAAiB;IACzB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,iBAAiB,EAAE,gBAAgB,EAAE,CAAC;IACtC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,oBAAoB,EAAE,OAAO,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,oBAAoB,EAAE,OAAO,CAAC;IAC9B,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,IAAI,CAAC;CAC/B;AAID,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAID,wBAAgB,cAAc,CAAC,EAC7B,QAAQ,EACR,WAAW,EACX,WAAW,EACX,KAAK,EACL,GAAG,GACJ,EAAE,mBAAmB,GAAG,GAAG,CAAC,OAAO,CA4EnC;AAED,wBAAgB,SAAS,IAAI,iBAAiB,CAM7C"}
|
|
@@ -20,7 +20,7 @@ const LabelsContext = createContext(null);
|
|
|
20
20
|
export function LabelsProvider({ children, queryClient, profileType, start, end, }) {
|
|
21
21
|
const [currentLabelName, setCurrentLabelName] = React.useState(null);
|
|
22
22
|
const utilizationLabels = useUtilizationLabels();
|
|
23
|
-
const { result: labelNamesResponse, loading: isLabelNamesLoading } = useLabelNames(queryClient, profileType, start, end);
|
|
23
|
+
const { result: labelNamesResponse, loading: isLabelNamesLoading, refetch: refetchLabelNames, } = useLabelNames(queryClient, profileType, start, end);
|
|
24
24
|
const labelNamesFromAPI = useMemo(() => {
|
|
25
25
|
return (labelNamesResponse.error === undefined || labelNamesResponse.error == null) &&
|
|
26
26
|
labelNamesResponse !== undefined &&
|
|
@@ -56,6 +56,7 @@ export function LabelsProvider({ children, queryClient, profileType, start, end,
|
|
|
56
56
|
setCurrentLabelName,
|
|
57
57
|
shouldHandlePrefixes,
|
|
58
58
|
refetchLabelValues,
|
|
59
|
+
refetchLabelNames,
|
|
59
60
|
}), [
|
|
60
61
|
labelNames,
|
|
61
62
|
labelValues,
|
|
@@ -65,6 +66,7 @@ export function LabelsProvider({ children, queryClient, profileType, start, end,
|
|
|
65
66
|
currentLabelName,
|
|
66
67
|
shouldHandlePrefixes,
|
|
67
68
|
refetchLabelValues,
|
|
69
|
+
refetchLabelNames,
|
|
68
70
|
]);
|
|
69
71
|
return _jsx(LabelsContext.Provider, { value: value, children: children });
|
|
70
72
|
}
|
|
@@ -8,7 +8,8 @@ interface LabelContextValue {
|
|
|
8
8
|
labelNameOptions: LabelNameSection[];
|
|
9
9
|
isLoading: boolean;
|
|
10
10
|
error: Error | null;
|
|
11
|
-
refetchLabelValues: () => void;
|
|
11
|
+
refetchLabelValues: (labelName?: string) => void;
|
|
12
|
+
refetchLabelNames: () => void;
|
|
12
13
|
}
|
|
13
14
|
interface LabelProviderProps {
|
|
14
15
|
children: React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SimpleMatchersLabelContext.d.ts","sourceRoot":"","sources":["../../src/contexts/SimpleMatchersLabelContext.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AAGzD,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,UAAU,iBAAiB;IACzB,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,kBAAkB,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"SimpleMatchersLabelContext.d.ts","sourceRoot":"","sources":["../../src/contexts/SimpleMatchersLabelContext.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAIjD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AAGzD,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,UAAU,iBAAiB;IACzB,gBAAgB,EAAE,gBAAgB,EAAE,CAAC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,kBAAkB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,iBAAiB,EAAE,MAAM,IAAI,CAAC;CAC/B;AAID,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,WAAW,EAAE,kBAAkB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAKD,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,WAAW,EACX,WAAW,EACX,qBAAqB,EACrB,KAAK,EACL,GAAG,GACJ,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CA0HlC;AAED,wBAAgB,SAAS,IAAI,iBAAiB,CAM7C"}
|
|
@@ -22,7 +22,7 @@ const LabelContext = createContext(null);
|
|
|
22
22
|
export function LabelProvider({ children, queryClient, profileType, labelNameFromMatchers, start, end, }) {
|
|
23
23
|
const reactQueryClient = useQueryClient();
|
|
24
24
|
const utilizationLabelResponse = useUtilizationLabels();
|
|
25
|
-
const { loading, result } = useLabelNames(queryClient, profileType, start, end);
|
|
25
|
+
const { loading, result, refetch: refetchLabelNamesQuery, } = useLabelNames(queryClient, profileType, start, end);
|
|
26
26
|
const profileValues = useMemo(() => {
|
|
27
27
|
const profileLabelNames = result.error != null ? [] : result.response?.labelNames.filter(e => e !== '__name__') ?? [];
|
|
28
28
|
const uniqueProfileLabelNames = Array.from(new Set(profileLabelNames));
|
|
@@ -79,21 +79,31 @@ export function LabelProvider({ children, queryClient, profileType, labelNameFro
|
|
|
79
79
|
error: null,
|
|
80
80
|
};
|
|
81
81
|
}, [profileValues, utilizationValues, labelNameFromMatchers]);
|
|
82
|
-
const refetchLabelValues = useCallback(() => {
|
|
82
|
+
const refetchLabelValues = useCallback((labelName) => {
|
|
83
83
|
void reactQueryClient.refetchQueries({
|
|
84
84
|
predicate: query => {
|
|
85
85
|
const key = query.queryKey;
|
|
86
|
-
|
|
86
|
+
const matchesStructure = Array.isArray(key) &&
|
|
87
87
|
key.length === 4 &&
|
|
88
88
|
typeof key[0] === 'string' &&
|
|
89
|
-
key[1] === profileType
|
|
89
|
+
key[1] === profileType;
|
|
90
|
+
if (!matchesStructure)
|
|
91
|
+
return false;
|
|
92
|
+
if (labelName !== undefined && labelName !== '') {
|
|
93
|
+
return key[0] === labelName;
|
|
94
|
+
}
|
|
95
|
+
return true;
|
|
90
96
|
},
|
|
91
97
|
});
|
|
92
98
|
}, [reactQueryClient, profileType]);
|
|
99
|
+
const refetchLabelNames = useCallback(() => {
|
|
100
|
+
refetchLabelNamesQuery();
|
|
101
|
+
}, [refetchLabelNamesQuery]);
|
|
93
102
|
const contextValue = useMemo(() => ({
|
|
94
103
|
...value,
|
|
95
104
|
refetchLabelValues,
|
|
96
|
-
|
|
105
|
+
refetchLabelNames,
|
|
106
|
+
}), [value, refetchLabelValues, refetchLabelNames]);
|
|
97
107
|
return _jsx(LabelContext.Provider, { value: contextValue, children: children });
|
|
98
108
|
}
|
|
99
109
|
export function useLabels() {
|