Merge branch 'zd_SCI_436' of https://github.com/ZmagoD/scinote-web into ZmagoD-zd_SCI_436

This commit is contained in:
zmagod 2016-09-21 19:20:55 +02:00
commit 06b1992e94
26 changed files with 263 additions and 305 deletions

View file

@ -3,8 +3,6 @@
// Create ajax hook on given 'element', which should return modal with 'id' =>
// show that modal
function initializeModal(element, id){
// Initializev new experiment modal listner
$(element)
.on("ajax:beforeSend", function(){
animateSpinner();
@ -16,7 +14,6 @@
keyboard: false,
});
validateMoveModal(id);
validateExperimentForm($(id));
})
.on("ajax:error", function() {
animateSpinner(null, false);
@ -61,42 +58,11 @@
var msg = JSON.parse(error.responseText);
renderFormError(e,
form.find("#experiment_project_id"),
msg.message.toString(),
true);
msg.message.toString());
})
.clearFormErrors();
}
}
// Setup front-end validations for experiment form
function validateExperimentForm(element){
if ( element ) {
var form = element.find("form");
form
.on('ajax:success' , function(){
animateSpinner(form, true);
location.reload();
})
.on('ajax:error', function(e, error){
var msg = JSON.parse(error.responseText);
if ( 'name' in msg ) {
renderFormError(e,
element.find("#experiment-name"),
msg.name.toString(),
true);
} else if ( 'description' in msg ) {
renderFormError(e,
element.find("#experiment-description"),
msg.description.toString(),
true);
} else {
renderFormError(e,
element.find("#experiment-name"),
error.statusText,
true);
}
})
}
}
// Initialize no description edit link
function initEditNoDescription(){
var modal = "#edit-experiment-modal-";

View file

@ -1,5 +1,4 @@
//= require comments
function initHandsOnTables(root) {
root.find("div.hot-table").each(function() {
var $container = $(this).find(".step-result-hot-table");
@ -31,82 +30,6 @@ function initHandsOnTables(root) {
});
}
// Initialize comment form.
function initResultCommentForm($el) {
var $form = $el.find("ul form");
$(".help-block", $form).addClass("hide");
$form.on("ajax:send", function (data) {
$("#comment_message", $form).attr("readonly", true);
})
.on("ajax:success", function (e, data) {
if (data.html) {
var list = $form.parents("ul");
// Remove potential "no comments" element
list.parent().find(".content-comments")
.find("li.no-comments").remove();
list.parent().find(".content-comments")
.prepend("<li class='comment'>" + data.html + "</li>")
.scrollTop(0);
list.parents("ul").find("> li.comment:gt(8)").remove();
$("#comment_message", $form).val("");
$(".form-group", $form)
.removeClass("has-error");
$(".help-block", $form)
.html("")
.addClass("hide");
scrollCommentOptions(
list.parent().find(".content-comments .dropdown-comment")
);
}
})
.on("ajax:error", function (ev, xhr) {
if (xhr.status === 400) {
var messageError = xhr.responseJSON.errors.message;
if (messageError) {
$(".form-group", $form)
.addClass("has-error");
$(".help-block", $form)
.html(messageError[0])
.removeClass("hide");
}
}
})
.on("ajax:complete", function () {
$("#comment_message", $form)
.attr("readonly", false)
.focus();
});
}
// Initialize show more comments link.
function initResultCommentsLink($el) {
$el.find(".btn-more-comments")
.on("ajax:success", function (e, data) {
if (data.html) {
var list = $(this).parents("ul");
var moreBtn = list.find(".btn-more-comments");
var listItem = moreBtn.parents('li');
$(data.html).insertBefore(listItem);
if (data.results_number < data.per_page) {
moreBtn.remove();
} else {
moreBtn.attr("href", data.more_url);
moreBtn.trigger("blur");
}
// Reposition dropdown comment options
scrollCommentOptions(listItem.closest(".content-comments").find(".dropdown-comment"));
}
});
}
function initResultCommentTabAjax() {
$(".comment-tab-link")
.on("ajax:before", function (e) {
@ -126,8 +49,8 @@ function initResultCommentTabAjax() {
var parentNode = $this.parents("ul").parent();
target.html(data.html);
initResultCommentForm(parentNode);
initResultCommentsLink(parentNode);
initCommentForm(parentNode);
initCommentsLink(parentNode);
parentNode.find(".active").removeClass("active");
$this.parents("li").addClass("active");

View file

@ -356,116 +356,6 @@ function initEditableHandsOnTable(root) {
});
}
// Initialize comment form.
function initStepCommentForm(ev, $el) {
var $form = $el.find("ul form");
var $commentInput = $form.find("#comment_message");
$(".help-block", $form).addClass("hide");
$form
.on("ajax:send", function (data) {
$("#comment_message", $form).attr("readonly", true);
})
.on("ajax:success", function (e, data) {
if (data.html) {
var list = $form.parents("ul");
// Remove potential "no comments" element
list.parent().find(".content-comments")
.find("li.no-comments").remove();
list.parent().find(".content-comments")
.prepend("<li class='comment'>" + data.html + "</li>")
.scrollTop(0);
list.parents("ul").find("> li.comment:gt(8)").remove();
$("#comment_message", $form).val("");
$(".form-group", $form)
.removeClass("has-error");
$(".help-block", $form)
.html("")
.addClass("hide");
scrollCommentOptions(
list.parent().find(".content-comments .dropdown-comment")
);
}
})
.on("ajax:error", function (ev, xhr) {
if (xhr.status === 400) {
var messageError = xhr.responseJSON.errors.message;
if (messageError) {
$(".form-group", $form)
.addClass("has-error");
$(".help-block", $form)
.html(messageError[0])
.removeClass("hide");
}
}
})
.on("ajax:complete", function () {
$("#comment_message", $form)
.attr("readonly", false)
.focus();
});
}
// Initialize show more comments link.
function initStepCommentsLink($el) {
$el.find(".btn-more-comments")
.on("ajax:success", function (e, data) {
if (data.html) {
var list = $(this).parents("ul");
var moreBtn = list.find(".btn-more-comments");
var listItem = moreBtn.parents('li');
$(data.html).insertBefore(listItem);
if (data.results_number < data.per_page) {
moreBtn.remove();
} else {
moreBtn.attr("href", data.more_url);
moreBtn.trigger("blur");
}
// Reposition dropdown comment options
scrollCommentOptions(listItem.closest(".content-comments")
.find(".dropdown-comment"));
}
});
}
function initStepCommentTabAjax() {
$(".comment-tab-link")
.on("ajax:before", function (e) {
var $this = $(this);
var parentNode = $this.parents("li");
var targetId = $this.attr("aria-controls");
if (parentNode.hasClass("active")) {
return false;
}
})
.on("ajax:success", function (e, data) {
if (data.html) {
var $this = $(this);
var targetId = $this.attr("aria-controls");
var target = $("#" + targetId);
var parentNode = $this.parents("ul").parent();
target.html(data.html);
initStepCommentForm(e, parentNode);
initStepCommentsLink(parentNode);
parentNode.find(".active").removeClass("active");
$this.parents("li").addClass("active");
target.addClass("active");
}
})
.on("ajax:error", function(e, xhr, status, error) {
// TODO
});
}
function applyCancelOnNew() {
$("[data-action='cancel-new']").click(function() {
var $form = $(this).closest("form");
@ -488,7 +378,6 @@ function initCallBacks() {
applyEditCallBack();
applyMoveStepCallBack();
applyCollapseLinkCallBack();
initStepCommentTabAjax();
initDeleteStep();
}

View file

@ -1,2 +0,0 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View file

@ -0,0 +1,155 @@
(function(){
"use strict";
/**
* Initializes the comments
*
*/
function initializeComments(){
var comments;
if ( $(".step-comment") && $(".step-comment").length > 0 ) {
comments = $(".step-comment");
} else if ( $(".result-comment") && $(".result-comment").length > 0 ) {
comments = $(".result-comment");
}
$.each(comments, function(){
var that = $(this);
var link = that.attr("data-href");
$.ajax({ method: 'GET',
url: link,
beforeSend: animateSpinner(that, true) })
.done(function(data) {
that.html(data.html);
initCommentForm(that);
initCommentsLink(that);
scrollBottom(that.find(".content-comments"));
animateSpinner(that, false);
})
.always(function() {
animateSpinner(that, false);
});
});
}
// scroll to the botttom
function scrollBottom(id) {
var list;
if ( id.hasClass("content-comments")) {
list = id;
} else {
list = id.find(".content-comments");
}
if ( list && list.length > 0) {
list.scrollTop($(list)[0].scrollHeight);
}
}
// Initialize show more comments link.
function initCommentsLink($el) {
$el.find(".btn-more-comments")
.on("ajax:success", function (e, data) {
if (data.html) {
var list = $(this).parents("ul");
var moreBtn = list.find(".btn-more-comments");
var listItem = moreBtn.parents("li");
$(data.html).insertAfter(listItem);
if (data.results_number < data.per_page) {
moreBtn.remove();
} else {
moreBtn.attr("href", data.more_url);
moreBtn.trigger("blur");
}
// Reposition dropdown comment options
scrollCommentOptions(listItem
.closest(".content-comments")
.find(".dropdown-comment"));
}
});
}
// Initialize comment form.
function initCommentForm($el) {
var $form = $el.find("ul form");
$(".help-block", $form).addClass("hide");
$form.on("ajax:send", function () {
$("#comment_message", $form).attr("readonly", true);
})
.on("ajax:success", function (e, data) {
if (data.html) {
var list = $form.parents("ul");
// Remove potential "no comments" element
list.parent().find(".content-comments")
.find("li.no-comments").remove();
list.parent().find(".content-comments")
.append("<li class='comment'>" + data.html + "</li>")
.scrollTop(0);
list.parents("ul").find("> li.comment:gt(8)").remove();
$("#comment_message", $form).val("");
$(".form-group", $form)
.removeClass("has-error");
$(".help-block", $form)
.html("")
.addClass("hide");
scrollBottom($el);
}
})
.on("ajax:error", function (ev, xhr) {
if (xhr.status === 400) {
var messageError = xhr.responseJSON.errors.message;
if (messageError) {
$(".form-group", $form)
.addClass("has-error");
$(".help-block", $form)
.html(messageError[0])
.removeClass("hide");
}
}
})
.on("ajax:complete", function () {
scrollBottom($("#comment_message", $form));
$("#comment_message", $form)
.attr("readonly", false)
.focus();
});
}
// restore comments after update or when new element is created
function bindCommentInitializerToNewElement() {
$(document)
.ready(function() {
if( document.getElementById("steps") !== null ) {
$("#steps")
.change(function() {
$(".step-save")
.on("click", function() {
setTimeout(function() {
initializeComments();
}, 500);
});
});
} else if ( document.getElementById("results") !== null ) {
$("#results")
.change(function() {
$(".save-result")
.on("click", function() {
setTimeout(function() {
initializeComments();
}, 500);
});
});
}
});
}
bindCommentInitializerToNewElement();
initializeComments();
})();

View file

@ -2,6 +2,8 @@
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
@import "colors";
.description-label {
word-wrap: break-word;
}
@ -14,4 +16,9 @@
.btn-colorselector{
background-color: transparent !important;
}
}
.step-container .row {
margin-left: 0;
margin-right: 0;
}

View file

@ -911,6 +911,10 @@ ul.content-module-activities {
margin-left: 38px;
}
.row {
padding: 0 20px;
}
.badge-num {
position: absolute;
@ -946,6 +950,7 @@ ul.content-module-activities {
.content-comments {
max-height: 250px;
overflow: auto;
padding: 0 15px;
}
}
@ -1177,6 +1182,10 @@ html.turbolinks-progress-bar::before {
// Comments
.comment-more {
margin-left: 15px;
}
.dropdown.dropdown-comment {
display: inline-block;

View file

@ -1,8 +1,8 @@
class ResultCommentsController < ApplicationController
before_action :load_vars
before_action :check_view_permissions, only: [ :index ]
before_action :check_add_permissions, only: [ :new, :create ]
before_action :check_view_permissions, only: [:index]
before_action :check_add_permissions, only: [:new, :create]
before_action :check_edit_permissions, only: [:edit, :update]
before_action :check_destroy_permissions, only: [:destroy]
@ -10,31 +10,28 @@ class ResultCommentsController < ApplicationController
@comments = @result.last_comments(@last_comment_id, @per_page)
respond_to do |format|
format.json {
format.json do
# 'index' partial includes header and form for adding new
# messages. 'list' partial is used for showing more
# comments.
partial = "index.html.erb"
partial = "list.html.erb" if @last_comment_id > 0
more_url = ""
partial = 'index.html.erb'
partial = 'list.html.erb' if @last_comment_id > 0
more_url = ''
if @comments.count > 0
more_url = url_for(result_result_comments_path(@result,
format: :json,
from: @comments.last.id))
format: :json,
from: @comments
.first.id))
end
render :json => {
render json: {
per_page: @per_page,
results_number: @comments.length,
more_url: more_url,
html: render_to_string({
partial: partial,
locals: {
comments: @comments,
more_comments_url: more_url
}
})
html: render_to_string(partial: partial,
locals: { comments: @comments,
more_comments_url: more_url })
}
}
end
end
end

View file

@ -1,8 +1,8 @@
class StepCommentsController < ApplicationController
before_action :load_vars
before_action :check_view_permissions, only: [ :index ]
before_action :check_add_permissions, only: [ :new, :create ]
before_action :check_view_permissions, only: [:index]
before_action :check_add_permissions, only: [:new, :create]
before_action :check_edit_permissions, only: [:edit, :update]
before_action :check_destroy_permissions, only: [:destroy]
@ -10,31 +10,27 @@ class StepCommentsController < ApplicationController
@comments = @step.last_comments(@last_comment_id, @per_page)
respond_to do |format|
format.json {
format.json do
# 'index' partial includes header and form for adding new
# messages. 'list' partial is used for showing more
# comments.
partial = "index.html.erb"
partial = "list.html.erb" if @last_comment_id > 0
more_url = ""
partial = 'index.html.erb'
partial = 'list.html.erb' if @last_comment_id > 0
more_url = ''
if @comments.count > 0
more_url = url_for(step_step_comments_path(@step,
format: :json,
from: @comments.last.id))
from: @comments.first.id))
end
render :json => {
render json: {
per_page: @per_page,
results_number: @comments.length,
more_url: more_url,
html: render_to_string({
partial: partial,
locals: {
comments: @comments,
more_comments_url: more_url
}
})
html: render_to_string(partial: partial,
locals: { comments: @comments,
more_comments_url: more_url })
}
}
end
end
end

View file

@ -73,11 +73,12 @@ class Result < ActiveRecord::Base
def last_comments(last_id = 1, per_page = 20)
last_id = 9999999999999 if last_id <= 1
Comment.joins(:result_comment)
.where(result_comments: {result_id: id})
.where('comments.id < ?', last_id)
.order(created_at: :desc)
.limit(per_page)
comments = Comment.joins(:result_comment)
.where(result_comments: { result_id: id })
.where('comments.id < ?', last_id)
.order(created_at: :desc)
.limit(per_page)
comments.reverse
end
def is_text

View file

@ -87,11 +87,12 @@ class Step < ActiveRecord::Base
def last_comments(last_id = 1, per_page = 20)
last_id = 9999999999999 if last_id <= 1
Comment.joins(:step_comment)
.where(step_comments: {step_id: id})
.where('comments.id < ?', last_id)
.order(created_at: :desc)
.limit(per_page)
comments = Comment.joins(:step_comment)
.where(step_comments: { step_id: id })
.where('comments.id < ?', last_id)
.order(created_at: :desc)
.limit(per_page)
comments.reverse
end
def save(current_user=nil)

View file

@ -41,7 +41,7 @@
<a href="#result-info-<%= result.id %>" data-toggle="tab"><span class="glyphicon glyphicon-info-sign"></span>
<%= t'my_modules.results.info_tab' %></a>
</li>
<% if can_view_result_comments(@my_module) %>
<% if false %>
<li role="presentation">
<a class="comment-tab-link" href="<%= url_for result_result_comments_path(result_id: result.id, format: :json) %>" aria-controls="result-comments-<%= result.id %>" data-remote="true">
<span class="glyphicon glyphicon-comment"></span>
@ -51,9 +51,18 @@
</ul>
<div class="tab-content">
<div class="tab-pane active" role="tabpanel" id="result-info-<%= result.id %>">
<%= render partial: 'my_modules/result_user_generated.html.erb', locals: { result: result, markdown: markdown } %>
<div class="row">
<%= render partial: 'my_modules/result_user_generated.html.erb',
locals: { result: result, markdown: markdown } %>
</div>
<% if can_view_result_comments(@my_module) %>
<div class="row">
<div class="result-comment"
id="result-comments-<%= result.id %>"
data-href="<%= result_result_comments_url(result) %>"></div>
</div>
<% end %>
</div>
<div class="tab-pane" role="tabpanel" id="result-comments-<%= result.id %>"></div>
</div>
</div>
</div>

View file

@ -44,3 +44,4 @@
<%= stylesheet_link_tag 'datatables' %>
<%= javascript_include_tag("my_modules/protocols") %>
<%= javascript_include_tag("step_result_comments") %>

View file

@ -50,6 +50,7 @@
<%= javascript_include_tag "handsontable.full.min" %>
<%= javascript_include_tag("canvas-to-blob.min") %>
<%= javascript_include_tag("direct-upload") %>
<%= javascript_include_tag("step_result_comments") %>
<%= javascript_include_tag "my_modules/results" %>
<%= javascript_include_tag "results/result_texts" %>
<%= javascript_include_tag "results/result_tables" %>

View file

@ -7,7 +7,7 @@
<%= ff.file_field :file %>
<% end %>
<hr>
<%= f.submit t("result_assets.edit.update"), class: 'btn btn-primary', onclick: "processResult(event, ResultTypeEnum.FILE, true, #{direct_upload});" %>
<%= f.submit t("result_assets.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.FILE, true, #{direct_upload});" %>
<button type="button" class="btn btn-default cancel-edit">
<%= t("general.cancel")%>
</button>

View file

@ -4,7 +4,7 @@
<%= f.fields_for :asset do |ff| %>
<%= ff.file_field :file %>
<% end %>
<%= f.submit t("result_assets.new.create"), class: 'btn btn-primary', onclick: "processResult(event, ResultTypeEnum.FILE, false, #{direct_upload});" %>
<%= f.submit t("result_assets.new.create"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.FILE, false, #{direct_upload});" %>
<button type="button" class="btn btn-default cancel-new">
<%= t("general.cancel")%>
</button>

View file

@ -1,11 +1,7 @@
<hr>
<h5 class="text-center"><%= t('my_modules.results.comments_tab') %></h5>
<hr>
<ul class="no-style double-line content-comments">
<% if @comments.size == 0 then %>
<li class="no-comments"><em><%= t 'general.no_comments' %></em></li>
<% else %>
<%= render 'result_comments/list.html.erb', comments: @comments %>
<% end %>
<% if @comments.length == @per_page %>
<li class="comment-more text-center">
<a class="btn btn-default btn-more-comments" href="<%= more_comments_url %>" data-remote="true">
@ -13,6 +9,11 @@
</a>
</li>
<% end %>
<% if @comments.size == 0 then %>
<li class="no-comments"><em><%= t 'general.no_comments' %></em></li>
<% else %>
<%= render 'result_comments/list.html.erb', comments: @comments %>
<% end %>
</ul>
<% if can_add_result_comment_in_module(@my_module) then %>
<ul class="no-style double-line">

View file

@ -9,7 +9,7 @@
<% end %>
</div>
<hr>
<%= f.submit t("result_tables.edit.update"), class: 'btn btn-primary', onclick: "processResult(event, ResultTypeEnum.TABLE, true);" %>
<%= f.submit t("result_tables.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TABLE, true);" %>
<button type="button" class="btn btn-default cancel-edit">
<%= t("general.cancel")%>
</button>

View file

@ -8,7 +8,7 @@
</div>
<% end %>
</div>
<%= f.submit t("result_tables.new.create"), class: 'btn btn-primary', onclick: "processResult(event, ResultTypeEnum.TABLE, false);" %>
<%= f.submit t("result_tables.new.create"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TABLE, false);" %>
<button type="button" class="btn btn-default cancel-new">
<%= t("general.cancel")%>
</button>

View file

@ -5,7 +5,7 @@
<%= ff.text_area :text, style: "margin-top: 10px;" %><br />
<% end %>
<hr>
<%= f.submit t("result_texts.edit.update"), class: 'btn btn-primary', onclick: "processResult(event, ResultTypeEnum.TEXT, true);" %>
<%= f.submit t("result_texts.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TEXT, true);" %>
<button type="button" class="btn btn-default cancel-edit">
<%= t("general.cancel")%>
</button>

View file

@ -4,7 +4,7 @@
<%= f.fields_for :result_text do |ff| %>
<%= ff.text_area :text, style: "margin-top: 10px;" %><br />
<% end %>
<%= f.submit t("result_texts.new.create"), class: 'btn btn-primary', onclick: "processResult(event, ResultTypeEnum.TEXT, false);" %>
<%= f.submit t("result_texts.new.create"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TEXT, false);" %>
<button type="button" class="btn btn-default cancel-new">
<%= t("general.cancel")%>
</button>

View file

@ -1,11 +1,7 @@
<hr>
<h5 class="text-center"><%= t('protocols.steps.comments_tab') %></h5>
<hr>
<ul class="no-style double-line content-comments">
<% if @comments.size == 0 then %>
<li class="no-comments"><em><%= t 'general.no_comments' %></em></li>
<% else %>
<%= render 'step_comments/list.html.erb', comments: @comments %>
<% end %>
<% if @comments.length == @per_page %>
<li class="comment-more text-center">
<a class="btn btn-default btn-more-comments" href="<%= more_comments_url %>" data-remote="true">
@ -13,12 +9,17 @@
</a>
</li>
<% end %>
<% if @comments.size == 0 then %>
<li class="no-comments"><em><%= t 'general.no_comments' %></em></li>
<% else %>
<%= render 'step_comments/list.html.erb', comments: @comments %>
<% end %>
</ul>
<% if can_add_step_comment_in_protocol(@protocol) %>
<ul class="no-style double-line">
<li>
<hr>
<%= bootstrap_form_for :comment, url: { format: :json }, method: :post, remote: true do |f| %>
<%= bootstrap_form_for :comment, url: { format: :json }, html: { class: 'comment-form', id: "step-comment-#{@step.id}" }, method: :post, remote: true do |f| %>
<%= f.text_field :message, hide_label: true, placeholder: t("general.comment_placeholder"), append: f.submit("+"), help: '.' %>
<% end %>
</li>

View file

@ -4,7 +4,7 @@
<hr>
<%= render partial: "empty_step.html.erb", locals: {step: @step, f: f} %>
<hr>
<%= f.submit t("protocols.steps.edit.edit_step"), class: 'btn btn-primary', onclick: "processStep(event, true, #{direct_upload});" %>
<%= f.submit t("protocols.steps.edit.edit_step"), class: 'btn btn-primary step-save', onclick: "processStep(event, true, #{direct_upload});" %>
<a type="button" data-action="cancel-edit" class="btn btn-default" href="<%= step_path(id: @step, format: :json) %>" data-remote="true">
<%= t("general.cancel")%>
</a>

View file

@ -4,7 +4,7 @@
<hr>
<%= render partial: "empty_step.html.erb", locals: {step: @step, f: f} %>
<hr>
<%= f.submit t("protocols.steps.new.add_step"), class: 'btn btn-primary', onclick: "processStep(event, false, #{direct_upload});" %>
<%= f.submit t("protocols.steps.new.add_step"), class: 'btn btn-primary step-save', onclick: "processStep(event, false, #{direct_upload});" %>
<button type="button" data-action="cancel-new" class="btn btn-default">
<%= t("general.cancel")%>
</button>

View file

@ -31,23 +31,17 @@
</div>
<div class="panel-collapse collapse" id="step-panel-<%= step.id %>" role="tabpanel">
<div class="panel-body">
<% if @protocol.in_module? %>
<% if @protocol.in_module? %>
<ul class="nav nav-tabs">
<li role="presentation" class="active">
<a class="step-info-tab" href="#step-info-<%= step.id %>" data-toggle="tab"><span class="glyphicon glyphicon-info-sign"></span>
<%= t("protocols.steps.info_tab") %></a>
</li>
<% if can_view_step_comments(@protocol) %>
<li role="presentation">
<a class="comment-tab-link" href="<%= url_for step_step_comments_path(step_id: step.id, format: :json) %>" aria-controls="step-comments-<%= step.id %>" data-remote="true">
<span class="glyphicon glyphicon-comment"></span>
<%= t("protocols.steps.comments_tab") %></a>
</li>
<% end %>
</ul>
<div class="tab-content">
<div class="tab-content step-container">
<div class="tab-pane active" role="tabpanel" id="step-info-<%= step.id %>">
<% end %>
<div class="row">
<% end %>
<% if step.description.blank? %>
<em><%= t("protocols.steps.no_description") %></em>
<% else %>
@ -132,8 +126,16 @@
<% end %>
<% if @protocol.in_module? %>
</div>
<div class="tab-pane" role="tabpanel" id="step-comments-<%= step.id %>"></div>
<% if can_view_step_comments(@protocol) %>
<div class="row">
<div class="step-comment"
id="step-comments-<%= step.id %>"
data-href="<%= url_for step_step_comments_path(step_id: step.id, format: :json) %>">
</div>
</div>
<% end %>
</div>
</div>
<% end %>
</div>
</div>

View file

@ -59,6 +59,7 @@ Rails.application.config.assets.precompile += %w(assets.js)
Rails.application.config.assets.precompile += %w(comments.js)
Rails.application.config.assets.precompile += %w(projects/show.js)
Rails.application.config.assets.precompile += %w(projects/introdutory_popup.js)
Rails.application.config.assets.precompile += %w(step_result_comments.js)
# Libraries needed for Handsontable formulas
Rails.application.config.assets.precompile += %w(lodash.js)