Skip to content

Commit f13bbf9

Browse files
authored
refactor(TagExplorer): Extract ExploreHeader component (#3038)
1 parent 685506f commit f13bbf9

File tree

2 files changed

+88
-82
lines changed

2 files changed

+88
-82
lines changed

public/app/pages/TagExplorerView.tsx

Lines changed: 2 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { useEffect, useMemo } from 'react';
22
import { NavLink, useLocation } from 'react-router-dom';
33
import type { Maybe } from 'true-myth';
4-
import type { ClickEvent } from '@pyroscope/ui/Menu';
54
import Color from 'color';
65
import TotalSamplesChart from '@pyroscope/pages/tagExplorer/components/TotalSamplesChart';
76
import type { Profile } from '@pyroscope/legacy/models';
@@ -10,7 +9,6 @@ import Toolbar from '@pyroscope/components/Toolbar';
109
import TimelineChartWrapper, {
1110
TimelineGroupData,
1211
} from '@pyroscope/components/TimelineChart/TimelineChartWrapper';
13-
import Dropdown, { MenuItem } from '@pyroscope/ui/Dropdown';
1412
import TagsSelector from '@pyroscope/pages/tagExplorer/components/TagsSelector';
1513
import TableUI, { useTableSort, BodyRow } from '@pyroscope/ui/Table';
1614
import useTimeZone from '@pyroscope/hooks/timeZone.hook';
@@ -23,7 +21,6 @@ import {
2321
selectQueries,
2422
selectContinuousState,
2523
selectAppTags,
26-
TagsState,
2724
fetchTagExplorerView,
2825
fetchTagExplorerViewProfile,
2926
ALL_TAGS,
@@ -48,6 +45,7 @@ import styles from './TagExplorerView.module.scss';
4845
import { formatTitle } from './formatTitle';
4946
import { FlameGraphWrapper } from '@pyroscope/components/FlameGraphWrapper';
5047
import profileMetrics from '../constants/profile-metrics.json';
48+
import { ExploreHeader } from '@pyroscope/pages/tagExplorer/components/ExploreHeader';
5149

5250
const TIMELINE_SERIES_COLORS = [
5351
Color.rgb(242, 204, 12),
@@ -160,7 +158,7 @@ const TIMELINE_WRAPPER_ID = 'explore_timeline_wrapper';
160158
const getTimelineColor = (index: number, palette: Color[]): Color =>
161159
Color(palette[index % (palette.length - 1)]);
162160

163-
const getProfileMetricTitle = (appName: Maybe<string>) => {
161+
export const getProfileMetricTitle = (appName: Maybe<string>) => {
164162
const name = appName.unwrapOr('');
165163
const profileMetric = (profileMetrics as Record<string, any>)[name];
166164

@@ -650,82 +648,4 @@ function Table({
650648
);
651649
}
652650

653-
function ExploreHeader({
654-
appName,
655-
whereDropdownItems,
656-
tags,
657-
selectedTag,
658-
selectedTagValue,
659-
handleGroupByTagChange,
660-
handleGroupByTagValueChange,
661-
}: {
662-
appName: Maybe<string>;
663-
whereDropdownItems: string[];
664-
tags: TagsState;
665-
selectedTag: string;
666-
selectedTagValue: string;
667-
handleGroupByTagChange: (value: string) => void;
668-
handleGroupByTagValueChange: (value: string) => void;
669-
}) {
670-
const tagKeys = Object.keys(tags.tags);
671-
const groupByDropdownItems =
672-
tagKeys.length > 0 ? tagKeys : ['No tags available'];
673-
674-
const handleGroupByClick = (e: ClickEvent) => {
675-
handleGroupByTagChange(e.value);
676-
};
677-
678-
const handleGroupByValueClick = (e: ClickEvent) => {
679-
handleGroupByTagValueChange(e.value);
680-
};
681-
682-
useEffect(() => {
683-
if (tagKeys.length && !selectedTag) {
684-
const firstGoodTag = tagKeys.find((tag) => !tag.startsWith('__'));
685-
handleGroupByTagChange(firstGoodTag || tagKeys[0]);
686-
}
687-
}, [tagKeys, selectedTag, handleGroupByTagChange]);
688-
689-
return (
690-
<div className={styles.header} data-testid="explore-header">
691-
<span className={styles.title}>{getProfileMetricTitle(appName)}</span>
692-
<div className={styles.queryGrouppedBy}>
693-
<span className={styles.selectName}>grouped by</span>
694-
<Dropdown
695-
label="select tag"
696-
value={selectedTag ? `tag: ${selectedTag}` : 'select tag'}
697-
onItemClick={tagKeys.length > 0 ? handleGroupByClick : undefined}
698-
menuButtonClassName={
699-
selectedTag === '' ? styles.notSelectedTagDropdown : undefined
700-
}
701-
>
702-
{groupByDropdownItems.map((tagName) => (
703-
<MenuItem key={tagName} value={tagName}>
704-
{tagName}
705-
</MenuItem>
706-
))}
707-
</Dropdown>
708-
</div>
709-
<div className={styles.query}>
710-
<span className={styles.selectName}>where</span>
711-
<Dropdown
712-
label="select where"
713-
value={`${selectedTag ? `${selectedTag} = ` : selectedTag} ${
714-
selectedTagValue || ALL_TAGS
715-
}`}
716-
onItemClick={handleGroupByValueClick}
717-
menuButtonClassName={styles.whereSelectButton}
718-
>
719-
{/* always show "All" option */}
720-
{[ALL_TAGS, ...whereDropdownItems].map((tagGroupName) => (
721-
<MenuItem key={tagGroupName} value={tagGroupName}>
722-
{tagGroupName}
723-
</MenuItem>
724-
))}
725-
</Dropdown>
726-
</div>
727-
</div>
728-
);
729-
}
730-
731651
export default TagExplorerView;
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import React, { useEffect } from 'react';
2+
import type { Maybe } from 'true-myth';
3+
import type { ClickEvent } from '@pyroscope/ui/Menu';
4+
import Dropdown, { MenuItem } from '@pyroscope/ui/Dropdown';
5+
import { TagsState, ALL_TAGS } from '@pyroscope/redux/reducers/continuous';
6+
import styles from '@pyroscope/pages/TagExplorerView.module.scss';
7+
import { getProfileMetricTitle } from '@pyroscope/pages/TagExplorerView';
8+
9+
export function ExploreHeader({
10+
appName,
11+
whereDropdownItems,
12+
tags,
13+
selectedTag,
14+
selectedTagValue,
15+
handleGroupByTagChange,
16+
handleGroupByTagValueChange,
17+
}: {
18+
appName: Maybe<string>;
19+
whereDropdownItems: string[];
20+
tags: TagsState;
21+
selectedTag: string;
22+
selectedTagValue: string;
23+
handleGroupByTagChange: (value: string) => void;
24+
handleGroupByTagValueChange: (value: string) => void;
25+
}) {
26+
const tagKeys = Object.keys(tags.tags);
27+
28+
const groupByDropdownItems =
29+
tagKeys.length > 0 ? tagKeys : ['No tags available'];
30+
31+
const handleGroupByClick = (e: ClickEvent) => {
32+
handleGroupByTagChange(e.value);
33+
};
34+
35+
const handleGroupByValueClick = (e: ClickEvent) => {
36+
handleGroupByTagValueChange(e.value);
37+
};
38+
39+
useEffect(() => {
40+
if (tagKeys.length && !selectedTag) {
41+
const firstGoodTag = tagKeys.find((tag) => !tag.startsWith('__'));
42+
handleGroupByTagChange(firstGoodTag || tagKeys[0]);
43+
}
44+
}, [tagKeys, selectedTag, handleGroupByTagChange]);
45+
46+
return (
47+
<div className={styles.header} data-testid="explore-header">
48+
<span className={styles.title}>{getProfileMetricTitle(appName)}</span>
49+
<div className={styles.queryGrouppedBy}>
50+
<span className={styles.selectName}>grouped by</span>
51+
<Dropdown
52+
label="select tag"
53+
value={selectedTag ? `tag: ${selectedTag}` : 'select tag'}
54+
onItemClick={tagKeys.length > 0 ? handleGroupByClick : undefined}
55+
menuButtonClassName={
56+
selectedTag === '' ? styles.notSelectedTagDropdown : undefined
57+
}
58+
>
59+
{groupByDropdownItems.map((tagName) => (
60+
<MenuItem key={tagName} value={tagName}>
61+
{tagName}
62+
</MenuItem>
63+
))}
64+
</Dropdown>
65+
</div>
66+
<div className={styles.query}>
67+
<span className={styles.selectName}>where</span>
68+
<Dropdown
69+
label="select where"
70+
value={`${selectedTag ? `${selectedTag} = ` : selectedTag} ${
71+
selectedTagValue || ALL_TAGS
72+
}`}
73+
onItemClick={handleGroupByValueClick}
74+
menuButtonClassName={styles.whereSelectButton}
75+
>
76+
{/* always show "All" option */}
77+
{[ALL_TAGS, ...whereDropdownItems].map((tagGroupName) => (
78+
<MenuItem key={tagGroupName} value={tagGroupName}>
79+
{tagGroupName}
80+
</MenuItem>
81+
))}
82+
</Dropdown>
83+
</div>
84+
</div>
85+
);
86+
}

0 commit comments

Comments
 (0)