utils.tsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. import {
  2. deleteHomepageQuery,
  3. updateHomepageQuery,
  4. } from 'sentry/actionCreators/discoverHomepageQueries';
  5. import {
  6. createSavedQuery,
  7. deleteSavedQuery,
  8. updateSavedQuery,
  9. } from 'sentry/actionCreators/discoverSavedQueries';
  10. import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
  11. import {Client} from 'sentry/api';
  12. import {t} from 'sentry/locale';
  13. import {NewQuery, Organization, SavedQuery} from 'sentry/types';
  14. import {trackAnalyticsEvent} from 'sentry/utils/analytics';
  15. import {SaveQueryEventParameters} from 'sentry/utils/analytics/discoverAnalyticsEvents';
  16. import trackAdvancedAnalyticsEvent from 'sentry/utils/analytics/trackAdvancedAnalyticsEvent';
  17. import EventView from 'sentry/utils/discover/eventView';
  18. import {DisplayModes} from 'sentry/utils/discover/types';
  19. import {DisplayType} from 'sentry/views/dashboardsV2/types';
  20. export function handleCreateQuery(
  21. api: Client,
  22. organization: Organization,
  23. eventView: EventView,
  24. yAxis: string[],
  25. // True if this is a brand new query being saved
  26. // False if this is a modification from a saved query
  27. isNewQuery: boolean = true
  28. ): Promise<SavedQuery> {
  29. const payload = eventView.toNewQuery();
  30. payload.yAxis = yAxis;
  31. trackAdvancedAnalyticsEvent(getAnalyticsCreateEventKeyName(isNewQuery, 'request'), {
  32. organization,
  33. ...extractAnalyticsQueryFields(payload),
  34. });
  35. const promise = createSavedQuery(api, organization.slug, payload);
  36. promise
  37. .then((savedQuery: SavedQuery) => {
  38. addSuccessMessage(t('Query saved'));
  39. trackAdvancedAnalyticsEvent(getAnalyticsCreateEventKeyName(isNewQuery, 'success'), {
  40. organization,
  41. ...extractAnalyticsQueryFields(payload),
  42. });
  43. return savedQuery;
  44. })
  45. .catch((err: Error) => {
  46. addErrorMessage(t('Query not saved'));
  47. trackAdvancedAnalyticsEvent(getAnalyticsCreateEventKeyName(isNewQuery, 'failed'), {
  48. organization,
  49. ...extractAnalyticsQueryFields(payload),
  50. error:
  51. (err && err.message) ||
  52. `Could not save a ${isNewQuery ? 'new' : 'existing'} query`,
  53. });
  54. });
  55. return promise;
  56. }
  57. export function handleUpdateQuery(
  58. api: Client,
  59. organization: Organization,
  60. eventView: EventView,
  61. yAxis: string[]
  62. ): Promise<SavedQuery> {
  63. const payload = eventView.toNewQuery();
  64. payload.yAxis = yAxis;
  65. if (!eventView.name) {
  66. addErrorMessage(t('Please name your query'));
  67. return Promise.reject();
  68. }
  69. trackAdvancedAnalyticsEvent('discover_v2.update_query_request', {
  70. organization,
  71. ...extractAnalyticsQueryFields(payload),
  72. });
  73. const promise = updateSavedQuery(api, organization.slug, payload);
  74. promise
  75. .then((savedQuery: SavedQuery) => {
  76. addSuccessMessage(t('Query updated'));
  77. trackAdvancedAnalyticsEvent('discover_v2.update_query_success', {
  78. organization,
  79. ...extractAnalyticsQueryFields(payload),
  80. });
  81. // NOTE: there is no need to convert _saved into an EventView and push it
  82. // to the browser history, since this.props.eventView already
  83. // derives from location.
  84. return savedQuery;
  85. })
  86. .catch((err: Error) => {
  87. addErrorMessage(t('Query not updated'));
  88. trackAdvancedAnalyticsEvent('discover_v2.update_query_failed', {
  89. organization,
  90. ...extractAnalyticsQueryFields(payload),
  91. error: (err && err.message) || 'Failed to update a query',
  92. });
  93. });
  94. return promise;
  95. }
  96. /**
  97. * Essentially the same as handleUpdateQuery, but specifically for changing the
  98. * name of the query
  99. */
  100. export function handleUpdateQueryName(
  101. api: Client,
  102. organization: Organization,
  103. eventView: EventView
  104. ) {
  105. const payload = eventView.toNewQuery();
  106. trackAnalyticsEvent({
  107. eventKey: 'discover_v2.update_query_name_request',
  108. eventName: "Discoverv2: Request to update a saved query's name",
  109. organization_id: parseInt(organization.id, 10),
  110. ...extractAnalyticsQueryFields(payload),
  111. });
  112. const promise = updateSavedQuery(api, organization.slug, payload);
  113. promise
  114. .then(_saved => {
  115. addSuccessMessage(t('Query name saved'));
  116. trackAnalyticsEvent({
  117. eventKey: 'discover_v2.update_query_name_success',
  118. eventName: "Discoverv2: Successfully updated a saved query's name",
  119. organization_id: parseInt(organization.id, 10),
  120. ...extractAnalyticsQueryFields(payload),
  121. });
  122. })
  123. .catch((err: Error) => {
  124. addErrorMessage(t('Query name not saved'));
  125. trackAnalyticsEvent({
  126. eventKey: 'discover_v2.update_query_failed',
  127. eventName: "Discoverv2: Failed to update a saved query's name",
  128. organization_id: parseInt(organization.id, 10),
  129. ...extractAnalyticsQueryFields(payload),
  130. error: (err && err.message) || 'Failed to update a query name',
  131. });
  132. });
  133. return promise;
  134. }
  135. export function handleDeleteQuery(
  136. api: Client,
  137. organization: Organization,
  138. eventView: EventView
  139. ): Promise<void> {
  140. trackAnalyticsEvent({
  141. eventKey: 'discover_v2.delete_query_request',
  142. eventName: 'Discoverv2: Request to delete a saved query',
  143. organization_id: parseInt(organization.id, 10),
  144. ...extractAnalyticsQueryFields(eventView.toNewQuery()),
  145. });
  146. const promise = deleteSavedQuery(api, organization.slug, eventView.id!);
  147. promise
  148. .then(() => {
  149. addSuccessMessage(t('Query deleted'));
  150. trackAnalyticsEvent({
  151. eventKey: 'discover_v2.delete_query_success',
  152. eventName: 'Discoverv2: Successfully deleted a saved query',
  153. organization_id: parseInt(organization.id, 10),
  154. ...extractAnalyticsQueryFields(eventView.toNewQuery()),
  155. });
  156. })
  157. .catch((err: Error) => {
  158. addErrorMessage(t('Query not deleted'));
  159. trackAnalyticsEvent({
  160. eventKey: 'discover_v2.delete_query_failed',
  161. eventName: 'Discoverv2: Failed to delete a saved query',
  162. organization_id: parseInt(organization.id, 10),
  163. ...extractAnalyticsQueryFields(eventView.toNewQuery()),
  164. error: (err && err.message) || 'Failed to delete query',
  165. });
  166. });
  167. return promise;
  168. }
  169. export function handleUpdateHomepageQuery(
  170. api: Client,
  171. organization: Organization,
  172. query: NewQuery
  173. ) {
  174. const promise = updateHomepageQuery(api, organization.slug, query);
  175. return promise
  176. .then(savedQuery => {
  177. addSuccessMessage(t('Saved as Discover default'));
  178. return savedQuery;
  179. })
  180. .catch(() => {
  181. addErrorMessage(t('Unable to set query as Discover default'));
  182. });
  183. }
  184. export function handleResetHomepageQuery(api: Client, organization: Organization) {
  185. const promise = deleteHomepageQuery(api, organization.slug);
  186. return promise
  187. .then(() => {
  188. addSuccessMessage(t('Successfully removed Discover default'));
  189. })
  190. .catch(() => {
  191. addErrorMessage(t('Unable to remove Discover default'));
  192. });
  193. }
  194. export function getAnalyticsCreateEventKeyName(
  195. // True if this is a brand new query being saved
  196. // False if this is a modification from a saved query
  197. isNewQuery: boolean,
  198. type: 'request' | 'success' | 'failed'
  199. ): keyof SaveQueryEventParameters {
  200. return (
  201. isNewQuery
  202. ? 'discover_v2.save_new_query_' + type
  203. : 'discover_v2.save_existing_query_' + type
  204. ) as keyof SaveQueryEventParameters;
  205. }
  206. /**
  207. * Takes in a DiscoverV2 NewQuery object and returns a Partial containing
  208. * the desired fields to populate into reload analytics
  209. */
  210. export function extractAnalyticsQueryFields(payload: NewQuery): Partial<NewQuery> {
  211. const {projects, fields, query} = payload;
  212. return {
  213. projects,
  214. fields,
  215. query,
  216. };
  217. }
  218. export function displayModeToDisplayType(displayMode: DisplayModes): DisplayType {
  219. switch (displayMode) {
  220. case DisplayModes.BAR:
  221. return DisplayType.BAR;
  222. case DisplayModes.WORLDMAP:
  223. return DisplayType.WORLD_MAP;
  224. case DisplayModes.TOP5:
  225. return DisplayType.TOP_N;
  226. default:
  227. return DisplayType.LINE;
  228. }
  229. }