CSC/ECE 517 Spring 2017/Convert Assignment Creation Form to ReactJS: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
(Final Edit)
 
(14 intermediate revisions by 3 users not shown)
Line 83: Line 83:
[[File:Uml for validation.png]]
[[File:Uml for validation.png]]


==Implementation==


Here is the main code for the regular expression check in Name of assignment and sub directory fields. Now, each time when a create button is clicked, the page is not checked with the model constraints but the reactjs component only. So, without reloading each time the checks are shown on the page as shown in the figure below.


[[File:Validate.PNG]]


==Proposed Solution==
==Proposed Solution==
=== Assignment Creation ===
=== Assignment Creation ===
The new implementation will use ReactJS to generate a drop-down window on clicking on the New Assignment button (private/public) , providing same features as before. Database entry is made on submitting the form and the form is closed.
The new implementation uses ReactJS to generate a drop-down window on clicking on the New Assignment button (private/public) , providing same features as before. Database entry is made on submitting the form and the form is closed.


Below is the mock view of what our implementation is going to look like:
Below is the view of the new implementation:


[[File:new_imp.png]]
[[File:Newassgn_RJS.png]]


==== Files to be modified ====
==== Files modified ====
*apps/assets/javascripts/tree_display.jsx.erb
*apps/assets/javascripts/tree_display.jsx.erb
*apps/controllers/assignments_controller.rb
*apps/controllers/assignments_controller.rb
*apps/controllers/tree_display_controller.rb
*apps/controllers/tree_display_controller.rb
====Code change details====
We created a new React class 'NewAssignmentForm' which dynamically creates and displays the form for New assignment. This class has the following methods:
    getInitialState function(){}      -  Initial method to identify the form parameters that will be sent to the database when a new assignment is created.
    handleNameChange function(e){}    -  The following methods get triggered on change of the form fields and capture/update the state variables 
    handleCourseChange: function(e){}  -//-
    handleSubChange: function(e){}  -//-
    handleDescChange: function(e){}  -//-
    handleTeamChange: function(e){}  -//-
    handleQuizChange: function(e){}  -//-
    handleDeadlineChange: function(e){}  -//-
    handleReviewsChange: function(e){}  -//-
    handleCalibrationChange: function(e){}  -//-
    handleAvailabilityChange: function(e){}  -//-
    handleReputationChange: function(e){}  -//-
      directoryValidate: function(e){}  - this method validates that there is valid directory entered
      nameValidate: function(e){}  - this method validates that a valid project name is entered
      handleCreateAssignment: function(e) {}  - this method sends ajax request with the parameters from the filled form.
      handleGetCourses: function() {}  - this method is triggered when a course selection drop down is clicked. It sends a jQuery request and gets all the courses based on the instructor role
      render: function(){}  - this method renders the form components
In assignment_controller.rb we changed the create method to:
    @assignment_form = AssignmentForm.new(assignment_form_params)
    @assignment_form.assignment.instructor_id = current_user.id  --  We now pass current instructor to the assignment form.
      if @assignment_form.save
        @assignment_form.create_assignment_node
        flash[:success] = "Assignment Successfully created"
        render 'tree_display/list'
      else
        flash[:error] = "Failed to Create Assignment"
        render 'tree_display/list'
      end
    end 
In tree_display_controller.rb we added new method get_courses_node_ng. This method returns the course list array of hashes based on the instructor chosen. This logic is similar to the helper method course_options:
    def get_courses_node_ng
    respond_to do |format|
      courses = []
        if session[:user].role.name == 'Teaching Assistant'
          ta = Ta.find(session[:user].id)
          ta.ta_mappings.each {|mapping| courses << Course.find(mapping.course_id) }
          # If a TA created some courses before, s/he can still add new assignments to these courses.
          courses << Course.where(instructor_id: session[:user].id)
          courses.flatten!
        # Administrator and Super-Administrator can see all courses
        elsif session[:user].role.name == 'Administrator' or session[:user].role.name == 'Super-Administrator'
          courses = Course.all
        elsif session[:user].role.name == 'Instructor'
          courses = Course.where(instructor_id: session[:user].id)
          # instructor can see courses his/her TAs created
          ta_ids = []
          ta_ids << Instructor.get_my_tas(session[:user].id)
          ta_ids.flatten!
          ta_ids.each do |ta_id|
            ta = Ta.find(ta_id)
            ta.ta_mappings.each {|mapping| courses << Course.find(mapping.course_id) }
          end
        end
        format.html { render json:courses}
      end
    end


