blob: 5f24564dc56088843739ffb960dc68ce5cc74000 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
# frozen_string_literal: true
module Milestoneish
DISPLAY_ISSUES_LIMIT = 3000
def total_issues_count
@total_issues_count ||= Milestones::IssuesCountService.new(self).count
end
def closed_issues_count
@close_issues_count ||= Milestones::ClosedIssuesCountService.new(self).count
end
def opened_issues_count
total_issues_count - closed_issues_count
end
def complete?
total_issues_count > 0 && total_issues_count == closed_issues_count
end
def percent_complete
closed_issues_count * 100 / total_issues_count
rescue ZeroDivisionError
0
end
def remaining_days
return 0 if !due_date || expired?
(due_date - Date.today).to_i
end
def elapsed_days
return 0 if !start_date || start_date.future?
(Date.today - start_date).to_i
end
def issues_visible_to_user(user)
memoize_per_user(user, :issues_visible_to_user) do
IssuesFinder.new(user, issues_finder_params)
.execute.preload(:assignees).where(milestone_id: milestoneish_id)
end
end
def issue_participants_visible_by_user(user)
User.joins(:issue_assignees)
.where('issue_assignees.issue_id' => issues_visible_to_user(user).select(:id))
.distinct
end
def issue_labels_visible_by_user(user)
Label.joins(:label_links)
.where('label_links.target_id' => issues_visible_to_user(user).select(:id), 'label_links.target_type' => 'Issue')
.distinct
end
def sorted_issues(user)
# This method is used on milestone view to filter opened assigned, opened unassigned and closed issues columns.
# We want a limit of DISPLAY_ISSUES_LIMIT for total issues present on all columns.
limited_ids =
issues_visible_to_user(user).sort_by_attribute('label_priority').limit(DISPLAY_ISSUES_LIMIT)
Issue
.where(id: Issue.select(:id).from(limited_ids))
.preload_associated_models
.sort_by_attribute('label_priority')
end
def sorted_merge_requests(user)
merge_requests_visible_to_user(user).sort_by_attribute('label_priority')
end
def merge_requests_visible_to_user(user)
memoize_per_user(user, :merge_requests_visible_to_user) do
MergeRequestsFinder.new(user, issues_finder_params)
.execute.where(milestone_id: milestoneish_id)
end
end
def upcoming?
start_date && start_date.future?
end
def expires_at
if due_date
if due_date.past?
"expired on #{due_date.to_s(:medium)}"
else
"expires on #{due_date.to_s(:medium)}"
end
end
end
def expired?
due_date && due_date.past?
end
def total_time_spent
@total_time_spent ||= issues.joins(:timelogs).sum(:time_spent) + merge_requests.joins(:timelogs).sum(:time_spent)
end
def human_total_time_spent
Gitlab::TimeTrackingFormatter.output(total_time_spent)
end
def total_time_estimate
@total_time_estimate ||= issues.sum(:time_estimate) + merge_requests.sum(:time_estimate)
end
def human_total_time_estimate
Gitlab::TimeTrackingFormatter.output(total_time_estimate)
end
private
def memoize_per_user(user, method_name)
memoized_users[method_name][user&.id] ||= yield
end
def memoized_users
@memoized_users ||= Hash.new { |h, k| h[k] = {} }
end
# override in a class that includes this module to get a faster query
# from IssuesFinder
def issues_finder_params
{}
end
end
|