sentryFunctionDetails.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import React, {useRef} from 'react';
  2. import Editor from '@monaco-editor/react';
  3. import {
  4. addErrorMessage,
  5. addLoadingMessage,
  6. addSuccessMessage,
  7. } from 'sentry/actionCreators/indicator';
  8. import Feature from 'sentry/components/acl/feature';
  9. import AsyncComponent from 'sentry/components/asyncComponent';
  10. import Form from 'sentry/components/forms/form';
  11. import JsonForm from 'sentry/components/forms/jsonForm';
  12. import FormModel from 'sentry/components/forms/model';
  13. import {Field} from 'sentry/components/forms/type';
  14. import {Panel, PanelBody, PanelHeader} from 'sentry/components/panels';
  15. import {t} from 'sentry/locale';
  16. type Props = WrapperProps;
  17. const formFields: Field[] = [
  18. {
  19. name: 'name',
  20. type: 'string',
  21. required: true,
  22. placeholder: 'e.g. My Sentry Function',
  23. label: 'Name',
  24. help: 'Human readable name of your Sentry Function',
  25. },
  26. {
  27. name: 'author',
  28. type: 'string',
  29. placeholder: 'e.g. Acme Software',
  30. label: 'Author',
  31. help: 'The company or person who built and maintains this Sentry Function.',
  32. },
  33. {
  34. name: 'overview',
  35. type: 'string',
  36. placeholder: 'e.g. This Sentry Function does something useful',
  37. label: 'Overview',
  38. help: 'A short description of your Sentry Function.',
  39. },
  40. ];
  41. function SentryFunctionDetails(props: Props) {
  42. const form = useRef(new FormModel());
  43. const {orgId, functionSlug} = props.params;
  44. const method = functionSlug ? 'PUT' : 'POST';
  45. const endpoint = `/organizations/${orgId}/functions/`;
  46. const handleSubmitError = err => {
  47. let errorMessage = t('Unknown Error');
  48. if (err.status >= 400 && err.status < 500) {
  49. errorMessage = err?.responseJSON.detail ?? errorMessage;
  50. }
  51. addErrorMessage(errorMessage);
  52. };
  53. const handleSubmitSuccess = data => {
  54. addSuccessMessage(t('Sentry Function successfully saved.', data.name));
  55. };
  56. function handleEditorChange(value, _event) {
  57. form.current.setValue('code', value);
  58. }
  59. const defaultCode = `exports.yourFunction = (req, res) => {
  60. let message = req.query.message || req.body.message || 'Hello World!';
  61. console.log('Query: ' + req.query);
  62. console.log('Body: ' + req.body);
  63. res.status(200).send(message);
  64. };`;
  65. return (
  66. <div>
  67. <Feature features={['organizations:sentry-functions']}>
  68. <h1>{t('Sentry Function Details')}</h1>
  69. <h2>{props.params.orgId}</h2>
  70. <Form
  71. apiMethod={method}
  72. apiEndpoint={endpoint}
  73. model={form.current}
  74. onPreSubmit={() => {
  75. addLoadingMessage(t('Saving changes..'));
  76. }}
  77. onSubmitError={handleSubmitError}
  78. onSubmitSuccess={handleSubmitSuccess}
  79. >
  80. <JsonForm forms={[{title: t('Sentry Function Details'), fields: formFields}]} />
  81. <Panel>
  82. <PanelHeader>Write your Code Below</PanelHeader>
  83. <PanelBody>
  84. <Editor
  85. height="40vh"
  86. theme="light"
  87. defaultLanguage="javascript"
  88. defaultValue={defaultCode}
  89. onChange={handleEditorChange}
  90. options={{
  91. minimap: {
  92. enabled: false,
  93. },
  94. scrollBeyondLastLine: false,
  95. }}
  96. />
  97. </PanelBody>
  98. </Panel>
  99. </Form>
  100. </Feature>
  101. </div>
  102. );
  103. }
  104. type WrapperState = {} & AsyncComponent['state'];
  105. type WrapperProps = {
  106. params: {orgId: string; functionSlug?: string};
  107. } & AsyncComponent['props'];
  108. class SentryFunctionsWrapper extends AsyncComponent<WrapperProps, WrapperState> {
  109. renderBody() {
  110. return <SentryFunctionDetails {...this.props} />;
  111. }
  112. }
  113. export default SentryFunctionsWrapper;