9f8d33c8b2b6bc61f6d02d781c4e02836f7099f9
max
  Fri Aug 21 02:05:42 2026 -0700
hgSession: new opt-in JavaScript "My Sessions" page; share gbModern.css with hgBlat. refs #38157

Applies the hgBlat facelift strategy (#37996) to hgSession: an opt-in,
client-rendered "My Sessions" page gated by the sessionNewPage /
sessionNewPageBanner hg.conf flags (mirroring blatNewForm / blatNewFormBanner),
with a banner linking between the classic and new pages so neither is a one-way
door. sessionNewPage also flips the site default.

hgSession.c stays the data/action backend: it emits the session list and page
config as an inline JSON global (hgSessionData) into an empty #sessionApp
container, and the new hgSession.js builds the UI - a save-current-view card
(name + optional description + "only I can load it"; empty name saves under a
random share_ name), a "most recently saved session" one-click Update, a
searchable/sortable/paged DataTable of sessions (assembly + position, created
with last-used on hover, views, a lock icon on private sessions), inline Share
(copy link / email / gallery), Edit (rename + description + private), Overwrite
and Delete, and a bulk Select -> Delete-all-selected mode.  The mutating actions
POST to new JSON endpoints (hgS_doDeleteJson / doShareJson / doGalleryJson /
doOverwriteJson / doDescribeJson) that run the same SQL as the classic full-page
handlers and return JSON, so the table updates in place; loads, file up/downloads
and custom-track backup stay as ordinary form submits/links.  The Advanced panel
keeps feature parity with the classic page (load another user's session, load
from URL/file, save to file, back up custom tracks, reset), minus the login/
change-password links that now live in the top menu.

Shared UCSC house-style components (design tokens, .gbPill, .gbCard, .gbStrip,
.gbSection, .gbShareBox, .gbBanner, the .gbModal* dialog and a .gbTable) are
factored into a new gbModern.css.  hgBlat is migrated onto it: its generic
.blat* classes are renamed to the shared .gb* names in hgBlat.css / hgBlat.js
and the #blatResults / #blatFormBox containers get class="gbApp"; verified
pixel-clean against the previous search form and results pages, including the
rename modal.  hgSession.css holds only session-specific layout.

diff --git src/hg/hgSession/hgSession.h src/hg/hgSession/hgSession.h
index f46c0336c92..a747b22f115 100644
--- src/hg/hgSession/hgSession.h
+++ src/hg/hgSession/hgSession.h
@@ -1,101 +1,110 @@
 /* hgSession - Manage information associated with a user identity. */
 
 /* Copyright (C) 2008 The Regents of the University of California 
  * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 
 #ifndef HGSESSION_H
 #define HGSESSION_H
 
 /* NOTE: some of the original contents have been moved up to cart.h for 
  * sharing with hgTracks. */
 
 #include "cart.h"
 
 /* Global variables - generally set during initialization and then read-only. */
 extern struct cart *cart;	/* This holds cgi and other variables between clicks. */
 extern char *database;		/* Current database, often but not always dbDatabase. */
 
 /* hgSession form inputs */
 #define hgsNewSessionName hgSessionPrefix "newSessionName"
 #define hgsNewSessionShare hgSessionPrefix "newSessionShare"
 #define hgsNewSessionDescription hgSessionPrefix "newSessionDescription"
 #define hgsDoNewSession hgSessionPrefix "doNewSession"
 
 // AJAX endpoint behind the "Share a link" menu button (see topLinks.js).  hgsShareAnon (when
 // set, or when no user is logged in) saves under the reserved anonymous user "l".
 #define hgsDoSaveSessionJson hgSessionPrefix "doSaveSessionJson"
 #define hgsShareAnon hgSessionPrefix "shareAnon"
 // Rename an existing session (hgsOldSessionName -> hgsNewSessionName) for the "Specify name" step.
 #define hgsDoRenameSessionJson hgSessionPrefix "doRenameSessionJson"
 
+// AJAX endpoints for the experimental client-rendered Sessions page (hgSession.js).  Each acts on
+// the session named by hgsOldSessionName (decoded) under the current user and returns JSON instead
+// of re-rendering the whole page.  All are covered by the hgsDo prefix in cleanHgSessionFromCart.
+#define hgsDoDeleteJson hgSessionPrefix "doDeleteJson"
+#define hgsDoShareJson hgSessionPrefix "doShareJson"
+#define hgsDoGalleryJson hgSessionPrefix "doGalleryJson"
+#define hgsDoOverwriteJson hgSessionPrefix "doOverwriteJson"
+#define hgsDoDescribeJson hgSessionPrefix "doDescribeJson"
+
 #define hgsSharePrefix hgSessionPrefix "share_"
 #define hgsGalleryPrefix hgSessionPrefix "gallery_"
 #define hgsEditPrefix hgSessionPrefix "edit_"
 #define hgsLoadPrefix hgSessionPrefix "load_"
 #define hgsDeletePrefix hgSessionPrefix "delete_"
 
 #define hgsShowDownloadPrefix hgSessionPrefix "showDownload_"
 #define hgsMakeDownloadPrefix hgSessionPrefix "makeDownload_"
 #define hgsDoDownloadPrefix hgSessionPrefix "doDownload_"
 
 #define hgsSaveLocalBackupFileName hgSessionPrefix "saveLocalBackupFileName"
 #define hgsSaveLocalFileName hgSessionPrefix "saveLocalFileName"
 #define hgsSaveLocalFileCompress hgSessionPrefix "saveLocalFileCompress"
 #define hgsDoSaveLocal hgSessionPrefix "doSaveLocal"
 
 #define hgsLoadLocalFileName hgSessionPrefix "loadLocalFileName"
 #define hgsDoLoadLocal hgSessionPrefix "doLoadLocal"
 
 #define hgsLoadUrlName hgSessionPrefix "loadUrlName"
 #define hgsDoLoadUrl hgSessionPrefix "doLoadUrl"
 
 #define hgsDoMainPage hgSessionPrefix "doMainPage"
 
 #define hgsDoSessionDetail hgSessionPrefix "doSessionDetail"
 #define hgsOldSessionName hgSessionPrefix "oldSessionName"
 #define hgsDoSessionChange hgSessionPrefix "doSessionChange"
 
 #define hgsCancel hgSessionPrefix "cancel"
 
 #define hgsDo hgSessionPrefix "do"
 
 // Non-UI reachable function to load a session and save it, for the purpose of moving files
 // and tables out of trash/customTrash into userdata/customData after sessionData* params are
 // added to hg.conf.
 #define hgsDoReSaveSession hgSessionPrefix "doReSaveSession"
 
 // Back-door CGI param to randomize the suffix (usually day of month) for sessionDataDbPrefix.
 // This is for bulk re-saving old sessions to move files and tables to safe storage;
 // we don't want all of the old sessions' tables to end up in the same day-of-month database.
 #define hgsSessionDataDbSuffix hgSessionPrefix "sessionDataDbSuffix"
 
 char *cgiDecodeClone(char *encStr);
 /* Allocate and return a CGI-decoded copy of encStr. */
 
 void startBackgroundWork(char *exec, char **pWorkUrl);
 /* deal with forking off child for background work
  * and setting up the trash file for communicating
  * from the child to the browser */
 
 void getBackgroundStatus(char *url);
 /* fetch status as the latest complete html block available.
  * fetch progress info instead if background proc still running. */
 
 // -----  htmlOpen 
 
 void htmlOpen(char *format, ...);
 /* Start up a page that will be in html format. */
 
 void htmlClose();
 /* Close down html format page. */
 
 void showDownloadSessionCtData(struct hashEl *downloadList);
 /* Show download page for the given session */
 
 void makeDownloadSessionCtData(char *param1, char *backgroundProgress);
 /* Download tables and data to save save in compressed archive. */
 
 void doDownloadSessionCtData(struct hashEl *downloadPathList);
 /* Download given table to browser to save. */
 
 #endif /* HGSESSION_H */