Feat v0.7.6 code hygiene (#60)
All checks were successful
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-frontend (push) Successful in 6s
CI/CD / test-go-pg (push) Successful in 2m48s
CI/CD / build-and-deploy (push) Successful in 25s
CI/CD / test-sqlite (push) Successful in 2m55s
All checks were successful
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / detect-changes (push) Successful in 4s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-frontend (push) Successful in 6s
CI/CD / test-go-pg (push) Successful in 2m48s
CI/CD / build-and-deploy (push) Successful in 25s
CI/CD / test-sqlite (push) Successful in 2m55s
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #60.
This commit is contained in:
@@ -30,12 +30,12 @@ export default function BackupSection() {
|
||||
sw.toast('Backup created', 'success');
|
||||
load();
|
||||
} else {
|
||||
// Stream download
|
||||
// Stream download — use _getToken() for raw bearer token
|
||||
const url = '/api/v1/admin/backup';
|
||||
const token = sw.auth.token();
|
||||
const token = sw.auth._getToken();
|
||||
const resp = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': 'Bearer ' + token },
|
||||
headers: token ? { 'Authorization': 'Bearer ' + token } : {},
|
||||
});
|
||||
if (!resp.ok) throw new Error('Backup failed');
|
||||
const blob = await resp.blob();
|
||||
@@ -54,9 +54,9 @@ export default function BackupSection() {
|
||||
}
|
||||
|
||||
async function downloadBackup(name) {
|
||||
const token = sw.auth.token();
|
||||
const token = sw.auth._getToken();
|
||||
const resp = await fetch(sw.api.admin.backup.download(name), {
|
||||
headers: { 'Authorization': 'Bearer ' + token },
|
||||
headers: token ? { 'Authorization': 'Bearer ' + token } : {},
|
||||
});
|
||||
if (!resp.ok) { sw.toast('Download failed', 'error'); return; }
|
||||
const blob = await resp.blob();
|
||||
|
||||
@@ -20,14 +20,14 @@ import { DialogStack } from '../../shell/dialog-stack.js';
|
||||
const ADMIN_SECTIONS = {
|
||||
people: ['users', 'teams', 'groups'],
|
||||
workflows: ['workflows'],
|
||||
system: ['settings', 'storage', 'packages', 'connections', 'broadcast', 'backup'],
|
||||
system: ['settings', 'packages', 'connections', 'broadcast', 'backup'],
|
||||
monitoring: ['health', 'audit'],
|
||||
};
|
||||
|
||||
const ADMIN_LABELS = {
|
||||
users: 'Users', teams: 'Teams', groups: 'Groups',
|
||||
workflows: 'Workflows',
|
||||
settings: 'Settings', storage: 'Storage', packages: 'Packages',
|
||||
settings: 'Settings', packages: 'Packages',
|
||||
connections: 'Connections', broadcast: 'Broadcast',
|
||||
backup: 'Backup',
|
||||
health: 'Health', audit: 'Audit',
|
||||
@@ -63,7 +63,6 @@ const sectionModules = {
|
||||
groups: () => import(`./groups.js${_v}`),
|
||||
workflows: () => import(`./workflows.js${_v}`),
|
||||
settings: () => import(`./settings.js${_v}`),
|
||||
storage: () => import(`./storage.js${_v}`),
|
||||
packages: () => import(`./packages.js${_v}`),
|
||||
connections: () => import(`./connections.js${_v}`),
|
||||
broadcast: () => import(`./broadcast.js${_v}`),
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* Admin > System > Storage
|
||||
*/
|
||||
const { html } = window;
|
||||
const { useState, useEffect, useCallback } = hooks;
|
||||
|
||||
export default function StorageSection() {
|
||||
const [status, setStatus] = useState(null);
|
||||
const [orphans, setOrphans] = useState(null);
|
||||
const [extraction, setExtraction] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
try {
|
||||
const [s, o, e] = await Promise.all([
|
||||
sw.api.admin.storage.status(),
|
||||
sw.api.admin.storage.orphans(),
|
||||
sw.api.admin.storage.extraction().catch(() => null),
|
||||
]);
|
||||
setStatus(s);
|
||||
setOrphans(o);
|
||||
setExtraction(e);
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
finally { setLoading(false); }
|
||||
}, []);
|
||||
|
||||
useEffect(() => { load(); }, []);
|
||||
|
||||
async function cleanup() {
|
||||
const ok = await sw.confirm('Remove orphaned blobs?');
|
||||
if (!ok) return;
|
||||
try {
|
||||
await sw.api.admin.storage.cleanup();
|
||||
sw.toast('Cleanup complete', 'success');
|
||||
load();
|
||||
} catch (e) { sw.toast(e.message, 'error'); }
|
||||
}
|
||||
|
||||
function formatBytes(b) {
|
||||
if (!b) return '0 B';
|
||||
if (b < 1024) return b + ' B';
|
||||
if (b < 1048576) return (b / 1024).toFixed(1) + ' KB';
|
||||
if (b < 1073741824) return (b / 1048576).toFixed(1) + ' MB';
|
||||
return (b / 1073741824).toFixed(2) + ' GB';
|
||||
}
|
||||
|
||||
if (loading) return html`<div class="settings-placeholder">Loading\u2026</div>`;
|
||||
|
||||
return html`
|
||||
<div>
|
||||
${status && html`
|
||||
<div class="stat-cards-grid" style="margin-bottom:16px;">
|
||||
<div class="stat-card"><div class="stat-value">${status.backend || '\u2014'}</div><div class="stat-label">Backend</div></div>
|
||||
<div class="stat-card"><div class="stat-value"><span class="badge ${status.healthy ? 'badge-active' : 'badge-inactive'}">${status.healthy ? 'Healthy' : 'Unhealthy'}</span></div><div class="stat-label">Status</div></div>
|
||||
<div class="stat-card"><div class="stat-value">${status.file_count ?? '\u2014'}</div><div class="stat-label">Files</div></div>
|
||||
<div class="stat-card"><div class="stat-value">${formatBytes(status.total_bytes)}</div><div class="stat-label">Total Size</div></div>
|
||||
</div>
|
||||
`}
|
||||
|
||||
${orphans && html`
|
||||
<div class="settings-section" style="margin-bottom:16px;">
|
||||
<h4>Orphaned Blobs</h4>
|
||||
<p class="text-muted" style="font-size:12px;">${orphans.count || 0} orphans found</p>
|
||||
${(orphans.count || 0) > 0 && html`<button class="sw-btn sw-btn--primary sw-btn--sm" onClick=${cleanup}>Clean Up</button>`}
|
||||
</div>
|
||||
`}
|
||||
|
||||
${extraction && html`
|
||||
<div class="settings-section">
|
||||
<h4>Extraction Queue</h4>
|
||||
<pre class="code-block" style="font-size:12px;max-height:200px;overflow:auto;">${JSON.stringify(extraction, null, 2)}</pre>
|
||||
</div>
|
||||
`}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
Reference in New Issue
Block a user