Author: jfthomps
Date: Wed Oct 20 16:17:19 2010
New Revision: 1025626

URL: http://svn.apache.org/viewvc?rev=1025626&view=rev
Log:
VCL-310 - remove jpgraph dependency
replaced all jpgraph code with dojox's charting api


VCL-399 - add a dashboard where admins can see current state of VCL system
added a new section to the site that is a page displaying various information 
about the site that gets updated with AJAX every n seconds; currently there are 
the following sections of information:
Current Status - some general info
Top 5 Images in Use
Top 5 Long Term Images in Use
Top Recent Computer Failures
Top Recent Image Failures
Block Allocation Status
Past 12 Hours of Active Reservations

statistics.php
-removed require_once code for jpgraph
-modified viewStatistics - when computing length of reservation, if $length 
ends up being < 0, set it to 0
-changed img references to jpgraphs to divs for dojox charts
-added AJgetStatData
-removed sendStatGraphDay
-modified getStatGraphDayData - removed labels from $data, added xlabels to 
$data, added maxy to $data
-removed statXaxisDayCallback
-removed sendStatGraphHour
-modified getStatGraphHourData - changed $data['points'] to be an array of 
data, added maxy to $data
-renamed statXaxisHourCallback to statHourFromatX
-removed sendStatGraphDayConUsers
-modified getStatGraphDayConUsersData - removed labels from $data, added 
xlabels to $data, added maxy to $data
-removed statXaxisDayConUsersCallback
-removed sendStatGraphConBladeUser
-modified getStatGraphConBladeUserData - removed labels from $data, added 
xlabels to $data, added maxy to $data
-removed statXaxisConBladeUserCallback

utils.php
-modified initGlobals - added dashboard to section that does require_once based 
on the mode
-modified getNavMenu - removed some old stuff left in there related to ecu 
$skin; added menu item for dashboard
-modified getDojoHTML - added sections for viewstats and dashboard modes

states.php
-added dashboard to entry actions
-added AJupdateDashboard and AJgetStatData to $noHTMLwrappers
-removed statgraphday, statgraphhour, statgraphdayconcuruser, and 
statgraphdayconcurblade
-added AJgetStatData
-added dashboard section with modes dashboard and AJupdateDashboard

js/code.js - modified errorHandler function reference - list of args were 
wrong; changed from 'type, error, data' to 'error, ioArgs'; changed 
args.dojoType to error.name (not sure if this is correct), changed alert to 
display better message

dashboard.php - initial add to source control
css/dashboard.css - initial add to source control
js/dashboard.js - initial add to source control
js/statistics.js - initial add to source control

Added:
    incubator/vcl/trunk/web/.ht-inc/dashboard.php
    incubator/vcl/trunk/web/css/dashboard.css
    incubator/vcl/trunk/web/js/dashboard.js
    incubator/vcl/trunk/web/js/statistics.js
Modified:
    incubator/vcl/trunk/web/.ht-inc/states.php
    incubator/vcl/trunk/web/.ht-inc/statistics.php
    incubator/vcl/trunk/web/.ht-inc/utils.php
    incubator/vcl/trunk/web/js/code.js

