* Allow passing of arguments to menu's via menu.json including formatted parameters
* Fix menu.json setting of focus on view
This commit is contained in:
parent
ae71aa9feb
commit
113e16df0d
|
@ -7,7 +7,6 @@ var assert = require('assert');
|
|||
var term = require('./client_term.js');
|
||||
var miscUtil = require('./misc_util.js');
|
||||
var ansi = require('./ansi_term.js');
|
||||
var logger = require('./logger.js'); // :TODO: cleanup and just use Log.
|
||||
var Log = require('./logger.js').log;
|
||||
var user = require('./user.js');
|
||||
var moduleUtil = require('./module_util.js');
|
||||
|
@ -196,19 +195,27 @@ Client.prototype.address = function() {
|
|||
return this.input.address();
|
||||
};
|
||||
|
||||
Client.prototype.gotoMenuModule = function(name, cb) {
|
||||
Client.prototype.gotoMenuModule = function(options, cb) {
|
||||
var self = this;
|
||||
|
||||
assert(options.name);
|
||||
|
||||
// Assign a default missing module handler callback if none was provided
|
||||
cb = miscUtil.valueWithDefault(cb, self.defaultHandlerMissingMod());
|
||||
|
||||
self.detachCurrentMenuModule();
|
||||
|
||||
menuUtil.loadMenu(name, self, function onMenuModuleLoaded(err, modInst) {
|
||||
var loadOptions = {
|
||||
name : options.name,
|
||||
client : self,
|
||||
args : options.args
|
||||
};
|
||||
|
||||
menuUtil.loadMenu(loadOptions, function onMenuModuleLoaded(err, modInst) {
|
||||
if(err) {
|
||||
cb(err);
|
||||
} else {
|
||||
Log.debug({ menuName : name }, 'Goto menu module');
|
||||
Log.debug({ name : options.name }, 'Goto menu module');
|
||||
|
||||
modInst.enter(self);
|
||||
|
||||
|
@ -221,11 +228,12 @@ Client.prototype.gotoMenuModule = function(name, cb) {
|
|||
// Default error handlers
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// :TODO: getDefaultHandler(name) -- handlers in default_handlers.js or something
|
||||
Client.prototype.defaultHandlerMissingMod = function(err) {
|
||||
var self = this;
|
||||
|
||||
function handler(err) {
|
||||
logger.log.error(err);
|
||||
Log.error(err);
|
||||
|
||||
self.term.write(ansi.resetScreen());
|
||||
self.term.write('An unrecoverable error has been encountered!\n');
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
'use strict';
|
||||
|
||||
// ENiGMA½
|
||||
var logger = require('./logger.js');
|
||||
var Log = require('./logger.js').log;
|
||||
|
||||
var iconv = require('iconv-lite');
|
||||
var assert = require('assert');
|
||||
|
@ -41,7 +41,7 @@ function ClientTerminal(output) {
|
|||
if(iconv.encodingExists(enc)) {
|
||||
outputEncoding = enc;
|
||||
} else {
|
||||
logger.log.warn({ encoding : enc }, 'Unknown encoding');
|
||||
Log.warn({ encoding : enc }, 'Unknown encoding');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -84,7 +84,8 @@ function connectEntry(client) {
|
|||
|
||||
setTimeout(function onTimeout() {
|
||||
term.write(ansi.clearScreen());
|
||||
client.gotoMenuModule(Config.entryMod);
|
||||
|
||||
client.gotoMenuModule({ name : Config.entryMod } );
|
||||
//moduleUtil.goto(Config.entryMod, client);
|
||||
}, timeout);
|
||||
});
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
|
||||
var PluginModule = require('./plugin_module.js').PluginModule;
|
||||
var theme = require('./theme.js');
|
||||
var Log = require('./logger.js').log;
|
||||
|
||||
var async = require('async');
|
||||
var assert = require('assert');
|
||||
|
||||
exports.MenuModule = MenuModule;
|
||||
|
||||
function MenuModule(menuConfig) {
|
||||
PluginModule.call(this);
|
||||
function MenuModule(options) {
|
||||
PluginModule.call(this, options);
|
||||
|
||||
var self = this;
|
||||
this.menuConfig = menuConfig;
|
||||
this.menuConfig = options.menuConfig;
|
||||
|
||||
this.viewControllers = [];
|
||||
|
||||
|
@ -41,7 +42,7 @@ function MenuModule(menuConfig) {
|
|||
callback(null);
|
||||
}
|
||||
],
|
||||
function onComplete(err) {
|
||||
function complete(err) {
|
||||
if(err) {
|
||||
// :TODO: Log me!!! ... and what else?
|
||||
console.log(err);
|
||||
|
|
|
@ -17,7 +17,14 @@ var stripJsonComments = require('strip-json-comments');
|
|||
exports.loadMenu = loadMenu;
|
||||
exports.getFormConfig = getFormConfig;
|
||||
|
||||
function loadMenu(name, client, cb) {
|
||||
function loadMenu(options, cb) {
|
||||
|
||||
assert(options);
|
||||
assert(options.name);
|
||||
assert(options.client);
|
||||
|
||||
var name = options.name;
|
||||
var client = options.client;
|
||||
/*
|
||||
TODO:
|
||||
* check access / ACS
|
||||
|
@ -44,21 +51,23 @@ function loadMenu(name, client, cb) {
|
|||
});
|
||||
},
|
||||
function menuConfigLoaded(menuConfig, callback) {
|
||||
Log.debug( { config : menuConfig }, 'Menu configuration loaded');
|
||||
|
||||
var moduleName = menuConfig.module || 'standard_menu';
|
||||
|
||||
moduleUtil.loadModule(moduleName, 'mods', function onModule(err, mod) {
|
||||
callback(err, mod, menuConfig, moduleName);
|
||||
});
|
||||
},
|
||||
}
|
||||
],
|
||||
function complete(err, mod, menuConfig, moduleName) {
|
||||
if(err) {
|
||||
cb(err);
|
||||
} else {
|
||||
Log.debug( { moduleName : moduleName, moduleInfo : mod.moduleInfo }, 'Loading menu module instance');
|
||||
cb(null, new mod.getModule(menuConfig));
|
||||
Log.debug(
|
||||
{ moduleName : moduleName, args : options.args, config : menuConfig, info : mod.moduleInfo },
|
||||
'Creating menu module instance');
|
||||
|
||||
// :TODO: throw from MenuModule() - catch here
|
||||
cb(null, new mod.getModule({ menuConfig : menuConfig, args : options.args } ));
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -92,61 +101,3 @@ function getFormConfig(menuConfig, formId, mciMap, cb) {
|
|||
|
||||
cb(new Error('No matching form configuration found'));
|
||||
}
|
||||
|
||||
/*
|
||||
function getFormConfig(menuConfig, mciMap, cb) {
|
||||
assert(menuConfig);
|
||||
|
||||
if(!menuConfig.form) {
|
||||
cb(new Error('No form section specified for menu'));
|
||||
return;
|
||||
}
|
||||
|
||||
async.filter(
|
||||
menuConfig.form,
|
||||
function check(form, callback) {
|
||||
if(!form.mciReq || form.mciReq.length <= 0) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var count = form.mciReq.length;
|
||||
if(Object.keys(mciMap).length === count) {
|
||||
for(var i = 0; i < count; ++i) {
|
||||
if(!mciMap[form.mciReq[i]]) {
|
||||
callback(false);
|
||||
}
|
||||
}
|
||||
callback(true);
|
||||
}
|
||||
},
|
||||
function filtered(form) {
|
||||
if(form.length > 0) {
|
||||
assert(1 === form.length);
|
||||
cb(null, form[0]);
|
||||
} else {
|
||||
cb(new Error('No matching form configuration found'));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function getFormConfig(menuConfig, mciMap) {
|
||||
var count = menuConfig.form ? menuConfig.form.length : 0;
|
||||
var mciReq;
|
||||
for(var i = 0; i < count; ++i) {
|
||||
mciReq = menuConfig.form[i].mciReq;
|
||||
if(mciReq) {
|
||||
if(mciReq.length === mciMap.length) {
|
||||
for(var m = 0; m < mciReq.length; ++m) {
|
||||
if(!mciMap[mciReq[m]]) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
exports.PluginModule = PluginModule;
|
||||
|
||||
function PluginModule() {
|
||||
function PluginModule(options) {
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
// ENiGMA½
|
||||
var baseClient = require('../client.js');
|
||||
var logger = require('../logger.js');
|
||||
var Log = require('../logger.js').log;
|
||||
var ServerModule = require('../server_module.js').ServerModule;
|
||||
|
||||
var net = require('net');
|
||||
|
@ -322,7 +322,7 @@ OPTION_IMPLS[OPTIONS.NEW_ENVIRONMENT] = function(bufs, i, event) {
|
|||
event.type = vars.isOrInfo;
|
||||
|
||||
if(vars.newEnv === OPTIONS.NEW_ENVIRONMENT_DEP) {
|
||||
logger.log.warn('Handling deprecated RFC 1408 NEW-ENVIRON');
|
||||
Log.warn('Handling deprecated RFC 1408 NEW-ENVIRON');
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -538,7 +538,7 @@ TelnetClient.prototype.setTermType = function(ttype) {
|
|||
this.term.env['TERM'] = ttype;
|
||||
this.term.termType = ttype;
|
||||
|
||||
logger.log.debug({ termType : ttype }, 'Set terminal type');
|
||||
Log.debug({ termType : ttype }, 'Set terminal type');
|
||||
}
|
||||
|
||||
TelnetClient.prototype.handleSbCommand = function(evt) {
|
||||
|
@ -571,15 +571,15 @@ TelnetClient.prototype.handleSbCommand = function(evt) {
|
|||
self.setTermType(evt.envVars[name]);
|
||||
} else if('COLUMNS' === name && 0 === self.term.termWidth) {
|
||||
self.term.termWidth = parseInt(evt.envVars[name]);
|
||||
logger.log.debug({ termWidth : self.term.termWidth, updateSource : 'NEW-ENVIRON'}, 'Window width updated');
|
||||
Log.debug({ termWidth : self.term.termWidth, updateSource : 'NEW-ENVIRON'}, 'Window width updated');
|
||||
} else if('ROWS' === name && 0 === self.term.termHeight) {
|
||||
self.term.termHeight = parseInt(evt.envVars[name]);
|
||||
logger.log.debug({ termHeight : self.term.termHeight, updateSource : 'NEW-ENVIRON'}, 'Window height updated');
|
||||
Log.debug({ termHeight : self.term.termHeight, updateSource : 'NEW-ENVIRON'}, 'Window height updated');
|
||||
} else {
|
||||
if(name in self.term.env) {
|
||||
assert(evt.type === SB_COMMANDS.INFO);
|
||||
|
||||
logger.log.warn(
|
||||
Log.warn(
|
||||
{ varName : name, value : evt.envVars[name], existingValue : self.term.env[name] },
|
||||
'Environment variable already exists');
|
||||
} else {
|
||||
|
@ -604,7 +604,7 @@ TelnetClient.prototype.handleSbCommand = function(evt) {
|
|||
self.term.env['ROWS'] = evt.height;
|
||||
}
|
||||
|
||||
logger.log.debug({ termWidth : evt.width , termHeight : evt.height, updateSource : 'NAWS' }, 'Window size updated');
|
||||
Log.debug({ termWidth : evt.width , termHeight : evt.height, updateSource : 'NAWS' }, 'Window size updated');
|
||||
} else {
|
||||
console.log('unhandled SB: ' + JSON.stringify(evt));
|
||||
}
|
||||
|
@ -625,15 +625,15 @@ TelnetClient.prototype.handleMiscCommand = function(evt) {
|
|||
//
|
||||
if('ip' === evt.command) {
|
||||
// Interrupt Process (IP)
|
||||
logger.log.debug('Interrupt Process (IP) - Ending');
|
||||
Log.debug('Interrupt Process (IP) - Ending');
|
||||
this.input.end();
|
||||
} else if('ayt' === evt.command) {
|
||||
this.output.write('\b');
|
||||
logger.log.debug('Are You There (AYT) - Replied "\\b"');
|
||||
Log.debug('Are You There (AYT) - Replied "\\b"');
|
||||
} else if(IGNORED_COMMANDS.indexOf(evt.commandCode)) {
|
||||
logger.log.debug({ evt : evt }, 'Ignoring command');
|
||||
Log.debug({ evt : evt }, 'Ignoring command');
|
||||
} else {
|
||||
logger.log.warn({ evt : evt }, 'Unknown command');
|
||||
Log.warn({ evt : evt }, 'Unknown command');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -144,4 +144,4 @@ function pad(s, len, padChar, dir, stringColor, padColor) {
|
|||
}
|
||||
|
||||
return stringColor + s;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
var Config = require('./config.js').config;
|
||||
var art = require('./art.js');
|
||||
var miscUtil = require('./misc_util.js');
|
||||
var logger = require('./logger.js').log;
|
||||
var Log = require('./logger.js').log;
|
||||
var fs = require('fs');
|
||||
var paths = require('path');
|
||||
var async = require('async');
|
||||
|
@ -56,7 +56,7 @@ function initAvailableThemes(cb) {
|
|||
availableThemes = {};
|
||||
}
|
||||
availableThemes[themeId] = info;
|
||||
logger.debug( { info : info }, 'Theme loaded');
|
||||
Log.debug( { info : info }, 'Theme loaded');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -209,9 +209,12 @@ ViewController.prototype.loadFromMCIMap = function(mciMap) {
|
|||
ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) {
|
||||
assert(options.mciMap);
|
||||
|
||||
var factory = new MCIViewFactory(this.client);
|
||||
var self = this;
|
||||
var formIdKey = options.formId ? options.formId.toString() : '0';
|
||||
var factory = new MCIViewFactory(this.client);
|
||||
var self = this;
|
||||
var formIdKey = options.formId ? options.formId.toString() : '0';
|
||||
var initialFocusId;
|
||||
|
||||
// :TODO: remove all the passing of fromConfig - use local
|
||||
|
||||
async.waterfall(
|
||||
[
|
||||
|
@ -258,14 +261,13 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) {
|
|||
view.submit = true; // :TODO: should really be actual value
|
||||
}
|
||||
|
||||
if(mciConf.focus) {
|
||||
self.switchFocus(viewId);
|
||||
}
|
||||
|
||||
if(mciConf.text) {
|
||||
view.setText(mciConf.text);
|
||||
}
|
||||
|
||||
if(mciConf.focus) {
|
||||
initialFocusId = viewId;
|
||||
}
|
||||
|
||||
eachCb(null);
|
||||
},
|
||||
|
@ -321,17 +323,32 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) {
|
|||
return true;
|
||||
};
|
||||
|
||||
var conf;
|
||||
for(var c = 0; c < confForFormId.length; ++c) {
|
||||
if(_.isEqual(formData.value, confForFormId[c].value, formValueCompare)) {
|
||||
self.client.gotoMenuModule(confForFormId[c].menu);
|
||||
conf = confForFormId[c];
|
||||
if(_.isEqual(formData.value, conf.value, formValueCompare)) {
|
||||
|
||||
var formattedArgs;
|
||||
if(conf.args) {
|
||||
formattedArgs = self.formatMenuArgs(conf.args);
|
||||
}
|
||||
|
||||
self.client.gotoMenuModule( { name : conf.menu, args : formattedArgs } );
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
|
||||
callback(null);
|
||||
},
|
||||
function setInitialFocus(callback) {
|
||||
if(initialFocusId) {
|
||||
self.switchFocus(initialFocusId);
|
||||
}
|
||||
|
||||
callback(null);
|
||||
}
|
||||
],
|
||||
function complete(err) {
|
||||
|
@ -341,3 +358,28 @@ ViewController.prototype.loadFromMCIMapAndConfig = function(options, cb) {
|
|||
}
|
||||
);
|
||||
};
|
||||
|
||||
ViewController.prototype.formatMCIString = function(format) {
|
||||
var self = this;
|
||||
var view;
|
||||
|
||||
return format.replace(/{(\d+)}/g, function replacer(match, number) {
|
||||
view = self.getView(number);
|
||||
|
||||
if(!view) {
|
||||
return match;
|
||||
}
|
||||
|
||||
return view.getViewData();
|
||||
});
|
||||
};
|
||||
|
||||
ViewController.prototype.formatMenuArgs = function(args) {
|
||||
var self = this;
|
||||
|
||||
return _.forIn(args, function onArg(value, key) {
|
||||
if('string' === typeof value) {
|
||||
args[key] = self.formatMCIString(value);
|
||||
}
|
||||
});
|
||||
};
|
|
@ -1,6 +1,14 @@
|
|||
{
|
||||
/*
|
||||
Menu Configuration
|
||||
|
||||
Some concept/ideas:
|
||||
"mci" : {
|
||||
"BN1" : {
|
||||
...
|
||||
"draw" : "@script:blah.js/drawButton"
|
||||
}
|
||||
}
|
||||
*/
|
||||
"matrix" : {
|
||||
"art" : "matrix",
|
||||
|
@ -20,7 +28,8 @@
|
|||
"*" : [
|
||||
{
|
||||
"value" : { "1" : 0 },
|
||||
"menu" : "login"
|
||||
"menu" : "loginForm",
|
||||
"args" : { "reason" : "show_form" }
|
||||
},
|
||||
{
|
||||
"value" : { "1" : 1 },
|
||||
|
@ -36,8 +45,8 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"login" : {
|
||||
"art" : "login",
|
||||
"loginForm" : {
|
||||
"art" : "login", // TODO: rename to login_form
|
||||
"module" : "login",
|
||||
"form" : {
|
||||
"0" : {
|
||||
|
@ -58,14 +67,25 @@
|
|||
"submit" : {
|
||||
"3" : [ // Login
|
||||
{
|
||||
"value" : { "3" : null }, // :TODO: allow "value" : null
|
||||
"menu" : "attempt_login"
|
||||
"value" : { "3" : null },
|
||||
"menu" : "attemptLogin",
|
||||
"args" : { "reason" : "attempt_login", "username" : "{1}", "password" : "{2}" }
|
||||
}
|
||||
],
|
||||
"4" : [ // cancel
|
||||
{
|
||||
"value" : { "4" : null },
|
||||
"menu" : "matrix"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"attemptLogin" : {
|
||||
"art" : "login",
|
||||
"module" : "login"
|
||||
},
|
||||
"logoff" : {
|
||||
"art" : "logoff",
|
||||
|
|
Loading…
Reference in New Issue