issueActions.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import {Form, FormState} from 'sentry/components/deprecatedforms';
  2. import DefaultIssueActions from 'sentry/plugins/components/issueActions';
  3. import {Writable} from 'sentry/types';
  4. class IssueActions extends DefaultIssueActions {
  5. changeField = (
  6. action: DefaultIssueActions['props']['actionType'],
  7. name: string,
  8. value: any
  9. ) => {
  10. const key = this.getFormDataKey(action);
  11. const formData = {
  12. ...this.state[key],
  13. [name]: value,
  14. };
  15. const state: Pick<Writable<DefaultIssueActions['state']>, 'state' | typeof key> = {
  16. ...this.state,
  17. [key]: formData,
  18. };
  19. if (name === 'issuetype') {
  20. state.state = FormState.LOADING;
  21. this.setState(
  22. state,
  23. this.onLoad.bind(this, () => {
  24. this.api.request(
  25. this.getPluginCreateEndpoint() + '?issuetype=' + encodeURIComponent(value),
  26. {
  27. success: (data: DefaultIssueActions['state']['unlinkFieldList']) => {
  28. // Try not to change things the user might have edited
  29. // unless they're no longer valid
  30. const oldData = this.state.createFormData;
  31. const createFormData = {};
  32. data?.forEach(field => {
  33. let val;
  34. if (
  35. field.choices &&
  36. !field.choices.find(c => c[0] === oldData[field.name])
  37. ) {
  38. val = field.default;
  39. } else {
  40. val = oldData[field.name] || field.default;
  41. }
  42. createFormData[field.name] = val;
  43. });
  44. this.setState(
  45. {
  46. createFieldList: data,
  47. error: undefined,
  48. loading: false,
  49. createFormData,
  50. },
  51. this.onLoadSuccess
  52. );
  53. },
  54. error: this.errorHandler,
  55. }
  56. );
  57. })
  58. );
  59. return;
  60. }
  61. this.setState(state);
  62. };
  63. renderForm(): React.ReactNode {
  64. let form: React.ReactNode = null;
  65. // For create form, split into required and optional fields
  66. if (this.props.actionType === 'create') {
  67. if (this.state.createFieldList) {
  68. const renderField = field => {
  69. if (field.has_autocomplete) {
  70. field = Object.assign(
  71. {
  72. url:
  73. '/api/0/issues/' +
  74. this.getGroup().id +
  75. '/plugins/' +
  76. this.props.plugin.slug +
  77. '/autocomplete',
  78. },
  79. field
  80. );
  81. }
  82. return (
  83. <div key={field.name}>
  84. {this.renderField({
  85. config: field,
  86. formData: this.state.createFormData,
  87. onChange: this.changeField.bind(this, 'create', field.name),
  88. })}
  89. </div>
  90. );
  91. };
  92. const isRequired = f => (f.required !== null ? f.required : true);
  93. const fields = this.state.createFieldList;
  94. const requiredFields = fields.filter(f => isRequired(f)).map(f => renderField(f));
  95. const optionalFields = fields
  96. .filter(f => !isRequired(f))
  97. .map(f => renderField(f));
  98. form = (
  99. <Form onSubmit={this.createIssue} submitLabel="Create Issue" footerClass="">
  100. <h5>Required Fields</h5>
  101. {requiredFields}
  102. {optionalFields.length ? <h5>Optional Fields</h5> : null}
  103. {optionalFields}
  104. </Form>
  105. );
  106. }
  107. } else {
  108. form = super.renderForm();
  109. }
  110. return form;
  111. }
  112. }
  113. export default IssueActions;