diff --git a/static/app/views/issueList/header.tsx b/static/app/views/issueList/header.tsx
index af306b1f949c25..3d8962f9959cd2 100644
--- a/static/app/views/issueList/header.tsx
+++ b/static/app/views/issueList/header.tsx
@@ -22,6 +22,7 @@ import {normalizeUrl} from 'sentry/utils/withDomainRequired';
import IssueListSetAsDefault from 'sentry/views/issueList/issueListSetAsDefault';
import {
+ CUSTOM_TAB_VALUE,
FOR_REVIEW_QUERIES,
getTabs,
IssueSortOptions,
@@ -91,6 +92,7 @@ function IssueListHeader({
const visibleTabs = displayReprocessingTab
? tabs
: tabs.filter(([tab]) => tab !== Query.REPROCESSING);
+ const tabValues = new Set(visibleTabs.map(([val]) => val));
// Remove cursor and page when switching tabs
const {cursor: _, page: __, ...queryParms} = router?.location?.query ?? {};
const sortParam =
@@ -130,11 +132,11 @@ function IssueListHeader({
- {}}>
+
{[
...visibleTabs.map(
- ([tabQuery, {name: queryName, tooltipTitle, tooltipHoverable}]) => {
+ ([tabQuery, {name: queryName, tooltipTitle, tooltipHoverable, hidden}]) => {
const to = normalizeUrl({
query: {
...queryParms,
@@ -147,7 +149,12 @@ function IssueListHeader({
});
return (
-
+
{
getTabs(TestStubs.Organization({features: ['escalating-issues']})).map(
tab => tab[1].name
)
- ).toEqual(['Unresolved', 'For Review', 'Regressed', 'Escalating', 'Archived']);
+ ).toEqual([
+ 'Unresolved',
+ 'For Review',
+ 'Regressed',
+ 'Escalating',
+ 'Archived',
+ 'Custom',
+ ]);
expect(
getTabs(TestStubs.Organization({features: []})).map(tab => tab[1].name)
- ).toEqual(['All Unresolved', 'For Review', 'Ignored']);
+ ).toEqual(['All Unresolved', 'For Review', 'Ignored', 'Custom']);
});
it('should enable/disable my_teams filter in For Review tab', () => {
@@ -20,12 +27,14 @@ describe('getTabs', () => {
'is:unresolved',
'is:unresolved is:for_review assigned_or_suggested:[me, my_teams, none]',
'is:ignored',
+ '__custom__',
]);
expect(getTabs(TestStubs.Organization({features: []})).map(tab => tab[0])).toEqual([
'is:unresolved',
'is:unresolved is:for_review assigned_or_suggested:[me, none]',
'is:ignored',
+ '__custom__',
]);
});
});
diff --git a/static/app/views/issueList/utils.tsx b/static/app/views/issueList/utils.tsx
index d4047ed115bb0b..779d119d69a564 100644
--- a/static/app/views/issueList/utils.tsx
+++ b/static/app/views/issueList/utils.tsx
@@ -15,6 +15,8 @@ export enum Query {
REPROCESSING = 'is:reprocessing',
}
+export const CUSTOM_TAB_VALUE = '__custom__';
+
type OverviewTab = {
/**
* Emitted analytics event tab name
@@ -29,6 +31,7 @@ type OverviewTab = {
*/
enabled: boolean;
name: string;
+ hidden?: boolean;
/**
* Tooltip text to be hoverable when text has links
*/
@@ -128,6 +131,19 @@ export function getTabs(organization: Organization) {
tooltipHoverable: true,
},
],
+ [
+ // Hidden tab to account for custom queries that don't match any of the queries
+ // above. It's necessary because if Tabs's value doesn't match that of any tab item
+ // then Tabs will fall back to a default value, causing unexpected behaviors.
+ CUSTOM_TAB_VALUE,
+ {
+ name: t('Custom'),
+ analyticsName: 'custom',
+ hidden: true,
+ count: false,
+ enabled: true,
+ },
+ ],
];
return tabs.filter(([_query, tab]) => tab.enabled);