<commit_before><script type='text/jsx'>
  /** @jsx React.DOM */
  $(document).ready(function() {
  // Prevent the enter key from releasing grades
    preventEnterSubmit();
  });

  /** This function will prevent the default HTML5 action of submitting the content form
    *  when the user presses "enter". As an Admin user, this would release the grades.
    */
  function preventEnterSubmit() {
    $(document).keypress(function(event) {
      if (event.which === 13) {
        event.preventDefault();
      }
    });
  }

  /** Updates total marks cell. Called from Rails controller grade_entry_forms/update_grade to
    * check if a cell exists before updating it, as cell existence can't be efficiently
    * checked from the Ruby controller
    */
  function update_cell(cell, value) {
    // If the total marks cell exists, change it's value to the one supplied
    if (document.getElementById(cell)) {
      document.getElementById(cell).innerHTML = value;
      var e = new MouseEvent('click', {
        'view': window,
        'bubbles': true,
        'cancelable': false
      });
      var node = document.getElementById(cell);
      node.dispatchEvent(e);
    }
  }

  var GradeBoxTotal = React.createClass({
    handleChange: function() {
      this.props.value = parseFloat(event.target.value, 10);
    },
    render: function() {
      return(
        <span
        id={this.props.grade_id}
        size="4"
        className="grade-total"
        >
        {this.props.value}
        </span>
        );
    }
  });

  var GradeEntryBox = React.createClass({
    componentDidMount: function(){
        this.props.value = this.props.default_value;
    },
    handleChange: function(event) {
      var updated_grade = event.target.value === '' ? null : parseFloat(event.target.value);
      var params = {
        'updated_grade':       updated_grade,
        'student_id':          this.props.student_id,
        'grade_entry_item_id': this.props.grade_entry_column,
        'authenticity_token':  AUTH_TOKEN
      };
      $.ajax({
        url:  this.props.data_action,
        data: params,
        type: 'POST',
        dataType: 'script',
      });
      this.props.value = parseFloat(event.target.value);
    },

    // TODO: Make this nicer by not using raw Javascript and jQuery
    handleKeyPress: function(event) {
      if (event.key === 'Enter') {
        var input = this.getDOMNode();
        var td = input.parentNode;
        var tr = td.parentNode;
        var tdIndex = $(tr).children().index(td);
        if (tr.nextSibling !== null) {
          var nextInput = tr.nextSibling.childNodes[tdIndex].firstChild;
          $(nextInput).select()
        }
      }
    },

    render: function() {
      return (
        <input id={this.props.grade_id} type="text" size="4"
          className="grade-input" defaultValue={this.props.default_value}
          onChange={this.handleChange}
          onKeyPress={this.handleKeyPress} />
        );
    }
  });

  var GradesTable = React.createClass({
    getDefaultProps: function() {
      // Creates a new table with the columns defined below.
      // The first column will be the column initially sorted.
      var gradesTable = {
        columns: [
          {
            id: 'user_name',
            content: '<%= j raw I18n.t(:'user.user_name') %>',
            sortable: true,
            searchable: true
          },
          {
            id: 'last_name',
            content: '<%= j raw I18n.t(:'user.last_name') %>',
            sortable: true,
            searchable: true
          },
          {
            id: 'first_name',
            content: '<%= j raw I18n.t(:'user.first_name') %>',
            sortable: true,
            searchable: true
          }
        ],
        filters: [
        {
          name: 'all',
          text: '<%= j raw I18n.t(:'all') %>',
          func: function(student) {
            return true;
          }
        }]
      };
      if (<%= Section.any? %>) {
          gradesTable['columns'].push({
              id: 'section',
              content: '<%= Section.model_name.human %>',
              sortable: true
          });
      }
      return gradesTable;
    },
    getInitialState: function() {
      return {
        row_data: [],
        grade_columns:[],
        selected_students: [],
      }
    },
    updateSelectedStudents: function(students) {
      this.setState({selected_students: students});
    },
    componentWillMount: function() {
      this.refresh();
    },
    refresh: function() {
      document.getElementById('working').style.display = '';

      // Getting additional grade entry item columns
      $.ajax({
        url: 'get_mark_columns',
        method: 'GET',
        dataType: 'json',
        success: function(data) {
          this.setState({
            grade_columns: data,
          });
        }.bind(this),
        // Close working indicator.
        complete: function () {
          document.getElementById('working').style.display = 'none';
        }
      });
      // Getting row data
      $.ajax({
        url: 'populate_grades_table',
        method: 'GET',
        dataType: 'json',
        success: function(data) {
          this.setState({
            row_data: data,
          });
        }.bind(this),
        // Close working indicator.
        complete: function () {
          document.getElementById('working').style.display = 'none';
        }
      });
    },
    render: function() {
      // need to filter for each section
      var sections = <%= raw @sections.to_json %>;
      if (sections.length > 0) {
        var section_filters = sections.map(function(section) {
          var filter = {
            name: section.name,
            text: section.name,
            func: function(group) {
              return group.section === section.name;
            }
          }
          return filter;
        });
        var all = '<%= t('sections.all') %>';
        section_filters.unshift({name: all, text: all, func: null});
      }

      // Add grades and marking state columns to array of table columns
      var all_columns = this.props.columns.concat(this.state.grade_columns);

      // Set React Table data from JSON data
      var rows = this.state.row_data.map(function(row){
        var r = {};
        r['id'] = row.id
        r['user_name'] = row.user_name
        r['first_name'] = row.first_name
        r['last_name'] = row.last_name
        r['section'] = row.section

        this.state.grade_columns.map(function(column){
          var column_id = column.id;

          if (column_id === 'marking_state'){
            if(row[column_id]){
              r[column_id] = <img src={row[column_id]} alt="<%= t('marking_state.released') %>" title="<%= t('marking_state.released') %>"/>;
            }
          }

          else if (column_id === 'total_marks'){
            r[column_id] = <GradeBoxTotal grade_id={'grade_' + row.id + '_' + column.id}
                           grade_entry_column={column.id} student_id={row.id}
                           value={row[column_id]}/>;
          }
          else {
            r[column_id] =
              <GradeEntryBox
               grade_id={'grade_' + row.id + '_' + column.id}
               data_action=
                 "<%= update_grade_grade_entry_form_path(@grade_entry_form) %>"
               grade_entry_column={column.id}
               student_id={row.id}
               default_value={row[column_id]}/>
          }
        }.bind(this));
        return r;
      }.bind(this));
      return (
        <div>
          <GradesActionBox
            selected_students={this.state.selected_students}
            refresh={this.refresh} />
          <Table data={rows}
            search_placeholder={'<%= j raw I18n.t(:'students.search_students') %>'}
            selectable={true} // True if you want checkboxed elements
            onSelectedRowsChange={this.updateSelectedStudents}
            columns={all_columns}
            filters={section_filters}
            filter_type={true}
           />
        </div>
      );
    }
  });

  var GradesActionBox = React.createClass({
    propTypes: {
      selected_students: React.PropTypes.array
    },
    releaseMarks: function() {
      document.getElementById('working').style.display = '';
      var dataLoad = {
        release_results: true,
        filter: 'none',
        students: this.props.selected_students
      };

      $.ajax({
        method: 'POST',
        url: 'update_grade_entry_students',
        data: dataLoad,
        success: function(data) {
          this.props.refresh();
        }.bind(this)
      });
    },
    unreleaseMarks: function() {
      document.getElementById('working').style.display = '';
      var dataLoad = {
        unrelease_results: false,
        filter: 'none',
        students: this.props.selected_students
      };
      $.ajax({
        method: 'POST',
        url: 'update_grade_entry_students',
        data: dataLoad,
        success: function(data) {
          this.props.refresh();
        }.bind(this)
      });
    },
    render: function() {
      return (
        <div class='floatRight'>
          <div className='react-release-marks'>
            <button onClick={this.releaseMarks}>
              <%= j raw I18n.t('browse_submissions.release_marks') %>
            </button>
            <button onClick={this.unreleaseMarks}>
              <%= j raw I18n.t('browse_submissions.unrelease_marks') %>
            </button>
          </div>
        </div>
      );
    }
  });

  React.renderComponent(<GradesTable />, document.getElementById('react_grades_table'));

