tempest_time 0.7.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +7 -1
  3. data/.rubocop_airbnb.yml +3 -0
  4. data/CONTRIBUTING.md +6 -0
  5. data/Gemfile +1 -1
  6. data/README.md +44 -5
  7. data/bin/tempest +1 -1
  8. data/lib/tempest_time/api/authorization.rb +3 -1
  9. data/lib/tempest_time/api/jira_api/authorization.rb +2 -0
  10. data/lib/tempest_time/api/jira_api/models/issue.rb +9 -5
  11. data/lib/tempest_time/api/jira_api/request.rb +3 -1
  12. data/lib/tempest_time/api/jira_api/requests/get_current_user.rb +0 -1
  13. data/lib/tempest_time/api/jira_api/requests/get_issue.rb +1 -1
  14. data/lib/tempest_time/api/jira_api/requests/get_user_issues.rb +3 -3
  15. data/lib/tempest_time/api/jira_api/response.rb +3 -1
  16. data/lib/tempest_time/api/jira_api/responses/get_current_user.rb +0 -1
  17. data/lib/tempest_time/api/jira_api/responses/get_issue.rb +1 -1
  18. data/lib/tempest_time/api/jira_api/responses/get_user_issues.rb +1 -1
  19. data/lib/tempest_time/api/request.rb +3 -3
  20. data/lib/tempest_time/api/response.rb +3 -1
  21. data/lib/tempest_time/api/tempo_api/models/worklog.rb +1 -1
  22. data/lib/tempest_time/api/tempo_api/request.rb +1 -1
  23. data/lib/tempest_time/api/tempo_api/requests/create_worklog.rb +2 -2
  24. data/lib/tempest_time/api/tempo_api/requests/delete_worklog.rb +1 -1
  25. data/lib/tempest_time/api/tempo_api/requests/get_worklog.rb +1 -1
  26. data/lib/tempest_time/api/tempo_api/requests/list_worklogs.rb +2 -3
  27. data/lib/tempest_time/api/tempo_api/requests/submit_timesheet.rb +3 -3
  28. data/lib/tempest_time/api/tempo_api/response.rb +1 -1
  29. data/lib/tempest_time/api/tempo_api/responses/create_worklog.rb +1 -1
  30. data/lib/tempest_time/api/tempo_api/responses/delete_worklog.rb +1 -1
  31. data/lib/tempest_time/api/tempo_api/responses/get_worklog.rb +4 -2
  32. data/lib/tempest_time/api/tempo_api/responses/list_worklogs.rb +4 -6
  33. data/lib/tempest_time/api/tempo_api/responses/submit_timesheet.rb +1 -1
  34. data/lib/tempest_time/cli.rb +5 -2
  35. data/lib/tempest_time/command.rb +13 -6
  36. data/lib/tempest_time/commands/config.rb +0 -1
  37. data/lib/tempest_time/commands/config/edit.rb +1 -1
  38. data/lib/tempest_time/commands/config/setup.rb +2 -3
  39. data/lib/tempest_time/commands/delete.rb +1 -1
  40. data/lib/tempest_time/commands/issue.rb +0 -1
  41. data/lib/tempest_time/commands/issue/list.rb +4 -4
  42. data/lib/tempest_time/commands/issue/open.rb +2 -2
  43. data/lib/tempest_time/commands/list.rb +5 -5
  44. data/lib/tempest_time/commands/report.rb +13 -10
  45. data/lib/tempest_time/commands/submit.rb +2 -2
  46. data/lib/tempest_time/commands/teams.rb +0 -1
  47. data/lib/tempest_time/commands/teams/add.rb +2 -2
  48. data/lib/tempest_time/commands/teams/delete.rb +2 -2
  49. data/lib/tempest_time/commands/teams/edit.rb +2 -2
  50. data/lib/tempest_time/commands/timer.rb +0 -1
  51. data/lib/tempest_time/commands/timer/delete.rb +1 -1
  52. data/lib/tempest_time/commands/timer/list.rb +3 -3
  53. data/lib/tempest_time/commands/timer/pause.rb +2 -2
  54. data/lib/tempest_time/commands/timer/start.rb +1 -1
  55. data/lib/tempest_time/commands/timer/status.rb +1 -1
  56. data/lib/tempest_time/commands/timer/track.rb +1 -1
  57. data/lib/tempest_time/commands/track.rb +12 -15
  58. data/lib/tempest_time/helpers/formatting_helper.rb +1 -1
  59. data/lib/tempest_time/helpers/git_helper.rb +1 -1
  60. data/lib/tempest_time/helpers/time_helper.rb +1 -1
  61. data/lib/tempest_time/models/report.rb +7 -6
  62. data/lib/tempest_time/models/timer.rb +3 -3
  63. data/lib/tempest_time/setting.rb +1 -1
  64. data/lib/tempest_time/settings/app.rb +1 -1
  65. data/lib/tempest_time/settings/authorization.rb +1 -1
  66. data/lib/tempest_time/settings/teams.rb +1 -1
  67. data/lib/tempest_time/version.rb +1 -1
  68. data/tempest_time.gemspec +4 -4
  69. metadata +18 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e9063e95fed5afa9e1fc6737a7411ef662ce7d67468dad0d7aa755d5c95e0fe2
