This is an automated email from the ASF dual-hosted git repository.

jfthomps pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/vcl.git


The following commit(s) were added to refs/heads/develop by this push:
     new afcb8492 VCL-1142 - add top images from past 6 months to dashboard
afcb8492 is described below

commit afcb8492d74c856d148bda4ed10c5f82336611f8
Author: Josh Thompson <[email protected]>
AuthorDate: Mon Feb 19 16:44:54 2024 -0500

    VCL-1142 - add top images from past 6 months to dashboard
    
    dashboard.php:
    -modified dashboard: added widget for toppast6moimages; added detaildialog 
dialog
    -modified AJupdateDashboard: added toppast6moimages to returned data; 
updated arguments to getTopPastImageData for toppastimages
    -added AJdashboardDetail
    -modified addWidget: added $clicktitle argument; modified to make title a 
link if $clicktitle is passed as true
    -modified getTopPastImageData: added $imagecnt, $intervalunit, and 
$intervalnum as arguments; modified queries to use arguments for date range and 
returned rows
    
    states.php: added AJdashboardDetail
    
    utils.php: added dijit.Dialog to to required dojo modules for dashboard
    
    dashboard.css: added "#detailcontent table td", ".dashwidget h3 a", and 
".dashwidget h3 a:hover"
    
    dashboard.js:
    -modified updateDashboardCB: added call to updateTopPast6MonthImages
    -added updateTopPast6MonthImages
    -added cancelDetail
    -added showdetail
    -added showDetailCB
    
    dropdownmenus/css/theme.css: added "#content div.dashwidget h3 a" and 
"#content div.dashwidget h3 a:hover"
---
 web/.ht-inc/dashboard.php              | 72 +++++++++++++++++++++++++++++-----
 web/.ht-inc/states.php                 |  3 ++
 web/.ht-inc/utils.php                  |  1 +
 web/css/dashboard.css                  | 20 +++++++++-
 web/js/dashboard.js                    | 43 ++++++++++++++++++++
 web/themes/dropdownmenus/css/theme.css |  8 +++-
 6 files changed, 135 insertions(+), 12 deletions(-)

diff --git a/web/.ht-inc/dashboard.php b/web/.ht-inc/dashboard.php
index 9018c206..82a16731 100644
--- a/web/.ht-inc/dashboard.php
+++ b/web/.ht-inc/dashboard.php
@@ -28,6 +28,7 @@
 ///
 
