pt 0.5.8 → 0.6.0

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