=== Assignment Edition ===
=== Assignment Edition ===
Similar to assignment creation, in the new implementation, using ReactJS, when the edit assignment button is clicked, instead of making a server request and rendering a new view, a drop down window appears and saving the details will make the database entry.Since all the processing is done on the client side there will be decrease in the number of server requests.
Similar to assignment creation, in the new implementation, using ReactJS, when the edit assignment button is clicked, instead of making a server request and rendering a new view, a drop down window appears and saving the details will make the database entry.Since all the processing is done on the client side there will be decrease in the number of server requests.


Below is the mock display of what our implementation is going to look like:
However, the edit form is a multilevel form with different tabs. We managed to implement only the general view as React JS form, hence we added a new action item "Quick Edit" which renders the ReactJS form and the "Edit" action item works as before.
 
Below is the view of the new implementation:
 
[[File:New editassignment.png]]
 
==== Files modified ====
*apps/assets/javascripts/tree_display.jsx.erb
*apps/controllers/assignments_controller.rb
*apps/controllers/tree_display_controller.rb
 
==== Code change details ====
In tree_display.jsx we created a new React class EditAssignmentForm which dynamically creates and displays the form for Editing assignment. This class has the following methods:
    componentWillReceiveProps(nextProps)  - To handle edit
    getInitialState function(){}      -  Here we identify the form parameters.
    handleNameChange function(e){}    -  The following methods get triggered on change of the form fields and capture/update the state variables 
    handleCourseChange: function(e){}  -//-
    handleSubChange: function(e){}  -//-
    handleDescChange: function(e){}  -//-
    handleTeamChange: function(e){}  -//-
    handleQuizChange: function(e){}  -//-
    handleDeadlineChange: function(e){}  -//-
    handleReviewsChange: function(e){}  -//-
    handleCalibrationChange: function(e){}  -//-
    handleAvailabilityChange: function(e){}  -//-
    handleReputationChange: function(e){}  -//-


[[File:Edit-new_imp.png]]
    directoryValidate: function(e){}  - this method validates that there is valid directory entered
    nameValidate: function(e){}  - this method validates that a valid project name isentered


==== Files to be modified ====
    handleEditAssignment: function(e) {}  - this method sends ajax request with the parameters from the filled form.
*apps/views/tree_display/list.html.erb
*apps/views/assignments/edit.html.erb
*apps/views/assignments/edit/_general.html.erb


=== Addition of topics ===
    handleGetCourses: function() {}  - this method is triggered when a course selection drop down is clicked. It sends a jQuery request and gets all the courses based on the instructor role
 
    render: function(){}  - this method renders the form components
 
 
We also added the following in the class RowAction to display the form fields when clicked on Quick Edit.
    if (this.props.dataType === 'assignment') {
      moreContent.push(
      <span>
      <a title="Quick Edit" onClick ={this.onClick} ><img src="/assets/tree_view/edit-icon-24.png" /></a>{this.state.showForm ? <EditAssignmentForm
      assignmentId={this.props.id} name={this.props.parent_name} directory_path={this.props.directory} spec_location={this.props.spec_location} course_id=
      {this.props.course_id} require_quiz={this.props.require_quiz} is_available={this.props.availability} max_team_size={this.props.max_team_size}
      staggered_deadline={this.props.staggered_deadline} microtask={this.props.microtask} review_visible={this.props.review_visible} calibration=
      {this.props.calibration} reputation={this.props.reputation} quiz_questions={this.props.quiz_questions} teammate_review={this.props.teammate_review} />
      :null}
      </span>)
    }
 
