From e2ab0726a79401ab46bd1154a30160c649e5a79d Mon Sep 17 00:00:00 2001 From: Scott Cooper Date: Thu, 16 Apr 2026 10:27:59 -0700 Subject: [PATCH] fix(supergroups): Hoist stream-matched issues to the first page of the drawer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The supergroup drawer paginates `group_ids` in page-size chunks, then filters each page against the current stream query. If the matched issues sit past the first page in the underlying list, they never show up when you open the drawer — which is the whole point of opening it. Run the stream-query match over the full `group_ids` list up front, sort matched issues first, then paginate. The per-page sort is gone since the order is already right, and the page index gets clamped in case the list shrinks. Co-Authored-By: Claude Opus 4.7 --- .../supergroups/supergroupDrawer.tsx | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/static/app/views/issueList/supergroups/supergroupDrawer.tsx b/static/app/views/issueList/supergroups/supergroupDrawer.tsx index c12ec12be786c6..b77585b425256d 100644 --- a/static/app/views/issueList/supergroups/supergroupDrawer.tsx +++ b/static/app/views/issueList/supergroups/supergroupDrawer.tsx @@ -153,24 +153,10 @@ function SupergroupIssueList({ end, } = location.query; const query = typeof searchQuery === 'string' ? searchQuery : ''; - const totalPages = Math.ceil(groupIds.length / PAGE_SIZE); - const pageGroupIds = groupIds.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE); - const issueIdFilter = `issue.id:[${pageGroupIds.join(',')}]`; - // Fetch all groups on this page - const {data: allGroups, isPending: allPending} = useQuery( - apiOptions.as()('/organizations/$organizationIdOrSlug/issues/', { - path: {organizationIdOrSlug: organization.slug}, - query: { - group: pageGroupIds.map(String), - project: ALL_ACCESS_PROJECTS, - }, - staleTime: 30_000, - }) - ); - - // Search with the stream query to find which ones match - const {data: matchedGroups} = useQuery({ + // Search with the stream query across all member issues so matched issues + // can be hoisted to page 1 before pagination. + const {data: matchedGroups, isPending: matchedPending} = useQuery({ ...apiOptions.as()('/organizations/$organizationIdOrSlug/issues/', { path: {organizationIdOrSlug: organization.slug}, query: { @@ -179,14 +165,39 @@ function SupergroupIssueList({ statsPeriod, start, end, - query: `${query} ${issueIdFilter}`, + query: `${query} issue.id:[${groupIds.join(',')}]`, + per_page: PAGE_SIZE, }, staleTime: 30_000, }), enabled: !!filterWithCurrentSearch, }); - if (allPending) { + const matchedIds = new Set(matchedGroups?.map(g => g.id)); + const sortedGroupIds = [...groupIds].sort( + (a, b) => Number(matchedIds.has(String(b))) - Number(matchedIds.has(String(a))) + ); + + const totalPages = Math.ceil(sortedGroupIds.length / PAGE_SIZE); + const safePage = Math.min(page, totalPages - 1); + const pageGroupIds = sortedGroupIds.slice( + safePage * PAGE_SIZE, + (safePage + 1) * PAGE_SIZE + ); + + // Fetch all groups on this page + const {data: allGroups, isPending: allPending} = useQuery( + apiOptions.as()('/organizations/$organizationIdOrSlug/issues/', { + path: {organizationIdOrSlug: organization.slug}, + query: { + group: pageGroupIds.map(String), + project: ALL_ACCESS_PROJECTS, + }, + staleTime: 30_000, + }) + ); + + if (allPending || (filterWithCurrentSearch && matchedPending)) { return ( {filterWithCurrentSearch && ( @@ -212,14 +223,11 @@ function SupergroupIssueList({ ); } - const matchedIds = new Set(matchedGroups?.map(g => g.id)); const groupMap = new Map(allGroups?.map(g => [g.id, g])); - // Sort: matched first, then the rest - const sortedGroups = [...pageGroupIds] + const sortedGroups = pageGroupIds .map(id => groupMap.get(String(id))) - .filter((g): g is Group => g !== undefined) - .sort((a, b) => Number(matchedIds.has(b.id)) - Number(matchedIds.has(a.id))); + .filter((g): g is Group => g !== undefined); const visibleGroupIds = sortedGroups.map(g => g.id); @@ -266,22 +274,22 @@ function SupergroupIssueList({ {totalPages > 1 && ( - {`${page * PAGE_SIZE + 1}-${Math.min((page + 1) * PAGE_SIZE, groupIds.length)} of ${groupIds.length}`} + {`${safePage * PAGE_SIZE + 1}-${Math.min((safePage + 1) * PAGE_SIZE, sortedGroupIds.length)} of ${sortedGroupIds.length}`}