trello_effort_tracker 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG +17 -0
  4. data/Gemfile +7 -4
  5. data/Gemfile.lock +27 -13
  6. data/README.md +106 -36
  7. data/Rakefile +1 -1
  8. data/config/config.template.yml +0 -1
  9. data/config/config.yml.trackinguser_for_test +7 -0
  10. data/lib/patches/trello/card.rb +19 -0
  11. data/lib/patches/trello/member.rb +5 -5
  12. data/lib/trello_effort_tracker/tracked_card.rb +17 -10
  13. data/lib/trello_effort_tracker/tracking/base.rb +82 -0
  14. data/lib/trello_effort_tracker/tracking/card_done_tracking.rb +10 -0
  15. data/lib/trello_effort_tracker/tracking/effort_tracking.rb +45 -0
  16. data/lib/trello_effort_tracker/tracking/estimate_tracking.rb +23 -0
  17. data/lib/trello_effort_tracker/tracking/invalid_tracking.rb +19 -0
  18. data/lib/trello_effort_tracker/tracking_factory.rb +22 -0
  19. data/lib/trello_effort_tracker/trello_authorize.rb +4 -20
  20. data/lib/trello_effort_tracker/trello_tracker.rb +5 -10
  21. data/lib/trello_effort_tracker/version.rb +1 -1
  22. data/lib/trello_effort_tracker.rb +7 -1
  23. data/spec/integration/trello_tracker_spec.rb +69 -0
  24. data/spec/patches/trello/card_spec.rb +25 -0
  25. data/spec/spec_helper.rb +46 -1
  26. data/spec/support/database_cleaner.rb +12 -0
  27. data/spec/tracked_card_spec.rb +56 -5
  28. data/spec/tracking/card_done_tracking_spec.rb +18 -0
  29. data/spec/tracking/effort_tracking_spec.rb +114 -0
  30. data/spec/tracking/estimate_tracking_spec.rb +44 -0
  31. data/spec/tracking_factory_spec.rb +42 -0
  32. data/spec/trello_authorize_spec.rb +10 -16
  33. data/spec/trello_configuration_spec.rb +2 -2
  34. data/trello_effort_tracker.gemspec +12 -0
  35. metadata +131 -5
  36. data/lib/trello_effort_tracker/tracking.rb +0 -130
  37. data/spec/tracking_spec.rb +0 -236
data/.gitignore CHANGED
@@ -13,6 +13,8 @@ test/tmp
13
13
  test/version_tmp
14
14
  tmp
15
15
  .tmtags
16
+ .tags
17
+ .tags_sorted_by_file
16
18
 
17
19
  # YARD artifacts
18
20
  .yardoc
@@ -20,6 +22,5 @@ _yardoc
20
22
  doc/
21
23
 
22
24
  config.yml
23
- config.yml.piero
24
25
  mongoid.yml
25
26
  .rvmrc
data/.travis.yml CHANGED
@@ -6,7 +6,6 @@ env:
6
6
  global:
7
7
  - developer_public_key: e/zPNGKOwapoxFWZs/CBTAhaoqrDTkqqz+InOmCUvGBcZBpUxH398nPLv8Hi\nNQSvWuspzqanyNbbQrTA/2XhsWF1gIFX+gNexYM7S+MxtRwUD3cpVT8DzVOS\nMuckdMTEAADVsm92vIX/bUs5igxD4+zfXlhzXUNDrzRlZnsUF2M=
8
8
  - access_token_key: GG1Q8oq7GkaXjP0lbMgvQLLEi+LXOZlwmELqjPk39Exfy8114QUs2ki8nr9n\ndGO+tgOSZsCd/bt9IHxS3WWWU0INSYOTgp/prfsDDgosg7/Elk/b6w1OW0At\nX3VAjMeI0yAGloT6XB58LCFyrj6S2b4vCQqyaHR3tlTHai/5bMQ=
9
- - developer_secret: jnWqZy2L5styLBGfgpZm9Unqog4KBlPTdtSHdFKG4I8PotrJEi6Kt2rSGljX\n8zFiRcnzelZSEEzGxa9z6pSMFuVz5Dkr3EK/Oa4+MpueMOXOoQA3zmty/865\n5Wokr1cEeJJOP/KXmnLgAkvPh9vOn7KEd8IlphsOkv5w+Rlmgb4=
10
9
  - tracker_username=trackinguser
11
10
  - MONGOID_ENV=test
12
11
 
data/CHANGELOG ADDED
@@ -0,0 +1,17 @@
1
+ 0.0.4
2
+ - A card moved into a DONE column is closed
3
+
4
+ 0.0.3
5
+ - When I send a tracking with "DONE" then the card is "closed" (aka "finished")
6
+ - Export all cards in a Google Docs spreadsheet
7
+ - When I card change its name, the tracked card should be updated too
8
+ - A card should tells its estimate error (3)
9
+
10
+ 0.0.2
11
+ - Very simple Rails app on a separate branch, still experimenting
12
+ - Should be able to open a Trello console with a rake task
13
+ - Avoid running the script if already run for that period
14
+ - Tracking data is now persisted in a mongo database
15
+
16
+ 0.0.1
17
+ - Initial Release.
data/Gemfile CHANGED
@@ -1,22 +1,25 @@
1
1
  source :rubygems
2
2
 
3
- gem 'trello_effort_tracker', :path => '.'
3
+ gemspec
4
4
 
5
5
  gem 'ruby-trello', :require => 'trello'
6
- gem 'debugger'
6
+ # gem 'ruby-trello', :require => 'trello', :path => '../ruby-trello' # to hack on the ruby-trello gem itself
7
+
7
8
  gem 'rainbow'
8
9
  gem 'chronic'
9
10
 
10
11
  gem 'mongoid'
11
12
  gem 'bson_ext'
12
13
 
13
- # google docs exporter
14
14
  gem 'google_drive'
15
15
  gem 'highline'
16
16
 
17
- group :test do
17
+ group :test, :development, :spec do
18
18
  gem 'rake'
19
19
  gem 'rspec'
20
+ gem 'simplecov', :require => false, :platforms => [:mri, :mri_19]
20
21
  gem 'rspec-mocks'
21
22
  gem 'mongoid-rspec'
23
+ gem 'database_cleaner'
24
+ gem 'debugger'
22
25
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- trello_effort_tracker (0.0.2)
4
+ trello_effort_tracker (0.0.3)
5
+ bson_ext
6
+ chronic
7
+ google_drive
8
+ highline
9
+ mongoid
10
+ rainbow
11
+ ruby-trello
5
12
 
6
13
  GEM
7
14
  remote: http://rubygems.org/
@@ -13,23 +20,24 @@ GEM
13
20
  i18n (~> 0.6)
14
21
  multi_json (~> 1.0)
15
22
  addressable (2.3.2)
16
- bson (1.8.1)
17
- bson_ext (1.8.1)
18
- bson (~> 1.8.1)
23
+ bson (1.8.2)
24
+ bson_ext (1.8.2)
25
+ bson (~> 1.8.2)
19
26
  builder (3.0.4)
20
27
  chronic (0.9.0)
21
28
  columnize (0.3.6)
22
- debugger (1.2.3)
29
+ database_cleaner (0.9.1)
30
+ debugger (1.3.0)
23
31
  columnize (>= 0.3.1)
24
32
  debugger-linecache (~> 1.1.1)
25
- debugger-ruby_core_source (~> 1.1.5)
33
+ debugger-ruby_core_source (~> 1.1.7)
26
34
  debugger-linecache (1.1.2)
27
35
  debugger-ruby_core_source (>= 1.1.1)
28
- debugger-ruby_core_source (1.1.6)
36
+ debugger-ruby_core_source (1.1.7)
29
37
  diff-lcs (1.1.3)
30
38
  faraday (0.8.4)
31
39
  multipart-post (~> 1.1)
32
- google_drive (0.3.2)
40
+ google_drive (0.3.3)
33
41
  nokogiri (>= 1.4.4, != 1.5.2, != 1.5.1)
