Drops into #main POST /api/capture/upload one file at a time, with space_id pre-filled from localStorage.last_space_id (set whenever the space view renders). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
68 lines
2.4 KiB
JavaScript
68 lines
2.4 KiB
JavaScript
// Void 2.0 SPA bootstrap. Mounts chrome (sidebar/topbar/rightrail) and
|
|
// delegates the #main panel to a view module based on the current route.
|
|
// Views are loaded dynamically so a missing view never breaks the shell.
|
|
|
|
import { api } from './api.js';
|
|
import { route, current, navigate } from './router.js';
|
|
import { renderSidebar } from './components/sidebar.js';
|
|
import { renderTopbar } from './components/topbar.js';
|
|
import { renderRightrail } from './components/rightrail.js';
|
|
import { emit } from './state.js';
|
|
import { el, mount } from './dom.js';
|
|
import { attachDropzone } from './components/dropzone.js';
|
|
|
|
const VIEWS = {
|
|
home: () => import('./views/home.js'),
|
|
space: () => import('./views/space.js'),
|
|
project: () => import('./views/project.js'),
|
|
page: () => import('./views/page.js'),
|
|
ref: () => import('./views/reference.js'),
|
|
resource: () => import('./views/resource.js'),
|
|
search: () => import('./views/search.js'),
|
|
inbox: () => import('./views/inbox.js'),
|
|
'sacred-valley': () => import('./views/sacred_valley.js'),
|
|
jobs: () => import('./views/jobs.js')
|
|
};
|
|
|
|
async function renderView(ctx) {
|
|
const main = document.getElementById('main');
|
|
const loader = VIEWS[ctx.name] || VIEWS.home;
|
|
try {
|
|
const mod = await loader();
|
|
await mod.render(main, ctx);
|
|
} catch (e) {
|
|
console.error('view render failed', e);
|
|
mount(main,
|
|
el('h1', { class: 'view-h1' }, 'Something went wrong'),
|
|
el('p', { class: 'view-sub' }, 'View failed to load. Check console for details.'),
|
|
el('pre', {}, String(e && e.stack || e))
|
|
);
|
|
}
|
|
}
|
|
|
|
async function pollPending() {
|
|
try {
|
|
const rows = await api.get('/api/pending-changes');
|
|
emit('pending-count', rows.length);
|
|
} catch (e) {
|
|
if (e.status === 403) emit('pending-count', 0);
|
|
}
|
|
}
|
|
|
|
async function init() {
|
|
if (!api.hasToken()) {
|
|
try { await api.get('/api/spaces'); }
|
|
catch { /* api wrapper opens the modal on 401 */ }
|
|
}
|
|
renderTopbar(document.getElementById('topbar'));
|
|
renderSidebar(document.getElementById('sidebar'));
|
|
renderRightrail(document.getElementById('rightrail'));
|
|
attachDropzone(document.getElementById('main'));
|
|
route(renderView);
|
|
pollPending();
|
|
setInterval(pollPending, 15000);
|
|
}
|
|
|
|
window.addEventListener('DOMContentLoaded', init);
|
|
window.voidNav = navigate; // dev convenience: window.voidNav('/space/abc')
|