tempest_time 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6b26cfdc661706032cc5149b28b05fbf1f322324f0f845c00af8d3e5135546c8
4
- data.tar.gz: 1cb5c84cf724531917ec9c759dc83cd47a7fba89a8dc9c74401c65f89b6ea207
3
+ metadata.gz: 8fadd5695c98443d2892aac9bdc9a907ff1825d8613c0955ce988af14386f0df
4
+ data.tar.gz: add6d9dc10500fc6236030b5da61c24003fe57a49896062cf7894e5e9d983372
5
5
  SHA512:
6
- metadata.gz: 1ac9e54ec617bae5c87fd405b1b1f6c5df82d47d668caa0a26deedfe52dc59352d5ce3e37b7e0cacb376562fbed3fcb670c1d6f92c737a81b911db2ff0658466
7
- data.tar.gz: 502bf3a2a0d11b21167d4fa68305d4993477914462f6110d5dc930e44ceb7a8cf7528e98e135c68cee312d166ef75f571a3f2891a7fc9418b9fbcc7ddad5cf0f
6
+ metadata.gz: 0742fd8630fc7744e7b814ff28b0b6498a0245cdf8b72e3b819d182001eae5281db7cb3785e03d91a8fa199f37e43b98d5078e3fe29921c2d8bfd3ef62426dac
7
+ data.tar.gz: 53060657cdcf5f6a524dfeb360e78cc38b9b2a6c78963d762d3a0d2acfc2d07ef5b69fa6687510d7b5e33b5563ee22e98fbf151d44a6a2ba3e0783baf2a41f81
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tempest_time (0.5.1)
4
+ tempest_time (0.5.2)
5
5
  git (~> 1.5)
6
6
  httparty (~> 0.16)
7
7
  pastel (~> 0.7.2)
@@ -7,12 +7,12 @@ module TempoAPI
7
7
  class SubmitTimesheet < TempoAPI::Request
8
8
  include TempestTime::Helpers::TimeHelper
9
9
 
10
- attr_reader :reviewer, :week_number
10
+ attr_reader :reviewer, :dates
11
11
 
12
- def initialize(reviewer, week_number)
12
+ def initialize(reviewer, dates)
13
13
  super
14
14
  @reviewer = reviewer
15
- @week_number = week_number
15
+ @dates = dates
16
16
  end
17
17
 
18
18
  private
@@ -30,7 +30,6 @@ module TempoAPI
30
30
  end
31
31
 
32
32
  def query_params
