r1836 + first working concept of tag navigation for objects
authorDenis Ovsienko <infrastation@yandex.ru>
Wed, 26 Mar 2008 13:12:49 +0000 (13:12 +0000)
committerDenis Ovsienko <infrastation@yandex.ru>
Wed, 26 Mar 2008 13:12:49 +0000 (13:12 +0000)
inc/database.php
inc/functions.php
inc/interface.php
inc/navigation.php
inc/pagetitles.php

index c515207..a3e854e 100644 (file)
@@ -47,8 +47,21 @@ function getObjectTypeList ()
        return readChapter ('RackObjectType');
 }
 
-function getObjectList ($type_id = 0)
+function getObjectList ($type_id = 0, $tagfilter = array())
 {
+       if (!count ($tagfilter))
+               $whereclause = '';
+       else
+       {
+               $whereclause = ' and (';
+               $orclause = '';
+               foreach ($tagfilter as $tag_id)
+               {
+                       $whereclause .= $orclause . 'tag_id = ' . $tag_id;
+                       $orclause = ' or ';
+               }
+               $whereclause .= ') ';
+       }
        $query =
                "select distinct RackObject.id as id , RackObject.name as name, dict_value as objtype_name, " .
                "RackObject.label as label, RackObject.barcode as barcode, " .
@@ -56,8 +69,10 @@ function getObjectList ($type_id = 0)
                "((RackObject inner join Dictionary on objtype_id=dict_key natural join Chapter) " .
                "left join RackSpace on RackObject.id = object_id) " .
                "left join Rack on rack_id = Rack.id " .
-               "where objtype_id = '${type_id}' and RackObject.deleted = 'no' " .
-               "and chapter_name = 'RackObjectType' order by name";
+               "left join TagStorage on RackObject.id = TagStorage.target_id and target_realm = 'object' " .
+               "where objtype_id = '${type_id}' and RackObject.deleted = 'no' and chapter_name = 'RackObjectType' " .
+               $whereclause .
+               "order by name";
        $result = useSelectBlade ($query);
        $ret = array();
        while ($row = $result->fetch (PDO::FETCH_ASSOC))
@@ -615,25 +630,22 @@ function getResidentRacksData ($object_id = 0, $fetch_rackdata = TRUE)
        return $ret;
 }
 
-function getObjectGroupInfo ($group_id = 0)
+function getObjectGroupInfo ()
 {
        $query =
                'select dict_key as id, dict_value as name, count(id) as count from ' .
                'Dictionary natural join Chapter left join RackObject on dict_key = objtype_id ' .
                'where chapter_name = "RackObjectType" ' .
-               (($group_id > 0) ? "and dict_key = ${group_id} " : '') .
-               'group by dict_key';
+               'group by dict_key order by dict_value';
        $result = useSelectBlade ($query);
        $ret = array();
        $clist = array ('id', 'name', 'count');
        while ($row = $result->fetch (PDO::FETCH_ASSOC))
-               foreach ($clist as $dummy => $cname)
-                       $ret[$row['id']][$cname] = $row[$cname];
+               if ($row['count'] > 0)
+                       foreach ($clist as $dummy => $cname)
+                               $ret[$row['id']][$cname] = $row[$cname];
        $result->closeCursor();
-       if ($group_id > 0)
-               return current ($ret);
-       else
-               return $ret;
+       return $ret;
 }
 
 // This function returns objects, which have no rackspace assigned to them.
@@ -2475,7 +2487,7 @@ function getTagList ()
        $result = useSelectBlade ($query);
        while ($row = $result->fetch (PDO::FETCH_ASSOC))
        {
-               if (!isset ($taglist[$row['id']]))
+               if (!isset ($ret[$row['id']]))
                        $ret[$row['id']] = array
                        (
                                'id' => $row['id'],
index 5dfae70..1064a68 100644 (file)
@@ -1590,4 +1590,46 @@ function buildTrailFromIds ($tagidlist)
        return $ret;
 }
 
+// Process a given tag tree and return only meaningful branches. The resulting
+// (sub)tree will have refcnt leaves on every last branch.
+function getObjectiveTagTree ($tree, $realm)
+{
+       $ret = array();
+       foreach ($tree as $taginfo)
+       {
+               $subsearch = array();
+               $pick = FALSE;
+               if (count ($taginfo['kids']))
+               {
+                       $subsearch = getObjectiveTagTree ($taginfo['kids'], $realm);
+                       $pick = count ($subsearch) > 0;
+               }
+               elseif (isset ($taginfo['refcnt'][$realm]))
+                       $pick = TRUE;
+               if (!$pick)
+                       continue;
+               $ret[] = array
+               (
+                       'id' => $taginfo['id'],
+                       'tag' => $taginfo['tag'],
+                       'parent_id' => $taginfo['parent_id'],
+                       'refcnt' => $taginfo['refcnt'],
+                       'kids' => $subsearch
+               );
+       }
+       return $ret;
+}
+
+function getStringFromTrail ($trail)
+{
+       $str = '';
+       $comma = '';
+       foreach ($trail as $tag)
+       {
+               $str .= $comma . $tag['id'];
+               $comma = ',';
+       }
+       return $str;
+}
+
 ?>
index ee47f25..66ea020 100644 (file)
@@ -1512,11 +1512,119 @@ function renderObjectGroupSummary ()
        echo '</td><td class=pcright>';
        renderProblematicObjectsPortlet();
        echo '</td><td class=pcright>';
-       renderTagFilterPortlet ($tagfilter, 'object');
+       startPortlet ('Tag filter');
+       renderTagFilterSelect ($tagfilter, 'object');
+       finishPortlet();
+       echo "</td></tr></table>\n";
+}
+
+function renderObjectSpace ()
+{
+       global $taglist, $tagtree;
+       echo "<table border=0 class=objectview>\n";
+       echo "<tr><td class=pcleft width='50%'>";
+       startPortlet ('View all by type');
+       $groupInfo = getObjectGroupInfo();
+       if ($groupInfo === NULL)
+       {
+               showError ('getObjectGroupInfo() failed', __FUNCTION__);
+               return;
+       }
+       if (count ($groupInfo) == 0)
+               echo "No objects exist in DB";
+       else
+       {
+               echo '<div align=left><ul>';
+               foreach ($groupInfo as $gi)
+                       echo "<li><a href='${root}?page=objgroup&group_id=${gi['id']}'>${gi['name']}</a> (${gi['count']})</li>";
+               echo '</ul></div>';
+       }
+       finishPortlet();
+
+       echo '</td><td class=pcright>';
+
+       startPortlet ('View all by tag');
+       if (count ($taglist) == 0)
+               echo "No tags exist in DB";
+       else
+               renderTagCloud ('object');
+       finishPortlet();
        echo "</td></tr></table>\n";
 }
 
 function renderObjectGroup ()
+{
+       global $root, $pageno, $tabno, $nextorder, $taglist, $tagtree;
+       assertUIntArg ('group_id', TRUE);
+       $group_id = $_REQUEST['group_id'];
+       $tagfilter = isset ($_REQUEST['tagfilter']) ? $_REQUEST['tagfilter'] : array();
+       $tagfilter_str = getStringFromTrail (getExplicitTagsOnly (buildTrailFromIds ($tagfilter)));
+       $tagfilter = complementByKids ($tagfilter);
+       echo "<form>\n";
+       echo "<input type=hidden name=page value=${pageno}>\n";
+       echo "<input type=hidden name=group_id value=${group_id}>\n";
+       echo "<table border=0 class=objectview>\n";
+       echo "<tr><td class=pcleft width='25%'>";
+       startPortlet ('change type');
+       $groupInfo = getObjectGroupInfo();
+       if ($groupInfo === NULL)
+       {
+               showError ('getObjectGroupInfo() failed', __FUNCTION__);
+               return;
+       }
+       if (count ($groupInfo) == 0)
+               echo "No objects exist in DB";
+       else
+       {
+               echo '<div align=left><ul>';
+               foreach ($groupInfo as $gi)
+               {
+                       echo "<li><a href='${root}?page=${pageno}&group_id=${gi['id']}&tagfilter[]=${tagfilter_str}'>";
+                       echo "${gi['name']}</a> (${gi['count']})</li>";
+               }
+               echo '</ul></div>';
+       }
+       finishPortlet();
+
+       echo '</td><td class=pcleft>';
+
+       startPortlet ('Objects');
+       $objects = getObjectList ($group_id, $tagfilter);
+       if ($objects === NULL)
+       {
+               showError ('getObjectList() failed', __FUNCTION__);
+               return;
+       }
+       echo '<br><br><table border=0 cellpadding=5 cellspacing=0 align=center class=cooltable>';
+       echo '<tr><th>Common name</th><th>Visible label</th><th>Asset tag</th><th>Barcode</th><th>Rack</th></tr>';
+       $order = 'odd';
+       foreach ($objects as $obj)
+       {
+               echo "<tr class=row_${order}><td><a href='${root}?page=object&object_id=${obj['id']}'>${obj['dname']}</a></td>";
+               echo "<td>${obj['label']}</td>";
+               echo "<td>${obj['asset_no']}</td>";
+               echo "<td>${obj['barcode']}</td>";
+               if ($obj['rack_id'])
+                       echo "<td><a href='${root}?page=rack&rack_id=${obj['rack_id']}'>${obj['Rack_name']}</a></td>";
+               else
+                       echo '<td>Unmounted</td>';
+               echo '</tr>';
+               $order = $nextorder[$order];
+       }
+       echo '</table>';
+       finishPortlet();
+
+       echo "</td><td class=pcright width='25%'>";
+
+       startPortlet ('change filter');
+       renderTagFilterSelect ($tagfilter, 'object');
+       echo "<input type=submit value='Apply'>\n";
+       finishPortlet();
+       echo "</td></tr></table>\n";
+       echo '</form>';
+}
+
+function renderObjectGroup_old ()
 {
        global $root;
        assertUIntArg ('group_id');
@@ -4703,14 +4811,31 @@ function renderAutoPortsForm ($object_id = 0)
        echo "</table>";
 }
 
-function renderTagRowForViewer ($taginfo, $level = 0)
+function renderTagRowForViewer ($taginfo, $realm, $level = 0)
 {
-       echo '<tr><td>';
+       echo '<tr><td align=left>';
        for ($i = 0; $i < $level; $i++)
                printImageHREF ('spacer');
-       echo $taginfo['tag'] . "</td></tr>\n";
+       echo $taginfo['tag'];
+       if ($realm != '' && isset ($taginfo['refcnt'][$realm]))
+               echo ' (' . $taginfo['refcnt'][$realm] . ')';
+       echo "</td></tr>\n";
        foreach ($taginfo['kids'] as $kid)
-               renderTagRowForViewer ($kid, $level + 1);
+               renderTagRowForViewer ($kid, $realm, $level + 1);
+}
+
+function renderTagRowForCloud ($taginfo, $realm, $level = 0)
+{
+       echo '<tr><td align=left>';
+       for ($i = 0; $i < $level; $i++)
+               printImageHREF ('spacer');
+       echo "<a href='${root}?page=objgroup&group_id=0&taglist[]=${taginfo['id']}'>";
+       echo $taginfo['tag'] . '</a>';
+       if (isset ($taginfo['refcnt'][$realm]))
+               echo ' (' . $taginfo['refcnt'][$realm] . ')';
+       echo "</td></tr>\n";
+       foreach ($taginfo['kids'] as $kid)
+               renderTagRowForCloud ($kid, $realm, $level + 1);
 }
 
 function renderTagRowForEditor ($taginfo, $level = 0)
@@ -4735,7 +4860,20 @@ function renderTagTree ()
        foreach ($tagtree as $taginfo)
        {
                echo '<tr>';
-               renderTagRowForViewer ($taginfo);
+               renderTagRowForViewer ($taginfo, $realm);
+               echo "</tr>\n";
+       }
+       echo '</table>';
+}
+
+function renderTagCloud ($realm = '')
+{
+       global $taglist, $tagtree;
+       echo '<table>';
+       foreach (getObjectiveTagTree ($tagtree, $realm) as $taginfo)
+       {
+               echo '<tr>';
+               renderTagRowForCloud ($taginfo, $realm);
                echo "</tr>\n";
        }
        echo '</table>';
@@ -4787,6 +4925,7 @@ function renderTagOption ($taginfo, $level = 0)
 }
 
 // Idem, but select those, which are shown on the $_REQUEST['tagfiler'] array.
+// Ignore tag ids, which can't be found on the tree.
 function renderTagOptionForFilter ($taginfo, $tagfilter, $realm, $level = 0)
 {
        echo $level;
@@ -4883,17 +5022,31 @@ function renderTagFilterPortlet ($tagfilter, $realm)
                echo "No tags defined";
                return;
        }
-       echo "<form method=get'>\n";
+       echo "<form method=get>\n";
        echo "<input type=hidden name=page value=${pageno}>\n";
        echo "<input type=hidden name=tab value=${tabno}>\n";
        echo '<select name=tagfilter[] multiple>';
-       foreach ($tagtree as $taginfo)
+       foreach (getObjectiveTagTree ($tagtree, $realm) as $taginfo)
                renderTagOptionForFilter ($taginfo, $tagfilter, $realm);
        echo '</select><br>';
        echo "<input type=submit value='Apply'></form>\n";
        finishPortlet();
 }
 
+function renderTagFilterSelect ($tagfilter, $realm)
+{
+       global $taglist, $tagtree;
+       if (!count ($taglist))
+       {
+               echo "No tags defined";
+               return;
+       }
+       echo '<select name=tagfilter[] multiple>';
+       foreach (getObjectiveTagTree ($tagtree, $realm) as $taginfo)
+               renderTagOptionForFilter ($taginfo, $tagfilter, $realm);
+       echo '</select><br>';
+}
+
 function renderTagSelect ()
 {
        global $taglist, $tagtree;
index 44d8786..c71a967 100644 (file)
@@ -30,7 +30,7 @@ $page['objects']['parent'] = 'index';
 $tab['objects']['default'] = 'View';
 $tab['objects']['newobj'] = 'Add an object';
 $tab['objects']['newmulti'] = 'Add multiple objects';
-$tabhandler['objects']['default'] = 'renderObjectGroupSummary';
+$tabhandler['objects']['default'] = 'renderObjectSpace';
 $tabhandler['objects']['newobj'] = 'renderNewObjectForm';
 $tabhandler['objects']['newmulti'] = 'renderAddMultipleObjectsForm';
 
index 0faabf1..efedbe7 100644 (file)
@@ -149,14 +149,15 @@ function dynamic_title_objgroup ()
        {
                case 'objgroup':
                        assertUIntArg ('group_id');
-                       $groupInfo = getObjectGroupInfo ($_REQUEST['group_id']);
+                       $group_id = $_REQUEST['group_id'];
+                       $groupInfo = getObjectGroupInfo();
                        if ($groupInfo == NULL)
                        {
                                showError ('getObjectGroupInfo() failed', __FUNCTION__);
                                return NULL;
                        }
-                       $ret['name'] = $groupInfo['name'];
-                       $ret['params']['group_id'] = $groupInfo['id'];
+                       $ret['name'] = $groupInfo[$group_id]['name'];
+                       $ret['params']['group_id'] = $group_id;
                        break;
                case 'object':
                        assertUIntArg ('object_id');