Finally a running version again, event pollers aren't dealt with yet though

This commit is contained in:
Dominic Bosch 2014-02-24 13:20:25 +01:00
parent 8a6d357439
commit f35aa5a285
18 changed files with 233 additions and 334 deletions

View file

@ -40,8 +40,8 @@ exports = module.exports = ( args ) =>
exports.addListener = ( evt, eh ) =>
@ee.addListener evt, eh
#TODO as soon as an event handler is added it needs to receive the
#full list of existing and activated rules
db.getRules ( err, obj ) =>
@ee.emit 'init', rule for id, rule of obj
# cb ( obj ) where obj should contain at least the HTTP response code and a message
@ -153,7 +153,6 @@ commandFunctions =
forge_rule: ( user, obj, cb ) =>
obj.event = JSON.parse obj.event
console.log obj
db.getRule obj.id, ( err, objRule ) =>
if objRule isnt null
answ =
@ -165,159 +164,15 @@ commandFunctions =
message: 'Rule stored and activated!'
rule =
id: obj.id
# users: [ user.username ] # This should be fetched from the db in each listener
event: "#{ obj.event.module } -> #{ obj.event.function }"
conditions: JSON.parse obj.conditions
actions: JSON.parse obj.actions
console.log rule
modules = JSON.parse obj.event.action_params
console.log 'store rule'
modules = JSON.parse obj.action_params
db.storeRule rule.id, JSON.stringify rule
console.log 'link rule'
db.linkRule rule.id, user.username
console.log 'activate rule'
db.activateRule rule.id, user.username
console.log 'store event params'
db.storeEventUserParams obj.event.module, user.username, obj.event_params
console.log 'store action params'
db.storeActionUserParams id, user.username, params for id, params of modules
#TODO implement ID approach, check for existing
@ee.emit 'newRule', rule
db.storeActionUserParams id, user.username, JSON.stringify params for id, params of modules
@ee.emit 'newRule', JSON.stringify rule
cb answ
# exports.loadModule = function(directory, name, callback) {
# try {
# fs.readFile(path.resolve(__dirname, '..', directory, name, name + '.js'), 'utf8', function (err, data) {
# if (err) {
# log.error('LM', 'Loading module file!');
# return;
# }
# var mod = exports.requireFromString(data, name, directory);
# if(mod && fs.existsSync(path.resolve(__dirname, '..', directory, name, 'credentials.json'))) {
# fs.readFile(path.resolve(__dirname, '..', directory, name, 'credentials.json'), 'utf8', function (err, auth) {
# if (err) {
# log.error('LM', 'Loading credentials file for "' + name + '"!');
# callback(name, data, mod, null);
# return;
# }
# if(mod.loadCredentials) mod.loadCredentials(JSON.parse(auth));
# callback(name, data, mod, auth);
# });
# } else {
# // Hand back the name, the string contents and the compiled module
# callback(name, data, mod, null);
# }
# });
# } catch(err) {
# log.error('LM', 'Failed loading module "' + name + '"');
# }
# };
# exports.loadModules = function(directory, callback) {
# fs.readdir(path.resolve(__dirname, '..', directory), function (err, list) {
# if (err) {
# log.error('LM', 'loading modules directory: ' + err);
# return;
# }
# log.info('LM', 'Loading ' + list.length + ' modules from "' + directory + '"');
# list.forEach(function (file) {
# fs.stat(path.resolve(__dirname, '..', directory, file), function (err, stat) {
# if (stat && stat.isDirectory()) {
# exports.loadModule(directory, file, callback);
# }
# });
# });
# });
# };
# exports.storeEventModule = function (objUser, obj, answHandler) {
# try {
# // TODO in the future we might want to link the modules close to the user
# // and allow for e.g. private modules
# // we need a child process to run this code and kill it after invocation
# var m = exports.requireFromString(obj.data, obj.id);
# obj.methods = Object.keys(m);
# answHandler.answerSuccess('Thank you for the event module!');
# db.storeEventModule(obj.id, obj);
# } catch (err) {
# answHandler.answerError(err.message);
# console.error(err);
# }
# };
# exports.getAllEventModules = function ( objUser, obj, answHandler ) {
# db.getEventModules(function(err, obj) {
# if(err) answHandler.answerError('Failed fetching event modules: ' + err.message);
# else answHandler.answerSuccess(obj);
# });
# };
# exports.storeActionModule = function (objUser, obj, answHandler) {
# var m = exports.requireFromString(obj.data, obj.id);
# obj.methods = Object.keys(m);
# answHandler.answerSuccess('Thank you for the action module!');
# db.storeActionModule(obj.id, obj);
# };
# exports.getAllActionModules = function ( objUser, obj, answHandler ) {
# db.getActionModules(function(err, obj) {
# if(err) answHandler.answerError('Failed fetching action modules: ' + err.message);
# else answHandler.answerSuccess(obj);
# });
# };
# exports.storeRule = function (objUser, obj, answHandler) {
# //TODO fix, twice same logic
# var cbEventModule = function (lstParams) {
# return function(err, data) {
# if(err) {
# err.addInfo = 'fetching event module';
# log.error('MM', err);
# }
# if(!err && data) {
# if(data.params) {
# lstParams.eventmodules[data.id] = data.params;
# }
# }
# if(--semaphore === 0) answHandler.answerSuccess(lstParams);
# };
# };
# var cbActionModule = function (lstParams) {
# return function(err, data) {
# if(err) {
# err.addInfo = 'fetching action module';
# log.error('MM', err);
# }
# if(!err && data) {
# if(data.params) {
# lstParams.actionmodules[data.id] = data.params;
# }
# }
# if(--semaphore === 0) answHandler.answerSuccess(lstParams);
# };
# };
# var semaphore = 1;
# var lst = {
# eventmodules: {},
# actionmodules: {}
# };
# try {
# var objRule = JSON.parse(obj.data);
# for(var i = 0; i < objRule.actions.length; i++) {
# semaphore++;
# db.getActionModule(objRule.actions[i].module.split('->')[0], cbActionModule(lst));
# }
# db.getEventModule(objRule.event.split('->')[0], cbEventModule(lst));
# db.storeRule(objRule.id, objUser.username, obj.data);
# ee.emit('newRule', objRule);
# // for( var i = 0; i < eventHandlers.length; i++ ) {
# // eventHandlers[i]( objRule );
# // }
# } catch(err) {
# answHandler.answerError(err.message);
# log.error('MM', err);
# }
# };

View file

@ -41,7 +41,8 @@ exports.compileString = ( src, id, params, lang ) =>
answ =
code: 200
message: 'Successfully compiled'
src = "'use strict;'\n" + src
# src = "'use strict;'\n" + src
if lang is '0'
try
src = cs.compile src
@ -49,13 +50,13 @@ exports.compileString = ( src, id, params, lang ) =>
answ.code = 400
answ.message = 'Compilation of CoffeeScript failed at line ' +
err.location.first_line
#FIXME not log but debug module is required to provide information to the user
sandbox =
id: id
params: params
needle: needle
log: @log
log: console.log
# console: console #TODO remove!
exports: {}
#TODO child_process to run module!
#Define max runtime per loop as 10 seconds, after that the child will be killed
@ -64,8 +65,10 @@ exports.compileString = ( src, id, params, lang ) =>
try
vm.runInNewContext src, sandbox, id + '.vm'
catch err
console.log err
answ.code = 400
answ.message = 'Loading Module failed: ' + err.message
ret =
answ: answ
module: sandbox.exports
module: sandbox.exports
ret

View file

@ -67,7 +67,7 @@ exports.handleEvent = ( req, resp ) ->
body += data
req.on 'end', ->
if req.session and req.session.user
obj = qs.parse body
obj = JSON.parse body
# If required event properties are present we process the event #
if obj and obj.event
timestamp = ( new Date ).toISOString()

View file

@ -159,10 +159,18 @@ init = =>
# from engine and event poller
@log.info 'RS | Initialzing module manager'
cm args
cm.addListener 'init', ( evt ) ->
poller.send
event: 'init'
data:evt
cm.addListener 'newRule', ( evt ) ->
poller.send evt
poller.send
event: 'newRule'
data:evt
cm.addListener 'init', ( evt ) ->
engine.internalEvent 'init', evt
cm.addListener 'newRule', ( evt ) ->
engine.internalEvent evt
engine.internalEvent 'newRule', evt
@log.info 'RS | Initialzing http listener'
# The request handler passes certain requests to the module manager

View file

@ -43,7 +43,16 @@ Components Manager
};
exports.addListener = function(evt, eh) {
return _this.ee.addListener(evt, eh);
_this.ee.addListener(evt, eh);
return db.getRules(function(err, obj) {
var id, rule, _results;
_results = [];
for (id in obj) {
rule = obj[id];
_results.push(_this.ee.emit('init', rule));
}
return _results;
});
};
exports.processRequest = function(user, obj, cb) {
@ -202,7 +211,6 @@ Components Manager
},
forge_rule: function(user, obj, cb) {
obj.event = JSON.parse(obj.event);
console.log(obj);
return db.getRule(obj.id, function(err, objRule) {
var answ, id, modules, params, rule;
if (objRule !== null) {
@ -221,22 +229,16 @@ Components Manager
conditions: JSON.parse(obj.conditions),
actions: JSON.parse(obj.actions)
};
console.log(rule);
modules = JSON.parse(obj.event.action_params);
console.log('store rule');
modules = JSON.parse(obj.action_params);
db.storeRule(rule.id, JSON.stringify(rule));
console.log('link rule');
db.linkRule(rule.id, user.username);
console.log('activate rule');
db.activateRule(rule.id, user.username);
console.log('store event params');
db.storeEventUserParams(obj.event.module, user.username, obj.event_params);
console.log('store action params');
for (id in modules) {
params = modules[id];
db.storeActionUserParams(id, user.username, params);
db.storeActionUserParams(id, user.username, JSON.stringify(params));
}
_this.ee.emit('newRule', rule);
_this.ee.emit('newRule', JSON.stringify(rule));
}
return cb(answ);
});

View file

@ -51,7 +51,6 @@ Dynamic Modules
code: 200,
message: 'Successfully compiled'
};
src = "'use strict;'\n" + src;
if (lang === '0') {
try {
src = cs.compile(src);
@ -65,20 +64,22 @@ Dynamic Modules
id: id,
params: params,
needle: needle,
log: _this.log,
log: console.log,
exports: {}
};
try {
vm.runInNewContext(src, sandbox, id + '.vm');
} catch (_error) {
err = _error;
console.log(err);
answ.code = 400;
answ.message = 'Loading Module failed: ' + err.message;
}
return ret = {
ret = {
answ: answ,
module: sandbox.exports
};
return ret;
};
}).call(this);

View file

