savedSearches.tsx 5.4 KB

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