diff --git a/app/assets/javascripts/experiments/dropdown_actions.js b/app/assets/javascripts/experiments/dropdown_actions.js index f6956737e..29a3f4990 100644 --- a/app/assets/javascripts/experiments/dropdown_actions.js +++ b/app/assets/javascripts/experiments/dropdown_actions.js @@ -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-"; diff --git a/app/assets/javascripts/my_modules/results.js b/app/assets/javascripts/my_modules/results.js index 2c71532c3..3692e8f36 100644 --- a/app/assets/javascripts/my_modules/results.js +++ b/app/assets/javascripts/my_modules/results.js @@ -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("
  • " + data.html + "
  • ") - .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"); diff --git a/app/assets/javascripts/protocols/steps.js b/app/assets/javascripts/protocols/steps.js index c9d78b11e..ff744a21f 100644 --- a/app/assets/javascripts/protocols/steps.js +++ b/app/assets/javascripts/protocols/steps.js @@ -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("
  • " + data.html + "
  • ") - .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(); } diff --git a/app/assets/javascripts/step_comments.js b/app/assets/javascripts/step_comments.js deleted file mode 100644 index dee720fac..000000000 --- a/app/assets/javascripts/step_comments.js +++ /dev/null @@ -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. diff --git a/app/assets/javascripts/step_result_comments.js b/app/assets/javascripts/step_result_comments.js new file mode 100644 index 000000000..7b07b4dcd --- /dev/null +++ b/app/assets/javascripts/step_result_comments.js @@ -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("
  • " + data.html + "
  • ") + .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(); + +})(); diff --git a/app/assets/stylesheets/my_modules.scss b/app/assets/stylesheets/my_modules.scss index 07dd950b8..b4bcb3395 100644 --- a/app/assets/stylesheets/my_modules.scss +++ b/app/assets/stylesheets/my_modules.scss @@ -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; -} \ No newline at end of file +} + +.step-container .row { + margin-left: 0; + margin-right: 0; +} diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index 43dd3c168..ccc724392 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -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; diff --git a/app/controllers/result_comments_controller.rb b/app/controllers/result_comments_controller.rb index 63d311447..c63e2dca5 100644 --- a/app/controllers/result_comments_controller.rb +++ b/app/controllers/result_comments_controller.rb @@ -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 diff --git a/app/controllers/step_comments_controller.rb b/app/controllers/step_comments_controller.rb index fad1c454d..9c68770e3 100644 --- a/app/controllers/step_comments_controller.rb +++ b/app/controllers/step_comments_controller.rb @@ -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 diff --git a/app/models/result.rb b/app/models/result.rb index 03e84bb6e..0c289272b 100644 --- a/app/models/result.rb +++ b/app/models/result.rb @@ -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 diff --git a/app/models/step.rb b/app/models/step.rb index 0589a157a..ecf8a1804 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -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) diff --git a/app/views/my_modules/_result.html.erb b/app/views/my_modules/_result.html.erb index 1daf0b471..29da2a114 100644 --- a/app/views/my_modules/_result.html.erb +++ b/app/views/my_modules/_result.html.erb @@ -41,7 +41,7 @@ <%= t'my_modules.results.info_tab' %> - <% if can_view_result_comments(@my_module) %> + <% if false %>
  • @@ -51,9 +51,18 @@
    - <%= render partial: 'my_modules/result_user_generated.html.erb', locals: { result: result, markdown: markdown } %> +
    + <%= render partial: 'my_modules/result_user_generated.html.erb', + locals: { result: result, markdown: markdown } %> +
    + <% if can_view_result_comments(@my_module) %> +
    +
    +
    + <% end %>
    -
    diff --git a/app/views/my_modules/protocols.html.erb b/app/views/my_modules/protocols.html.erb index aed62bfba..d083f2321 100644 --- a/app/views/my_modules/protocols.html.erb +++ b/app/views/my_modules/protocols.html.erb @@ -44,3 +44,4 @@ <%= stylesheet_link_tag 'datatables' %> <%= javascript_include_tag("my_modules/protocols") %> +<%= javascript_include_tag("step_result_comments") %> diff --git a/app/views/my_modules/results.html.erb b/app/views/my_modules/results.html.erb index f2193f5d1..dc85b347d 100644 --- a/app/views/my_modules/results.html.erb +++ b/app/views/my_modules/results.html.erb @@ -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" %> diff --git a/app/views/result_assets/_edit.html.erb b/app/views/result_assets/_edit.html.erb index f6960a6f7..b1bf833fd 100644 --- a/app/views/result_assets/_edit.html.erb +++ b/app/views/result_assets/_edit.html.erb @@ -7,7 +7,7 @@ <%= ff.file_field :file %> <% end %>
    - <%= 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});" %> diff --git a/app/views/result_assets/_new.html.erb b/app/views/result_assets/_new.html.erb index 370f07d6b..e96a8190f 100644 --- a/app/views/result_assets/_new.html.erb +++ b/app/views/result_assets/_new.html.erb @@ -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});" %> diff --git a/app/views/result_comments/_index.html.erb b/app/views/result_comments/_index.html.erb index c10e46e5d..00bf407dd 100644 --- a/app/views/result_comments/_index.html.erb +++ b/app/views/result_comments/_index.html.erb @@ -1,11 +1,7 @@ +
    <%= t('my_modules.results.comments_tab') %>

    <% if can_add_result_comment_in_module(@my_module) then %>