Files
dss/admin-ui/js/core/team-dashboards.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

460 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Team-Specific Dashboard Templates
*
* Each team (UI, UX, QA) gets a tailored dashboard with relevant metrics and actions
*/
export const UITeamDashboard = (health, stats, discovery, activity, projectName = 'Default Project', dashboardData = {}, projectId = null, app = null) => {
const uiData = dashboardData.ui || { token_drift: { total: 0, by_severity: {} }, code_metrics: {} };
const tokenDrift = uiData.token_drift || { total: 0, by_severity: {} };
return `
<div class="page-header">
<h1>UI Team Dashboard</h1>
<p class="text-muted">Component library & Figma sync tools · <strong class="text-primary">${projectName}</strong></p>
</div>
<!-- Key Metrics -->
<div class="grid grid-cols-4 gap-4 mt-6">
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Components</div>
<div class="stat__value">${stats.components?.total || discovery.files?.components || 0}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Token Drift Issues</div>
<div class="stat__value">${tokenDrift.total || 0}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Critical Issues</div>
<div class="stat__value">${tokenDrift.by_severity?.critical || 0}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Warnings</div>
<div class="stat__value">${tokenDrift.by_severity?.warning || 0}</div>
</div>
</ds-card-content>
</ds-card>
</div>
<!-- Quick Actions -->
<div class="grid grid-cols-2 gap-6 mt-6">
<ds-card>
<ds-card-header>
<ds-card-title>Figma Tools</ds-card-title>
<ds-card-description>Extract and sync from Figma</ds-card-description>
</ds-card-header>
<ds-card-content>
<div class="flex flex-col gap-3">
<ds-button variant="primary" data-action="extractTokens">
🎨 Extract Tokens from Figma
</ds-button>
<ds-button variant="outline" data-action="extractComponents">
📦 Extract Components
</ds-button>
<ds-button variant="outline" data-action="syncTokens">
🔄 Sync Tokens to File
</ds-button>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-header>
<ds-card-title>Component Generation</ds-card-title>
<ds-card-description>Generate code from designs</ds-card-description>
</ds-card-header>
<ds-card-content>
<div class="flex flex-col gap-3">
<ds-button variant="primary">
⚡ Generate Component Code
</ds-button>
<ds-button variant="outline">
📚 Generate Storybook Stories
</ds-button>
<ds-button variant="outline">
🎨 Generate Storybook Theme
</ds-button>
</div>
</ds-card-content>
</ds-card>
</div>
<!-- Recent Activity -->
<div class="mt-6">
<ds-card>
<ds-card-header>
<ds-card-title>Recent Syncs</ds-card-title>
</ds-card-header>
<ds-card-content>
${activity.length > 0 ? `
<div class="flex flex-col gap-3">
${activity.slice(0, 5).map(item => `
<div class="flex items-center gap-3 text-sm">
<span class="status-dot ${item.status === 'success' ? 'status-dot--success' : 'status-dot--error'}"></span>
<span class="flex-1">${item.message}</span>
<span class="text-muted text-xs">${new Date(item.timestamp).toLocaleTimeString()}</span>
</div>
`).join('')}
</div>
` : '<p class="text-muted text-sm">No recent activity</p>'}
</ds-card-content>
</ds-card>
</div>
`;
};
export const UXTeamDashboard = (health, stats, discovery, activity, projectName = 'Default Project', dashboardData = {}, projectId = null, app = null) => {
const uxData = dashboardData.ux || { figma_files_count: 0, figma_files: [] };
const figmaFiles = uxData.figma_files || [];
return `
<div class="page-header">
<h1>UX Team Dashboard</h1>
<p class="text-muted">Design consistency & token validation · <strong class="text-primary">${projectName}</strong></p>
</div>
<!-- Key Metrics -->
<div class="grid grid-cols-4 gap-4 mt-6">
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Figma Files</div>
<div class="stat__value">${uxData.figma_files_count || 0}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Synced Files</div>
<div class="stat__value">${figmaFiles.filter(f => f.sync_status === 'success').length}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Pending Sync</div>
<div class="stat__value">${figmaFiles.filter(f => f.sync_status === 'pending').length}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Design Tokens</div>
<div class="stat__value">${stats.tokens?.total || 0}</div>
</div>
</ds-card-content>
</ds-card>
</div>
<!-- Add New Figma File Form -->
<div class="mt-6">
<ds-card>
<ds-card-header>
<ds-card-title> Add Figma File</ds-card-title>
<ds-card-description>Configure Figma files for this project</ds-card-description>
</ds-card-header>
<ds-card-content>
<form id="add-figma-file-form" class="flex flex-col gap-3">
<div>
<label class="text-sm font-medium">File Name</label>
<input
type="text"
name="file_name"
placeholder="Design System Components"
required
class="w-full p-2 border rounded mt-1"
/>
</div>
<div>
<label class="text-sm font-medium">Figma URL</label>
<input
type="url"
name="figma_url"
placeholder="https://figma.com/file/..."
required
class="w-full p-2 border rounded mt-1"
/>
</div>
<div>
<label class="text-sm font-medium">File Key</label>
<input
type="text"
name="file_key"
placeholder="abc123xyz"
required
class="w-full p-2 border rounded mt-1"
/>
<p class="text-xs text-muted mt-1">Extract from Figma URL: figma.com/file/<strong>FILE_KEY</strong>/...</p>
</div>
<ds-button type="submit" variant="primary" class="w-full">
Add Figma File
</ds-button>
</form>
</ds-card-content>
</ds-card>
</div>
<!-- Figma Files List -->
<div class="mt-6">
<ds-card>
<ds-card-header>
<ds-card-title>Figma Files (${figmaFiles.length})</ds-card-title>
<ds-card-description>Manage Figma files for this project</ds-card-description>
</ds-card-header>
<ds-card-content>
${figmaFiles.length === 0 ? `
<p class="text-muted text-sm text-center py-8">
No Figma files configured yet. Add your first file above! 👆
</p>
` : `
<div class="flex flex-col gap-3">
${figmaFiles.map(file => {
const statusColors = {
pending: 'text-muted',
syncing: 'text-warning',
success: 'text-success',
error: 'text-destructive'
};
const statusIcons = {
pending: '⏳',
syncing: '🔄',
success: '✓',
error: '❌'
};
return `
<div class="flex items-center gap-3 p-3 rounded border">
<span class="text-2xl">${statusIcons[file.sync_status] || '📄'}</span>
<div class="flex-1">
<div class="font-medium">${file.file_name}</div>
<div class="text-xs text-muted">Key: ${file.file_key}</div>
<div class="text-xs ${statusColors[file.sync_status] || 'text-muted'}">
Status: ${file.sync_status || 'pending'}
${file.last_synced ? `· Last synced: ${new Date(file.last_synced).toLocaleString()}` : ''}
</div>
</div>
<div class="flex gap-2">
<ds-button
variant="outline"
size="sm"
data-action="sync-figma-file"
data-file-id="${file.id}"
>
🔄 Sync
</ds-button>
<ds-button
variant="ghost"
size="sm"
data-action="delete-figma-file"
data-file-id="${file.id}"
>
🗑️
</ds-button>
</div>
</div>
`;
}).join('')}
</div>
`}
</ds-card-content>
</ds-card>
</div>
`;
};
export const QATeamDashboard = (health, stats, discovery, activity, projectName = 'Default Project', dashboardData = {}, projectId = null, app = null) => {
const healthScore = discovery.health?.score || 0;
const healthGrade = discovery.health?.grade || '-';
const qaData = dashboardData.qa || { esre_count: 0, test_summary: {} };
return `
<div class="page-header">
<h1>QA Team Dashboard</h1>
<p class="text-muted">Testing, validation & quality metrics · <strong class="text-primary">${projectName}</strong></p>
</div>
<!-- Key Metrics -->
<div class="grid grid-cols-4 gap-4 mt-6">
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Health Score</div>
<div class="stat__value flex items-center gap-2">
<span class="status-dot ${healthScore >= 80 ? 'status-dot--success' : healthScore >= 60 ? 'status-dot--warning' : 'status-dot--error'}"></span>
${healthScore}% (${healthGrade})
</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">ESRE Definitions</div>
<div class="stat__value">${qaData.esre_count || 0}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Tests Run</div>
<div class="stat__value">${qaData.test_summary?.total_tests || 0}</div>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-content>
<div class="stat">
<div class="stat__label">Tests Passed</div>
<div class="stat__value">${qaData.test_summary?.passed_tests || 0}</div>
</div>
</ds-card-content>
</ds-card>
</div>
<!-- Quick Actions -->
<div class="grid grid-cols-2 gap-6 mt-6">
<ds-card>
<ds-card-header>
<ds-card-title>Quality Analysis</ds-card-title>
<ds-card-description>Find issues and improvements</ds-card-description>
</ds-card-header>
<ds-card-content>
<div class="flex flex-col gap-3">
<ds-button variant="primary" data-action="navigate-quick-wins">
⚡ Get Quick Wins
</ds-button>
<ds-button variant="outline">
🔍 Find Unused Styles
</ds-button>
<ds-button variant="outline">
📍 Find Inline Styles
</ds-button>
</div>
</ds-card-content>
</ds-card>
<ds-card>
<ds-card-header>
<ds-card-title>Validation</ds-card-title>
<ds-card-description>Check compliance and quality</ds-card-description>
</ds-card-header>
<ds-card-content>
<div class="flex flex-col gap-3">
<ds-button variant="primary" data-action="validateComponents">
✅ Validate Components
</ds-button>
<ds-button variant="outline">
📊 Analyze React Components
</ds-button>
<ds-button variant="outline">
🎯 Check Story Coverage
</ds-button>
</div>
</ds-card-content>
</ds-card>
</div>
<!-- Add New ESRE Definition Form -->
<div class="mt-6">
<ds-card>
<ds-card-header>
<ds-card-title> Add ESRE Definition</ds-card-title>
<ds-card-description>Define Expected State Requirements for components</ds-card-description>
</ds-card-header>
<ds-card-content>
<form id="add-esre-form" class="flex flex-col gap-3">
<div>
<label class="text-sm font-medium">Name</label>
<input
type="text"
name="name"
placeholder="Button Color Test"
required
class="w-full p-2 border rounded mt-1"
/>
</div>
<div>
<label class="text-sm font-medium">Component Name (Optional)</label>
<input
type="text"
name="component_name"
placeholder="Button"
class="w-full p-2 border rounded mt-1"
/>
</div>
<div>
<label class="text-sm font-medium">Definition (Natural Language)</label>
<textarea
name="definition_text"
placeholder="Primary button background should use the primary-500 token"
required
rows="3"
class="w-full p-2 border rounded mt-1"
></textarea>
</div>
<div>
<label class="text-sm font-medium">Expected Value (Optional)</label>
<input
type="text"
name="expected_value"
placeholder="var(--primary-500)"
class="w-full p-2 border rounded mt-1"
/>
</div>
<ds-button type="submit" variant="primary" class="w-full">
Add ESRE Definition
</ds-button>
</form>
</ds-card-content>
</ds-card>
</div>
<!-- ESRE Definitions List -->
<div class="mt-6">
<ds-card>
<ds-card-header>
<ds-card-title>ESRE Definitions (${qaData.esre_count || 0})</ds-card-title>
<ds-card-description>Expected State Requirements for testing</ds-card-description>
</ds-card-header>
<ds-card-content>
${qaData.esre_count === 0 ? `
<p class="text-muted text-sm text-center py-8">
No ESRE definitions yet. Add your first definition above! 👆
</p>
` : `
<p class="text-muted text-sm text-center py-4">
Use the API to list ESRE definitions for this project.
</p>
`}
</ds-card-content>
</ds-card>
</div>
`;
};