diff --git a/app/assets/javascripts/sitewide/comments_sidebar.js b/app/assets/javascripts/sitewide/comments_sidebar.js index 4e0192cc1..8b1be3d18 100644 --- a/app/assets/javascripts/sitewide/comments_sidebar.js +++ b/app/assets/javascripts/sitewide/comments_sidebar.js @@ -7,14 +7,28 @@ var CommentsSidebar = (function() { }); } + function loadCommentsList() { + var commentsUrl = $(SIDEBAR).data('comments-url'); + $.get(commentsUrl, { + object_type: $(SIDEBAR).data('object-type'), + object_id: $(SIDEBAR).data('object-id') + }, function(result) { + $(SIDEBAR).removeClass('loading'); + $(SIDEBAR).find('.comments-subject-title').text(result.object_name); + $(SIDEBAR).find('.comments-list').html(result.comments); + }); + } + return { init: function() { initCloseButton(); }, - open: function() { + open: function(objectType, objectId) { $(SIDEBAR).find('.comments-subject-title').empty(); $(SIDEBAR).find('.comments-list').empty(); + $(SIDEBAR).data('object-type', objectType).data('object-id', objectId); $(SIDEBAR).addClass('open loading'); + loadCommentsList(); }, close: function() { $(SIDEBAR).removeClass('open'); diff --git a/app/assets/stylesheets/shared/comments_sidebar.scss b/app/assets/stylesheets/shared/comments_sidebar.scss index 5f7b81317..34f57c780 100644 --- a/app/assets/stylesheets/shared/comments_sidebar.scss +++ b/app/assets/stylesheets/shared/comments_sidebar.scss @@ -33,8 +33,13 @@ padding: 1em; .comments-subject-title { + @include font-h3; flex-grow: 1; height: 2em; + line-height: 2em; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .close-btn { @@ -76,6 +81,7 @@ .send-comment { color: $brand-primary; + cursor: pointer; display: inline-block; line-height: 2.5em; position: absolute; @@ -88,6 +94,63 @@ } } + .comment-container { + margin: 0 1em 2em 0; + + .comment-header { + align-items: center; + display: flex; + margin-bottom: .5em; + min-height: 1.75em; + + .user-name { + margin: 0 .5em; + order: 2; + } + + .user-avatar { + max-width: 1.75em; + } + } + + .comment-body { + background: $color-white; + border-radius: $border-radius-default; + + .comment-message { + @include font-main; + color: $color-volcano; + padding: 1em; + } + } + + .comment-footer { + padding: 0 1em 1em; + + .comment-create-date { + @include font-small; + color: $color-volcano; + opacity: .5; + } + } + + &.current-user { + margin: 0 0 2em 1em; + + .comment-body { + background: $color-alto; + } + + .comment-header { + justify-content: flex-end; + + .user-avatar { + order: 3; + } + } + } + } + .loading-placeholder { display: none; diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb new file mode 100644 index 000000000..3174078c8 --- /dev/null +++ b/app/controllers/comments_controller.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true + +class CommentsController < ApplicationController + before_action :load_object, only: %i(index create) + before_action :load_comment, only: %i(update delete) + before_action :check_view_permissions, only: :index + before_action :check_create_permissions, only: :create + before_action :check_manage_permissions, only: %i(update delete) + + def index + comments = @commentable.comments + + render json: { + object_name: @commentable.name, + comments: render_to_string(partial: 'shared/comments/comments_list.html.erb', + locals: { comments: comments }) + } + end + + def create; end + + def update; end + + def delete; end + + private + + def load_object + @commentable = case params[:object_type] + when 'Project' + Project.find_by(id: params[:object_id]) + when 'MyModule' + MyModule.find_by(id: params[:object_id]) + when 'Step' + Step.find_by(id: params[:object_id]) + when 'Result' + Result.find_by(id: params[:object_id]) + end + + render_404 and return unless @commentable + end + + def load_comment + @comment = Comment.find_by(id: params[:id]) + render_404 and return unless @commentable + + @commentable = @comment.commentable + render_404 and return unless @commentable + end + + def check_view_permissions + case @commentable + when Project + render_403 and return unless can_read_project?(@commentable) + when MyModule + render_403 and return unless can_read_experiment?(@commentable.experiment) + when Step + render_403 and return unless can_read_protocol_in_module?(@commentable.protocol) + when Result + render_403 and return unless can_read_experiment?(@commentable.my_module.experiment) + else + render_403 and return + end + end + + def check_create_permissions + case @commentable + when Project + render_403 and return unless can_create_comments_in_project?(@commentable) + when MyModule + render_403 and return unless can_create_comments_in_module?(@commentable) + when Step + render_403 and return unless can_create_comments_in_module?(@commentable.protocol.my_module) + when Result + render_403 and return unless can_create_comments_in_module?(@commentable.my_module) + else + render_403 and return + end + end + + def check_manage_permissions + if @commentable.class == Project + render_403 and return unless can_manage_comment_in_project?(@comment) + elsif [MyModule, Step, Result].include? @commentable.class + render_403 and return unless can_manage_comment_in_module?(@comment.becomes(Comment)) + else + render_403 and return + end + end +end diff --git a/app/models/my_module.rb b/app/models/my_module.rb index 6beac9652..2e70fba2d 100644 --- a/app/models/my_module.rb +++ b/app/models/my_module.rb @@ -456,6 +456,10 @@ class MyModule < ApplicationRecord user_target: user.id }) end + def comments + task_comments + end + private def create_blank_protocol diff --git a/app/models/project.rb b/app/models/project.rb index 589af04de..cdd709fb7 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -248,6 +248,10 @@ class Project < ApplicationRecord res end + def comments + project_comments + end + def generate_teams_export_report_html( user, team, html_title, obj_filenames = nil ) diff --git a/app/models/project_comment.rb b/app/models/project_comment.rb index 3bddd89e1..c92f770d9 100644 --- a/app/models/project_comment.rb +++ b/app/models/project_comment.rb @@ -4,4 +4,8 @@ class ProjectComment < Comment belongs_to :project, foreign_key: :associated_id, inverse_of: :project_comments, touch: true validates :project, presence: true + + def commentable + project + end end diff --git a/app/models/result.rb b/app/models/result.rb index 740f5c958..768c71e09 100644 --- a/app/models/result.rb +++ b/app/models/result.rb @@ -104,4 +104,9 @@ class Result < ApplicationRecord true end + + def comments + result_comments + end + end diff --git a/app/models/result_comment.rb b/app/models/result_comment.rb index 7395144db..be32285fe 100644 --- a/app/models/result_comment.rb +++ b/app/models/result_comment.rb @@ -4,4 +4,8 @@ class ResultComment < Comment belongs_to :result, foreign_key: :associated_id, inverse_of: :result_comments, touch: true validates :result, presence: true + + def commentable + result + end end diff --git a/app/models/step.rb b/app/models/step.rb index 90eb0cd38..d0c08317c 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -136,6 +136,10 @@ class Step < ApplicationRecord move_in_protocol(:down) end + def comments + step_comments + end + private def move_in_protocol(direction) diff --git a/app/models/step_comment.rb b/app/models/step_comment.rb index bcce10909..5cbcc3443 100644 --- a/app/models/step_comment.rb +++ b/app/models/step_comment.rb @@ -4,4 +4,9 @@ class StepComment < Comment belongs_to :step, foreign_key: :associated_id, inverse_of: :step_comments, touch: true validates :step, presence: true + + def commentable + step + end + end diff --git a/app/models/task_comment.rb b/app/models/task_comment.rb index f7d8b244a..00d0368dd 100644 --- a/app/models/task_comment.rb +++ b/app/models/task_comment.rb @@ -4,4 +4,8 @@ class TaskComment < Comment belongs_to :my_module, foreign_key: :associated_id, inverse_of: :task_comments validates :my_module, presence: true + + def commentable + my_module + end end diff --git a/app/views/shared/comments/_comment.html.erb b/app/views/shared/comments/_comment.html.erb new file mode 100644 index 000000000..ddea16d80 --- /dev/null +++ b/app/views/shared/comments/_comment.html.erb @@ -0,0 +1,19 @@ +<% user = comment.user %> +