โ All Skills Knowledge History
Per-memo .txt import-into-form and single-memo export inside the add/edit modal
memoimport-exportuseFileSystemAccessform-prefillui-refactorscope-correction
Request
- Not an all-memos backup: when adding a memo, let the user import a .txt to FILL the form instead of typing.
- In the same add/edit modal, export the single memo being edited as a .txt.
- Update Mono Skills.
Summary
Per-memo .txt import-into-form + single-memo export (inside the add/edit modal)
Corrects the earlier "all-memos backup" design. The real requirement: when adding a memo the
user can import a .txt to fill the form (instead of typing), and from the same add/edit
modal they can export the single memo being edited as a .txt.
Scope correction (the lesson)
"Downloadable .txt / backup" was first built as an all-memos backup/restore (toolbar, then a
dedicated modal). The user actually meant per-memo, in the edit/add modal: import fills the
open form; export downloads just the current memo. Removed the whole all-memos path:
backupOpen + the dedicated backup modal + the "Cadangan & Impor" toolbar button, the
exportBackup/importBackup functions, serializeMemos/backupFileName in utils, and the
store.importMemos action. Net code shrank.
What it does now
- Two buttons in the add/edit modal footer (left of Batal/Simpan): Impor .txt and Ekspor .txt.
- Import = prefill the form, not create.
importMemo()reads a.txt(viauseFileSystemAccess.open()or the hidden-input fallback), parses the first memo, and writes itstitle/content/category/pinnedontostore.input. The user reviews and then Simpan as usual (the store assigns id + timestamps on save). Importantly it sets the form ref fields, it does NOT push to the list. - Export = the current form memo.
exportMemo()serializesstore.input(guard: needs a title or content) and saves viasaveAs({ suggestedName }), falling back to a Blob/anchor download. Filename is a slug of the title:memo-<slug>.txt.
Reused mechanics (unchanged from the FSA session)
useFileSystemAccess({ dataType: 'Text' });isSupported/dataare refs (.value); guardisSupported.valuewith a Blob-download / hidden<input type=file>fallback; swallow the picker-cancelAbortError.- Same human-readable round-trip block (
===== MEMO =====header lines +----- ISI -----body), now emitted one block per file byserializeMemo(memo);parseMemosis reused and also accepts a plain.txt(first line = title, rest = content), so importing an arbitrary text file works.
Files
src/composables/use-memo-utils.tsโ replacedserializeMemos/backupFileNamewithserializeMemo(memo)+memoFileName(memo); keptparseMemos.src/stores/use-memo.tsโ removedimportMemos(no longer needed; the page writesstore.input).src/pages/memo/index.vueโexportMemo()/importMemo()/applyImported(); modal-footer buttons; removed the dedicated backup modal + toolbar button.
Outcome
successvite module transform + wiring grep /memo, page, store, and use-memo-utils.ts transform 200 Page exposes exportMemo/importMemo/applyImported; utils export serializeMemo/parseMemos/memoFileName All all-memos remnants removed (backupOpen, exportBackup/importBackup, serializeMemos, store.importMemos, the dedicated backup modal + toolbar button)
Decisions
Import PREFILLS the form, it does not create a memo
importMemo() parses the .txt and writes title/content/category/pinned onto store.input; the user then saves normally.
Why: User wanted to 'import instead of typing' while adding โ so the file populates the open form and stays editable/reviewable before Simpan. Creation (id + timestamps) still happens in store.save().
Per-memo export from the edit/add modal, not an all-memos backup
exportMemo() serializes only store.input (the open memo) to memo-<title-slug>.txt.
Why: User corrected the earlier all-memos backup: they want to export the single memo being edited, from the same modal.
Removed the all-memos backup path entirely
Deleted the dedicated backup modal, the toolbar button, serializeMemos/backupFileName, and store.importMemos.
Why: It was a misinterpretation of 'backup'. Keeping dead code would confuse the next session; the per-memo design fully covers the actual need.
Kept the round-trip block format + parseMemos
serializeMemo emits one ===== MEMO ===== block; parseMemos is reused (handles one/many blocks and plain text).
Why: Preserves category/pinned/timestamps on re-import and still lets an arbitrary .txt import as a memo (first line = title).
Files changed
| File | Operation | Note |
|---|---|---|
src/composables/use-memo-utils.ts | modified | Replaced serializeMemos/backupFileName with serializeMemo(memo) (single block) + memoFileName(memo) (title slug); kept parseMemos (reused for single import + plain-text) |
src/stores/use-memo.ts | modified | Removed importMemos action (no longer used; the page prefills store.input directly) |
src/pages/memo/index.vue | modified | Added exportMemo()/importMemo()/applyImported(); Impor .txt + Ekspor .txt buttons in the add/edit modal footer; import prefills the form fields; removed the all-memos backup modal, toolbar button, and exportBackup/importBackup |
Commands
pnpm dev
curl /memo + page + store + use-memo-utils.ts (all 200)
MONO_SKILLS=true MONO_SKILLS_GITHUB_TOKEN=[REDACTED] pnpm exec mono skills save --app my-memo --dir .mono/skills/pending/<id>Validation
Tests: not run Build: passed