Move pages to and from the vault
CI / test (push) Successful in 2m12s
Release / release (push) Successful in 3m42s

A page, including a journal day, can be moved into the unlocked vault with its id kept. Links to it elsewhere become [[locked:id]], shown as Locked Page until the vault is unlocked, so its title is kept only in the vault. Move out reverses it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
VeillaxandClaude Sonnet 5.5 committed 2026-11-01 01:58:29 -07:00
1 parent c08a8b8718
commit 994927c704
10 files changed
+443 -14

No files matched your search

+26 -4
View File
@@ -6,6 +6,17 @@
// or download, and they cannot link to it.
const VAULT = '/api/vault';
// S.vaultNames maps the id of each vault page to its name while the vault is unlocked, so that a
// [[locked:id]] link elsewhere can say what it points at. It is null while the vault is locked.
async function refreshVaultNames() {
try {
const v = await api('GET', VAULT);
if (!v.unlocked) { S.vaultNames = null; return; }
const r = await api('GET', VAULT + '/pages');
S.vaultNames = new Map(r.pages.map(p => [p.id, p.name]));
} catch { S.vaultNames = null; }
}
function vaultView(arg) {
const root = h('div', { class: 'page vault' });
let ed = null, dead = false;
@@ -14,6 +25,7 @@ function vaultView(arg) {
const lock = async () => {
await flushAll();
await api('POST', VAULT + '/lock');
S.vaultNames = null;
location.hash = '#/vault';
show();
};
@@ -115,9 +127,9 @@ function vaultView(arg) {
h('a', { href: '#/vault' }, 'Vault'));
const meta = h('p', { class: 'sub page-meta' });
ed = pageEditor({
note, vault: true,
onCreated(c) { note = c; history.replaceState(null, '', '#/vault/' + c.id); document.title = (c.name || 'New page') + ' · Vault · Mako'; draw(); },
onSaved(c) { note = c; meta.textContent = 'Edited ' + fmtTime(c.updated); document.title = (c.name || 'New page') + ' · Vault · Mako'; },
note, vault: true, fixedTitle: note?.daily ? note.title : undefined, // a journal day is named by its date
onCreated(c) { note = c; history.replaceState(null, '', '#/vault/' + c.id); document.title = (c.name || 'New page') + ' · Vault · Mako'; draw(); refreshVaultNames(); },
onSaved(c, { renamed }) { note = c; meta.textContent = 'Edited ' + fmtTime(c.updated); document.title = (c.name || 'New page') + ' · Vault · Mako'; if (renamed) refreshVaultNames(); },
});
ed.onMode = () => draw();
view.toggleMode = () => ed.setMode(ed.mode === 'read' ? ed.lastEdit : 'read');
@@ -126,6 +138,15 @@ function vaultView(arg) {
[['live', 'Live', 'Rendered, except the line you are on'], ['write', 'Edit', 'Plain markdown'], ['read', 'View', 'The finished page']].map(([m, label, tip]) =>
h('button', { class: 'seg-b' + (ed.mode === m ? ' on' : ''), 'aria-pressed': String(ed.mode === m), title: tip, onclick: () => ed.setMode(m) }, label)));
fill(actions, ed.status, h('span', { class: 'grow' }), seg, btn('Lock', 'lock', act(lock)),
btn('Move out', 'move', act(async () => {
if (!note || !note.id) return toast('Type something first, then you can move the page out');
await ed.flush();
const n = note;
await api('POST', `${VAULT}/notes/${n.id}/out`);
await Promise.all([refreshPages(), refreshVaultNames()]);
toast('Moved out of the vault', false, { label: 'Undo', fn: act(async () => { await api('POST', `/api/notes/${n.id}/vault`); await Promise.all([refreshPages(), refreshVaultNames()]); location.hash = '#/vault/' + n.id; }) });
location.hash = hrefOf(n);
})),
btn('Delete', 'trash', act(async () => {
if (!note) { location.hash = '#/vault'; return; }
await ed.flush();
@@ -152,7 +173,8 @@ function vaultView(arg) {
const v = await api('GET', VAULT);
if (dead) return;
if (!v.exists) return create();
if (!v.unlocked) return unlock();
if (!v.unlocked) { S.vaultNames = null; return unlock(); }
refreshVaultNames();
return arg ? page(arg) : list(false);
});
return view;