r3927 merge Alexey's tag filter patch
authorDenis Ovsienko <infrastation@yandex.ru>
Wed, 8 Sep 2010 13:34:04 +0000 (13:34 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Wed, 8 Sep 2010 13:34:04 +0000 (13:34 +0000)
ChangeLog
inc/functions.php
inc/init.php
inc/interface.php
inc/ophandlers.php
install/init-dictbase.sql
js/racktables.js
upgrade.php

index 709309d..f36833d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,7 @@
        bugfix: suppress inputs borders in MSIE (by Alexey Andrianov)
        update: allow scrollbars in port selector (#361)
        new feature: enable IMS caching of progress bars (by Alexey Andrianov)
+       new feature: rebuild tag filter as soon as user changes it (by Alexey Andrianov)
 0.18.4 2010-07-13
        bugfix: a race condition could be triggered in permissions editor
        new feature: "any mode" of user port in VLAN switch template
index fa5a802..6d098c3 100644 (file)
@@ -1223,6 +1223,57 @@ function getObjectiveTagTree ($tree, $realm, $preselect)
        return $ret;
 }
 
+// Preprocess tag tree to get only tags which can effectively reduce given filter result,
+// than passes shrinked tag tree to getObjectiveTagTree and return its result.
+// This makes sense only if andor mode is 'and', otherwhise function does not modify tree.
+// 'Given filter' is a pair of $entity_list(filter result) and $preselect(filter data).
+// 'Effectively' means reduce to non-empty result.
+function getShrinkedTagTree($entity_list, $realm, $preselect) {
+       global $tagtree;
+       if ($preselect['andor'] != 'and' || empty($entity_list))
+               return getObjectiveTagTree($tagtree, $realm, $preselect['tagidlist']);
+       
+       $used_tags = array(); //associative, keys - tag ids, values - taginfos
+       foreach ($entity_list as $entity)
+       {
+               foreach ($entity['etags'] as $etag)
+                       if (! array_key_exists($etag['id'], $used_tags))
+                               $used_tags[$etag['id']] = 1;
+                       else
+                               $used_tags[$etag['id']]++;
+       
+               foreach ($entity['itags'] as $itag)
+                       if (! array_key_exists($itag['id'], $used_tags))
+                               $used_tags[$itag['id']] = 0;
+       }
+       
+       $shrinked_tree = shrinkSubtree($tagtree, $used_tags, $preselect, $realm);
+       return getObjectiveTagTree($shrinked_tree, $realm, $preselect['tagidlist']);
+}
+
+// deletes item from tag subtree unless it exists in $used_tags and not preselected
+function shrinkSubtree($tree, $used_tags, $preselect, $realm) {
+       $self = __FUNCTION__;
+       
+       foreach($tree as $i => &$item) {
+               $item['kids'] = $self($item['kids'], $used_tags, $preselect, $realm);
+               $item['kidc'] = count($item['kids']);
+               if
+               (
+                       ! array_key_exists($item['id'], $used_tags) && 
+                       ! in_array($item['id'], $preselect['tagidlist']) &&
+                       ! $item['kidc']
+               )
+                       unset($tree[$i]);
+               else {
+                       $item['refcnt'][$realm] = $used_tags[$item['id']];
+                       if (! $item['refcnt'][$realm])
+                               unset($item['refcnt'][$realm]);
+               }
+       }
+       return $tree;
+}
+
 // Get taginfo record by tag name, return NULL, if record doesn't exist.
 function getTagByName ($target_name)
 {
index 10eb29c..59ae293 100644 (file)
@@ -165,8 +165,8 @@ $pageheaders = array
 (
        100 => "<link rel='STYLESHEET' type='text/css' href='pi.css' />",
        102 => "<link rel='ICON' type='image/x-icon' href='pix/racktables.ico' />",
-       200 => "<script language='javascript' type='text/javascript' src='js/racktables.js'></script>",
-       201 => "<script language='javascript' type='text/javascript' src='js/jquery-1.3.1.min.js'></script>",
+       200 => "<script language='javascript' type='text/javascript' src='js/jquery-1.3.1.min.js'></script>",
+       201 => "<script language='javascript' type='text/javascript' src='js/racktables.js'></script>",
        202 => "<script language='javascript' type='text/javascript' src='js/live_validation.js'></script>",
        203 => "<script language='javascript' type='text/javascript' src='js/codepress/codepress.js'></script>",
 );
index 84bf51c..0483f68 100644 (file)
@@ -369,9 +369,21 @@ foreach ($indexlayout as $row)
 
 function renderRackspace ()
 {
-       echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
+       $found_racks = array();
+       $rows = array();
        $cellfilter = getCellFilter();
-       renderCellFilterPortlet ($cellfilter, 'rack');
+       foreach (getRackRows() as $row_id => $row_name) {
+               $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
+               $found_racks = array_merge($found_racks, $rackList);
+               $rows[] = array(
+                       'row_id' => $row_id,
+                       'row_name' => $row_name,
+                       'racks' => $rackList
+               );
+       }
+       
+       echo "<table class=objview border=0 width='100%'><tr><td class=pcleft>";
+       renderCellFilterPortlet ($cellfilter, 'rack', $found_racks);
        echo '</td><td class=pcright>';
        echo '<table border=0 cellpadding=10 cellpadding=1>';
        // generate thumb gallery
@@ -380,9 +392,12 @@ function renderRackspace ()
        // Zero value effectively disables the limit.
        $maxPerRow = getConfigVar ('RACKS_PER_ROW');
        $order = 'odd';
-       foreach (getRackRows() as $row_id => $row_name)
+       foreach ($rows as $row)
        {
-               $rackList = filterCellList (listCells ('rack', $row_id), $cellfilter['expression']);
+               $row_id = $row['row_id'];
+               $row_name = $row['row_name'];
+               $rackList = $row['racks'];
+               
                if (!count ($rackList) and count ($cellfilter['expression']))
                        continue;
                $rackListIdx = 0;
@@ -472,7 +487,7 @@ function renderRow ($row_id)
        echo "</td></tr>\n";
        echo "</table><br>\n";
        finishPortlet();
-       renderCellFilterPortlet ($cellfilter, 'rack', 'row_id', $row_id);
+       renderCellFilterPortlet ($cellfilter, 'rack', $rackList, 'row_id', $row_id);
 
        echo "</td><td class=pcright>";
 
@@ -1912,7 +1927,7 @@ function renderDepot ()
 
        echo "</td><td class=pcright width='25%'>";
 
-       renderCellFilterPortlet ($cellfilter, 'object');
+       renderCellFilterPortlet ($cellfilter, 'object', $objects);
        echo "</td></tr></table>\n";
 }
 
@@ -2157,7 +2172,7 @@ function renderIPv4Space ()
        echo "</table>\n";
        finishPortlet();
        echo '</td><td class=pcright>';
-       renderCellFilterPortlet ($cellfilter, 'ipv4net');
+       renderCellFilterPortlet ($cellfilter, 'ipv4net', $netlist);
        echo "</td></tr></table>\n";
 }
 
@@ -3283,7 +3298,7 @@ function renderCellList ($realm = NULL, $title = 'items', $do_amplify = FALSE)
        echo '</table>';
        finishPortlet();
        echo '</td><td class=pcright>';
-       renderCellFilterPortlet ($cellfilter, $realm);
+       renderCellFilterPortlet ($cellfilter, $realm, $celllist);
        echo "</td></tr></table>\n";
 }
 
@@ -4973,7 +4988,7 @@ function renderTagCheckbox ($inputname, $preselect, $taginfo, $refcnt_realm = ''
                $class = 'tagbox';
        }
        echo "<tr><td colspan=2 class=${class} style='padding-left: " . ($level * 16) . "px;'>";
-       echo "<label><input type=checkbox name='${inputname}[]' value='${taginfo['id']}'${selected}> ";
+       echo "<label><input type=checkbox class='tag-cb' name='${inputname}[]' value='${taginfo['id']}'${selected}> ";
        echo $taginfo['tag'];
        if (strlen ($refcnt_realm) and isset ($taginfo['refcnt'][$refcnt_realm]))
                echo ' <i>(' . $taginfo['refcnt'][$refcnt_realm] . ')</i>';
@@ -5050,7 +5065,7 @@ function printTagTRs ($cell, $baseurl = '')
 }
 
 // This one is going to replace the tag filter.
