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:
256
admin-ui/js/services/dashboard-service.js
Normal file
256
admin-ui/js/services/dashboard-service.js
Normal file
@@ -0,0 +1,256 @@
|
||||
/**
|
||||
* 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;
|
||||
Reference in New Issue
Block a user