app/views/response/response.html.erb
<!-- <script type="text/javascript" src="/assets/response.js" ></script> -->
<!--including tinymce javascript-->
<%= tinymce_assets %>
<%= tinymce %>
<script>
// todo: to be moved to assets, once it's fixed so that not every script is loaded in every page.
//detect if the window is in foreground or background
var vis = (function(){
var stateKey, eventKey, keys = {
hidden: "visibilitychange",
webkitHidden: "webkitvisibilitychange",
mozHidden: "mozvisibilitychange",
msHidden: "msvisibilitychange"
};
for (stateKey in keys) {
if (stateKey in document) {
eventKey = keys[stateKey];
break;
}
}
return function(c) {
if (c) document.addEventListener(eventKey, c);
return !document[stateKey];
}
})();
jQuery(document).ready(function() {
//use barrating for dropdown
$('.review-rating').each(function(index, el) {
var $El;
$El = $(el);
$El.barrating({
theme: 'fontawesome-stars',
initialRating: $El.attr('data-current-rating'),
showSelectedRating: true
});
});
// auto save every changes to local storage
$(function(){
$("form").sisyphus({
locationBased: true,
autoRelease: true
});
});
// Server AUTO SAVE: triggers every 60 seconds to save the draft version of the review to database
var interval = 60000;
var last_save = new Date();
// detect how many seconds the userhas been idle
var idleTime = 0;
//threshold to turn off the autosave
var maxIdleTime = 30;
$('#autosave_cbx_lbl').html(" Auto save your response every " + interval / 1000 + " seconds? ");
//if it's was in the background, don't auto save to avoid conflict
setInterval(function() {
if(vis() && $("#autosave_cbx").prop("checked"))
executeSave();
}, interval);
//click ajax
function executeSave(){
timeDiff = (new Date().getTime() - last_save.getTime())/1000;
// ignore saving unless the last save was more than 5s
if (timeDiff>5 && $('.review_form').length > 0) {
$('form').attr('data-remote', 'true');
$('#save_review').click();
last_save = new Date;
if ($('input[name=saved]').value = "0")
$('input[name=saved]').val("1");
$('form').removeAttr('data-remote');
}
$(document).ajaxError(function(event, request, settings) {
if (settings.url.includes("response") && settings.type == "POST")
$('#save_progress').html('<span id="tick"> ⛔ </span>' + 'Unable to reach the expertiza server. <br>Create a backup of your comments and you may try to login again in a while');
})
$('form#<%=@modified_object%>').bind('ajax:success', function(evt, data, status, xhr){
$('#save_progress').html('<span id="tick"> ✔ </span>' +
'A draft was saved on ' + last_save.toLocaleString('en-US', {
weekday: 'short',
day: 'numeric',
month: 'short',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
hour12: true }));
});
}
$('#save_review').click(function(){
$('#save_confirm').html('<span id="tick"> ✔ </span> Saving review!')
setTimeout(function(){
$('#save_confirm').html('')
}, 5000);
});
$('#Submit').click(function(e){
if(!confirm('Once a review has been submitted, you cannot edit it again')){
e.preventDefault();
e.stopPropagation();
return;
}else{
jQuery('#isSubmit').val('Yes');
window.location.href= "../../../student_review/list?id=<%= @map.reviewer.id %>";
}
});
// update the values in the form using ajax
function updateForm(){
//update the additional comments
$.get("../../../response/json?response_id=<%= @response.id %>", function(data){
if(data.additional_comment != null) {
tinymce.get('review_comments').setContent(data.additional_comment);
}
});
//update the questions
$.get("../../../answer?response_id=<%= @response.id %>&questionnaire_id=<%= @questionnaire.id %>", function(data){
var index, len;
$("[type=radio]").each(function (){
$(this).removeAttr("checked");
});
var tinymce_index = 0
for (index = 0, len = data.length; index < len; ++index) {
switch(data[index].qtype){
case "Criterion":
if(data[index].answer != null) {
$('#responses_' + index + '_score').val(data[index].answer);
<% if @dropdown_or_scale == "dropdown" %>
$('#responses_' + index + '_score').barrating('set', data[index].answer);
<% else %>
$("input[name='Radio_" + data[index].question_id +"']").each(function(){
if(data[index].answer == $(this).val())
$(this).prop("checked", "true");
else
$(this).removeProp("checked");
});
<% end %>
}
if(data[index].comments != null)
tinymce.get('responses_' + index + '_comments').setContent(data[index].comments);
break;
case "TextArea" :
if(data[index].comments != null)
tinymce.get('responses_' + index + '_comments').setContent(data[index].comments);
break;
case "TextField":
if(data[index].comments != null)
$('#responses_' + index + '_comments').val(data[index].comments);
break;
case "Checkbox" :
if(data[index].answer != null)
$('#responses_' + index + '_score').prop( "checked", data[index].score == 1).change();
break;
case "Dropdown" :
if(data[index].comments != null) {
$('#responses_' + index + '_comments').val(data[index].comments);
}
break;
case "Scale":
$("input[name='Radio_" + data[index].question_id +"']").each(function(){
if(data[index].answer == $(this).val())
$(this).prop("checked", "true");
else
$(this).removeProp("checked");
});
break;
default:
}
}
// release the form
removeOverlay();
});
}
// update the form after it's back to the foreground.
// save review when the window is sent to background
vis(function () {
// reload review when the window is sent to the foreground
if (vis() && $("#autosave_cbx").prop("checked")){
// freeze the form until it's updated
displayOverlay("Loading");
// delay one second to let the data saved if the user switch back and forth
setTimeout(function() {
updateForm();
}, 1000);
}else if (!vis() && $("#autosave_cbx").prop("checked")){
executeSave();
//console.log("Saving before going to background at " + new Date().toLocaleString('en-US', { weekday: 'short', day: 'numeric', month: 'short', year: 'numeric', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: true }));
}
});
//overlay to block user entering new info before the form is updated with data from the server
function displayOverlay(text) {
$("<table id='overlay'><tbody><tr><td>" + text + "</td></tr></tbody></table>").css({
"position": "fixed",
"top": "0px",
"left": "0px",
"width": "100%",
"height": "100%",
"background-color": "rgba(0,0,0,.5)",
"z-index": "10000",
"vertical-align": "middle",
"text-align": "center",
"color": "#fff",
"font-size": "40px",
"font-weight": "bold",
"cursor": "wait"
}).appendTo("body");
}
function removeOverlay() {
$("#overlay").remove();
}
//Increment the idle time counter every minute and restart the timer if there is a mouse movement or keypress.
var idleInterval = setInterval(function(){
idleTime = idleTime + 1;
if (idleTime >= maxIdleTime && vis() && $("#autosave_cbx").prop("checked")) {
$("#autosave_cbx").removeProp("checked");
setTimeout(function(){
var r = confirm("The window has been idle more than " + maxIdleTime + " minutes. Auto save is disabled. Do you want to enable it again?");
if (r == true) {
updateForm();
$("#autosave_cbx").prop("checked","true");
}else
$("#autosave_cbx").removeProp("checked");
}, 1000);
}
}, interval);
//Zero the idle timer on mouse movement.
$(this).mousemove(function (e) {
idleTime = 0;
});
$(this).keypress(function (e) {
idleTime = 0;
});
//restart the counter if it's just checked
$("#autosave_cbx").change(function (e){
if($(this).prop("checked"))
idleTime = 0;
});
/// end auto reload
//attach event handler to all tinymce editors
tinyMCE.on('AddEditor', function(e) {
e.editor.on('blur', function (e) {
ed = e.target;
if (ed.id.includes("comments")){
json_review = JSON.stringify({ "review": ed.getContent({format : 'text'}) })
$.ajax({
url: "http://peerlogic.csc.ncsu.edu/sentiment/visualize_sentiment",
type: "POST",
crossDomain: true,
contentType: "application/json",
data: json_review,
dataType: "html",
success: function (response) {
var toneAnalysisResult = '<div class="panel panel-default">' +
'<div class="panel-heading">Tone analysis</div>' +
'<div class="panel-body">' + response + '</div>' +
'</div>'
if(ed.id.includes("responses"))
$('#' + ed.id.replace("responses", "analysis")).html(toneAnalysisResult);
else if(ed.id.includes('review_comments'))
$('#review_comments_analysis').html(toneAnalysisResult);
},
error: function (xhr, status) {
$('#save_progress').html('Unable to reach tone analysis service at the moment')
}
});
}
});
});
});
</script>
<% if @map.survey? %>
<h1><%= @header %> <%= @title %> for <%= @map.survey_parent.name %></h1>
<% else %>
<h1><%= @header %> <%= @title %> for <%= @map.assignment.name %></h1>
<% if !@map.contributor.nil? && !@map.instance_of?(FeedbackResponseMap) %>
<% if @map.assignment.team_assignment? %>
<% team_member = TeamsUser.find_by_team_id(@map.contributor).user_id%>
<% topic_id = SignedUpTeam.topic_id(@map.assignment.id, team_member) %>
<% else %>
<% participant = Participant.find(TeamsUser.find_by_team_id(@map.contributor).user_id) %>
<% topic_id = SignedUpTeam.where(participant.parent_id, participant.user_id) %>
<% end %>
<% if !topic_id.nil? %>
<% topic = SignUpTopic.find(topic_id)%>
<h2>You are reviewing <%= topic.topic_name %></h2>
<% if !topic.description.nil? %>
<b>Description </b>
<% if topic.description.to_s.length>90 %>
<%= topic.description.to_s[0..90]+'...'%>
<a style="cursor: pointer" onclick="show_alert('<%= topic.description%>')">more...</a>
<% else %>
<%= topic.description.to_s%>
<% end %>
<% if topic.link != nil then %>
<%= link_to image_tag('external-link-16.png', :border => 0, :align => 'middle'), topic.link, :target=>'_blank' %>
<% end%>
<% end %>
<% end %>
<%if @assignment.teams?%>
<% topic_id = SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id) %>
<%= render :partial => 'submitted_content/main', :locals => {:reviewee_participant => @contributor.participants.first,:participant => @contributor.participants.first, :stage => @assignment.get_current_stage(topic_id)} %>
<%else%>
<% topic_id = SignedUpTeam.topic_id(@participant.parent_id, @participant.user_id) %>
<%= render :partial => 'submitted_content/main', :locals => {:participant => @contributor, :stage => @assignment.get_current_stage(topic_id)} %>
<%end%>
<hr/>
<% end %>
<% end %>
<!-- display all versions available -->
<% @responses_versions = Array.new %>
<% @responses_versions = @map.get_all_versions() %>
<% if @responses_versions.empty? %>
<I>No previous review was performed.</I><br/><hr/><br/>
<% else %>
<%= render :partial => 'review', :locals => {:versions => @responses_versions} %>
<% end %>
<h2>Directions for the reviewer</h2>
<input type="checkbox" id="autosave_cbx" checked>
<label id="autosave_cbx_lbl" for="autosave_cbx"></label>
<div id="save_progress"></div>
<%= form_tag({:action => @next_action}, :id => @modified_object, :class => "review_form") do %>
<%= hidden_field_tag "map_id", @modified_object %>
<%= hidden_field_tag "saved", (@header == "New") ? 1 : 0 %>
<% if @next_action.eql?'update' %>
<input name="_method" type="hidden" value="put" />
<%end%>
<table width="100%">
<tr>
<td>
<% i = 0 %>
<% @questions.each do |question| %>
<% answer = Answer.where(question_id: question.id, response_id: @response.id).first if !@response.nil?%>
<% if question.instance_of? Criterion%>
<%= question.complete(i, answer, @questionnaire.min_question_score, @questionnaire.max_question_score, @dropdown_or_scale) %>
<% elsif question.instance_of? Scale %>
<%= question.complete(i, answer, @questionnaire.min_question_score, @questionnaire.max_question_score) %>
<% else %>
<%= question.complete(i, answer) %>
<% end %>
<% if [Criterion, TextArea].include? question.class %>
<div id="analysis_<%= i.to_s %>_comments"></div>
<% end %>
<% i += 1%>
<% end %>
</td>
</tr>
<tr>
<td>
<label for="review_comments">Additional Comments</label><BR/>
<textarea cols="70" rows="1" id="review_comments" name="review[comments]" style="overflow:hidden;" class="tinymce">
<% if controller.action_name != 'new' and @response.additional_comment != nil %>
<%= @response.additional_comment.strip if !@response.nil?%>
<% end %>
</textarea>
</td>
<td width="25%">
<div id="review_comments_analysis"></div>
</td>
</tr>
<!-- Add a Good Teammate badge to the Teammate Review Questionnaire if the assignment has badges -->
<% if @assignment.has_badge? and (@questionnaire.type == 'TeammateReviewQuestionnaire' or @questionnaire.type == 'Teammate ReviewQuestionnaire') and AssignmentBadge.where(assignment_id: @assignment.id, badge_id: Badge.get_id_from_name('Good Teammate')).any?%>
<tr>
<td>
<img width = "100px" src=<%= "/assets/badges/#{Badge.get_image_name_from_name("Good Teammate")}" %> title="GoodTeammate">
Would you like to award a Good Teammate badge?
<input type="checkbox" id="good_teammate_checkbox" name="review[good_teammate_checkbox]">
</td>
</tr>
<% end%>
<!-- Add a Good Reviewer badge to the Feedback Review Questionnaire if the assignment has badges -->
<% if @assignment.has_badge? and (@questionnaire.type == 'AuthorFeedbackQuestionnaire' or @questionnaire.type == 'Author FeedbackQuestionnaire') and AssignmentBadge.where(assignment_id: @assignment.id, badge_id: Badge.get_id_from_name('Good Reviewer')).any?%>
<tr>
<td>
<img width="100px" src=<%= "/assets/badges/#{Badge.get_image_name_from_name("Good Reviewer")}" %> title="GoodReviewer">
Would you like to award a Good Reviewer badge?
<input type="checkbox" id="good_reviewer_checkbox" name="review[good_reviewer_checkbox]">
</td>
</tr>
<% end %>
</table>
<%if @current_round%>
<%= hidden_field_tag "review[round]", @current_round %>
<%end%>
<%= hidden_field_tag "review[questionnaire_id]", @questionnaire.id %>
<br/>
<br>
<div id="save_confirm"></div>
<%= submit_tag "Save "+@title, :name => "save", :id => "save_review" %>
<!--#E1600 check title for selfreview to show submit button-->
<% if @title && ((@title.eql? 'Review') || (@title.eql? 'Self Review')) %>
<%= submit_tag "Submit "+@title, :name => "Submit", :id => "Submit" %>
<img src="/assets/info.png" title='- SAVE will only store the peer-review as draft and the peer-review will not be displayed to the reviewee. After clicking SUBMIT, the peer-review will be displayed to reviewee, and you will not be able to update it any more.'>
<% end %>
<%= hidden_field_tag('return', @return) %>
<%= hidden_field_tag "isSubmit", :id=>"isSubmit" %>
<% end %>
<!--Check whether there is a UploadFile question.-->
<%@questions.each do |question| %>
<% if question.instance_of? UploadFile %>
<!--params[:origin] means from where do the files upload-->
<!--If the files uploaded from submitted_work (students hand in assignment), params[:origin] will be nil-->
<!--If the files uploaded from peer review, params[:origin] will be 'review'-->
<% if params[:action] == 'new' %>
<% response_map_id = params[:id] %>
<% elsif params[:action] == 'edit' %>
<% response_map_id = Response.find(params[:id]).response_map.id %>
<% end %>
<%= render partial: 'submitted_content/submitted_files', locals: {participant: @participant, stage: @stage, origin: 'review', response_map_id: response_map_id} %>
<% end %>
<% end %>
<%= @map.show_feedback(@response) %>
<a href="javascript:window.history.back()">Back</a>
<div id="dialog-message" style="word-wrap: normal"></div>