Skip to content
Snippets Groups Projects
Commit 76c3d2d4 authored by Douwe Maan's avatar Douwe Maan Committed by Fatih Acet
Browse files

Add full JSON endpoints for issue notes and discussions

parent cb2287df
No related branches found
No related tags found
No related merge requests found
Showing
with 149 additions and 24 deletions
Loading
Loading
@@ -11,14 +11,16 @@ module NotesActions
 
notes_json = { notes: [], last_fetched_at: current_fetched_at }
 
@notes = notes_finder.execute.inc_relations_for_view
@notes = notes_finder.execute.inc_relations_for_view.to_a
@notes.reject! { |n| n.cross_reference_not_visible_for?(current_user) }
@notes = prepare_notes_for_rendering(@notes)
 
@notes.each do |note|
next if note.cross_reference_not_visible_for?(current_user)
notes_json[:notes] << note_json(note)
end
notes_json[:notes] =
if params[:full_data]
note_serializer.represent(@notes)
else
@notes.map { |note| note_json(note) }
end
 
render json: notes_json
end
Loading
Loading
@@ -80,22 +82,27 @@ module NotesActions
}
 
if note.persisted?
attrs.merge!(
valid: true,
id: note.id,
discussion_id: note.discussion_id(noteable),
html: note_html(note),
note: note.note
)
attrs[:valid] = true
 
