trollolo 0.0.5 → 0.0.6

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.
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