mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-02-28 17:54:16 +08:00
Add comments list
This commit is contained in:
parent
2294d396f9
commit
da4b8aaf2f
15 changed files with 228 additions and 2 deletions
|
@ -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');
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
90
app/controllers/comments_controller.rb
Normal file
90
app/controllers/comments_controller.rb
Normal 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
|
|
@ -456,6 +456,10 @@ class MyModule < ApplicationRecord
|
|||
user_target: user.id })
|
||||
end
|
||||
|
||||
def comments
|
||||
task_comments
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_blank_protocol
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -104,4 +104,9 @@ class Result < ApplicationRecord
|
|||
|
||||
true
|
||||
end
|
||||
|
||||
def comments
|
||||
result_comments
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -136,6 +136,10 @@ class Step < ApplicationRecord
|
|||
move_in_protocol(:down)
|
||||
end
|
||||
|
||||
def comments
|
||||
step_comments
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def move_in_protocol(direction)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
19
app/views/shared/comments/_comment.html.erb
Normal file
19
app/views/shared/comments/_comment.html.erb
Normal 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>
|
4
app/views/shared/comments/_comments_list.html.erb
Normal file
4
app/views/shared/comments/_comments_list.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<% comments.each do |comment| %>
|
||||
<%= render partial: 'shared/comments/comment.html.erb',
|
||||
locals: { comment: comment } %>
|
||||
<% end %>
|
|
@ -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>
|
||||
|
|
|
@ -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',
|
||||
|
|
Loading…
Reference in a new issue