IanGallacher/SC2-AI-Website

View on GitHub
client-src/js/component/form-zone.jsx

Summary

Maintainability
B
6 hrs
Test Coverage
import axios from "axios";
import React from "react";
import PropTypes from "prop-types";

import AlertLogic from "./../logic/alert.js";
import { API_URL } from "./../app.js";

export default class FormZone extends React.Component {
  constructor(props) {
    super(props);
    this.state = { errors: [] };
    this.form_values = {};
  }

  static propTypes = {
    children: PropTypes.array,
    uploadPath: PropTypes.string,
    method: PropTypes.string.isRequired
  }

  componentDidMount() {
    // Make sure we have a form_value for each child object.
    if(this.props.children) React.Children.forEach(child => {
      if(child.props.group)
        this.form_values[child.props.group] = [];
      else
        this.form_values[child.props.name] = "";
    });
  }

  onChange = event => {
    var group = event.target.getAttribute("group");
    if(group) {
      var obj = {[event.target.name]: Number(event.target.value)};
      this.form_values[group][event.target.getAttribute("id")] = obj;
    }
    else { this.form_values[event.target.name] = this.getEventValue(event); }
  }

  getEventValue = event => {
    if (event.target.files) return event.target.files[0];
    else return event.target.value;
  }

  onSubmit = event => {
    event.preventDefault();
    this.fileUpload(this.form_values);
  }

  fileUpload = data => {
    // Configure upload.
    const url = API_URL + this.props.uploadPath;
    const formData = new FormData();
    Object.keys(this.form_values).forEach((key) => {
      var d = data[key];
      if(typeof(data[key]) === "object" && key != "file") {
        d = JSON.stringify(data[key]);
      }
      formData.append(key, d);
    });
    const config = { headers: { "content-type": "multipart/form-data" } };
    // Submit the upload
    axios[this.props.method](url, formData, config)
      .then(() => AlertLogic.addSuccess("Upload successful!"))
      .catch(error => this.setState({errors: error.response.data}));
  }

  render() {
    const children = this.props.children;
    // We have to do this at render time to make sure we get the most up to date
    // state of all children.
    var childrenWithProps = React.Children.map(children, child =>
      React.cloneElement(child, {
        onChange: this.onChange, error: this.state.errors[child.name]
      })
    );
    return <form onSubmit={this.onSubmit} className="flex-vertical">
      { childrenWithProps }
      <input type="submit" value="Submit" className="btn"/>
    </form>;
  }
}