@parca/profile 0.16.412 → 0.16.413

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.
Files changed (33) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/ProfileExplorer/ProfileExplorerCompare.d.ts.map +1 -1
  3. package/dist/ProfileExplorer/ProfileExplorerCompare.js +1 -1
  4. package/dist/ProfileExplorer/ProfileExplorerSingle.d.ts.map +1 -1
  5. package/dist/ProfileExplorer/ProfileExplorerSingle.js +1 -1
  6. package/dist/ProfileExplorer/index.d.ts.map +1 -1
  7. package/dist/ProfileExplorer/index.js +3 -1
  8. package/dist/ProfileMetricsGraph/index.d.ts +4 -2
  9. package/dist/ProfileMetricsGraph/index.d.ts.map +1 -1
  10. package/dist/ProfileMetricsGraph/index.js +9 -23
  11. package/dist/ProfileSelector/index.d.ts +3 -1
  12. package/dist/ProfileSelector/index.d.ts.map +1 -1
  13. package/dist/ProfileSelector/index.js +31 -6
  14. package/dist/ProfileSelector/useAutoQuerySelector.d.ts.map +1 -1
  15. package/dist/ProfileSelector/useAutoQuerySelector.js +6 -0
  16. package/dist/styles.css +1 -1
  17. package/dist/useSumBy.d.ts +8 -0
  18. package/dist/useSumBy.d.ts.map +1 -0
  19. package/dist/{ProfileMetricsGraph/useSumBy.js → useSumBy.js} +8 -3
  20. package/package.json +2 -2
  21. package/src/ProfileExplorer/ProfileExplorerCompare.tsx +2 -0
  22. package/src/ProfileExplorer/ProfileExplorerSingle.tsx +1 -0
  23. package/src/ProfileExplorer/index.tsx +4 -0
  24. package/src/ProfileMetricsGraph/index.tsx +8 -41
  25. package/src/ProfileSelector/index.tsx +66 -3
  26. package/src/ProfileSelector/useAutoQuerySelector.ts +9 -1
  27. package/src/{ProfileMetricsGraph/useSumBy.ts → useSumBy.ts} +20 -4
  28. package/dist/ProfileMetricsGraph/Toolbar/index.d.ts +0 -9
  29. package/dist/ProfileMetricsGraph/Toolbar/index.d.ts.map +0 -1
  30. package/dist/ProfileMetricsGraph/Toolbar/index.js +0 -29
  31. package/dist/ProfileMetricsGraph/useSumBy.d.ts +0 -4
  32. package/dist/ProfileMetricsGraph/useSumBy.d.ts.map +0 -1
  33. package/src/ProfileMetricsGraph/Toolbar/index.tsx +0 -94
package/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
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.413](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.412...@parca/profile@0.16.413) (2024-07-22)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
6
10
  ## [0.16.412](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.411...@parca/profile@0.16.412) (2024-07-16)
7
11
 
8
12
  **Note:** Version bump only for package @parca/profile
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAoB,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AAC5E,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAEhC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,+IAYzB,2BAA2B,KAAG,GAAG,CAAC,OAsEpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
1
+ {"version":3,"file":"ProfileExplorerCompare.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerCompare.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAoB,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AAC5E,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,2BAA2B;IACnC,WAAW,EAAE,kBAAkB,CAAC;IAEhC,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAClC,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,YAAY,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACnD,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAErC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,sBAAsB,+IAYzB,2BAA2B,KAAG,GAAG,CAAC,OAwEpC,CAAC;AAEF,eAAe,sBAAsB,CAAC"}
@@ -12,6 +12,6 @@ const ProfileExplorerCompare = ({ queryClient, queryA, queryB, profileA, profile
12
12
  };
13
13
  const [compareAbsolute] = useURLState({ param: 'compare_absolute', navigateTo });
14
14
  const [functionFilter] = useURLState({ param: 'filter_by_function', navigateTo });
15
- return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex justify-between gap-2", children: [_jsx(Card, { className: "mt-2 p-2", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryA, profileSelection: profileA, selectProfile: selectProfileA, selectQuery: selectQueryA, closeProfile: closeProfileA, enforcedProfileName: '', comparing: true, navigateTo: navigateTo }) }), _jsx(Card, { className: "mt-2 p-2", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryB, profileSelection: profileB, selectProfile: selectProfileB, selectQuery: selectQueryB, closeProfile: closeProfileB, enforcedProfileName: Query.parse(queryA.expression).profileName(), comparing: true, navigateTo: navigateTo }) })] }), _jsx("div", { className: "grid grid-cols-1", children: profileA != null && profileB != null ? (_jsx("div", { children: _jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileViewWithData, { navigateTo: navigateTo, queryClient: queryClient, profileSource: new ProfileDiffSource(profileA.ProfileSource(), profileB.ProfileSource(), Array.isArray(functionFilter) ? functionFilter[0] : functionFilter, compareAbsolute === 'true') }) }) })) : (_jsx("div", { children: _jsx("div", { className: "my-20 text-center", children: _jsx("p", { children: "Select a profile on both sides." }) }) })) })] }));
15
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex justify-between gap-2", children: [_jsx(Card, { className: "mt-2 p-2", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryA, profileSelection: profileA, selectProfile: selectProfileA, selectQuery: selectQueryA, closeProfile: closeProfileA, enforcedProfileName: '', comparing: true, navigateTo: navigateTo, suffix: "_a" }) }), _jsx(Card, { className: "mt-2 p-2", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: queryB, profileSelection: profileB, selectProfile: selectProfileB, selectQuery: selectQueryB, closeProfile: closeProfileB, enforcedProfileName: Query.parse(queryA.expression).profileName(), comparing: true, navigateTo: navigateTo, suffix: "_b" }) })] }), _jsx("div", { className: "grid grid-cols-1", children: profileA != null && profileB != null ? (_jsx("div", { children: _jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileViewWithData, { navigateTo: navigateTo, queryClient: queryClient, profileSource: new ProfileDiffSource(profileA.ProfileSource(), profileB.ProfileSource(), Array.isArray(functionFilter) ? functionFilter[0] : functionFilter, compareAbsolute === 'true') }) }) })) : (_jsx("div", { children: _jsx("div", { className: "my-20 text-center", children: _jsx("p", { children: "Select a profile on both sides." }) }) })) })] }));
16
16
  };
17
17
  export default ProfileExplorerCompare;
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileExplorerSingle.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerSingle.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAC,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AACzD,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,0BAA0B;IAClC,WAAW,EAAE,kBAAkB,CAAC;IAChC,KAAK,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,qBAAqB,6EAOxB,0BAA0B,KAAG,GAAG,CAAC,OA6BnC,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
1
+ {"version":3,"file":"ProfileExplorerSingle.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/ProfileExplorerSingle.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAC,gBAAgB,EAAsB,MAAM,IAAI,CAAC;AACzD,OAAwB,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAEnE,UAAU,0BAA0B;IAClC,WAAW,EAAE,kBAAkB,CAAC;IAChC,KAAK,EAAE,cAAc,CAAC;IACtB,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,QAAA,MAAM,qBAAqB,6EAOxB,0BAA0B,KAAG,GAAG,CAAC,OA8BnC,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -3,6 +3,6 @@ import { Card } from '@parca/components';
3
3
  import { ProfileViewWithData } from '..';
4
4
  import ProfileSelector from '../ProfileSelector';
5
5
  const ProfileExplorerSingle = ({ queryClient, query, selectQuery, selectProfile, profile, navigateTo, }) => {
6
- return (_jsxs(_Fragment, { children: [_jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: query, selectQuery: selectQuery, selectProfile: selectProfile, closeProfile: () => { }, profileSelection: profile, comparing: false, enforcedProfileName: '', navigateTo: navigateTo }) }), profile != null ? (_jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileViewWithData, { queryClient: queryClient, profileSource: profile.ProfileSource(), navigateTo: navigateTo }) })) : (_jsx(_Fragment, {}))] }));
6
+ return (_jsxs(_Fragment, { children: [_jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileSelector, { queryClient: queryClient, querySelection: query, selectQuery: selectQuery, selectProfile: selectProfile, closeProfile: () => { }, profileSelection: profile, comparing: false, enforcedProfileName: '', navigateTo: navigateTo, suffix: "_a" }) }), profile != null ? (_jsx(Card, { className: "mt-2 px-6 py-4", children: _jsx(ProfileViewWithData, { queryClient: queryClient, profileSource: profile.ProfileSource(), navigateTo: navigateTo }) })) : (_jsx(_Fragment, {}))] }));
7
7
  };
8
8
  export default ProfileExplorerSingle;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,EAA4B,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAOlF,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,WAAW,EAAE,GAAG,CAAC;IACjB,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAaD,eAAO,MAAM,sBAAsB,eAAgB,MAAM,GAAG,EAAE,KAAG,MAGhE,CAAC;AA4UF,QAAA,MAAM,eAAe,8CAIlB,oBAAoB,KAAG,GAAG,CAAC,OAkB7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileExplorer/index.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAGjD,OAAO,EAA4B,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAOlF,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,WAAW,EAAE,GAAG,CAAC;IACjB,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAaD,eAAO,MAAM,sBAAsB,eAAgB,MAAM,GAAG,EAAE,KAAG,MAGhE,CAAC;AAgVF,QAAA,MAAM,eAAe,8CAIlB,oBAAoB,KAAG,GAAG,CAAC,OAkB7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -66,7 +66,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
