pt 0.8.6 → 0.9.0

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.
@@ -3,7 +3,7 @@ require 'iconv' unless "older_ruby?".respond_to?(:force_encoding)
3
3
  module PT
4
4
  class DataRow
5
5
 
6
- attr_accessor :num, :record, :state
6
+ attr_accessor :num, :record, :state, :owners
7
7
 
8
8
  def initialize(orig, dataset)
9
9
  @record = orig
@@ -11,6 +11,10 @@ module PT
11
11
  if defined? orig.current_state
12
12
  @state = orig.current_state
13
13
  end
14
+
15
+ if defined? orig.owners
16
+ @owners = orig.owners.map(&:initials).join(',')
17
+ end
14
18
  end
15
19
 
16
20
  def method_missing(method)
@@ -20,6 +20,9 @@ module PT
20
20
  if config[:max_width] && config[:max_width] < max_width
21
21
  max_width = config[:max_width]
22
22
  end
23
+ headers = [:num]
24
+
25
+ headers += self.class.headers.present? ? self.class.headers : self.class.fields
23
26
 
24
27
  self.class.table @rows, :fields => [:num] + self.class.fields,
25
28
  :change_fields => %w{num pt_id},
@@ -41,6 +44,10 @@ module PT
41
44
  []
42
45
  end
43
46
 
47
+ def self.headers
48
+ []
49
+ end
50
+
44
51
  end
45
52
 
46
53
 
@@ -56,7 +63,11 @@ module PT
56
63
  class TasksTable < DataTable
57
64
 
58
65
  def self.fields
59
- [:name, :state, :id]
66
+ [:name, :owners, :story_type, :estimate, :state, :id]
67
+ end
68
+
69
+ def self.headers
70
+ [:name, :owners, :type, :point, :state, :id]
60
71
  end
61
72
 
62
73
  end
