createBroadcastModal.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import {useCallback} from 'react';
  2. import moment from 'moment-timezone';
  3. import {addErrorMessage, addLoadingMessage} from 'sentry/actionCreators/indicator';
  4. import type {ModalRenderProps} from 'sentry/actionCreators/modal';
  5. import FieldFromConfig from 'sentry/components/forms/fieldFromConfig';
  6. import Form from 'sentry/components/forms/form';
  7. import type {Field, OnSubmitCallback} from 'sentry/components/forms/types';
  8. import type {Broadcast} from 'sentry/types/system';
  9. import {useMutation} from 'sentry/utils/queryClient';
  10. import {safeURL} from 'sentry/utils/url/safeURL';
  11. import useApi from 'sentry/utils/useApi';
  12. import {useNavigate} from 'sentry/utils/useNavigate';
  13. interface CreateBroadcastModal extends ModalRenderProps {
  14. fields: Field[];
  15. }
  16. export function CreateBroadcastModal({
  17. Header,
  18. Body,
  19. closeModal,
  20. fields,
  21. }: CreateBroadcastModal) {
  22. const navigate = useNavigate();
  23. const api = useApi();
  24. const {mutate: updateBroadcast} = useMutation({
  25. mutationFn: (data: Broadcast) => {
  26. return api.requestPromise(`/broadcasts/`, {
  27. method: 'POST',
  28. data,
  29. });
  30. },
  31. onSuccess: (data: Broadcast) => {
  32. navigate(`/_admin/broadcasts/${data.id}/`);
  33. },
  34. onError: () => {
  35. addErrorMessage('An error occurred while submitting this form.');
  36. },
  37. });
  38. const handleSubmit: OnSubmitCallback = useCallback(
  39. (data, _onSubmitSuccess, onSubmitError) => {
  40. addLoadingMessage('Saving form\u2026');
  41. const errors: Partial<Record<keyof Broadcast, [string]>> = {};
  42. if (!safeURL(data.link)) {
  43. errors.link = ['Invalid URL'];
  44. }
  45. if (data.mediaUrl && !safeURL(data.mediaUrl)) {
  46. errors.mediaUrl = ['Invalid image URL'];
  47. }
  48. if (Object.keys(errors).length) {
  49. onSubmitError({responseJSON: errors});
  50. return;
  51. }
  52. const newData = {
  53. ...(data as Broadcast),
  54. category: data.category || undefined,
  55. mediaUrl: data.mediaUrl || undefined,
  56. region: data.region || undefined,
  57. };
  58. updateBroadcast(newData);
  59. },
  60. [updateBroadcast]
  61. );
  62. return (
  63. <Form
  64. onSubmit={handleSubmit}
  65. onCancel={closeModal}
  66. saveOnBlur={false}
  67. initialData={{
  68. isActive: true,
  69. dateExpires: moment().add(7, 'days').format('YYYY-MM-DDTHH:mm'),
  70. }}
  71. submitLabel="Save"
  72. >
  73. <Header>
  74. <h4>Add Broadcast</h4>
  75. </Header>
  76. <Body>
  77. {fields.map(field => (
  78. <FieldFromConfig
  79. key={field.name}
  80. field={field}
  81. flexibleControlStateSize
  82. inline={false}
  83. stacked
  84. />
  85. ))}
  86. </Body>
  87. </Form>
  88. );
  89. }