CSC/ECE 517 Spring 2017/Use Ajax to add Participants,TA and Edit Questionnaire
Introduction
Expertiza is an opensource software developed to assist people in education institutions to perform peer reviews and group projects. It is exceptionally helpful to the students and instructors. The software is designed in MVC (Model-View-Controller) architecture using ruby on rails.
Problem Statement
Expertiza provides many categories to manage for an instructor. Few of these categories are assignments, courses and questionnaires. Currently, to add/remove/update records, the entire page is submitted to save the record and the entire page is re-loaded back again to reflect the changes on the page. The task is to improve this functionality such that some of the records, specifically adding participants to courses or assignments, adding/removing teaching assistants to/from courses and adding questions to questionnaires, can be saved remotely and the page updated without submitting and reloading the entire page. Additionally, on assign reviewers page for an assignment, there is no way to see the current status of reviews and there is no way for an instructor to unsubmit a submitted review. So, another task is to add this functionality such that review status is seen for each review and to unsubmit a submitted review without reloading the page.
Proposed Solution
This project proposes use of AJAX for the required pages to avoid page reloading at the time of adding and saving records. This solution will make sure that adding or saving of record is done remotely and the page is updated without reloading. It can be achieved by calling corresponding controller method, adding/saving the record remotely and rendering it back to JavaScript pages in the view instead of redirecting it to the same page. JavaScript pages in the view will update the page without reloading it, for example by appending the newly added record to the list of records. Thus, records are saved remotely and page refresh is avoided. For the review status part, responses to the corresponding reviews on the page can be checked in the Response table and the review status shown as the status of the latest response. Unsubmitting a review can be done using AJAX without reloading the page.
Tasks
- Add Participant in the assignments section using AJAX
- Add/Remove TA in the courses section using AJAX
- Edit Questionnaire by using AJAX for adding questions in the Questionnaire section
- Show Review Status on assign reviewers page and allow to un-submit a review using AJAX
Implementation
Adding participant
Earlier scenario: When an instructor goes to "Manage Assignments -> Add Participants" page, he/she can add/remove new Participant to the assignment. The add page also displays list of participants above the form for new participant. Every time a new Participant is added, the page reloads to reflect the changes and render the updated list of participants, even in case of non-existing userid.
Updates/Changes: This page has been updated such that an instructor can add a new Participant using AJAX. After adding AJAX changes, the list gets updated without reloading the entire page. The changes made are below.
- Updated the shared_scripts/_user_list.html.erb file in views so that the Participants are listed by rendering another partial _participant.html.erb in participants controller. This change is to make it feasible to add AJAX to just append to the list without any extra formatting.
- Created a new file participants/add.js.erb for adding AJAX to render newly added participant in case of successful addition and display error in case of any error.
- Updated the shared_scripts/_add_individual.html.erb form such that request should be through AJAX by setting remote flag to true.
- Updated the participants controller participant_controller.rb in controllers to render JavaScript when add method is invoked by the form submit action instead of redirect to list page.
Adding/Removing TA
Earlier scenario: When an instructor goes to "Manage Courses -> Add TA" page, he/she can add/remove new TA to the course. Every time a new TA is added or removed, the page reloads to reflect the changes, even if the userid used does not exist.
Updates/Changes: This page has been updated such that an instructor can add a new TA or remove a new TA using AJAX. With these updates, the changes are reflected on the page without reloading the page, thus saving time.
- Updated the course/view_teaching_assistants.html.erb file in views so that the TAs are listed by rendering another partial _ta.html.erb. This is done so that when a new TA has been added, AJAX call can be used to render the format required for the new TA in the list append to the already existing list without reloading the page.
- Created a new file course/_ta.html.erb in views which is a partial as described above and contains the code to list the TAs. The link_to "Delete" line in this file is updated to use :remote=>:true, so that AJAX call can be made to remove the TA remotely without reloading the page.
<%= link_to "Delete", { :action => 'remove_ta', :controller =>'course', :id => ta.id, :course_id => ta.course_id }, method: :post, :remote => true, :class => 'remove_ta' %>
- Updated the course/_add_individual.html.erb file in views to perform the form_tag action to Add a TA remotely using :remote=>:true. In the below code, form_action and remote are local variables passed to this partial from course/view_teaching_assistants.html.erb with the values "add_ta" and "true" respectively
- Updated the course_controller.rb" file and replaced the redirect option in add_ta and remove_ta to render add_ta.js.erb and remove_ta.js.erb. Also changed flash[:error] to flash.now[:error] so that the flash message is displayed now instead of after page reload.
- Added a new file course/add.js.erb and course/remove_ta.js.erb to views. The add_ta.js.erb file renders the newly added TA and appends it to the list of TAs. It also shows flash error message if the userid used to add TA does not exist. Similarly, remote_ta.js.erb file removes the deleted TA from the list.
Edit Questionnaire
Current scenario : page consists of different subsections for creating questionnaire,adding questions to the questionnaire and saving the questionnaire i.e.
- _questionnaire.html.erb
Adding questions feature is performed in the following method of questionnaires_controller.rb class
def add_new_questions
questionnaire_id = params[:id] unless params[:id].nil? num_of_existed_questions = Questionnaire.find(questionnaire_id).questions.size ((num_of_existed_questions + 1)..(num_of_existed_questions + params[:question][:total_num].to_i)).each do |i| question = Object.const_get(params[:question][:type]).create(txt: , questionnaire_id: questionnaire_id, seq: i, type: params[:question][:type], break_before: true) if question.is_a? ScoredQuestion question.weight = 1 question.max_label = 'Strongly agree' question.min_label = 'Strongly disagree' end question.size = '50, 3' if question.is_a? Criterion question.alternatives = '0|1|2|3|4|5' if question.is_a? Dropdown question.size = '60, 5' if question.is_a? TextArea question.size = '30' if question.is_a? TextField begin question.save rescue flash[:error] = $ERROR_INFO end end redirect_to edit_questionnaire_path(questionnaire_id.to_sym) end
This method invokes question.create method in questions_cotroller.rb and saves the created question to the database. Then it redirects to the edit.html.erb page which causes page refresh while adding questions.
Solution: This problem was tried to solve using AJAX by changing or adding the following classes and pages
- _question.html.erb (added) - displays added question
<a rel="nofollow" data-method="delete" href="/questions/' <%= @question.id%> '">Remove</a>' <input size="6" value="' <%= @question.seq%> '" name="question[' question.id %>'][seq]" id="question_' +<%=@question.id %> '_seq" type="text"> <textarea cols="50" rows="1" name="question[' <%= @question.id%> '][txt]" id="question_' <%= @question.id%> '_txt" placeholder="Edit question content here">' <%= @question.txt%> '</textarea> <input size="10" disabled="disabled" value="' <%= @question.type%> '" name="question[' <%= @question.id%>'][type]" id="question_' <%= @question.id%> '_type" type="text">
- add_new_questions.js.erb (added) - appends the html content with added question in _question.html.erb to questions_table in _questionnaire.html.erb
$("#questions_table").append("<%= j render :partial => 'question', :locals => {question: @question, :id => @question.id, :controller => 'questions'} %>");
- edit.html.erb (modified : code removed) - following code is removed as it internally calls respective question header models and appends html string to questions_table internally.
<% for @question in @questionnaire.questions do%> <%-# The following line call certain method of the object, which returns html string-%> <%= @question.edit %> <% end %>
@question.edit invokes QuestionHeader.rb model which adds html content
def edit(_count)
html = '' html += '<a rel="nofollow" data-method="delete" href="/questions/' + self.id.to_s + '">Remove</a>' html += '<input size="6" value="' + self.seq.to_s + '" name="question[' + self.id.to_s + '][seq]" id="question_' + self.id.to_s + '_seq" type="text">' html += '<textarea cols="50" rows="1" name="question[' + self.id.to_s + '][txt]" id="question_' + self.id.to_s + '_txt" placeholder="Edit question content here">' + self.txt + '</textarea>' html += '<input size="10" disabled="disabled" value="' + self.type + '" name="question[' + self.id.to_s + '][type]" id="question_' + self.id.to_s + '_type" type="text">' html += '' html += '' html.html_safe end
- questionnaires_controller.rb (modified) - add_new_questions method is modified by replacing redire rendering add_new_questions.js.erb file
render :action=> 'add_new_questions.js.erb', :layout=>false, :question=> question #redirect_to edit_questionnaire_path(questionnaire_id.to_sym) Issue : But this solution is not working as AJAX can be applied to the browser side processing if the controller method is redirecting to the same page, which is not in this case as page gets redirected from question.html.erb to edit.html.erb. Another problem faced is the creation of questions which is called through _questionnaire.html.erb but not through _question.html.erb which makes it difficult to pass correct questionnaire id to the AJAX call. Alternative Approach to Edit Questionnaire: Another approach to solve this issue is to create a seperate java-script function which handles the entire process of adding,saving,deleting questions and appending them. Call this function from _questionnaire.html.erb instead of invoking add_new_questions method. Questions can be saved and retrived from data using JavaScript Rest API calls. But, this approach not only needs to restructure entire questionnaire structure and many components in the Expertiza project but also violates the MVC design of the project.
Un-submit reviews
Earlier scenario: When an instructor/TA goes to "Manage Assignments -> Assign Reviewers" page, he/she can see a list of all the topics, the contributors and the reviewers for each topic. This page did not show the status of each review which can be in Assigned state or Saved state or Submitted state. Also, there was no way for the instructor/TA to un-submit an already submitted review.
New Additions:
- Updated the review_mappings/_list_review_mappings.html.erb file in views to display the status of each review by the reviewer. For each review_mapping, the code checks if there is a response in Response table with the same map_id used in the review_mappings on this page.
- If there is no such response, it means that the reviewer has not saved/submitted the review and it is currently in Assigned State. So, "Response Status: Saved" is shown for that review.
- If there is a response, the last (latest) response is checked as per requirement and the is_submitted attribute of this response is checked in the Response table.
- If the attribute is false, the review has been saved but not submitted. So, "Response Status: Saved" is shown for that review.
- If the attribute is true, the review has been submitted. So, "Response Status: Submitted" is shown for that review. Next to this, a link is created to un-submit the review. Clicking on this link changes the is_submitted attribute to false and updates the Response Status to Saved on the page by using AJAX call, without reloading the page
- Added a new method "unsubmit_review" to the review_mapping_controller.rb file. In this, we first find the latest response and then update the is_submitted attribute to false. The flash message is created based on whether the response was updated correctly. After this, unsubmit_review.js.rb file is rendered which updates the response status for the corresponding review on the page to Saved, without reloading the page
- Added a new file review_mappings/unsubmit_review.js.erb to views. This file just changes the response status for the corresponding review displayed on the page to Saved from Submit after the review has been un-submitted and also prints the corresponding success or error flash message.
- Added a new line to routes.rb page for unsubmit_review action
Test Plan
Log in details
Username: instructor6 password: password
Some valid user id's are student5000, student5001, student5002 etc. These can be used while adding new Participant or TA as described below.
Automated Testing
- Created a helper module wait_for_ajax.rb with methods to wait for ajax requests to finish
- Updated the test "check to see if participants can be added" in assignment_creation_spec.rb to wait for AJAX calls to finish after adding a participant by using the helper module created
- Added a new file course_creation_spec.rb to test adding and remove TA's
- This contains test named "should display newly created course" to check if the new course is successfully created (There was no such test earlier)
- This also contains a test named "check to see if TA can be added and removed" which checks if a new TA has gotten added after clicking on Add TA and and later removed after clicking on Delete
- Added a new test named "can unsubmit a review" in review_mapping_spec.rb
- In this test, a new reviewer is added to review mapping, a new review is created and submitted, and then checked if unsubmit functionality is working correctly
UI Testing
Steps to test adding participant:
- Login as instructor
- Go to Manage -> Assignments.
- Switch to Assignments tab incase you are on some other tab
- For any assignment, click on the 'Add Participant' icon to go on add new participant page
- Enter userid of the participant and click on Add to add the participant
Expected Output: When add button is clicked with valid userid, new participant should be added to the list without the page getting reloaded. In case of an attempt to add invalid user, the error should be displayed on top without page getting reloaded.
Steps to test adding/removing TA:
- Login as instructor
- Go to Manage -> Courses.
- Switch to Courses tab incase you are on some other tab
- For any course, click on the 'Add TA' icon to go on add new TA page
- Enter userid of the TA and click on Add to add the TA
- Click on 'remove_ta' link for any TA in the list to remove the TA
Expected Output: When add button is clicked with valid userid, new TA should be added to the list without the page getting reloaded. In case of an attempt to add invalid user, the error should be displayed on top without page getting reloaded. When remove_ta link is clicked for any TA in the list, that corresponding TA should be removed from the list without the page getting reloaded.
Steps to test adding question in questionnaire:
- Login as instructor
- Go to Manage -> Questionnaires. Create a new Review Questionnaire by clicking on the ‘New public item’ button for ‘Review’.
- Name the Questionnaire and click on create button
- Click on Edit for newly created questionnaire. You will now be navigated to page where you can add new questions to the questionnaire.
- Click on add button in "Questions" section.
Expected output: When add button is clicked, question should be created and the questionnaire page should not get reloaded
Steps to test un-submit reviews
- Login as instructor
- Go to Manage -> Assignments.
- Switch to Assignments tab incase you are on some other tab
- For any assignment, click on the 'Assign reviewers' icon to go to the review mappings page
- Note: Some assignments might not have reviewers. So, try this for assignments with many reviewers
- For any review with Review Status = Submitted, click on 'unsubmit' button
Expected output: For every review, the review status should be seen as either Assigned or Saved or Submitted. For submitted reviews, when unsubmit button is clicked, that review should be unsubmitted and status should change to Saved without page getting reloaded.
Project Deployment
Expertiza setup is done in VCL which is reserved for 30 days with Ubuntu 14.04 base. Started expertiza server publicly and link to access the server is: http://152.7.99.101:3000
Future work
In future, we will try to implement the edit questionnaire part using alternative approach. We will try to implement testing using rspec framework and improve the UI design of the pages.
References
- https://www.youtube.com/channel/UCdKXzox7hrWjfOMML6FzTWg
- https://github.com/expertiza/expertiza
- http://wiki.expertiza.ncsu.edu/index.php/Expertiza_documentation
- http://guides.rubyonrails.org/working_with_javascript_in_rails.html
- http://wiki.expertiza.ncsu.edu/index.php/Development:Setup:Linux:Debian