utils.tsx 7.7 KB

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