@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 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":"AAwBA,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;CAChC;AAaD,QAAA,MAAM,eAAe,GAAI,sJAUtB,KAAK,KAAG,GAAG,CAAC,OAwSd,CAAC;AAEF,eAAe,eAAe,CAAC"}
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, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
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 [isRefetching, setIsRefetching] = useState(false);
51
- const handleRefetch = useCallback(async () => {
52
- if (isRefetching)
60
+ const [isRefetchingValues, setIsRefetchingValues] = useState(false);
61
+ const [isRefetchingNames, setIsRefetchingNames] = useState(false);
62
+ const handleRefetchValues = useCallback(async () => {
63
+ if (isRefetchingValues)
53
64
  return;
54
- setIsRefetching(true);
65
+ setIsRefetchingValues(true);
55
66
  try {
56
67
  await refetchLabelValues();
57
68
  }
58
69
  finally {
59
- setIsRefetching(false);
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
- }, [refetchLabelValues, isRefetching]);
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
- 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: _jsx("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", children: _jsxs("div", { className: "relative pb-12", children: [isLabelNamesLoading ? (_jsx(LoadingSpinner, {})) : (_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 ? (_jsxs(_Fragment, { children: [suggestions.labelValues.length === 0 ? (_jsx("div", { className: "px-4 py-3 text-sm text-gray-500 dark:text-gray-400 text-center", "data-testid": "suggestions-no-results", children: "No label values found" })) : (suggestions.labelValues.map((l, i) => (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex ===
154
- 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)))), _jsx("div", { className: "absolute w-full flex items-center justify-center bottom-0 px-3 py-2 bg-gray-50 dark:bg-gray-800", children: _jsxs("button", { onClick: e => {
155
- e.preventDefault();
156
- e.stopPropagation();
157
- void handleRefetch();
158
- }, disabled: isRefetching, className: cx('p-1 flex items-center gap-1 rounded-full transition-all duration-200 w-auto justify-center', isRefetching
159
- ? 'cursor-wait opacity-50'
160
- : 'hover:bg-gray-200 dark:hover:bg-gray-700 cursor-pointer'), title: "Refresh label values", type: "button", "data-testid": "suggestions-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" })] }) })] })) : (suggestions.labelValues.map((l, i) => (_jsx(SuggestionItem, { isHighlighted: highlightedSuggestionIndex ===
161
- 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))))] }) }) }) })) }));
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;CAClB;AAED,eAAO,MAAM,aAAa,GACxB,QAAQ,kBAAkB,EAC1B,aAAa,MAAM,EACnB,QAAQ,MAAM,EACd,MAAM,MAAM,EACZ,QAAQ,MAAM,EAAE,KACf,aAwBF,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,cA+BF,CAAC;AAEF,eAAO,MAAM,8BAA8B,GACzC,WAAW,MAAM,EACjB,oBAAoB,iBAAiB,KACpC,MAAM,EAWR,CAAC;AAuMF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,kBAAkB,GAAG,GAAG,CAAC,OAAO,CAWxF"}
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
- return { result: { response: data, error: error }, loading: isLoading };
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
- refetchLabelValues?: () => void;
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;AAQtE,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,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAsV7C,CAAC;AAkDF,eAAe,YAAY,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
- 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, refetchLabelValues, showLoadingInButton = false, hasRefreshButton = false, }) => {
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 (refetchLabelValues == null || isRefetching)
31
+ if (refetchValues == null || isRefetching)
31
32
  return;
32
33
  setIsRefetching(true);
33
34
  try {
34
- await refetchLabelValues();
35
+ await refetchValues();
35
36
  }
36
37
  finally {
37
38
  setIsRefetching(false);
38
39
  }
39
- }, [refetchLabelValues, isRefetching]);
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", "data-testid": "label-value-loading-indicator", children: [_jsx(Icon, { icon: "svg-spinners:ring-resize", className: "w-4 h-4" }), _jsx("span", { children: "Loading..." })] }));
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 pt-0 max-h-[50vh] w-max overflow-auto rounded-md bg-gray-50 py-1 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: cx('relative', { 'pb-6': hasRefreshButton }), 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
+ 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) })) }) })), refetchLabelValues !== undefined && loading !== true && (_jsx("div", { className: "absolute w-full bottom-0 px-3 bg-gray-50 dark:bg-gray-800", children: _jsxs("button", { onClick: e => {
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('p-1 flex items-center gap-1 rounded-full transition-all duration-200 w-full justify-center', isRefetching
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", "data-testid": "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" })] }) })), 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", "data-testid": "label-value-no-results", children: "No values found" })) : (groupedFilteredItems.map(group => (_jsxs(_Fragment, { children: [groupedFilteredItems.length > 1 &&
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;AA2cF,MAAM,CAAC,OAAO,UAAU,yBAAyB,CAAC,KAAK,EAAE,KAAK,GAAG,GAAG,CAAC,OAAO,CAoB3E"}
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), refetchLabelValues: refetchLabelValues, showLoadingInButton: true, hasRefreshButton: 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
+ }), 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);
@@ -14,6 +14,7 @@ interface LabelsContextType {
14
14
  setCurrentLabelName: (name: string | null) => void;
15
15
  shouldHandlePrefixes: boolean;
16
16
  refetchLabelValues: () => void;
17
+ refetchLabelNames: () => void;
17
18
  }
18
19
  interface LabelsProviderProps {
19
20
  children: React.ReactNode;
@@ -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;CAChC;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,CA2EnC;AAED,wBAAgB,SAAS,IAAI,iBAAiB,CAM7C"}
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;CAChC;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,CAuGlC;AAED,wBAAgB,SAAS,IAAI,iBAAiB,CAM7C"}
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
- return (Array.isArray(key) &&
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
- }), [value, refetchLabelValues]);
105
+ refetchLabelNames,
106
+ }), [value, refetchLabelValues, refetchLabelNames]);
97
107
  return _jsx(LabelContext.Provider, { value: contextValue, children: children });
98
108
  }
99
109
  export function useLabels() {