fix(mobile): give the Add Case modal a reachable submit button

mobile.css hides #createCaseModal's .set-foot below 860px, and that modal's
header — unlike Settings' — carries no set-head-save. So on a phone the
Create/Link button existed nowhere and the modal could not be submitted at all.

Adds the header button and drives both together through switchCaseModalTab()
and submitCaseModal(), so whichever one is pressed the other shows the same
pending state and is equally unclickable. Following the Settings pattern also
means Add Case picks up the existing .set-head-actions:has(.set-head-save) tray
and .set-head-save sizing with no new CSS; the mobile.css comment that still
listed Add Case as a lone-× sheet is corrected to match.
This commit is contained in:
shenlvkang-collab
2026-09-01 12:29:02 +08:00
parent e5c5d890aa
commit 5969a1df96
4 changed files with 55 additions and 15 deletions
+28 -13
View File
@@ -2416,15 +2416,19 @@ Object.assign(CodemanApp.prototype, {
// A switched-to panel starts at its own top.
const doc = document.getElementById('createCaseDoc');
if (doc) doc.scrollTop = 0;
// Update submit button (hide for manage tab)
const submitBtn = document.getElementById('caseModalSubmit');
// Update submit buttons (hide for manage tab). Two of them: mobile.css hides
// this modal's .set-foot, so phones submit through the header button instead.
const submitBtns = ['caseModalSubmit', 'caseModalSubmitMobile']
.map((id) => document.getElementById(id))
.filter(Boolean);
if (tabName === 'case-manage') {
submitBtn.style.display = 'none';
submitBtns.forEach((btn) => {
btn.style.display = 'none';
});
this.renderCaseManageList();
this.refreshDockerExports();
} else {
submitBtn.style.display = '';
submitBtn.textContent =
const label =
tabName === 'case-create'
? 'Create'
: tabName === 'case-clone'
@@ -2434,6 +2438,10 @@ Object.assign(CodemanApp.prototype, {
: tabName === 'case-docker'
? 'Link Docker'
: 'Link';
submitBtns.forEach((btn) => {
btn.style.display = '';
btn.textContent = label;
});
}
// Focus appropriate input
if (tabName === 'case-create') {
@@ -2454,14 +2462,19 @@ Object.assign(CodemanApp.prototype, {
},
async submitCaseModal() {
const btn = document.getElementById('caseModalSubmit');
const originalText = btn.textContent;
btn.classList.add('loading');
btn.textContent =
// Both submit buttons move together: whichever one the user pressed, the
// other must show the same pending state and be equally unclickable.
const btns = ['caseModalSubmit', 'caseModalSubmitMobile'].map((id) => document.getElementById(id)).filter(Boolean);
const originalText = btns.map((btn) => btn.textContent);
const pendingText =
this.caseModalTab === 'case-create' ? 'Creating...' : this.caseModalTab === 'case-clone' ? 'Cloning...' : 'Linking...';
// A clone holds this request open for minutes; without disabling the button a
// second click fires a second clone (the loser then fails on ALREADY_EXISTS).
btn.disabled = true;
btns.forEach((btn) => {
btn.classList.add('loading');
btn.textContent = pendingText;
btn.disabled = true;
});
try {
if (this.caseModalTab === 'case-create') {
await this.createCase();
@@ -2475,9 +2488,11 @@ Object.assign(CodemanApp.prototype, {
await this.linkCase();
}
} finally {
btn.classList.remove('loading');
btn.disabled = false;
btn.textContent = originalText;
btns.forEach((btn, index) => {
btn.classList.remove('loading');
btn.disabled = false;
btn.textContent = originalText[index];
});
}
},