diff --git a/apps/Cloud-Computer-Control-Panel/app/dashboard/page.tsx b/apps/Cloud-Computer-Control-Panel/app/dashboard/page.tsx index 8f63f17a..5d04e41c 100644 --- a/apps/Cloud-Computer-Control-Panel/app/dashboard/page.tsx +++ b/apps/Cloud-Computer-Control-Panel/app/dashboard/page.tsx @@ -6,9 +6,9 @@ import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Plus, Server, Activity, Settings, BookOpen } from "lucide-react" -import { ManagerList } from "@/components/manager-list" -import { CreateManager } from "@/components/create-manager" -import { CredentialsSettings } from "@/components/credentials-settings" +import { ManagerList } from "@/components/dashboard/manager-list" +import { CreateManager } from "@/components/instance/create-manager" +import { CredentialsSettings } from "@/components/dashboard/credentials-settings" export default function DashboardPage() { const router = useRouter() @@ -73,7 +73,7 @@ export default function DashboardPage() { CCCP

CCCP Cloud Computer Control Panel

-

Cloud Infrastructure Management

+

Manage your own personal cloud with fully self-hosted cloud applications using Dokploy

diff --git a/apps/Cloud-Computer-Control-Panel/components/cost-estimator.tsx b/apps/Cloud-Computer-Control-Panel/components/cost-estimator.tsx deleted file mode 100644 index faffd2dc..00000000 --- a/apps/Cloud-Computer-Control-Panel/components/cost-estimator.tsx +++ /dev/null @@ -1,270 +0,0 @@ -"use client" - -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Badge } from "@/components/ui/badge" -import { DollarSign, TrendingUp, TrendingDown, PieChart, Calculator } from "lucide-react" - -interface CostEstimatorProps { - managers: any[] -} - -export function CostEstimator({ managers }: CostEstimatorProps) { - const calculateTotalCosts = () => { - return managers.reduce((total, manager) => { - const cost = manager.costEstimate?.estimatedMonthlyCost?.total || 0 - return total + cost - }, 0) - } - - const calculateCostsByType = () => { - const costsByType: { [key: string]: number } = {} - managers.forEach((manager) => { - const type = manager.config.instanceType - const cost = manager.costEstimate?.estimatedMonthlyCost?.total || 0 - costsByType[type] = (costsByType[type] || 0) + cost - }) - return costsByType - } - - const calculateCostsByRegion = () => { - const costsByRegion: { [key: string]: number } = {} - managers.forEach((manager) => { - const region = manager.config.region - const cost = manager.costEstimate?.estimatedMonthlyCost?.total || 0 - costsByRegion[region] = (costsByRegion[region] || 0) + cost - }) - return costsByRegion - } - - const getRunningCosts = () => { - return managers - .filter((m) => m.status?.state === "running") - .reduce((total, manager) => { - const cost = manager.costEstimate?.estimatedMonthlyCost?.total || 0 - return total + cost - }, 0) - } - - const totalCost = calculateTotalCosts() - const runningCost = getRunningCosts() - const costsByType = calculateCostsByType() - const costsByRegion = calculateCostsByRegion() - const potentialSavings = totalCost - runningCost - - return ( -
- {/* Cost Overview */} -
- - - Total Monthly Cost - - - -
${totalCost.toFixed(2)}
-

All instances if running

-
-
- - - - Current Running Cost - - - -
${runningCost.toFixed(2)}
-

Only running instances

-
-
- - - - Potential Savings - - - -
${potentialSavings.toFixed(2)}
-

From stopped instances

-
-
- - - - Cost Efficiency - - - -
- {totalCost > 0 ? Math.round((potentialSavings / totalCost) * 100) : 0}% -
-

Savings percentage

-
-
-
- - {/* Cost Breakdown by Instance Type */} - - - - - Cost Breakdown by Instance Type - - Monthly cost distribution across different instance types - - - {Object.keys(costsByType).length > 0 ? ( -
- {Object.entries(costsByType) - .sort(([, a], [, b]) => b - a) - .map(([type, cost]) => { - const percentage = totalCost > 0 ? (cost / totalCost) * 100 : 0 - return ( -
-
-
- {type} - - {managers.filter((m) => m.config.instanceType === type).length} instance(s) - -
-
-
${cost.toFixed(2)}
-
{percentage.toFixed(1)}%
-
-
-
-
-
-
- ) - })} -
- ) : ( -
No cost data available
- )} - - - - {/* Cost Breakdown by Region */} - - - - - Cost Breakdown by Region - - Monthly cost distribution across AWS regions - - - {Object.keys(costsByRegion).length > 0 ? ( -
- {Object.entries(costsByRegion) - .sort(([, a], [, b]) => b - a) - .map(([region, cost]) => { - const percentage = totalCost > 0 ? (cost / totalCost) * 100 : 0 - return ( -
-
-
- {region} - - {managers.filter((m) => m.config.region === region).length} instance(s) - -
-
-
${cost.toFixed(2)}
-
{percentage.toFixed(1)}%
-
-
-
-
-
-
- ) - })} -
- ) : ( -
No cost data available
- )} - - - - {/* Individual Instance Costs */} - - - Individual Instance Costs - Detailed cost breakdown for each managed instance - - - {managers.length > 0 ? ( -
- {managers.map((manager) => { - const cost = manager.costEstimate?.estimatedMonthlyCost - const isRunning = manager.status?.state === "running" - return ( -
-
-
{manager.config.instanceName || "Unnamed Instance"}
-
- {manager.config.instanceType} • {manager.config.region} • {manager.config.storageSize}GB -
-
- - {manager.status?.state || "Not launched"} - -
-
-
-
${cost?.total?.toFixed(2) || "0.00"}/mo
-
- Compute: ${cost?.compute?.toFixed(2) || "0.00"} • Storage: $ - {cost?.storage?.toFixed(2) || "0.00"} -
-
-
- ) - })} -
- ) : ( -
No instances to display
- )} -
-
- - {/* Cost Optimization Tips */} - - - 💡 Cost Optimization Tips - Ways to reduce your AWS EC2 costs - - -
-
-

Stop Unused Instances

-

- Stop instances when not in use to save ~70% on compute costs. You only pay for storage when stopped. -

-
-
-

Right-size Your Instances

-

- Choose the appropriate instance type for your workload. Start small and scale up as needed. -

-
-
-

Use Spot Instances

-

- For non-critical workloads, consider Spot instances which can be up to 90% cheaper. -

-
-
-

Monitor and Set Alerts

-

- Set up billing alerts in AWS Console to get notified when costs exceed your budget. -

-
-
-
-
-
- ) -} diff --git a/apps/Cloud-Computer-Control-Panel/components/credentials-settings.tsx b/apps/Cloud-Computer-Control-Panel/components/dashboard/credentials-settings.tsx similarity index 100% rename from apps/Cloud-Computer-Control-Panel/components/credentials-settings.tsx rename to apps/Cloud-Computer-Control-Panel/components/dashboard/credentials-settings.tsx diff --git a/apps/Cloud-Computer-Control-Panel/components/manager-list.tsx b/apps/Cloud-Computer-Control-Panel/components/dashboard/manager-list.tsx similarity index 99% rename from apps/Cloud-Computer-Control-Panel/components/manager-list.tsx rename to apps/Cloud-Computer-Control-Panel/components/dashboard/manager-list.tsx index 45a4e5a0..b3b92d7e 100644 --- a/apps/Cloud-Computer-Control-Panel/components/manager-list.tsx +++ b/apps/Cloud-Computer-Control-Panel/components/dashboard/manager-list.tsx @@ -18,8 +18,8 @@ import { RotateCw, Trash2, } from "lucide-react" -import { InstanceControls } from "./instance-controls" -import { AddSoftwareModal } from "./add-software-modal" +import { InstanceControls } from "../instance/instance-controls" +import { AddSoftwareModal } from "../instance/add-software-modal" import { useToast } from "@/hooks/use-toast" interface Manager { diff --git a/apps/Cloud-Computer-Control-Panel/components/instance-dashboard.tsx b/apps/Cloud-Computer-Control-Panel/components/instance-dashboard.tsx deleted file mode 100644 index ff85f39a..00000000 --- a/apps/Cloud-Computer-Control-Panel/components/instance-dashboard.tsx +++ /dev/null @@ -1,239 +0,0 @@ -"use client" - -import { useState, useEffect } from "react" -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Button } from "@/components/ui/button" -import { Badge } from "@/components/ui/badge" -import { Alert, AlertDescription } from "@/components/ui/alert" -import { - Server, - Play, - Square, - Trash2, - RefreshCw, - ExternalLink, - DollarSign, - Clock, - MapPin, - HardDrive, - Shield, - Terminal, -} from "lucide-react" -import { useToast } from "@/hooks/use-toast" - -interface InstanceDashboardProps { - manager: any - apiUrl: string - onSelect: () => void - onDelete: () => void - onStatusUpdate: () => void - isActive: boolean -} - -export function InstanceDashboard({ - manager, - apiUrl, - onSelect, - onDelete, - onStatusUpdate, - isActive, -}: InstanceDashboardProps) { - const [loading, setLoading] = useState(false) - const { toast } = useToast() - - const getStateColor = (state: string) => { - switch (state) { - case "running": - return "bg-green-500" - case "stopped": - return "bg-yellow-500" - case "pending": - return "bg-blue-500" - case "stopping": - return "bg-orange-500" - case "terminated": - return "bg-red-500" - default: - return "bg-gray-500" - } - } - - const getStateIcon = (state: string) => { - switch (state) { - case "running": - return - case "stopped": - return - case "pending": - return - default: - return - } - } - - const refreshStatus = async () => { - setLoading(true) - try { - await onStatusUpdate() - toast({ - title: "Status Updated", - description: "Instance status refreshed successfully", - }) - } catch (error) { - toast({ - title: "Error", - description: "Failed to refresh status", - variant: "destructive", - }) - } finally { - setLoading(false) - } - } - - // Auto-refresh status every 30 seconds for active manager - useEffect(() => { - if (isActive && manager.status?.instanceId) { - const interval = setInterval(onStatusUpdate, 30000) - return () => clearInterval(interval) - } - }, [isActive, manager.status?.instanceId, onStatusUpdate]) - - return ( - - -
-
-
- -
-
- {manager.config.instanceName || "Unnamed Instance"} - - {manager.managerId} - {manager.status?.state && ( - -
- {manager.status.state} - - )} - -
-
-
- - -
-
- - - - {/* Instance Details */} -
-
- - {manager.config.instanceType} -
-
- - {manager.config.region} -
-
- - {manager.config.storageSize}GB -
-
- - ${manager.costEstimate?.estimatedMonthlyCost?.total?.toFixed(2) || "0.00"}/mo -
-
- - {/* Connection Info */} - {manager.status?.publicIp && ( - - - -
-
- Public IP: {manager.status.publicIp} -
- {manager.config.setupDokploy && ( -
- Dokploy Dashboard:{" "} - - http://{manager.status.publicIp}:3000 - - -
- )} -
- SSH Command: -
- - {manager.config.keyName - ? `ssh -i ${manager.config.keyName}.pem ubuntu@${manager.status.publicIp}` - : `# Connect via AWS Systems Manager Session Manager`} - -
-
-
- )} - - {/* Security Groups */} - {manager.config.allowedPorts && ( -
-
- - Allowed Ports -
-
- {manager.config.allowedPorts.map((port: number) => ( - - {port} - - ))} -
-
- )} - - {/* Development Environment */} - {manager.config.setupDevEnvironment && ( -
-
Development Tools
-
- {manager.config.devTools?.map((tool: string) => ( - - {tool} - - ))} -
-
- )} - - {/* Actions */} -
- - {manager.status?.publicIp && ( - - )} -
-
- - ) -} diff --git a/apps/Cloud-Computer-Control-Panel/components/add-software-modal.tsx b/apps/Cloud-Computer-Control-Panel/components/instance/add-software-modal.tsx similarity index 100% rename from apps/Cloud-Computer-Control-Panel/components/add-software-modal.tsx rename to apps/Cloud-Computer-Control-Panel/components/instance/add-software-modal.tsx diff --git a/apps/Cloud-Computer-Control-Panel/components/create-manager.tsx b/apps/Cloud-Computer-Control-Panel/components/instance/create-manager.tsx similarity index 91% rename from apps/Cloud-Computer-Control-Panel/components/create-manager.tsx rename to apps/Cloud-Computer-Control-Panel/components/instance/create-manager.tsx index c154ec1a..51752999 100644 --- a/apps/Cloud-Computer-Control-Panel/components/create-manager.tsx +++ b/apps/Cloud-Computer-Control-Panel/components/instance/create-manager.tsx @@ -11,11 +11,12 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import { Checkbox } from "@/components/ui/checkbox" import { Badge } from "@/components/ui/badge" import { Alert, AlertDescription } from "@/components/ui/alert" +import { Slider } from "@/components/ui/slider" import { Rocket, CheckCircle, HardDrive, Cpu, MapPin } from "lucide-react" import { useToast } from "@/hooks/use-toast" import { Textarea } from "@/components/ui/textarea" -import { DockerImageSearch } from "@/components/docker-image-search" -import { GitHubRepoSearch } from "@/components/github-repo-search" +import { DockerImageSearch } from "@/components/search/docker-image-search" +import { GitHubRepoSearch } from "@/components/search/github-repo-search" const INSTANCE_TYPES = [ { value: "t3.micro", label: "t3.micro", vcpu: 2, ram: 1, cost: 7.59 }, @@ -264,15 +265,23 @@ export function CreateManager({ credentials, onSuccess }: { credentials: any; on
- - + + {formData.storageSize} GB +
+ setFormData({ ...formData, storageSize: Number.parseInt(e.target.value) })} + step={10} + value={[formData.storageSize]} + onValueChange={([value]) => setFormData({ ...formData, storageSize: value })} + className="py-4" /> +
+ 20 GB + 200 GB +
@@ -281,7 +290,32 @@ export function CreateManager({ credentials, onSuccess }: { credentials: any; on SSH key pairs will be automatically generated and saved securely when you launch the instance + + {/* Cost Estimate */} +
+
Cost Estimate
+
+
+
Instance
+
${cost.estimatedMonthlyCost.instance.toFixed(2)}
+
+
+
Storage ({formData.storageSize}GB)
+
${cost.estimatedMonthlyCost.storage.toFixed(2)}
+
+
+
Total Monthly
+
${cost.estimatedMonthlyCost.total.toFixed(2)}
+
+
+
+ + +
{/* Software Setup */} @@ -467,41 +501,6 @@ export function CreateManager({ credentials, onSuccess }: { credentials: any; on )} - {/* Cost Estimate */} - - - Cost Estimate - Estimated monthly AWS costs - - -
-
-
Instance
-
${cost.estimatedMonthlyCost.instance.toFixed(2)}
-
-
-
Storage ({formData.storageSize}GB)
-
${cost.estimatedMonthlyCost.storage.toFixed(2)}
-
-
-
Total Monthly
-
${cost.estimatedMonthlyCost.total.toFixed(2)}
-
-
- - - {formData.region} - -
-
-
- - - -
) diff --git a/apps/Cloud-Computer-Control-Panel/components/instance-controls.tsx b/apps/Cloud-Computer-Control-Panel/components/instance/instance-controls.tsx similarity index 100% rename from apps/Cloud-Computer-Control-Panel/components/instance-controls.tsx rename to apps/Cloud-Computer-Control-Panel/components/instance/instance-controls.tsx diff --git a/apps/Cloud-Computer-Control-Panel/components/docker-image-search.tsx b/apps/Cloud-Computer-Control-Panel/components/search/docker-image-search.tsx similarity index 100% rename from apps/Cloud-Computer-Control-Panel/components/docker-image-search.tsx rename to apps/Cloud-Computer-Control-Panel/components/search/docker-image-search.tsx diff --git a/apps/Cloud-Computer-Control-Panel/components/github-repo-search.tsx b/apps/Cloud-Computer-Control-Panel/components/search/github-repo-search.tsx similarity index 100% rename from apps/Cloud-Computer-Control-Panel/components/github-repo-search.tsx rename to apps/Cloud-Computer-Control-Panel/components/search/github-repo-search.tsx diff --git a/apps/Cloud-Computer-Control-Panel/components/system-status.tsx b/apps/Cloud-Computer-Control-Panel/components/system-status.tsx deleted file mode 100644 index 572f8ac4..00000000 --- a/apps/Cloud-Computer-Control-Panel/components/system-status.tsx +++ /dev/null @@ -1,33 +0,0 @@ -"use client" - -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Badge } from "@/components/ui/badge" -import { CheckCircle, Activity } from "lucide-react" - -export function SystemStatus() { - return ( - - - - - System Status - - AWS Manager with Dokploy Integration - - -
-
- - -
- System Operational - -
-
- Ready to create and manage EC2 instances with automated Dokploy installation -
-
- - - ) -} diff --git a/apps/Cloud-Computer-Control-Panel/components/theme-provider.tsx b/apps/Cloud-Computer-Control-Panel/components/theme-provider.tsx deleted file mode 100644 index 55c2f6eb..00000000 --- a/apps/Cloud-Computer-Control-Panel/components/theme-provider.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client' - -import * as React from 'react' -import { - ThemeProvider as NextThemesProvider, - type ThemeProviderProps, -} from 'next-themes' - -export function ThemeProvider({ children, ...props }: ThemeProviderProps) { - return {children} -} diff --git a/apps/Cloud-Computer-Control-Panel/components/ui/slider.tsx b/apps/Cloud-Computer-Control-Panel/components/ui/slider.tsx new file mode 100644 index 00000000..e161daec --- /dev/null +++ b/apps/Cloud-Computer-Control-Panel/components/ui/slider.tsx @@ -0,0 +1,26 @@ +import * as React from "react" +import * as SliderPrimitive from "@radix-ui/react-slider" + +import { cn } from "@/lib/utils" + +const Slider = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + + + +)) +Slider.displayName = SliderPrimitive.Root.displayName + +export { Slider } diff --git a/apps/Cloud-Computer-Control-Panel/package.json b/apps/Cloud-Computer-Control-Panel/package.json index a70bba7b..2e54a1eb 100644 --- a/apps/Cloud-Computer-Control-Panel/package.json +++ b/apps/Cloud-Computer-Control-Panel/package.json @@ -12,34 +12,15 @@ "dependencies": { "@aws-sdk/client-ec2": "3.956.0", "@aws-sdk/credential-providers": "3.956.0", - "@hookform/resolvers": "^3.10.0", - "@radix-ui/react-accordion": "1.2.2", - "@radix-ui/react-alert-dialog": "1.1.4", - "@radix-ui/react-aspect-ratio": "1.1.1", - "@radix-ui/react-avatar": "1.1.2", "@radix-ui/react-checkbox": "1.1.3", - "@radix-ui/react-collapsible": "1.1.2", - "@radix-ui/react-context-menu": "2.2.4", "@radix-ui/react-dialog": "1.1.4", - "@radix-ui/react-dropdown-menu": "2.1.4", - "@radix-ui/react-hover-card": "1.1.4", "@radix-ui/react-label": "2.1.1", - "@radix-ui/react-menubar": "1.1.4", - "@radix-ui/react-navigation-menu": "1.2.3", - "@radix-ui/react-popover": "1.1.4", - "@radix-ui/react-progress": "1.1.1", - "@radix-ui/react-radio-group": "1.2.2", "@radix-ui/react-scroll-area": "1.2.2", "@radix-ui/react-select": "2.1.4", - "@radix-ui/react-separator": "1.1.1", "@radix-ui/react-slider": "1.2.2", "@radix-ui/react-slot": "1.1.1", - "@radix-ui/react-switch": "1.1.2", "@radix-ui/react-tabs": "1.1.2", "@radix-ui/react-toast": "1.2.4", - "@radix-ui/react-toggle": "1.1.1", - "@radix-ui/react-toggle-group": "1.1.1", - "@radix-ui/react-tooltip": "1.1.6", "@scalar/nextjs-api-reference": "0.9.7", "@types/node-forge": "^1.3.14", "@types/ssh2": "^1.15.5", @@ -47,26 +28,15 @@ "autoprefixer": "^10.4.20", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", - "cmdk": "1.0.4", - "date-fns": "4.1.0", - "embla-carousel-react": "8.5.1", - "input-otp": "1.4.1", "lucide-react": "^0.454.0", "next": "16.0.10", "next-themes": "^0.4.6", "node-forge": "^1.3.3", "react": "19.2.0", - "react-day-picker": "9.8.0", "react-dom": "19.2.0", - "react-hook-form": "^7.60.0", - "react-resizable-panels": "^2.1.7", - "recharts": "2.15.4", - "sonner": "^1.7.4", "ssh2": "^1.17.0", "tailwind-merge": "^3.3.1", - "tailwindcss-animate": "^1.0.7", - "vaul": "^1.1.2", - "zod": "3.25.76" + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.9",