dashboards.tsx 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. orgId: 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/${orgId}/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. },
  55. }
  56. );
  57. promise.catch(response => {
  58. const errorResponse = response?.responseJSON ?? null;
  59. if (errorResponse) {
  60. const errors = flattenErrors(errorResponse, {});
  61. addErrorMessage(errors[Object.keys(errors)[0]]);
  62. } else {
  63. addErrorMessage(t('Unable to create dashboard'));
  64. }
  65. });
  66. return promise;
  67. }
  68. export function updateDashboardVisit(
  69. api: Client,
  70. orgId: string,
  71. dashboardId: string | string[]
  72. ): Promise<void> {
  73. const promise = api.requestPromise(
  74. `/organizations/${orgId}/dashboards/${dashboardId}/visit/`,
  75. {
  76. method: 'POST',
  77. }
  78. );
  79. return promise;
  80. }
  81. export function fetchDashboard(
  82. api: Client,
  83. orgId: string,
  84. dashboardId: string
  85. ): Promise<DashboardDetails> {
  86. const promise: Promise<DashboardDetails> = api.requestPromise(
  87. `/organizations/${orgId}/dashboards/${dashboardId}/`,
  88. {
  89. method: 'GET',
  90. }
  91. );
  92. promise.catch(response => {
  93. const errorResponse = response?.responseJSON ?? null;
  94. if (errorResponse) {
  95. const errors = flattenErrors(errorResponse, {});
  96. addErrorMessage(errors[Object.keys(errors)[0]]);
  97. } else {
  98. addErrorMessage(t('Unable to load dashboard'));
  99. }
  100. });
  101. return promise;
  102. }
  103. export function updateDashboard(
  104. api: Client,
  105. orgId: string,
  106. dashboard: DashboardDetails
  107. ): Promise<DashboardDetails> {
  108. const {title, widgets, projects, environment, period, start, end, filters, utc} =
  109. dashboard;
  110. const data = {
  111. title,
  112. widgets: widgets.map(widget => omit(widget, ['tempId'])),
  113. projects,
  114. environment,
  115. period,
  116. start,
  117. end,
  118. filters,
  119. utc,
  120. };
  121. const promise: Promise<DashboardDetails> = api.requestPromise(
  122. `/organizations/${orgId}/dashboards/${dashboard.id}/`,
  123. {
  124. method: 'PUT',
  125. data,
  126. query: {
  127. project: projects,
  128. },
  129. }
  130. );
  131. // We let the callers of `updateDashboard` handle adding a success message, so
  132. // that it can be more specific than just "Dashboard updated," but do the
  133. // error-handling here, since it doesn't depend on the caller's context
  134. promise.catch(response => {
  135. const errorResponse = response?.responseJSON ?? null;
  136. if (errorResponse) {
  137. const errors = flattenErrors(errorResponse, {});
  138. addErrorMessage(errors[Object.keys(errors)[0]]);
  139. } else {
  140. addErrorMessage(t('Unable to update dashboard'));
  141. }
  142. });
  143. return promise;
  144. }
  145. export function deleteDashboard(
  146. api: Client,
  147. orgId: string,
  148. dashboardId: string
  149. ): Promise<undefined> {
  150. const promise: Promise<undefined> = api.requestPromise(
  151. `/organizations/${orgId}/dashboards/${dashboardId}/`,
  152. {
  153. method: 'DELETE',
  154. }
  155. );
  156. promise.catch(response => {
  157. const errorResponse = response?.responseJSON ?? null;
  158. if (errorResponse) {
  159. const errors = flattenErrors(errorResponse, {});
  160. addErrorMessage(errors[Object.keys(errors)[0]]);
  161. } else {
  162. addErrorMessage(t('Unable to delete dashboard'));
  163. }
  164. });
  165. return promise;
  166. }
  167. export function validateWidget(
  168. api: Client,
  169. orgId: string,
  170. widget: Widget
  171. ): Promise<undefined> {
  172. const {selection} = PageFiltersStore.getState();
  173. const promise: Promise<undefined> = api.requestPromise(
  174. `/organizations/${orgId}/dashboards/widgets/`,
  175. {
  176. method: 'POST',
  177. data: widget,
  178. query: {
  179. // TODO: This should be replaced in the future with projects
  180. // when we save Dashboard page filters. This is being sent to
  181. // bypass validation when creating or updating dashboards
  182. project: [ALL_ACCESS_PROJECTS],
  183. environment: selection.environments,
  184. },
  185. }
  186. );
  187. return promise;
  188. }