Commit 4cedb18c authored by Lee Tickett's avatar Lee Tickett Committed by Matthias Käppler

Support setting timelog summary via API

We recentlly added the timelogs.summary column, but don't currently
have any mechanmic to populate it. This MR introduces a way to
populate via the API.

Changelog: added
parent 26b971c2
...@@ -11,7 +11,7 @@ module TimeTrackable ...@@ -11,7 +11,7 @@ module TimeTrackable
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
attr_reader :time_spent, :time_spent_user, :spent_at attr_reader :time_spent, :time_spent_user, :spent_at, :summary
alias_method :time_spent?, :time_spent alias_method :time_spent?, :time_spent
...@@ -29,6 +29,7 @@ module TimeTrackable ...@@ -29,6 +29,7 @@ module TimeTrackable
@time_spent_note_id = options[:note_id] @time_spent_note_id = options[:note_id]
@time_spent_user = User.find(options[:user_id]) @time_spent_user = User.find(options[:user_id])
@spent_at = options[:spent_at] @spent_at = options[:spent_at]
@summary = options[:summary]
@original_total_time_spent = nil @original_total_time_spent = nil
return if @time_spent == 0 return if @time_spent == 0
...@@ -78,7 +79,8 @@ module TimeTrackable ...@@ -78,7 +79,8 @@ module TimeTrackable
time_spent: time_spent, time_spent: time_spent,
note_id: @time_spent_note_id, note_id: @time_spent_note_id,
user: @time_spent_user, user: @time_spent_user,
spent_at: @spent_at spent_at: @spent_at,
summary: @summary
) )
end end
# rubocop:enable Gitlab/ModuleWithInstanceVariables # rubocop:enable Gitlab/ModuleWithInstanceVariables
......
...@@ -1950,6 +1950,7 @@ POST /projects/:id/issues/:issue_iid/add_spent_time ...@@ -1950,6 +1950,7 @@ POST /projects/:id/issues/:issue_iid/add_spent_time
| `duration` | string | yes | The duration in human format. e.g: 3h30m | | `duration` | string | yes | The duration in human format. e.g: 3h30m |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `issue_iid` | integer | yes | The internal ID of a project's issue | | `issue_iid` | integer | yes | The internal ID of a project's issue |
| `summary` | string | no | A summary of how the time was spent |
```shell ```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/93/add_spent_time?duration=1h" curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/93/add_spent_time?duration=1h"
......
...@@ -2538,6 +2538,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time ...@@ -2538,6 +2538,7 @@ POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `merge_request_iid` | integer | yes | The internal ID of the merge request. | | `merge_request_iid` | integer | yes | The internal ID of the merge request. |
| `duration` | string | yes | The duration in human format, such as `3h30m` | | `duration` | string | yes | The duration in human format, such as `3h30m` |
| `summary` | string | no | A summary of how the time was spent. |
```shell ```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h" curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h"
......
...@@ -88,6 +88,7 @@ module API ...@@ -88,6 +88,7 @@ module API
update_params = { update_params = {
spend_time: { spend_time: {
duration: Gitlab::TimeTrackingFormatter.parse(params.delete(:duration)), duration: Gitlab::TimeTrackingFormatter.parse(params.delete(:duration)),
summary: params.delete(:summary),
user_id: current_user.id user_id: current_user.id
} }
} }
......
...@@ -8,7 +8,7 @@ RSpec.describe MergeRequests::AddSpentTimeService do ...@@ -8,7 +8,7 @@ RSpec.describe MergeRequests::AddSpentTimeService do
let_it_be_with_reload(:merge_request) { create(:merge_request, :simple, :unique_branches, source_project: project) } let_it_be_with_reload(:merge_request) { create(:merge_request, :simple, :unique_branches, source_project: project) }
let(:duration) { 1500 } let(:duration) { 1500 }
let(:params) { { spend_time: { duration: duration, user_id: user.id } } } let(:params) { { spend_time: { duration: duration, summary: 'summary', user_id: user.id } } }
let(:service) { described_class.new(project: project, current_user: user, params: params) } let(:service) { described_class.new(project: project, current_user: user, params: params) }
describe '#execute' do describe '#execute' do
...@@ -16,13 +16,14 @@ RSpec.describe MergeRequests::AddSpentTimeService do ...@@ -16,13 +16,14 @@ RSpec.describe MergeRequests::AddSpentTimeService do
project.add_developer(user) project.add_developer(user)
end end
it 'creates a new timelog with the specified duration' do it 'creates a new timelog with the specified duration and summary' do
expect { service.execute(merge_request) }.to change { Timelog.count }.from(0).to(1) expect { service.execute(merge_request) }.to change { Timelog.count }.from(0).to(1)
timelog = merge_request.timelogs.last timelog = merge_request.timelogs.last
expect(timelog).not_to be_nil expect(timelog).not_to be_nil
expect(timelog.time_spent).to eq(1500) expect(timelog.time_spent).to eq(1500)
expect(timelog.summary).to eq('summary')
end end
it 'creates a system note with the time added' do it 'creates a system note with the time added' do
......
...@@ -128,17 +128,25 @@ RSpec.shared_examples 'time tracking endpoints' do |issuable_name| ...@@ -128,17 +128,25 @@ RSpec.shared_examples 'time tracking endpoints' do |issuable_name|
if issuable_name == 'merge_request' if issuable_name == 'merge_request'
it 'calls update service with :use_specialized_service param' do it 'calls update service with :use_specialized_service param' do
expect(::MergeRequests::UpdateService).to receive(:new).with(project: project, current_user: user, params: hash_including(use_specialized_service: true)) expect(::MergeRequests::UpdateService).to receive(:new).with(
project: project,
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '2h' } current_user: user,
params: hash_including(
use_specialized_service: true,
spend_time: hash_including(duration: 7200, summary: 'summary')))
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '2h', summary: 'summary' }
end end
end end
if issuable_name == 'issue' if issuable_name == 'issue'
it 'calls update service without :use_specialized_service param' do it 'calls update service without :use_specialized_service param' do
expect(::Issues::UpdateService).to receive(:new).with(project: project, current_user: user, params: hash_not_including(use_specialized_service: true)) expect(::Issues::UpdateService).to receive(:new).with(
project: project,
current_user: user,
params: { spend_time: { duration: 3600, summary: 'summary', user_id: user.id } })
post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '2h' } post api("/projects/#{project.id}/#{issuable_collection_name}/#{issuable.iid}/add_spent_time", user), params: { duration: '1h', summary: 'summary' }
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment