Files
dss/admin-ui/js/components/tools/ds-metrics-panel.js
Digital Production Factory 276ed71f31 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
2025-12-09 18:45:48 -03:00

179 lines
5.2 KiB
JavaScript

/**
* ds-metrics-panel.js
* Universal metrics panel showing tool execution stats and activity
*/
import toolBridge from '../../services/tool-bridge.js';
class DSMetricsPanel extends HTMLElement {
constructor() {
super();
this.metrics = {
totalExecutions: 0,
successCount: 0,
errorCount: 0,
recentActivity: []
};
this.refreshInterval = null;
}
connectedCallback() {
this.render();
this.startAutoRefresh();
}
disconnectedCallback() {
this.stopAutoRefresh();
}
render() {
const successRate = this.metrics.totalExecutions > 0
? Math.round((this.metrics.successCount / this.metrics.totalExecutions) * 100)
: 0;
this.innerHTML = `
<div style="padding: 16px;">
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 16px;">
<!-- Total Executions Card -->
<div style="
background-color: var(--vscode-sidebar);
border: 1px solid var(--vscode-border);
border-radius: 4px;
padding: 12px;
">
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 4px;">
TOTAL EXECUTIONS
</div>
<div style="font-size: 24px; font-weight: 600;">
${this.metrics.totalExecutions}
</div>
</div>
<!-- Success Rate Card -->
<div style="
background-color: var(--vscode-sidebar);
border: 1px solid var(--vscode-border);
border-radius: 4px;
padding: 12px;
">
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 4px;">
SUCCESS RATE
</div>
<div style="font-size: 24px; font-weight: 600; color: ${successRate >= 80 ? '#4caf50' : successRate >= 50 ? '#ff9800' : '#f44336'};">
${successRate}%
</div>
</div>
<!-- Error Count Card -->
<div style="
background-color: var(--vscode-sidebar);
border: 1px solid var(--vscode-border);
border-radius: 4px;
padding: 12px;
">
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 4px;">
ERRORS
</div>
<div style="font-size: 24px; font-weight: 600; color: ${this.metrics.errorCount > 0 ? '#f44336' : 'inherit'};">
${this.metrics.errorCount}
</div>
</div>
</div>
<!-- Recent Activity -->
<div>
<div style="font-size: 11px; color: var(--vscode-text-dim); margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px;">
Recent Activity
</div>
<div style="
background-color: var(--vscode-bg);
border: 1px solid var(--vscode-border);
border-radius: 4px;
max-height: 200px;
overflow-y: auto;
">
${this.metrics.recentActivity.length === 0 ? `
<div style="padding: 16px; text-align: center; color: var(--vscode-text-dim); font-size: 12px;">
No recent activity
</div>
` : this.metrics.recentActivity.map(activity => `
<div style="
padding: 8px 12px;
border-bottom: 1px solid var(--vscode-border);
font-size: 12px;
display: flex;
justify-content: space-between;
align-items: center;
">
<div>
<span style="color: ${activity.success ? '#4caf50' : '#f44336'};">
${activity.success ? '✓' : '✗'}
</span>
<span style="margin-left: 8px;">${activity.toolName}</span>
</div>
<span style="color: var(--vscode-text-dim); font-size: 11px;">
${activity.timestamp}
</span>
</div>
`).join('')}
</div>
</div>
</div>
`;
}
recordExecution(toolName, success = true) {
this.metrics.totalExecutions++;
if (success) {
this.metrics.successCount++;
} else {
this.metrics.errorCount++;
}
// Add to recent activity
const now = new Date();
const timestamp = now.toLocaleTimeString();
this.metrics.recentActivity.unshift({
toolName,
success,
timestamp
});
// Keep only last 10 activities
if (this.metrics.recentActivity.length > 10) {
this.metrics.recentActivity = this.metrics.recentActivity.slice(0, 10);
}
this.render();
}
startAutoRefresh() {
// Refresh metrics every 5 seconds
this.refreshInterval = setInterval(() => {
this.render();
}, 5000);
}
stopAutoRefresh() {
if (this.refreshInterval) {
clearInterval(this.refreshInterval);
this.refreshInterval = null;
}
}
reset() {
this.metrics = {
totalExecutions: 0,
successCount: 0,
errorCount: 0,
recentActivity: []
};
this.render();
}
}
customElements.define('ds-metrics-panel', DSMetricsPanel);
export default DSMetricsPanel;