2018-09-11 15:08:34 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2014-09-02 08:28:27 -04:00
|
|
|
# IssuableFinder
|
2014-01-15 09:16:23 -05:00
|
|
|
#
|
|
|
|
# Used to filter Issues and MergeRequests collections by set of params
|
|
|
|
#
|
|
|
|
# Arguments:
|
|
|
|
# klass - actual class like Issue or MergeRequest
|
|
|
|
# current_user - which user use
|
|
|
|
# params:
|
2018-05-13 22:07:53 -04:00
|
|
|
# scope: 'created_by_me' or 'assigned_to_me' or 'all'
|
2018-06-26 15:30:29 -04:00
|
|
|
# state: 'opened' or 'closed' or 'locked' or 'all'
|
2014-01-15 09:16:23 -05:00
|
|
|
# group_id: integer
|
|
|
|
# project_id: integer
|
2015-06-28 16:12:32 -04:00
|
|
|
# milestone_title: string
|
2017-07-20 16:44:48 -04:00
|
|
|
# author_id: integer
|
2018-10-25 03:02:28 -04:00
|
|
|
# assignee_id: integer or 'None' or 'Any'
|
2014-01-15 09:16:23 -05:00
|
|
|
# search: string
|
|
|
|
# label_name: string
|
|
|
|
# sort: string
|
2016-11-27 05:33:15 -05:00
|
|
|
# non_archived: boolean
|
2017-02-17 13:28:32 -05:00
|
|
|
# iids: integer[]
|
2017-08-30 03:48:55 -04:00
|
|
|
# my_reaction_emoji: string
|
2018-02-28 06:16:29 -05:00
|
|
|
# created_after: datetime
|
|
|
|
# created_before: datetime
|
|
|
|
# updated_after: datetime
|
|
|
|
# updated_before: datetime
|
2018-06-05 13:31:32 -04:00
|
|
|
# use_cte_for_search: boolean
|
2014-01-15 09:16:23 -05:00
|
|
|
#
|
2014-09-02 08:28:27 -04:00
|
|
|
class IssuableFinder
|
2017-12-11 09:21:06 -05:00
|
|
|
prepend FinderWithCrossProjectAccess
|
|
|
|
include FinderMethods
|
2017-07-07 12:31:50 -04:00
|
|
|
include CreatedAtFilter
|
2017-07-11 08:19:43 -04:00
|
|
|
|
2017-12-11 09:21:06 -05:00
|
|
|
requires_cross_project_access unless: -> { project? }
|
|
|
|
|
2018-10-25 03:02:28 -04:00
|
|
|
# This is used as a common filter for None / Any
|
2018-10-25 22:47:14 -04:00
|
|
|
FILTER_NONE = 'none'.freeze
|
|
|
|
FILTER_ANY = 'any'.freeze
|
2018-10-25 03:02:28 -04:00
|
|
|
|
|
|
|
# This is accepted as a deprecated filter and is also used in unassigning users
|
2017-02-21 18:32:18 -05:00
|
|
|
NONE = '0'.freeze
|
2015-03-26 21:56:42 -04:00
|
|
|
|
2014-02-25 12:15:08 -05:00
|
|
|
attr_accessor :current_user, :params
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2018-02-20 07:33:49 -05:00
|
|
|
def self.scalar_params
|
|
|
|
@scalar_params ||= %i[
|
|
|
|
assignee_id
|
|
|
|
assignee_username
|
|
|
|
author_id
|
|
|
|
author_username
|
|
|
|
authorized_only
|
|
|
|
group_id
|
|
|
|
iids
|
|
|
|
label_name
|
|
|
|
milestone_title
|
|
|
|
my_reaction_emoji
|
|
|
|
non_archived
|
|
|
|
project_id
|
|
|
|
scope
|
|
|
|
search
|
|
|
|
sort
|
|
|
|
state
|
|
|
|
include_subgroups
|
2018-06-05 13:31:32 -04:00
|
|
|
use_cte_for_search
|
2018-02-20 07:33:49 -05:00
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.array_params
|
|
|
|
@array_params ||= { label_name: [], iids: [], assignee_username: [] }
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.valid_params
|
|
|
|
@valid_params ||= scalar_params + [array_params]
|
|
|
|
end
|
|
|
|
|
2016-11-22 05:25:04 -05:00
|
|
|
def initialize(current_user, params = {})
|
2014-01-15 09:16:23 -05:00
|
|
|
@current_user = current_user
|
|
|
|
@params = params
|
2015-05-25 07:36:28 -04:00
|
|
|
end
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2015-05-25 07:36:28 -04:00
|
|
|
def execute
|
2014-02-03 10:02:44 -05:00
|
|
|
items = init_collection
|
2018-02-20 07:33:49 -05:00
|
|
|
items = filter_items(items)
|
|
|
|
|
2018-06-05 13:31:32 -04:00
|
|
|
# This has to be last as we may use a CTE as an optimization fence by
|
|
|
|
# passing the use_cte_for_search param
|
|
|
|
# https://www.postgresql.org/docs/current/static/queries-with.html
|
|
|
|
items = by_search(items)
|
2018-02-20 07:33:49 -05:00
|
|
|
|
|
|
|
sort(items)
|
|
|
|
end
|
|
|
|
|
|
|
|
def filter_items(items)
|
2018-06-05 13:31:32 -04:00
|
|
|
items = by_project(items)
|
2014-02-03 10:02:44 -05:00
|
|
|
items = by_scope(items)
|
2017-07-07 12:31:50 -04:00
|
|
|
items = by_created_at(items)
|
2018-02-28 06:16:29 -05:00
|
|
|
items = by_updated_at(items)
|
2014-01-15 09:16:23 -05:00
|
|
|
items = by_state(items)
|
|
|
|
items = by_group(items)
|
|
|
|
items = by_assignee(items)
|
2014-12-05 10:13:07 -05:00
|
|
|
items = by_author(items)
|
2016-11-27 05:33:15 -05:00
|
|
|
items = by_non_archived(items)
|
2017-02-17 13:28:32 -05:00
|
|
|
items = by_iids(items)
|
2017-02-07 08:15:07 -05:00
|
|
|
items = by_milestone(items)
|
|
|
|
items = by_label(items)
|
2018-02-20 07:33:49 -05:00
|
|
|
by_my_reaction_emoji(items)
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|
|
|
|
|
2017-08-24 12:17:04 -04:00
|
|
|
def row_count
|
|
|
|
Gitlab::IssuablesCountForState.new(self).for_state_or_opened(params[:state])
|
|
|
|
end
|
|
|
|
|
2016-11-25 08:57:56 -05:00
|
|
|
# We often get counts for each state by running a query per state, and
|
|
|
|
# counting those results. This is typically slower than running one query
|
|
|
|
# (even if that query is slower than any of the individual state queries) and
|
|
|
|
# grouping and counting within that query.
|
|
|
|
#
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2016-11-25 08:57:56 -05:00
|
|
|
def count_by_state
|
2017-08-31 07:21:39 -04:00
|
|
|
count_params = params.merge(state: nil, sort: nil)
|
2016-11-25 08:57:56 -05:00
|
|
|
finder = self.class.new(current_user, count_params)
|
|
|
|
counts = Hash.new(0)
|
|
|
|
|
|
|
|
# Searching by label includes a GROUP BY in the query, but ours will be last
|
|
|
|
# because it is added last. Searching by multiple labels also includes a row
|
|
|
|
# per issuable, so we have to count those in Ruby - which is bad, but still
|
|
|
|
# better than performing multiple queries.
|
|
|
|
#
|
2018-06-05 13:31:32 -04:00
|
|
|
# This does not apply when we are using a CTE for the search, as the labels
|
|
|
|
# GROUP BY is inside the subquery in that case, so we set labels_count to 1.
|
|
|
|
labels_count = label_names.any? ? label_names.count : 1
|
|
|
|
labels_count = 1 if use_cte_for_search?
|
|
|
|
|
2016-11-25 08:57:56 -05:00
|
|
|
finder.execute.reorder(nil).group(:state).count.each do |key, value|
|
2018-10-01 07:45:15 -04:00
|
|
|
counts[count_key(key)] += value / labels_count
|
2016-11-25 08:57:56 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
counts[:all] = counts.values.sum
|
|
|
|
|
2018-07-27 06:13:36 -04:00
|
|
|
counts.with_indifferent_access
|
2016-11-25 08:57:56 -05:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2016-11-25 08:57:56 -05:00
|
|
|
|
2015-05-25 07:36:28 -04:00
|
|
|
def group
|
|
|
|
return @group if defined?(@group)
|
|
|
|
|
2015-06-18 13:15:17 -04:00
|
|
|
@group =
|
2015-05-25 07:36:28 -04:00
|
|
|
if params[:group_id].present?
|
|
|
|
Group.find(params[:group_id])
|
2015-06-18 13:15:17 -04:00
|
|
|
else
|
2015-05-25 07:36:28 -04:00
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-14 06:23:49 -04:00
|
|
|
def project?
|
|
|
|
params[:project_id].present?
|
|
|
|
end
|
|
|
|
|
2015-05-25 07:36:28 -04:00
|
|
|
def project
|
|
|
|
return @project if defined?(@project)
|
|
|
|
|
2016-10-26 13:34:06 -04:00
|
|
|
project = Project.find(params[:project_id])
|
|
|
|
project = nil unless Ability.allowed?(current_user, :"read_#{klass.to_ability_name}", project)
|
2015-11-11 06:49:16 -05:00
|
|
|
|
2016-10-26 13:34:06 -04:00
|
|
|
@project = project
|
2015-10-14 06:23:49 -04:00
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2017-02-07 08:15:07 -05:00
|
|
|
def projects(items = nil)
|
2016-10-26 13:34:06 -04:00
|
|
|
return @projects = project if project?
|
|
|
|
|
|
|
|
projects =
|
|
|
|
if current_user && params[:authorized_only].presence && !current_user_related?
|
|
|
|
current_user.authorized_projects
|
|
|
|
elsif group
|
2018-01-24 01:06:24 -05:00
|
|
|
finder_options = { include_subgroups: params[:include_subgroups], only_owned: true }
|
2018-08-27 11:31:01 -04:00
|
|
|
GroupProjectsFinder.new(group: group, current_user: current_user, options: finder_options).execute # rubocop: disable CodeReuse/Finder
|
2016-10-26 13:34:06 -04:00
|
|
|
else
|
2018-08-27 11:31:01 -04:00
|
|
|
ProjectsFinder.new(current_user: current_user).execute # rubocop: disable CodeReuse/Finder
|
2016-10-26 13:34:06 -04:00
|
|
|
end
|
2015-10-14 06:23:49 -04:00
|
|
|
|
2016-10-26 13:34:06 -04:00
|
|
|
@projects = projects.with_feature_available_for_user(klass, current_user).reorder(nil)
|
2015-05-25 07:36:28 -04:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2015-05-25 07:36:28 -04:00
|
|
|
|
|
|
|
def search
|
|
|
|
params[:search].presence
|
|
|
|
end
|
|
|
|
|
|
|
|
def milestones?
|
|
|
|
params[:milestone_title].present?
|
|
|
|
end
|
|
|
|
|
|
|
|
def milestones
|
|
|
|
return @milestones if defined?(@milestones)
|
|
|
|
|
|
|
|
@milestones =
|
2015-10-06 12:57:13 -04:00
|
|
|
if milestones?
|
2017-07-07 11:08:49 -04:00
|
|
|
if project?
|
|
|
|
group_id = project.group&.id
|
|
|
|
project_id = project.id
|
|
|
|
end
|
|
|
|
|
|
|
|
group_id = group.id if group
|
2015-10-14 06:20:48 -04:00
|
|
|
|
2017-07-07 11:08:49 -04:00
|
|
|
search_params =
|
|
|
|
{ title: params[:milestone_title], project_ids: project_id, group_ids: group_id }
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
MilestonesFinder.new(search_params).execute # rubocop: disable CodeReuse/Finder
|
2015-05-25 07:36:28 -04:00
|
|
|
else
|
2016-07-23 19:28:12 -04:00
|
|
|
Milestone.none
|
2015-05-25 07:36:28 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-10-16 05:43:26 -04:00
|
|
|
def labels?
|
|
|
|
params[:label_name].present?
|
|
|
|
end
|
|
|
|
|
2015-10-19 05:46:22 -04:00
|
|
|
def filter_by_no_label?
|
2016-04-20 12:23:10 -04:00
|
|
|
labels? && params[:label_name].include?(Label::None.title)
|
2015-10-16 05:43:26 -04:00
|
|
|
end
|
|
|
|
|
2016-02-19 00:27:41 -05:00
|
|
|
def labels
|
|
|
|
return @labels if defined?(@labels)
|
|
|
|
|
2016-10-17 14:55:46 -04:00
|
|
|
@labels =
|
|
|
|
if labels? && !filter_by_no_label?
|
2018-08-27 11:31:01 -04:00
|
|
|
LabelsFinder.new(current_user, project_ids: projects, title: label_names).execute(skip_authorization: true) # rubocop: disable CodeReuse/Finder
|
2016-10-17 14:55:46 -04:00
|
|
|
else
|
|
|
|
Label.none
|
2016-02-19 00:27:41 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-11-07 17:33:51 -05:00
|
|
|
def assignee_id?
|
2018-10-25 03:02:28 -04:00
|
|
|
params[:assignee_id].present?
|
2015-05-25 07:36:28 -04:00
|
|
|
end
|
|
|
|
|
2016-11-07 17:33:51 -05:00
|
|
|
def assignee_username?
|
2018-10-25 03:02:28 -04:00
|
|
|
params[:assignee_username].present?
|
2016-11-07 17:33:51 -05:00
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2015-05-25 07:36:28 -04:00
|
|
|
def assignee
|
|
|
|
return @assignee if defined?(@assignee)
|
|
|
|
|
2015-06-18 13:15:17 -04:00
|
|
|
@assignee =
|
2016-12-16 06:58:59 -05:00
|
|
|
if assignee_id?
|
2016-12-16 07:12:59 -05:00
|
|
|
User.find_by(id: params[:assignee_id])
|
2016-12-16 06:58:59 -05:00
|
|
|
elsif assignee_username?
|
2018-10-18 05:06:44 -04:00
|
|
|
User.find_by_username(params[:assignee_username])
|
2015-05-25 07:36:28 -04:00
|
|
|
else
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2015-05-25 07:36:28 -04:00
|
|
|
|
2016-11-07 17:33:51 -05:00
|
|
|
def author_id?
|
2016-12-16 06:58:59 -05:00
|
|
|
params[:author_id].present? && params[:author_id] != NONE
|
2015-05-25 07:36:28 -04:00
|
|
|
end
|
|
|
|
|
2016-11-07 17:33:51 -05:00
|
|
|
def author_username?
|
2016-12-16 06:58:59 -05:00
|
|
|
params[:author_username].present? && params[:author_username] != NONE
|
2016-11-07 17:33:51 -05:00
|
|
|
end
|
|
|
|
|
2016-12-16 09:28:18 -05:00
|
|
|
def no_author?
|
2017-01-10 20:51:57 -05:00
|
|
|
# author_id takes precedence over author_username
|
2016-12-16 09:28:18 -05:00
|
|
|
params[:author_id] == NONE || params[:author_username] == NONE
|
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2015-05-25 07:36:28 -04:00
|
|
|
def author
|
|
|
|
return @author if defined?(@author)
|
|
|
|
|
2015-06-18 13:15:17 -04:00
|
|
|
@author =
|
2016-12-16 07:12:59 -05:00
|
|
|
if author_id?
|
|
|
|
User.find_by(id: params[:author_id])
|
|
|
|
elsif author_username?
|
2018-10-18 05:06:44 -04:00
|
|
|
User.find_by_username(params[:author_username])
|
2015-05-25 07:36:28 -04:00
|
|
|
else
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2015-05-25 07:36:28 -04:00
|
|
|
|
2014-01-15 09:16:23 -05:00
|
|
|
private
|
|
|
|
|
2014-02-03 10:02:44 -05:00
|
|
|
def init_collection
|
2015-10-14 06:23:49 -04:00
|
|
|
klass.all
|
2014-02-03 10:02:44 -05:00
|
|
|
end
|
|
|
|
|
2018-10-01 07:45:15 -04:00
|
|
|
def count_key(value)
|
|
|
|
Array(value).last.to_sym
|
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2014-02-03 10:02:44 -05:00
|
|
|
def by_scope(items)
|
2017-09-18 13:29:17 -04:00
|
|
|
return items.none if current_user_related? && !current_user
|
|
|
|
|
2016-03-21 19:09:20 -04:00
|
|
|
case params[:scope]
|
2018-05-13 22:07:53 -04:00
|
|
|
when 'created_by_me', 'authored'
|
2014-02-10 08:04:52 -05:00
|
|
|
items.where(author_id: current_user.id)
|
2018-05-13 22:07:53 -04:00
|
|
|
when 'assigned_to_me'
|
2017-05-04 08:11:15 -04:00
|
|
|
items.assigned_to(current_user)
|
2014-01-15 09:16:23 -05:00
|
|
|
else
|
2016-03-21 19:09:20 -04:00
|
|
|
items
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2018-02-28 06:16:29 -05:00
|
|
|
def by_updated_at(items)
|
|
|
|
items = items.updated_after(params[:updated_after]) if params[:updated_after].present?
|
|
|
|
items = items.updated_before(params[:updated_before]) if params[:updated_before].present?
|
|
|
|
|
|
|
|
items
|
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
def by_state(items)
|
2016-11-30 03:11:43 -05:00
|
|
|
case params[:state].to_s
|
|
|
|
when 'closed'
|
|
|
|
items.closed
|
|
|
|
when 'merged'
|
|
|
|
items.respond_to?(:merged) ? items.merged : items.closed
|
|
|
|
when 'opened'
|
|
|
|
items.opened
|
2018-06-26 15:30:29 -04:00
|
|
|
when 'locked'
|
|
|
|
items.where(state: 'locked')
|
2014-01-15 09:16:23 -05:00
|
|
|
else
|
2016-09-23 09:16:11 -04:00
|
|
|
items
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
|
|
|
|
def by_group(items)
|
2016-03-20 16:14:39 -04:00
|
|
|
# Selection by group is already covered by `by_project` and `projects`
|
2014-01-15 09:16:23 -05:00
|
|
|
items
|
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
def by_project(items)
|
2015-10-14 06:23:49 -04:00
|
|
|
items =
|
2015-11-11 06:50:36 -05:00
|
|
|
if project?
|
2018-04-06 06:24:33 -04:00
|
|
|
items.of_projects(projects).references_project
|
|
|
|
elsif projects
|
|
|
|
items.merge(projects.reorder(nil)).join_project
|
2015-10-14 06:23:49 -04:00
|
|
|
else
|
|
|
|
items.none
|
|
|
|
end
|
2014-01-15 09:16:23 -05:00
|
|
|
|
|
|
|
items
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2018-06-05 13:31:32 -04:00
|
|
|
def use_cte_for_search?
|
|
|
|
return false unless search
|
|
|
|
return false unless Gitlab::Database.postgresql?
|
2018-10-05 06:46:54 -04:00
|
|
|
return false unless Feature.enabled?(:use_cte_for_group_issues_search, default_enabled: true)
|
2018-06-05 13:31:32 -04:00
|
|
|
|
|
|
|
params[:use_cte_for_search]
|
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
def by_search(items)
|
2018-06-05 13:31:32 -04:00
|
|
|
return items unless search
|
|
|
|
|
|
|
|
if use_cte_for_search?
|
|
|
|
cte = Gitlab::SQL::RecursiveCTE.new(klass.table_name)
|
|
|
|
cte << items
|
|
|
|
|
|
|
|
items = klass.with(cte.to_arel).from(klass.table_name)
|
|
|
|
end
|
|
|
|
|
|
|
|
items.full_search(search)
|
2017-02-17 13:28:32 -05:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2017-02-17 13:28:32 -05:00
|
|
|
def by_iids(items)
|
|
|
|
params[:iids].present? ? items.where(iid: params[:iids]) : items
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
def sort(items)
|
2015-11-11 06:50:36 -05:00
|
|
|
# Ensure we always have an explicit sort order (instead of inheriting
|
|
|
|
# multiple orders when combining ActiveRecord::Relation objects).
|
2018-04-04 05:19:47 -04:00
|
|
|
params[:sort] ? items.sort_by_attribute(params[:sort], excluded_labels: label_names) : items.reorder(id: :desc)
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
def by_assignee(items)
|
2018-10-25 03:02:28 -04:00
|
|
|
if filter_by_no_assignee?
|
|
|
|
items.where(assignee_id: nil)
|
|
|
|
elsif filter_by_any_assignee?
|
|
|
|
items.where('assignee_id IS NOT NULL')
|
|
|
|
elsif assignee
|
|
|
|
items.where(assignee_id: assignee.id)
|
2016-12-16 07:12:59 -05:00
|
|
|
elsif assignee_id? || assignee_username? # assignee not found
|
2018-10-25 03:02:28 -04:00
|
|
|
items.none
|
|
|
|
else
|
|
|
|
items
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2018-10-26 22:52:06 -04:00
|
|
|
def filter_by_no_assignee?
|
|
|
|
# Assignee_id takes precedence over assignee_username
|
|
|
|
[NONE, FILTER_NONE].include?(params[:assignee_id].to_s.downcase) || params[:assignee_username].to_s == NONE
|
|
|
|
end
|
|
|
|
|
|
|
|
def filter_by_any_assignee?
|
|
|
|
params[:assignee_id].to_s.downcase == FILTER_ANY
|
|
|
|
end
|
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2014-12-05 10:13:07 -05:00
|
|
|
def by_author(items)
|
2016-12-16 07:12:59 -05:00
|
|
|
if author
|
|
|
|
items = items.where(author_id: author.id)
|
2016-12-16 09:28:18 -05:00
|
|
|
elsif no_author?
|
|
|
|
items = items.where(author_id: nil)
|
2016-12-16 07:12:59 -05:00
|
|
|
elsif author_id? || author_username? # author not found
|
|
|
|
items = items.none
|
2014-12-05 10:13:07 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
items
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2014-12-05 10:13:07 -05:00
|
|
|
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: disable CodeReuse/ActiveRecord
|
2015-10-16 05:43:26 -04:00
|
|
|
def by_milestone(items)
|
|
|
|
if milestones?
|
2015-10-19 05:46:22 -04:00
|
|
|
if filter_by_no_milestone?
|
2016-05-19 18:30:38 -04:00
|
|
|
items = items.left_joins_milestones.where(milestone_id: [-1, nil])
|
2018-10-03 07:00:03 -04:00
|
|
|
elsif filter_by_any_milestone?
|
|
|
|
items = items.any_milestone
|
2016-03-13 08:19:27 -04:00
|
|
|
elsif filter_by_upcoming_milestone?
|
2017-02-07 08:15:07 -05:00
|
|
|
upcoming_ids = Milestone.upcoming_ids_by_projects(projects(items))
|
2016-04-27 11:35:30 -04:00
|
|
|
items = items.left_joins_milestones.where(milestone_id: upcoming_ids)
|
2017-03-10 14:01:05 -05:00
|
|
|
elsif filter_by_started_milestone?
|
|
|
|
items = items.left_joins_milestones.where('milestones.start_date <= NOW()')
|
2015-10-16 05:43:26 -04:00
|
|
|
else
|
2016-05-19 18:30:38 -04:00
|
|
|
items = items.with_milestone(params[:milestone_title])
|
2015-10-16 05:43:26 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
items
|
|
|
|
end
|
2018-08-27 11:31:01 -04:00
|
|
|
# rubocop: enable CodeReuse/ActiveRecord
|
2015-10-16 05:43:26 -04:00
|
|
|
|
2018-10-26 22:54:05 -04:00
|
|
|
def filter_by_no_milestone?
|
|
|
|
# Accepts `No Milestone` for compatibility
|
|
|
|
params[:milestone_title].to_s.downcase == FILTER_NONE || params[:milestone_title] == Milestone::None.title
|
|
|
|
end
|
|
|
|
|
|
|
|
def filter_by_any_milestone?
|
|
|
|
# Accepts `Any Milestone` for compatibility
|
|
|
|
params[:milestone_title].to_s.downcase == FILTER_ANY || params[:milestone_title] == Milestone::Any.title
|
|
|
|
end
|
|
|
|
|
|
|
|
def filter_by_upcoming_milestone?
|
|
|
|
params[:milestone_title] == Milestone::Upcoming.name
|
|
|
|
end
|
|
|
|
|
|
|
|
def filter_by_started_milestone?
|
|
|
|
params[:milestone_title] == Milestone::Started.name
|
|
|
|
end
|
|
|
|
|
2014-01-15 09:16:23 -05:00
|
|
|
def by_label(items)
|
2017-12-26 14:16:43 -05:00
|
|
|
return items unless labels?
|
|
|
|
|
|
|
|
items =
|
2015-10-19 05:46:22 -04:00
|
|
|
if filter_by_no_label?
|
2017-12-26 14:16:43 -05:00
|
|
|
items.without_label
|
2015-10-06 12:57:13 -04:00
|
|
|
else
|
2017-12-26 14:16:43 -05:00
|
|
|
items.with_label(label_names, params[:sort])
|
2015-10-06 12:57:13 -04:00
|
|
|
end
|
2014-01-15 09:16:23 -05:00
|
|
|
|
2016-04-21 12:49:08 -04:00
|
|
|
items
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|
2014-01-31 11:06:13 -05:00
|
|
|
|
2017-08-30 03:48:55 -04:00
|
|
|
def by_my_reaction_emoji(items)
|
|
|
|
if params[:my_reaction_emoji].present? && current_user
|
2018-10-27 11:52:26 -04:00
|
|
|
items =
|
|
|
|
if filter_by_no_reaction?
|
|
|
|
items.not_awarded(current_user)
|
|
|
|
elsif filter_by_any_reaction?
|
|
|
|
items.awarded(current_user)
|
|
|
|
else
|
|
|
|
items.awarded(current_user, params[:my_reaction_emoji])
|
|
|
|
end
|
2017-08-30 03:48:55 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
items
|
|
|
|
end
|
|
|
|
|
2018-10-26 22:52:06 -04:00
|
|
|
def filter_by_no_reaction?
|
|
|
|
params[:my_reaction_emoji].to_s.downcase == FILTER_NONE
|
|
|
|
end
|
|
|
|
|
|
|
|
def filter_by_any_reaction?
|
|
|
|
params[:my_reaction_emoji].to_s.downcase == FILTER_ANY
|
|
|
|
end
|
|
|
|
|
2016-02-19 00:27:41 -05:00
|
|
|
def label_names
|
2016-03-14 05:46:26 -04:00
|
|
|
if labels?
|
|
|
|
params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name]
|
|
|
|
else
|
|
|
|
[]
|
|
|
|
end
|
2016-02-19 00:27:41 -05:00
|
|
|
end
|
|
|
|
|
2016-11-27 05:33:15 -05:00
|
|
|
def by_non_archived(items)
|
|
|
|
params[:non_archived].present? ? items.non_archived : items
|
|
|
|
end
|
|
|
|
|
2014-10-27 05:02:20 -04:00
|
|
|
def current_user_related?
|
2018-05-13 22:07:53 -04:00
|
|
|
scope = params[:scope]
|
|
|
|
scope == 'created_by_me' || scope == 'authored' || scope == 'assigned_to_me'
|
2014-10-27 05:02:20 -04:00
|
|
|
end
|
2014-01-15 09:16:23 -05:00
|
|
|
end
|