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
257 lines
7.3 KiB
JavaScript
257 lines
7.3 KiB
JavaScript
/**
|
|
* Dashboard Service
|
|
*
|
|
* Handles team dashboard data fetching and management
|
|
* - UX Dashboard: Figma files and component tokens
|
|
* - UI Dashboard: Token drift detection and code metrics
|
|
* - QA Dashboard: ESRE definitions and test results
|
|
*/
|
|
|
|
const API_BASE = '/api';
|
|
|
|
export class DashboardService {
|
|
/**
|
|
* Get aggregated dashboard summary for all teams
|
|
*/
|
|
static async getDashboardSummary(projectId) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/dashboard/summary`);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch dashboard summary: ${response.statusText}`);
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error fetching dashboard summary:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// UX DASHBOARD - Figma Files
|
|
// ============================================
|
|
|
|
/**
|
|
* List all Figma files for a project
|
|
*/
|
|
static async listFigmaFiles(projectId) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/figma-files`);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch Figma files: ${response.statusText}`);
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error fetching Figma files:', error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add a new Figma file to a project
|
|
*/
|
|
static async addFigmaFile(projectId, figmaData) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/figma-files`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(figmaData)
|
|
});
|
|
if (!response.ok) {
|
|
const error = await response.json();
|
|
throw new Error(error.detail || 'Failed to add Figma file');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error adding Figma file:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update Figma file sync status
|
|
*/
|
|
static async updateFigmaFileSync(projectId, fileId, syncStatus) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/figma-files/${fileId}/sync`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({
|
|
sync_status: syncStatus,
|
|
last_synced: new Date().toISOString()
|
|
})
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error('Failed to update sync status');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error updating Figma sync status:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a Figma file
|
|
*/
|
|
static async deleteFigmaFile(projectId, fileId) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/figma-files/${fileId}`, {
|
|
method: 'DELETE'
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error('Failed to delete Figma file');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error deleting Figma file:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// UI DASHBOARD - Token Drift
|
|
// ============================================
|
|
|
|
/**
|
|
* List token drift issues for a project
|
|
*/
|
|
static async listTokenDrift(projectId, severity = null) {
|
|
try {
|
|
const url = severity
|
|
? `${API_BASE}/projects/${projectId}/token-drift?severity=${severity}`
|
|
: `${API_BASE}/projects/${projectId}/token-drift`;
|
|
|
|
const response = await fetch(url);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch token drift: ${response.statusText}`);
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error fetching token drift:', error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Record a new token drift issue
|
|
*/
|
|
static async recordTokenDrift(projectId, driftData) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/token-drift`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(driftData)
|
|
});
|
|
if (!response.ok) {
|
|
const error = await response.json();
|
|
throw new Error(error.detail || 'Failed to record token drift');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error recording token drift:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update token drift status (pending/fixed/ignored)
|
|
*/
|
|
static async updateTokenDriftStatus(projectId, driftId, status) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/token-drift/${driftId}/status`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ status })
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error('Failed to update token drift status');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error updating token drift status:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// QA DASHBOARD - ESRE Definitions
|
|
// ============================================
|
|
|
|
/**
|
|
* List all ESRE definitions for a project
|
|
*/
|
|
static async listESREDefinitions(projectId) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/esre`);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch ESRE definitions: ${response.statusText}`);
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error fetching ESRE definitions:', error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a new ESRE definition
|
|
*/
|
|
static async createESREDefinition(projectId, esreData) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/esre`, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(esreData)
|
|
});
|
|
if (!response.ok) {
|
|
const error = await response.json();
|
|
throw new Error(error.detail || 'Failed to create ESRE definition');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error creating ESRE definition:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update an ESRE definition
|
|
*/
|
|
static async updateESREDefinition(projectId, esreId, updateData) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/esre/${esreId}`, {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(updateData)
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error('Failed to update ESRE definition');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error updating ESRE definition:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete an ESRE definition
|
|
*/
|
|
static async deleteESREDefinition(projectId, esreId) {
|
|
try {
|
|
const response = await fetch(`${API_BASE}/projects/${projectId}/esre/${esreId}`, {
|
|
method: 'DELETE'
|
|
});
|
|
if (!response.ok) {
|
|
throw new Error('Failed to delete ESRE definition');
|
|
}
|
|
return await response.json();
|
|
} catch (error) {
|
|
console.error('Error deleting ESRE definition:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
}
|
|
|
|
export default DashboardService;
|