Merge branch 'master' of ssh://numinibsd/git/base/enigma-bbs
This commit is contained in:
commit
513ff7109f
|
@ -96,8 +96,16 @@ function getDefaultConfig() {
|
||||||
usernameMin : 2,
|
usernameMin : 2,
|
||||||
usernameMax : 16, // Note that FidoNet wants 36 max
|
usernameMax : 16, // Note that FidoNet wants 36 max
|
||||||
usernamePattern : '^[A-Za-z0-9~!@#$%^&*()\\-\\_+]+$',
|
usernamePattern : '^[A-Za-z0-9~!@#$%^&*()\\-\\_+]+$',
|
||||||
|
|
||||||
passwordMin : 6,
|
passwordMin : 6,
|
||||||
passwordMax : 128,
|
passwordMax : 128,
|
||||||
|
|
||||||
|
realNameMax : 32,
|
||||||
|
locationMax : 32,
|
||||||
|
affilsMax : 32,
|
||||||
|
emailMax : 255,
|
||||||
|
webMax : 255,
|
||||||
|
|
||||||
requireActivation : true, // require SysOp activation?
|
requireActivation : true, // require SysOp activation?
|
||||||
invalidUsernames : [],
|
invalidUsernames : [],
|
||||||
|
|
||||||
|
|
|
@ -103,6 +103,14 @@ MaskEditTextView.maskPatternCharacterRegEx = {
|
||||||
'&' : /[\w\d\s]/, // Any "printable" 32-126, 128-255
|
'&' : /[\w\d\s]/, // Any "printable" 32-126, 128-255
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MaskEditTextView.prototype.setText = function(text) {
|
||||||
|
MaskEditTextView.super_.prototype.setText.call(this, text);
|
||||||
|
|
||||||
|
if(this.patternArray) { // :TODO: This is a hack - see TextView ctor note about setText()
|
||||||
|
this.patternArrayPos = this.patternArray.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
MaskEditTextView.prototype.setMaskPattern = function(pattern) {
|
MaskEditTextView.prototype.setMaskPattern = function(pattern) {
|
||||||
this.dimens.width = pattern.length;
|
this.dimens.width = pattern.length;
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,12 @@ SpinnerMenuView.prototype.setFocus = function(focused) {
|
||||||
this.redraw();
|
this.redraw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SpinnerMenuView.prototype.setFocusItemIndex = function(index) {
|
||||||
|
SpinnerMenuView.super_.prototype.setFocusItemIndex.call(this, index); // sets this.focusedItemIndex
|
||||||
|
|
||||||
|
this.updateSelection(); // will redraw
|
||||||
|
};
|
||||||
|
|
||||||
SpinnerMenuView.prototype.onKeyPress = function(ch, key) {
|
SpinnerMenuView.prototype.onKeyPress = function(ch, key) {
|
||||||
if(key) {
|
if(key) {
|
||||||
if(this.isKeyMapped('up', key.name)) {
|
if(this.isKeyMapped('up', key.name)) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ function validateNonEmpty(data, cb) {
|
||||||
|
|
||||||
function validateMessageSubject(data, cb) {
|
function validateMessageSubject(data, cb) {
|
||||||
cb(data && data.length > 1 ? null : new Error('Subject too short'));
|
cb(data && data.length > 1 ? null : new Error('Subject too short'));
|
||||||
};
|
}
|
||||||
|
|
||||||
function validateUserNameAvail(data, cb) {
|
function validateUserNameAvail(data, cb) {
|
||||||
if(data.length < Config.users.usernameMin) {
|
if(data.length < Config.users.usernameMin) {
|
||||||
|
|
|
@ -89,6 +89,7 @@ function TextView(options) {
|
||||||
return this.position.col + offset;
|
return this.position.col + offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// :TODO: Whatever needs init here should be done separately from setText() since it redraws/etc.
|
||||||
this.setText(options.text || '');
|
this.setText(options.text || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +98,9 @@ util.inherits(TextView, View);
|
||||||
TextView.prototype.redraw = function() {
|
TextView.prototype.redraw = function() {
|
||||||
TextView.super_.prototype.redraw.call(this);
|
TextView.super_.prototype.redraw.call(this);
|
||||||
|
|
||||||
this.drawText(this.text);
|
if(_.isString(this.text)) {
|
||||||
|
this.drawText(this.text);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TextView.prototype.setFocus = function(focused) {
|
TextView.prototype.setFocus = function(focused) {
|
||||||
|
|
|
@ -16,8 +16,10 @@ var async = require('async');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
|
||||||
|
|
||||||
exports.loadTheme = loadTheme;
|
exports.loadTheme = loadTheme;
|
||||||
exports.getThemeArt = getThemeArt;
|
exports.getThemeArt = getThemeArt;
|
||||||
|
exports.getAvailableThemes = getAvailableThemes;
|
||||||
exports.getRandomTheme = getRandomTheme;
|
exports.getRandomTheme = getRandomTheme;
|
||||||
exports.initAvailableThemes = initAvailableThemes;
|
exports.initAvailableThemes = initAvailableThemes;
|
||||||
exports.displayThemeArt = displayThemeArt;
|
exports.displayThemeArt = displayThemeArt;
|
||||||
|
@ -72,7 +74,7 @@ function refreshThemeHelpers(theme) {
|
||||||
|
|
||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadTheme(themeID, cb) {
|
function loadTheme(themeID, cb) {
|
||||||
|
@ -83,8 +85,11 @@ function loadTheme(themeID, cb) {
|
||||||
if(err) {
|
if(err) {
|
||||||
cb(err);
|
cb(err);
|
||||||
} else {
|
} else {
|
||||||
if(!_.isObject(theme.info)) {
|
if(!_.isObject(theme.info) ||
|
||||||
cb(new Error('Invalid theme or missing \'info\' section'));
|
!_.isString(theme.info.name) ||
|
||||||
|
!_.isString(theme.info.author))
|
||||||
|
{
|
||||||
|
cb(new Error('Invalid or missing "info" section!'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +133,8 @@ function initAvailableThemes(cb) {
|
||||||
});
|
});
|
||||||
|
|
||||||
Log.debug( { info : theme.info }, 'Theme loaded');
|
Log.debug( { info : theme.info }, 'Theme loaded');
|
||||||
|
} else {
|
||||||
|
Log.warn( { themeId : themeId, error : err.toString() }, 'Failed to load theme');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -146,6 +153,10 @@ function initAvailableThemes(cb) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getAvailableThemes() {
|
||||||
|
return availableThemes;
|
||||||
|
}
|
||||||
|
|
||||||
function getRandomTheme() {
|
function getRandomTheme() {
|
||||||
if(Object.getOwnPropertyNames(availableThemes).length > 0) {
|
if(Object.getOwnPropertyNames(availableThemes).length > 0) {
|
||||||
var themeIds = Object.keys(availableThemes);
|
var themeIds = Object.keys(availableThemes);
|
||||||
|
|
19
core/user.js
19
core/user.js
|
@ -375,6 +375,25 @@ User.prototype.persistAllProperties = function(cb) {
|
||||||
*/
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
|
User.prototype.setNewAuthCredentials = function(password, cb) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
generatePasswordDerivedKeyAndSalt(password, function dkAndSalt(err, info) {
|
||||||
|
if(err) {
|
||||||
|
cb(err);
|
||||||
|
} else {
|
||||||
|
var newProperties = {
|
||||||
|
pw_pbkdf2_salt : info.salt,
|
||||||
|
pw_pbkdf2_dk : info.dk,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.persistProperties(newProperties, function persisted(err) {
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
User.prototype.getAge = function() {
|
User.prototype.getAge = function() {
|
||||||
if(_.has(this.properties, 'birthdate')) {
|
if(_.has(this.properties, 'birthdate')) {
|
||||||
return moment().diff(this.properties.birthdate, 'years');
|
return moment().diff(this.properties.birthdate, 'years');
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
var MenuModule = require('./menu_module.js').MenuModule;
|
var MenuModule = require('./menu_module.js').MenuModule;
|
||||||
var ViewController = require('./view_controller.js').ViewController;
|
var ViewController = require('./view_controller.js').ViewController;
|
||||||
|
var theme = require('./theme.js');
|
||||||
|
var sysValidate = require('./system_view_validate.js');
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
|
@ -18,16 +20,21 @@ exports.moduleInfo = {
|
||||||
};
|
};
|
||||||
|
|
||||||
var MciCodeIds = {
|
var MciCodeIds = {
|
||||||
Email : 1,
|
RealName : 1,
|
||||||
Loc : 2,
|
BirthDate : 2,
|
||||||
Web : 3,
|
Sex : 3,
|
||||||
Affils : 4,
|
Loc : 4,
|
||||||
|
Affils : 5,
|
||||||
|
Email : 6,
|
||||||
|
Web : 7,
|
||||||
|
TermHeight : 8,
|
||||||
|
Theme : 9,
|
||||||
|
Password : 10,
|
||||||
|
PassConfirm : 11,
|
||||||
|
ThemeInfo : 20,
|
||||||
|
ErrorMsg : 21,
|
||||||
|
|
||||||
BirthDate : 5,
|
SaveCancel : 25,
|
||||||
Sex : 6,
|
|
||||||
|
|
||||||
Theme : 10,
|
|
||||||
ScreenSize : 11,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function UserConfigModule(options) {
|
function UserConfigModule(options) {
|
||||||
|
@ -35,18 +42,112 @@ function UserConfigModule(options) {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
self.getView = function(viewId) {
|
||||||
|
return self.viewControllers.menu.getView(viewId);
|
||||||
|
};
|
||||||
|
|
||||||
self.setViewText = function(viewId, text) {
|
self.setViewText = function(viewId, text) {
|
||||||
var v = self.viewControllers.menu.getView(viewId);
|
var v = self.getView(viewId);
|
||||||
if(v) {
|
if(v) {
|
||||||
v.setText(text);
|
v.setText(text);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.menuMethods = {
|
this.menuMethods = {
|
||||||
exitKeyPressed : function(formData, extraArgs) {
|
//
|
||||||
// :TODO: save/etc.
|
// Validation support
|
||||||
self.prevMenu();
|
//
|
||||||
}
|
validateEmailAvail : function(data, cb) {
|
||||||
|
//
|
||||||
|
// If nothing changed, we know it's OK
|
||||||
|
//
|
||||||
|
if(self.client.user.properties.email_address.toLowerCase() === data.toLowerCase()) {
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we can use the standard system method
|
||||||
|
return sysValidate.validateEmailAvail(data, cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
validatePassword : function(data, cb) {
|
||||||
|
//
|
||||||
|
// Blank is OK - this means we won't be changing it
|
||||||
|
//
|
||||||
|
if(!data || 0 === data.length) {
|
||||||
|
return cb(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise we can use the standard system method
|
||||||
|
return sysValidate.validatePasswordSpec(data, cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
validatePassConfirmMatch : function(data, cb) {
|
||||||
|
var passwordView = self.getView(MciCodeIds.Password);
|
||||||
|
cb(passwordView.getData() === data ? null : new Error('Passwords do not match'));
|
||||||
|
},
|
||||||
|
|
||||||
|
viewValidationListener : function(err, cb) {
|
||||||
|
var errMsgView = self.getView(MciCodeIds.ErrorMsg);
|
||||||
|
var newFocusId;
|
||||||
|
if(errMsgView) {
|
||||||
|
if(err) {
|
||||||
|
errMsgView.setText(err.message);
|
||||||
|
|
||||||
|
if(err.view.getId() === MciCodeIds.PassConfirm) {
|
||||||
|
newFocusId = MciCodeIds.Password;
|
||||||
|
var passwordView = self.getView(MciCodeIds.Password);
|
||||||
|
passwordView.clearText();
|
||||||
|
err.view.clearText();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errMsgView.clearText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cb(newFocusId);
|
||||||
|
},
|
||||||
|
|
||||||
|
saveChanges : function(formData, extraArgs) {
|
||||||
|
assert(formData.value.password === formData.value.passwordConfirm);
|
||||||
|
|
||||||
|
var newProperties = {
|
||||||
|
real_name : formData.value.realName,
|
||||||
|
birthdate : new Date(Date.parse(formData.value.birthdate)).toISOString(),
|
||||||
|
sex : formData.value.sex,
|
||||||
|
location : formData.value.location,
|
||||||
|
affiliation : formData.value.affils,
|
||||||
|
email_address : formData.value.email,
|
||||||
|
web_address : formData.value.web,
|
||||||
|
term_height : formData.value.termHeight.toString(),
|
||||||
|
theme_id : self.availThemeInfo[formData.value.theme].themeId,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.client.user.persistProperties(newProperties, function persisted(err) {
|
||||||
|
if(err) {
|
||||||
|
self.client.log.warn( { error : err.toString() }, 'Failed persisting updated properties');
|
||||||
|
// :TODO: warn end user!
|
||||||
|
self.prevMenu();
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// New password if it's not empty
|
||||||
|
//
|
||||||
|
self.client.log.info('User updated properties');
|
||||||
|
|
||||||
|
if(formData.value.password.length > 0) {
|
||||||
|
self.client.user.setNewAuthCredentials(formData.value.password, function newAuthStored(err) {
|
||||||
|
if(err) {
|
||||||
|
// :TODO: warn the end user!
|
||||||
|
self.client.log.warn( { error : err.toString() }, 'Failed storing new authentication credentials');
|
||||||
|
} else {
|
||||||
|
self.client.log.info('User changed authentication credentials');
|
||||||
|
}
|
||||||
|
self.prevMenu();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.prevMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +157,8 @@ UserConfigModule.prototype.mciReady = function(mciData, cb) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var vc = self.viewControllers.menu = new ViewController( { client : self.client} );
|
var vc = self.viewControllers.menu = new ViewController( { client : self.client} );
|
||||||
|
|
||||||
|
var currentThemeIdIndex = 0;
|
||||||
|
|
||||||
async.series(
|
async.series(
|
||||||
[
|
[
|
||||||
function callParentMciReady(callback) {
|
function callParentMciReady(callback) {
|
||||||
|
@ -64,17 +167,57 @@ UserConfigModule.prototype.mciReady = function(mciData, cb) {
|
||||||
function loadFromConfig(callback) {
|
function loadFromConfig(callback) {
|
||||||
vc.loadFromMenuConfig( { callingMenu : self, mciMap : mciData.menu }, callback);
|
vc.loadFromMenuConfig( { callingMenu : self, mciMap : mciData.menu }, callback);
|
||||||
},
|
},
|
||||||
|
function prepareAvailableThemes(callback) {
|
||||||
|
self.availThemeInfo = _.sortBy(_.map(theme.getAvailableThemes(), function makeThemeInfo(t, themeId) {
|
||||||
|
return {
|
||||||
|
themeId : themeId,
|
||||||
|
name : t.info.name,
|
||||||
|
author : t.info.author,
|
||||||
|
desc : _.isString(t.info.desc) ? t.info.desc : '',
|
||||||
|
group : _.isString(t.info.group) ? t.info.group : '',
|
||||||
|
};
|
||||||
|
}), 'name');
|
||||||
|
|
||||||
|
currentThemeIdIndex = _.findIndex(self.availThemeInfo, function cmp(ti) {
|
||||||
|
return ti.themeId === self.client.user.properties.theme_id;
|
||||||
|
});
|
||||||
|
|
||||||
|
callback(null);
|
||||||
|
},
|
||||||
function populateViews(callback) {
|
function populateViews(callback) {
|
||||||
var user = self.client.user;
|
var user = self.client.user;
|
||||||
|
|
||||||
self.setViewText(MciCodeIds.Email, user.properties.email_address);
|
self.setViewText(MciCodeIds.RealName, user.properties.real_name);
|
||||||
self.setViewText(MciCodeIds.Loc, user.properties.location);
|
|
||||||
self.setViewText(MciCodeIds.Web, user.properties.web_address);
|
|
||||||
self.setViewText(MciCodeIds.Affils, user.properties.affiliation);
|
|
||||||
self.setViewText(MciCodeIds.BirthDate, moment(user.properties.birthdate).format('YYYYMMDD'));
|
self.setViewText(MciCodeIds.BirthDate, moment(user.properties.birthdate).format('YYYYMMDD'));
|
||||||
self.setViewText(MciCodeIds.Sex, user.properties.sex);
|
self.setViewText(MciCodeIds.Sex, user.properties.sex);
|
||||||
|
self.setViewText(MciCodeIds.Loc, user.properties.location);
|
||||||
|
self.setViewText(MciCodeIds.Affils, user.properties.affiliation);
|
||||||
|
self.setViewText(MciCodeIds.Email, user.properties.email_address);
|
||||||
|
self.setViewText(MciCodeIds.Web, user.properties.web_address);
|
||||||
|
self.setViewText(MciCodeIds.TermHeight, user.properties.term_height.toString());
|
||||||
|
|
||||||
|
|
||||||
|
var themeView = self.getView(MciCodeIds.Theme);
|
||||||
|
if(themeView) {
|
||||||
|
themeView.setItems(_.map(self.availThemeInfo, 'name'));
|
||||||
|
themeView.setFocusItemIndex(currentThemeIdIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
var realNameView = self.getView(MciCodeIds.RealName);
|
||||||
|
if(realNameView) {
|
||||||
|
realNameView.setFocus(true); // :TODO: HACK! menu.hjson sets focus, but manual population above breaks this. Needs a real fix!
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null);
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
function complete(err) {
|
||||||
|
if(err) {
|
||||||
|
self.client.log.warn( { error : err.toString() }, 'User configuration failed to init');
|
||||||
|
self.prevMenu();
|
||||||
|
} else {
|
||||||
|
cb(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -146,6 +146,12 @@ VerticalMenuView.prototype.setFocus = function(focused) {
|
||||||
this.redraw();
|
this.redraw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VerticalMenuView.prototype.setFocusItemIndex = function(index) {
|
||||||
|
VerticalMenuView.super_.prototype.setFocusItemIndex.call(this, index); // sets this.focusedItemIndex
|
||||||
|
|
||||||
|
this.redraw();
|
||||||
|
};
|
||||||
|
|
||||||
VerticalMenuView.prototype.onKeyPress = function(ch, key) {
|
VerticalMenuView.prototype.onKeyPress = function(ch, key) {
|
||||||
|
|
||||||
if(key) {
|
if(key) {
|
||||||
|
|
|
@ -190,7 +190,7 @@
|
||||||
}
|
}
|
||||||
ET2: {
|
ET2: {
|
||||||
argName: realName
|
argName: realName
|
||||||
maxLength: 32
|
maxLength: @config:users.realNameMax
|
||||||
validate: @systemMethod:validateNonEmpty
|
validate: @systemMethod:validateNonEmpty
|
||||||
}
|
}
|
||||||
MET3: {
|
MET3: {
|
||||||
|
@ -206,21 +206,21 @@
|
||||||
}
|
}
|
||||||
ET5: {
|
ET5: {
|
||||||
argName: location
|
argName: location
|
||||||
maxLength: 32
|
maxLength: @config:users.locationMax
|
||||||
validate: @systemMethod:validateNonEmpty
|
validate: @systemMethod:validateNonEmpty
|
||||||
}
|
}
|
||||||
ET6: {
|
ET6: {
|
||||||
argName: affils
|
argName: affils
|
||||||
maxLength: 32
|
maxLength: @config:users.affilsMax
|
||||||
}
|
}
|
||||||
ET7: {
|
ET7: {
|
||||||
argName: email
|
argName: email
|
||||||
maxLength: 255
|
maxLength: @config:users.emailMax
|
||||||
validate: @systemMethod:validateEmailAvail
|
validate: @systemMethod:validateEmailAvail
|
||||||
}
|
}
|
||||||
ET8: {
|
ET8: {
|
||||||
argName: web
|
argName: web
|
||||||
maxLength: 255
|
maxLength: @config:users.webMax
|
||||||
}
|
}
|
||||||
ET9: {
|
ET9: {
|
||||||
argName: password
|
argName: password
|
||||||
|
@ -287,7 +287,7 @@
|
||||||
}
|
}
|
||||||
ET2: {
|
ET2: {
|
||||||
argName: realName
|
argName: realName
|
||||||
maxLength: 32
|
maxLength: @config:users.realNameMax
|
||||||
validate: @systemMethod:validateNonEmpty
|
validate: @systemMethod:validateNonEmpty
|
||||||
}
|
}
|
||||||
MET3: {
|
MET3: {
|
||||||
|
@ -303,21 +303,21 @@
|
||||||
}
|
}
|
||||||
ET5: {
|
ET5: {
|
||||||
argName: location
|
argName: location
|
||||||
maxLength: 32
|
maxLength: @config:users.locationMax
|
||||||
validate: @systemMethod:validateNonEmpty
|
validate: @systemMethod:validateNonEmpty
|
||||||
}
|
}
|
||||||
ET6: {
|
ET6: {
|
||||||
argName: affils
|
argName: affils
|
||||||
maxLength: 32
|
maxLength: @config:users.affilsMax
|
||||||
}
|
}
|
||||||
ET7: {
|
ET7: {
|
||||||
argName: email
|
argName: email
|
||||||
maxLength: 255
|
maxLength: @config:users.emailMax
|
||||||
validate: @systemMethod:validateEmailAvail
|
validate: @systemMethod:validateEmailAvail
|
||||||
}
|
}
|
||||||
ET8: {
|
ET8: {
|
||||||
argName: web
|
argName: web
|
||||||
maxLength: 255
|
maxLength: @config:users.webMax
|
||||||
}
|
}
|
||||||
ET9: {
|
ET9: {
|
||||||
argName: password
|
argName: password
|
||||||
|
@ -625,6 +625,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mainMenuUserConfig: {
|
mainMenuUserConfig: {
|
||||||
module: @systemModule:user_config
|
module: @systemModule:user_config
|
||||||
art: CONFSCR
|
art: CONFSCR
|
||||||
|
@ -632,30 +633,83 @@
|
||||||
0: {
|
0: {
|
||||||
mci: {
|
mci: {
|
||||||
ET1: {
|
ET1: {
|
||||||
argName: email
|
argName: realName
|
||||||
|
maxLength: @config:users.realNameMax
|
||||||
|
validate: @systemMethod:validateNonEmpty
|
||||||
|
focus: true
|
||||||
}
|
}
|
||||||
ET2: {
|
ME2: {
|
||||||
argName: location
|
argName: birthdate
|
||||||
|
maskPattern: "####/##/##"
|
||||||
}
|
}
|
||||||
ET3: {
|
ME3: {
|
||||||
argName: webAddress
|
argName: sex
|
||||||
|
maskPattern: A
|
||||||
|
textStyle: upper
|
||||||
|
validate: @systemMethod:validateNonEmpty
|
||||||
}
|
}
|
||||||
ET4: {
|
ET4: {
|
||||||
|
argName: location
|
||||||
|
maxLength: @config:users.locationMax
|
||||||
|
validate: @systemMethod:validateNonEmpty
|
||||||
|
}
|
||||||
|
ET5: {
|
||||||
argName: affils
|
argName: affils
|
||||||
|
maxLength: @config:users.affilsMax
|
||||||
}
|
}
|
||||||
ME5: {
|
ET6: {
|
||||||
maskPattern: "####/##/##"
|
argName: email
|
||||||
argName: birthdate
|
maxLength: @config:users.emailMax
|
||||||
|
validate: @method:validateEmailAvail
|
||||||
}
|
}
|
||||||
ME11: {
|
ET7: {
|
||||||
maskPattern: "##x##"
|
argName: web
|
||||||
argName: termSize
|
maxLength: @config:users.webMax
|
||||||
|
}
|
||||||
|
ME8: {
|
||||||
|
maskPattern: "##"
|
||||||
|
argName: termHeight
|
||||||
|
validate: @systemMethod:validateNonEmpty
|
||||||
|
}
|
||||||
|
SM9: {
|
||||||
|
argName: theme
|
||||||
|
}
|
||||||
|
ET10: {
|
||||||
|
argName: password
|
||||||
|
maxLength: @config:users.passwordMax
|
||||||
|
password: true
|
||||||
|
validate: @method:validatePassword
|
||||||
|
}
|
||||||
|
ET11: {
|
||||||
|
argName: passwordConfirm
|
||||||
|
maxLength: @config:users.passwordMax
|
||||||
|
password: true
|
||||||
|
validate: @method:validatePassConfirmMatch
|
||||||
|
}
|
||||||
|
TM25: {
|
||||||
|
argName: submission
|
||||||
|
items: [ "save", "cancel" ]
|
||||||
|
submit: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
submit: {
|
||||||
|
*: [
|
||||||
|
{
|
||||||
|
value: { submission: 0 }
|
||||||
|
action: @method:saveChanges
|
||||||
|
}
|
||||||
|
{
|
||||||
|
value: { submission: 1 }
|
||||||
|
action: @systemMethod:prevMenu
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
actionKeys: [
|
actionKeys: [
|
||||||
{
|
{
|
||||||
keys: [ "escape" ]
|
keys: [ "escape" ]
|
||||||
action: @method:exitKeyPressed
|
action: @systemMethod:prevMenu
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ exports.getModule = NewUserAppModule;
|
||||||
exports.moduleInfo = {
|
exports.moduleInfo = {
|
||||||
name : 'NUA',
|
name : 'NUA',
|
||||||
desc : 'New User Application',
|
desc : 'New User Application',
|
||||||
}
|
};
|
||||||
|
|
||||||
var MciViewIds = {
|
var MciViewIds = {
|
||||||
userName : 1,
|
userName : 1,
|
||||||
|
|
Binary file not shown.
|
@ -273,6 +273,28 @@
|
||||||
ST8: { width: 17 }
|
ST8: { width: 17 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainMenuUserConfig: {
|
||||||
|
mci: {
|
||||||
|
ET1: { width: 27 }
|
||||||
|
ME2: { width: 27 }
|
||||||
|
ME3: { width: 27 }
|
||||||
|
ET4: { width: 27 }
|
||||||
|
ET5: { width: 27 }
|
||||||
|
ET6: { width: 27 }
|
||||||
|
ET7: { width: 27 }
|
||||||
|
ET8: { width: 27 }
|
||||||
|
ET9: { width: 27 }
|
||||||
|
ET10: { width: 18 }
|
||||||
|
ET11: { width: 18 }
|
||||||
|
TL20: { width: 71 }
|
||||||
|
TL21: { width: 43 }
|
||||||
|
|
||||||
|
TM25: {
|
||||||
|
focusTextStyle: first lower
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue