mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
data export commit, supports exporting task history via csv
*adds the following new dependencies: moment, express-csv *recommend replacing functionality of 'relative-date' with features from 'moment' *supports retrieval of CSV history via the API and in browser **/api/v1/export/history (requires typical API authorization) **/export/history.csv (requires session authorization) *adds new routes for data export
This commit is contained in:
@@ -42,7 +42,9 @@
|
||||
"validator": "~1.5.1",
|
||||
"nodemailer": "~0.5.2",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"paypal-ipn": "~1.0.1"
|
||||
"paypal-ipn": "~1.0.1",
|
||||
"express-csv": "~0.6.0",
|
||||
"moment": "2.4.0"
|
||||
},
|
||||
"private": true,
|
||||
"subdomain": "habitrpg",
|
||||
|
||||
@@ -61,6 +61,10 @@ window.habitrpg = angular.module('habitrpg',
|
||||
url: "/profile",
|
||||
templateUrl: "partials/options.profile.profile.html"
|
||||
})
|
||||
.state('options.profile.data', {
|
||||
url: "/profile/data",
|
||||
templateUrl: "partials/options.profile.data.html"
|
||||
})
|
||||
|
||||
// Options > Groups
|
||||
.state('options.social', {
|
||||
|
||||
51
src/controllers/dataexport.js
Normal file
51
src/controllers/dataexport.js
Normal file
@@ -0,0 +1,51 @@
|
||||
var _ = require('lodash');
|
||||
var csv = require('express-csv');
|
||||
var User = require('../models/user').model;
|
||||
var nconf = require('nconf');
|
||||
var moment = require('moment');
|
||||
var dataexport = module.exports;
|
||||
|
||||
|
||||
/*
|
||||
------------------------------------------------------------------------
|
||||
Data export
|
||||
------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
dataexport.history = function(req, res) {
|
||||
var user = res.locals.user;
|
||||
var output = [
|
||||
["Task Name", "Task ID", "Task Type", "Date", "Value"]
|
||||
];
|
||||
_.each(user.tasks, function(task) {
|
||||
_.each(task.history, function(history) {
|
||||
output.push(
|
||||
[task.text, task.id, task.type, moment(history.date).format("MM-DD-YYYY HH:mm:ss"), history.value]
|
||||
);
|
||||
});
|
||||
});
|
||||
return res.csv(output);
|
||||
}
|
||||
|
||||
dataexport.auth = function(req, res, next) { //[todo] there is probably a more elegant way of doing this...
|
||||
var uid;
|
||||
uid = req.session.userId;
|
||||
if (!(req.session && req.session.userId)) {
|
||||
return res.json(401, "You must be logged in.");
|
||||
}
|
||||
return User.findOne({
|
||||
_id: uid,
|
||||
}, function(err, user) {
|
||||
if (err) {
|
||||
return res.json(500, {
|
||||
err: err
|
||||
});
|
||||
}
|
||||
if (_.isEmpty(user)) {
|
||||
return res.json(401, "No user found.");
|
||||
}
|
||||
|
||||
res.locals.user = user;
|
||||
return next();
|
||||
});
|
||||
};
|
||||
@@ -4,6 +4,7 @@ var user = require('../controllers/user');
|
||||
var groups = require('../controllers/groups');
|
||||
var auth = require('../controllers/auth');
|
||||
var challenges = require('../controllers/challenges');
|
||||
var dataexport = require('../controllers/dataexport');
|
||||
var nconf = require('nconf');
|
||||
|
||||
/*
|
||||
@@ -25,6 +26,9 @@ router.get('/status', function(req, res) {
|
||||
});
|
||||
});
|
||||
|
||||
/* Data export */
|
||||
router.get('/export/history',auth.auth,dataexport.history); //[todo] encode data output options in the data controller and use these to build routes
|
||||
|
||||
/* Scoring*/
|
||||
router.post('/user/task/:id/:direction', auth.auth, cron, user.scoreTask);
|
||||
router.post('/user/tasks/:id/:direction', auth.auth, cron, user.scoreTask);
|
||||
|
||||
9
src/routes/dataexport.js
Normal file
9
src/routes/dataexport.js
Normal file
@@ -0,0 +1,9 @@
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var dataexport = require('../controllers/dataexport');
|
||||
var nconf = require('nconf');
|
||||
|
||||
/* Data export */
|
||||
router.get('/history.csv',dataexport.auth,dataexport.history); //[todo] encode data output options in the data controller and use these to build routes
|
||||
|
||||
module.exports = router;
|
||||
@@ -116,6 +116,7 @@ if ("development" === app.get("env")) {
|
||||
app.use(require('./routes/pages').middleware);
|
||||
app.use(require('./routes/auth').middleware);
|
||||
app.use('/api/v1', require('./routes/api').middleware);
|
||||
app.use('/export', require('./routes/dataexport').middleware);
|
||||
app.use(require('./controllers/deprecated').middleware);
|
||||
server = http.createServer(app).listen(app.get("port"), function() {
|
||||
return console.log("Express server listening on port " + app.get("port"));
|
||||
|
||||
@@ -121,6 +121,9 @@ script(id='partials/options.profile.profile.html', type='text/ng-template')
|
||||
a(ng-click='removeWebsite($index)')
|
||||
i.icon-remove
|
||||
|
||||
script(id='partials/options.profile.data.html', type="text/ng-template")
|
||||
a(href="/export/history.csv") Export History (CSV)
|
||||
|
||||
script(id='partials/options.profile.html', type="text/ng-template")
|
||||
ul.nav.nav-tabs
|
||||
li(ng-class="{ active: $state.includes('options.profile.avatar') }")
|
||||
@@ -132,6 +135,9 @@ script(id='partials/options.profile.html', type="text/ng-template")
|
||||
li(ng-class="{ active: $state.includes('options.profile.profile') }")
|
||||
a(ui-sref='options.profile.profile')
|
||||
| Profile
|
||||
li(ng-class="{ active: $state.includes('options.profile.data') }")
|
||||
a(ui-sref='options.profile.data')
|
||||
| My Data
|
||||
|
||||
.tab-content
|
||||
.tab-pane.active
|
||||
|
||||
Reference in New Issue
Block a user