Added: incubator/vcl/trunk/web/.ht-inc/dashboard.php
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/dashboard.php?rev=1025626&view=auto
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/dashboard.php (added)
+++ incubator/vcl/trunk/web/.ht-inc/dashboard.php Wed Oct 20 16:17:19 2010
@@ -0,0 +1,422 @@
+<?php
+/*
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+
+/**
+ * \file
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn dashboard()
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function dashboard() {
+       print "<h2>VCL Dashboard</h2>\n";
+       print "<table summary=\"\">\n";
+       print "<tr>\n";
+
+       # -------- left column ---------
+       print "<td valign=\"top\">\n";
+       print addWidget('status', 'Current Status');
+       print addWidget('topimages', 'Top 5 Images in Use', '(Reservations &lt; 
24 hours long)');
+       print addWidget('toplongimages', 'Top 5 Long Term Images in Use', 
'(Reservations &gt; 24 hours long)');
+       print addWidget('topfailedcomputers', 'Top Recent Computer Failures', 
'(Failed in the last 5 days)');
+       print "</td>\n";
+       # -------- end left column ---------
+
+       # ---------- right column ---------
+       print "<td valign=\"top\">\n";
+       print addWidget('topfailed', 'Top Recent Image Failures', '(Failed in 
the last 5 days)');
+       print addWidget('blockallocation', 'Block Allocation Status');
+       print addLineChart('reschart', 'Past 12 Hours of Active Reservations');
+       print "</td>\n";
+       # -------- end right column --------
+
+       print "</tr>\n";
+       print "</table>\n";
+       $cont = addContinuationsEntry('AJupdateDashboard', array('val' => 0), 
60, 1, 0);
+       print "<input type=\"hidden\" id=\"updatecont\" value=\"$cont\">\n";
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn 
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJupdateDashboard() {
+       $data = array();
+       $data['cont'] = addContinuationsEntry('AJupdateDashboard', array(), 60, 
1, 0);
+       $data['status'] = getStatusData();
+       $data['topimages'] = getTopImageData();
+       $data['toplongimages'] = getTopLongImageData();
+       $data['topfailed'] = getTopFailedData();
+       $data['topfailedcomputers'] = getTopFailedComputersData();
+       $data['reschart'] = getActiveResChartData();
+       $data['blockallocation'] = getBlockAllocationData();
+       sendJSON($data);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn addWidget($id, $title)
+///
+/// \param 
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function addWidget($id, $title, $extra='') {
+       $txt  = "<div class=\"dashwidget\">\n";
+       $txt .= "<h3>$title</h3>\n";
+       if($extra != '')
+               $txt .= "<div class=\"extra\">$extra</div>\n";
+       $txt .= "<div id=\"$id\"></div>\n";
+       $txt .= "</div>\n";
+       return $txt;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn addLineChart($id)
+///
+/// \param 
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function addLineChart($id, $title) {
+       $txt  = "<div class=\"dashwidget\">\n";
+       $txt .= "<h3>$title</h3>\n";
+       $txt .= "<div dojoType=\"dojox.charting.widget.Chart2D\" id=\"$id\"\n";
+       $txt .= "     theme=\"dojox.charting.themes.ThreeD\"\n";
+       $txt .= "     style=\"width: 300px; height: 300px;\">\n";
+       $txt .= "<div class=\"axis\"\n";
+       $txt .= "     name=\"x\"\n";
+       $txt .= "     labelFunc=\"timestampToTime\"\n";
+       $txt .= "     maxLabelSize=\"35\"\n";
+       $txt .= "     rotation=\"-90\"\n";
+       $txt .= "     majorTickStep=\"4\"\n";
+       $txt .= "     minorTickStep=\"1\">\n";
+       $txt .= "     </div>\n";
+       $txt .= "<div class=\"axis\" name=\"y\" vertical=\"true\" 
includeZero=\"true\"></div>\n";
+       $txt .= "<div class=\"plot\" name=\"default\" type=\"Lines\" 
markers=\"true\"></div>\n";
+       $txt .= "<div class=\"plot\" name=\"grid\" type=\"Grid\" 
vMajorLines=\"false\"></div>\n";
+       $txt .= "<div class=\"series\" name=\"Main\" data=\"0\"></div>\n";
+       $txt .= "<div class=\"action\" type=\"Tooltip\"></div>\n";
+       $txt .= "<div class=\"action\" type=\"Magnify\"></div>\n";
+       $txt .= "</div>\n";
+       $txt .= "</div>\n";
+       return $txt;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getStatusData()
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function getStatusData() {
+       $data = array();
+       $data[] = array('key' => 'Active Reservations', 'val' => 0);
+       $data[] = array('key' => 'Online Computers', 'val' => 0, 'tooltip' => 
'Computers in states available, reserved,<br>reloading, inuse, or timeout');
+       $data[] = array('key' => 'Failed Computers', 'val' => 0);
+       $reloadid = getUserlistID('vclrel...@local');
+       $query = "SELECT COUNT(id) "
+              . "FROM request "
+              . "WHERE userid != $reloadid AND "
+              .       "stateid NOT IN (1, 5, 12) AND "
+              .       "start < NOW() AND "
+                        .       "end > NOW()";
+       $qh = doQuery($query, 101);
+       if($row = mysql_fetch_row($qh))
+               $data[0]['val'] = $row[0];
+
+       $query = "SELECT COUNT(id) FROM computer WHERE stateid IN (2, 3, 6, 8, 
11)";
+       $qh = doQuery($query, 101);
+       if($row = mysql_fetch_row($qh))
+               $data[1]['val'] = $row[0];
+
+       $query = "SELECT COUNT(id) FROM computer WHERE stateid = 5";
+       $qh = doQuery($query, 101);
+       if($row = mysql_fetch_row($qh))
+               $data[2]['val'] = $row[0];
+       return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn 
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function getTopImageData() {
+       $query = "SELECT COUNT(c.currentimageid) AS count, "
+              .        "i.prettyname "
+              . "FROM computer c, "
+              .      "image i "
+              . "WHERE c.currentimageid = i.id AND "
+                        .       "c.stateid = 8 "
+              . "GROUP BY c.currentimageid "
+              . "ORDER BY count DESC "
+              . "LIMIT 5";
+       $query = "SELECT COUNT(rs.imageid) AS count, "
+              .        "i.prettyname "
+              . "FROM reservation rs, "
+              .      "request rq, "
+              .      "image i "
+              . "WHERE rs.imageid = i.id AND "
+                        .       "rq.stateid = 8 AND "
+                        .       "rs.requestid = rq.id AND "
+                        .       "TIMESTAMPDIFF(HOUR, rq.start, rq.end) <= 24 "
+              . "GROUP BY rs.imageid "
+              . "ORDER BY count DESC "
+              . "LIMIT 5";
+       $data = array();
+       $qh = doQuery($query, 101);
+       while($row = mysql_fetch_assoc($qh))
+               $data[] = $row;
+       return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn 
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function getTopLongImageData() {
+       $query = "SELECT COUNT(rs.imageid) AS count, "
+              .        "i.prettyname, "
+              .        "TIMESTAMPDIFF(HOUR, rq.start, rq.end) AS reslen "
+              . "FROM reservation rs, "
+              .      "request rq, "
+              .      "image i "
+              . "WHERE rs.imageid = i.id AND "
+                        .       "rq.stateid = 8 AND "
+                        .       "rs.requestid = rq.id "
+              . "GROUP BY rs.imageid "
+              . "HAVING reslen > 24 "
+              . "ORDER BY count DESC "
+              . "LIMIT 5";
+       $query = "SELECT COUNT(rs.imageid) AS count, "
+              .        "i.prettyname "
+              . "FROM reservation rs, "
+              .      "request rq, "
+              .      "image i "
+              . "WHERE rs.imageid = i.id AND "
+                        .       "rq.stateid = 8 AND "
+                        .       "rs.requestid = rq.id AND "
+                        .       "TIMESTAMPDIFF(HOUR, rq.start, rq.end) > 24 "
+              . "GROUP BY rs.imageid "
+              . "ORDER BY count DESC "
+              . "LIMIT 5";
+       $data = array();
+       $qh = doQuery($query, 101);
+       while($row = mysql_fetch_assoc($qh))
+               $data[] = $row;
+       return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getTopFailedData()
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function getTopFailedData() {
+       $query = "SELECT COUNT(l.imageid) AS count, "
+              .        "i.prettyname "
+              . "FROM log l, "
+              .      "image i "
+              . "WHERE l.imageid = i.id AND "
+              .       "l.ending = 'failed' AND "
+              .       "l.start > DATE_SUB(NOW(), INTERVAL 5 DAY) "
+              . "GROUP BY l.imageid "
+              . "ORDER BY count DESC "
+              . "LIMIT 5";
+       $data = array();
+       $qh = doQuery($query, 101);
+       while($row = mysql_fetch_assoc($qh))
+               $data[] = $row;
+       return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getTopFailedComputersData()
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function getTopFailedComputersData() {
+       $query = "SELECT COUNT(s.computerid) AS count, "
+              .        "c.hostname "
+              . "FROM log l, "
+              .      "sublog s, "
+              .      "computer c "
+              . "WHERE s.logid = l.id AND "
+              .       "s.computerid = c.id AND "
+              .       "l.ending = 'failed' AND "
+              .       "l.start > DATE_SUB(NOW(), INTERVAL 5 DAY) "
+              . "GROUP BY s.computerid "
+              . "ORDER BY count DESC "
+              . "LIMIT 5";
+       $data = array();
+       $qh = doQuery($query, 101);
+       while($row = mysql_fetch_assoc($qh))
+               $data[] = $row;
+       return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getActiveResChartData()
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function getActiveResChartData() {
+       $data = array();
+       $chartstart = unixFloor15(time() - (12 * 3600));
+       $chartend = $chartstart + (12 * 3600) + 900;
+       for($time = $chartstart, $i = 0; $time < $chartend; $time += 900, $i++) 
{
+               $fmttime = date('g:i a', $time);
+               $data["points"][$i] = array('x' => $i, 'y' => 0, 'value' => $i, 
'text' => $fmttime);
+       }
+       $data['maxy'] = 0;
+       $reloadid = getUserlistID('vclrel...@local');
+       $query = "SELECT id, "
+              .        "UNIX_TIMESTAMP(start) AS start, "
+              .        "UNIX_TIMESTAMP(finalend) AS end "
+              . "FROM log "
+              . "WHERE start < NOW() AND "
+              .       "finalend > DATE_SUB(NOW(), INTERVAL 12 HOUR) AND "
+              .       "ending NOT IN ('failed', 'failedtest') AND "
+              .       "wasavailable = 1 AND "
+              .       "userid != $reloadid";
+       $qh = doQuery($query, 101);
+       while($row = mysql_fetch_assoc($qh)) {
+               for($binstart = $chartstart, $binend = $chartstart + 900, 
$binindex = 0; 
+                  $binend <= $chartend;
+                  $binstart += 900, $binend += 900, $binindex++) {
+                       if($binend <= $row['start'])
+                               continue;
+                       elseif($row['start'] < $binend &&
+                               $row['end'] > $binstart) {
+                               $data["points"][$binindex]['y']++;
+                       }
+                       elseif($binstart >= $row['end'])
+                               break;
+               }
+       }
+       for($time = $chartstart, $i = 0; $time < $chartend; $time += 900, $i++) 
{
+               if($data["points"][$i]['y'] > $data['maxy'])
+                       $data['maxy'] = $data['points'][$i]['y'];
+               $data["points"][$i]['tooltip'] = 
"{$data['points'][$i]['text']}: {$data['points'][$i]['y']}";
+       }
+       return $data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn getBlockAllocationData()
+///
+/// \param 
+///
+/// \return
+///
+/// \brief 
+///
+////////////////////////////////////////////////////////////////////////////////
+function getBlockAllocationData() {
+       # active block allocation
+       $query = "SELECT COUNT(id) "
+              . "FROM blockTimes "
+              . "WHERE skip = 0 AND "
+              .       "start < NOW() AND "
+                        .       "end > NOW()";
+       $qh = doQuery($query, 101);
+       $row = mysql_fetch_row($qh);
+       $blockcount = $row[0];
+       # computers in blockComputers for active allocations
+       $query = "SELECT bc.computerid, "
+              .        "c.stateid "
+              . "FROM blockComputers bc "
+              . "LEFT JOIN computer c ON (c.id = bc.computerid) "
+              . "LEFT JOIN blockTimes bt ON (bt.id = bc.blockTimeid) "
+              . "WHERE c.stateid IN (2, 3, 6, 8, 19) AND "
+              .       "bt.start < NOW() AND "
+              .       "bt.end > NOW()";
+       $qh = doQuery($query, 101);
+       $total = 0;
+       $used = 0;
+       while($row = mysql_fetch_assoc($qh)) {
+               $total++;
+               if($row['stateid'] == 3 || $row['stateid'] == 8)
+                       $used++;
+       }
+       if($total)
+               $compused = sprintf('%d / %d (%0.2f %%)', $used, $total, ($used 
/ $total * 100));
+       else
+               $compused = 0;
+       # number of computers that should be allocated
+       $query = "SELECT br.numMachines "
+              . "FROM blockRequest br "
+              . "LEFT JOIN blockTimes bt ON (bt.blockRequestid = br.id) "
+              . "WHERE bt.start < NOW() AND "
+              .       "bt.end > NOW() AND "
+              .       "bt.skip = 0";
+       $alloc = 0;
+       $qh = doQuery($query, 101);
+       while($row = mysql_fetch_assoc($qh))
+               $alloc += $row['numMachines'];
+       if($alloc)
+               $failed = sprintf('%d / %d (%0.2f %%)', ($alloc - $total), 
$alloc, (($alloc - $total) / $alloc * 100));
+       else
+               $failed = 0;
+       $data = array();
+       $data[] = array('title' => 'Active Block Allocations', 'val' => 
$blockcount);
+       $data[] = array('title' => 'Block Computer Usage', 'val' => $compused);
+       $data[] = array('title' => 'Failed Block Computers', 'val' => $failed);
+       return $data;
+}
+?>

Modified: incubator/vcl/trunk/web/.ht-inc/states.php
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/states.php?rev=1025626&r1=1025625&r2=1025626&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/states.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/states.php Wed Oct 20 16:17:19 2010
@@ -55,6 +55,7 @@ $actions["entry"] = array('main',
                           'continuationsError',
                           'requestBlockAllocation',
                           'siteMaintenance',
+                          'dashboard',
 );
 
 $noHTMLwrappers = array('sendRDPfile',
@@ -142,6 +143,8 @@ $noHTMLwrappers = array('sendRDPfile',
                         'AJgetScheduleTimesData',
                         'AJsaveScheduleTimes',
                         'AJvalidateUserid',
+                        'AJupdateDashboard',
+                        'AJgetStatData',
 );
 
 # main
@@ -555,19 +558,12 @@ $actions['pages']['userLookup'] = "userL
 $actions['pages']['submitUserLookup'] = "userLookup";
 
 # statistics
-# TODO might need the statgraph modes to be entry modes
 $actions['mode']['selectstats'] = "selectStatistics"; # entry
 $actions['mode']['viewstats'] = "viewStatistics";
-$actions['mode']['statgraphday'] = "sendStatGraphDay";
-$actions['mode']['statgraphhour'] = "sendStatGraphHour";
-$actions['mode']['statgraphdayconcuruser'] = "sendStatGraphDayConUsers";
-$actions['mode']['statgraphdayconcurblade'] = "sendStatGraphConBladeUser";
+$actions['mode']['AJgetStatData'] = "AJgetStatData";
 $actions['pages']['selectstats'] = "statistics";
 $actions['pages']['viewstats'] = "statistics";
-$actions['pages']['statgraphday'] = "statistics";
-$actions['pages']['statgraphhour'] = "statistics";
-$actions['pages']['statgraphdayconcuruser'] = "statistics";
-$actions['pages']['statgraphdayconcurblade'] = "statistics";
+$actions['pages']['AJgetStatData'] = "statistics";
 
 # help
 $actions['mode']['helpform'] = "printHelpForm"; # entry
@@ -635,6 +631,12 @@ $actions['pages']['AJgetDelSiteMaintenan
 $actions['pages']['AJeditSiteMaintenance'] = "sitemaintenance";
 $actions['pages']['AJdeleteSiteMaintenance'] = "sitemaintenance";
 
+# dashboard
+$actions['mode']['dashboard'] = "dashboard";
+$actions['mode']['AJupdateDashboard'] = "AJupdateDashboard";
+$actions['pages']['dashboard'] = "dashboard";
+$actions['pages']['AJupdateDashboard'] = "dashboard";
+
 # RPC
 $actions['mode']['xmlrpccall'] = "xmlrpccall";
 $actions['mode']['xmlrpcaffiliations'] = "xmlrpcgetaffiliations";

Modified: incubator/vcl/trunk/web/.ht-inc/statistics.php
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/statistics.php?rev=1025626&r1=1025625&r2=1025626&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/statistics.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/statistics.php Wed Oct 20 16:17:19 2010
@@ -16,21 +16,6 @@
   limitations under the License.
 */
 
