diff options
author | Robert Speicher <rspeicher@gmail.com> | 2021-01-20 22:34:23 +0300 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2021-01-20 22:34:23 +0300 |
commit | 6438df3a1e0fb944485cebf07976160184697d72 (patch) | |
tree | 00b09bfd170e77ae9391b1a2f5a93ef6839f2597 /app/services/boards | |
parent | 42bcd54d971da7ef2854b896a7b34f4ef8601067 (diff) |
Add latest changes from gitlab-org/gitlab@13-8-stable-eev13.8.0-rc42
Diffstat (limited to 'app/services/boards')
-rw-r--r-- | app/services/boards/base_items_list_service.rb | 128 | ||||
-rw-r--r-- | app/services/boards/issues/list_service.rb | 111 |
2 files changed, 139 insertions, 100 deletions
diff --git a/app/services/boards/base_items_list_service.rb b/app/services/boards/base_items_list_service.rb new file mode 100644 index 00000000000..851120ef597 --- /dev/null +++ b/app/services/boards/base_items_list_service.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +module Boards + class BaseItemsListService < Boards::BaseService + include Gitlab::Utils::StrongMemoize + include ActiveRecord::ConnectionAdapters::Quoting + + def execute + return items.order_closed_date_desc if list&.closed? + + ordered_items + end + + private + + def ordered_items + raise NotImplementedError + end + + def finder + raise NotImplementedError + end + + def board + raise NotImplementedError + end + + def item_model + raise NotImplementedError + end + + # We memoize the query here since the finder methods we use are quite complex. This does not memoize the result of the query. + # rubocop: disable CodeReuse/ActiveRecord + def items + strong_memoize(:items) do + filter(finder.execute).reorder(nil) + end + end + # rubocop: enable CodeReuse/ActiveRecord + + def filter(items) + # when grouping board issues by epics (used in board swimlanes) + # we need to get all issues in the board + # TODO: ignore hidden columns - + # https://gitlab.com/gitlab-org/gitlab/-/issues/233870 + return items if params[:all_lists] + + items = without_board_labels(items) unless list&.movable? || list&.closed? + items = with_list_label(items) if list&.label? + items + end + + def list + return unless params.key?(:id) + + strong_memoize(:list) do + id = params[:id] + + if board.lists.loaded? + board.lists.find { |l| l.id == id } + else + board.lists.find(id) + end + end + end + + def filter_params + set_parent + set_state + set_attempt_search_optimizations + + params + end + + def set_parent + if parent.is_a?(Group) + params[:group_id] = parent.id + else + params[:project_id] = parent.id + end + end + + def set_state + return if params[:all_lists] + + params[:state] = list && list.closed? ? 'closed' : 'opened' + end + + def set_attempt_search_optimizations + return unless params[:search].present? + + if board.group_board? + params[:attempt_group_search_optimizations] = true + else + params[:attempt_project_search_optimizations] = true + end + end + + # rubocop: disable CodeReuse/ActiveRecord + def board_label_ids + @board_label_ids ||= board.lists.movable.pluck(:label_id) + end + # rubocop: enable CodeReuse/ActiveRecord + + # rubocop: disable CodeReuse/ActiveRecord + def without_board_labels(items) + return items unless board_label_ids.any? + + items.where.not('EXISTS (?)', label_links(board_label_ids).limit(1)) + end + # rubocop: enable CodeReuse/ActiveRecord + + # rubocop: disable CodeReuse/ActiveRecord + def label_links(label_ids) + LabelLink + .where('label_links.target_type = ?', item_model) + .where(item_model.arel_table[:id].eq(LabelLink.arel_table[:target_id]).to_sql) + .where(label_id: label_ids) + end + # rubocop: enable CodeReuse/ActiveRecord + + # rubocop: disable CodeReuse/ActiveRecord + def with_list_label(items) + items.where('EXISTS (?)', label_links(list.label_id).limit(1)) + end + # rubocop: enable CodeReuse/ActiveRecord + end +end diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb index ab9d11abe98..27d59e052c7 100644 --- a/app/services/boards/issues/list_service.rb +++ b/app/services/boards/issues/list_service.rb @@ -2,26 +2,20 @@ module Boards module Issues - class ListService < Boards::BaseService + class ListService < Boards::BaseItemsListService include Gitlab::Utils::StrongMemoize def self.valid_params IssuesFinder.valid_params end - def execute - return fetch_issues.order_closed_date_desc if list&.closed? - - fetch_issues.order_by_position_and_priority(with_cte: params[:search].present?) - end - # rubocop: disable CodeReuse/ActiveRecord def metadata issues = Issue.arel_table keys = metadata_fields.keys # TODO: eliminate need for SQL literal fragment columns = Arel.sql(metadata_fields.values_at(*keys).join(', ')) - results = Issue.where(id: fetch_issues.select(issues[:id])).pluck(columns) + results = Issue.where(id: items.select(issues[:id])).pluck(columns) Hash[keys.zip(results.flatten)] end @@ -29,74 +23,28 @@ module Boards private - def metadata_fields - { size: 'COUNT(*)' } - end - - # We memoize the query here since the finder methods we use are quite complex. This does not memoize the result of the query. - # rubocop: disable CodeReuse/ActiveRecord - def fetch_issues - strong_memoize(:fetch_issues) do - issues = IssuesFinder.new(current_user, filter_params).execute - - filter(issues).reorder(nil) - end + def ordered_items + items.order_by_position_and_priority(with_cte: params[:search].present?) end - # rubocop: enable CodeReuse/ActiveRecord - def filter(issues) - # when grouping board issues by epics (used in board swimlanes) - # we need to get all issues in the board - # TODO: ignore hidden columns - - # https://gitlab.com/gitlab-org/gitlab/-/issues/233870 - return issues if params[:all_lists] - - issues = without_board_labels(issues) unless list&.movable? || list&.closed? - issues = with_list_label(issues) if list&.label? - issues + def finder + IssuesFinder.new(current_user, filter_params) end def board @board ||= parent.boards.find(params[:board_id]) end - def list - return unless params.key?(:id) - - strong_memoize(:list) do - id = params[:id] - - if board.lists.loaded? - board.lists.find { |l| l.id == id } - else - board.lists.find(id) - end - end + def metadata_fields + { size: 'COUNT(*)' } end def filter_params - set_parent - set_state set_scope set_non_archived - set_attempt_search_optimizations set_issue_types - params - end - - def set_parent - if parent.is_a?(Group) - params[:group_id] = parent.id - else - params[:project_id] = parent.id - end - end - - def set_state - return if params[:all_lists] - - params[:state] = list && list.closed? ? 'closed' : 'opened' + super end def set_scope @@ -107,49 +55,12 @@ module Boards params[:non_archived] = parent.is_a?(Group) end - def set_attempt_search_optimizations - return unless params[:search].present? - - if board.group_board? - params[:attempt_group_search_optimizations] = true - else - params[:attempt_project_search_optimizations] = true - end - end - def set_issue_types params[:issue_types] = Issue::TYPES_FOR_LIST end - # rubocop: disable CodeReuse/ActiveRecord - def board_label_ids - @board_label_ids ||= board.lists.movable.pluck(:label_id) - end - # rubocop: enable CodeReuse/ActiveRecord - - # rubocop: disable CodeReuse/ActiveRecord - def without_board_labels(issues) - return issues unless board_label_ids.any? - - issues.where.not('EXISTS (?)', issues_label_links.limit(1)) - end - # rubocop: enable CodeReuse/ActiveRecord - - # rubocop: disable CodeReuse/ActiveRecord - def issues_label_links - LabelLink.where("label_links.target_type = 'Issue' AND label_links.target_id = issues.id").where(label_id: board_label_ids) - end - # rubocop: enable CodeReuse/ActiveRecord - - # rubocop: disable CodeReuse/ActiveRecord - def with_list_label(issues) - issues.where('EXISTS (?)', LabelLink.where("label_links.target_type = 'Issue' AND label_links.target_id = issues.id") - .where("label_links.label_id = ?", list.label_id).limit(1)) - end - # rubocop: enable CodeReuse/ActiveRecord - - def board_group - board.group_board? ? parent : parent.group + def item_model + Issue end end end |