In assignment_controller.rb we edited update method:
 
    if @assignment_form.update_attributes(assignment_form_params, current_user)
      flash[:note] = 'The assignment was successfully saved.'
      render 'tree_display/list'
    else
      flash[:error] = "Failed to save the assignment: #{@assignment_form.errors}"
      render 'tree_display/list'
    end
 
In tree_display_controller.rb we edited assignments_method to fetch all the parameters we need to display fields with appropriate values when Quick edit is clicked:
 
    def assignments_method(node, tmp_object)
    tmp_object.merge!(
      "course_id" => node.get_course_id,
      "max_team_size" => node.get_max_team_size,
      "is_intelligent" => node.get_is_intelligent,
      "require_quiz" => node.get_require_quiz,
      "quiz_questions" => node.get_quiz_questions,
      "allow_suggestions" => node.get_allow_suggestions,
      "spec_location" => node.get_spec_location,
      "staggered_deadline" =>node.get_staggered_deadline,
      "microtask" => node.get_microtask,
      "review_visible" => node.get_review_visible,
      "calibration" => node.get_calibration,
      "reputation" => node.get_reputation_algorithm,
      "teammate_review" => node.get_teammate_review,
      "availability" => node.get_availability,
      "has_topic" => SignUpTopic.where(['assignment_id = ?', node.node_object_id]).first ? true : false
    )
    end
 
=== Adding/Editing of topics ===
* An interactive React JS component should be created and should be called by the ruby injection page ''sign_up_sheet/_add_topics.html.erb'' when New Topic link is clicked. This should show a form in that page to create topic.
* An interactive React JS component should be created and should be called by the ruby injection page ''sign_up_sheet/_add_topics.html.erb'' when New Topic link is clicked. This should show a form in that page to create topic.
* Delete/avoid usage of ''sign_up_sheet/new.html.erb'' page.
* Delete/avoid usage of ''sign_up_sheet/new.html.erb'' page.
* Implement an React JS functional component to handle creation of topic and saving it to database.
* Implement an React JS functional component to handle creation of topic and saving it to database.


=== Editing topic ===
====Code change details====
* An interactive React JS component should be created and should be called by the ruby injection page ''sign_up_sheet/_all_actions.html.erb'' when edit action is clicked. This should show a form in that page to edit topic.
Tried to add topics using react js code in the file * app/views/sign_up_sheet/_add_topics.html.erb
* Delete/avoid usage of ''sign_up_sheet/edit.html.erb'' page.
 
* Implement an React JS functional component to handle editing  of topic and updating it to database.
Modified files code:
 
[[File:T1.PNG]]
 
[[File:T2.PNG]]
 
[[File:T3.PNG]]
 
[[File:T4.PNG]]


=== Make the table in topics tab sortable by its header ===
=== Make the table in topics tab sortable by its header ===
Following sub-tasks identified to implement sortable feature for topics table.
Following sub-tasks are implemented for sortable feature for topics table.
* Modify sign_up_sheet/_table_header.html.erb partial to change the table header fields to sortable type.
* Modify sign_up_sheet/_table_header.html.erb partial to change the table header fields to sortable type.
* Add sort functionality using ReactJS for each column that is meaningful to be sorted.
* Add sort functionality using ReactJS for each column that is meaningful to be sorted.
* Below is how output will look like
====Code change details====
Below are the files modified.
* app/views/sign_up_sheet/_add_signup_topics.html.erb
[[File:Signup_topics.PNG]]
* app/views/sign_up_sheet/_table_header.html.erb
[[File:Table_header.PNG]]
[[File:Js.PNG]]
[[File:css.PNG]]


=== Validating user entries ===
=== Validating user entries ===
The following tasks are to be implemented to achieve users validation,
The following tasks are implemented to achieve users validation,
* Add the regular expression validation to avoid special characters in the names of assignment or directories.
* Add the regular expression validation to avoid special characters in the names of assignment or directories.
* Correcting the code in edit assignment page too.
* Correcting the code in edit assignment page too.
* Create validation for edge cases like giving empty values.
* Create validation for edge cases like giving empty values.