33
- dates = week_dates(week_number)
34
33
  {
35
34
  from: dates.first.strftime(DATE_FORMAT),
36
35
  to: dates.last.strftime(DATE_FORMAT)
@@ -7,7 +7,7 @@ module TempoAPI
7
7
  class ListWorklogs < TempoAPI::Response
8
8
  include TempestTime::Helpers::TimeHelper
9
9
 
10
- attr_reader :worklogs
10
+ attr_reader :worklogs, :total_hours_spent
11
11
 
12
12
  def worklogs
13
13
  @worklogs ||= raw_response['results'].map do |worklog|
@@ -20,18 +20,6 @@ module TempoAPI
20
20
  end
21
21
  end
22
22
 
23
- private
24
-
25
- def success_message
26
- output = ""
27
- output << worklogs_output
28
- output << "\nTOTAL TIME LOGGED: #{total_hours_spent} hours."
29
- end
30
-
31
- def worklogs_output
32
- worklogs.map(&:to_s).join("\n")
33
- end
34
-
35
23
  def total_hours_spent
36
24
  worklogs.map(&:hours).reduce(:+)&.round(2) || 0
37
25
  end
@@ -23,17 +23,11 @@ module TempestTime
23
23
  'teams', 'teams [SUBCOMMAND]',
24
24
  'Add or modify teams.'
25
25
 
26
- desc 'list [DATE]', 'List worklogs for given date. (Defaults to today.)'
27
- long_desc <<-LONGDESC
28
- `tempest list` will list a day's worklogs.\n
29
- e.g. `tempest list today`\n
30
- e.g. `tempest list yesterday`\n
31
- e.g. `tempest list 2019-01-31`\n
32
- e.g. `tempest list 2019-01-31 --user=jsmith`
33
- LONGDESC
34
- def list(date = nil)
26
+ desc 'list', 'List worklogs for a specific date.'
27
+ option :user, aliases: '-u', type: :string
28
+ def list
35
29
  require_relative 'commands/list'
36
- TempestTime::Commands::List.new(date, options).execute
30
+ TempestTime::Commands::List.new(options).execute
37
31
  end
38
32
 
39
33
 
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'forwardable'
4
+ require_relative 'helpers/time_helper'
5
+ require_relative 'helpers/formatting_helper'
4
6
 
5
7
  module TempestTime
6
8
  class Command
7
9
  extend Forwardable
10
+ include TempestTime::Helpers::TimeHelper
11
+ include TempestTime::Helpers::FormattingHelper
8
12
 
9
13
  def_delegators :command, :run
10
14
 
@@ -30,6 +34,26 @@ module TempestTime
30
34
  TTY::Prompt.new(options)
31
35
  end
32
36
 
37
+ def week_prompt(message, past_weeks = 51)
38
+ require 'tty-prompt'
39
+ weeks = past_week_selections(past_weeks)
40
+ TTY::Prompt.new.select(
41
+ message,
42
+ weeks,
43
+ per_page: 5
44
+ )
45
+ end
46
+
47
+ def date_prompt(message, past_days = 6)
48
+ require 'tty-prompt'
49
+ dates = past_date_selections(past_days)
50
+ TTY::Prompt.new.select(
51
+ message,
52
+ dates,
53
+ per_page: 5
54
+ )
55
+ end
56
+
33
57
  def spinner
34
58
  require 'tty-spinner'
35
59
  TTY::Spinner
@@ -26,7 +26,7 @@ module TempestTime
26
26
  table.new(
27
27
  %w[Status Issue Summary],
28
28
  issues.map { |issue| row(issue) }
29
- ).render(:ascii, padding: [0, 1])
29
+ ).render(:ascii, padding: [0, 1], column_widths: [15, 10, 30])
30
30
  end
31
31
 
32
32
  def row(issue)
@@ -9,24 +9,52 @@ module TempestTime
9
9
  class List < TempestTime::Command
10
10
  include TempestTime::Helpers::TimeHelper
11
11
 
12
- def initialize(date, options)
13
- @date = date
12
+ def initialize(options)
14
13
  @options = options
15
14
  end
16
15
 
17
16
  def execute(input: $stdin, output: $stdout)