discussion = note.to_discussion(noteable)
unless discussion.individual_note?
if params[:full_data]
attrs.merge!(note_serializer.represent(note))
else
attrs.merge!(
discussion_resolvable: discussion.resolvable?,
diff_discussion_html: diff_discussion_html(discussion),
discussion_html: discussion_html(discussion)
id: note.id,
discussion_id: note.discussion_id(noteable),
html: note_html(note),
note: note.note
)
discussion = note.to_discussion(noteable)
unless discussion.individual_note?
attrs.merge!(
discussion_resolvable: discussion.resolvable?,
diff_discussion_html: diff_discussion_html(discussion),
discussion_html: discussion_html(discussion)
)
end
end
else
attrs.merge!(
Loading
Loading
@@ -177,4 +184,8 @@ module NotesActions
def notes_finder
@notes_finder ||= NotesFinder.new(project, current_user, finder_params)
end
def note_serializer
NoteSerializer.new(project: project, noteable: noteable, current_user: current_user)
end
end
Loading
Loading
@@ -97,6 +97,14 @@ class Projects::IssuesController < Projects::ApplicationController
end
end
 
def discussions
@discussions = @issue.discussions
@discussions.reject! { |d| d.individual_note? && d.first_note.cross_reference_not_visible_for?(current_user) }
prepare_notes_for_rendering(@discussions.flat_map(&:notes))
render json: DiscussionSerializer.new(project: @project, noteable: @issue, current_user: current_user).represent(@discussions)
end
def create
create_params = issue_params.merge(spammable_params).merge(
merge_request_to_resolve_discussions_of: params[:merge_request_to_resolve_discussions_of],
Loading
Loading
Loading
Loading
@@ -119,7 +119,7 @@ module IssuesHelper
end
 
def awards_sort(awards)
awards.sort_by do |award, notes|
awards.sort_by do |award, award_emojis|
if award == "thumbsup"
0
elsif award == "thumbsdown"
Loading
Loading
Loading
Loading
@@ -21,8 +21,14 @@ module SystemNoteHelper
'outdated' => 'icon_edit'
}.freeze
 
def system_note_icon_name(note)
ICON_NAMES_BY_ACTION[note.system_note_metadata&.action]
end
def icon_for_system_note(note)
icon_name = ICON_NAMES_BY_ACTION[note.system_note_metadata&.action]
icon_name = system_note_icon_name(note)
custom_icon(icon_name) if icon_name
end
extend self
end
Loading
Loading
@@ -81,6 +81,10 @@ class Discussion
last_note.author
end
 
def updated?
last_updated_at != created_at
end
def id
first_note.discussion_id(context_noteable)
end
Loading
Loading
class AwardEmojiEntity < Grape::Entity
expose :name
expose :user, using: API::Entities::UserSafe
end
class DiscussionEntity < Grape::Entity
include RequestAwareEntity
expose :id, :reply_id
expose :expanded?, as: :expanded
expose :author, using: UserEntity
expose :created_at
expose :last_updated_at, if: -> (discussion, _) { discussion.updated? }
expose :last_updated_by, if: -> (discussion, _) { discussion.updated? }, using: UserEntity
expose :notes, using: NoteEntity
expose :individual_note?, as: :individual_note
expose :can_reply do |discussion|
can?(request.current_user, :create_note, discussion.project)
end
end
class DiscussionSerializer < BaseSerializer
entity DiscussionEntity
end
class NoteAttachmentEntity < Grape::Entity
expose :url
expose :filename
expose :image?, as: :image
end
class NoteEntity < API::Entities::Note
include RequestAwareEntity
expose :type
expose :author, using: UserEntity
expose :human_access do |note|
note.project.team.human_max_access(note.author_id)
end
unexpose :note, as: :body
expose :note
expose :redacted_note_html, as: :note_html
expose :last_edited_at, if: -> (note, _) { note.is_edited? }
expose :last_edited_by, using: UserEntity, if: -> (note, _) { note.is_edited? }
expose :can_edit do |note|
Ability.can_edit_note?(request.current_user, note)
end
expose :system_note_icon_name, if: -> (note, _) { note.system? } do |note|
SystemNoteHelper.system_note_icon_name(note)
end
expose :discussion_id do |note|
note.discussion_id(request.noteable)
end
expose :emoji_awardable?, as: :emoji_awardable
expose :award_emoji, if: -> (note, _) { note.emoji_awardable? }, using: AwardEmojiEntity
expose :toggle_award_path, if: -> (note, _) { note.emoji_awardable? } do |note|
if note.for_personal_snippet?
toggle_award_emoji_snippet_note_path(note.noteable, note)
else
toggle_award_emoji_namespace_project_note_path(note.project.namespace, note.project, note.id)
end
end
expose :report_abuse_path do |note|
new_abuse_report_path(user_id: note.author.id, ref_url: Gitlab::UrlBuilder.build(note))
end
expose :path do |note|
if note.for_personal_snippet?
snippet_note_path(note.noteable, note)
else
namespace_project_note_path(note.project.namespace, note.project, note)
end
end
expose :attachment, using: NoteAttachmentEntity
expose :delete_attachment_path, if: -> (note, _) { note.attachment? } do |note|
delete_attachment_namespace_project_note_path(note.project.namespace, note.project, note)
end
end
class NoteSerializer < BaseSerializer
entity NoteEntity
end
class UserEntity < API::Entities::UserBasic
include RequestAwareEntity
 
unexpose :web_url
expose :path do |user|
user_path(user)
end
Loading
Loading
Loading
Loading
@@ -5,7 +5,7 @@
by
= link_to_member(@project, discussion.resolved_by, avatar: false)
= time_ago_with_tooltip(discussion.resolved_at, placement: "bottom")
- elsif discussion.last_updated_at != discussion.created_at
- elsif discussion.updated?
.discussion-headline-light.js-discussion-headline
Last updated
- if discussion.last_updated_by
Loading
Loading
Loading
Loading
@@ -308,6 +308,7 @@ constraints(ProjectUrlConstrainer.new) do
get :can_create_branch
get :realtime_changes
post :create_merge_request
get :discussions, format: :json
end
collection do
post :bulk_update
Loading
Loading
module API
module Entities
class UserSafe < Grape::Entity
expose :name, :username
expose :id, :name, :username
end
 
class UserBasic < UserSafe
expose :id, :state
expose :state
expose :avatar_url do |user, options|
user.avatar_url(only_path: false)
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment