271 lines
8.8 KiB
Plaintext
271 lines
8.8 KiB
Plaintext
<div class="list-group">
|
|
<h4 id ="exercise_caption" class="list-group-item-heading" data-exercise-id="<%=@request_for_comment.exercise.id%>" data-comment-exercise-url="<%=create_comment_exercise_request_for_comment_path%>" data-rfc-id = "<%= @request_for_comment.id %>" ><%= link_to(@request_for_comment.exercise.title, [:implement, @request_for_comment.exercise]) %></h4>
|
|
<p class="list-group-item-text">
|
|
<%
|
|
user = @request_for_comment.user
|
|
submission = @request_for_comment.submission
|
|
%>
|
|
<%= user.displayname %> | <%= @request_for_comment.created_at.localtime %>
|
|
|
|
</p>
|
|
|
|
<h5>
|
|
<u><%= t('activerecord.attributes.exercise.description') %>:</u> <%= render_markdown(@request_for_comment.exercise.description) %>
|
|
</h5>
|
|
|
|
<h5>
|
|
<% if @request_for_comment.question and not @request_for_comment.question == '' %>
|
|
<u><%= t('activerecord.attributes.request_for_comments.question')%>:</u> "<%= @request_for_comment.question %>"
|
|
<% else %>
|
|
<u><%= t('activerecord.attributes.request_for_comments.question')%>:</u> <%= t('request_for_comments.no_question') %>
|
|
<% end %>
|
|
</h5>
|
|
|
|
<% if (policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved?) %>
|
|
<button class="btn btn-primary" id="mark-as-solved-button"><%= t('request_for_comments.mark_as_solved') %></button>
|
|
<% elsif (@request_for_comment.solved?) %>
|
|
<button type="button" class="btn btn-success"><%= t('request_for_comments.solved') %></button>
|
|
<% else %>
|
|
|
|
<% end %>
|
|
|
|
|
|
|
|
<% if @current_user.admin? && user.is_a?(ExternalUser) %>
|
|
<br>
|
|
<br>
|
|
<h4>Admin Menu</h4>
|
|
<h5>
|
|
<ul>
|
|
<li><%= link_to "User's current status of this exercise", statistics_external_user_exercise_path(id: @request_for_comment.exercise_id, external_user_id: @request_for_comment.user_id) %></li>
|
|
<li><%= link_to "All exercises of this user", statistics_external_user_path(id: @request_for_comment.user_id) %></li> <br>
|
|
<li><%= link_to "Implement the exercise yourself", implement_exercise_path(id: @request_for_comment.exercise_id) %> </li>
|
|
<li><%= link_to "Show the exercise", exercise_path(id: @request_for_comment.exercise_id) %> </li>
|
|
</ul>
|
|
</h5>
|
|
<% end %>
|
|
<h5>
|
|
<u><%= t('request_for_comments.howto_title') %></u><br> <%= render_markdown(t('request_for_comments.howto')) %>
|
|
</h5>
|
|
</div>
|
|
<hr>
|
|
<!--
|
|
do not put a carriage return in the line below. it will be present in the presentation of the source code, otherwise.
|
|
also, all settings from the rails model needed for the editor configuration in the JavaScript are attached to the editor as data attributes here.
|
|
-->
|
|
<% submission.files.each do |file| %>
|
|
<%= (file.path or "") + "/" + file.name + file.file_type.file_extension %><br>
|
|
<i class="fa fa-arrow-down" aria-hidden="true"></i> <%= t('request_for_comments.click_here') %>
|
|
<div id='commentitor' class='editor' data-read-only='true' data-file-id='<%=file.id%>' data-mode='<%=file.file_type.editor_mode%>'><%= file.content %>
|
|
</div>
|
|
<% end %>
|
|
|
|
<%= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.dialogtitle'), template: 'exercises/_comment_dialogcontent') %>
|
|
|
|
<script type="text/javascript">
|
|
|
|
var solvedButton = $('#mark-as-solved-button');
|
|
var commentOnExerciseButton = $('#comment-exercise-button');
|
|
var addCommentExerciseButton = $('#addCommentExerciseButton')
|
|
|
|
solvedButton.on('click', function(event){
|
|
var jqrequest = $.ajax({
|
|
dataType: 'json',
|
|
method: 'GET',
|
|
url: location + '/mark_as_solved'
|
|
});
|
|
|
|
jqrequest.done(function(response){
|
|
if(response.solved){
|
|
solvedButton.hide();
|
|
}
|
|
});
|
|
});
|
|
|
|
// set file paths for ace
|
|
var ACE_FILES_PATH = '/assets/ace/';
|
|
_.each(['modePath', 'themePath', 'workerPath'], function(attribute) {
|
|
ace.config.set(attribute, ACE_FILES_PATH);
|
|
});
|
|
|
|
var commentitor = $('.editor');
|
|
var userid = commentitor.data('user-id');
|
|
|
|
commentitor.each(function (index, editor) {
|
|
var currentEditor = ace.edit(editor);
|
|
currentEditor.setReadOnly(true);
|
|
// set editor mode (used for syntax highlighting
|
|
currentEditor.getSession().setMode($(editor).data('mode'));
|
|
|
|
setAnnotations(currentEditor, $(editor).data('file-id'));
|
|
currentEditor.on("guttermousedown", handleSidebarClick);
|
|
});
|
|
|
|
function setAnnotations(editor, fileid) {
|
|
var session = editor.getSession();
|
|
|
|
var jqrequest = $.ajax({
|
|
dataType: 'json',
|
|
method: 'GET',
|
|
url: '/comments',
|
|
data: {
|
|
file_id: fileid
|
|
}
|
|
});
|
|
|
|
jqrequest.done(function(response){
|
|
$.each(response, function(index, comment) {
|
|
comment.className = "code-ocean_comment";
|
|
|
|
// if we have tabs or carriage returns in the comment, just add the name and leave it as it is. otherwise: format!
|
|
if(comment.text.includes("\n") || comment.text.includes("\t")){
|
|
comment.text = comment.username + ": " + comment.text;
|
|
} else {
|
|
comment.text = comment.username + ": " + stringDivider(comment.text, 80, "\n\t\t");
|
|
}
|
|
|
|
});
|
|
|
|
session.setAnnotations(response);
|
|
})
|
|
}
|
|
|
|
function hasCommentsInRow(editor, row){
|
|
return editor.getSession().getAnnotations().some(function(element) {
|
|
return element.row === row;
|
|
})
|
|
}
|
|
|
|
function getCommentsForRow(editor, row){
|
|
return editor.getSession().getAnnotations().filter(function(element) {
|
|
return element.row === row;
|
|
})
|
|
}
|
|
|
|
function deleteComment(file_id, row, editor) {
|
|
var jqxhr = $.ajax({
|
|
type: 'DELETE',
|
|
url: "/comments",
|
|
data: {
|
|
row: row,
|
|
file_id: file_id }
|
|
});
|
|
jqxhr.done(function (response) {
|
|
setAnnotations(editor, file_id);
|
|
});
|
|
jqxhr.fail(ajaxError);
|
|
}
|
|
|
|
function createComment(file_id, row, editor, commenttext){
|
|
var jqxhr = $.ajax({
|
|
data: {
|
|
comment: {
|
|
file_id: file_id,
|
|
row: row,
|
|
column: 0,
|
|
text: commenttext,
|
|
request_id: $('h4#exercise_caption').data('rfc-id')
|
|
}
|
|
},
|
|
dataType: 'json',
|
|
method: 'POST',
|
|
url: "/comments"
|
|
});
|
|
jqxhr.done(function(response){
|
|
setAnnotations(editor, file_id);
|
|
});
|
|
jqxhr.fail(ajaxError);
|
|
}
|
|
|
|
function createCommentOnExercise(file_id, row, editor, commenttext){
|
|
var jqxhr = $.ajax({
|
|
data: {
|
|
comment: {
|
|
file_id: file_id,
|
|
row: row,
|
|
column: 0,
|
|
text: commenttext,
|
|
request_id: $('h4#exercise_caption').data('rfc-id')
|
|
}
|
|
},
|
|
dataType: 'json',
|
|
method: 'POST',
|
|
url: "/comments"
|
|
});
|
|
jqxhr.done(function(response){
|
|
setAnnotations(editor, file_id);
|
|
});
|
|
jqxhr.fail(ajaxError);
|
|
}
|
|
|
|
function handleSidebarClick(e) {
|
|
var target = e.domEvent.target;
|
|
var editor = e.editor;
|
|
|
|
if (target.className.indexOf("ace_gutter-cell") == -1) return;
|
|
//if (!editor.isFocused()) return;
|
|
//if (e.clientX > 25 + target.getBoundingClientRect().left) return;
|
|
|
|
|
|
var row = e.getDocumentPosition().row;
|
|
e.stop();
|
|
|
|
var commentModal = $('#comment-modal');
|
|
|
|
if (hasCommentsInRow(editor, row)) {
|
|
var rowComments = getCommentsForRow(editor, row);
|
|
var comments = _.pluck(rowComments, 'text').join('\n');
|
|
commentModal.find('#otherComments').show();
|
|
commentModal.find('#otherCommentsTextfield').text(comments);
|
|
} else {
|
|
commentModal.find('#otherComments').hide();
|
|
}
|
|
|
|
commentModal.find('#addCommentButton').off('click');
|
|
commentModal.find('#removeAllButton').off('click');
|
|
|
|
commentModal.find('#addCommentButton').on('click', function(e){
|
|
var commenttext = commentModal.find('textarea').val();
|
|
var file_id = $(editor.container).data('file-id');
|
|
|
|
if (commenttext !== "") {
|
|
createComment(file_id, row, editor, commenttext);
|
|
commentModal.find('textarea').val('') ;
|
|
commentModal.modal('hide');
|
|
}
|
|
});
|
|
|
|
commentModal.find('#removeAllButton').on('click', function(e){
|
|
var file_id = $(editor.container).data('file-id');
|
|
deleteComment(file_id, row, editor);
|
|
commentModal.modal('hide');
|
|
});
|
|
|
|
commentModal.modal('show');
|
|
}
|
|
|
|
function ajaxError(response) {
|
|
var message = ((response || {}).responseJSON || {}).message || '';
|
|
|
|
$.flash.danger({
|
|
text: message.length > 0 ? message : $('#flash').data('message-failure')
|
|
});
|
|
};
|
|
|
|
|
|
function stringDivider(str, width, spaceReplacer) {
|
|
if (str.length>width) {
|
|
var p=width
|
|
for (;p>0 && str[p]!=' ';p--) {
|
|
}
|
|
if (p>0) {
|
|
var left = str.substring(0, p);
|
|
var right = str.substring(p+1);
|
|
return left + spaceReplacer + stringDivider(right, width, spaceReplacer);
|
|
}
|
|
}
|
|
return str;
|
|
}
|
|
|
|
</script>
|