34
42
  oauth (>= 0.3.6)
35
43
  oauth2 (>= 0.5.0)
@@ -40,12 +48,12 @@ GEM
40
48
  jwt (0.1.5)
41
49
  multi_json (>= 1.0)
42
50
  mime-types (1.19)
43
- mongoid (3.0.17)
51
+ mongoid (3.0.19)
44
52
  activemodel (~> 3.1)
45
53
  moped (~> 1.2)
46
54
  origin (~> 1.0)
47
55
  tzinfo (~> 0.3.22)
48
- mongoid-rspec (1.5.6)
56
+ mongoid-rspec (1.6.0)
49
57
  mongoid (>= 3.0.1)
50
58
  rake
51
59
  rspec (>= 2.9)
@@ -61,7 +69,7 @@ GEM
61
69
  multi_json (~> 1.0)
62
70
  rack (~> 1.2)
63
71
  origin (1.0.11)
64
- rack (1.4.4)
72
+ rack (1.5.1)
65
73
  rainbow (1.1.4)
66
74
  rake (10.0.3)
67
75
  rest-client (1.6.7)
@@ -73,13 +81,17 @@ GEM
73
81
  rspec-core (2.12.2)
74
82
  rspec-expectations (2.12.1)
75
83
  diff-lcs (~> 1.1.3)
76
- rspec-mocks (2.12.1)
77
- ruby-trello (0.4.4.3)
84
+ rspec-mocks (2.12.2)
85
+ ruby-trello (0.5.0)
78
86
  activemodel
79
87
  addressable (~> 2.3)
80
88
  json
81
89
  oauth (~> 0.4.5)
82
90
  rest-client (~> 1.6.7)
91
+ simplecov (0.7.1)
92
+ multi_json (~> 1.0)
93
+ simplecov-html (~> 0.7.1)
94
+ simplecov-html (0.7.1)
83
95
  tzinfo (0.3.35)
84
96
 
85
97
  PLATFORMS
@@ -88,6 +100,7 @@ PLATFORMS
88
100
  DEPENDENCIES
89
101
  bson_ext
90
102
  chronic
103
+ database_cleaner
91
104
  debugger
92
105
  google_drive
93
106
  highline
@@ -98,4 +111,5 @@ DEPENDENCIES
98
111
  rspec
99
112
  rspec-mocks
100
113
  ruby-trello
114
+ simplecov
101
115
  trello_effort_tracker!
