Skip to content
Snippets Groups Projects
Commit 945e0684 authored by Vlad's avatar Vlad Committed by Sean McGivern
Browse files

added date parameter for time tracking

parent 5843a43c
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -9,7 +9,7 @@ module TimeTrackable
extend ActiveSupport::Concern
 
included do
attr_reader :time_spent, :time_spent_user
attr_reader :time_spent, :time_spent_user, :spent_at
 
alias_method :time_spent?, :time_spent
 
Loading
Loading
@@ -24,6 +24,7 @@ module TimeTrackable
def spend_time(options)
@time_spent = options[:duration]
@time_spent_user = options[:user]
@spent_at = options[:spent_at]
@original_total_time_spent = nil
 
return if @time_spent == 0
Loading
Loading
@@ -55,7 +56,11 @@ module TimeTrackable
end
 
def add_or_subtract_spent_time
timelogs.new(time_spent: time_spent, user: @time_spent_user)
timelogs.new(
time_spent: time_spent,
user: @time_spent_user,
spent_at: @spent_at
)
end
 
def check_negative_time_spent
Loading
Loading
Loading
Loading
@@ -381,7 +381,7 @@ module QuickActions
end
 
desc 'Add or substract spent time'
explanation do |time_spent|
explanation do |time_spent, time_spent_date|
if time_spent
if time_spent > 0
verb = 'Adds'
Loading
Loading
@@ -394,16 +394,20 @@ module QuickActions
"#{verb} #{Gitlab::TimeTrackingFormatter.output(value)} spent time."
end
end
params '<1h 30m | -1h 30m>'
params '<time(1h30m | -1h30m)> <date(YYYY-MM-DD)>'
condition do
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
parse_params do |raw_duration|
Gitlab::TimeTrackingFormatter.parse(raw_duration)
parse_params do |raw_time_date|
Gitlab::QuickActions::SpendTimeAndDateSeparator.new(raw_time_date).execute
end
command :spend do |time_spent|
command :spend do |time_spent, time_spent_date|
if time_spent
@updates[:spend_time] = { duration: time_spent, user: current_user }
@updates[:spend_time] = {
duration: time_spent,
user: current_user,
spent_at: time_spent_date
}
end
end
 
Loading
Loading
Loading
Loading
@@ -195,9 +195,11 @@ module SystemNoteService
if time_spent == :reset
body = "removed time spent"
else
spent_at = noteable.spent_at
parsed_time = Gitlab::TimeTrackingFormatter.output(time_spent.abs)
action = time_spent > 0 ? 'added' : 'subtracted'
body = "#{action} #{parsed_time} of time spent"
body << " at #{spent_at}" if spent_at
end
 
create_note(NoteSummary.new(noteable, project, author, body, action: 'time_tracking'))
Loading
Loading
---
title: Added possibility to enter past date in /spend command to log time in the past
merge_request: 3044
author: g3dinua, LockiStrike
type: changed
class AddSpentAtToTimelogs < ActiveRecord::Migration
DOWNTIME = false
def up
add_column :timelogs, :spent_at, :datetime_with_timezone
end
def down
remove_column :timelogs, :spent_at
end
end
Loading
Loading
@@ -1550,6 +1550,7 @@ ActiveRecord::Schema.define(version: 20171006091000) do
t.datetime "updated_at", null: false
t.integer "issue_id"
t.integer "merge_request_id"
t.datetime_with_timezone "spent_at"
end
 
