Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[jsx/Form.js] new radio component! #5279

Closed
wants to merge 7 commits into from

Conversation

maltheism
Copy link
Member

@maltheism maltheism commented Oct 4, 2019

Brief summary of changes

  • I created a "radio" component for the form in LORIS.
  • The component is named: <RadioElement/>
  • Also it will resize well with the browser in the form!

Note: I kept the design simple for now.

Preview:
component_radio_example

Links to related tickets (GitHub, Redmine, ...)

Testing instructions (if applicable)

  1. Checkout PR.
  2. Add to a form.
  3. Test away!

Example replace modules/new_profile/jsx/NewProfileIndex.js with:

import Panel from 'Panel';
import Loader from 'Loader';
import swal from 'sweetalert2';

/**
 * New Profile Form
 *
 * Create a new profile form
 *
 * @author  Shen Wang
 * @version 1.0.0
 * */
class NewProfileIndex extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      configData: {},
      formData: {},
      newData: {},
      isLoaded: false,
      isCreated: false,
      error: false,
      radioValue: '',
    };
    this.handleSubmit = this.handleSubmit.bind(this);
    this.setFormData = this.setFormData.bind(this);
    this.fetchData = this.fetchData.bind(this);
    this.handleRadio = this.handleRadio.bind(this);
  }

  componentDidMount() {
    this.fetchData()
      .then(() => this.setState({isLoaded: true}));
  }

  /**
   * Retrieve data from the provided URL and save it in state
   *
   * @return {object}
   */
  fetchData() {
    return fetch(this.props.dataURL,
      {credentials: 'same-origin'})
      .then((resp) => resp.json())
      .then((data) => this.setState({configData: data.fieldOptions}))
      .catch((error) => {
        this.setState({error: true});
      });
  }
  /**
   * It checks the date of birth and Expected Date of Confinement,
   * the date fields must match.
   * If match, this function will return true.
   *
   * @return {boolean}
   */
  validateMatchDate() {
    let validate = false;
    const formData = this.state.formData;
    if (formData.dobDate !== formData.dobDateConfirm) {
      swal('Error!', 'Date of Birth fields must match', 'error');
    } else if (this.state.configData['edc'] === 'true' &&
      (formData.edcDate !== formData.edcDateConfirm)
    ) {
      swal('Error!', 'EDC fields must match', 'error');
    } else {
      validate = true;
    }
    return validate;
  }

  /**
   * Handles form submission
   *
   * @param {event} e - Form submission event
   */
  handleSubmit(e) {
    e.preventDefault();
    const match = this.validateMatchDate();
    if (!match) {
      this.setState({
        isCreated: false,
      });
    } else {
      let formData = this.state.formData;
      let formObject = new FormData();
      for (let key in formData) {
        if (formData[key] !== '') {
          formObject.append(key, formData[key]);
        }
      }
      formObject.append('fire_away', 'New Candidate');

      fetch(this.props.submitURL, {
        method: 'POST',
        cache: 'no-cache',
        credentials: 'same-origin',
        body: formObject,
      })
        .then((resp) => {
          if (resp.ok && resp.status === 201) {
            resp.json().then((data) => {
              this.setState({newData: data});
              this.setState({isCreated: true});
            });
          } else {
            resp.json().then((message) => {
              swal('Error!', message, 'error');
            });
          }
        })
        .catch((error) => {
          console.error(error);
        });
    }
  }

  /**
   * Set the form data based on state values of child elements/components
   *
   * @param {string} formElement - name of the selected element
   * @param {string} value - selected value for corresponding form element
   */
  setFormData(formElement, value) {
    let formData = Object.assign({}, this.state.formData);
    formData[formElement] = value;

    this.setState({formData: formData});
  }

  handleRadio(formElement, value) {
    const state = Object.assign({}, this.state);
    state.radioValue = value;
    this.setState(state);
  }

  render() {
    // If error occurs, return a message.
    if (this.state.error) {
      return <h3>An error occured while loading the page.</h3>;
    }

    // Waiting for async data to load
    if (!this.state.isLoaded) {
      return <Loader/>;
    }
    let profile = null;
    let edc = null;
    let pscid = null;
    let site = null;
    let minYear = this.state.configData.minYear;
    let maxYear = this.state.configData.maxYear;
    let dateFormat = this.state.configData.dobFormat;

    if (this.state.configData['edc'] === 'true') {
      edc =
        <div>
          <DateElement
            name = "edcDate"
            label = "Expected Date of Confinement"
            minYear = {minYear}
            maxYear = {maxYear}
            dateFormat = {dateFormat}
            onUserInput = {this.setFormData}
            value = {this.state.formData.edcDate}
            required = {true}
          />
          <DateElement
            name = "edcDateConfirm"
            label = "Confirm EDC"
            minYear = {minYear}
            maxYear = {maxYear}
            dateFormat = {dateFormat}
            onUserInput = {this.setFormData}
            value = {this.state.formData.edcDateConfirm}
            required = {true}
          />
        </div>;
    }
    if (this.state.configData['pscidSet'] === 'true') {
      pscid =
        <TextboxElement
          name = "pscid"
          label = "PSCID"
          onUserInput = {this.setFormData}
          value = {this.state.formData.pscid}
          required = {true}
        />;
    }
    if (this.state.configData['site'] !== null) {
      site =
        <SelectElement
          name = "site"
          label = "Site"
          options = {this.state.configData.site}
          onUserInput = {this.setFormData}
          value = {this.state.formData.site}
          required = {true}
        />;
    }
    if (!this.state.isCreated) {
      profile = (
        <FormElement
          name = "newProfileForm"
          onSubmit = {this.handleSubmit}
        >
          <DateElement
            name = "dobDate"
            label = "Date of Birth"
            minYear = {minYear}
            maxYear = {maxYear}
            dateFormat = {dateFormat}
            onUserInput = {this.setFormData}
            value = {this.state.formData.dobDate}
            required = {true}
          />
          <DateElement
            name = "dobDateConfirm"
            label = "Date of Birth Confirm"
            minYear = {minYear}
            maxYear = {maxYear}
            dateFormat = {dateFormat}
            onUserInput = {this.setFormData}
            value = {this.state.formData.dobDateConfirm}
            required = {true}
          />
          {edc}
          <SelectElement
            name = "sex"
            label = "Sex"
            options = {this.state.configData.sex}
            onUserInput = {this.setFormData}
            value = {this.state.formData.sex}
            required = {true}
          />
          {site}
          {pscid}
          <SelectElement
            name = "project"
            label = "Project"
            options = {this.state.configData.project}
            onUserInput = {this.setFormData}
            value = {this.state.formData.project}
            required = {true}
          />
          <RadioElement
            name={'myRadio'}
            label={'Radio example'}
            id='myRadio'
            items={{
              Male: 'male',
              Female: 'female',
            }}
            value={this.state.radioValue}
            required={true}
            onUserInput={this.handleRadio}
          />
          <ButtonElement
            name = "fire_away"
            label = "Create"
            id = "button"
            type = "submit"
          />
        </FormElement>
      );
    } else {
      profile = (
        <div>
          <p>New candidate created. DCCID: {this.state.newData.candID} PSCID: {this.state.newData.pscid} </p>
          <p><a href = {'/' + this.state.newData.candID}> Access this candidate </a></p>
          <p><a href = "/new_profile/" > Recruit another candidate </a></p>
        </div>
      );
    }
    return (<Panel title="Create a new profile">{profile}</Panel>);
  }
}
window.addEventListener('load', () => {
  ReactDOM.render(
    <NewProfileIndex
      dataURL = {`${loris.BaseURL}/new_profile/?format=json`}
      submitURL = {`${loris.BaseURL}/new_profile/`}
      hasPermission = {loris.userHasPermission}
    />,
    document.getElementById('lorisworkspace')
  );
});