data/README.md CHANGED
@@ -1,78 +1,110 @@
1
1
  [![Build Status](https://secure.travis-ci.org/xpepper/trello_effort_tracker.png)](http://travis-ci.org/xpepper/trello_effort_tracker)
2
2
  [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/xpepper/trello_effort_tracker)
3
3
 
4
- # TrelloEffortTracker
4
+ # Trello Effort Tracker
5
5
 
6
+ ## What is Trello Effort Tracker?
6
7
  The purpose of this tool is to extract and track estimates and actual efforts on Trello cards.
7
- You just have to notify all of your estimates and efforts tracked on your Trello cards using a conventional format.
8
- This tool will extract and store these estimates and actual efforts to let you extract useful key metrics (e.g. estimate errors, remaining efforts, pair programming frequencies, and so on).
8
+ You simply notify all of your estimates and efforts tracked on your Trello cards using a conventional format.
9
+ Trello Effort Tracker will extract and store these estimates and actual efforts to let you extract useful key metrics (e.g. estimate errors, remaining efforts, pair programming frequencies, and so on).
9
10
 
10
- The Trello API is used in readonly mode in this code, so all you need to access is your developer key.
11
- TrelloEffortTracker uses the [Trello API Ruby wrapper](https://github.com/jeremytregunna/ruby-trello) for this purpose.
11
+ ## Why Trello Effort Tracker?
12
+ Trello is a very good surrogate for a physical team board: it's simple and effective, and it can really help when you have a distributed team.
13
+ That said, Trello does not (still) offer a way to track time estimated and actually spent on cards, though many people [ask for that feature](https://trello.com/card/time-tracking/4d5ea62fd76aa1136000000c/1054) on Trello's development board.
14
+
15
+ We had the need to add time tracking to Trello, so we define a simple convention to track estimates and efforts on cards: we use a predefined board member (let's call him 'tracking user') which we sent special notifications to (we call them 'tracking notifications').
16
+ This 'tracking user' will then receives estimates and efforts notifications, and Trello Effort Tracker will collect them in a simple domain model, backed on a persistent storage.
17
+ Moreover, a web app will be soon available to properly present card estimates and efforts. We're working on it.
18
+
19
+ ## More details
20
+ All you need to have to start using Trello Effort Tracker is a Trello account, a Trello board and a board member to use as 'tracking user'.
21
+ You'll also need to know your Trello developer key and generate a proper auth token to have access to the trackinguser's notifications.
22
+ To see how to have these two keys, see [the following section](#api_key).
23
+
24
+ The Trello API is used behind the scenes to read data from the team board.
25
+ Trello Effort Tracker uses the awesome [Trello API Ruby wrapper](https://github.com/jeremytregunna/ruby-trello) for this purpose.
26
+
27
+ ## Installation
28
+
29
+ ```
30
+ # gem install trello_effort_tracker
31
+ ```
32
+
33
+ Full Disclosure: This library is still work-in-progress, so if you find anything missing or not functioning as you expect it to, please [open an issue on github](https://github.com/xpepper/trello_effort_tracker/issues).
12
34
 
13
35
  ## Requirements
14
- * [rvm](https://rvm.io/rvm/install/)
15
36
  * [mongoDB](http://www.mongodb.org/) - mac users with homebrew will just run 'brew install mongodb' to have mongoDB installed on their machine.
37
+ * [rvm](https://rvm.io/rvm/install/) (optional)
16
38
 
17
39
  ## Setup
18
40
  Copy the config template
19
41
 
20
- cp config/config.template.yaml config/config.yml
42
+ ```shell
43
+ cp config/config.template.yaml config/config.yml
44
+ ```
21
45
 
22
46
  and then fill the correct values in the placeholders in config.yml (see _"Where do I get an API key and API secret?"_ section).
23
47
 
24
48
  Then copy the mongoid config template
25
49
 
26
- cp config/mongoid.template.yaml config/mongoid.yml
50
+ ```shell
51
+ cp config/mongoid.template.yaml config/mongoid.yml
52
+ ```
27
53
 
28
54
  and fill the correct values for the mongodb environments ([see here](http://mongoid.org/en/mongoid/docs/installation.html#configuration) to have more details).
29
55
 
30
56
  Then run bundle to get all the required gems:
31
57
 
32
- bundle install
58
+ ```shell
59
+ bundle install
60
+ ```
33
61
 
34
- ### Where do I get an API key and API secret?
35
- Log in as a Trello user and visit [this URL](https://trello.com/1/appKey/generate) to get your developer\_public\_key and the developer\_public\_key.
62
+ ### <a id="api_key"></a>Where do I get an API key?
63
+ Log in to Trello with your account and visit [https://trello.com/1/appKey/generate](https://trello.com/1/appKey/generate) to get your developer\_public\_key.
36
64
 
37
65
  ### Where do I get an API Access Token Key?
38
- You will need an access token to use ruby-trello, which trello tracker depends on. To get it, you'll need to go to this URL:
66
+ To generate a proper access token key, log in to Trello with the 'tracking user' account. Then go to this URL:
39
67
 
40
68
  https://trello.com/1/connect?key=<YOUR_DEVELOPER_PUBLIC_KEY>&name=Trello+Effort+Tracker&response_type=token&scope=read,write&expiration=never
41
69
 
42
- At the end of this process, You'll be told to give some key to the app, this is what you want to put in the access\_token\_key yml prop file.
70
+ At the end of this process, you'll receive a valid access\_token\_key, which is needed by Trello Effort Tracker to fetch all the tracking notifications sent to the 'tracking user'.
43
71
 
44
72
  ## Usage
45
73
  The best way is to use one of the rake task defined, e.g.
46
74
 
47
- rake 'run:today[test]' # will extract today's tracked data and store on the test db
75
+ ```ruby
76
+ rake 'run:today[test]' # will extract today's tracked data and store on the test db
48
77
 
49
- rake run:today # will extract today's tracked data and store on the default (that is development) db
78
+ rake run:today # will extract today's tracked data and store on the default (that is development) db
50
79
 
51
- rake 'run:from_day[2012-11-1, production]' # will extract tracked data starting from November the 1st, 2012 and store them into the production db
80
+ rake 'run:from_day[2012-11-1, production]' # will extract tracked data starting from November the 1st, 2012 and store them into the production db
81
+ ```
52
82
 
53
83
  Or you may just create a TrelloTracker instance and execute its track method.
54
84
 
55
- tracker = TrelloTracker.new
56
- tracker.track
57
-
85
+ ```ruby
86
+ tracker = TrelloTracker.new
87
+ tracker.track
88
+ ```
58
89
  You can set the Trello's auth params in three ways
59
90
 
60
91
  * setting the three auth params via environment variables (ENV object)
61
- * using the config.yml (which remains the default mode)
62
92
  * passing into the constructor a hash containing the auth values, e.g.
93
+ * using the config.yml (which remains the default mode)
63
94
 
64
- tracker = TrelloTracker.new(
65
- "developer_public_key" => "487635b55e6fe9021902fa763b4d101a",
66
- "access_token_key" => "33bed56f2a12a49c9ba1c2d6ad3e2002e11a34358c3f3fe260d7fba746a06203",
67
- "developer_secret" => "ab999c4396493dba4c04ade055eabfdfabdffd0ffd7c281a23234350a993524d")
68
-
69
- tracker.track
95
+ ```ruby
96
+ tracker = TrelloTracker.new(
97
+ "developer_public_key" => "487635b55e6fe9021902fa763b4d101a",
98
+ "access_token_key" => "33bed56f2a12a49c9ba1c2d6ad3e2002e11a34358c3f3fe260d7fba746a06203")
70
99
 
100
+ tracker.track
101
+ ```
71
102
  ### Console
72
103
  You can open a irb console with the ruby-trello gem and this gem loaded, so that you can query the db or the Trello API and play with them
73
104
 
74
- rake console
75
-
105
+ ```ruby
106
+ rake console
107
+ ```
76
108
 
77
109
  ### Storage configuration
78
110
  Tracking data collected from Trello are stored in a MongoDB, as configured in config/mongoid.yml.
@@ -121,20 +153,32 @@ To set an effort just for other Trello users (excluding the current user), just
121
153
 
122
154
  @trackinguser +3p (@alessandrodescovi @michelevincenzi)
123
155
 
156
+ ### Tracking a card as finished (aka DONE)
157
+ Sending a tracking notification with the word DONE
158
+
159
+ @trackinguser DONE
160
+
161
+ will mark the card as closed.
162
+
124
163
  ## Database import/export
125
164
  To export the db you can execute something like:
126
165
 
127
- mongoexport --db trello_effort_tracker_production --collection tracked_cards --out trello_effort_tracker_production.json
166
+ ```shell
167
+ mongoexport --db trello_effort_tracker_production --collection tracked_cards --out trello_effort_tracker_production.json
168
+ ```
128
169
 
129
170
  To reimport that db:
130
171
 
131
- mongoimport --db trello_effort_tracker_production --collection tracked_cards --file trello_effort_tracker_production.json
172
+ ```shell
173
+ mongoimport --db trello_effort_tracker_production --collection tracked_cards --file trello_effort_tracker_production.json
174
+ ```
132
175
 
133
176
  ## Google Docs exporter
134
177
  To export all your tracked cards on a google docs named 'my_sheet' in the 'tracking' worksheet, run
135
178
 
136
- rake "export:google_docs[my_sheet, tracking, production]"
137
-
179
+ ```ruby
180
+ rake "export:google_docs[my_sheet, tracking, production]"
181
+ ```
138
182
  The default env is development.
139
183
 
140
184
  If you provide no name for the spreadsheet, a default name will be used.
@@ -142,18 +186,44 @@ If the spreadsheet name you provide does not exists, it will be created in you g
142
186
 
143
187
  So, running simply
144
188
 
145
- rake export:google_docs
146
-
189
+ ```ruby
190
+ rake export:google_docs
191
+ ```
147
192
  will create (or update) a spreadsheet named "trello effort tracking" using the development db env.
148
193
 
194
+ ## Keeping your tracking database up to date
195
+ You may install a crontab entry to run the trello tracker periodically, for example
196
+
197
+ ```shell
198
+ SHELL=/Users/futur3/.rvm/bin/rvm-shell
199
+ GEMSET="ruby-1.9.3-p194@spikes"
200
+ PROJECT_PATH="/Users/$USER/Documents/workspace/trello_effort_tracker"
201
+ LC_ALL=en_US.UTF-8
202
+
203
+ # m h dom mon dow command
204
+ */10 * * * * rvm-shell $GEMSET -c "cd $PROJECT_PATH; bundle exec rake run:today[production]" >> /tmp/crontab.out 2>&1
205
+ ```
149
206
 
150
207
  ## Roadmap and improvements
151
208
  We develop Trello Effort Tracker using [Trello itself](https://trello.com/board/trello-effort-tracker-roadmap/509c3228dcb1ac3f1c018791).
152
209
 
153
210
  ## Contributing
211
+ To get started, [sign the Contributor License Agreement](http://www.clahub.com/agreements/xpepper/trello_effort_tracker).
212
+
213
+ If you'd like to hack on Trello Effort Tracker, start by forking the repo on GitHub:
214
+
215
+ https://github.com/xpepper/trello_effort_tracker
154
216
 
155
- Several ways you can contribute. Documentation, code, tests, feature requests, bug reports.
217
+ The best way to get your changes merged back into core is as follows:
156
218
 
157
- Pull requests are welcome :)
219
+ 1. Clone down your fork
220
+ 1. Create a thoughtfully named topic branch to contain your change
221
+ 1. Hack away
222
+ 1. Add tests and make sure everything still passes by running `rake spec`
223
+ 1. If you are adding new functionality, document it in the README
224
+ 1. Do not change the version number, we will do that on our end
225
+ 1. If necessary, rebase your commits into logical chunks, without errors
226
+ 1. Push the branch up to GitHub
227
+ 1. Send a pull request for your branch
158
228
 
159
229
  [@pierodibello](http://twitter.com/pierodibello)
data/Rakefile CHANGED
@@ -59,7 +59,7 @@ namespace :export do
59
59
  end
60
60
 
61
61
  task :ensure_environment do
62
- %w{developer_public_key developer_secret access_token_key}.each do |each_name|
62
+ %w{developer_public_key access_token_key}.each do |each_name|
63
63
  unless ENV[each_name] || authorization_params_from_config_file[each_name]
64
64
  puts "ERROR: Missing <#{each_name}> environment variable."
65
65
  exit 1
@@ -1,7 +1,6 @@
1
1
  trello:
2
2
  developer_public_key: <here put the key taken from https://trello.com/1/appKey/generate>
3
3
  access_token_key: <here put the token taken in the 'Reading Private Data' section from https://trello.com/1/appKey/generate>
4
- developer_secret: <here put the Secret (for OAuth signing) taken from https://trello.com/1/appKey/generate>
5
4
 
6
5
  tracker_username: <here put the Trello member used as recipient of the tracking notifications>
7
6
  google_docs_username: <here put your Google Docs username>
@@ -0,0 +1,7 @@
1
+ # read-only access to @trackinguser_for_test/testinguser! boards
2
+ trello:
3
+ developer_public_key: ef7c400e711057d7ba5e00be20139a33
4
+ access_token_key: 9047d8fdbfdc960d41910673e300516cc8630dd4967e9b418fc27e410516362e
5
+
6
+ tracker_username: trackinguser_for_test
7
+ google_docs_username: pietro.dibello@xpeppers.com
@@ -0,0 +1,19 @@
1
+ module Trello
2
+
3
+ class Card
4
+ # Reopening the Trello::Card class to add a method detecting a card moved in a DONE column
5
+ def in_done_column?
6
+ list_name = ""
7
+ begin
8
+ list_name = list.name.strip
9
+ rescue Trello::Error => e
10
+ Trello::Logger.error("Cannot find column for card #{name}")
11
+ end
12
+
13
+ !!(list_name =~ /^DONE/i)
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+
@@ -1,14 +1,14 @@
1
1
  module Trello
2
-
3
2
  class Member
4
- def notifications_from(from_date)
5
- notifications(limit:1000).select(&greater_than_or_equal_to(from_date)).select(&tracking_notification?)
3
+ # Reopening the Trello::Member class to add a notifications helper method
4
+ def notifications_from(starting_date)
5
+ notifications(limit:1000).select(&greater_than_or_equal_to(starting_date)).select(&tracking_notification?)
6
6
  end
7
7
 
8
8
  private
9
9
 
10
- def greater_than_or_equal_to(from_date)
11
- lambda { |notification| Chronic.parse(notification.date) >= from_date }
10
+ def greater_than_or_equal_to(starting_date)
11
+ lambda { |notification| Chronic.parse(notification.date) >= starting_date }
12
12
  end
13
13
 
14
14
  def tracking_notification?
@@ -7,6 +7,7 @@ class TrackedCard
7
7
  field :description
8
8
  field :short_id, type: Integer
9
9
  field :trello_id
10
+ field :done, type: Boolean
10
11
  field :due, type: Date
11
12
  field :closed, type: Boolean
12
13
  field :url
@@ -25,10 +26,10 @@ class TrackedCard
25
26
  end
26
27
 
27
28
  def self.update_or_create_with(trello_card)
28
- card = TrackedCard.find_or_create_by(trello_id: trello_card.id)
29
+ tracked_card = find_or_create_by(trello_id: trello_card.id)
29
30
  trello_card.attributes.delete(:id)
30
- success = card.update_attributes(trello_card.attributes)
31
- return card if success
31
+ updated_successfully = tracked_card.update_attributes(trello_card.attributes.merge(done: trello_card.in_done_column?))
32
+ return tracked_card if updated_successfully
32
33
  end
33
34
 
34
35
  def self.build_from(trello_card)
@@ -38,13 +39,19 @@ class TrackedCard
38
39
  end
39
40
 
40
41
  def add(tracking)
41
- if tracking.estimate? && estimates.none? {|e| e.tracking_notification_id == tracking.estimate.tracking_notification_id}
42
- estimates << tracking.estimate
43
- elsif tracking.effort? && efforts.none? {|e| e.tracking_notification_id == tracking.effort.tracking_notification_id}
44
- efforts << tracking.effort
45
- else
46
- Trello.logger.warn "Ignoring tracking notification: #{tracking}" if tracking.unknown_format?
47
- end
42
+ tracking.add_to(self)
43
+ end
44
+
45
+ def add!(tracking)
46
+ add(tracking) && save!
47
+ end
48
+
49
+ def contains_effort?(effort)
50
+ efforts.any? { |e| e.tracking_notification_id == effort.tracking_notification_id }
51
+ end
52
+
53
+ def contains_estimate?(estimate)
54
+ estimates.any? { |e| e.tracking_notification_id == estimate.tracking_notification_id }
48
55
  end
49
56
 
50
57
  def no_tracking?
@@ -0,0 +1,82 @@
1
+ module Tracking
2
+ module Base
3
+ extend Forwardable
4
+ include TrelloConfiguration
5
+
6
+ TIME_CONVERTERS = {
7
+ 'h' => lambda { |estimate| estimate },
8
+ 'd' => lambda { |estimate| estimate * 8 },
9
+ 'g' => lambda { |estimate| estimate * 8 },
10
+ 'p' => lambda { |estimate| estimate / 2 }
11
+ }
12
+
13
+ DURATION_REGEXP = '(\d+\.?\d*[phdg])'
14
+ DATE_REGEXP = /(\d{2})\.(\d{2})\.(\d{4})/
15
+
16
+ # delegate to the trello notification the member_creator method aliased as 'notifier'
17
+ def_delegator :@tracking_notification, :member_creator, :notifier
18
+
19
+ def initialize(tracking_notification)
20
+ @tracking_notification = tracking_notification
21
+ end
22
+
23
+ def date
24
+ Chronic.parse(date_as_string).to_date
25
+ end
26
+
27
+ def to_s
28
+ "[#{date}] From #{notifier.username.color(:green)}\t on card '#{trello_card.name.color(:yellow)}': #{raw_text}"
29
+ end
30
+
31
+ private
32
+
33
+ def tracking_notification
34
+ @tracking_notification
35
+ end
36
+
37
+ def trello_card
38
+ @trello_card ||= tracking_notification.card
39
+ end
40
+
41
+ def notification_date
42
+ Chronic.parse(tracking_notification.date).to_date
43
+ end
44
+
45
+ def raw_tracking
46
+ raw_text.gsub("@#{tracker_username}", "")
47
+ end
48
+
49
+ def raw_text
50
+ tracking_notification.data['text']
51
+ end
52
+
53
+ def convert_to_hours(duration_as_string)
54
+ return if duration_as_string.nil?
55
+
56
+ time_scale = duration_as_string.slice!(-1)
57
+ converter = TIME_CONVERTERS[time_scale]
58
+ converter.call(Float(duration_as_string))
59
+ end
60
+
61
+ def date_as_string
62
+ case raw_tracking
63
+ when DATE_REGEXP
64
+ day, month, year = raw_tracking.scan(DATE_REGEXP).flatten
65
+ "#{year}-#{month}-#{day}"
66
+ when /yesterday\s+\+#{DURATION_REGEXP}/, /\+#{DURATION_REGEXP}\s+yesterday/
67
+ (notification_date - 1).to_s
68
+ else
69
+ tracking_notification.date
70
+ end
71
+ end
72
+
73
+ def extract_match_from_raw_tracking(regexp)
74
+ extracted = nil
75
+ raw_tracking.scan(regexp) do |match|
76
+ extracted = match.first
77
+ end
78
+
79
+ extracted
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,10 @@
1
+ module Tracking
2
+ class CardDoneTracking
3
+ include Base
4
+
5
+ def add_to(card)
6
+ card.done = true
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,45 @@
1
+ module Tracking
2
+ class EffortTracking
3
+ include Base
4
+
5
+ #TODO: rename to 'amount' ?
6
+ #TODO: avoid recomputing effort every time using a lazy instance variable
7
+ def effort
8
+ effort_amount = convert_to_hours(raw_effort)
9
+ if effort_amount
10
+ total_effort = effort_amount * effort_members.size
11
+ Effort.new(amount: total_effort, date: date, members: effort_members, tracking_notification_id: tracking_notification.id)
12
+ end
13
+ end
14
+
15
+ def add_to(card)
16
+ card.efforts << effort unless card.contains_effort?(effort)
17
+ end
18
+
19
+ private
20
+
21
+ def raw_effort
22
+ extract_match_from_raw_tracking(/\+#{DURATION_REGEXP}/)
23
+ end
24
+
25
+ def effort_members
26
+ @effort_members ||= users_involved_in_the_effort.map do |username|
27
+ Member.build_from(Trello::Member.find(username))
28
+ end
29
+
30
+ @effort_members
31
+ end
32
+
33
+ def users_involved_in_the_effort
34
+ users_involved_in_the_effort = raw_tracking.scan(/@(\w+)/).flatten
35
+ users_involved_in_the_effort << notifier.username unless should_count_only_listed_members?
36
+
37
+ users_involved_in_the_effort
38
+ end
39
+
40
+ def should_count_only_listed_members?
41
+ raw_tracking =~ /\((@\w+\W*\s*)+\)/
42
+ end
43
+
44
+ end
45
+ end