dashboards.tsx 5.4 KB

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