mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 14:39:42 +02:00
fix(docker): pre-fill the copied case instead of blanking two fields
The previous version cleared the case name and the in-container directory on the
grounds that they must differ. That left a form with three fields mysteriously
filled and two empty, and turned the most common operation — changing
/srv/app/api to /srv/app/web — into retyping a long path.
Both are now pre-filled, with focus on the in-container directory and the caret
at the end, since the tail is what changes. What stops an unmodified submit is no
longer an empty field but a guard: the values applied are recorded, compared at
submit time, and if nothing changed the reason is stated next to the field and
focus moves to it, without sending a request that is certain to be refused.
The server refuses these anyway (a duplicate case name, a twin case on the same
container and directory) and its errors are clear; but making a round trip to be
told "you forgot to edit the field you are looking at" is worse than saying so on
the spot. The guard only applies when a source case was actually selected, so
filling the adopt form from scratch is unaffected.
⚠️ The status text is written into dockerLinkStatus. My first version referenced
an id that does not exist (dockerAdoptStatus), which made the explanation vanish
silently and left only a toast. The test now extracts that id from the code and
looks it up in index.html, pinning that it must really exist.
(cherry picked from commit ba21ae11f4)
This commit is contained in:
committed by
Codeman maintainer
parent
7a5543da09
commit
025f061383
@@ -3210,6 +3210,7 @@ Object.assign(CodemanApp.prototype, {
|
||||
option.dataset.container = c.docker.container;
|
||||
option.dataset.hostId = c.docker.hostId;
|
||||
option.dataset.path = c.docker.path;
|
||||
option.dataset.workdir = c.docker.containerWorkdir || c.docker.path;
|
||||
select.appendChild(option);
|
||||
}
|
||||
// Nothing to duplicate yet: an empty picker is noise on the first adoption.
|
||||
@@ -3236,9 +3237,49 @@ Object.assign(CodemanApp.prototype, {
|
||||
set('dockerContainerName', option.dataset.container);
|
||||
set('dockerHostId', option.dataset.hostId);
|
||||
set('dockerWorkspacePath', option.dataset.path);
|
||||
set('dockerCaseName', '');
|
||||
set('dockerAdoptWorkdir', '');
|
||||
document.getElementById('dockerAdoptWorkdir')?.focus();
|
||||
// Pre-filled, NOT cleared: these two must differ from the source, but editing
|
||||
// `/srv/app/api` into `/srv/app/web` beats retyping a long path, and the same
|
||||
// goes for the name. What keeps a duplicate from being submitted unchanged is
|
||||
// the guard below (dockerCloneGuard), which is a better trade than an empty
|
||||
// field: the form stays a starting point instead of a blank form with three
|
||||
// fields mysteriously filled in.
|
||||
set('dockerCaseName', option.value);
|
||||
set('dockerAdoptWorkdir', option.dataset.workdir);
|
||||
// Remembered so the guard can tell "unchanged" from "happens to look similar".
|
||||
select.dataset.appliedName = option.value;
|
||||
select.dataset.appliedWorkdir = option.dataset.workdir || '';
|
||||
const workdir = document.getElementById('dockerAdoptWorkdir');
|
||||
workdir?.focus();
|
||||
// Caret at the end: the tail is the part that changes.
|
||||
if (workdir) workdir.setSelectionRange(workdir.value.length, workdir.value.length);
|
||||
},
|
||||
|
||||
/**
|
||||
* Refuse a duplicate that still carries the source case's name or directory.
|
||||
*
|
||||
* Both are pre-filled so they can be EDITED, which means both can also be left
|
||||
* alone by accident. The server refuses either (an existing case name, or an
|
||||
* exact same-container-same-directory twin) with a clear message, but a
|
||||
* round-trip to be told "you forgot to change the field you were looking at" is
|
||||
* worse than saying so here, next to the field, before anything is sent.
|
||||
*
|
||||
* Returns the offending element, or null when the form is fine.
|
||||
*/
|
||||
dockerCloneGuard() {
|
||||
const select = document.getElementById('dockerAdoptCloneFrom');
|
||||
if (!select || !select.value) return null;
|
||||
const name = document.getElementById('dockerCaseName');
|
||||
const workdir = document.getElementById('dockerAdoptWorkdir');
|
||||
if (name && name.value.trim() === (select.dataset.appliedName || '')) {
|
||||
return { el: name, message: `"${name.value.trim()}" is the case you copied from — give this one a new name.` };
|
||||
}
|
||||
if (workdir && workdir.value.trim() === (select.dataset.appliedWorkdir || '')) {
|
||||
return {
|
||||
el: workdir,
|
||||
message: 'Same container and same directory as the case you copied from — point this one at another directory.',
|
||||
};
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
async _loadDockerContainerOptions() {
|
||||
@@ -3341,6 +3382,17 @@ Object.assign(CodemanApp.prototype, {
|
||||
this.showToast('Enter the name of the running container to attach to', 'error');
|
||||
return;
|
||||
}
|
||||
// A duplicate that still carries the source's name or directory: say so here,
|
||||
// beside the field, rather than sending a request certain to come back refused.
|
||||
const cloneIssue = adopting ? this.dockerCloneGuard() : null;
|
||||
if (cloneIssue) {
|
||||
this.showToast(cloneIssue.message, 'error');
|
||||
const statusEl = document.getElementById('dockerLinkStatus');
|
||||
if (statusEl) statusEl.textContent = cloneIssue.message;
|
||||
cloneIssue.el.focus();
|
||||
cloneIssue.el.select?.();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (statusEl) {
|
||||
|
||||
Reference in New Issue
Block a user