dashboards.tsx 5.3 KB

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