utils.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import moment from 'moment-timezone';
  4. import {t} from 'sentry/locale';
  5. import plugins from 'sentry/plugins';
  6. import ConfigStore from 'sentry/stores/configStore';
  7. import space from 'sentry/styles/space';
  8. import {defined} from 'sentry/utils';
  9. const CONTEXT_TYPES = {
  10. default: require('sentry/components/events/contexts/default').default,
  11. app: require('sentry/components/events/contexts/app/app').default,
  12. device: require('sentry/components/events/contexts/device/device').default,
  13. os: require('sentry/components/events/contexts/operatingSystem/operatingSystem')
  14. .default,
  15. runtime: require('sentry/components/events/contexts/runtime/runtime').default,
  16. browser: require('sentry/components/events/contexts/browser/browser').default,
  17. user: require('sentry/components/events/contexts/user').default,
  18. gpu: require('sentry/components/events/contexts/gpu/gpu').default,
  19. trace: require('sentry/components/events/contexts/trace/trace').default,
  20. // 'redux.state' will be replaced with more generic context called 'state'
  21. 'redux.state': require('sentry/components/events/contexts/redux').default,
  22. state: require('sentry/components/events/contexts/state').default,
  23. };
  24. export function getContextComponent(type: string) {
  25. return CONTEXT_TYPES[type] || plugins.contexts[type] || CONTEXT_TYPES.default;
  26. }
  27. export function getSourcePlugin(pluginContexts: Array<any>, contextType: string) {
  28. if (CONTEXT_TYPES[contextType]) {
  29. return null;
  30. }
  31. for (const plugin of pluginContexts) {
  32. if (plugin.contexts.indexOf(contextType) >= 0) {
  33. return plugin;
  34. }
  35. }
  36. return null;
  37. }
  38. export function getRelativeTimeFromEventDateCreated(
  39. eventDateCreated: string,
  40. timestamp?: string,
  41. showTimestamp = true
  42. ) {
  43. if (!defined(timestamp)) {
  44. return timestamp;
  45. }
  46. const dateTime = moment(timestamp);
  47. if (!dateTime.isValid()) {
  48. return timestamp;
  49. }
  50. const relativeTime = `(${dateTime.from(eventDateCreated, true)} ${t(
  51. 'before this event'
  52. )})`;
  53. if (!showTimestamp) {
  54. return <RelativeTime>{relativeTime}</RelativeTime>;
  55. }
  56. return (
  57. <Fragment>
  58. {timestamp}
  59. <RelativeTime>{relativeTime}</RelativeTime>
  60. </Fragment>
  61. );
  62. }
  63. // Typescript doesn't have types for DisplayNames yet and that's why the type assertion "any" is needed below.
  64. // There is currently an open PR that intends to introduce the types https://github.com/microsoft/TypeScript/pull/44022
  65. export function getFullLanguageDescription(locale: string) {
  66. const sentryAppLanguageCode = ConfigStore.get('languageCode');
  67. const [languageAbbreviation, countryAbbreviation] = locale.includes('_')
  68. ? locale.split('_')
  69. : locale.split('-');
  70. try {
  71. const languageNames = new (Intl as any).DisplayNames(sentryAppLanguageCode, {
  72. type: 'language',
  73. });
  74. const languageName = languageNames.of(languageAbbreviation);
  75. if (countryAbbreviation) {
  76. const regionNames = new (Intl as any).DisplayNames(sentryAppLanguageCode, {
  77. type: 'region',
  78. });
  79. const countryName = regionNames.of(countryAbbreviation.toUpperCase());
  80. return `${languageName} (${countryName})`;
  81. }
  82. return languageName;
  83. } catch {
  84. return locale;
  85. }
  86. }
  87. const RelativeTime = styled('span')`
  88. color: ${p => p.theme.subText};
  89. margin-left: ${space(0.5)};
  90. `;