==== Files to be modified ====
Here is the display of the implementation:
As, the project needs to be implemented in reactJS, which helps in reducing the complexing binding in MVC framework, only changing the javascript file can help to achieve this without changing model,
[[File:Validate_create.JPG]]
 
[[File:Validate_edit.JPG]]
 
==== Files modified ====
* app/assets/javascripts/tree_display.jsx.erb
* app/assets/javascripts/tree_display.jsx.erb
==== Code change details ====
These methods are added inside Create/Edit ReactJS class and called whenever Create/Update buttons are clicked:
    nameValidate: function(e){
      var regex_valid = /^[a-zA-Z0-9]*$/;
      var regex=/^(?=\s*\S).*$/;
      if(regex.test(e) && regex_valid.test(e))
          return true;
      else{
          document.getElementById("name_span").innerHTML = " &#x2716 Name cannot be empty! and no special characters are allowed. Please check the format";
          return false;
          }
    },
    directoryValidate: function(e){
      var regex=/^[a-zA-Z0-9]*$/;
      var regex_empty=/^(?=\s*\S).*$/;
      if(regex.test(e) && regex_empty.test(e))
        return true;
      else {   
          document.getElementById("directory_span").innerHTML = "&#x2716 Submission Directory cannot have special characters or spaces. It cannot be empty!";
          return false;
        }
      },


=== Fixing Tooltips ===
=== Fixing Tooltips ===
On exploring, it was noticed that all the existing tooltips work. However, we intend to increase the proximity of the tooltips in the assignment tab by increasing the size of the images.
On exploring, it was noticed that all the existing tooltips work. However, we have increased the proximity of the tooltips in the assignment tab by increasing the size of the images.


==Test Plan==
==Test Plan==
Rails development is the Test Driven development, which helps in ensuring the implementation of all proposed implementations. We will be writing all the implementations proposed as tests that will eventually be red in rspec and try to make them green by adding to the development part.
Rails development is the Test Driven development, which helps in ensuring the implementation of all proposed implementations. We will be writing all the implementations proposed as tests that will eventually be red in rspec and try to make them green by adding to the development part.


For now the manual testing of these current implementations can help in testing the functionality from UI.
===Manual Testing===
===Manual Testing===
Steps to manually test the feature are as follows:  
Steps to manually test the feature are as follows:  
Line 195: Line 385:
*Try adding the assignment using the weird names, with special symbols, ignoring check boxes
*Try adding the assignment using the weird names, with special symbols, ignoring check boxes
*Verify if the assignment which is updated with special characters is shown in the table.
*Verify if the assignment which is updated with special characters is shown in the table.
===Automation testing===
The above tests all will be automated using rspec. Rspec Mock-ups will be created for checking the navigation flow of newly created React JS components.


==Future Work==
==Future Work==


We will try to convert edit assignment page in to React JS. Design pages more clearly.
*Covert the multi-level edit assignment form to ReactJS
*Convert add/edit topics to ReactJS


==References==
==References==

Latest revision as of 16:35, 3 May 2017

Introduction

This page is a part of CSC/ECE 517 Final Project for Spring 2017 to describe the changes made by us to the open source software project Expertiza. We are converting the assignment creation form to ReactJS. Following contains a brief introduction to Expertiza, ReactJS followed by the problems we are tackling, our strategy for the implementation and the test plan.

Expertiza

Expertiza is a Ruby on Rails based web application where students can submit and peer review learning objects such as codes, articles, websites etc., It is an open source software project funded by National Science Foundation(NSF). The instructor has the capability to create assignments with varied specifications such as topics, courses, team size, level of reviews etc., later review the submitted work and provide feedback. Students can enter their submissions and also review others' work.

ReactJS

