dashboards.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. import omit from 'lodash/omit';
  2. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  3. import type {Client} from 'sentry/api';
  4. import {ALL_ACCESS_PROJECTS} from 'sentry/constants/pageFilters';
  5. import {t} from 'sentry/locale';
  6. import PageFiltersStore from 'sentry/stores/pageFiltersStore';
  7. import type {
  8. DashboardDetails,
  9. DashboardListItem,
  10. Widget,
  11. } from 'sentry/views/dashboards/types';
  12. import {flattenErrors} from 'sentry/views/dashboards/utils';
  13. export function fetchDashboards(api: Client, orgSlug: string) {
  14. const promise: Promise<DashboardListItem[]> = api.requestPromise(
  15. `/organizations/${orgSlug}/dashboards/`,
  16. {
  17. method: 'GET',
  18. query: {sort: 'myDashboardsAndRecentlyViewed'},
  19. }
  20. );
  21. promise.catch(response => {
  22. const errorResponse = response?.responseJSON ?? null;
  23. if (errorResponse) {
  24. const errors = flattenErrors(errorResponse, {});
  25. addErrorMessage(errors[Object.keys(errors)[0]]);
  26. } else {
  27. addErrorMessage(t('Unable to fetch dashboards'));
  28. }
  29. });
  30. return promise;
  31. }
  32. export function createDashboard(
  33. api: Client,
  34. orgSlug: string,
  35. newDashboard: DashboardDetails,
  36. duplicate?: boolean
  37. ): Promise<DashboardDetails> {
  38. const {title, widgets, projects, environment, period, start, end, filters, utc} =
  39. newDashboard;
  40. const promise: Promise<DashboardDetails> = api.requestPromise(
  41. `/organizations/${orgSlug}/dashboards/`,
  42. {
  43. method: 'POST',
  44. data: {
  45. title,
  46. widgets: widgets.map(widget => omit(widget, ['tempId'])),
  47. duplicate,
  48. projects,
  49. environment,
  50. period,
  51. start,
  52. end,
  53. filters,
  54. utc,
  55. },
  56. query: {
  57. project: projects,
  58. environment,
  59. },
  60. }
  61. );
  62. promise.catch(response => {
  63. const errorResponse = response?.responseJSON ?? null;
  64. if (errorResponse) {
  65. const errors = flattenErrors(errorResponse, {});
  66. addErrorMessage(errors[Object.keys(errors)[0]]);
  67. } else {
  68. addErrorMessage(t('Unable to create dashboard'));
  69. }
  70. });
  71. return promise;
  72. }
  73. export function updateDashboardVisit(
  74. api: Client,
  75. orgId: string,
  76. dashboardId: string | string[]
  77. ): Promise<void> {
  78. const promise = api.requestPromise(
  79. `/organizations/${orgId}/dashboards/${dashboardId}/visit/`,
  80. {
  81. method: 'POST',
  82. }
  83. );
  84. return promise;
  85. }
  86. export function fetchDashboard(
  87. api: Client,
  88. orgId: string,
  89. dashboardId: string
  90. ): Promise<DashboardDetails> {
  91. const promise: Promise<DashboardDetails> = api.requestPromise(
  92. `/organizations/${orgId}/dashboards/${dashboardId}/`,
  93. {
  94. method: 'GET',
  95. }
  96. );
  97. promise.catch(response => {
  98. const errorResponse = response?.responseJSON ?? null;
  99. if (errorResponse) {
  100. const errors = flattenErrors(errorResponse, {});
  101. addErrorMessage(errors[Object.keys(errors)[0]]);
  102. } else {
  103. addErrorMessage(t('Unable to load dashboard'));
  104. }
  105. });
  106. return promise;
  107. }
  108. export function updateDashboard(
  109. api: Client,
  110. orgId: string,
  111. dashboard: DashboardDetails
  112. ): Promise<DashboardDetails> {
  113. const {title, widgets, projects, environment, period, start, end, filters, utc} =
  114. dashboard;
  115. const data = {
  116. title,
  117. widgets: widgets.map(widget => omit(widget, ['tempId'])),
  118. projects,
  119. environment,
  120. period,
  121. start,
  122. end,
  123. filters,
  124. utc,
  125. };
  126. const promise: Promise<DashboardDetails> = api.requestPromise(
  127. `/organizations/${orgId}/dashboards/${dashboard.id}/`,
  128. {
  129. method: 'PUT',
  130. data,
  131. query: {
  132. project: projects,
  133. environment,
  134. },
  135. }
  136. );
  137. // We let the callers of `updateDashboard` handle adding a success message, so
  138. // that it can be more specific than just "Dashboard updated," but do the
  139. // error-handling here, since it doesn't depend on the caller's context
  140. promise.catch(response => {
  141. const errorResponse = response?.responseJSON ?? null;
  142. if (errorResponse) {
  143. const errors = flattenErrors(errorResponse, {});
  144. addErrorMessage(errors[Object.keys(errors)[0]]);
  145. } else {
  146. addErrorMessage(t('Unable to update dashboard'));
  147. }
  148. });
  149. return promise;
  150. }
  151. export function deleteDashboard(
  152. api: Client,
  153. orgId: string,
  154. dashboardId: string
  155. ): Promise<undefined> {
  156. const promise: Promise<undefined> = api.requestPromise(
  157. `/organizations/${orgId}/dashboards/${dashboardId}/`,
  158. {
  159. method: 'DELETE',
  160. }
  161. );
  162. promise.catch(response => {
  163. const errorResponse = response?.responseJSON ?? null;
  164. if (errorResponse) {
  165. const errors = flattenErrors(errorResponse, {});
  166. addErrorMessage(errors[Object.keys(errors)[0]]);
  167. } else {
  168. addErrorMessage(t('Unable to delete dashboard'));
  169. }
  170. });
  171. return promise;
  172. }
  173. export function validateWidget(
  174. api: Client,
  175. orgId: string,
  176. widget: Widget
  177. ): Promise<undefined> {
  178. const {selection} = PageFiltersStore.getState();
  179. const promise: Promise<undefined> = api.requestPromise(
  180. `/organizations/${orgId}/dashboards/widgets/`,
  181. {
  182. method: 'POST',
  183. data: widget,
  184. query: {
  185. // TODO: This should be replaced in the future with projects
  186. // when we save Dashboard page filters. This is being sent to
  187. // bypass validation when creating or updating dashboards
  188. project: [ALL_ACCESS_PROJECTS],
  189. environment: selection.environments,
  190. },
  191. }
  192. );
  193. return promise;
  194. }