7f2c71980d90f22204d7aa2ca39cc09eaaf47d97
jcasper
  Fri Jun 3 19:20:38 2016 -0700
Added session details button, plus code review changes refs #15312, #17439

diff --git src/hg/hgPublicSessions/hgPublicSessions.c src/hg/hgPublicSessions/hgPublicSessions.c
index 9d0b860..c42dc7f 100644
--- src/hg/hgPublicSessions/hgPublicSessions.c
+++ src/hg/hgPublicSessions/hgPublicSessions.c
@@ -11,32 +11,38 @@
 #include "htmshell.h"
 #include "web.h"
 #include "cheapcgi.h"
 #include "cart.h"
 #include "hui.h"
 #include "ra.h"
 #include "dystring.h"
 #include "hPrint.h"
 #include "hgConfig.h"
 #include "sessionThumbnail.h"
 
 struct galleryEntry
 /* Holds data for a single session in the gallery*/
     {
     struct galleryEntry *next;
-    char *userName, *realName, *sessionName, *settings, *db, *firstUse;
-    char *imgPath, *imgUri;
+    char *userName;
+    char *realName;
+    char *sessionName;
+    char *settings;
+    char *db;
+    char *firstUse;
+    char *imgPath;
+    char *imgUri;
     struct dyString *sessionUrl;
     unsigned long useCount;
     };
 
 /* Global Variables */
 struct cart *cart;             /* CGI and other variables */
 struct hash *oldVars = NULL;
 
 
 struct galleryEntry *galLoad(char **row)
 /* Load a session entry from a row.  A row consists of:
  * 0. gbMembers.realName
  * 1. namedSessionDb.userName
  * 2. gbMembers.idx
  * 3. namedSessionDb.sessionName
@@ -50,36 +56,44 @@
 AllocVar(ret);
 ret->realName = cloneString(row[0]);
 ret->userName = cloneString(row[1]);
 cgiDecodeFull(ret->userName, ret->userName, strlen(ret->userName));
 ret->sessionName = cloneString(row[3]);
 cgiDecodeFull(ret->sessionName, ret->sessionName, strlen(ret->sessionName));
 ret->sessionUrl = dyStringCreate("hgS_doOtherUser=submit&hgS_otherUserName=%s&hgS_otherUserSessionName=%s", row[1], row[3]);
 
 ret->imgPath = sessionThumbnailFilePath(row[2], row[3], row[7]);
 if (fileExists(ret->imgPath))
     ret->imgUri = sessionThumbnailFileUri(row[2], row[3], row[7]);
 else
     ret->imgUri = NULL;
 ret->useCount = sqlUnsignedLong(row[4]);
 ret->settings = cloneString(row[5]);
-dbIdx = strstr(row[6], "db=") + 3;
+if (startsWith("db=", row[6]))
+    dbIdx = row[6] + 3;
+else
+    dbIdx = strstr(row[6], "&db=") + 4;
+if (dbIdx != NULL)
+    {
     dbEnd = strchr(dbIdx, '&');
     if (dbEnd != NULL)
         ret->db = cloneStringZ(dbIdx, dbEnd-dbIdx);
     else
         ret->db = cloneString(dbIdx);
+    }
+else
+    ret->db = cloneString("n/a");
 ret->firstUse = cloneString(row[7]);
 char *spacePt = strchr(ret->firstUse, ' ');
 if (spacePt != NULL) *spacePt = '\0';
 return ret;
 }
 
 void deleteGallery (struct galleryEntry **pGal)
 /* Free all memory associated with a gallery entry */
 {
 struct galleryEntry *gal;
 if ((gal = *pGal) != NULL)
     {
     freeMem(gal->realName);
     freeMem(gal->userName);
     freeMem(gal->sessionName);
@@ -126,30 +140,33 @@
 {
 printf ("<link rel=\"stylesheet\" type=\"text/css\" "
         "href=\"https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css\">\n");
 printf ("<script type=\"text/javascript\" "
         "src=\"https://code.jquery.com/jquery-1.12.3.min.js\"></script>\n");
 printf ("<script type=\"text/javascript\" charset=\"utf8\" "
         "src=\"https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js\"></script>\n");
 }
 
 
 void galleryDisplay(struct galleryEntry *galList)
 /* Print a table containing the gallery data from galList */
 {
 struct galleryEntry *thisSession = galList;
 
+/* Hide the orderable columns and disable ordering on the visible columns
+ * https://datatables.net/reference/option/columnDefs for more info.
+ * Then set up the ordering drop-down menu */
 printf ("<script type=\"text/javascript\">"
 "$(document).ready(function () {\n"
 "    $('#sessionTable').DataTable({\"columnDefs\": [{\"visible\":false, \"targets\":[2,3]},\n"
 "                                                   {\"orderable\":false, \"targets\":[0,1]}\n"
 "                                                  ],\n"
 "                                       \"order\":[3,'desc']});\n"
 "} );\n"
 "function changeSort() {\n"
 "   var newSort = document.getElementById('sortMethod').value;\n"
 "   var theTable = $('#sessionTable').DataTable();\n"
 "   if (newSort == \"useDesc\") {theTable.order([3,'desc']).draw(); }\n"
 "   if (newSort == \"useAsc\") {theTable.order([3,'asc']).draw(); }\n"
 "   if (newSort == \"dateDesc\") {theTable.order([2,'desc']).draw(); }\n"
 "   if (newSort == \"dateAsc\") {theTable.order([2,'asc']).draw(); }\n"
 "}\n"
@@ -235,31 +252,32 @@
 cart = theCart;
 char *db = cartUsualString(cart, "db", hDefaultDb());
 cartWebStart(cart, db, "Public Sessions");
 
 doGalleryIncludes();
 
 printf("<p>Our users have marked the following sessions as being of "
     "interest to the community."
     "<br>See the <a href=\"../goldenPath/help/hgSessionHelp.html\" "
     "target=_blank>Sessions User's Guide</a> "
     "for more information on how to add your sessions to this page.<p/>\n");
 
 showGalleryTab();
 
 printf ("<p>You can adjust the settings for your own sessions on\n"
-    "the <a href=\"hgSession\">Sessions</a> page.\n</p>");
+    "the <a href=\"hgSession?%s\">Sessions</a> page.\n</p>",
+    cartSidUrlString(cart));
 
 cartWebEnd();
 }
 
 /* Null terminated list of CGI Variables we don't want to save
  * permanently. */
 char *excludeVars[] = {"Submit", "submit", NULL,};
 
 int main(int argc, char *argv[])
 /* Process command line. */
 {
 cgiSpoof(&argc, argv);
 cartEmptyShell(doMiddle, hUserCookie(), excludeVars, oldVars);
 return 0;
 }