66
66
  }
67
67
  }, [profileTypesError, onError]);
68
68
  /* eslint-disable @typescript-eslint/naming-convention */
69
- let { from_a, to_a, merge_from_a, merge_to_a, time_selection_a, compare_a, from_b, to_b, merge_from_b, merge_to_b, time_selection_b, compare_b, filter_by_function, dashboard_items, } = queryParams;
69
+ let { from_a, to_a, merge_from_a, merge_to_a, time_selection_a, compare_a, sum_by_a, from_b, to_b, merge_from_b, merge_to_b, time_selection_b, compare_b, sum_by_b, filter_by_function, dashboard_items, } = queryParams;
70
70
  // eslint-disable-next-line @typescript-eslint/naming-convention
71
71
  const expression_a = getExpressionAsAString(queryParams.expression_a);
72
72
  // eslint-disable-next-line @typescript-eslint/naming-convention
@@ -134,6 +134,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
134
134
  from: parseInt(from_a),
135
135
  to: parseInt(to_a),
136
136
  timeSelection: time_selection_a,
137
+ sumBy: sum_by_a,
137
138
  };
138
139
  // Show the SingleProfileExplorer when not comparing
139
140
  if (compare_a !== 'true' && compare_b !== 'true') {
@@ -175,6 +176,7 @@ const ProfileExplorerApp = ({ queryClient, queryParams, navigateTo, }) => {
175
176
  from: parseInt(from_b),
176
177
  to: parseInt(to_b),
177
178
  timeSelection: time_selection_b,
179
+ sumBy: sum_by_b,
178
180
  };
179
181
  const selectQueryA = (q) => {
180
182
  const mergeParams = q.mergeFrom !== undefined && q.mergeTo !== undefined
@@ -13,6 +13,8 @@ interface ProfileMetricsGraphProps {
13
13
  profile: ProfileSelection | null;
14
14
  from: number;
15
15
  to: number;
16
+ sumByLoading: boolean;
17
+ sumBy: string[];
16
18
  setTimeRange: (range: DateTimeRange) => void;
17
19
  addLabelMatcher: (labels: {
18
20
  key: string;
@@ -29,7 +31,7 @@ export interface IQueryRangeState {
29
31
  isLoading: boolean;
30
32
  error: RpcError | null;
31
33
  }
32
- export declare const useQueryRange: (client: QueryServiceClient, queryExpression: string, start: number, end: number, sumBy?: string[], skip?: boolean) => IQueryRangeState;
33
- declare const ProfileMetricsGraph: ({ queryClient, queryExpression, dirtyQueryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing, }: ProfileMetricsGraphProps) => JSX.Element;
34
+ export declare const useQueryRange: (client: QueryServiceClient, queryExpression: string, start: number, end: number, sumBy: string[], skip?: boolean) => IQueryRangeState;
35
+ declare const ProfileMetricsGraph: ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing, sumBy, sumByLoading, }: ProfileMetricsGraphProps) => JSX.Element;
34
36
  export default ProfileMetricsGraph;
35
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileMetricsGraph/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAW,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAY,MAAM,eAAe,CAAC;AACjG,OAAO,EACL,aAAa,EAKd,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAQ5D,UAAU,6BAA6B;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,eAAO,MAAM,wBAAwB,gBAAe,6BAA6B,KAAG,GAAG,CAAC,OAMvF,CAAC;AAEF,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,eAAe,EAAE,CACf,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,YAAY,EAAE,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,KAAK,EAAE,EACf,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,KACb,IAAI,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;CACxB;AAYD,eAAO,MAAM,aAAa,WAChB,kBAAkB,mBACT,MAAM,SAChB,MAAM,OACR,MAAM,UACJ,MAAM,EAAE,qBAEd,gBA+CF,CAAC;AAEF,QAAA,MAAM,mBAAmB,uIAWtB,wBAAwB,KAAG,GAAG,CAAC,OAsHjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileMetricsGraph/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAW,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAY,MAAM,eAAe,CAAC;AACjG,OAAO,EACL,aAAa,EAKd,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAK5D,UAAU,6BAA6B;IACrC,OAAO,EAAE,MAAM,CAAC;CACjB;AAaD,eAAO,MAAM,wBAAwB,gBAAe,6BAA6B,KAAG,GAAG,CAAC,OAMvF,CAAC;AAEF,UAAU,wBAAwB;IAChC,WAAW,EAAE,kBAAkB,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,eAAe,EAAE,CACf,MAAM,EAAE;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,KACvE,IAAI,CAAC;IACV,YAAY,EAAE,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,KAAK,EAAE,EACf,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,KACb,IAAI,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACpC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;CACxB;AAYD,eAAO,MAAM,aAAa,WAChB,kBAAkB,mBACT,MAAM,SAChB,MAAM,OACR,MAAM,SACJ,MAAM,EAAE,qBAEd,gBA+CF,CAAC;AAEF,QAAA,MAAM,mBAAmB,sIAYtB,wBAAwB,KAAG,GAAG,CAAC,OAqFjC,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx } 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,12 +17,9 @@ import { Duration, Timestamp } from '@parca/client';
17
17
  import { MetricsGraphSkeleton, useGrpcMetadata, useParcaContext, useURLState, } from '@parca/components';
18
18
  import { Query } from '@parca/parser';
19
19
  import { capitalizeOnlyFirstLetter, getStepDuration } from '@parca/utilities';
20
- import { useLabelNames } from '../MatchersInput';
21
20
  import MetricsGraph from '../MetricsGraph';
22
21
  import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
23
22
  import useGrpcQuery from '../useGrpcQuery';
24
- import { Toolbar } from './Toolbar';
25
- import { DEFAULT_EMPTY_SUM_BY, useSumBy } from './useSumBy';
26
23
  const ErrorContent = ({ errorMessage }) => {
27
24
  return (_jsx("div", { className: "relative rounded border border-red-400 bg-red-100 px-4 py-3 text-red-700", role: "alert", children: _jsx("span", { className: "block sm:inline", children: errorMessage }) }));
28
25
  };
@@ -37,7 +34,7 @@ const getStepCountFromScreenWidth = (pixelsPerPoint) => {
37
34
  width = width - (20 + 24 + 68) * 2;
38
35
  return Math.round(width / pixelsPerPoint);
39
36
  };
40
- export const useQueryRange = (client, queryExpression, start, end, sumBy = DEFAULT_EMPTY_SUM_BY, skip = false) => {
37
+ export const useQueryRange = (client, queryExpression, start, end, sumBy, skip = false) => {
41
38
  const metadata = useGrpcMetadata();
42
39
  const { navigateTo } = useParcaContext();
43
40
  const [stepCountStr, setStepCount] = useURLState({ param: 'step_count', navigateTo });
@@ -71,22 +68,14 @@ export const useQueryRange = (client, queryExpression, start, end, sumBy = DEFAU
71
68
  },
72
69
  options: {
73
70
  retry: false,
74
- enabled: !skip && sumBy !== DEFAULT_EMPTY_SUM_BY,
71
+ enabled: !skip,
75
72
  staleTime: 1000 * 60 * 5, // 5 minutes
76
73
  },
77
74
  });
78
75
  return { isLoading, error: error, response: data ?? null };
79
76
  };
80
- const ProfileMetricsGraph = ({ queryClient, queryExpression, dirtyQueryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing = false, }) => {
81
- const profileType = useMemo(() => {
82
- return Query.parse(queryExpression).profileType();
83
- }, [queryExpression]);
84
- const dirtyProfileType = useMemo(() => {
85
- return Query.parse(dirtyQueryExpression).profileType();
86
- }, [dirtyQueryExpression]);
87
- const { loading: labelNamesLoading, result: labelNamesResult } = useLabelNames(queryClient, profileType.toString() ?? '', from, to);
88
- const [sumBy, setSumBy] = useSumBy(profileType, labelNamesLoading, labelNamesResult.response?.labelNames);
89
- const { isLoading: metricsGraphLoading, response, error, } = useQueryRange(queryClient, queryExpression, from, to, sumBy, labelNamesLoading);
77
+ const ProfileMetricsGraph = ({ queryClient, queryExpression, profile, from, to, setTimeRange, addLabelMatcher, onPointClick, comparing = false, sumBy, sumByLoading, }) => {
78
+ const { isLoading: metricsGraphLoading, response, error, } = useQueryRange(queryClient, queryExpression, from, to, sumBy, sumByLoading);
90
79
  const { onError, perf, authenticationErrorMessage, isDarkMode } = useParcaContext();
91
80
  const { width, height, margin, heightStyle } = useMetricsGraphDimensions(comparing);
92
81
  useEffect(() => {
@@ -102,10 +91,7 @@ const ProfileMetricsGraph = ({ queryClient, queryExpression, dirtyQueryExpressio
102
91
  }, [perf, response]);
103
92
  const series = response?.series;
104
93
  const dataAvailable = series !== null && series !== undefined && series?.length > 0;
105
- const loading = metricsGraphLoading || labelNamesLoading;
106
- if (!labelNamesLoading && labelNamesResult?.error?.message != null) {
107
- return (_jsx(ErrorContent, { errorMessage: capitalizeOnlyFirstLetter(labelNamesResult.error.message) }));
108
- }
94
+ const loading = metricsGraphLoading;
109
95
  if (!metricsGraphLoading && error !== null) {
110
96
  if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
111
97
  return _jsx(ErrorContent, { errorMessage: authenticationErrorMessage });
@@ -121,8 +107,8 @@ const ProfileMetricsGraph = ({ queryClient, queryExpression, dirtyQueryExpressio
121
107
  sampleUnit = Query.parse(queryExpression).profileType().sampleUnit;
122
108
  }
123
109
  }
124
- return (_jsx(AnimatePresence, { children: _jsxs(motion.div, { className: "h-full w-full relative", initial: { display: 'none', opacity: 0 }, animate: { display: 'block', opacity: 1 }, transition: { duration: 0.5 }, children: [dirtyProfileType.delta ? (_jsx(Toolbar, { sumBy: sumBy, setSumBy: setSumBy, labels: labelNamesResult.response?.labelNames ?? [] })) : null, loading ? (_jsx(MetricsGraphSkeleton, { heightStyle: heightStyle, isDarkMode: isDarkMode })) : dataAvailable ? (_jsx(MetricsGraph, { data: series, from: from, to: to, profile: profile, setTimeRange: setTimeRange, onSampleClick: (timestamp, _value, labels, duration) => {
125
- onPointClick(timestamp, labels, queryExpression, duration);
126
- }, addLabelMatcher: addLabelMatcher, sampleUnit: sampleUnit, height: height, width: width, margin: margin })) : (_jsx(ProfileMetricsEmptyState, { message: "No data found. Try a different query." }))] }, "metrics-graph-loaded") }));
110
+ return (_jsx(AnimatePresence, { children: _jsx(motion.div, { className: "h-full w-full relative", initial: { display: 'none', opacity: 0 }, animate: { display: 'block', opacity: 1 }, transition: { duration: 0.5 }, children: loading ? (_jsx(MetricsGraphSkeleton, { heightStyle: heightStyle, isDarkMode: isDarkMode })) : dataAvailable ? (_jsx(MetricsGraph, { data: series, from: from, to: to, profile: profile, setTimeRange: setTimeRange, onSampleClick: (timestamp, _value, labels, duration) => {
111
+ onPointClick(timestamp, labels, queryExpression, duration);
112
+ }, addLabelMatcher: addLabelMatcher, sampleUnit: sampleUnit, height: height, width: width, margin: margin })) : (_jsx(ProfileMetricsEmptyState, { message: "No data found. Try a different query." })) }, "metrics-graph-loaded") }));
127
113
  };
128
114
  export default ProfileMetricsGraph;
@@ -7,6 +7,7 @@ export interface QuerySelection {
7
7
  from: number;
8
8
  to: number;
9
9
  timeSelection: string;
10
+ sumBy?: string[];
10
11
  mergeFrom?: number;
11
12
  mergeTo?: number;
12
13
  }
@@ -20,6 +21,7 @@ interface ProfileSelectorProps {
20
21
  profileSelection: ProfileSelection | null;
21
22
  comparing: boolean;
22
23
  navigateTo: NavigateFunction;
24
+ suffix?: string;
23
25
  }
24
26
  export interface IProfileTypesResult {
25
27
  loading: boolean;
@@ -27,6 +29,6 @@ export interface IProfileTypesResult {
27
29
  error?: RpcError;
28
30
  }
29
31
  export declare const useProfileTypes: (client: QueryServiceClient) => IProfileTypesResult;
30
- declare const ProfileSelector: ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, navigateTo, }: ProfileSelectorProps) => JSX.Element;
32
+ declare const ProfileSelector: ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, navigateTo, suffix, }: ProfileSelectorProps) => JSX.Element;
31
33
  export default ProfileSelector;
32
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAElD,OAAO,EAAQ,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY9E,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAO5D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,WAAY,kBAAkB,KAAG,mBAkB5D,CAAC;AAEF,QAAA,MAAM,eAAe,6IAUlB,oBAAoB,KAAG,GAAG,CAAC,OA4P7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAC,QAAQ,EAAC,MAAM,0BAA0B,CAAC;AAGlD,OAAO,EAAQ,oBAAoB,EAAE,kBAAkB,EAAC,MAAM,eAAe,CAAC;AAY9E,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAyB,gBAAgB,EAAC,MAAM,IAAI,CAAC;AAQ5D,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,oBAAoB;IAC5B,WAAW,EAAE,kBAAkB,CAAC;IAChC,cAAc,EAAE,cAAc,CAAC;IAC/B,aAAa,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClD,WAAW,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;CAClB;AAED,eAAO,MAAM,eAAe,WAAY,kBAAkB,KAAG,mBAkB5D,CAAC;AAEF,QAAA,MAAM,eAAe,qJAWlB,oBAAoB,KAAG,GAAG,CAAC,OAsT7B,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -11,15 +11,17 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
11
11
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  // See the License for the specific language governing permissions and
13
13
  // limitations under the License.
14
- import { useEffect, useState } from 'react';
14
+ import { useEffect, useMemo, useState } from 'react';
15
+ import Select from 'react-select';
15
16
  import { Button, ButtonGroup, DateTimeRange, DateTimeRangePicker, IconButton, useGrpcMetadata, useParcaContext, } from '@parca/components';
16
17
  import { CloseIcon } from '@parca/icons';
17
18
  import { Query } from '@parca/parser';
18
19
  import { MergedProfileSelection } from '..';
19
- import MatchersInput from '../MatchersInput/index';
20
+ import MatchersInput, { useLabelNames } from '../MatchersInput/index';
20
21
  import { useMetricsGraphDimensions } from '../MetricsGraph/useMetricsGraphDimensions';
21
22
  import ProfileMetricsGraph, { ProfileMetricsEmptyState } from '../ProfileMetricsGraph';
22
23
  import ProfileTypeSelector from '../ProfileTypeSelector/index';
24
+ import { useSumBy } from '../useSumBy';
23
25
  import { useAutoQuerySelector } from './useAutoQuerySelector';
24
26
  export const useProfileTypes = (client) => {
25
27
  const [result, setResult] = useState(undefined);
@@ -38,12 +40,28 @@ export const useProfileTypes = (client) => {
38
40
  }, [client, metadata, loading]);
39
41
  return { loading, data: result, error };
40
42
  };
41
- const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, navigateTo, }) => {
43
+ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQuery, closeProfile, enforcedProfileName, profileSelection, comparing, navigateTo, suffix = '', }) => {
42
44
  const { loading: profileTypesLoading, data: profileTypesData, error, } = useProfileTypes(queryClient);
43
45
  const { heightStyle } = useMetricsGraphDimensions(comparing);
44
46
  const { viewComponent } = useParcaContext();
45
47
  const [timeRangeSelection, setTimeRangeSelection] = useState(DateTimeRange.fromRangeKey(querySelection.timeSelection, querySelection.from, querySelection.to));
46
48
  const [queryExpressionString, setQueryExpressionString] = useState(querySelection.expression);
49
+ const profileType = useMemo(() => {
50
+ return Query.parse(queryExpressionString).profileType();
51
+ }, [queryExpressionString]);
52
+ const { loading: labelNamesLoading, result } = useLabelNames(queryClient, profileType.toString());
53
+ const labels = useMemo(() => {
54
+ return result.response?.labelNames === undefined ? [] : result.response.labelNames;
55
+ }, [result]);
56
+ const [sumBy, setSumBy, userSelectedSumBy] = useSumBy(profileType, labelNamesLoading, result.response?.labelNames, {
57
+ urlParamKey: 'sum_by' + suffix,
58
+ });
59
+ const [sumBySelection, setSumBySelection] = useSumBy(profileType, labelNamesLoading, result.response?.labelNames, {
60
+ urlParamKey: 'sum_by_selection' + suffix,
61
+ withURLUpdate: false,
62
+ defaultValue: userSelectedSumBy,
63
+ });
64
+ const sumByLoading = labelNamesLoading;
47
65
  useEffect(() => {
48
66
  if (enforcedProfileName !== '') {
49
67
  const [q, changed] = Query.parse(querySelection.expression).setProfileName(enforcedProfileName);
@@ -62,6 +80,9 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
62
80
  const query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(queryExpressionString);
63
81
  const selectedProfileName = query.profileName();
64
82
  const setNewQueryExpression = (expr, updateTs = false) => {
83
+ if (!sumByLoading) {
84
+ setSumBy(sumBySelection);
85
+ }
65
86
  const query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(expr);
66
87
  const delta = query.profileType().delta;
67
88
  const from = timeRangeSelection.getFromMs(updateTs);
@@ -136,20 +157,24 @@ const ProfileSelector = ({ queryClient, querySelection, selectProfile, selectQue
136
157
  profileTypesData,
137
158
  setProfileName,
138
159
  setQueryExpression,
139
- querySelection,
160
+ querySelection: { ...querySelection, sumBy },
140
161
  navigateTo,
141
162
  });
142
163
  const searchDisabled = queryExpressionString === undefined ||
143
164
  queryExpressionString === '' ||
144
165
  queryExpressionString === '{}';
145
166
  return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "mb-2 flex gap-2", children: [_jsxs("div", { className: "flex w-full flex-wrap content-start items-center gap-2", children: [_jsxs("div", { className: "pb-6", children: [_jsx("label", { className: "text-xs", children: "Profile type" }), _jsx(ProfileTypeSelector, { profileTypesData: profileTypesData, loading: profileTypesLoading, selectedKey: selectedProfileName, onSelection: setProfileName, error: error, disabled: viewComponent?.disableProfileTypesDropdown })] }), _jsxs("div", { className: "w-full flex-1 pb-6", children: [_jsxs("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: [_jsx("label", { className: "text-xs", children: "Query" }), (query.matchers.length > 0 || query.inputMatcherString.length > 0) &&
146
- viewComponent !== undefined && _jsx("div", { children: viewComponent?.createViewComponent })] }), _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName })] }), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsx(ButtonGroup, { children: _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
167
+ viewComponent !== undefined && _jsx("div", { children: viewComponent?.createViewComponent })] }), _jsx(MatchersInput, { queryClient: queryClient, setMatchersString: setMatchersString, runQuery: setQueryExpression, currentQuery: query, profileType: selectedProfileName })] }), _jsxs("div", { className: "pb-6", children: [_jsx("div", { className: "mb-0.5 mt-1.5 flex items-center justify-between", children: _jsx("label", { className: "text-xs", children: "Sum by" }) }), _jsx(Select, { defaultValue: [], isMulti: true, name: "colors", options: labels.map(label => ({ label, value: label })), className: "parca-select-container text-sm w-80", classNamePrefix: "parca-select", value: sumBySelection.map(sumBy => ({ label: sumBy, value: sumBy })), onChange: selectedOptions => {
168
+ setSumBySelection(selectedOptions.map(option => option.value));
169
+ }, placeholder: "Labels...", styles: {
170
+ indicatorSeparator: () => ({ display: 'none' }),
171
+ } })] }), _jsx(DateTimeRangePicker, { onRangeSelection: setTimeRangeSelection, range: timeRangeSelection }), _jsx(ButtonGroup, { children: _jsx(Button, { disabled: searchDisabled, onClick: (e) => {
147
172
  e.preventDefault();
148
173
  setQueryExpression(true);
149
174
  }, id: "h-matcher-search-button", children: "Search" }) })] }), _jsx("div", { children: comparing && _jsx(IconButton, { onClick: () => closeProfile(), icon: _jsx(CloseIcon, {}) }) })] }), _jsx("div", { className: "rounded bg-white shadow dark:border-gray-500 dark:bg-gray-700", children: _jsx("div", { style: { height: heightStyle }, children: querySelection.expression !== undefined &&
150
175
  querySelection.expression.length > 0 &&
151
176
  querySelection.from !== undefined &&
152
- querySelection.to !== undefined ? (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, dirtyQueryExpression: queryExpressionString, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, setTimeRange: (range) => {
177
+ querySelection.to !== undefined ? (_jsx("div", { className: "p-2", children: _jsx(ProfileMetricsGraph, { queryClient: queryClient, queryExpression: querySelection.expression, dirtyQueryExpression: queryExpressionString, from: querySelection.from, to: querySelection.to, profile: profileSelection, comparing: comparing, sumBy: sumBy, sumByLoading: sumByLoading, setTimeRange: (range) => {
153
178
  const from = range.getFromMs();
154
179
  const to = range.getToMs();
155
180
  let mergedProfileParams = {};
@@ -1 +1 @@
1
- {"version":3,"file":"useAutoQuerySelector.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/useAutoQuerySelector.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAGlD,UAAU,KAAK;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACnD,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,eAAO,MAAM,oBAAoB,+GAO9B,KAAK,KAAG,IA0HV,CAAC"}
1
+ {"version":3,"file":"useAutoQuerySelector.d.ts","sourceRoot":"","sources":["../../src/ProfileSelector/useAutoQuerySelector.ts"],"names":[],"mappings":"AAeA,OAAO,EAAC,oBAAoB,EAAC,MAAM,eAAe,CAAC;AAEnD,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAC,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAGlD,UAAU,KAAK;IACb,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACnD,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,UAAU,EAAE,gBAAgB,CAAC;CAC9B;AAED,eAAO,MAAM,oBAAoB,+GAO9B,KAAK,KAAG,IAkIV,CAAC"}
@@ -31,7 +31,9 @@ export const useAutoQuerySelector = ({ selectedProfileName, profileTypesData, se
31
31
  from: querySelection.from,
32
32
  to: querySelection.to,
33
33
  timeSelection: querySelection.timeSelection,
34
+ sumBy: querySelection.sumBy,
34
35
  };
36
+ const sumBy = queryA.sumBy?.join(',');
35
37
  let compareQuery = {
36
38
  compare_a: 'true',
37
39
  expression_a: encodeURIComponent(queryA.expression),
@@ -44,6 +46,10 @@ export const useAutoQuerySelector = ({ selectedProfileName, profileTypesData, se
44
46
  to_b: queryA.to.toString(),
45
47
  time_selection_b: queryA.timeSelection,
46
48
  };
49
+ if (sumBy != null) {
50
+ compareQuery.sum_by_a = sumBy;
51
+ compareQuery.sum_by_b = sumBy;
52
+ }
47
53
  if (profileA != null) {
48
54
  compareQuery = {
49
55
  ...SuffixParams(profileA.HistoryParams(), '_a'),
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.-inset-2{bottom:-.5rem;left:-.5rem;right:-.5rem;top:-.5rem}.inset-y-0{bottom:0;top:0}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-0{top:0}.top-\[-1px\]{top:-1px}.left-\[18px\]{left:18px}.bottom-0{bottom:0}.-top-3{top:-.75rem}.-right-3{right:-.75rem}.z-50{z-index:50}.z-10{z-index:10}.z-20{z-index:20}.m-auto{margin:auto}.m-2{margin:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.my-4{margin-bottom:1rem;margin-top:1rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.ml-2{margin-left:.5rem}.mb-2{margin-bottom:.5rem}.mb-0\.5{margin-bottom:.125rem}.mt-1\.5{margin-top:.375rem}.mb-0{margin-bottom:0}.mb-4{margin-bottom:1rem}.ml-3{margin-left:.75rem}.mr-6{margin-right:1.5rem}.mr-1{margin-right:.25rem}.mb-1{margin-bottom:.25rem}.mr-4{margin-right:1rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-fit{height:-moz-fit-content;height:fit-content}.h-10{height:2.5rem}.h-\[38px\]{height:38px}.h-auto{height:auto}.h-full{height:100%}.h-1{height:.25rem}.h-6{height:1.5rem}.h-4{height:1rem}.h-\[700px\]{height:700px}.h-\[80vh\]{height:80vh}.h-5{height:1.25rem}.h-14{height:3.5rem}.max-h-\[400px\]{max-height:400px}.max-h-\[300px\]{max-height:300px}.min-h-52{min-height:13rem}.min-h-\[38px\]{min-height:38px}.min-h-48{min-height:12rem}.min-h-\[78px\]{min-height:78px}.min-h-96{min-height:24rem}.min-h-\[700px\]{min-height:700px}.w-full{width:100%}.w-auto{width:auto}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-max{width:-moz-max-content;width:max-content}.w-40{width:10rem}.w-3{width:.75rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-9{width:2.25rem}.w-11{width:2.75rem}.w-\[52px\]{width:52px}.w-\[68px\]{width:68px}.w-\[76px\]{width:76px}.w-\[84px\]{width:84px}.w-\[92px\]{width:92px}.w-\[100px\]{width:100px}.w-\[108px\]{width:108px}.w-\[116px\]{width:116px}.w-4{width:1rem}.w-\[18px\]{width:18px}.w-8{width:2rem}.w-44{width:11rem}.w-\[460px\]{width:460px}.w-1\/5{width:20%}.w-11\/12{width:91.666667%}.w-1\/12{width:8.333333%}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.min-w-\[400px\]{min-width:400px}.min-w-60{min-width:15rem}.max-w-\[500px\]{max-width:500px}.max-w-\[300px\]{max-width:300px}.max-w-\[400px\]{max-width:400px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.flex-grow-0{flex-grow:0}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.origin-top-left{transform-origin:top left}.origin-bottom-left{transform-origin:bottom left}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.-rotate-90{--tw-rotate:-90deg}.-rotate-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-auto{cursor:auto}.cursor-grabbing{cursor:grabbing}.cursor-grab{cursor:grab}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-clip{overflow:clip}.overflow-scroll{overflow:scroll}.overflow-x-hidden{overflow-x:hidden}.text-ellipsis{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-full{border-radius:9999px}.rounded-none{border-radius:0}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-x{border-left-width:1px;border-right-width:1px}.border-y{border-bottom-width:1px;border-top-width:1px}.border-r{border-right-width:1px}.border-l{border-left-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.border-r-gray-200{--tw-border-opacity:1;border-right-color:rgb(229 231 235/var(--tw-border-opacity))}.border-l-amber-900{--tw-border-opacity:1;border-left-color:rgb(120 53 15/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-yellow-200{--tw-bg-opacity:1;background-color:rgb(254 240 138/var(--tw-bg-opacity))}.bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}.bg-indigo-100{--tw-bg-opacity:1;background-color:rgb(224 231 255/var(--tw-bg-opacity))}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}.bg-indigo-50{--tw-bg-opacity:1;background-color:rgb(238 242 255/var(--tw-bg-opacity))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.bg-opacity-90{--tw-bg-opacity:0.9}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.stroke-gray-300{stroke:#d1d5db}.stroke-white{stroke:#fff}.stroke-\[3\]{stroke-width:3}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1\.5{padding:.375rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-4{padding-bottom:1rem;padding-top:1rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.\!py-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.\!px-3{padding-left:.75rem!important;padding-right:.75rem!important}.px-3{padding-left:.75rem;padding-right:.75rem}.py-0{padding-bottom:0;padding-top:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-8{padding-left:2rem;padding-right:2rem}.pr-0{padding-right:0}.pt-2{padding-top:.5rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pb-4{padding-bottom:1rem}.pb-2{padding-bottom:.5rem}.pb-6{padding-bottom:1.5rem}.pb-\[10px\]{padding-bottom:10px}.pl-1{padding-left:.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pl-5{padding-left:1.25rem}.pr-\[1\.7rem\]{padding-right:1.7rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-\[10px\]{font-size:10px}.text-lg{font-size:1.125rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-6{line-height:1.5rem}.leading-5{line-height:1.25rem}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-90{opacity:.9}.opacity-50{opacity:.5}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 10px 2px rgba(0,0,0,.3);--tw-shadow-colored:0 0 10px 2px var(--tw-shadow-color)}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[stroke-dasharray\:6\2c 4\]{stroke-dasharray:6,4}.\[stroke-linecap\:round\]{stroke-linecap:round}.\[stroke-linejoin\:round\]{stroke-linejoin:round}.hover\:whitespace-normal:hover{white-space:normal}.hover\:bg-\[\#62626212\]:hover{background-color:#62626212}.hover\:bg-indigo-200:hover{--tw-bg-opacity:1;background-color:rgb(199 210 254/var(--tw-bg-opacity))}.hover\:bg-gray-200:hover{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.focus\:border-indigo-500:focus{--tw-border-opacity:1;border-color:rgb(99 102 241/var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-1:focus,.focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-indigo-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(99 102 241/var(--tw-ring-opacity))}.focus\:ring-indigo-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(79 70 229/var(--tw-ring-opacity))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.group:hover .group-hover\:flex{display:flex}[class~=theme-dark] .dark\:border{border-width:1px}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-r-gray-700{--tw-border-opacity:1;border-right-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-opacity-80{--tw-bg-opacity:0.8}[class~=theme-dark] .dark\:stroke-gray-500{stroke:#6b7280}[class~=theme-dark] .dark\:stroke-gray-700{stroke:#374151}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}[class~=theme-dark] .dark\:ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:ring-opacity-20{--tw-ring-opacity:0.2}[class~=theme-dark] .dark\:hover\:bg-\[\#ffffff12\]:hover{background-color:#ffffff12}[class~=theme-dark] .dark\:hover\:bg-indigo-500:hover{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:hover\:bg-gray-700:hover{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .hover\:dark\:text-gray-100:hover{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:block{display:block}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:justify-end{justify-content:flex-end}}@media (min-width:1024px){.lg\:flex{display:flex}}
1
+ /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.-inset-2{bottom:-.5rem;left:-.5rem;right:-.5rem;top:-.5rem}.inset-y-0{bottom:0;top:0}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-0{top:0}.top-\[-1px\]{top:-1px}.left-\[18px\]{left:18px}.bottom-0{bottom:0}.z-50{z-index:50}.z-10{z-index:10}.z-20{z-index:20}.m-auto{margin:auto}.m-2{margin:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.my-4{margin-bottom:1rem;margin-top:1rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.ml-2{margin-left:.5rem}.mb-2{margin-bottom:.5rem}.mb-0\.5{margin-bottom:.125rem}.mt-1\.5{margin-top:.375rem}.mb-0{margin-bottom:0}.mb-4{margin-bottom:1rem}.ml-3{margin-left:.75rem}.mr-6{margin-right:1.5rem}.mr-1{margin-right:.25rem}.mb-1{margin-bottom:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-fit{height:-moz-fit-content;height:fit-content}.h-10{height:2.5rem}.h-\[38px\]{height:38px}.h-auto{height:auto}.h-full{height:100%}.h-1{height:.25rem}.h-6{height:1.5rem}.h-4{height:1rem}.h-\[700px\]{height:700px}.h-\[80vh\]{height:80vh}.h-5{height:1.25rem}.max-h-\[400px\]{max-height:400px}.max-h-\[300px\]{max-height:300px}.min-h-52{min-height:13rem}.min-h-\[38px\]{min-height:38px}.min-h-48{min-height:12rem}.min-h-\[78px\]{min-height:78px}.min-h-96{min-height:24rem}.min-h-\[700px\]{min-height:700px}.w-full{width:100%}.w-auto{width:auto}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-max{width:-moz-max-content;width:max-content}.w-40{width:10rem}.w-80{width:20rem}.w-3{width:.75rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-9{width:2.25rem}.w-11{width:2.75rem}.w-\[52px\]{width:52px}.w-\[68px\]{width:68px}.w-\[76px\]{width:76px}.w-\[84px\]{width:84px}.w-\[92px\]{width:92px}.w-\[100px\]{width:100px}.w-\[108px\]{width:108px}.w-\[116px\]{width:116px}.w-4{width:1rem}.w-\[18px\]{width:18px}.w-8{width:2rem}.w-44{width:11rem}.w-\[460px\]{width:460px}.w-1\/5{width:20%}.w-11\/12{width:91.666667%}.w-1\/12{width:8.333333%}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.min-w-\[400px\]{min-width:400px}.max-w-\[500px\]{max-width:500px}.max-w-\[300px\]{max-width:300px}.max-w-\[400px\]{max-width:400px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.flex-grow-0{flex-grow:0}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.origin-top-left{transform-origin:top left}.origin-bottom-left{transform-origin:bottom left}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.-rotate-90{--tw-rotate:-90deg}.-rotate-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-auto{cursor:auto}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-clip{overflow:clip}.overflow-scroll{overflow:scroll}.overflow-x-hidden{overflow-x:hidden}.text-ellipsis{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-x{border-left-width:1px;border-right-width:1px}.border-y{border-bottom-width:1px;border-top-width:1px}.border-r{border-right-width:1px}.border-l{border-left-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.border-r-gray-200{--tw-border-opacity:1;border-right-color:rgb(229 231 235/var(--tw-border-opacity))}.border-l-amber-900{--tw-border-opacity:1;border-left-color:rgb(120 53 15/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-yellow-200{--tw-bg-opacity:1;background-color:rgb(254 240 138/var(--tw-bg-opacity))}.bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}.bg-indigo-100{--tw-bg-opacity:1;background-color:rgb(224 231 255/var(--tw-bg-opacity))}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}.bg-indigo-50{--tw-bg-opacity:1;background-color:rgb(238 242 255/var(--tw-bg-opacity))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.bg-opacity-90{--tw-bg-opacity:0.9}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.stroke-gray-300{stroke:#d1d5db}.stroke-white{stroke:#fff}.stroke-\[3\]{stroke-width:3}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1\.5{padding:.375rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-4{padding-bottom:1rem;padding-top:1rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.\!py-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.\!px-3{padding-left:.75rem!important;padding-right:.75rem!important}.px-3{padding-left:.75rem;padding-right:.75rem}.py-0{padding-bottom:0;padding-top:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-8{padding-left:2rem;padding-right:2rem}.pr-0{padding-right:0}.pt-2{padding-top:.5rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pb-4{padding-bottom:1rem}.pb-2{padding-bottom:.5rem}.pb-6{padding-bottom:1.5rem}.pb-\[10px\]{padding-bottom:10px}.pl-1{padding-left:.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pl-5{padding-left:1.25rem}.pr-\[1\.7rem\]{padding-right:1.7rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-\[10px\]{font-size:10px}.text-lg{font-size:1.125rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-6{line-height:1.5rem}.leading-5{line-height:1.25rem}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-90{opacity:.9}.opacity-50{opacity:.5}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 10px 2px rgba(0,0,0,.3);--tw-shadow-colored:0 0 10px 2px var(--tw-shadow-color)}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[stroke-dasharray\:6\2c 4\]{stroke-dasharray:6,4}.\[stroke-linecap\:round\]{stroke-linecap:round}.\[stroke-linejoin\:round\]{stroke-linejoin:round}.hover\:whitespace-normal:hover{white-space:normal}.hover\:bg-\[\#62626212\]:hover{background-color:#62626212}.hover\:bg-indigo-200:hover{--tw-bg-opacity:1;background-color:rgb(199 210 254/var(--tw-bg-opacity))}.focus\:border-indigo-500:focus{--tw-border-opacity:1;border-color:rgb(99 102 241/var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-1:focus,.focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-indigo-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(99 102 241/var(--tw-ring-opacity))}.focus\:ring-indigo-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(79 70 229/var(--tw-ring-opacity))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.group:hover .group-hover\:flex{display:flex}[class~=theme-dark] .dark\:border{border-width:1px}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-r-gray-700{--tw-border-opacity:1;border-right-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-opacity-80{--tw-bg-opacity:0.8}[class~=theme-dark] .dark\:stroke-gray-500{stroke:#6b7280}[class~=theme-dark] .dark\:stroke-gray-700{stroke:#374151}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}[class~=theme-dark] .dark\:ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:ring-opacity-20{--tw-ring-opacity:0.2}[class~=theme-dark] .dark\:hover\:bg-\[\#ffffff12\]:hover{background-color:#ffffff12}[class~=theme-dark] .dark\:hover\:bg-indigo-500:hover{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .hover\:dark\:text-gray-100:hover{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:block{display:block}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:justify-end{justify-content:flex-end}}@media (min-width:1024px){.lg\:flex{display:flex}}
@@ -0,0 +1,8 @@
1
+ import { ProfileType } from '@parca/parser';
2
+ export declare const DEFAULT_EMPTY_SUM_BY: string[];
3
+ export declare const useSumBy: (profileType: ProfileType | undefined, labelNamesLoading: boolean, labels: string[] | undefined, { urlParamKey, withURLUpdate, defaultValue, }?: {
4
+ urlParamKey?: string;
5
+ withURLUpdate?: boolean;
6
+ defaultValue?: string[];
7
+ }) => [string[], (labels: string[]) => void, string[] | undefined];
8
+ //# sourceMappingURL=useSumBy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSumBy.d.ts","sourceRoot":"","sources":["../src/useSumBy.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAE1C,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAAO,CAAC;AAyBjD,eAAO,MAAM,QAAQ,gBACN,WAAW,GAAG,SAAS,qBACjB,OAAO,UAClB,MAAM,EAAE,GAAG,SAAS,kDAKzB;IACD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,KACA,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,CAkE7D,CAAC"}
@@ -28,11 +28,12 @@ const getDefaultSumBy = (profile, labels) => {
28
28
  }
29
29
  return undefined;
30
30
  };
31
- export const useSumBy = (profileType, labelNamesLoading, labels) => {
31
+ export const useSumBy = (profileType, labelNamesLoading, labels, { urlParamKey = 'sum_by', withURLUpdate = true, defaultValue, } = {}) => {
32
32
  const { navigateTo } = useParcaContext();
33
33
  const [userSelectedSumByParam, setUserSelectedSumByParam] = useURLState({
34
- param: 'sum_by',
34
+ param: urlParamKey,
35
35
  navigateTo,
36
+ withURLUpdate,
36
37
  });
37
38
  const userSelectedSumBy = useMemo(() => {
38
39
  if (userSelectedSumByParam?.length === 0) {
@@ -41,10 +42,14 @@ export const useSumBy = (profileType, labelNamesLoading, labels) => {
41
42
  if (userSelectedSumByParam === '__none__') {
42
43
  return [];
43
44
  }
45
+ if (userSelectedSumByParam === undefined && defaultValue !== undefined) {
46
+ return defaultValue;
47
+ }
44
48
  if (typeof userSelectedSumByParam === 'string') {
45
49
  return [userSelectedSumByParam];
46
50
  }
47
51
  return userSelectedSumByParam;
52
+ // eslint-disable-next-line react-hooks/exhaustive-deps
48
53
  }, [userSelectedSumByParam]);
49
54
  const setUserSelectedSumBy = useCallback((sumBy) => {
50
55
  if (sumBy.length === 0) {
@@ -69,5 +74,5 @@ export const useSumBy = (profileType, labelNamesLoading, labels) => {
69
74
  if (profileType?.delta !== true) {
70
75
  sumBy = [];
71
76
  }
72
- return [sumBy, setUserSelectedSumBy];
77
+ return [sumBy, setUserSelectedSumBy, userSelectedSumBy];
73
78
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.412",
3
+ "version": "0.16.413",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@headlessui/react": "^1.7.19",
@@ -73,5 +73,5 @@
73
73
  "access": "public",
74
74
  "registry": "https://registry.npmjs.org/"
75
75
  },
76
- "gitHead": "ba668d046e2eea3514961fac022c19b21ff16412"
76
+ "gitHead": "8b3121b9f7c20b041cf55ca866260acbe0bd70c2"
77
77
  }
@@ -73,6 +73,7 @@ const ProfileExplorerCompare = ({
73
73
  enforcedProfileName={''}
74
74
  comparing={true}
75
75
  navigateTo={navigateTo}
76
+ suffix="_a"
76
77
  />
77
78
  </Card>
78
79
  <Card className="mt-2 p-2">
@@ -86,6 +87,7 @@ const ProfileExplorerCompare = ({
86
87
  enforcedProfileName={Query.parse(queryA.expression).profileName()}
87
88
  comparing={true}
88
89
  navigateTo={navigateTo}
90
+ suffix="_b"
89
91
  />
90
92
  </Card>
91
93
  </div>
@@ -48,6 +48,7 @@ const ProfileExplorerSingle = ({
48
48
  comparing={false}
49
49
  enforcedProfileName={''} // TODO
50
50
  navigateTo={navigateTo}
51
+ suffix="_a"
51
52
  />
52
53
  </Card>
53
54
  {profile != null ? (
@@ -120,12 +120,14 @@ const ProfileExplorerApp = ({
120
120
  merge_to_a,
121
121
  time_selection_a,
122
122
  compare_a,
123
+ sum_by_a,
123
124
  from_b,
124
125
  to_b,
125
126
  merge_from_b,
126
127
  merge_to_b,
127
128
  time_selection_b,
128
129
  compare_b,
130
+ sum_by_b,
129
131
  filter_by_function,
130
132
  dashboard_items,
131
133
  } = queryParams;
@@ -223,6 +225,7 @@ const ProfileExplorerApp = ({
223
225
  from: parseInt(from_a as string),
224
226
  to: parseInt(to_a as string),
225
227
  timeSelection: time_selection_a as string,
228
+ sumBy: sum_by_a as string[],
226
229
  };
227
230
 
228
231
  // Show the SingleProfileExplorer when not comparing
@@ -280,6 +283,7 @@ const ProfileExplorerApp = ({
280
283
  from: parseInt(from_b as string),
281
284
  to: parseInt(to_b as string),
282
285
  timeSelection: time_selection_b as string,
286
+ sumBy: sum_by_b as string[],
283
287
  };
284
288
 
285
289
  const selectQueryA = (q: QuerySelection): void => {
@@ -28,12 +28,9 @@ import {Query} from '@parca/parser';
28
28
  import {capitalizeOnlyFirstLetter, getStepDuration} from '@parca/utilities';
29
29
 
30
30
  import {MergedProfileSelection, ProfileSelection} from '..';
31
- import {useLabelNames} from '../MatchersInput';
32
31
  import MetricsGraph from '../MetricsGraph';
33
32
  import {useMetricsGraphDimensions} from '../MetricsGraph/useMetricsGraphDimensions';
34
33
  import useGrpcQuery from '../useGrpcQuery';
35
- import {Toolbar} from './Toolbar';
36
- import {DEFAULT_EMPTY_SUM_BY, useSumBy} from './useSumBy';
37
34
 
38
35
  interface ProfileMetricsEmptyStateProps {
39
36
  message: string;
@@ -65,6 +62,8 @@ interface ProfileMetricsGraphProps {
65
62
  profile: ProfileSelection | null;
66
63
  from: number;
67
64
  to: number;
65
+ sumByLoading: boolean;
66
+ sumBy: string[];
68
67
  setTimeRange: (range: DateTimeRange) => void;
69
68
  addLabelMatcher: (
70
69
  labels: {key: string; value: string} | Array<{key: string; value: string}>
@@ -99,7 +98,7 @@ export const useQueryRange = (
99
98
  queryExpression: string,
100
99
  start: number,
101
100
  end: number,
102
- sumBy: string[] = DEFAULT_EMPTY_SUM_BY,
101
+ sumBy: string[],
103
102
  skip = false
104
103
  ): IQueryRangeState => {
105
104
  const metadata = useGrpcMetadata();
@@ -142,7 +141,7 @@ export const useQueryRange = (
142
141
  },
143
142
  options: {
144
143
  retry: false,
145
- enabled: !skip && sumBy !== DEFAULT_EMPTY_SUM_BY,
144
+ enabled: !skip,
146
145
  staleTime: 1000 * 60 * 5, // 5 minutes
147
146
  },
148
147
  });
@@ -153,7 +152,6 @@ export const useQueryRange = (
153
152
  const ProfileMetricsGraph = ({
154
153
  queryClient,
155
154
  queryExpression,
156
- dirtyQueryExpression,
157
155
  profile,
158
156
  from,
159
157
  to,
@@ -161,32 +159,14 @@ const ProfileMetricsGraph = ({
161
159
  addLabelMatcher,
162
160
  onPointClick,
163
161
  comparing = false,
162
+ sumBy,
163
+ sumByLoading,
164
164
  }: ProfileMetricsGraphProps): JSX.Element => {
165
- const profileType = useMemo(() => {
166
- return Query.parse(queryExpression).profileType();
167
- }, [queryExpression]);
168
-
169
- const dirtyProfileType = useMemo(() => {
170
- return Query.parse(dirtyQueryExpression).profileType();
171
- }, [dirtyQueryExpression]);
172
-
173
- const {loading: labelNamesLoading, result: labelNamesResult} = useLabelNames(
174
- queryClient,
175
- profileType.toString() ?? '',
176
- from,
177
- to
178
- );
179
- const [sumBy, setSumBy] = useSumBy(
180
- profileType,
181
- labelNamesLoading,
182
- labelNamesResult.response?.labelNames
183
- );
184
-
185
165
  const {
186
166
  isLoading: metricsGraphLoading,
187
167
  response,
188
168
  error,
189
- } = useQueryRange(queryClient, queryExpression, from, to, sumBy, labelNamesLoading);
169
+ } = useQueryRange(queryClient, queryExpression, from, to, sumBy, sumByLoading);
190
170
  const {onError, perf, authenticationErrorMessage, isDarkMode} = useParcaContext();
191
171
  const {width, height, margin, heightStyle} = useMetricsGraphDimensions(comparing);
192
172
 
@@ -207,13 +187,7 @@ const ProfileMetricsGraph = ({
207
187
  const series = response?.series;
208
188
  const dataAvailable = series !== null && series !== undefined && series?.length > 0;
209
189
 
210
- const loading = metricsGraphLoading || labelNamesLoading;
211
-
212
- if (!labelNamesLoading && labelNamesResult?.error?.message != null) {
213
- return (
214
- <ErrorContent errorMessage={capitalizeOnlyFirstLetter(labelNamesResult.error.message)} />
215
- );
216
- }
190
+ const loading = metricsGraphLoading;
217
191
 
218
192
  if (!metricsGraphLoading && error !== null) {
219
193
  if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
@@ -243,13 +217,6 @@ const ProfileMetricsGraph = ({
243
217
  animate={{display: 'block', opacity: 1}}
244
218
  transition={{duration: 0.5}}
245
219
  >
246
- {dirtyProfileType.delta ? (
247
- <Toolbar
248
- sumBy={sumBy}
249
- setSumBy={setSumBy}
250
- labels={labelNamesResult.response?.labelNames ?? []}
251
- />
252
- ) : null}
253
220
  {loading ? (
254
221
  <MetricsGraphSkeleton heightStyle={heightStyle} isDarkMode={isDarkMode} />
255
222
  ) : dataAvailable ? (
@@ -11,9 +11,10 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
 
14
- import React, {useEffect, useState} from 'react';
14
+ import React, {useEffect, useMemo, useState} from 'react';
15
15
 
16
16
  import {RpcError} from '@protobuf-ts/runtime-rpc';
17
+ import Select from 'react-select';
17
18
 
18
19
  import {Label, ProfileTypesResponse, QueryServiceClient} from '@parca/client';
19
20
  import {
@@ -30,10 +31,11 @@ import {Query} from '@parca/parser';
30
31
  import {type NavigateFunction} from '@parca/utilities';
31
32
 
32
33
  import {MergedProfileSelection, ProfileSelection} from '..';
33
- import MatchersInput from '../MatchersInput/index';
34
+ import MatchersInput, {useLabelNames} from '../MatchersInput/index';
34
35
  import {useMetricsGraphDimensions} from '../MetricsGraph/useMetricsGraphDimensions';
35
36
  import ProfileMetricsGraph, {ProfileMetricsEmptyState} from '../ProfileMetricsGraph';
36
37
  import ProfileTypeSelector from '../ProfileTypeSelector/index';
38
+ import {useSumBy} from '../useSumBy';
37
39
  import {useAutoQuerySelector} from './useAutoQuerySelector';
38
40
 
39
41
  export interface QuerySelection {
@@ -41,6 +43,7 @@ export interface QuerySelection {
41
43
  from: number;
42
44
  to: number;
43
45
  timeSelection: string;
46
+ sumBy?: string[];
44
47
  mergeFrom?: number;
45
48
  mergeTo?: number;
46
49
  }
@@ -55,6 +58,7 @@ interface ProfileSelectorProps {
55
58
  profileSelection: ProfileSelection | null;
56
59
  comparing: boolean;
57
60
  navigateTo: NavigateFunction;
61
+ suffix?: string;
58
62
  }
59
63
 
60
64
  export interface IProfileTypesResult {
@@ -93,6 +97,7 @@ const ProfileSelector = ({
93
97
  profileSelection,
94
98
  comparing,
95
99
  navigateTo,
100
+ suffix = '',
96
101
  }: ProfileSelectorProps): JSX.Element => {
97
102
  const {
98
103
  loading: profileTypesLoading,
@@ -108,6 +113,38 @@ const ProfileSelector = ({
108
113
 
109
114
  const [queryExpressionString, setQueryExpressionString] = useState(querySelection.expression);
110
115
 
116
+ const profileType = useMemo(() => {
117
+ return Query.parse(queryExpressionString).profileType();
118
+ }, [queryExpressionString]);
119
+
120
+ const {loading: labelNamesLoading, result} = useLabelNames(queryClient, profileType.toString());
121
+
122
+ const labels = useMemo(() => {
123
+ return result.response?.labelNames === undefined ? [] : result.response.labelNames;
124
+ }, [result]);
125
+
126
+ const [sumBy, setSumBy, userSelectedSumBy] = useSumBy(
127
+ profileType,
128
+ labelNamesLoading,
129
+ result.response?.labelNames,
130
+ {
131
+ urlParamKey: 'sum_by' + suffix,
132
+ }
133
+ );
134
+
135
+ const [sumBySelection, setSumBySelection] = useSumBy(
136
+ profileType,
137
+ labelNamesLoading,
138
+ result.response?.labelNames,
139
+ {
140
+ urlParamKey: 'sum_by_selection' + suffix,
141
+ withURLUpdate: false,
142
+ defaultValue: userSelectedSumBy,
143
+ }
144
+ );
145
+
146
+ const sumByLoading = labelNamesLoading;
147
+
111
148
  useEffect(() => {
112
149
  if (enforcedProfileName !== '') {
113
150
  const [q, changed] = Query.parse(querySelection.expression).setProfileName(
@@ -132,6 +169,9 @@ const ProfileSelector = ({
132
169
  const selectedProfileName = query.profileName();
133
170
 
134
171
  const setNewQueryExpression = (expr: string, updateTs = false): void => {
172
+ if (!sumByLoading) {
173
+ setSumBy(sumBySelection);
174
+ }
135
175
  const query = enforcedProfileName !== '' ? enforcedProfileNameQuery() : Query.parse(expr);
136
176
  const delta = query.profileType().delta;
137
177
  const from = timeRangeSelection.getFromMs(updateTs);
@@ -217,7 +257,7 @@ const ProfileSelector = ({
217
257
  profileTypesData,
218
258
  setProfileName,
219
259
  setQueryExpression,
220
- querySelection,
260
+ querySelection: {...querySelection, sumBy},
221
261
  navigateTo,
222
262
  });
223
263
 
@@ -255,6 +295,27 @@ const ProfileSelector = ({
255
295
  profileType={selectedProfileName}
256
296
  />
257
297
  </div>
298
+ <div className="pb-6">
299
+ <div className="mb-0.5 mt-1.5 flex items-center justify-between">
300
+ <label className="text-xs">Sum by</label>
301
+ </div>
302
+ <Select
303
+ defaultValue={[]}
304
+ isMulti
305
+ name="colors"
306
+ options={labels.map(label => ({label, value: label}))}
307
+ className="parca-select-container text-sm w-80"
308
+ classNamePrefix="parca-select"
309
+ value={sumBySelection.map(sumBy => ({label: sumBy, value: sumBy}))}
310
+ onChange={selectedOptions => {
311
+ setSumBySelection(selectedOptions.map(option => option.value));
312
+ }}
313
+ placeholder="Labels..."
314
+ styles={{
315
+ indicatorSeparator: () => ({display: 'none'}),
316
+ }}
317
+ />
318
+ </div>
258
319
  <DateTimeRangePicker
259
320
  onRangeSelection={setTimeRangeSelection}
260
321
  range={timeRangeSelection}
@@ -289,6 +350,8 @@ const ProfileSelector = ({
289
350
  to={querySelection.to}
290
351
  profile={profileSelection}
291
352
  comparing={comparing}
353
+ sumBy={sumBy}
354
+ sumByLoading={sumByLoading}
292
355
  setTimeRange={(range: DateTimeRange) => {
293
356
  const from = range.getFromMs();
294
357
  const to = range.getToMs();
@@ -61,9 +61,12 @@ export const useAutoQuerySelector = ({
61
61
  from: querySelection.from,
62
62
  to: querySelection.to,
63
63
  timeSelection: querySelection.timeSelection,
64
+ sumBy: querySelection.sumBy,
64
65
  };
65
66
 
66
- let compareQuery = {
67
+ const sumBy = queryA.sumBy?.join(',');
68
+
69
+ let compareQuery: Record<string, string> = {
67
70
  compare_a: 'true',
68
71
  expression_a: encodeURIComponent(queryA.expression),
69
72
  from_a: queryA.from.toString(),
@@ -77,6 +80,11 @@ export const useAutoQuerySelector = ({
77
80
  time_selection_b: queryA.timeSelection,
78
81
  };
79
82
 
83
+ if (sumBy != null) {
84
+ compareQuery.sum_by_a = sumBy;
85
+ compareQuery.sum_by_b = sumBy;
86
+ }
87
+
80
88
  if (profileA != null) {
81
89
  compareQuery = {
82
90
  ...SuffixParams(profileA.HistoryParams(), '_a'),
@@ -44,12 +44,22 @@ const getDefaultSumBy = (
44
44
  export const useSumBy = (
45
45
  profileType: ProfileType | undefined,
46
46
  labelNamesLoading: boolean,
47
- labels: string[] | undefined
48
- ): [string[], (labels: string[]) => void] => {
47
+ labels: string[] | undefined,
48
+ {
49
+ urlParamKey = 'sum_by',
50
+ withURLUpdate = true,
51
+ defaultValue,
52
+ }: {
53
+ urlParamKey?: string;
54
+ withURLUpdate?: boolean;
55
+ defaultValue?: string[];
56
+ } = {}
57
+ ): [string[], (labels: string[]) => void, string[] | undefined] => {
49
58
  const {navigateTo} = useParcaContext();
50
59
  const [userSelectedSumByParam, setUserSelectedSumByParam] = useURLState({
51
- param: 'sum_by',
60
+ param: urlParamKey,
52
61
  navigateTo,
62
+ withURLUpdate,
53
63
  });
54
64
 
55
65
  const userSelectedSumBy = useMemo<string[] | undefined>(() => {
@@ -61,11 +71,17 @@ export const useSumBy = (
61
71
  return [];
62
72
  }
63
73
 
74
+ if (userSelectedSumByParam === undefined && defaultValue !== undefined) {
75
+ return defaultValue;
76
+ }
77
+
64
78
  if (typeof userSelectedSumByParam === 'string') {
65
79
  return [userSelectedSumByParam];
66
80
  }
67
81
 
68
82
  return userSelectedSumByParam;
83
+
84
+ // eslint-disable-next-line react-hooks/exhaustive-deps
69
85
  }, [userSelectedSumByParam]);
70
86
 
71
87
  const setUserSelectedSumBy = useCallback(
@@ -103,5 +119,5 @@ export const useSumBy = (
103
119
  sumBy = [];
104
120
  }
105
121
 
106
- return [sumBy, setUserSelectedSumBy];
122
+ return [sumBy, setUserSelectedSumBy, userSelectedSumBy];
107
123
  };
@@ -1,9 +0,0 @@
1
- import { ReactNode } from 'react';
2
- interface Props {
3
- sumBy: string[];
4
- setSumBy: (sumBy: string[]) => void;
5
- labels: string[];
6
- }
7
- export declare const Toolbar: ({ sumBy, setSumBy, labels }: Props) => ReactNode;
8
- export {};
9
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ProfileMetricsGraph/Toolbar/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAC,SAAS,EAA2B,MAAM,OAAO,CAAC;AAQ1D,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,OAAO,gCAA+B,KAAK,KAAG,SAkE1D,CAAC"}
@@ -1,29 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // Copyright 2022 The Parca Authors
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
14
- import { useId, useMemo, useState } from 'react';
15
- import { Icon } from '@iconify/react';
16
- import Draggable from 'react-draggable';
17
- import Select from 'react-select';
18
- import { IconButton } from '@parca/components';
19
- export const Toolbar = ({ sumBy, setSumBy, labels }) => {
20
- const [collapsed, setCollapsed] = useState(false);
21
- const [isDragging, setIsDragging] = useState(false);
22
- const idWithColon = useId();
23
- const id = useMemo(() => idWithColon.replace(/[^a-zA-Z0-9]/g, ''), [idWithColon]);
24
- return (_jsx(Draggable, { handle: `#${id}`, onStart: () => setIsDragging(true), onStop: () => setIsDragging(false), bounds: "parent", defaultPosition: { x: 96, y: 4 }, children: _jsx("div", { className: "absolute rounded-full bg-gray-100 dark:bg-gray-800 z-10 text-xs", children: _jsxs("div", { className: "flex items-center h-14 gap-4 py-1 px-3", children: [_jsx(Icon, { icon: "radix-icons:drag-handle-dots-2", height: 20, className: isDragging ? 'cursor-grabbing' : 'cursor-grab', id: id }), !collapsed ? (_jsxs("div", { className: "flex gap-2 items-center mr-4", children: [_jsx("span", { children: "Sum by" }), _jsx(Select, { defaultValue: [], isMulti: true, name: "colors", options: labels.map(label => ({ label, value: label })), className: "parca-select-container min-w-60", classNamePrefix: "parca-select", value: sumBy.map(sumBy => ({ label: sumBy, value: sumBy })), onChange: selectedOptions => {
25
- setSumBy(selectedOptions.map(option => option.value));
26
- }, placeholder: "Labels...", styles: {
27
- indicatorSeparator: () => ({ display: 'none' }),
28
- } })] })) : null, _jsxs("div", { className: "relative", children: [_jsx(IconButton, { icon: _jsx(Icon, { icon: collapsed ? 'iconamoon:arrow-right-2-light' : 'iconamoon:arrow-left-2-light', height: 24 }), onClick: () => setCollapsed(!collapsed), className: "hover:bg-gray-200 dark:hover:bg-gray-700 rounded-full p-1" }), collapsed && sumBy.length > 0 ? (_jsx("div", { className: "rounded-full bg-indigo-600 dark:bg-indigo-500 absolute text-xs h-4 w-4 flex items-center justify-center -top-3 -right-3 text-white text-[10px]", children: sumBy.length })) : null] })] }) }) }));
29
- };
@@ -1,4 +0,0 @@
1
- import { ProfileType } from '@parca/parser';
2
- export declare const DEFAULT_EMPTY_SUM_BY: string[];
3
- export declare const useSumBy: (profileType: ProfileType | undefined, labelNamesLoading: boolean, labels: string[] | undefined) => [string[], (labels: string[]) => void];
4
- //# sourceMappingURL=useSumBy.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useSumBy.d.ts","sourceRoot":"","sources":["../../src/ProfileMetricsGraph/useSumBy.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAE1C,eAAO,MAAM,oBAAoB,EAAE,MAAM,EAAO,CAAC;AAyBjD,eAAO,MAAM,QAAQ,gBACN,WAAW,GAAG,SAAS,qBACjB,OAAO,UAClB,MAAM,EAAE,GAAG,SAAS,KAC3B,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CA2DvC,CAAC"}
@@ -1,94 +0,0 @@
1
- // Copyright 2022 The Parca Authors
2
- // Licensed under the Apache License, Version 2.0 (the "License");
3
- // you may not use this file except in compliance with the License.
4
- // You may obtain a copy of the License at
5
- //
6
- // http://www.apache.org/licenses/LICENSE-2.0
7
- //
8
- // Unless required by applicable law or agreed to in writing, software
9
- // distributed under the License is distributed on an "AS IS" BASIS,
10
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
- // See the License for the specific language governing permissions and
12
- // limitations under the License.
13
-
14
- import {ReactNode, useId, useMemo, useState} from 'react';
15
-
16
- import {Icon} from '@iconify/react';
17
- import Draggable from 'react-draggable';
18
- import Select from 'react-select';
19
-
20
- import {IconButton} from '@parca/components';
21
-
22
- interface Props {
23
- sumBy: string[];
24
- setSumBy: (sumBy: string[]) => void;
25
- labels: string[];
26
- }
27
-
28
- export const Toolbar = ({sumBy, setSumBy, labels}: Props): ReactNode => {
29
- const [collapsed, setCollapsed] = useState<boolean>(false);
30
- const [isDragging, setIsDragging] = useState<boolean>(false);
31
- const idWithColon = useId();
32
- const id = useMemo(() => idWithColon.replace(/[^a-zA-Z0-9]/g, ''), [idWithColon]);
33
-
34
- return (
35
- <Draggable
36
- handle={`#${id}`}
37
- onStart={() => setIsDragging(true)}
38
- onStop={() => setIsDragging(false)}
39
- bounds="parent"
40
- defaultPosition={{x: 96, y: 4}}
41
- >
42
- <div className="absolute rounded-full bg-gray-100 dark:bg-gray-800 z-10 text-xs">
43
- <div className="flex items-center h-14 gap-4 py-1 px-3">
44
- <Icon
45
- icon="radix-icons:drag-handle-dots-2"
46
- height={20}
47
- className={isDragging ? 'cursor-grabbing' : 'cursor-grab'}
48
- id={id}
49
- />
50
- {!collapsed ? (
51
- <div className="flex gap-2 items-center mr-4">
52
- <span>Sum by</span>
53
- <Select
54
- defaultValue={[]}
55
- isMulti
56
- name="colors"
57
- options={labels.map(label => ({label, value: label}))}
58
- className="parca-select-container min-w-60"
59
- classNamePrefix="parca-select"
60
- value={sumBy.map(sumBy => ({label: sumBy, value: sumBy}))}
61
- onChange={selectedOptions => {
62
- setSumBy(selectedOptions.map(option => option.value));
63
- }}
64
- placeholder="Labels..."
65
- styles={{
66
- indicatorSeparator: () => ({display: 'none'}),
67
- }}
68
- />
69
- </div>
70
- ) : null}
71
- <div className="relative">
72
- <IconButton
73
- icon={
74
- <Icon
75
- icon={
76
- collapsed ? 'iconamoon:arrow-right-2-light' : 'iconamoon:arrow-left-2-light'
77
- }
78
- height={24}
79
- />
80
- }
81
- onClick={() => setCollapsed(!collapsed)}
82
- className="hover:bg-gray-200 dark:hover:bg-gray-700 rounded-full p-1"
83
- />
84
- {collapsed && sumBy.length > 0 ? (
85
- <div className="rounded-full bg-indigo-600 dark:bg-indigo-500 absolute text-xs h-4 w-4 flex items-center justify-center -top-3 -right-3 text-white text-[10px]">
86
- {sumBy.length}
87
- </div>
88
- ) : null}
89
- </div>
90
- </div>
91
- </div>
92
- </Draggable>
93
- );
94
- };