routes.tsx 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937
  1. import * as React from 'react';
  2. import {
  3. EnterHook,
  4. IndexRedirect,
  5. IndexRoute as BaseIndexRoute,
  6. IndexRouteProps,
  7. Redirect,
  8. Route as BaseRoute,
  9. RouteProps,
  10. } from 'react-router';
  11. import LazyLoad from 'app/components/lazyLoad';
  12. import {EXPERIMENTAL_SPA} from 'app/constants';
  13. import {t} from 'app/locale';
  14. import HookStore from 'app/stores/hookStore';
  15. import {HookName} from 'app/types/hooks';
  16. import errorHandler from 'app/utils/errorHandler';
  17. import App from 'app/views/app';
  18. import AuthLayout from 'app/views/auth/layout';
  19. import IssueListContainer from 'app/views/issueList/container';
  20. import IssueListOverview from 'app/views/issueList/overview';
  21. import OrganizationContext from 'app/views/organizationContext';
  22. import OrganizationDetails, {
  23. LightWeightOrganizationDetails,
  24. } from 'app/views/organizationDetails';
  25. import {TAB} from 'app/views/organizationGroupDetails/header';
  26. import OrganizationRoot from 'app/views/organizationRoot';
  27. import ProjectEventRedirect from 'app/views/projectEventRedirect';
  28. import redirectDeprecatedProjectRoute from 'app/views/projects/redirectDeprecatedProjectRoute';
  29. import RouteNotFound from 'app/views/routeNotFound';
  30. import SettingsProjectProvider from 'app/views/settings/components/settingsProjectProvider';
  31. import SettingsWrapper from 'app/views/settings/components/settingsWrapper';
  32. const appendTrailingSlash: EnterHook = (nextState, replace) => {
  33. const lastChar = nextState.location.pathname.slice(-1);
  34. if (lastChar !== '/') {
  35. replace(nextState.location.pathname + '/');
  36. }
  37. };
  38. type CustomProps = {
  39. name?: string;
  40. componentPromise?: () => Promise<any>;
  41. };
  42. /**
  43. * We add some additional props to our routes
  44. */
  45. const Route = BaseRoute as React.ComponentClass<RouteProps & CustomProps>;
  46. const IndexRoute = BaseIndexRoute as React.ComponentClass<IndexRouteProps & CustomProps>;
  47. type ComponentCallback = Parameters<NonNullable<RouteProps['getComponent']>>[1];
  48. /**
  49. * Use react-router to lazy load a route. Use this for codesplitting containers (e.g. SettingsLayout)
  50. *
  51. * The method for lazy loading a route leaf node is using the <LazyLoad> component + `componentPromise`.
  52. * The reason for this is because react-router handles the route tree better and if we use <LazyLoad> it will end
  53. * up having to re-render more components than necessary.
  54. */
  55. const lazyLoad = (cb: ComponentCallback) => (m: {default: any}) => cb(null, m.default);
  56. const hook = (name: HookName) => HookStore.get(name).map(cb => cb());
  57. function routes() {
  58. const accountSettingsRoutes = (
  59. <React.Fragment>
  60. <IndexRedirect to="details/" />
  61. <Route
  62. path="details/"
  63. name="Details"
  64. componentPromise={() => import('app/views/settings/account/accountDetails')}
  65. component={errorHandler(LazyLoad)}
  66. />
  67. <Route path="notifications/" name="Notifications">
  68. <IndexRoute
  69. componentPromise={() =>
  70. import('app/views/settings/account/accountNotifications')
  71. }
  72. component={errorHandler(LazyLoad)}
  73. />
  74. <Route
  75. path=":fineTuneType/"
  76. name="Fine Tune Alerts"
  77. componentPromise={() =>
  78. import('app/views/settings/account/accountNotificationFineTuning')
  79. }
  80. component={errorHandler(LazyLoad)}
  81. />
  82. </Route>
  83. <Route
  84. path="emails/"
  85. name="Emails"
  86. componentPromise={() => import('app/views/settings/account/accountEmails')}
  87. component={errorHandler(LazyLoad)}
  88. />
  89. <Route
  90. path="authorizations/"
  91. componentPromise={() =>
  92. import('app/views/settings/account/accountAuthorizations')
  93. }
  94. component={errorHandler(LazyLoad)}
  95. />
  96. <Route name="Security" path="security/">
  97. <Route
  98. componentPromise={() =>
  99. import('app/views/settings/account/accountSecurity/accountSecurityWrapper')
  100. }
  101. component={errorHandler(LazyLoad)}
  102. >
  103. <IndexRoute
  104. componentPromise={() => import('app/views/settings/account/accountSecurity')}
  105. component={errorHandler(LazyLoad)}
  106. />
  107. <Route
  108. path="session-history/"
  109. name="Session History"
  110. componentPromise={() =>
  111. import('app/views/settings/account/accountSecurity/sessionHistory')
  112. }
  113. component={errorHandler(LazyLoad)}
  114. />
  115. <Route
  116. path="mfa/:authId/"
  117. name="Details"
  118. componentPromise={() =>
  119. import('app/views/settings/account/accountSecurity/accountSecurityDetails')
  120. }
  121. component={errorHandler(LazyLoad)}
  122. />
  123. </Route>
  124. <Route
  125. path="mfa/:authId/enroll/"
  126. name="Enroll"
  127. componentPromise={() =>
  128. import('app/views/settings/account/accountSecurity/accountSecurityEnroll')
  129. }
  130. component={errorHandler(LazyLoad)}
  131. />
  132. </Route>
  133. <Route
  134. path="subscriptions/"
  135. name="Subscriptions"
  136. componentPromise={() => import('app/views/settings/account/accountSubscriptions')}
  137. component={errorHandler(LazyLoad)}
  138. />
  139. <Route
  140. path="identities/"
  141. name="Identities"
  142. componentPromise={() => import('app/views/settings/account/accountIdentities')}
  143. component={errorHandler(LazyLoad)}
  144. />
  145. <Route path="api/" name="API">
  146. <IndexRedirect to="auth-tokens/" />
  147. <Route path="auth-tokens/" name="Auth Tokens">
  148. <IndexRoute
  149. componentPromise={() => import('app/views/settings/account/apiTokens')}
  150. component={errorHandler(LazyLoad)}
  151. />
  152. <Route
  153. path="new-token/"
  154. name="Create New Token"
  155. componentPromise={() => import('app/views/settings/account/apiNewToken')}
  156. component={errorHandler(LazyLoad)}
  157. />
  158. </Route>
  159. <Route path="applications/" name="Applications">
  160. <IndexRoute
  161. componentPromise={() => import('app/views/settings/account/apiApplications')}
  162. component={errorHandler(LazyLoad)}
  163. />
  164. <Route
  165. path=":appId/"
  166. name="Details"
  167. componentPromise={() =>
  168. import('app/views/settings/account/apiApplications/details')
  169. }
  170. component={errorHandler(LazyLoad)}
  171. />
  172. </Route>
  173. {hook('routes:api')}
  174. </Route>
  175. <Route
  176. path="close-account/"
  177. name="Close Account"
  178. componentPromise={() => import('app/views/settings/account/accountClose')}
  179. component={errorHandler(LazyLoad)}
  180. />
  181. </React.Fragment>
  182. );
  183. const projectSettingsRoutes = (
  184. <React.Fragment>
  185. <IndexRoute
  186. name="General"
  187. componentPromise={() => import('app/views/settings/projectGeneralSettings')}
  188. component={errorHandler(LazyLoad)}
  189. />
  190. <Route
  191. path="teams/"
  192. name="Teams"
  193. componentPromise={() => import('app/views/settings/project/projectTeams')}
  194. component={errorHandler(LazyLoad)}
  195. />
  196. <Route
  197. name="Alerts"
  198. path="alerts/"
  199. component={errorHandler(LazyLoad)}
  200. componentPromise={() => import('app/views/settings/projectAlerts')}
  201. >
  202. <IndexRoute
  203. component={errorHandler(LazyLoad)}
  204. componentPromise={() => import('app/views/settings/projectAlerts/settings')}
  205. />
  206. <Redirect from="new/" to="/organizations/:orgId/alerts/:projectId/new/" />
  207. <Redirect from="rules/" to="/organizations/:orgId/alerts/rules/" />
  208. <Redirect from="rules/new/" to="/organizations/:orgId/alerts/:projectId/new/" />
  209. <Redirect
  210. from="metric-rules/new/"
  211. to="/organizations/:orgId/alerts/:projectId/new/"
  212. />
  213. <Redirect
  214. from="rules/:ruleId/"
  215. to="/organizations/:orgId/alerts/rules/:projectId/:ruleId/"
  216. />
  217. <Redirect
  218. from="metric-rules/:ruleId/"
  219. to="/organizations/:orgId/alerts/metric-rules/:projectId/:ruleId/"
  220. />
  221. </Route>
  222. <Route
  223. name="Environments"
  224. path="environments/"
  225. componentPromise={() => import('app/views/settings/project/projectEnvironments')}
  226. component={errorHandler(LazyLoad)}
  227. >
  228. <IndexRoute />
  229. <Route path="hidden/" />
  230. </Route>
  231. <Route
  232. name="Tags"
  233. path="tags/"
  234. componentPromise={() => import('app/views/settings/projectTags')}
  235. component={errorHandler(LazyLoad)}
  236. />
  237. <Redirect from="issue-tracking/" to="/settings/:orgId/:projectId/plugins/" />
  238. <Route
  239. path="release-tracking/"
  240. name="Release Tracking"
  241. componentPromise={() =>
  242. import('app/views/settings/project/projectReleaseTracking')
  243. }
  244. component={errorHandler(LazyLoad)}
  245. />
  246. <Route
  247. path="ownership/"
  248. name="Issue Owners"
  249. componentPromise={() => import('app/views/settings/project/projectOwnership')}
  250. component={errorHandler(LazyLoad)}
  251. />
  252. <Route
  253. path="data-forwarding/"
  254. name="Data Forwarding"
  255. componentPromise={() => import('app/views/settings/projectDataForwarding')}
  256. component={errorHandler(LazyLoad)}
  257. />
  258. <Route
  259. name={t('Security & Privacy')}
  260. path="security-and-privacy/"
  261. component={errorHandler(LazyLoad)}
  262. componentPromise={() => import('app/views/settings/projectSecurityAndPrivacy')}
  263. />
  264. <Route
  265. path="debug-symbols/"
  266. name="Debug Information Files"
  267. componentPromise={() => import('app/views/settings/projectDebugFiles')}
  268. component={errorHandler(LazyLoad)}
  269. />
  270. <Route
  271. path="proguard/"
  272. name={t('ProGuard Mappings')}
  273. componentPromise={() => import('app/views/settings/projectProguard')}
  274. component={errorHandler(LazyLoad)}
  275. />
  276. <Route
  277. path="performance/"
  278. name={t('Performance')}
  279. componentPromise={() => import('app/views/settings/projectPerformance')}
  280. component={errorHandler(LazyLoad)}
  281. />
  282. <Route
  283. path="source-maps/"
  284. name={t('Source Maps')}
  285. componentPromise={() => import('app/views/settings/projectSourceMaps')}
  286. component={errorHandler(LazyLoad)}
  287. >
  288. <IndexRoute
  289. componentPromise={() => import('app/views/settings/projectSourceMaps/list')}
  290. component={errorHandler(LazyLoad)}
  291. />
  292. <Route
  293. path=":name/"
  294. name={t('Archive')}
  295. componentPromise={() => import('app/views/settings/projectSourceMaps/detail')}
  296. component={errorHandler(LazyLoad)}
  297. />
  298. </Route>
  299. <Route
  300. path="processing-issues/"
  301. name="Processing Issues"
  302. componentPromise={() =>
  303. import('app/views/settings/project/projectProcessingIssues')
  304. }
  305. component={errorHandler(LazyLoad)}
  306. />
  307. <Route
  308. path="filters/"
  309. name="Inbound Filters"
  310. componentPromise={() => import('app/views/settings/project/projectFilters')}
  311. component={errorHandler(LazyLoad)}
  312. >
  313. <IndexRedirect to="data-filters/" />
  314. <Route path=":filterType/" />
  315. </Route>
  316. <Route
  317. name={t('Filters & Sampling')}
  318. path="filters-and-sampling/"
  319. componentPromise={() => import('app/views/settings/project/filtersAndSampling')}
  320. component={errorHandler(LazyLoad)}
  321. />
  322. <Route
  323. path="issue-grouping/"
  324. name={t('Issue Grouping')}
  325. componentPromise={() => import('app/views/settings/projectIssueGrouping')}
  326. component={errorHandler(LazyLoad)}
  327. />
  328. <Route
  329. path="hooks/"
  330. name="Service Hooks"
  331. componentPromise={() => import('app/views/settings/project/projectServiceHooks')}
  332. component={errorHandler(LazyLoad)}
  333. />
  334. <Route
  335. path="hooks/new/"
  336. name="Create Service Hook"
  337. componentPromise={() =>
  338. import('app/views/settings/project/projectCreateServiceHook')
  339. }
  340. component={errorHandler(LazyLoad)}
  341. />
  342. <Route
  343. path="hooks/:hookId/"
  344. name="Service Hook Details"
  345. componentPromise={() =>
  346. import('app/views/settings/project/projectServiceHookDetails')
  347. }
  348. component={errorHandler(LazyLoad)}
  349. />
  350. <Route path="keys/" name="Client Keys">
  351. <IndexRoute
  352. componentPromise={() => import('app/views/settings/project/projectKeys/list')}
  353. component={errorHandler(LazyLoad)}
  354. />
  355. <Route
  356. path=":keyId/"
  357. name="Details"
  358. componentPromise={() =>
  359. import('app/views/settings/project/projectKeys/details')
  360. }
  361. component={errorHandler(LazyLoad)}
  362. />
  363. </Route>
  364. <Route
  365. path="user-feedback/"
  366. name="User Feedback"
  367. componentPromise={() => import('app/views/settings/project/projectUserFeedback')}
  368. component={errorHandler(LazyLoad)}
  369. />
  370. <Redirect from="csp/" to="security-headers/" />
  371. <Route path="security-headers/" name="Security Headers">
  372. <IndexRoute
  373. componentPromise={() => import('app/views/settings/projectSecurityHeaders')}
  374. component={errorHandler(LazyLoad)}
  375. />
  376. <Route
  377. path="csp/"
  378. name="Content Security Policy"
  379. componentPromise={() => import('app/views/settings/projectSecurityHeaders/csp')}
  380. component={errorHandler(LazyLoad)}
  381. />
  382. <Route
  383. path="expect-ct/"
  384. name="Certificate Transparency"
  385. componentPromise={() =>
  386. import('app/views/settings/projectSecurityHeaders/expectCt')
  387. }
  388. component={errorHandler(LazyLoad)}
  389. />
  390. <Route
  391. path="hpkp/"
  392. name="HPKP"
  393. componentPromise={() =>
  394. import('app/views/settings/projectSecurityHeaders/hpkp')
  395. }
  396. component={errorHandler(LazyLoad)}
  397. />
  398. </Route>
  399. <Route path="plugins/" name="Legacy Integrations">
  400. <IndexRoute
  401. componentPromise={() => import('app/views/settings/projectPlugins')}
  402. component={errorHandler(LazyLoad)}
  403. />
  404. <Route
  405. path=":pluginId/"
  406. name="Integration Details"
  407. componentPromise={() => import('app/views/settings/projectPlugins/details')}
  408. component={errorHandler(LazyLoad)}
  409. />
  410. </Route>
  411. <Route path="install/" name="Configuration">
  412. <IndexRoute
  413. componentPromise={() => import('app/views/projectInstall/overview')}
  414. component={errorHandler(LazyLoad)}
  415. />
  416. <Route
  417. path=":platform/"
  418. name="Docs"
  419. componentPromise={() =>
  420. import('app/views/projectInstall/platformOrIntegration')
  421. }
  422. component={errorHandler(LazyLoad)}
  423. />
  424. </Route>
  425. </React.Fragment>
  426. );
  427. // This is declared in the routes() function because some routes need the
  428. // hook store which is not available at import time.
  429. const orgSettingsRoutes = (
  430. <React.Fragment>
  431. <IndexRoute
  432. name="General"
  433. componentPromise={() => import('app/views/settings/organizationGeneralSettings')}
  434. component={errorHandler(LazyLoad)}
  435. />
  436. <Route
  437. path="projects/"
  438. name="Projects"
  439. componentPromise={() => import('app/views/settings/organizationProjects')}
  440. component={errorHandler(LazyLoad)}
  441. />
  442. <Route path="api-keys/" name="API Key">
  443. <IndexRoute
  444. componentPromise={() => import('app/views/settings/organizationApiKeys')}
  445. component={errorHandler(LazyLoad)}
  446. />
  447. <Route
  448. path=":apiKey/"
  449. name="Details"
  450. componentPromise={() =>
  451. import('app/views/settings/organizationApiKeys/organizationApiKeyDetails')
  452. }
  453. component={errorHandler(LazyLoad)}
  454. />
  455. </Route>
  456. <Route
  457. path="audit-log/"
  458. name="Audit Log"
  459. componentPromise={() => import('app/views/settings/organizationAuditLog')}
  460. component={errorHandler(LazyLoad)}
  461. />
  462. <Route
  463. path="auth/"
  464. name="Auth Providers"
  465. componentPromise={() => import('app/views/settings/organizationAuth')}
  466. component={errorHandler(LazyLoad)}
  467. />
  468. <Route path="members/" name="Members">
  469. <Route
  470. componentPromise={() =>
  471. import('app/views/settings/organizationMembers/organizationMembersWrapper')
  472. }
  473. component={errorHandler(LazyLoad)}
  474. >
  475. <IndexRoute
  476. componentPromise={() =>
  477. import('app/views/settings/organizationMembers/organizationMembersList')
  478. }
  479. component={errorHandler(LazyLoad)}
  480. />
  481. <Route
  482. path="requests/"
  483. name="Requests"
  484. componentPromise={() =>
  485. import('app/views/settings/organizationMembers/organizationRequestsView')
  486. }
  487. component={errorHandler(LazyLoad)}
  488. />
  489. </Route>
  490. <Route
  491. path=":memberId/"
  492. name="Details"
  493. componentPromise={() =>
  494. import('app/views/settings/organizationMembers/organizationMemberDetail')
  495. }
  496. component={errorHandler(LazyLoad)}
  497. />
  498. </Route>
  499. <Route
  500. path="rate-limits/"
  501. name="Rate Limits"
  502. componentPromise={() => import('app/views/settings/organizationRateLimits')}
  503. component={errorHandler(LazyLoad)}
  504. />
  505. <Route
  506. name={t('Relay')}
  507. path="relay/"
  508. componentPromise={() => import('app/views/settings/organizationRelay')}
  509. component={errorHandler(LazyLoad)}
  510. />
  511. <Route
  512. path="repos/"
  513. name="Repositories"
  514. componentPromise={() => import('app/views/settings/organizationRepositories')}
  515. component={errorHandler(LazyLoad)}
  516. />
  517. <Route
  518. path="performance/"
  519. name={t('Performance')}
  520. componentPromise={() => import('app/views/settings/organizationPerformance')}
  521. component={errorHandler(LazyLoad)}
  522. />
  523. <Route
  524. path="settings/"
  525. componentPromise={() => import('app/views/settings/organizationGeneralSettings')}
  526. component={errorHandler(LazyLoad)}
  527. />
  528. <Route
  529. name={t('Security & Privacy')}
  530. path="security-and-privacy/"
  531. componentPromise={() =>
  532. import('app/views/settings/organizationSecurityAndPrivacy')
  533. }
  534. component={errorHandler(LazyLoad)}
  535. />
  536. <Route name="Teams" path="teams/">
  537. <IndexRoute
  538. componentPromise={() => import('app/views/settings/organizationTeams')}
  539. component={errorHandler(LazyLoad)}
  540. />
  541. <Route
  542. name="Team"
  543. path=":teamId/"
  544. componentPromise={() =>
  545. import('app/views/settings/organizationTeams/teamDetails')
  546. }
  547. component={errorHandler(LazyLoad)}
  548. >
  549. <IndexRedirect to="members/" />
  550. <Route
  551. path="members/"
  552. name="Members"
  553. componentPromise={() =>
  554. import('app/views/settings/organizationTeams/teamMembers')
  555. }
  556. component={errorHandler(LazyLoad)}
  557. />
  558. <Route
  559. path="projects/"
  560. name="Projects"
  561. componentPromise={() =>
  562. import('app/views/settings/organizationTeams/teamProjects')
  563. }
  564. component={errorHandler(LazyLoad)}
  565. />
  566. <Route
  567. path="settings/"
  568. name="settings"
  569. componentPromise={() =>
  570. import('app/views/settings/organizationTeams/teamSettings')
  571. }
  572. component={errorHandler(LazyLoad)}
  573. />
  574. </Route>
  575. </Route>
  576. <Redirect from="plugins/" to="integrations/" />
  577. <Route name="Integrations" path="plugins/">
  578. <Route
  579. name="Integration Details"
  580. path=":integrationSlug/"
  581. componentPromise={() =>
  582. import('app/views/organizationIntegrations/pluginDetailedView')
  583. }
  584. component={errorHandler(LazyLoad)}
  585. />
  586. </Route>
  587. <Redirect from="sentry-apps/" to="integrations/" />
  588. <Route name="Integrations" path="sentry-apps/">
  589. <Route
  590. name="Details"
  591. path=":integrationSlug"
  592. componentPromise={() =>
  593. import('app/views/organizationIntegrations/sentryAppDetailedView')
  594. }
  595. component={errorHandler(LazyLoad)}
  596. />
  597. </Route>
  598. <Redirect from="document-integrations/" to="integrations/" />
  599. <Route name="Integrations" path="document-integrations/">
  600. <Route
  601. name="Details"
  602. path=":integrationSlug"
  603. componentPromise={() =>
  604. import('app/views/organizationIntegrations/docIntegrationDetailedView')
  605. }
  606. component={errorHandler(LazyLoad)}
  607. />
  608. </Route>
  609. <Route name="Integrations" path="integrations/">
  610. <IndexRoute
  611. componentPromise={() =>
  612. import('app/views/organizationIntegrations/integrationListDirectory')
  613. }
  614. component={errorHandler(LazyLoad)}
  615. />
  616. <Route
  617. name="Integration Details"
  618. path=":integrationSlug"
  619. componentPromise={() =>
  620. import('app/views/organizationIntegrations/integrationDetailedView')
  621. }
  622. component={errorHandler(LazyLoad)}
  623. />
  624. <Route
  625. name="Configure Integration"
  626. path=":providerKey/:integrationId/"
  627. componentPromise={() =>
  628. import('app/views/settings/organizationIntegrations/configureIntegration')
  629. }
  630. component={errorHandler(LazyLoad)}
  631. />
  632. </Route>
  633. <Route name="Developer Settings" path="developer-settings/">
  634. <IndexRoute
  635. componentPromise={() =>
  636. import('app/views/settings/organizationDeveloperSettings')
  637. }
  638. component={errorHandler(LazyLoad)}
  639. />
  640. <Route
  641. name="New Public Integration"
  642. path="new-public/"
  643. componentPromise={() =>
  644. import(
  645. 'app/views/settings/organizationDeveloperSettings/sentryApplicationDetails'
  646. )
  647. }
  648. component={errorHandler(LazyLoad)}
  649. />
  650. <Route
  651. name="New Internal Integration"
  652. path="new-internal/"
  653. componentPromise={() =>
  654. import(
  655. 'app/views/settings/organizationDeveloperSettings/sentryApplicationDetails'
  656. )
  657. }
  658. component={errorHandler(LazyLoad)}
  659. />
  660. <Route
  661. name="Edit Integration"
  662. path=":appSlug/"
  663. componentPromise={() =>
  664. import(
  665. 'app/views/settings/organizationDeveloperSettings/sentryApplicationDetails'
  666. )
  667. }
  668. component={errorHandler(LazyLoad)}
  669. />
  670. <Route
  671. name="Integration Dashboard"
  672. path=":appSlug/dashboard/"
  673. componentPromise={() =>
  674. import(
  675. 'app/views/settings/organizationDeveloperSettings/sentryApplicationDashboard'
  676. )
  677. }
  678. component={errorHandler(LazyLoad)}
  679. />
  680. </Route>
  681. </React.Fragment>
  682. );
  683. return (
  684. <Route>
  685. {EXPERIMENTAL_SPA && (
  686. <Route path="/auth/login/" component={errorHandler(AuthLayout)}>
  687. <IndexRoute
  688. componentPromise={() => import('app/views/auth/login')}
  689. component={errorHandler(LazyLoad)}
  690. />
  691. </Route>
  692. )}
  693. <Route path="/" component={errorHandler(App)}>
  694. <IndexRoute
  695. componentPromise={() => import('app/views/app/root')}
  696. component={errorHandler(LazyLoad)}
  697. />
  698. <Route
  699. path="/accept/:memberId/:token/"
  700. componentPromise={() => import('app/views/acceptOrganizationInvite')}
  701. component={errorHandler(LazyLoad)}
  702. />
  703. <Route
  704. path="/accept-transfer/"
  705. componentPromise={() => import('app/views/acceptProjectTransfer')}
  706. component={errorHandler(LazyLoad)}
  707. />
  708. <Route
  709. path="/extensions/external-install/:integrationSlug/:installationId"
  710. componentPromise={() => import('app/views/integrationOrganizationLink')}
  711. component={errorHandler(LazyLoad)}
  712. />
  713. <Route
  714. path="/extensions/:integrationSlug/link/"
  715. getComponent={(_loc, cb) =>
  716. import('app/views/integrationOrganizationLink').then(lazyLoad(cb))
  717. }
  718. />
  719. <Route
  720. path="/sentry-apps/:sentryAppSlug/external-install/"
  721. componentPromise={() => import('app/views/sentryAppExternalInstallation')}
  722. component={errorHandler(LazyLoad)}
  723. />
  724. <Redirect from="/account/" to="/settings/account/details/" />
  725. <Redirect from="/share/group/:shareId/" to="/share/issue/:shareId/" />
  726. <Route
  727. path="/share/issue/:shareId/"
  728. componentPromise={() => import('app/views/sharedGroupDetails')}
  729. component={errorHandler(LazyLoad)}
  730. />
  731. <Route
  732. path="/organizations/new/"
  733. componentPromise={() => import('app/views/organizationCreate')}
  734. component={errorHandler(LazyLoad)}
  735. />
  736. <Route
  737. path="/organizations/:orgId/data-export/:dataExportId"
  738. componentPromise={() => import('app/views/dataExport/dataDownload')}
  739. component={errorHandler(LazyLoad)}
  740. />
  741. <Route
  742. path="/organizations/:orgId/disabled-member/"
  743. componentPromise={() => import('app/views/disabledMember')}
  744. component={errorHandler(LazyLoad)}
  745. />
  746. <Route
  747. path="/join-request/:orgId/"
  748. componentPromise={() => import('app/views/organizationJoinRequest')}
  749. component={errorHandler(LazyLoad)}
  750. />
  751. <Route path="/onboarding/:orgId/" component={errorHandler(OrganizationContext)}>
  752. <IndexRedirect to="welcome/" />
  753. <Route
  754. path=":step/"
  755. componentPromise={() => import('app/views/onboarding/onboarding')}
  756. component={errorHandler(LazyLoad)}
  757. />
  758. </Route>
  759. {/* Settings routes */}
  760. <Route component={errorHandler(OrganizationDetails)}>
  761. <Route path="/settings/" name="Settings" component={SettingsWrapper}>
  762. <IndexRoute
  763. getComponent={(_loc, cb) =>
  764. import('app/views/settings/settingsIndex').then(lazyLoad(cb))
  765. }
  766. />
  767. <Route
  768. path="account/"
  769. name="Account"
  770. getComponent={(_loc, cb) =>
  771. import('app/views/settings/account/accountSettingsLayout').then(
  772. lazyLoad(cb)
  773. )
  774. }
  775. >
  776. {accountSettingsRoutes}
  777. </Route>
  778. <Route name="Organization" path=":orgId/">
  779. <Route
  780. getComponent={(_loc, cb) =>
  781. import(
  782. 'app/views/settings/organization/organizationSettingsLayout'
  783. ).then(lazyLoad(cb))
  784. }
  785. >
  786. {hook('routes:organization')}
  787. {orgSettingsRoutes}
  788. </Route>
  789. <Route
  790. name="Project"
  791. path="projects/:projectId/"
  792. getComponent={(_loc, cb) =>
  793. import('app/views/settings/project/projectSettingsLayout').then(
  794. lazyLoad(cb)
  795. )
  796. }
  797. >
  798. <Route component={errorHandler(SettingsProjectProvider)}>
  799. {projectSettingsRoutes}
  800. </Route>
  801. </Route>
  802. <Redirect from=":projectId/" to="projects/:projectId/" />
  803. <Redirect from=":projectId/alerts/" to="projects/:projectId/alerts/" />
  804. <Redirect
  805. from=":projectId/alerts/rules/"
  806. to="projects/:projectId/alerts/rules/"
  807. />
  808. <Redirect
  809. from=":projectId/alerts/rules/:ruleId/"
  810. to="projects/:projectId/alerts/rules/:ruleId/"
  811. />
  812. </Route>
  813. </Route>
  814. </Route>
  815. {/* A route tree for lightweight organizational detail views. We place
  816. this above the heavyweight organization detail views because there
  817. exist some redirects from deprecated routes which should not take
  818. precedence over these lightweight routes */}
  819. <Route component={errorHandler(LightWeightOrganizationDetails)}>
  820. <Route
  821. path="/organizations/:orgId/projects/"
  822. componentPromise={() => import('app/views/projectsDashboard')}
  823. component={errorHandler(LazyLoad)}
  824. />
  825. <Route
  826. path="/organizations/:orgId/dashboards/"
  827. componentPromise={() => import('app/views/dashboardsV2')}
  828. component={errorHandler(LazyLoad)}
  829. >
  830. <IndexRoute
  831. componentPromise={() => import('app/views/dashboardsV2/manage')}
  832. component={errorHandler(LazyLoad)}
  833. />
  834. </Route>
  835. <Route
  836. path="/organizations/:orgId/user-feedback/"
  837. componentPromise={() => import('app/views/userFeedback')}
  838. component={errorHandler(LazyLoad)}
  839. />
  840. <Route
  841. path="/organizations/:orgId/issues/"
  842. component={errorHandler(IssueListContainer)}
  843. >
  844. <Redirect from="/organizations/:orgId/" to="/organizations/:orgId/issues/" />
  845. <IndexRoute component={errorHandler(IssueListOverview)} />
  846. <Route
  847. path="searches/:searchId/"
  848. component={errorHandler(IssueListOverview)}
  849. />
  850. <Route
  851. path="sessionPercent"
  852. componentPromise={() => import('app/views/issueList/testSessionPercent')}
  853. component={errorHandler(LazyLoad)}
  854. />
  855. </Route>
  856. {/* Once org issues is complete, these routes can be nested under
  857. /organizations/:orgId/issues */}
  858. <Route
  859. path="/organizations/:orgId/issues/:groupId/"
  860. componentPromise={() => import('app/views/organizationGroupDetails')}
  861. component={errorHandler(LazyLoad)}
  862. >
  863. <IndexRoute
  864. componentPromise={() =>
  865. import('app/views/organizationGroupDetails/groupEventDetails')
  866. }
  867. component={errorHandler(LazyLoad)}
  868. props={{
  869. currentTab: TAB.DETAILS,
  870. isEventRoute: false,
  871. }}
  872. />
  873. <Route
  874. path="/organizations/:orgId/issues/:groupId/activity/"
  875. componentPromise={() =>
  876. import('app/views/organizationGroupDetails/groupActivity')
  877. }
  878. component={errorHandler(LazyLoad)}
  879. props={{
  880. currentTab: TAB.ACTIVITY,
  881. isEventRoute: false,
  882. }}
  883. />
  884. <Route
  885. path="/organizations/:orgId/issues/:groupId/events/"
  886. componentPromise={() =>
  887. import('app/views/organizationGroupDetails/groupEvents')
  888. }
  889. component={errorHandler(LazyLoad)}
  890. props={{
  891. currentTab: TAB.EVENTS,
  892. isEventRoute: false,
  893. }}
  894. />
  895. <Route
  896. path="/organizations/:orgId/issues/:groupId/tags/"
  897. componentPromise={() =>
  898. import('app/views/organizationGroupDetails/groupTags')
  899. }
  900. component={errorHandler(LazyLoad)}
  901. props={{
  902. currentTab: TAB.TAGS,
  903. isEventRoute: false,
  904. }}
  905. />
  906. <Route
  907. path="/organizations/:orgId/issues/:groupId/tags/:tagKey/"
  908. componentPromise={() =>
  909. import('app/views/organizationGroupDetails/groupTagValues')
  910. }
  911. component={errorHandler(LazyLoad)}
  912. props={{
  913. currentTab: TAB.TAGS,
  914. isEventRoute: false,
  915. }}
  916. />
  917. <Route
  918. path="/organizations/:orgId/issues/:groupId/feedback/"
  919. componentPromise={() =>
  920. import('app/views/organizationGroupDetails/groupUserFeedback')
  921. }
  922. component={errorHandler(LazyLoad)}
  923. props={{
  924. currentTab: TAB.USER_FEEDBACK,
  925. isEventRoute: false,
  926. }}
  927. />
  928. <Route
  929. path="/organizations/:orgId/issues/:groupId/attachments/"
  930. componentPromise={() =>
  931. import('app/views/organizationGroupDetails/groupEventAttachments')
  932. }
  933. component={errorHandler(LazyLoad)}
  934. props={{
  935. currentTab: TAB.ATTACHMENTS,
  936. isEventRoute: false,
  937. }}
  938. />
  939. <Route
  940. path="/organizations/:orgId/issues/:groupId/similar/"
  941. componentPromise={() =>
  942. import('app/views/organizationGroupDetails/groupSimilarIssues')
  943. }
  944. component={errorHandler(LazyLoad)}
  945. props={{
  946. currentTab: TAB.SIMILAR_ISSUES,
  947. isEventRoute: false,
  948. }}
  949. />
  950. <Route
  951. path="/organizations/:orgId/issues/:groupId/merged/"
  952. componentPromise={() =>
  953. import('app/views/organizationGroupDetails/groupMerged')
  954. }
  955. component={errorHandler(LazyLoad)}
  956. props={{
  957. currentTab: TAB.MERGED,
  958. isEventRoute: false,
  959. }}
  960. />
  961. <Route
  962. path="/organizations/:orgId/issues/:groupId/grouping/"
  963. componentPromise={() =>
  964. import('app/views/organizationGroupDetails/grouping')
  965. }
  966. component={errorHandler(LazyLoad)}
  967. props={{
  968. currentTab: TAB.GROUPING,
  969. isEventRoute: false,
  970. }}
  971. />
  972. <Route path="/organizations/:orgId/issues/:groupId/events/:eventId/">
  973. <IndexRoute
  974. componentPromise={() =>
  975. import('app/views/organizationGroupDetails/groupEventDetails')
  976. }
  977. component={errorHandler(LazyLoad)}
  978. props={{
  979. currentTab: TAB.DETAILS,
  980. isEventRoute: true,
  981. }}
  982. />
  983. <Route
  984. path="activity/"
  985. componentPromise={() =>
  986. import('app/views/organizationGroupDetails/groupActivity')
  987. }
  988. component={errorHandler(LazyLoad)}
  989. props={{
  990. currentTab: TAB.ACTIVITY,
  991. isEventRoute: true,
  992. }}
  993. />
  994. <Route
  995. path="events/"
  996. componentPromise={() =>
  997. import('app/views/organizationGroupDetails/groupEvents')
  998. }
  999. component={errorHandler(LazyLoad)}
  1000. props={{
  1001. currentTab: TAB.EVENTS,
  1002. isEventRoute: true,
  1003. }}
  1004. />
  1005. <Route
  1006. path="similar/"
  1007. componentPromise={() =>
  1008. import('app/views/organizationGroupDetails/groupSimilarIssues')
  1009. }
  1010. component={errorHandler(LazyLoad)}
  1011. props={{
  1012. currentTab: TAB.SIMILAR_ISSUES,
  1013. isEventRoute: true,
  1014. }}
  1015. />
  1016. <Route
  1017. path="tags/"
  1018. componentPromise={() =>
  1019. import('app/views/organizationGroupDetails/groupTags')
  1020. }
  1021. component={errorHandler(LazyLoad)}
  1022. props={{
  1023. currentTab: TAB.TAGS,
  1024. isEventRoute: true,
  1025. }}
  1026. />
  1027. <Route
  1028. path="tags/:tagKey/"
  1029. componentPromise={() =>
  1030. import('app/views/organizationGroupDetails/groupTagValues')
  1031. }
  1032. component={errorHandler(LazyLoad)}
  1033. props={{
  1034. currentTab: TAB.TAGS,
  1035. isEventRoute: true,
  1036. }}
  1037. />
  1038. <Route
  1039. path="feedback/"
  1040. componentPromise={() =>
  1041. import('app/views/organizationGroupDetails/groupUserFeedback')
  1042. }
  1043. component={errorHandler(LazyLoad)}
  1044. props={{
  1045. currentTab: TAB.USER_FEEDBACK,
  1046. isEventRoute: true,
  1047. }}
  1048. />
  1049. <Route
  1050. path="attachments/"
  1051. componentPromise={() =>
  1052. import('app/views/organizationGroupDetails/groupEventAttachments')
  1053. }
  1054. component={errorHandler(LazyLoad)}
  1055. props={{
  1056. currentTab: TAB.ATTACHMENTS,
  1057. isEventRoute: true,
  1058. }}
  1059. />
  1060. <Route
  1061. path="merged/"
  1062. componentPromise={() =>
  1063. import('app/views/organizationGroupDetails/groupMerged')
  1064. }
  1065. component={errorHandler(LazyLoad)}
  1066. props={{
  1067. currentTab: TAB.MERGED,
  1068. isEventRoute: true,
  1069. }}
  1070. />
  1071. <Route
  1072. path="grouping/"
  1073. componentPromise={() =>
  1074. import('app/views/organizationGroupDetails/grouping')
  1075. }
  1076. component={errorHandler(LazyLoad)}
  1077. props={{
  1078. currentTab: TAB.GROUPING,
  1079. isEventRoute: true,
  1080. }}
  1081. />
  1082. </Route>
  1083. </Route>
  1084. <Route
  1085. path="/organizations/:orgId/alerts/"
  1086. componentPromise={() => import('app/views/alerts')}
  1087. component={errorHandler(LazyLoad)}
  1088. >
  1089. <IndexRoute
  1090. componentPromise={() => import('app/views/alerts/list')}
  1091. component={errorHandler(LazyLoad)}
  1092. />
  1093. <Route
  1094. path="rules/details/:ruleId/"
  1095. name="Alert Rule Details"
  1096. component={errorHandler(LazyLoad)}
  1097. componentPromise={() => import('app/views/alerts/rules/details')}
  1098. />
  1099. <Route path="rules/">
  1100. <IndexRoute
  1101. component={errorHandler(LazyLoad)}
  1102. componentPromise={() => import('app/views/alerts/rules')}
  1103. />
  1104. <Route
  1105. path=":projectId/"
  1106. componentPromise={() =>
  1107. import('app/views/alerts/builder/projectProvider')
  1108. }
  1109. component={errorHandler(LazyLoad)}
  1110. >
  1111. <IndexRedirect to="/organizations/:orgId/alerts/rules/" />
  1112. <Route
  1113. path=":ruleId/"
  1114. name="Edit Alert Rule"
  1115. componentPromise={() => import('app/views/alerts/edit')}
  1116. component={errorHandler(LazyLoad)}
  1117. />
  1118. </Route>
  1119. </Route>
  1120. <Route path="metric-rules/">
  1121. <IndexRedirect to="/organizations/:orgId/alerts/rules/" />
  1122. <Route
  1123. path=":projectId/"
  1124. componentPromise={() =>
  1125. import('app/views/alerts/builder/projectProvider')
  1126. }
  1127. component={errorHandler(LazyLoad)}
  1128. >
  1129. <IndexRedirect to="/organizations/:orgId/alerts/rules/" />
  1130. <Route
  1131. path=":ruleId/"
  1132. name="Edit Alert Rule"
  1133. componentPromise={() => import('app/views/alerts/edit')}
  1134. component={errorHandler(LazyLoad)}
  1135. />
  1136. </Route>
  1137. </Route>
  1138. <Route
  1139. path="rules/"
  1140. componentPromise={() => import('app/views/alerts/rules')}
  1141. component={errorHandler(LazyLoad)}
  1142. />
  1143. <Route
  1144. path=":alertId/"
  1145. componentPromise={() => import('app/views/alerts/details')}
  1146. component={errorHandler(LazyLoad)}
  1147. />
  1148. <Route
  1149. path=":projectId/"
  1150. componentPromise={() => import('app/views/alerts/builder/projectProvider')}
  1151. component={errorHandler(LazyLoad)}
  1152. >
  1153. <Route
  1154. path="new/"
  1155. name="New Alert Rule"
  1156. component={errorHandler(LazyLoad)}
  1157. componentPromise={() => import('app/views/alerts/create')}
  1158. />
  1159. <Route
  1160. path="wizard/"
  1161. name="Alert Creation Wizard"
  1162. component={errorHandler(LazyLoad)}
  1163. componentPromise={() => import('app/views/alerts/wizard')}
  1164. />
  1165. </Route>
  1166. </Route>
  1167. <Route
  1168. path="/organizations/:orgId/monitors/"
  1169. componentPromise={() => import('app/views/monitors')}
  1170. component={errorHandler(LazyLoad)}
  1171. >
  1172. <IndexRoute
  1173. componentPromise={() => import('app/views/monitors/monitors')}
  1174. component={errorHandler(LazyLoad)}
  1175. />
  1176. <Route
  1177. path="/organizations/:orgId/monitors/create/"
  1178. componentPromise={() => import('app/views/monitors/create')}
  1179. component={errorHandler(LazyLoad)}
  1180. />
  1181. <Route
  1182. path="/organizations/:orgId/monitors/:monitorId/"
  1183. componentPromise={() => import('app/views/monitors/details')}
  1184. component={errorHandler(LazyLoad)}
  1185. />
  1186. <Route
  1187. path="/organizations/:orgId/monitors/:monitorId/edit/"
  1188. componentPromise={() => import('app/views/monitors/edit')}
  1189. component={errorHandler(LazyLoad)}
  1190. />
  1191. </Route>
  1192. <Route
  1193. path="/organizations/:orgId/releases/"
  1194. componentPromise={() => import('app/views/releases')}
  1195. component={errorHandler(LazyLoad)}
  1196. >
  1197. <IndexRoute
  1198. componentPromise={() => import('app/views/releases/list')}
  1199. component={errorHandler(LazyLoad)}
  1200. />
  1201. <Route
  1202. path=":release/"
  1203. componentPromise={() => import('app/views/releases/detail')}
  1204. component={errorHandler(LazyLoad)}
  1205. >
  1206. <IndexRoute
  1207. componentPromise={() => import('app/views/releases/detail/overview')}
  1208. component={errorHandler(LazyLoad)}
  1209. />
  1210. <Route
  1211. path="commits/"
  1212. componentPromise={() => import('app/views/releases/detail/commits')}
  1213. component={errorHandler(LazyLoad)}
  1214. />
  1215. <Route
  1216. path="files-changed/"
  1217. componentPromise={() => import('app/views/releases/detail/filesChanged')}
  1218. component={errorHandler(LazyLoad)}
  1219. />
  1220. <Redirect
  1221. from="new-events/"
  1222. to="/organizations/:orgId/releases/:release/"
  1223. />
  1224. <Redirect
  1225. from="all-events/"
  1226. to="/organizations/:orgId/releases/:release/"
  1227. />
  1228. </Route>
  1229. </Route>
  1230. <Route
  1231. path="/organizations/:orgId/activity/"
  1232. componentPromise={() => import('app/views/organizationActivity')}
  1233. component={errorHandler(LazyLoad)}
  1234. />
  1235. <Route
  1236. path="/organizations/:orgId/stats/"
  1237. componentPromise={() =>
  1238. import(
  1239. /* webpackChunkName: "OrganizationStats" */ 'app/views/organizationStats'
  1240. )
  1241. }
  1242. component={errorHandler(LazyLoad)}
  1243. />
  1244. <Route
  1245. path="/organizations/:orgId/projects/:projectId/events/:eventId/"
  1246. component={errorHandler(ProjectEventRedirect)}
  1247. />
  1248. {/*
  1249. TODO(mark) Long term this /queries route should go away and /discover should be the
  1250. canoncial route for discover2. We have a redirect right now as /discover was for
  1251. discover 1 and most of the application is linking to /discover/queries and not /discover
  1252. */}
  1253. <Redirect
  1254. from="/organizations/:orgId/discover/"
  1255. to="/organizations/:orgId/discover/queries/"
  1256. />
  1257. <Route
  1258. path="/organizations/:orgId/discover/"
  1259. componentPromise={() => import('app/views/eventsV2')}
  1260. component={errorHandler(LazyLoad)}
  1261. >
  1262. <Route
  1263. path="queries/"
  1264. componentPromise={() => import('app/views/eventsV2/landing')}
  1265. component={errorHandler(LazyLoad)}
  1266. />
  1267. <Route
  1268. path="results/"
  1269. componentPromise={() => import('app/views/eventsV2/results')}
  1270. component={errorHandler(LazyLoad)}
  1271. />
  1272. <Route
  1273. path=":eventSlug/"
  1274. componentPromise={() => import('app/views/eventsV2/eventDetails')}
  1275. component={errorHandler(LazyLoad)}
  1276. />
  1277. </Route>
  1278. <Route
  1279. path="/organizations/:orgId/performance/"
  1280. componentPromise={() => import('app/views/performance')}
  1281. component={errorHandler(LazyLoad)}
  1282. >
  1283. <IndexRoute
  1284. componentPromise={() => import('app/views/performance/content')}
  1285. component={errorHandler(LazyLoad)}
  1286. />
  1287. </Route>
  1288. <Route
  1289. path="/organizations/:orgId/performance/trends/"
  1290. componentPromise={() => import('app/views/performance')}
  1291. component={errorHandler(LazyLoad)}
  1292. >
  1293. <IndexRoute
  1294. componentPromise={() => import('app/views/performance/trends')}
  1295. component={errorHandler(LazyLoad)}
  1296. />
  1297. </Route>
  1298. <Route
  1299. path="/organizations/:orgId/performance/summary/"
  1300. componentPromise={() => import('app/views/performance')}
  1301. component={errorHandler(LazyLoad)}
  1302. >
  1303. <IndexRoute
  1304. componentPromise={() => import('app/views/performance/transactionSummary')}
  1305. component={errorHandler(LazyLoad)}
  1306. />
  1307. <Route
  1308. path="/organizations/:orgId/performance/summary/vitals/"
  1309. componentPromise={() =>
  1310. import('app/views/performance/transactionSummary/transactionVitals')
  1311. }
  1312. component={errorHandler(LazyLoad)}
  1313. />
  1314. <Route
  1315. path="/organizations/:orgId/performance/summary/tags/"
  1316. componentPromise={() =>
  1317. import('app/views/performance/transactionSummary/transactionTags')
  1318. }
  1319. component={errorHandler(LazyLoad)}
  1320. />
  1321. <Route
  1322. path="/organizations/:orgId/performance/summary/events/"
  1323. componentPromise={() =>
  1324. import('app/views/performance/transactionSummary/transactionEvents')
  1325. }
  1326. component={errorHandler(LazyLoad)}
  1327. />
  1328. </Route>
  1329. <Route
  1330. path="/organizations/:orgId/performance/vitaldetail/"
  1331. componentPromise={() => import('app/views/performance')}
  1332. component={errorHandler(LazyLoad)}
  1333. >
  1334. <IndexRoute
  1335. componentPromise={() => import('app/views/performance/vitalDetail')}
  1336. component={errorHandler(LazyLoad)}
  1337. />
  1338. </Route>
  1339. <Route
  1340. path="/organizations/:orgId/performance/trace/:traceSlug/"
  1341. componentPromise={() => import('app/views/performance')}
  1342. component={errorHandler(LazyLoad)}
  1343. >
  1344. <IndexRoute
  1345. componentPromise={() => import('app/views/performance/traceDetails')}
  1346. component={errorHandler(LazyLoad)}
  1347. />
  1348. </Route>
  1349. <Route
  1350. path="/organizations/:orgId/performance/:eventSlug/"
  1351. componentPromise={() => import('app/views/performance')}
  1352. component={errorHandler(LazyLoad)}
  1353. >
  1354. <IndexRoute
  1355. componentPromise={() => import('app/views/performance/transactionDetails')}
  1356. component={errorHandler(LazyLoad)}
  1357. />
  1358. </Route>
  1359. <Route
  1360. path="/organizations/:orgId/performance/compare/:baselineEventSlug/:regressionEventSlug/"
  1361. componentPromise={() => import('app/views/performance')}
  1362. component={errorHandler(LazyLoad)}
  1363. >
  1364. <IndexRoute
  1365. componentPromise={() => import('app/views/performance/compare')}
  1366. component={errorHandler(LazyLoad)}
  1367. />
  1368. </Route>
  1369. <Route
  1370. path="/organizations/:orgId/dashboards/new/"
  1371. componentPromise={() => import('app/views/dashboardsV2/create')}
  1372. component={errorHandler(LazyLoad)}
  1373. >
  1374. <Route
  1375. path="widget/:widgetId/edit/"
  1376. componentPromise={() => import('app/views/dashboardsV2/widget')}
  1377. component={errorHandler(LazyLoad)}
  1378. />
  1379. <Route
  1380. path="widget/new/"
  1381. componentPromise={() => import('app/views/dashboardsV2/widget')}
  1382. component={errorHandler(LazyLoad)}
  1383. />
  1384. </Route>
  1385. <Redirect
  1386. from="/organizations/:orgId/dashboards/:dashboardId/"
  1387. to="/organizations/:orgId/dashboard/:dashboardId/"
  1388. />
  1389. <Route
  1390. path="/organizations/:orgId/dashboard/:dashboardId/"
  1391. componentPromise={() => import('app/views/dashboardsV2/view')}
  1392. component={errorHandler(LazyLoad)}
  1393. >
  1394. <Route
  1395. path="widget/:widgetId/edit/"
  1396. componentPromise={() => import('app/views/dashboardsV2/widget')}
  1397. component={errorHandler(LazyLoad)}
  1398. />
  1399. <Route
  1400. path="widget/new/"
  1401. componentPromise={() => import('app/views/dashboardsV2/widget')}
  1402. component={errorHandler(LazyLoad)}
  1403. />
  1404. </Route>
  1405. {/* Admin/manage routes */}
  1406. <Route
  1407. name="Admin"
  1408. path="/manage/"
  1409. componentPromise={() => import('app/views/admin/adminLayout')}
  1410. component={errorHandler(LazyLoad)}
  1411. >
  1412. <IndexRoute
  1413. componentPromise={() => import('app/views/admin/adminOverview')}
  1414. component={errorHandler(LazyLoad)}
  1415. />
  1416. <Route
  1417. name="Buffer"
  1418. path="buffer/"
  1419. componentPromise={() => import('app/views/admin/adminBuffer')}
  1420. component={errorHandler(LazyLoad)}
  1421. />
  1422. <Route
  1423. name="Relays"
  1424. path="relays/"
  1425. componentPromise={() => import('app/views/admin/adminRelays')}
  1426. component={errorHandler(LazyLoad)}
  1427. />
  1428. <Route
  1429. name="Organizations"
  1430. path="organizations/"
  1431. componentPromise={() => import('app/views/admin/adminOrganizations')}
  1432. component={errorHandler(LazyLoad)}
  1433. />
  1434. <Route
  1435. name="Projects"
  1436. path="projects/"
  1437. componentPromise={() => import('app/views/admin/adminProjects')}
  1438. component={errorHandler(LazyLoad)}
  1439. />
  1440. <Route
  1441. name="Queue"
  1442. path="queue/"
  1443. componentPromise={() => import('app/views/admin/adminQueue')}
  1444. component={errorHandler(LazyLoad)}
  1445. />
  1446. <Route
  1447. name="Quotas"
  1448. path="quotas/"
  1449. componentPromise={() => import('app/views/admin/adminQuotas')}
  1450. component={errorHandler(LazyLoad)}
  1451. />
  1452. <Route
  1453. name="Settings"
  1454. path="settings/"
  1455. componentPromise={() => import('app/views/admin/adminSettings')}
  1456. component={errorHandler(LazyLoad)}
  1457. />
  1458. <Route name="Users" path="users/">
  1459. <IndexRoute
  1460. componentPromise={() => import('app/views/admin/adminUsers')}
  1461. component={errorHandler(LazyLoad)}
  1462. />
  1463. <Route
  1464. path=":id"
  1465. componentPromise={() => import('app/views/admin/adminUserEdit')}
  1466. component={errorHandler(LazyLoad)}
  1467. />
  1468. </Route>
  1469. <Route
  1470. name="Mail"
  1471. path="status/mail/"
  1472. componentPromise={() => import('app/views/admin/adminMail')}
  1473. component={errorHandler(LazyLoad)}
  1474. />
  1475. <Route
  1476. name="Environment"
  1477. path="status/environment/"
  1478. componentPromise={() => import('app/views/admin/adminEnvironment')}
  1479. component={errorHandler(LazyLoad)}
  1480. />
  1481. <Route
  1482. name="Packages"
  1483. path="status/packages/"
  1484. componentPromise={() => import('app/views/admin/adminPackages')}
  1485. component={errorHandler(LazyLoad)}
  1486. />
  1487. <Route
  1488. name="Warnings"
  1489. path="status/warnings/"
  1490. componentPromise={() => import('app/views/admin/adminWarnings')}
  1491. component={errorHandler(LazyLoad)}
  1492. />
  1493. {hook('routes:admin')}
  1494. </Route>
  1495. </Route>
  1496. {/* The heavyweight organization detail views */}
  1497. <Route path="/:orgId/" component={errorHandler(OrganizationDetails)}>
  1498. <Route component={errorHandler(OrganizationRoot)}>
  1499. {hook('routes:organization-root')}
  1500. <Route
  1501. path="/organizations/:orgId/projects/:projectId/getting-started/"
  1502. componentPromise={() => import('app/views/projectInstall/gettingStarted')}
  1503. component={errorHandler(LazyLoad)}
  1504. >
  1505. <IndexRoute
  1506. componentPromise={() => import('app/views/projectInstall/overview')}
  1507. component={errorHandler(LazyLoad)}
  1508. />
  1509. <Route
  1510. path=":platform/"
  1511. componentPromise={() =>
  1512. import('app/views/projectInstall/platformOrIntegration')
  1513. }
  1514. component={errorHandler(LazyLoad)}
  1515. />
  1516. </Route>
  1517. <Route
  1518. path="/organizations/:orgId/teams/new/"
  1519. componentPromise={() => import('app/views/teamCreate')}
  1520. component={errorHandler(LazyLoad)}
  1521. />
  1522. <Route path="/organizations/:orgId/">
  1523. {hook('routes:organization')}
  1524. <Redirect
  1525. from="/organizations/:orgId/teams/"
  1526. to="/settings/:orgId/teams/"
  1527. />
  1528. <Redirect
  1529. from="/organizations/:orgId/teams/your-teams/"
  1530. to="/settings/:orgId/teams/"
  1531. />
  1532. <Redirect
  1533. from="/organizations/:orgId/teams/all-teams/"
  1534. to="/settings/:orgId/teams/"
  1535. />
  1536. <Redirect
  1537. from="/organizations/:orgId/teams/:teamId/"
  1538. to="/settings/:orgId/teams/:teamId/"
  1539. />
  1540. <Redirect
  1541. from="/organizations/:orgId/teams/:teamId/members/"
  1542. to="/settings/:orgId/teams/:teamId/members/"
  1543. />
  1544. <Redirect
  1545. from="/organizations/:orgId/teams/:teamId/projects/"
  1546. to="/settings/:orgId/teams/:teamId/projects/"
  1547. />
  1548. <Redirect
  1549. from="/organizations/:orgId/teams/:teamId/settings/"
  1550. to="/settings/:orgId/teams/:teamId/settings/"
  1551. />
  1552. <Redirect from="/organizations/:orgId/settings/" to="/settings/:orgId/" />
  1553. <Redirect
  1554. from="/organizations/:orgId/api-keys/"
  1555. to="/settings/:orgId/api-keys/"
  1556. />
  1557. <Redirect
  1558. from="/organizations/:orgId/api-keys/:apiKey/"
  1559. to="/settings/:orgId/api-keys/:apiKey/"
  1560. />
  1561. <Redirect
  1562. from="/organizations/:orgId/members/"
  1563. to="/settings/:orgId/members/"
  1564. />
  1565. <Redirect
  1566. from="/organizations/:orgId/members/:memberId/"
  1567. to="/settings/:orgId/members/:memberId/"
  1568. />
  1569. <Redirect
  1570. from="/organizations/:orgId/rate-limits/"
  1571. to="/settings/:orgId/rate-limits/"
  1572. />
  1573. <Redirect
  1574. from="/organizations/:orgId/repos/"
  1575. to="/settings/:orgId/repos/"
  1576. />
  1577. </Route>
  1578. <Route
  1579. path="/organizations/:orgId/projects/new/"
  1580. componentPromise={() => import('app/views/projectInstall/newProject')}
  1581. component={errorHandler(LazyLoad)}
  1582. />
  1583. </Route>
  1584. <Route
  1585. path=":projectId/getting-started/"
  1586. componentPromise={() => import('app/views/projectInstall/gettingStarted')}
  1587. component={errorHandler(LazyLoad)}
  1588. >
  1589. <IndexRoute
  1590. componentPromise={() => import('app/views/projectInstall/overview')}
  1591. component={errorHandler(LazyLoad)}
  1592. />
  1593. <Route
  1594. path=":platform/"
  1595. componentPromise={() =>
  1596. import('app/views/projectInstall/platformOrIntegration')
  1597. }
  1598. component={errorHandler(LazyLoad)}
  1599. />
  1600. </Route>
  1601. </Route>
  1602. {/* A route tree for lightweight organizational detail views.
  1603. This is strictly for deprecated URLs that we need to maintain */}
  1604. <Route component={errorHandler(LightWeightOrganizationDetails)}>
  1605. {/* This is in the bottom lightweight group because "/organizations/:orgId/projects/new/" in heavyweight needs to be matched first */}
  1606. <Route
  1607. path="/organizations/:orgId/projects/:projectId/"
  1608. componentPromise={() => import('app/views/projectDetail')}
  1609. component={errorHandler(LazyLoad)}
  1610. />
  1611. <Route name="Organization" path="/:orgId/">
  1612. <Route path=":projectId/">
  1613. {/* Support for deprecated URLs (pre-Sentry 10). We just redirect users to new canonical URLs. */}
  1614. <IndexRoute
  1615. component={errorHandler(
  1616. redirectDeprecatedProjectRoute(
  1617. ({orgId, projectId}) =>
  1618. `/organizations/${orgId}/issues/?project=${projectId}`
  1619. )
  1620. )}
  1621. />
  1622. <Route
  1623. path="issues/"
  1624. component={errorHandler(
  1625. redirectDeprecatedProjectRoute(
  1626. ({orgId, projectId}) =>
  1627. `/organizations/${orgId}/issues/?project=${projectId}`
  1628. )
  1629. )}
  1630. />
  1631. <Route
  1632. path="dashboard/"
  1633. component={errorHandler(
  1634. redirectDeprecatedProjectRoute(
  1635. ({orgId, projectId}) =>
  1636. `/organizations/${orgId}/dashboards/?project=${projectId}`
  1637. )
  1638. )}
  1639. />
  1640. <Route
  1641. path="user-feedback/"
  1642. component={errorHandler(
  1643. redirectDeprecatedProjectRoute(
  1644. ({orgId, projectId}) =>
  1645. `/organizations/${orgId}/user-feedback/?project=${projectId}`
  1646. )
  1647. )}
  1648. />
  1649. <Route
  1650. path="releases/"
  1651. component={errorHandler(
  1652. redirectDeprecatedProjectRoute(
  1653. ({orgId, projectId}) =>
  1654. `/organizations/${orgId}/releases/?project=${projectId}`
  1655. )
  1656. )}
  1657. />
  1658. <Route
  1659. path="releases/:version/"
  1660. component={errorHandler(
  1661. redirectDeprecatedProjectRoute(
  1662. ({orgId, projectId, router}) =>
  1663. `/organizations/${orgId}/releases/${router.params.version}/?project=${projectId}`
  1664. )
  1665. )}
  1666. />
  1667. <Route
  1668. path="releases/:version/new-events/"
  1669. component={errorHandler(
  1670. redirectDeprecatedProjectRoute(
  1671. ({orgId, projectId, router}) =>
  1672. `/organizations/${orgId}/releases/${router.params.version}/new-events/?project=${projectId}`
  1673. )
  1674. )}
  1675. />
  1676. <Route
  1677. path="releases/:version/all-events/"
  1678. component={errorHandler(
  1679. redirectDeprecatedProjectRoute(
  1680. ({orgId, projectId, router}) =>
  1681. `/organizations/${orgId}/releases/${router.params.version}/all-events/?project=${projectId}`
  1682. )
  1683. )}
  1684. />
  1685. <Route
  1686. path="releases/:version/commits/"
  1687. component={errorHandler(
  1688. redirectDeprecatedProjectRoute(
  1689. ({orgId, projectId, router}) =>
  1690. `/organizations/${orgId}/releases/${router.params.version}/commits/?project=${projectId}`
  1691. )
  1692. )}
  1693. />
  1694. </Route>
  1695. </Route>
  1696. </Route>
  1697. <Route path="/:orgId/">
  1698. <Route path=":projectId/settings/">
  1699. <Redirect from="teams/" to="/settings/:orgId/projects/:projectId/teams/" />
  1700. <Redirect from="alerts/" to="/settings/:orgId/projects/:projectId/alerts/" />
  1701. <Redirect
  1702. from="alerts/rules/"
  1703. to="/settings/:orgId/projects/:projectId/alerts/rules/"
  1704. />
  1705. <Redirect
  1706. from="alerts/rules/new/"
  1707. to="/settings/:orgId/projects/:projectId/alerts/rules/new/"
  1708. />
  1709. <Redirect
  1710. from="alerts/rules/:ruleId/"
  1711. to="/settings/:orgId/projects/:projectId/alerts/rules/:ruleId/"
  1712. />
  1713. <Redirect
  1714. from="environments/"
  1715. to="/settings/:orgId/projects/:projectId/environments/"
  1716. />
  1717. <Redirect
  1718. from="environments/hidden/"
  1719. to="/settings/:orgId/projects/:projectId/environments/hidden/"
  1720. />
  1721. <Redirect
  1722. from="tags/"
  1723. to="/settings/projects/:orgId/projects/:projectId/tags/"
  1724. />
  1725. <Redirect
  1726. from="issue-tracking/"
  1727. to="/settings/:orgId/projects/:projectId/issue-tracking/"
  1728. />
  1729. <Redirect
  1730. from="release-tracking/"
  1731. to="/settings/:orgId/projects/:projectId/release-tracking/"
  1732. />
  1733. <Redirect
  1734. from="ownership/"
  1735. to="/settings/:orgId/projects/:projectId/ownership/"
  1736. />
  1737. <Redirect
  1738. from="data-forwarding/"
  1739. to="/settings/:orgId/projects/:projectId/data-forwarding/"
  1740. />
  1741. <Redirect
  1742. from="debug-symbols/"
  1743. to="/settings/:orgId/projects/:projectId/debug-symbols/"
  1744. />
  1745. <Redirect
  1746. from="processing-issues/"
  1747. to="/settings/:orgId/projects/:projectId/processing-issues/"
  1748. />
  1749. <Redirect
  1750. from="filters/"
  1751. to="/settings/:orgId/projects/:projectId/filters/"
  1752. />
  1753. <Redirect from="hooks/" to="/settings/:orgId/projects/:projectId/hooks/" />
  1754. <Redirect from="keys/" to="/settings/:orgId/projects/:projectId/keys/" />
  1755. <Redirect
  1756. from="keys/:keyId/"
  1757. to="/settings/:orgId/projects/:projectId/keys/:keyId/"
  1758. />
  1759. <Redirect
  1760. from="user-feedback/"
  1761. to="/settings/:orgId/projects/:projectId/user-feedback/"
  1762. />
  1763. <Redirect
  1764. from="security-headers/"
  1765. to="/settings/:orgId/projects/:projectId/security-headers/"
  1766. />
  1767. <Redirect
  1768. from="security-headers/csp/"
  1769. to="/settings/:orgId/projects/:projectId/security-headers/csp/"
  1770. />
  1771. <Redirect
  1772. from="security-headers/expect-ct/"
  1773. to="/settings/:orgId/projects/:projectId/security-headers/expect-ct/"
  1774. />
  1775. <Redirect
  1776. from="security-headers/hpkp/"
  1777. to="/settings/:orgId/projects/:projectId/security-headers/hpkp/"
  1778. />
  1779. <Redirect
  1780. from="plugins/"
  1781. to="/settings/:orgId/projects/:projectId/plugins/"
  1782. />
  1783. <Redirect
  1784. from="plugins/:pluginId/"
  1785. to="/settings/:orgId/projects/:projectId/plugins/:pluginId/"
  1786. />
  1787. <Redirect
  1788. from="integrations/:providerKey/"
  1789. to="/settings/:orgId/projects/:projectId/integrations/:providerKey/"
  1790. />
  1791. <Redirect
  1792. from="install/"
  1793. to="/settings/:orgId/projects/:projectId/install/"
  1794. />
  1795. <Redirect
  1796. from="install/:platform'"
  1797. to="/settings/:orgId/projects/:projectId/install/:platform/"
  1798. />
  1799. </Route>
  1800. <Redirect from=":projectId/group/:groupId/" to="issues/:groupId/" />
  1801. <Redirect
  1802. from=":projectId/issues/:groupId/"
  1803. to="/organizations/:orgId/issues/:groupId/"
  1804. />
  1805. <Redirect
  1806. from=":projectId/issues/:groupId/events/"
  1807. to="/organizations/:orgId/issues/:groupId/events/"
  1808. />
  1809. <Redirect
  1810. from=":projectId/issues/:groupId/events/:eventId/"
  1811. to="/organizations/:orgId/issues/:groupId/events/:eventId/"
  1812. />
  1813. <Redirect
  1814. from=":projectId/issues/:groupId/tags/"
  1815. to="/organizations/:orgId/issues/:groupId/tags/"
  1816. />
  1817. <Redirect
  1818. from=":projectId/issues/:groupId/tags/:tagKey/"
  1819. to="/organizations/:orgId/issues/:groupId/tags/:tagKey/"
  1820. />
  1821. <Redirect
  1822. from=":projectId/issues/:groupId/feedback/"
  1823. to="/organizations/:orgId/issues/:groupId/feedback/"
  1824. />
  1825. <Redirect
  1826. from=":projectId/issues/:groupId/similar/"
  1827. to="/organizations/:orgId/issues/:groupId/similar/"
  1828. />
  1829. <Redirect
  1830. from=":projectId/issues/:groupId/merged/"
  1831. to="/organizations/:orgId/issues/:groupId/merged/"
  1832. />
  1833. <Route
  1834. path=":projectId/events/:eventId/"
  1835. component={errorHandler(ProjectEventRedirect)}
  1836. />
  1837. </Route>
  1838. {hook('routes')}
  1839. <Route
  1840. path="*"
  1841. component={errorHandler(RouteNotFound)}
  1842. onEnter={appendTrailingSlash}
  1843. />
  1844. </Route>
  1845. </Route>
  1846. );
  1847. }
  1848. export default routes;