Add comments list

This commit is contained in:
aignatov-bio 2020-11-20 12:29:40 +01:00
parent 2294d396f9
commit da4b8aaf2f
15 changed files with 228 additions and 2 deletions

View file

@ -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');

View file

@ -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;

View file

@ -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

View file

@ -456,6 +456,10 @@ class MyModule < ApplicationRecord
user_target: user.id })
end
def comments
task_comments
end
private
def create_blank_protocol

View file

@ -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
)

View file

@ -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

View file

@ -104,4 +104,9 @@ class Result < ApplicationRecord
true
end
def comments
result_comments
end
end

View file

@ -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

View file

@ -136,6 +136,10 @@ class Step < ApplicationRecord
move_in_protocol(:down)
end
def comments
step_comments
end
private
def move_in_protocol(direction)

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,19 @@
<% user = comment.user %>
<div class="comment-container <%= 'current-user' if user == current_user %>">
<div class="comment-header">
<%= image_tag avatar_path(comment.user, :icon_small), class: 'user-avatar' %>
<div class="user-name">
<%= user == current_user ? 'You' : comment.user.full_name %>
</div>
</div>
<div class="comment-body">
<div class="comment-message">
<%= comment.message %>
</div>
<div class="comment-footer">
<div class="comment-create-date">
<%= I18n.l(comment.created_at, format: :full_date) %>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,4 @@
<% comments.each do |comment| %>
<%= render partial: 'shared/comments/comment.html.erb',
locals: { comment: comment } %>
<% end %>

View file

@ -1,4 +1,4 @@
<div class="comments-sidebar">
<div class="comments-sidebar" data-comments-url="<%= comments_path %>">
<div class="sidebar-content">
<div class="sidebar-header">
<div class="comments-subject-title"></div>

View file

@ -508,6 +508,8 @@ Rails.application.routes.draw do
end
end
resources :comments, only: %i(index create update delete)
resources :repositories do
post 'repository_index',
to: 'repository_rows#index',