createSavedSearchModal.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import {useState} from 'react';
  2. import {addLoadingMessage, clearIndicators} from 'sentry/actionCreators/indicator';
  3. import {ModalRenderProps} from 'sentry/actionCreators/modal';
  4. import {Alert} from 'sentry/components/alert';
  5. import {Form} from 'sentry/components/forms';
  6. import {OnSubmitCallback} from 'sentry/components/forms/types';
  7. import {SavedSearchModalContent} from 'sentry/components/modals/savedSearchModal/savedSearchModalContent';
  8. import {t} from 'sentry/locale';
  9. import {Organization, SavedSearchType, SavedSearchVisibility} from 'sentry/types';
  10. import {trackAnalytics} from 'sentry/utils/analytics';
  11. import {useCreateSavedSearch} from 'sentry/views/issueList/mutations/useCreateSavedSearch';
  12. import {IssueSortOptions} from 'sentry/views/issueList/utils';
  13. interface CreateSavedSearchModalProps extends ModalRenderProps {
  14. organization: Organization;
  15. query: string;
  16. sort?: string;
  17. }
  18. function validateSortOption({
  19. sort,
  20. organization,
  21. }: {
  22. organization: Organization;
  23. sort?: string;
  24. }) {
  25. const hasBetterPrioritySort = organization.features.includes(
  26. 'issue-list-better-priority-sort'
  27. );
  28. const sortOptions = [
  29. ...(hasBetterPrioritySort ? [IssueSortOptions.BETTER_PRIORITY] : []), // show better priority for EA orgs
  30. IssueSortOptions.DATE,
  31. IssueSortOptions.NEW,
  32. ...(hasBetterPrioritySort ? [] : [IssueSortOptions.PRIORITY]), // hide regular priority for EA orgs
  33. IssueSortOptions.FREQ,
  34. IssueSortOptions.USER,
  35. ];
  36. if (sortOptions.find(option => option === sort)) {
  37. return sort as string;
  38. }
  39. return IssueSortOptions.DATE;
  40. }
  41. export function CreateSavedSearchModal({
  42. Header,
  43. Body,
  44. closeModal,
  45. organization,
  46. query,
  47. sort,
  48. }: CreateSavedSearchModalProps) {
  49. const [error, setError] = useState(null);
  50. const {mutateAsync: createSavedSearch} = useCreateSavedSearch();
  51. const initialData = {
  52. name: '',
  53. query,
  54. sort: validateSortOption({sort, organization}),
  55. visibility: SavedSearchVisibility.OWNER,
  56. };
  57. const handleSubmit: OnSubmitCallback = async (
  58. data,
  59. onSubmitSuccess,
  60. onSubmitError,
  61. event
  62. ) => {
  63. event.preventDefault();
  64. setError(null);
  65. addLoadingMessage(t('Saving Changes'));
  66. trackAnalytics('search.saved_search_create', {
  67. name: data.name,
  68. organization,
  69. query: data.query,
  70. search_type: 'issues',
  71. sort: data.sort,
  72. visibility: data.visibility,
  73. });
  74. try {
  75. await createSavedSearch({
  76. orgSlug: organization.slug,
  77. name: data.name,
  78. query: data.query,
  79. sort: data.sort,
  80. type: SavedSearchType.ISSUE,
  81. visibility: data.visibility,
  82. });
  83. closeModal();
  84. clearIndicators();
  85. onSubmitSuccess(data);
  86. } catch (err) {
  87. clearIndicators();
  88. onSubmitError(
  89. err?.responseJSON?.detail
  90. ? err.responseJSON.detail
  91. : t('Unable to save your changes.')
  92. );
  93. }
  94. };
  95. return (
  96. <Form
  97. onSubmit={handleSubmit}
  98. onCancel={closeModal}
  99. saveOnBlur={false}
  100. initialData={initialData}
  101. submitLabel={t('Save')}
  102. onSubmitError={submitError => setError(submitError)}
  103. >
  104. <Header>
  105. <h4>{t('Create a Saved Search')}</h4>
  106. </Header>
  107. <Body>
  108. {error && <Alert type="error">{error}</Alert>}
  109. <SavedSearchModalContent organization={organization} />
  110. </Body>
  111. </Form>
  112. );
  113. }