ReactJS is the javascript framework developed by Facebook to solve the specific problem, UI rendering. It is developed to solve the problem with complex binding in MVC framework using only one-way data binding. It is used for dynamic reloading of the page. It helps in reloading only the particular component required using Virtual DOM, which makes it fast by temporarily storing DOM

Reasons for using ReactJS

  • It has every functionality that an user interface required
  • Easy data binding.
  • Only single component changes are stored/changed without reloading the complete page.
  • Fast and efficient
  • Easy to scale

Problem Statement

The Assignment Create and Edit Form are multi level forms. It consists of multiple inputs and user interactions. Many input types have dependency on interactions by the user. For example, on check for a particular checkbox, remaining form is displayed. Also, edit page is reloaded whenever a topic is added. The task is to convert this pages into ReactJS components.

Tasks to be done

  • Organize the form layout, create several mockups and validate them to your users
  • Make the table in topics tab sortable by its header
  • Allow users to edit / add topics in the table instead of loading a new page
  • Implement the new layout and convert the javascript to a ReactJS component
  • Validate user entries
  • Fix tooltips - Needed to increase the proximity of the tool tips in the assignments tab.

Current Implementation

Assignment Creation

The assignment creation form consists of multiple inputs and requires interactions from the user. The current implementation is mostly in HTML with data validations being done by JQuery. When a user wants to create a new assignment by clicking the new assignment button, a server request is generated and new view is rendered. Again, another server request to make database entry is generated once the user fills in the data and clicks on 'save' button and again a new view is rendered. This kind of implementation doesn't support dynamic view rendering hence lacks the fluidity in overall user experience that one would expect.






Assignment Edition

Similar to assignment creation page, edit page lacks the dynamic view rendering which makes the user experience cumbersome. Every time user wants to make changes to the assignment, a server request is generated and new view is rendered. The save button hit on completion will again generate another server request and render a new view.

Add/Edit topics in Assignment

In current implementation whenever a topic is added to the assignment, a request is sent to the server and user is redirected to a form in another page. Upon creation of topic user is rendered back to edit assignment page. This process involves lot of redirection. Now, the task is to avoid this redirection of pages and create a interactive ReactJS form for adding and editing topic.

Currently this logic is implemented in new method in sign_up_controller.rb file and is invoked in the _add_topics.rb ruby injection file. With this action new.html.erb page is rendered. This should be avoided.

Add topic:

Similar is the case for editing a topic. For editing a topic user is rendered to a form in edit page and again redirected to edit assignment page.

Edit Topic:

Make the table in topics tab sortable by its header

Currently after creating an assignment, we can add topics related to the assignment. The "Topics" tab in the edit assignment form shows the list of topics that are added to the assignment. The picture below shows the current page for displaying the list of topics of an assignment. The list is not sortable. The task is to make it sortable using ReactJS by topic id, topic name, Num. of slots, Available slots, Num. on waitlist columns as sorting on remaining columns doesn't give any meaningful display.

Validating user entries

The entries for the assignment creation are not according to any restrictions, that can add problem to database maintenance like sorting the entries, comparing them, retrieving. There are many such problem causing situations in the new assignment form, such as

This is essential in both new assignment or editing assignment page.

  • User can add the number as new assignment name or he can give only special characters for it like "$$$$".
  • Though mentioned a mandatory no special characters, it was not properly implemented. System is accepting the special characters.
  • Neglecting check boxes may lead to confusion with deadlines.


UML Diagram

The following diagram depicts the flow of events leading to validations.



Proposed Solution

Assignment Creation

The new implementation uses ReactJS to generate a drop-down window on clicking on the New Assignment button (private/public) , providing same features as before. Database entry is made on submitting the form and the form is closed.

Below is the view of the new implementation:

Files modified

  • apps/assets/javascripts/tree_display.jsx.erb
  • apps/controllers/assignments_controller.rb
  • apps/controllers/tree_display_controller.rb

Code change details

