Skip to content

Commit 020de25

Browse files
roggenkemperandrewshie-sentry
authored andcommitted
feat(issue-details): Add tags from highlights to preview + drawer (#84278)
this pr updates the tag preview and drawer to show any tags that are highlighted for a project first. for the preview, it filters out any default highlights (because we already have a list of tags to show in the preview).
1 parent a9d4781 commit 020de25

File tree

6 files changed

+63
-8
lines changed

6 files changed

+63
-8
lines changed

static/app/views/issueDetails/groupTags/groupTagsDrawer.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {t, tct} from 'sentry/locale';
2424
import {space} from 'sentry/styles/space';
2525
import type {Group} from 'sentry/types/group';
2626
import {trackAnalytics} from 'sentry/utils/analytics';
27+
import {useDetailedProject} from 'sentry/utils/useDetailedProject';
2728
import {useLocation} from 'sentry/utils/useLocation';
2829
import useOrganization from 'sentry/utils/useOrganization';
2930
import {useParams} from 'sentry/utils/useParams';
@@ -67,6 +68,15 @@ export function GroupTagsDrawer({group}: {group: Group}) {
6768
environment: environments,
6869
});
6970

71+
const {data: detailedProject, isPending: isHighlightsPending} = useDetailedProject({
72+
orgSlug: organization.slug,
73+
projectSlug: project.slug,
74+
});
75+
76+
const highlightTagKeys = useMemo(() => {
77+
return detailedProject?.highlightTags ?? project?.highlightTags ?? [];
78+
}, [detailedProject, project]);
79+
7080
const tagValues = useMemo(
7181
() =>
7282
data.reduce((valueMap, tag) => {
@@ -78,18 +88,24 @@ export function GroupTagsDrawer({group}: {group: Group}) {
7888
);
7989

8090
const displayTags = useMemo(() => {
81-
const sortedTags = data.sort((a, b) => a.key.localeCompare(b.key));
82-
const searchedTags = sortedTags.filter(
91+
const highlightTags = data.filter(tag => highlightTagKeys.includes(tag.key));
92+
const orderedHighlightTags = highlightTags.sort(
93+
(a, b) => highlightTagKeys.indexOf(a.key) - highlightTagKeys.indexOf(b.key)
94+
);
95+
const remainingTags = data.filter(tag => !highlightTagKeys.includes(tag.key));
96+
const sortedTags = remainingTags.sort((a, b) => a.key.localeCompare(b.key));
97+
const orderedTags = [...orderedHighlightTags, ...sortedTags];
98+
const searchedTags = orderedTags.filter(
8399
tag =>
84100
tag.key.includes(search) ||
85101
tag.name.includes(search) ||
86102
// @ts-expect-error TS(7053): Element implicitly has an 'any' type because expre... Remove this comment to see the full error message
87103
tagValues[tag.key].includes(search)
88104
);
89105
return searchedTags;
90-
}, [data, search, tagValues]);
106+
}, [data, search, tagValues, highlightTagKeys]);
91107

92-
if (isPending) {
108+
if (isPending || isHighlightsPending) {
93109
return <LoadingIndicator />;
94110
}
95111

static/app/views/issueDetails/streamline/eventDetailsHeader.spec.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ describe('EventDetailsHeader', () => {
5757
new Set(['environments'])
5858
);
5959
ProjectsStore.loadInitialData([project]);
60+
MockApiClient.addMockResponse({
61+
url: '/projects/org-slug/project-slug/',
62+
body: [project],
63+
});
6064
MockApiClient.addMockResponse({
6165
url: `/organizations/${organization.slug}/events-stats/`,
6266
body: {'count()': EventsStatsFixture(), 'count_unique(user)': EventsStatsFixture()},

static/app/views/issueDetails/streamline/eventGraph.spec.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ describe('EventGraph', () => {
4242
url: `/organizations/${organization.slug}/releases/stats/`,
4343
body: [],
4444
});
45+
MockApiClient.addMockResponse({
46+
url: '/projects/org-slug/project-slug/',
47+
body: [project],
48+
});
4549
PageFiltersStore.init();
4650
PageFiltersStore.onInitializeUrlState(
4751
{

static/app/views/issueDetails/streamline/groupDetailsLayout.spec.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ describe('GroupDetailsLayout', () => {
8888
githubWriteIntegration: {ok: true},
8989
},
9090
});
91+
MockApiClient.addMockResponse({
92+
url: '/projects/org-slug/project-slug/',
93+
body: [project],
94+
});
9195
});
9296

9397
it('renders children, can collapse sidebar', async () => {

static/app/views/issueDetails/streamline/issueTagsPreview.spec.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
import {GroupFixture} from 'sentry-fixture/group';
2+
import {ProjectFixture} from 'sentry-fixture/project';
23
import {TagsFixture} from 'sentry-fixture/tags';
34

45
import {render, screen} from 'sentry-test/reactTestingLibrary';
56

67
import IssueTagsPreview from './issueTagsPreview';
78

89
describe('IssueTagsPreview', () => {
10+
beforeEach(() => {
11+
MockApiClient.addMockResponse({
12+
url: '/projects/org-slug/project-slug/',
13+
body: [ProjectFixture()],
14+
});
15+
});
916
it('renders preview tags', async () => {
1017
const group = GroupFixture();
1118
MockApiClient.addMockResponse({

static/app/views/issueDetails/streamline/issueTagsPreview.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ import {space} from 'sentry/styles/space';
1717
import type {Project} from 'sentry/types/project';
1818
import {percent} from 'sentry/utils';
1919
import {isMobilePlatform} from 'sentry/utils/platform';
20+
import {useDetailedProject} from 'sentry/utils/useDetailedProject';
2021
import {useLocation} from 'sentry/utils/useLocation';
22+
import useOrganization from 'sentry/utils/useOrganization';
2123
import {formatVersion} from 'sentry/utils/versions/formatVersion';
2224
import type {GroupTag} from 'sentry/views/issueDetails/groupTags/useGroupTags';
2325
import {useGroupTagsReadable} from 'sentry/views/issueDetails/groupTags/useGroupTags';
@@ -199,6 +201,19 @@ export default function IssueTagsPreview({
199201
project: Project;
200202
}) {
201203
const searchQuery = useEventQuery({groupId});
204+
const organization = useOrganization();
205+
206+
const {data: detailedProject, isPending: isHighlightPending} = useDetailedProject({
207+
orgSlug: organization.slug,
208+
projectSlug: project.slug,
209+
});
210+
211+
const highlightTagKeys = useMemo(() => {
212+
const tagKeys = detailedProject?.highlightTags ?? project?.highlightTags ?? [];
213+
const highlightDefaults =
214+
detailedProject?.highlightPreset?.tags ?? project?.highlightPreset?.tags ?? [];
215+
return tagKeys.filter(tag => !highlightDefaults.includes(tag));
216+
}, [detailedProject, project]);
202217

203218
const {
204219
isError,
@@ -213,6 +228,10 @@ export default function IssueTagsPreview({
213228
return [];
214229
}
215230

231+
const highlightTags = tags
232+
.filter(tag => highlightTagKeys.includes(tag.key))
233+
.sort((a, b) => highlightTagKeys.indexOf(a.key) - highlightTagKeys.indexOf(b.key));
234+
216235
const priorityTags = isMobilePlatform(project?.platform)
217236
? MOBILE_TAGS
218237
: frontend.some(val => val === project?.platform)
@@ -226,11 +245,12 @@ export default function IssueTagsPreview({
226245
.sort((a, b) => priorityTags.indexOf(a.key) - priorityTags.indexOf(b.key));
227246

228247
const remainingTagKeys = tags.filter(tag => !priorityTags.includes(tag.key)).sort();
229-
const orderedTags = [...sortedTags, ...remainingTagKeys];
230-
return orderedTags.slice(0, 4);
231-
}, [tags, project?.platform]);
248+
const orderedTags = [...highlightTags, ...sortedTags, ...remainingTagKeys];
249+
const uniqueTags = [...new Set(orderedTags)];
250+
return uniqueTags.slice(0, 4);
251+
}, [tags, project?.platform, highlightTagKeys]);
232252

233-
if (isPending) {
253+
if (isPending || isHighlightPending) {
234254
return (
235255
<IssueTagPreviewSection>
236256
<Placeholder width="240px" height="100px" />

0 commit comments

Comments
 (0)