globalSdkUpdateAlert.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import {Fragment, useCallback, useEffect, useState} from 'react';
  2. import {promptsCheck, promptsUpdate} from 'sentry/actionCreators/prompts';
  3. import Alert, {AlertProps} from 'sentry/components/alert';
  4. import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters';
  5. import {t} from 'sentry/locale';
  6. import SidebarPanelStore from 'sentry/stores/sidebarPanelStore';
  7. import {PageFilters, ProjectSdkUpdates} from 'sentry/types';
  8. import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
  9. import {promptIsDismissed} from 'sentry/utils/promptIsDismissed';
  10. import useApi from 'sentry/utils/useApi';
  11. import useOrganization from 'sentry/utils/useOrganization';
  12. import withPageFilters from 'sentry/utils/withPageFilters';
  13. import withSdkUpdates from 'sentry/utils/withSdkUpdates';
  14. import {SidebarPanelKey} from './sidebar/types';
  15. import Button from './button';
  16. interface InnerGlobalSdkSuggestionsProps extends AlertProps {
  17. sdkUpdates?: ProjectSdkUpdates[] | null;
  18. selection?: PageFilters;
  19. }
  20. function InnerGlobalSdkUpdateAlert(
  21. props: InnerGlobalSdkSuggestionsProps
  22. ): React.ReactElement | null {
  23. const api = useApi();
  24. const organization = useOrganization();
  25. const [showUpdateAlert, setShowUpdateAlert] = useState<boolean>(false);
  26. const handleSnoozePrompt = useCallback(() => {
  27. promptsUpdate(api, {
  28. organizationId: organization.id,
  29. feature: 'sdk_updates',
  30. status: 'snoozed',
  31. });
  32. trackAdvancedAnalyticsEvent('sdk_updates.snoozed', {organization});
  33. setShowUpdateAlert(false);
  34. }, [api, organization]);
  35. const handleReviewUpdatesClick = useCallback(() => {
  36. SidebarPanelStore.activatePanel(SidebarPanelKey.Broadcasts);
  37. trackAdvancedAnalyticsEvent('sdk_updates.clicked', {organization});
  38. }, []);
  39. useEffect(() => {
  40. trackAdvancedAnalyticsEvent('sdk_updates.seen', {organization});
  41. let isUnmounted = false;
  42. promptsCheck(api, {
  43. organizationId: organization.id,
  44. feature: 'sdk_updates',
  45. }).then(prompt => {
  46. if (isUnmounted) {
  47. return;
  48. }
  49. setShowUpdateAlert(!promptIsDismissed(prompt));
  50. });
  51. return () => {
  52. isUnmounted = true;
  53. };
  54. }, []);
  55. if (!showUpdateAlert || !props.sdkUpdates?.length) {
  56. return null;
  57. }
  58. // withSdkUpdates explicitly only queries My Projects. This means that when
  59. // looking at any projects outside of My Projects (like All Projects), this
  60. // will only show the updates relevant to the to user.
  61. const projectSpecificUpdates =
  62. props.selection?.projects?.length === 0 ||
  63. props.selection?.projects[0] === ALL_ACCESS_PROJECTS
  64. ? props.sdkUpdates
  65. : props.sdkUpdates.filter(update =>
  66. props.selection?.projects?.includes(parseInt(update.projectId, 10))
  67. );
  68. // Check if we have at least one suggestion out of the list of updates
  69. if (projectSpecificUpdates.every(v => v.suggestions.length === 0)) {
  70. return null;
  71. }
  72. return (
  73. <Alert
  74. type="info"
  75. showIcon
  76. trailingItems={
  77. <Fragment>
  78. <Button
  79. priority="link"
  80. size="zero"
  81. title={t('Dismiss for the next two weeks')}
  82. onClick={handleSnoozePrompt}
  83. >
  84. {t('Remind me later')}
  85. </Button>
  86. <span>|</span>
  87. <Button priority="link" size="zero" onClick={handleReviewUpdatesClick}>
  88. {t('Review updates')}
  89. </Button>
  90. </Fragment>
  91. }
  92. >
  93. {t(
  94. `You have outdated SDKs in your projects. Update them for important fixes and features.`
  95. )}
  96. </Alert>
  97. );
  98. }
  99. const WithSdkUpdatesGlobalSdkUpdateAlert = withSdkUpdates(
  100. withPageFilters(InnerGlobalSdkUpdateAlert)
  101. );
  102. export {
  103. WithSdkUpdatesGlobalSdkUpdateAlert as GlobalSdkUpdateAlert,
  104. InnerGlobalSdkUpdateAlert,
  105. };