upgradeGrouping.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import {Fragment, useEffect} from 'react';
  2. import {Location} from 'history';
  3. import {addLoadingMessage, clearIndicators} from 'sentry/actionCreators/indicator';
  4. import ProjectActions from 'sentry/actions/projectActions';
  5. import {Client} from 'sentry/api';
  6. import Alert from 'sentry/components/alert';
  7. import Button from 'sentry/components/button';
  8. import {openConfirmModal} from 'sentry/components/confirm';
  9. import Field from 'sentry/components/forms/field';
  10. import {Panel, PanelBody, PanelHeader} from 'sentry/components/panels';
  11. import {t, tct} from 'sentry/locale';
  12. import {EventGroupingConfig, Organization, Project} from 'sentry/types';
  13. import handleXhrErrorResponse from 'sentry/utils/handleXhrErrorResponse';
  14. import marked from 'sentry/utils/marked';
  15. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  16. import {getGroupingChanges, getGroupingRisk} from './utils';
  17. const upgradeGroupingId = 'upgrade-grouping';
  18. type Props = {
  19. api: Client;
  20. groupingConfigs: EventGroupingConfig[];
  21. location: Location;
  22. onUpgrade: () => void;
  23. organization: Organization;
  24. project: Project;
  25. projectId: string;
  26. };
  27. function UpgradeGrouping({
  28. groupingConfigs,
  29. organization,
  30. projectId,
  31. project,
  32. onUpgrade,
  33. api,
  34. location,
  35. }: Props) {
  36. const hasProjectWriteAccess = organization.access.includes('project:write');
  37. const {updateNotes, riskLevel, latestGroupingConfig} = getGroupingChanges(
  38. project,
  39. groupingConfigs
  40. );
  41. const {riskNote, alertType} = getGroupingRisk(riskLevel);
  42. const noUpdates = !latestGroupingConfig;
  43. const priority = riskLevel >= 2 ? 'danger' : 'primary';
  44. useEffect(() => {
  45. if (
  46. location.hash !== `#${upgradeGroupingId}` ||
  47. noUpdates ||
  48. !groupingConfigs ||
  49. !hasProjectWriteAccess
  50. ) {
  51. return;
  52. }
  53. handleOpenConfirmModal();
  54. }, [location.hash]);
  55. if (!groupingConfigs) {
  56. return null;
  57. }
  58. async function handleConfirmUpgrade() {
  59. const newData: Record<string, string | number> = {};
  60. if (latestGroupingConfig) {
  61. const now = Math.floor(new Date().getTime() / 1000);
  62. const ninety_days = 3600 * 24 * 90;
  63. newData.groupingConfig = latestGroupingConfig.id;
  64. newData.secondaryGroupingConfig = project.groupingConfig;
  65. newData.secondaryGroupingExpiry = now + ninety_days;
  66. }
  67. addLoadingMessage(t('Changing grouping\u2026'));
  68. try {
  69. const response = await api.requestPromise(
  70. `/projects/${organization.slug}/${projectId}/`,
  71. {
  72. method: 'PUT',
  73. data: newData,
  74. }
  75. );
  76. clearIndicators();
  77. ProjectActions.updateSuccess(response);
  78. onUpgrade();
  79. } catch {
  80. handleXhrErrorResponse(t('Unable to upgrade config'));
  81. }
  82. }
  83. function handleOpenConfirmModal() {
  84. openConfirmModal({
  85. confirmText: t('Upgrade'),
  86. priority,
  87. onConfirm: handleConfirmUpgrade,
  88. message: (
  89. <Fragment>
  90. <TextBlock>
  91. <strong>{t('Upgrade Grouping Strategy')}</strong>
  92. </TextBlock>
  93. <TextBlock>
  94. {t(
  95. 'You can upgrade the grouping strategy to the latest but this is an irreversible operation.'
  96. )}
  97. </TextBlock>
  98. <TextBlock>
  99. <strong>{t('New Behavior')}</strong>
  100. <div dangerouslySetInnerHTML={{__html: marked(updateNotes)}} />
  101. </TextBlock>
  102. <TextBlock>
  103. <Alert type={alertType}>{riskNote}</Alert>
  104. </TextBlock>
  105. </Fragment>
  106. ),
  107. });
  108. }
  109. function getButtonTitle() {
  110. if (!hasProjectWriteAccess) {
  111. return t('You do not have sufficient permissions to do this');
  112. }
  113. if (noUpdates) {
  114. return t('You are already on the latest version');
  115. }
  116. return undefined;
  117. }
  118. return (
  119. <Panel id={upgradeGroupingId}>
  120. <PanelHeader>{t('Upgrade Grouping')}</PanelHeader>
  121. <PanelBody>
  122. <Field
  123. label={t('Upgrade Grouping Strategy')}
  124. help={tct(
  125. 'If the project uses an old grouping strategy an update is possible.[linebreak]Doing so will cause new events to group differently.',
  126. {
  127. linebreak: <br />,
  128. }
  129. )}
  130. disabled
  131. >
  132. <div>
  133. <Button
  134. onClick={handleOpenConfirmModal}
  135. disabled={!hasProjectWriteAccess || noUpdates}
  136. title={getButtonTitle()}
  137. type="button"
  138. priority={priority}
  139. >
  140. {t('Upgrade Grouping Strategy')}
  141. </Button>
  142. </div>
  143. </Field>
  144. </PanelBody>
  145. </Panel>
  146. );
  147. }
  148. export default UpgradeGrouping;