4
- data.tar.gz: d2553e4623e3f70881b082f74fc506b50bf219dc6fe28ab59918b34614330439
3
+ metadata.gz: 19ecc90a766883eb5563c29111a30ffc3bd5c2fcaf13e549894af2b94c68fafc
4
+ data.tar.gz: 40db9b3ab1cadc3e01ae3ee324c0a0cb0bbb5a2cb9955907c6e6feef97e40a09
5
5
  SHA512:
6
- metadata.gz: f1d085090a5274bd8a65db7b23a33f4ce9703ce530586b177f14b0759391565a88deb2c2a414f36e9b5643757657544acafc37083e91226c879dcc915509a8a8
7
- data.tar.gz: 833ed9330dacef6e846de522985fc06e6b31b11bb517ff9d040c2774b024f1a3a9f60e12f6fd9c8ce89fb831a31d94d1372e1427e8a3cb59c7f83456fd8a066e
6
+ metadata.gz: 1daa51c89fb224a118379a213d4ad99a5102e628985f8095a6574b439c9d759f18e9b6699895da7fe1fb9a374b97b3b0acc0215dcfdac7df22af991fd2480472
7
+ data.tar.gz: 477bd2d18f6335e6087fc1cc2857f23be945313983b8ac2eceb89bdcf63e0bbbd46eb975894480c48114e96279c4bdf195fdb99b874e283be61ef7470ce9a418
data/.rubocop.yml CHANGED
@@ -1 +1,7 @@
1
- ---
1
+ ---
2
+ inherit_from:
3
+ - .rubocop_airbnb.yml
4
+ Airbnb/RiskyActiverecordInvocation:
5
+ Enabled: false
6
+ Airbnb/OptArgParameters:
7
+ Enabled: false
@@ -0,0 +1,3 @@
1
+ ---
2
+ require:
3
+ - rubocop-airbnb
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,6 @@
1
+ # Contributing to Tempest
2
+ 1. Fork the repo.
3
+ 2. When running your local copy of tempest, run `bin/tempest` from the project directory.
4
+ 3. Run `./git-hooks/install.sh` to install a pre-commit hook that will lint your code.
5
+ 4. Make your changes.
6
+ 5. Submit a pull request to this repo.
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in tempest_time.gemspec
6
6
  gemspec
data/README.md CHANGED
@@ -1,8 +1,47 @@
1
- # Tempest
1
+ # Tempest Time Tracker
2
+ Smart CLI for Jira Cloud.
2
3
 
