abt-cli 0.0.2

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.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/bin/abt +14 -0
  3. data/lib/abt.rb +5 -0
  4. data/lib/abt/asana_client.rb +53 -0
  5. data/lib/abt/cli.rb +103 -0
  6. data/lib/abt/cli/dialogs.rb +67 -0
  7. data/lib/abt/git_config.rb +78 -0
  8. data/lib/abt/harvest_client.rb +58 -0
  9. data/lib/abt/help.rb +56 -0
  10. data/lib/abt/help/cli.rb +59 -0
  11. data/lib/abt/help/markdown.rb +66 -0
  12. data/lib/abt/http_error.rb +45 -0
  13. data/lib/abt/providers.rb +5 -0
  14. data/lib/abt/providers/asana.rb +60 -0
  15. data/lib/abt/providers/asana/base_command.rb +62 -0
  16. data/lib/abt/providers/asana/clear.rb +24 -0
  17. data/lib/abt/providers/asana/clear_global.rb +24 -0
  18. data/lib/abt/providers/asana/current.rb +69 -0
  19. data/lib/abt/providers/asana/harvest_link_entry_data.rb +48 -0
  20. data/lib/abt/providers/asana/init.rb +62 -0
  21. data/lib/abt/providers/asana/move.rb +54 -0
  22. data/lib/abt/providers/asana/pick_task.rb +46 -0
  23. data/lib/abt/providers/asana/projects.rb +30 -0
  24. data/lib/abt/providers/asana/start.rb +22 -0
  25. data/lib/abt/providers/asana/tasks.rb +35 -0
  26. data/lib/abt/providers/harvest.rb +52 -0
  27. data/lib/abt/providers/harvest/base_command.rb +70 -0
  28. data/lib/abt/providers/harvest/clear.rb +24 -0
  29. data/lib/abt/providers/harvest/clear_global.rb +24 -0
  30. data/lib/abt/providers/harvest/current.rb +79 -0
  31. data/lib/abt/providers/harvest/init.rb +61 -0
  32. data/lib/abt/providers/harvest/pick_task.rb +45 -0
  33. data/lib/abt/providers/harvest/projects.rb +29 -0
  34. data/lib/abt/providers/harvest/start.rb +58 -0
  35. data/lib/abt/providers/harvest/stop.rb +51 -0
  36. data/lib/abt/providers/harvest/tasks.rb +36 -0
  37. data/lib/abt/version.rb +5 -0
  38. metadata +138 -0
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ class Harvest
6
+ class Init < BaseCommand
7
+ def self.command
8
+ 'init harvest'
9
+ end
10
+
11
+ def self.description
12
+ 'Pick Harvest project for current git repository'
13
+ end
14
+
15
+ def call
16
+ warn 'Loading projects'
17
+
18
+ projects # Load projects up front to make it obvious that searches are instant
19
+ project = find_search_result
20
+
21
+ remember_project_id(project['id'])
22
+ remember_task_id(nil)
23
+
24
+ print_project(project)
25
+ end
26
+
27
+ private
28
+
29
+ def find_search_result
30
+ loop do
31
+ matches = matches_for_string cli.prompt('Enter search')
32
+ if matches.empty?
33
+ warn 'No matches'
34
+ next
35
+ end
36
+
37
+ warn 'Showing the 10 first matches' if matches.size > 10
38
+ choice = cli.prompt_choice 'Select a project', matches[0...10], true
39
+ break choice unless choice.nil?
40
+ end
41
+ end
42
+
43
+ def matches_for_string(string)
44
+ search_string = sanitize_string(string)
45
+
46
+ projects.select do |project|
47
+ sanitize_string(project['name']).include?(search_string)
48
+ end
49
+ end
50
+
51
+ def sanitize_string(string)
52
+ string.downcase.gsub(/[^\w]/, '')
53
+ end
54
+
55
+ def projects
56
+ @projects ||= Harvest.client.get_paged('projects')
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ class Harvest
6
+ class PickTask < BaseCommand
7
+ def self.command
8
+ 'pick-task harvest[:<project-id>]'
9
+ end
10
+
11
+ def self.description
12
+ 'Pick task for current git repository'
13
+ end
14
+
15
+ def call
16
+ warn project['name']
17
+ task = cli.prompt_choice 'Select a task', tasks
18
+
19
+ remember_project_id(project_id) # We might have gotten the project ID as an argument
20
+ remember_task_id(task['id'])
21
+
22
+ print_task(project, task)
23
+ end
24
+
25
+ private
26
+
27
+ def project
28
+ @project ||= Harvest.client.get("projects/#{project_id}")
29
+ end
30
+
31
+ def tasks
32
+ project_task_assignments.map { |assignment| assignment['task'] }
33
+ end
34
+
35
+ def project_task_assignments
36
+ @project_task_assignments ||= begin
37
+ Harvest.client.get_paged("projects/#{project_id}/task_assignments", is_active: true)
38
+ rescue Abt::HttpError::HttpError # rubocop:disable Layout/RescueEnsureAlignment
39
+ []
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ class Harvest
6
+ class Projects < BaseCommand
7
+ def self.command
8
+ 'projects harvest'
9
+ end
10
+
11
+ def self.description
12
+ 'List all available projects - useful for piping into grep etc.'
13
+ end
14
+
15
+ def call
16
+ projects.map do |project|
17
+ print_project(project)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def projects
24
+ @projects ||= Harvest.client.get_paged('projects', is_active: true)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ class Harvest
6
+ class Start < BaseCommand
7
+ def self.command
8
+ 'start harvest[:<project-id>/<task-id>]'
9
+ end
10
+
11
+ def self.description
12
+ 'Start tracker for current or specified task. Add a relevant provider to link the time entry: E.g. `abt start harvest asana`' # rubocop:disable Layout/LineLength
13
+ end
14
+
15
+ def call
16
+ Current.new(arg_str: arg_str, cli: cli).call unless arg_str.nil?
17
+
18
+ abort('No task selected') if task_id.nil?
19
+
20
+ create_time_entry
21
+
22
+ warn 'Tracker successfully started'
23
+ rescue Abt::HttpError::HttpError => e
24
+ warn e
25
+ abort 'Unable to start tracker'
26
+ end
27
+
28
+ private
29
+
30
+ def create_time_entry
31
+ body = Oj.dump({
32
+ project_id: Abt::GitConfig.local('abt.harvest.projectId'),
33
+ task_id: Abt::GitConfig.local('abt.harvest.taskId'),
34
+ user_id: Harvest.user_id,
35
+ spent_date: Date.today.iso8601
36
+ }.merge(external_link_data), mode: :json)
37
+ Harvest.client.post('time_entries', body)
38
+ end
39
+
40
+ def external_link_data
41
+ @external_link_data ||= begin
42
+ arg_strs = cli.args.join(' ')
43
+ lines = `#{$PROGRAM_NAME} harvest-time-entry-data #{arg_strs}`.split("\n")
44
+
45
+ return {} if lines.empty?
46
+
47
+ # TODO: Make user choose which reference to use by printing the urls
48
+ if lines.length > 1
49
+ abort 'Multiple providers had harvest reference data, only one is supported at a time'
50
+ end
51
+
52
+ Oj.load(lines.first)
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ class Harvest
6
+ class Stop < BaseCommand
7
+ def self.command
8
+ 'stop harvest'
9
+ end
10
+
11
+ def self.description
12
+ 'Stop running harvest tracker'
13
+ end
14
+
15
+ def call
16
+ abort 'No running time entry' if time_entry.nil?
17
+
18
+ Harvest.client.patch("time_entries/#{time_entry['id']}/stop")
19
+ warn 'Harvest time entry stopped'
20
+ print_task(project, task)
21
+ rescue Abt::HttpError::HttpError => e
22
+ warn e
23
+ abort 'Unable to stop time entry'
24
+ end
25
+
26
+ private
27
+
28
+ def project
29
+ time_entry['project']
30
+ end
31
+
32
+ def task
33
+ time_entry['task']
34
+ end
35
+
36
+ def time_entry
37
+ @time_entry ||= begin
38
+ Harvest.client.get_paged(
39
+ 'time_entries',
40
+ is_running: true,
41
+ user_id: Harvest.user_id
42
+ ).first
43
+ rescue Abt::HttpError::HttpError => e # rubocop:disable Layout/RescueEnsureAlignment
44
+ warn e
45
+ abort 'Unable to fetch running time entry'
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ module Providers
5
+ class Harvest
6
+ class Tasks < BaseCommand
7
+ def self.command
8
+ 'tasks harvest'
9
+ end
10
+
11
+ def self.description
12
+ 'List available tasks on project - useful for piping into grep etc.'
13
+ end
14
+
15
+ def call
16
+ project_task_assignments.each do |a|
17
+ project = a['project']
18
+ task = a['task']
19
+
20
+ print_task(project, task)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def project_task_assignments
27
+ @project_task_assignments ||= begin
28
+ Harvest.client.get_paged("projects/#{project_id}/task_assignments", is_active: true)
29
+ rescue Abt::HttpError::HttpError # rubocop:disable Layout/RescueEnsureAlignment
30
+ []
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abt
4
+ VERSION = '0.0.2'
5
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: abt-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Jesper Sørensen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-inflector
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: oj
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.10'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ description:
70
+ email:
71
+ - js@abtion.com
72
+ executables:
73
+ - abt
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - "./lib/abt.rb"
78
+ - "./lib/abt/asana_client.rb"
79
+ - "./lib/abt/cli.rb"
80
+ - "./lib/abt/cli/dialogs.rb"
81
+ - "./lib/abt/git_config.rb"
82
+ - "./lib/abt/harvest_client.rb"
83
+ - "./lib/abt/help.rb"
84
+ - "./lib/abt/help/cli.rb"
85
+ - "./lib/abt/help/markdown.rb"
86
+ - "./lib/abt/http_error.rb"
87
+ - "./lib/abt/providers.rb"
88
+ - "./lib/abt/providers/asana.rb"
89
+ - "./lib/abt/providers/asana/base_command.rb"
90
+ - "./lib/abt/providers/asana/clear.rb"
91
+ - "./lib/abt/providers/asana/clear_global.rb"
92
+ - "./lib/abt/providers/asana/current.rb"
93
+ - "./lib/abt/providers/asana/harvest_link_entry_data.rb"
94
+ - "./lib/abt/providers/asana/init.rb"
95
+ - "./lib/abt/providers/asana/move.rb"
96
+ - "./lib/abt/providers/asana/pick_task.rb"
97
+ - "./lib/abt/providers/asana/projects.rb"
98
+ - "./lib/abt/providers/asana/start.rb"
99
+ - "./lib/abt/providers/asana/tasks.rb"
100
+ - "./lib/abt/providers/harvest.rb"
101
+ - "./lib/abt/providers/harvest/base_command.rb"
102
+ - "./lib/abt/providers/harvest/clear.rb"
103
+ - "./lib/abt/providers/harvest/clear_global.rb"
104
+ - "./lib/abt/providers/harvest/current.rb"
105
+ - "./lib/abt/providers/harvest/init.rb"
106
+ - "./lib/abt/providers/harvest/pick_task.rb"
107
+ - "./lib/abt/providers/harvest/projects.rb"
108
+ - "./lib/abt/providers/harvest/start.rb"
109
+ - "./lib/abt/providers/harvest/stop.rb"
110
+ - "./lib/abt/providers/harvest/tasks.rb"
111
+ - "./lib/abt/version.rb"
112
+ - bin/abt
113
+ homepage: https://github.com/abtion/abt
114
+ licenses:
115
+ - MIT
116
+ metadata:
117
+ homepage_uri: https://github.com/abtion/abt
118
+ source_code_uri: https://github.com/abtion/abt
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ required_rubygems_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ requirements: []
134
+ rubygems_version: 3.0.3
135
+ signing_key:
136
+ specification_version: 4
137
+ summary: Versatile scripts
138
+ test_files: []