@@ -0,0 +1,271 @@
1
+ module PT
2
+ module Helper
3
+
4
+ GLOBAL_CONFIG_PATH = ENV['HOME'] + "/.pt"
5
+ LOCAL_CONFIG_PATH = Dir.pwd + '/.pt'
6
+
7
+ def load_global_config
8
+
9
+ # skip global config if env vars are set
10
+ if ENV['PIVOTAL_EMAIL'] and ENV['PIVOTAL_API_KEY']
11
+ config = {
12
+ :email => ENV['PIVOTAL_EMAIL'],
13
+ :api_number => ENV['PIVOTAL_API_KEY']
14
+ }
15
+ return config
16
+ end
17
+
18
+ config = YAML.load(File.read(GLOBAL_CONFIG_PATH)) rescue {}
19
+ if config.empty?
20
+ message "I can't find info about your Pivotal Tracker account in #{GLOBAL_CONFIG_PATH}."
21
+ while !config[:api_number] do
22
+ config[:api_number] = ask "What is your token?"
23
+ end
24
+ congrats "Thanks!",
25
+ "Your API id is " + config[:api_number],
26
+ "I'm saving it in #{GLOBAL_CONFIG_PATH} so you don't have to log in again."
27
+ save_config(config, GLOBAL_CONFIG_PATH)
28
+ end
29
+ config
30
+ end
31
+
32
+ def get_local_config_path
33
+ # If the local config path does not exist, check to see if we're in a git repo
34
+ # And if so, try the top level of the checkout
35
+ if (!File.exist?(LOCAL_CONFIG_PATH) && system('git rev-parse 2> /dev/null'))
36
+ return `git rev-parse --show-toplevel`.chomp() + '/.pt'
37
+ else
38
+ return LOCAL_CONFIG_PATH
39
+ end
40
+ end
41
+
42
+ def load_local_config
43
+ check_local_config_path
44
+ config = YAML.load(File.read(get_local_config_path())) rescue {}
45
+
46
+
47
+ if ENV['PIVOTAL_PROJECT_ID']
48
+
49
+ config[:project_id] = ENV['PIVOTAL_PROJECT_ID']
50
+
51
+ @client = Client.new(@global_config[:api_number])
52
+ project = @client.get_project(config[:project_id])
53
+ config[:project_name] = project.name
54
+
55
+ membership = @client.get_my_info
56
+ config[:user_name], config[:user_id], config[:user_initials] = membership.name, membership.id, membership.initials
57
+ save_config(config, get_local_config_path())
58
+
59
+ end
60
+
61
+ if config.empty?
62
+ message "I can't find info about this project in #{get_local_config_path()}"
63
+ @client = Client.new(@global_config[:api_number])
64
+ projects = ProjectTable.new(@client.get_projects)
65
+ project = select("Please select the project for the current directory", projects)
66
+ config[:project_id], config[:project_name] = project.id, project.name
67
+ project = @client.get_project(project.id)
68
+ membership = @client.get_my_info
69
+ config[:user_name], config[:user_id], config[:user_initials] = membership.name, membership.id, membership.initials
70
+ congrats "Thanks! I'm saving this project's info",
71
+ "in #{get_local_config_path()}: remember to .gitignore it!"
72
+ save_config(config, get_local_config_path())
73
+ end
74
+ config
75
+ end
76
+
77
+ def check_local_config_path
78
+ if GLOBAL_CONFIG_PATH == get_local_config_path()
79
+ error("Please execute .pt inside your project directory and not in your home.")
80
+ exit
81
+ end
82
+ end
83
+
84
+ def save_config(config, path)
85
+ File.new(path, 'w') unless File.exists?(path)
86
+ File.open(path, 'w') {|f| f.write(config.to_yaml) }
87
+ end
88
+
89
+ # I/O
90
+
91
+ def split_lines(text)
92
+ text.respond_to?(:join) ? text.join("\n") : text
93
+ end
94
+
95
+ def title(*msg)
96
+ puts "\n#{split_lines(msg)}".bold
97
+ end
98
+
99
+ def congrats(*msg)
100
+ puts "\n#{split_lines(msg).green.bold}"
101
+ end
102
+
103
+ def message(*msg)
104
+ puts "\n#{split_lines(msg)}"
105
+ end
106
+
107
+ def compact_message(*msg)
108
+ puts "#{split_lines(msg)}"
109
+ end
110
+
111
+ def error(*msg)
112
+ puts "\n#{split_lines(msg).red.bold}"
113
+ end
114
+
115
+ def select(msg, table)
116
+ if table.length > 0
117
+ begin
118
+ table.print @global_config
119
+ row = ask "#{msg} (1-#{table.length}, 'n' to fetch next data, 'p' to fetch previous data, 'q' to exit)"
120
+ case row
121
+ when 'q'
122
+ quit
123
+ when 'n'
124
+ return 'n'
125
+ when 'p'
126
+ return 'p'
127
+ end
128
+ selected = table[row]
129
+ error "Invalid selection, try again:" unless selected
130
+ end until selected
131
+ selected
132
+ else
133
+ table.print @global_config
134
+ message "Sorry, there are no options to select."
135
+ quit
136
+ end
137
+ end
138
+
139
+ def quit
140
+ message "bye!"
141
+ exit
142
+ end
143
+
144
+ def ask(msg)
145
+ @io.ask("#{msg.bold}")
146
+ end
147
+
148
+ def ask_secret(msg)
149
+ @io.ask("#{msg.bold}"){ |q| q.echo = '*' }
150
+ end
151
+
152
+ def user_s
153
+ "#{@local_config[:user_name]} (#{@local_config[:user_initials]})"
154
+ end
155
+
156
+ def project_to_s
157
+ "Project #{@local_config[:project_name].upcase}"
158
+ end
159
+
160
+ def task_type_or_nil query
161
+ if (["feature", "bug", "chore"].index query)
162
+ return query
163
+ end
164
+ nil
165
+ end
166
+
167
+ def task_by_id_or_pt_id id
168
+ if id < 1000
169
+ tasks = @client.get_my_work(@local_config[:user_name])
170
+ table = TasksTable.new(tasks)
171
+ table[id]
172
+ else
173
+ @client.get_task_by_id id
174
+ end
175
+ end
176
+
177
+ def find_task query
178
+ members = @client.get_members
179
+ members.each do | member |
180
+ if member.name.downcase.index query
181
+ return member.name
182
+ end
183
+ end
184
+ nil
185
+ end
186
+
187
+ def find_owner query
188
+ if query
189
+ member = @client.get_member(query)
190
+ return member ? member.person : nil
191
+ end
192
+ nil
193
+ end
194
+
195
+
196
+ def show_activity(activity, tasks)
197
+ message("#{activity.message}")
198
+ end
199
+
200
+ def get_open_story_task_from_params(task)
201
+ title "Pending tasks for '#{task.name}'"
202
+ task_struct = Struct.new(:description, :position)
203
+
204
+ pending_tasks = [
205
+ task_struct.new('<< Add new task >>', -1)
206
+ ]
207
+
208
+ task.tasks.each{ |t| pending_tasks << t unless t.complete }
209
+ table = TodoTaskTable.new(pending_tasks)
210
+ select("Pick task to edit, 1 to add new task", table)
211
+ end
212
+
213
+ def edit_story_task(task)
214
+ action_class = Struct.new(:action, :key)
215
+
216
+ table = ActionTable.new([
217
+ action_class.new('Complete', :complete),
218
+ # action_class.new('Delete', :delete),
219
+ action_class.new('Edit', :edit)
220
+ # Move?
221
+ ])
222
+ action_to_execute = select('What to do with todo?', table)
223
+
224
+ task.project_id = project.id
225
+ task.client = project.client
226
+ case action_to_execute.key
227
+ when :complete then
228
+ task.complete = true
229
+ congrats('Todo task completed!')
230
+ # when :delete then
231
+ # task.delete
232
+ # congrats('Todo task removed')
233
+ when :edit then
234
+ new_description = ask('New task description')
235
+ task.description = new_description
236
+ congrats("Todo task changed to: \"#{task.description}\"")
237
+ end
238
+ task.save
239
+ end
240
+
241
+ def save_recent_task( task_id )
242
+ # save list of recently accessed tasks
243
+ unless (@local_config[:recent_tasks])
244
+ @local_config[:recent_tasks] = Array.new();
245
+ end
246
+ @local_config[:recent_tasks].unshift( task_id )
247
+ @local_config[:recent_tasks] = @local_config[:recent_tasks].uniq()
248
+ if @local_config[:recent_tasks].length > 10
249
+ @local_config[:recent_tasks].pop()
250
+ end
251
+ save_config( @local_config, get_local_config_path() )
252
+ end
253
+
254
+ def select_story_from_paginated_table(&block)
255
+ prompt = "Please select a story"
256
+ page = 0
257
+ begin
258
+ stories = block.call(page)
259
+ table = TasksTable.new(stories)
260
+ story = select(prompt, table)
261
+ if story == 'n'
262
+ page+=1
263
+ elsif story == 'p'
264
+ page-=1
265
+ end
266
+ end while story.kind_of?(String)
267
+ story
268
+ end
269
+ end
270
+ end
271
+
@@ -1,3 +1,3 @@
1
1
  module PT
