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
${flashHtml(flash)}
${body}
`;
}
export function messagePage(opts) {
const { heading, text, link } = opts;
const body = ``;
return layout({ ...opts, body });
}
export function loginPage(opts = {}) {
const body = ``;
return layout({ title: 'Log in', body, ...opts });
}
export function registerPage(opts = {}) {
const needCode = !!config.signupCode;
const body = `
Register
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
? ``
: '';
const body = `
${verifyBanner}
${newLinkBanner}
Disk: ${disk ? `${humanBytes(disk.freeBytes)} free of ${humanBytes(disk.totalBytes)}` : 'n/a'}
${diskPct}% used
${uploadCard}
My files
| File | Scan | Link | Download URL | |
${rows}
`;
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 = ``;
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
| File | Owner | Scan | Link | |
${rows || `| 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 ``;
}