add_index "timelogs", ["issue_id"], name: "index_timelogs_on_issue_id", using: :btree
Loading
Loading
Loading
Loading
@@ -32,7 +32,7 @@ do.
| `/wip` | Toggle the Work In Progress status |
| <code>/estimate &lt;1w 3d 2h 14m&gt;</code> | Set time estimate |
| `/remove_estimate` | Remove estimated time |
| <code>/spend &lt;1h 30m &#124; -1h 5m&gt;</code> | Add or subtract spent time |
| <code>/spend &lt;time(1h 30m &#124; -1h 5m)&gt; &lt;date(YYYY-MM-DD)&gt;</code> | Add or subtract spent time; optionally, specify the date that time was spent on |
| `/remove_time_spent` | Remove time spent |
| `/target_branch <Branch Name>` | Set target branch for current merge request |
| `/award :emoji:` | Toggle award for :emoji: |
Loading
Loading
module Gitlab
module QuickActions
# This class takes spend command argument
# and separates date and time from spend command arguments if it present
# example:
# spend_command_time_and_date = "15m 2017-01-02"
# SpendTimeAndDateSeparator.new(spend_command_time_and_date).execute
# => [900, Mon, 02 Jan 2017]
# if date doesn't present return time with current date
# in other cases return nil
class SpendTimeAndDateSeparator
DATE_REGEX = /(\d{2,4}[\/\-.]\d{1,2}[\/\-.]\d{1,2})/
def initialize(spend_command_arg)
@spend_arg = spend_command_arg
end
def execute
return if @spend_arg.blank?
return [get_time, DateTime.now.to_date] unless date_present?
return unless valid_date?
[get_time, get_date]
end
private
def get_time
raw_time = @spend_arg.gsub(DATE_REGEX, '')
Gitlab::TimeTrackingFormatter.parse(raw_time)
end
def get_date
string_date = @spend_arg.match(DATE_REGEX)[0]
Date.parse(string_date)
end
def date_present?
DATE_REGEX =~ @spend_arg
end
def valid_date?
string_date = @spend_arg.match(DATE_REGEX)[0]
date = Date.parse(string_date) rescue nil
date_past_or_today?(date)
end
def date_past_or_today?(date)
date&.past? || date&.today?
end
end
end
end
Loading
Loading
@@ -496,6 +496,7 @@ Timelog:
- merge_request_id
- issue_id
- user_id
- spent_at
- created_at
- updated_at
ProjectAutoDevops:
Loading
Loading
require 'spec_helper'
describe Gitlab::QuickActions::SpendTimeAndDateSeparator do
subject { described_class }
shared_examples 'arg line with invalid parameters' do
it 'return nil' do
expect(subject.new(invalid_arg).execute).to eq(nil)
end
end
shared_examples 'arg line with valid parameters' do
it 'return time and date array' do
expect(subject.new(valid_arg).execute).to eq(expected_response)
end
end
describe '#execute' do
context 'invalid paramenter in arg line' do
context 'empty arg line' do
it_behaves_like 'arg line with invalid parameters' do
let(:invalid_arg) { '' }
end
end
context 'future date in arg line' do
it_behaves_like 'arg line with invalid parameters' do
let(:invalid_arg) { '10m 6023-02-02' }
end
end
context 'unparseable date(invalid mixes of delimiters)' do
it_behaves_like 'arg line with invalid parameters' do
let(:invalid_arg) { '10m 2017.02-02' }
end
end
context 'trash in arg line' do
let(:invalid_arg) { 'dfjkghdskjfghdjskfgdfg' }
it 'return nil as time value' do
time_date_response = subject.new(invalid_arg).execute
expect(time_date_response).to be_an_instance_of(Array)
expect(time_date_response.first).to eq(nil)
end
end
end
context 'only time present in arg line' do
it_behaves_like 'arg line with valid parameters' do
let(:valid_arg) { '2m 3m 5m 1h' }
let(:time) { Gitlab::TimeTrackingFormatter.parse(valid_arg) }
let(:date) { DateTime.now.to_date }
let(:expected_response) { [time, date] }
end
end
context 'simple time with date in arg line' do
it_behaves_like 'arg line with valid parameters' do
let(:raw_time) { '10m' }
let(:raw_date) { '2016-02-02' }
let(:valid_arg) { "#{raw_time} #{raw_date}" }
let(:date) { Date.parse(raw_date) }
let(:time) { Gitlab::TimeTrackingFormatter.parse(raw_time) }
let(:expected_response) { [time, date] }
end
end
context 'composite time with date in arg line' do
it_behaves_like 'arg line with valid parameters' do
let(:raw_time) { '2m 10m 1h 3d' }
let(:raw_date) { '2016/02/02' }
let(:valid_arg) { "#{raw_time} #{raw_date}" }
let(:date) { Date.parse(raw_date) }
let(:time) { Gitlab::TimeTrackingFormatter.parse(raw_time) }
let(:expected_response) { [time, date] }
end
end
end
end
Loading
Loading
@@ -207,7 +207,11 @@ describe QuickActions::InterpretService do
it 'populates spend_time: 3600 if content contains /spend 1h' do
_, updates = service.execute(content, issuable)
 
expect(updates).to eq(spend_time: { duration: 3600, user: developer })
expect(updates).to eq(spend_time: {
duration: 3600,
user: developer,
spent_at: DateTime.now.to_date
})
end
end
 
Loading
Loading
@@ -215,7 +219,39 @@ describe QuickActions::InterpretService do
it 'populates spend_time: -1800 if content contains /spend -30m' do
_, updates = service.execute(content, issuable)
 
expect(updates).to eq(spend_time: { duration: -1800, user: developer })
expect(updates).to eq(spend_time: {
duration: -1800,
user: developer,
spent_at: DateTime.now.to_date
})
end
end
shared_examples 'spend command with valid date' do
it 'populates spend time: 1800 with date in date type format' do
_, updates = service.execute(content, issuable)
expect(updates).to eq(spend_time: {
duration: 1800,
user: developer,
spent_at: Date.parse(date)
})
end
end
shared_examples 'spend command with invalid date' do
it 'will not create any note and timelog' do
_, updates = service.execute(content, issuable)
expect(updates).to eq({})
end
end
shared_examples 'spend command with future date' do
it 'will not create any note and timelog' do
_, updates = service.execute(content, issuable)
expect(updates).to eq({})
end
end
 
Loading
Loading
@@ -669,6 +705,22 @@ describe QuickActions::InterpretService do
let(:issuable) { issue }
end
 
it_behaves_like 'spend command with valid date' do
let(:date) { '2016-02-02' }
let(:content) { "/spend 30m #{date}" }
let(:issuable) { issue }
end
it_behaves_like 'spend command with invalid date' do
let(:content) { '/spend 30m 17-99-99' }
let(:issuable) { issue }
end
it_behaves_like 'spend command with future date' do
let(:content) { '/spend 30m 6017-10-10' }
let(:issuable) { issue }
end
it_behaves_like 'empty command' do
let(:content) { '/spend' }
let(:issuable) { issue }
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment