CSC/ECE 517 Fall 2019 - E1966. Tabbed reviews partial file refactor for displaying the alternate view of reviews

From Expertiza_Wiki
Jump to navigation Jump to search

About Expertiza

Expertiza is a open source project currently for CSC517 instructor and students forming groups, submit work, review, and view grades. The project is based on Ruby on Rails framework and the code is on Github: https://github.com/expertiza/expertiza. Expertiza serves wiki page, collecting information of all internal information and updates of all versions.

Problem Statement

Issue details

1) On student-end, Expertiza uses grades/_reviews.html.erb partial file to display reviewers, scores and review details; on instructor-end, it uses Response model methods to construct html file for review pages. We need to use the same kinds of partials in instructor-end and student-end, so we decide to use grades/_team_statistics.html.erb to display reviewers and scores and to use grades/_tabbed_reviews.html.erb to display review details.

2) Give Feedback link at view_my_score at student-end should not appear at folded view. Give Feedback link at view_my_score should appear at the bottom of expanded view.

What to do

1) We need to use the same kinds of partials in instructor-end and student-end.

2) Give Feedback link at view_my_score should appear at the bottom of expanded view.

Solution

Deploy Link

Our project is deployed at VCL

Student End

  • In student end, add render partial to tabbed reviews.

app/views/grades/_participant.html.erb

<TR id="<%= prefix %>_reviews" style="display:none; background-color: white;">
    <TD COLSPAN="10"><%= render :partial=>'grades/reviews', :locals => {:prefix => 'user', :participant => participant, :rscore => pscore[:review]} %></TD>
    <TD COLSPAN="10"><%= render :partial=>'grades/tabbed_reviews', :locals => {:prefix => 'user', :participant => participant, :rscore => pscore[:review]} %></TD>
</TR>
  • Add feed back link in student end view.

app/views/grades/_tabbed_reviews.html.erb

    <% rounds.each do |round| %>
        <h3>Round <%= round %></h3>
        <a href="#" name= <%= participant.id.to_s + '_' + round.to_s + "Link" %> onClick="toggleElement('<%= participant.id.to_s +
                 '_' + round.to_s %>','round <%= round.to_s%> reviews');return false;">show round <%= round.to_s%> reviews</a>
        <table class="table table-striped" id=<%= participant.id.to_s + '_' + round.to_s %> <%= style="display: none;" if controller.action_name != "view_my_scores"%>>
            <% rscore[:assessments].select{|response| response.round == round}.reverse.uniq{|response| response.map_id}.sort_by{|response| response.map_id}.each_with_index do |review, index| %>
                <tr><td>
                <% review_feedback = nil %>
                        <%= display_directory_tree(@participant, files, true).html_safe %>
                    <% end %>
                <% end %>
                <%= review.display_as_html(prefix, index + 1, nil, true) %>
                <!-- Generate the feedback html -->
                <% map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id: participant.id).first
                    review_feedbacks = map.try :response %>
                <% if review_feedbacks && !review_feedbacks.empty? %>
                    <%= link_to "View", :controller => 'response', :action => 'view', :id => review_feedbacks.first.id %> or
                    <%= link_to "Edit", :controller => 'response', :action => 'edit', :id => review_feedbacks.first.id, :return => "feedback" %> feedback for Review <%= count %>
                <% else %>                   
                    <%= link_to "Give feedback", :controller => 'response', :action => 'new_feedback', :id => review.id %> for Review <%= count %>
                <% end %>
                </td></tr>
            <% end %>
        </table><hr>
  • Add javascript to tabbed review so it can be hidden or shown by clicking the show/hide reviews.

app/views/grades/_tabbed_reviews.html.erb

<script type="text/javascript">
  toggle_tag_prompt = function() {
    $('.tag_prompt_container').toggle();
  };
  $( document ).ready(function() {
    $('#tag_prompt_toggler').click(function () {
      if ($('#tag_prompt_toggler').text() == "hide tags")
        $('#tag_prompt_toggler').text("show tags")
      else
        $('#tag_prompt_toggler').text("hide tags")
    });
  });
</script>
  • Add statistic view to student end by using the team_review_statistics.html.erb file.

app/views/grades/_participant.html.erb

<TR id="<%= prefix %>_reviews" style="display:none; background-color: white;">
    <TD COLSPAN="10">
    <%= render :partial=>'grades/team_review_statistics', :locals => {:prefix => 'user', :participant => participant, :pscore => pscore} %>
    <%= render :partial=>'grades/tabbed_reviews', :locals => {:prefix => 'user', :participant => participant, :rscore => pscore[:review]} %>
    </TD>
</TR>

app/views/grades/_tabbed_reviews.html.erb

<% if @assignment.is_answer_tagging_allowed %>
            <span class="spn_qsttog" id="tag_prompt_toggler" title="Click to display/hide tags" onclick="toggle_tag_prompt()">hide tags</span>
        <% end %>

app/views/grades/_team_review_statistics.html.erb

<% if controller.action_name != "view_my_scores"%>
    <tr>
        <td colspan="10">
<% end %> 

<% if rscore and rscore[:assessments].length > 0 %>
    <%flag_varying_rubrics=false%>

@@ -25,6 +29,9 @@
    <%if flag_varying_rubrics==false%>
        <%= render :partial => 'grades/review_table', :locals => { :ctrl => 'review', :caction => 'view_review', :symbol => "review".to_sym, :prefix => prefix, :assignment => participant.assignment, :reviews => rscore[:assessments], :collabel => "Review", :rowlabel => "Reviewer" }%>
    <%end%>
    </td>
</tr>
<% end %>  

<% if controller.action_name != "view_my_scores"%>    
        </td>
    </tr>
<% end %> 

Instructor End

  • Create new method view2 for response_controller

app/controllers/response_controller.rb

def view2
    @response = Response.find(params[:id])
    @map = @response.map
    set_content2
    render "response/view"
  end 
......
......
    @participant = @map.reviewer
......
def set_content2(new_response = false)
    @contributor = @map.contributor
    members = TeamsUser.where(team_id: params[:team])
    @user = members.first
    @participant = AssignmentParticipant.where(user_id: @user.user_id, parent_id: params[:assignment]).first
@@ -264,7 +273,9 @@ def set_content(new_response = false)
    @questions = retrieve_questions questionnaires, @assignment.id
    # @pscore has the newest versions of response for each response map, and only one for each response map (unless it is vary rubric by round)
    @pscore = @participant.scores(@questions)
    @reviewer = @map.reviewer
    @round = params[:round]
  end  

app/views/grades/_tabbed_reviews.html.erb

                <% prefix = nil %>
......
<% if controller.action_name == "view_my_scores"%>
                    <!-- Generate the feedback html -->
                    <% map = FeedbackResponseMap.where(reviewed_object_id: review.id, reviewer_id: participant.id).first
                        review_feedbacks = map.try :response %>
                    <% if review_feedbacks && !review_feedbacks.empty? %>
                        <%= link_to "View", :controller => 'response', :action => 'view', :id => review_feedbacks.first.id %> or
                        <%= link_to "Edit", :controller => 'response', :action => 'edit', :id => review_feedbacks.first.id, :return => "feedback" %> feedback for Review <%= count %>
                    <% else %>
                        <%= link_to "Give feedback", :controller => 'response', :action => 'new_feedback', :id => review.id %> for Review <%= count %>
                    <% end %>
                </td></tr>
                <% end %>
            <% end %>
        </table><hr>
    <% end %>

app/views/grades/_view_heatgrid.html.erb

                      <th class="sorter-false"> <a target="_blank" href="../response/view2?id=<%= review.id.to_s %>&&team=<%= @team.id %>&&round=<%= vm.round.to_s %>&&assignment=<%= @assignment.id %>"  
data-toggle="tooltip" data-placement="right" title="Click to see details"><%= user_name.to_s %></a>  </th>

app/views/response/view.html.erb

<% if controller.action_name != "view2" %>
    <% file_url = nil %>
    <%= @response.display_as_html(nil, nil, file_url) %>
    <br/>
<% else %>
    <TR style="display:none; background-color: white;">
        <TD COLSPAN="10">
        <%= render :partial=>'grades/tabbed_reviews', :locals => {:prefix => 'user', :participant => @participant, :rscore => @pscore[:review], :reviewer => @reviewer, :round => @round} %>
        </TD>
    </TR>
<% end %>
  • show right round for instructor-end

app/views/grades/_tabbed_reviews.html.erb

        <% next if round.to_s != @round.to_s %>
  • Create construct_instructor2_html in order to not show review number

