config.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import type {NavConfig, NavSidebarItem} from 'sentry/components/nav/utils';
  2. import {
  3. IconDashboard,
  4. IconGraph,
  5. IconIssues,
  6. IconLightning,
  7. IconProject,
  8. IconSearch,
  9. IconSettings,
  10. IconSiren,
  11. } from 'sentry/icons';
  12. import {t} from 'sentry/locale';
  13. import type {Organization} from 'sentry/types/organization';
  14. import {getDiscoverLandingUrl} from 'sentry/utils/discover/urls';
  15. import {MODULE_BASE_URLS} from 'sentry/views/insights/common/utils/useModuleURL';
  16. import {MODULE_SIDEBAR_TITLE as MODULE_TITLE_HTTP} from 'sentry/views/insights/http/settings';
  17. import {
  18. AI_LANDING_SUB_PATH,
  19. AI_LANDING_TITLE,
  20. } from 'sentry/views/insights/pages/ai/settings';
  21. import {
  22. BACKEND_LANDING_SUB_PATH,
  23. BACKEND_LANDING_TITLE,
  24. } from 'sentry/views/insights/pages/backend/settings';
  25. import {
  26. FRONTEND_LANDING_SUB_PATH,
  27. FRONTEND_LANDING_TITLE,
  28. } from 'sentry/views/insights/pages/frontend/settings';
  29. import {
  30. MOBILE_LANDING_SUB_PATH,
  31. MOBILE_LANDING_TITLE,
  32. } from 'sentry/views/insights/pages/mobile/settings';
  33. import {DOMAIN_VIEW_BASE_URL} from 'sentry/views/insights/pages/settings';
  34. import {INSIGHTS_BASE_URL, MODULE_TITLES} from 'sentry/views/insights/settings';
  35. import {getSearchForIssueGroup, IssueGroup} from 'sentry/views/issueList/utils';
  36. /**
  37. * Global nav settings for all Sentry users.
  38. * Links are generated per-organization with the proper `/organization/:slug/` prefix.
  39. *
  40. * To permission-gate certain items, include props to be passed to the `<Feature>` component
  41. */
  42. export function createNavConfig({organization}: {organization: Organization}): NavConfig {
  43. const prefix = `organizations/${organization.slug}`;
  44. const insightsPrefix = `${prefix}/${INSIGHTS_BASE_URL}`;
  45. const hasPerfDomainViews = organization.features.includes('insights-domain-view');
  46. const insights: NavSidebarItem = {
  47. label: t('Insights'),
  48. icon: <IconGraph />,
  49. feature: {features: 'insights-entry-points'},
  50. submenu: [
  51. {
  52. label: MODULE_TITLE_HTTP,
  53. to: `/${insightsPrefix}/${MODULE_BASE_URLS.http}/`,
  54. },
  55. {label: MODULE_TITLES.db, to: `/${insightsPrefix}/${MODULE_BASE_URLS.db}/`},
  56. {
  57. label: MODULE_TITLES.resource,
  58. to: `/${insightsPrefix}/${MODULE_BASE_URLS.resource}/`,
  59. },
  60. {
  61. label: MODULE_TITLES.app_start,
  62. to: `/${insightsPrefix}/${MODULE_BASE_URLS.app_start}/`,
  63. },
  64. {
  65. label: MODULE_TITLES['mobile-screens'],
  66. to: `/${insightsPrefix}/${MODULE_BASE_URLS['mobile-screens']}/`,
  67. feature: {features: 'insights-mobile-screens-module'},
  68. },
  69. {
  70. label: MODULE_TITLES.vital,
  71. to: `/${insightsPrefix}/${MODULE_BASE_URLS.vital}/`,
  72. },
  73. {
  74. label: MODULE_TITLES.cache,
  75. to: `/${insightsPrefix}/${MODULE_BASE_URLS.cache}/`,
  76. },
  77. {
  78. label: MODULE_TITLES.queue,
  79. to: `/${insightsPrefix}/${MODULE_BASE_URLS.queue}/`,
  80. },
  81. {
  82. label: MODULE_TITLES.ai,
  83. to: `/${insightsPrefix}/${MODULE_BASE_URLS.ai}/`,
  84. feature: {features: 'insights-entry-points'},
  85. },
  86. ],
  87. };
  88. const perf: NavSidebarItem = {
  89. label: t('Perf.'),
  90. to: '/performance/',
  91. icon: <IconLightning />,
  92. feature: {
  93. features: 'performance-view',
  94. hookName: 'feature-disabled:performance-sidebar-item',
  95. },
  96. };
  97. const perfDomainViews: NavSidebarItem = {
  98. label: t('Perf.'),
  99. icon: <IconLightning />,
  100. feature: {features: ['insights-domain-view', 'performance-view']},
  101. submenu: [
  102. {
  103. label: FRONTEND_LANDING_TITLE,
  104. to: `/${prefix}/${DOMAIN_VIEW_BASE_URL}/${FRONTEND_LANDING_SUB_PATH}/`,
  105. },
  106. {
  107. label: BACKEND_LANDING_TITLE,
  108. to: `/${prefix}/${DOMAIN_VIEW_BASE_URL}/${BACKEND_LANDING_SUB_PATH}/`,
  109. },
  110. {
  111. label: AI_LANDING_TITLE,
  112. to: `/${prefix}/${DOMAIN_VIEW_BASE_URL}/${AI_LANDING_SUB_PATH}/`,
  113. },
  114. {
  115. label: MOBILE_LANDING_TITLE,
  116. to: `/${prefix}/${DOMAIN_VIEW_BASE_URL}/${MOBILE_LANDING_SUB_PATH}/`,
  117. },
  118. ],
  119. };
  120. return {
  121. main: [
  122. {
  123. label: t('Issues'),
  124. icon: <IconIssues />,
  125. submenu: [
  126. {
  127. label: t('All'),
  128. to: `/${prefix}/issues/?query=is:unresolved`,
  129. },
  130. {
  131. label: t('Error & Outage'),
  132. to: `/${prefix}/issues/${getSearchForIssueGroup(IssueGroup.ERROR_OUTAGE)}`,
  133. },
  134. {
  135. label: t('Trend'),
  136. to: `/${prefix}/issues/${getSearchForIssueGroup(IssueGroup.TREND)}`,
  137. },
  138. {
  139. label: t('Craftsmanship'),
  140. to: `/${prefix}/issues/${getSearchForIssueGroup(IssueGroup.CRAFTSMANSHIP)}`,
  141. },
  142. {
  143. label: t('Security'),
  144. to: `/${prefix}/issues/${getSearchForIssueGroup(IssueGroup.SECURITY)}`,
  145. },
  146. {label: t('Feedback'), to: `/${prefix}/feedback/`},
  147. ],
  148. },
  149. {label: t('Projects'), to: `/${prefix}/projects/`, icon: <IconProject />},
  150. {
  151. label: t('Explore'),
  152. icon: <IconSearch />,
  153. submenu: [
  154. {
  155. label: t('Traces'),
  156. to: `/${prefix}/traces/`,
  157. feature: {features: 'performance-trace-explorer'},
  158. },
  159. {
  160. label: t('Metrics'),
  161. to: `/${prefix}/metrics/`,
  162. feature: {features: 'custom-metrics'},
  163. },
  164. {
  165. label: t('Profiles'),
  166. to: `/${prefix}/profiling/`,
  167. feature: {
  168. features: 'profiling',
  169. hookName: 'feature-disabled:profiling-sidebar-item',
  170. requireAll: false,
  171. },
  172. },
  173. {
  174. label: t('Replays'),
  175. to: `/${prefix}/replays/`,
  176. feature: {
  177. features: 'session-replay-ui',
  178. hookName: 'feature-disabled:replay-sidebar-item',
  179. },
  180. },
  181. {
  182. label: t('Discover'),
  183. to: getDiscoverLandingUrl(organization),
  184. feature: {
  185. features: 'discover-basic',
  186. hookName: 'feature-disabled:discover2-sidebar-item',
  187. },
  188. },
  189. {label: t('Releases'), to: `/${prefix}/releases/`},
  190. {label: t('Crons'), to: `/${prefix}/crons/`},
  191. ],
  192. },
  193. ...(hasPerfDomainViews ? [perfDomainViews, perf] : [insights, perf]),
  194. {
  195. label: t('Boards'),
  196. to: '/dashboards/',
  197. icon: <IconDashboard />,
  198. feature: {
  199. features: ['discover', 'discover-query', 'dashboards-basic', 'dashboards-edit'],
  200. hookName: 'feature-disabled:dashboards-sidebar-item',
  201. requireAll: false,
  202. },
  203. },
  204. {label: t('Alerts'), to: `/${prefix}/alerts/rules/`, icon: <IconSiren />},
  205. ],
  206. footer: [
  207. {
  208. label: t('Settings'),
  209. to: `/settings/${organization.slug}/`,
  210. icon: <IconSettings />,
  211. },
  212. ],
  213. };
  214. }