2
- VERSION = '0.8.6'
2
+ VERSION = '0.9.0'
3
3
  end
data/pt.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.summary = "Pivotal Tracker CLI (API v5)"
14
14
  spec.description = "Pivotal Tracker Command Line Interface"
15
15
  spec.executables = ["pt"]
16
-
16
+
17
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
18
  f.match(%r{^(test|spec|features)/})
19
19
  end
@@ -23,10 +23,15 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 1.13"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "pry"
26
+ spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'aruba'
28
+ spec.add_development_dependency 'vcr'
29
+ spec.add_development_dependency 'fakeweb'
26
30
 
27
31
  spec.add_dependency 'hirb', '~> 0.7', '>= 0.7.3'
28
32
  spec.add_dependency 'hirb-unicode', '~> 0.0.5', '>= 0.0.5'
29
33
  spec.add_dependency 'colored', '~> 1.2'
30
34
  spec.add_dependency 'highline'
31
35
  spec.add_dependency 'tracker_api', '~> 1.6.0'
36
+ spec.add_dependency 'thor'
32
37
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.6
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Slamet Kristanto
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2017-02-02 00:00:00.000000000 Z
14
+ date: 2017-02-08 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -55,6 +55,62 @@ dependencies:
55
55
  - - ">="
56
56
  - !ruby/object:Gem::Version
57
57
  version: '0'
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ - !ruby/object:Gem::Dependency
73
+ name: aruba
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ - !ruby/object:Gem::Dependency
87
+ name: vcr
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ - !ruby/object:Gem::Dependency
101
+ name: fakeweb
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ type: :development
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
58
114
  - !ruby/object:Gem::Dependency
59
115
  name: hirb
60
116
  requirement: !ruby/object:Gem::Requirement
@@ -137,6 +193,20 @@ dependencies:
137
193
  - - "~>"
138
194
  - !ruby/object:Gem::Version
139
195
  version: 1.6.0
196
+ - !ruby/object:Gem::Dependency
197
+ name: thor
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ type: :runtime
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
140
210
  description: Pivotal Tracker Command Line Interface
141
211
  email:
142
212
  - cakmet14@gmail.com
@@ -160,12 +230,14 @@ files:
160
230
  - bin/pt
161
231
  - bin/setup
162
232
  - lib/pt.rb
233
+ - lib/pt/action.rb
234
+ - lib/pt/cli.rb
163
235
  - lib/pt/client.rb
164
236
  - lib/pt/data_row.rb
165
237
  - lib/pt/data_table.rb
166
238
  - lib/pt/debugger.rb
239
+ - lib/pt/helper.rb
167
240
  - lib/pt/switch_ssl.rb
168
- - lib/pt/ui.rb
169
241
  - lib/pt/version.rb
170
242
  - pt.gemspec
171
243
  homepage: http://www.github.com/raul/pt