issueListSetAsDefault.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import {Button} from 'sentry/components/button';
  2. import {removeSpace} from 'sentry/components/smartSearchBar/utils';
  3. import {IconBookmark} from 'sentry/icons';
  4. import {t} from 'sentry/locale';
  5. import {SavedSearchType} from 'sentry/types';
  6. import type {Organization} from 'sentry/types/organization';
  7. import {trackAnalytics} from 'sentry/utils/analytics';
  8. import {browserHistory} from 'sentry/utils/browserHistory';
  9. import {useLocation} from 'sentry/utils/useLocation';
  10. import useOrganization from 'sentry/utils/useOrganization';
  11. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  12. import {usePinSearch} from 'sentry/views/issueList/mutations/usePinSearch';
  13. import {useUnpinSearch} from 'sentry/views/issueList/mutations/useUnpinSearch';
  14. import {useFetchSavedSearchesForOrg} from 'sentry/views/issueList/queries/useFetchSavedSearchesForOrg';
  15. import {isDefaultIssueStreamSearch} from 'sentry/views/issueList/utils';
  16. import {useSelectedSavedSearch} from 'sentry/views/issueList/utils/useSelectedSavedSearch';
  17. interface IssueListSetAsDefaultProps {
  18. organization: Organization;
  19. query: string;
  20. sort: string;
  21. }
  22. const usePinnedSearch = () => {
  23. const organization = useOrganization();
  24. const {data: savedSearches} = useFetchSavedSearchesForOrg(
  25. {orgSlug: organization.slug},
  26. {notifyOnChangeProps: ['data']}
  27. );
  28. return savedSearches?.find(savedSearch => savedSearch.isPinned) ?? null;
  29. };
  30. function IssueListSetAsDefault({organization, sort, query}: IssueListSetAsDefaultProps) {
  31. const location = useLocation();
  32. const selectedSavedSearch = useSelectedSavedSearch();
  33. const pinnedSearch = usePinnedSearch();
  34. const pinnedSearchActive = selectedSavedSearch
  35. ? pinnedSearch?.id === selectedSavedSearch?.id
  36. : false;
  37. const {mutate: pinSearch, isLoading: isPinning} = usePinSearch({
  38. onSuccess: response => {
  39. const {cursor: _cursor, page: _page, ...currentQuery} = location.query;
  40. browserHistory.replace(
  41. normalizeUrl({
  42. ...location,
  43. pathname: `/organizations/${organization.slug}/issues/searches/${response.id}/`,
  44. query: {referrer: 'search-bar', ...currentQuery},
  45. })
  46. );
  47. },
  48. });
  49. const {mutate: unpinSearch, isLoading: isUnpinning} = useUnpinSearch({
  50. onSuccess: () => {
  51. const {cursor: _cursor, page: _page, ...currentQuery} = location.query;
  52. browserHistory.replace(
  53. normalizeUrl({
  54. ...location,
  55. pathname: `/organizations/${organization.slug}/issues/`,
  56. query: {
  57. referrer: 'search-bar',
  58. query,
  59. sort,
  60. ...currentQuery,
  61. },
  62. })
  63. );
  64. },
  65. });
  66. const onTogglePinnedSearch = () => {
  67. trackAnalytics('search.pin', {
  68. organization,
  69. action: pinnedSearch ? 'unpin' : 'pin',
  70. search_type: 'issues',
  71. query: pinnedSearch?.query ?? query,
  72. sort,
  73. });
  74. if (pinnedSearchActive) {
  75. unpinSearch({orgSlug: organization.slug, type: SavedSearchType.ISSUE});
  76. } else {
  77. pinSearch({
  78. orgSlug: organization.slug,
  79. type: SavedSearchType.ISSUE,
  80. query: removeSpace(query),
  81. sort,
  82. });
  83. }
  84. };
  85. // Hide if we are already on the default search,
  86. // except when the user has a different search pinned.
  87. if (
  88. isDefaultIssueStreamSearch({query, sort}) &&
  89. (!pinnedSearch || isDefaultIssueStreamSearch(pinnedSearch))
  90. ) {
  91. return null;
  92. }
  93. return (
  94. <Button
  95. onClick={onTogglePinnedSearch}
  96. size="sm"
  97. icon={<IconBookmark isSolid={pinnedSearchActive} />}
  98. disabled={isPinning || isUnpinning}
  99. >
  100. {pinnedSearchActive ? t('Remove Default') : t('Set as Default')}
  101. </Button>
  102. );
  103. }
  104. export default IssueListSetAsDefault;