smartui-migration-tool
Version:
Enterprise-grade CLI tool for migrating visual testing platforms to LambdaTest SmartUI
834 lines (723 loc) ⢠28.7 kB
JavaScript
const { Command, Flags } = require('@oclif/core');
const chalk = require('chalk');
const fs = require('fs-extra');
const path = require('path');
const glob = require('glob');
class EnterpriseDashboard extends Command {
static description = 'Enterprise dashboard with advanced analytics, reporting, and team collaboration features';
static flags = {
path: Flags.string({
char: 'p',
description: 'Path to analyze (default: current directory)',
default: process.cwd()
}),
include: Flags.string({
char: 'i',
description: 'File patterns to include (comma-separated)',
default: '**/*.{js,ts,jsx,tsx,py,java,cs}'
}),
exclude: Flags.string({
char: 'e',
description: 'File patterns to exclude (comma-separated)',
default: 'node_modules/**,dist/**,build/**,*.min.js'
}),
dashboard: Flags.string({
char: 'd',
description: 'Dashboard type to display',
options: ['overview', 'analytics', 'reports', 'team', 'settings', 'all'],
default: 'overview'
}),
format: Flags.string({
char: 'f',
description: 'Output format',
options: ['console', 'json', 'html', 'pdf'],
default: 'console'
}),
output: Flags.string({
char: 'o',
description: 'Output file for dashboard data',
default: 'enterprise-dashboard.json'
}),
team: Flags.string({
char: 't',
description: 'Team configuration file',
default: 'team-config.json'
}),
metrics: Flags.boolean({
char: 'm',
description: 'Include detailed metrics',
default: true
}),
realtime: Flags.boolean({
char: 'r',
description: 'Enable real-time updates',
default: false
}),
verbose: Flags.boolean({
char: 'v',
description: 'Enable verbose output',
default: false
})
};
async run() {
const { flags } = await this.parse(EnterpriseDashboard);
console.log(chalk.blue.bold('\nš¢ Enterprise Dashboard'));
console.log(chalk.gray(`Generating ${flags.dashboard} dashboard in ${flags.format} format...\n`));
try {
// Create enterprise dashboard
const dashboard = this.createEnterpriseDashboard(flags);
// Find files to analyze
const files = await this.findFiles(flags);
// Generate dashboard data
const results = await this.generateDashboardData(files, flags, dashboard);
// Display results
this.displayResults(results, flags.verbose);
// Save results
await this.saveResults(results, flags.output);
console.log(chalk.green(`\nā
Dashboard data saved to: ${flags.output}`));
} catch (error) {
console.error(chalk.red(`\nā Error generating dashboard: ${error.message}`));
this.exit(1);
}
}
createEnterpriseDashboard(flags) {
return {
// Overview Dashboard
generateOverview: async (data) => {
return {
title: 'Migration Overview',
timestamp: new Date().toISOString(),
summary: {
totalProjects: data.projects.length,
completedMigrations: data.projects.filter(p => p.status === 'completed').length,
inProgressMigrations: data.projects.filter(p => p.status === 'in-progress').length,
pendingMigrations: data.projects.filter(p => p.status === 'pending').length,
totalFiles: data.files.length,
totalLines: data.files.reduce((sum, f) => sum + f.lines, 0),
totalIssues: data.issues.length,
criticalIssues: data.issues.filter(i => i.severity === 'critical').length
},
metrics: {
migrationProgress: this.calculateMigrationProgress(data.projects),
codeQuality: this.calculateCodeQuality(data.files),
teamProductivity: this.calculateTeamProductivity(data.team),
riskAssessment: this.calculateRiskAssessment(data.issues)
}
};
},
// Analytics Dashboard
generateAnalytics: async (data) => {
return {
title: 'Advanced Analytics',
timestamp: new Date().toISOString(),
trends: {
migrationVelocity: this.calculateMigrationVelocity(data.projects),
codeQualityTrends: this.calculateCodeQualityTrends(data.files),
teamPerformance: this.calculateTeamPerformance(data.team),
issueResolution: this.calculateIssueResolution(data.issues)
},
insights: {
topIssues: this.getTopIssues(data.issues),
performanceBottlenecks: this.getPerformanceBottlenecks(data.files),
securityVulnerabilities: this.getSecurityVulnerabilities(data.issues),
codeDuplication: this.getCodeDuplication(data.files)
},
predictions: {
completionTime: this.predictCompletionTime(data.projects),
riskFactors: this.predictRiskFactors(data.issues),
resourceNeeds: this.predictResourceNeeds(data.team)
}
};
},
// Reports Dashboard
generateReports: async (data) => {
return {
title: 'Comprehensive Reports',
timestamp: new Date().toISOString(),
reports: {
migrationReport: this.generateMigrationReport(data.projects),
qualityReport: this.generateQualityReport(data.files),
securityReport: this.generateSecurityReport(data.issues),
teamReport: this.generateTeamReport(data.team),
performanceReport: this.generatePerformanceReport(data.files)
},
exports: {
csv: this.generateCSVExport(data),
pdf: this.generatePDFExport(data),
html: this.generateHTMLExport(data)
}
};
},
// Team Dashboard
generateTeam: async (data) => {
return {
title: 'Team Collaboration',
timestamp: new Date().toISOString(),
team: {
members: data.team.members,
roles: data.team.roles,
assignments: data.team.assignments,
performance: data.team.performance
},
collaboration: {
activeTasks: this.getActiveTasks(data.team),
codeReviews: this.getCodeReviews(data.team),
pullRequests: this.getPullRequests(data.team),
meetings: this.getMeetings(data.team)
},
communication: {
channels: this.getCommunicationChannels(data.team),
notifications: this.getNotifications(data.team),
updates: this.getUpdates(data.team)
}
};
},
// Settings Dashboard
generateSettings: async (data) => {
return {
title: 'Enterprise Settings',
timestamp: new Date().toISOString(),
configuration: {
migration: this.getMigrationSettings(data.config),
quality: this.getQualitySettings(data.config),
security: this.getSecuritySettings(data.config),
notifications: this.getNotificationSettings(data.config)
},
integrations: {
ci: this.getCIIntegrations(data.config),
monitoring: this.getMonitoringIntegrations(data.config),
reporting: this.getReportingIntegrations(data.config)
},
permissions: {
roles: this.getRolePermissions(data.config),
access: this.getAccessControls(data.config),
policies: this.getPolicies(data.config)
}
};
}
};
}
async generateDashboardData(files, flags, dashboard) {
const results = {
timestamp: new Date().toISOString(),
dashboard: flags.dashboard,
format: flags.format,
data: {},
summary: {}
};
// Analyze files
const fileData = await this.analyzeFiles(files);
// Generate mock data for demonstration
const mockData = this.generateMockData(fileData);
// Generate dashboard based on type
if (flags.dashboard === 'all' || flags.dashboard === 'overview') {
results.data.overview = await dashboard.generateOverview(mockData);
}
if (flags.dashboard === 'all' || flags.dashboard === 'analytics') {
results.data.analytics = await dashboard.generateAnalytics(mockData);
}
if (flags.dashboard === 'all' || flags.dashboard === 'reports') {
results.data.reports = await dashboard.generateReports(mockData);
}
if (flags.dashboard === 'all' || flags.dashboard === 'team') {
results.data.team = await dashboard.generateTeam(mockData);
}
if (flags.dashboard === 'all' || flags.dashboard === 'settings') {
results.data.settings = await dashboard.generateSettings(mockData);
}
// Generate summary
results.summary = this.generateSummary(results.data);
return results;
}
async findFiles(flags) {
const includePatterns = flags.include.split(',');
const excludePatterns = flags.exclude.split(',');
const files = [];
for (const pattern of includePatterns) {
const matches = glob.sync(pattern, {
cwd: flags.path,
absolute: true,
ignore: excludePatterns
});
files.push(...matches.map(file => ({ path: file })));
}
return files;
}
async analyzeFiles(files) {
const fileData = [];
for (const file of files) {
try {
const content = await fs.readFile(file.path, 'utf8');
const lines = content.split('\n').length;
const language = this.detectLanguage(file.path);
const framework = this.detectFramework(content);
fileData.push({
path: file.path,
language,
framework,
lines,
size: content.length,
complexity: this.calculateComplexity(content),
issues: this.detectIssues(content)
});
} catch (error) {
// Skip files that can't be read
}
}
return fileData;
}
detectLanguage(filePath) {
const ext = path.extname(filePath).toLowerCase();
const languageMap = {
'.js': 'javascript',
'.ts': 'typescript',
'.jsx': 'javascript',
'.tsx': 'typescript',
'.py': 'python',
'.java': 'java',
'.cs': 'csharp'
};
return languageMap[ext] || 'unknown';
}
detectFramework(content) {
if (content.includes('react') || content.includes('React')) return 'react';
if (content.includes('angular') || content.includes('Angular')) return 'angular';
if (content.includes('vue') || content.includes('Vue')) return 'vue';
if (content.includes('cypress') || content.includes('Cypress')) return 'cypress';
if (content.includes('playwright') || content.includes('Playwright')) return 'playwright';
return 'unknown';
}
calculateComplexity(content) {
const complexityKeywords = ['if', 'else', 'for', 'while', 'switch', 'case', 'catch', '&&', '||', '?'];
let complexity = 1;
for (const keyword of complexityKeywords) {
const regex = new RegExp(`\\b${keyword}\\b`, 'g');
const matches = content.match(regex);
if (matches) {
complexity += matches.length;
}
}
return complexity;
}
detectIssues(content) {
const issues = [];
// Detect common issues
if (content.includes('TODO') || content.includes('FIXME')) {
issues.push({ type: 'technical-debt', severity: 'low' });
}
if (content.includes('console.log')) {
issues.push({ type: 'debug-code', severity: 'low' });
}
if (content.includes('eval(')) {
issues.push({ type: 'security', severity: 'high' });
}
return issues;
}
generateMockData(fileData) {
return {
projects: [
{ id: 1, name: 'Project Alpha', status: 'completed', progress: 100, team: 'Team A' },
{ id: 2, name: 'Project Beta', status: 'in-progress', progress: 75, team: 'Team B' },
{ id: 3, name: 'Project Gamma', status: 'pending', progress: 0, team: 'Team C' }
],
files: fileData,
issues: [
{ id: 1, type: 'security', severity: 'critical', status: 'open', assignee: 'John Doe' },
{ id: 2, type: 'performance', severity: 'high', status: 'in-progress', assignee: 'Jane Smith' },
{ id: 3, type: 'quality', severity: 'medium', status: 'resolved', assignee: 'Bob Johnson' }
],
team: {
members: [
{ id: 1, name: 'John Doe', role: 'Lead Developer', status: 'active' },
{ id: 2, name: 'Jane Smith', role: 'QA Engineer', status: 'active' },
{ id: 3, name: 'Bob Johnson', role: 'DevOps Engineer', status: 'active' }
],
roles: ['Lead Developer', 'QA Engineer', 'DevOps Engineer', 'Product Manager'],
assignments: [
{ member: 'John Doe', project: 'Project Alpha', tasks: 5 },
{ member: 'Jane Smith', project: 'Project Beta', tasks: 3 },
{ member: 'Bob Johnson', project: 'Project Gamma', tasks: 2 }
],
performance: {
'John Doe': { velocity: 8.5, quality: 9.2, collaboration: 8.8 },
'Jane Smith': { velocity: 7.8, quality: 9.5, collaboration: 9.1 },
'Bob Johnson': { velocity: 9.1, quality: 8.9, collaboration: 8.7 }
}
},
config: {
migration: { strategy: 'incremental', rollback: true, validation: true },
quality: { thresholds: { coverage: 80, complexity: 10 }, tools: ['eslint', 'prettier'] },
security: { scanning: true, policies: ['owasp'], monitoring: true },
notifications: { email: true, slack: true, teams: false }
}
};
}
calculateMigrationProgress(projects) {
const total = projects.length;
const completed = projects.filter(p => p.status === 'completed').length;
return total > 0 ? (completed / total * 100).toFixed(1) : 0;
}
calculateCodeQuality(files) {
const totalFiles = files.length;
const filesWithIssues = files.filter(f => f.issues.length > 0).length;
const avgComplexity = files.reduce((sum, f) => sum + f.complexity, 0) / totalFiles;
return {
score: totalFiles > 0 ? ((totalFiles - filesWithIssues) / totalFiles * 100).toFixed(1) : 0,
averageComplexity: avgComplexity.toFixed(2),
filesWithIssues,
totalFiles
};
}
calculateTeamProductivity(team) {
const members = team.members.length;
const avgVelocity = Object.values(team.performance).reduce((sum, p) => sum + p.velocity, 0) / members;
const avgQuality = Object.values(team.performance).reduce((sum, p) => sum + p.quality, 0) / members;
return {
averageVelocity: avgVelocity.toFixed(2),
averageQuality: avgQuality.toFixed(2),
totalMembers: members,
activeMembers: team.members.filter(m => m.status === 'active').length
};
}
calculateRiskAssessment(issues) {
const critical = issues.filter(i => i.severity === 'critical').length;
const high = issues.filter(i => i.severity === 'high').length;
const medium = issues.filter(i => i.severity === 'medium').length;
const low = issues.filter(i => i.severity === 'low').length;
const riskScore = (critical * 4 + high * 3 + medium * 2 + low * 1) / (critical + high + medium + low);
return {
score: riskScore.toFixed(2),
level: riskScore > 3 ? 'high' : riskScore > 2 ? 'medium' : 'low',
breakdown: { critical, high, medium, low }
};
}
calculateMigrationVelocity(projects) {
// Mock calculation
return {
current: 2.5,
trend: 'increasing',
target: 3.0,
efficiency: 83.3
};
}
calculateCodeQualityTrends(files) {
// Mock calculation
return {
current: 85.2,
trend: 'improving',
target: 90.0,
improvement: 5.8
};
}
calculateTeamPerformance(team) {
const members = team.members.length;
const avgVelocity = Object.values(team.performance).reduce((sum, p) => sum + p.velocity, 0) / members;
const avgQuality = Object.values(team.performance).reduce((sum, p) => sum + p.quality, 0) / members;
return {
velocity: avgVelocity.toFixed(2),
quality: avgQuality.toFixed(2),
collaboration: (Object.values(team.performance).reduce((sum, p) => sum + p.collaboration, 0) / members).toFixed(2)
};
}
calculateIssueResolution(issues) {
const total = issues.length;
const resolved = issues.filter(i => i.status === 'resolved').length;
const inProgress = issues.filter(i => i.status === 'in-progress').length;
return {
resolutionRate: total > 0 ? (resolved / total * 100).toFixed(1) : 0,
inProgress: inProgress,
total: total
};
}
getTopIssues(issues) {
return issues
.sort((a, b) => {
const severityOrder = { critical: 4, high: 3, medium: 2, low: 1 };
return severityOrder[b.severity] - severityOrder[a.severity];
})
.slice(0, 5);
}
getPerformanceBottlenecks(files) {
return files
.filter(f => f.complexity > 10)
.sort((a, b) => b.complexity - a.complexity)
.slice(0, 5);
}
getSecurityVulnerabilities(issues) {
return issues.filter(i => i.type === 'security');
}
getCodeDuplication(files) {
// Mock calculation
return {
percentage: 12.5,
files: 8,
lines: 156
};
}
predictCompletionTime(projects) {
const inProgress = projects.filter(p => p.status === 'in-progress');
const avgProgress = inProgress.reduce((sum, p) => sum + p.progress, 0) / inProgress.length;
const remainingProgress = 100 - avgProgress;
const estimatedDays = Math.ceil(remainingProgress / 10); // Mock calculation
return {
estimatedDays,
confidence: 85,
factors: ['team velocity', 'complexity', 'dependencies']
};
}
predictRiskFactors(issues) {
const critical = issues.filter(i => i.severity === 'critical').length;
const high = issues.filter(i => i.severity === 'high').length;
return {
level: critical > 0 ? 'high' : high > 2 ? 'medium' : 'low',
factors: critical > 0 ? ['critical issues'] : high > 2 ? ['multiple high severity issues'] : ['low risk']
};
}
predictResourceNeeds(team) {
const activeMembers = team.members.filter(m => m.status === 'active').length;
const totalTasks = team.assignments.reduce((sum, a) => sum + a.tasks, 0);
return {
currentCapacity: activeMembers,
requiredCapacity: Math.ceil(totalTasks / 5), // Mock calculation
shortage: Math.max(0, Math.ceil(totalTasks / 5) - activeMembers)
};
}
generateMigrationReport(projects) {
return {
total: projects.length,
completed: projects.filter(p => p.status === 'completed').length,
inProgress: projects.filter(p => p.status === 'in-progress').length,
pending: projects.filter(p => p.status === 'pending').length,
averageProgress: projects.reduce((sum, p) => sum + p.progress, 0) / projects.length
};
}
generateQualityReport(files) {
const totalFiles = files.length;
const filesWithIssues = files.filter(f => f.issues.length > 0).length;
const avgComplexity = files.reduce((sum, f) => sum + f.complexity, 0) / totalFiles;
return {
totalFiles,
filesWithIssues,
averageComplexity: avgComplexity.toFixed(2),
qualityScore: totalFiles > 0 ? ((totalFiles - filesWithIssues) / totalFiles * 100).toFixed(1) : 0
};
}
generateSecurityReport(issues) {
const securityIssues = issues.filter(i => i.type === 'security');
const critical = securityIssues.filter(i => i.severity === 'critical').length;
const high = securityIssues.filter(i => i.severity === 'high').length;
return {
total: securityIssues.length,
critical,
high,
resolved: securityIssues.filter(i => i.status === 'resolved').length
};
}
generateTeamReport(team) {
const members = team.members.length;
const avgVelocity = Object.values(team.performance).reduce((sum, p) => sum + p.velocity, 0) / members;
const avgQuality = Object.values(team.performance).reduce((sum, p) => sum + p.quality, 0) / members;
return {
totalMembers: members,
activeMembers: team.members.filter(m => m.status === 'active').length,
averageVelocity: avgVelocity.toFixed(2),
averageQuality: avgQuality.toFixed(2),
totalTasks: team.assignments.reduce((sum, a) => sum + a.tasks, 0)
};
}
generatePerformanceReport(files) {
const totalLines = files.reduce((sum, f) => sum + f.lines, 0);
const avgComplexity = files.reduce((sum, f) => sum + f.complexity, 0) / files.length;
const highComplexityFiles = files.filter(f => f.complexity > 10).length;
return {
totalLines,
averageComplexity: avgComplexity.toFixed(2),
highComplexityFiles,
performanceScore: Math.max(0, 100 - (avgComplexity * 5)).toFixed(1)
};
}
generateCSVExport(data) {
// Mock CSV generation
return 'Project,Status,Progress,Team\nProject Alpha,completed,100,Team A\nProject Beta,in-progress,75,Team B\n';
}
generatePDFExport(data) {
// Mock PDF generation
return { pages: 5, size: '2.3MB', generated: new Date().toISOString() };
}
generateHTMLExport(data) {
// Mock HTML generation
return { file: 'dashboard.html', size: '1.8MB', generated: new Date().toISOString() };
}
getActiveTasks(team) {
return team.assignments.map(a => ({
member: a.member,
project: a.project,
tasks: a.tasks,
status: 'active'
}));
}
getCodeReviews(team) {
// Mock data
return [
{ id: 1, reviewer: 'John Doe', project: 'Project Alpha', status: 'pending' },
{ id: 2, reviewer: 'Jane Smith', project: 'Project Beta', status: 'approved' }
];
}
getPullRequests(team) {
// Mock data
return [
{ id: 1, author: 'John Doe', project: 'Project Alpha', status: 'open' },
{ id: 2, author: 'Jane Smith', project: 'Project Beta', status: 'merged' }
];
}
getMeetings(team) {
// Mock data
return [
{ id: 1, title: 'Sprint Planning', date: '2024-01-15', attendees: team.members.length },
{ id: 2, title: 'Code Review', date: '2024-01-16', attendees: team.members.length }
];
}
getCommunicationChannels(team) {
return ['Slack', 'Microsoft Teams', 'Email', 'Jira'];
}
getNotifications(team) {
return {
email: true,
slack: true,
teams: false,
jira: true
};
}
getUpdates(team) {
return [
{ id: 1, type: 'migration', message: 'Project Alpha migration completed', timestamp: new Date().toISOString() },
{ id: 2, type: 'issue', message: 'Critical security issue resolved', timestamp: new Date().toISOString() }
];
}
getMigrationSettings(config) {
return config.migration;
}
getQualitySettings(config) {
return config.quality;
}
getSecuritySettings(config) {
return config.security;
}
getNotificationSettings(config) {
return config.notifications;
}
getCIIntegrations(config) {
return ['Jenkins', 'GitHub Actions', 'Azure DevOps', 'CircleCI'];
}
getMonitoringIntegrations(config) {
return ['New Relic', 'DataDog', 'Splunk', 'Grafana'];
}
getReportingIntegrations(config) {
return ['Tableau', 'Power BI', 'Grafana', 'Custom Dashboard'];
}
getRolePermissions(config) {
return {
'Lead Developer': ['read', 'write', 'admin'],
'QA Engineer': ['read', 'write'],
'DevOps Engineer': ['read', 'write', 'deploy'],
'Product Manager': ['read', 'view']
};
}
getAccessControls(config) {
return {
projects: 'role-based',
reports: 'team-based',
settings: 'admin-only'
};
}
getPolicies(config) {
return {
codeQuality: 'enforced',
security: 'strict',
documentation: 'required'
};
}
generateSummary(data) {
const totalDashboards = Object.keys(data).length;
const hasOverview = data.overview ? 1 : 0;
const hasAnalytics = data.analytics ? 1 : 0;
const hasReports = data.reports ? 1 : 0;
const hasTeam = data.team ? 1 : 0;
const hasSettings = data.settings ? 1 : 0;
return {
totalDashboards,
components: { hasOverview, hasAnalytics, hasReports, hasTeam, hasSettings },
generated: new Date().toISOString()
};
}
async saveResults(results, outputFile) {
await fs.writeJson(outputFile, results, { spaces: 2 });
}
displayResults(results, verbose) {
console.log(chalk.green.bold('\nš¢ Enterprise Dashboard Results'));
console.log(chalk.gray('=' * 50));
// Summary
console.log(chalk.blue.bold('\nš Summary:'));
console.log(` Total dashboards: ${results.summary.totalDashboards}`);
console.log(` Components: ${Object.values(results.summary.components).reduce((sum, v) => sum + v, 0)}`);
console.log(` Generated: ${results.summary.generated}`);
// Overview Dashboard
if (results.data.overview) {
console.log(chalk.blue.bold('\nš Overview Dashboard:'));
const overview = results.data.overview;
console.log(` Projects: ${overview.summary.totalProjects}`);
console.log(` Completed: ${overview.summary.completedMigrations}`);
console.log(` In Progress: ${overview.summary.inProgressMigrations}`);
console.log(` Migration Progress: ${overview.metrics.migrationProgress}%`);
console.log(` Code Quality: ${overview.metrics.codeQuality.score}%`);
console.log(` Team Productivity: ${overview.metrics.teamProductivity.averageVelocity}`);
console.log(` Risk Level: ${overview.metrics.riskAssessment.level}`);
}
// Analytics Dashboard
if (results.data.analytics) {
console.log(chalk.blue.bold('\nš Analytics Dashboard:'));
const analytics = results.data.analytics;
console.log(` Migration Velocity: ${analytics.trends.migrationVelocity.current}`);
console.log(` Code Quality Trend: ${analytics.trends.codeQualityTrends.trend}`);
console.log(` Team Performance: ${analytics.trends.teamPerformance.velocity}`);
console.log(` Issue Resolution: ${analytics.trends.issueResolution.resolutionRate}%`);
console.log(` Top Issues: ${analytics.insights.topIssues.length}`);
console.log(` Performance Bottlenecks: ${analytics.insights.performanceBottlenecks.length}`);
console.log(` Security Vulnerabilities: ${analytics.insights.securityVulnerabilities.length}`);
}
// Reports Dashboard
if (results.data.reports) {
console.log(chalk.blue.bold('\nš Reports Dashboard:'));
const reports = results.data.reports;
console.log(` Migration Report: ${reports.reports.migrationReport.total} projects`);
console.log(` Quality Report: ${reports.reports.qualityReport.qualityScore}% quality score`);
console.log(` Security Report: ${reports.reports.securityReport.total} security issues`);
console.log(` Team Report: ${reports.reports.teamReport.totalMembers} team members`);
console.log(` Performance Report: ${reports.reports.performanceReport.performanceScore}% performance score`);
}
// Team Dashboard
if (results.data.team) {
console.log(chalk.blue.bold('\nš„ Team Dashboard:'));
const team = results.data.team;
console.log(` Team Members: ${team.team.members.length}`);
console.log(` Active Tasks: ${team.collaboration.activeTasks.length}`);
console.log(` Code Reviews: ${team.collaboration.codeReviews.length}`);
console.log(` Pull Requests: ${team.collaboration.pullRequests.length}`);
console.log(` Meetings: ${team.collaboration.meetings.length}`);
}
// Settings Dashboard
if (results.data.settings) {
console.log(chalk.blue.bold('\nāļø Settings Dashboard:'));
const settings = results.data.settings;
console.log(` Migration Strategy: ${settings.configuration.migration.strategy}`);
console.log(` Quality Thresholds: ${settings.configuration.quality.thresholds.coverage}% coverage`);
console.log(` Security Scanning: ${settings.configuration.security.scanning ? 'enabled' : 'disabled'}`);
console.log(` Notifications: ${Object.keys(settings.configuration.notifications).filter(k => settings.configuration.notifications[k]).join(', ')}`);
}
if (verbose) {
console.log(chalk.blue.bold('\nš Detailed Results:'));
console.log(JSON.stringify(results, null, 2));
}
}
}
module.exports.default = EnterpriseDashboard;