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.
- data/.gitignore +2 -1
- data/.travis.yml +0 -1
- data/CHANGELOG +17 -0
- data/Gemfile +7 -4
- data/Gemfile.lock +27 -13
- data/README.md +106 -36
- data/Rakefile +1 -1
- data/config/config.template.yml +0 -1
- data/config/config.yml.trackinguser_for_test +7 -0
- data/lib/patches/trello/card.rb +19 -0
- data/lib/patches/trello/member.rb +5 -5
- data/lib/trello_effort_tracker/tracked_card.rb +17 -10
- data/lib/trello_effort_tracker/tracking/base.rb +82 -0
- data/lib/trello_effort_tracker/tracking/card_done_tracking.rb +10 -0
- data/lib/trello_effort_tracker/tracking/effort_tracking.rb +45 -0
- data/lib/trello_effort_tracker/tracking/estimate_tracking.rb +23 -0
- data/lib/trello_effort_tracker/tracking/invalid_tracking.rb +19 -0
- data/lib/trello_effort_tracker/tracking_factory.rb +22 -0
- data/lib/trello_effort_tracker/trello_authorize.rb +4 -20
- data/lib/trello_effort_tracker/trello_tracker.rb +5 -10
- data/lib/trello_effort_tracker/version.rb +1 -1
- data/lib/trello_effort_tracker.rb +7 -1
- data/spec/integration/trello_tracker_spec.rb +69 -0
- data/spec/patches/trello/card_spec.rb +25 -0
- data/spec/spec_helper.rb +46 -1
- data/spec/support/database_cleaner.rb +12 -0
- data/spec/tracked_card_spec.rb +56 -5
- data/spec/tracking/card_done_tracking_spec.rb +18 -0
- data/spec/tracking/effort_tracking_spec.rb +114 -0
- data/spec/tracking/estimate_tracking_spec.rb +44 -0
- data/spec/tracking_factory_spec.rb +42 -0
- data/spec/trello_authorize_spec.rb +10 -16
- data/spec/trello_configuration_spec.rb +2 -2
- data/trello_effort_tracker.gemspec +12 -0
- metadata +131 -5
- data/lib/trello_effort_tracker/tracking.rb +0 -130
- data/spec/tracking_spec.rb +0 -236
data/.gitignore
CHANGED
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
|
-
|
3
|
+
gemspec
|
4
4
|
|
5
5
|
gem 'ruby-trello', :require => 'trello'
|
6
|
-
gem '
|
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.
|
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.
|
17
|
-
bson_ext (1.8.
|
18
|
-
bson (~> 1.8.
|
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
|
-
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
77
|
-
ruby-trello (0.
|
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
|
-
#
|
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
|
8
|
-
|
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
|
-
|
11
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
58
|
+
```shell
|
59
|
+
bundle install
|
60
|
+
```
|
33
61
|
|
34
|
-
### Where do I get an API key
|
35
|
-
Log in
|
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
|
-
|
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,
|
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
|
-
|
75
|
+
```ruby
|
76
|
+
rake 'run:today[test]' # will extract today's tracked data and store on the test db
|
48
77
|
|
49
|
-
|
78
|
+
rake run:today # will extract today's tracked data and store on the default (that is development) db
|
50
79
|
|
51
|
-
|
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
|
-
|
56
|
-
|
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
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
217
|
+
The best way to get your changes merged back into core is as follows:
|
156
218
|
|
157
|
-
|
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
|
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
|
data/config/config.template.yml
CHANGED
@@ -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
|
-
|
5
|
-
|
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(
|
11
|
-
lambda { |notification| Chronic.parse(notification.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
|
-
|
29
|
+
tracked_card = find_or_create_by(trello_id: trello_card.id)
|
29
30
|
trello_card.attributes.delete(:id)
|
30
|
-
|
31
|
-
return
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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,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
|