Class: Todo
Constant Summary
collapse
- WAIT_FOR_DELETE =
Time to wait for todos being removed when not visible for user anymore. Prevents TODOs being removed by mistake, for example, removing access from a user and giving it back again.
1.hour
- ASSIGNED =
1
- MENTIONED =
2
- BUILD_FAILED =
3
- MARKED =
4
- APPROVAL_REQUIRED =
This is an EE-only feature
5
- UNMERGEABLE =
6
- DIRECTLY_ADDRESSED =
7
- MERGE_TRAIN_REMOVED =
This is an EE-only feature
8
- REVIEW_REQUESTED =
9
- MEMBER_ACCESS_REQUESTED =
10
- REVIEW_SUBMITTED =
This is an EE-only feature
11
- ACTION_NAMES =
{
ASSIGNED => :assigned,
REVIEW_REQUESTED => :review_requested,
MENTIONED => :mentioned,
BUILD_FAILED => :build_failed,
MARKED => :marked,
APPROVAL_REQUIRED => :approval_required,
UNMERGEABLE => :unmergeable,
DIRECTLY_ADDRESSED => :directly_addressed,
MERGE_TRAIN_REMOVED => :merge_train_removed,
MEMBER_ACCESS_REQUESTED => :member_access_requested,
REVIEW_SUBMITTED => :review_submitted
}.freeze
- ACTIONS_MULTIPLE_ALLOWED =
[Todo::MENTIONED, Todo::DIRECTLY_ADDRESSED, Todo::MEMBER_ACCESS_REQUESTED].freeze
ApplicationRecord::MAX_PLUCK
ResetOnUnionError::MAX_RESET_PERIOD
Class Method Summary
collapse
Instance Method Summary
collapse
cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order
#serializable_hash
Class Method Details
.any_for_target?(target, state = nil) ⇒ Boolean
Returns ‘true` if the current user has any todos for the given target with the optional given state.
target - The value of the ‘target_type` column, such as `Issue`. state - The value of the `state` column, such as `pending` or `done`.
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
# File 'app/models/todo.rb', line 121
def any_for_target?(target, state = nil)
conditions = {}
if target.respond_to?(:todoable_target_type_name)
conditions[:target_type] = target.todoable_target_type_name
conditions[:target_id] = target.id
else
conditions[:target] = target
end
conditions[:state] = state unless state.nil?
exists?(conditions)
end
|
.batch_update(**new_attributes) ⇒ Object
Updates attributes of a relation of todos to the new state.
new_attributes - The new attributes of the todos.
Returns an ‘Array` containing the IDs of the updated todos.
141
142
143
144
145
146
147
148
149
|
# File 'app/models/todo.rb', line 141
def batch_update(**new_attributes)
base = where.not(state: new_attributes[:state]).except(:order)
ids = base.pluck(:id)
base.update_all(new_attributes.merge(updated_at: Time.current))
ids
end
|
.count_grouped_by_user_id_and_state ⇒ Object
Count todos grouped by user_id and state, using an UNION query so we can utilize the partial indexes for each state.
186
187
188
189
190
191
192
193
194
195
196
197
|
# File 'app/models/todo.rb', line 186
def count_grouped_by_user_id_and_state
grouped_count = select(:user_id, 'count(id) AS count').group(:user_id)
done = grouped_count.where(state: :done).select("'done' AS state")
pending = grouped_count.where(state: :pending).select("'pending' AS state")
union = unscoped.from_union([done, pending], remove_duplicates: false)
.select(:user_id, :count, :state)
connection.select_all(union).each_with_object({}) do |row, counts|
counts[[row['user_id'], row['state']]] = row['count']
end
end
|
.distinct_user_ids ⇒ Object
180
181
182
|
# File 'app/models/todo.rb', line 180
def distinct_user_ids
distinct.pluck(:user_id)
end
|
.for_group_ids_and_descendants(group_ids) ⇒ Object
Returns all todos for the given group ids and their descendants.
group_ids - Group Ids to retrieve todos for.
Returns an ‘ActiveRecord::Relation`.
107
108
109
110
111
112
113
114
115
|
# File 'app/models/todo.rb', line 107
def for_group_ids_and_descendants(group_ids)
groups = Group.where(id: group_ids).self_and_descendants
from_union(
[
for_project(Project.for_group(groups)),
for_group(groups)
])
end
|
.order_by_labels_priority ⇒ Object
Order by priority depending on which issue/merge request the Todo belongs to Todos with highest priority first then oldest todos Need to order by created_at last because of differences on Mysql and Postgres when joining by type “Merge_request/Issue”
168
169
170
171
172
173
174
175
176
177
178
|
# File 'app/models/todo.rb', line 168
def order_by_labels_priority
highest_priority = highest_label_priority(
target_type_column: "todos.target_type",
target_column: "todos.target_id",
project_column: "todos.project_id"
).arel.as('highest_priority')
select(arel_table[Arel.star], highest_priority)
.order(Arel.sql('highest_priority').asc.nulls_last)
.order('todos.created_at')
end
|
.sort_by_attribute(method) ⇒ Object
Priority sorting isn’t displayed in the dropdown, because we don’t show milestones, but still show something if the user has a URL with that selected.
154
155
156
157
158
159
160
161
162
163
|
# File 'app/models/todo.rb', line 154
def sort_by_attribute(method)
sorted =
case method.to_s
when 'priority', 'label_priority' then order_by_labels_priority
else order_by(method)
end
sorted.order(id: :desc)
end
|
Instance Method Details
#access_request_url(only_path: false) ⇒ Object
236
237
238
239
240
241
242
243
244
|
# File 'app/models/todo.rb', line 236
def access_request_url(only_path: false)
if target.instance_of? Group
Gitlab::Routing.url_helpers.group_group_members_url(self.target, tab: 'access_requests', only_path: only_path)
elsif target.instance_of? Project
Gitlab::Routing.url_helpers.project_project_members_url(self.target, tab: 'access_requests', only_path: only_path)
else
""
end
end
|
#action_name ⇒ Object
250
251
252
|
# File 'app/models/todo.rb', line 250
def action_name
ACTION_NAMES[action]
end
|
#assigned? ⇒ Boolean
212
213
214
|
# File 'app/models/todo.rb', line 212
def assigned?
action == ASSIGNED
end
|
#body ⇒ Object
254
255
256
257
258
259
260
261
262
|
# File 'app/models/todo.rb', line 254
def body
if note.present?
note.note
elsif member_access_requested?
target.full_path
else
target.title
end
end
|
#build_failed? ⇒ Boolean
208
209
210
|
# File 'app/models/todo.rb', line 208
def build_failed?
action == BUILD_FAILED
end
|
#done? ⇒ Boolean
246
247
248
|
# File 'app/models/todo.rb', line 246
def done?
state == 'done'
end
|
#for_alert? ⇒ Boolean
272
273
274
|
# File 'app/models/todo.rb', line 272
def for_alert?
target_type == AlertManagement::Alert.name
end
|
#for_commit? ⇒ Boolean
264
265
266
|
# File 'app/models/todo.rb', line 264
def for_commit?
target_type == "Commit"
end
|
#for_design? ⇒ Boolean
268
269
270
|
# File 'app/models/todo.rb', line 268
def for_design?
target_type == DesignManagement::Design.name
end
|
#for_issue_or_work_item? ⇒ Boolean
276
277
278
|
# File 'app/models/todo.rb', line 276
def for_issue_or_work_item?
[Issue.name, WorkItem.name].any?(target_type)
end
|
#member_access_requested? ⇒ Boolean
224
225
226
|
# File 'app/models/todo.rb', line 224
def member_access_requested?
action == MEMBER_ACCESS_REQUESTED
end
|
#member_access_type ⇒ Object
232
233
234
|
# File 'app/models/todo.rb', line 232
def member_access_type
target.class.name.downcase
end
|
#merge_train_removed? ⇒ Boolean
220
221
222
|
# File 'app/models/todo.rb', line 220
def merge_train_removed?
action == MERGE_TRAIN_REMOVED
end
|
#resource_parent ⇒ Object
200
201
202
|
# File 'app/models/todo.rb', line 200
def resource_parent
project || group
end
|
#review_requested? ⇒ Boolean
216
217
218
|
# File 'app/models/todo.rb', line 216
def review_requested?
action == REVIEW_REQUESTED
end
|
#review_submitted? ⇒ Boolean
228
229
230
|
# File 'app/models/todo.rb', line 228
def review_submitted?
action == REVIEW_SUBMITTED
end
|
#self_added? ⇒ Boolean
303
304
305
|
# File 'app/models/todo.rb', line 303
def self_added?
author == user
end
|
#self_assigned? ⇒ Boolean
307
308
309
|
# File 'app/models/todo.rb', line 307
def self_assigned?
self_added? && (assigned? || review_requested?)
end
|
#target ⇒ Object
override to return commits, which are not active record
281
282
283
284
285
286
287
288
289
290
291
|
# File 'app/models/todo.rb', line 281
def target
if for_commit?
begin
project.commit(commit_id)
rescue StandardError
nil
end
else
super
end
end
|
#target_reference ⇒ Object
293
294
295
296
297
298
299
300
301
|
# File 'app/models/todo.rb', line 293
def target_reference
if for_commit?
target.reference_link_text
elsif member_access_requested?
target.full_path
else
target.to_reference
end
end
|
#unmergeable? ⇒ Boolean
204
205
206
|
# File 'app/models/todo.rb', line 204
def unmergeable?
action == UNMERGEABLE
end
|