import ExternalLink from 'sentry/components/links/externalLink';
import {t, tct} from 'sentry/locale';
import {Organization} from 'sentry/types';
export enum Query {
FOR_REVIEW = 'is:unresolved is:for_review assigned_or_suggested:[me, none]',
UNRESOLVED = 'is:unresolved',
IGNORED = 'is:ignored',
REPROCESSING = 'is:reprocessing',
}
type OverviewTab = {
/**
* Emitted analytics event tab name
*/
analyticsName: string;
/**
* Will fetch a count to display on this tab
*/
count: boolean;
/**
* Tabs can be disabled via flag
*/
enabled: boolean;
name: string;
/**
* Tooltip text to be hoverable when text has links
*/
tooltipHoverable?: boolean;
/**
* Tooltip text for each tab
*/
tooltipTitle?: React.ReactNode;
};
/**
* Get a list of currently active tabs
*/
export function getTabs(organization: Organization) {
const tabs: Array<[string, OverviewTab]> = [
[
Query.UNRESOLVED,
{
name: t('All Unresolved'),
analyticsName: 'unresolved',
count: true,
enabled: true,
},
],
[
Query.FOR_REVIEW,
{
name: t('For Review'),
analyticsName: 'needs_review',
count: true,
enabled: true,
tooltipTitle:
t(`Issues are marked for review when they are created, unresolved, or unignored.
Mark an issue reviewed to move it out of this list.
Issues are automatically marked reviewed in 7 days.`),
},
],
[
Query.IGNORED,
{
name: t('Ignored'),
analyticsName: 'ignored',
count: true,
enabled: true,
tooltipTitle: t(`Ignored issues don’t trigger alerts. When their ignore
conditions are met they become Unresolved and are flagged for review.`),
},
],
[
Query.REPROCESSING,
{
name: t('Reprocessing'),
analyticsName: 'reprocessing',
count: true,
enabled: organization.features.includes('reprocessing-v2'),
tooltipTitle: tct(
`These [link:reprocessing issues] will take some time to complete.
Any new issues that are created during reprocessing will be flagged for review.`,
{
link: (
),
}
),
tooltipHoverable: true,
},
],
];
return tabs.filter(([_query, tab]) => tab.enabled);
}
/**
* @returns queries that should have counts fetched
*/
export function getTabsWithCounts(organization: Organization) {
const tabs = getTabs(organization);
return tabs.filter(([_query, tab]) => tab.count).map(([query]) => query);
}
export function isForReviewQuery(query: string | undefined) {
return !!query && /\bis:for_review\b/.test(query);
}
// the tab counts will look like 99+
export const TAB_MAX_COUNT = 99;
type QueryCount = {
count: number;
hasMore: boolean;
};
export type QueryCounts = Partial>;
export enum IssueSortOptions {
DATE = 'date',
NEW = 'new',
PRIORITY = 'priority',
FREQ = 'freq',
USER = 'user',
TREND = 'trend',
INBOX = 'inbox',
}
export function getSortLabel(key: string) {
switch (key) {
case IssueSortOptions.NEW:
return t('First Seen');
case IssueSortOptions.PRIORITY:
return t('Priority');
case IssueSortOptions.FREQ:
return t('Events');
case IssueSortOptions.USER:
return t('Users');
case IssueSortOptions.TREND:
return t('Relative Change');
case IssueSortOptions.INBOX:
return t('Date Added');
case IssueSortOptions.DATE:
default:
return t('Last Seen');
}
}
export const DISCOVER_EXCLUSION_FIELDS: string[] = [
'query',
'status',
'bookmarked_by',
'assigned',
'assigned_to',
'unassigned',
'subscribed_by',
'active_at',
'first_release',
'first_seen',
'is',
'__text',
];