utils.tsx 8.5 KB

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