123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- import ExternalLink from 'sentry/components/links/externalLink';
- import {DEFAULT_QUERY, NEW_DEFAULT_QUERY} from 'sentry/constants';
- import {t, tct} from 'sentry/locale';
- import type {Organization} from 'sentry/types/organization';
- export enum Query {
- FOR_REVIEW = 'is:unresolved is:for_review assigned_or_suggested:[me, my_teams, none]',
- // biome-ignore lint/style/useLiteralEnumMembers: Disable for maintenance cost.
- PRIORITIZED = NEW_DEFAULT_QUERY,
- UNRESOLVED = 'is:unresolved',
- IGNORED = 'is:ignored',
- NEW = 'is:new',
- ARCHIVED = 'is:archived',
- ESCALATING = 'is:escalating',
- REGRESSED = 'is:regressed',
- REPROCESSING = 'is:reprocessing',
- }
- export const CUSTOM_TAB_VALUE = '__custom__';
- 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;
- hidden?: boolean;
- /**
- * 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 hasIssuePriority = organization.features.includes('issue-priority-ui');
- const tabs: Array<[string, OverviewTab]> = [
- [
- Query.PRIORITIZED,
- {
- name: t('Prioritized'),
- analyticsName: 'prioritized',
- count: true,
- enabled: hasIssuePriority,
- },
- ],
- [
- Query.UNRESOLVED,
- {
- name: t('Unresolved'),
- analyticsName: 'unresolved',
- count: true,
- enabled: !hasIssuePriority,
- },
- ],
- [
- Query.FOR_REVIEW,
- {
- name: t('For Review'),
- analyticsName: 'needs_review',
- count: true,
- enabled: true,
- tooltipTitle: t(
- 'Issues are marked for review if they are new or escalating, and have not been resolved or archived. Issues are automatically marked reviewed in 7 days.'
- ),
- },
- ],
- [
- Query.REGRESSED,
- {
- name: t('Regressed'),
- analyticsName: 'regressed',
- count: true,
- enabled: true,
- },
- ],
- [
- Query.ESCALATING,
- {
- name: t('Escalating'),
- analyticsName: 'escalating',
- count: true,
- enabled: true,
- },
- ],
- [
- Query.ARCHIVED,
- {
- name: t('Archived'),
- analyticsName: 'archived',
- count: true,
- enabled: true,
- },
- ],
- [
- Query.IGNORED,
- {
- name: t('Ignored'),
- analyticsName: 'ignored',
- count: true,
- enabled: false,
- 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: true,
- 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: (
- <ExternalLink href="https://docs.sentry.io/product/error-monitoring/reprocessing/" />
- ),
- }
- ),
- 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);
- }
- /**
- * @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<Record<Query, QueryCount>>;
- export enum IssueSortOptions {
- DATE = 'date',
- NEW = 'new',
- TRENDS = 'trends',
- FREQ = 'freq',
- USER = 'user',
- INBOX = 'inbox',
- }
- export const DEFAULT_ISSUE_STREAM_SORT = IssueSortOptions.DATE;
- export function isDefaultIssueStreamSearch(
- {query, sort}: {query: string; sort: string},
- {organization}: {organization: Organization}
- ) {
- const defaultQuery = organization.features.includes('issue-priority-ui')
- ? NEW_DEFAULT_QUERY
- : DEFAULT_QUERY;
- return query === defaultQuery && sort === DEFAULT_ISSUE_STREAM_SORT;
- }
- export function getSortLabel(key: string) {
- switch (key) {
- case IssueSortOptions.NEW:
- return t('First Seen');
- case IssueSortOptions.TRENDS:
- return t('Trends');
- case IssueSortOptions.FREQ:
- return t('Events');
- case IssueSortOptions.USER:
- return t('Users');
- 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',
- ];
- export const FOR_REVIEW_QUERIES: string[] = [Query.FOR_REVIEW];
- export const SAVED_SEARCHES_SIDEBAR_OPEN_LOCALSTORAGE_KEY =
- 'issue-stream-saved-searches-sidebar-open';
|