From: Ben Klang Date: Sat, 12 Nov 2005 08:27:08 +0000 (+0000) Subject: Finally!! X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=d91874244b21dd2aa84d55a12992e6c1d92ad123;p=horde.git Finally!! Extension management javascript is just about complete. Priorities can now be dyamically added and all other priorities will be renumbered to suit. The interface is entirely drawn in javascript and is accessible via a PHP class which calls a Javascript class. Inspired by Horde_Tree and functions similarly. Todo on the dialplan manager: * Support removing priorities * Support adding/removing extensions * Flesh out the application list (need PHP to populate js arrays) * Perfect the layout of the UI. Thinking need to move to divs instead of tables git-svn-id: https://svn.alkaloid.net/gpl/shout/trunk@91 06cd67b6-e706-0410-b29e-9de616bca6e9 --- diff --git a/andrew.webprj b/andrew.webprj index ed54c47fb..86e93e26a 100644 --- a/andrew.webprj +++ b/andrew.webprj @@ -9,15 +9,15 @@ - + - + - + @@ -33,7 +33,7 @@ - + @@ -60,10 +60,10 @@ - + - + @@ -71,7 +71,7 @@ - + @@ -84,13 +84,14 @@ - + + - - + + @@ -122,11 +123,11 @@ - - + - + + diff --git a/lib/Dialplan.php b/lib/Dialplan.php index 4bee05ea2..e1b58916f 100644 --- a/lib/Dialplan.php +++ b/lib/Dialplan.php @@ -10,186 +10,215 @@ * @package Shout */ // {{{ -class ExtensionDetailsForm extends Horde_Form { +/** + * The Shout_Dialplan:: class provides an interactive view of an Asterisk dialplan. + * It allows for expanding/collapsing of extensions and priorities and maintains their state. + * It can work together with the Horde_Tree javascript class to achieve this in + * DHTML on supported browsers. + * + * Copyright 2005 Ben Klang + * + * See the enclosed file COPYING for license information (LGPL). If you + * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html. + * + * $Horde: framework/Tree/Tree.php,v 1.46.6.7 2005/07/03 05:22:36 selsky Exp $ + * + * @author Ben Klang + * @package Shout_Dialplan + * @since Shout 0.1 + */ +class Shout_Dialplan +{ + /** + * The name of this instance. + * + * @var string + */ + var $_instance = null; - function ExtensionDetailsForm(&$vars) - { - global $shout; - $context = $vars->get("context"); - $extension = $vars->get("extension"); - - $dialplan = &$shout->getDialplan($context); - $extendata = $dialplan['extensions'][$extension]; - if (array_key_exists($extension, $dialplan['extensions'])) { - $formtitle = "Edit Extension"; - } else { - $formtitle = "Add Extension"; - } - - parent::Horde_Form($vars, _("$formtitle - Context: $context")); - - $this->addHidden('', 'context', 'text', true); - $this->addHidden('', 'oldextension', 'text', true); - $vars->set('oldextension', $extension); - $this->addHidden('', 'action', 'text', true); -// $vars->set('action', 'save'); - $this->addVariable(_("Extension"), 'extension', 'text', true); - $this->addVariable(_("Priority"), 'priority', 'priority', true); -// foreach ($extendata as $priority => $application) { -// $vars->set("priority$priority", $application); -// $this->addVariable("Priority $priority", "priority$priority", -// 'text', false); -// } - } - - // {{{ fillUserForm method /** - * Fill in the blanks for the UserDetailsForm + * The array of dialplan information to render the form * - * @param object Reference to a Variables object to fill in + * @var array + */ + var $_dialplan = array(); + + /** + * Object containing the instantiation of the Horde_Tree class * - * @param array User details + * @var object + */ + var $_tree = null; + + /** + * Create or return a unique instance of the Shout_Dialplan object * - * @return boolean True if successful, Pear::raiseError object on failure + * @param string $instance Unique identifier for this instance + * @param array $dialplan Dialplan array as returned by the driver + * @return object Instantiation of the Shout_Dialplan object */ - function fillExtensionFormPriority(&$vars, $extensiondetails) - { - #Array ( [dialopts] => Array ( [0] => m [1] => t ) [mailboxopts] => Array ( - #) [mailboxpin] => 1234 [name] => Ricardo Paul [phonenumbers] => Array ( ) - #[dialtimeout] => 30 [email] => ricardo.paul@v-office.biz [pageremail] => ) - $vars->set('name', $userdetails['name']); - $vars->set('email', @$userdetails['email']); - $vars->set('pin', $userdetails['mailboxpin']); - - $i = 1; - foreach($userdetails['phonenumbers'] as $number) { - $vars->set("telephone$i", $number); - $i++; - } - - if (in_array('m', $userdetails['dialopts'])) { - $vars->set('moh', true); - } else { - $vars->set('moh', false); - } - - if (in_array('t', $userdetails['dialopts'])) { - $vars->set('transfer', true); - } else { - $vars->set('transfer', false); + function &singleton($instance, $dialplan) + { + static $instances = array(); + + if (isset($instances[$instance])) { + return $instances[$instance]; } - - return true; + $instances[$instance] = new Shout_Dialplan($instance, $dialplan); + return $instances[$instance]; } - // }}} -} -// }}} - -class Horde_Form_Type_priority extends Horde_Form_Type { - -// var $_regex; -// var $_size; -// var $_maxlength; /** - * The initialisation function for the text variable type. - * - * @access private + * Instantiator for the Shout_Dialplan * - * @param string $regex Any valid PHP PCRE pattern syntax that - * needs to be matched for the field to be - * considered valid. If left empty validity - * will be checked only for required fields - * whether they are empty or not. - * If using this regex test it is advisable - * to enter a description for this field to - * warn the user what is expected, as the - * generated error message is quite generic - * and will not give any indication where - * the regex failed. - * @param integer $size The size of the input field. - * @param integer $maxlength The max number of characters. + * @param string $instance Unique identifier for this instance + * @param array $dialplan Dialplan array as returned by the driver + * @return Shout_Dialplan Instantiation of the Shout_Dialplan object */ - function init() - { - } -// function init($regex = '', $size = 40, $maxlength = null) -// { -// $this->_regex = $regex; -// $this->_size = $size; -// $this->_maxlength = $maxlength; -// } - - function isValid(&$var, &$vars, $value, &$message) + function Shout_Dialplan($instance, $dialplan) { - $valid = true; + require_once 'Horde/Tree.php'; + require_once 'Horde/Block.php'; + require_once 'Horde/Block/Collection.php'; -// if ($var->isRequired() && empty($this->_regex)) { -// $valid = strlen(trim($value)) > 0; -// -// if (!$valid) { -// $message = _("This field is required."); -// } -// } elseif (!empty($this->_regex)) { -// $valid = preg_match($this->_regex, $value); -// -// if (!$valid) { -// $message = _("You have to enter a valid value."); -// } -// } + $this->_instance = $instance; + $this->_dialplan = $dialplan; + $this->_tree = Horde_Tree::singleton('shout_dialplan_nav_'.$instance, 'javascript'); - return $valid; - } + foreach ($this->_dialplan as $linetype => $linedata) { + switch($linetype) { + case 'extensions': + $url = '#top'; + $this->_tree->addNode('extensions', null, 'Extensions', null, array('url' => $url)); + foreach ($linedata as $extension => $priorities) { + $nodetext = Shout::exten2name($extension); + $url = Horde::applicationUrl('index.php?section=dialplan' . + '&extension=' . $extension . '&context=' . $this->_dialplan['name']); + $url = "#$extension"; + $this->_tree->addNode("extension_".$extension, 'extensions', $nodetext, + null, false, + array( + 'url' => $url, + 'onclick' => + 'shout_dialplan_object_'.$this->_instance. + '.highlightExten(\''.$extension.'\')', + ) + ); + // foreach ($priorities as $priority => $application) { + // $this->_tree->addNode("$extension-$priority", $extension, "$priority: $application", null); + // } + } + break; - function getSize() - { - return $this->_size; - } + case 'includes': + $this->_tree->addNode('includes', null, 'Includes', null); + foreach ($linedata as $include) { + $url = Horde::applicationUrl('index.php?section=dialplan&context='.$include); + $this->_tree->addNode("include_$include", 'includes', $include, null, + true, array('url' => $url)); + } + break; - function getMaxLength() - { - return $this->_maxlength; + # TODO Ignoring ignorepat lines for now + + case 'barelines': + $this->_tree->addNode('barelines', null, 'Extra Settings', null); + $i = 0; + foreach ($linedata as $bareline) { + $this->_tree->addNode("bareline_".$i, 'barelines', $bareline, null); + $i++; + } + break; + } + } } /** - * Return info about field type. + * Render dialplan side navigation tree */ - function about() + function renderNavTree() + { + print '
'."\n"; + $this->_tree->renderTree(true); + print '
'."\n"; + print ' Back to Top'."\n"; + print '
'."\n"; + return true; + } + + function renderAppList() { - $about = array(); - $about['name'] = _("Extension Priority"); - $about['params'] = array( - 'priority' => array('label' => _("Priority"), - 'type' => 'int'), - 'application' => array('label' => _("Application"), - 'type' => 'stringlist'), - 'args' => array('label' => _("Arguments"), - 'type' => 'text'), - ); - return $about; + # $applist = Shout::getApplist(); + print ''."\n"; + return true; } -} + function renderExtensions() + { + if(!isset($this->_dialplan['extensions'])) { + print '
'."\n"; + print '
No Configured Extensions
'."\n"; + print '
'."\n"; + } else { + print ''."\n"; + print ''."\n"; -// require_once HORDE_BASE . '/lib/Horde/UI/VarRenderer.php'; -// require_once HORDE_BASE . '/lib/Horde/UI/VarRenderer/html.php'; -// class Horde_UI_VarRenderer_html_priority extends Horde_UI_VarRenderer_html -// { -// function _renderVarInput_priority(&$form, &$var, &$vars) -// { -// echo ''; -// echo '\n'; -// echo ''; -// } -// -// function _renderVarDisplay_priority(&$form, &$var, &$vars) -// { -// echo ''; -// echo '\n'; -// echo ''; -// } -// } \ No newline at end of file + print '
'."\n"; + $e = 0; + foreach($this->_dialplan['extensions'] as $extension => $priorities) { + print '
'."\n"; + print '
'."\n"; + print Shout::exten2name($extension); + print '
'."\n"; + print '
'."\n"; + print '
'."\n"; + $e++; + print '
'."\n"; + print '
'."\n"; + print ''."\n"; + } + print '
'."\n"; + } + } +} \ No newline at end of file diff --git a/lib/Driver/ldap.php b/lib/Driver/ldap.php index 0b73804f3..e42dd6854 100644 --- a/lib/Driver/ldap.php +++ b/lib/Driver/ldap.php @@ -341,6 +341,7 @@ for $context")); $res = ldap_get_entries($this->_LDAP, $res); $dialplans[$context] = array(); + $dialplans[$context]['name'] = $context; $i = 0; while ($i < $res['count']) { # Handle extension lines diff --git a/main/dialplan.php b/main/dialplan.php index 6f934a4d2..37986644e 100644 --- a/main/dialplan.php +++ b/main/dialplan.php @@ -12,61 +12,13 @@ if (!defined(SHOUT_BASE)) { define(SHOUT_BASE, dirname(__FILE__)); } -$dialplan = &$shout->getDialplan($context); +require_once SHOUT_BASE . '/lib/Dialplan.php'; -require_once 'Horde/Tree.php'; -require_once 'Horde/Block.php'; -require_once 'Horde/Block/Collection.php'; +$dialplan = &$shout->getDialplan($context); // Set up the tree. -$tree = &Horde_Tree::singleton('shout_dialplan_menu', 'javascript'); -foreach ($dialplan as $linetype => $linedata) { - switch($linetype) { - case 'extensions': - $url = '#top'; - $tree->addNode('extensions', null, 'Extensions', null, array('url' => $url)); - foreach ($linedata as $extension => $priorities) { - $nodetext = Shout::exten2name($extension); - $url = Horde::applicationUrl('index.php?section=dialplan' . - '&extension=' . $extension . '&context=' . $context); - $url = "#$extension"; - $tree->addNode("extension_".$extension, 'extensions', $nodetext, - null, false, - array( - 'url' => $url, - 'onclick' => 'dp.highlightExten(\''.$extension.'\')', - ) - ); -// foreach ($priorities as $priority => $application) { -// $tree->addNode("$extension-$priority", $extension, "$priority: $application", null); -// } - } - break; - - case 'includes': - $tree->addNode('includes', null, 'Includes', null); - foreach ($linedata as $include) { - $url = Horde::applicationUrl('index.php?section=dialplan&context='.$include); - $tree->addNode("include_$include", 'includes', $include, null, - true, array('url' => $url)); - } - break; - - # TODO Ignoring ignorepat lines for now - - case 'barelines': - $tree->addNode('barelines', null, 'Extra Settings', null); - $i = 0; - foreach ($linedata as $bareline) { - $tree->addNode("bareline_".$i, 'barelines', $bareline, null); - $i++; - } - break; - } -} - -require SHOUT_TEMPLATES . '/dialplan/contexttree.inc'; -require SHOUT_TEMPLATES . '/dialplan/extensiondetail.inc'; +$dpgui = Shout_Dialplan::singleton('x', $dialplan); +require SHOUT_TEMPLATES . '/dialplan/manager.inc'; // Horde::addScriptFile('httpclient.js', 'horde', true); // Horde::addScriptFile('hideable.js', 'horde', true); diff --git a/templates/dialplan/extensiondetail.inc b/templates/dialplan/extensiondetail.inc index 8bac71c05..a7ba902c4 100644 --- a/templates/dialplan/extensiondetail.inc +++ b/templates/dialplan/extensiondetail.inc @@ -1,52 +1,9 @@ - -
-
No Configured Extensions
-
- - - -
- $priorities) { ?> -
- -
" - id="" - onclick="dp.highlightExten('');"> - -
-
-
" - name=""> - + +
$data) { @@ -96,16 +53,4 @@ if(!isset($dialplan['extensions'])) { $p++; } ?> -
-
- -
-
- -
- + \ No newline at end of file diff --git a/templates/javascript/dialplan.js b/templates/javascript/dialplan.js index bfca7afed..96db88e73 100644 --- a/templates/javascript/dialplan.js +++ b/templates/javascript/dialplan.js @@ -18,7 +18,9 @@ function Dialplan(instanceName) { this._instanceName = instanceName; this.dp = new Array(); - this.dp = eval('shout_dialplan_'+instanceName); + this.dp = eval('shout_dialplan_entry_'+instanceName); + this.applist = eval('shout_dialplan_applist_'+instanceName); + this.object = 'shout_dialplan_object_'+instanceName; this.curExten = ''; this.curPrio = ''; } @@ -72,26 +74,26 @@ Dialplan.prototype.drawPrioTable = function (exten) alert('Must first choose an extension to draw'); return false; } - alert(document.getElementById('pList-'+exten).innerHTML); + //alert(document.getElementById('pList-'+exten).innerHTML); table = ''; table += ' \n'; table += ' \n'; for (var p in this.dp[exten]['priorities']) { table += ' \n'; table += ' \n'; table += ' \n'; @@ -104,10 +106,16 @@ Dialplan.prototype.drawPrioTable = function (exten) table += ' \n'; table += ' \n'; table += '
\n'; - table += ' +\n'; - table += ' -\n'; + table += ' +\n'; + table += ' -\n'; table += ' \n'; + table += ' onclick="javascript:'+this.object+'.activatePriority(\''+exten+'\', \''+p+'\')">\n'; table += ' '+p+'\n'; table += ' \n'; table += ' \n'; - table += ' \n';; + table += this.genAppList(this.dp[exten]['priorities'][p]['application']); table += ' \n'; table += ' \n'; table += '
\n'; - alert(table); + //alert(table); document.getElementById('pList-'+exten).innerHTML = table; } +Dialplan.prototype.genAppList = function (app) +{ + applist = '\n'; + return applist; +} + Dialplan.prototype.addExten = function (exten, extenName) { this.dp[exten] = new Array(); @@ -123,23 +131,50 @@ Dialplan.prototype.addPrio = function(exten, prio) this.drawPrioTable(exten); } +Dialplan.prototype._numCompare = function(a, b) +{ + return (a - b); +} + Dialplan.prototype._incrPrio = function (exten, prio) { - p = Number(prio) + 1; - h = Number(prio) + 101; + // Due to javascript's inability to remove an array element while maintaining + // associations, we copy the elements into a tmp array and ultimately replace + // the object's copy. We will also have to sort the resulting array manually + // so it renders correctly. + var tmp = new Array(); + var plist = new Array(); + var i = 0; + var p; - // Check for error handlers - if (this.dp[exten]['priorities'][h] != 'undefined') { - alert(this.dp[exten][h]); - //this._incrPrio(exten, h); + for (p in this.dp[exten]['priorities']) { + p = Number(p); + // Make a notch for the new priority by incrementing all priorities greater + // than the requested one + if (p > prio) { + tmp[p + 1] = this.dp[exten]['priorities'][p]; + plist[i] = p + 1; + } else { + tmp[p] = this.dp[exten]['priorities'][p]; + plist[i] = p; + } + i++; } + // Seed the new priority + prio = Number(prio) + 1; + tmp[prio] = new Array(); + tmp[prio]['application'] = ''; + tmp[prio]['args'] = ''; + plist[i] = prio; - // Make sure the next slot is empty. If not move it first. - if (this.dp[exten]['priorities'][p] != 'undefined') { - alert(p); - //this._incrPrio(exten, p); - } + // Empty the original array + this.dp[exten]['priorities'] = new Array(); - // Copy the existing prio to its new home - this.dp[exten]['priorities'][p] = this.dp[exten]['priorities'][prio]; + // Sort the priorities and put them back into the original array + plist.sort(this._numCompare); + for (i = 0; i < plist.length; i++) { + p = Number(plist[i]); + this.dp[exten]['priorities'][p] = tmp[p]; + } + return true; } \ No newline at end of file diff --git a/templates/menu.inc b/templates/menu.inc index 80e0324e5..12de29a53 100644 --- a/templates/menu.inc +++ b/templates/menu.inc @@ -7,15 +7,16 @@ $menu_view = $prefs->getValue('menu_view');