@parca/profile 0.16.103 → 0.16.105
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/Callgraph/index.d.ts +1 -0
- package/dist/GraphTooltip/index.d.ts +1 -0
- package/dist/IcicleGraph.d.ts +1 -0
- package/dist/IcicleGraph.js +1 -2
- package/dist/MatchersInput/SuggestionItem.d.ts +1 -0
- package/dist/MatchersInput/SuggestionsList.d.ts +1 -0
- package/dist/MatchersInput/index.d.ts +1 -0
- package/dist/MetricsCircle/index.d.ts +1 -0
- package/dist/MetricsGraph/index.d.ts +1 -0
- package/dist/MetricsSeries/index.d.ts +1 -0
- package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts +1 -0
- package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts +1 -0
- package/dist/ProfileExplorer/index.d.ts +1 -0
- package/dist/ProfileIcicleGraph/index.d.ts +3 -1
- package/dist/ProfileIcicleGraph/index.js +2 -2
- package/dist/ProfileMetricsGraph/index.d.ts +1 -0
- package/dist/ProfileSelector/CompareButton.d.ts +1 -0
- package/dist/ProfileSelector/MergeButton.d.ts +1 -0
- package/dist/ProfileSelector/index.d.ts +1 -0
- package/dist/ProfileSource.d.ts +1 -0
- package/dist/ProfileTypeSelector/index.d.ts +1 -0
- package/dist/ProfileView/FilterByFunctionButton.d.ts +1 -0
- package/dist/ProfileView/ViewSelector.d.ts +1 -0
- package/dist/ProfileView/index.d.ts +1 -0
- package/dist/ProfileView/index.js +4 -4
- package/dist/ProfileViewWithData.d.ts +1 -0
- package/dist/TopTable/index.d.ts +3 -1
- package/dist/TopTable/index.js +2 -2
- package/dist/components/DiffLegend.d.ts +1 -0
- package/dist/components/ProfileShareButton/ResultBox.d.ts +1 -0
- package/dist/components/ProfileShareButton/index.d.ts +1 -0
- package/package.json +4 -4
- package/src/IcicleGraph.tsx +7 -2
- package/src/ProfileIcicleGraph/index.tsx +5 -1
- package/src/ProfileView/index.tsx +7 -3
- package/src/TopTable/index.tsx +8 -2
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.16.105](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.104...@parca/profile@0.16.105) (2023-02-02)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @parca/profile
|
|
9
|
+
|
|
10
|
+
## [0.16.104](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.103...@parca/profile@0.16.104) (2023-01-27)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @parca/profile
|
|
13
|
+
|
|
6
14
|
## [0.16.103](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.102...@parca/profile@0.16.103) (2023-01-27)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @parca/profile
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { CallgraphNode, FlamegraphNode, FlamegraphNodeMeta, FlamegraphRootNode } from '@parca/client';
|
|
2
3
|
import { Function as ParcaFunction, Location, Mapping } from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
3
4
|
interface GraphTooltipProps {
|
package/dist/IcicleGraph.d.ts
CHANGED
package/dist/IcicleGraph.js
CHANGED
|
@@ -28,12 +28,11 @@ import { throttle } from 'lodash';
|
|
|
28
28
|
import { pointer } from 'd3-selection';
|
|
29
29
|
import { scaleLinear } from 'd3-scale';
|
|
30
30
|
import GraphTooltip from './GraphTooltip';
|
|
31
|
-
import { diffColor, getLastItem, isSearchMatch, selectQueryParam } from '@parca/functions';
|
|
31
|
+
import { diffColor, getLastItem, isSearchMatch, selectQueryParam, useURLState, } from '@parca/functions';
|
|
32
32
|
import { selectDarkMode, useAppSelector } from '@parca/store';
|
|
33
33
|
import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
|
|
34
34
|
import { Button } from '@parca/components';
|
|
35
35
|
import { hexifyAddress } from './utils';
|
|
36
|
-
import { useURLState } from '@parca/functions';
|
|
37
36
|
var RowHeight = 26;
|
|
38
37
|
var icicleRectStyles = {
|
|
39
38
|
cursor: 'pointer',
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { Flamegraph } from '@parca/client';
|
|
2
3
|
export type ResizeHandler = (width: number, height: number) => void;
|
|
3
4
|
interface ProfileIcicleGraphProps {
|
|
@@ -7,6 +8,7 @@ interface ProfileIcicleGraphProps {
|
|
|
7
8
|
curPath: string[] | [];
|
|
8
9
|
setNewCurPath: (path: string[]) => void;
|
|
9
10
|
onContainerResize?: ResizeHandler;
|
|
11
|
+
loading: boolean;
|
|
10
12
|
}
|
|
11
|
-
declare const ProfileIcicleGraph: ({ graph, curPath, setNewCurPath, sampleUnit, onContainerResize, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
13
|
+
declare const ProfileIcicleGraph: ({ graph, curPath, setNewCurPath, sampleUnit, onContainerResize, loading, }: ProfileIcicleGraphProps) => JSX.Element;
|
|
12
14
|
export default ProfileIcicleGraph;
|
|
@@ -17,7 +17,7 @@ import { selectQueryParam } from '@parca/functions';
|
|
|
17
17
|
import { useEffect, useMemo } from 'react';
|
|
18
18
|
var numberFormatter = new Intl.NumberFormat('en-US');
|
|
19
19
|
var ProfileIcicleGraph = function (_a) {
|
|
20
|
-
var graph = _a.graph, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit, onContainerResize = _a.onContainerResize;
|
|
20
|
+
var graph = _a.graph, curPath = _a.curPath, setNewCurPath = _a.setNewCurPath, sampleUnit = _a.sampleUnit, onContainerResize = _a.onContainerResize, loading = _a.loading;
|
|
21
21
|
var compareMode = selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
|
|
22
22
|
var _b = useContainerDimensions(), ref = _b.ref, dimensions = _b.dimensions;
|
|
23
23
|
useEffect(function () {
|
|
@@ -45,7 +45,7 @@ var ProfileIcicleGraph = function (_a) {
|
|
|
45
45
|
if (graph === undefined)
|
|
46
46
|
return _jsx("div", { children: "no data..." });
|
|
47
47
|
var total = graph.total;
|
|
48
|
-
if (parseFloat(total) === 0)
|
|
48
|
+
if (parseFloat(total) === 0 && !loading)
|
|
49
49
|
return _jsx(_Fragment, { children: "Profile has no samples" });
|
|
50
50
|
return (_jsxs(_Fragment, { children: [compareMode && _jsx(DiffLegend, {}), trimDifference > BigInt(0) ? (_jsxs("p", __assign({ className: "my-2 text-sm" }, { children: ["Showing ", formattedTotal, "(", trimmedPercentage, "%) out of ", formattedUntrimmedTotal, " samples"] }))) : null, _jsx("div", __assign({ ref: ref }, { children: _jsx(IcicleGraph, { width: dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, graph: graph, curPath: curPath, setCurPath: setNewCurPath, sampleUnit: sampleUnit }) }))] }));
|
|
51
51
|
};
|
package/dist/ProfileSource.d.ts
CHANGED
|
@@ -101,13 +101,13 @@ export var ProfileView = function (_a) {
|
|
|
101
101
|
var type = _a.type, isHalfScreen = _a.isHalfScreen;
|
|
102
102
|
switch (type) {
|
|
103
103
|
case 'icicle': {
|
|
104
|
-
return (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null ? (_jsx(Profiler, __assign({ id: "icicleGraph", onRender: perf === null || perf === void 0 ? void 0 : perf.onRender }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize }) }))) : (_jsx(_Fragment, {}));
|
|
104
|
+
return (flamegraphData === null || flamegraphData === void 0 ? void 0 : flamegraphData.data) != null ? (_jsx(Profiler, __assign({ id: "icicleGraph", onRender: perf === null || perf === void 0 ? void 0 : perf.onRender }, { children: _jsx(ProfileIcicleGraph, { curPath: curPath, setNewCurPath: setNewCurPath, graph: flamegraphData.data, sampleUnit: sampleUnit, onContainerResize: onFlamegraphContainerResize, loading: flamegraphData.loading }) }))) : (_jsx(_Fragment, {}));
|
|
105
105
|
}
|
|
106
106
|
case 'callgraph': {
|
|
107
107
|
return (callgraphData === null || callgraphData === void 0 ? void 0 : callgraphData.data) != null && (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) !== undefined ? (_jsx(Callgraph, { graph: callgraphData.data, sampleUnit: sampleUnit, width: isHalfScreen ? (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) / 2 : dimensions === null || dimensions === void 0 ? void 0 : dimensions.width, colorRange: colorRange })) : (_jsx(_Fragment, {}));
|
|
108
108
|
}
|
|
109
109
|
case 'table': {
|
|
110
|
-
return topTableData != null ? (_jsx(TopTable, { data: topTableData.data, sampleUnit: sampleUnit, navigateTo: navigateTo })) : (_jsx(_Fragment, {}));
|
|
110
|
+
return topTableData != null ? (_jsx(TopTable, { loading: topTableData.loading, data: topTableData.data, sampleUnit: sampleUnit, navigateTo: navigateTo })) : (_jsx(_Fragment, {}));
|
|
111
111
|
}
|
|
112
112
|
default: {
|
|
113
113
|
return _jsx(_Fragment, {});
|
|
@@ -128,10 +128,10 @@ export var ProfileView = function (_a) {
|
|
|
128
128
|
setDashboardItems(newDashboardItems);
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
|
-
return (_jsx(_Fragment, { children: _jsx("div", __assign({ className: "py-3" }, { children: _jsx(Card, { children: _jsxs(Card.Body, { children: [_jsxs("div", __assign({ className: "flex py-3 w-full" }, { children: [_jsxs("div", __assign({ className: "w-2/5 flex space-x-4" }, { children: [_jsxs("div", __assign({ className: "flex space-x-1" }, { children: [profileSource != null && queryClient != null ? (_jsx(ProfileShareButton, { queryRequest: profileSource.QueryRequest(), queryClient: queryClient
|
|
131
|
+
return (_jsx(_Fragment, { children: _jsx("div", __assign({ className: "py-3" }, { children: _jsx(Card, { children: _jsxs(Card.Body, { children: [_jsxs("div", __assign({ className: "flex py-3 w-full" }, { children: [_jsxs("div", __assign({ className: "w-2/5 flex space-x-4" }, { children: [_jsxs("div", __assign({ className: "flex space-x-1" }, { children: [profileSource != null && queryClient != null ? (_jsx(ProfileShareButton, { queryRequest: profileSource.QueryRequest(), queryClient: queryClient })) : null, _jsx(Button, __assign({ color: "neutral", onClick: function (e) {
|
|
132
132
|
e.preventDefault();
|
|
133
133
|
onDownloadPProf();
|
|
134
|
-
}
|
|
134
|
+
} }, { children: "Download pprof" }))] })), _jsx(FilterByFunctionButton, { navigateTo: navigateTo })] })), _jsx("div", __assign({ className: "flex ml-auto gap-2" }, { children: _jsx(ViewSelector, { defaultValue: "", navigateTo: navigateTo, position: -1, placeholderText: "Add panel...", primary: true, addView: true, disabled: isMultiPanelView || dashboardItems.length < 1 }) }))] })), isLoaderVisible ? (_jsx(_Fragment, { children: loader })) : (_jsx(DragDropContext, __assign({ onDragEnd: onDragEnd }, { children: _jsx("div", __assign({ className: "w-full", ref: ref }, { children: _jsx(Droppable, __assign({ droppableId: "droppable", direction: "horizontal" }, { children: function (provided) { return (_jsx("div", __assign({ ref: provided.innerRef, className: "flex space-x-4 justify-between w-full" }, provided.droppableProps, { children: dashboardItems.map(function (dashboardItem, index) {
|
|
135
135
|
return (_jsx(Draggable, __assign({ draggableId: dashboardItem, index: index, isDragDisabled: !isMultiPanelView }, { children: function (provided, snapshot) { return (_createElement("div", __assign({ ref: provided.innerRef }, provided.draggableProps, { key: dashboardItem, className: cx('border dark:bg-gray-700 rounded border-gray-300 dark:border-gray-500 p-3', isMultiPanelView ? 'w-1/2' : 'w-full', snapshot.isDragging ? 'bg-gray-200' : 'bg-white') }),
|
|
136
136
|
_jsxs("div", __assign({ className: "w-full flex justify-end pb-2" }, { children: [_jsxs("div", __assign({ className: "w-full flex justify-between" }, { children: [_jsx("div", __assign({ className: cx(isMultiPanelView ? 'visible' : 'invisible', 'flex items-center') }, provided.dragHandleProps, { children: _jsx(Icon, { className: "text-xl", icon: "material-symbols:drag-indicator" }) })), _jsx(ViewSelector, { defaultValue: dashboardItem, navigateTo: navigateTo, position: index })] })), isMultiPanelView && (_jsx("button", __assign({ type: "button", onClick: function () { return handleClosePanel(dashboardItem); }, className: "pl-2" }, { children: _jsx(CloseIcon, {}) })))] })),
|
|
137
137
|
getDashboardItemByType({
|
package/dist/TopTable/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
import { NavigateFunction } from '@parca/functions';
|
|
2
3
|
import { TopNodeMeta, Top } from '@parca/client';
|
|
3
4
|
import '../TopTable.styles.css';
|
|
4
5
|
interface TopTableProps {
|
|
6
|
+
loading: boolean;
|
|
5
7
|
data?: Top;
|
|
6
8
|
sampleUnit: string;
|
|
7
9
|
navigateTo?: NavigateFunction;
|
|
8
10
|
}
|
|
9
11
|
export declare const RowLabel: (meta: TopNodeMeta | undefined) => string;
|
|
10
|
-
export declare const TopTable: ({ data: top, sampleUnit: unit, navigateTo }: TopTableProps) => JSX.Element;
|
|
12
|
+
export declare const TopTable: ({ data: top, sampleUnit: unit, navigateTo, loading, }: TopTableProps) => JSX.Element;
|
|
11
13
|
export default TopTable;
|
package/dist/TopTable/index.js
CHANGED
|
@@ -50,7 +50,7 @@ var addPlusSign = function (num) {
|
|
|
50
50
|
};
|
|
51
51
|
export var TopTable = function (_a) {
|
|
52
52
|
var _b;
|
|
53
|
-
var top = _a.data, unit = _a.sampleUnit, navigateTo = _a.navigateTo;
|
|
53
|
+
var top = _a.data, unit = _a.sampleUnit, navigateTo = _a.navigateTo, loading = _a.loading;
|
|
54
54
|
var router = parseParams(window.location.search);
|
|
55
55
|
var currentSearchString = selectQueryParam('search_string');
|
|
56
56
|
var compareMode = Boolean(selectQueryParam('compare_a')) && Boolean(selectQueryParam('compare_b'));
|
|
@@ -128,7 +128,7 @@ export var TopTable = function (_a) {
|
|
|
128
128
|
return [{ id: compareMode ? 'diff' : 'cumulative', desc: true }];
|
|
129
129
|
}, [compareMode]);
|
|
130
130
|
var total = top != null ? top.list.length : 0;
|
|
131
|
-
if (total === 0)
|
|
131
|
+
if (total === 0 && !loading)
|
|
132
132
|
return _jsx(_Fragment, { children: "Profile has no samples" });
|
|
133
133
|
return (_jsx(_Fragment, { children: _jsx("div", __assign({ className: "w-full font-robotoMono h-[80vh] overflow-scroll" }, { children: _jsx(Table, { data: (_b = top === null || top === void 0 ? void 0 : top.list) !== null && _b !== void 0 ? _b : [], columns: columns, initialSorting: initialSorting, onRowClick: onRowClick, enableHighlighting: enableHighlighting, shouldHighlightRow: shouldHighlightRow }) })) }));
|
|
134
134
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parca/profile",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.105",
|
|
4
4
|
"description": "Profile viewing libraries",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@parca/client": "^0.16.62",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"d3-scale": "^4.0.2",
|
|
15
15
|
"d3-selection": "3.0.0",
|
|
16
16
|
"graphviz-wasm": "3.0.0",
|
|
17
|
-
"konva": "8.4.
|
|
17
|
+
"konva": "8.4.2",
|
|
18
18
|
"react-beautiful-dnd": "^13.1.1",
|
|
19
19
|
"react-copy-to-clipboard": "^5.1.0",
|
|
20
20
|
"react-cytoscapejs": "1.2.1",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@types/react-copy-to-clipboard": "5.0.4"
|
|
28
28
|
},
|
|
29
29
|
"resolutions": {
|
|
30
|
-
"konva": "8.4.
|
|
30
|
+
"konva": "8.4.2"
|
|
31
31
|
},
|
|
32
32
|
"main": "dist/index.js",
|
|
33
33
|
"scripts": {
|
|
@@ -44,5 +44,5 @@
|
|
|
44
44
|
"access": "public",
|
|
45
45
|
"registry": "https://registry.npmjs.org/"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "453c1e45d742e4f815eb34e4fa542ae691d23ba5"
|
|
48
48
|
}
|
package/src/IcicleGraph.tsx
CHANGED
|
@@ -26,12 +26,17 @@ import {
|
|
|
26
26
|
} from '@parca/client/dist/parca/metastore/v1alpha1/metastore';
|
|
27
27
|
import type {HoveringNode} from './GraphTooltip';
|
|
28
28
|
import GraphTooltip from './GraphTooltip';
|
|
29
|
-
import {
|
|
29
|
+
import {
|
|
30
|
+
diffColor,
|
|
31
|
+
getLastItem,
|
|
32
|
+
isSearchMatch,
|
|
33
|
+
selectQueryParam,
|
|
34
|
+
useURLState,
|
|
35
|
+
} from '@parca/functions';
|
|
30
36
|
import {selectDarkMode, useAppSelector} from '@parca/store';
|
|
31
37
|
import useIsShiftDown from '@parca/components/src/hooks/useIsShiftDown';
|
|
32
38
|
import {Button} from '@parca/components';
|
|
33
39
|
import {hexifyAddress} from './utils';
|
|
34
|
-
import {useURLState} from '@parca/functions';
|
|
35
40
|
|
|
36
41
|
interface IcicleGraphProps {
|
|
37
42
|
graph: Flamegraph;
|
|
@@ -30,6 +30,7 @@ interface ProfileIcicleGraphProps {
|
|
|
30
30
|
curPath: string[] | [];
|
|
31
31
|
setNewCurPath: (path: string[]) => void;
|
|
32
32
|
onContainerResize?: ResizeHandler;
|
|
33
|
+
loading: boolean;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
const ProfileIcicleGraph = ({
|
|
@@ -38,6 +39,7 @@ const ProfileIcicleGraph = ({
|
|
|
38
39
|
setNewCurPath,
|
|
39
40
|
sampleUnit,
|
|
40
41
|
onContainerResize,
|
|
42
|
+
loading,
|
|
41
43
|
}: ProfileIcicleGraphProps): JSX.Element => {
|
|
42
44
|
const compareMode: boolean =
|
|
43
45
|
selectQueryParam('compare_a') === 'true' && selectQueryParam('compare_b') === 'true';
|
|
@@ -71,8 +73,10 @@ const ProfileIcicleGraph = ({
|
|
|
71
73
|
}, [graph]);
|
|
72
74
|
|
|
73
75
|
if (graph === undefined) return <div>no data...</div>;
|
|
76
|
+
|
|
74
77
|
const total = graph.total;
|
|
75
|
-
|
|
78
|
+
|
|
79
|
+
if (parseFloat(total) === 0 && !loading) return <>Profile has no samples</>;
|
|
76
80
|
|
|
77
81
|
return (
|
|
78
82
|
<>
|
|
@@ -157,6 +157,7 @@ export const ProfileView = ({
|
|
|
157
157
|
graph={flamegraphData.data}
|
|
158
158
|
sampleUnit={sampleUnit}
|
|
159
159
|
onContainerResize={onFlamegraphContainerResize}
|
|
160
|
+
loading={flamegraphData.loading}
|
|
160
161
|
/>
|
|
161
162
|
</Profiler>
|
|
162
163
|
) : (
|
|
@@ -177,7 +178,12 @@ export const ProfileView = ({
|
|
|
177
178
|
}
|
|
178
179
|
case 'table': {
|
|
179
180
|
return topTableData != null ? (
|
|
180
|
-
<TopTable
|
|
181
|
+
<TopTable
|
|
182
|
+
loading={topTableData.loading}
|
|
183
|
+
data={topTableData.data}
|
|
184
|
+
sampleUnit={sampleUnit}
|
|
185
|
+
navigateTo={navigateTo}
|
|
186
|
+
/>
|
|
181
187
|
) : (
|
|
182
188
|
<></>
|
|
183
189
|
);
|
|
@@ -220,7 +226,6 @@ export const ProfileView = ({
|
|
|
220
226
|
<ProfileShareButton
|
|
221
227
|
queryRequest={profileSource.QueryRequest()}
|
|
222
228
|
queryClient={queryClient}
|
|
223
|
-
disabled={isLoading}
|
|
224
229
|
/>
|
|
225
230
|
) : null}
|
|
226
231
|
|
|
@@ -230,7 +235,6 @@ export const ProfileView = ({
|
|
|
230
235
|
e.preventDefault();
|
|
231
236
|
onDownloadPProf();
|
|
232
237
|
}}
|
|
233
|
-
disabled={isLoading}
|
|
234
238
|
>
|
|
235
239
|
Download pprof
|
|
236
240
|
</Button>
|
package/src/TopTable/index.tsx
CHANGED
|
@@ -31,6 +31,7 @@ import {hexifyAddress} from '../utils';
|
|
|
31
31
|
import '../TopTable.styles.css';
|
|
32
32
|
|
|
33
33
|
interface TopTableProps {
|
|
34
|
+
loading: boolean;
|
|
34
35
|
data?: Top;
|
|
35
36
|
sampleUnit: string;
|
|
36
37
|
navigateTo?: NavigateFunction;
|
|
@@ -62,7 +63,12 @@ const addPlusSign = (num: string): string => {
|
|
|
62
63
|
return `+${num}`;
|
|
63
64
|
};
|
|
64
65
|
|
|
65
|
-
export const TopTable = ({
|
|
66
|
+
export const TopTable = ({
|
|
67
|
+
data: top,
|
|
68
|
+
sampleUnit: unit,
|
|
69
|
+
navigateTo,
|
|
70
|
+
loading,
|
|
71
|
+
}: TopTableProps): JSX.Element => {
|
|
66
72
|
const router = parseParams(window.location.search);
|
|
67
73
|
const currentSearchString = selectQueryParam('search_string') as string;
|
|
68
74
|
const compareMode =
|
|
@@ -166,7 +172,7 @@ export const TopTable = ({data: top, sampleUnit: unit, navigateTo}: TopTableProp
|
|
|
166
172
|
|
|
167
173
|
const total = top != null ? top.list.length : 0;
|
|
168
174
|
|
|
169
|
-
if (total === 0) return <>Profile has no samples</>;
|
|
175
|
+
if (total === 0 && !loading) return <>Profile has no samples</>;
|
|
170
176
|
|
|
171
177
|
return (
|
|
172
178
|
<>
|