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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
# frozen_string_literal: true
module API
module TimeTrackingEndpoints
extend ActiveSupport::Concern
included do
helpers do
def issuable_name
declared_params.key?(:issue_iid) ? 'issue' : 'merge_request'
end
def issuable_key
"#{issuable_name}_iid".to_sym
end
def admin_issuable_key
"admin_#{issuable_name}".to_sym
end
def read_issuable_key
"read_#{issuable_name}".to_sym
end
def load_issuable
@issuable ||= case issuable_name
when 'issue'
find_project_issue(params.delete(issuable_key))
when 'merge_request'
find_project_merge_request(params.delete(issuable_key))
end
end
def update_issuable(attrs)
custom_params = declared_params(include_missing: false)
custom_params.merge!(attrs)
issuable = update_service.new(**update_service.constructor_container_arg(user_project),
current_user: current_user, params: custom_params).execute(load_issuable)
if issuable.valid?
present issuable, with: Entities::IssuableTimeStats
else
render_validation_error!(issuable)
end
end
def update_service
issuable_name == 'issue' ? ::Issues::UpdateService : ::MergeRequests::UpdateService
end
end
issuable_name = name.end_with?('Issues') ? 'issue' : 'merge_request'
issuable_collection_name = issuable_name.pluralize
issuable_key = "#{issuable_name}_iid".to_sym
desc "Set a time estimate for a #{issuable_name}" do
detail "Sets an estimated time of work for this #{issuable_name}."
success Entities::IssuableTimeStats
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 400, message: 'Bad request' },
{ code: 404, message: 'Not found' }
]
tags [issuable_collection_name]
end
params do
requires issuable_key, type: Integer, desc: "The internal ID of the #{issuable_name}."
requires :duration, type: String, desc: 'The duration in human format.', documentation: { example: '3h30m' }
end
post ":id/#{issuable_collection_name}/:#{issuable_key}/time_estimate" do
authorize! admin_issuable_key, load_issuable
time_estimate = Gitlab::TimeTrackingFormatter.parse(params.delete(:duration), keep_zero: true)
if time_estimate && time_estimate >= 0
status :ok
update_issuable(time_estimate: time_estimate)
else
bad_request!(reason: 'Time estimate must have a valid format and be greater than or equal to zero.')
end
end
desc "Reset the time estimate for a project #{issuable_name}" do
detail "Resets the estimated time for this #{issuable_name} to 0 seconds."
success Entities::IssuableTimeStats
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' }
]
tags [issuable_collection_name]
end
params do
requires issuable_key, type: Integer, desc: "The internal ID of the #{issuable_name}."
end
post ":id/#{issuable_collection_name}/:#{issuable_key}/reset_time_estimate" do
authorize! admin_issuable_key, load_issuable
status :ok
update_issuable(time_estimate: 0)
end
desc "Add spent time for a #{issuable_name}" do
detail "Adds spent time for this #{issuable_name}."
success Entities::IssuableTimeStats
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' }
]
tags [issuable_collection_name]
end
params do
requires issuable_key, type: Integer, desc: "The internal ID of the #{issuable_name}."
requires :duration, type: String, desc: 'The duration in human format.'
end
post ":id/#{issuable_collection_name}/:#{issuable_key}/add_spent_time" do
authorize! admin_issuable_key, load_issuable
update_params = {
spend_time: {
duration: Gitlab::TimeTrackingFormatter.parse(params.delete(:duration)),
summary: params.delete(:summary),
user_id: current_user.id
}
}
update_params[:use_specialized_service] = true if issuable_name == 'merge_request'
update_issuable(update_params)
end
desc "Reset spent time for a #{issuable_name}" do
detail "Resets the total spent time for this #{issuable_name} to 0 seconds."
success Entities::IssuableTimeStats
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' }
]
tags [issuable_collection_name]
end
params do
requires issuable_key, type: Integer, desc: "The internal ID of the #{issuable_name}"
end
post ":id/#{issuable_collection_name}/:#{issuable_key}/reset_spent_time" do
authorize! admin_issuable_key, load_issuable
status :ok
update_issuable(spend_time: { duration: :reset, user_id: current_user.id })
end
desc "Get time tracking stats" do
detail "Get time tracking stats"
success Entities::IssuableTimeStats
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' }
]
tags [issuable_collection_name]
end
params do
requires issuable_key, type: Integer, desc: "The internal ID of the #{issuable_name}"
end
get ":id/#{issuable_collection_name}/:#{issuable_key}/time_stats" do
authorize! read_issuable_key, load_issuable
present load_issuable, with: Entities::IssuableTimeStats
end
end
end
end
|