pt 0.5.8 → 0.6.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.
@@ -1,5 +1,10 @@
1
1
  # pt changelog
2
2
 
3
+ ## v0.6
4
+
5
+ Added command pt started ( Matthijs Groen )
6
+ Added command pt tasks ( Matthijs Groen )
7
+
3
8
  ## v0.5.8
4
9
 
5
10
  Improved support for ruby 1.8 ( Paco Benavent )
data/README.md CHANGED
@@ -16,10 +16,14 @@ Run `pt` from the root folder of your project.
16
16
 
17
17
  pt todo # show all unscheduled tasks
18
18
 
19
+ pt started # show all started stories
20
+
19
21
  pt create [title] ~[owner] ~[type] # create a new task
20
22
 
21
23
  pt show [id] # shows detailed info about a task
22
24
 
25
+ pt tasks [id] # manage tasks of story
26
+
23
27
  pt open [id] # open a task in the browser
24
28
 
25
29
  pt assign [id] [member] # assign owner
@@ -43,8 +47,8 @@ Run `pt` from the root folder of your project.
43
47
  pt done [id] ~[0-3] ~[comment] # lazy mans finish task, does everything
44
48
 
45
49
  pt list [member] # list all tasks for another pt user
46
-
47
- pt list all # list all tasks for all users
50
+
51
+ pt list all # list all tasks for all users
48
52
 
49
53
  pt updates [number] # shows number recent activity from your current project
50
54
 
