coming together
This commit is contained in:
@@ -121,6 +121,11 @@
|
||||
<span class="font-medium">Global Search</span>
|
||||
<kbd class="text-xs text-neutral-500 dark:text-neutral-400 mt-1">Ctrl+F</kbd>
|
||||
</button>
|
||||
<button onclick="window.location.href='/import'" class="w-full flex flex-col items-center justify-center p-4 bg-neutral-50 dark:bg-neutral-900/50 hover:bg-neutral-100 dark:hover:bg-neutral-900 rounded-lg border border-neutral-200 dark:border-neutral-700 transition-colors duration-200">
|
||||
<i class="fa-solid fa-cloud-arrow-up text-2xl text-primary-600 mb-1"></i>
|
||||
<span class="font-medium">Import Data</span>
|
||||
<kbd class="text-xs text-neutral-500 dark:text-neutral-400 mt-1">Alt+I</kbd>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -130,14 +135,22 @@
|
||||
<div class="px-6 py-4 border-b border-neutral-200 dark:border-neutral-700">
|
||||
<h5 class="text-lg font-semibold text-neutral-900 dark:text-neutral-100 flex items-center gap-2">
|
||||
<i class="fa-solid fa-clock-rotate-left"></i>
|
||||
<span>Recent Activity</span>
|
||||
<span>Recent Activity & Imports</span>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="p-6" id="recent-activity">
|
||||
<div class="p-6 space-y-4">
|
||||
<div id="recent-imports">
|
||||
<div class="flex flex-col items-center justify-center py-4 text-neutral-500 dark:text-neutral-400">
|
||||
<i class="fa-solid fa-file-arrow-up text-2xl mb-2"></i>
|
||||
<p>Loading recent imports...</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="recent-activity">
|
||||
<div class="flex flex-col items-center justify-center py-4 text-neutral-500 dark:text-neutral-400">
|
||||
<i class="fa-solid fa-hourglass-half text-2xl mb-2"></i>
|
||||
<p>Loading recent activity...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -227,6 +240,81 @@ function globalSearch() {
|
||||
// Load data on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
loadDashboardData(); // Uncomment when authentication is implemented
|
||||
loadRecentImports();
|
||||
loadRecentActivity();
|
||||
});
|
||||
async function loadRecentActivity() {
|
||||
// Placeholder: existing system would populate; if an endpoint exists, hook it here.
|
||||
}
|
||||
|
||||
async function loadRecentImports() {
|
||||
try {
|
||||
const [statusResp, recentResp] = await Promise.all([
|
||||
window.http.wrappedFetch('/api/import/status'),
|
||||
window.http.wrappedFetch('/api/import/recent-batches?limit=5')
|
||||
]);
|
||||
if (!statusResp.ok) return;
|
||||
const status = await statusResp.json();
|
||||
const recent = recentResp && recentResp.ok ? (await recentResp.json()).recent || [] : [];
|
||||
const entries = Object.entries(status || {});
|
||||
const total = entries.reduce((sum, [, v]) => sum + (v && v.record_count ? v.record_count : 0), 0);
|
||||
const top = entries
|
||||
.filter(([, v]) => (v && v.record_count) > 0)
|
||||
.slice(0, 6)
|
||||
.map(([k, v]) => ({ name: k, count: v.record_count, table: v.table_name }));
|
||||
|
||||
const container = document.getElementById('recent-imports');
|
||||
if (!container) return;
|
||||
if (entries.length === 0 && recent.length === 0) {
|
||||
container.innerHTML = '<p class="text-neutral-500">No import status available.</p>';
|
||||
return;
|
||||
}
|
||||
const items = top.map(({ name, count }) => `
|
||||
<div class="flex items-center justify-between py-1 text-sm">
|
||||
<span class="font-mono">${name}</span>
|
||||
<span class="inline-block px-2 py-0.5 rounded bg-neutral-100 dark:bg-neutral-700">${Number(count).toLocaleString()}</span>
|
||||
</div>
|
||||
`).join('');
|
||||
const recentRows = (recent || []).map(r => `
|
||||
<tr>
|
||||
<td class="px-2 py-1"><span class="inline-block px-2 py-0.5 rounded text-xs ${r.status === 'success' ? 'bg-green-100 text-green-700' : (r.status === 'completed_with_errors' ? 'bg-yellow-100 text-yellow-700' : 'bg-red-100 text-red-700')}">${r.status}</span></td>
|
||||
<td class="px-2 py-1 text-xs">${r.started_at ? new Date(r.started_at).toLocaleString() : ''}</td>
|
||||
<td class="px-2 py-1 text-xs">${r.finished_at ? new Date(r.finished_at).toLocaleString() : ''}</td>
|
||||
<td class="px-2 py-1 text-xs">${r.successful_files}/${r.total_files}</td>
|
||||
<td class="px-2 py-1 text-xs">${Number(r.total_imported || 0).toLocaleString()}</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
const html = `
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<h6 class="text-sm font-semibold flex items-center gap-2"><i class="fa-solid fa-file-arrow-up"></i> Recent Import Status</h6>
|
||||
<a href="/import" class="text-primary-600 hover:underline text-sm">Open Import</a>
|
||||
</div>
|
||||
<div class="border border-neutral-200 dark:border-neutral-700 rounded-lg p-3">${items || '<p class="text-neutral-500 text-sm">No imported data yet.</p>'}</div>
|
||||
<div class="mt-2 text-xs text-neutral-600 dark:text-neutral-400">Total records across tracked CSVs: <strong>${Number(total).toLocaleString()}</strong></div>
|
||||
<div class="mt-3">
|
||||
<h6 class="text-sm font-semibold mb-1">Last 5 Batch Uploads</h6>
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full text-xs border border-neutral-200 dark:border-neutral-700 rounded">
|
||||
<thead class="bg-neutral-50 dark:bg-neutral-800">
|
||||
<tr>
|
||||
<th class="px-2 py-1 text-left">Status</th>
|
||||
<th class="px-2 py-1 text-left">Started</th>
|
||||
<th class="px-2 py-1 text-left">Finished</th>
|
||||
<th class="px-2 py-1 text-left">Files</th>
|
||||
<th class="px-2 py-1 text-left">Imported</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${recentRows || '<tr><td class="px-2 py-2 text-neutral-500" colspan="5">No recent batch uploads</td></tr>'}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
container.innerHTML = html;
|
||||
} catch (_) {}
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user