tempest_time 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
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