modal.tsx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import * as React from 'react';
  2. import ModalActions from 'sentry/actions/modalActions';
  3. import type {ModalTypes} from 'sentry/components/globalModal';
  4. import type {DashboardWidgetModalOptions} from 'sentry/components/modals/addDashboardWidgetModal';
  5. import {DashboardWidgetLibraryModalOptions} from 'sentry/components/modals/dashboardWidgetLibraryModal';
  6. import type {DashboardWidgetQuerySelectorModalOptions} from 'sentry/components/modals/dashboardWidgetQuerySelectorModal';
  7. import {InviteRow} from 'sentry/components/modals/inviteMembersModal/types';
  8. import type {ReprocessEventModalOptions} from 'sentry/components/modals/reprocessEventModal';
  9. import {
  10. Group,
  11. IssueOwnership,
  12. Organization,
  13. Project,
  14. SentryApp,
  15. Team,
  16. } from 'sentry/types';
  17. import {AppStoreConnectStatusData, CustomRepoType} from 'sentry/types/debugFiles';
  18. import {Event} from 'sentry/types/event';
  19. export type ModalOptions = ModalTypes['options'];
  20. export type ModalRenderProps = ModalTypes['renderProps'];
  21. /**
  22. * Show a modal
  23. */
  24. export function openModal(
  25. renderer: (renderProps: ModalRenderProps) => React.ReactNode,
  26. options?: ModalOptions
  27. ) {
  28. ModalActions.openModal(renderer, options ?? {});
  29. }
  30. /**
  31. * Close modal
  32. */
  33. export function closeModal() {
  34. ModalActions.closeModal();
  35. }
  36. type OpenSudoModalOptions = {
  37. onClose?: () => void;
  38. superuser?: boolean;
  39. sudo?: boolean;
  40. retryRequest?: () => Promise<any>;
  41. };
  42. type emailVerificationModalOptions = {
  43. onClose?: () => void;
  44. emailVerified?: boolean;
  45. actionMessage?: string;
  46. };
  47. type inviteMembersModalOptions = {
  48. onClose?: () => void;
  49. initialData?: Partial<InviteRow>[];
  50. source?: string;
  51. };
  52. export async function openSudo({onClose, ...args}: OpenSudoModalOptions = {}) {
  53. const mod = await import('sentry/components/modals/sudoModal');
  54. const {default: Modal} = mod;
  55. openModal(deps => <Modal {...deps} {...args} />, {onClose});
  56. }
  57. export async function openEmailVerification({
  58. onClose,
  59. ...args
  60. }: emailVerificationModalOptions = {}) {
  61. const mod = await import('sentry/components/modals/emailVerificationModal');
  62. const {default: Modal} = mod;
  63. openModal(deps => <Modal {...deps} {...args} />, {onClose});
  64. }
  65. type OpenDiffModalOptions = {
  66. targetIssueId: string;
  67. project: Project;
  68. baseIssueId: Group['id'];
  69. orgId: Organization['id'];
  70. baseEventId?: Event['id'];
  71. targetEventId?: string;
  72. };
  73. export async function openDiffModal(options: OpenDiffModalOptions) {
  74. const mod = await import('sentry/components/modals/diffModal');
  75. const {default: Modal, modalCss} = mod;
  76. openModal(deps => <Modal {...deps} {...options} />, {modalCss});
  77. }
  78. type CreateTeamModalOptions = {
  79. /**
  80. * The organization to create a team for
  81. */
  82. organization: Organization;
  83. /**
  84. * An initial project to add the team to. This may be deprecated soon as we may add a project selection inside of the modal flow
  85. */
  86. project?: Project;
  87. onClose?: (team: Team) => void;
  88. };
  89. export async function openCreateTeamModal(options: CreateTeamModalOptions) {
  90. const mod = await import('sentry/components/modals/createTeamModal');
  91. const {default: Modal} = mod;
  92. openModal(deps => <Modal {...deps} {...options} />);
  93. }
  94. type CreateOwnershipRuleModalOptions = {
  95. /**
  96. * The organization to create a rules for
  97. */
  98. organization: Organization;
  99. /**
  100. * The project to create a rules for
  101. */
  102. project: Project;
  103. issueId: string;
  104. };
  105. export type EditOwnershipRulesModalOptions = {
  106. organization: Organization;
  107. project: Project;
  108. ownership: IssueOwnership;
  109. onSave: (text: string | null) => void;
  110. };
  111. export async function openCreateOwnershipRule(options: CreateOwnershipRuleModalOptions) {
  112. const mod = await import('sentry/components/modals/createOwnershipRuleModal');
  113. const {default: Modal, modalCss} = mod;
  114. openModal(deps => <Modal {...deps} {...options} />, {modalCss});
  115. }
  116. export async function openEditOwnershipRules(options: EditOwnershipRulesModalOptions) {
  117. const mod = await import('sentry/components/modals/editOwnershipRulesModal');
  118. const {default: Modal, modalCss} = mod;
  119. openModal(deps => <Modal {...deps} {...options} />, {backdrop: 'static', modalCss});
  120. }
  121. export async function openCommandPalette(options: ModalOptions = {}) {
  122. const mod = await import('sentry/components/modals/commandPalette');
  123. const {default: Modal, modalCss} = mod;
  124. openModal(deps => <Modal {...deps} {...options} />, {modalCss});
  125. }
  126. type RecoveryModalOptions = {
  127. authenticatorName: string;
  128. };
  129. export async function openRecoveryOptions(options: RecoveryModalOptions) {
  130. const mod = await import('sentry/components/modals/recoveryOptionsModal');
  131. const {default: Modal} = mod;
  132. openModal(deps => <Modal {...deps} {...options} />);
  133. }
  134. export type TeamAccessRequestModalOptions = {
  135. memberId: string;
  136. teamId: string;
  137. orgId: string;
  138. };
  139. export async function openTeamAccessRequestModal(options: TeamAccessRequestModalOptions) {
  140. const mod = await import('sentry/components/modals/teamAccessRequestModal');
  141. const {default: Modal} = mod;
  142. openModal(deps => <Modal {...deps} {...options} />);
  143. }
  144. export async function redirectToProject(newProjectSlug: string) {
  145. const mod = await import('sentry/components/modals/redirectToProject');
  146. const {default: Modal} = mod;
  147. openModal(deps => <Modal {...deps} slug={newProjectSlug} />, {});
  148. }
  149. type HelpSearchModalOptions = {
  150. organization?: Organization;
  151. placeholder?: string;
  152. };
  153. export async function openHelpSearchModal(options?: HelpSearchModalOptions) {
  154. const mod = await import('sentry/components/modals/helpSearchModal');
  155. const {default: Modal, modalCss} = mod;
  156. openModal(deps => <Modal {...deps} {...options} />, {modalCss});
  157. }
  158. export type SentryAppDetailsModalOptions = {
  159. sentryApp: SentryApp;
  160. isInstalled: boolean;
  161. onInstall: () => Promise<void>;
  162. organization: Organization;
  163. onCloseModal?: () => void; // used for analytics
  164. };
  165. type DebugFileSourceModalOptions = {
  166. sourceType: CustomRepoType;
  167. onSave: (data: Record<string, any>) => Promise<void>;
  168. appStoreConnectStatusData?: AppStoreConnectStatusData;
  169. onClose?: () => void;
  170. sourceConfig?: Record<string, any>;
  171. };
  172. export async function openDebugFileSourceModal({
  173. onClose,
  174. ...restOptions
  175. }: DebugFileSourceModalOptions) {
  176. const mod = await import('sentry/components/modals/debugFileCustomRepository');
  177. const {default: Modal, modalCss} = mod;
  178. openModal(deps => <Modal {...deps} {...restOptions} />, {
  179. modalCss,
  180. onClose,
  181. });
  182. }
  183. export async function openInviteMembersModal({
  184. onClose,
  185. ...args
  186. }: inviteMembersModalOptions = {}) {
  187. const mod = await import('sentry/components/modals/inviteMembersModal');
  188. const {default: Modal, modalCss} = mod;
  189. openModal(deps => <Modal {...deps} {...args} />, {modalCss, onClose});
  190. }
  191. export async function openAddDashboardWidgetModal(options: DashboardWidgetModalOptions) {
  192. const mod = await import('sentry/components/modals/addDashboardWidgetModal');
  193. const {default: Modal, modalCss} = mod;
  194. openModal(deps => <Modal {...deps} {...options} />, {backdrop: 'static', modalCss});
  195. }
  196. export async function openReprocessEventModal({
  197. onClose,
  198. ...options
  199. }: ReprocessEventModalOptions & {onClose?: () => void}) {
  200. const mod = await import('sentry/components/modals/reprocessEventModal');
  201. const {default: Modal} = mod;
  202. openModal(deps => <Modal {...deps} {...options} />, {onClose});
  203. }
  204. export async function demoSignupModal(options: ModalOptions = {}) {
  205. const mod = await import('sentry/components/modals/demoSignUp');
  206. const {default: Modal, modalCss} = mod;
  207. openModal(deps => <Modal {...deps} {...options} />, {modalCss});
  208. }
  209. export async function openDashboardWidgetQuerySelectorModal(
  210. options: DashboardWidgetQuerySelectorModalOptions
  211. ) {
  212. const mod = await import('sentry/components/modals/dashboardWidgetQuerySelectorModal');
  213. const {default: Modal, modalCss} = mod;
  214. openModal(deps => <Modal {...deps} {...options} />, {backdrop: 'static', modalCss});
  215. }
  216. export async function openDashboardWidgetLibraryModal(
  217. options: DashboardWidgetLibraryModalOptions
  218. ) {
  219. const mod = await import('sentry/components/modals/dashboardWidgetLibraryModal');
  220. const {default: Modal, modalCss} = mod;
  221. openModal(deps => <Modal {...deps} {...options} />, {backdrop: 'static', modalCss});
  222. }