Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
d89bb15
bugfix: backup multiple boards
Jan 5, 2012
942664f
merged upstream
Jan 6, 2012
9ae7fca
refactoring to object
Jan 6, 2012
d55352a
Extracted code from example usage
Jan 6, 2012
cee09ca
basic csv support
Jan 6, 2012
fb81e71
Revising example to backup lists and cards for multiple boards
Jan 8, 2012
df09923
Merge branch 'master' of https://github.com/lmatteis/node-trello
Jan 8, 2012
cc01a68
Corrected typo
Jan 8, 2012
0f54e21
Merge branch 'master' of https://github.com/adcloud/node-trello into …
Jan 8, 2012
4a68ba7
Corrected typo
Jan 8, 2012
85d094c
Merge remote branch 'mybranch/master'
Jan 8, 2012
8714c77
Added recursive CSV to create CSV with one row per card including all…
Jan 9, 2012
e893ea4
Merge branch 'master' of git://github.com/lmatteis/node-trello
Jan 10, 2012
9822514
Merge branch 'master' of https://github.com/naven87/node-trello
Jan 10, 2012
e6ba238
whitespace cleanup
Jan 10, 2012
6f3b445
added ability to ignore certain attributes in the backup
Jan 10, 2012
917edce
refactoring: createCSVTitle & createCSVData
Jan 10, 2012
55b27b1
refactoring: new function convertToCSVField
Jan 10, 2012
d91a7dc
started with a stats example
Jan 10, 2012
dddfcab
refactoring and tests
Jan 11, 2012
cd3250a
wrong variable name
Jan 11, 2012
fe212fa
use better parameter names
Mar 21, 2012
44ba6c1
backup data in own directory
Mar 21, 2012
8752082
complete rewrite: creates a flat json object first and converts it in…
Mar 22, 2012
756261b
append Start und Finished Time
Mar 22, 2012
f9a7244
- moved to waterfall. now methods are more independent
Mar 27, 2012
21527c9
first tests on basis of sanboxed-module
Mar 27, 2012
0e97d38
testfix
Mar 28, 2012
6857555
removed old stats examples
Mar 28, 2012
980f31c
moved api in node_module
Mar 28, 2012
736f065
readme
Mar 28, 2012
b212de8
rename to trello-stats
Mar 28, 2012
dcdfa91
rename to stats
Mar 28, 2012
5ac6eb0
fallback for start / finished date
Mar 28, 2012
fe2f447
append feature areas
Mar 28, 2012
2af01dc
rename
Mar 28, 2012
f4647f8
format
Mar 28, 2012
a4ce658
tests for appendListAndCardInfos
Mar 28, 2012
8379802
-apifix: open cards
luebken Jul 2, 2012
3a5f33c
specify boards from the outside
luebken Jul 2, 2012
e7cb250
new usage comments
luebken Jul 2, 2012
43002ba
green tests via uncommenting - no comment
luebken Jul 3, 2012
f64ee6f
async lib
luebken Jul 3, 2012
56fa87d
jasmine lib
luebken Jul 3, 2012
cb8a9c8
lib sandboxed-module
luebken Jul 3, 2012
0d6fe38
primitive calculation of working hours
luebken Jul 3, 2012
ccdf5ad
working time mo-fr 9-12 & 13-18
luebken Jul 3, 2012
42be805
temp bug fix for inconsistent data
luebken Jul 3, 2012
79400ab
lib moment
luebken Jul 3, 2012
1ec181f
try to get latest date. even if its not in a released column
luebken Sep 28, 2012
bb4802b
Fix for smallest release date
luebken Sep 28, 2012
9057d16
bugfixes
luebken Sep 28, 2012
7fd4073
test for filter released
luebken Oct 2, 2012
83a8011
tests for appendListAndCardInfos
luebken Oct 2, 2012
f557e0a
cleanup
luebken Oct 2, 2012
c68c893
added tests for appendDateAndVersionFromListTitle
luebken Oct 2, 2012
de294a8
moved tests around
luebken Oct 2, 2012
a3570ce
tests for appendmemberinfos
luebken Oct 2, 2012
dea6dd2
first tests for appendmembernames
luebken Oct 2, 2012
fb62740
first tests for appendStartAndDone
luebken Oct 12, 2012
ec516ae
config in gitignore
luebken Oct 12, 2012
06de9c7
gitignore
luebken Oct 12, 2012
ad471bc
init
luebken Oct 12, 2012
bfe9bc7
hello
luebken Oct 12, 2012
23698f0
heroku
luebken Oct 12, 2012
d1ec7db
yes
Oct 12, 2012
552fa4f
test pull request
luebken Oct 12, 2012
02f0a85
Merge pull request #1 from adcloud/test-pull-request
Velrok Oct 12, 2012
cbae281
Write file moved to main.js
luebken Oct 12, 2012
ff9e108
'stats' route zum download
luebken Oct 12, 2012
4d1bb8b
Merge pull request #2 from adcloud/csv-downloadable
luebken Oct 12, 2012
d957a69
unnecessary require
luebken Oct 12, 2012
ca2b31a
removed main.js
luebken Oct 12, 2012
a4731d3
error message and default values for tello environment vars
Oct 12, 2012
5d27861
Merge branch 'master' into fix-config-missing-error
Oct 12, 2012
1fb070d
fixes syntax error in config
Oct 12, 2012
fa31758
use config module in main.js
Oct 12, 2012
1562d7c
throwing error inset of log messages, because the application can not…
Oct 12, 2012
26da977
Merge pull request #3 from adcloud/fix-config-missing-error
luebken Oct 12, 2012
748b755
very simple authentication
luebken Oct 12, 2012
30ef28f
merged
luebken Oct 12, 2012
f6ec08d
moved password in environment
luebken Oct 12, 2012
3e7cdbd
Merge pull request #4 from adcloud/auth
luebken Oct 12, 2012
77591cb
removed deprecated express warning
luebken Oct 12, 2012
64b1812
Integrated Twitter Bootstrap
luebken Oct 12, 2012
0219cf9
button styling
luebken Oct 12, 2012
e16c01e
we can now load resource files form the public folder
Oct 12, 2012
32c2e36
Merge branch 'serve-files-in-public'
Oct 12, 2012
105088f
switched port back to 5000
Oct 12, 2012
507f288
revered poor man resource serving
Oct 12, 2012
ce14c10
stated working on dashboard
Oct 12, 2012
b3a9729
see stats in a table
luebken Oct 12, 2012
58ac586
Merge branch 'master' of github.com:adcloud/trello-stats
luebken Oct 12, 2012
594a604
simple table with google charts
luebken Oct 12, 2012
db06769
correct column titles
luebken Oct 12, 2012
d945189
cleanup
luebken Oct 12, 2012
a139707
fewer logging
luebken Oct 12, 2012
d715caf
clean up
luebken Oct 12, 2012
6866560
each board of the three teams visual
luebken Oct 12, 2012
71171cd
removed dorment index.html
Oct 13, 2012
1628208
introduced lib and spec folder
luebken Oct 13, 2012
169896a
Merge branch 'master' of github.com:adcloud/trello-stats
Oct 13, 2012
79892fc
dummy api route
luebken Oct 13, 2012
51a1493
Merge branch 'master' of github.com:adcloud/trello-stats
Oct 13, 2012
d5128d2
dummy burnup charts for dashboard
Oct 13, 2012
75b6a49
extract sprint range
luebken Oct 13, 2012
11ef41c
returning real sprint range
luebken Oct 13, 2012
2f274ba
Merge branch 'master' of github.com:adcloud/trello-stats
luebken Oct 13, 2012
5554f63
using the api to fetch data now
Oct 13, 2012
4e8bf69
Merge branch 'master' of github.com:adcloud/trello-stats
luebken Oct 13, 2012
9334c63
enhancing all cards with actions
luebken Oct 13, 2012
e616c13
new function getCardsWithActions
luebken Oct 13, 2012
313682a
very simplified version of total points
luebken Oct 13, 2012
8e26ea5
fixes burnup graph. xAxis is still little bit off and prediction line…
Oct 13, 2012
e770207
Merge branch 'master' of github.com:adcloud/trello-stats
Oct 13, 2012
6df47aa
first step to basic support for points
luebken Oct 13, 2012
e3e4374
new method for sprint: adduntilend
luebken Oct 15, 2012
52348d0
reactivated total points
luebken Oct 15, 2012
00887b0
Renaming, indention fix. documentation, cleanup
luebken Oct 15, 2012
1b18447
ignoring backlog for burndowns
luebken Oct 16, 2012
ee6ca79
first menu item
luebken Oct 16, 2012
4105f6b
extract header to layout.jade file
luebken Oct 16, 2012
d613c08
layout for stats view
luebken Oct 16, 2012
7994acd
First Google Chart integration
luebken Oct 16, 2012
2c531d6
async with progress indicator
luebken Oct 16, 2012
c55db7c
some texts
luebken Oct 17, 2012
59a7ad0
jasmine-node 1.0.26
luebken Oct 17, 2012
d3c7d85
moved test call into npm (hi timo ;-)
luebken Oct 17, 2012
e528a7c
Travis integration
luebken Oct 17, 2012
4cd93af
fixed travis icon
luebken Oct 17, 2012
847d44e
mark points uncertain if the dates have not passed
luebken Oct 17, 2012
8777e7f
total points takes into account created date
luebken Oct 19, 2012
4b524ad
bugfix für knick am ende
luebken Oct 19, 2012
b0d76c3
better error logging in case of api errors
luebken Oct 29, 2012
10306db
better logging if board error
luebken Oct 29, 2012
7d65867
better error messaging
luebken Nov 6, 2012
94ed9ce
logging
luebken Dec 14, 2012
44861ec
better error message
luebken Dec 14, 2012
7e66a2c
better logging message and fetching all cards
luebken Dec 14, 2012
2d1f8f2
filter passed a certain date
luebken Dec 14, 2012
090af5f
fixed broken test. now testing to sprint_end not sprint_range
luebken Dec 17, 2012
f6fefca
removed appendMemberInfos
luebken Dec 17, 2012
82f4fa0
reading member_added and member_removed actions
luebken Dec 18, 2012
898a9ce
better logging in case of error
luebken Dec 18, 2012
6683557
removing old member duplicate code
luebken Dec 18, 2012
9b24643
first test for appendMemberToCardActions
luebken Dec 18, 2012
f4229a5
several things for better timing
luebken Dec 18, 2012
acd10d0
fixed tests
luebken Apr 3, 2013
e145701
tests
luebken Apr 3, 2013
f77136e
more robust csv export
luebken Apr 3, 2013
ae481ba
card features
luebken Apr 3, 2013
9fc632e
csv export
luebken Apr 3, 2013
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.DS_Store
*.swp
test/
public/javascripts/compiled/*.js
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
language: node_js
node_js:
- 0.6
1 change: 1 addition & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
web: node web.js
30 changes: 6 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
Node wrapper for Trello's HTTP API.
====
Get statistics from Trello based on naming conventions and card data
===

## Example
- configuration in main.js
- start with node main.js
- tests with ./node_modules/jasmine-node/bin/jasmine-node spec/

### Getting the Token

* Public Key & Secret: [visit this link while logged in Trello](https://trello.com/1/appKey/generate).

* With these values [visit this other link](https://trello.com/1/connect?key=<PUBLIC_KEY>&name=MyApp&response_type=token) (Replacing, of course &lt;PUBLIC_KEY&gt; for the public key value obtained).

* Authorice MyApp to read the application

* MyApp now have the token.

### Example Code

````javascript
var Trello = require("node-trello");

var t = new Trello("<your key>", "<token>");

t.get("/1/organization/some-org/boards/all", function(err, data) {
if(err) throw err;
console.log(data);
});
Build status: [![Build Status](https://travis-ci.org/adcloud/trello-stats.png)](https://travis-ci.org/adcloud/trello-stats)
4 changes: 4 additions & 0 deletions backup-data/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore
27 changes: 27 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@

var api_key, api_token;

if (process.env.TRELLO_API_KEY) {
api_key = process.env.TRELLO_API_KEY;
} else {
throw new Error("Environment variable (TRELLO_API_KEY) not set, but required!");
api_key = "";
}

if (process.env.TRELLO_API_TOKEN) {
api_token = process.env.TRELLO_API_TOKEN;
} else {
throw new Error("Environment variable (TRELLO_API_TOKEN) not set, but required!");
api_token = "";
}

if (process.env.TRELLO_STATS_PASSWORD) {
password = process.env.TRELLO_STATS_PASSWORD;
} else {
console.log("Didn't find Password for Trellostats using empty");
password = "";
}

exports.api_key = api_key;
exports.api_token = api_token;
exports.password = password;
28 changes: 0 additions & 28 deletions example_backup.js

This file was deleted.

40 changes: 40 additions & 0 deletions lib/csv.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
var convertToCSV = function(data, callback) {
var csv = "";
var title = data[0];
for(key in title) {
csv += key + ", ";
}
csv = csv.substr(0, csv.length-2);
csv += '\n';

for (var i=0; i < data.length; i++) {
var card = data[i];
for(key in card) {
var prop;
if(card[key] || card[key] === 0) {
prop = card[key].toString();
} else {
console.log('couldnt find property to key ', key)
prop = '<undef>'
}
prop = convertToCSVField(prop);
csv += prop + ", ";
}
csv = csv.substr(0, csv.length-2);
csv += '\n';
}
callback(null, csv);
}


//TODO: preserve quotes, commata and new lines. use csv-standard
var convertToCSVField = function (field) {
field = field.replace(/"/g,' '); // remove "
field = field.replace(/,/g,''); // remove ,
field = field.replace(/\n/g, ' '); // remove new lines
return field;
}


exports.convertToCSVField = module.exports.convertToCSVField = convertToCSVField;
exports.convertToCSV = module.exports.convertToCSV = convertToCSV;
77 changes: 77 additions & 0 deletions lib/sprint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
var moment = require('moment');

// A Sprint object
// Represents a sprint by days with done_points and total_points

var Sprint = function(start, end) {
this.dates = {};
var self = this;
forEachDay(start, end, function(date) {
self.dates[date] = { 'totalpoints':0 , 'donepoints':0 };
});
};

Sprint.prototype.get = function(date) {
for(key in this.dates) {
if(moment(key).format('YYYYDDMM') == moment(date).format('YYYYDDMM')) return this.dates[key];
}
return null;
}

Sprint.prototype.add = function(date, total, done) {
var d = this.get(date);
if(d == null) return;
d.totalpoints += total;
d.donepoints += done;
return;
}

Sprint.prototype.startDate = function() {
//Fixme: Cleaner way to get first key of object
for(key in this.dates) {
return key;
}
}

Sprint.prototype.endDate = function() {
//Fixme: Cleaner way to get last key of object
var end;
for(key in this.dates) {
end = key;
}
return end;
}

Sprint.prototype.addUntilEnd = function(date, total, done) {
var self = this;

//Bugfix: für "Knick" am Ende.
//TODO Ursache recherchieren.
var end = moment(this.endDate()).add('days', 1)

forEachDay(date, end, function(d) {
self.add(d, total, done);
});
return;
}

Sprint.prototype.asArray = function() {
var array = [];
for(key in this.dates) {
array.push({'date':key, 'totalpoints':this.dates[key].totalpoints, 'donepoints':this.dates[key].donepoints })
}
return array;
}

//helper function to iterate over days
function forEachDay(start, end, cb) {
var s = moment(start).clone().minutes(0).seconds(0).milliseconds(0);
var f = moment(end).minutes(0).seconds(0).milliseconds(0);
while(s.unix() <= f.unix()) {
cb(moment(s).clone().toDate())
s.add('days', 1);
}
}


exports = module.exports = Sprint;
151 changes: 151 additions & 0 deletions lib/sprint_board.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
var Trello = require('node-trello'),
moment = require('moment'),
Sprint = require('./sprint'),
async = require('async');

//these functions try to extract sprint informations out of an trello board. based on naming an usage conventions

// main function: calls trello and tries to extract sprint information
var query_sprints = function(api_key, api_token, board_id, callback) {
var api = new Trello(api_key, api_token);
query_cards_and_actions(api, board_id, function(err, lists) {
if(err) {
callback(err)
} else {
var sprint = find_sprint(lists);
if(sprint == null) {
callback( 'Couldnt extract sprintrange for board id ' + board_id + '. Please check naming convention')
return;
}

//total points
lists.forEach(function(list) {
list.cards.forEach(function(card) {
var created = new Date(sprint.startDate());
var points = grep_estimates(card.name);
card.actions.forEach(function(action) {
var actionDate = new Date(action.date);
if(action.type == 'createCard' && actionDate.getTime() > created.getTime()) {
created = actionDate;
}
})
sprint.addUntilEnd(created, points, 0);

});
});

//done points
lists.forEach(function(list) {
list.cards.forEach(function(card) {
card.actions.forEach(function(action) {
if(action.type == 'updateCard' && action.data.listAfter) {
if (action.data.listAfter.name.indexOf('Released:') == 0) {
var points = grep_estimates(card.name);
sprint.addUntilEnd(action.date, 0, points);
}
}
});
})
})

//Make it Google Chart Compatible
var cols = [
{label: 'Datum', type: 'string'},
{label: 'Total', type: 'number'},
{type:'boolean', p: {role: "certainty"}},
{label: 'Done', type: 'number'},
{type:'boolean', p: {role: "certainty"}}
];

var rows = [];
var today = new Date().getTime()
sprint.asArray().forEach(function(item) {
var certain = today > new Date(item.date).getTime();
rows.push({'c': [
{ 'v' : item.date.toString()},
{ 'v' : item.totalpoints},
{ 'v' : certain},
{ 'v' : item.donepoints},
{ 'v' : certain}
]});
});

callback(null, {'cols': cols, 'rows': rows, p: 'Board ' + board_id });
}
});
}

//queries the trello api and gets all cards with actions
var query_cards_and_actions = function(api, board_id, callback) {
api.get('/1/board/' + board_id + '/lists/open', {'cards':'open'}, function(err, lists) {
console.log('Error while quering API ' , err)
if(err) {
callback(err);
} else {

// Ignoring Backlog. Starting with Sprintlog
lists = lists.filter(function(item, index, array) {
return item.name != 'Backlog';
});

console.log('Found ' + lists.length + ' lists');

try {
async.forEach(
lists,
function(list, list_callback) {
//console.log('Got ' + list.cards.length + ' cards');
async.forEach(
list.cards,
function(card, card_ballback) {
api.get('/1/cards/' + card.id + '/actions', {filter:['createCard', 'updateCard']}, function(err, actions) {
//console.log('got action for ' + card.id);
card.actions = actions;
card_ballback();
});
},
function(err) {
list_callback(err)
}
);
},
function(lists_err) {
callback(lists_err, lists)
}
);
} catch(err) {
callback(err);
}
}
});
}


var tick = function() { process.stdout.write('.') };

var grep_estimates = function(cardname) {
var n = cardname.match(/\((\d)\)/);
var estimate = n ? n[1] : 0;
return parseInt(estimate);
}

//based on naming convention one list with "Released: 2012-12-21--2012-23-12 vXXX"
var find_sprint = function(lists) {
var start;
var end;
lists.forEach(function(list) {
var regx = list.name.match(/Released: (\d{4})-(\d{2})-(\d{2})--(\d{4})-(\d{2})-(\d{2}).*$/);
if(regx) {
start = new Date(regx[1], regx[2]-1, regx[3], 12);
end = new Date(regx[4], regx[5]-1, regx[6], 12);
}
});
if(start) {
return new Sprint(start, end);
} else {
return null;
}

}

exports.query_sprints = query_sprints;
Loading