-function renderCellFilterPortlet ($preselect, $realm, $bypass_name = '', $bypass_value = '')
+function renderCellFilterPortlet ($preselect, $realm, $cell_list = array(), $bypass_name = '', $bypass_value = '')
 {
        global $pageno, $tabno, $taglist, $tagtree;
        $filterc =
@@ -5091,9 +5106,9 @@ function renderCellFilterPortlet ($preselect, $realm, $bypass_name = '', $bypass
                        $enable_reset = TRUE;
                echo $hr;
                $hr = $ruler;
+
                // Show a tree of tags, pre-select according to currently requested list filter.
-               global $tagtree;
-               $objectivetags = getObjectiveTagTree ($tagtree, $realm, $preselect['tagidlist']);
+               $objectivetags = getShrinkedTagTree($cell_list, $realm, $preselect);
                if (!count ($objectivetags))
                        echo "<tr><td colspan=2 class='tagbox sparenetwork'>(nothing is tagged yet)</td></tr>";
                else
@@ -5102,6 +5117,9 @@ function renderCellFilterPortlet ($preselect, $realm, $bypass_name = '', $bypass
                        foreach ($objectivetags as $taginfo)
                                renderTagCheckbox ('cft', buildTagChainFromIds ($preselect['tagidlist']), $taginfo, $realm);
                }
+               
+               if (getConfigVar('SHRINK_TAG_TREE_ON_CLICK') == 'yes')
+                       echo "\n" . '<script type="text/javascript">init_cb_click();</script>' . "\n";
        }
        // predicates block
        if (getConfigVar ('FILTER_SUGGEST_PREDICATES') == 'yes' or count ($preselect['pnamelist']))
index 47333d8..fe143b3 100644 (file)
@@ -1067,6 +1067,7 @@ function resetUIConfig()
        setConfigVar ('CDP_RUNNERS_LISTSRC', '');
        setConfigVar ('LLDP_RUNNERS_LISTSRC', '');
        setConfigVar ('HNDP_RUNNERS_LISTSRC', '');
+       setConfigVar ('SHRINK_TAG_TREE_ON_CLICK', 'yes');
        return buildRedirectURL (__FUNCTION__, 'OK');
 }
 
