Commit cbe30cb8 authored by Nick Thomas's avatar Nick Thomas

Merge branch '6769-epics-votes' into 'master'

Add upvote/downvote counts to Epics API

Closes gitlab-ce#56723 and #6769

See merge request gitlab-org/gitlab-ee!9264
parents 050312ed 6b1881b1
...@@ -79,7 +79,9 @@ Example response: ...@@ -79,7 +79,9 @@ Example response:
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": [],
"upvotes": 4,
"downvotes": 0
} }
] ]
``` ```
...@@ -129,7 +131,9 @@ Example response: ...@@ -129,7 +131,9 @@ Example response:
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": [],
"upvotes": 4,
"downvotes": 0
} }
``` ```
...@@ -189,7 +193,9 @@ Example response: ...@@ -189,7 +193,9 @@ Example response:
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": [],
"upvotes": 4,
"downvotes": 0
} }
``` ```
...@@ -251,7 +257,9 @@ Example response: ...@@ -251,7 +257,9 @@ Example response:
"due_date_from_milestones": "2018-07-31", "due_date_from_milestones": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z", "created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z", "updated_at": "2018-07-18T12:22:05.239Z",
"labels": [] "labels": [],
"upvotes": 4,
"downvotes": 0
} }
``` ```
......
...@@ -107,6 +107,8 @@ Example response: ...@@ -107,6 +107,8 @@ Example response:
"created_at" : "2016-01-04T15:31:51.081Z", "created_at" : "2016-01-04T15:31:51.081Z",
"iid" : 6, "iid" : 6,
"labels" : [], "labels" : [],
"upvotes": 4,
"downvotes": 0,
"user_notes_count": 1, "user_notes_count": 1,
"due_date": "2016-07-22", "due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/6", "web_url": "http://example.com/example/example/issues/6",
...@@ -217,6 +219,8 @@ Example response: ...@@ -217,6 +219,8 @@ Example response:
"name" : "Dr. Luella Kovacek" "name" : "Dr. Luella Kovacek"
}, },
"labels" : [], "labels" : [],
"upvotes": 4,
"downvotes": 0,
"id" : 41, "id" : 41,
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z", "updated_at" : "2016-01-04T15:31:46.176Z",
...@@ -332,6 +336,8 @@ Example response: ...@@ -332,6 +336,8 @@ Example response:
"name" : "Dr. Luella Kovacek" "name" : "Dr. Luella Kovacek"
}, },
"labels" : [], "labels" : [],
"upvotes": 4,
"downvotes": 0,
"id" : 41, "id" : 41,
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z", "updated_at" : "2016-01-04T15:31:46.176Z",
...@@ -427,6 +433,8 @@ Example response: ...@@ -427,6 +433,8 @@ Example response:
"name" : "Dr. Luella Kovacek" "name" : "Dr. Luella Kovacek"
}, },
"labels" : [], "labels" : [],
"upvotes": 4,
"downvotes": 0,
"id" : 41, "id" : 41,
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.", "title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z", "updated_at" : "2016-01-04T15:31:46.176Z",
...@@ -502,6 +510,8 @@ Example response: ...@@ -502,6 +510,8 @@ Example response:
"labels" : [ "labels" : [
"bug" "bug"
], ],
"upvotes": 4,
"downvotes": 0,
"author" : { "author" : {
"name" : "Alexandra Bashirian", "name" : "Alexandra Bashirian",
"avatar_url" : null, "avatar_url" : null,
...@@ -601,6 +611,8 @@ Example response: ...@@ -601,6 +611,8 @@ Example response:
"labels" : [ "labels" : [
"bug" "bug"
], ],
"upvotes": 4,
"downvotes": 0,
"id" : 85, "id" : 85,
"assignees" : [], "assignees" : [],
"assignee" : null, "assignee" : null,
...@@ -686,6 +698,8 @@ Example response: ...@@ -686,6 +698,8 @@ Example response:
"closed_at": null, "closed_at": null,
"closed_by": null, "closed_by": null,
"labels": [], "labels": [],
"upvotes": 4,
"downvotes": 0,
"milestone": null, "milestone": null,
"assignees": [{ "assignees": [{
"name": "Miss Monserrate Beier", "name": "Miss Monserrate Beier",
...@@ -769,6 +783,8 @@ Example response: ...@@ -769,6 +783,8 @@ Example response:
"closed_at": null, "closed_at": null,
"closed_by": null, "closed_by": null,
"labels": [], "labels": [],
"upvotes": 4,
"downvotes": 0,
"milestone": null, "milestone": null,
"assignees": [{ "assignees": [{
"name": "Miss Monserrate Beier", "name": "Miss Monserrate Beier",
...@@ -851,6 +867,8 @@ Example response: ...@@ -851,6 +867,8 @@ Example response:
"created_at": "2016-04-05T21:41:45.217Z", "created_at": "2016-04-05T21:41:45.217Z",
"updated_at": "2016-04-07T13:02:37.905Z", "updated_at": "2016-04-07T13:02:37.905Z",
"labels": [], "labels": [],
"upvotes": 4,
"downvotes": 0,
"milestone": null, "milestone": null,
"assignee": { "assignee": {
"name": "Edwardo Grady", "name": "Edwardo Grady",
......
---
title: Add upvote/downvote information to epics API
merge_request: 9264
author:
type: added
...@@ -9,6 +9,8 @@ module API ...@@ -9,6 +9,8 @@ module API
authorize_epics_feature! authorize_epics_feature!
end end
helpers ::Gitlab::IssuableMetadata
helpers do helpers do
def authorize_epics_feature! def authorize_epics_feature!
forbidden! unless user_group.feature_available?(:epics) forbidden! unless user_group.feature_available?(:epics)
...@@ -69,9 +71,9 @@ module API ...@@ -69,9 +71,9 @@ module API
use :pagination use :pagination
end end
get ':id/(-/)epics' do get ':id/(-/)epics' do
epics = find_epics(group_id: user_group.id) epics = paginate(find_epics(group_id: user_group.id))
present paginate(epics), with: EE::API::Entities::Epic, user: current_user present epics, with: EE::API::Entities::Epic, user: current_user, epics_metadata: issuable_meta_data(epics, 'Epic')
end end
desc 'Get details of an epic' do desc 'Get details of an epic' do
......
...@@ -203,6 +203,22 @@ module EE ...@@ -203,6 +203,22 @@ module EE
# Avoids an N+1 query since labels are preloaded # Avoids an N+1 query since labels are preloaded
epic.labels.map(&:title).sort epic.labels.map(&:title).sort
end end
expose :upvotes do |epic, options|
if options[:epics_metadata]
# Avoids an N+1 query when metadata is included
options[:epics_metadata][epic.id].upvotes
else
epic.upvotes
end
end
expose :downvotes do |epic, options|
if options[:epics_metadata]
# Avoids an N+1 query when metadata is included
options[:epics_metadata][epic.id].downvotes
else
epic.downvotes
end
end
end end
class EpicIssue < ::API::Entities::Issue class EpicIssue < ::API::Entities::Issue
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
"type": "string" "type": "string"
} }
}, },
"upvotes": { "type": "integer" },
"downvotes": { "type": "integer" },
"start_date": { "type": ["date", "null"] }, "start_date": { "type": ["date", "null"] },
"start_date_fixed": { "type": ["date", "null"] }, "start_date_fixed": { "type": ["date", "null"] },
"start_date_from_milestones": { "type": ["date", "null"] }, "start_date_from_milestones": { "type": ["date", "null"] },
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
"due_date_from_milestones": { "type": ["date", "null"] }, "due_date_from_milestones": { "type": ["date", "null"] },
"due_date_is_fixed": { "type": "boolean" }, "due_date_is_fixed": { "type": "boolean" },
"state": { "type": "string" }, "state": { "type": "string" },
"upvotes": { "type": "integer" },
"downvotes": { "type": "integer" },
"created_at": { "type": ["string", "null"] }, "created_at": { "type": ["string", "null"] },
"updated_at": { "type": ["string", "null"] }, "updated_at": { "type": ["string", "null"] },
"labels": { "labels": {
......
...@@ -142,6 +142,20 @@ describe API::Epics do ...@@ -142,6 +142,20 @@ describe API::Epics do
expect_paginated_array_response([epic2.id, epic.id]) expect_paginated_array_response([epic2.id, epic.id])
end end
it 'has upvote/downvote information' do
epic.create_award_emoji('thumbsup', user)
epic2.create_award_emoji('thumbsdown', user)
get api(url, user)
expect(response).to have_gitlab_http_status(200)
expect(json_response).to contain_exactly(
a_hash_including('upvotes' => 1, 'downvotes' => 0),
a_hash_including('upvotes' => 0, 'downvotes' => 1)
)
end
it 'sorts by created_at descending by default' do it 'sorts by created_at descending by default' do
get api(url, user) get api(url, user)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment