savedSearches.tsx 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  2. import {Client} from 'sentry/api';
  3. import {MAX_AUTOCOMPLETE_RECENT_SEARCHES} from 'sentry/constants';
  4. import {t} from 'sentry/locale';
  5. import SavedSearchesStore from 'sentry/stores/savedSearchesStore';
  6. import {
  7. RecentSearch,
  8. SavedSearch,
  9. SavedSearchType,
  10. SavedSearchVisibility,
  11. } from 'sentry/types';
  12. import handleXhrErrorResponse from 'sentry/utils/handleXhrErrorResponse';
  13. export function resetSavedSearches() {
  14. SavedSearchesStore.onReset();
  15. }
  16. export function fetchSavedSearches(api: Client, orgSlug: string): Promise<SavedSearch[]> {
  17. const url = `/organizations/${orgSlug}/searches/`;
  18. SavedSearchesStore.onStartFetchSavedSearches();
  19. const promise = api.requestPromise(url, {
  20. method: 'GET',
  21. });
  22. promise
  23. .then(resp => {
  24. SavedSearchesStore.onFetchSavedSearchesSuccess(resp);
  25. })
  26. .catch(err => {
  27. SavedSearchesStore.onFetchSavedSearchesError(err);
  28. addErrorMessage(t('Unable to load saved searches'));
  29. });
  30. return promise;
  31. }
  32. const getRecentSearchUrl = (orgSlug: string): string =>
  33. `/organizations/${orgSlug}/recent-searches/`;
  34. /**
  35. * Saves search term for `user` + `orgSlug`
  36. *
  37. * @param api API client
  38. * @param orgSlug Organization slug
  39. * @param type Context for where search happened, 0 for issue, 1 for event
  40. * @param query The search term that was used
  41. */
  42. export function saveRecentSearch(
  43. api: Client,
  44. orgSlug: string,
  45. type: SavedSearchType,
  46. query: string
  47. ): Promise<SavedSearch> {
  48. const url = getRecentSearchUrl(orgSlug);
  49. const promise = api.requestPromise(url, {
  50. method: 'POST',
  51. data: {
  52. query,
  53. type,
  54. },
  55. });
  56. promise.catch(handleXhrErrorResponse('Unable to save a recent search'));
  57. return promise;
  58. }
  59. /**
  60. * Creates a saved search
  61. *
  62. * @param api API client
  63. * @param orgSlug Organization slug
  64. * @param name Saved search name
  65. * @param query Query to save
  66. */
  67. export function createSavedSearch(
  68. api: Client,
  69. orgSlug: string,
  70. name: string,
  71. query: string,
  72. sort: string | null,
  73. visibility: SavedSearchVisibility
  74. ): Promise<SavedSearch> {
  75. const promise = api.requestPromise(`/organizations/${orgSlug}/searches/`, {
  76. method: 'POST',
  77. data: {
  78. type: SavedSearchType.ISSUE,
  79. query,
  80. name,
  81. sort,
  82. visibility,
  83. },
  84. });
  85. // Need to wait for saved search to save unfortunately because we need to redirect
  86. // to saved search URL
  87. promise.then(resp => {
  88. SavedSearchesStore.onCreateSavedSearchSuccess(resp);
  89. });
  90. return promise;
  91. }
  92. /**
  93. * Fetches a list of recent search terms conducted by `user` for `orgSlug`
  94. *
  95. * @param api API client
  96. * @param orgSlug Organization slug
  97. * @param type Context for where search happened, 0 for issue, 1 for event
  98. * @param query A query term used to filter results
  99. *
  100. * @return Returns a list of objects of recent search queries performed by user
  101. */
  102. export function fetchRecentSearches(
  103. api: Client,
  104. orgSlug: string,
  105. type: SavedSearchType,
  106. query?: string
  107. ): Promise<RecentSearch[]> {
  108. const url = getRecentSearchUrl(orgSlug);
  109. const promise = api.requestPromise(url, {
  110. query: {
  111. query,
  112. type,
  113. limit: MAX_AUTOCOMPLETE_RECENT_SEARCHES,
  114. },
  115. });
  116. promise.catch(resp => {
  117. if (resp.status !== 401 && resp.status !== 403) {
  118. handleXhrErrorResponse('Unable to fetch recent searches')(resp);
  119. }
  120. });
  121. return promise;
  122. }
  123. const getPinSearchUrl = (orgSlug: string): string =>
  124. `/organizations/${orgSlug}/pinned-searches/`;
  125. export function pinSearch(
  126. api: Client,
  127. orgSlug: string,
  128. type: SavedSearchType,
  129. query: string,
  130. sort?: string
  131. ): Promise<SavedSearch> {
  132. const url = getPinSearchUrl(orgSlug);
  133. // Optimistically update store
  134. SavedSearchesStore.onPinSearch(type, query, sort);
  135. const promise = api.requestPromise(url, {
  136. method: 'PUT',
  137. data: {
  138. query,
  139. type,
  140. sort,
  141. },
  142. });
  143. promise.then(SavedSearchesStore.onPinSearchSuccess);
  144. promise.catch(handleXhrErrorResponse('Unable to pin search'));
  145. promise.catch(() => {
  146. SavedSearchesStore.onUnpinSearch(type);
  147. });
  148. return promise;
  149. }
  150. export function unpinSearch(
  151. api: Client,
  152. orgSlug: string,
  153. type: SavedSearchType,
  154. pinnedSearch: SavedSearch
  155. ) {
  156. const url = getPinSearchUrl(orgSlug);
  157. // Optimistically update store
  158. SavedSearchesStore.onUnpinSearch(type);
  159. const promise = api.requestPromise(url, {
  160. method: 'DELETE',
  161. data: {
  162. type,
  163. },
  164. });
  165. promise.catch(handleXhrErrorResponse('Unable to un-pin search'));
  166. promise.catch(() => {
  167. const {type: pinnedType, query} = pinnedSearch;
  168. SavedSearchesStore.onPinSearch(pinnedType, query);
  169. });
  170. return promise;
  171. }
  172. /**
  173. * Send a DELETE request to remove a saved search
  174. *
  175. * @param api API client
  176. * @param orgSlug Organization slug
  177. * @param search The search to remove.
  178. */
  179. export function deleteSavedSearch(
  180. api: Client,
  181. orgSlug: string,
  182. search: SavedSearch
  183. ): Promise<void> {
  184. const url = `/organizations/${orgSlug}/searches/${search.id}/`;
  185. const promise = api
  186. .requestPromise(url, {
  187. method: 'DELETE',
  188. })
  189. .then(() => SavedSearchesStore.onDeleteSavedSearchSuccess(search))
  190. .catch(handleXhrErrorResponse('Unable to delete a saved search'));
  191. return promise;
  192. }