Merge feat/csv-example-download: downloadable CSV example link

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMHQTtnQtQqL8muAXHr9kd
This commit is contained in:
2026-07-02 09:09:08 +07:00
2 changed files with 35 additions and 1 deletions
+18
View File
@@ -221,6 +221,24 @@
color: var(--fg-faint); color: var(--fg-faint);
} }
.link-btn {
appearance: none;
background: transparent;
border: none;
padding: 0;
cursor: pointer;
font: inherit;
font-size: 11px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--fg-dim);
border-bottom: 1px dashed var(--border-bright);
}
.link-btn:hover {
color: var(--accent-strong);
}
/* ---------- buttons ---------- */ /* ---------- buttons ---------- */
.btn { .btn {
+17 -1
View File
@@ -51,6 +51,20 @@ export function TaskDetail({ id }: { id: number }) {
} }
} }
function downloadExampleCSV() {
const sample = [
'alice@source.example,SrcPass1,alice@dest.example,DstPass1',
'bob@source.example,SrcPass2,bob@dest.example,DstPass2',
'carol@source.example,SrcPass3,carol@dest.example,DstPass3',
].join('\n') + '\n'
const url = URL.createObjectURL(new Blob([sample], { type: 'text/csv' }))
const a = document.createElement('a')
a.href = url
a.download = 'imap-copier-accounts-example.csv'
a.click()
URL.revokeObjectURL(url)
}
async function onFileChosen(e: ChangeEvent<HTMLInputElement>) { async function onFileChosen(e: ChangeEvent<HTMLInputElement>) {
const file = e.target.files?.[0] const file = e.target.files?.[0]
if (!file) return if (!file) return
@@ -218,7 +232,9 @@ export function TaskDetail({ id }: { id: number }) {
{busy === 'import' ? 'Importing…' : 'Upload CSV'} {busy === 'import' ? 'Importing…' : 'Upload CSV'}
<input ref={fileInputRef} type="file" accept=".csv,text/csv" onChange={onFileChosen} disabled={busy !== null} /> <input ref={fileInputRef} type="file" accept=".csv,text/csv" onChange={onFileChosen} disabled={busy !== null} />
</button> </button>
<span className="hint">columns: src_login, src_pass, dst_login, dst_pass</span> <button type="button" className="link-btn" onClick={downloadExampleCSV}>
download example.csv
</button>
</div> </div>
</div> </div>