feat(velxio): improve teacher arduino toolbar, add expected_wiring template, and harden deployer board detection
- Add EXPECTED_WIRING block to set-arduino template and standalone expected-wiring feature in teacher content editor - Reposition reload button to the far left inline with status dot, and shorten status text to 'Siap' / 'Menghubungkan...' - Decouple transfer from save: replace 'Simpan ke Dokumen' with 'Pindahkan Hasil' and centralize document saving to top header save button - Dynamically detect board FQBN from circuit in DeployTab with arduino:avr:uno fallback
This commit is contained in:
parent
5429dc17f9
commit
e4ab058078
|
|
@ -5,10 +5,12 @@
|
|||
let {
|
||||
initialCode = '',
|
||||
initialCircuit = '',
|
||||
onTransfer,
|
||||
onSave
|
||||
}: {
|
||||
initialCode?: string;
|
||||
initialCircuit?: string;
|
||||
onTransfer?: (state: { code: string; circuit: string }) => void;
|
||||
onSave?: (state: { code: string; circuit: string }) => void;
|
||||
} = $props();
|
||||
|
||||
|
|
@ -63,17 +65,23 @@
|
|||
showFeedback('Dimuat ulang dari dokumen');
|
||||
}
|
||||
|
||||
function handleSave() {
|
||||
function handleTransfer() {
|
||||
const state = getCurrentState();
|
||||
if (!state) {
|
||||
showFeedback('Gagal membaca state simulator');
|
||||
return;
|
||||
}
|
||||
|
||||
if (onSave) {
|
||||
if (onTransfer) {
|
||||
onTransfer(state);
|
||||
} else if (onSave) {
|
||||
onSave(state);
|
||||
}
|
||||
showFeedback('Tersimpan ke dokumen!');
|
||||
showFeedback('Hasil dipindahkan ke editor');
|
||||
}
|
||||
|
||||
function handleSave() {
|
||||
handleTransfer();
|
||||
}
|
||||
|
||||
function showFeedback(msg: string) {
|
||||
|
|
@ -137,17 +145,7 @@
|
|||
|
||||
<div class="teacher-velxio-container">
|
||||
<div class="teacher-velxio-toolbar">
|
||||
<div class="toolbar-status">
|
||||
<span class="status-dot" class:ready={isReady}></span>
|
||||
<span class="status-text">
|
||||
{isReady ? 'Simulator Siap (Mode Lengkap)' : 'Menghubungkan Simulator...'}
|
||||
</span>
|
||||
{#if saveFeedback}
|
||||
<span class="save-feedback">{saveFeedback}</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="toolbar-actions">
|
||||
<div class="toolbar-left">
|
||||
<button
|
||||
type="button"
|
||||
class="toolbar-btn btn-reload"
|
||||
|
|
@ -163,19 +161,33 @@
|
|||
<span>Muat Ulang</span>
|
||||
</button>
|
||||
|
||||
<div class="toolbar-status">
|
||||
<span class="status-dot" class:ready={isReady}></span>
|
||||
<span class="status-text">
|
||||
{isReady ? 'Siap' : 'Menghubungkan...'}
|
||||
</span>
|
||||
{#if saveFeedback}
|
||||
<span class="save-feedback">{saveFeedback}</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toolbar-actions">
|
||||
<button
|
||||
type="button"
|
||||
class="toolbar-btn btn-save"
|
||||
onclick={handleSave}
|
||||
title="Simpan rangkaian dan kode saat ini langsung ke dokumen markdown"
|
||||
class="toolbar-btn btn-transfer"
|
||||
onclick={handleTransfer}
|
||||
title="Pindahkan rangkaian dan kode dari simulator ke dokumen editor"
|
||||
disabled={!isReady}
|
||||
>
|
||||
<svg class="icon" viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path>
|
||||
<polyline points="17 21 17 13 7 13 7 21"></polyline>
|
||||
<polyline points="7 3 7 8 15 8"></polyline>
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
||||
<polyline points="14 2 14 8 20 8"></polyline>
|
||||
<line x1="16" y1="13" x2="8" y2="13"></line>
|
||||
<line x1="16" y1="17" x2="8" y2="17"></line>
|
||||
<polyline points="10 9 9 9 8 9"></polyline>
|
||||
</svg>
|
||||
<span>Simpan ke Dokumen</span>
|
||||
<span>Pindahkan Hasil</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -215,6 +227,13 @@
|
|||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.toolbar-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.toolbar-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -292,13 +311,13 @@
|
|||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.btn-save {
|
||||
.btn-transfer {
|
||||
background: var(--color-primary, #0d6efd);
|
||||
color: #ffffff;
|
||||
border-color: var(--color-primary, #0d6efd);
|
||||
}
|
||||
|
||||
.btn-save:hover:not(:disabled) {
|
||||
.btn-transfer:hover:not(:disabled) {
|
||||
background: var(--color-primary-dark, #0a58ca);
|
||||
border-color: var(--color-primary-dark, #0a58ca);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,12 +163,21 @@
|
|||
deployMessage = 'Mengompilasi kode...';
|
||||
|
||||
let code = '';
|
||||
let boardFqbn = 'arduino:avr:uno';
|
||||
|
||||
if (velxioIframe) {
|
||||
const state = getVelxioState(velxioIframe);
|
||||
if (state?.code) {
|
||||
code = state.code;
|
||||
}
|
||||
if (state?.circuit) {
|
||||
try {
|
||||
const parsed = JSON.parse(state.circuit);
|
||||
if (parsed?.board) {
|
||||
boardFqbn = parsed.board;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
|
|
@ -179,7 +188,7 @@
|
|||
throw new Error('Tidak ada kode Arduino untuk di-deploy');
|
||||
}
|
||||
|
||||
const res = await getHexContent({ code, board_fqbn: 'arduino:avr:uno' });
|
||||
const res = await getHexContent({ code, board_fqbn: boardFqbn });
|
||||
|
||||
if (!res.success || !res.hex_content) {
|
||||
throw new Error(res.error || 'Kompilasi gagal');
|
||||
|
|
|
|||
|
|
@ -209,9 +209,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
async function handleSaveVelxioFromTab(state: { code: string; circuit: string }) {
|
||||
function handleTransferVelxioFromTab(state: { code: string; circuit: string }) {
|
||||
applyVelxioToBody(state.code, state.circuit);
|
||||
await mgr.handleSave();
|
||||
}
|
||||
|
||||
async function handleSaveAction() {
|
||||
|
|
@ -375,10 +374,40 @@
|
|||
'\n---EXPECTED_SERIAL_OUTPUT---\n' +
|
||||
'LED ON\nLED OFF\n' +
|
||||
'---END_EXPECTED_SERIAL_OUTPUT---\n' +
|
||||
'\n---EXPECTED_WIRING---\n' +
|
||||
'{\n' +
|
||||
' "wires": [\n' +
|
||||
' {\n' +
|
||||
' "start": { "componentId": "arduino-uno", "pinName": "13" },\n' +
|
||||
' "end": { "componentId": "led-builtin", "pinName": "A" }\n' +
|
||||
' },\n' +
|
||||
' {\n' +
|
||||
' "start": { "componentId": "arduino-uno", "pinName": "GND" },\n' +
|
||||
' "end": { "componentId": "led-builtin", "pinName": "C" }\n' +
|
||||
' }\n' +
|
||||
' ]\n' +
|
||||
'}\n' +
|
||||
'---END_EXPECTED_WIRING---\n' +
|
||||
'\n---KEY_TEXT---\n' +
|
||||
'kata_kunci\n' +
|
||||
'---END_KEY_TEXT---\n',
|
||||
},
|
||||
{
|
||||
id: 'expected-wiring',
|
||||
label: 'Expected Wiring',
|
||||
group: 'set_soal',
|
||||
snippet:
|
||||
'\n---EXPECTED_WIRING---\n' +
|
||||
'{\n' +
|
||||
' "wires": [\n' +
|
||||
' {\n' +
|
||||
' "start": { "componentId": "arduino-uno", "pinName": "13" },\n' +
|
||||
' "end": { "componentId": "led-builtin", "pinName": "A" }\n' +
|
||||
' }\n' +
|
||||
' ]\n' +
|
||||
'}\n' +
|
||||
'---END_EXPECTED_WIRING---\n',
|
||||
},
|
||||
{
|
||||
id: 'set-flowchart',
|
||||
label: 'Set Flowchart',
|
||||
|
|
@ -648,7 +677,7 @@
|
|||
{#snippet saveActions()}
|
||||
{#if mgr.activePath && !isAssetFile}
|
||||
<button class="panel-btn toolbar-toggle" class:active={featureSidebarOpen} onclick={() => featureSidebarOpen = !featureSidebarOpen} title="Tampilkan/sembunyikan panel Fitur">🧩</button>
|
||||
<button class="panel-btn save-btn" onclick={() => handleSaveAction()} disabled={mgr.saving || !mgr.dirty} title="Simpan">
|
||||
<button class="panel-btn save-btn" onclick={() => handleSaveAction()} disabled={mgr.saving || (!mgr.dirty && mgr.activeTab !== 'velxio')} title="Simpan">
|
||||
{mgr.saving ? '⏳' : '💾'}
|
||||
</button>
|
||||
<button class="panel-btn publish-btn" onclick={() => handlePublishAction()} disabled={mgr.publishing || !mgr.draftId} title="Publish">
|
||||
|
|
@ -870,7 +899,8 @@
|
|||
bind:this={velxioEditorRef}
|
||||
initialCode={extractedCodes.velxio}
|
||||
initialCircuit={extractedCircuitVelxio}
|
||||
onSave={handleSaveVelxioFromTab}
|
||||
onTransfer={handleTransferVelxioFromTab}
|
||||
onSave={handleTransferVelxioFromTab}
|
||||
/>
|
||||
</div>
|
||||
{:else if dynTab.id === 'flowchart'}
|
||||
|
|
|
|||
Loading…
Reference in New Issue