+ stats.js: public APIs for accessing various system stats. Probably needs a better name
* Fix pause placement. Wait for all views ready before placing cursor such that the prompt will display in the right spot
This commit is contained in:
@@ -244,7 +244,7 @@ function getArtFromPath(path, options, cb) {
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if(options.readSauce === true) {
|
||||
readSAUCE(data, function onSauce(err, sauce) {
|
||||
|
||||
@@ -84,6 +84,18 @@ function MenuModule(options) {
|
||||
callback(null);
|
||||
}
|
||||
},
|
||||
function recordCursorPosition(callback) {
|
||||
if(self.shouldPause()) {
|
||||
self.client.once('cursor position report', function cpr(pos) {
|
||||
self.afterArtPos = pos;
|
||||
self.client.log.trace( { position : pos }, 'After art position recorded');
|
||||
callback(null);
|
||||
});
|
||||
self.client.term.write(ansi.queryPos());
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
},
|
||||
function afterArtDisplayed(callback) {
|
||||
self.mciReady(mciData);
|
||||
callback(null);
|
||||
@@ -99,6 +111,31 @@ function MenuModule(options) {
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
this.shouldPause = function() {
|
||||
return 'end' === self.menuConfig.pause || true === self.menuConfig.pause;
|
||||
};
|
||||
|
||||
this.allViewsReady = function() {
|
||||
if(self.shouldPause()) {
|
||||
self.client.term.write(ansi.goto(self.afterArtPos[0], 1));
|
||||
|
||||
// :TODO: really need a client.term.pause() that uses the correct art/etc.
|
||||
theme.displayThemedPause( { client : self.client }, function keyPressed() {
|
||||
self.nextAction();
|
||||
});
|
||||
} else {
|
||||
self.nextAction();
|
||||
}
|
||||
};
|
||||
|
||||
this.nextAction = function() {
|
||||
if(!_.isObject(self.menuConfig.form) && !_.isString(self.menuConfig.prompt) &&
|
||||
_.isString(self.menuConfig.action))
|
||||
{
|
||||
menuUtil.handleAction(self.client, null, self.menuConfig);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
require('util').inherits(MenuModule, PluginModule);
|
||||
@@ -144,19 +181,29 @@ MenuModule.prototype.standardMCIReadyHandler = function(mciData) {
|
||||
// * Standard/prefdefined MCI entries must load both (e.g. %BN is expected to resolve)
|
||||
//
|
||||
var self = this;
|
||||
var vcCount = 0;
|
||||
var vcReady = 0;
|
||||
|
||||
_.forEach(mciData, function entry(mciMap, name) {
|
||||
assert('menu' === name || 'prompt' === name);
|
||||
++vcCount;
|
||||
self.addViewController(name, new ViewController( { client : self.client } ));
|
||||
});
|
||||
|
||||
|
||||
var viewsReady = function(err) {
|
||||
// :TODO: what should really happen here?
|
||||
if(err) {
|
||||
self.client.log.warn(err);
|
||||
}
|
||||
|
||||
++vcReady;
|
||||
if(vcReady === vcCount) {
|
||||
self.allViewsReady();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
if(self.viewControllers.menu) {
|
||||
var menuLoadOpts = {
|
||||
mciMap : mciData.menu,
|
||||
@@ -188,6 +235,7 @@ MenuModule.prototype.finishedLoading = function() {
|
||||
self.client.gotoMenuModule( { name : self.menuConfig.next } );
|
||||
}, this.menuConfig.options.nextTimeout);
|
||||
} else {
|
||||
/*
|
||||
var nextAction = function() {
|
||||
if(!_.isObject(self.menuConfig.form) && !_.isString(self.menuConfig.prompt) &&
|
||||
_.isString(self.menuConfig.action))
|
||||
@@ -196,7 +244,9 @@ MenuModule.prototype.finishedLoading = function() {
|
||||
}
|
||||
};
|
||||
|
||||
if('end' === self.menuConfig.pause || true === self.menuConfig.pause) {
|
||||
if(self.shouldPause()) {
|
||||
self.client.term.write(ansi.goto(self.afterArtPos[0], 1));
|
||||
|
||||
// :TODO: really need a client.term.pause() that uses the correct art/etc.
|
||||
theme.displayThemedPause( { client : self.client }, function keyPressed() {
|
||||
nextAction();
|
||||
@@ -204,5 +254,6 @@ MenuModule.prototype.finishedLoading = function() {
|
||||
} else {
|
||||
nextAction();
|
||||
}
|
||||
*/
|
||||
}
|
||||
};
|
||||
32
core/stats.js
Normal file
32
core/stats.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/* jslint node: true */
|
||||
'use strict';
|
||||
|
||||
var userDb = require('./database.js').dbs.user;
|
||||
|
||||
var async = require('async');
|
||||
|
||||
exports.getUserLoginHistory = getUserLoginHistory;
|
||||
|
||||
function getUserLoginHistory(numRequested, cb) {
|
||||
|
||||
numRequested = Math.max(1, numRequested);
|
||||
|
||||
var loginHistory = [];
|
||||
|
||||
userDb.each(
|
||||
'SELECT user_id, user_name, timestamp ' +
|
||||
'FROM user_login_history ' +
|
||||
'ORDER BY timestamp DESC ' +
|
||||
'LIMIT ' + numRequested + ';',
|
||||
function historyRow(err, histEntry) {
|
||||
loginHistory.push( {
|
||||
userId : histEntry.user_id,
|
||||
userName : histEntry.user_name,
|
||||
timestamp : histEntry.timestamp,
|
||||
} );
|
||||
},
|
||||
function complete(err, recCount) {
|
||||
cb(err, loginHistory);
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -152,7 +152,7 @@ function getThemeArt(name, themeID, options, cb) {
|
||||
options.random = miscUtil.valueWithDefault(options.random, true);
|
||||
options.basePath = paths.join(Config.paths.themes, themeID);
|
||||
|
||||
art.getArt(name, options, function onThemeArt(err, artInfo) {
|
||||
art.getArt(name, options, function onThemeArt(err, artInfo) {
|
||||
if(err) {
|
||||
// try fallback of art directory
|
||||
options.basePath = Config.paths.art;
|
||||
@@ -227,7 +227,7 @@ function displayThemedPause(options, cb) {
|
||||
callback(new Error('Missing standard \'pause\' prompt'))
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
function displayPausePrompt(callback) {
|
||||
displayThemedAsset(
|
||||
|
||||
Reference in New Issue
Block a user