@@ -69,4 +73,4 @@ You can [open a new issue](https://github.com/raul/pt/issues/new). It can be hel
69
73
  See the LICENSE file included in the distribution.
70
74
 
71
75
  ## Copyright
72
- Copyright (C) 2011 Raul Murciano <raul@murciano.net>.
76
+ Copyright (C) 2011 Raul Murciano <raul@murciano.net>.
data/lib/pt.rb CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  module PT
4
4
  class InputError < StandardError; end
5
- VERSION = '0.5.8'
5
+ VERSION = '0.6.0'
6
6
  end
7
7
 
8
8
  require 'pt/client'
@@ -32,7 +32,7 @@ class PT::Client
32
32
  def get_current_iteration(project)
33
33
  PivotalTracker::Iteration.current(project)
34
34
  end
35
-
35
+
36
36
  def get_activities(project, limit)
37
37
  if limit
38
38
  project.activities.all :limit => limit
@@ -61,4 +61,18 @@ module PT
61
61
 
62
62
  end
63
63
 
64
+ class TodoTaskTable < DataTable
65
+
66
+ def self.fields
67
+ [:description]
68
+ end
69
+ end
70
+
71
+ class ActionTable < DataTable
72
+
73
+ def self.fields
74
+ [:action]
75
+ end
76
+ end
77
+
64
78
  end
@@ -32,8 +32,14 @@ class PT::UI
32
32
  PT::TasksTable.new(stories).print @global_config
33
33
  end
34
34
 
35
+ def started
36
+ title("Stories started for #{project_to_s}")
37
+ stories = @project.stories.all(:current_state => 'started')
38
+ PT::TasksTable.new(stories).print @global_config
39
+ end
40
+
35
41
  def list
36
- if @params[0]
42
+ if @params[0]
37
43
  if @params[0] == "all"
38
44
  stories = @client.get_work(@project)
39
45
  PT::TasksTable.new(stories).print @global_config
@@ -64,7 +70,7 @@ class PT::UI
64
70
  title("Let's create a new task:")
65
71
  name = ask("Name for the new task:")
66
72
  end
67
-
73
+
68
74
  unless owner
69
75
  if ask('Do you want to assign it now? (y/n)').downcase == 'y'
70
76
  members = @client.get_members(@project)
@@ -76,7 +82,7 @@ class PT::UI
76
82
  requester = @local_config[:user_name]
77
83
  task_type = ask('Type? (c)hore, (b)ug, anything else for feature)')
78
84
  end
79
-
85
+
80
86
  task_type = case task_type
81
87
  when 'c', 'chore'
82
88
  'chore'
@@ -94,7 +100,7 @@ class PT::UI
94
100
  end
95
101
 
96
102
  def open
97
- if @params[0]
103
+ if @params[0]
98
104
  tasks = @client.get_my_work(@project, @local_config[:user_name])
99
105
  table = PT::TasksTable.new(tasks)
100
106
  task = table[ @params[0].to_i ]
@@ -118,7 +124,7 @@ class PT::UI
118
124
  else
119
125
  title("Tasks for #{user_s} in #{project_to_s}")
120
126
  task = select("Please select a story to comment it", table)
121
- comment = ask("Write your comment")
127
+ comment = ask("Write your comment")
122
128
  end
123
129
  if @client.comment_task(@project, task, comment)
124
130
  congrats("Comment sent, thanks!")
@@ -133,7 +139,7 @@ class PT::UI
133
139
  table = PT::TasksTable.new(tasks)
134
140
  task = table[@params[0].to_i]
135
141
  owner = find_owner @params[1]
136
- else
142
+ else
137
143
  title("Tasks for #{user_s} in #{project_to_s}")
138
144
  tasks = @client.get_tasks_to_assign(@project, @local_config[:user_name])
139
145
  table = PT::TasksTable.new(tasks)
@@ -157,8 +163,8 @@ class PT::UI
157
163
  tasks = @client.get_my_work(@project, @local_config[:user_name])
158
164
  table = PT::TasksTable.new(tasks)
159
165
  task = table[@params[0].to_i]
160
- title("Estimating '#{task.name}'")
161
-
166
+ title("Estimating '#{task.name}'")
167
+
162
168
  if [0,1,2,3].include? @params[1].to_i
163
169
  estimation = @params[1]
164
170
  end
@@ -168,8 +174,8 @@ class PT::UI
168
174
  title("Tasks for #{user_s} in #{project_to_s}")
169
175
  task = select("Please select a story to estimate it", table)
170
176
  end
171
-
172
- estimation ||= ask("How many points you estimate for it? (#{@project.point_scale})")
177
+
178
+ estimation ||= ask("How many points you estimate for it? (#{@project.point_scale})")
173
179
  result = @client.estimate_task(@project, task, estimation)
174
180
  if result.errors.any?
175
181
  error(result.errors.errors)
@@ -178,7 +184,7 @@ class PT::UI
178
184
  end
179
185
  end
180
186
 
181
- def start
187
+ def start
182
188
  if @params[0]
183
189
  tasks = @client.get_my_work(@project, @local_config[:user_name])
184
190
  table = PT::TasksTable.new(tasks)
@@ -188,7 +194,7 @@ class PT::UI
188
194
  tasks = @client.get_my_tasks_to_start(@project, @local_config[:user_name])
189
195
  table = PT::TasksTable.new(tasks)
190
196
  title("Tasks for #{user_s} in #{project_to_s}")
191
- task = select("Please select a story to mark it as started", table)
197
+ task = select("Please select a story to mark it as started", table)
192
198
  end
193
199
  start_task task
194
200
  end
@@ -203,7 +209,7 @@ class PT::UI
203
209
  tasks = @client.get_my_tasks_to_finish(@project, @local_config[:user_name])
204
210
  table = PT::TasksTable.new(tasks)
205
211
  title("Tasks for #{user_s} in #{project_to_s}")
206
- task = select("Please select a story to mark it as finished", table)
212
+ task = select("Please select a story to mark it as finished", table)
207
213
  end
208
214
  finish_task task
209
215
  end
@@ -218,7 +224,7 @@ class PT::UI
218
224
  tasks = @client.get_my_tasks_to_deliver(@project, @local_config[:user_name])
219
225
  table = PT::TasksTable.new(tasks)
220
226
  title("Tasks for #{user_s} in #{project_to_s}")
221
- task = select("Please select a story to mark it as delivered", table)
227
+ task = select("Please select a story to mark it as delivered", table)
222
228
  end
223
229
 
224
230
  deliver_task task
@@ -234,7 +240,7 @@ class PT::UI
234
240
  tasks = @client.get_my_tasks_to_accept(@project, @local_config[:user_name])
235
241
  table = PT::TasksTable.new(tasks)
236
242
  title("Tasks for #{user_s} in #{project_to_s}")
237
- task = select("Please select a story to mark it as accepted", table)
243
+ task = select("Please select a story to mark it as accepted", table)
238
244
  end
239
245
  result = @client.mark_task_as(@project, task, 'accepted')
240
246
  if result.errors.any?
@@ -246,17 +252,45 @@ class PT::UI
246
252
 
247
253
  def show
248
254
  title("Tasks for #{user_s} in #{project_to_s}")
249
- tasks = @client.get_my_work(@project, @local_config[:user_name])
250
- table = PT::TasksTable.new(tasks)
251
- if @params[0]
252
- task = table[@params[0].to_i]
253
- else
254
- task = select("Please select a story to show", table)
255
+ task = get_task_from_params "Please select a story to show"
256
+ unless task
257
+ message("No matches found for '#{@params[0]}', please use a valid pivotal story Id")
258
+ return
255
259
  end
256
-
257
260
  result = show_task(task)
258
261
  end
259
262
 
263
+ def tasks
264
+ title("Open story tasks for #{user_s} in #{project_to_s}")
265
+ task = get_task_from_params "Please select a story to show pending tasks"
266
+ unless task
267
+ message("No matches found for '#{@params[0]}', please use a valid pivotal story Id")
268
+ return
269
+ end
270
+ story_task = get_open_story_task_from_params(task)
271
+
272
+ if story_task.position == -1
273
+ description = ask('Title for new task')
274
+ task.tasks.create(:description => description)
275
+ congrats("New todo task added to \"#{task.name}\"")
276
+ else
277
+ edit_story_task story_task
278
+ end
279
+ end
280
+
281
+ # takes a comma separated list of ids and prints the collection of tasks
282
+ def show_condensed
283
+ title("Tasks for #{user_s} in #{project_to_s}")
284
+ tasks = []
285
+ if @params[0]
286
+ @params[0].each_line(',') do |line|
287
+ tasks << @client.get_task_by_id(line.to_i)
288
+ end
289
+ table = PT::TasksTable.new(tasks)
290
+ table.print
291
+ end
292
+ end
293
+
260
294
  def reject
261
295
  title("Tasks for #{user_s} in #{project_to_s}")
262
296
  if @params[0]
@@ -268,7 +302,7 @@ class PT::UI
268
302
  tasks = @client.get_my_tasks_to_reject(@project, @local_config[:user_name])
269
303
  table = PT::TasksTable.new(tasks)
270
304
  title("Tasks for #{user_s} in #{project_to_s}")
271
- task = select("Please select a story to mark it as rejected", table)
305
+ task = select("Please select a story to mark it as rejected", table)
272
306
  end
273
307
 
274
308
  if @params[1]
@@ -276,7 +310,7 @@ class PT::UI
276
310
  else
277
311
  comment = ask("Please explain why are you rejecting the task.")
278
312
  end
279
-
313
+
280
314
  if @client.comment_task(@project, task, comment)
281
315
  result = @client.mark_task_as(@project, task, 'rejected')
282
316
  congrats("Task rejected, thanks!")
@@ -285,7 +319,7 @@ class PT::UI
285
319
  end
286
320
  end
287
321
 
288
- def done
322
+ def done
289
323
  if @params[0]
290
324
  tasks = @client.get_my_work(@project, @local_config[:user_name])
291
325
  table = PT::TasksTable.new(tasks)
@@ -316,7 +350,7 @@ class PT::UI
316
350
 
317
351
  task = find_my_task_by_task_id task_id
318
352
  finish_task task
319
-
353
+
320
354
  task = find_my_task_by_task_id task_id
321
355
  deliver_task task
322
356
  end
@@ -376,20 +410,20 @@ class PT::UI
376
410
 
377
411
  if @params[0]
378
412
  tasks = @client.get_my_work(@project, @local_config[:user_name])
379
- matched_tasks = tasks.select do | task |
380
- task.name.downcase.index(@params[0]) && task.current_state != 'delivered'
413
+ matched_tasks = tasks.select do |story_task|
414
+ task.name.downcase.index(@params[0]) && story_task.current_state != 'delivered'
381
415
  end
382
416
 
383
- matched_tasks.each do | task |
384
- title("--- [#{(tasks.index task) + 1 }] -----------------")
385
- show_task(task)
417
+ matched_tasks.each do |story_task|
418
+ title("--- [#{(tasks.index story_task) + 1 }] -----------------")
419
+ show_task(story_task)
386
420
  end
387
421
  message("No matches found for '#{@params[0]}'") if matched_tasks.empty?
388
422
  else
389
423
  message("You need to provide a substring for a tasks title.")
390
424
  end
391
425
  end
392
-
426
+
393
427
  def updates
394
428
  activities = @client.get_activities(@project, @params[0])
395
429
  tasks = @client.get_my_work(@project, @local_config[:user_name])
@@ -399,17 +433,19 @@ class PT::UI
399
433
  end
400
434
  end
401
435
 
402
-
403
- def help
436
+
437
+ def help
404
438
  if ARGV[0] && ARGV[0] != 'help'
405
439
  message("Command #{ARGV[0]} not recognized. Showing help.")
406
440
  end
407
-
441
+
408
442
  title("Command line usage")
409
443
  puts("pt # show all available tasks")
410
444
  puts("pt todo # show all unscheduled tasks")
445
+ puts("pt started # show all started stories")
411
446
  puts("pt create [title] ~[owner] ~[type] # create a new task")
412
447
  puts("pt show [id] # shows detailed info about a task")
448
+ puts("pt tasks [id] # manage tasks of story")
413
449
  puts("pt open [id] # open a task in the browser")
414
450
  puts("pt assign [id] [member] # assign owner")
415
451
  puts("pt comment [id] [comment] # add a comment")
@@ -505,6 +541,10 @@ class PT::UI
505
541
  puts "\n#{split_lines(msg)}"
506
542
  end
507
543
 
544
+ def compact_message(*msg)
545
+ puts "#{split_lines(msg)}"
546
+ end
547
+
508
548
  def error(*msg)
509
549
  puts "\n#{split_lines(msg).red.bold}"
510
550
  end
@@ -548,13 +588,13 @@ class PT::UI
548
588
  end
549
589
 
550
590
  def task_type_or_nil query
551
- if (["feature", "bug", "chore"].index query)
591
+ if (["feature", "bug", "chore"].index query)
552
592
  return query
553
593
  end
554
594
  nil
555
595
  end
556
-
557
- def find_task query
596
+
597
+ def find_task query
558
598
  members = @client.get_members(@project)
559
599
  members.each do | member |
560
600
  if member.name.downcase.index query
@@ -563,8 +603,8 @@ class PT::UI
563
603
  end
564
604
  nil
565
605
  end
566
-
567
- def find_my_task_by_task_id task_id
606
+
607
+ def find_my_task_by_task_id task_id
568
608
  tasks = @client.get_my_work(@project, @local_config[:user_name])
569
609
  tasks.each do |task|
570
610
  if task.id == task_id
@@ -573,25 +613,25 @@ class PT::UI
573
613
  end
574
614
  end
575
615
 
576
- def find_owner query
616
+ def find_owner query
577
617
  if query
578
618
  member = @client.get_member(@project, query)
579
619
  return member ? member.name : nil
580
620
  end
581
621
  nil
582
622
  end
583
-
623
+
584
624
  def show_task(task)
585
625
  title task.name
586
626
  estimation = [-1, nil].include?(task.estimate) ? "Unestimated" : "#{task.estimate} points"
587
627
  message "#{task.current_state.capitalize} #{task.story_type} | #{estimation} | Req: #{task.requested_by} | Owns: #{task.owned_by} | Id: #{task.id}"
588
628
  message task.description unless task.description.nil? || task.description.empty?
589
- task.tasks.all.each{ |t| message "- #{t.complete ? "(done) " : "(pend)"} #{t.description}" }
629
+ task.tasks.all.each{ |t| compact_message "- #{t.complete ? "(done) " : "(pend)"} #{t.description}" }
590
630
  task.notes.all.each{ |n| message "#{n.author}: \"#{n.text}\"" }
591
631
  task.attachments.each{ |a| message "#{a.uploaded_by} uploaded: \"#{a.description && a.description.empty? ? "#{a.filename}" : "#{a.description} (#{a.filename})" }\" #{a.url}" }
592
632
  puts task.url
593
633
  end
594
-
634
+
595
635
  def show_activity(activity, tasks)
596
636
  story_id = activity.stories.first.id
597
637
  task_id = nil
@@ -602,5 +642,54 @@ class PT::UI
602
642
  end
603
643
  message("#{activity.description} [#{task_id}]")
604
644
  end
605
-
645
+
646
+ def get_open_story_task_from_params(task)
647
+ title "Pending tasks for '#{task.name}'"
648
+ task_struct = Struct.new(:description, :position)
649
+
650
+ pending_tasks = [
651
+ task_struct.new('<< Add new task >>', -1)
652
+ ]
653
+
654
+ task.tasks.all.each{ |t| pending_tasks << t unless t.complete }
655
+ table = PT::TodoTaskTable.new(pending_tasks)
656
+ todo_task = select("Pick task to edit, 1 to add new task", table)
657
+ end
658
+
659
+ def get_task_from_params(prompt)
660
+ if @params[0]
661
+ task = @client.get_task_by_id(@params[0].to_i)
662
+ else
663
+ tasks = @client.get_my_work(@project, @local_config[:user_name])
664
+ table = PT::TasksTable.new(tasks)
665
+ task = select(prompt, table)
666
+ end
667
+ task
668
+ end
669
+
670
+ def edit_story_task(story_task)
671
+ action_class = Struct.new(:action, :key)
672
+
673
+ table = PT::ActionTable.new([
674
+ action_class.new('Complete', :complete),
675
+ action_class.new('Delete', :delete),
676
+ action_class.new('Edit', :edit)
677
+ # Move?
678
+ ])
679
+ action_to_execute = select('What to do with todo?', table)
680
+
681
+ case action_to_execute.key
682
+ when :complete then
683
+ story_task.update(:complete => true)
684
+ congrats('Todo task completed!')
685
+ when :delete then
686
+ story_task.delete
687
+ congrats('Todo task removed')
688
+ when :edit then
689
+ new_description = ask('New task description')
690
+ story_task.update(:description => new_description)
691
+ congrats("Todo task changed to: \"#{story_task.description}\"")
692
+ end
693
+ end
694
+
606
695
  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.5.8
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-11-16 00:00:00.000000000 Z
14
+ date: 2013-01-23 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: pivotal-tracker
@@ -120,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
120
  version: '0'
121
121
  requirements: []
122
122
  rubyforge_project: pt
123
- rubygems_version: 1.8.24
123
+ rubygems_version: 1.8.23
124
124
  signing_key:
125
125
  specification_version: 3
126
126
  summary: Client to use Pivotal Tracker from the console.