routes.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. import './dashboard_loaders';
  2. import './ReactContainer';
  3. import { applyRouteRegistrationHandlers } from './registry';
  4. // Pages
  5. import CreateFolderCtrl from 'app/features/folders/CreateFolderCtrl';
  6. import FolderDashboardsCtrl from 'app/features/folders/FolderDashboardsCtrl';
  7. import DashboardImportCtrl from 'app/features/manage-dashboards/DashboardImportCtrl';
  8. import LdapPage from 'app/features/admin/ldap/LdapPage';
  9. import LdapUserPage from 'app/features/admin/ldap/LdapUserPage';
  10. import config from 'app/core/config';
  11. import { route, ILocationProvider } from 'angular';
  12. // Types
  13. import { DashboardRouteInfo } from 'app/types';
  14. import { LoginPage } from 'app/core/components/Login/LoginPage';
  15. import { SafeDynamicImport } from '../core/components/SafeDynamicImport';
  16. /** @ngInject */
  17. export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locationProvider: ILocationProvider) {
  18. $locationProvider.html5Mode(true);
  19. // Routes here are guarded both here and server side for react-container routes or just on the server for angular
  20. // ones. That means angular ones could be navigated to in case there is a client side link some where.
  21. const importDashboardPage = () =>
  22. SafeDynamicImport(import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/DashboardPage'));
  23. $routeProvider
  24. .when('/', {
  25. template: '<react-container />',
  26. //@ts-ignore
  27. pageClass: 'page-dashboard',
  28. routeInfo: DashboardRouteInfo.Home,
  29. reloadOnSearch: false,
  30. resolve: {
  31. component: importDashboardPage,
  32. },
  33. })
  34. .when('/d/:uid/:slug', {
  35. template: '<react-container />',
  36. pageClass: 'page-dashboard',
  37. routeInfo: DashboardRouteInfo.Normal,
  38. reloadOnSearch: false,
  39. resolve: {
  40. component: importDashboardPage,
  41. },
  42. })
  43. .when('/d/:uid', {
  44. template: '<react-container />',
  45. pageClass: 'page-dashboard',
  46. reloadOnSearch: false,
  47. routeInfo: DashboardRouteInfo.Normal,
  48. resolve: {
  49. component: importDashboardPage,
  50. },
  51. })
  52. .when('/dashboard/:type/:slug', {
  53. template: '<react-container />',
  54. pageClass: 'page-dashboard',
  55. routeInfo: DashboardRouteInfo.Normal,
  56. reloadOnSearch: false,
  57. resolve: {
  58. component: importDashboardPage,
  59. },
  60. })
  61. .when('/dashboard/new', {
  62. template: '<react-container />',
  63. pageClass: 'page-dashboard',
  64. routeInfo: DashboardRouteInfo.New,
  65. reloadOnSearch: false,
  66. resolve: {
  67. component: importDashboardPage,
  68. },
  69. })
  70. .when('/d-solo/:uid/:slug', {
  71. template: '<react-container />',
  72. pageClass: 'dashboard-solo',
  73. routeInfo: DashboardRouteInfo.Normal,
  74. reloadOnSearch: false,
  75. resolve: {
  76. component: () =>
  77. SafeDynamicImport(
  78. import(/* webpackChunkName: "SoloPanelPage" */ '../features/dashboard/containers/SoloPanelPage')
  79. ),
  80. },
  81. })
  82. .when('/dashboard-solo/:type/:slug', {
  83. template: '<react-container />',
  84. pageClass: 'dashboard-solo',
  85. routeInfo: DashboardRouteInfo.Normal,
  86. reloadOnSearch: false,
  87. resolve: {
  88. component: () =>
  89. SafeDynamicImport(
  90. import(/* webpackChunkName: "SoloPanelPage" */ '../features/dashboard/containers/SoloPanelPage')
  91. ),
  92. },
  93. })
  94. .when('/dashboard/import', {
  95. templateUrl: 'public/app/features/manage-dashboards/partials/dashboard_import.html',
  96. controller: DashboardImportCtrl,
  97. controllerAs: 'ctrl',
  98. })
  99. .when('/datasources', {
  100. template: '<react-container />',
  101. resolve: {
  102. component: () =>
  103. SafeDynamicImport(
  104. import(/* webpackChunkName: "DataSourcesListPage"*/ 'app/features/datasources/DataSourcesListPage')
  105. ),
  106. },
  107. })
  108. .when('/datasources/edit/:id/', {
  109. template: '<react-container />',
  110. reloadOnSearch: false, // for tabs
  111. resolve: {
  112. component: () =>
  113. SafeDynamicImport(
  114. import(/* webpackChunkName: "DataSourceSettingsPage"*/ '../features/datasources/settings/DataSourceSettingsPage')
  115. ),
  116. },
  117. })
  118. .when('/datasources/edit/:id/dashboards', {
  119. template: '<react-container />',
  120. resolve: {
  121. component: () =>
  122. SafeDynamicImport(
  123. import(/* webpackChunkName: "DataSourceDashboards"*/ 'app/features/datasources/DataSourceDashboards')
  124. ),
  125. },
  126. })
  127. .when('/datasources/new', {
  128. template: '<react-container />',
  129. resolve: {
  130. component: () =>
  131. SafeDynamicImport(
  132. import(/* webpackChunkName: "NewDataSourcePage"*/ '../features/datasources/NewDataSourcePage')
  133. ),
  134. },
  135. })
  136. .when('/dashboards', {
  137. templateUrl: 'public/app/features/manage-dashboards/partials/dashboard_list.html',
  138. controller: 'DashboardListCtrl',
  139. controllerAs: 'ctrl',
  140. })
  141. .when('/dashboards/folder/new', {
  142. templateUrl: 'public/app/features/folders/partials/create_folder.html',
  143. controller: CreateFolderCtrl,
  144. controllerAs: 'ctrl',
  145. })
  146. .when('/dashboards/f/:uid/:slug/permissions', {
  147. template: '<react-container />',
  148. resolve: {
  149. component: () =>
  150. SafeDynamicImport(
  151. import(/* webpackChunkName: "FolderPermissions"*/ 'app/features/folders/FolderPermissions')
  152. ),
  153. },
  154. })
  155. .when('/dashboards/f/:uid/:slug/settings', {
  156. template: '<react-container />',
  157. resolve: {
  158. component: () =>
  159. SafeDynamicImport(
  160. import(/* webpackChunkName: "FolderSettingsPage"*/ 'app/features/folders/FolderSettingsPage')
  161. ),
  162. },
  163. })
  164. .when('/dashboards/f/:uid/:slug', {
  165. templateUrl: 'public/app/features/folders/partials/folder_dashboards.html',
  166. controller: FolderDashboardsCtrl,
  167. controllerAs: 'ctrl',
  168. })
  169. .when('/dashboards/f/:uid', {
  170. templateUrl: 'public/app/features/folders/partials/folder_dashboards.html',
  171. controller: FolderDashboardsCtrl,
  172. controllerAs: 'ctrl',
  173. })
  174. .when('/explore', {
  175. template: '<react-container />',
  176. reloadOnSearch: false,
  177. resolve: {
  178. roles: () => (config.viewersCanEdit ? [] : ['Editor', 'Admin']),
  179. component: () => SafeDynamicImport(import(/* webpackChunkName: "explore" */ 'app/features/explore/Wrapper')),
  180. },
  181. })
  182. .when('/a/:pluginId/', {
  183. // Someday * and will get a ReactRouter under that path!
  184. template: '<react-container />',
  185. reloadOnSearch: false,
  186. resolve: {
  187. component: () =>
  188. SafeDynamicImport(import(/* webpackChunkName: "AppRootPage" */ 'app/features/plugins/AppRootPage')),
  189. },
  190. })
  191. .when('/org', {
  192. template: '<react-container />',
  193. resolve: {
  194. component: () =>
  195. SafeDynamicImport(import(/* webpackChunkName: "OrgDetailsPage" */ '../features/org/OrgDetailsPage')),
  196. },
  197. })
  198. .when('/org/new', {
  199. templateUrl: 'public/app/features/org/partials/newOrg.html',
  200. controller: 'NewOrgCtrl',
  201. })
  202. .when('/org/users', {
  203. template: '<react-container />',
  204. resolve: {
  205. component: () =>
  206. SafeDynamicImport(import(/* webpackChunkName: "UsersListPage" */ 'app/features/users/UsersListPage')),
  207. },
  208. })
  209. .when('/org/users/invite', {
  210. templateUrl: 'public/app/features/org/partials/invite.html',
  211. controller: 'UserInviteCtrl',
  212. controllerAs: 'ctrl',
  213. })
  214. .when('/org/apikeys', {
  215. template: '<react-container />',
  216. resolve: {
  217. roles: () => ['Editor', 'Admin'],
  218. component: () =>
  219. SafeDynamicImport(import(/* webpackChunkName: "ApiKeysPage" */ 'app/features/api-keys/ApiKeysPage')),
  220. },
  221. })
  222. .when('/org/teams', {
  223. template: '<react-container />',
  224. resolve: {
  225. roles: () => (config.editorsCanAdmin ? [] : ['Editor', 'Admin']),
  226. component: () => SafeDynamicImport(import(/* webpackChunkName: "TeamList" */ 'app/features/teams/TeamList')),
  227. },
  228. })
  229. .when('/org/teams/new', {
  230. templateUrl: 'public/app/features/teams/partials/create_team.html',
  231. controller: 'CreateTeamCtrl',
  232. controllerAs: 'ctrl',
  233. })
  234. .when('/org/teams/edit/:id/:page?', {
  235. template: '<react-container />',
  236. resolve: {
  237. roles: () => (config.editorsCanAdmin ? [] : ['Admin']),
  238. component: () => SafeDynamicImport(import(/* webpackChunkName: "TeamPages" */ 'app/features/teams/TeamPages')),
  239. },
  240. })
  241. .when('/profile', {
  242. templateUrl: 'public/app/features/profile/partials/profile.html',
  243. controller: 'ProfileCtrl',
  244. controllerAs: 'ctrl',
  245. })
  246. .when('/profile/password', {
  247. template: '<react-container />',
  248. resolve: {
  249. component: () =>
  250. SafeDynamicImport(
  251. import(/* webPackChunkName: "ChangePasswordPage" */ 'app/features/profile/ChangePasswordPage')
  252. ),
  253. },
  254. })
  255. .when('/profile/select-org', {
  256. templateUrl: 'public/app/features/org/partials/select_org.html',
  257. controller: 'SelectOrgCtrl',
  258. })
  259. // ADMIN
  260. .when('/admin', {
  261. templateUrl: 'public/app/features/admin/partials/admin_home.html',
  262. controller: 'AdminHomeCtrl',
  263. controllerAs: 'ctrl',
  264. })
  265. .when('/admin/settings', {
  266. templateUrl: 'public/app/features/admin/partials/settings.html',
  267. controller: 'AdminSettingsCtrl',
  268. controllerAs: 'ctrl',
  269. })
  270. .when('/admin/users', {
  271. templateUrl: 'public/app/features/admin/partials/users.html',
  272. controller: 'AdminListUsersCtrl',
  273. controllerAs: 'ctrl',
  274. })
  275. .when('/admin/users/create', {
  276. templateUrl: 'public/app/features/admin/partials/new_user.html',
  277. controller: 'AdminEditUserCtrl',
  278. })
  279. .when('/admin/users/edit/:id', {
  280. templateUrl: 'public/app/features/admin/partials/edit_user.html',
  281. controller: 'AdminEditUserCtrl',
  282. })
  283. .when('/admin/users/ldap/edit/:id', {
  284. template: '<react-container />',
  285. resolve: {
  286. component: () => LdapUserPage,
  287. },
  288. })
  289. .when('/admin/orgs', {
  290. templateUrl: 'public/app/features/admin/partials/orgs.html',
  291. controller: 'AdminListOrgsCtrl',
  292. controllerAs: 'ctrl',
  293. })
  294. .when('/admin/orgs/edit/:id', {
  295. templateUrl: 'public/app/features/admin/partials/edit_org.html',
  296. controller: 'AdminEditOrgCtrl',
  297. controllerAs: 'ctrl',
  298. })
  299. .when('/admin/stats', {
  300. template: '<react-container />',
  301. resolve: {
  302. component: () =>
  303. SafeDynamicImport(import(/* webpackChunkName: "ServerStats" */ 'app/features/admin/ServerStats')),
  304. },
  305. })
  306. .when('/admin/ldap', {
  307. template: '<react-container />',
  308. resolve: {
  309. component: () => LdapPage,
  310. },
  311. })
  312. // LOGIN / SIGNUP
  313. .when('/login', {
  314. template: '<react-container/>',
  315. resolve: {
  316. component: () => LoginPage,
  317. },
  318. pageClass: 'login-page sidemenu-hidden',
  319. })
  320. .when('/invite/:code', {
  321. templateUrl: 'public/app/partials/signup_invited.html',
  322. controller: 'InvitedCtrl',
  323. pageClass: 'sidemenu-hidden',
  324. })
  325. .when('/signup', {
  326. templateUrl: 'public/app/partials/signup_step2.html',
  327. controller: 'SignUpCtrl',
  328. pageClass: 'sidemenu-hidden',
  329. })
  330. .when('/user/password/send-reset-email', {
  331. templateUrl: 'public/app/partials/reset_password.html',
  332. controller: 'ResetPasswordCtrl',
  333. pageClass: 'sidemenu-hidden',
  334. })
  335. .when('/user/password/reset', {
  336. templateUrl: 'public/app/partials/reset_password.html',
  337. controller: 'ResetPasswordCtrl',
  338. pageClass: 'sidemenu-hidden',
  339. })
  340. .when('/dashboard/snapshots', {
  341. templateUrl: 'public/app/features/manage-dashboards/partials/snapshot_list.html',
  342. controller: 'SnapshotListCtrl',
  343. controllerAs: 'ctrl',
  344. })
  345. .when('/plugins', {
  346. template: '<react-container />',
  347. resolve: {
  348. component: () =>
  349. SafeDynamicImport(import(/* webpackChunkName: "PluginListPage" */ 'app/features/plugins/PluginListPage')),
  350. },
  351. })
  352. .when('/plugins/:pluginId/', {
  353. template: '<react-container />',
  354. reloadOnSearch: false, // tabs from query parameters
  355. resolve: {
  356. component: () =>
  357. SafeDynamicImport(import(/* webpackChunkName: "PluginPage" */ '../features/plugins/PluginPage')),
  358. },
  359. })
  360. .when('/plugins/:pluginId/page/:slug', {
  361. templateUrl: 'public/app/features/plugins/partials/plugin_page.html',
  362. controller: 'AppPageCtrl',
  363. controllerAs: 'ctrl',
  364. })
  365. .when('/styleguide/:page?', {
  366. controller: 'StyleGuideCtrl',
  367. controllerAs: 'ctrl',
  368. templateUrl: 'public/app/features/admin/partials/styleguide.html',
  369. })
  370. .when('/alerting', {
  371. redirectTo: '/alerting/list',
  372. })
  373. .when('/alerting/list', {
  374. template: '<react-container />',
  375. reloadOnSearch: false,
  376. resolve: {
  377. component: () =>
  378. SafeDynamicImport(import(/* webpackChunkName: "AlertRuleList" */ 'app/features/alerting/AlertRuleList')),
  379. },
  380. })
  381. .when('/alerting/notifications', {
  382. templateUrl: 'public/app/features/alerting/partials/notifications_list.html',
  383. controller: 'AlertNotificationsListCtrl',
  384. controllerAs: 'ctrl',
  385. })
  386. .when('/alerting/notification/new', {
  387. templateUrl: 'public/app/features/alerting/partials/notification_edit.html',
  388. controller: 'AlertNotificationEditCtrl',
  389. controllerAs: 'ctrl',
  390. })
  391. .when('/alerting/notification/:id/edit', {
  392. templateUrl: 'public/app/features/alerting/partials/notification_edit.html',
  393. controller: 'AlertNotificationEditCtrl',
  394. controllerAs: 'ctrl',
  395. })
  396. .otherwise({
  397. templateUrl: 'public/app/partials/error.html',
  398. controller: 'ErrorCtrl',
  399. });
  400. applyRouteRegistrationHandlers($routeProvider);
  401. }