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:
241
admin-ui/js/services/team-service.js
Normal file
241
admin-ui/js/services/team-service.js
Normal file
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* Design System Server (DSS) - Team Service
|
||||
*
|
||||
* Multi-team management with RBAC handling team operations,
|
||||
* role management, and permissions.
|
||||
*/
|
||||
|
||||
// Role definitions with permissions
|
||||
const ROLES = {
|
||||
SUPER_ADMIN: {
|
||||
name: 'Super Admin',
|
||||
description: 'Full system access',
|
||||
permissions: ['*'],
|
||||
level: 100
|
||||
},
|
||||
TEAM_LEAD: {
|
||||
name: 'Team Lead',
|
||||
description: 'Full team access, can manage members',
|
||||
permissions: [
|
||||
'read', 'write', 'delete',
|
||||
'sync_tokens', 'sync_components',
|
||||
'manage_team_members', 'invite_users',
|
||||
'configure_figma', 'run_visual_diff',
|
||||
'generate_code', 'export_tokens'
|
||||
],
|
||||
level: 80
|
||||
},
|
||||
DEVELOPER: {
|
||||
name: 'Developer',
|
||||
description: 'Read/write access, can sync and generate',
|
||||
permissions: [
|
||||
'read', 'write',
|
||||
'sync_tokens', 'sync_components',
|
||||
'generate_code', 'export_tokens',
|
||||
'run_visual_diff'
|
||||
],
|
||||
level: 50
|
||||
},
|
||||
VIEWER: {
|
||||
name: 'Viewer',
|
||||
description: 'Read-only access',
|
||||
permissions: ['read', 'export_tokens'],
|
||||
level: 10
|
||||
}
|
||||
};
|
||||
|
||||
class TeamService {
|
||||
constructor() {
|
||||
this.apiBase = '/api/teams';
|
||||
this.useMock = false;
|
||||
this.currentUser = null;
|
||||
this.currentTeam = null;
|
||||
}
|
||||
|
||||
// === Role Management ===
|
||||
|
||||
getRoles() {
|
||||
return ROLES;
|
||||
}
|
||||
|
||||
getRole(roleKey) {
|
||||
return ROLES[roleKey];
|
||||
}
|
||||
|
||||
hasPermission(userRole, permission) {
|
||||
const role = ROLES[userRole];
|
||||
if (!role) return false;
|
||||
if (role.permissions.includes('*')) return true;
|
||||
return role.permissions.includes(permission);
|
||||
}
|
||||
|
||||
canManage(managerRole, targetRole) {
|
||||
const manager = ROLES[managerRole];
|
||||
const target = ROLES[targetRole];
|
||||
if (!manager || !target) return false;
|
||||
return manager.level > target.level;
|
||||
}
|
||||
|
||||
// === Team Operations ===
|
||||
|
||||
async getTeams() {
|
||||
if (this.useMock) {
|
||||
await this._delay(300);
|
||||
return this._getMockTeams();
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async getTeam(teamId) {
|
||||
if (this.useMock) {
|
||||
await this._delay(200);
|
||||
const teams = this._getMockTeams();
|
||||
return teams.find(t => t.id === teamId);
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async createTeam(data) {
|
||||
if (this.useMock) {
|
||||
await this._delay(400);
|
||||
return {
|
||||
id: `team-${Date.now()}`,
|
||||
...data,
|
||||
createdAt: new Date().toISOString(),
|
||||
members: []
|
||||
};
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async updateTeam(teamId, data) {
|
||||
if (this.useMock) {
|
||||
await this._delay(300);
|
||||
return { id: teamId, ...data, updatedAt: new Date().toISOString() };
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// === Member Management ===
|
||||
|
||||
async getTeamMembers(teamId) {
|
||||
if (this.useMock) {
|
||||
await this._delay(200);
|
||||
return this._getMockMembers(teamId);
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}/members`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async addTeamMember(teamId, email, role) {
|
||||
if (this.useMock) {
|
||||
await this._delay(400);
|
||||
return {
|
||||
id: `member-${Date.now()}`,
|
||||
email,
|
||||
role,
|
||||
teamId,
|
||||
status: 'pending',
|
||||
invitedAt: new Date().toISOString()
|
||||
};
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}/members`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, role })
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async updateMemberRole(teamId, memberId, role) {
|
||||
if (this.useMock) {
|
||||
await this._delay(300);
|
||||
return { id: memberId, role, updatedAt: new Date().toISOString() };
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}/members/${memberId}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ role })
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async removeMember(teamId, memberId) {
|
||||
if (this.useMock) {
|
||||
await this._delay(300);
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}/members/${memberId}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// === Team Settings ===
|
||||
|
||||
async getTeamSettings(teamId) {
|
||||
if (this.useMock) {
|
||||
await this._delay(200);
|
||||
return this._getMockTeamSettings(teamId);
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}/settings`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async updateTeamSettings(teamId, settings) {
|
||||
if (this.useMock) {
|
||||
await this._delay(300);
|
||||
return { ...settings, updatedAt: new Date().toISOString() };
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}/settings`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(settings)
|
||||
});
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// === Dashboard Data ===
|
||||
|
||||
async getTeamDashboard(teamId) {
|
||||
if (this.useMock) {
|
||||
await this._delay(400);
|
||||
return this._getMockDashboard(teamId);
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/${teamId}/dashboard`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async getAdminDashboard() {
|
||||
if (this.useMock) {
|
||||
await this._delay(500);
|
||||
return this._getMockAdminDashboard();
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.apiBase}/admin/dashboard`);
|
||||
return response.json();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user