changeset 171:705dabdc37d4

Move administration interface page to separate layout, to make things less cramped.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 27 Oct 2013 06:47:42 +0200
parents dffededcdd92
children 2359744b4087
files admin.inc.php admin.php admlogin.php fap.css index.php
diffstat 5 files changed, 501 insertions(+), 433 deletions(-) [+]
line wrap: on
line diff
--- a/admin.inc.php	Sun Oct 27 06:46:21 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,396 +0,0 @@
-<?
-//
-// FAPWeb Simple Demoparty System
-// Party administration page frontend module
-// (C) Copyright 2012-2013 Tecnic Software productions (TNSP)
-//
-$sessionType = "admin";
-require "majax.php";
-
-function stCreateSettingsData()
-{
-  $args = array();
-
-  if (($res = stExecSQL("SELECT * FROM settings")) !== FALSE)
-  {
-    foreach ($res as $item)
-    {
-      switch ($item["vtype"])
-      {
-        case VT_STR:
-        case VT_TEXT: $type = 0; break;
-        case VT_INT:  $type = 4; break;
-        case VT_BOOL: $type = 3; break;
-      }
-      $args[] = "\"".$item["key"]."\":".$type;
-    }
-  }
-
-  echo
-  "\n".
-  "function updateSettings()\n".
-  "{\n".
-  "  var args = makePostArgs({".implode(",", $args)."}, \"st\", \"\");\n".
-  "  sendPOSTRequest(\"action=update&type=settings&\"+args);\n".
-  "  return false;\n".
-  "}\n";
-}
-
-// Check if sessions are enabled
-if (!stChkSetting("admPassword"))
-{
-  echo "<h1>Oh noes, admin configuration not done!</h1>\n".
-  "<p>Better go and prod that, so you get to use the fine admin interface.</p>\n";
-}
-else
-if (!stAdmSessionAuth(FALSE))
-{
-  // Perform authentication if we are not in session already
-  echo
-    "<h1>Party admin login</h1>\n".
-    "<p>Please use illegal telepathy over HTTP to provide a password to enter the party administration systembolaget.</p>\n".
-    stGetFormStart("admlogin", "admlogin.php").
-    stGetFormHiddenInput("mode", "check")."\n".
-    stGetFormPasswordInput("admpass", "", "")."\n".
-    stGetFormSubmitInput("submit", "Login").
-    "</form>\n";
-}
-else
-{
-?>
-<script type="text/javascript">
-// <? stCreateSettingsData(); stCommonAJAX("admajax.php", "admlogout.php", FALSE); ?>
-
-
-function refreshItems(id,name,msgname)
-{
-  var msuccess = function(txt)
-  {
-    var nitem = document.getElementById(id);
-    nitem.innerHTML = txt;
-  }
-
-  sendPOSTRequest("action=get&type="+name, msuccess);
-}
-
-
-function deleteItem(id,prefix,type,func,dsc)
-{
-  var msuccess = function(txt)
-  {
-    var item = document.getElementById(prefix+id);
-    item.style.display = "none";
-    setTimeout(func, 50);
-  }
-
-  // Clearly mark the element when asking confirmation
-  var item = document.getElementById(prefix+id);
-  var tmp = item.style.background;
-  item.style.background = "red";
-
-  // Ask confirmation for deletion
-  if (confirm("Are you sure you want to delete "+dsc+" #"+id+"?"))
-  {
-    // Okay, delete
-    sendPOSTRequest("action=delete&type="+type+"&id="+id, msuccess);
-  }
-
-  // Restore background
-  item.style.background = tmp;
-}
-
-
-function refreshSettings()
-{
-  refreshItems("nsettings", "settings", "General settings");
-}
-
-
-function refreshNews()
-{
-  refreshItems("nnews", "news", "News list");
-}
-
-
-function refreshAttendees()
-{
-  refreshItems("nattendees", "attendees", "Attendees list");
-}
-
-
-function refreshVoters()
-{
-  refreshItems("nvoters", "voters", "Voters list");
-}
-
-
-function refreshCompos()
-{
-  refreshItems("ncompos", "compos", "Compo list");
-}
-
-
-function refreshEntries()
-{
-  refreshItems("nentries", "entries", "Entry list");
-}
-
-
-function addNews()
-{
-  var args = makePostArgs({"title":1,"text":1,"author":1}, "nn", "");
-
-  var msuccess = function(txt)
-  {
-    setTimeout("refreshNews();", 50);
-  }
-
-  if (args != "")
-    sendPOSTRequest("action=add&type=news&"+args, msuccess);
-
-  return false;
-}
-
-
-function deleteNews(id)
-{
-  deleteItem(id, "news", "news", "refreshNews();", "news item");
-}
-
-
-function addAttendee()
-{
-  var args = makePostArgs({"name":1,"groups":0,"oneliner":0,"email":0}, "ne", "x");
-
-  var msuccess = function(txt)
-  {
-    setTimeout("refreshAttendees();", 50);
-  }
-
-  if (args != "")
-    sendPOSTRequest("action=add&type=attendees&"+args, msuccess);
-
-  return false;
-}
-
-
-function deleteAttendee(id)
-{
-  deleteItem(id, "attendee", "attendees", "refreshAttendees();", "attendee");
-}
-
-
-function updateAttendee(id)
-{
-  var args = makePostArgs({"oneliner":0,"email":0,"active":3}, "at", id);
-
-  var msuccess = function(txt)
-  {
-    setTimeout("refreshAttendees();", 50);
-  }
-
-  if (args != "")
-    sendPOSTRequest("action=update&type=attendees&id="+id+"&"+args, msuccess);
-}
-
-
-function updateAttendee2(id)
-{
-  var elem = document.getElementById("atactive"+id);
-  if (elem && !elem.checked)
-  {
-    if (confirm("Are you sure you want deactivate vote ID #"+id+"?"))
-      updateAttendee(id);
-    else
-      setTimeout("refreshAttendees();", 50);
-  }
-  else
-    updateAttendee(id);
-}
-
-
-function addCompo()
-{
-  var args = makePostArgs({"name":1, "description":1}, "nc", "");
-
-  var msuccess = function(txt)
-  {
-    setTimeout("refreshCompos();", 50);
-  }
-
-  if (args != "")
-    sendPOSTRequest("action=add&type=compo&"+args, msuccess);
-  return false;
-}
-
-
-function updateCompo(id)
-{
-  var args = makePostArgs({"name":1, "description":1, "visible":3, "voting":3, "showAuthors":3}, "co", id);
-
-  if (args != "")
-    sendPOSTRequest("action=update&type=compo&id="+id+"&"+args);
-}
-
-
-function addEntry(id)
-{
-  var args = makePostArgs({"name":1, "author":1, "filename":0}, "ne", id);
-
-  var msuccess = function(txt)
-  {
-    setTimeout("refreshEntries();", 50);
-  }
-
-  if (args != "")
-    sendPOSTRequest("action=add&type=entry&compo_id="+id+"&"+args, msuccess);
-  return false;
-}
-
-
-function updateEntry(id)
-{
-  var args = makePostArgs({"name":1, "author":1, "filename":0, "compo_id":2}, "en", id);
-
-  var msuccess = function(txt)
-  {
-    setTimeout("refreshEntries();", 50);
-  }
-
-  if (args != "")
-    sendPOSTRequest("action=update&type=entry&id="+id+"&"+args, msuccess);
-}
-
-
-function deleteEntry(id)
-{
-  deleteItem(id, "entry", "entries", "refreshEntries();", "entry");
-}
-
-
-var registeredTabs = Object();
-
-
-function updateTabList()
-{
-  var item = document.getElementById("pageTabs");
-  var str = "";
-  for (var id in registeredTabs)
-  {
-    str += "<a id=\"cc"+id+
-      "\"href=\"#\" onClick=\"switchActiveTab('"+id+
-      "')\">"+registeredTabs[id]+"</a>";
-  }
-  
-  str += "<a class=\"admin\" href=\"admlogout.php\">Logout</a>";
-  
-  item.innerHTML = str;
-}
-
-
-function registerTab(id, name)
-{
-  registeredTabs[id] = name;
-}
-
-
-function refreshTabs()
-{
-  for (var id in registeredTabs)
-  {
-    setTimeout("refresh"+ registeredTabs[id] +"();", 10);
-  }
-}
-
-
-function switchActiveTab(tab)
-{
-  for (var id in registeredTabs)
-  {
-    var ob = document.getElementById(id);
-    var ccob = document.getElementById("cc"+id);
-    if (ob && ccob)
-    {
-      ob.style.display = (tab == id) ? "block" : "none";
-      ccob.style.borderTop = (tab == id) ? "4px solid white" : "none";
-      if (tab == id)
-      {
-        setTimeout("refresh"+ registeredTabs[id] +"();", 10);
-      }
-    }
-  }
-}
-</script>
-
-<!-- ========================== -->
-
-<div id="nstatus">-</div>
-
-<div id="pageTabs"></div>
-
-<!-- ========================== -->
-
-<div id="tabSettings">
-  <form method="post" action="" onsubmit="return updateSettings()">
-    <div id="nsettings"></div>
-  </form>
-</div>
-
-<!-- ========================== -->
-
-<div id="tabNews">
-  <form method="post" action="" onsubmit="return addNews()">
-    <input id="nntitle" type="text" size="40" /><br />
-    <textarea id="nntext" rows="5" cols="60"></textarea><br />
-    <input id="nnauthor" type="text" value="orgaz" />
-    <input id="nnadd" type="submit" value=" Add post " />
-    <input type="button" value=" Clear " onClick="this.form.reset()" />
-  </form>
-  <hr />
-  <div id="nnews"></div>
-</div>
-
-<!-- ========================== -->
-
-<div id="tabAttendees">
-  <div id="nattendees"></div>
-</div>
-
-<!-- ========================== -->
-
-<div id="tabVoters">
-  <div id="nvoters"></div>
-</div>
-
-<!-- ========================== -->
-
-<div id="tabCompos">
-  <form method="post" action="" onsubmit="return addCompo()">
-    <input id="ncname" type="text" size="64" /><br />
-    <textarea id="ncdescription" rows="5" cols="60"></textarea><br />
-    <input id="nccompo" type="submit" value=" Add compo " />
-    <input type="button" value=" Clear " onClick="this.form.reset()" />
-  </form>
-  <hr />
-  <div id="ncompos"></div>
-</div>
-
-<!-- ========================== -->
-
-<div id="tabEntries">
-  <div id="nentries"></div>
-</div>
-
-<!-- ========================== -->
-
-<script type="text/javascript">
-  registerTab("tabSettings", "Settings");
-  registerTab("tabNews", "News");
-  registerTab("tabAttendees", "Attendees");
-  registerTab("tabVoters", "Voters");
-  registerTab("tabCompos", "Compos");
-  registerTab("tabEntries", "Entries");
-  updateTabList();
-  switchActiveTab("tabSettings");
-</script>
-<? } ?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/admin.php	Sun Oct 27 06:47:42 2013 +0200
@@ -0,0 +1,445 @@
+<?
+//
+// FAPWeb Simple Demoparty System
+// Party administration page frontend module
+// (C) Copyright 2012-2013 Tecnic Software productions (TNSP)
+//
+$sessionType = "admin";
+require "mconfig.inc.php";
+require "msite.inc.php";
+require "mcommon.inc.php";
+require "msession.inc.php";
+require "majax.php";
+
+
+// Switch to https first, if needed
+if (!stCheckHTTPS())
+{
+  header("Location: https://".$_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"]);
+  exit;
+}
+
+// Start output
+cmPrintPageHeader("FAPWeb Administration",
+  " <meta http-equiv=\"Pragma\" content=\"no-cache\" />",
+  FALSE);
+
+echo "<div id=\"admCont\">\n";
+
+// Initiate SQL database connection
+if (!stConnectSQLDB())
+{
+  // Error occured, bail out early
+  cmPrintPageFooter();
+  exit;
+}
+
+// Fetch non-"hardcoded" settings from SQL database
+stReloadSettings();
+
+function stCreateSettingsData()
+{
+  $args = array();
+
+  if (($res = stExecSQL("SELECT * FROM settings")) !== FALSE)
+  {
+    foreach ($res as $item)
+    {
+      switch ($item["vtype"])
+      {
+        case VT_STR:
+        case VT_TEXT: $type = 0; break;
+        case VT_INT:  $type = 4; break;
+        case VT_BOOL: $type = 3; break;
+      }
+      $args[] = "\"".$item["key"]."\":".$type;
+    }
+  }
+
+  echo
+  "\n".
+  "function updateSettings()\n".
+  "{\n".
+  "  var args = makePostArgs({".implode(",", $args)."}, \"st\", \"\");\n".
+  "  sendPOSTRequest(\"action=update&type=settings&\"+args);\n".
+  "  return false;\n".
+  "}\n";
+}
+
+// Check if sessions are enabled
+if (!stChkSetting("admPassword"))
+{
+  echo
+    "<h1>Oh noes, admin configuration not done!</h1>\n".
+    "<p>Better go and prod that, so you get to use the fine admin interface.</p>\n";
+}
+else
+if (!stAdmSessionAuth(FALSE))
+{
+  // Perform authentication if we are not in session already
+  echo
+    "<h1>Party admin login</h1>\n".
+    "<p>Please use illegal telepathy over HTTP to provide a password to enter the party administration systembolaget.</p>\n".
+    stGetFormStart("admlogin", "admlogin.php").
+    stGetFormHiddenInput("mode", "check")."\n".
+    stGetFormPasswordInput("admpass", "", "")."\n".
+    stGetFormSubmitInput("submit", "Login").
+    "</form>\n";
+}
+else
+{
+?>
+<script type="text/javascript">
+// <? stCreateSettingsData(); stCommonAJAX("admajax.php", "admlogout.php", FALSE); ?>
+
+
+function refreshItems(id,name,msgname)
+{
+  var msuccess = function(txt)
+  {
+    var nitem = document.getElementById(id);
+    nitem.innerHTML = txt;
+  }
+
+  sendPOSTRequest("action=get&type="+name, msuccess);
+}
+
+
+function deleteItem(id,prefix,type,func,dsc)
+{
+  var msuccess = function(txt)
+  {
+    var item = document.getElementById(prefix+id);
+    item.style.display = "none";
+    setTimeout(func, 50);
+  }
+
+  // Clearly mark the element when asking confirmation
+  var item = document.getElementById(prefix+id);
+  var tmp = item.style.background;
+  item.style.background = "red";
+
+  // Ask confirmation for deletion
+  if (confirm("Are you sure you want to delete "+dsc+" #"+id+"?"))
+  {
+    // Okay, delete
+    sendPOSTRequest("action=delete&type="+type+"&id="+id, msuccess);
+  }
+
+  // Restore background
+  item.style.background = tmp;
+}
+
+
+function refreshSettings()
+{
+  refreshItems("nsettings", "settings", "General settings");
+}
+
+
+function refreshNews()
+{
+  refreshItems("nnews", "news", "News list");
+}
+
+
+function refreshAttendees()
+{
+  refreshItems("nattendees", "attendees", "Attendees list");
+}
+
+
+function refreshVoters()
+{
+  refreshItems("nvoters", "voters", "Voters list");
+}
+
+
+function refreshCompos()
+{
+  refreshItems("ncompos", "compos", "Compo list");
+}
+
+
+function refreshEntries()
+{
+  refreshItems("nentries", "entries", "Entry list");
+}
+
+
+function addNews()
+{
+  var args = makePostArgs({"title":1,"text":1,"author":1}, "nn", "");
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshNews();", 50);
+  }
+
+  if (args != "")
+    sendPOSTRequest("action=add&type=news&"+args, msuccess);
+
+  return false;
+}
+
+
+function deleteNews(id)
+{
+  deleteItem(id, "news", "news", "refreshNews();", "news item");
+}
+
+
+function addAttendee()
+{
+  var args = makePostArgs({"name":1,"groups":0,"oneliner":0,"email":0}, "ne", "x");
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshAttendees();", 50);
+  }
+
+  if (args != "")
+    sendPOSTRequest("action=add&type=attendees&"+args, msuccess);
+
+  return false;
+}
+
+
+function deleteAttendee(id)
+{
+  deleteItem(id, "attendee", "attendees", "refreshAttendees();", "attendee");
+}
+
+
+function updateAttendee(id)
+{
+  var args = makePostArgs({"oneliner":0,"email":0,"active":3}, "at", id);
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshAttendees();", 50);
+  }
+
+  if (args != "")
+    sendPOSTRequest("action=update&type=attendees&id="+id+"&"+args, msuccess);
+}
+
+
+function updateAttendee2(id)
+{
+  var elem = document.getElementById("atactive"+id);
+  if (elem && !elem.checked)
+  {
+    if (confirm("Are you sure you want deactivate vote ID #"+id+"?"))
+      updateAttendee(id);
+    else
+      setTimeout("refreshAttendees();", 50);
+  }
+  else
+    updateAttendee(id);
+}
+
+
+function addCompo()
+{
+  var args = makePostArgs({"name":1, "description":1}, "nc", "");
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshCompos();", 50);
+  }
+
+  if (args != "")
+    sendPOSTRequest("action=add&type=compo&"+args, msuccess);
+  return false;
+}
+
+
+function updateCompo(id)
+{
+  var args = makePostArgs({"name":1, "description":1, "visible":3, "voting":3, "showAuthors":3}, "co", id);
+
+  if (args != "")
+    sendPOSTRequest("action=update&type=compo&id="+id+"&"+args);
+}
+
+
+function addEntry(id)
+{
+  var args = makePostArgs({"name":1, "author":1, "filename":0}, "ne", id);
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshEntries();", 50);
+  }
+
+  if (args != "")
+    sendPOSTRequest("action=add&type=entry&compo_id="+id+"&"+args, msuccess);
+  return false;
+}
+
+
+function updateEntry(id)
+{
+  var args = makePostArgs({"name":1, "author":1, "filename":0, "compo_id":2}, "en", id);
+
+  var msuccess = function(txt)
+  {
+    setTimeout("refreshEntries();", 50);
+  }
+
+  if (args != "")
+    sendPOSTRequest("action=update&type=entry&id="+id+"&"+args, msuccess);
+}
+
+
+function deleteEntry(id)
+{
+  deleteItem(id, "entry", "entries", "refreshEntries();", "entry");
+}
+
+
+var registeredTabs = Object();
+
+
+function updateTabList()
+{
+  var item = document.getElementById("pageTabs");
+  var str = "";
+  for (var id in registeredTabs)
+  {
+    str += "<a id=\"cc"+id+
+      "\"href=\"#\" onClick=\"switchActiveTab('"+id+
+      "')\">"+registeredTabs[id]+"</a>";
+  }
+  
+  str += "<a class=\"admin\" href=\"admlogout.php\">Logout</a>";
+  
+  item.innerHTML = str;
+}
+
+
+function registerTab(id, name)
+{
+  registeredTabs[id] = name;
+}
+
+
+function refreshTabs()
+{
+  for (var id in registeredTabs)
+  {
+    setTimeout("refresh"+ registeredTabs[id] +"();", 10);
+  }
+}
+
+
+function switchActiveTab(tab)
+{
+  for (var id in registeredTabs)
+  {
+    var ob = document.getElementById(id);
+    var ccob = document.getElementById("cc"+id);
+    if (ob && ccob)
+    {
+      ob.style.display = (tab == id) ? "block" : "none";
+      ccob.style.borderTop = (tab == id) ? "4px solid white" : "none";
+      if (tab == id)
+      {
+        setTimeout("refresh"+ registeredTabs[id] +"();", 10);
+      }
+    }
+  }
+}
+</script>
+
+<!-- ========================== -->
+
+<div id="nstatus">-</div>
+
+<div id="pageTabs"></div>
+
+<div id="admin">
+<div>
+
+<!-- ========================== -->
+
+<div id="tabSettings">
+  <form method="post" action="" onsubmit="return updateSettings()">
+    <div id="nsettings"></div>
+  </form>
+</div>
+
+<!-- ========================== -->
+
+<div id="tabNews">
+  <form method="post" action="" onsubmit="return addNews()">
+    <input id="nntitle" type="text" size="40" /><br />
+    <textarea id="nntext" rows="5" cols="60"></textarea><br />
+    <input id="nnauthor" type="text" value="orgaz" />
+    <input id="nnadd" type="submit" value=" Add post " />
+    <input type="button" value=" Clear " onClick="this.form.reset()" />
+  </form>
+  <hr />
+  <div id="nnews"></div>
+</div>
+
+<!-- ========================== -->
+
+<div id="tabAttendees">
+  <div id="nattendees"></div>
+</div>
+
+<!-- ========================== -->
+
+<div id="tabVoters">
+  <div id="nvoters"></div>
+</div>
+
+<!-- ========================== -->
+
+<div id="tabCompos">
+  <form method="post" action="" onsubmit="return addCompo()">
+    <input id="ncname" type="text" size="64" /><br />
+    <textarea id="ncdescription" rows="5" cols="60"></textarea><br />
+    <input id="nccompo" type="submit" value=" Add compo " />
+    <input type="button" value=" Clear " onClick="this.form.reset()" />
+  </form>
+  <hr />
+  <div id="ncompos"></div>
+</div>
+
+<!-- ========================== -->
+
+<div id="tabEntries">
+  <div id="nentries"></div>
+</div>
+
+<!-- ========================== -->
+
+<div id="tabInfo">
+  <div id="ninfo"></div>
+</div>
+
+<!-- ========================== -->
+
+</div>
+</div>
+
+<script type="text/javascript">
+  registerTab("tabSettings", "Settings");
+  registerTab("tabNews", "News");
+  registerTab("tabAttendees", "Attendees");
+  registerTab("tabVoters", "Voters");
+  registerTab("tabCompos", "Compos");
+  registerTab("tabEntries", "Entries");
+  registerTab("tabInfo", "Party Info");
+  updateTabList();
+  switchActiveTab("tabSettings");
+</script>
+<?
+}
+
+cmPrintPageFooter();
+
+?>
\ No newline at end of file
--- a/admlogin.php	Sun Oct 27 06:46:21 2013 +0200
+++ b/admlogin.php	Sun Oct 27 06:47:42 2013 +0200
@@ -29,5 +29,5 @@
   error_log("Admin session AUTH LOGIN failed (password)");
 }
 
-header("Location: admin");
+header("Location: admin.php");
 ?>
\ No newline at end of file
--- a/fap.css	Sun Oct 27 06:46:21 2013 +0200
+++ b/fap.css	Sun Oct 27 06:47:42 2013 +0200
@@ -1,7 +1,3 @@
-/*
-	http://colorschemedesigner.com/#0351ZuJm6iKUB
-*/
-
 html {
 	-webkit-backface-visibility: hidden;
 }
@@ -9,7 +5,7 @@
 body {
 	font-family: monospace;
 	font-size: 12pt;
-	color: black;
+	color: #0f0;
 	margin: 0px;
 	padding: 0px;
 	background: black url(img/grid.png);
@@ -223,7 +219,7 @@
 	color: white;
 }
 
-#maincontent > div {
+#maincontent > div, #admin > div {
 	width: 100%;
 	height: 100%;
 	overflow-y: auto;
@@ -331,35 +327,6 @@
 	color: red;
 }
 
-#pageTabs {
-	margin-top: 10pt;
-	margin-bottom: 0px;
-	border-bottom: 5pt solid #595F23;
-}
-
-#pageTabs a {
-	text-decoration: none;
-	padding: 5pt;
-	margin: 5pt;
-	background: #595F23;
-	text-shadow: 2px 2px 1px rgba(0,0,0,0.4);
-	border-top-left-radius: 5pt;
-	border-top-right-radius: 5pt;
-}
-
-#pageTabs a:hover {
-	background: #C8D286;
-}
-
-#pageTabs a:active {
-	background: #C8D286;
-}
-
-#pageTabs a.admin {
-	position: relative;
-	right: -2em;
-}
-
 table.vote th.vvalue {
 	width: 1%;
 	min-width: 2.5em;
@@ -477,3 +444,55 @@
 	text-align: left;
 }
 
+
+
+#pageTabs {
+	margin-top: 10pt;
+	margin-bottom: 0px;
+	border-bottom: 5pt solid #595F23;
+}
+
+#pageTabs a {
+	text-decoration: none;
+	padding: 5pt;
+	margin: 5pt;
+	background: #595F23;
+	text-shadow: 2px 2px 1px rgba(0,0,0,0.4);
+	border-top-left-radius: 5pt;
+	border-top-right-radius: 5pt;
+}
+
+#pageTabs a:hover {
+	background: #C8D286;
+}
+
+#pageTabs a:active {
+	background: #C8D286;
+}
+
+#pageTabs a.admin {
+	position: relative;
+	right: -2em;
+}
+
+#admCont {
+	position: absolute;
+	top: 1em;
+	bottom: 1em;
+	left: 1em;
+	right: 1em;
+	padding: 1em;
+	border-radius: 10pt;
+	box-shadow: 2px 2px 4px rgba(0,255,0,0.5) inset, -2px -2px 4px rgba(0,255,0,0.5) inset;
+	background: rgba(0,0,0,0.7);
+}
+
+#admin {
+	position: absolute;
+	left: 0em;
+	right: 0em;
+	top: 4em;
+	bottom: 0em;
+	padding: 1em;
+	margin: 0px;
+}
--- a/index.php	Sun Oct 27 06:46:21 2013 +0200
+++ b/index.php	Sun Oct 27 06:47:42 2013 +0200
@@ -70,7 +70,7 @@
 echo "  <a href=\"results\">Results</a>\n";
 
 if ($visibility || stGetSetting("showAdmin"))
-echo "  <a href=\"admin\">Admin</a>\n";
+echo "  <a href=\"admin.php\">Admin</a>\n";
 ?>
   <? echo stGetSetting("siteMenuFooter") ?>
 </div>