useModuleURL.tsx 4.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import normalizeUrl from 'sentry/utils/url/normalizeUrl';
  2. import useOrganization from 'sentry/utils/useOrganization';
  3. import {BASE_URL as RESOURCES_BASE_URL} from 'sentry/views/insights/browser/resources/settings';
  4. import {BASE_URL as VITALS_BASE_URL} from 'sentry/views/insights/browser/webVitals/settings';
  5. import {BASE_URL as CACHE_BASE_URL} from 'sentry/views/insights/cache/settings';
  6. import {BASE_URL as CRONS_BASE_URL} from 'sentry/views/insights/crons/settings';
  7. import {BASE_URL as DB_BASE_URL} from 'sentry/views/insights/database/settings';
  8. import {BASE_URL as HTTP_BASE_URL} from 'sentry/views/insights/http/settings';
  9. import {BASE_URL as AI_BASE_URL} from 'sentry/views/insights/llmMonitoring/settings';
  10. import {BASE_URL as APP_STARTS_BASE_URL} from 'sentry/views/insights/mobile/appStarts/settings';
  11. import {BASE_URL as SCREEN_LOADS_BASE_URL} from 'sentry/views/insights/mobile/screenload/settings';
  12. import {BASE_URL as SCREEN_RENDERING_BASE_URL} from 'sentry/views/insights/mobile/screenRendering/settings';
  13. import {BASE_URL as MOBILE_SCREENS_BASE_URL} from 'sentry/views/insights/mobile/screens/settings';
  14. import {BASE_URL as MOBILE_UI_BASE_URL} from 'sentry/views/insights/mobile/ui/settings';
  15. import {DOMAIN_VIEW_BASE_URL} from 'sentry/views/insights/pages/settings';
  16. import {
  17. type DomainView,
  18. useDomainViewFilters,
  19. } from 'sentry/views/insights/pages/useFilters';
  20. import {getModuleView} from 'sentry/views/insights/pages/utils';
  21. import {BASE_URL as QUEUE_BASE_URL} from 'sentry/views/insights/queues/settings';
  22. import {ModuleName} from 'sentry/views/insights/types';
  23. import {BASE_URL as UPTIME_BASE_URL} from 'sentry/views/insights/uptime/settings';
  24. export const MODULE_BASE_URLS: Record<ModuleName, string> = {
  25. [ModuleName.DB]: DB_BASE_URL,
  26. [ModuleName.HTTP]: HTTP_BASE_URL,
  27. [ModuleName.CACHE]: CACHE_BASE_URL,
  28. [ModuleName.QUEUE]: QUEUE_BASE_URL,
  29. [ModuleName.SCREEN_LOAD]: SCREEN_LOADS_BASE_URL,
  30. [ModuleName.APP_START]: APP_STARTS_BASE_URL,
  31. [ModuleName.VITAL]: VITALS_BASE_URL,
  32. [ModuleName.RESOURCE]: RESOURCES_BASE_URL,
  33. [ModuleName.AI]: AI_BASE_URL,
  34. [ModuleName.MOBILE_UI]: MOBILE_UI_BASE_URL,
  35. [ModuleName.MOBILE_VITALS]: MOBILE_SCREENS_BASE_URL,
  36. [ModuleName.SCREEN_RENDERING]: SCREEN_RENDERING_BASE_URL,
  37. [ModuleName.CRONS]: CRONS_BASE_URL,
  38. [ModuleName.UPTIME]: UPTIME_BASE_URL,
  39. [ModuleName.OTHER]: '',
  40. };
  41. type ModuleNameStrings = `${ModuleName}`;
  42. export type RoutableModuleNames = Exclude<ModuleNameStrings, '' | 'other'>;
  43. export const useModuleURL = (
  44. moduleName: RoutableModuleNames,
  45. bare: boolean = false,
  46. view?: DomainView // Todo - this should be required when a module belongs to multiple views
  47. ): string => {
  48. const builder = useModuleURLBuilder(bare);
  49. return builder(moduleName, view);
  50. };
  51. export type URLBuilder = (
  52. moduleName: RoutableModuleNames,
  53. domainView?: DomainView
  54. ) => string;
  55. /**
  56. * This hook returns a function to build URLs for the module summary pages.
  57. * This function will return the domain specific module url, the domain is determined in the following order of priority:
  58. * 1. The domain view passed in by the user
  59. * 2. (when detectDomainView=true) The current domain view (i.e if the current url is `/performance/frontend`, the current view is frontned)
  60. * 3. The default view for the module
  61. */
  62. export function useModuleURLBuilder(
  63. bare: boolean = false,
  64. detectDomainView: boolean = true
  65. ): URLBuilder {
  66. const organization = useOrganization({allowNull: true}); // Some parts of the app, like the main sidebar, render even if the organization isn't available (during loading, or at all).
  67. const {view: currentView} = useDomainViewFilters();
  68. if (!organization) {
  69. // If there isn't an organization, items that link to modules won't be visible, so this is a fallback just-in-case, and isn't trying too hard to be useful
  70. return () => '';
  71. }
  72. const {slug} = organization;
  73. return function (moduleName: RoutableModuleNames, domainView?: DomainView) {
  74. let view = detectDomainView ? currentView : currentView ?? domainView;
  75. if (!view) {
  76. view = getModuleView(moduleName as ModuleName);
  77. }
  78. return bare
  79. ? `${DOMAIN_VIEW_BASE_URL}/${view}/${MODULE_BASE_URLS[moduleName]}`
  80. : normalizeUrl(
  81. `/organizations/${slug}/${DOMAIN_VIEW_BASE_URL}/${view}/${MODULE_BASE_URLS[moduleName]}`
  82. );
  83. };
  84. }