@maltheism maltheism added Feature PR or issue introducing/requiring at least one new feature UI PR or issue introducing/requiring improvements to the LORIS User Interface labels Oct 4, 2019
Copy link
Contributor

@zaliqarosli zaliqarosli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool! one request i have is to swap the radios and labels so that the label comes after the radio button. like the first example here

jsx/Form.js Outdated Show resolved Hide resolved
jsx/Form.js Outdated Show resolved Hide resolved
@maltheism
Copy link
Member Author

Hi @zaliqarosli, I added the requested changes and it's ready for review again. Thank you for the help!

jsx/Form.js Outdated Show resolved Hide resolved
jsx/Form.js Outdated Show resolved Hide resolved
zaliqarosli
zaliqarosli previously approved these changes Oct 21, 2019
Copy link
Contributor

@zaliqarosli zaliqarosli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks alizee! looks good!

@zaliqarosli zaliqarosli added the Passed Manual Tests PR has undergone proper testing by at least one peer label Oct 21, 2019
@driusan
Copy link
Collaborator

driusan commented Oct 25, 2019

This has conflicts since the Slider one was merged.

@maltheism
Copy link
Member Author

Hi @driusan, I fixed the conflicts.

@ridz1208 ridz1208 added the Needs Rebase PR contains conflicts with the current target branch or was issued to the wrong branch label Nov 6, 2019
@zaliqarosli
Copy link
Contributor

zaliqarosli commented Nov 21, 2019

i think this needs to be rebased to major? or is it master @ridz1208?

@ridz1208
Copy link
Collaborator

@zaliqarosli I would refrain from doing any rebasing right now. the branches will be shifted around once the release is out.

@maltheism
Copy link
Member Author

@zaliqarosli Please see #5846. Trouble rebasing and so I made a new PR.

@maltheism maltheism closed this Dec 9, 2019
@maltheism maltheism deleted the minor_new_component_radio branch May 24, 2020 02:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature PR or issue introducing/requiring at least one new feature Needs Rebase PR contains conflicts with the current target branch or was issued to the wrong branch Passed Manual Tests PR has undergone proper testing by at least one peer UI PR or issue introducing/requiring improvements to the LORIS User Interface
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants