import config from './config.js'; export function esc(s) { return String(s ?? '') .replaceAll('&', '&') .replaceAll('<', '<') .replaceAll('>', '>') .replaceAll('"', '"') .replaceAll("'", '''); } const u = (p) => esc(config.url(p)); export function humanBytes(n) { n = Number(n) || 0; const units = ['B', 'KB', 'MB', 'GB', 'TB']; let i = 0; while (n >= 1024 && i < units.length - 1) { n /= 1024; i++; } return `${n.toFixed(i === 0 ? 0 : 1)} ${units[i]}`; } function flashHtml(flash) { if (!flash) return ''; const cls = flash.type === 'error' ? 'flash error' : 'flash ok'; return `
${esc(flash.msg)}
`; } export function layout({ title, body, user, flash, active }) { const nav = user ? `My files ${user.is_admin ? `Admin` : ''} ${esc(user.username)}
` : `Log in Register`; return ` ${esc(title)} · File Share
📦 File Share
${flashHtml(flash)} ${body}
`; } export function messagePage(opts) { const { heading, text, link } = opts; const body = `

${esc(heading)}

${esc(text)}

${link ? `

${esc(link.label)}

` : ''}
`; return layout({ ...opts, body }); } export function loginPage(opts = {}) { const body = `

Log in

No account? Register

`; return layout({ title: 'Log in', body, ...opts }); } export function registerPage(opts = {}) { const needCode = !!config.signupCode; const body = `

Register

${needCode ? `` : ''}

Already have an account? Log in

`; return layout({ title: 'Register', body, ...opts }); } function linkStatusBadge(file) { const s = file.link_state; // 'active' | 'downloaded' | 'expired' | 'none' const labels = { active: 'Active link', downloaded: 'Downloaded', expired: 'Expired', none: 'No link', }; return `${labels[s] || s}`; } function avBadge(file) { return `${esc(file.av_status)}`; } function fileRow(file) { const link = file.token ? config.absoluteUrl(`/d/${file.token}`) : ''; const expires = file.expires_at ? new Date(file.expires_at).toLocaleString() : ''; return `
${esc(file.original_name)}
${humanBytes(file.size_bytes)}${file.is_bundle ? ' · bundle' : ''}${file.compressed ? ' · compressed' : ''}
${avBadge(file)} ${linkStatusBadge(file)}${file.link_state === 'active' ? `
expires ${esc(expires)}
` : ''} ${ file.link_state === 'active' ? `` : '' }
`; } export function dashboardPage({ user, files, disk, flash, newLink }) { const diskPct = disk ? Math.round(disk.usedPct) : 0; const rows = files.length ? files.map(fileRow).join('') : `No files yet. Upload one below.`; const newLinkBanner = newLink ? `
One-time link ready:
` : ''; const verifyBanner = !user.email_verified ? `
Your email isn't verified yet — you can't upload until it is.
` : ''; const uploadCard = user.email_verified ? `

Upload

Select multiple files to bundle them into a single .zip behind one link.

` : ''; const body = ` ${verifyBanner} ${newLinkBanner}
Disk: ${disk ? `${humanBytes(disk.freeBytes)} free of ${humanBytes(disk.totalBytes)}` : 'n/a'}
${diskPct}% used
${uploadCard}

My files

${rows}
FileScanLinkDownload URL
`; return layout({ title: 'My files', body, user, flash, active: 'dash' }); } export function gonePage() { return messagePage({ title: 'Link unavailable', heading: 'This link is no longer available', text: 'It may have already been used, expired, or never existed.', }); } // ---- Admin views ---- export function adminOverviewPage({ user, stats, disk, flash }) { const diskPct = disk ? Math.round(disk.usedPct) : 0; const body = `

Admin overview

${stats.users}users
${stats.files}files
${stats.activeLinks}active links
${stats.usedLinks}used links
${stats.expiredLinks}expired links
${stats.queueDepth}compress queue
${stats.infected}infected blocked
Disk: ${disk ? `${humanBytes(disk.freeBytes)} free of ${humanBytes(disk.totalBytes)}` : 'n/a'}
${diskPct}% used

Manage users Manage files

`; return layout({ title: 'Admin', body, user, flash, active: 'admin' }); } export function adminUsersPage({ user, users, flash }) { const rows = users .map( (r) => ` ${esc(r.username)}${r.is_admin ? ' admin' : ''} ${r.disabled ? ' disabled' : ''} ${!r.email_verified ? ' unverified' : ''}
${esc(r.email)}
${r.file_count}
${humanBytes(r.bytes_used)}
${!r.email_verified ? actionBtn(`/admin/users/${r.id}/verify`, 'Verify') : ''} ${r.disabled ? actionBtn(`/admin/users/${r.id}/enable`, 'Enable') : actionBtn(`/admin/users/${r.id}/disable`, 'Disable', r.id === user.id)} ${actionBtn(`/admin/users/${r.id}/delete`, 'Delete', r.id === user.id, true)} ` ) .join(''); const body = `

Users

${rows}
UserFiles

← Overview

`; return layout({ title: 'Admin · Users', body, user, flash, active: 'admin' }); } export function adminFilesPage({ user, files, flash }) { const rows = files .map( (f) => `
${esc(f.original_name)}
${humanBytes(f.size_bytes)}${f.is_bundle ? ' · bundle' : ''}${f.compressed ? ' · compressed' : ''}
${esc(f.username)} ${esc(f.av_status)} ${f.link_state} ${actionBtn(`/admin/files/${f.id}/link`, 'New link')} ${f.link_id ? actionBtn(`/admin/links/${f.link_id}/expire`, 'Expire') : ''} ${actionBtn(`/admin/files/${f.id}/delete`, 'Delete', false, true)} ` ) .join(''); const body = `

All files

${rows || ``}
FileOwnerScanLink
No files.

← Overview

`; return layout({ title: 'Admin · Files', body, user, flash, active: 'admin' }); } function actionBtn(path, label, disabled = false, danger = false) { if (disabled) return ``; const confirmAttr = danger ? ` data-confirm="Are you sure?"` : ''; return `
`; }