trello_effort_tracker 0.0.3 → 0.0.4

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