index 8e626a2..d1901d9 100644 (file)
@@ -407,6 +407,7 @@ INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, is_userdef
 ('CDP_RUNNERS_LISTSRC', '', 'string', 'yes', 'no', 'no', 'List of devices running CDP'),
 ('LLDP_RUNNERS_LISTSRC', '', 'string', 'yes', 'no', 'no', 'List of devices running LLDP'),
 ('HNDP_RUNNERS_LISTSRC', '', 'string', 'yes', 'no', 'no', 'List of devices running HNDP (RackCode)'),
+('SHRINK_TAG_TREE_ON_CLICK','yes','string','no','no','yes','Dynamically hide useless tags in tagtree'),
 ('DB_VERSION','0.18.4','string','no','yes','no','Database version.');
 
 INSERT INTO `Script` VALUES ('RackCode','allow {$userid_1}');
index d93933e..3d446af 100644 (file)
@@ -62,3 +62,22 @@ function checkColumnOfRadios (prefix, numRows, suffix)
                document.getElementById(elemId).checked = true;
        }
 }
+
+// called from interface.php:renderCellFilterPortlet() if SHRINK_TAG_TREE_ON_CLICK is set
+function init_cb_click() {
+       $(document).ready(function () {
+               $('.tag-cb , input[name=andor]').click(function (event) {
+                       var or_check = $('input[name=andor][value=or]')[0];
+                       if
+                       (
+                               event.target.type == 'checkbox' &&
+                               or_check.checked
+                               || event.target.type == 'radio' &&
+                               $('.tag-cb:checked').size() == 0
+                       )
+                               return;
+                       
+                       $(event.target).closest('form')[0].submit();
+               });
+       });
+}
index 770c6f5..2f99b17 100644 (file)
@@ -746,6 +746,10 @@ CREATE TABLE `VLANValidID` (
                        $query[] = "ALTER TABLE VLANSTRule MODIFY port_role enum('access','trunk','anymode','uplink','downlink','none') NOT NULL default 'none'";
                        $query[] = "UPDATE Config SET varvalue = '0.18.4' WHERE varname = 'DB_VERSION'";
                        break;
+               case '0.18.5':
+                       $query[] = "INSERT INTO `Config` (varname, varvalue, vartype, emptyok, is_hidden, is_userdefined, description) VALUES ('SHRINK_TAG_TREE_ON_CLICK','yes','string','no','no','yes','Dynamically hide useless tags in tagtree')";
+                       $query[] = "UPDATE Config SET varvalue = '0.18.5' WHERE varname = 'DB_VERSION'";
+                       break;
                default:
                        showFailure ("executeUpgradeBatch () failed, because batch '${batchid}' isn't defined", __FILE__);
                        die;