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:
2025-10-15 08:30:21 -05:00
parent 1ce27976a9
commit 4bc8310070
8 changed files with 209 additions and 108 deletions

View File

@@ -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;
}
}
}