@manojkmfsi/monodog 1.1.37 → 1.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/monodog-dashboard/dist/assets/index-C08ciT3A.js +20 -0
- package/monodog-dashboard/dist/assets/index-C08ciT3A.js.map +1 -0
- package/monodog-dashboard/dist/assets/index-Dc2vaUOq.css +1 -0
- package/monodog-dashboard/{index.html → dist/index.html} +2 -1
- package/monodog-dashboard/package.json +0 -3
- package/package.json +2 -2
- package/monodog-dashboard/THEME_SYSTEM.md +0 -309
- package/monodog-dashboard/__tests__/AuthCallbackPage.test.ts +0 -138
- package/monodog-dashboard/__tests__/ConfigInspector.test.ts +0 -33
- package/monodog-dashboard/__tests__/DependencyGraph.test.ts +0 -72
- package/monodog-dashboard/__tests__/HealthStatus.test.ts +0 -69
- package/monodog-dashboard/__tests__/LoginPage.test.ts +0 -79
- package/monodog-dashboard/__tests__/PackageDetail.test.ts +0 -22
- package/monodog-dashboard/__tests__/ReleaseManager.test.tsx +0 -510
- package/monodog-dashboard/__tests__/api-client.test.ts +0 -475
- package/monodog-dashboard/__tests__/components.test.ts +0 -117
- package/monodog-dashboard/__tests__/dashboard.utils.test.ts +0 -144
- package/monodog-dashboard/__tests__/dependency.utils.test.ts +0 -125
- package/monodog-dashboard/__tests__/monorepoService.unit.test.ts +0 -103
- package/monodog-dashboard/__tests__/packages.utils.test.ts +0 -37
- package/monodog-dashboard/__tests__/pages.test.ts +0 -103
- package/monodog-dashboard/package-lock.json +0 -4587
- package/monodog-dashboard/postcss.config.js +0 -6
- package/monodog-dashboard/src/components/App.tsx +0 -36
- package/monodog-dashboard/src/components/LoadingState.tsx +0 -18
- package/monodog-dashboard/src/components/PermissionGuard.tsx +0 -92
- package/monodog-dashboard/src/components/ProtectedRoute.tsx +0 -24
- package/monodog-dashboard/src/components/configuration/Configuration.tsx +0 -91
- package/monodog-dashboard/src/components/configuration/components/BrandingSettings.tsx +0 -128
- package/monodog-dashboard/src/components/configuration/components/ConfigurationHeader.tsx +0 -34
- package/monodog-dashboard/src/components/configuration/components/ConfigurationModal.tsx +0 -20
- package/monodog-dashboard/src/components/configuration/components/ConfigurationTabs.tsx +0 -30
- package/monodog-dashboard/src/components/configuration/components/FeatureToggles.tsx +0 -66
- package/monodog-dashboard/src/components/configuration/components/GeneralSettings.tsx +0 -77
- package/monodog-dashboard/src/components/configuration/components/MonorepoSettings.tsx +0 -179
- package/monodog-dashboard/src/components/configuration/components/index.ts +0 -8
- package/monodog-dashboard/src/components/configuration/types/config.types.ts +0 -52
- package/monodog-dashboard/src/components/configuration/utils/config.utils.tsx +0 -115
- package/monodog-dashboard/src/components/main-dashboard/Dashboard.tsx +0 -242
- package/monodog-dashboard/src/components/main-dashboard/Layout.tsx +0 -112
- package/monodog-dashboard/src/components/main-dashboard/components/Header.tsx +0 -47
- package/monodog-dashboard/src/components/main-dashboard/components/PackageDistribution.tsx +0 -35
- package/monodog-dashboard/src/components/main-dashboard/components/PackageSearchFilter.tsx +0 -47
- package/monodog-dashboard/src/components/main-dashboard/components/PackageTable.tsx +0 -87
- package/monodog-dashboard/src/components/main-dashboard/components/QuickActions.tsx +0 -60
- package/monodog-dashboard/src/components/main-dashboard/components/StatsCards.tsx +0 -73
- package/monodog-dashboard/src/components/main-dashboard/components/index.ts +0 -7
- package/monodog-dashboard/src/components/main-dashboard/types/dashboard.types.ts +0 -33
- package/monodog-dashboard/src/components/main-dashboard/utils/dashboard.utils.tsx +0 -70
- package/monodog-dashboard/src/components/modules/ci-integration/CIIntegration.tsx +0 -277
- package/monodog-dashboard/src/components/modules/ci-integration/components/BuildDetails.tsx +0 -228
- package/monodog-dashboard/src/components/modules/ci-integration/components/BuildList.tsx +0 -212
- package/monodog-dashboard/src/components/modules/ci-integration/components/BuildOverview.tsx +0 -158
- package/monodog-dashboard/src/components/modules/ci-integration/components/CIIntegrationHeader.tsx +0 -38
- package/monodog-dashboard/src/components/modules/ci-integration/components/ErrorState.tsx +0 -25
- package/monodog-dashboard/src/components/modules/ci-integration/components/LoadingState.tsx +0 -16
- package/monodog-dashboard/src/components/modules/ci-integration/components/PipelineStatus.tsx +0 -223
- package/monodog-dashboard/src/components/modules/ci-integration/components/index.ts +0 -8
- package/monodog-dashboard/src/components/modules/ci-integration/types/ci.types.ts +0 -97
- package/monodog-dashboard/src/components/modules/ci-integration/utils/ci.utils.tsx +0 -264
- package/monodog-dashboard/src/components/modules/config-inspector/ConfigInspector.tsx +0 -324
- package/monodog-dashboard/src/components/modules/config-inspector/components/ConfigEditor.tsx +0 -93
- package/monodog-dashboard/src/components/modules/config-inspector/components/ConfigInspectorHeader.tsx +0 -36
- package/monodog-dashboard/src/components/modules/config-inspector/components/ConfigPreview.tsx +0 -89
- package/monodog-dashboard/src/components/modules/config-inspector/components/ConfigSidebar.tsx +0 -141
- package/monodog-dashboard/src/components/modules/config-inspector/components/ConfigToolbar.tsx +0 -184
- package/monodog-dashboard/src/components/modules/config-inspector/components/ErrorState.tsx +0 -25
- package/monodog-dashboard/src/components/modules/config-inspector/components/LoadingState.tsx +0 -16
- package/monodog-dashboard/src/components/modules/config-inspector/components/ValidationPanel.tsx +0 -155
- package/monodog-dashboard/src/components/modules/config-inspector/components/index.ts +0 -9
- package/monodog-dashboard/src/components/modules/config-inspector/types/config.types.ts +0 -100
- package/monodog-dashboard/src/components/modules/config-inspector/utils/config.utils.tsx +0 -704
- package/monodog-dashboard/src/components/modules/dependency-graph/DependencyGraph.tsx +0 -224
- package/monodog-dashboard/src/components/modules/dependency-graph/components/CircularDependencies.tsx +0 -177
- package/monodog-dashboard/src/components/modules/dependency-graph/components/DependencyDetails.tsx +0 -192
- package/monodog-dashboard/src/components/modules/dependency-graph/components/DependencyGraphHeader.tsx +0 -30
- package/monodog-dashboard/src/components/modules/dependency-graph/components/DependencyList.tsx +0 -177
- package/monodog-dashboard/src/components/modules/dependency-graph/components/ErrorState.tsx +0 -25
- package/monodog-dashboard/src/components/modules/dependency-graph/components/GraphLegend.tsx +0 -89
- package/monodog-dashboard/src/components/modules/dependency-graph/components/GraphStats.tsx +0 -141
- package/monodog-dashboard/src/components/modules/dependency-graph/components/GraphToolbar.tsx +0 -107
- package/monodog-dashboard/src/components/modules/dependency-graph/components/GraphVisualization.tsx +0 -179
- package/monodog-dashboard/src/components/modules/dependency-graph/components/LoadingState.tsx +0 -16
- package/monodog-dashboard/src/components/modules/dependency-graph/components/index.ts +0 -11
- package/monodog-dashboard/src/components/modules/dependency-graph/types/dependency.types.ts +0 -105
- package/monodog-dashboard/src/components/modules/dependency-graph/utils/dependency.utils.tsx +0 -433
- package/monodog-dashboard/src/components/modules/health-status/HealthStatus.tsx +0 -739
- package/monodog-dashboard/src/components/modules/health-status/components/ErrorState.tsx +0 -25
- package/monodog-dashboard/src/components/modules/health-status/components/HealthActions.tsx +0 -122
- package/monodog-dashboard/src/components/modules/health-status/components/HealthAlerts.tsx +0 -151
- package/monodog-dashboard/src/components/modules/health-status/components/HealthMetrics.tsx +0 -132
- package/monodog-dashboard/src/components/modules/health-status/components/HealthStatusHeader.tsx +0 -30
- package/monodog-dashboard/src/components/modules/health-status/components/LoadingState.tsx +0 -16
- package/monodog-dashboard/src/components/modules/health-status/components/OverallHealthScore.tsx +0 -122
- package/monodog-dashboard/src/components/modules/health-status/components/PackageHealthList.tsx +0 -195
- package/monodog-dashboard/src/components/modules/health-status/types/health.types.ts +0 -80
- package/monodog-dashboard/src/components/modules/health-status/utils/health.utils.tsx +0 -220
- package/monodog-dashboard/src/components/modules/packages/PackageDetail.tsx +0 -255
- package/monodog-dashboard/src/components/modules/packages/PackagesOverview.tsx +0 -166
- package/monodog-dashboard/src/components/modules/packages/components/ConfigurationTab.tsx +0 -311
- package/monodog-dashboard/src/components/modules/packages/components/DependenciesTab.tsx +0 -154
- package/monodog-dashboard/src/components/modules/packages/components/ErrorState.tsx +0 -21
- package/monodog-dashboard/src/components/modules/packages/components/HealthMetricsTab.tsx +0 -275
- package/monodog-dashboard/src/components/modules/packages/components/LoadingState.tsx +0 -14
- package/monodog-dashboard/src/components/modules/packages/components/PackageDetailHeader.tsx +0 -167
- package/monodog-dashboard/src/components/modules/packages/components/PackageDetailTabs.tsx +0 -49
- package/monodog-dashboard/src/components/modules/packages/components/PackageStats.tsx +0 -70
- package/monodog-dashboard/src/components/modules/packages/components/PackagesTable.tsx +0 -163
- package/monodog-dashboard/src/components/modules/packages/components/RecentCommitsTab.tsx +0 -90
- package/monodog-dashboard/src/components/modules/packages/components/SearchAndFilter.tsx +0 -66
- package/monodog-dashboard/src/components/modules/packages/components/index.ts +0 -12
- package/monodog-dashboard/src/components/modules/packages/types/packages.types.ts +0 -101
- package/monodog-dashboard/src/components/modules/packages/utils/packages.utils.tsx +0 -178
- package/monodog-dashboard/src/components/pipeline/JobsList.tsx +0 -83
- package/monodog-dashboard/src/components/pipeline/LogViewer.tsx +0 -392
- package/monodog-dashboard/src/components/pipeline/PipelineManager.tsx +0 -562
- package/monodog-dashboard/src/components/pipeline/WorkflowRunsList.tsx +0 -272
- package/monodog-dashboard/src/components/pipeline/WorkflowTrigger.tsx +0 -182
- package/monodog-dashboard/src/components/pipeline/utils/pipeline.utils.tsx +0 -11
- package/monodog-dashboard/src/components/publish-control/PublishControl.tsx +0 -229
- package/monodog-dashboard/src/components/publish-control/components/ChangelogViewer.tsx +0 -103
- package/monodog-dashboard/src/components/publish-control/components/ErrorState.tsx +0 -23
- package/monodog-dashboard/src/components/publish-control/components/LoadingState.tsx +0 -10
- package/monodog-dashboard/src/components/publish-control/components/PackageReleaseTable.tsx +0 -140
- package/monodog-dashboard/src/components/publish-control/components/PublishHeader.tsx +0 -30
- package/monodog-dashboard/src/components/publish-control/components/QuickActionCards.tsx +0 -56
- package/monodog-dashboard/src/components/publish-control/components/ReleaseSchedule.tsx +0 -104
- package/monodog-dashboard/src/components/publish-control/components/index.ts +0 -8
- package/monodog-dashboard/src/components/publish-control/types/publish.types.ts +0 -39
- package/monodog-dashboard/src/components/publish-control/utils/publish.utils.ts +0 -59
- package/monodog-dashboard/src/components/release-manager/ReleaseManager.tsx +0 -342
- package/monodog-dashboard/src/components/release-manager/components/ChangesetPreview.tsx +0 -123
- package/monodog-dashboard/src/components/release-manager/components/ErrorState.tsx +0 -38
- package/monodog-dashboard/src/components/release-manager/components/LoadingState.tsx +0 -18
- package/monodog-dashboard/src/components/release-manager/components/PackageSelector.tsx +0 -137
- package/monodog-dashboard/src/components/release-manager/components/PublishConfirmation.tsx +0 -150
- package/monodog-dashboard/src/components/release-manager/components/ReleaseValidation.tsx +0 -138
- package/monodog-dashboard/src/components/release-manager/components/VersionBumpSelector.tsx +0 -142
- package/monodog-dashboard/src/components/release-manager/types/index.ts +0 -9
- package/monodog-dashboard/src/components/release-manager/types/release-manager.types.ts +0 -29
- package/monodog-dashboard/src/components/setup-guide/SetupGuide.tsx +0 -96
- package/monodog-dashboard/src/components/setup-guide/components/SetupHeader.tsx +0 -24
- package/monodog-dashboard/src/components/setup-guide/components/SetupModal.tsx +0 -24
- package/monodog-dashboard/src/components/setup-guide/components/SetupProgress.tsx +0 -29
- package/monodog-dashboard/src/components/setup-guide/components/StepContent.tsx +0 -272
- package/monodog-dashboard/src/components/setup-guide/components/StepNavigation.tsx +0 -62
- package/monodog-dashboard/src/components/setup-guide/components/index.ts +0 -6
- package/monodog-dashboard/src/components/setup-guide/types/setup.types.ts +0 -38
- package/monodog-dashboard/src/components/setup-guide/utils/setup.utils.ts +0 -79
- package/monodog-dashboard/src/constants/api-config.ts +0 -81
- package/monodog-dashboard/src/constants/index.ts +0 -9
- package/monodog-dashboard/src/constants/messages.ts +0 -40
- package/monodog-dashboard/src/icons/heroicons.ts +0 -65
- package/monodog-dashboard/src/icons/index.tsx +0 -1788
- package/monodog-dashboard/src/index.css +0 -175
- package/monodog-dashboard/src/main.tsx +0 -9
- package/monodog-dashboard/src/pages/AuthCallbackPage.tsx +0 -103
- package/monodog-dashboard/src/pages/CIPage.tsx +0 -6
- package/monodog-dashboard/src/pages/ConfigPage.tsx +0 -6
- package/monodog-dashboard/src/pages/DashboardPage.tsx +0 -6
- package/monodog-dashboard/src/pages/DependenciesPage.tsx +0 -6
- package/monodog-dashboard/src/pages/HealthPage.tsx +0 -6
- package/monodog-dashboard/src/pages/LoginPage.tsx +0 -77
- package/monodog-dashboard/src/pages/PackageDetailPage.tsx +0 -6
- package/monodog-dashboard/src/pages/PackagesPage.tsx +0 -6
- package/monodog-dashboard/src/pages/PipelinePage.tsx +0 -22
- package/monodog-dashboard/src/pages/PublishPage.tsx +0 -6
- package/monodog-dashboard/src/pages/ReleaseManagerPage.tsx +0 -9
- package/monodog-dashboard/src/pages/index.ts +0 -28
- package/monodog-dashboard/src/routes/AppRouter.tsx +0 -89
- package/monodog-dashboard/src/routes/AppRouterPages.tsx +0 -56
- package/monodog-dashboard/src/routes/index.ts +0 -10
- package/monodog-dashboard/src/routes/routes.config.ts +0 -94
- package/monodog-dashboard/src/services/api/api-client.ts +0 -189
- package/monodog-dashboard/src/services/api/index.ts +0 -30
- package/monodog-dashboard/src/services/api/types/api.types.ts +0 -63
- package/monodog-dashboard/src/services/auth-context.tsx +0 -344
- package/monodog-dashboard/src/services/monorepoService.ts +0 -733
- package/monodog-dashboard/src/services/permission-context.tsx +0 -193
- package/monodog-dashboard/src/theme/COMPONENT_UPDATES.md +0 -273
- package/monodog-dashboard/src/theme/INTEGRATION.md +0 -381
- package/monodog-dashboard/src/theme/README.md +0 -239
- package/monodog-dashboard/src/theme/examples.tsx +0 -386
- package/monodog-dashboard/src/theme/index.ts +0 -402
- package/monodog-dashboard/src/theme/migration-guide.md +0 -335
- package/monodog-dashboard/src/types/auth-context.types.ts +0 -51
- package/monodog-dashboard/src/types/component.types.ts +0 -96
- package/monodog-dashboard/src/types/icons.types.ts +0 -13
- package/monodog-dashboard/src/types/index.ts +0 -68
- package/monodog-dashboard/src/types/monorepo-service.types.ts +0 -53
- package/monodog-dashboard/src/types/permission-context.types.ts +0 -49
- package/monodog-dashboard/src/types/pipeline.types.ts +0 -89
- package/monodog-dashboard/src/types/routes.types.ts +0 -12
- package/monodog-dashboard/src/utils/cookies.ts +0 -47
- package/monodog-dashboard/tailwind.config.js +0 -68
- package/monodog-dashboard/tsconfig.app.json +0 -14
- package/monodog-dashboard/tsconfig.json +0 -17
- package/monodog-dashboard/tsconfig.node.json +0 -10
- package/monodog-dashboard/vite.config.ts +0 -9
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, useMemo } from 'react';
|
|
2
|
-
import { monorepoService } from '../../../services/monorepoService';
|
|
3
|
-
import { DASHBOARD_ERROR_MESSAGES } from '../../../constants/messages';
|
|
4
|
-
// Import sub-components
|
|
5
|
-
import {
|
|
6
|
-
LoadingState,
|
|
7
|
-
ErrorState,
|
|
8
|
-
DependencyGraphHeader,
|
|
9
|
-
GraphToolbar,
|
|
10
|
-
GraphVisualization,
|
|
11
|
-
DependencyList,
|
|
12
|
-
DependencyDetails,
|
|
13
|
-
GraphStats,
|
|
14
|
-
CircularDependencies,
|
|
15
|
-
GraphLegend,
|
|
16
|
-
} from './components';
|
|
17
|
-
|
|
18
|
-
// Import types and utilities
|
|
19
|
-
import { PackageNode } from './types/dependency.types';
|
|
20
|
-
import {
|
|
21
|
-
calculateGraphStats,
|
|
22
|
-
detectCircularDependencies,
|
|
23
|
-
sortPackages,
|
|
24
|
-
calculateLayout,
|
|
25
|
-
mapAllDependents,
|
|
26
|
-
} from './utils/dependency.utils';
|
|
27
|
-
import { LinkIcon } from '../../../icons/heroicons';
|
|
28
|
-
// Re-export types for backward compatibility
|
|
29
|
-
export type { PackageNode } from './types/dependency.types';
|
|
30
|
-
|
|
31
|
-
export default function DependencyGraph() {
|
|
32
|
-
// Fetch packages
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
const fetchPackages = async () => {
|
|
35
|
-
try {
|
|
36
|
-
setLoading(true);
|
|
37
|
-
const pkgs = await monorepoService.getPackages();
|
|
38
|
-
const dependentsMap = mapAllDependents(pkgs);
|
|
39
|
-
const packagesMap = pkgs.map(pkg => ({
|
|
40
|
-
...pkg, // Keep all existing package data
|
|
41
|
-
dependencies: {
|
|
42
|
-
...pkg.dependencies,
|
|
43
|
-
...pkg.devDependencies,
|
|
44
|
-
...pkg.peerDependencies,
|
|
45
|
-
},
|
|
46
|
-
dependents: dependentsMap[pkg.name],
|
|
47
|
-
}));
|
|
48
|
-
|
|
49
|
-
setPackages(packagesMap);
|
|
50
|
-
setError(null);
|
|
51
|
-
} catch (err) {
|
|
52
|
-
setError(DASHBOARD_ERROR_MESSAGES.FAILED_TO_FETCH_PACKAGES);
|
|
53
|
-
console.error('Error fetching packages:', err);
|
|
54
|
-
} finally {
|
|
55
|
-
setLoading(false);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
fetchPackages();
|
|
60
|
-
}, []);
|
|
61
|
-
// State management
|
|
62
|
-
const [loading, setLoading] = useState(false);
|
|
63
|
-
const [error, setError] = useState<string | null>(null);
|
|
64
|
-
const [packages, setPackages] = useState<PackageNode[]>([]);
|
|
65
|
-
|
|
66
|
-
// View state
|
|
67
|
-
const [viewMode, setViewMode] = useState<'graph' | 'list'>('graph');
|
|
68
|
-
const [layout, setLayout] = useState<'hierarchical' | 'circular' | 'force'>(
|
|
69
|
-
'hierarchical'
|
|
70
|
-
);
|
|
71
|
-
const [selectedPackage, setSelectedPackage] = useState<string | null>(null);
|
|
72
|
-
const [hoveredPackage, setHoveredPackage] = useState<string | null>(null);
|
|
73
|
-
const [showLegend, setShowLegend] = useState(true);
|
|
74
|
-
const [zoomLevel, setZoomLevel] = useState(1);
|
|
75
|
-
|
|
76
|
-
// List view state
|
|
77
|
-
const [sortBy, setSortBy] = useState<
|
|
78
|
-
'name' | 'dependencies' | 'dependents' | 'status'
|
|
79
|
-
>('name');
|
|
80
|
-
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc');
|
|
81
|
-
|
|
82
|
-
// Computed values
|
|
83
|
-
const layoutedPackages = useMemo(() => {
|
|
84
|
-
return calculateLayout(packages ?? [], layout, 800, 600);
|
|
85
|
-
}, [packages, layout]);
|
|
86
|
-
|
|
87
|
-
const sortedPackages = useMemo(() => {
|
|
88
|
-
return sortPackages(packages, sortBy, sortOrder);
|
|
89
|
-
}, [packages, sortBy, sortOrder]);
|
|
90
|
-
|
|
91
|
-
const stats = useMemo(() => {
|
|
92
|
-
return calculateGraphStats(packages);
|
|
93
|
-
}, [packages]);
|
|
94
|
-
|
|
95
|
-
const circularDependencies = useMemo(() => {
|
|
96
|
-
return detectCircularDependencies(packages);
|
|
97
|
-
}, [packages]);
|
|
98
|
-
|
|
99
|
-
const selectedPackageData = selectedPackage
|
|
100
|
-
? packages.find(pkg => pkg.name === selectedPackage) || null
|
|
101
|
-
: null;
|
|
102
|
-
|
|
103
|
-
// Event handlers
|
|
104
|
-
const handleRefresh = () => {
|
|
105
|
-
// In real implementation, this would refetch data
|
|
106
|
-
// console.log('Refreshing dependency graph...');
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const handlePackageSelect = (packageId: string | null) => {
|
|
110
|
-
setSelectedPackage(packageId);
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const handleSortChange = (field: string, order: 'asc' | 'desc') => {
|
|
114
|
-
setSortBy(field as any);
|
|
115
|
-
setSortOrder(order);
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const handleRetry = () => {
|
|
119
|
-
window.location.reload();
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
// Loading state
|
|
123
|
-
if (loading) {
|
|
124
|
-
return <LoadingState />;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// Error state
|
|
128
|
-
if (error) {
|
|
129
|
-
return <ErrorState error={error} onRetry={handleRetry} />;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return (
|
|
133
|
-
<div className="space-y-6">
|
|
134
|
-
{/* Header */}
|
|
135
|
-
<DependencyGraphHeader onRefresh={handleRefresh} loading={loading} />
|
|
136
|
-
|
|
137
|
-
{/* Stats */}
|
|
138
|
-
<GraphStats stats={stats} packages={packages ?? []} />
|
|
139
|
-
|
|
140
|
-
{/* Circular Dependencies Warning */}
|
|
141
|
-
{circularDependencies.length > 0 && (
|
|
142
|
-
<CircularDependencies
|
|
143
|
-
cycles={circularDependencies}
|
|
144
|
-
packages={packages}
|
|
145
|
-
onPackageSelect={handlePackageSelect}
|
|
146
|
-
/>
|
|
147
|
-
)}
|
|
148
|
-
|
|
149
|
-
{/* Toolbar */}
|
|
150
|
-
<GraphToolbar
|
|
151
|
-
viewMode={viewMode}
|
|
152
|
-
onViewModeChange={setViewMode}
|
|
153
|
-
layout={layout}
|
|
154
|
-
onLayoutChange={setLayout}
|
|
155
|
-
showLegend={showLegend}
|
|
156
|
-
onToggleLegend={() => setShowLegend(!showLegend)}
|
|
157
|
-
zoomLevel={zoomLevel}
|
|
158
|
-
onZoomChange={setZoomLevel}
|
|
159
|
-
/>
|
|
160
|
-
|
|
161
|
-
{/* Main Content */}
|
|
162
|
-
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
|
|
163
|
-
{/* Graph/List View */}
|
|
164
|
-
<div className={`${showLegend ? 'lg:col-span-3' : 'lg:col-span-4'}`}>
|
|
165
|
-
{viewMode === 'graph' ? (
|
|
166
|
-
<div className="relative">
|
|
167
|
-
<div
|
|
168
|
-
style={{
|
|
169
|
-
transform: `scale(${zoomLevel})`,
|
|
170
|
-
transformOrigin: 'top left',
|
|
171
|
-
}}
|
|
172
|
-
>
|
|
173
|
-
<GraphVisualization
|
|
174
|
-
packages={layoutedPackages}
|
|
175
|
-
selectedPackage={selectedPackage}
|
|
176
|
-
hoveredPackage={hoveredPackage}
|
|
177
|
-
onPackageSelect={handlePackageSelect}
|
|
178
|
-
onPackageHover={setHoveredPackage}
|
|
179
|
-
layout={layout}
|
|
180
|
-
/>
|
|
181
|
-
</div>
|
|
182
|
-
|
|
183
|
-
{/* Package Details Overlay */}
|
|
184
|
-
<DependencyDetails
|
|
185
|
-
package={selectedPackageData}
|
|
186
|
-
packages={packages}
|
|
187
|
-
onClose={() => setSelectedPackage(null)}
|
|
188
|
-
/>
|
|
189
|
-
</div>
|
|
190
|
-
) : (
|
|
191
|
-
<DependencyList
|
|
192
|
-
packages={sortedPackages}
|
|
193
|
-
selectedPackage={selectedPackage}
|
|
194
|
-
onPackageSelect={handlePackageSelect}
|
|
195
|
-
sortBy={sortBy}
|
|
196
|
-
sortOrder={sortOrder}
|
|
197
|
-
onSortChange={handleSortChange}
|
|
198
|
-
/>
|
|
199
|
-
)}
|
|
200
|
-
</div>
|
|
201
|
-
|
|
202
|
-
{/* Legend */}
|
|
203
|
-
{showLegend && (
|
|
204
|
-
<div className="lg:col-span-1">
|
|
205
|
-
<GraphLegend show={showLegend} />
|
|
206
|
-
</div>
|
|
207
|
-
)}
|
|
208
|
-
</div>
|
|
209
|
-
|
|
210
|
-
{/* Empty State */}
|
|
211
|
-
{/* {packages.length === 0 && !loading && (
|
|
212
|
-
<div className="text-center py-12">
|
|
213
|
-
<div className="flex justify-center text-gray-400 text-6xl mb-4"><LinkIcon className="w-6 h-6 text-primary-600" /></div>
|
|
214
|
-
<h3 className="text-lg font-medium text-gray-900 mb-2">
|
|
215
|
-
No dependencies found
|
|
216
|
-
</h3>
|
|
217
|
-
<p className="text-gray-600 mb-4">
|
|
218
|
-
No package dependencies available to display.
|
|
219
|
-
</p>
|
|
220
|
-
</div>
|
|
221
|
-
)} */}
|
|
222
|
-
</div>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ExclamationTriangleIcon,
|
|
3
|
-
ArrowRightIcon,
|
|
4
|
-
} from '../../../../icons/heroicons';
|
|
5
|
-
import { CircularDependenciesProps } from '../types/dependency.types';
|
|
6
|
-
import { Fragment } from 'react';
|
|
7
|
-
|
|
8
|
-
export default function CircularDependencies({
|
|
9
|
-
cycles,
|
|
10
|
-
packages,
|
|
11
|
-
onPackageSelect,
|
|
12
|
-
}: CircularDependenciesProps) {
|
|
13
|
-
const getSeverityColor = (severity: string) => {
|
|
14
|
-
switch (severity) {
|
|
15
|
-
case 'high':
|
|
16
|
-
return 'bg-red-100 text-red-800 border-red-200';
|
|
17
|
-
case 'medium':
|
|
18
|
-
return 'bg-yellow-100 text-yellow-800 border-yellow-200';
|
|
19
|
-
case 'low':
|
|
20
|
-
return 'bg-blue-100 text-blue-800 border-blue-200';
|
|
21
|
-
default:
|
|
22
|
-
return 'bg-gray-100 text-gray-800 border-gray-200';
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const getSeverityIcon = (severity: string) => {
|
|
27
|
-
switch (severity) {
|
|
28
|
-
case 'high':
|
|
29
|
-
return '🔴';
|
|
30
|
-
case 'medium':
|
|
31
|
-
return '🟡';
|
|
32
|
-
case 'low':
|
|
33
|
-
return '🔵';
|
|
34
|
-
default:
|
|
35
|
-
return '⚪';
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
if (cycles.length === 0) {
|
|
40
|
-
return (
|
|
41
|
-
<div className="bg-white p-6 rounded-lg shadow border">
|
|
42
|
-
<div className="flex items-center space-x-3 mb-4">
|
|
43
|
-
<div className="p-2 bg-green-100 rounded-lg">
|
|
44
|
-
<ExclamationTriangleIcon className="w-6 h-6 text-green-600" />
|
|
45
|
-
</div>
|
|
46
|
-
<div>
|
|
47
|
-
<h3 className="text-lg font-medium text-gray-900">
|
|
48
|
-
Circular Dependencies
|
|
49
|
-
</h3>
|
|
50
|
-
<p className="text-sm text-gray-600">Dependency cycle analysis</p>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
|
|
54
|
-
<div className="text-center py-8">
|
|
55
|
-
<div className="text-green-400 text-4xl mb-2"></div>
|
|
56
|
-
<h4 className="text-green-800 font-medium mb-1">
|
|
57
|
-
No Circular Dependencies!
|
|
58
|
-
</h4>
|
|
59
|
-
<p className="text-green-700 text-sm">
|
|
60
|
-
Your dependency graph is clean and free of circular references.
|
|
61
|
-
</p>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<div className="bg-white p-6 rounded-lg shadow border">
|
|
69
|
-
<div className="flex items-center space-x-3 mb-4">
|
|
70
|
-
<div className="p-2 bg-red-100 rounded-lg">
|
|
71
|
-
<ExclamationTriangleIcon className="w-6 h-6 text-red-600" />
|
|
72
|
-
</div>
|
|
73
|
-
<div>
|
|
74
|
-
<h3 className="text-lg font-medium text-gray-900">
|
|
75
|
-
Circular Dependencies
|
|
76
|
-
</h3>
|
|
77
|
-
<p className="text-sm text-gray-600">
|
|
78
|
-
Found {cycles.length} circular dependency cycle
|
|
79
|
-
{cycles.length > 1 ? 's' : ''}
|
|
80
|
-
</p>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
|
|
84
|
-
<div className="space-y-4">
|
|
85
|
-
{cycles.map((cycle, index) => (
|
|
86
|
-
<div
|
|
87
|
-
key={index}
|
|
88
|
-
className={`border rounded-lg p-4 ${getSeverityColor(cycle.severity)}`}
|
|
89
|
-
>
|
|
90
|
-
<div className="flex items-center justify-between mb-3">
|
|
91
|
-
<div className="flex items-center space-x-2">
|
|
92
|
-
<span className="text-lg">
|
|
93
|
-
{getSeverityIcon(cycle.severity)}
|
|
94
|
-
</span>
|
|
95
|
-
<span className="text-sm font-medium capitalize">
|
|
96
|
-
{cycle.severity} Severity
|
|
97
|
-
</span>
|
|
98
|
-
</div>
|
|
99
|
-
<span className="text-xs opacity-75">
|
|
100
|
-
{cycle.cycle.length} packages affected
|
|
101
|
-
</span>
|
|
102
|
-
</div>
|
|
103
|
-
|
|
104
|
-
<div className="mb-3">
|
|
105
|
-
<p className="text-sm mb-2">{cycle.impact}</p>
|
|
106
|
-
</div>
|
|
107
|
-
|
|
108
|
-
{/* Cycle Visualization */}
|
|
109
|
-
<div className="bg-white bg-opacity-50 rounded-lg p-3">
|
|
110
|
-
<div className="flex items-center flex-wrap gap-2">
|
|
111
|
-
{cycle.cycle.map((packageId, idx) => (
|
|
112
|
-
<Fragment key={`${packageId}-${idx}`}>
|
|
113
|
-
<button
|
|
114
|
-
onClick={() => onPackageSelect(packageId)}
|
|
115
|
-
className="px-3 py-1 bg-white rounded-lg text-sm font-medium hover:bg-gray-50 transition-colors border shadow-sm"
|
|
116
|
-
>
|
|
117
|
-
{packageId}
|
|
118
|
-
</button>
|
|
119
|
-
{idx < cycle.cycle.length - 1 && (
|
|
120
|
-
<ArrowRightIcon className="w-4 h-4 text-gray-400" />
|
|
121
|
-
)}
|
|
122
|
-
</Fragment>
|
|
123
|
-
))}
|
|
124
|
-
{/* Arrow back to start */}
|
|
125
|
-
{cycle.cycle.length > 1 && (
|
|
126
|
-
<>
|
|
127
|
-
<ArrowRightIcon className="w-4 h-4 text-gray-400" />
|
|
128
|
-
<span className="text-sm text-gray-500 italic">
|
|
129
|
-
(cycles back to {cycle.cycle[0]})
|
|
130
|
-
</span>
|
|
131
|
-
</>
|
|
132
|
-
)}
|
|
133
|
-
</div>
|
|
134
|
-
</div>
|
|
135
|
-
|
|
136
|
-
{/* Recommendations */}
|
|
137
|
-
<div className="mt-3 pt-3 border-t border-current border-opacity-20">
|
|
138
|
-
<h5 className="text-xs font-medium mb-1">Recommendation:</h5>
|
|
139
|
-
<p className="text-xs opacity-90">
|
|
140
|
-
{cycle.severity === 'high' &&
|
|
141
|
-
'Critical: Refactor immediately to break this cycle. Consider dependency inversion or splitting packages.'}
|
|
142
|
-
{cycle.severity === 'medium' &&
|
|
143
|
-
'Important: Plan to refactor this cycle. Review package boundaries and extract common dependencies.'}
|
|
144
|
-
{cycle.severity === 'low' &&
|
|
145
|
-
'Minor: Monitor this cycle. Consider if these packages could be merged or dependencies restructured.'}
|
|
146
|
-
</p>
|
|
147
|
-
</div>
|
|
148
|
-
</div>
|
|
149
|
-
))}
|
|
150
|
-
</div>
|
|
151
|
-
|
|
152
|
-
{/* Summary */}
|
|
153
|
-
<div className="mt-6 pt-4 border-t border-gray-200">
|
|
154
|
-
<div className="grid grid-cols-3 gap-4 text-center">
|
|
155
|
-
<div>
|
|
156
|
-
<div className="text-lg font-bold text-red-600">
|
|
157
|
-
{cycles.filter(c => c.severity === 'high').length}
|
|
158
|
-
</div>
|
|
159
|
-
<div className="text-xs text-gray-600">High Severity</div>
|
|
160
|
-
</div>
|
|
161
|
-
<div>
|
|
162
|
-
<div className="text-lg font-bold text-yellow-600">
|
|
163
|
-
{cycles.filter(c => c.severity === 'medium').length}
|
|
164
|
-
</div>
|
|
165
|
-
<div className="text-xs text-gray-600">Medium Severity</div>
|
|
166
|
-
</div>
|
|
167
|
-
<div>
|
|
168
|
-
<div className="text-lg font-bold text-blue-600">
|
|
169
|
-
{cycles.filter(c => c.severity === 'low').length}
|
|
170
|
-
</div>
|
|
171
|
-
<div className="text-xs text-gray-600">Low Severity</div>
|
|
172
|
-
</div>
|
|
173
|
-
</div>
|
|
174
|
-
</div>
|
|
175
|
-
</div>
|
|
176
|
-
);
|
|
177
|
-
}
|
package/monodog-dashboard/src/components/modules/dependency-graph/components/DependencyDetails.tsx
DELETED
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { Link } from 'react-router-dom';
|
|
2
|
-
import { XMarkIcon } from '../../../../icons/heroicons';
|
|
3
|
-
import { DependencyDetailsProps } from '../types/dependency.types';
|
|
4
|
-
import {
|
|
5
|
-
getStatusColor,
|
|
6
|
-
getTypeColor,
|
|
7
|
-
getDependencyStatusColor,
|
|
8
|
-
} from '../utils/dependency.utils';
|
|
9
|
-
|
|
10
|
-
export default function DependencyDetails({
|
|
11
|
-
package: pkg,
|
|
12
|
-
packages,
|
|
13
|
-
onClose,
|
|
14
|
-
}: DependencyDetailsProps) {
|
|
15
|
-
if (!pkg) return null;
|
|
16
|
-
|
|
17
|
-
return (
|
|
18
|
-
<div className="absolute top-4 right-4 bg-white p-4 rounded-lg shadow-lg border border-gray-200 w-80 max-h-[80vh] overflow-y-auto">
|
|
19
|
-
<div className="flex items-center justify-between mb-3">
|
|
20
|
-
<h3 className="text-lg font-medium text-gray-900">{pkg.name}</h3>
|
|
21
|
-
<button
|
|
22
|
-
onClick={onClose}
|
|
23
|
-
className="text-gray-400 hover:text-gray-600 transition-colors"
|
|
24
|
-
>
|
|
25
|
-
<XMarkIcon className="w-5 h-5" />
|
|
26
|
-
</button>
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<div className="space-y-4">
|
|
30
|
-
{/* Package Info */}
|
|
31
|
-
<div>
|
|
32
|
-
<div className="flex items-center space-x-2 mb-2">
|
|
33
|
-
<span
|
|
34
|
-
className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getTypeColor(pkg.type)}`}
|
|
35
|
-
>
|
|
36
|
-
{pkg.type}
|
|
37
|
-
</span>
|
|
38
|
-
<span
|
|
39
|
-
className={`inline-flex px-2 py-1 text-xs font-semibold rounded-full ${getStatusColor(pkg.status)}`}
|
|
40
|
-
>
|
|
41
|
-
{pkg.status}
|
|
42
|
-
</span>
|
|
43
|
-
</div>
|
|
44
|
-
<div className="text-sm text-gray-600">
|
|
45
|
-
Version: <span className="font-mono">{pkg.version}</span>
|
|
46
|
-
</div>
|
|
47
|
-
</div>
|
|
48
|
-
|
|
49
|
-
{/* Dependencies */}
|
|
50
|
-
<div>
|
|
51
|
-
<div className="flex items-center justify-between mb-2">
|
|
52
|
-
<h4 className="text-sm font-medium text-gray-700">Dependencies</h4>
|
|
53
|
-
<span className="text-xs text-gray-500">
|
|
54
|
-
({Object.keys(pkg.dependencies).length})
|
|
55
|
-
</span>
|
|
56
|
-
</div>
|
|
57
|
-
{Object.keys(pkg.dependencies).length > 0 ? (
|
|
58
|
-
<div className="space-y-1 max-h-32 overflow-y-auto">
|
|
59
|
-
{Object.keys(pkg.dependencies).map(depName => {
|
|
60
|
-
const dep = packages.find(p => p.name === depName);
|
|
61
|
-
return dep ? (
|
|
62
|
-
<div
|
|
63
|
-
key={depName}
|
|
64
|
-
className="flex items-center justify-between text-sm py-1"
|
|
65
|
-
>
|
|
66
|
-
<span className="text-gray-600 truncate">{dep.name}</span>
|
|
67
|
-
<div className="flex items-center space-x-1">
|
|
68
|
-
<span className="text-xs text-gray-400">
|
|
69
|
-
{dep.version}
|
|
70
|
-
</span>
|
|
71
|
-
<span
|
|
72
|
-
className={`${getDependencyStatusColor(depName, packages)} p-1`}
|
|
73
|
-
>
|
|
74
|
-
{dep.status === 'healthy'
|
|
75
|
-
? (<div className="w-2 h-2 bg-green-500 rounded-full"></div>)
|
|
76
|
-
: dep.status === 'warning'
|
|
77
|
-
? (<div className="w-2 h-2 bg-yellow-500 rounded-full"></div>)
|
|
78
|
-
: (<div className="w-2 h-2 bg-red-500 rounded-full"></div>)}
|
|
79
|
-
</span>
|
|
80
|
-
</div>
|
|
81
|
-
</div>
|
|
82
|
-
) : (
|
|
83
|
-
<div key={depName} className="text-sm text-gray-400 py-1">
|
|
84
|
-
{depName} (not found)
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
87
|
-
})}
|
|
88
|
-
</div>
|
|
89
|
-
) : (
|
|
90
|
-
<div className="text-sm text-gray-500 text-center py-2">
|
|
91
|
-
No dependencies
|
|
92
|
-
</div>
|
|
93
|
-
)}
|
|
94
|
-
</div>
|
|
95
|
-
|
|
96
|
-
{/* Dependents */}
|
|
97
|
-
<div>
|
|
98
|
-
<div className="flex items-center justify-between mb-2">
|
|
99
|
-
<h4 className="text-sm font-medium text-gray-700">Dependents</h4>
|
|
100
|
-
<span className="text-xs text-gray-500">
|
|
101
|
-
({pkg.dependents.length})
|
|
102
|
-
</span>
|
|
103
|
-
</div>
|
|
104
|
-
{pkg.dependents.length > 0 ? (
|
|
105
|
-
<div className="space-y-1 max-h-32 overflow-y-auto">
|
|
106
|
-
{pkg.dependents.map(depName => {
|
|
107
|
-
const dep = packages.find(p => p.name === depName);
|
|
108
|
-
return dep ? (
|
|
109
|
-
<div
|
|
110
|
-
key={depName}
|
|
111
|
-
className="flex items-center justify-between text-sm py-1"
|
|
112
|
-
>
|
|
113
|
-
<span className="text-gray-600 truncate">{dep.name}</span>
|
|
114
|
-
<div className="flex items-center space-x-1">
|
|
115
|
-
<span className="text-xs text-gray-400">
|
|
116
|
-
{dep.version}
|
|
117
|
-
</span>
|
|
118
|
-
<span
|
|
119
|
-
className={`${getDependencyStatusColor(depName, packages)} p-1`}
|
|
120
|
-
>
|
|
121
|
-
{dep.status === 'healthy'
|
|
122
|
-
? (<div className="w-2 h-2 bg-green-500 rounded-full"></div>)
|
|
123
|
-
: dep.status === 'warning'
|
|
124
|
-
? (<div className="w-2 h-2 bg-yellow-500 rounded-full"></div>)
|
|
125
|
-
: (<div className="w-2 h-2 bg-red-500 rounded-full"></div>)}
|
|
126
|
-
</span>
|
|
127
|
-
</div>
|
|
128
|
-
</div>
|
|
129
|
-
) : (
|
|
130
|
-
<div key={depName} className="text-sm text-gray-400 py-1">
|
|
131
|
-
{depName} (not found)
|
|
132
|
-
</div>
|
|
133
|
-
);
|
|
134
|
-
})}
|
|
135
|
-
</div>
|
|
136
|
-
) : (
|
|
137
|
-
<div className="text-sm text-gray-500 text-center py-2">
|
|
138
|
-
No dependents
|
|
139
|
-
</div>
|
|
140
|
-
)}
|
|
141
|
-
</div>
|
|
142
|
-
|
|
143
|
-
{/* Impact Analysis */}
|
|
144
|
-
<div className="pt-2 border-t border-gray-200">
|
|
145
|
-
<h4 className="text-sm font-medium text-gray-700 mb-2">
|
|
146
|
-
Impact Analysis
|
|
147
|
-
</h4>
|
|
148
|
-
<div className="space-y-1 text-xs text-gray-600">
|
|
149
|
-
<div className="flex justify-between">
|
|
150
|
-
<span>Direct dependencies:</span>
|
|
151
|
-
<span className="font-medium">
|
|
152
|
-
{Object.keys(pkg.dependencies).length}
|
|
153
|
-
</span>
|
|
154
|
-
</div>
|
|
155
|
-
<div className="flex justify-between">
|
|
156
|
-
<span>Direct dependents:</span>
|
|
157
|
-
<span className="font-medium">{pkg.dependents.length}</span>
|
|
158
|
-
</div>
|
|
159
|
-
<div className="flex justify-between">
|
|
160
|
-
<span>Risk level:</span>
|
|
161
|
-
<span
|
|
162
|
-
className={`font-medium ${
|
|
163
|
-
pkg.dependents.length > 5
|
|
164
|
-
? 'text-red-600'
|
|
165
|
-
: pkg.dependents.length > 2
|
|
166
|
-
? 'text-yellow-600'
|
|
167
|
-
: 'text-green-600'
|
|
168
|
-
}`}
|
|
169
|
-
>
|
|
170
|
-
{pkg.dependents.length > 5
|
|
171
|
-
? 'High'
|
|
172
|
-
: pkg.dependents.length > 2
|
|
173
|
-
? 'Medium'
|
|
174
|
-
: 'Low'}
|
|
175
|
-
</span>
|
|
176
|
-
</div>
|
|
177
|
-
</div>
|
|
178
|
-
</div>
|
|
179
|
-
|
|
180
|
-
{/* Actions */}
|
|
181
|
-
<div className="pt-2 border-t border-gray-200">
|
|
182
|
-
<Link
|
|
183
|
-
to={`/packages/${encodeURIComponent(pkg.name)}`}
|
|
184
|
-
className="block w-full text-center bg-blue-600 text-white px-3 py-2 rounded-lg hover:bg-blue-700 text-sm font-medium transition-colors"
|
|
185
|
-
>
|
|
186
|
-
View Package Details →
|
|
187
|
-
</Link>
|
|
188
|
-
</div>
|
|
189
|
-
</div>
|
|
190
|
-
</div>
|
|
191
|
-
);
|
|
192
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { ArrowPathIcon } from '../../../../icons/heroicons';
|
|
2
|
-
import type { DependencyGraphHeaderProps } from '../../../../types';
|
|
3
|
-
|
|
4
|
-
export default function DependencyGraphHeader({
|
|
5
|
-
onRefresh,
|
|
6
|
-
loading = false,
|
|
7
|
-
}: DependencyGraphHeaderProps) {
|
|
8
|
-
return (
|
|
9
|
-
<div className="flex items-center justify-between">
|
|
10
|
-
<div>
|
|
11
|
-
<h1 className="text-2xl font-bold text-gray-900">Dependency Graph</h1>
|
|
12
|
-
<p className="text-gray-600 mt-1">
|
|
13
|
-
Visualize package dependencies and relationships
|
|
14
|
-
</p>
|
|
15
|
-
</div>
|
|
16
|
-
{onRefresh && (
|
|
17
|
-
<button
|
|
18
|
-
onClick={onRefresh}
|
|
19
|
-
disabled={loading}
|
|
20
|
-
className="hidden bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center space-x-2 transition-colors"
|
|
21
|
-
>
|
|
22
|
-
<ArrowPathIcon
|
|
23
|
-
className={`w-5 h-5 ${loading ? 'animate-spin' : ''}`}
|
|
24
|
-
/>
|
|
25
|
-
<span>Refresh</span>
|
|
26
|
-
</button>
|
|
27
|
-
)}
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
30
|
-
}
|