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.
- 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
|
[](http://travis-ci.org/xpepper/trello_effort_tracker)
|
2
2
|
[](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
|