////////////////////////////////////////////////////////////////////////////////
 function dashboard() {
+       $affilid = getDashboardAffilID();
        print "<h2>VCL Dashboard</h2>\n";
        print "(Times and dates on this page are in " . date('T') . 
")<br><br>\n";
        if(checkUserHasPerm('View Dashboard (global)')) {
@@ -46,6 +47,7 @@ function dashboard() {
        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('toppastimages', 'Top 5 Images From Past Day', 
'(Reservations with a start<br>time within past 24 hours)');
+       print addWidget('toppast6moimages', 'Top 5 Images From Past 6 Months', 
'(Reservations with a start<br>time within past 6 months)', 1);
        print addWidget('topfailedcomputers', 'Top Recent Computer Failures', 
'(Failed in the last 5 days)');
        print addWidget('blockallocation', 'Block Allocation Status');
        print "</div>\n"; # dashleft
@@ -65,6 +67,24 @@ function dashboard() {
                print addWidget('failedimaging', 'Failed Imaging Reservations', 
'(Imaging Reservations in the maintenance state)');
        $cont = addContinuationsEntry('AJupdateDashboard', array('val' => 0), 
90, 1, 0);
        print "<input type=\"hidden\" id=\"updatecont\" value=\"$cont\">\n";
+       $cont = addContinuationsEntry('AJdashboardDetail', array('affilid' => 
$affilid));
+       print "<input type=\"hidden\" id=\"detailcont\" value=\"$cont\">\n";
+
+       # detail dialog
+       $h = '';
+       $h .= "<div dojoType=dijit.Dialog\n";
+       $h .= "      id=\"detaildialog\"\n";
+       $h .= "      duration=250\n";
+       $h .= "      autofocus=false\n";
+       $h .= "      draggable=true>\n";
+       $h .= "<h3><div id=\"detailtitle\"></div></h3>\n";
+       $h .= "<div id=\"detailcontent\"></div>\n";
+       $h .= "<input type=\"hidden\" id=\"submitcont\">\n";
+       $h .= "<div style=\"text-align: center;\"><br>\n";
+       $h .= dijitButton('canceldetailbtn', 'Close', 'cancelDetail();', 0);
+       $h .= "</div>\n"; # btn div
+       $h .= "</div>\n"; # detaildialog
+       print $h;
 }
 
 
////////////////////////////////////////////////////////////////////////////////
@@ -80,7 +100,8 @@ function AJupdateDashboard() {
        $data['status'] = getStatusData();
        $data['topimages'] = getTopImageData();
        $data['toplongimages'] = getTopLongImageData();
-       $data['toppastimages'] = getTopPastImageData();
+       $data['toppastimages'] = getTopPastImageData(5, 'DAY', 1);
+       $data['toppast6moimages'] = getTopPastImageData(5, 'MONTH', 6);
        $data['topfailed'] = getTopFailedData();
        $data['topfailedcomputers'] = getTopFailedComputersData();
        $data['reschart'] = getActiveResChartData();
@@ -91,6 +112,28 @@ function AJupdateDashboard() {
        sendJSON($data);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \fn AJdashboardDetail()
+///
+/// \param id - id of widget type
+///
+/// \brief gets detailed information for specified type
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJdashboardDetail() {
+       $id = processInputVar('id', ARG_STRING);
+       switch($id) {
+       case 'toppast6moimages':
+               $data = array('divid' => 'detailcontent');
+               $data['title'] = "Top Images From Past 6 Months";
+               $data['result'] = getTopPastImageData(30, 'MONTH', 6);
+               break;
+       default:
+       }
+       sendJSON($data);
+}
+
 
////////////////////////////////////////////////////////////////////////////////
 ///
 /// \fn addWidget($id, $title, extra)
@@ -99,15 +142,20 @@ function AJupdateDashboard() {
 /// \param $title - title to print at top of box
 /// \param $extra (optional, default='') - extra text to be placed below title,
 ///        but above data
+/// \param $clicktitle - (optional, default=0) boolean for title being 
clickable
+///        to display more details
 ///
 /// \return div element for a section of data
 ///
 /// \brief creates HTML for a box of data to be displayed
 ///
 
////////////////////////////////////////////////////////////////////////////////
-function addWidget($id, $title, $extra='') {
+function addWidget($id, $title, $extra='', $clicktitle=0) {
        $txt  = "<div class=\"dashwidget\">\n";
-       $txt .= "<h3>$title</h3>\n";
+       if($clicktitle)
+               $txt .= "<h3><a 
onclick=\"showdetail('$id');\">$title</a></h3>\n";
+       else
+               $txt .= "<h3>$title</h3>\n";
        if($extra != '')
                $txt .= "<div class=\"extra\">$extra</div>\n";
        $txt .= "<div id=\"$id\"></div>\n";
@@ -343,7 +391,11 @@ function getTopLongImageData() {
 
 
////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn getTopPastImageData()
+/// \fn getTopPastImageData($imagecnt, $intervalunit, $intervalnum)
+///
+/// \param $imagecnt - number of images to return
+/// \param $intervalunit - units of interval for DATE_SUB in query
+/// \param $intervalnum - how many interval units to use in query
 ///
 /// \return array of data with these keys:\n
 /// \b prettyname - name of image\n
@@ -352,7 +404,7 @@ function getTopLongImageData() {
 /// \brief gets data about top reserved images over past day
 ///
 
////////////////////////////////////////////////////////////////////////////////
-function getTopPastImageData() {
+function getTopPastImageData($imagecnt, $intervalunit, $intervalnum) {
        $affilid = getDashboardAffilID();
        $reloadid = getUserlistID('vclreload@Local');
        if($affilid == 0) {
@@ -363,10 +415,10 @@ function getTopPastImageData() {
                       . "WHERE l.imageid = i.id AND "
                       .       "l.wasavailable = 1 AND "
                       .       "l.userid != $reloadid AND "
-                      .       "l.start > DATE_SUB(NOW(), INTERVAL 1 DAY) "
+                      .       "l.start > DATE_SUB(NOW(), INTERVAL $intervalnum 
$intervalunit) "
                       . "GROUP BY l.imageid "
                       . "ORDER BY count DESC "
-                      . "LIMIT 5";
+                      . "LIMIT $imagecnt";
        }
        else {
                $query = "SELECT COUNT(l.imageid) AS count, "
@@ -379,10 +431,10 @@ function getTopPastImageData() {
                       .       "l.imageid = i.id AND "
                       .       "l.wasavailable = 1 AND "
                       .       "l.userid != $reloadid AND "
-                      .       "l.start > DATE_SUB(NOW(), INTERVAL 1 DAY) "
+                      .       "l.start > DATE_SUB(NOW(), INTERVAL $intervalnum 
$intervalunit) "
                       . "GROUP BY l.imageid "
                       . "ORDER BY count DESC "
-                      . "LIMIT 5";
+                      . "LIMIT $imagecnt";
        }
        $data = array();
        $qh = doQuery($query, 101);
@@ -918,7 +970,7 @@ function getDashboardAffilID() {
        global $user;
        if(! checkUserHasPerm('View Dashboard (global)'))
                return $user['affiliationid'];
-       $affilid = processInputVar('affilid', ARG_NUMERIC);
+       $affilid = getContinuationVar('affilid', processInputVar('affilid', 
ARG_NUMERIC, 0));
        $affils = getAffiliations();
        if($affilid != 0 && ! array_key_exists($affilid, $affils))
                return 0;
diff --git a/web/.ht-inc/states.php b/web/.ht-inc/states.php
index 2e7cb06d..9ac803e0 100644
--- a/web/.ht-inc/states.php
+++ b/web/.ht-inc/states.php
@@ -136,6 +136,7 @@ $noHTMLwrappers = array('sendRDPfile',
                         'AJdeleteSiteMaintenance',
                         'AJvalidateUserid',
                         'AJupdateDashboard',
+                        'AJdashboardDetail',
                         'AJgetStatData',
                         'AJgetBlockAllocatedMachineData',
                         'AJpermSelectUserGroup',
@@ -554,9 +555,11 @@ $actions['pages']['AJdeleteSiteMaintenance'] = 
"sitemaintenance";
 $actions['mode']['dashboard'] = "dashboard";
 $actions['mode']['AJupdateDashboard'] = "AJupdateDashboard";
 $actions['mode']['AJrestartImageCapture'] = "AJrestartImageCapture";
+$actions['mode']['AJdashboardDetail'] = "AJdashboardDetail";
 $actions['pages']['dashboard'] = "dashboard";
 $actions['pages']['AJupdateDashboard'] = "dashboard";
 $actions['pages']['AJrestartImageCapture'] = "dashboard";
+$actions['pages']['AJdashboardDetail'] = "dashboard";
 
 # site configuration
 $actions['mode']['siteconfig'] = "siteconfig";
diff --git a/web/.ht-inc/utils.php b/web/.ht-inc/utils.php
index 667673b6..3032e5a6 100644
--- a/web/.ht-inc/utils.php
+++ b/web/.ht-inc/utils.php
@@ -13957,6 +13957,7 @@ function getDojoHTML($refresh) {
                        $filename = 'vclDashboard.js';
                        $dojoRequires = array('dojo.parser',
                                              'dijit.Tooltip',
+                                             'dijit.Dialog',
                                              'dijit.form.Button',
                                              'dojox.charting.widget.Chart2D',
                                              'dojox.charting.action2d.Tooltip',
diff --git a/web/css/dashboard.css b/web/css/dashboard.css
index c592364e..5c1ae0b5 100644
--- a/web/css/dashboard.css
+++ b/web/css/dashboard.css
@@ -18,7 +18,8 @@
        padding-right: 10px;
 }
 
-#dashboard table td {
+#dashboard table td,
+#detailcontent table td {
        padding-left: 5px;
 }
 
@@ -45,3 +46,20 @@
        margin-top: 0px;
        margin-bottom: 2px;
 }
+
+.dashwidget h3 a {
+       background: #0053fb;
+       color: white;
+       margin-top: 0px;
+       margin-bottom: 2px;
+}
+
+.dashwidget h3 a:hover {
+       background: black;
+       color: white;
+       margin-top: 0px;
+       margin-bottom: 2px;
+       text-decoration: none;
+       cursor: pointer;
+}
+
diff --git a/web/js/dashboard.js b/web/js/dashboard.js
index 0591c5ca..582825a0 100644
--- a/web/js/dashboard.js
+++ b/web/js/dashboard.js
@@ -35,6 +35,7 @@ function updateDashboardCB(data, ioArgs) {
        updateTopImages(data.items.topimages);
        updateTopLongImages(data.items.toplongimages);
        updateTopPastImages(data.items.toppastimages);
+       updateTopPast6MonthImages(data.items.toppast6moimages);
        updateTopFailed(data.items.topfailed);
        updateTopFailedComputers(data.items.topfailedcomputers);
        updateResChart(data.items.reschart);
@@ -134,6 +135,31 @@ function updateTopPastImages(data) {
        obj.innerHTML = txt;
 }
 
+function updateTopPast6MonthImages(data) {
+       if('items' in data && 'divid' in data.items) {
+           var obj = dojo.byId(data.items.divid);
+           dojo.byId('detailtitle').innerHTML = data.items.title;
+               data = data.items.result;
+       }
+       else {
+               var obj = dojo.byId('toppast6moimages');
+       }
+       console.log("data length: " + data.length);
+       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) {
@@ -372,3 +398,20 @@ function secToHour(time) {
        var min = parseInt((time - (hour * 3600)) / 60);
        return dojox.string.sprintf('%d:%02d hour(s)', hour, min);
 }
+
+function cancelDetail() {
+    dijit.byId('detaildialog').hide();
+}
+
+function showdetail(id) {
+       var data = {
+               id: id,
+               continuation: dojo.byId('detailcont').value
+       };
+       RPCwrapper(data, showDetailCB, 1);
+}
+
+function showDetailCB(data, ioArgs) {
+       updateTopPast6MonthImages(data);
+       dijit.byId('detaildialog').show();
+}
diff --git a/web/themes/dropdownmenus/css/theme.css 
b/web/themes/dropdownmenus/css/theme.css
index be025f7c..3b682864 100644
--- a/web/themes/dropdownmenus/css/theme.css
+++ b/web/themes/dropdownmenus/css/theme.css
@@ -380,9 +380,15 @@ div.dijitMenuPopup table tbody tr.dijitMenuItemFocused td {
 #addResourceGroupPane td.privCascade:hover {
        background-color: #008000 !important;
 }
-#content div.dashwidget h3 {
+#content div.dashwidget h3,
+#content div.dashwidget h3 a {
        background-color: #ed1c24;
 }
+#content div.dashwidget h3 a:hover {
+       background-color: black;
+       color: white;
+       cursor: pointer;
+}
 a:hover, a:active {
   text-decoration: underline;
 }

Reply via email to