</script>
<commit_msg>Updated code so all marks spreadsheet grades that contain non-numerical digits, other than a period, is returned as NaN<commit_after><script type='text/jsx'>
  /** @jsx React.DOM */
  $(document).ready(function() {
  // Prevent the enter key from releasing grades
    preventEnterSubmit();
  });

  /** This function will prevent the default HTML5 action of submitting the content form
    *  when the user presses "enter". As an Admin user, this would release the grades.
    */
  function preventEnterSubmit() {
    $(document).keypress(function(event) {
      if (event.which === 13) {
        event.preventDefault();
      }
    });
  }

  /** Updates total marks cell. Called from Rails controller grade_entry_forms/update_grade to
    * check if a cell exists before updating it, as cell existence can't be efficiently
    * checked from the Ruby controller
    */
  function update_cell(cell, value) {
    // If the total marks cell exists, change it's value to the one supplied
    if (document.getElementById(cell)) {
      document.getElementById(cell).innerHTML = value;
      var e = new MouseEvent('click', {
        'view': window,
        'bubbles': true,
        'cancelable': false
      });
      var node = document.getElementById(cell);
      node.dispatchEvent(e);
    }
  }

  var GradeBoxTotal = React.createClass({
    handleChange: function() {
      this.props.value = parseFloat(event.target.value, 10);
    },
    render: function() {
      return(
        <span
        id={this.props.grade_id}
        size="4"
        className="grade-total"
        >
        {this.props.value}
        </span>
        );
    }
  });

  var GradeEntryBox = React.createClass({
    componentDidMount: function(){
        this.props.value = this.props.default_value;
    },
    handleChange: function(event) {
      var updated_grade = event.target.value === '' ? null : Number(event.target.value);
      var params = {
        'updated_grade':       updated_grade,
        'student_id':          this.props.student_id,
        'grade_entry_item_id': this.props.grade_entry_column,
        'authenticity_token':  AUTH_TOKEN
      };
      $.ajax({
        url:  this.props.data_action,
        data: params,
        type: 'POST',
        dataType: 'script',
      });
      this.props.value = parseFloat(event.target.value);
    },

    // TODO: Make this nicer by not using raw Javascript and jQuery
    handleKeyPress: function(event) {
      if (event.key === 'Enter') {
        var input = this.getDOMNode();
        var td = input.parentNode;
        var tr = td.parentNode;
        var tdIndex = $(tr).children().index(td);
        if (tr.nextSibling !== null) {
          var nextInput = tr.nextSibling.childNodes[tdIndex].firstChild;
          $(nextInput).select()
        }
      }
    },

    render: function() {
      return (
        <input id={this.props.grade_id} type="text" size="4"
          className="grade-input" defaultValue={this.props.default_value}
          onChange={this.handleChange}
          onKeyPress={this.handleKeyPress} />
        );
    }
  });

  var GradesTable = React.createClass({
    getDefaultProps: function() {
      // Creates a new table with the columns defined below.
      // The first column will be the column initially sorted.
      var gradesTable = {
        columns: [
          {
            id: 'user_name',
            content: '<%= j raw I18n.t(:'user.user_name') %>',
            sortable: true,
            searchable: true
          },
          {
            id: 'last_name',
            content: '<%= j raw I18n.t(:'user.last_name') %>',
            sortable: true,
            searchable: true
          },
          {
            id: 'first_name',
            content: '<%= j raw I18n.t(:'user.first_name') %>',
            sortable: true,
            searchable: true
          }
        ],
        filters: [
        {
          name: 'all',
          text: '<%= j raw I18n.t(:'all') %>',
          func: function(student) {
            return true;
          }
        }]
      };
      if (<%= Section.any? %>) {
          gradesTable['columns'].push({
              id: 'section',
              content: '<%= Section.model_name.human %>',
              sortable: true
          });
      }
      return gradesTable;
    },
    getInitialState: function() {
      return {
        row_data: [],
        grade_columns:[],
        selected_students: [],
      }
    },
    updateSelectedStudents: function(students) {
      this.setState({selected_students: students});
    },
    componentWillMount: function() {
      this.refresh();
    },
    refresh: function() {
      document.getElementById('working').style.display = '';

      // Getting additional grade entry item columns
      $.ajax({
        url: 'get_mark_columns',
        method: 'GET',
        dataType: 'json',
        success: function(data) {
          this.setState({
            grade_columns: data,
          });
        }.bind(this),
        // Close working indicator.
        complete: function () {
          document.getElementById('working').style.display = 'none';
        }
      });
      // Getting row data
      $.ajax({
        url: 'populate_grades_table',
        method: 'GET',
        dataType: 'json',
        success: function(data) {
          this.setState({
            row_data: data,
          });
        }.bind(this),
        // Close working indicator.
        complete: function () {
          document.getElementById('working').style.display = 'none';
        }
      });
    },
    render: function() {
      // need to filter for each section
      var sections = <%= raw @sections.to_json %>;
      if (sections.length > 0) {
        var section_filters = sections.map(function(section) {
          var filter = {
            name: section.name,
            text: section.name,
            func: function(group) {
              return group.section === section.name;
            }
          }
          return filter;
        });
        var all = '<%= t('sections.all') %>';
        section_filters.unshift({name: all, text: all, func: null});
      }

      // Add grades and marking state columns to array of table columns
      var all_columns = this.props.columns.concat(this.state.grade_columns);

      // Set React Table data from JSON data
      var rows = this.state.row_data.map(function(row){
        var r = {};
        r['id'] = row.id
        r['user_name'] = row.user_name
        r['first_name'] = row.first_name
        r['last_name'] = row.last_name
        r['section'] = row.section

        this.state.grade_columns.map(function(column){
          var column_id = column.id;

          if (column_id === 'marking_state'){
            if(row[column_id]){
              r[column_id] = <img src={row[column_id]} alt="<%= t('marking_state.released') %>" title="<%= t('marking_state.released') %>"/>;
            }
          }

          else if (column_id === 'total_marks'){
            r[column_id] = <GradeBoxTotal grade_id={'grade_' + row.id + '_' + column.id}
                           grade_entry_column={column.id} student_id={row.id}
                           value={row[column_id]}/>;
          }
          else {
            r[column_id] =
              <GradeEntryBox
               grade_id={'grade_' + row.id + '_' + column.id}
               data_action=
                 "<%= update_grade_grade_entry_form_path(@grade_entry_form) %>"
               grade_entry_column={column.id}
               student_id={row.id}
               default_value={row[column_id]}/>
          }
        }.bind(this));
        return r;
      }.bind(this));
      return (
        <div>
          <GradesActionBox
            selected_students={this.state.selected_students}
            refresh={this.refresh} />
          <Table data={rows}
            search_placeholder={'<%= j raw I18n.t(:'students.search_students') %>'}
            selectable={true} // True if you want checkboxed elements
            onSelectedRowsChange={this.updateSelectedStudents}
            columns={all_columns}
            filters={section_filters}
            filter_type={true}
           />
        </div>
      );
    }
  });

  var GradesActionBox = React.createClass({
    propTypes: {
      selected_students: React.PropTypes.array
    },
    releaseMarks: function() {
      document.getElementById('working').style.display = '';
      var dataLoad = {
        release_results: true,
        filter: 'none',
        students: this.props.selected_students
      };

      $.ajax({
        method: 'POST',
        url: 'update_grade_entry_students',
        data: dataLoad,
        success: function(data) {
          this.props.refresh();
        }.bind(this)
      });
    },
    unreleaseMarks: function() {
      document.getElementById('working').style.display = '';
      var dataLoad = {
        unrelease_results: false,
        filter: 'none',
        students: this.props.selected_students
      };
      $.ajax({
        method: 'POST',
        url: 'update_grade_entry_students',
        data: dataLoad,
        success: function(data) {
          this.props.refresh();
        }.bind(this)
      });
    },
    render: function() {
      return (
        <div class='floatRight'>
          <div className='react-release-marks'>
            <button onClick={this.releaseMarks}>
              <%= j raw I18n.t('browse_submissions.release_marks') %>
            </button>
            <button onClick={this.unreleaseMarks}>
              <%= j raw I18n.t('browse_submissions.unrelease_marks') %>
            </button>
          </div>
        </div>
      );
    }
  });

  React.renderComponent(<GradesTable />, document.getElementById('react_grades_table'));

</script>

{'fraction_non_alphanumeric': 0.13303507147999588, 'fraction_numerical': 0.0022626761287668413, 'mean_word_length': 1.8573317660887452, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 75, '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': '6538388', 'n_tokens_mistral': 5584, 'n_tokens_neox': 5460, 'n_words': 1150}