diff options
author | Alexandru Croitor <acroitor@gitlab.com> | 2019-04-08 14:17:22 +0300 |
---|---|---|
committer | Alexandru Croitor <acroitor@gitlab.com> | 2019-05-15 10:15:16 +0300 |
commit | 5ec28dc387fb4adc3c5b65ac47819a8663186954 (patch) | |
tree | 4e40a2bf57265d1613ab207e18ab45ee2c4195a5 /lib | |
parent | 6bf5af2acd5e046d4235dee6473c214e91d86379 (diff) | |
download | gitlab-ce-5ec28dc387fb4adc3c5b65ac47819a8663186954.tar.gz |
Changes to issues api
When issues_controller endpoint was used for search, the parameters
passed to the controller were slightly different then the ones
passed to API. Because the searchbar UI is reused in different
places and builds the parameters passed to request in same way
we need to account for old parameter names.
Add issues_statistics api endpoints
Adds issue_statistics api endpoints for issue lists and returns
counts of issues for all, closed and opened states.
Expose more label attributes based on a param
When requesting issues list through API expose more attributes
for labels, like color, description if with_labels_data param is
being passed, avoiding this way to change response schema for users
that already use API.
https://gitlab.com/gitlab-org/gitlab-ce/issues/57402
Diffstat (limited to 'lib')
-rw-r--r-- | lib/api/entities.rb | 10 | ||||
-rw-r--r-- | lib/api/helpers/issues_helpers.rb | 37 | ||||
-rw-r--r-- | lib/api/issues.rb | 78 |
3 files changed, 97 insertions, 28 deletions
diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 296688ba25b..a57c7e9f851 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -542,9 +542,13 @@ module API class IssueBasic < ProjectEntity expose :closed_at expose :closed_by, using: Entities::UserBasic - expose :labels do |issue| + expose :labels do |issue, options| # Avoids an N+1 query since labels are preloaded - issue.labels.map(&:title).sort + if options[:with_labels_data] + ::API::Entities::LabelBasic.represent(issue.labels.sort_by(&:title)) + else + issue.labels.map(&:title).sort + end end expose :milestone, using: Entities::Milestone expose :assignees, :author, using: Entities::UserBasic @@ -560,6 +564,8 @@ module API expose :due_date expose :confidential expose :discussion_locked + expose(:has_tasks) {|issue, _| !issue.task_list_items.empty? } + expose :task_status, if: -> (issue, _) { !issue.task_list_items.empty? } expose :web_url do |issue| Gitlab::UrlBuilder.build(issue) diff --git a/lib/api/helpers/issues_helpers.rb b/lib/api/helpers/issues_helpers.rb index f6762910b0c..00aaf5243b7 100644 --- a/lib/api/helpers/issues_helpers.rb +++ b/lib/api/helpers/issues_helpers.rb @@ -18,6 +18,43 @@ module API :title ] end + + def issue_finder(args = {}) + args = declared_params.merge(args) + + args.delete(:id) + args[:milestone_title] ||= args.delete(:milestone) + args[:milestone_title] ||= args.delete(:milestone_title) + args[:label_name] ||= args.delete(:labels) + args[:scope] = args[:scope].underscore if args[:scope] + + IssuesFinder.new(current_user, args) + end + + def find_issues(args = {}) + # rubocop: disable CodeReuse/ActiveRecord + finder = issue_finder(args) + issues = finder.execute.with_api_entity_associations + order_by = declared_params[:sort].present? && %w(asc desc).include?(declared_params[:sort].downcase) + issues = issues.reorder(order_options_with_tie_breaker) if order_by + issues + # rubocop: enable CodeReuse/ActiveRecord + end + + def issues_statistics(args = {}) + finder = issue_finder(args) + counter = Gitlab::IssuablesCountForState.new(finder) + + { + statistics: { + counts: { + all: counter[:all], + closed: counter[:closed], + opened: counter[:opened] + } + } + } + end end end end diff --git a/lib/api/issues.rb b/lib/api/issues.rb index d0a93b77951..67da1c46480 100644 --- a/lib/api/issues.rb +++ b/lib/api/issues.rb @@ -3,27 +3,12 @@ module API class Issues < Grape::API include PaginationParams + helpers Helpers::IssuesHelpers + helpers ::Gitlab::IssuableMetadata before { authenticate_non_get! } - helpers ::Gitlab::IssuableMetadata - helpers do - # rubocop: disable CodeReuse/ActiveRecord - def find_issues(args = {}) - args = declared_params.merge(args) - - args.delete(:id) - args[:milestone_title] = args.delete(:milestone) - args[:label_name] = args.delete(:labels) - args[:scope] = args[:scope].underscore if args[:scope] - - issues = IssuesFinder.new(current_user, args).execute - .with_api_entity_associations - issues.reorder(order_options_with_tie_breaker) - end - # rubocop: enable CodeReuse/ActiveRecord - if Gitlab.ee? params :issues_params_ee do optional :weight, types: [Integer, String], integer_none_any: true, desc: 'The weight of the issue' @@ -35,13 +20,14 @@ module API end params :issues_params do - optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' + optional :labels, :label_name, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names' + optional :with_labels_data, type: Boolean, desc: 'Return more label data than just lable title', default: false optional :milestone, type: String, desc: 'Milestone title' optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at', desc: 'Return issues ordered by `created_at` or `updated_at` fields.' - optional :sort, type: String, values: %w[asc desc], default: 'desc', + optional :sort, type: String, default: 'desc', desc: 'Return issues sorted in `asc` or `desc` order.' - optional :milestone, type: String, desc: 'Return issues for a specific milestone' + optional :milestone, :milestone_title, type: String, desc: 'Return issues for a specific milestone' optional :iids, type: Array[Integer], desc: 'The IID array of issues' optional :search, type: String, desc: 'Search issues for text present in the title, description, or any combination of these' optional :in, type: String, desc: '`title`, `description`, or a string joining them with comma' @@ -50,12 +36,17 @@ module API optional :updated_after, type: DateTime, desc: 'Return issues updated after the specified time' optional :updated_before, type: DateTime, desc: 'Return issues updated before the specified time' optional :author_id, type: Integer, desc: 'Return issues which are authored by the user with the given ID' + optional :author_username, type: String, desc: 'Return issues which are authored by the user with the given username' optional :assignee_id, types: [Integer, String], integer_none_any: true, desc: 'Return issues which are assigned to the user with the given ID' + optional :assignee_username, type: Array[String], + desc: 'Return issues which are assigned to the user with the given username' optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all], desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`' optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji' optional :confidential, type: Boolean, desc: 'Filter confidential or public issues' + optional :state, type: String, values: %w[opened closed all], default: 'all', + desc: 'Return opened, closed, or all issues' use :pagination use :issues_params_ee if Gitlab.ee? @@ -75,13 +66,25 @@ module API end end + desc "Get currently authenticated user's issues statistics" + params do + use :issues_params + optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all], default: 'created_by_me', + desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`' + end + get '/issues_statistics' do + authenticate! unless params[:scope] == 'all' + + stats = issues_statistics + + present stats, with: Grape::Presenters::Presenter + end + resource :issues do desc "Get currently authenticated user's issues" do success Entities::IssueBasic end params do - optional :state, type: String, values: %w[opened closed all], default: 'all', - desc: 'Return opened, closed, or all issues' use :issues_params optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all], default: 'created_by_me', desc: 'Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`' @@ -92,6 +95,7 @@ module API options = { with: Entities::IssueBasic, + with_labels_data: declared_params[:with_labels_data], current_user: current_user, issuable_metadata: issuable_meta_data(issues, 'Issue') } @@ -108,8 +112,6 @@ module API success Entities::IssueBasic end params do - optional :state, type: String, values: %w[opened closed all], default: 'all', - desc: 'Return opened, closed, or all issues' use :issues_params end get ":id/issues" do @@ -119,12 +121,25 @@ module API options = { with: Entities::IssueBasic, + with_labels_data: declared_params[:with_labels_data], current_user: current_user, issuable_metadata: issuable_meta_data(issues, 'Issue') } present issues, options end + + desc 'Get statistics for the list of group issues' + params do + use :issues_params + end + get ":id/issues_statistics" do + group = find_group!(params[:id]) + + stats = issues_statistics(group_id: group.id, include_subgroups: true) + + present stats, with: Grape::Presenters::Presenter + end end params do @@ -137,8 +152,6 @@ module API success Entities::IssueBasic end params do - optional :state, type: String, values: %w[opened closed all], default: 'all', - desc: 'Return opened, closed, or all issues' use :issues_params end get ":id/issues" do @@ -148,6 +161,7 @@ module API options = { with: Entities::IssueBasic, + with_labels_data: declared_params[:with_labels_data], current_user: current_user, project: user_project, issuable_metadata: issuable_meta_data(issues, 'Issue') @@ -156,6 +170,18 @@ module API present issues, options end + desc 'Get statistics for the list of project issues' + params do + use :issues_params + end + get ":id/issues_statistics" do + project = find_project!(params[:id]) + + stats = issues_statistics(project_id: project.id) + + present stats, with: Grape::Presenters::Presenter + end + desc 'Get a single project issue' do success Entities::Issue end |