Initial commit: Clean DSS implementation
Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
219
admin-ui/js/components/tools/ds-system-log.js
Normal file
219
admin-ui/js/components/tools/ds-system-log.js
Normal file
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
* ds-system-log.js
|
||||
* System health dashboard with DSS status, MCP health, and compiler metrics
|
||||
*/
|
||||
|
||||
import toolBridge from '../../services/tool-bridge.js';
|
||||
import { ComponentHelpers } from '../../utils/component-helpers.js';
|
||||
|
||||
class DSSystemLog extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
this.status = null;
|
||||
this.autoRefresh = false;
|
||||
this.refreshInterval = null;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.render();
|
||||
this.setupEventListeners();
|
||||
this.loadStatus();
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
if (this.refreshInterval) {
|
||||
clearInterval(this.refreshInterval);
|
||||
}
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
const refreshBtn = this.querySelector('#system-refresh-btn');
|
||||
if (refreshBtn) {
|
||||
refreshBtn.addEventListener('click', () => this.loadStatus());
|
||||
}
|
||||
|
||||
const autoRefreshToggle = this.querySelector('#system-auto-refresh');
|
||||
if (autoRefreshToggle) {
|
||||
autoRefreshToggle.addEventListener('change', (e) => {
|
||||
this.autoRefresh = e.target.checked;
|
||||
if (this.autoRefresh) {
|
||||
this.refreshInterval = setInterval(() => this.loadStatus(), 5000);
|
||||
} else {
|
||||
if (this.refreshInterval) {
|
||||
clearInterval(this.refreshInterval);
|
||||
this.refreshInterval = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async loadStatus() {
|
||||
const content = this.querySelector('#system-content');
|
||||
if (!content) return;
|
||||
|
||||
// Only show loading on first load
|
||||
if (!this.status) {
|
||||
content.innerHTML = ComponentHelpers.renderLoading('Loading system status...');
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await toolBridge.getDSSStatus('json');
|
||||
|
||||
if (result) {
|
||||
this.status = result;
|
||||
this.renderStatus();
|
||||
} else {
|
||||
content.innerHTML = ComponentHelpers.renderEmpty('No status data available', '📊');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load system status:', error);
|
||||
content.innerHTML = ComponentHelpers.renderError('Failed to load system status', error);
|
||||
}
|
||||
}
|
||||
|
||||
getHealthBadge(isHealthy) {
|
||||
return isHealthy
|
||||
? ComponentHelpers.createBadge('Healthy', 'success')
|
||||
: ComponentHelpers.createBadge('Degraded', 'error');
|
||||
}
|
||||
|
||||
renderStatus() {
|
||||
const content = this.querySelector('#system-content');
|
||||
if (!content || !this.status) return;
|
||||
|
||||
const health = this.status.health || {};
|
||||
const config = this.status.configuration || {};
|
||||
const metrics = this.status.metrics || {};
|
||||
const recommendations = this.status.recommendations || [];
|
||||
|
||||
content.innerHTML = `
|
||||
<div style="display: grid; gap: 16px;">
|
||||
<!-- Overall Health Card -->
|
||||
<div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 16px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
||||
<h3 style="font-size: 14px; font-weight: 600;">System Health</h3>
|
||||
${this.getHealthBadge(health.overall)}
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px;">
|
||||
<div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 4px;">MCP Server</div>
|
||||
<div style="font-size: 12px;">${this.getHealthBadge(health.mcp_server)}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 4px;">Context Compiler</div>
|
||||
<div style="font-size: 12px;">${this.getHealthBadge(health.context_compiler)}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 4px;">Browser Connection</div>
|
||||
<div style="font-size: 12px;">${this.getHealthBadge(health.browser_connection)}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 4px;">Dependencies</div>
|
||||
<div style="font-size: 12px;">${this.getHealthBadge(health.dependencies)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Configuration Card -->
|
||||
<div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 16px;">
|
||||
<h3 style="font-size: 14px; font-weight: 600; margin-bottom: 12px;">Configuration</h3>
|
||||
<div style="display: grid; gap: 8px; font-size: 12px;">
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--vscode-text-dim);">Base Theme:</span>
|
||||
<span style="font-family: 'Courier New', monospace;">${ComponentHelpers.escapeHtml(config.base_theme || 'N/A')}</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--vscode-text-dim);">Active Skin:</span>
|
||||
<span style="font-family: 'Courier New', monospace;">${ComponentHelpers.escapeHtml(config.skin || 'None')}</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--vscode-text-dim);">Project Name:</span>
|
||||
<span style="font-family: 'Courier New', monospace;">${ComponentHelpers.escapeHtml(config.project_name || 'N/A')}</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span style="color: var(--vscode-text-dim);">Cache Enabled:</span>
|
||||
<span>${config.cache_enabled ? '✓ Yes' : '✗ No'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Metrics Card -->
|
||||
${metrics.token_count !== undefined ? `
|
||||
<div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 16px;">
|
||||
<h3 style="font-size: 14px; font-weight: 600; margin-bottom: 12px;">Metrics</h3>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px;">
|
||||
<div style="text-align: center; padding: 12px; background-color: var(--vscode-bg); border-radius: 4px;">
|
||||
<div style="font-size: 24px; font-weight: 600; color: var(--vscode-accent);">${metrics.token_count || 0}</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-top: 4px;">Design Tokens</div>
|
||||
</div>
|
||||
<div style="text-align: center; padding: 12px; background-color: var(--vscode-bg); border-radius: 4px;">
|
||||
<div style="font-size: 24px; font-weight: 600; color: var(--vscode-accent);">${metrics.component_count || 0}</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-top: 4px;">Components</div>
|
||||
</div>
|
||||
<div style="text-align: center; padding: 12px; background-color: var(--vscode-bg); border-radius: 4px;">
|
||||
<div style="font-size: 24px; font-weight: 600; color: var(--vscode-accent);">${metrics.theme_count || 0}</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-top: 4px;">Themes</div>
|
||||
</div>
|
||||
${metrics.compilation_time ? `
|
||||
<div style="text-align: center; padding: 12px; background-color: var(--vscode-bg); border-radius: 4px;">
|
||||
<div style="font-size: 24px; font-weight: 600; color: var(--vscode-accent);">${Math.round(metrics.compilation_time)}ms</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-top: 4px;">Compilation Time</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<!-- Recommendations Card -->
|
||||
${recommendations.length > 0 ? `
|
||||
<div style="background-color: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 16px;">
|
||||
<h3 style="font-size: 14px; font-weight: 600; margin-bottom: 12px;">Recommendations</h3>
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
${recommendations.map(rec => `
|
||||
<div style="display: flex; align-items: start; gap: 8px; padding: 8px; background-color: var(--vscode-bg); border-radius: 2px;">
|
||||
<span style="font-size: 16px;">💡</span>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-size: 12px; margin-bottom: 2px;">${ComponentHelpers.escapeHtml(rec.title || rec)}</div>
|
||||
${rec.description ? `
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim);">${ComponentHelpers.escapeHtml(rec.description)}</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<!-- Last Updated -->
|
||||
<div style="font-size: 11px; color: var(--vscode-text-dim); text-align: center; padding-top: 8px;">
|
||||
Last updated: ${ComponentHelpers.formatTimestamp(new Date())}
|
||||
${this.autoRefresh ? '• Auto-refreshing every 5s' : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
render() {
|
||||
this.innerHTML = `
|
||||
<div style="padding: 16px; height: 100%; display: flex; flex-direction: column;">
|
||||
<div style="margin-bottom: 16px; display: flex; gap: 12px; align-items: center; justify-content: flex-end;">
|
||||
<label style="display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--vscode-text);">
|
||||
<input type="checkbox" id="system-auto-refresh" />
|
||||
Auto-refresh
|
||||
</label>
|
||||
<button id="system-refresh-btn" class="button" style="padding: 4px 12px; font-size: 11px;">
|
||||
🔄 Refresh
|
||||
</button>
|
||||
</div>
|
||||
<div id="system-content" style="flex: 1; overflow-y: auto;">
|
||||
${ComponentHelpers.renderLoading('Initializing...')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('ds-system-log', DSSystemLog);
|
||||
|
||||
export default DSSystemLog;
|
||||
Reference in New Issue
Block a user