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
205 lines
8.0 KiB
JavaScript
205 lines
8.0 KiB
JavaScript
/**
|
|
* ds-metrics-dashboard.js
|
|
* Metrics dashboard for design system adoption and health
|
|
* Shows key metrics like component adoption rate, token usage, etc.
|
|
*/
|
|
|
|
import store from '../../stores/app-store.js';
|
|
|
|
export default class MetricsDashboard extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.isLoading = true;
|
|
this.error = null;
|
|
this.metrics = {
|
|
adoptionRate: 0,
|
|
componentsUsed: 0,
|
|
totalComponents: 0,
|
|
tokensCovered: 0,
|
|
teamsActive: 0,
|
|
averageUpdateFreq: 'N/A'
|
|
};
|
|
}
|
|
|
|
connectedCallback() {
|
|
this.render();
|
|
this.loadMetrics();
|
|
}
|
|
|
|
async loadMetrics() {
|
|
this.isLoading = true;
|
|
this.error = null;
|
|
this.render();
|
|
|
|
try {
|
|
const response = await fetch('/api/discovery/stats');
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`API Error: ${response.status}`);
|
|
}
|
|
|
|
const json = await response.json();
|
|
|
|
if (json.status === 'success' && json.data) {
|
|
const stats = json.data;
|
|
|
|
// Map backend field names to component properties
|
|
this.metrics = {
|
|
adoptionRate: stats.adoption_percentage || 0,
|
|
componentsUsed: stats.components_in_use || 0,
|
|
totalComponents: stats.total_components || 0,
|
|
tokensCovered: stats.tokens_count || 0,
|
|
teamsActive: stats.active_projects || 0,
|
|
averageUpdateFreq: stats.avg_update_days
|
|
? `${stats.avg_update_days} days`
|
|
: 'N/A'
|
|
};
|
|
} else {
|
|
throw new Error(json.message || 'Invalid response format');
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to load metrics:', error);
|
|
this.error = error.message;
|
|
} finally {
|
|
this.isLoading = false;
|
|
this.render();
|
|
}
|
|
}
|
|
|
|
render() {
|
|
if (this.isLoading) {
|
|
this.innerHTML = `
|
|
<div style="padding: 24px; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
<div style="text-align: center;">
|
|
<div style="font-size: 14px; color: var(--vscode-text-dim);">Loading metrics...</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
if (this.error) {
|
|
this.innerHTML = `
|
|
<div style="padding: 24px; height: 100%; display: flex; align-items: center; justify-content: center;">
|
|
<div style="text-align: center;">
|
|
<div style="font-size: 14px; color: var(--vscode-error); margin-bottom: 12px;">
|
|
Failed to load metrics: ${this.error}
|
|
</div>
|
|
<button
|
|
onclick="document.querySelector('ds-metrics-dashboard').loadMetrics()"
|
|
style="
|
|
padding: 8px 16px;
|
|
background: var(--vscode-button);
|
|
color: var(--vscode-button-fg);
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
"
|
|
>
|
|
Retry
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
return;
|
|
}
|
|
|
|
this.innerHTML = `
|
|
<div style="padding: 24px; height: 100%; overflow-y: auto;">
|
|
<h1 style="margin-bottom: 8px; font-size: 24px;">Design System Metrics</h1>
|
|
<p style="color: var(--vscode-text-dim); margin-bottom: 32px;">
|
|
Track adoption, health, and usage of your design system
|
|
</p>
|
|
|
|
<!-- Metrics Grid -->
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; margin-bottom: 32px;">
|
|
${this.renderMetricCard('Adoption Rate', `${this.metrics.adoptionRate}%`, '#4caf50', 'Percentage of team using DS')}
|
|
${this.renderMetricCard('Components in Use', this.metrics.componentsUsed, '#2196f3', `of ${this.metrics.totalComponents} total`)}
|
|
${this.renderMetricCard('Design Tokens', this.metrics.tokensCovered, '#ff9800', 'Total tokens managed')}
|
|
${this.renderMetricCard('Active Projects', this.metrics.teamsActive, '#9c27b0', 'Projects in system')}
|
|
</div>
|
|
|
|
<!-- Activity Timeline -->
|
|
<div style="background: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 20px; margin-bottom: 24px;">
|
|
<h2 style="margin-top: 0; margin-bottom: 16px; font-size: 16px;">Recent Activity</h2>
|
|
<div style="font-size: 12px;">
|
|
<div style="padding: 8px 0; border-bottom: 1px solid var(--vscode-border);">
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
|
|
<span style="font-weight: 500;">Component Library Updated</span>
|
|
<span style="color: var(--vscode-text-dim);">2 hours ago</span>
|
|
</div>
|
|
<div style="color: var(--vscode-text-dim); font-size: 11px;">Added 3 new components to Button family</div>
|
|
</div>
|
|
<div style="padding: 8px 0; border-bottom: 1px solid var(--vscode-border);">
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
|
|
<span style="font-weight: 500;">Tokens Synchronized</span>
|
|
<span style="color: var(--vscode-text-dim);">6 hours ago</span>
|
|
</div>
|
|
<div style="color: var(--vscode-text-dim); font-size: 11px;">Synced 42 color tokens from Figma</div>
|
|
</div>
|
|
<div style="padding: 8px 0;">
|
|
<div style="display: flex; justify-content: space-between; margin-bottom: 4px;">
|
|
<span style="font-weight: 500;">Team Onboarded</span>
|
|
<span style="color: var(--vscode-text-dim);">1 day ago</span>
|
|
</div>
|
|
<div style="color: var(--vscode-text-dim); font-size: 11px;">Marketing team completed DS training</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Health Indicators -->
|
|
<div style="background: var(--vscode-sidebar); border: 1px solid var(--vscode-border); border-radius: 4px; padding: 20px;">
|
|
<h2 style="margin-top: 0; margin-bottom: 16px; font-size: 16px;">System Health</h2>
|
|
<div style="font-size: 12px;">
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
|
<span>Component Coverage</span>
|
|
<div style="width: 150px; height: 6px; background: var(--vscode-bg); border-radius: 3px; overflow: hidden;">
|
|
<div style="width: 69%; height: 100%; background: #4caf50;"></div>
|
|
</div>
|
|
<span>69%</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;">
|
|
<span>Token Coverage</span>
|
|
<div style="width: 150px; height: 6px; background: var(--vscode-bg); border-radius: 3px; overflow: hidden;">
|
|
<div style="width: 85%; height: 100%; background: #2196f3;"></div>
|
|
</div>
|
|
<span>85%</span>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
<span>Documentation</span>
|
|
<div style="width: 150px; height: 6px; background: var(--vscode-bg); border-radius: 3px; overflow: hidden;">
|
|
<div style="width: 92%; height: 100%; background: #ff9800;"></div>
|
|
</div>
|
|
<span>92%</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
renderMetricCard(title, value, color, subtitle) {
|
|
return `
|
|
<div style="
|
|
background: var(--vscode-sidebar);
|
|
border: 1px solid var(--vscode-border);
|
|
border-radius: 4px;
|
|
padding: 16px;
|
|
border-top: 3px solid ${color};
|
|
">
|
|
<div style="color: var(--vscode-text-dim); font-size: 11px; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px;">
|
|
${title}
|
|
</div>
|
|
<div style="font-size: 32px; font-weight: 600; margin-bottom: 4px; color: ${color};">
|
|
${value}
|
|
</div>
|
|
<div style="color: var(--vscode-text-dim); font-size: 11px;">
|
|
${subtitle}
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
|
|
customElements.define('ds-metrics-dashboard', MetricsDashboard);
|