18
- dates = parsed_date_input(@date)
19
- dates.each do |start_date|
20
- request = TempoAPI::Requests::ListWorklogs.new(
21
- start_date,
22
- @options['end_date'],
17
+ @date ||= date_prompt('Please select a date.')
18
+
19
+ with_spinner("Retrieving logs for #{formatted_date(@date)}...") do |spin|
20
+ @response = TempoAPI::Requests::ListWorklogs.new(
21
+ @date,
22
+ nil,
23
23
  @options[:user]
24
+ ).send_request
25
+ spin.stop(pastel.green('Done!'))
26
+ prompt.say(render_table)
27
+ prompt.say(
28
+ 'Total Time Logged: '\
29
+ "#{pastel.green("#{@response.total_hours_spent} hours")}"
24
30
  )
25
- request.send_request
26
- puts "\nHere are your logs for #{formatted_date_range(start_date, @options['end_date'])}:\n"
27
- puts request.response_message
28
31
  end
29
32
  end
33
+
34
+ private
35
+
36
+ def table_headings
37
+ %w[Worklog Issue Time Description]
38
+ end
39
+
40
+ def render_table
41
+ t = table.new(table_headings, @response.worklogs.map { |r| row(r) })
42
+ t.render(
43
+ :ascii,
44
+ padding: [0, 1],
45
+ column_widths: [7,10,15,30],
46
+ multiline: true
47
+ )
48
+ end
49
+
50
+ def row(worklog)
51
+ [
52
+ worklog.id,
53
+ worklog.issue,
54
+ formatted_time(worklog.seconds),
55
+ worklog.description
56
+ ]
57
+ end
30
58
  end
31
59
  end
32
60
  end
@@ -2,8 +2,9 @@
2
2
 
3
3
  require_relative '../command'
4
4
  require_relative '../settings/teams'
5
- require_relative '../services/generate_report'
6
5
  require_relative '../helpers/time_helper'
6
+ require_relative '../api/tempo_api/requests/list_worklogs'
7
+ require_relative '../models/report'
7
8
 
8
9
  module TempestTime
9
10
  module Commands
@@ -13,7 +14,6 @@ module TempestTime
13
14
  def initialize(users, options)
14
15
  @users = users || []
15
16
  @team = options[:team]
16
- @week = options[:week]
17
17
  end
18
18
 
19
19
  def execute(input: $stdin, output: $stdout)
@@ -21,14 +21,14 @@ module TempestTime
21
21
  @users.push(TempestTime::Settings::Teams.members(@team)) if @team
22
22
  abort('No users specified.') unless @users.any?
23
23
 
24
- @week ||= week_prompt
24
+ @week = week_prompt('Please select the week to report.')
25
25
 
26
26
  with_spinner('Generating report...') do |spinner|
27
27
  table = render_table
28
28
  spinner.stop(pastel.green('Your report is ready!'))
29
- date_range = "#{formatted_date(report.start_date)}"\
29
+ date_range = "#{formatted_date(start_date)}"\
30
30
  ' to '\
31
- "#{formatted_date(report.end_date)}"
31
+ "#{formatted_date(end_date)}"
32
32
  prompt.say("\nReport for #{pastel.green(date_range)}")
33
33
  puts table
34
34
  end
@@ -36,61 +36,92 @@ module TempestTime
36
36
 
37
37
  private
38
38
 
39
- def report
40
- @report ||= TempestTime::Services::GenerateReport.new(
41
- @users.flatten, @week
42
- )
43
- end
44
-
45
39
  def user_prompt
46
40
  type = prompt.select(
47
- "Generate a report for a #{pastel.green('user')} or #{pastel.green('team')}?",
48
- ['User', 'Team']
41
+ 'Generate a report for a '\
42
+ "#{pastel.green('team')} or a specific #{pastel.green('user')}?",
43
+ %w[Team User]
49
44
  )
50
- return [prompt.ask('Which user would you like to analyse?')] if type == 'User'
45
+
46
+ if type == 'User'
47
+ return [
48
+ prompt.ask("Please enter a #{pastel.green('user')}.")
49
+ ]
50
+ end
51
+
51
52
  teams = TempestTime::Settings::Teams
52
- abort('You have no teams yet! Go make one! (tempest teams add)') unless teams.keys.any?
53
+ if teams.keys.empty?
54
+ abort('You have no teams yet! Go make one! (tempest teams add)')
55
+ end
56
+
53
57
  team = prompt.select(
54
- "Which #{pastel.green('team')} would you like to analyse?",
58
+ "Please select a #{pastel.green('team')}.",
55
59
  teams.keys
56
60
  )
57
61
  teams.members(team)
58
62
  end
59
63
 
60
- def week_prompt
61
- week = TTY::Prompt.new.select(
62
- 'Please select the week to report.',
63
- week_ranges,
64
- default: current_week,
65
- per_page: 5
64
+ def start_date
65
+ @start_date ||= week_dates(@week).first
66
+ end
67
+
68
+ def end_date
69
+ @end_date ||= week_dates(@week).last
70
+ end
71
+
72
+ def reports
73
+ @reports ||= @users.map do |user|
74
+ list = TempoAPI::Requests::ListWorklogs.new(
75
+ start_date,
76
+ end_date,
77
+ user
78
+ ).send_request
79
+ TempestTime::Models::Report.new(user, list.worklogs)
80
+ end || []
81
+ end
82
+
83
+ def aggregate
84
+ @aggregate ||= TempestTime::Models::Report.new(
85
+ 'TOTAL',
86
+ reports.flat_map(&:worklogs),
87
+ @users.count
66
88
  )
67
- week_ranges.find_index(week) + 1
89
+ end
90
+
91
+ def projects
92
+ @projects ||= reports.flat_map(&:projects).uniq
68
93
  end
69
94
 
70
95
  def table_headings
71
- %w[User COMP% UTIL%] + report.projects
96
+ %w[User COMP% UTIL%] + projects
72
97
  end
73
98
 
74
99
  def render_table
75
100
  t = table.new(
76
101
  table_headings,
77
- report.reports.map { |r| row(r) } + [row(report.aggregate)]
102
+ reports.map { |r| row(r) } + [row(aggregate)]
78
103
  )
79
104
 
80
105
  t.render(:ascii, padding: [0, 1])
81
106
  end
82
107
 
83
- def row(r)
108
+ def row(data)
84
109
  row = [
85
- r.user,
86
- r.total_compliance_percentage.round(2),
87
- r.utilization_percentage.round(2)
110
+ data.user,
111
+ percentage(data.total_compliance_percentage),
112
+ percentage(data.utilization_percentage)
88
113
  ]
89
- report.projects.each do |project|
90
- row.push(r.project_compliance_percentages.to_h.fetch(project, 0).round(2))
114
+ projects.each do |project|
115
+ row.push(
116
+ percentage(data.project_compliance_percentages.to_h.fetch(project, 0))
117
+ )
91
118
  end
92
119
  row
93
120
  end
121
+
122
+ def percentage(decimal)
123
+ (decimal * 100).to_i.to_s + '%'
124
+ end
94
125
  end
95
126
  end
96
127
  end
@@ -16,28 +16,16 @@ module TempestTime
16
16
  def execute(input: $stdin, output: $stdout)
17
17
  # Command logic goes here ...
18
18
  reviewer = prompt.ask('Who should review this timesheet? (username)')
19
- week_number = week_prompt
19
+ dates = week_dates(week_prompt('Select a week to submit.'))
20
20
 
21
21
  message = 'Submit the selected timesheet to ' + pastel.green(reviewer) + '?'
22
22
  abort unless prompt.yes?(message)
23
23
  abort unless prompt.yes?('Are you sure? No edits can be made once submitted!')
24
24
 
25
25
  with_success_fail_spinner("Submitting your timesheet...") do
26
- TempoAPI::Requests::SubmitTimesheet.new(reviewer, week_number).send_request
26
+ TempoAPI::Requests::SubmitTimesheet.new(reviewer, dates).send_request
27
27
  end
28
28
  end
29
-
30
- private
31
-
32
- def week_prompt
33
- week = TTY::Prompt.new.select(
34
- 'Please select the week to submit.',
35
- week_ranges,
36
- default: current_week,
37
- per_page: 5
38
- )
39
- week_ranges.find_index(week) + 1
40
- end
41
29
  end
42
30
  end
43
31
  end
@@ -20,7 +20,7 @@ module TempestTime
20
20
  TempestTime::Commands::Teams::Edit.new(options).execute
21
21
  end
22
22
 
23
- desc 'delete', 'Edit a team.'
23
+ desc 'delete', 'Delete a team.'
24
24
  def delete(*)
25
25
  require_relative 'teams/delete'
26
26
  TempestTime::Commands::Teams::Delete.new(options).execute
@@ -13,11 +13,15 @@ module TempestTime
13
13
  return time.chomp('m').to_i * 60
14
14
  end
15
15
 
16
- abort("Please provide time in the correct format. e.g. 0.5h, .5h, 30m")
16
+ abort('Please provide time in the correct format. e.g. 0.5h, .5h, 30m')
17
17
  end
18
18
 
19
19
  def formatted_time(seconds)
20
- seconds < 3600 ? "#{seconds / 60} minutes" : "#{(seconds / 3600.to_f).round(2)} hours"
20
+ if seconds < 3600
21
+ "#{seconds / 60} minutes"
22
+ else
23
+ "#{(seconds / 3600.to_f).round(2)} hours"
24
+ end
21
25
  end
22
26
 
23
27
  def formatted_date_range(start_date, end_date)
@@ -26,46 +30,45 @@ module TempestTime
26
30
  end
27
31
 
28
32
  def formatted_date(date)
29
- "#{Date::DAYNAMES[date.wday]}, #{Date::MONTHNAMES[date.month]} #{date.day}"
33
+ Date::DAYNAMES[date.wday] +
34
+ ', ' +
35
+ Date::MONTHNAMES[date.month] +
36
+ ' ' +
37
+ date.day.to_s
30
38
  end
31
39
 
32
- def parsed_date_input(date_input)
33
- case date_input
34
- when 'today', nil
35
- [Date.today]
36
- when 'yesterday'
37
- [Date.today.prev_day]
38
- when 'week', 'thisweek'
39
- week_dates(current_week)
40
- when 'lastweek'
41
- week_dates(current_week - 1)
42
- else
43
- [Date.parse(date_input)]
44
- end
40
+ def beginning_of_week(weeks_ago = 0)
41
+ return unless weeks_ago >= 0
42
+ (Date.today - Date.today.wday) - (weeks_ago * 7)
45
43
  end
46
44
 
47
- def current_week
48
- # Helper method to make weeks start on Sunday instead of Monday.
49
- @current_week ||= (Date.today + 1).cweek
45
+ def end_of_week(weeks_ago = 0)
46
+ beginning_of_week(weeks_ago) + 6
50
47
  end
51
48
 
52
- def beginning_of_week(week_number)
53
- return unless week_number.positive? && week_number < 53
54
- (Date.today - Date.today.wday) - ((current_week - week_number) * 7)
49
+ def week_beginnings(number_of_weeks)
50
+ (0..number_of_weeks).map { |weeks_ago| beginning_of_week(weeks_ago) }
55
51
  end
56
52
 
57
- def week_beginnings
58
- @week_beginnings ||= (1..52).map { |week_number| beginning_of_week(week_number) }
53
+ def past_week_selections(number_of_weeks)
54
+ weeks = {}
55
+ week_beginnings(number_of_weeks).each do |beginning|
56
+ weeks[formatted_date_range(beginning, beginning + 6)] = beginning
57
+ end
58
+ weeks
59
59
  end
60
60
 
61
- def week_ranges
62
- @week_ranges ||= week_beginnings.map do |start_date|
63
- formatted_date_range(start_date, start_date + 6)
61
+ def past_date_selections(number_of_days)
62
+ dates = {}
63
+ (0..number_of_days).each do |n|
64
+ date = Date.today - n
65
+ dates[formatted_date(date)] = date
64
66
  end
67
+ dates
65
68
  end
66
69
 
67
- def week_dates(week_number)
68
- (0..6).map { |days| beginning_of_week(week_number) + days }
70
+ def week_dates(first_day)
71
+ (0..6).map { |days| first_day + days }
69
72
  end
70
73
  end
71
74
  end
@@ -1,3 +1,3 @@
1
1
  module TempestTime
2
- VERSION = '0.5.2'.freeze
2
+ VERSION = '0.5.3'.freeze
3
3
  end
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.5.2
4
+ version: 0.5.3
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-03 00:00:00.000000000 Z
11
+ date: 2019-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -466,7 +466,6 @@ files:
466
466
  - lib/tempest_time/helpers/formatting_helper.rb
467
467
  - lib/tempest_time/helpers/time_helper.rb
468
468
  - lib/tempest_time/models/report.rb
469
- - lib/tempest_time/services/generate_report.rb
470
469
  - lib/tempest_time/setting.rb
471
470
  - lib/tempest_time/settings/authorization.rb
472
471
  - lib/tempest_time/settings/teams.rb
@@ -1,49 +0,0 @@
1
- require_relative '../helpers/time_helper'
2
- require_relative '../api/tempo_api/requests/list_worklogs'
3
- require_relative '../models/report'
4
-
5
- module TempestTime
6
- module Services
7
- class GenerateReport
8
- include TempestTime::Helpers::TimeHelper
9
-
10
- attr_reader :users, :week_number, :reports
11
-
12
- def initialize(users, week_number)
13
- @users = users
14
- @week_number = week_number || Date.today.cweek
15
- @reports = build_reports
16
- end
17
-
18
- def projects
19
- @projects ||= reports.flat_map(&:projects).uniq
20
- end
21
-
22
- def aggregate
23
- @aggregate ||= TempestTime::Models::Report.new(
24
- 'TOTAL',
25
- reports.flat_map(&:worklogs),
26
- users.count
27
- )
28
- end
29
-
30
- def start_date
31
- @start_date ||= beginning_of_week(week_number)
32
- end
33
-
34
- def end_date
35
- @end_date ||= start_date + 6
36
- end
37
-
38
- private
39
-
40
- def build_reports
41
- users.map do |user|
42
- request = TempoAPI::Requests::ListWorklogs.new(start_date, end_date, user)
43
- request.send_request
44
- TempestTime::Models::Report.new(user, request.response.worklogs)
45
- end || []
46
- end
47
- end
48
- end
49
- end