routes.tsx 66 KB

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