MAJOR CHANGE to theming system:
* Less complex * Themes are only loaded once. Users share avail themes[] objects * Themes are applied to configuration _once_ * Users can switch themes in configuration * Other related improvements
This commit is contained in:
parent
ef047bc515
commit
4fdd3dbbfe
|
@ -274,9 +274,7 @@ function prepareClient(client, cb) {
|
||||||
} else {
|
} else {
|
||||||
client.user.properties.theme_id = conf.config.preLoginTheme;
|
client.user.properties.theme_id = conf.config.preLoginTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
theme.loadTheme(client.user.properties.theme_id, function themeLoaded(err, theme) {
|
theme.setClientTheme(client, client.user.properties.theme_id);
|
||||||
client.currentTheme = theme;
|
cb(null); // note: currently useless to use cb here - but this may change...again...
|
||||||
cb(null);
|
|
||||||
});
|
|
||||||
}
|
}
|
|
@ -87,6 +87,7 @@ function getDefaultConfig() {
|
||||||
loginAttempts : 3,
|
loginAttempts : 3,
|
||||||
|
|
||||||
menuFile : 'menu.hjson', // Override to use something else, e.g. demo.hjson. Can be a full path (defaults to ./mods)
|
menuFile : 'menu.hjson', // Override to use something else, e.g. demo.hjson. Can be a full path (defaults to ./mods)
|
||||||
|
promptFile : 'prompt.hjson', // Override to use soemthing else, e.g. myprompt.hjson. Can be a full path (defaults to ./mods)
|
||||||
},
|
},
|
||||||
|
|
||||||
// :TODO: see notes below about 'theme' section - move this!
|
// :TODO: see notes below about 'theme' section - move this!
|
||||||
|
|
|
@ -194,13 +194,6 @@ MenuModule.prototype.enter = function(client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
assert(_.isObject(client));
|
assert(_.isObject(client));
|
||||||
|
|
||||||
menuUtil.applyGeneralThemeCustomization( {
|
|
||||||
name : this.menuName,
|
|
||||||
client : this.client,
|
|
||||||
type : 'menus',
|
|
||||||
config : this.menuConfig.config,
|
|
||||||
});
|
|
||||||
|
|
||||||
if(_.isString(this.menuConfig.status)) {
|
if(_.isString(this.menuConfig.status)) {
|
||||||
this.client.currentStatus = this.menuConfig.status;
|
this.client.currentStatus = this.menuConfig.status;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -101,7 +101,7 @@ MenuStack.prototype.goto = function(name, options, cb) {
|
||||||
client : self.client,
|
client : self.client,
|
||||||
};
|
};
|
||||||
|
|
||||||
if(options) {
|
if(_.isObject(options)) {
|
||||||
loadOpts.extraArgs = options.extraArgs;
|
loadOpts.extraArgs = options.extraArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ var conf = require('./config.js'); // :TODO: remove me!
|
||||||
var Config = require('./config.js').config;
|
var Config = require('./config.js').config;
|
||||||
var asset = require('./asset.js');
|
var asset = require('./asset.js');
|
||||||
var theme = require('./theme.js');
|
var theme = require('./theme.js');
|
||||||
var configCache = require('./config_cache.js');
|
var getFullConfig = require('./config_util.js').getFullConfig;
|
||||||
var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory;
|
var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory;
|
||||||
var acsUtil = require('./acs_util.js');
|
var acsUtil = require('./acs_util.js');
|
||||||
|
|
||||||
|
@ -22,53 +22,33 @@ exports.loadMenu = loadMenu;
|
||||||
exports.getFormConfigByIDAndMap = getFormConfigByIDAndMap;
|
exports.getFormConfigByIDAndMap = getFormConfigByIDAndMap;
|
||||||
exports.handleAction = handleAction;
|
exports.handleAction = handleAction;
|
||||||
exports.handleNext = handleNext;
|
exports.handleNext = handleNext;
|
||||||
exports.applyGeneralThemeCustomization = applyGeneralThemeCustomization;
|
//exports.applyGeneralThemeCustomization = applyGeneralThemeCustomization;
|
||||||
exports.applyMciThemeCustomization = applyMciThemeCustomization;
|
//exports.applyMciThemeCustomization = applyMciThemeCustomization;
|
||||||
|
|
||||||
function getMenuConfig(name, cb) {
|
function getMenuConfig(client, name, cb) {
|
||||||
var menuConfig;
|
var menuConfig;
|
||||||
|
|
||||||
async.waterfall(
|
async.waterfall(
|
||||||
[
|
[
|
||||||
function loadMenuJSON(callback) {
|
function locateMenuConfig(callback) {
|
||||||
var menuFilePath = Config.general.menuFile;
|
if(_.has(client.currentTheme, [ 'menus', name ])) {
|
||||||
|
menuConfig = client.currentTheme.menus[name];
|
||||||
// menuFile is assumed to be in 'mods' if a path is not supplied
|
|
||||||
if('.' === paths.dirname(menuFilePath)) {
|
|
||||||
menuFilePath = paths.join(__dirname, '../mods', menuFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
configCache.getConfig(menuFilePath, function loaded(err, menuJson) {
|
|
||||||
callback(err, menuJson);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function locateMenuConfig(menuJson, callback) {
|
|
||||||
if(_.has(menuJson, [ 'menus', name ])) {
|
|
||||||
menuConfig = menuJson.menus[name];
|
|
||||||
callback(null);
|
callback(null);
|
||||||
} else {
|
} else {
|
||||||
callback(new Error('No menu entry for \'' + name + '\''));
|
callback(new Error('No menu entry for \'' + name + '\''));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
function loadPromptJSON(callback) {
|
function locatePromptConfig(callback) {
|
||||||
if(_.isString(menuConfig.prompt)) {
|
if(_.isString(menuConfig.prompt)) {
|
||||||
configCache.getModConfig('prompt.hjson', function loaded(err, promptJson, reCached) {
|
if(_.has(client.currentTheme, [ 'prompts', menuConfig.prompt ])) {
|
||||||
callback(err, promptJson);
|
menuConfig.promptConfig = client.currentTheme.prompts[menuConfig.prompt];
|
||||||
});
|
callback(null);
|
||||||
} else {
|
|
||||||
callback(null, null);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
function locatePromptConfig(promptJson, callback) {
|
|
||||||
if(promptJson) {
|
|
||||||
if(_.has(promptJson, [ 'prompts', menuConfig.prompt ])) {
|
|
||||||
menuConfig.promptConfig = promptJson.prompts[menuConfig.prompt];
|
|
||||||
} else {
|
} else {
|
||||||
callback(new Error('No prompt entry for \'' + menuConfig.prompt + '\''));
|
callback(new Error('No prompt entry for \'' + menuConfig.prompt + '\''));
|
||||||
return;
|
}
|
||||||
}
|
} else {
|
||||||
|
callback(null);
|
||||||
}
|
}
|
||||||
callback(null);
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
function complete(err) {
|
function complete(err) {
|
||||||
|
@ -85,7 +65,7 @@ function loadMenu(options, cb) {
|
||||||
async.waterfall(
|
async.waterfall(
|
||||||
[
|
[
|
||||||
function getMenuConfiguration(callback) {
|
function getMenuConfiguration(callback) {
|
||||||
getMenuConfig(options.name, function menuConfigLoaded(err, menuConfig) {
|
getMenuConfig(options.client, options.name, function menuConfigLoaded(err, menuConfig) {
|
||||||
callback(err, menuConfig);
|
callback(err, menuConfig);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -272,7 +252,7 @@ function handleNext(client, nextSpec, conf) {
|
||||||
|
|
||||||
// :TODO: Seems better in theme.js, but that includes ViewController...which would then include theme.js
|
// :TODO: Seems better in theme.js, but that includes ViewController...which would then include theme.js
|
||||||
// ...theme.js only brings in VC to create themed pause prompt. Perhaps that should live elsewhere
|
// ...theme.js only brings in VC to create themed pause prompt. Perhaps that should live elsewhere
|
||||||
|
/*
|
||||||
function applyGeneralThemeCustomization(options) {
|
function applyGeneralThemeCustomization(options) {
|
||||||
//
|
//
|
||||||
// options.name
|
// options.name
|
||||||
|
@ -298,8 +278,9 @@ function applyGeneralThemeCustomization(options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
function applyMciThemeCustomization(options) {
|
function applyMciThemeCustomization(options) {
|
||||||
//
|
//
|
||||||
// options.name : menu/prompt name
|
// options.name : menu/prompt name
|
||||||
|
@ -346,3 +327,4 @@ function applyMciThemeCustomization(options) {
|
||||||
|
|
||||||
// :TODO: apply generic stuff, e.g. "VM" (vs "VM1")
|
// :TODO: apply generic stuff, e.g. "VM" (vs "VM1")
|
||||||
}
|
}
|
||||||
|
*/
|
180
core/theme.js
180
core/theme.js
|
@ -7,6 +7,7 @@ var ansi = require('./ansi_term.js');
|
||||||
var miscUtil = require('./misc_util.js');
|
var miscUtil = require('./misc_util.js');
|
||||||
var Log = require('./logger.js').log;
|
var Log = require('./logger.js').log;
|
||||||
var configCache = require('./config_cache.js');
|
var configCache = require('./config_cache.js');
|
||||||
|
var getFullConfig = require('./config_util.js').getFullConfig;
|
||||||
var asset = require('./asset.js');
|
var asset = require('./asset.js');
|
||||||
var ViewController = require('./view_controller.js').ViewController;
|
var ViewController = require('./view_controller.js').ViewController;
|
||||||
|
|
||||||
|
@ -16,11 +17,10 @@ var async = require('async');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
|
|
||||||
exports.loadTheme = loadTheme;
|
|
||||||
exports.getThemeArt = getThemeArt;
|
exports.getThemeArt = getThemeArt;
|
||||||
exports.getAvailableThemes = getAvailableThemes;
|
exports.getAvailableThemes = getAvailableThemes;
|
||||||
exports.getRandomTheme = getRandomTheme;
|
exports.getRandomTheme = getRandomTheme;
|
||||||
|
exports.setClientTheme = setClientTheme;
|
||||||
exports.initAvailableThemes = initAvailableThemes;
|
exports.initAvailableThemes = initAvailableThemes;
|
||||||
exports.displayThemeArt = displayThemeArt;
|
exports.displayThemeArt = displayThemeArt;
|
||||||
exports.displayThemedPause = displayThemedPause;
|
exports.displayThemedPause = displayThemedPause;
|
||||||
|
@ -102,25 +102,174 @@ function loadTheme(themeID, cb) {
|
||||||
|
|
||||||
var availableThemes = {};
|
var availableThemes = {};
|
||||||
|
|
||||||
|
var IMMUTABLE_MCI_PROPERTIES = [
|
||||||
|
'maxLength', 'argName', 'submit', 'validate'
|
||||||
|
];
|
||||||
|
|
||||||
|
function getMergedTheme(menuConfig, promptConfig, theme) {
|
||||||
|
assert(_.isObject(menuConfig));
|
||||||
|
assert(_.isObject(theme));
|
||||||
|
|
||||||
|
// :TODO: merge in defaults (customization.defaults{} )
|
||||||
|
// :TODO: apply generic stuff, e.g. "VM" (vs "VM1")
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a *clone* of menuConfig (menu.hjson) then bring in
|
||||||
|
// promptConfig (prompt.hjson)
|
||||||
|
//
|
||||||
|
var mergedTheme = _.cloneDeep(menuConfig);
|
||||||
|
|
||||||
|
if(_.isObject(promptConfig.prompts)) {
|
||||||
|
mergedTheme.prompts = _.cloneDeep(promptConfig.prompts);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add in data we won't be altering directly from the theme
|
||||||
|
//
|
||||||
|
mergedTheme.info = theme.info;
|
||||||
|
mergedTheme.helpers = theme.helpers;
|
||||||
|
|
||||||
|
//
|
||||||
|
// merge customizer to disallow immutable MCI properties
|
||||||
|
//
|
||||||
|
var mciCustomizer = function(objVal, srcVal, key) {
|
||||||
|
return IMMUTABLE_MCI_PROPERTIES.indexOf(key) > -1 ? objVal : srcVal;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getFormKeys(fromObj) {
|
||||||
|
return _.remove(_.keys(fromObj), function pred(k) {
|
||||||
|
return !isNaN(k); // remove all non-numbers
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeMciProperties(dest, src) {
|
||||||
|
Object.keys(src).forEach(function mciEntry(mci) {
|
||||||
|
_.merge(dest[mci], src[mci], mciCustomizer);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyThemeMciBlock(dest, src, formKey) {
|
||||||
|
if(_.isObject(src.mci)) {
|
||||||
|
mergeMciProperties(dest, src.mci);
|
||||||
|
} else {
|
||||||
|
if(_.has(src, [ formKey, 'mci' ])) {
|
||||||
|
mergeMciProperties(dest, src[formKey].mci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// menu.hjson can have a couple different structures:
|
||||||
|
// 1) Explicit declaration of expected MCI code(s) under 'form:<id>' before a 'mci' block
|
||||||
|
// (this allows multiple layout types defined by one menu for example)
|
||||||
|
//
|
||||||
|
// 2) Non-explicit declaration: 'mci' directly under 'form:<id>'
|
||||||
|
//
|
||||||
|
// theme.hjson has it's own mix:
|
||||||
|
// 1) Explicit: Form ID before 'mci' (generally used where there are > 1 forms)
|
||||||
|
//
|
||||||
|
// 2) Non-explicit: 'mci' directly under an entry
|
||||||
|
//
|
||||||
|
// Additionally, #1 or #2 may be under an explicit key of MCI code(s) to match up
|
||||||
|
// with menu.hjson in #1.
|
||||||
|
//
|
||||||
|
// * When theming an explicit menu.hjson entry (1), we will use a matching explicit
|
||||||
|
// entry with a matching MCI code(s) key in theme.hjson (e.g. menu="ETVM"/theme="ETVM"
|
||||||
|
// and fall back to generic if a match is not found.
|
||||||
|
//
|
||||||
|
// * If theme.hjson provides form ID's, use them. Otherwise, we'll apply directly assuming
|
||||||
|
// there is a generic 'mci' block.
|
||||||
|
//
|
||||||
|
function applyToForm(form, menuTheme, formKey) {
|
||||||
|
if(_.isObject(form.mci)) {
|
||||||
|
// non-explicit: no MCI code(s) key assumed since we found 'mci' directly under form ID
|
||||||
|
applyThemeMciBlock(form.mci, menuTheme, formKey);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
var menuMciCodeKeys = _.remove(_.keys(form), function pred(k) {
|
||||||
|
return k === k.toUpperCase(); // remove anything not uppercase
|
||||||
|
});
|
||||||
|
|
||||||
|
menuMciCodeKeys.forEach(function mciKeyEntry(mciKey) {
|
||||||
|
var applyFrom;
|
||||||
|
if(_.has(menuTheme, [ mciKey, 'mci' ])) {
|
||||||
|
applyFrom = menuTheme[mciKey];
|
||||||
|
} else {
|
||||||
|
applyFrom = menuTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyThemeMciBlock(form[mciKey].mci, applyFrom);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ 'menus', 'prompts' ].forEach(function areaEntry(areaName) {
|
||||||
|
_.keys(mergedTheme[areaName]).forEach(function menuEntry(menuName) {
|
||||||
|
if(_.has(theme, [ 'customization', areaName, menuName ])) {
|
||||||
|
|
||||||
|
var menuTheme = theme.customization[areaName][menuName];
|
||||||
|
var mergedThemeMenu = mergedTheme[areaName][menuName];
|
||||||
|
|
||||||
|
// config block is direct assign/overwrite
|
||||||
|
// :TODO: should probably be _.merge()
|
||||||
|
if(menuTheme.config) {
|
||||||
|
mergedThemeMenu.config = _.assign(mergedThemeMenu || {}, menuTheme.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
if('menus' === areaName) {
|
||||||
|
if(_.isObject(mergedThemeMenu.form)) {
|
||||||
|
getFormKeys(mergedThemeMenu.form).forEach(function formKeyEntry(formKey) {
|
||||||
|
applyToForm(mergedThemeMenu.form[formKey], menuTheme, formKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if('prompts' === areaName) {
|
||||||
|
// no 'form' or form keys for prompts -- direct to mci
|
||||||
|
applyToForm(mergedThemeMenu, menuTheme);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
return mergedTheme;
|
||||||
|
}
|
||||||
|
|
||||||
function initAvailableThemes(cb) {
|
function initAvailableThemes(cb) {
|
||||||
|
var menuConfig;
|
||||||
|
var promptConfig;
|
||||||
|
|
||||||
async.waterfall(
|
async.waterfall(
|
||||||
[
|
[
|
||||||
|
function loadMenuConfig(callback) {
|
||||||
|
getFullConfig(Config.general.menuFile, function gotConfig(err, mc) {
|
||||||
|
menuConfig = mc;
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
function loadPromptConfig(callback) {
|
||||||
|
getFullConfig(Config.general.promptFile, function gotConfig(err, pc) {
|
||||||
|
promptConfig = pc;
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
},
|
||||||
function getDir(callback) {
|
function getDir(callback) {
|
||||||
fs.readdir(Config.paths.themes, function onReadDir(err, files) {
|
fs.readdir(Config.paths.themes, function dirRead(err, files) {
|
||||||
callback(err, files);
|
callback(err, files);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function filterFiles(files, callback) {
|
function filterFiles(files, callback) {
|
||||||
var filtered = files.filter(function onFilter(file) {
|
var filtered = files.filter(function filter(file) {
|
||||||
return fs.statSync(paths.join(Config.paths.themes, file)).isDirectory();
|
return fs.statSync(paths.join(Config.paths.themes, file)).isDirectory();
|
||||||
});
|
});
|
||||||
callback(null, filtered);
|
callback(null, filtered);
|
||||||
},
|
},
|
||||||
function populateAvailable(filtered, callback) {
|
function populateAvailable(filtered, callback) {
|
||||||
filtered.forEach(function onTheme(themeId) {
|
// :TODO: this is a bit broken with callback placement and configCache.on() handler
|
||||||
|
|
||||||
|
filtered.forEach(function themeEntry(themeId) {
|
||||||
loadTheme(themeId, function themeLoaded(err, theme, themePath) {
|
loadTheme(themeId, function themeLoaded(err, theme, themePath) {
|
||||||
if(!err) {
|
if(!err) {
|
||||||
availableThemes[themeId] = theme;
|
availableThemes[themeId] = getMergedTheme(menuConfig, promptConfig, theme);
|
||||||
|
|
||||||
configCache.on('recached', function recached(path) {
|
configCache.on('recached', function recached(path) {
|
||||||
if(themePath === path) {
|
if(themePath === path) {
|
||||||
|
@ -164,6 +313,20 @@ function getRandomTheme() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setClientTheme(client, themeId) {
|
||||||
|
var desc;
|
||||||
|
|
||||||
|
try {
|
||||||
|
client.currentTheme = getAvailableThemes()[themeId];
|
||||||
|
desc = 'Set client theme';
|
||||||
|
} catch(e) {
|
||||||
|
client.currentTheme = getAvailableThemes()[Config.defaults.theme];
|
||||||
|
desc = 'Failed setting theme by supplied ID; Using default';
|
||||||
|
}
|
||||||
|
|
||||||
|
client.log.debug( { themeId : themeId, info : client.currentTheme.info }, desc);
|
||||||
|
}
|
||||||
|
|
||||||
function getThemeArt(options, cb) {
|
function getThemeArt(options, cb) {
|
||||||
//
|
//
|
||||||
// options - required:
|
// options - required:
|
||||||
|
@ -333,11 +496,12 @@ function displayThemedPause(options, cb) {
|
||||||
},
|
},
|
||||||
function clearPauseArt(callback) {
|
function clearPauseArt(callback) {
|
||||||
if(options.clearPrompt) {
|
if(options.clearPrompt) {
|
||||||
if(artInfo.startRow) {
|
if(artInfo.startRow && artInfo.height) {
|
||||||
options.client.term.rawWrite(ansi.goto(artInfo.startRow, 1));
|
options.client.term.rawWrite(ansi.goto(artInfo.startRow, 1));
|
||||||
|
// :TODO: This will not work with NetRunner:
|
||||||
options.client.term.rawWrite(ansi.deleteLine(artInfo.height));
|
options.client.term.rawWrite(ansi.deleteLine(artInfo.height));
|
||||||
} else {
|
} else {
|
||||||
options.client.term.rawWrite(ansi.up(1) + ansi.deleteLine());
|
options.client.term.rawWrite(ansi.eraseLine(1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callback(null);
|
callback(null);
|
||||||
|
|
|
@ -120,7 +120,11 @@ function UserConfigModule(options) {
|
||||||
term_height : formData.value.termHeight.toString(),
|
term_height : formData.value.termHeight.toString(),
|
||||||
theme_id : self.availThemeInfo[formData.value.theme].themeId,
|
theme_id : self.availThemeInfo[formData.value.theme].themeId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// runtime set theme
|
||||||
|
theme.setClientTheme(self.client, newProperties.theme_id);
|
||||||
|
|
||||||
|
// persist all changes
|
||||||
self.client.user.persistProperties(newProperties, function persisted(err) {
|
self.client.user.persistProperties(newProperties, function persisted(err) {
|
||||||
if(err) {
|
if(err) {
|
||||||
self.client.log.warn( { error : err.toString() }, 'Failed persisting updated properties');
|
self.client.log.warn( { error : err.toString() }, 'Failed persisting updated properties');
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
/* jslint node: true */
|
/* jslint node: true */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var theme = require('./theme.js');
|
var setClientTheme = require('./theme.js').setClientTheme;
|
||||||
var clientConnections = require('./client_connections.js').clientConnections;
|
var clientConnections = require('./client_connections.js').clientConnections;
|
||||||
var userDb = require('./database.js').dbs.user;
|
var userDb = require('./database.js').dbs.user;
|
||||||
var sysProp = require('./system_property.js');
|
var sysProp = require('./system_property.js');
|
||||||
var logger = require('./logger.js');
|
var logger = require('./logger.js');
|
||||||
|
var Config = require('./config.js').config;
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
|
@ -47,7 +48,7 @@ function userLogin(client, username, password, cb) {
|
||||||
);
|
);
|
||||||
|
|
||||||
var existingConnError = new Error('Already logged in as supplied user');
|
var existingConnError = new Error('Already logged in as supplied user');
|
||||||
existingClientConnection.existingConn = true;
|
existingConnError.existingConn = true;
|
||||||
|
|
||||||
return cb(existingClientConnection);
|
return cb(existingClientConnection);
|
||||||
}
|
}
|
||||||
|
@ -59,12 +60,10 @@ function userLogin(client, username, password, cb) {
|
||||||
|
|
||||||
async.parallel(
|
async.parallel(
|
||||||
[
|
[
|
||||||
function loadThemeConfig(callback) {
|
function setTheme(callback) {
|
||||||
theme.loadTheme(user.properties.theme_id, function themeLoaded(err, theme) {
|
setClientTheme(client, user.properties.theme_id);
|
||||||
client.currentTheme = theme;
|
callback(null);
|
||||||
callback(null); // always non-fatal
|
},
|
||||||
});
|
|
||||||
},
|
|
||||||
function updateSystemLoginCount(callback) {
|
function updateSystemLoginCount(callback) {
|
||||||
var sysLoginCount = sysProp.getSystemProperty('login_count') || 0;
|
var sysLoginCount = sysProp.getSystemProperty('login_count') || 0;
|
||||||
sysLoginCount = parseInt(sysLoginCount, 10) + 1;
|
sysLoginCount = parseInt(sysLoginCount, 10) + 1;
|
||||||
|
|
Loading…
Reference in New Issue