<commit_before>import React from 'react';

import FormState from './state';
import {t} from '../../locale';

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      formData: Object.assign({}, this.props.initialData),
      errors: {}
    };
    ['onSubmit', 'onFieldChange'].forEach(f => {
      this[f] = this[f].bind(this);
    });
  }

  onSubmit(e) {
    e.preventDefault();
    this.props.onSubmit && this.props.onSubmit(this.state.formData);
  }

  onFieldChange(name, value) {
    let formData = this.state.formData;
    formData[name] = value;
    this.setState({
      formData: formData
    });
  }

  render() {
    let isSaving = this.state.state === FormState.SAVING;
    let {formData, errors} = this.state;
    return (
      <form onSubmit={this.onSubmit} className={this.props.className}>
        {this.state.state === FormState.ERROR &&
          <div className="alert alert-error alert-block">
            {t(
              'Unable to save your changes. Please ensure all fields are valid and try again.'
            )}
          </div>}
        <fieldset>
          {this.props.fields.map(config => {
            return (
              <config.component
                key={`field_${config.name}`}
                {...config}
                value={formData[config.name]}
                error={errors[config.name]}
                onChange={this.onFieldChange.bind(this, config.name)}
              />
            );
          })}
        </fieldset>
        {this.props.children}
        <div className={this.props.footerClass} style={{marginTop: 25}}>
          <button
            className="btn btn-primary"
            disabled={isSaving || this.props.submitDisabled}
            type="submit">
            {this.props.submitLabel}
          </button>
          {this.props.extraButton}
        </div>
      </form><commit_msg>ui: gracefully handle missing fields property<commit_after>import React from 'react';

import FormState from './state';
import {t} from '../../locale';

class Form extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      formData: Object.assign({}, this.props.initialData),
      errors: {}
    };
    ['onSubmit', 'onFieldChange'].forEach(f => {
      this[f] = this[f].bind(this);
    });
  }

  onSubmit(e) {
    e.preventDefault();
    this.props.onSubmit && this.props.onSubmit(this.state.formData);
  }

  onFieldChange(name, value) {
    let formData = this.state.formData;
    formData[name] = value;
    this.setState({
      formData: formData
    });
  }

  render() {
    let isSaving = this.state.state === FormState.SAVING;
    let {formData, errors} = this.state;
    return (
      <form onSubmit={this.onSubmit} className={this.props.className}>
        {this.state.state === FormState.ERROR &&
          <div className="alert alert-error alert-block">
            {t(
              'Unable to save your changes. Please ensure all fields are valid and try again.'
            )}
          </div>}
        <fieldset>
          {(this.props.fields || []).map(config => {
            return (
              <config.component
                key={`field_${config.name}`}
                {...config}
                value={formData[config.name]}
                error={errors[config.name]}
                onChange={this.onFieldChange.bind(this, config.name)}
              />
            );
          })}
        </fieldset>
        {this.props.children}
        <div className={this.props.footerClass} style={{marginTop: 25}}>
          <button
            className="btn btn-primary"
            disabled={isSaving || this.props.submitDisabled}
            type="submit">
            {this.props.submitLabel}
          </button>
          {this.props.extraButton}
        </div>
      </form>
{'fraction_non_alphanumeric': 0.1459417273673257, 'fraction_numerical': 0.001040582726326743, 'mean_word_length': 1.930640243902439, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6267844', 'n_tokens_mistral': 1118, 'n_tokens_neox': 1104, 'n_words': 211}