* Validation framework functional
* Use validation for FSE, NUA, etc. * Switch to nua.js from apply.js (MenuModule + validation)
This commit is contained in:
parent
e4cfb2b92e
commit
da5d88d20d
34
core/fse.js
34
core/fse.js
|
@ -49,6 +49,8 @@ exports.moduleInfo = {
|
|||
TL12 - User1
|
||||
TL13 - User2
|
||||
|
||||
TL16 - Error / Information area
|
||||
|
||||
Footer - Viewing
|
||||
HM1 - Menu (prev/next/etc.)
|
||||
|
||||
|
@ -73,7 +75,9 @@ var MCICodeIds = {
|
|||
ViewCount : 8,
|
||||
HashTags : 9,
|
||||
MessageID : 10,
|
||||
ReplyToMsgID : 11
|
||||
ReplyToMsgID : 11,
|
||||
|
||||
ErrorMsg : 16,
|
||||
},
|
||||
ViewModeFooter : {
|
||||
MsgNum : 6,
|
||||
|
@ -540,6 +544,8 @@ function FullScreenEditorModule(options) {
|
|||
self.createInitialViews(mciData, function viewsCreated(err) {
|
||||
// :TODO: Can probably be replaced with @systemMethod:validateUserNameExists when the framework is in
|
||||
// place - if this is for existing usernames else validate spec
|
||||
|
||||
/*
|
||||
self.viewControllers.header.on('leave', function headerViewLeave(view) {
|
||||
|
||||
if(2 === view.id) { // "to" field
|
||||
|
@ -551,7 +557,7 @@ function FullScreenEditorModule(options) {
|
|||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});*/
|
||||
|
||||
cb(err);
|
||||
});
|
||||
|
@ -762,6 +768,26 @@ function FullScreenEditorModule(options) {
|
|||
};
|
||||
|
||||
this.menuMethods = {
|
||||
//
|
||||
// Validation stuff
|
||||
//
|
||||
viewValidationListener : function(err, cb) {
|
||||
var errMsgView = self.viewControllers.header.getView(MCICodeIds.ViewModeHeader.ErrorMsg);
|
||||
var newFocusViewId;
|
||||
if(errMsgView) {
|
||||
if(err) {
|
||||
errMsgView.setText(err.message);
|
||||
|
||||
if(MCICodeIds.ViewModeHeader.Subject === err.view.getId()) {
|
||||
// :TODO: for "area" mode, should probably just bail if this is emtpy (e.g. cancel)
|
||||
}
|
||||
} else {
|
||||
errMsgView.clearText();
|
||||
}
|
||||
}
|
||||
cb(newFocusViewId);
|
||||
},
|
||||
|
||||
headerSubmit : function(formData, extraArgs) {
|
||||
self.switchToBody();
|
||||
},
|
||||
|
@ -880,7 +906,3 @@ FullScreenEditorModule.prototype.mciReady = function(mciData, cb) {
|
|||
this.mciReadyHandler(mciData, cb);
|
||||
//this['mciReadyHandler' + _.capitalize(this.editorType)](mciData);
|
||||
};
|
||||
|
||||
FullScreenEditorModule.prototype.validateToUserName = function(un, cb) {
|
||||
cb(null); // note: to be implemented by sub classes
|
||||
};
|
||||
|
|
|
@ -178,6 +178,11 @@ MaskEditTextView.prototype.setPropertyValue = function(propName, value) {
|
|||
|
||||
MaskEditTextView.prototype.getData = function() {
|
||||
var rawData = MaskEditTextView.super_.prototype.getData.call(this);
|
||||
|
||||
if(!rawData || 0 === rawData.length) {
|
||||
return rawData;
|
||||
}
|
||||
|
||||
var data = '';
|
||||
|
||||
assert(rawData.length <= this.patternArray.length);
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
var user = require('./user.js');
|
||||
var Config = require('./config.js').config;
|
||||
|
||||
|
||||
exports.validateNonEmpty = validateNonEmpty;
|
||||
exports.validateMessageSubject = validateMessageSubject;
|
||||
exports.validateUserNameAvail = validateUserNameAvail;
|
||||
exports.validateEmailAvail = validateEmailAvail;
|
||||
exports.validateBirthdate = validateBirthdate;
|
||||
exports.validatePasswordSpec = validatePasswordSpec;
|
||||
|
||||
function validateNonEmpty(data, cb) {
|
||||
cb(data && data.length > 0 ? null : new Error('Field cannot be empty'));
|
||||
}
|
||||
|
||||
function validateMessageSubject(data, cb) {
|
||||
cb(data && data.length > 1 ? null : new Error('Subject too short'));
|
||||
};
|
||||
|
||||
function validateUserNameAvail(data, cb) {
|
||||
if(data.length < Config.users.usernameMin) {
|
||||
cb(new Error('Username too short'));
|
||||
|
@ -34,6 +43,24 @@ function validateUserNameAvail(data, cb) {
|
|||
}
|
||||
|
||||
function validateEmailAvail(data, cb) {
|
||||
//
|
||||
// This particular method allows empty data - e.g. no email entered
|
||||
//
|
||||
if(!data || 0 === data.length) {
|
||||
return cb(null);
|
||||
}
|
||||
|
||||
//
|
||||
// Otherwise, it must be a valid email. We'll be pretty lose here, like
|
||||
// the HTML5 spec.
|
||||
//
|
||||
// See http://stackoverflow.com/questions/7786058/find-the-regex-used-by-html5-forms-for-validation
|
||||
//
|
||||
var emailRegExp = /[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9-]+(.[a-z0-9-]+)*/;
|
||||
if(!emailRegExp.test(data)) {
|
||||
return cb(new Error('Invalid email address'));
|
||||
}
|
||||
|
||||
user.getUserIdsWithProperty('email_address', data, function userIdsWithEmail(err, uids) {
|
||||
if(err) {
|
||||
cb(new Error('Internal system error'));
|
||||
|
|
|
@ -73,7 +73,17 @@ function ViewController(options) {
|
|||
case 'accept' :
|
||||
if(self.focusedView && self.focusedView.submit) {
|
||||
// :TODO: need to do validation here!!!
|
||||
self.submitForm(key);
|
||||
var focusedView = self.focusedView;
|
||||
self.validateView(focusedView, function validated(err, newFocusedViewId) {
|
||||
console.log(err)
|
||||
if(err) {
|
||||
var newFocusedView = self.getView(newFocusedViewId) || focusedView;
|
||||
self.setViewFocusWithEvents(newFocusedView, true);
|
||||
} else {
|
||||
self.submitForm(key);
|
||||
}
|
||||
});
|
||||
//self.submitForm(key);
|
||||
} else {
|
||||
self.nextFocus();
|
||||
}
|
||||
|
@ -313,6 +323,27 @@ function ViewController(options) {
|
|||
|
||||
view.setFocus(focused);
|
||||
};
|
||||
|
||||
this.validateView = function(view, cb) {
|
||||
if(view && _.isFunction(view.validate)) {
|
||||
view.validate(view.getData(), function validateResult(err) {
|
||||
var viewValidationListener = self.client.currentMenuModule.menuMethods.viewValidationListener;
|
||||
if(_.isFunction(viewValidationListener)) {
|
||||
if(err) {
|
||||
err.view = view; // pass along the view that failed
|
||||
}
|
||||
|
||||
viewValidationListener(err, function validationComplete(newViewFocusId) {
|
||||
cb(err, newViewFocusId);
|
||||
});
|
||||
} else {
|
||||
cb(err);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
cb(null);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
util.inherits(ViewController, events.EventEmitter);
|
||||
|
@ -384,56 +415,20 @@ ViewController.prototype.switchFocus = function(id) {
|
|||
var self = this;
|
||||
var focusedView = self.focusedView;
|
||||
|
||||
function performSwitch() {
|
||||
self.attachClientEvents();
|
||||
self.validateView(focusedView, function validated(err, newFocusedViewId) {
|
||||
if(err) {
|
||||
var newFocusedView = self.getView(newFocusedViewId) || focusedView;
|
||||
self.setViewFocusWithEvents(newFocusedView, true);
|
||||
} else {
|
||||
self.attachClientEvents();
|
||||
|
||||
// remove from old
|
||||
self.setViewFocusWithEvents(focusedView, false);
|
||||
// remove from old
|
||||
self.setViewFocusWithEvents(focusedView, false);
|
||||
|
||||
// set to new
|
||||
self.setViewFocusWithEvents(self.getView(id), true);
|
||||
};
|
||||
|
||||
|
||||
if(focusedView && focusedView.validate) {
|
||||
focusedView.validate(focusedView.getData(), function validated(err) {
|
||||
if(_.isFunction(self.client.currentMenuModule.menuMethods.viewValidationListener)) {
|
||||
if(err) {
|
||||
err.view = focusedView;
|
||||
}
|
||||
|
||||
self.client.currentMenuModule.menuMethods.viewValidationListener(err, function validateComplete(newFocusId) {
|
||||
if(err) {
|
||||
// :TODO: switchFocus() really needs a cb --
|
||||
var newFocusView;
|
||||
if(newFocusId) {
|
||||
newFocusView = self.getView(newFocusId) || focusedView;
|
||||
}
|
||||
|
||||
self.setViewFocusWithEvents(newFocusView, true);
|
||||
} else {
|
||||
performSwitch();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if(!err) {
|
||||
performSwitch();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
performSwitch();
|
||||
}
|
||||
|
||||
/*
|
||||
this.attachClientEvents();
|
||||
|
||||
// remove from old
|
||||
this.setViewFocusWithEvents(this.focusedView, false);
|
||||
|
||||
// set to new
|
||||
this.setViewFocusWithEvents(this.getView(id), true);
|
||||
*/
|
||||
// set to new
|
||||
self.setViewFocusWithEvents(self.getView(id), true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ViewController.prototype.nextFocus = function() {
|
||||
|
|
|
@ -153,6 +153,7 @@
|
|||
ET2: {
|
||||
argName: realName
|
||||
maxLength: 32
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
MET3: {
|
||||
argName: birthdate
|
||||
|
@ -163,10 +164,12 @@
|
|||
argName: sex
|
||||
maskPattern: A
|
||||
textStyle: upper
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
ET5: {
|
||||
argName: location
|
||||
maxLength: 32
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
ET6: {
|
||||
argName: affils
|
||||
|
@ -239,23 +242,28 @@
|
|||
focus: true
|
||||
argName: username
|
||||
maxLength: @config:users.usernameMax
|
||||
validate: @systemMethod:validateUserNameAvail
|
||||
}
|
||||
ET2: {
|
||||
argName: realName
|
||||
maxLength: 32
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
MET3: {
|
||||
argName: birthdate
|
||||
maskPattern: "####/##/##"
|
||||
validate: @systemMethod:validateBirthdate
|
||||
}
|
||||
ME4: {
|
||||
argName: sex
|
||||
maskPattern: A
|
||||
textStyle: upper
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
ET5: {
|
||||
argName: location
|
||||
maxLength: 32
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
ET6: {
|
||||
argName: affils
|
||||
|
@ -264,6 +272,7 @@
|
|||
ET7: {
|
||||
argName: email
|
||||
maxLength: 255
|
||||
validate: @systemMethod:validateEmailAvail
|
||||
}
|
||||
ET8: {
|
||||
argName: web
|
||||
|
@ -273,11 +282,13 @@
|
|||
argName: password
|
||||
password: true
|
||||
maxLength: @config:users.passwordMax
|
||||
validate: @systemMethod:validatePasswordSpec
|
||||
}
|
||||
ET10: {
|
||||
argName: passwordConfirm
|
||||
password: true
|
||||
maxLength: @config:users.passwordMax
|
||||
validate: @method:validatePassConfirmMatch
|
||||
}
|
||||
TM12: {
|
||||
argName: submission
|
||||
|
@ -362,6 +373,7 @@
|
|||
maxLength: 72
|
||||
submit: true
|
||||
text: New user feedback
|
||||
validate: @systemMethod:validateMessageSubject
|
||||
}
|
||||
}
|
||||
submit: {
|
||||
|
@ -921,11 +933,13 @@
|
|||
ET2: {
|
||||
argName: to
|
||||
focus: true
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
ET3: {
|
||||
argName: subject
|
||||
maxLength: 72
|
||||
submit: true
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
TL4: {
|
||||
// :TODO: this is for RE: line (NYI)
|
||||
|
@ -1068,11 +1082,13 @@
|
|||
argName: to
|
||||
focus: true
|
||||
text: All
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
}
|
||||
ET3: {
|
||||
argName: subject
|
||||
maxLength: 72
|
||||
submit: true
|
||||
validate: @systemMethod:validateNonEmpty
|
||||
// :TODO: Validate -> close/cancel if empty
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,22 +64,3 @@ AreaPostFSEModule.prototype.enter = function(client) {
|
|||
|
||||
AreaPostFSEModule.super_.prototype.enter.call(this, client);
|
||||
};
|
||||
|
||||
AreaPostFSEModule.prototype.validateToUserName = function(un, cb) {
|
||||
var self = this;
|
||||
|
||||
if(!un) {
|
||||
cb(new Error('Username must be supplied!'));
|
||||
return;
|
||||
}
|
||||
|
||||
if(!self.isLocalEmail()) {
|
||||
cb(null);
|
||||
return;
|
||||
}
|
||||
|
||||
user.getUserIdAndName(un, function uidAndName(err, userId, userName) {
|
||||
self.toUserId = userId;
|
||||
cb(err);
|
||||
});
|
||||
};
|
Binary file not shown.
Loading…
Reference in New Issue