fix: auto-select firmware after upload, guard flash button without selection

- Auto-select uploaded firmware immediately after upload completes
- Auto-select single firmware on list load (no manual click needed)
- Hide flash button and show warning when no firmware is selected
- Re-apply manifest on list reload to avoid stale state
- Restore warning banner on firmware delete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-05-19 05:39:23 +09:00
parent 3b7a28828d
commit 88094afe06
2 changed files with 43 additions and 22 deletions

View File

@@ -262,26 +262,33 @@
<div style="border-top:1px solid var(--border);padding-top:16px;margin-top:4px;"> <div style="border-top:1px solid var(--border);padding-top:16px;margin-top:4px;">
<div class="status-row" style="margin-bottom:12px;"> <div class="status-row" style="margin-bottom:12px;">
<span>💾</span> <span>💾</span>
<span id="selected-fw-info" style="font-size:14px;">선택된 펌웨어 없음 — 위 목록에서 선택하세요</span> <span id="selected-fw-info" style="font-size:14px;">선택된 펌웨어 없음 — 위 목록에서 클릭하여 선택하세요</span>
</div> </div>
<!-- <!-- 펌웨어 미선택 경고 -->
esp-web-install-button 웹 컴포넌트 <div id="no-fw-warning" class="alert alert-warn" style="margin-bottom:12px;">
manifest 속성에 백엔드 manifest URL을 동적으로 설정 <span></span>
펌웨어 선택 시 selectFirmware() 함수가 manifest를 업데이트 <div style="font-size:13px;">
--> <strong>펌웨어를 먼저 선택하세요.</strong>
<esp-web-install-button id="esp-install-btn"> 위 목록에서 플래시할 펌웨어를 클릭하면 이 버튼이 활성화됩니다.
<button </div>
slot="activate" </div>
class="btn btn-primary needs-serial"
style="width:100%;justify-content:center;padding:12px;" <!-- 플래시 버튼 (펌웨어 선택 후 표시) -->
> <div id="flash-btn-wrap" style="display:none;">
⚡ 플래시 실행 <esp-web-install-button id="esp-install-btn">
</button> <button
<span slot="unsupported" style="color:var(--danger);font-size:13px;"> slot="activate"
⚠ 이 브라우저는 Web Serial을 지원하지 않습니다 (Chrome/Edge 필요) class="btn btn-primary needs-serial"
</span> style="width:100%;justify-content:center;padding:12px;"
</esp-web-install-button> >
⚡ 플래시 실행
</button>
<span slot="unsupported" style="color:var(--danger);font-size:13px;">
⚠ 이 브라우저는 Web Serial을 지원하지 않습니다 (Chrome/Edge 필요)
</span>
</esp-web-install-button>
</div>
<div class="alert alert-warn" style="margin-top:14px;"> <div class="alert alert-warn" style="margin-top:14px;">
<span></span> <span></span>

View File

@@ -288,6 +288,7 @@ uploadForm.addEventListener('submit', async e => {
}); });
await loadFirmwareList(); await loadFirmwareList();
selectFirmware(data.id); // 업로드 직후 자동 선택
switchTab('tab-flash'); switchTab('tab-flash');
} catch (err) { } catch (err) {
progressPct.textContent = `${err.message}`; progressPct.textContent = `${err.message}`;
@@ -324,6 +325,8 @@ async function loadFirmwareList() {
const resp = await fetch(`${API}/api/firmware`); const resp = await fetch(`${API}/api/firmware`);
state.firmwareList = await resp.json(); state.firmwareList = await resp.json();
renderFwList(); renderFwList();
// 목록 로드 후 자동 선택 적용 (선택된 것이 있으면 manifest 재설정)
if (state.selectedFwId) selectFirmware(state.selectedFwId);
} catch (err) { } catch (err) {
log(`✗ 펌웨어 목록 로드 실패: ${err.message}`, 'err'); log(`✗ 펌웨어 목록 로드 실패: ${err.message}`, 'err');
} }
@@ -340,6 +343,11 @@ function renderFwList() {
return; return;
} }
// 선택된 펌웨어가 없고 하나만 있으면 자동 선택
if (!state.selectedFwId && state.firmwareList.length === 1) {
state.selectedFwId = state.firmwareList[0].id;
}
fwListEl.innerHTML = ''; fwListEl.innerHTML = '';
state.firmwareList.forEach(fw => { state.firmwareList.forEach(fw => {
const el = document.createElement('div'); const el = document.createElement('div');
@@ -379,10 +387,14 @@ function selectFirmware(id) {
const manifestUrl = `${location.origin}/api/firmware/${id}/manifest`; const manifestUrl = `${location.origin}/api/firmware/${id}/manifest`;
installBtn.setAttribute('manifest', manifestUrl); installBtn.setAttribute('manifest', manifestUrl);
$('#selected-fw-info').textContent = `선택됨: ${state.firmwareList.find(f=>f.id===id)?.name}`;
log(`✓ 플래시 대상 선택: ${state.firmwareList.find(f=>f.id===id)?.name}`, 'ok'); const fw = state.firmwareList.find(f => f.id === id);
log(` Manifest: ${manifestUrl}`, 'info'); $('#selected-fw-info').textContent = `선택됨: ${fw?.name}`;
$('#flash-btn-wrap').style.display = 'block';
$('#no-fw-warning').style.display = 'none';
log(`✓ 플래시 대상 선택: ${fw?.name}`, 'ok');
log(` Manifest URL: ${manifestUrl}`, 'info');
} }
async function deleteFirmware(id) { async function deleteFirmware(id) {
@@ -392,7 +404,9 @@ async function deleteFirmware(id) {
if (state.selectedFwId === id) { if (state.selectedFwId === id) {
state.selectedFwId = null; state.selectedFwId = null;
installBtn.removeAttribute('manifest'); installBtn.removeAttribute('manifest');
$('#selected-fw-info').textContent = '선택된 펌웨어 없음'; $('#selected-fw-info').textContent = '선택된 펌웨어 없음 — 위 목록에서 클릭하여 선택하세요';
$('#flash-btn-wrap').style.display = 'none';
$('#no-fw-warning').style.display = 'block';
} }
await loadFirmwareList(); await loadFirmwareList();
log(`✓ 펌웨어 삭제 완료`, 'ok'); log(`✓ 펌웨어 삭제 완료`, 'ok');