mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-08-16 17:13:01 +00:00
173 lines
5.4 KiB
Ruby
173 lines
5.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module SystemNotes
|
|
class TimeTrackingService < ::SystemNotes::BaseService
|
|
# Called when the start_date or due_date of an Issue/WorkItem is changed
|
|
#
|
|
# start_date - Start date being assigned, or nil
|
|
# due_date - Due date being assigned, or nil
|
|
#
|
|
# Example Note text:
|
|
#
|
|
# "removed due date"
|
|
#
|
|
# "changed due date to September 20, 2018"
|
|
|
|
# "changed start date to September 20, 2018 and changed due date to September 25, 2018"
|
|
#
|
|
# Returns the created Note object
|
|
def change_start_date_or_due_date(changed_dates = {})
|
|
return if changed_dates.empty?
|
|
|
|
# Using instance_of because WorkItem < Issue. We don't want to track work item updates as issue updates
|
|
if noteable.instance_of?(Issue) && changed_dates.key?('due_date')
|
|
issue_activity_counter.track_issue_due_date_changed_action(author: author, project: project)
|
|
end
|
|
|
|
work_item_activity_counter.track_work_item_date_changed_action(author: author) if noteable.is_a?(WorkItem)
|
|
|
|
create_note(
|
|
NoteSummary.new(noteable, project, author, changed_date_body(changed_dates), action: 'start_date_or_due_date')
|
|
)
|
|
end
|
|
|
|
# Called when the estimated time of a Noteable is changed
|
|
#
|
|
# time_estimate - Estimated time
|
|
#
|
|
# Example Note text:
|
|
#
|
|
# "removed time estimate"
|
|
#
|
|
# "changed time estimate to 3d 5h"
|
|
#
|
|
# Returns the created Note object
|
|
def change_time_estimate
|
|
if noteable.is_a?(Issue)
|
|
issue_activity_counter.track_issue_time_estimate_changed_action(author: author, project: project)
|
|
end
|
|
|
|
create_note(NoteSummary.new(noteable, project, author, time_estimate_system_note, action: 'time_tracking'))
|
|
end
|
|
|
|
# Called when the spent time of a Noteable is changed
|
|
#
|
|
# time_spent - Spent time
|
|
#
|
|
# Example Note text:
|
|
#
|
|
# "removed time spent"
|
|
#
|
|
# "added 2h 30m of time spent"
|
|
#
|
|
# Returns the created Note object
|
|
def change_time_spent
|
|
update_activity_counter
|
|
time_spent = noteable.time_spent
|
|
|
|
if time_spent == :reset
|
|
body = "removed time spent"
|
|
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
|
|
else
|
|
spent_at = noteable.spent_at
|
|
time_spent_note(time_spent, spent_at)
|
|
end
|
|
end
|
|
|
|
# Called when a timelog is added to an issuable
|
|
#
|
|
# timelog - Added timelog
|
|
#
|
|
# Example Note text:
|
|
#
|
|
# "subtracted 1h 15m of time spent"
|
|
#
|
|
# "added 2h 30m of time spent"
|
|
#
|
|
# Returns the created Note object
|
|
def created_timelog(timelog)
|
|
time_spent = timelog.time_spent
|
|
spent_at = timelog.spent_at
|
|
|
|
update_activity_counter
|
|
time_spent_note(time_spent, spent_at)
|
|
end
|
|
|
|
def remove_timelog(timelog)
|
|
time_spent = timelog.time_spent
|
|
spent_at = timelog.spent_at
|
|
|
|
parsed_time = Gitlab::TimeTrackingFormatter.output(time_spent)
|
|
|
|
body = "deleted #{parsed_time} of spent time from #{formatted_spent_at(spent_at)}"
|
|
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
|
|
end
|
|
|
|
private
|
|
|
|
def update_activity_counter
|
|
return unless noteable.is_a?(Issue)
|
|
|
|
issue_activity_counter.track_issue_time_spent_changed_action(author: author, project: project)
|
|
end
|
|
|
|
def formatted_spent_at(spent_at)
|
|
spent_at ||= DateTime.current
|
|
timezone = author.timezone
|
|
timezone = Time.zone.name if timezone.blank? || ActiveSupport::TimeZone[timezone].nil?
|
|
spent_at.in_time_zone(timezone)
|
|
end
|
|
|
|
def time_spent_note(time_spent, spent_at)
|
|
parsed_time = Gitlab::TimeTrackingFormatter.output(time_spent.abs)
|
|
action = time_spent > 0 ? 'added' : 'subtracted'
|
|
|
|
body = "#{action} #{parsed_time} of time spent at #{formatted_spent_at(spent_at)}"
|
|
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
|
|
end
|
|
|
|
def changed_date_body(changed_dates)
|
|
%w[start_date due_date].each_with_object([]) do |date_field, word_array|
|
|
next unless changed_dates.key?(date_field)
|
|
|
|
word_array << 'and' if word_array.any?
|
|
|
|
word_array << message_for_changed_date(changed_dates, date_field)
|
|
end.join(' ')
|
|
end
|
|
|
|
def message_for_changed_date(changed_dates, date_key)
|
|
changed_date = changed_dates[date_key].last
|
|
readable_date = date_key.humanize.downcase
|
|
|
|
if changed_date.nil?
|
|
"removed #{readable_date} #{changed_dates[date_key].first.to_fs(:long)}"
|
|
else
|
|
"changed #{readable_date} to #{changed_date.to_fs(:long)}"
|
|
end
|
|
end
|
|
|
|
def issue_activity_counter
|
|
Gitlab::UsageDataCounters::IssueActivityUniqueCounter
|
|
end
|
|
|
|
def work_item_activity_counter
|
|
Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter
|
|
end
|
|
|
|
def time_estimate_system_note
|
|
parsed_time = Gitlab::TimeTrackingFormatter.output(noteable.time_estimate)
|
|
previous_estimate = noteable.previous_changes['time_estimate']&.at(0) || 0
|
|
parsed_previous_estimate = Gitlab::TimeTrackingFormatter.output(previous_estimate)
|
|
|
|
if previous_estimate == 0
|
|
"added time estimate of #{parsed_time}"
|
|
elsif noteable.time_estimate == 0
|
|
"removed time estimate of #{parsed_previous_estimate}"
|
|
else
|
|
"changed time estimate to #{parsed_time} from #{parsed_previous_estimate}"
|
|
end
|
|
end
|
|
end
|
|
end
|