-if($phpVer == 5) {
-       if(is_dir(".ht-inc/jpgraph")) {
-               require_once(".ht-inc/jpgraph/jpgraph.php");
-               require_once(".ht-inc/jpgraph/jpgraph_bar.php");
-               require_once(".ht-inc/jpgraph/jpgraph_line.php");
-       }
-}
-else {
-       if(is_dir(".ht-inc/jpgraph.old")) {
-               require_once(".ht-inc/jpgraph.old/jpgraph.php");
-               require_once(".ht-inc/jpgraph.old/jpgraph_bar.php");
-               require_once(".ht-inc/jpgraph.old/jpgraph_line.php");
-       }
-}
-
 /**
  * \file
  */
@@ -289,6 +274,8 @@ function viewStatistics() {
 
                # lengths
                $length = $row["finalend"] - $row["start"];
+               if($length < 0)
+                       $length = 0;
                if($length <= 1800)
                        $lengths["30min"]++;
                elseif($length <= 3600)
@@ -467,6 +454,7 @@ function viewStatistics() {
        print "  </TR>\n";
        print "</TABLE>\n";
        print "<br>\n";
+       print "</div>\n";
 
        $unixstart = datetimeToUnix($start);
        $unixend = datetimeToUnix($end);
@@ -476,30 +464,38 @@ function viewStatistics() {
                       'end' => $end,
                       'affilid' => $affilid);
        print "<H2>Reservations by Day</H2>\n";
-       $cont = addContinuationsEntry('statgraphday', $cdata);
-       print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>";
+       print "<small>(Reservations with start time on given 
day)</small><br>\n";
+       $cdata['divid'] = 'resbyday';
+       $cont = addContinuationsEntry('AJgetStatData', $cdata);
+       print "<input type=hidden id=statdaycont value=\"$cont\">\n";
+       print "<div id=\"resbyday\" style=\"width: 400px; height: 
310px;\">(Loading...)</div>\n";
 
        print "<H2>Max Concurrent Reservations By Day</H2>\n";
        if($unixend - $unixstart > SECINMONTH)
                print "(this graph only available for up to a month of 
data)<br>\n";
        else {
-               $cont = addContinuationsEntry('statgraphdayconcuruser', $cdata);
-               print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>";
+               $cdata['divid'] = 'maxconcurresday';
+               $cont = addContinuationsEntry('AJgetStatData', $cdata);
+               print "<input type=hidden id=statconcurrescont 
value=\"$cont\">\n";
+               print "<div id=\"maxconcurresday\" style=\"width: 400px; 
height: 310px;\">Loading graph data...</div>\n";
        }
 
        print "<H2>Max Concurrent Blade Reservations By Day</H2>\n";
        if($unixend - $unixstart > SECINMONTH)
                print "(this graph only available for up to a month of 
