Commit b84c7bd6 authored by Matthias Käppler's avatar Matthias Käppler

Merge branch '330839-allow-setting-timelog-summary' into 'master'

Support setting timelog summary via API

See merge request gitlab-org/gitlab!66793
parents 26b971c2 4cedb18c
...@@ -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