0cdd15681f10789132dc9e88fcf4be23bd47ee4b max Wed Sep 9 09:14:37 2026 -0700 New Sessions page: Replace on the save card keeps the session's sharing level Confirming Replace re-saved through the save endpoint, which always writes a session as shared by link. Replacing a session that was in the public listing took it off the list, and replacing a private one made it loadable by anyone with the link. Replace now goes through the overwrite endpoint, which reads the row's sharing level and keeps it - the same endpoint the floppy button on each table row already uses. The description and the "only I can load it" box on the save card are still applied afterwards, refs #38311 diff --git src/hg/js/hgSession.js src/hg/js/hgSession.js index 0ed45401fa3..15160be5b58 100644 --- src/hg/js/hgSession.js +++ src/hg/js/hgSession.js @@ -486,41 +486,41 @@ var rand = sessRandomShareName(); sessConfirm({ title: 'Save without a name?', bodyHtml: 'You left the session name empty. Your session will be saved under the ' + 'randomly generated name ' + sessEnc(rand) + '.

You can also create ' + 'these quick share links any time from the Share a link option at the top ' + 'right of every Genome Browser page.', okLabel: 'Save session', onOk: function() { sessModalClose(); sessDoSaveWithName(rand); } }); return; } sessDoSaveWithName(name); } -function sessDoSaveWithName(name, allowOverwrite) { +function sessDoSaveWithName(name) { var priv = document.getElementById('sessSavePrivate').checked; var descEl = document.getElementById('sessSaveDesc'); var desc = descEl ? descEl.value.trim() : ''; var p = {}; p[SESS_ACT.save] = '1'; p[SESS_P.newName] = name; // Saving under a name you are already using replaces that session's contents, so ask first. // With failIfExists set the CGI answers {exists: true} instead of saving, which is how the // top-right "Share a link" menu handles the same collision. - if (!allowOverwrite) { p[SESS_P.failIfExists] = '1'; } + p[SESS_P.failIfExists] = '1'; // doSaveSessionJson always saves shared-by-link (the default); chain the optional description // and, if the user asked for "only I can load it", make it private, then reload to show the row. // The session is saved by the time those run, so a failure in one of them has to be reported: a // silent reload would leave a session sitting there shared by link, or with no description, and // tell the user nothing. function reload() { window.location.reload(); } function partlySaved(problem) { sessAlert('Session saved, with a problem', 'Your session ' + sessEnc(name) + ' was saved, but ' + sessEnc(problem), reload); } function afterDesc() { if (!priv) { reload(); return; } var sp = {}; @@ -530,39 +530,51 @@ sessAjax(sp, reload, function(m) { partlySaved('it could not be made private, so anyone with the link can still load it. ' + m); }); } function afterSave() { if (!desc) { afterDesc(); return; } var dp = {}; dp[SESS_ACT.describe] = '1'; dp[SESS_P.oldName] = name; dp[SESS_P.descr] = desc; sessAjax(dp, afterDesc, function(m) { partlySaved('the description could not be saved. ' + m); }); } + function replace() { + // Replace goes through the overwrite endpoint rather than saving again. A save always + // writes the session as shared by link, which would take a session out of the public + // gallery, or make a private one loadable by anyone holding the link. Overwrite keeps + // whatever sharing level the session already had, and the chained steps below still apply + // the description and the "only I can load it" box if the user set them. + var op = {}; + op[SESS_ACT.overwrite] = '1'; + op[SESS_P.oldName] = name; + sessAjax(op, afterSave); + } sessAjax(p, function(resp) { if (resp && resp.exists) { sessConfirm({ title: 'Replace this session?', bodyHtml: 'You already have a session named ' + sessEnc(name) + '. Replacing ' + 'it points that name at the view you are looking at now, and what the session ' + - 'held before is gone.', + 'held before is gone.' + + (priv ? '' : ' Who can load it stays as it is.'), okLabel: 'Replace it', - onOk: function() { sessModalClose(); sessDoSaveWithName(name, true); } + onOk: function() { sessModalClose(); replace(); } }); return; } afterSave(); }); } // ---- Advanced panel (navigation forms) ---------------------------------- function sessAdvancedHtml(C) { var sid = ''; var loadUser = ''; if (C.loggedIn) { loadUser = '
Load another user’s session' +