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:
204
admin-ui/js/components/metrics/ds-metrics-dashboard.js
Normal file
204
admin-ui/js/components/metrics/ds-metrics-dashboard.js
Normal file
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* 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);
|
||||
Reference in New Issue
Block a user