trollolo 0.0.5 → 0.0.6

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
  SHA1:
3
- metadata.gz: dc793ce4458762baaa87ab20d73a5027b393a59b
4
- data.tar.gz: d146b5a8919127354689e1456d92a32abbe3f74f
3
+ metadata.gz: b4ae1e203030317bbb9ec7e96f53ee12c5d81d82
4
+ data.tar.gz: d8943b820b15ce09f72b6147289af3c89ba207b0
5
5
  SHA512:
6
- metadata.gz: aabfadb3c1ef41fced864fea53761768df318e99881e4c3b37a46e9e40e272f0b2b835494a7d69ce9e829941a1fa60088aaf825e29308844651c73d23772d595
7
- data.tar.gz: 6d4972fee9466043300f52b0aa6585118f3d3feb5584ff530c2c34bd02756e8c3b40d02cc23f6761c114e44e8c24ad4a6c90b261df59447c044183136ae641e9
6
+ metadata.gz: 245e86bbe23e00552dd795479d44f271b11643ed82e9516d59541c50ce6b8bcf726de0fb0ab88ba68eb3bdab9f004e4bdb9357d4276c45b008b05855dc8069f5
7
+ data.tar.gz: a732a4c652a3769e90fa3b9c17206adb8c1dc1b5736e952974073ff576de1bf1924118dfdfdf116d63701604b83db2eba4b75cb2021e5bd17d6c4aa222a09e43
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Trollolo Changelog
2
2
 
3
+ ## Version 0.0.6
4
+
5
+ * Track cards with unplanned work separately
6
+ * Fix error when parsing of meta data on card fails
7
+ * Implement `set-cover` command. This command uploads a picture to a given card,
8
+ which is then set as cover.
9
+ * Fix raw output of cards list
10
+ * Fix commands to get basic data
11
+ * Don't overwrite data on first day of sprint
12
+
3
13
  ## Version 0.0.5
4
14
 
5
15
  * Allow done columns which have a name stating with `Done` and do not insist on
