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 =
'