We created a new React class 'NewAssignmentForm' which dynamically creates and displays the form for New assignment. This class has the following methods:

    getInitialState function(){}      -  Initial method to identify the form parameters that will be sent to the database when a new assignment is created.
    handleNameChange function(e){}    -  The following methods get triggered on change of the form fields and capture/update the state variables  
    handleCourseChange: function(e){}  -//-
    handleSubChange: function(e){}  -//-
    handleDescChange: function(e){}   -//-
    handleTeamChange: function(e){}   -//-
    handleQuizChange: function(e){}   -//-
    handleDeadlineChange: function(e){}  -//-
    handleReviewsChange: function(e){}   -//-
    handleCalibrationChange: function(e){}   -//-
    handleAvailabilityChange: function(e){}  -//-
    handleReputationChange: function(e){}   -//-
     directoryValidate: function(e){}  - this method validates that there is valid directory entered
     nameValidate: function(e){}  - this method validates that a valid project name is entered
     handleCreateAssignment: function(e) {}  - this method sends ajax request with the parameters from the filled form.
     handleGetCourses: function() {}  - this method is triggered when a course selection drop down is clicked. It sends a jQuery request and gets all the courses based on the instructor role 
     render: function(){}  - this method renders the form components

In assignment_controller.rb we changed the create method to:

   @assignment_form = AssignmentForm.new(assignment_form_params)
   @assignment_form.assignment.instructor_id = current_user.id  --  We now pass current instructor to the assignment form.
     if @assignment_form.save
       @assignment_form.create_assignment_node
       flash[:success] = "Assignment Successfully created"
       render 'tree_display/list'
     else
       flash[:error] = "Failed to Create Assignment"
       render 'tree_display/list'
     end
    end   

In tree_display_controller.rb we added new method get_courses_node_ng. This method returns the course list array of hashes based on the instructor chosen. This logic is similar to the helper method course_options:

   def get_courses_node_ng
   respond_to do |format|
     courses = []
       if session[:user].role.name == 'Teaching Assistant'
         ta = Ta.find(session[:user].id)
         ta.ta_mappings.each {|mapping| courses << Course.find(mapping.course_id) }
         # If a TA created some courses before, s/he can still add new assignments to these courses.
         courses << Course.where(instructor_id: session[:user].id)
         courses.flatten!
       # Administrator and Super-Administrator can see all courses
       elsif session[:user].role.name == 'Administrator' or session[:user].role.name == 'Super-Administrator'
         courses = Course.all
       elsif session[:user].role.name == 'Instructor'
         courses = Course.where(instructor_id: session[:user].id)
         # instructor can see courses his/her TAs created
         ta_ids = []
         ta_ids << Instructor.get_my_tas(session[:user].id)
         ta_ids.flatten!
         ta_ids.each do |ta_id|
           ta = Ta.find(ta_id)
           ta.ta_mappings.each {|mapping| courses << Course.find(mapping.course_id) }
         end
       end
       format.html { render json:courses}
     end
   end

Assignment Edition

Similar to assignment creation, in the new implementation, using ReactJS, when the edit assignment button is clicked, instead of making a server request and rendering a new view, a drop down window appears and saving the details will make the database entry.Since all the processing is done on the client side there will be decrease in the number of server requests.

However, the edit form is a multilevel form with different tabs. We managed to implement only the general view as React JS form, hence we added a new action item "Quick Edit" which renders the ReactJS form and the "Edit" action item works as before.

Below is the view of the new implementation:

Files modified

  • apps/assets/javascripts/tree_display.jsx.erb
  • apps/controllers/assignments_controller.rb
  • apps/controllers/tree_display_controller.rb

Code change details

In tree_display.jsx we created a new React class EditAssignmentForm which dynamically creates and displays the form for Editing assignment. This class has the following methods:

    componentWillReceiveProps(nextProps)  - To handle edit
    getInitialState function(){}      -  Here we identify the form parameters.
    handleNameChange function(e){}    -  The following methods get triggered on change of the form fields and capture/update the state variables  
    handleCourseChange: function(e){}  -//-
    handleSubChange: function(e){}  -//-
    handleDescChange: function(e){}   -//-
    handleTeamChange: function(e){}   -//-
    handleQuizChange: function(e){}   -//-
    handleDeadlineChange: function(e){}  -//-
    handleReviewsChange: function(e){}   -//-
    handleCalibrationChange: function(e){}   -//-
    handleAvailabilityChange: function(e){}  -//-
    handleReputationChange: function(e){}   -//-
    directoryValidate: function(e){}  - this method validates that there is valid directory entered
    nameValidate: function(e){}  - this method validates that a valid project name isentered
    handleEditAssignment: function(e) {}  - this method sends ajax request with the parameters from the filled form.
    handleGetCourses: function() {}  - this method is triggered when a course selection drop down is clicked. It sends a jQuery request and gets all the courses based on the instructor role 
    render: function(){}  - this method renders the form components


We also added the following in the class RowAction to display the form fields when clicked on Quick Edit.

   if (this.props.dataType === 'assignment') {
     moreContent.push(
     
     <a title="Quick Edit" onClick ={this.onClick} ><img src="/assets/tree_view/edit-icon-24.png" /></a>{this.state.showForm ? <EditAssignmentForm 
     assignmentId={this.props.id} name={this.props.parent_name} directory_path={this.props.directory} spec_location={this.props.spec_location} course_id=
     {this.props.course_id} require_quiz={this.props.require_quiz} is_available={this.props.availability} max_team_size={this.props.max_team_size} 
     staggered_deadline={this.props.staggered_deadline} microtask={this.props.microtask} review_visible={this.props.review_visible} calibration=
     {this.props.calibration} reputation={this.props.reputation} quiz_questions={this.props.quiz_questions} teammate_review={this.props.teammate_review} /> 
     :null}
     ) 
   }

In assignment_controller.rb we edited update method:

   if @assignment_form.update_attributes(assignment_form_params, current_user)
     flash[:note] = 'The assignment was successfully saved.'
     render 'tree_display/list'
   else
     flash[:error] = "Failed to save the assignment: #{@assignment_form.errors}"
     render 'tree_display/list'
   end

In tree_display_controller.rb we edited assignments_method to fetch all the parameters we need to display fields with appropriate values when Quick edit is clicked:

   def assignments_method(node, tmp_object)
   tmp_object.merge!(
     "course_id" => node.get_course_id,
     "max_team_size" => node.get_max_team_size,
     "is_intelligent" => node.get_is_intelligent,
     "require_quiz" => node.get_require_quiz,
     "quiz_questions" => node.get_quiz_questions,
     "allow_suggestions" => node.get_allow_suggestions,
     "spec_location" => node.get_spec_location,
     "staggered_deadline" =>node.get_staggered_deadline,
     "microtask" => node.get_microtask,
     "review_visible" => node.get_review_visible,
     "calibration" => node.get_calibration,
     "reputation" => node.get_reputation_algorithm,
     "teammate_review" => node.get_teammate_review,
     "availability" => node.get_availability,
     "has_topic" => SignUpTopic.where(['assignment_id = ?', node.node_object_id]).first ? true : false
    )
   end

Adding/Editing of topics

  • An interactive React JS component should be created and should be called by the ruby injection page sign_up_sheet/_add_topics.html.erb when New Topic link is clicked. This should show a form in that page to create topic.
  • Delete/avoid usage of sign_up_sheet/new.html.erb page.
  • Implement an React JS functional component to handle creation of topic and saving it to database.

Code change details

Tried to add topics using react js code in the file * app/views/sign_up_sheet/_add_topics.html.erb

Modified files code:

Make the table in topics tab sortable by its header

Following sub-tasks are implemented for sortable feature for topics table.

  • Modify sign_up_sheet/_table_header.html.erb partial to change the table header fields to sortable type.
  • Add sort functionality using ReactJS for each column that is meaningful to be sorted.
  • Below is how output will look like

Code change details

Below are the files modified.

  • app/views/sign_up_sheet/_add_signup_topics.html.erb

  • app/views/sign_up_sheet/_table_header.html.erb


