@parca/profile 0.19.138 → 0.19.140
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 +10 -0
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.d.ts.map +1 -1
- package/dist/GraphTooltipArrow/useGraphTooltipMetaInfo/index.js +11 -13
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
- package/dist/ProfileExplorer/ProfileExplorerCompare.js +4 -9
- package/dist/ProfileFlameChart/SamplesStrips/index.d.ts +2 -2
- package/dist/ProfileFlameChart/SamplesStrips/index.d.ts.map +1 -1
- package/dist/ProfileFlameChart/index.d.ts.map +1 -1
- package/dist/ProfileFlameChart/index.js +13 -19
- package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/FlameGraphArrow/ContextMenu.js +8 -8
- package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.js +4 -3
- package/dist/ProfileFlameGraph/index.d.ts.map +1 -1
- package/dist/ProfileFlameGraph/index.js +6 -4
- package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
- package/dist/ProfileMetricsGraph/index.js +4 -6
- package/dist/ProfileSelector/MetricsGraphSection.d.ts.map +1 -1
- package/dist/ProfileSelector/MetricsGraphSection.js +5 -10
- package/dist/ProfileSelector/index.d.ts.map +1 -1
- package/dist/ProfileSelector/index.js +27 -25
- package/dist/ProfileSelector/useAutoQuerySelector.d.ts.map +1 -1
- package/dist/ProfileSelector/useAutoQuerySelector.js +3 -0
- package/dist/ProfileTypeSelector/index.d.ts.map +1 -1
- package/dist/ProfileTypeSelector/index.js +4 -0
- package/dist/ProfileView/components/ActionButtons/SortByDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/ActionButtons/SortByDropdown.js +5 -5
- package/dist/ProfileView/components/ColorStackLegend.d.ts.map +1 -1
- package/dist/ProfileView/components/ColorStackLegend.js +2 -3
- package/dist/ProfileView/components/InvertCallStack/index.d.ts.map +1 -1
- package/dist/ProfileView/components/InvertCallStack/index.js +5 -4
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts +1 -2
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.d.ts.map +1 -1
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.js +14 -16
- package/dist/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.js +84 -170
- package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/MultiLevelDropdown.js +16 -20
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/TableColumnsDropdown.js +4 -5
- package/dist/ProfileView/components/Toolbars/index.d.ts +2 -2
- package/dist/ProfileView/components/Toolbars/index.d.ts.map +1 -1
- package/dist/ProfileView/components/Toolbars/index.js +1 -1
- package/dist/ProfileView/components/ViewSelector/index.d.ts.map +1 -1
- package/dist/ProfileView/components/ViewSelector/index.js +8 -14
- package/dist/ProfileView/context/DashboardContext.d.ts.map +1 -1
- package/dist/ProfileView/context/DashboardContext.js +6 -6
- package/dist/ProfileView/hooks/useResetFlameGraphState.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useResetFlameGraphState.js +5 -4
- package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useResetStateOnProfileTypeChange.js +25 -26
- package/dist/ProfileView/hooks/useResetStateOnSeriesChange.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useResetStateOnSeriesChange.js +13 -8
- package/dist/ProfileView/hooks/useVisualizationState.d.ts +3 -3
- package/dist/ProfileView/hooks/useVisualizationState.d.ts.map +1 -1
- package/dist/ProfileView/hooks/useVisualizationState.js +35 -51
- package/dist/ProfileViewWithData.d.ts.map +1 -1
- package/dist/ProfileViewWithData.js +19 -28
- package/dist/Sandwich/index.d.ts.map +1 -1
- package/dist/Sandwich/index.js +4 -3
- package/dist/SourceView/index.d.ts.map +1 -1
- package/dist/SourceView/index.js +4 -2
- package/dist/SourceView/useSelectedLineRange.d.ts.map +1 -1
- package/dist/SourceView/useSelectedLineRange.js +21 -16
- package/dist/Table/MoreDropdown.d.ts.map +1 -1
- package/dist/Table/MoreDropdown.js +8 -11
- package/dist/Table/TableContextMenu.d.ts.map +1 -1
- package/dist/Table/TableContextMenu.js +10 -13
- package/dist/Table/hooks/useTableConfiguration.d.ts.map +1 -1
- package/dist/Table/hooks/useTableConfiguration.js +3 -4
- package/dist/Table/index.d.ts.map +1 -1
- package/dist/Table/index.js +11 -9
- package/dist/TopTable/index.d.ts.map +1 -1
- package/dist/TopTable/index.js +3 -4
- package/dist/hooks/urlParsers.d.ts +18 -0
- package/dist/hooks/urlParsers.d.ts.map +1 -0
- package/dist/hooks/urlParsers.js +32 -0
- package/dist/hooks/useColorBy.d.ts +5 -0
- package/dist/hooks/useColorBy.d.ts.map +1 -0
- package/dist/hooks/useColorBy.js +26 -0
- package/dist/hooks/useCompareModeMeta.d.ts.map +1 -1
- package/dist/hooks/useCompareModeMeta.js +55 -86
- package/dist/hooks/useDashboardItems.d.ts +5 -0
- package/dist/hooks/useDashboardItems.d.ts.map +1 -0
- package/dist/hooks/useDashboardItems.js +27 -0
- package/dist/hooks/useQueryState.d.ts +3 -3
- package/dist/hooks/useQueryState.d.ts.map +1 -1
- package/dist/hooks/useQueryState.js +105 -105
- package/dist/hooks/useQueryState.test.js +186 -302
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -12
- package/dist/useSumBy.d.ts +1 -1
- package/dist/useSumBy.d.ts.map +1 -1
- package/dist/useSumBy.js +2 -2
- package/package.json +12 -11
- package/src/GraphTooltipArrow/useGraphTooltipMetaInfo/index.ts +11 -13
- package/src/ProfileExplorer/ProfileExplorerCompare.tsx +4 -9
- package/src/ProfileFlameChart/SamplesStrips/index.tsx +2 -2
- package/src/ProfileFlameChart/index.tsx +21 -28
- package/src/ProfileFlameGraph/FlameGraphArrow/ContextMenu.tsx +10 -9
- package/src/ProfileFlameGraph/FlameGraphArrow/TextWithEllipsis.tsx +5 -3
- package/src/ProfileFlameGraph/index.tsx +6 -9
- package/src/ProfileMetricsGraph/index.tsx +6 -8
- package/src/ProfileSelector/MetricsGraphSection.tsx +5 -10
- package/src/ProfileSelector/index.tsx +32 -31
- package/src/ProfileSelector/useAutoQuerySelector.ts +5 -0
- package/src/ProfileTypeSelector/index.tsx +4 -0
- package/src/ProfileView/components/ActionButtons/SortByDropdown.tsx +10 -6
- package/src/ProfileView/components/ColorStackLegend.tsx +2 -4
- package/src/ProfileView/components/InvertCallStack/index.tsx +5 -4
- package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.test.tsx +94 -192
- package/src/ProfileView/components/ProfileFilters/useProfileFiltersUrlState.ts +21 -21
- package/src/ProfileView/components/Toolbars/MultiLevelDropdown.tsx +24 -25
- package/src/ProfileView/components/Toolbars/TableColumnsDropdown.tsx +4 -5
- package/src/ProfileView/components/Toolbars/index.tsx +3 -3
- package/src/ProfileView/components/ViewSelector/index.tsx +9 -16
- package/src/ProfileView/context/DashboardContext.tsx +6 -6
- package/src/ProfileView/hooks/useResetFlameGraphState.ts +6 -4
- package/src/ProfileView/hooks/useResetStateOnProfileTypeChange.ts +24 -26
- package/src/ProfileView/hooks/useResetStateOnSeriesChange.ts +16 -8
- package/src/ProfileView/hooks/useVisualizationState.ts +61 -69
- package/src/ProfileViewWithData.tsx +29 -35
- package/src/Sandwich/index.tsx +4 -3
- package/src/SourceView/index.tsx +4 -2
- package/src/SourceView/useSelectedLineRange.ts +34 -19
- package/src/Table/MoreDropdown.tsx +9 -11
- package/src/Table/TableContextMenu.tsx +10 -13
- package/src/Table/hooks/useTableConfiguration.tsx +3 -4
- package/src/Table/index.tsx +12 -21
- package/src/TopTable/index.tsx +3 -4
- package/src/hooks/urlParsers.ts +38 -0
- package/src/hooks/useColorBy.ts +42 -0
- package/src/hooks/useCompareModeMeta.ts +61 -91
- package/src/hooks/useDashboardItems.ts +46 -0
- package/src/hooks/useQueryState.test.tsx +275 -345
- package/src/hooks/useQueryState.ts +136 -118
- package/src/index.tsx +16 -15
- package/src/useSumBy.ts +3 -3
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import {useCallback, useMemo} from 'react';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {createParser, useQueryState} from 'nuqs';
|
|
17
|
+
|
|
17
18
|
import {safeDecode} from '@parca/utilities';
|
|
18
19
|
|
|
19
20
|
import {isPresetKey} from './filterPresets';
|
|
@@ -137,31 +138,32 @@ export const decodeProfileFilters = (encoded: string): ProfileFilter[] => {
|
|
|
137
138
|
}
|
|
138
139
|
};
|
|
139
140
|
|
|
141
|
+
const profileFiltersParser = createParser<ProfileFilter[]>({
|
|
142
|
+
parse: (value: string) => decodeProfileFilters(value),
|
|
143
|
+
serialize: (value: ProfileFilter[]) => encodeProfileFilters(value),
|
|
144
|
+
eq: (a, b) => encodeProfileFilters(a) === encodeProfileFilters(b),
|
|
145
|
+
})
|
|
146
|
+
.withDefault([])
|
|
147
|
+
.withOptions({history: 'replace'});
|
|
148
|
+
|
|
140
149
|
export const useProfileFiltersUrlState = (): {
|
|
141
150
|
appliedFilters: ProfileFilter[];
|
|
142
|
-
setAppliedFilters:
|
|
151
|
+
setAppliedFilters: (filters: ProfileFilter[]) => void;
|
|
143
152
|
forceApplyFilters: (filters: ProfileFilter[]) => void;
|
|
144
153
|
} => {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
// Store applied filters in URL state for persistence using compact encoding
|
|
148
|
-
const [appliedFilters, setAppliedFilters] = useURLStateCustom<ProfileFilter[]>(
|
|
149
|
-
`profile_filters`,
|
|
150
|
-
{
|
|
151
|
-
parse: value => {
|
|
152
|
-
return decodeProfileFilters(value as string);
|
|
153
|
-
},
|
|
154
|
-
stringify: value => {
|
|
155
|
-
return encodeProfileFilters(value);
|
|
156
|
-
},
|
|
157
|
-
defaultValue: [],
|
|
158
|
-
}
|
|
159
|
-
);
|
|
154
|
+
const [appliedFilters, setRawFilters] = useQueryState('profile_filters', profileFiltersParser);
|
|
160
155
|
|
|
161
156
|
const memoizedAppliedFilters = useMemo(() => {
|
|
162
157
|
return appliedFilters ?? [];
|
|
163
158
|
}, [appliedFilters]);
|
|
164
159
|
|
|
160
|
+
const setAppliedFilters = useCallback(
|
|
161
|
+
(filters: ProfileFilter[]) => {
|
|
162
|
+
void setRawFilters(filters);
|
|
163
|
+
},
|
|
164
|
+
[setRawFilters]
|
|
165
|
+
);
|
|
166
|
+
|
|
165
167
|
// Force apply filters (bypasses preserve-existing strategy)
|
|
166
168
|
const forceApplyFilters = useCallback(
|
|
167
169
|
(filters: ProfileFilter[]) => {
|
|
@@ -172,11 +174,9 @@ export const useProfileFiltersUrlState = (): {
|
|
|
172
174
|
return f.value !== '' && f.type != null && f.field != null && f.matchType != null;
|
|
173
175
|
});
|
|
174
176
|
|
|
175
|
-
|
|
176
|
-
setAppliedFilters(validFilters);
|
|
177
|
-
});
|
|
177
|
+
setAppliedFilters(validFilters);
|
|
178
178
|
},
|
|
179
|
-
[
|
|
179
|
+
[setAppliedFilters]
|
|
180
180
|
);
|
|
181
181
|
|
|
182
182
|
return {
|
|
@@ -16,8 +16,8 @@ import React, {useCallback, useEffect, useRef, useState} from 'react';
|
|
|
16
16
|
import {Menu} from '@headlessui/react';
|
|
17
17
|
import {Icon} from '@iconify/react';
|
|
18
18
|
import cx from 'classnames';
|
|
19
|
+
import {useQueryState} from 'nuqs';
|
|
19
20
|
|
|
20
|
-
import {useURLState} from '@parca/components';
|
|
21
21
|
import {USER_PREFERENCES, useUserPreference} from '@parca/hooks';
|
|
22
22
|
import {ProfileType} from '@parca/parser';
|
|
23
23
|
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
FIELD_LOCATION_ADDRESS,
|
|
28
28
|
FIELD_MAPPING_FILE,
|
|
29
29
|
} from '../../../ProfileFlameGraph/FlameGraphArrow';
|
|
30
|
+
import {boolParam, hiddenBinariesParser, stringParam} from '../../../hooks/urlParsers';
|
|
30
31
|
import {useProfileViewContext} from '../../context/ProfileViewContext';
|
|
31
32
|
import SwitchMenuItem from './SwitchMenuItem';
|
|
32
33
|
|
|
@@ -206,14 +207,15 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
206
207
|
}) => {
|
|
207
208
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
208
209
|
const [shouldOpenLeft, setShouldOpenLeft] = useState(false);
|
|
209
|
-
const [storeSortBy] =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
const [storeSortBy] = useQueryState('sort_by', stringParam.withDefault(FIELD_FUNCTION_NAME));
|
|
211
|
+
const [colorStackLegend, setStoreColorStackLegend] = useQueryState(
|
|
212
|
+
'color_stack_legend',
|
|
213
|
+
stringParam
|
|
214
|
+
);
|
|
215
|
+
const [hiddenBinaries, setHiddenBinaries] = useQueryState(
|
|
216
|
+
'hidden_binaries',
|
|
217
|
+
hiddenBinariesParser
|
|
218
|
+
);
|
|
217
219
|
const {compareMode} = useProfileViewContext();
|
|
218
220
|
const [colorProfileName] = useUserPreference<string>(
|
|
219
221
|
USER_PREFERENCES.FLAMEGRAPH_COLOR_PROFILE.key
|
|
@@ -223,11 +225,10 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
223
225
|
|
|
224
226
|
// By default, we want delta profiles (CPU) to be relatively compared.
|
|
225
227
|
// For non-delta profiles, like goroutines or memory, we want the profiles to be compared absolutely.
|
|
226
|
-
const compareAbsoluteDefault = profileType?.delta === false
|
|
228
|
+
const compareAbsoluteDefault = profileType?.delta === false;
|
|
227
229
|
|
|
228
|
-
const [compareAbsolute
|
|
229
|
-
|
|
230
|
-
const isCompareAbsolute = compareAbsolute === 'true';
|
|
230
|
+
const [compareAbsolute, setCompareAbsolute] = useQueryState('compare_absolute', boolParam);
|
|
231
|
+
const isCompareAbsolute = compareAbsolute ?? compareAbsoluteDefault;
|
|
231
232
|
|
|
232
233
|
useEffect(() => {
|
|
233
234
|
const checkOverflow = (): void => {
|
|
@@ -248,20 +249,20 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
248
249
|
}, [isTableVizOnly]);
|
|
249
250
|
|
|
250
251
|
const handleBinaryToggle = (index: number): void => {
|
|
251
|
-
const updatedBinaries = [...
|
|
252
|
+
const updatedBinaries = [...hiddenBinaries];
|
|
252
253
|
updatedBinaries.splice(index, 1);
|
|
253
|
-
setHiddenBinaries(updatedBinaries);
|
|
254
|
+
void setHiddenBinaries(updatedBinaries);
|
|
254
255
|
};
|
|
255
256
|
|
|
256
257
|
const setColorStackLegend = useCallback(
|
|
257
258
|
(value: string): void => {
|
|
258
|
-
setStoreColorStackLegend(value);
|
|
259
|
+
void setStoreColorStackLegend(value);
|
|
259
260
|
},
|
|
260
261
|
[setStoreColorStackLegend]
|
|
261
262
|
);
|
|
262
263
|
|
|
263
264
|
const resetLegend = (): void => {
|
|
264
|
-
setHiddenBinaries([]);
|
|
265
|
+
void setHiddenBinaries([]);
|
|
265
266
|
};
|
|
266
267
|
|
|
267
268
|
const menuItems: MenuItemType[] = [
|
|
@@ -329,7 +330,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
329
330
|
},
|
|
330
331
|
{
|
|
331
332
|
label: isCompareAbsolute ? 'Compare Relative' : 'Compare Absolute',
|
|
332
|
-
onclick: () => setCompareAbsolute(isCompareAbsolute
|
|
333
|
+
onclick: () => void setCompareAbsolute(!isCompareAbsolute),
|
|
333
334
|
hide: !compareMode,
|
|
334
335
|
icon: isCompareAbsolute ? 'fluent-mdl2:compare' : 'fluent-mdl2:compare-uneven',
|
|
335
336
|
},
|
|
@@ -359,7 +360,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
359
360
|
},
|
|
360
361
|
{
|
|
361
362
|
label: 'Reset Legend',
|
|
362
|
-
hide: hiddenBinaries
|
|
363
|
+
hide: hiddenBinaries.length === 0,
|
|
363
364
|
onclick: () => resetLegend(),
|
|
364
365
|
id: 'h-reset-legend-button',
|
|
365
366
|
icon: 'system-uicons:reset',
|
|
@@ -367,7 +368,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
367
368
|
{
|
|
368
369
|
label: 'Hidden Binaries',
|
|
369
370
|
id: 'h-hidden-binaries',
|
|
370
|
-
items:
|
|
371
|
+
items: hiddenBinaries.map((binary, index) => ({
|
|
371
372
|
label: binary,
|
|
372
373
|
customSubmenu: (
|
|
373
374
|
<div className="flex items-center gap-2 w-full">
|
|
@@ -383,7 +384,7 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
383
384
|
</div>
|
|
384
385
|
),
|
|
385
386
|
})),
|
|
386
|
-
hide: hiddenBinaries
|
|
387
|
+
hide: hiddenBinaries.length === 0,
|
|
387
388
|
icon: 'ph:eye-closed',
|
|
388
389
|
},
|
|
389
390
|
];
|
|
@@ -424,10 +425,8 @@ const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
|
|
|
424
425
|
{...item}
|
|
425
426
|
onSelect={onSelect}
|
|
426
427
|
closeDropdown={close}
|
|
427
|
-
activeValueForSortBy={storeSortBy
|
|
428
|
-
activeValueForColorBy={
|
|
429
|
-
colorBy === undefined || colorBy === '' ? 'binary' : colorBy
|
|
430
|
-
}
|
|
428
|
+
activeValueForSortBy={storeSortBy}
|
|
429
|
+
activeValueForColorBy={colorBy}
|
|
431
430
|
activeValuesForLevel={groupBy}
|
|
432
431
|
renderAsDiv={item.renderAsDiv}
|
|
433
432
|
/>
|
|
@@ -14,14 +14,15 @@
|
|
|
14
14
|
import {useEffect, useMemo, useState} from 'react';
|
|
15
15
|
|
|
16
16
|
import {createColumnHelper, type ColumnDef} from '@tanstack/table-core';
|
|
17
|
+
import {useQueryState} from 'nuqs';
|
|
17
18
|
|
|
18
|
-
import {useURLState} from '@parca/components';
|
|
19
19
|
import {ProfileType} from '@parca/parser';
|
|
20
20
|
import {valueFormatter} from '@parca/utilities';
|
|
21
21
|
|
|
22
22
|
import {Row} from '../../../Table';
|
|
23
23
|
import ColumnsVisibility from '../../../Table/ColumnsVisibility';
|
|
24
24
|
import {ColumnName, addPlusSign, getRatioString} from '../../../Table/utils/functions';
|
|
25
|
+
import {tableColumnsParser} from '../../../hooks/urlParsers';
|
|
25
26
|
import {useProfileViewContext} from '../../context/ProfileViewContext';
|
|
26
27
|
|
|
27
28
|
interface Props {
|
|
@@ -32,9 +33,7 @@ interface Props {
|
|
|
32
33
|
|
|
33
34
|
const TableColumnsDropdown = ({profileType, total, filtered}: Props): JSX.Element => {
|
|
34
35
|
const {compareMode} = useProfileViewContext();
|
|
35
|
-
const [tableColumns, setTableColumns] =
|
|
36
|
-
alwaysReturnArray: true,
|
|
37
|
-
});
|
|
36
|
+
const [tableColumns, setTableColumns] = useQueryState('table_columns', tableColumnsParser);
|
|
38
37
|
|
|
39
38
|
const columnHelper = createColumnHelper<Row>();
|
|
40
39
|
|
|
@@ -190,7 +189,7 @@ const TableColumnsDropdown = ({profileType, total, filtered}: Props): JSX.Elemen
|
|
|
190
189
|
const newTableColumns = (Object.keys(updatedColumns) as ColumnName[]).filter(
|
|
191
190
|
col => updatedColumns[col]
|
|
192
191
|
);
|
|
193
|
-
setTableColumns(newTableColumns);
|
|
192
|
+
void setTableColumns(newTableColumns);
|
|
194
193
|
};
|
|
195
194
|
|
|
196
195
|
return (
|
|
@@ -50,7 +50,7 @@ export interface VisualisationToolbarProps {
|
|
|
50
50
|
flamechartDimension: string[];
|
|
51
51
|
setFlamechartDimension: (labels: string[]) => void;
|
|
52
52
|
showVisualizationSelector?: boolean;
|
|
53
|
-
sandwichFunctionName
|
|
53
|
+
sandwichFunctionName: string | null;
|
|
54
54
|
alignFunctionName: string;
|
|
55
55
|
setAlignFunctionName: (align: string) => void;
|
|
56
56
|
colorBy: string;
|
|
@@ -75,7 +75,7 @@ export interface FlameGraphToolbarProps {
|
|
|
75
75
|
|
|
76
76
|
export interface SandwichFlameGraphToolbarProps {
|
|
77
77
|
resetSandwichFunctionName: () => void;
|
|
78
|
-
sandwichFunctionName
|
|
78
|
+
sandwichFunctionName: string | null;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
export const TableToolbar: FC<TableToolbarProps> = ({profileType, total, filtered}) => {
|
|
@@ -120,7 +120,7 @@ export const SandwichFlameGraphToolbar: FC<SandwichFlameGraphToolbarProps> = ({
|
|
|
120
120
|
onClick={() => resetSandwichFunctionName()}
|
|
121
121
|
className="w-auto"
|
|
122
122
|
variant="neutral"
|
|
123
|
-
disabled={sandwichFunctionName
|
|
123
|
+
disabled={sandwichFunctionName == null || sandwichFunctionName.length === 0}
|
|
124
124
|
>
|
|
125
125
|
Reset view
|
|
126
126
|
</Button>
|
|
@@ -13,9 +13,13 @@
|
|
|
13
13
|
|
|
14
14
|
import {ReactNode} from 'react';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {useQueryState} from 'nuqs';
|
|
17
|
+
|
|
18
|
+
import {useParcaContext} from '@parca/components';
|
|
17
19
|
|
|
18
20
|
import {ProfileSource} from '../../../ProfileSource';
|
|
21
|
+
import {stringParam} from '../../../hooks/urlParsers';
|
|
22
|
+
import {useDashboardItems} from '../../../hooks/useDashboardItems';
|
|
19
23
|
import Dropdown, {DropdownElement, InnerAction} from './Dropdown';
|
|
20
24
|
|
|
21
25
|
interface Props {
|
|
@@ -23,15 +27,9 @@ interface Props {
|
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
const ViewSelector = ({profileSource}: Props): JSX.Element => {
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
{
|
|
29
|
-
alwaysReturnArray: true,
|
|
30
|
-
}
|
|
31
|
-
);
|
|
32
|
-
const [, setSandwichFunctionName] = useURLState<string | undefined>('sandwich_function_name');
|
|
30
|
+
const {dashboardItems, setDashboardItems} = useDashboardItems();
|
|
31
|
+
const [, setSandwichFunctionName] = useQueryState('sandwich_function_name', stringParam);
|
|
33
32
|
const {enableSourcesView, enableSandwichView} = useParcaContext();
|
|
34
|
-
const batchUpdates = useURLStateBatch();
|
|
35
33
|
|
|
36
34
|
const allItems: Array<{
|
|
37
35
|
key: string;
|
|
@@ -129,14 +127,9 @@ const ViewSelector = ({profileSource}: Props): JSX.Element => {
|
|
|
129
127
|
} else {
|
|
130
128
|
const newDashboardItems = dashboardItems.filter(v => v !== item.key);
|
|
131
129
|
|
|
132
|
-
|
|
130
|
+
setDashboardItems(newDashboardItems);
|
|
133
131
|
if (item.key === 'sandwich') {
|
|
134
|
-
|
|
135
|
-
setDashboardItems(newDashboardItems);
|
|
136
|
-
setSandwichFunctionName(undefined);
|
|
137
|
-
});
|
|
138
|
-
} else {
|
|
139
|
-
setDashboardItems(newDashboardItems);
|
|
132
|
+
void setSandwichFunctionName(null);
|
|
140
133
|
}
|
|
141
134
|
}
|
|
142
135
|
},
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
|
|
14
14
|
import {FC, PropsWithChildren, createContext, useContext} from 'react';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {useQueryState} from 'nuqs';
|
|
17
17
|
|
|
18
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
19
|
+
import {useDashboardItems} from '../../hooks/useDashboardItems';
|
|
18
20
|
import {VisualizationType} from '../types/visualization';
|
|
19
21
|
|
|
20
22
|
interface DashboardContextType {
|
|
@@ -27,10 +29,8 @@ interface DashboardContextType {
|
|
|
27
29
|
const DashboardContext = createContext<DashboardContextType | undefined>(undefined);
|
|
28
30
|
|
|
29
31
|
export const DashboardProvider: FC<PropsWithChildren> = ({children}) => {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
});
|
|
33
|
-
const [, setSandwichFunctionName] = useURLState<string | undefined>('sandwich_function_name');
|
|
32
|
+
const {dashboardItems, setDashboardItems} = useDashboardItems();
|
|
33
|
+
const [, setSandwichFunctionName] = useQueryState('sandwich_function_name', stringParam);
|
|
34
34
|
|
|
35
35
|
const handleClosePanel = (visualizationType: VisualizationType): void => {
|
|
36
36
|
const newDashboardItems = dashboardItems.filter(item => item !== visualizationType);
|
|
@@ -38,7 +38,7 @@ export const DashboardProvider: FC<PropsWithChildren> = ({children}) => {
|
|
|
38
38
|
|
|
39
39
|
// Reset sandwich function name when closing sandwich panel
|
|
40
40
|
if (visualizationType === 'sandwich') {
|
|
41
|
-
setSandwichFunctionName(
|
|
41
|
+
void setSandwichFunctionName(null);
|
|
42
42
|
}
|
|
43
43
|
};
|
|
44
44
|
|
|
@@ -11,17 +11,19 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {useQueryState} from 'nuqs';
|
|
15
|
+
|
|
16
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
15
17
|
|
|
16
18
|
export const useResetFlameGraphState = (): (() => void) => {
|
|
17
|
-
const [val, setCurPath] =
|
|
19
|
+
const [val, setCurPath] = useQueryState('cur_path', stringParam);
|
|
18
20
|
|
|
19
21
|
return () => {
|
|
20
22
|
setTimeout(() => {
|
|
21
|
-
if (val ===
|
|
23
|
+
if (val === null) {
|
|
22
24
|
return;
|
|
23
25
|
}
|
|
24
|
-
setCurPath(
|
|
26
|
+
void setCurPath(null);
|
|
25
27
|
});
|
|
26
28
|
};
|
|
27
29
|
};
|
|
@@ -11,39 +11,37 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {useQueryStates} from 'nuqs';
|
|
15
15
|
|
|
16
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
16
17
|
import {useProfileFilters} from '../components/ProfileFilters/useProfileFilters';
|
|
17
18
|
|
|
18
19
|
export const useResetStateOnProfileTypeChange = (): (() => void) => {
|
|
19
|
-
const [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const [state, setState] = useQueryStates(
|
|
21
|
+
{
|
|
22
|
+
group_by: stringParam,
|
|
23
|
+
cur_path: stringParam,
|
|
24
|
+
sum_by_a: stringParam,
|
|
25
|
+
sum_by_b: stringParam,
|
|
26
|
+
sandwich_function_name: stringParam,
|
|
27
|
+
},
|
|
28
|
+
{history: 'replace'}
|
|
29
|
+
);
|
|
23
30
|
const {resetFilters} = useProfileFilters();
|
|
24
|
-
const [sandwichFunctionName, setSandwichFunctionName] = useURLState('sandwich_function_name');
|
|
25
|
-
const batchUpdates = useURLStateBatch();
|
|
26
31
|
|
|
27
32
|
return () => {
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
if (sandwichFunctionName !== undefined) {
|
|
37
|
-
setSandwichFunctionName(undefined);
|
|
38
|
-
}
|
|
39
|
-
if (sumByA !== undefined) {
|
|
40
|
-
setSumByA(undefined);
|
|
41
|
-
}
|
|
42
|
-
if (sumByB !== undefined) {
|
|
43
|
-
setSumByB(undefined);
|
|
44
|
-
}
|
|
33
|
+
// Atomic reset: clear all params in single URL update
|
|
34
|
+
const updates: Record<string, null> = {};
|
|
35
|
+
if (state.group_by !== null) updates.group_by = null;
|
|
36
|
+
if (state.cur_path !== null) updates.cur_path = null;
|
|
37
|
+
if (state.sandwich_function_name !== null) updates.sandwich_function_name = null;
|
|
38
|
+
if (state.sum_by_a !== null) updates.sum_by_a = null;
|
|
39
|
+
if (state.sum_by_b !== null) updates.sum_by_b = null;
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
if (Object.keys(updates).length > 0) {
|
|
42
|
+
void setState(updates);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
resetFilters();
|
|
48
46
|
};
|
|
49
47
|
};
|
|
@@ -11,19 +11,27 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {useQueryStates} from 'nuqs';
|
|
15
|
+
|
|
16
|
+
import {stringParam} from '../../hooks/urlParsers';
|
|
15
17
|
|
|
16
18
|
export const useResetStateOnSeriesChange = (): (() => void) => {
|
|
17
|
-
const [
|
|
18
|
-
|
|
19
|
+
const [state, setState] = useQueryStates(
|
|
20
|
+
{
|
|
21
|
+
cur_path: stringParam,
|
|
22
|
+
sandwich_function_name: stringParam,
|
|
23
|
+
},
|
|
24
|
+
{history: 'replace'}
|
|
25
|
+
);
|
|
19
26
|
|
|
20
27
|
return () => {
|
|
21
28
|
setTimeout(() => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
const updates: Record<string, null> = {};
|
|
30
|
+
if (state.cur_path !== null) updates.cur_path = null;
|
|
31
|
+
if (state.sandwich_function_name !== null) updates.sandwich_function_name = null;
|
|
32
|
+
|
|
33
|
+
if (Object.keys(updates).length > 0) {
|
|
34
|
+
void setState(updates);
|
|
27
35
|
}
|
|
28
36
|
});
|
|
29
37
|
};
|