@ -1,110 +1,66 @@
'use strict';
var path = require('path'),
// qEvents = new (require('./queue')).Queue(), //TODO export queue into redis
regex = /\$X\.[\w\.\[\]]*/g, // find properties of $X
listRules = {},
listActionModules = {},
isRunning = true,
mm, poller, db, log;
dynmod = require('./dynamic-modules'),
db = require('./persistence'), log;
exports = module.exports = function( args ) {
log = args.logger;
mm = require('./components-manager')(args);
db( args);
dynmod(args);
pollQueue();
return module.exports;
};
exports.internalEvent = function( evt ) {
console.log('engine got internal event');
console.log(evt);
}
/*
* Initialize the rules engine which initializes the module loader.
* @param {Object} db_link the link to the db, see [db\_interface](db_interface.html)
* @param {String} db_port the db port
* @param {String} crypto_key the key to be used for encryption on the db, max legnth 256
*/
exports.addPersistence = function(db_link) {
db = db_link;
// if(mm && db) db.getActionModules(function(err, obj) {
// if(err) log.error('EN', 'retrieving Action Modules from DB!');
// else {
// if(!obj) {
// log.info('EN', 'No Action Modules found in DB!');
// loadRulesFromDB();
// } else {
// var m;
// for(var el in obj) {
// log.info('EN', 'Loading Action Module from DB: ' + el);
// try{
// m = mm.requireFromString(obj[el], el);
// db.getActionModuleAuth(el, function(mod) {
// return function(err, obj) {
// if(obj && mod.loadCredentials) mod.loadCredentials(JSON.parse(obj));
// };
// }(m));
// listActionModules[el] = m;
// } catch(e) {
// e.addInfo = 'error in action module "' + el + '"';
// log.error('EN', e);
// }
// }
// loadRulesFromDB();
// }
// }
// });
// else log.severe('EN', new Error('Module Loader or DB not defined!'));
};
var updateActionModules = function() {
for ( var user in listRules ) {
if(!listActionModules[user]) listActionModules[user] = {};
for ( var rule in listRules[user] ) {
var actions = listRules[user][rule].actions;
for ( var i = 0; i < actions.length; i++ ){
var arrMod = actions[i].split(' -> ');
if ( !listActionModules[user][arrMod[0]] ){
db.getActionInvoker(arrMod[0], function( err, objAM ){
db.getActionUserParams(arrMod[0], user, function( err, objParams ) {
console.log (objAM);
function loadRulesFromDB() {
if(db) db.getRules(function(err, obj) {
for(var el in obj){
if(obj[el]) exports.addRule(JSON.parse(obj[el]));
//FIXME am name is called 'actions'???
// if(objParams) { //TODO we don't need them for all modules
var answ = dynmod.compileString(objAM.code, objAM.actions + "_" + user, objParams, objAM.lang);
console.log('answ');
console.log(answ);
listActionModules[user][arrMod[0]] = answ.module;
console.log('loaded ' + user + ': ' + arrMod[0]);
console.log(listActionModules);
// }
});
});
}
}
}
});
//start to poll the event queue
pollQueue();
}
/**
* Insert an action module into the list of available interfaces.
* @param {Object} objModule the action module object
*/
exports.loadActionModule = function(name, objModule) {
//TODO not used yet, load action modules from db for each rule per user
// TODO only load module once, load user specific parameters per user
// when rule is activated by user. invoked action then uses user specific
// parameters
log.info('EN', 'Action module "' + name + '" loaded');
listActionModules[name] = objModule;
};
exports.getActionModule = function(name) {
return listActionModules[name];
};
/**
* Add a rule into the working memory
* @param {Object} objRule the rule object
*/
exports.addRule = function(objRule) {
//TODO validate rule
log.info('EN', 'Loading Rule');
log.info('EN', objRule);
log.info('EN', 'Loading Rule: ' + objRule.id);
if(listRules[objRule.id]) log.info('EN', 'Replacing rule: ' + objRule.id);
listRules[objRule.id] = objRule;
// Notify poller about eventual candidate
try {
poller.send('event|'+objRule.event);
} catch (err) {
log.info('EN', 'Unable to inform poller about new active rule!');
}
};
exports.internalEvent = function( evt, data ) {
try{
var obj = JSON.parse( data );
db.getRuleActivatedUsers(obj.id, function ( err, arrUsers ) {
for(var i = 0; i < arrUsers.length; i++) {
if( !listRules[arrUsers[i]]) listRules[arrUsers[i]] = {};
listRules[arrUsers[i]][obj.id] = obj;
updateActionModules();
}
});
} catch( err ) {
console.log( err );
}
};
function pollQueue() {
if(isRunning) {
db.popEvent(function (err, obj) {
@ -123,8 +79,10 @@ function pollQueue() {
function processEvent(evt) {
log.info('EN', 'processing event: ' + evt.event + '(' + evt.eventid + ')');
var actions = checkEvent(evt);
for(var i = 0; i < actions.length; i++) {
invokeAction(evt, actions[i]);
for(var user in actions) {
for(var i = 0; i < actions[user].length; i++) {
invokeAction(evt, user, actions[user][i]);
}
}
}
@ -134,25 +92,50 @@ function processEvent(evt) {
* @param {Object} evt the event to check
*/
function checkEvent(evt) {
var actions = [];
for(var rn in listRules) {
var actions = {};
for(var user in listRules) {
actions[user] = [];
for(var rule in listRules[user]) {
//TODO this needs to get depth safe, not only data but eventually also
// on one level above (eventid and other meta)
if(listRules[rn].event === evt.event && validConditions(evt.payload, listRules[rn])) {
log.info('EN', 'Rule "' + rn + '" fired');
actions = actions.concat(listRules[rn].actions);
if(listRules[user][rule].event === evt.event && validConditions(evt.payload, listRules[user][rule])) {
log.info('EN', 'Rule "' + rule + '" fired');
var arrAct = listRules[user][rule].actions;
for(var i = 0; i < arrAct.length; i++) {
if(actions[user].indexOf(arrAct[i]) === -1) actions[user].push(arrAct[i]);
}
}
}
}
return actions;
}
// {
// "event": "emailyak -> newMail",
// "payload": {
// "TextBody": "hello"
// }
// }
// exports.sendMail = ( args ) ->
// url = 'https://api.emailyak.com/v1/ps1g59ndfcwg10w/json/send/email/'
// data =
// FromAddress: 'tester@mscliveweb.simpleyak.com'
// ToAddress: 'dominic.bosch.db@gmail.com'
// TextBody: 'test'
// needle.post url, JSON.stringify( data ), {json: true}, ( err, resp, body ) ->
// log err
// log body
/**
* Checks whether all conditions of the rule are met by the event.
* @param {Object} evt the event to check
* @param {Object} rule the rule with its conditions
*/
function validConditions(evt, rule) {
for(var property in rule.condition){
for(var property in rule.conditions){
if(!evt[property] || evt[property] != rule.condition[property]) return false;
}
return true;
@ -163,22 +146,27 @@ function validConditions(evt, rule) {
* @param {Object} evt The event that invoked the action
* @param {Object} action The action to be invoked
*/
function invokeAction(evt, action) {
function invokeAction( evt, user, action ) {
var actionargs = {},
arrModule = action.module.split('->');
arrModule = action.split(' -> ');
//FIXME internal events, such as loopback ha sno arrow
//TODO this requires change. the module property will be the identifier
// in the actions object (or shall we allow several times the same action?)
if(arrModule.length < 2) {
log.error('EN', 'Invalid rule detected!');
return;
}
var srvc = listActionModules[arrModule[0]];
console.log('invoking action');
console.log(arrModule[0]);
console.log(listActionModules);
var srvc = listActionModules[user][arrModule[0]];
console.log(srvc);
if(srvc && srvc[arrModule[1]]) {
//FIXME preprocessing not only on data
//FIXME no preprocessing at all, why don't we just pass the whole event to the action?'
preprocessActionArguments(evt.payload, action.arguments, actionargs);
// preprocessActionArguments(evt.payload, action.arguments, actionargs);
try {
if(srvc[arrModule[1]]) srvc[arrModule[1]](actionargs);
if(srvc[arrModule[1]]) srvc[arrModule[1]](evt.payload);
} catch(err) {
log.error('EN', 'during action execution: ' + err);
}
@ -186,53 +174,52 @@ function invokeAction(evt, action) {
else log.info('EN', 'No api interface found for: ' + action.module);
}
/**
* Action properties may contain event properties which need to be resolved beforehand.
* @param {Object} evt The event whose property values can be used in the rules action
* @param {Object} act The rules action arguments
* @param {Object} res The object to be used to enter the new properties
*/
function preprocessActionArguments(evt, act, res) {
for(var prop in act) {
/*
* If the property is an object itself we go into recursion
*/
if(typeof act[prop] === 'object') {
res[prop] = {};
preprocessActionArguments(evt, act[prop], res[prop]);
}
else {
var txt = act[prop];
var arr = txt.match(regex);
/*
* If rules action property holds event properties we resolve them and
* replace the original action property
*/
// console.log(evt);
if(arr) {
for(var i = 0; i < arr.length; i++) {
/*
* The first three characters are '$X.', followed by the property
*/
var actionProp = arr[i].substring(3).toLowerCase();
// console.log(actionProp);
for(var eprop in evt) {
// our rules language doesn't care about upper or lower case
if(eprop.toLowerCase() === actionProp) {
txt = txt.replace(arr[i], evt[eprop]);
}
}
txt = txt.replace(arr[i], '[property not available]');
}
}
res[prop] = txt;
}
}
}
// /**
// * Action properties may contain event properties which need to be resolved beforehand.
// * @param {Object} evt The event whose property values can be used in the rules action
// * @param {Object} act The rules action arguments
// * @param {Object} res The object to be used to enter the new properties
// */
// function preprocessActionArguments(evt, act, res) {
// for(var prop in act) {
// /*
// * If the property is an object itself we go into recursion
// */
// if(typeof act[prop] === 'object') {
// res[prop] = {};
// preprocessActionArguments(evt, act[prop], res[prop]);
// }
// else {
// var txt = act[prop];
// var arr = txt.match(regex);
// * If rules action property holds event properties we resolve them and
// * replace the original action property
// // console.log(evt);
// if(arr) {
// for(var i = 0; i < arr.length; i++) {
// /*
// * The first three characters are '$X.', followed by the property
// */
// var actionProp = arr[i].substring(3).toLowerCase();
// // console.log(actionProp);
// for(var eprop in evt) {
// // our rules language doesn't care about upper or lower case
// if(eprop.toLowerCase() === actionProp) {
// txt = txt.replace(arr[i], evt[eprop]);
// }
// }
// txt = txt.replace(arr[i], '[property not available]');
// }
// }
// res[prop] = txt;
// }
// }
// }
exports.shutDown = function() {
if(log) log.info('EN', 'Shutting down Poller and DB Link');
isRunning = false;
if(poller) poller.send('cmd|shutdown');
if(db) db.shutDown();
};

View file

@ -114,8 +114,8 @@ function initMessageActions() {
};
process.on('message', function( obj ) {
console.log( 'message: ');
console.log (obj);
// console.log( 'message: ');
// console.log (obj);
// var arrProps = obj .split('|');
// if(arrProps.length < 2) log.error('EP', 'too few parameter in message!');
// else {

View file

@ -74,7 +74,7 @@ Request Handler
return req.on('end', function() {
var answ, obj, rand, timestamp;
if (req.session && req.session.user) {
obj = qs.parse(body);
obj = JSON.parse(body);
if (obj && obj.event) {
timestamp = (new Date).toISOString();
rand = (Math.floor(Math.random() * 10e9)).toString(16).toUpperCase();

View file

@ -149,11 +149,23 @@ WebAPI-ECA Engine
poller = cp.fork(path.resolve(__dirname, nameEP), cliArgs);
_this.log.info('RS | Initialzing module manager');
cm(args);
cm.addListener('newRule', function(evt) {
return poller.send(evt);
cm.addListener('init', function(evt) {
return poller.send({
event: 'init',
data: evt
});
});
cm.addListener('newRule', function(evt) {
return engine.internalEvent(evt);
return poller.send({
event: 'newRule',
data: evt
});
});
cm.addListener('init', function(evt) {
return engine.internalEvent('init', evt);
});
cm.addListener('newRule', function(evt) {
return engine.internalEvent('newRule', evt);
});
_this.log.info('RS | Initialzing http listener');
args['request-service'] = cm.processRequest;

View file

@ -0,0 +1,8 @@
fOnLoad = () ->
document.title = 'Error!'
$( '#pagetitle' ).text 'Hi {{{user.username}}}, there has been an error!'
$( '#info' ).text 'Error: {{{message}}}'
$( '#info' ).attr 'class', 'error'
window.addEventListener 'load', fOnLoad, true

View file

@ -13,8 +13,9 @@ fOnLoad = () ->
$( '#but_submit' ).click () ->
try
data = JSON.parse editor.getValue()
$.post( '/event', data )
val = editor.getValue()
JSON.parse val # try to parse, throw an error if JSON not valid
$.post( '/event', val )
.done ( data ) ->
$( '#info' ).text data.message
$( '#info' ).attr 'class', 'success'

View file

@ -127,10 +127,13 @@ fOnLoad = () ->
$( '#but_submit' ).click () ->
arrEP = $( '#select_event option:selected' ).val().split ' -> '
try
if $( '#select_event option:selected' ).length is 0
throw new Error 'Please create an Event Poller first!'
arrEP = $( '#select_event option:selected' ).val().split ' -> '
if $( '#input_id' ).val() is ''
throw new Error 'Please enter a module name!'
throw new Error 'Please enter a rule name!'
ep = {}
$( "#event_poller_params tr" ).each () ->

View file

@ -0,0 +1,14 @@
// Generated by CoffeeScript 1.6.3
(function() {
var fOnLoad;
fOnLoad = function() {
document.title = 'Error!';
$('#pagetitle').text('Hi {{{user.username}}}, there has been an error!');
$('#info').text('Error: {{{message}}}');
return $('#info').attr('class', 'error');
};
window.addEventListener('load', fOnLoad, true);
}).call(this);

View file

@ -13,10 +13,11 @@
$('#editor').css('height', '400px');
$('#editor').css('width', '600px');
return $('#but_submit').click(function() {
var data, err;
var err, val;
try {
data = JSON.parse(editor.getValue());
return $.post('/event', data).done(function(data) {
val = editor.getValue();
JSON.parse(val);
return $.post('/event', val).done(function(data) {
$('#info').text(data.message);
return $('#info').attr('class', 'success');
}).fail(function(err) {

View file

@ -162,10 +162,13 @@
});
return $('#but_submit').click(function() {
var acts, ap, arrEP, ep, err;
arrEP = $('#select_event option:selected').val().split(' -> ');
try {
if ($('#select_event option:selected').length === 0) {
throw new Error('Please create an Event Poller first!');
}
arrEP = $('#select_event option:selected').val().split(' -> ');
if ($('#input_id').val() === '') {
throw new Error('Please enter a module name!');
throw new Error('Please enter a rule name!');
}
ep = {};
$("#event_poller_params tr").each(function() {

View file

View file

@ -37,7 +37,8 @@ exports.createBinderEntry = ( args ) ->
if err
log err
if resp.statusCode isnt 200
log "Request not successful: #{ body }"
log 'Request not successful:'
log body
</div>
<button id="but_submit">save</button>
</td>