data)<br>\n";
        else {
-               $cont = addContinuationsEntry('statgraphdayconcurblade', 
$cdata);
-               print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>";
+               $cdata['divid'] = 'maxconcurbladeday';
+               $cont = addContinuationsEntry('AJgetStatData', $cdata);
+               print "<input type=hidden id=statconcurbladecont 
value=\"$cont\">\n";
+               print "<div id=\"maxconcurbladeday\" style=\"width: 400px; 
height: 310px;\">Loading graph data...</div>\n";
        }
 
        print "<H2>Reservations by Hour</H2>\n";
-       print "(Averaged over the time period)<br><br>\n";
-       $cont = addContinuationsEntry('statgraphhour', $cdata);
-       print "<img src=" . BASEURL . SCRIPT . "?continuation=$cont>";
-       print "</div>\n";
+       print "<small>(Active reservations during given hour averaged over 
selected dates)</small><br><br>\n";
+       $cdata['divid'] = 'resbyhour';
+       $cont = addContinuationsEntry('AJgetStatData', $cdata);
+       print "<input type=hidden id=statreshourcont value=\"$cont\">\n";
+       print "<div id=\"resbyhour\" style=\"width: 400px; height: 
310px;\">Loading graph data...</div>\n";
 
        $endtime = microtime(1);
        $end = $endtime - $timestart;
@@ -508,36 +504,26 @@ function viewStatistics() {
 
 
////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn sendStatGraphDay()
+/// \fn AJgetStatData()
 ///
-/// \brief sends a graph image
+/// \brief gets statistical data for a dojox chart and returns it in json 
format
 ///
 
////////////////////////////////////////////////////////////////////////////////
-function sendStatGraphDay() {
-       global $xaxislabels, $inContinuation;
-       if(! $inContinuation)
-               return;
+function AJgetStatData() {
        $start = getContinuationVar("start");
        $end = getContinuationVar("end");
        $affilid = getContinuationVar("affilid");
-       $graphdata = getStatGraphDayData($start, $end, $affilid);
-       $count = count($graphdata["labels"]);
-       if($count < 8)
-               $labelinterval = 1;
-       else
-               $labelinterval = $count / 7;
-       $xaxislabels = $graphdata["labels"];
-       $graph = new Graph(300, 300, "auto");
-       $graph->SetScale("textlin");
-       $plot = new BarPlot($graphdata["points"]);
-       $graph->Add($plot);
-       $graph->xaxis->SetLabelFormatCallback('statXaxisDayCallback');
-       $graph->xaxis->SetLabelAngle(90);
-       $graph->xaxis->SetTextLabelInterval($labelinterval);
-       $graph->yaxis->SetTitle('Reservations with start time on given day', 
-                               'high');
-       $graph->SetMargin(40,40,20,80);
-       $graph->Stroke();
+       $divid = getContinuationVar('divid');
+       if($divid == 'resbyday')
+               $data = getStatGraphDayData($start, $end, $affilid);
+       elseif($divid == 'maxconcurresday')
+               $data = getStatGraphDayConUsersData($start, $end, $affilid);
+       elseif($divid == 'maxconcurbladeday')
+               $data = getStatGraphConBladeUserData($start, $end, $affilid);
+       elseif($divid == 'resbyhour')
+               $data = getStatGraphHourData($start, $end, $affilid);
+       $data['id'] = $divid;
+       sendJSON($data);
 }
 
 
////////////////////////////////////////////////////////////////////////////////
@@ -548,9 +534,13 @@ function sendStatGraphDay() {
 /// \param $end - ending day in YYYY-MM-DD format
 /// \param $affilid - affiliationid of data to gather
 ///
-/// \return an array whose keys are the days (in YYYY-MM-DD format) between
-/// $start and $end, inclusive, and whose values are the number of reservations
-/// on each day
+/// \return an array with three keys:\n
+/// \b points - an array with y and tooltip keys that have the same value which
+///             is the y value at that point\n
+/// \b xlabels - an array with value and text keys, value's value is just an
+///              increasing integer starting from 1, text's value is the label
+///              to display on the x axis for the poing\n
+/// \b maxy - the max y value of the data
 ///
 /// \brief queries the log table to get reservations between $start and $end
 /// and creates an array with the number of reservations on each day
@@ -562,10 +552,12 @@ function getStatGraphDayData($start, $en
 
        $data = array();
        $data["points"] = array();
-       $data["labels"] = array();
+       $data['xlabels'] = array();
+       $data['maxy'] = 0;
        $reloadid = getUserlistID('vclrel...@local');
+       $cnt = 0;
        for($i = $startunix; $i < $endunix; $i += SECINDAY) {
-               array_push($data["labels"], date('Y-m-d', $i));
+               $cnt++;
                $startdt = unixToDatetime($i);
                $enddt = unixToDatetime($i + SECINDAY);
                if($affilid != 0) {
@@ -589,69 +581,35 @@ function getStatGraphDayData($start, $en
                }
                $qh = doQuery($query, 295);
                if($row = mysql_fetch_row($qh))
-                       array_push($data["points"], $row[0]);
+                       $value = $row[0];
                else
-                       array_push($data["points"], 0);
+                       $value = 0;
+               $label = date('m/d/Y', $i);
+               $data['points'][] = array('y' => (int)$value, 'tooltip' => 
"$label: " . (int)$value);
+               if($value > $data['maxy'])
+                       $data['maxy'] = (int)$value;
+               $data['xlabels'][] = array('value' => $cnt, 'text' => $label);
        }
        return($data);
 }
 
 
////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn statXaxisDayCallback($val)
-///
-/// \param $val - value passed in by SetLabelFormatCallback
-///
-/// \return day of week
-///
-/// \brief formats $val into day of week
-///
-////////////////////////////////////////////////////////////////////////////////
-function statXaxisDayCallback($val) {
-       global $xaxislabels;
-       if(array_key_exists((int)$val, $xaxislabels)) {
-               return date('n/d/Y', datetimeToUnix($xaxislabels[$val] . " 
00:00:00")) . " ";
-       }
-       else {
-               return $val;
-       }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \fn sendStatGraphHour()
-///
-/// \brief sends a graph image
-///
-////////////////////////////////////////////////////////////////////////////////
-function sendStatGraphHour() {
-       global $xaxislabels, $inContinuation;
-       if(! $inContinuation)
-               return;
-       $start = getContinuationVar("start");
-       $end = getContinuationVar("end");
-       $affilid = getContinuationVar("affilid");
-       $graphdata = getStatGraphHourData($start, $end, $affilid);
-       $graph = new Graph(300, 300, "auto");
-       $graph->SetScale("textlin");
-       $plot = new LinePlot($graphdata["points"]);
-       $graph->Add($plot);
-       $graph->xaxis->SetLabelFormatCallback('statXaxisHourCallback');
-       $graph->xaxis->SetLabelAngle(90);
-       $graph->xaxis->SetTextLabelInterval(2);
-       $graph->yaxis->SetTitle('Active reservations during given hour', 
'high');
-       $graph->SetMargin(40,40,20,80);
-       $graph->Stroke();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
 /// \fn getStatGraphHourData($start, $end, $affilid)
 ///
 /// \param $start - starting day in YYYY-MM-DD format
 /// \param $end - ending day in YYYY-MM-DD format
 /// \param $affilid - affiliationid of data to gather
 ///
+/// \return an array with two keys:\n
+/// \b points - an array with 5 keys:\n
+///             \t x - increasing integer starting from 1\n
+///             \t y - y value for the point\n
+///             \t value - same as x\n
+///             \t text - label for x axis for the point\n
+///             \t tooltip - tooltip to be displayed when point is hovered\n
+/// \b maxy - the max y value of the data
+///
 /// \return an array whose keys are the days (in YYYY-MM-DD format) between
 /// $start and $end, inclusive, and whose values are the number of reservations
 /// on each day
@@ -671,8 +629,9 @@ function getStatGraphHourData($start, $e
        $data = array();
        $data["points"] = array();
        for($i = 0; $i < 24; $i++) {
-               $data["points"][$i] = 0;
+               $data["points"][$i] = array('x' => $i, 'y' => 0, 'value' => $i, 
'text' => statHourFormatX($i), 'tooltip' => 0);
        }
+       $data["maxy"] = 0;
 
        $reloadid = getUserlistID('vclrel...@local');
        if($affilid != 0) {
@@ -701,7 +660,6 @@ function getStatGraphHourData($start, $e
                       .       "l.wasavailable = 1";
        }
        $qh = doQuery($query, 296);
-       $count = 0;
        while($row = mysql_fetch_assoc($qh)) {
                $startmin = ($row['shour'] * 60) + $row['smin'];
                $endmin = ($row['ehour'] * 60) + $row['emin'];
@@ -713,7 +671,7 @@ function getStatGraphHourData($start, $e
                                continue;
                        elseif($startmin < $binend &&
                                $endmin > $binstart) {
-                               $data["points"][$binindex]++;
+                               $data["points"][$binindex]['y']++;
                        }
                        elseif($binstart >= $endmin)
                                break;
@@ -721,70 +679,39 @@ function getStatGraphHourData($start, $e
        }
 
        # comment this to change graph to be aggregate instead of average
-       foreach($data["points"] as $key => $val)
-               $data["points"][$key] = $val / $days;
+       foreach($data["points"] as $key => $val) {
+               $newval = $val['y'] / $days;
+               if($newval - (int)$newval != 0)
+                       $newval = sprintf('%.2f', $newval);
+               $data['points'][$key]['y'] = $newval;
+               $data['points'][$key]['tooltip'] = $newval;
+               if($newval > $data['maxy'])
+                       $data['maxy'] = $newval;
+       }
 
        return($data);
 }
 
 
////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn statXaxisHourCallback($val)
+/// \fn statHourFormatX($val)
 ///
-/// \param $val - value passed in by SetLabelFormatCallback
+/// \param $val - hour of day (0-23)
 ///
 /// \return day of week
 ///
-/// \brief formats $val into day of week
+/// \brief formats $val into "hour am/pm"
 ///
 
////////////////////////////////////////////////////////////////////////////////
-function statXaxisHourCallback($val) {
-       if($val == 0) {
+function statHourFormatX($val) {
+       if($val == 0)
                return "12 am ";
-       }
-       elseif($val < 12) {
+       elseif($val < 12)
                return "$val am ";
-       }
-       elseif($val == 12) {
+       elseif($val == 12)
                return "$val pm ";
-       }
-       else {
-               return $val - 12 . " pm ";
-       }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \fn sendStatGraphDayConUsers()
-///
-/// \brief sends a graph image
-///
-////////////////////////////////////////////////////////////////////////////////
-function sendStatGraphDayConUsers() {
-       global $xaxislabels, $inContinuation;
-       if(! $inContinuation)
-               return;
-       $start = getContinuationVar("start");
-       $end = getContinuationVar("end");
-       $affilid = getContinuationVar("affilid");
-       $graphdata = getStatGraphDayConUsersData($start, $end, $affilid);
-       $count = count($graphdata["labels"]);
-       if($count < 8)
-               $labelinterval = 1;
        else
-               $labelinterval = $count / 7;
-       $xaxislabels = $graphdata["labels"];
-       $graph = new Graph(300, 300, "auto");
-       $graph->SetScale("textlin");
-       $plot = new BarPlot($graphdata["points"]);
-       $graph->Add($plot);
-       $graph->xaxis->SetLabelFormatCallback('statXaxisDayConUsersCallback');
-       $graph->xaxis->SetLabelAngle(90);
-       $graph->xaxis->SetTextLabelInterval($labelinterval);
-       $graph->yaxis->SetTitle('Maximum concurrent reservations per day', 
-                               'high');
-       $graph->SetMargin(40,40,20,80);
-       $graph->Stroke();
+               return $val - 12 . " pm ";
 }
 
 
////////////////////////////////////////////////////////////////////////////////
@@ -795,9 +722,13 @@ function sendStatGraphDayConUsers() {
 /// \param $end - ending day in YYYY-MM-DD format
 /// \param $affilid - affiliationid of data to gather
 ///
-/// \return an array whose keys are the days (in YYYY-MM-DD format) between
-/// $start and $end, inclusive, and whose values are the max concurrent users
-/// on each day
+/// \return an array with three keys:\n
+/// \b points - an array with y and tooltip keys that have the same value which
+///             is the y value at that point\n
+/// \b xlabels - an array with value and text keys, value's value is just an
+///              increasing integer starting from 1, text's value is the label
+///              to display on the x axis for the poing\n
+/// \b maxy - the max y value of the data
 ///
 /// \brief queries the log table to get reservations between $start and $end
 /// and creates an array with the max concurrent users per day
@@ -812,16 +743,17 @@ function getStatGraphDayConUsersData($st
 
        $data = array();
        $data["points"] = array();
-       $data["labels"] = array();
+       $data["xlabels"] = array();
+       $data["maxy"] = 0;
 
        $reloadid = getUserlistID('vclrel...@local');
+       $cnt = 0;
        for($daystart = $startunix; $daystart < $endunix; $daystart += 
SECINDAY) {
-               array_push($data["labels"], date('Y-m-d', $daystart));
+               $cnt++;
                $count = array();
                for($j = 0; $j < 24; $j++) {
                        $count[$j] = 0;
                }
-
                $startdt = unixToDatetime($daystart);
                $enddt = unixToDatetime($daystart + SECINDAY);
                if($affilid != 0) {
@@ -863,77 +795,30 @@ function getStatGraphDayConUsersData($st
                        }
                }
                rsort($count);
-               array_push($data["points"], $count[0]);
+               $label = date('m/d/Y', $daystart);
+               $data["points"][] = array('y' => $count[0], 'tooltip' => 
"$label: {$count[0]}");
+               if($count[0] > $data['maxy'])
+                       $data['maxy'] = $count[0];
+               $data['xlabels'][] = array('value' => $cnt, 'text' => $label);
        }
        return($data);
 }
 
 
////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn statXaxisDayConUsersCallback($val)
-///
-/// \param $val - value passed in by SetLabelFormatCallback
-///
-/// \return day of week
-///
-/// \brief formats $val into day of week
-///
-////////////////////////////////////////////////////////////////////////////////
-function statXaxisDayConUsersCallback($val) {
-       global $xaxislabels;
-       if(array_key_exists((int)$val, $xaxislabels)) {
-               return date('n/d/Y', datetimeToUnix($xaxislabels[$val] . " 
00:00:00")) . " ";
-       }
-       else {
-               return $val;
-       }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \fn sendStatGraphConBladeUser()
-///
-/// \brief sends a graph image of max concurrent users of blades per day
-///
-////////////////////////////////////////////////////////////////////////////////
-function sendStatGraphConBladeUser() {
-       global $xaxislabels, $inContinuation;
-       if(! $inContinuation)
-               return;
-       $start = getContinuationVar("start");
-       $end = getContinuationVar("end");
-       $affilid = getContinuationVar("affilid");
-       $graphdata = getStatGraphConBladeUserData($start, $end, $affilid);
-       $count = count($graphdata["labels"]);
-       if($count < 8)
-               $labelinterval = 1;
-       else
-               $labelinterval = $count / 7;
-       $xaxislabels = $graphdata["labels"];
-       $graph = new Graph(300, 300, "auto");
-       $graph->SetScale("textlin");
-       $plot = new BarPlot($graphdata["points"]);
-       $graph->Add($plot);
-       $graph->xaxis->SetLabelFormatCallback('statXaxisDayConUsersCallback');
-       $graph->xaxis->SetLabelAngle(90);
-       $graph->xaxis->SetTextLabelInterval($labelinterval);
-       $graph->yaxis->SetTitle('Maximum concurrent reservations per day', 
-                               'high');
-       $graph->SetMargin(40,40,20,80);
-       $graph->Stroke();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
 /// \fn getStatGraphConBladeUserData($start, $end, $affilid)
 ///
 /// \param $start - starting day in YYYY-MM-DD format
 /// \param $end - ending day in YYYY-MM-DD format
 /// \param $affilid - affiliationid of data to gather
 ///
-/// \return an array whose keys are the days (in YYYY-MM-DD format) between
-/// $start and $end, inclusive, and whose values are the max concurrent users
-/// of blades on each day
+/// \return an array with three keys:\n
+/// \b points - an array with y and tooltip keys that have the same value which
+///             is the y value at that point\n
+/// \b xlabels - an array with value and text keys, value's value is just an
+///              increasing integer starting from 1, text's value is the label
+///              to display on the x axis for the poing\n
+/// \b maxy - the max y value of the data
 ///
 /// \brief queries the log table to get reservations between $start and $end
 /// and creates an array with the max concurrent users of blades per day
@@ -948,11 +833,13 @@ function getStatGraphConBladeUserData($s
 
        $data = array();
        $data["points"] = array();
-       $data["labels"] = array();
+       $data["xlabels"] = array();
+       $data["maxy"] = 0;
 
        $reloadid = getUserlistID('vclrel...@local');
+       $cnt = 0;
        for($daystart = $startunix; $daystart < $endunix; $daystart += 
SECINDAY) {
-               array_push($data["labels"], date('Y-m-d', $daystart));
+               $cnt++;
                $count = array();
                for($j = 0; $j < 24; $j++) {
                        $count[$j] = 0;
@@ -1010,29 +897,12 @@ function getStatGraphConBladeUserData($s
                        }
                }
                rsort($count);
-               array_push($data["points"], $count[0]);
+               $label = date('m/d/Y', $daystart);
+               $data["points"][] = array('y' => $count[0], 'tooltip' => 
"$label: {$count[0]}");
+               if($count[0] > $data['maxy'])
+                       $data['maxy'] = $count[0];
+               $data['xlabels'][] = array('value' => $cnt, 'text' => $label);
        }
        return($data);
 }
-
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \fn statXaxisConBladeUserCallback($val)
-///
-/// \param $val - value passed in by SetLabelFormatCallback
-///
-/// \return day of week
-///
-/// \brief formats $val into day of week
-///
-////////////////////////////////////////////////////////////////////////////////
-function statXaxisConBladeUserCallback($val) {
-       global $xaxislabels;
-       if(array_key_exists((int)$val, $xaxislabels)) {
-               return date('n/d/Y', datetimeToUnix($xaxislabels[$val] . " 
00:00:00")) . " ";
-       }
-       else {
-               return $val;
-       }
-}
 ?>

Modified: incubator/vcl/trunk/web/.ht-inc/utils.php
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/utils.php?rev=1025626&r1=1025625&r2=1025626&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/utils.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/utils.php Wed Oct 20 16:17:19 2010
@@ -307,6 +307,9 @@ function initGlobals() {
                case 'vm':
                        require_once(".ht-inc/vm.php");
                        break;
+               case 'dashboard':
+                       require_once(".ht-inc/dashboard.php");
+                       break;
                default:
                        require_once(".ht-inc/requests.php");
        }
@@ -8776,14 +8779,10 @@ function getNavMenu($inclogout, $inchome
        $rt .= menulistLI('statistics');
        $rt .= "<a href=\"" . BASEURL . SCRIPT . "?mode=selectstats\">";
        $rt .= "Statistics</a></li>\n";
-       if($skin != 'ecu') {
-               $rt .= menulistLI('help');
-               $rt .= "<a href=\"" . HELPURL . "\">Help</a></li>\n";
-       }
-       if($skin == 'ecu') {
-               $rt .= "<li><a 
href=\"http://www.ecu.edu/cs-itcs/vcl/connect.cfm\";>Requirements</a></li>\n";
-               $rt .= "<li><a 
href=\"http://www.ecu.edu/cs-itcs/vcl/save.cfm\";>File Saving</a></li>\n";
-               $rt .= "<li><a 
href=\"http://www.ecu.edu/cs-itcs/vcl/faqs.cfm\";>Help</a></li>\n";
+       if($viewmode == ADMIN_DEVELOPER) {
+               $rt .= menulistLI('dashboard');
+               $rt .= "<a href=\"" . BASEURL . SCRIPT . "?mode=dashboard\">";
+               $rt .= "Dashboard</a></li>\n";
        }
        if(in_array("userGrant", $user["privileges"]) ||
                in_array("resourceGrant", $user["privileges"]) ||
@@ -8989,6 +8988,21 @@ function getDojoHTML($refresh) {
                                              'dijit.Tooltip',
                                              'dijit.Dialog');
                        break;
+               case 'viewstats':
+                       $dojoRequires = array('dojo.parser',
+                                             'dojox.charting.Chart2D',
+                                             'dojox.charting.action2d.Tooltip',
+                                             'dojox.charting.action2d.Magnify',
+                                             'dojox.charting.themes.ThreeD');
+                       break;
+               case 'dashboard':
+                       $dojoRequires = array('dojo.parser',
+                                             'dijit.Tooltip',
+                                             'dojox.charting.widget.Chart2D',
+                                             'dojox.charting.action2d.Tooltip',
+                                             'dojox.charting.action2d.Magnify',
+                                             'dojox.charting.themes.ThreeD');
+                       break;
        }
        if(empty($dojoRequires))
                return '';
@@ -9313,6 +9327,39 @@ function getDojoHTML($refresh) {
                        $rt .= "   });\n";
                        $rt .= "</script>\n";
                        return $rt;
+               case "viewstats":
+                       $rt .= "<style type=\"text/css\">\n";
+                       $rt .= "   @import 
\"themes/$skin/css/dojo/$skin.css\";\n";
+                       $rt .= "</style>\n";
+                       $rt .= "<script type=\"text/javascript\" 
src=\"js/statistics.js\"></script>\n";
+                       $rt .= "<script type=\"text/javascript\" 
src=\"dojo/dojo/dojo.js\"\n";
+                       $rt .= "   djConfig=\"parseOnLoad: true\">\n";
+                       $rt .= "</script>\n";
+                       $rt .= "<script type=\"text/javascript\">\n";
+                       $rt .= "   dojo.addOnLoad(function() {\n";
+                       foreach($dojoRequires as $req)
+                               $rt .= "   dojo.require(\"$req\");\n";
+                       $rt .= "   generateGraphs();\n";
+                       $rt .= "   });\n";
+                       $rt .= "</script>\n";
+                       return $rt;
+               case "dashboard":
+                       $rt .= "<style type=\"text/css\">\n";
+                       $rt .= "   @import 
\"themes/$skin/css/dojo/$skin.css\";\n";
+                       $rt .= "   @import \"css/dashboard.css\";\n";
+                       $rt .= "</style>\n";
+                       $rt .= "<script type=\"text/javascript\" 
src=\"js/dashboard.js\"></script>\n";
+                       $rt .= "<script type=\"text/javascript\" 
src=\"dojo/dojo/dojo.js\"\n";
+                       $rt .= "   djConfig=\"parseOnLoad: true, debug: 
true\">\n";
+                       $rt .= "</script>\n";
+                       $rt .= "<script type=\"text/javascript\">\n";
+                       $rt .= "   dojo.addOnLoad(function() {\n";
+                       foreach($dojoRequires as $req)
+                               $rt .= "   dojo.require(\"$req\");\n";
+                       $rt .= "   updateDashboard();\n";
+                       $rt .= "   });\n";
+                       $rt .= "</script>\n";
+                       return $rt;
 
                default:
                        $rt .= "<style type=\"text/css\">\n";

Added: incubator/vcl/trunk/web/css/dashboard.css
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/css/dashboard.css?rev=1025626&view=auto
==============================================================================
--- incubator/vcl/trunk/web/css/dashboard.css (added)
+++ incubator/vcl/trunk/web/css/dashboard.css Wed Oct 20 16:17:19 2010
@@ -0,0 +1,23 @@
+.dashwidget {
+       border: 1px solid;
+       text-align: center;
+       /*border-radius: 10px;
+       -moz-border-radius: 10px;*/
+       margin-bottom: 8px;
+}
+
+.dashwidget .extra {
+       margin-bottom: 5px;
+}
+
+.dashwidget table {
+       margin-left: auto;
+       margin-right: auto;
+}
+
+.dashwidget h3 {
+       background: #0053fb;
+       color: white;
+       margin-top: 0px;
+       margin-bottom: 2px;
+}

Modified: incubator/vcl/trunk/web/js/code.js
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/code.js?rev=1025626&r1=1025625&r2=1025626&view=diff
==============================================================================
--- incubator/vcl/trunk/web/js/code.js (original)
+++ incubator/vcl/trunk/web/js/code.js Wed Oct 20 16:17:19 2010
@@ -123,10 +123,10 @@ var genericCB = function(type, data, evt
        eval(data);
 }
 
-var errorHandler = function(type, error, data) {
-       if(args.dojoType == 'cancel')
+var errorHandler = function(error, ioArgs) {
+       if(error.name == 'cancel')
                return;
-       alert('error occurred' + error.message + data.responseText);
+       alert('AJAX Error: ' + error.message + '\nLine ' + error.lineNumber + ' 
in ' + error.fileName);
 }
 
 function errorHandler(data, ioArgs) {

Added: incubator/vcl/trunk/web/js/dashboard.js
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/dashboard.js?rev=1025626&view=auto
==============================================================================
--- incubator/vcl/trunk/web/js/dashboard.js (added)
+++ incubator/vcl/trunk/web/js/dashboard.js Wed Oct 20 16:17:19 2010
@@ -0,0 +1,204 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+function RPCwrapper(data, CB, dojson) {
+       if(dojson) {
+               dojo.xhrPost({
+                       url: 'index.php',
+                       load: CB,
+                       handleAs: "json",
+                       error: errorHandler,
+                       content: data,
+                       timeout: 15000
+               });
+       }
+       else {
+               dojo.xhrPost({
+                       url: 'index.php',
+                       load: CB,
+                       error: errorHandler,
+                       content: data,
+                       timeout: 15000
+               });
+       }
+}
+
+function generalReqCB(data, ioArgs) {
+       eval(data);
+       document.body.style.cursor = 'default';
+}
+
+function updateDashboard() {
+       var cont = dojo.byId('updatecont').value;
+       RPCwrapper({continuation: cont}, updateDashboardCB, 1);
+}
+
+function updateDashboardCB(data, ioArgs) {
+       dojo.byId('updatecont').value = data.items.cont;
+       updateStatus(data.items.status);
+       updateTopImages(data.items.topimages);
+       updateTopLongImages(data.items.toplongimages);
+       updateTopFailed(data.items.topfailed);
+       updateTopFailedComputers(data.items.topfailedcomputers);
+       updateResChart(data.items.reschart);
+       updateBlockAllocation(data.items.blockallocation);
+       setTimeout(updateDashboard, 15000);
+}
+
+function updateStatus(data) {
+       var obj = dojo.byId('status');
+       var txt = '<table>';
+       for(var i = 0; i < data.length; i++) {
+               txt += '<tr><th align="right">'
+               if(data[i].tooltip) {
+                       txt += '<span id="status' + i + '">'
+                           + data[i].key
+                           + '</span>'
+                           + '</th><td>'
+                           + data[i].val
+                           + '</td></tr>';
+               }
+               else {
+                       txt += data[i].key
+                           + '</th><td>'
+                           + data[i].val
+                           + '</td></tr>';
+               }
+       }
+       txt += '</table>';
+       obj.innerHTML = txt;
+       for(var i = 0; i < data.length; i++) {
+               if(data[i].tooltip) {
+                       var tt = new dijit.Tooltip({
+                               connectId: ['status' + i],
+                               label: data[i].tooltip
+                       });
+               }
+       }
+}
+
+function updateTopImages(data) {
+       var obj = dojo.byId('topimages');
+       if(data.length == 0) {
+               obj.innerHTML = 'No recent reservations';
+               return;
+       }
+       var txt = '<table>';
+       for(var i = 0; i < data.length; i++) {
+               txt += '<tr><th align="right">'
+                   + data[i].prettyname
+                   + '</th><td>'
+                   + data[i].count
+                   + '</td></tr>';
+       }
+       txt += '</table>';
+       obj.innerHTML = txt;
+}
+
+function updateTopLongImages(data) {
+       var obj = dojo.byId('toplongimages');
+       if(data.length == 0) {
+               obj.innerHTML = 'No recent reservations';
+               return;
+       }
+       var txt = '<table>';
+       for(var i = 0; i < data.length; i++) {
+               txt += '<tr><th align="right">'
+                   + data[i].prettyname
+                   + '</th><td>'
+                   + data[i].count
+                   + '</td></tr>';
+       }
+       txt += '</table>';
+       obj.innerHTML = txt;
+}
+
+function updateTopFailed(data) {
+       var obj = dojo.byId('topfailed');
+       if(data.length == 0) {
+               obj.innerHTML = 'No recent reservations';
+               return;
+       }
+       var txt = '<table>';
+       for(var i = 0; i < data.length; i++) {
+               txt += '<tr><th align="right">'
+                   + data[i].prettyname
+                   + '</th><td>'
+                   + data[i].count
+                   + '</td></tr>';
+       }
+       txt += '</table>';
+       obj.innerHTML = txt;
+}
+
+function updateTopFailedComputers(data) {
+       var obj = dojo.byId('topfailedcomputers');
+       if(data.length == 0) {
+               obj.innerHTML = 'No recent reservations';
+               return;
+       }
+       var txt = '<table>';
+       for(var i = 0; i < data.length; i++) {
+               txt += '<tr><th align="right">'
+                   + data[i].hostname
+                   + '</th><td>'
+                   + data[i].count
+                   + '</td></tr>';
+       }
+       txt += '</table>';
+       obj.innerHTML = txt;
+}
+
+function updateBlockAllocation(data) {
+       var obj = dojo.byId('blockallocation');
+       var txt = '<table>';
+       for(var i = 0; i < data.length; i++) {
+               txt += '<tr><th align="right">'
+                   + data[i].title
+                   + '</th><td>'
+                   + data[i].val
+                   + '</td></tr>';
+       }
+       txt += '</table>';
+       obj.innerHTML = txt;
+}
+
+function updateResChart(data) {
+       var graph = dijit.byId('reschart').chart;
+       graph.updateSeries('Main', data.points);
+       graph.labeldata = data.points;
+       graph.render();
+}
+
+function timestampToTime(val) {
+       if(! dijit.byId('reschart').chart.labeldata)
+               return '';
+       else
+               var data = dijit.byId('reschart').chart.labeldata;
+       return data[val]['text'];
+       var d = new Date();
+       d.setTime(val*1000);
+       var h = d.getHours();
+       if(h == 0)
+               return "12:" + d.getMinutes() + " am";
+       else if(h < 12)
+               return h + ":" + d.getMinutes() + " am";
+       else if(h == 12)
+               return "12:" + d.getMinutes() + " pm";
+       else
+               return (h - 12) + ":" + d.getMinutes() + "pm";
+}

Added: incubator/vcl/trunk/web/js/statistics.js
URL: 
http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/statistics.js?rev=1025626&view=auto
==============================================================================
--- incubator/vcl/trunk/web/js/statistics.js (added)
+++ incubator/vcl/trunk/web/js/statistics.js Wed Oct 20 16:17:19 2010
@@ -0,0 +1,144 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+function RPCwrapper(data, CB, dojson) {
+       if(dojson) {
+               dojo.xhrPost({
+                       url: 'index.php',
+                       load: CB,
+                       handleAs: "json",
+                       error: errorHandler,
+                       content: data,
+                       timeout: 300000
+               });
+       }
+       else {
+               dojo.xhrPost({
+                       url: 'index.php',
+                       load: CB,
+                       error: errorHandler,
+                       content: data,
+                       timeout: 300000
+               });
+       }
+}
+
+function generalReqCB(data, ioArgs) {
+       eval(data);
+       document.body.style.cursor = 'default';
+}
+
+function generateGraphs() {
+       var cont = dojo.byId('statdaycont').value;
+       RPCwrapper({continuation: cont}, generateColGraphsCB, 1);
+       var cont = dojo.byId('statreshourcont').value;
+       RPCwrapper({continuation: cont}, generateHourGraphsCB, 1);
+       if(dojo.byId('statconcurrescont')) {
+               var cont = dojo.byId('statconcurrescont').value;
+               RPCwrapper({continuation: cont}, generateColGraphsCB, 1);
+       }
+       if(dojo.byId('statconcurbladecont')) {
+               var cont = dojo.byId('statconcurbladecont').value;
+               RPCwrapper({continuation: cont}, generateColGraphsCB, 1);
+       }
+}
+
+function generateColGraphsCB(data, ioArgs) {
+       dojo.byId(data.items.id).innerHTML = '';
+       var graph = new dojox.charting.Chart2D(data.items.id);
+       if(data.items.maxy <= 400)
+               var majortick = 50;
+       else if(data.items.maxy <= 600)
+               var majortick = 100;
+       else if(data.items.maxy <= 1000)
+               var majortick = 200;
+       else {
+               var majortick = data.items.maxy / 10;
+               majortick = (majortick - (majortick % 200)) || 200;
+       }
+       graph.setTheme(dojox.charting.themes.ThreeD);
+       if(data.items.points.length < 10)
+               var gap = 6;
+       else if(data.items.points.length < 20)
+               var gap = 3;
+       else if(data.items.points.length < 50)
+               var gap = 2;
+       else
+               var gap = 0;
+       var xtickstep = parseInt(data.items.xlabels.length / 10) || 1;
+       graph.addAxis("x", {
+               includeZero: false,
+               labels: data.items.xlabels,
+               rotation: -90,
+               minorTicks: false,
+               font: 'normal normal normal 11px verdana',
+               majorTickStep: xtickstep
+       });
+       graph.addAxis('y', {
+               vertical: true,
+               fixUpper: "major",
+               includeZero: true,
+               minorTicks: true,
+               minorLabels: false,
+               majorTickStep: majortick,
+               minorTickStep: majortick / 2,
+       });
+       graph.addPlot('default', {type: "Columns", gap: gap});
+       graph.addPlot('Grid', {type: 'Grid', hMajorLines: true, vMajorLines: 
false});
+       graph.addSeries("Main", data.items.points, {stroke: {width: 1}});
+       var a = new dojox.charting.action2d.Tooltip(graph);
+       graph.render();
+}
+
+function generateHourGraphsCB(data, ioArgs) {
+       dojo.byId(data.items.id).innerHTML = '';
+       var graph = new dojox.charting.Chart2D(data.items.id);
+       if(data.items.maxy <= 50)
+               var majortick = 5;
+       else if(data.items.maxy <= 100)
+               var majortick = 10;
+       else if(data.items.maxy <= 200)
+               var majortick = 20;
+       else {
+               var majortick = data.items.maxy / 10;
+               majortick = (majortick - (majortick % 100)) || 100;
+       }
+       graph.setTheme(dojox.charting.themes.ThreeD);
+       graph.addAxis("x", {
+               includeZero: true,
+               labels: data.items.points,
+               rotation: -90,
+               minorTicks: false,
+               font: 'normal normal normal 11px verdana',
+               majorTickStep: 2
+       });
+       graph.addAxis('y', {
+               vertical: true,
+               fixUpper: "major",
+               includeZero: true,
+               minorTicks: true,
+               minorLabels: false,
+               majorTickStep: majortick,
+               minorTickStep: majortick / 5,
+       });
+       graph.addPlot('default', {markers: true});
+       graph.addPlot('Grid', {type: 'Grid', hMajorLines: true, vMajorLines: 
false});
+       graph.addSeries("Main", data.items.points);
+       var a = new dojox.charting.action2d.Tooltip(graph);
+       var a = new dojox.charting.action2d.Magnify(graph);
+       graph.render();
+}


Reply via email to