rbrindley: branch rbrindley/features_revamp r4742 - /team/rbrindley/features_...
SVN commits to the Asterisk-GUI project
asterisk-gui-commits at lists.digium.com
Thu Apr 16 14:18:28 CDT 2009
Author: rbrindley
Date: Thu Apr 16 14:18:24 2009
New Revision: 4742
URL: http://svn.digium.com/svn-view/asterisk-gui?view=rev&rev=4742
Log:
- added all major javascript functions for the call features page
Modified:
team/rbrindley/features_revamp/config/js/features2.js
Modified: team/rbrindley/features_revamp/config/js/features2.js
URL: http://svn.digium.com/svn-view/asterisk-gui/team/rbrindley/features_revamp/config/js/features2.js?view=diff&rev=4742&r1=4741&r2=4742
==============================================================================
--- team/rbrindley/features_revamp/config/js/features2.js (original)
+++ team/rbrindley/features_revamp/config/js/features2.js Thu Apr 16 14:18:24 2009
@@ -16,19 +16,155 @@
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
-var enabled_apps;
var exten_conf;
var feat_conf;
+var gui_conf;
var amap_table = $('#application_map_list tbody');
+var amap_orig_name;
+var vals = {};
+var dial_options;
+var dial_options_list = ['t', 'T', 'h', 'H', 'k', 'K'];
/**
* function to edit options
* @param obj the DOM object
*/
var edit = function(obj) {
- this.vals[obj.attr('id')] = obj.val();
- updateMsg(obj, 'edit');
-};
+ vals[obj.attr('id')] = obj.val();
+ if (typeof edit_funcs[obj.attr('id')] !== 'function') {
+ top.log.error('edit: edit_funcs["' + obj.attr('id') + '"] is not a function.');
+ updateMsg(obj, 'error', 'Error: Edit function was not found.');
+ return false;
+ }
+
+ try {
+ edit_funcs[obj.attr('id')](obj.val());
+ updateMsg(obj, 'edit');
+ } catch(e) {
+ switch (e.name) {
+ case 'ShouldRemoveException':
+ updateMsg(obj, 'error', 'Error: Should be removed instead.');
+ default:
+ updateMsg(obj, 'error', e.message);
+ }
+ }
+};
+
+/**
+ * object to hold all the (asterisk) editing/removing functions.
+ * This is done instead of generalizing them into sectioned objects
+ * because the layout/sections/organization may change.
+ * NOTE: only dial options use remove_funcs, removing for the others
+ * is just their edit_func with '' as the val
+ */
+var edit_funcs = {};
+var remove_funcs = {};
+
+edit_funcs['feature_featuredigittimeout'] = function(val) {
+ /* lets validate the val */
+ validate(val, {num: true, positive: true});
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'general', name: 'featuredigittimeout', val: val});
+};
+
+edit_funcs['parkext'] = function(val) {
+ /* lets validate */
+ validate(val, {num: true, positive: true, extens: true});
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'general', name: 'parkext', val: val});
+};
+
+edit_funcs['parkpos'] = function(val) {
+ /* validate special format */
+ if (!val.match(/[0-9][0-9]*\-[0-9][0-9]*/)) {
+ throw TypeError('Invalid: Please use "<num>-<num>" format');
+ }
+
+ /* lets split */
+ var splits = val.split('-');
+ var pos_start = parseInt(splits[0], 10);
+ var pos_end = parseInt(splits[1], 10);
+
+ /* now lets validate the start and end */
+ validate(pos_start, {num: true, positive: true});
+ validate(pos_end, {num: true, positive: true});
+
+ /* we need to do a special validate for extens */
+ gui_conf = context2json({
+ filename: 'guipreferences.conf',
+ context: 'general',
+ usf: 1
+ });
+ var prefs = {ue: 'User Extensions', mm: 'Conference Extensions', qe: 'Queue Extensions', vme: 'Voicemail Extensions', rge: 'Ring Group Extensions', vmg: 'Voicemail Group Extensions'};
+ for (pref in prefs) {
+ if (!prefs.hasOwnProperty(pref)) {
+ continue;
+ }
+
+ var start = gui_conf[pref + '_start'];
+ var end = gui_conf[pref + '_end'];
+
+ if ((pos_start >= start && pos_start <= end) || (pos_end >= start && pos_end <= end) || (pos_start < start && pos_end >= start)) {
+ top.log.warn('edit_funcs[\'parkext\']: conflicts with ' + pref + '.');
+ throw RangeError('Invalid: Conflicts with ' + prefs[pref] + ' range, ' + start + '-' + end);
+ }
+ }
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'general', name: 'parkpos', val: val});
+}
+
+edit_funcs['parkingtime'] = function(val) {
+ /* lets validate */
+ validate(val, {num: true, positive: true});
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'general', name: 'parkingtime', val: val});
+};
+
+edit_funcs['fmap_blindxfer'] = function(val) {
+ /* lets validate */
+ validate(val, {keypress: true});
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'featuremap', name: 'blindxfer', val: val});
+};
+
+edit_funcs['fmap_disconnect'] = function(val) {
+ /* lets validate */
+ validate(val, {keypress: true});
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'featuremap', name: 'disconnect', val: val});
+};
+
+edit_funcs['fmap_atxfer'] = function(val) {
+ /* lets validate */
+ validate(val, {keypress: true});
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'featuremap', name: 'atxfer', val: val});
+};
+
+edit_funcs['fmap_parkcall'] = function(val) {
+ /* lets validate */
+ validate(val, {keypress: true});
+
+ /* kk, all good, now update asterisk and go */
+ return sendUpdate({cxt: 'featuremap', name: 'parkcall', val: val});
+};
+
+/* dynamically define all the dial options edit/remove funcs since there the same */
+for (var i=0; i<dial_options_list.length; i++) {
+ edit_funcs['dial_'+dial_options_list[i]] = function(val) {
+ top.pbx.dial_options.add(val);
+ }
+ remove_funcs['dial_'+dial_options_list[i]] = function(val) {
+ top.pbx.dial_options.remove(val);
+ }
+}
/**
* function to load options
@@ -40,14 +176,14 @@
usf: 1
});
- var dial_opts = exten_conf['DIALOPTIONS'] || '';
+ var dial_options = exten_conf['DIALOPTIONS'] || '';
if (exten_conf['FEATURES'] && exten_conf['FEATURES'].length) {
- enabled_apps = exten_conf['FEATURES'].split('#');
+ amap_enabled = exten_conf['FEATURES'].split('#');
}
/* set all the enabled dial options to checked */
- dial_opts = dial_opts.split('');
+ dial_opts = dial_options.split('');
for (var i=0; i<dial_opts.length; i++) {
$('#dial_'+dial_opts[i]).attr('checked', 'checked').parents('.feature').removeClass('disabled');
}
@@ -115,9 +251,12 @@
}
var listAmap = function(name) {
+ /* is it new or not? */
if (name) {
+ /* list an existing amap */
var amap_fields = feat_conf['applicationmap'][name].split(',');
} else {
+ /* set a new amap default values */
name = '';
var amap_fields = ['', 'self', '', ''];
}
@@ -127,7 +266,11 @@
}
var row = $('#application_map_list > tbody > tr.template').clone();
- row.find('.enabled :checkbox').attr('checked', (enabled_apps.contains(name)?true:false));
+ /* only set id if its an existing amap */
+ if (name !== '') {
+ row.attr('id', 'amap_' + name);
+ }
+ row.find('.enabled :checkbox').attr('checked', (amap_enabled.contains(name)?true:false));
row.find('.name :text').attr('value', name);
row.find('.digits :text').attr('value', amap_fields[0]);
row.find('.app_name :text').attr('value', amap_fields[2]);
@@ -143,31 +286,270 @@
listAmap('');
};
+var editAmap = function(obj) {
+ var vali = '';
+ var resp;
+
+ /* get the variables */
+ obj = obj.parents('tr');
+ var enabled = obj.find('.enabled > input').attr('checked');
+ var name = obj.find('.name > :text').val();
+ var digits = obj.find('.digits > :text').val();
+ var active = obj.find('.active option:selected').val();
+ var app_name = obj.find('.app_name :text').val();
+ var app_args = obj.find('.app_args :text').val();
+
+ if (!validateAmap(obj, name, digits, app_name)) {
+ return false;
+ }
+
+ /* generate the applicationmap string */
+ var value = [digits, active, app_name, app_args].join();
+
+ /* time to upload to Asterisk */
+ var actions = listOfSynActions('features.conf');
+ if (obj.attr('id').substring(5) !== name) {
+ actions.new_action('delete', 'applicationmap', obj.attr('id').substring(5), '');
+ }
+ actions.new_action('update', 'applicationmap', name, value);
+
+ resp = actions.callActions();
+ if (!resp.contains('Response: Success')) {
+ top.log.error('editAmap: error updating features.conf');
+ return false;
+ }
+
+ if (enabled) {
+ actions.clearActions('extensions.conf');
+ resp = '';
+
+ if (obj.attr('id') !== '') {
+ amap_enabled.splice(amap_enabled.indexOf(obj.attr('id').substring('5'), 1));
+ }
+ amap_enabled.push(name);
+ actions.new_action('update', 'globals', 'FEATURES', amap_enabled.join('#'));
+
+ resp = actions.callActions();
+ if (!resp.contains('Response: Success')) {
+ top.log.error('editAmap: error updating features.conf');
+ return false;
+ }
+ }
+
+ obj.attr('id', 'name');
+};
+
+var removeAmap = function(obj) {
+ /* if this doesn't have an id, its most likely a 'new, unsaved' amap */
+ if (!obj.parents('tr').attr('id')) {
+ obj.parents('tr').queue(function() {
+ $(this).fadeOut(500);
+ $(this).dequeue();
+ });
+ obj.parents('tr').queue(function() {
+ $(this).remove();
+ $(this).dequeue();
+ });
+ return true;
+ }
+ var name = obj.parents('tr').attr('id').substring('5'); /* amap_XXXNAMEXXX */
+ var actions = new listOfSynActions('extensions.conf');
+ var resp;
+
+ if (amap_enabled.contains(name)) {
+ amap_enabled.splice(amap_enabled.indexOf(name), 1);
+ actions.new_action('update', 'globals', 'FEATURES', amap_enabled.join('#'));
+
+ resp = actions.callActions();
+ if (!resp.contains('Response: Success')) {
+ top.log.error('removeAmap: Error updating extensions.conf');
+ return false;
+ }
+ }
+ actions.clearActions('features.conf');
+
+ actions.new_action('delete', 'applicationmap', name, '');
+
+ resp = actions.callActions();
+ if (!resp.contains('Response: Success')) {
+ top.log.error('removeAmap: Error updating features.conf');
+ return false;
+ }
+
+ obj.parents('tr').queue(function() {
+ $(this).fadeOut(500);
+ $(this).dequeue();
+ });
+ obj.parents('tr').queue(function() {
+ $(this).remove();
+ $(this).dequeue();
+ });
+};
+
+var validateAmap = function(obj, name, digits, app_name) {
+ /* lets validate all the variables before we send */
+ try {
+ vali = 'name';
+ validate(name, {notnull: true, str: true, aststr: true});
+ vali = 'digits';
+ validate(digits, {notnull: true, num: true});
+ vali = 'app_name';
+ validate(app_name, {notnull: true, str: true});
+ } catch(e) {
+ obj.find('td.'+vali+' input').focus().addClass('error');
+ top.log.error(e.message);
+ return false;
+ }
+
+ obj.find('input').removeClass('error');
+ return true;
+}
+
/**
* function to removing options
* @param obj the DOM object
*/
var remove = function(obj) {
- this.vals[obj.attr('id')] = obj.val();
- updateMsg(obj, 'remove');
-};
+ vals[obj.attr('id')] = obj.val();
+ if (obj.attr('type') === 'checkbox') {
+ if (typeof remove_funcs[obj.attr('id')] !== 'function') {
+ top.log.error('remove: remove_funcs["' + obj.attr('id') + '"] is not a function.');
+ updateMsg(obj, 'error', 'Error: Remove function was not found.');
+ return false;
+ }
+ } else {
+ if (typeof edit_funcs[obj.attr('id')] !== 'function') {
+ top.log.error('remove: edit_funcs["' + obj.attr('id') + '"] is not a function.');
+ updateMsg(obj, 'error', 'Error: Remove function was not found.');
+ return false;
+ }
+ }
+
+ try {
+ if (obj.attr('type') === 'checkbox') {
+ remove_funcs[obj.attr('id')](obj.val());
+ } else {
+ edit_funcs[obj.attr('id')]('');
+ }
+
+ updateMsg(obj, 'remove');
+ } catch(e) {
+ switch (e.name) {
+ default:
+ updateMsg(obj, 'error', e.message);
+ }
+ }
+};
+
+/**
+ * sends updates to Asterisk.
+ * @param cxt variable's context.
+ * @param name variable name.
+ * @param val variable value.
+ * @throws CommunicationError.
+ * @return boolean of success.
+ */
+var sendUpdate = function(params) {
+ if (!params.cxt || !params.name) {
+ top.log.error('sendUpdate: params.cxt or params.name is undefined.');
+ throw TypeError('Error: params.cxt or params.name is undefined.');
+ }
+
+ var actions = listOfSynActions('features.conf');
+ actions.new_action('update', params.cxt, params.name, params.val);
+ var resp = actions.callActions();
+ if (!resp.contains('Response: Success')) {
+ top.log.error('sendUpdate: error updating features.conf.');
+ throw CommunicationError('Error: Unable to update features.conf.');
+ }
+
+ return true;
+}
/**
* function to show update mesgs
* @param obj the DOM object
* @param msg the msg to display
*/
-var updateMsg = function(obj, type) {
+var updateMsg = function(obj, type, err) {
var type = type || '';
+ var err = err || '';
switch(type) {
case 'edit':
- var clr = '#aeffae';
+ obj.siblings('.update').hide();
+ obj.parents('.feature').effect('highlight', {color: '#aeffae'}, 1000);
break;
case 'error':
- var clr = 'orange';
+ obj.siblings('.update').html(err);
+ obj.siblings('.update').show();
break;
default:
- var clr = '#ffaeae';
- }
- obj.parents('.feature').effect('highlight', {color: clr}, 1000);
-};
+ obj.siblings('.update').hide();
+ obj.parents('.feature').effect('highlight', {color: '#ffaeae'}, 1000);
+ }
+};
+
+var validate = function(val, chks) {
+ /* does val exist? */
+ if (chks.notnull && (typeof val === 'undefined' || val === '' || val === null)) {
+ top.log.error('validate: val is not defined.');
+ throw TypeError('Invalid: This cannot be empty.');
+ }
+
+ /* make sure val is a num */
+ if (chks.num && isNaN(val)) {
+ top.log.error('validate: val needs to be a number.');
+ throw TypeError('Invalid: This needs to be a number.');
+ }
+
+ /* is val a string? */
+ if (chks.str && typeof val !== 'string') {
+ top.log.error('validate: val needs to be a string.');
+ throw TypeError('Invalid: This needs to be a string.');
+ }
+
+ /* make sure its 0 or more */
+ if (chks.positive && val < 0) {
+ top.log.warn('validate: val needs to be 0 or greater.');
+ throw RangeError('Invalid: This needs to be 0 or greater.');
+ }
+
+ /* lets make sure the exten doesn't conflict with any extension ranges */
+ if (chks.extens) {
+ gui_conf = context2json({
+ filename: 'guipreferences.conf',
+ context: 'general',
+ usf: 1
+ });
+ var prefs = {ue: 'User Extensions', mm: 'Conference Extensions', qe: 'Queue Extensions', vme: 'Voicemail Extensions', rge: 'Ring Group Extensions', vmg: 'Voicemail Group Extensions'};
+ for (pref in prefs) {
+ if (!prefs.hasOwnProperty(pref)) {
+ continue;
+ }
+
+ var start = gui_conf[pref + '_start'];
+ var end = gui_conf[pref + '_end'];
+
+ if (val >= start && val <= end) {
+ top.log.warn('validate: conflicts with ' + pref + '.');
+ throw RangeError('Invalid: Conflicts with ' + prefs[pref] + ' range, ' + start + '-' + end);
+ }
+ }
+ }
+
+ if (chks.keypress && val !== '' && !val.match(/[0-9#*][0-9#*]*/)) {
+ top.log.error('validate: val should only contain 0-9, #, or *.');
+ throw TypeError('Invalid: This should only contain 0-9, #, or *.');
+ }
+
+ if (chks.aststr && !val.match(/[a-zA-Z0-9_-][a-zA-Z0-9_-]*/)) {
+ top.log.error('validate: val should only contain a-z, A-Z, 0-9, _, or -.');
+ throw TypeError('Invalid: This should only contain a-z, A-Z, 0-9, _, or -');
+ }
+};
+
+/********* EXCEPTIONS **********/
+var CommunicationError = function(msg) {
+ this.name = "CommunicationError";
+ this.msg = msg || "An error occurred while communicating with Asterisk.";
+};
More information about the asterisk-gui-commits
mailing list