Rebrand to Obsidian with modern UI and auto-refresh
- Renamed project from "Test Artifact Data Lake" to "Obsidian" - Updated all branding across README, quickstart scripts, and API - Implemented dark mode theme with professional color palette - Simplified table to 4 essential columns (Sim Source, Artifacts, Date, Uploaded By) - Replaced emoji icons with Lucide SVG icons for better scaling - Added auto-refresh functionality (5-second intervals, toggleable) - Enhanced UI with modern flexbox layouts and hover effects - Updated upload form labels to match new terminology 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6,10 +6,16 @@ let currentPage = 1;
|
||||
let pageSize = 25;
|
||||
let totalArtifacts = 0;
|
||||
|
||||
// Auto-refresh
|
||||
let autoRefreshEnabled = true;
|
||||
let autoRefreshInterval = null;
|
||||
const REFRESH_INTERVAL_MS = 5000; // 5 seconds
|
||||
|
||||
// Load API info on page load
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
loadApiInfo();
|
||||
loadArtifacts();
|
||||
startAutoRefresh();
|
||||
});
|
||||
|
||||
// Load API information
|
||||
@@ -48,33 +54,28 @@ function displayArtifacts(artifacts) {
|
||||
const tbody = document.getElementById('artifacts-tbody');
|
||||
|
||||
if (artifacts.length === 0) {
|
||||
tbody.innerHTML = '<tr><td colspan="10" class="loading">No artifacts found. Upload some files to get started!</td></tr>';
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="loading">No artifacts found. Upload some files to get started!</td></tr>';
|
||||
document.getElementById('artifact-count').textContent = '0 artifacts';
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = artifacts.map(artifact => `
|
||||
<tr>
|
||||
<td><strong>${artifact.id}</strong></td>
|
||||
<td>${artifact.test_suite || '-'}</td>
|
||||
<td>
|
||||
<a href="#" onclick="showDetail(${artifact.id}); return false;" style="color: #667eea; text-decoration: none;">
|
||||
<a href="#" onclick="showDetail(${artifact.id}); return false;" style="color: #60a5fa; text-decoration: none;">
|
||||
${escapeHtml(artifact.filename)}
|
||||
</a>
|
||||
</td>
|
||||
<td><span class="file-type-badge">${artifact.file_type}</span></td>
|
||||
<td>${formatBytes(artifact.file_size)}</td>
|
||||
<td>${formatDate(artifact.created_at)}</td>
|
||||
<td>${artifact.test_name || '-'}</td>
|
||||
<td>${artifact.test_suite || '-'}</td>
|
||||
<td>${formatResult(artifact.test_result)}</td>
|
||||
<td>${formatTags(artifact.tags)}</td>
|
||||
<td><small>${formatDate(artifact.created_at)}</small></td>
|
||||
<td>
|
||||
<div class="action-buttons">
|
||||
<button class="icon-btn" onclick="downloadArtifact(${artifact.id}, '${escapeHtml(artifact.filename)}')" title="Download">
|
||||
💾
|
||||
<i data-lucide="download" style="width: 16px; height: 16px;"></i>
|
||||
</button>
|
||||
<button class="icon-btn" onclick="deleteArtifact(${artifact.id})" title="Delete">
|
||||
🗑️
|
||||
<i data-lucide="trash-2" style="width: 16px; height: 16px;"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
@@ -82,6 +83,9 @@ function displayArtifacts(artifacts) {
|
||||
`).join('');
|
||||
|
||||
document.getElementById('artifact-count').textContent = `${artifacts.length} artifacts`;
|
||||
|
||||
// Re-initialize Lucide icons for dynamically added content
|
||||
lucide.createIcons();
|
||||
}
|
||||
|
||||
// Format result badge
|
||||
@@ -149,11 +153,11 @@ async function showDetail(id) {
|
||||
<div class="detail-value"><code>${artifact.storage_path}</code></div>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Test Name</div>
|
||||
<div class="detail-label">Uploaded By</div>
|
||||
<div class="detail-value">${artifact.test_name || '-'}</div>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Test Suite</div>
|
||||
<div class="detail-label">Sim Source</div>
|
||||
<div class="detail-value">${artifact.test_suite || '-'}</div>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
@@ -198,15 +202,18 @@ async function showDetail(id) {
|
||||
</div>
|
||||
<div style="margin-top: 20px; display: flex; gap: 10px;">
|
||||
<button onclick="downloadArtifact(${artifact.id}, '${escapeHtml(artifact.filename)}')" class="btn btn-primary">
|
||||
💾 Download
|
||||
<i data-lucide="download" style="width: 16px; height: 16px;"></i> Download
|
||||
</button>
|
||||
<button onclick="deleteArtifact(${artifact.id}); closeDetailModal();" class="btn btn-danger">
|
||||
🗑️ Delete
|
||||
<i data-lucide="trash-2" style="width: 16px; height: 16px;"></i> Delete
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.getElementById('detail-modal').classList.add('active');
|
||||
|
||||
// Re-initialize Lucide icons for modal content
|
||||
lucide.createIcons();
|
||||
} catch (error) {
|
||||
alert('Error loading artifact details: ' + error.message);
|
||||
}
|
||||
@@ -460,3 +467,40 @@ function nextPage() {
|
||||
currentPage++;
|
||||
loadArtifacts(pageSize, (currentPage - 1) * pageSize);
|
||||
}
|
||||
|
||||
// Auto-refresh functions
|
||||
function startAutoRefresh() {
|
||||
if (autoRefreshInterval) {
|
||||
clearInterval(autoRefreshInterval);
|
||||
}
|
||||
|
||||
if (autoRefreshEnabled) {
|
||||
autoRefreshInterval = setInterval(() => {
|
||||
// Only refresh if on the artifacts tab
|
||||
const artifactsTab = document.getElementById('artifacts-tab');
|
||||
if (artifactsTab && artifactsTab.classList.contains('active')) {
|
||||
loadArtifacts(pageSize, (currentPage - 1) * pageSize);
|
||||
}
|
||||
}, REFRESH_INTERVAL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAutoRefresh() {
|
||||
autoRefreshEnabled = !autoRefreshEnabled;
|
||||
|
||||
const toggleBtn = document.getElementById('auto-refresh-toggle');
|
||||
if (autoRefreshEnabled) {
|
||||
toggleBtn.textContent = 'Auto-refresh: ON';
|
||||
toggleBtn.classList.remove('btn-secondary');
|
||||
toggleBtn.classList.add('btn-success');
|
||||
startAutoRefresh();
|
||||
} else {
|
||||
toggleBtn.textContent = 'Auto-refresh: OFF';
|
||||
toggleBtn.classList.remove('btn-success');
|
||||
toggleBtn.classList.add('btn-secondary');
|
||||
if (autoRefreshInterval) {
|
||||
clearInterval(autoRefreshInterval);
|
||||
autoRefreshInterval = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user