mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 20:49:41 +02:00
Merge pull request #368 from shenlvkang-collab/pr/mobile-add-case-submit
fix(mobile): give the Add Case modal a reachable submit button
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
---
|
||||
"aicodeman": patch
|
||||
---
|
||||
|
||||
fix(mobile): give the Add Case modal a reachable submit button
|
||||
|
||||
`mobile.css` hides `#createCaseModal`'s `.set-foot` on phones, and unlike the Settings
|
||||
modal that header carries no `set-head-save` — so the Create/Link button existed nowhere
|
||||
on a phone and the modal could not be submitted at all. Adds the header button and drives
|
||||
both together, so whichever one is pressed the other shows the same pending state and is
|
||||
equally unclickable.
|
||||
|
||||
Add Case follows the Settings modal's header-save pattern, so it picks up the existing
|
||||
`.set-head-actions:has(.set-head-save)` tray and `.set-head-save` sizing below 860px with no
|
||||
new CSS; the `mobile.css` comment that still listed Add Case as a lone-× sheet is updated to
|
||||
match.
|
||||
@@ -2589,8 +2589,15 @@
|
||||
<div class="modal-content modal-lg set-shell">
|
||||
<div class="modal-header set-shell-head">
|
||||
<h3>Add Case</h3>
|
||||
<!-- mobile.css hides this modal's .set-foot, so on a phone the footer's
|
||||
Create/Link button is unreachable and the modal cannot be submitted
|
||||
at all. Mirrors the Settings modal's header Save: close first in the
|
||||
DOM so the focus trap still lands on it, row-reverse puts this to
|
||||
its left. Both buttons are driven together by switchCaseModalTab()
|
||||
and submitCaseModal(). -->
|
||||
<div class="set-head-actions">
|
||||
<button class="modal-close" onclick="app.closeCreateCaseModal()" aria-label="Close create case">×</button>
|
||||
<button class="set-head-save" id="caseModalSubmitMobile" onclick="app.submitCaseModal()">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="set-body">
|
||||
|
||||
@@ -3333,8 +3333,10 @@ html:is([data-skin="paper-gray"], [data-skin="solarized-light"], [data-skin="cat
|
||||
recessed tray and matching pill geometry instead of reading as a fat
|
||||
accent pill parked beside a stray × glyph. Tray colors come from skin
|
||||
tokens, never a hardcoded black alpha, or the light skins get a grey slab.
|
||||
`:has()` keeps the tray off the two sheets that carry a lone × (Session
|
||||
Options and Add Case save from inside their own forms). */
|
||||
`:has()` keeps the tray off Session Options, the one sheet left carrying a
|
||||
lone × because it saves from inside its own per-section forms. Add Case
|
||||
now has a header save of its own (its footer is hidden below 860px, so
|
||||
that button is the only way to submit it there), and picks up the tray. */
|
||||
:is(#appSettingsModal, #sessionOptionsModal, #createCaseModal) .set-head-actions:has(.set-head-save) {
|
||||
padding: 3px;
|
||||
border: 1px solid var(--border);
|
||||
|
||||
@@ -2550,15 +2550,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'
|
||||
@@ -2568,6 +2572,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') {
|
||||
@@ -2588,14 +2596,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();
|
||||
@@ -2609,9 +2622,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];
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user