Validating user entries

The following tasks are implemented to achieve users validation,

  • Add the regular expression validation to avoid special characters in the names of assignment or directories.
  • Correcting the code in edit assignment page too.
  • Create validation for edge cases like giving empty values.

Here is the display of the implementation:

Files modified

  • app/assets/javascripts/tree_display.jsx.erb

Code change details

These methods are added inside Create/Edit ReactJS class and called whenever Create/Update buttons are clicked:

   nameValidate: function(e){
     var regex_valid = /^[a-zA-Z0-9]*$/;
     var regex=/^(?=\s*\S).*$/;
     if(regex.test(e) && regex_valid.test(e))
         return true;
     else{
         document.getElementById("name_span").innerHTML = " &#x2716 Name cannot be empty! and no special characters are allowed. Please check the format";
         return false;
          }
    },


    directoryValidate: function(e){
      var regex=/^[a-zA-Z0-9]*$/;
      var regex_empty=/^(?=\s*\S).*$/;
      if(regex.test(e) && regex_empty.test(e))
        return true;
      else {     
         document.getElementById("directory_span").innerHTML = "&#x2716 Submission Directory cannot have special characters or spaces. It cannot be empty!";
         return false;
       }
     },

Fixing Tooltips

On exploring, it was noticed that all the existing tooltips work. However, we have increased the proximity of the tooltips in the assignment tab by increasing the size of the images.

Test Plan

Rails development is the Test Driven development, which helps in ensuring the implementation of all proposed implementations. We will be writing all the implementations proposed as tests that will eventually be red in rspec and try to make them green by adding to the development part.

Manual Testing

Steps to manually test the feature are as follows:

Assignment Creation

  • Log in as an instructor (user-name:instructor6 password:password)
  • Go to Manage->Assignments and click on the Assignments tab.
  • Click on the 'New public assignment' or 'New private assignment' button
  • Verify if drop-down window is displayed.
  • Make valid entries for the available fields and click on 'create'.
  • Verify if new assignment is successfully created.

Assignment Creation

  • Log in as an instructor (user-name:instructor6 password:password)
  • Go to Manage->Assignments and click on the Assignments tab.
  • Click on the Edit button for any of the available assignment.
  • Verify if drop-down window is displayed.
  • Make changes and click on 'save'.
  • Verify if the changes made are successfully updated.

Topic Creation/Editing

  • Login as an instructor (user-name:instructor6 password:password)
  • Create an assignment
  • Click 'New Topic' link or 'edit' action in topics table for a particular topic
  • A pop window or form should be displayed in the same page
  • Add topic details in that window/ form
  • Save it
  • Created or modified topic should be seen in topics table

Make the table in topics tab sortable by its header

  • Login as an instructor (user-name:instructor6 password:password)
  • Create an assignment
  • Add 2 topics to the assignment
  • Click sort on Topic ID and check if they are sorted
  • Click sort on Topic title and check if they are sorted
  • Similarly test using other columns

Validating user entries

  • Log in as an instructor (user-name:instructor6 password:password)
  • Go to Manage->Assignments and click on the Assignments tab.
  • Click on the 'New public assignment' or 'New private assignment' button
  • Try adding the assignment using the weird names, with special symbols, ignoring check boxes
  • Verify if the assignment is shown in the table.

Another way to check is from editing page too.

  • Log in as an instructor (user-name:instructor6 password:password)
  • Go to Manage->Assignments and click on the Assignments tab.
  • Click on the Edit icon page.
  • Try adding the assignment using the weird names, with special symbols, ignoring check boxes
  • Verify if the assignment which is updated with special characters is shown in the table.

Future Work

  • Covert the multi-level edit assignment form to ReactJS
  • Convert add/edit topics to ReactJS

References

  1. http://railscasts.com/episodes/228-sortable-table-columns sortable-columns
  2. https://www.airpair.com/reactjs/posts/reactjs-a-guide-for-rails-developers adding-reactjs
  3. https://github.com/expertiza/expertiza/pull/855