3
- Track Tempo hours, directly from command line!
4
+ ## Install and Setup
5
+ ### Install Ruby
6
+ All you need to install Tempest is Ruby! It is recommended to install a Ruby version manager if you have not already done so.
7
+ ```
8
+ brew install rbenv
9
+ OR
10
+ brew install rvm
11
+ ```
12
+ ### Install the Tempest Gem
13
+ The application is hosted on [Rubygems](https://rubygems.org/gems/tempest_time), so you can install it with the following command:
14
+ ```
15
+ gem install tempest_time
16
+ ```
4
17
 
5
- For more info...
18
+ ### Provide Tempest with your Credentials
19
+ Run the setup command to get started.
20
+ ```
21
+ tempest config setup
22
+ ```
23
+
24
+ ### Keep Tempest Updated
25
+ ```
26
+ gem update tempest_time
6
27
  ```
7
- tempest help
8
- ```
28
+
29
+ ## Built With
30
+ * [TTY: The Ruby Terminal Apps Toolkit](https://piotrmurach.github.io/tty/)
31
+ * [Jira Cloud API](https://developer.atlassian.com/cloud/jira/platform/rest/v3/)
32
+ * [Tempo Cloud API](https://tempo-io.github.io/tempo-api-docs/)
33
+
34
+ ## Contributing
35
+ Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull requests to us.
36
+
37
+ ## Versioning
38
+ We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/devanhurst/tempest_time/tags).
39
+
40
+ ## Authors
41
+ * **Devan Hurst** - *Initial work* - [Bounteous](https://www.bounteous.ca)
42
+
43
+ See also the list of [contributors](https://github.com/devanhurst/tempest_time/contributors) who participated in this project.
44
+
45
+ ## License
46
+
47
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
data/bin/tempest CHANGED
@@ -2,7 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  lib_path = File.expand_path('../lib', __dir__)
5
- $:.unshift(lib_path) if !$:.include?(lib_path)
5
+ $LOAD_PATH.unshift(lib_path) if !$LOAD_PATH.include?(lib_path)
6
6
  require 'tempest_time/cli'
7
7
 
8
8
  Signal.trap('INT') do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../settings/authorization'
2
4
 
3
5
  module TempestTime
@@ -14,4 +16,4 @@ module TempestTime
14
16
  end
15
17
  end
16
18
  end
17
- end
19
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../authorization'
2
4
 
3
5
  module JiraAPI
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../../../helpers/formatting_helper'
2
4
 
3
5
  module JiraAPI
@@ -5,7 +7,7 @@ module JiraAPI
5
7
  class Issue
6
8
  include TempestTime::Helpers::FormattingHelper
7
9
 
8
- attr_reader :fields, :summary, :key
10
+ attr_reader :fields, :key
9
11
 
10
12
  def initialize(issue)
11
13
  @key = issue['key']
@@ -13,16 +15,18 @@ module JiraAPI
13
15
  end
14
16
 
15
17
  def remaining_estimate
16
- @remaining_estimate ||= fields.dig('timetracking', 'remainingEstimateSeconds')
18
+ @remaining_estimate ||= fields.fetch('timetracking', {}).fetch(
19
+ 'remainingEstimateSeconds', nil
20
+ )
17
21
  end
18
22
 
19
23
  def summary
20
- @summary ||= fields.dig('summary')
24
+ @summary ||= fields.fetch('summary')
21
25
  end
22
26
 
23
27
  def status
24
- @status ||= fields.dig('status', 'name')
28
+ @status ||= fields.fetch('status', {}).fetch('name', nil)
25
29
  end
26
30
  end
27
31
  end
28
- end
32
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'httparty'
2
4
  require 'json'
3
5
 
@@ -37,4 +39,4 @@ module JiraAPI
37
39
  credentials.fetch(:user, nil)
38
40
  end
39
41
  end
40
- end
42
+ end
@@ -5,7 +5,6 @@ require_relative '../responses/get_current_user'
5
5
 
6
6
  module JiraAPI
7
7
  module Requests
8
- # :no-doc:
9
8
  class GetCurrentUser < JiraAPI::Request
10
9
  private
11
10
 
@@ -26,4 +26,4 @@ module JiraAPI
26
26
  end
27
27
  end
28
28
  end
29
- end
29
+ end
@@ -6,7 +6,7 @@ module JiraAPI
6
6
  class GetUserIssues < JiraAPI::Request
7
7
  attr_reader :requested_user
8
8
 
9
- def initialize(requested_user = nil)
9
+ def initialize(requested_user: nil)
10
10
  super
11
11
  @requested_user = requested_user || username
12
12
  end
@@ -24,7 +24,7 @@ module JiraAPI
24
24
  def query_params
25
25
  {
26
26
  'jql' => "assignee=#{requested_user} AND resolution is EMPTY",
27
- 'maxResults' => 100
27
+ 'maxResults' => 100,
28
28
  }
29
29
  end
30
30
 
@@ -33,4 +33,4 @@ module JiraAPI
33
33
  end
34
34
  end
35
35
  end
36
- end
36
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../response'
2
4
 
3
5
  module JiraAPI
4
6
  class Response < TempestTime::API::Response; end
5
- end
7
+ end
@@ -4,7 +4,6 @@ require_relative '../response'
4
4
 
5
5
  module JiraAPI
6
6
  module Responses
7
- # :no-doc:
8
7
  class GetCurrentUser < JiraAPI::Response; end
9
8
  end
10
9
  end
@@ -13,4 +13,4 @@ module JiraAPI
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -11,4 +11,4 @@ module JiraAPI
11
11
  end
12
12
  end
13
13
  end
14
- end
14
+ end
@@ -11,9 +11,9 @@ module TempestTime
11
11
  class Request
12
12
  include HTTParty
13
13
 
14
- DATE_FORMAT = "%Y-%m-%d"
14
+ DATE_FORMAT = '%Y-%m-%d'
15
15
 
16
- def initialize(*args)
16
+ def initialize(*_args)
17
17
  self.class.base_uri credentials.fetch(:url)
18
18
  end
19
19
 
@@ -86,4 +86,4 @@ module TempestTime
86
86
  end
87
87
  end
88
88
  end
89
- end
89
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TempestTime
2
4
  module API
3
5
  class Response
@@ -31,4 +33,4 @@ module TempestTime
31
33
  end
32
34
  end
33
35
  end
34
- end
36
+ end
@@ -33,4 +33,4 @@ module TempoAPI
33
33
  end
34
34
  end
35
35
  end
36
- end
36
+ end
@@ -32,4 +32,4 @@ module TempoAPI
32
32
  TempoAPI::Response
33
33
  end
34
34
  end
35
- end
35
+ end
@@ -39,7 +39,7 @@ module TempoAPI
39
39
  "startDate": date.strftime('%Y-%m-%d'),
40
40
  "startTime": '12:00:00',
41
41
  "authorUsername": user,
42
- "description": message
42
+ "description": message,
43
43
  }
44
44
  end
45
45
 
@@ -48,4 +48,4 @@ module TempoAPI
48
48
  end
49
49
  end
50
50
  end
51
- end
51
+ end
@@ -26,4 +26,4 @@ module TempoAPI
26
26
  end
27
27
  end
28
28
  end
29
- end
29
+ end
@@ -26,4 +26,4 @@ module TempoAPI
26
26
  end
27
27
  end
28
28
  end
29
- end
29
+ end
@@ -5,11 +5,10 @@ require_relative '../responses/list_worklogs'
5
5
 
6
6
  module TempoAPI
7
7
  module Requests
8
- # :no-doc:
9
8
  class ListWorklogs < TempoAPI::Request
10
9
  attr_reader :start_date, :end_date
11
10
 
12
- def initialize(start_date, end_date = nil, requested_user = nil)
11
+ def initialize(start_date, end_date:, requested_user:)
13
12
  super
14
13
  @start_date = start_date
15
14
  @end_date = end_date || start_date
@@ -36,7 +35,7 @@ module TempoAPI
36
35
  {
37
36
  "from": start_date.strftime(DATE_FORMAT),
38
37
  "to": end_date.strftime(DATE_FORMAT),
39
- "limit": 1000
38
+ "limit": 1000,
40
39
  }
41
40
  end
42
41
  end
@@ -32,15 +32,15 @@ module TempoAPI
32
32
  def query_params
33
33
  {
34
34
  from: dates.first.strftime(DATE_FORMAT),
35
- to: dates.last.strftime(DATE_FORMAT)
35
+ to: dates.last.strftime(DATE_FORMAT),
36
36
  }
37
37
  end
38
38
 
39
39
  def request_body
40
40
  {
41
- reviewerUsername: reviewer
41
+ reviewerUsername: reviewer,
42
42
  }
43
43
  end
44
44
  end
45
45
  end
46
- end
46
+ end
@@ -2,4 +2,4 @@ require_relative '../response'
2
2
 
3
3
  module TempoAPI
4
4
  class Response < TempestTime::API::Response; end
5
- end
5
+ end
@@ -25,4 +25,4 @@ module TempoAPI
25
25
  end
26
26
  end
27
27
  end
28
- end
28
+ end
@@ -5,4 +5,4 @@ module TempoAPI
5
5
  class DeleteWorklog < TempoAPI::Response
6
6
  end
7
7
  end
8
- end
8
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../response'
2
4
 
3
5
  module TempoAPI
@@ -8,7 +10,7 @@ module TempoAPI
8
10
  def worklog
9
11
  @worklog ||= TempoAPI::Models::Worklog.new(
10
12
  id: raw_response['tempoWorklogId'],
11
- issue: raw_response.dig('issue', 'key'),
13
+ issue: raw_response.fetch('issue', {}).fetch('key', nil),
12
14
  seconds: raw_response['timeSpentSeconds'],
13
15
  description: raw_response['description']
14
16
  )
@@ -19,4 +21,4 @@ module TempoAPI
19
21
  end
20
22
  end
21
23
  end
22
- end
24
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative '../response'
2
4
  require_relative '../models/worklog'
3
5
  require_relative '../../../helpers/time_helper'
@@ -7,13 +9,11 @@ module TempoAPI
7
9
  class ListWorklogs < TempoAPI::Response
8
10
  include TempestTime::Helpers::TimeHelper
9
11
 
10
- attr_reader :worklogs, :total_hours_spent
11
-
12
12
  def worklogs
13
13
  @worklogs ||= results.map do |worklog|
14
14
  TempoAPI::Models::Worklog.new(
15
15
  id: worklog['tempoWorklogId'],
16
- issue: worklog.dig('issue', 'key'),
16
+ issue: worklog.fetch('issue', {}).fetch('key', nil),
17
17
  seconds: worklog['timeSpentSeconds'],
18
18
  description: worklog['description']
19
19
  )
@@ -26,11 +26,9 @@ module TempoAPI
26
26
 
27
27
  private
28
28
 
29
- attr_reader :results
30
-
31
29
  def results
32
30
  @results = raw_response['results'] || []
33
31
  end
34
32
  end
35
33
  end
36
- end
34
+ end
@@ -10,4 +10,4 @@ module TempoAPI
10
10
  end
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  require 'git'
3
5
 
4
6
  module TempestTime
5
7
  class CLI < Thor
8
+ package_name 'Tempest'
6
9
  # Error raised by this runner
7
10
  Error = Class.new(StandardError)
8
11
 
@@ -62,7 +65,7 @@ module TempestTime
62
65
  TempestTime::Commands::Delete.new(worklogs, options).execute
63
66
  end
64
67
 
65
- desc "track [TIME] [ISSUE(S)]", 'Track time to Tempo.'
68
+ desc 'track [TIME] [ISSUE(S)]', 'Track time to Tempo.'
66
69
  long_desc <<-LONGDESC
67
70
  `tempest track` or `tempest log` will track the specified number of hours or minutes to the issue(s) specified.\n
68
71
  If not specified, it will check the name of the current git branch and automatically track the logged time to that issue, if found.\n
@@ -88,4 +91,4 @@ module TempestTime
88
91
 
89
92
  map log: :track
90
93
  end
91
- end
94
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'tty-reader'
3
4
  require 'forwardable'
4
5
  require_relative 'helpers/time_helper'
5
6
  require_relative 'helpers/formatting_helper'
@@ -15,9 +16,15 @@ module TempestTime
15
16
  def_delegators :command, :run
16
17
 
17
18
  def execute(*)
19
+ execute!
20
+ rescue TTY::Reader::InputInterrupt
21
+ prompt.say(pastel.yellow("\nGoodbye!"))
22
+ end
23
+
24
+ def execute!(*)
18
25
  raise(
19
- NotImplementedError,
20
- "#{self.class}##{__method__} must be implemented"
26
+ NotImplementedError,
27
+ "#{self.class}##{__method__} must be implemented"
21
28
  )
22
29
  end
23
30
 
@@ -36,7 +43,7 @@ module TempestTime
36
43
  TTY::Prompt.new(options)
37
44
  end
38
45
 
39
- def week_prompt(message, past_weeks = 51)
46
+ def week_prompt(message, past_weeks: 51)
40
47
  require 'tty-prompt'
41
48
  weeks = past_week_selections(past_weeks)
42
49
  TTY::Prompt.new.select(
@@ -46,7 +53,7 @@ module TempestTime
46
53
  )
47
54
  end
48
55
 
49
- def date_prompt(message, past_days = 6)
56
+ def date_prompt(message, past_days: 6)
50
57
  require 'tty-prompt'
51
58
  dates = past_date_selections(past_days)
52
59
  TTY::Prompt.new.select(
@@ -66,13 +73,13 @@ module TempestTime
66
73
  TTY::Table
67
74
  end
68
75
 
69
- def with_spinner(message, format = :pong)
76
+ def with_spinner(message, format: :pong)
70
77
  s = spinner.new(":spinner #{message}", format: format)
71
78
  s.auto_spin
72
79
  yield(s)
73
80
  end
74
81
 
75
- def with_success_fail_spinner(message, format = :spin_3)
82
+ def with_success_fail_spinner(message, format: :spin_3)
76
83
  s = spinner.new(":spinner #{message}", format: format)
77
84
  s.auto_spin
78
85
  response = yield
@@ -5,7 +5,6 @@ require 'thor'
5
5
  module TempestTime
6
6
  module Commands
7
7
  class Config < Thor
8
-
9
8
  namespace :config
10
9
 
11
10
  desc 'setup', 'Set up Tempest with your credentials.'
@@ -11,7 +11,7 @@ module TempestTime
11
11
  @options = options
12
12
  end
13
13
 
14
- def execute(input: $stdin, output: $stdout)
14
+ def execute!
15
15
  settings = TempestTime::Settings::Authorization.new
16
16
  setting = prompt.select(
17
17
  "Which #{pastel.green('setting')} would you like to edit?",
@@ -8,13 +8,12 @@ require_relative '../../api/tempo_api/requests/list_worklogs'
8
8
  module TempestTime
9
9
  module Commands
10
10
  class Config
11
- # :no-doc:
12
11
  class Setup < TempestTime::Command
13
12
  def initialize(options)
14
13
  @options = options
15
14
  end
16
15
 
17
- def execute
16
+ def execute!
18
17
  check_for_completion
19
18
  set_authorization_values
20
19
  with_spinner('Checking credentials...') do |spinner|
@@ -35,7 +34,7 @@ module TempestTime
35
34
  'username' => username,
36
35
  'subdomain' => subdomain,
37
36
  'jira_token' => jira_token,
38
- 'tempo_token' => tempo_token
37
+ 'tempo_token' => tempo_token,
39
38
  }
40
39
  end
41
40
 
@@ -11,7 +11,7 @@ module TempestTime
11
11
  @options = options
12
12
  end
13
13
 
14
- def execute(input: $stdin, output: $stdout)
14
+ def execute!
15
15
  pluralized = @worklogs.length > 1 ? 'worklogs' : 'worklog'
16
16
 
17
17
  unless @options[:autoconfirm]
@@ -5,7 +5,6 @@ require 'thor'
5
5
  module TempestTime
6
6
  module Commands
7
7
  class Issue < Thor
8
-
9
8
  namespace :issue
10
9
 
11
10
  desc 'list', 'List unresolved issues.'
@@ -11,8 +11,8 @@ module TempestTime
11
11
  @user = user || current_user
12
12
  end
13
13
 
14
- def execute(input: $stdin, output: $stdout)
15
- request = JiraAPI::Requests::GetUserIssues.new(@user)
14
+ def execute!
15
+ request = JiraAPI::Requests::GetUserIssues.new(requested_user: @user)
16
16
  message = "Getting issues for #{request.requested_user}"
17
17
  response = with_spinner(message) do |spinner|
18
18
  request.send_request.tap { spinner.stop }
@@ -36,7 +36,7 @@ module TempestTime
36
36
 
37
37
  def format_output(issues)
38
38
  table.new(
39
- %w[Status Issue Summary],
39
+ %w(Status Issue Summary),
40
40
  issues.map { |issue| row(issue) }
41
41
  ).render(:ascii, padding: [0, 1], column_widths: [15, 10, 30])
42
42
  end
@@ -52,4 +52,4 @@ module TempestTime
52
52
  end
53
53
  end
54
54
  end
55
- end
55
+ end
@@ -12,7 +12,7 @@ module TempestTime
12
12
  @issues = [automatic_issue] if issues.empty?
13
13
  end
14
14
 
15
- def execute(input: $stdin, output: $stdout)
15
+ def execute!
16
16
  @issues.each { |issue| command.run("open #{url(issue)}") }
17
17
  end
18
18
 
@@ -25,4 +25,4 @@ module TempestTime
25
25
  end
26
26
  end
27
27
  end
28
- end
28
+ end
@@ -11,14 +11,14 @@ module TempestTime
11
11
  @date = options[:date] ? Date.parse(options[:date]) : nil
12
12
  end
13
13
 
14
- def execute(input: $stdin, output: $stdout)
14
+ def execute!
15
15
  @date ||= date_prompt('Please select a date.')
16
16
 
17
17
  with_spinner("Retrieving logs for #{formatted_date(@date)}...") do |spin|
18
18
  @response = TempoAPI::Requests::ListWorklogs.new(
19
19
  @date,
20
- nil,
21
- @user
20
+ end_date: nil,
21
+ requested_user: @user
22
22
  ).send_request
23
23
  spin.stop(pastel.green('Done!'))
24
24
  prompt.say(render_table)
@@ -32,7 +32,7 @@ module TempestTime
32
32
  private
33
33
 
34
34
  def table_headings
35
- %w[Worklog Issue Time Description]
35
+ %w(Worklog Issue Time Description)
36
36
  end
37
37
 
38
38
  def render_table
@@ -50,7 +50,7 @@ module TempestTime
50
50
  worklog.id,
51
51
  worklog.issue,
52
52
  formatted_time(worklog.seconds),
53
- worklog.description
53
+ worklog.description,
54
54
  ]
55
55
  end
56
56
  end
@@ -14,9 +14,12 @@ module TempestTime
14
14
  @teams = TempestTime::Settings::Teams.new
15
15
  end
16
16
 
17
- def execute(input: $stdin, output: $stdout)
18
- @users = user_prompt if @users.empty? && @team.nil?
19
- @users.push(teams.members(@team)) if @team
17
+ def execute!
18
+ if @users.empty? && @team.nil?
19
+ @users = user_prompt
20
+ end
21
+
22
+ @users.push(@teams.members(@team)) if @team
20
23
  abort('No users specified.') unless @users.any?
21
24
 
22
25
  @week = week_prompt('Please select the week to report.')
@@ -38,12 +41,12 @@ module TempestTime
38
41
  type = prompt.select(
39
42
  'Generate a report for a '\
40
43
  "#{pastel.green('team')} or a specific #{pastel.green('user')}?",
41
- %w[Team User]
44
+ %w(Team User)
42
45
  )
43
46
 
44
47
  if type == 'User'
45
48
  return [
46
- prompt.ask("Please enter a #{pastel.green('user')}.")
49
+ prompt.ask("Please enter a #{pastel.green('user')}."),
47
50
  ]
48
51
  end
49
52
 
@@ -70,8 +73,8 @@ module TempestTime
70
73
  @reports ||= @users.map do |user|
71
74
  list = TempoAPI::Requests::ListWorklogs.new(
72
75
  start_date,
73
- end_date,
74
- user
76
+ end_date: end_date,
77
+ requested_user: user
75
78
  ).send_request
76
79
  TempestTime::Models::Report.new(user, list.worklogs)
77
80
  end || []
@@ -81,7 +84,7 @@ module TempestTime
81
84
  @aggregate ||= TempestTime::Models::Report.new(
82
85
  'TOTAL',
83
86
  reports.flat_map(&:worklogs),
84
- @users.count
87
+ number_of_users: @users.count
85
88
  )
86
89
  end
87
90
 
@@ -93,7 +96,7 @@ module TempestTime
93
96
  end
94
97
 
95
98
  def table_headings
96
- %w[User COMP% UTIL%] + projects
99
+ %w(User COMP% UTIL%) + projects
97
100
  end
98
101
 
99
102
  def render_table
@@ -109,7 +112,7 @@ module TempestTime
109
112
  row = [
110
113
  data.user,
111
114
  right_align(percentage(data.total_compliance_percentage)),
112
- right_align(percentage(data.utilization_percentage))
115
+ right_align(percentage(data.utilization_percentage)),
113
116
  ]
114
117
  projects.each do |project|
115
118
  row.push(
@@ -10,7 +10,7 @@ module TempestTime
10
10
  @options = options
11
11
  end
12
12
 
13
- def execute(input: $stdin, output: $stdout)
13
+ def execute!
14
14
  reviewer = prompt.ask('Who should review this timesheet? (username)')
15
15
  dates = week_dates(week_prompt('Select a week to submit.'))
16
16
 
@@ -18,7 +18,7 @@ module TempestTime
18
18
  abort unless prompt.yes?(message)
19
19
  abort unless prompt.yes?('Are you sure? No edits can be made once submitted!')
20
20
 
21
- with_success_fail_spinner("Submitting your timesheet...") do
21
+ with_success_fail_spinner('Submitting your timesheet...') do
22
22
  TempoAPI::Requests::SubmitTimesheet.new(reviewer, dates).send_request
23
23
  end
24
24
  end
@@ -5,7 +5,6 @@ require 'thor'
5
5
  module TempestTime
6
6
  module Commands
7
7
  class Teams < Thor
8
-
9
8
  namespace :config
10
9
 
11
10
  desc 'add', 'Add a team.'
@@ -11,10 +11,10 @@ module TempestTime
11
11
  @options = options
12
12
  end
13
13
 
14
- def execute(input: $stdin, output: $stdout)
14
+ def execute!
15
15
  teams = TempestTime::Settings::Teams.new
16
16
  message =
17
- 'Please enter ' + pastel.green('the members') + " of this team. "\
17
+ 'Please enter ' + pastel.green('the members') + ' of this team. '\
18
18
  '(Comma-separated, e.g. jkirk, jpicard, bsisko, kjaneway) '
19
19
  members = prompt.ask(message) do |q|
20
20
  q.convert ->(input) { input.split(/,\s*/) }
@@ -12,8 +12,8 @@ module TempestTime
12
12
  @options = options
13
13
  end
14
14
 
15
- def execute(input: $stdin, output: $stdout)
16
- abort("There are no teams to delete!") unless @teams.keys.any?
15
+ def execute!
16
+ abort('There are no teams to delete!') unless @teams.keys.any?
17
17
  team = prompt.select(
18
18
  "Which #{pastel.green('team')} would you like to delete?",
19
19
  @teams.names
@@ -11,9 +11,9 @@ module TempestTime
11
11
  @options = options
12
12
  end
13
13
 
14
- def execute(input: $stdin, output: $stdout)
14
+ def execute!
15
15
  teams = TempestTime::Settings::Teams.new
16
- abort("There are no teams to edit!") unless teams.names.any?
16
+ abort('There are no teams to edit!') unless teams.names.any?
17
17
  team = prompt.select(
18
18
  "Which #{pastel.green('team')} would you like to edit?",
19
19
  teams.names
@@ -5,7 +5,6 @@ require 'thor'
5
5
  module TempestTime
6
6
  module Commands
7
7
  class Timer < Thor
8
-
9
8
  namespace :timer
10
9
 
11
10
  desc 'start [ISSUE]', 'Start a new timer, or continue a paused timer.'
@@ -12,7 +12,7 @@ module TempestTime
12
12
  @timer = TempestTime::Models::Timer.new(@issue)
13
13
  end
14
14
 
15
- def execute(input: $stdin, output: $stdout)
15
+ def execute!
16
16
  timer.delete ? deleted_message : no_timer_message
17
17
  end
18
18
 
@@ -8,7 +8,7 @@ module TempestTime
8
8
  module Commands
9
9
  class Timer
10
10
  class List < TempestTime::Command
11
- def execute(input: $stdin, output: $stdout)
11
+ def execute!
12
12
  abort(pastel.red('No timers running!')) unless all_timers.any?
13
13
  all_timers.each do |timer|
14
14
  TempestTime::Commands::Timer::Status.new(timer.issue).execute
@@ -33,9 +33,9 @@ module TempestTime
33
33
 
34
34
  def action_prompt(timer)
35
35
  if timer.running?
36
- prompt.select('', %w[Pause Track])
36
+ prompt.select('', %w(Pause Track))
37
37
  else
38
- prompt.select('', %w[Resume Track])
38
+ prompt.select('', %w(Resume Track))
39
39
  end
40
40
  end
41
41
 
@@ -13,7 +13,7 @@ module TempestTime
13
13
  @timer = TempestTime::Models::Timer.new(@issue)
14
14
  end
15
15
 
16
- def execute(input: $stdin, output: $stdout)
16
+ def execute!
17
17
  timer.pause
18
18
  TempestTime::Commands::Timer::Status.new(issue).execute
19
19
  end
@@ -24,4 +24,4 @@ module TempestTime
24
24
  end
25
25
  end
26
26
  end
27
- end
27
+ end
@@ -13,7 +13,7 @@ module TempestTime
13
13
  @timer = TempestTime::Models::Timer.new(@issue)
14
14
  end
15
15
 
16
- def execute(input: $stdin, output: $stdout)
16
+ def execute!
17
17
  timer.start
18
18
  TempestTime::Commands::Timer::Status.new(issue).execute
19
19
  end
@@ -12,7 +12,7 @@ module TempestTime
12
12
  @timer = TempestTime::Models::Timer.new(issue)
13
13
  end
14
14
 
15
- def execute(input: $stdin, output: $stdout)
15
+ def execute!
16
16
  prompt.say("#{issue}: #{status_message}")
17
17
  end
18
18
 
@@ -15,7 +15,7 @@ module TempestTime
15
15
  @timer = TempestTime::Models::Timer.new(@issue)
16
16
  end
17
17
 
18
- def execute(input: $stdin, output: $stdout)
18
+ def execute!
19
19
  abort(pastel.red("No timer for #{issue}!")) unless timer.exists?
20
20
  timer.pause
21
21
  track_time
@@ -7,26 +7,23 @@ require_relative '../api/tempo_api/requests/create_worklog'
7
7
  module TempestTime
8
8
  module Commands
9
9
  class Track < TempestTime::Command
10
+ attr_reader :time, :issues, :options
11
+
10
12
  def initialize(time, issues, options)
11
- @time = time
12
- @issues = issues
13
13
  @options = options
14
+ @issues = issues.any? ? issues.map(&:upcase) : [automatic_issue]
15
+ @time = parsed_time(time) / issues.count
14
16
  end
15
17
 
16
- def execute(input: $stdin, output: $stdout)
17
- time = @options[:split] ? parsed_time(@time) / @issues.count : parsed_time(@time)
18
- issues = @issues.any? ? @issues.map(&:upcase) : [automatic_issue]
19
-
18
+ def execute!
20
19
  unless @options[:autoconfirm]
21
20
  prompt_message = "Track #{formatted_time(time)}, "\
22
- "#{billability(@options)}, "\
23
- "to #{issues.join(', ')}?"
21
+ "#{billability(options)}, "\
22
+ "to #{issues.join(', ')}?"
24
23
  abort unless prompt.yes?(prompt_message, convert: :bool)
25
24
  end
26
25
 
27
- issues.each do |issue|
28
- track_time(time, @options.merge('issue' => issue))
29
- end
26
+ issues.each { |issue| track_time(time, options.merge('issue' => issue)) }
30
27
  end
31
28
 
32
29
  private
@@ -35,10 +32,10 @@ module TempestTime
35
32
  message = "Tracking #{formatted_time(time)} to #{options['issue']}..."
36
33
  with_success_fail_spinner(message) do
37
34
  options['remaining'] = if options['remaining'].nil?
38
- remaining_estimate(options['issue'], time)
39
- else
40
- parsed_time(options['remaining'])
41
- end
35
+ remaining_estimate(options['issue'], time)
36
+ else
37
+ parsed_time(options['remaining'])
38
+ end
42
39
  TempoAPI::Requests::CreateWorklog.new(time, options).send_request
43
40
  end
44
41
  end
@@ -13,4 +13,4 @@ module TempestTime
13
13
  end
14
14
  end
15
15
  end
16
- end
16
+ end
@@ -10,4 +10,4 @@ module TempestTime
10
10
  end
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -78,4 +78,4 @@ module TempestTime
78
78
  end
79
79
  end
80
80
  end
81
- end
81
+ end
@@ -9,7 +9,7 @@ module TempestTime
9
9
 
10
10
  attr_reader :user, :worklogs, :number_of_users
11
11
 
12
- def initialize(user, worklogs, number_of_users = 1)
12
+ def initialize(user, worklogs, number_of_users: 1)
13
13
  @user = user
14
14
  @worklogs = worklogs
15
15
  @number_of_users = number_of_users
@@ -36,10 +36,11 @@ module TempestTime
36
36
  end
37
37
 
38
38
  def utilization_percentage
39
- @utilization_percentage ||= project_compliance_percentages.inject(0) do |memo, (project, percentage)|
40
- memo += percentage unless project == INTERNAL_PROJECT
41
- memo
42
- end
39
+ @utilization_percentage ||=
40
+ project_compliance_percentages.inject(0) do |memo, (project, percentage)|
41
+ memo += percentage unless project == INTERNAL_PROJECT
42
+ memo
43
+ end
43
44
  end
44
45
 
45
46
  def time_logged_seconds(logs)
@@ -55,4 +56,4 @@ module TempestTime
55
56
  end
56
57
  end
57
58
  end
58
- end
59
+ end
@@ -5,7 +5,7 @@ require 'tempfile'
5
5
  module TempestTime
6
6
  module Models
7
7
  class Timer
8
- TEMP_DIR = '/tmp/timer/logs'
8
+ TEMP_DIR = Dir.home + '/.tempest/timer/logs'
9
9
  FILE_EXT = '.timer'
10
10
  PREFIX_SEPARATOR = '___'
11
11
 
@@ -43,12 +43,12 @@ module TempestTime
43
43
  end
44
44
 
45
45
  def runtime
46
- @logs ||= log_files.each_with_object([]) do |log, array|
46
+ @runtime ||= log_files.each_with_object([]) do |log, array|
47
47
  start_time = File.birthtime(log)
48
48
  end_time = log_running?(log) ? Time.now : File.mtime(log)
49
49
 
50
50
  array << (end_time - start_time)
51
- end.sum
51
+ end.reduce(:+)
52
52
  end
53
53
 
54
54
  def running?
@@ -52,4 +52,4 @@ module TempestTime
52
52
  config.write(force: true)
53
53
  end
54
54
  end
55
- end
55
+ end
@@ -9,4 +9,4 @@ module TempestTime
9
9
  end
10
10
  end
11
11
  end
12
- end
12
+ end
@@ -9,4 +9,4 @@ module TempestTime
9
9
  end
10
10
  end
11
11
  end
12
- end
12
+ end
@@ -15,4 +15,4 @@ module TempestTime
15
15
  end
16
16
  end
17
17
  end
18
- end
18
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TempestTime
4
- VERSION = '0.7.4'
4
+ VERSION = '1.0.0'
5
5
  end
data/tempest_time.gemspec CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'tempest_time/version'
@@ -11,13 +10,13 @@ Gem::Specification.new do |spec|
11
10
  spec.authors = ['Devan Hurst']
12
11
  spec.email = ['devan.hurst@gmail.com']
13
12
 
14
- spec.summary = %q{Smart CLI for Jira Cloud.}
15
- spec.description = %q{Log time and more... directly from the command line!}
13
+ spec.summary = %q(Smart CLI for Jira Cloud.)
14
+ spec.description = %q(Log time and more... directly from the command line!)
16
15
  spec.homepage = 'https://github.com/devanhurst/tempest_time'
17
16
 
18
17
  spec.required_ruby_version = '~> 2.3'
19
18
 
20
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
20
  f.match(%r{^(test|spec|features)/})
22
21
  end
23
22
  spec.executables = ['tempest']
@@ -27,6 +26,7 @@ Gem::Specification.new do |spec|
27
26
  spec.add_development_dependency 'byebug', '~> 10.0'
28
27
  spec.add_development_dependency 'minitest', '~> 5.0'
29
28
  spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rubocop-airbnb', '~> 2.0'
30
30
 
31
31
  spec.add_dependency 'git', '~>1.5'
32
32
  spec.add_dependency 'httparty', '~>0.16'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tempest_time
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.4
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Devan Hurst
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-11 00:00:00.000000000 Z
11
+ date: 2019-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-airbnb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: git
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -216,8 +230,10 @@ extra_rdoc_files: []
216
230
  files:
217
231
  - ".gitignore"
218
232
  - ".rubocop.yml"
233
+ - ".rubocop_airbnb.yml"
219
234
  - ".ruby-version"
220
235
  - ".travis.yml"
236
+ - CONTRIBUTING.md
221
237
  - Gemfile
222
238
  - LICENSE
223
239
  - README.md