app/models/response.rb

if prefix == "instructor"
      self_id = self.id.to_s
      code = construct_instructor2_html identifier, self_id, count
    elsif prefix # has prefix means view_score page in instructor end
      self_id = prefix + '_' + self.id.to_s
      code = construct_instructor_html identifier, self_id, count
......
def construct_instructor2_html identifier, self_id, count
    identifier += '<table width="100%">'\
						 '<tr>'\
						 '<td align="left" width="70%"><b>Review ' + '</b>   '\
						 '<a href="#" name= "review_' + self_id + 'Link" onClick="toggleElement(' + "'review_" + self_id + "','review'" + ');return false;">hide review</a>'\
						 '</td>'\
						 '<td align="left"><b>Last Reviewed:</b>'\
						 "<span>#{(self.updated_at.nil? ? 'Not available' : self.updated_at.strftime('%A %B %d %Y, %I:%M%p'))}</span></td>"\
						 '</tr></table>'
  end

app/views/grades/_tabbed_reviews.html.erb

<% if controller.action_name != "view2"%>
            <h3>Round <%= round %></h3>
            <% if controller.action_name != "view_my_scores" %>
                <a href="#" name= <%= participant.id.to_s + '_' + round.to_s + "Link" %> onClick="toggleElement('<%= participant.id.to_s + '_' + round.to_s %>','round <%= round.to_s%> reviews');return false;">show round <%= round.to_s%> reviews</a>
            <% end %>
        <% end %>
        <% if @assignment.is_answer_tagging_allowed %>
            <span class="spn_qsttog" id="tag_prompt_toggler" title="Click to display/hide tags" onclick="toggle_tag_prompt()">hide tags</span>
@@ -37,6 +39,7 @@
                <% review_feedback = nil %>
                <% count = count + 1 %>
                <% prefix = nil %>
                <% prefix = "instructor" if controller.action_name == "view2" %>
  • Show just one review in instructor-end

app/views/grades/_tabbed_reviews.html.erb

<% rounds.each do |round| %>
        <% if controller.action_name == "view2"%>
        <% next if round.to_s != @round.to_s %>
        <% end %>
        <% if controller.action_name != "view2"%>
            <h3>Round <%= round %></h3>
            <% if controller.action_name != "view_my_scores" %>
@@ -33,8 +35,13 @@
        <% if @assignment.is_answer_tagging_allowed %>
            <span class="spn_qsttog" id="tag_prompt_toggler" title="Click to display/hide tags" onclick="toggle_tag_prompt()">hide tags</span>
        <% end %>
        <% if controller.action_name != "view2"%>
        <table class="table table-striped" id=<%= participant.id.to_s + '_' + round.to_s %> <%= style="display: none;" if controller.action_name != "view_my_scores"%>>
        <% end %>
            <% rscore[:assessments].select{|response| response.round == round}.reverse.uniq{|response| response.map_id}.sort_by{|response| response.map_id}.each_with_index do |review, index| %>
                <% if controller.action_name == "view2"%>
                <% next if review.reviewer != @reviewer || count > 0 %>
                <% end %>
                <tr><td>
                <% review_feedback = nil %>
                <% count = count + 1 %>
@@ -72,7 +79,9 @@
                </td></tr>
                <% end %>
            <% end %>
        <% if controller.action_name != "view2"%>    
        </table><hr>
        <% end %>
    <% end %>
<% else %>


Test files

  • tabbed_review_spec.rb created and added 3 test cases for alternate view of reviews

spec/features/tabbed_review_spec.rb