data/README.md CHANGED
@@ -46,9 +46,10 @@ For creating a developer key go to the
46
46
  [Developer API Keys](https://trello.com/1/appKey/generate) page on Trello. It's
47
47
  the key in the first box.
48
48
 
49
- For creating a member token go follow the
50
- [instructions](https://trello.com/docs/gettingstarted/index.html#getting-a-token-from-a-user)
51
- in the Trello API documentation.
49
+ For creating a member token use the following URL, replacing `applicationkey` by
50
+ the key you obtained in the first step.
51
+
52
+ https://trello.com/1/authorize?key=applicationkey&name=trollolo&expiration=never&response_type=token
52
53
 
53
54
  The board id is the cryptic string in the URL of your board.
54
55
 
@@ -20,7 +20,6 @@ class BurndownChart
20
20
 
21
21
  def initialize(settings)
22
22
  @settings = settings
23
- @burndown_data = BurndownData.new settings
24
23
 
25
24
  @data = {
26
25
  "meta" => {
@@ -74,7 +73,7 @@ class BurndownChart
74
73
 
75
74
  def add_data(burndown_data)
76
75
  new_entry = burndown_data.to_hash
77
- if entry_exists?(burndown_data.date_time.to_date)
76
+ if entry_exists?(burndown_data.date_time.to_date) && days.length > 1
78
77
  replace_entry(burndown_data.date_time.to_date, new_entry)
79
78
  else
80
79
  days.push(new_entry)
@@ -168,10 +167,15 @@ class BurndownChart
168
167
 
169
168
  def update(options)
170
169
  burndown_data_path = load_last_sprint(options['output'] || Dir.pwd)
171
- @burndown_data.board_id = board_id
172
- @burndown_data.fetch
173
- add_data(@burndown_data)
174
- write_data burndown_data_path
170
+
171
+ burndown_data = BurndownData.new(@settings)
172
+ burndown_data.board_id = board_id
173
+ burndown_data.fetch
174
+
175
+ add_data(burndown_data)
176
+
177
+ write_data(burndown_data_path)
178
+
175
179
  if options[:plot]
176
180
  BurndownChart.plot(self.sprint, options)
177
181
  end
data/lib/burndown_data.rb CHANGED
@@ -34,16 +34,19 @@ class BurndownData
34
34
  end
35
35
 
36
36
  attr_accessor :story_points, :tasks, :extra_story_points, :extra_tasks,
37
+ :unplanned_story_points, :unplanned_tasks,
37
38
  :board_id, :fast_lane_cards, :date_time
38
39
  attr_reader :meta
39
40
 
40
41
  def initialize(settings)
41
- @settings = settings
42
- @story_points = Result.new
43
- @tasks = Result.new
44
- @extra_story_points = Result.new
45
- @extra_tasks = Result.new
46
- @fast_lane_cards = Result.new
42
+ @settings = settings
43
+ @story_points = Result.new
44
+ @tasks = Result.new
45
+ @extra_story_points = Result.new
46
+ @extra_tasks = Result.new
47
+ @unplanned_story_points = Result.new
48
+ @unplanned_tasks = Result.new
49
+ @fast_lane_cards = Result.new
47
50
  end
48
51
 
49
52
  def to_hash
@@ -66,13 +69,22 @@ class BurndownData
66
69
  }
67
70
  }
68
71
  if fast_lane_cards.total > 0
69
- base.merge("fast_lane" => {
70
- "total" => fast_lane_cards.total,
71
- "open" => fast_lane_cards.open
72
- })
73
- else
74
- base
72
+ base["fast_lane"] = {
73
+ "total" => fast_lane_cards.total,
74
+ "open" => fast_lane_cards.open
75
+ }
76
+ end
77
+ if unplanned_story_points.total > 0
78
+ base["unplanned_story_points"] = {
79
+ "total" => unplanned_story_points.total,
80
+ "open" => unplanned_story_points.open
81
+ }
82
+ base["unplanned_tasks"] = {
83
+ "total" => unplanned_tasks.total,
84
+ "open" => unplanned_tasks.open
85
+ }
75
86
  end
87
+ base
76
88
  end
77
89
 
78
90
  def trello
@@ -84,7 +96,7 @@ class BurndownData
84
96
  end
85
97
 
86
98
  def fetch
87
- get_meta
99
+ @meta = get_meta
88
100
  @story_points.done = board.done_story_points
89
101
  @story_points.open = board.open_story_points
90
102
  @tasks.open = board.tasks - board.closed_tasks
@@ -93,6 +105,10 @@ class BurndownData
93
105
  @extra_story_points.open = board.extra_open_story_points
94
106
  @extra_tasks.done = board.extra_closed_tasks
95
107
  @extra_tasks.open = board.extra_tasks - board.extra_closed_tasks
108
+ @unplanned_story_points.done = board.unplanned_done_story_points
109
+ @unplanned_story_points.open = board.unplanned_open_story_points
110
+ @unplanned_tasks.done = board.unplanned_closed_tasks
111
+ @unplanned_tasks.open = board.unplanned_tasks - board.unplanned_closed_tasks
96
112
  @fast_lane_cards.done = board.done_fast_lane_cards_count
97
113
  @fast_lane_cards.open = board.open_fast_lane_cards_count
98
114
  @date_time = DateTime.now
@@ -102,10 +118,12 @@ class BurndownData
102
118
 
103
119
  def get_meta
104
120
  meta_cards = board.meta_cards
105
- return unless meta_cards.any?
121
+ return nil unless meta_cards.any?
106
122
  current_sprint_meta_card = meta_cards.max_by(&:sprint_number)
107
- @meta = Card.parse_yaml_from_description(current_sprint_meta_card.desc)
108
- @meta['sprint'] = current_sprint_meta_card.sprint_number
123
+ meta = Card.parse_yaml_from_description(current_sprint_meta_card.desc)
124
+ return nil unless meta
125
+ meta['sprint'] = current_sprint_meta_card.sprint_number
126
+ meta
109
127
  end
110
128
 
111
129
  end
data/lib/card.rb CHANGED
@@ -29,6 +29,10 @@ class Card
29
29
  @card_data = @board_data["cards"].select{|c| c["id"] == card_id}.first
30
30
  end
31
31
 
32
+ def as_json
33
+ JSON.pretty_generate(@card_data)
34
+ end
35
+
32
36
  def estimated?
33
37
  name =~ ESTIMATED_REGEX
34
38
  end
@@ -66,6 +70,14 @@ class Card
66
70
  @card_data["labels"]
67
71
  end
68
72
 
73
+ def checklists
74
+ checklists = []
75
+ @card_data["checklists"].each do |checklist|
76
+ checklists.push(Checklist.new(checklist))
77
+ end
78
+ checklists
79
+ end
80
+
69
81
  def desc
70
82
  @card_data["desc"]
71
83
  end
@@ -77,6 +89,12 @@ class Card
77
89
  end
78
90
  end
79
91
 
92
+ def unplanned?
93
+ self.card_labels.any? do |label|
94
+ label['name'].include?('Unplanned')
95
+ end
96
+ end
97
+
80
98
  def meta_card?
81
99
  name =~ SPRINT_NUMBER_REGEX
82
100
  end
data/lib/checklist.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Checklist
2
+ def initialize(checklist_data)
3
+ @checklist_data = checklist_data
4
+ end
5
+
6
+ def name
7
+ @checklist_data["name"]
8
+ end
9
+ end
data/lib/cli.rb CHANGED
@@ -73,14 +73,15 @@ EOT
73
73
  process_global_options options
74
74
  require_trello_credentials
75
75
 
76
- trello = Trello.new(board_id: options["board-id"], developer_public_key: @@settings.developer_public_key, member_token: @@settings.member_token)
77
- lists = trello.lists
76
+ trello = TrelloWrapper.new(@@settings)
77
+ board = trello.board(options["board-id"])
78
+ lists = board.columns
78
79
 
79
80
  if @@settings.raw
80
81
  puts JSON.pretty_generate lists
81
82
  else
82
83
  lists.each do |list|
83
- puts "#{list[ "name" ]}"
84
+ puts list.name
84
85
  end
85
86
  end
86
87
  end
@@ -91,78 +92,22 @@ EOT
91
92
  process_global_options options
92
93
  require_trello_credentials
93
94
 
94
- trello = Trello.new(board_id: options["board-id"], developer_public_key: @@settings.developer_public_key, member_token: @@settings.member_token)
95
-
96
- cards = trello.cards
95
+ trello = TrelloWrapper.new(@@settings)
96
+ board = trello.board(options["board-id"])
97
+ cards = board.cards
97
98
 
98
99
  if @@settings.raw
99
- puts JSON.pretty_generate cards
100
- else
101
- burndown = BurndownData.new @@settings
102
- burndown.board_id = options["board-id"]
103
-
104
- todo_list_id = burndown.fetch_todo_list_id
105
- doing_list_id = burndown.fetch_doing_list_id
106
- done_list_id = burndown.fetch_done_list_id
107
-
108
- cards_todo = Array.new
109
- cards_doing = Array.new
110
- cards_done = Array.new
111
-
112
- above_waterline = true
113
-
100
+ cards_as_json = []
114
101
  cards.each do |card|
115
- name = card["name"]
116
- list = card["idList"]
117
- puts "CARD #{name} (#{list})"
118
-
119
- if name == "Waterline"
120
- above_waterline = false
121
- next
122
- end
123
-
124
- if Card.name_to_points(name).nil?
125
- next
126
- end
127
-
128
- if list == todo_list_id && above_waterline
129
- cards_todo.push card
130
- elsif list == doing_list_id
131
- cards_doing.push card
132
- elsif list == done_list_id
133
- cards_done.push card
134
- end
135
- end
136
-
137
- story_points_todo = 0
138
- story_points_doing = 0
139
- story_points_done = 0
140
-
141
- puts
142
-
143
- puts "Todo"
144
- cards_todo.each do |card|
145
- puts " #{card["name"]}"
146
- story_points_todo += Card.name_to_points(card["name"])
147
- end
148
-
149
- puts "Doing"
150
- cards_doing.each do |card|
151
- puts " #{card["name"]}"
152
- story_points_doing += Card.name_to_points(card["name"])
102
+ cards_as_json.push(card.as_json)
153
103
  end
154
-
155
- puts "Done"
156
- cards_done.each do |card|
157
- puts " #{card["name"]}"
158
- story_points_done += Card.name_to_points(card["name"])
104
+ puts "["
105
+ puts cards_as_json.join(",")
106
+ puts "]"
107
+ else
108
+ cards.each do |card|
109
+ puts card.name
159
110
  end
160
-
161
- puts
162
-
163
- story_points_total = story_points_todo + story_points_doing + story_points_done
164
-
165
- puts "Done: #{story_points_done}/#{story_points_total} (#{story_points_doing} in progress)"
166
111
  end
167
112
  end
168
113
 
@@ -172,48 +117,15 @@ EOT
172
117
  process_global_options options
173
118
  require_trello_credentials
174
119
 
175
- trello = Trello.new(board_id: options["board-id"], developer_public_key: @@settings.developer_public_key, member_token: @@settings.member_token)
176
-
177
- data = trello.checklists
178
-
179
- puts JSON.pretty_generate data
120
+ trello = TrelloWrapper.new(@@settings)
121
+ board = trello.board(options["board-id"])
122
+ board.cards.each do |card|
123
+ card.checklists.each do |checklist|
124
+ puts checklist.name
125
+ end
126
+ end
180
127
  end
181
128
 
182
- desc "fetch-burndown-data", "Fetch data for burndown chart"
183
- option "board-id", :desc => "Id of Trello board", :required => true
184
- def fetch_burndown_data
185
- process_global_options options
186
- require_trello_credentials
187
-
188
- burndown = BurndownData.new @@settings
189
- burndown.board_id = options["board-id"]
190
- burndown.fetch
191
-
192
- puts "Story points:"
193
- puts " Open: #{burndown.story_points.open}"
194
- puts " Done: #{burndown.story_points.done}"
195
- puts " Total: #{burndown.story_points.total}"
196
- puts
197
- puts "Tasks:"
198
- puts " Open: #{burndown.tasks.open}"
199
- puts " Done: #{burndown.tasks.done}"
200
- puts " Total: #{burndown.tasks.total}"
201
- puts
202
- puts "Extra story points:"
203
- puts " Open: #{burndown.extra_story_points.open}"
204
- puts " Done: #{burndown.extra_story_points.done}"
205
- puts " Total: #{burndown.extra_story_points.total}"
206
- puts "Extra tasks:"
207
- puts " Open: #{burndown.extra_tasks.open}"
208
- puts " Done: #{burndown.extra_tasks.done}"
209
- puts " Total: #{burndown.extra_tasks.total}"
210
- puts
211
- puts "FastLane Cards:"
212
- puts " Open: #{burndown.fast_lane_cards.open}"
213
- puts " Done: #{burndown.fast_lane_cards.done}"
214
- puts " Total: #{burndown.fast_lane_cards.total}"
215
- end
216
-
217
129
  desc "burndowns", "run multiple burndowns"
218
130
  option "board-list", :desc => "path to board-list.yaml", :required => true
219
131
  option :plot, :type => :boolean, :desc => "also plot the new data"
@@ -250,7 +162,7 @@ EOT
250
162
  puts "Preparing directory..."
251
163
  chart.setup(options[:output],options["board-id"])
252
164
  end
253
-
165
+
254
166
  desc "burndown", "Update burndown chart"
255
167
  option :output, :aliases => :o, :desc => "Output directory", :required => false
256
168
  option :new_sprint, :aliases => :n, :desc => "Create new sprint"
@@ -339,8 +251,18 @@ EOT
339
251
  end
340
252
  end
341
253
 
254
+ desc "set-cover <filename>", "Set cover picture"
255
+ option "card-id", :desc => "Id of card", :required => true
256
+ def set_cover(filename)
257
+ process_global_options(options)
258
+ require_trello_credentials
259
+
260
+ trello = TrelloWrapper.new(@@settings)
261
+ trello.add_attachment(options["card-id"], filename)
262
+ end
263
+
342
264
  private
343
-
265
+
344
266
  def process_global_options options
345
267
  @@settings.verbose = options[:verbose]
346
268
  @@settings.raw = options[:raw]
@@ -354,7 +276,7 @@ EOT
354
276
  @@settings.developer_public_key = STDIN.gets.chomp
355
277
  write_back = true
356
278
  end
357
-
279
+
358
280
  if !@@settings.member_token
359
281
  puts "Put in Trello member token:"
360
282
  @@settings.member_token = STDIN.gets.chomp
@@ -364,7 +286,7 @@ EOT
364
286
  if write_back
365
287
  @@settings.save_config
366
288
  end
367
-
289
+
368
290
  if !@@settings.developer_public_key || !@@settings.member_token
369
291
  STDERR.puts "Require trello credentials in config file"
370
292
  exit 1
data/lib/column.rb CHANGED
@@ -44,8 +44,12 @@ class Column
44
44
  cards.select{|c| c.extra?}
45
45
  end
46
46
 
47
+ def unplanned_cards
48
+ cards.select{|c| c.unplanned?}
49
+ end
50
+
47
51
  def committed_cards
48
- cards.select{|c| !c.extra?}
52
+ cards.select{|c| !c.extra? && !c.unplanned?}
49
53
  end
50
54
 
51
55
  def fast_lane_cards
data/lib/scrum_board.rb CHANGED
@@ -54,6 +54,7 @@ class ScrumBoard
54
54
  committed_cards.map(&:tasks).sum
55
55
  end
56
56
 
57
+
57
58
  def extra_cards
58
59
  (done_column.extra_cards + open_columns.map(&:extra_cards)).flatten(1)
59
60
  end
@@ -82,6 +83,36 @@ class ScrumBoard
82
83
  extra_cards.map(&:done_tasks).sum
83
84
  end
84
85
 
86
+
87
+ def unplanned_cards
88
+ (done_column.unplanned_cards + open_columns.map(&:unplanned_cards)).flatten(1)
89
+ end
90
+
91
+ def unplanned_done_cards
92
+ done_column.unplanned_cards
93
+ end
94
+
95
+ def unplanned_done_story_points
96
+ unplanned_done_cards.map(&:story_points).sum
97
+ end
98
+
99
+ def unplanned_open_cards
100
+ open_columns.map{|col| col.cards.select{|c| c.unplanned?}}.flatten
101
+ end
102
+
103
+ def unplanned_open_story_points
104
+ unplanned_open_cards.map(&:story_points).sum
105
+ end
106
+
107
+ def unplanned_tasks
108
+ unplanned_cards.map(&:tasks).sum
109
+ end
110
+
111
+ def unplanned_closed_tasks
112
+ unplanned_cards.map(&:done_tasks).sum
113
+ end
114
+
115
+
85
116
  def open_fast_lane_cards_count
86
117
  open_columns.map(&:fast_lane_cards).flatten(1).count
87
118
  end
@@ -101,4 +132,13 @@ class ScrumBoard
101
132
  def id
102
133
  @board_data["id"]
103
134
  end
135
+
136
+ def cards
137
+ return @cards if @cards
138
+ @cards = []
139
+ columns.each do |column|
140
+ @cards += column.cards
141
+ end
142
+ @cards
143
+ end
104
144
  end
@@ -50,6 +50,11 @@ class TrelloWrapper
50
50
  Trello::Organization.find(org_id)
51
51
  end
52
52
 
53
+ def add_attachment(card_id, filename)
54
+ card = Trello::Card.find(card_id)
55
+ card.add_attachment(File.open(filename, "rb"))
56
+ end
57
+
53
58
  private
54
59
 
55
60
  def init_trello
data/lib/trollolo.rb CHANGED
@@ -32,6 +32,7 @@ require_relative 'trello_wrapper'
32
32
  require_relative 'burndown_chart'
33
33
  require_relative 'burndown_data'
34
34
  require_relative 'backup'
35
+ require_relative 'checklist'
35
36
 
36
37
  class TrolloloError < StandardError
37
38
  end
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Trollolo
2
2
 
3
- VERSION = "0.0.5"
3
+ VERSION = "0.0.6"
4
4
 
5
5
  end
@@ -0,0 +1 @@
1
+ abc
data/spec/data/board.json CHANGED
@@ -16,6 +16,7 @@
16
16
  "selfJoin": false,
17
17
  "cardCovers": true,
18
18
  "cardAging": "regular",
19
+ "calendarFeedEnabled": false,
19
20
  "background": "5319bb612fb0bcdf451401a8",
20
21
  "backgroundColor": null,
21
22
  "backgroundImage": "https://trello-backgrounds.s3.amazonaws.com/4e727168cb2ac700002cf6b6/990df8f044b98679ccbef943beff54d6/4268316033_6d847a0219_b.jpg",
@@ -57,7 +58,7 @@
57
58
  "blue": "Sticky",
58
59
  "sky": "",
59
60
  "lime": "",
60
- "pink": "",
61
+ "pink": "Unplanned",
61
62
  "black": ""
62
63
  }
63
64
  }
@@ -27,3 +27,9 @@ days:
27
27
  done: 3
28
28
  tasks_extra:
29
29
  done: 2
30
+ story_points_unplanned:
31
+ total: 3
32
+ open: 1
33
+ tasks_unplanned:
34
+ total: 2
35
+ open: 1
@@ -6,4 +6,16 @@ meta:
6
6
  weekend_lines:
7
7
  - 3.5
8
8
  - 7.5
9
- days: []
9
+ days:
10
+ - date: '2015-08-28'
11
+ updated_at: '2015-08-28T11:04:52+02:00'
12
+ story_points:
13
+ total: 24.0
14
+ open: 24.0
15
+ tasks:
16
+ total: 43
17
+ open: 28
18
+ story_points_extra:
19
+ done: 2.0
20
+ tasks_extra:
21
+ done: 5