1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- import {Children} from 'react';
- import {
- addErrorMessage,
- addLoadingMessage,
- clearIndicators,
- } from 'sentry/actionCreators/indicator';
- import {APIRequestMethod, Client} from 'sentry/api';
- import Form from 'sentry/components/deprecatedforms/form';
- import FormField from 'sentry/components/deprecatedforms/formField';
- import FormState from 'sentry/components/forms/state';
- import {t} from 'sentry/locale';
- type Props = Form['props'] & {
- apiEndpoint: string;
- apiMethod: APIRequestMethod;
- omitDisabled?: boolean;
- onSubmit?: (data: object) => void;
- submitErrorMessage?: string;
- submitLoadingMessage?: string;
- };
- export default class ApiForm extends Form<Props> {
- api = new Client();
- static defaultProps = {
- ...Form.defaultProps,
- omitDisabled: false, // TODO(chadwhitacre) Upstream, flip to true, deprecate.
- submitErrorMessage: t('There was an error saving your changes.'),
- submitLoadingMessage: t('Saving changes\u2026'),
- };
- componentWillUnmount() {
- this.api.clear();
- }
- getEnabledData() {
- // Return a hash of data from non-disabled fields.
- // Start with this.state.data and remove rather than starting from scratch
- // and adding, because a) this.state.data is our source of truth, and b)
- // we'd have to do more work to loop over the state.data Object and lookup
- // against the props.children Array (looping over the Array and looking up
- // in the Object is more natural). Maybe the consequent use of delete
- // carries a slight performance hit. Why is yer form so big? 🤔
- const data = {...this.state.data}; // Copy to avoid mutating state.data itself.
- Children.forEach(this.props.children, (child: any) => {
- if (!FormField.isPrototypeOf(child.type)) {
- return; // Form children include h4's, etc.
- }
- if (child.key && child.props?.disabled) {
- delete data[child.key]; // Assume a link between child.key and data. 🐭
- }
- });
- return data;
- }
- onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
- e.preventDefault();
- if (this.state.state === FormState.SAVING) {
- return;
- }
- // Actual HTML forms do not submit data for disabled fields, and because of
- // the way some of our APIs are implemented, we need to start doing the
- // same. But, since some other parts of the app very probably depend on
- // sending disabled fields, keep that the default for now.
- // TODO(chadwhitacre): Expand and upstream this.
- const data = this.props.omitDisabled ? this.getEnabledData() : this.state.data;
- this.props.onSubmit && this.props.onSubmit(data);
- this.setState(
- {
- state: FormState.SAVING,
- },
- () => {
- addLoadingMessage(this.props.submitLoadingMessage);
- this.api.request(this.props.apiEndpoint, {
- method: this.props.apiMethod,
- data,
- success: result => {
- clearIndicators();
- this.onSubmitSuccess(result);
- },
- error: error => {
- addErrorMessage(this.props.submitErrorMessage);
- this.onSubmitError(error);
- },
- });
- }
- );
- };
- }
|