require "spec_helper"
require 'rspec'
describe "alternate view of reviews" do
    before(:each) do
      assignment1 = create(:assignment, name: "111", directory_path: 'test_assignment')
      create_list(:participant, 3)
      create(:assignment_node)
      create(:deadline_type, name: "submission")
      create(:deadline_type, name: "review")
      create(:deadline_type, name: "metareview")
      create(:deadline_type, name: "drop_topic")
      create(:deadline_type, name: "signup")
      create(:deadline_type, name: "team_formation")
      create(:deadline_right)
      create(:deadline_right, name: 'Late')
      create(:deadline_right, name: 'OK')
      create(:assignment_due_date, deadline_type: DeadlineType.where(name: 'review').first, due_at: Time.now.in_time_zone + 1.day)
      create(:topic)
      create(:topic, topic_name: "TestReview")
      create(:team_user, user: User.where(role_id: 2).first)
      create(:team_user, user: User.where(role_id: 2).second)
      create(:assignment_team)
      create(:team_user, user: User.where(role_id: 2).third, team: AssignmentTeam.second)
      create(:signed_up_team)
      create(:signed_up_team, team_id: 2, topic: SignUpTopic.second)
      create(:assignment_questionnaire)
      create(:question)
      # create(:review_response_map, reviewer_id: User.where(role_id: 2).third.id)
      # create(:review_response_map, reviewer_id: User.where(role_id: 2).second.id, reviewee: AssignmentTeam.second)
      # sleep(10000)
    end

  def load_alternate
    login_as('student2064')
    expect(page).to have_content "User: student2064"
    expect(page).to have_content "111"

    click_link "111"
    expect(page).to have_content "Submit or Review work for 111"
    expect(page).to have_content "Alternate View"

    click_link "Alternate View"
    expect(page).to have_content "Contributor"
  end

  it "shows the correct alternate view" do
    # Load questionnaire with generic setup
    load_alternate
    expect(page).to have_content "Contributor"
    expect(page).to have_content "Stats"
    expect(page).to have_content "Submitted work"
    expect(page).to have_content "Author Feedback"
    expect(page).to have_content "Teammate Review"
    expect(page).to have_content "Final Score"
    expect(page).to have_content "Range"
    expect(page).to have_content "Average"
    expect(page).to have_content "student2064"

    expect(page).to have_css "a[href='#']", text: 'hide stats' 
    expect(page).to have_css "a[href='#']", text: 'show submission' 
    #expect(page).to have_css "a[href='#']", text: 'show reviews' 
    #page.should have_selector('table tr', text: 'show reviews')
    #find(:xpath, "//tr[contains(.,'show reviews')]/td/a", :text => 'show reviews').click
    #expect(page).to have_content "Writeup"
    end
      #describe "grades/participant", :type => :view do
        #it 'exists' do
          #find(:xpath, "//tr[contains(.,'show reviews')]/td/a", :text => 'show reviews').click
        #end
      #end
end

describe "test for instructor" do
  before (:each) do
    create(:instructor)
    create(:assignment, course: nil, name: 'Test Assignment')
    assignment_id = Assignment.where(name: 'Test Assignment')[0].id

    assignment_team = create(:assignment_team)

    create(:team_user)
    login_as 'instructor6'
    visit "/grades/view?id=#{assignment_id}"

  end

  it "shows summary report" do
    expect(page).to have_content "Summary report for Test Assignment"
    expect(page).to have_content "Show all teams"
    page.first(:xpath, "//a[contains(@href,'#')]").click

  end


end

describe "test for instructor" do
  before (:each) do
    create(:instructor)
    @assignment = create(:assignment, name: "Test Assignment", directory_path: 'test_assignment')
    assignment_id = Assignment.where(name: 'Test Assignment')[0].id
    assignment_team = create(:assignment_team)
    create(:team_user)
    team_id = AssignmentTeam.first.id.to_s
    create(:topic)
    create(:topic, topic_name: "TestReview")
    create(:assignment_questionnaire)
    create(:question)
    create(:signed_up_team)
    create(:signed_up_team, team_id: 2, topic: SignUpTopic.second)
    #create(:review)
    #review_id = Review.first.id.to_s
    #create(:review_response_map, reviewer_id: User.where(role_id: 2).third.id)
    login_as 'instructor6'
    #visit "/response/view2?id=#{review_id}&&team=#{team_id}&&round=1&&assignment=#{assignment_id}"
  end
  it "can go to review details" do
    login_as 'instructor6'
    visit "/response/view2?id=#{review_id}&&team=#{team_id}&&round=1&&assignment=#{assignment_id}"
  end
  it "can go to review details" do
  end
end

Team Information

  1. Forked Issue on Github
  2. Weiran Fu (@ncsu.edu)
  3. Qingyan Wang (qwang20@ncsu.edu)
  4. Hongli Wang (hwang85@ncsu.edu)
  5. Mentor: Mohit Jain (mjain6@ncsu.edu)

References

  1. Expertiza on GitHub
  2. The live Expertiza website
  3. Expertiza project documentation wiki
  4. Rspec Documentation