Commit 45723e99 authored by Leigh B Stoller's avatar Leigh B Stoller
Browse files

Add ranking pages (user/project) for admins.

parent ba216a5e
require(window.APT_OPTIONS.configObject,
['underscore', 'js/quickvm_sup',
'js/lib/text!template/ranking.html'
],
function (_, sup, mainString)
{
'use strict';
var mainTemplate = _.template(mainString);
function initialize()
{
window.APT_OPTIONS.initialize(sup);
var userlist = decodejson('#user-json');
var projlist = decodejson('#project-json');
// Generate the main template.
var html = mainTemplate({
"users" : userlist,
"projects" : projlist,
"days" : window.DAYS,
});
$('#main-body').html(html);
InitTable("users");
InitTable("projects");
// Javascript to enable link to tab
var hash = document.location.hash;
if (hash) {
$('.nav-tabs a[href='+hash+']').tab('show');
}
// Change hash for page-reload
$('a[data-toggle="tab"]').on('show.bs.tab', function (e) {
window.location.hash = e.target.hash;
});
// Button to change the number of days.
$('#change_days').click(function () {
var days = $('#days').val();
window.location.replace("ranking.php?days=" + days);
});
}
function InitTable(name)
{
var tablename = "#" + name + "_table";
var searchname = "#" + name + "_search";
var table = $(tablename)
.tablesorter({
theme : 'green',
// initialize zebra and filter widgets
widgets: ["zebra", "filter"],
widgetOptions: {
// include child row content while filtering, if true
filter_childRows : true,
// include all columns in the search.
filter_anyMatch : true,
// class name applied to filter row and each input
filter_cssFilter : 'form-control',
// search from beginning
filter_startsWith : false,
// Set this option to false for case sensitive search
filter_ignoreCase : true,
// Only one search box.
filter_columnFilters : false,
}
});
// Target the $('.search') input using built in functioning
// this binds to the search using "search" and "keyup"
// Allows using filter_liveSearch or delayed search &
// pressing escape to cancel the search
$.tablesorter.filter.bindSearch(table, $(searchname));
}
// Helper.
function decodejson(id) {
return JSON.parse(_.unescape($(id)[0].textContent));
}
$(document).ready(initialize);
});
...@@ -277,7 +277,8 @@ $PAGEHEADER_FUNCTION = function($thinheader = 0, $ignore1 = NULL, ...@@ -277,7 +277,8 @@ $PAGEHEADER_FUNCTION = function($thinheader = 0, $ignore1 = NULL,
$then = time() - (30 * 3600 * 24); $then = time() - (30 * 3600 * 24);
echo " <li><a href='activity.php?min=$then'> echo " <li><a href='activity.php?min=$then'>
History Data</a></li> History Data</a></li>
<li><a href='sumstats.php?min=$then'>Summary Stats</a></li>"; <li><a href='sumstats.php?min=$then'>Summary Stats</a></li>
<li><a href='ranking.php'>User/Proj Ranking</a></li>";
echo "<li><a href='myexperiments.php?all=1'> echo "<li><a href='myexperiments.php?all=1'>
All Experiments</a></li> All Experiments</a></li>
<li><a href='myprofiles.php?all=1'> <li><a href='myprofiles.php?all=1'>
...@@ -312,6 +313,7 @@ $PAGEHEADER_FUNCTION = function($thinheader = 0, $ignore1 = NULL, ...@@ -312,6 +313,7 @@ $PAGEHEADER_FUNCTION = function($thinheader = 0, $ignore1 = NULL,
list($pcount, $phours) = Instance::CurrentUsage($login_user); list($pcount, $phours) = Instance::CurrentUsage($login_user);
list($foo, $weeksusage) = Instance::WeeksUsage($login_user); list($foo, $weeksusage) = Instance::WeeksUsage($login_user);
list($foo, $monthsusage) = Instance::MonthsUsage($login_user); list($foo, $monthsusage) = Instance::MonthsUsage($login_user);
list($rank, $ranktotal) = Instance::Ranking($login_user, 30);
if ($phours || $weeksusage || $monthsusage) { if ($phours || $weeksusage || $monthsusage) {
echo "<center style='margin-bottom: 5px; margin-top: -8px'>"; echo "<center style='margin-bottom: 5px; margin-top: -8px'>";
if ($phours) if ($phours)
...@@ -329,12 +331,16 @@ $PAGEHEADER_FUNCTION = function($thinheader = 0, $ignore1 = NULL, ...@@ -329,12 +331,16 @@ $PAGEHEADER_FUNCTION = function($thinheader = 0, $ignore1 = NULL,
echo ", "; echo ", ";
echo "<span class='text-danger'> echo "<span class='text-danger'>
Prev Month: $monthsusage</span>"; Prev Month: $monthsusage</span>";
if ($rank) {
echo "<span class='text-info'>
(30 day rank: $rank of $ranktotal users)</span>";
}
} }
echo "<a href='#' class='btn btn-xs' data-toggle='modal' ". echo "<a href='#' class='btn btn-xs' data-toggle='modal' ".
"data-target='#myusage_modal'> ". "data-target='#myusage_modal'> ".
"<span class='glyphicon glyphicon-question-sign' ". "<span class='glyphicon glyphicon-question-sign' ".
" style='margin-bottom: 4px;'></span> ". " style='margin-bottom: 4px;'></span> ".
"</a>\n"; "</a>";
echo "</center>\n"; echo "</center>\n";
} }
readfile("template/myusage.html"); readfile("template/myusage.html");
......
<?php
#
# Copyright (c) 2000-2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
chdir("..");
include("defs.php3");
chdir("apt");
include("quickvm_sup.php");
# Must be after quickvm_sup.php since it changes the auth domain.
$page_title = "Ranking";
#
# Get current user.
#
RedirectSecure();
$this_user = CheckLoginOrRedirect();
$this_idx = $this_user->uid_idx();
$this_uid = $this_user->uid();
$optargs = OptionalPageArguments("days", PAGEARG_INTEGER);
if (!isset($days)) {
$days = 30;
}
#
# Verify page arguments.
#
SPITHEADER(1);
if (!ISADMIN() && !ISFOREIGN_ADMIN()) {
SPITUSERERROR("You do not have permission to view this information!");
return;
}
echo "<link rel='stylesheet'
href='css/tablesorter.css'>\n";
echo "<script type='text/javascript'>\n";
echo " window.DAYS = $days;\n";
echo "</script>\n";
# Place to hang the toplevel template.
echo "<div id='main-body'></div>\n";
function SpitRankList($target, $days)
{
$count = 1;
if ($target == "user") {
$which = "c.creator,c.creator_idx";
$join = "left join users as u on u.uid_idx=c.creator_idx ";
}
else {
$which = "c.pid,c.pid_idx";
$join = "left join projects as p on p.pid_idx=c.pid_idx ".
" left join users as u on u.uid_idx=p.head_idx";
}
$query_result =
DBQueryFatal("select $which,SUM(physnode_count) as physnode_count,".
" SUM(phours) as phours,u.usr_name,u.usr_affil, ".
" u.uid from ".
" ((select $which,physnode_count,created,NULL, ".
" physnode_count * (TIMESTAMPDIFF(HOUR, ".
" IF(created > DATE_SUB(now(), INTERVAL $days DAY), ".
" created, DATE_SUB(now(), INTERVAL $days DAY)), now())) ".
" as phours ".
" from apt_instances as c ".
" where physnode_count>0) ".
" union ".
" (select $which,physnode_count,created,destroyed, ".
" physnode_count * (TIMESTAMPDIFF(HOUR, ".
" IF(created > DATE_SUB(now(), INTERVAL $days DAY), ".
" created, DATE_SUB(now(), INTERVAL $days DAY)), destroyed))".
" as phours ".
" from apt_instance_history as c ".
" where physnode_count>0 and ".
" destroyed>DATE_SUB(now(),INTERVAL $days DAY)))".
" as c ".
"$join ".
"group by $which ".
"order by phours desc");
$results = array();
while ($row = mysql_fetch_array($query_result)) {
$blob = array();
$blob["rank"] = $count++;
$blob["usr_uid"] = $row["uid"];
$blob["usr_name"] = $row["usr_name"];
$blob["usr_affil"] = $row["usr_affil"];
$blob["pnodes"] = $row["physnode_count"];
$blob["phours"] = $row["phours"];
$results[$row[0]] = $blob;
}
echo "<script type='text/plain' id='${target}-json'>\n";
echo json_encode($results);
echo "</script>\n";
}
SpitRankList("user", $days);
SpitRankList("project", $days);
SPITREQUIRE("ranking",
"<script src='js/lib/jquery.tablesorter.min.js'></script>".
"<script src='js/lib/jquery.tablesorter.widgets.min.js'></script>".
"<script src='js/lib/sugar.min.js'></script>".
"<script src='js/lib/jquery.tablesorter.parser-date.js'></script>");
SPITFOOTER();
?>
<div class='row'>
<div class='col-sm-12'>
<center>
<input value=<%= days %> id="days" size="4"> day ranking.
<button class='btn btn-primary btn-xs'
id='change_days'
type='submit'>Go</button>
</center>
</div>
</div>
<div class='row'>
<div class='col-sm-12'>
<div class='panel panel-default'>
<div class='panel-body'>
<div class='row'>
<div class='col-sm-12'>
<div>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active">
<a href="#users" role="tab"
data-toggle="tab">Users</a></li>
<li role="presentation">
<a href="#projects" role="tab"
data-toggle="tab">Projects</a></li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane active" id="users">
<div class="table-responsive">
<input class='form-control search' type='search' data-column='all'
id='users_search' placeholder='Search'>
<table class='tablesorter' id='users_table'>
<thead>
<tr>
<th>UID</th>
<th>Rank</th>
<th>Name</th>
<th>Affiliation</th>
<th>Pnodes</th>
<th>Phours</th>
</tr>
</thead>
<tbody>
<% _.each(users, function(value, uid) { %>
<tr>
<td>
<a href='user-dashboard.php?user=<%= uid %>'>
<%= uid %></a>
</td>
<td><%= value.rank %></td>
<td><%= value.usr_name %></td>
<td><%= value.usr_affil %></td>
<td><%= value.pnodes %></td>
<td><%= value.phours %></td>
</tr>
<% }); %>
</tbody>
</table>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="projects">
<div class="table-responsive">
<input class='form-control search' type='search' data-column='all'
id='projects_search' placeholder='Search'>
<table class='tablesorter' id='projects_table'>
<thead>
<tr>
<th>PID</th>
<th>Rank</th>
<th>Leader</th>
<th>Affiliation</th>
<th>Pnodes</th>
<th>Phours</th>
</tr>
</thead>
<tbody>
<% _.each(projects, function(value, pid) { %>
<tr>
<td>
<a href='show-project.php?project=<%= pid %>'>
<%= pid %></a>
</td>
<td><%= value.rank %></td>
<td>
<a href='user-dashboard.php?user=<%= value.usr_uid %>'>
<%= value.usr_name %></a>
</td>
<td><%= value.usr_affil %></td>
<td><%= value.pnodes %></td>
<td><%= value.phours %></td>
</tr>
<% }); %>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment