Commit 69ec957f authored by Leigh Stoller's avatar Leigh Stoller

Moderate rework of the Emulab UI. When logged in, all of the main

menus that used to be on the left side, are now drop down menus along
the top. The banner across the top will also be smaller and more space
efficient.

The primary motivation for these changes is to leave more room for
actual content in the main window.

Tested with Firefox (1.5 and 2.0), Safari (2.0 and 3.0) and on
Internet Explorer Version 7. IE6 has some visual issues that might
make it a little annoying, but should be viewed as incentive to
upgrade to IE7 since it has been out a long time.
parent 5b61577a
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2006 University of Utah and the Flux Group.
* Copyright (c) 2000-2007 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -12,7 +12,8 @@ h5,h6 { font-weight: normal; }
p { text-indent: 1em; }
body, html {
margin: 0;
top: 0px;
margin: 0px;
color: #000000;
font-family: arial, helvetica, sans-serif; }
......
/*==============================================================================
GRC multi-level script-free pure-CSS menuing system stylesheet.
This code is hereby placed into the public domain by its author
Steve Gibson. It may be freely used for any purpose whatsoever.
Computed Geometries: with a default 12px font, 1.0em == 12px and
1px == 0.08333em.
Thus, our 98px wide Freeware & Research buttons are 8.166666em wide.
==============================================================================*/
/*========================= TOP OF THE MENU CASCADE =========================*/
.menu {
position:relative; /* establish a menu-relative positioning context */
/* float:left; /* play nicely with others */
margin:0;
padding:0;
border:0;
/* height:18px; /* the menu's overall height */
width:100%; /* we always want our menu to fill the available space */
background:#111;
color: #FFF;
font:normal 16px arial,Helvetica,sans-serif;
}
.menu img, img.droparrow {
border: 0px;
color:#111;
vertical-align: top; /* prevent images from being pushed down by text */
}
.menu ul {
padding:0;
margin:0;
border:0;
list-style-type:none; /* we don't want to view the list as a list */
/* line-height:1.5em; /* globally set the menu's item spacing. note */
} /* this must be 1.0 or 1.5 or 2.0 for Mozilla */
/* Top level links, no dropdowns. */
.menu ul li.toplevel a {
color: #FFF;
text-decoration:underline;
}
.menu li,
.menu li.divider {
float:left; /* this creates the side-by-side array of top-level buttons */
position:relative; /* create local positioning contexts for each button */
margin:0;
}
.menu li.divider {
border-top: solid 2px black;
}
.menu ul li table {
margin:-1px 0; /* IE5 needs -1px top and bottom table margins */
border-collapse:collapse; /* IE5 needs this for the sub-menus to work */
font:14px arial, Helvetica, sans-serif; /* this sets the base font size for our entire menu */
}
.drop {
display:block;
padding:0px 0.33em; /* this sets the l/r margins for our menu item */
margin:0;
text-align:right; /* this right alignment goes with the float:left below */
cursor:pointer; /* IE tries to switch back to an I-beam, don't let it */
cursor:hand; /* IE5 only knows about "hand", so set it both ways */
}
.drop span { /* this simultaneously left and right aligns the text and */
float:left; /* the >> in the drop-down menus which link to sub-menus */
}
.rightmenu {
position:relative; /* establish a local positioning context for YAH label */
float:right; /* and right-align it at the top of our page */
}
#research { /* this rightmost "Research" button must be positioned */
position:absolute; /* absolutely so that the YAH (you are here) text */
top:0px; /* label will slide underneath it under Opera v8.54 */
left:364px; /* which has a z-order sequencing bug with abs-pos elements */
}
/*======================== TOP LEVEL MENU DEFINITIONS ========================*/
.menu ul li ul {
font:14px arial, Helvetica, sans-serif; /* this sets the base font size for our entire menu */
display:none; /* initially hide the entire list hierarchy */
padding:1px; /* this is our box border width */
}
.menu ul li img {
vertical-align: middle; /* Force down-arrow to middle of line. */
}
.menu ul li {
padding:0;
border:0;
margin-right:10px; /* Space between toplevel items. */
}
.menu ul li a,
.menu ul li a:visited { /* unselected top-level menu items */
color: #FFF;
background: #111;
display:block;
float:left;
text-decoration:none;
height:18px;
}
.menu ul li:hover a,
.menu ul li a:hover { /* selected top-level menu items */
border-top: 0;
height:16px;
}
/*======================== 2ND LEVEL MENU DEFINITIONS ========================*/
.menu ul li:hover ul,
.menu ul li a:hover ul { /* 2nd level drop-down box */
display:block;
position:absolute;
margin:0;
top:16px; /* place us just up underneath the top-level images */
left:-1px; /* left-align our drop-down to the previous button border */
height:auto; /* the drop-down height will be determiend by line count */
width:13.5em;
color:#000; /* this sets the unselected-text color */
background:black; /* this sets our menu's effective "border" color */
}
.menu ul li:hover ul.leftbutton,
.menu ul li a:hover ul.leftbutton {/* our first dropdown should not be skewed */
left:0px;
}
.menu ul li:hover ul.skinny,
.menu ul li a:hover ul.skinny { /* 2nd level skinny drop-down box */
width:8.08333em; /* with a 12px default font, this is 97px width (97/12) */
}
.menu ul.rightmenu li:hover ul,
.menu ul.rightmenu li a:hover ul { /* 2nd level neighborhood drop-down box */
left:auto;
right:0; /* nudge the right menu right to line up under the border */
}
* html .menu ul.rightmenu li a:hover ul { /* IE5/6 needs a tweak here */
right:-1px;
}
.menu ul li:hover ul li a,
.menu ul li a:hover ul li a { /* 2nd level unselected items */
border-top: solid 1px black;
margin:0;
padding:0;
height:auto;
color:#000; /* this sets the unselected drop-down text color */
background:#FFFFFF; /* this sets the drop-down menu background color */
width:13.5em;
}
.menu ul li:hover ul li.divider a,
.menu ul li a:hover ul li.divider a { /* 2nd level unselected items */
border-top: solid 2px black;
margin:0;
padding:0;
height:auto;
color:#000; /* this sets the unselected drop-down text color */
background:#FFFFFF; /* this sets the drop-down menu background color */
width:13.5em;
}
.menu ul li:hover ul li:hover a,
.menu ul li a:hover ul li a:hover { /* 2nd level selected item */
color:#000;
background:#99A;
}
.menu ul li:hover ul.skinny li a,
.menu ul li a:hover ul.skinny li a,
.menu ul li:hover ul.skinny li a:hover,
.menu ul li a:hover ul.skinny li a:hover { /* 2nd level un+selected items */
width:8.08333em;
}
/*======================== 3RD LEVEL MENU DEFINITIONS ========================*/
.menu ul li:hover ul li ul,
.menu ul li a:hover ul li a ul { /* hide inactive 3rd-level menus */
visibility:hidden;
}
.menu ul li:hover ul li:hover ul,
.menu ul li a:hover ul li a:hover ul { /* 3rd level drop-down box */
visibility:visible;
position:absolute;
margin-top:-1px; /* bring the top edge of the 3rd level menu up one */
top:0;
left:8.08333em;
width:14em;
}
.menu ul li:hover ul li:hover ul li a,
.menu ul li a:hover ul li a:hover ul li a { /* 3rd level unselected items */
width:14em;
background:#d8d8d8;
}
.menu ul li:hover ul li:hover ul li a:hover,
.menu ul li a:hover ul li a:hover ul li a:hover { /* level3 selected items */
width:14em;
background:white;
}
......@@ -83,6 +83,33 @@ function SHOWSTATS()
return $output;
}
#
# Logged in users, show free node counts.
#
function ShowStatus()
{
$freepcs = TBFreePCs();
$reload = TBReloadingPCs();
$users = TBLoggedIn();
$active = TBActiveExperiments();
$output = "";
$output .= "<table valign=top align=center width=100% height=100%
cellspacing=1 cellpadding=0>";
$output .= "<tr><td nowrap class=usagefreenodes>$freepcs Free PCs</td>".
"</tr>\n";
$output .= "<tr><td nowrap class=usagefreenodes>$reload PCs reloading</td>".
"</tr>\n";
$output .= "<tr><td nowrap class=usagefreenodes>$users active users</td>".
"</tr>\n";
$output .= "<tr><td nowrap class=usagefreenodes>$active active expts.</td>".
"</tr>\n";
$output .= "</table>";
return $output;
}
#
# Logged in users, show free node counts.
#
......@@ -129,14 +156,15 @@ function SHOWFREENODES()
$freepcs = TBFreePCs();
$reloading = TBReloadingPCs();
$output .= "<table valign=top align=center width=100% height=100% border=1>
<tr><td nowrap colspan=6 class=menuoptusage align=center>
<font size=+1>$freepcs Free PCs</font></td></tr>\n";
$output .= "<table valign=top align=center width=100% height=100% border=1
cellspacing=1 cellpadding=0>
<tr><td nowrap colspan=8 class=usagefreenodes align=center>
<b>$freepcs Free PCs, $reloading reloading</b></td></tr>\n";
$pccount = count($freecounts);
$newrow = 1;
$maxcols = (int) ($pccount / 3);
if ($pccount % 3)
$maxcols = (int) ($pccount / 2);
if ($pccount % 2)
$maxcols++;
$cols = 0;
foreach($freecounts as $key => $value) {
......@@ -146,14 +174,14 @@ function SHOWFREENODES()
$output .= "<tr>\n";
}
$output .= "<td class=menuoptusage align=right>
$output .= "<td class=usagefreenodes align=right>
<a target=_parent href=shownodetype.php3?node_type=$key>
$key</a></td>
<td class=menuoptusage align=left>${freecount}</td>\n";
<td class=usagefreenodes align=left>${freecount}</td>\n";
$cols++;
$newrow = 0;
if ($cols == $maxcols || $pccount <= 3) {
if ($cols == $maxcols || $pccount <= 4) {
$cols = 0;
$newrow = 1;
}
......@@ -165,23 +193,19 @@ function SHOWFREENODES()
if (! $newrow) {
# Fill out to $maxcols
for ($i = $cols + 1; $i <= $maxcols; $i++) {
$output .= "<td class=menuoptusage>&nbsp</td>";
$output .= "<td class=menuoptusage>&nbsp</td>";
$output .= "<td class=usagefreenodes>&nbsp</td>";
$output .= "<td class=usagefreenodes>&nbsp</td>";
}
$output .= "</tr>\n";
}
# Fill in up to 3 rows.
if ($pccount < 3) {
for ($i = $pccount + 1; $i <= 3; $i++) {
$output .= "<tr><td class=menuoptusage>&nbsp</td>
<td class=menuoptusage>&nbsp</td></tr>\n";
# Fill in up to 2 rows.
if ($pccount < 2) {
for ($i = $pccount + 1; $i <= 2; $i++) {
$output .= "<tr><td class=usagefreenodes>&nbsp</td>
<td class=usagefreenodes>&nbsp</td></tr>\n";
}
}
$output .= "<tr>
<td class=menuoptusage colspan=6 align=center>
<font size=+1>$reloading PCs reloading</font></td>
</tr>\n";
$output .= "</table>";
return $output;
}
......@@ -193,7 +217,7 @@ function FreeNodeHtml() {
global $this_user;
if ($this_user) {
return SHOWFREENODES();
return ShowStatus();
}
else {
return SHOWSTATS();
......@@ -233,7 +257,7 @@ if ($this_user) {
?>
function FreeNodeHtml_CB(stuff) {
getObjbyName('usage').innerHTML = stuff;
getObjbyName('usagefreenodes').innerHTML = stuff;
setTimeout('GetFreeNodeHtml()', 60000);
}
function GetFreeNodeHtml() {
......@@ -244,8 +268,8 @@ if ($this_user) {
<?php
echo "</script>\n";
echo "<div id=usage>\n";
echo SHOWFREENODES();
echo "<div id=usagefreenodes>\n";
echo ShowStatus();
echo "</div>\n";
echo "</body></html>";
}
......
......@@ -368,6 +368,39 @@ function TBFreePCs()
return $row[0];
}
#
# Number of logged in users
#
function TBLoggedIn()
{
$query_result =
DBQueryFatal("select count(distinct uid) from login ".
"where timeout > UNIX_TIMESTAMP(now())");
if (mysql_num_rows($query_result) == 0) {
return 0;
}
$row = mysql_fetch_row($query_result);
return $row[0];
}
#
# Number of active experiments.
#
function TBActiveExperiments()
{
$query_result =
DBQueryFatal("select count(*) from experiments where ".
"state='active' and pid!='emulab-ops' and ".
"pid!='testbed'");
if (mysql_num_rows($query_result) != 1) {
return 0;
}
$row = mysql_fetch_array($query_result);
return $row[0];
}
#
# Number of PCs reloading.
#
......
<?php
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2002 University of Utah and the Flux Group.
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
include("defs.php3");
......@@ -12,10 +12,9 @@ include("defs.php3");
PAGEHEADER("Send us an email message!");
echo "<p>
What, you expected a fancy form? Maybe someday ...
What, you expected a fancy form?
<p>
For now, here is a plain old hyperlink: $TBMAILADDR
Sorry, here is a plain old hyperlink: $TBMAILADDR
\n";
#
......
......@@ -9,10 +9,14 @@
var user_agent = navigator.userAgent.toLowerCase();
var is_safari = false;
var is_firefox = false;
if (user_agent.indexOf("safari") != -1) {
is_safari = true;
}
if (user_agent.indexOf("firefox") != -1) {
is_firefox = true;
}
/* Clear the various 'loading' indicators. */
function ClearLoadingIndicators(done_msg)
......@@ -130,9 +134,9 @@ function SetupOutputArea(id, clean) {
}
Iframe.style.border = "2px solid";
Iframe.style.width = "100%";
Iframe.style.width = "98%";
Iframe.height = winheight;
Iframe.width = "100%";
Iframe.width = "98%";
Iframe.scrolling = "auto";
Iframe.frameBorder = "1";
}
......@@ -180,7 +184,7 @@ function ShowDownLoader(id) {
Iframe.style.border = "2px solid";
Iframe.height = winheight;
Iframe.width = "100%";
Iframe.width = "98%";
Iframe.scrolling = "auto";
Iframe.frameBorder = "1";
}
......@@ -413,3 +417,86 @@ function getObjNN4(obj,name) {
}
return foundLayer;
}
function toggle_tableold(e_table, e_checkbox, e_title, e_footer) {
var id_table = getObjbyName(e_table);
var id_footer = getObjbyName(e_footer);
var id_title = getObjbyName(e_title);
var id_check = getObjbyName(e_checkbox);
var checked = id_check.checked;
//Set the object to table-cell if the browser is
//Firefox and block if it's anything else.
if (is_firefox || is_safari) {
if (! checked) {
id_table.style.display = "none";
if (id_footer) {
id_footer.style.display = "none";
}
if (id_title) {
id_title.style.display = "none";
}
}
else {
id_table.style.display = "table";
if (id_footer) {
id_footer.style.display = "block";
}
if (id_title) {
id_title.style.display = "block";
}
}
}
else {
if (! checked) {
id_table.style.display = "none";
if (id_footer) {
id_footer.style.display = "none";
}
if (id_title) {
id_title.style.display = "none";
}
}
else {
id_table.style.display = "block";
if (id_footer) {
id_footer.style.display = "block";
}
if (id_title) {
id_title.style.display = "block";
}
}
}
return true;
}
function toggle_table(e_table, e_checkbox) {
var id_table = getObjbyName(e_table);
var id_check = getObjbyName(e_checkbox);
var checked = id_check.checked;
if (! checked) {
id_table.style.display = "none";
}
else {
id_table.style.display = "block";
}
return true;
}
function toggle_menu(e_list, e_arrow) {
var id_list = getObjbyName(e_list);
var id_arrow = getObjbyName(e_arrow);
if (id_list.style.display == "none") {
id_list.style.display = "block";
id_arrow.src = "menu-expanded.png";
id_arrow.alt = "Collapse";
}
else {
id_list.style.display = "none";
id_arrow.src = "menu-collapsed.png";
id_arrow.alt = "Expand";
}
return true;
}
......@@ -746,12 +746,13 @@ class Experiment
#
# Generate the table.
#
echo "<table align=center cellpadding=2 cellspacing=2 border=1>\n";
echo "<table align=center border=1>\n";
if (!$short) {
$thisurl = CreateURL("showexp", $this);
echo "<tr>
<td>Name: </td>
<td class=left>$eid</td>
<td class=left><a href='$thisurl'>$eid</a></td>
</tr>\n";
echo "<tr>
......@@ -1274,12 +1275,25 @@ function ShowExperimentList($type, $this_user, $object) {
}
function ShowExperimentList_internal($templates_only,
$type, $this_user, $object) {
$type, $this_user, $object,
$tabledefs = null) {
global $TB_EXPTSTATE_SWAPPED, $TB_EXPTSTATE_SWAPPING;
$from_idx = $this_user->uid_idx();
$nopid = 0;
$parens = 0;
$id = "explist";
$class = "explist";
$wanthtml = 0;
$notitle = FALSE;
if ($tabledefs) {
$id = (isset($tabledefs['#id']) ? $tabledefs['#id'] : $id);
$class = (isset($tabledefs['#class']) ? $tabledefs['#class'] : $class);
$html = (isset($tabledefs['#html']) ? $tabledefs['#html'] : $html);
$notitle = (isset($tabledefs['#notitle']) ?
$tabledefs['#notitle'] : $notitle);
}
if ($type == "USER") {
$uid = $object->uid();
......@@ -1338,12 +1352,15 @@ function ShowExperimentList_internal($templates_only,
}
if (mysql_num_rows($query_result)) {
if ($html)
ob_start();
echo "<center>
<h3>$title ".
($templates_only ? "Template Instances" : "Experiments") . "</h3>
</center>
<table align=center border=1 cellpadding=2
id='explist' cellspacing=2>\n";
<h3>$title ".
($templates_only ?
"Template Instances" : "Experiments") . "</h3>
</center>
<table align=center border=1 class=class id=$id>\n";
if ($nopid) {
$pidrow="";
......@@ -1422,9 +1439,14 @@ function ShowExperimentList_internal($templates_only,
}
echo "</ol></font></td></tr></table>\n";
echo "<script type='text/javascript' language='javascript'>
sorttable.makeSortable(getObjbyName('explist'));
</script>\n";
# Sort initialized later when page fully loaded.
AddSortedTable($id);
if ($html) {
$html = ob_get_contents();
ob_end_clean();
return $html;
}
}
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
......@@ -1344,4 +1344,103 @@ function ShowNodeHistory($node = null,
}
}
#
# Logged in users, show free node counts.
#
function ShowFreeNodes()
{
$freecounts = array();
# Get typelist and set freecounts to zero.
$query_result =
DBQueryFatal("select n.type from nodes as n ".
"left join node_types as nt on n.type=nt.type ".
"where (role='testnode') and class='pc' ");
while ($row = mysql_fetch_array($query_result)) {
$type = $row[0];
$freecounts[$type] = 0;
}
if (!count($freecounts)) {
return "";
}
# Get free totals by type.
$query_result =
DBQueryFatal("select n.eventstate,n.type,count(*) from nodes as n ".
"left join node_types as nt on n.type=nt.type ".
"left join reserved as r on r.node_id=n.node_id ".
"where (role='testnode') and class='pc' ".
" and r.pid is null and n.reserved_pid is null ".
"group BY n.eventstate,n.type");
while ($row = mysql_fetch_array($query_result)) {
$type = $row[1];
$count = $row[2];
# XXX Yeah, I'm a doofus and can't figure out how to do this in SQL.
if (($row[0] == TBDB_NODESTATE_ISUP) ||
($row[0] == TBDB_NODESTATE_PXEWAIT) ||
($row[0] == TBDB_NODESTATE_ALWAYSUP) ||
($row[0] == TBDB_NODESTATE_POWEROFF)) {
$freecounts[$type] = $count;
}
}
$output = "";
$freepcs = TBFreePCs();
$reloading = TBReloadingPCs();
$output .= "<table valign=top align=center width=100% height=100% border=1
cellspacing=1 cellpadding=0>
<tr><td nowrap colspan=6 class=usagefreenodes align=center>
<b>$freepcs Free PCs, $reloading reloading</b></td></tr>\n";
$pccount = count($freecounts);
$newrow = 1;
$maxcols = (int) ($pccount / 3);
if ($pccount % 3)
$maxcols++;
$cols = 0;
foreach($freecounts as $key => $value) {
$freecount = $freecounts[$key];
if ($newrow) {
$output .= "<tr>\n";
}
$output .= "<td class=usagefreenodes align=right>
<a target=_parent href=shownodetype.php3?node_type=$key>
$key</a></td>
<td class=usagefreenodes align=left>${freecount}</td>\n";
$cols++;
$newrow = 0;
if ($cols == $maxcols || $pccount <= 3) {
$cols = 0;
$newrow = 1;
}
if ($newrow) {
$output .= "</tr>\n";
}
}
if (! $newrow) {