c5a326f3cc42beca0b59c284a2819763548c166a max Wed Jul 8 05:31:13 2026 -0700 Add top-right "Share a link" and "Login" links to the menu bar, refs #10138 New js/topLinks.js drives two links at the top-right of the menu bar on all pages: - Login: links to the login page when logged out; when logged in it shows the username and opens an account dialog (My Sessions / My Custom Tracks / My Track Hubs, change password, sign out). - Share a link: on hgTracks, one click saves the current view as a session and shows a copyable short link, with an optional "Specify name" rename step; works logged-in or anonymously (reserved user "l"). On hgTrackUi and the hgc/hgGene item-details popup it instead shares the page URL with the hgsid stripped and the db argument kept. hgSession gains two JSON endpoints (hgS_doSaveSessionJson, hgS_doRenameSessionJson) that reuse saveCartAsSession() and addSessionLink(). The menu bar is patched in lib/web.c (CGI pages) and hgMenubar.c (static pages) via comment placeholders in globalNavBar.inc. On narrow/phone screens the links collapse into a menu icon with a dropdown so they no longer overlap the menu. diff --git src/hg/hgMenubar/hgMenubar.c src/hg/hgMenubar/hgMenubar.c index 2ae5fca7093..f3fcc977176 100644 --- src/hg/hgMenubar/hgMenubar.c +++ src/hg/hgMenubar/hgMenubar.c @@ -1,72 +1,111 @@ /* * This CGI is used by static html pages to show a menu bar. * On an Apache with activated SSI, a html statement like * * will include the menu bar into a static page. */ #include "common.h" #include "cheapcgi.h" #include "dystring.h" #include "filePath.h" #include "linefile.h" #include "jsHelper.h" +#include "wikiLink.h" #define CGI_NAME "cgi-bin/hgMenubar" #define NAVBAR_INC_PATH "/inc/globalNavBar.inc" #define OLD_HREF "href=\"../" char* errMessage; +char *loginLinkHtml() +/* Return HTML
  • for the top-right Login menu item, or "" if no login system is configured. + * Static-page variant: the logged-out link uses href="../cgi-bin/hgSession" so the caller's + * OLD_HREF substitution rewrites it to a page-relative path; logged-in account-dialog URLs come + * from wikiLink and are absolute. topLinks.js turns the logged-in item into a dialog. */ +{ +if (!(loginSystemEnabled() || wikiLinkEnabled())) + return cloneString(""); +struct dyString *dy = dyStringNew(512); +char *userName = wikiLinkUserName(); +if (userName == NULL) + { + // Link straight to the login page (absolute URL from wikiLink), not through hgSession. + char *loginUrl = wikiLinkUserLoginUrl(""); + dyStringPrintf(dy, "Login", loginUrl); + } +else + { + // No hgsid available on static pages; the logout return URL simply omits it. + char *logoutUrl = wikiLinkUserLogoutUrl(""); + char *changePwUrl = wikiLinkChangePasswordUrl(""); + dyStringPrintf(dy, "%s", + userName, logoutUrl, changePwUrl ? changePwUrl : "", userName); + } +return dyStringCannibalize(&dy); +} + char *incFilePath(char *cgiPath, char *filePath, char *docRoot) /* Replace CGI_NAME in cgiPath with docRoot/filePath. filePath must begin with "/" eg "/inc/..." */ { char *incPath = replaceChars(cgiPath, "/"CGI_NAME, filePath); return catTwoStrings(docRoot, incPath); } void printIncludes(char* baseDir) { printf ("\n"); printf ("\n", baseDir); printf ("\n", baseDir); printf("\n", baseDir); +printf("\n", baseDir); printf ("\n", baseDir); } void printMenuBar(char *cgiPath, char *docRoot, char *pagePath, char *filePath) { char *navBarLoc = incFilePath(cgiPath, filePath, docRoot); struct lineFile *menuFile = lineFileOpen(navBarLoc, TRUE); char* oldLine = NULL; int lineSize = 0; char *cgiContainerPath = replaceChars(cgiPath, CGI_NAME, ""); char *newPath = makeRelativePath(pagePath, cgiContainerPath); char *newHref = catTwoStrings("href=\"", newPath); printf ("Content-type: text/html\r\n\r\n"); if (sameString(filePath, NAVBAR_INC_PATH)) printIncludes(newPath); while (lineFileNext(menuFile, &oldLine, &lineSize)) { // Not quite as robust as perl search and replace - no variable whitespace handling // Also lots of memory leakage - every line is reallocated and forgotten - char *newLine = replaceChars(oldLine, OLD_HREF, newHref); + char *line = oldLine; + // Fill the top-right link placeholders. Login shows the user or a link to hgSession; + // the Share-a-link button is browser-only, so it is dropped on static pages. + if (stringIn("", line)) + line = replaceChars(line, "", loginLinkHtml()); + if (stringIn("", line)) + line = replaceChars(line, "", ""); + char *newLine = replaceChars(line, OLD_HREF, newHref); printf("%s\n", newLine); } lineFileClose(&menuFile); // links to hgTracks need to use the web browser width and set the hgTracks image // size in pixels correctly to match the hgGateway "GO" button jsInline("$(\"#tools1 ul li a\").each( function (a) {\n" " if (this.href && this.href.indexOf(\"hgTracks\") !== -1) {\n" " var obj = this;\n" " obj.onclick = function(e) {\n" " var pix = calculateHgTracksWidth();\n" " e.currentTarget.href += \"&pix=\" + pix;\n" " }\n" " }\n" "});\n");