Enhance deployment system with retry functionality and improved UX
Major Improvements: - Added retry deployment buttons in machine list for failed deployments - Added retry button in SSH console modal footer for enhanced UX - Enhanced deployment process with comprehensive cleanup of existing services - Improved binary installation with password-based sudo authentication - Updated configuration generation to include all required sections (agent, ai, network, security) - Fixed deployment verification and error handling Security Enhancements: - Enhanced verifiedStopExistingServices with thorough cleanup process - Improved binary copying with proper sudo authentication - Added comprehensive configuration validation UX Improvements: - Users can retry deployments without re-running machine discovery - Retry buttons available from both machine list and console modal - Real-time deployment progress with detailed console output - Clear error states with actionable retry options Technical Changes: - Modified ServiceDeployment.tsx with retry button components - Enhanced api/setup_manager.go with improved deployment functions - Updated main.go with command line argument support (--config, --setup) - Added comprehensive zero-trust security validation system 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -149,10 +149,29 @@ export default function AIConfiguration({
|
||||
|
||||
setValidatingLocal(true)
|
||||
try {
|
||||
const response = await fetch(`${config.localAIEndpoint}/api/tags`)
|
||||
setLocalAIValid(response.ok)
|
||||
const response = await fetch('/api/setup/ollama/validate', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
endpoint: config.localAIEndpoint
|
||||
})
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
if (result.valid && result.models) {
|
||||
setLocalAIValid(true)
|
||||
// Update the local AI models list with discovered models
|
||||
setConfig(prev => ({ ...prev, localAIModels: result.models }))
|
||||
} else {
|
||||
setLocalAIValid(false)
|
||||
console.error('Ollama validation failed:', result.message)
|
||||
}
|
||||
} catch (error) {
|
||||
setLocalAIValid(false)
|
||||
console.error('Ollama validation error:', error)
|
||||
} finally {
|
||||
setValidatingLocal(false)
|
||||
}
|
||||
@@ -232,26 +251,26 @@ export default function AIConfiguration({
|
||||
</h3>
|
||||
|
||||
<div className={`p-4 rounded-lg border mb-4 ${
|
||||
gpuRecommendation.type === 'success' ? 'bg-green-50 border-green-200' :
|
||||
gpuRecommendation.type === 'success' ? 'bg-eucalyptus-50 border-eucalyptus-950' :
|
||||
gpuRecommendation.type === 'warning' ? 'bg-yellow-50 border-yellow-200' :
|
||||
'bg-blue-50 border-blue-200'
|
||||
}`}>
|
||||
<div className="flex items-start">
|
||||
<InformationCircleIcon className={`h-5 w-5 mt-0.5 mr-2 ${
|
||||
gpuRecommendation.type === 'success' ? 'text-green-600' :
|
||||
gpuRecommendation.type === 'success' ? 'text-eucalyptus-600' :
|
||||
gpuRecommendation.type === 'warning' ? 'text-yellow-600' :
|
||||
'text-blue-600'
|
||||
}`} />
|
||||
<div>
|
||||
<div className={`font-medium ${
|
||||
gpuRecommendation.type === 'success' ? 'text-green-800' :
|
||||
gpuRecommendation.type === 'success' ? 'text-eucalyptus-600' :
|
||||
gpuRecommendation.type === 'warning' ? 'text-yellow-800' :
|
||||
'text-blue-800'
|
||||
}`}>
|
||||
{gpuRecommendation.recommendation}
|
||||
</div>
|
||||
<div className={`text-sm mt-1 ${
|
||||
gpuRecommendation.type === 'success' ? 'text-green-700' :
|
||||
gpuRecommendation.type === 'success' ? 'text-eucalyptus-600' :
|
||||
gpuRecommendation.type === 'warning' ? 'text-yellow-700' :
|
||||
'text-blue-700'
|
||||
}`}>
|
||||
@@ -376,7 +395,7 @@ export default function AIConfiguration({
|
||||
</button>
|
||||
</div>
|
||||
{localAIValid === true && (
|
||||
<div className="flex items-center mt-1 text-green-600 text-sm">
|
||||
<div className="flex items-center mt-1 text-eucalyptus-600 text-sm">
|
||||
<CheckCircleIcon className="h-4 w-4 mr-1" />
|
||||
Connection successful
|
||||
</div>
|
||||
@@ -468,7 +487,7 @@ export default function AIConfiguration({
|
||||
</button>
|
||||
</div>
|
||||
{openaiValid === true && (
|
||||
<div className="flex items-center mt-1 text-green-600 text-sm">
|
||||
<div className="flex items-center mt-1 text-eucalyptus-600 text-sm">
|
||||
<CheckCircleIcon className="h-4 w-4 mr-1" />
|
||||
API key valid
|
||||
</div>
|
||||
|
||||
@@ -141,7 +141,7 @@ export default function LicenseValidation({
|
||||
<div className="flex items-center mb-4">
|
||||
<KeyIcon className="h-6 w-6 text-bzzz-primary mr-2" />
|
||||
<h3 className="text-lg font-medium text-gray-900">License Information</h3>
|
||||
{validationResult?.valid && <CheckCircleIcon className="h-5 w-5 text-green-500 ml-2" />}
|
||||
{validationResult?.valid && <CheckCircleIcon className="h-5 w-5 text-eucalyptus-600 ml-2" />}
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
@@ -230,7 +230,7 @@ export default function LicenseValidation({
|
||||
<div className="flex items-start">
|
||||
<div className="flex-shrink-0">
|
||||
{validationResult.valid ? (
|
||||
<CheckCircleIcon className="h-6 w-6 text-eucalyptus-950 dark:text-eucalyptus-50" />
|
||||
<CheckCircleIcon className="h-6 w-6 text-eucalyptus-600 dark:text-eucalyptus-50" />
|
||||
) : (
|
||||
<ExclamationTriangleIcon className="h-6 w-6 text-coral-950 dark:text-coral-50" />
|
||||
)}
|
||||
|
||||
@@ -347,16 +347,16 @@ export default function RepositoryConfiguration({
|
||||
{validation && (
|
||||
<div className={`flex items-center p-3 rounded-lg mb-4 ${
|
||||
validation.valid
|
||||
? 'bg-green-50 border border-green-200'
|
||||
? 'bg-eucalyptus-50 border border-eucalyptus-950'
|
||||
: 'bg-red-50 border border-red-200'
|
||||
}`}>
|
||||
{validation.valid ? (
|
||||
<CheckCircleIcon className="h-5 w-5 text-green-600 mr-2" />
|
||||
<CheckCircleIcon className="h-5 w-5 text-eucalyptus-600 mr-2" />
|
||||
) : (
|
||||
<XCircleIcon className="h-5 w-5 text-red-600 mr-2" />
|
||||
)}
|
||||
<span className={`text-sm ${
|
||||
validation.valid ? 'text-green-800' : 'text-red-800'
|
||||
validation.valid ? 'text-eucalyptus-600' : 'text-red-800'
|
||||
}`}>
|
||||
{validation.valid ? validation.message : validation.error}
|
||||
</span>
|
||||
|
||||
@@ -208,7 +208,7 @@ b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAFwwAAAAd...
|
||||
<div className="flex items-center mb-4">
|
||||
<KeyIcon className="h-6 w-6 text-bzzz-primary mr-2" />
|
||||
<h3 className="text-lg font-medium text-gray-900">SSH Key Management</h3>
|
||||
{validation.sshKeys === true && <CheckCircleIcon className="h-5 w-5 text-green-500 ml-2" />}
|
||||
{validation.sshKeys === true && <CheckCircleIcon className="h-5 w-5 text-eucalyptus-600 ml-2" />}
|
||||
{validation.sshKeys === false && <XCircleIcon className="h-5 w-5 text-red-500 ml-2" />}
|
||||
</div>
|
||||
|
||||
@@ -420,7 +420,7 @@ b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAFwwAAAAd...
|
||||
<div className="flex items-center mb-4">
|
||||
<LockClosedIcon className="h-6 w-6 text-bzzz-primary mr-2" />
|
||||
<h3 className="text-lg font-medium text-gray-900">TLS/SSL Configuration</h3>
|
||||
{validation.tlsCert === true && <CheckCircleIcon className="h-5 w-5 text-green-500 ml-2" />}
|
||||
{validation.tlsCert === true && <CheckCircleIcon className="h-5 w-5 text-eucalyptus-600 ml-2" />}
|
||||
{validation.tlsCert === false && <XCircleIcon className="h-5 w-5 text-red-500 ml-2" />}
|
||||
</div>
|
||||
|
||||
@@ -626,7 +626,7 @@ b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAFwwAAAAd...
|
||||
className="w-full p-3 border border-gray-300 rounded-lg"
|
||||
/>
|
||||
{configData?.network && (
|
||||
<p className="text-sm text-green-600 mt-1 flex items-center">
|
||||
<p className="text-sm text-eucalyptus-600 mt-1 flex items-center">
|
||||
<CheckCircleIcon className="h-4 w-4 mr-1" />
|
||||
Ports automatically configured from Network Settings: {[
|
||||
configData.network.bzzzPort,
|
||||
|
||||
@@ -380,10 +380,10 @@ export default function ServiceDeployment({
|
||||
|
||||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case 'connected': return <CheckCircleIcon className="h-5 w-5 text-green-500" />
|
||||
case 'connected': return <CheckCircleIcon className="h-5 w-5 text-eucalyptus-600" />
|
||||
case 'failed': return <XCircleIcon className="h-5 w-5 text-red-500" />
|
||||
case 'testing': return <ArrowPathIcon className="h-5 w-5 text-blue-500 animate-spin" />
|
||||
case 'running': return <CheckCircleIcon className="h-5 w-5 text-green-500" />
|
||||
case 'running': return <CheckCircleIcon className="h-5 w-5 text-eucalyptus-600" />
|
||||
case 'installing': return <ArrowPathIcon className="h-5 w-5 text-blue-500 animate-spin" />
|
||||
case 'error': return <XCircleIcon className="h-5 w-5 text-red-500" />
|
||||
case 'stopped': return <StopIcon className="h-5 w-5 text-yellow-500" />
|
||||
@@ -585,12 +585,24 @@ export default function ServiceDeployment({
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => deployToMachine(machine.id)}
|
||||
className="text-green-600 hover:text-green-900"
|
||||
className="text-eucalyptus-600 hover:text-eucalyptus-600"
|
||||
>
|
||||
Install
|
||||
</button>
|
||||
)}
|
||||
|
||||
{machine.sshStatus === 'connected' && machine.deployStatus === 'error' && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => deployToMachine(machine.id)}
|
||||
className="text-amber-600 hover:text-amber-700 mr-2"
|
||||
title="Retry deployment"
|
||||
>
|
||||
<ArrowPathIcon className="h-4 w-4 inline mr-1" />
|
||||
Retry
|
||||
</button>
|
||||
)}
|
||||
|
||||
{machine.deployStatus !== 'not_deployed' && (
|
||||
<>
|
||||
<button
|
||||
@@ -684,7 +696,7 @@ export default function ServiceDeployment({
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<div className="bg-gray-900 text-green-400 p-4 rounded font-mono text-sm max-h-64 overflow-y-auto">
|
||||
<div className="bg-gray-900 text-eucalyptus-600 p-4 rounded font-mono text-sm max-h-64 overflow-y-auto">
|
||||
{deploymentLogs[showLogs]?.map((log, index) => (
|
||||
<div key={index}>{log}</div>
|
||||
)) || <div>No logs available</div>}
|
||||
@@ -699,7 +711,7 @@ export default function ServiceDeployment({
|
||||
<div className="bg-gray-900 rounded-lg overflow-hidden max-w-4xl w-full max-h-[80vh] flex flex-col">
|
||||
<div className="bg-gray-800 px-4 py-3 flex justify-between items-center border-b border-gray-700">
|
||||
<div className="flex items-center">
|
||||
<ComputerDesktopIcon className="h-5 w-5 text-green-400 mr-2" />
|
||||
<ComputerDesktopIcon className="h-5 w-5 text-eucalyptus-600 mr-2" />
|
||||
<h3 className="text-lg font-medium text-white">
|
||||
SSH Console - {machines.find(m => m.id === showConsole)?.hostname}
|
||||
</h3>
|
||||
@@ -711,7 +723,7 @@ export default function ServiceDeployment({
|
||||
<div className="flex items-center space-x-1">
|
||||
<div className="w-2 h-2 bg-red-500 rounded-full"></div>
|
||||
<div className="w-2 h-2 bg-yellow-500 rounded-full"></div>
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full"></div>
|
||||
<div className="w-2 h-2 bg-eucalyptus-500 rounded-full"></div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowConsole(null)}
|
||||
@@ -722,7 +734,7 @@ export default function ServiceDeployment({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 p-4 font-mono text-sm overflow-y-auto bg-gray-900">
|
||||
<div className="text-green-400 space-y-1">
|
||||
<div className="text-eucalyptus-600 space-y-1">
|
||||
{consoleLogs[showConsole]?.length > 0 ? (
|
||||
consoleLogs[showConsole].map((log, index) => (
|
||||
<div key={index} className="whitespace-pre-wrap">{log}</div>
|
||||
@@ -734,10 +746,26 @@ export default function ServiceDeployment({
|
||||
<div className="inline-block w-2 h-4 bg-green-400 animate-pulse"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-gray-800 px-4 py-2 border-t border-gray-700">
|
||||
<div className="bg-gray-800 px-4 py-2 border-t border-gray-700 flex justify-between items-center">
|
||||
<div className="text-xs text-gray-400">
|
||||
💡 This console shows real-time deployment progress and SSH operations
|
||||
</div>
|
||||
{(() => {
|
||||
const machine = machines.find(m => m.id === showConsole)
|
||||
return machine?.sshStatus === 'connected' && machine?.deployStatus === 'error' && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
deployToMachine(showConsole!)
|
||||
}}
|
||||
className="ml-4 px-3 py-1 bg-amber-600 hover:bg-amber-700 text-white text-xs rounded-md flex items-center space-x-1 transition-colors"
|
||||
title="Retry deployment"
|
||||
>
|
||||
<ArrowPathIcon className="h-3 w-3" />
|
||||
<span>Retry Deployment</span>
|
||||
</button>
|
||||
)
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -94,7 +94,7 @@ export default function SystemDetection({
|
||||
|
||||
|
||||
const getStatusColor = (condition: boolean) => {
|
||||
return condition ? 'text-green-600' : 'text-red-600'
|
||||
return condition ? 'text-eucalyptus-600' : 'text-red-600'
|
||||
}
|
||||
|
||||
const getStatusIcon = (condition: boolean) => {
|
||||
@@ -106,7 +106,7 @@ export default function SystemDetection({
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<ArrowPathIcon className="h-8 w-8 text-bzzz-primary animate-spin mx-auto mb-4" />
|
||||
<p className="text-gray-600">Detecting system configuration...</p>
|
||||
<p className="text-chorus-text-secondary">Detecting system configuration...</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -116,10 +116,10 @@ export default function SystemDetection({
|
||||
return (
|
||||
<div className="text-center py-12">
|
||||
<ExclamationTriangleIcon className="h-12 w-12 text-red-500 mx-auto mb-4" />
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-2">
|
||||
<h3 className="heading-subsection mb-2">
|
||||
System Detection Failed
|
||||
</h3>
|
||||
<p className="text-gray-600 mb-4">
|
||||
<p className="text-chorus-text-secondary mb-4">
|
||||
Unable to detect system configuration. Please try again.
|
||||
</p>
|
||||
<button
|
||||
@@ -136,9 +136,9 @@ export default function SystemDetection({
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* System Overview */}
|
||||
<div className="bg-gray-50 rounded-lg p-6">
|
||||
<div className="card">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-lg font-medium text-gray-900">System Overview</h3>
|
||||
<h3 className="heading-subsection">System Overview</h3>
|
||||
<button
|
||||
onClick={refreshSystemInfo}
|
||||
disabled={refreshing}
|
||||
@@ -150,12 +150,12 @@ export default function SystemDetection({
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700">Hostname</div>
|
||||
<div className="text-lg text-gray-900">{detectedInfo.network.hostname}</div>
|
||||
<div className="text-sm font-medium text-chorus-text-secondary">Hostname</div>
|
||||
<div className="text-lg text-chorus-text-primary">{detectedInfo.network.hostname}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700">Operating System</div>
|
||||
<div className="text-lg text-gray-900">
|
||||
<div className="text-sm font-medium text-chorus-text-secondary">Operating System</div>
|
||||
<div className="text-lg text-chorus-text-primary">
|
||||
{detectedInfo.os} ({detectedInfo.architecture})
|
||||
</div>
|
||||
</div>
|
||||
@@ -165,22 +165,22 @@ export default function SystemDetection({
|
||||
{/* Hardware Information */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
{/* CPU & Memory */}
|
||||
<div className="bg-white border border-gray-200 rounded-lg p-6">
|
||||
<div className="card">
|
||||
<div className="flex items-center mb-4">
|
||||
<CpuChipIcon className="h-6 w-6 text-bzzz-primary mr-2" />
|
||||
<h3 className="text-lg font-medium text-gray-900">CPU & Memory</h3>
|
||||
<h3 className="heading-subsection">CPU & Memory</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700">CPU</div>
|
||||
<div className="text-gray-900">
|
||||
<div className="text-sm font-medium text-chorus-text-secondary">CPU</div>
|
||||
<div className="text-chorus-text-primary">
|
||||
{detectedInfo.cpu_cores} cores
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700">Memory</div>
|
||||
<div className="text-gray-900">
|
||||
<div className="text-sm font-medium text-chorus-text-secondary">Memory</div>
|
||||
<div className="text-chorus-text-primary">
|
||||
{Math.round(detectedInfo.memory_mb / 1024)} GB total
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,21 +188,21 @@ export default function SystemDetection({
|
||||
</div>
|
||||
|
||||
{/* Storage */}
|
||||
<div className="bg-white border border-gray-200 rounded-lg p-6">
|
||||
<div className="card">
|
||||
<div className="flex items-center mb-4">
|
||||
<CircleStackIcon className="h-6 w-6 text-bzzz-primary mr-2" />
|
||||
<h3 className="text-lg font-medium text-gray-900">Storage</h3>
|
||||
<h3 className="heading-subsection">Storage</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700">Disk Space</div>
|
||||
<div className="text-gray-900">
|
||||
<div className="text-sm font-medium text-chorus-text-secondary">Disk Space</div>
|
||||
<div className="text-chorus-text-primary">
|
||||
{detectedInfo.storage.total_space_gb} GB total, {' '}
|
||||
{detectedInfo.storage.free_space_gb} GB available
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-2">
|
||||
<div className="w-full bg-chorus-border-invisible rounded-full h-2">
|
||||
<div
|
||||
className="bg-bzzz-primary h-2 rounded-full"
|
||||
style={{
|
||||
@@ -216,19 +216,19 @@ export default function SystemDetection({
|
||||
|
||||
{/* GPU Information */}
|
||||
{detectedInfo.gpus && detectedInfo.gpus.length > 0 && (
|
||||
<div className="bg-white border border-gray-200 rounded-lg p-6">
|
||||
<div className="card">
|
||||
<div className="flex items-center mb-4">
|
||||
<ServerIcon className="h-6 w-6 text-bzzz-primary mr-2" />
|
||||
<h3 className="text-lg font-medium text-gray-900">
|
||||
<h3 className="heading-subsection">
|
||||
GPU Configuration ({detectedInfo.gpus.length} GPU{detectedInfo.gpus.length !== 1 ? 's' : ''})
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
{detectedInfo.gpus.map((gpu, index) => (
|
||||
<div key={index} className="bg-gray-50 rounded-lg p-4">
|
||||
<div className="font-medium text-gray-900">{gpu.name}</div>
|
||||
<div className="text-sm text-gray-600">
|
||||
<div key={index} className="bg-chorus-warm rounded-lg p-4">
|
||||
<div className="font-medium text-chorus-text-primary">{gpu.name}</div>
|
||||
<div className="text-sm text-chorus-text-secondary">
|
||||
{gpu.type.toUpperCase()} • {gpu.memory} • {gpu.driver}
|
||||
</div>
|
||||
</div>
|
||||
@@ -238,21 +238,21 @@ export default function SystemDetection({
|
||||
)}
|
||||
|
||||
{/* Network Information */}
|
||||
<div className="bg-white border border-gray-200 rounded-lg p-6">
|
||||
<div className="card">
|
||||
<div className="flex items-center mb-4">
|
||||
<GlobeAltIcon className="h-6 w-6 text-bzzz-primary mr-2" />
|
||||
<h3 className="text-lg font-medium text-gray-900">Network Configuration</h3>
|
||||
<h3 className="heading-subsection">Network Configuration</h3>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700">Hostname</div>
|
||||
<div className="text-gray-900">{detectedInfo.network.hostname}</div>
|
||||
<div className="text-sm font-medium text-chorus-text-secondary">Hostname</div>
|
||||
<div className="text-chorus-text-primary">{detectedInfo.network.hostname}</div>
|
||||
</div>
|
||||
|
||||
{detectedInfo.network.private_ips && detectedInfo.network.private_ips.length > 0 && (
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700 mb-2">Private IP Addresses</div>
|
||||
<div className="text-sm font-medium text-chorus-text-secondary mb-2">Private IP Addresses</div>
|
||||
<div className="space-y-2">
|
||||
{detectedInfo.network.private_ips.map((ip, index) => (
|
||||
<div key={index} className="flex justify-between items-center text-sm">
|
||||
@@ -266,16 +266,16 @@ export default function SystemDetection({
|
||||
|
||||
{detectedInfo.network.public_ip && (
|
||||
<div>
|
||||
<div className="text-sm font-medium text-gray-700">Public IP</div>
|
||||
<div className="text-gray-900">{detectedInfo.network.public_ip}</div>
|
||||
<div className="text-sm font-medium text-chorus-text-secondary">Public IP</div>
|
||||
<div className="text-chorus-text-primary">{detectedInfo.network.public_ip}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Software Requirements */}
|
||||
<div className="bg-white border border-gray-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-medium text-gray-900 mb-4">Software Requirements</h3>
|
||||
<div className="card">
|
||||
<h3 className="heading-subsection mb-4">Software Requirements</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
@@ -304,9 +304,9 @@ export default function SystemDetection({
|
||||
<div className="flex items-center">
|
||||
<StatusIcon className={`h-5 w-5 mr-3 ${getStatusColor(software.installed)}`} />
|
||||
<div>
|
||||
<div className="font-medium text-gray-900">{software.name}</div>
|
||||
<div className="font-medium text-chorus-text-primary">{software.name}</div>
|
||||
{software.version && (
|
||||
<div className="text-sm text-gray-600">Version: {software.version}</div>
|
||||
<div className="text-sm text-chorus-text-secondary">Version: {software.version}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -327,8 +327,8 @@ export default function SystemDetection({
|
||||
</div>
|
||||
|
||||
{/* System Validation */}
|
||||
<div className="bg-blue-50 border border-blue-200 rounded-lg p-6">
|
||||
<h3 className="text-lg font-medium text-blue-900 mb-4">System Validation</h3>
|
||||
<div className="panel panel-info">
|
||||
<h3 className="heading-subsection mb-4 panel-title">System Validation</h3>
|
||||
|
||||
<div className="space-y-2">
|
||||
{[
|
||||
@@ -351,13 +351,13 @@ export default function SystemDetection({
|
||||
<div key={index} className="flex items-center">
|
||||
<StatusIcon className={`h-4 w-4 mr-3 ${
|
||||
validation.passed
|
||||
? 'text-green-600'
|
||||
? 'text-eucalyptus-600'
|
||||
: 'text-red-600'
|
||||
}`} />
|
||||
<span className={`text-sm ${
|
||||
validation.passed
|
||||
? 'text-green-800'
|
||||
: 'text-red-800'
|
||||
? 'text-eucalyptus-600'
|
||||
: 'text-red-600'
|
||||
}`}>
|
||||
{validation.check}
|
||||
{validation.warning && validation.passed && (
|
||||
@@ -371,7 +371,7 @@ export default function SystemDetection({
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex justify-between pt-6 border-t border-gray-200">
|
||||
<div className="flex justify-between pt-6 border-t border-chorus-border-defined">
|
||||
<div>
|
||||
{onBack && (
|
||||
<button onClick={onBack} className="btn-outline">
|
||||
|
||||
@@ -124,7 +124,7 @@ export default function TermsAndConditions({
|
||||
</div>
|
||||
|
||||
{/* Agreement Checkbox */}
|
||||
<div className="card">
|
||||
<div className="card agreement">
|
||||
<div className="space-y-4">
|
||||
<label className="flex items-start">
|
||||
<input
|
||||
@@ -152,7 +152,7 @@ export default function TermsAndConditions({
|
||||
)}
|
||||
|
||||
{agreed && (
|
||||
<div className="flex items-center text-green-600 text-sm">
|
||||
<div className="flex items-center text-eucalyptus-600 text-sm">
|
||||
<CheckCircleIcon className="h-4 w-4 mr-1" />
|
||||
Thank you for accepting the terms and conditions
|
||||
</div>
|
||||
|
||||
@@ -86,14 +86,14 @@ export default function TestingValidation({
|
||||
)}
|
||||
|
||||
{isCompleted && (
|
||||
<div className="mt-8 bg-green-50 border border-green-200 rounded-lg p-6">
|
||||
<h4 className="text-lg font-medium text-green-900 mb-2">
|
||||
<div className="mt-8 bg-eucalyptus-50 border border-eucalyptus-950 rounded-lg p-6">
|
||||
<h4 className="text-lg font-medium text-eucalyptus-600 mb-2">
|
||||
🎉 Setup Complete!
|
||||
</h4>
|
||||
<p className="text-green-700 mb-4">
|
||||
<p className="text-eucalyptus-600 mb-4">
|
||||
Your CHORUS:agents cluster has been successfully configured and deployed.
|
||||
</p>
|
||||
<div className="space-y-2 text-sm text-green-600 mb-4">
|
||||
<div className="space-y-2 text-sm text-eucalyptus-600 mb-4">
|
||||
<div>✓ System configuration validated</div>
|
||||
<div>✓ Network connectivity tested</div>
|
||||
<div>✓ Services deployed to all nodes</div>
|
||||
|
||||
@@ -224,7 +224,7 @@ export default function SetupPage() {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-4 gap-12">
|
||||
{/* Progress Sidebar */}
|
||||
<div className="lg:col-span-1">
|
||||
<div className="card sticky top-8 bg-chorus-white dark:bg-ocean-700">
|
||||
<div className="card sticky top-8 setup-progress">
|
||||
<h2 className="heading-subsection mb-6">
|
||||
Setup Progress
|
||||
</h2>
|
||||
@@ -252,7 +252,7 @@ export default function SetupPage() {
|
||||
<div className="flex items-center">
|
||||
<div className="flex-shrink-0 mr-3">
|
||||
{isCompleted ? (
|
||||
<CheckCircleIcon className="h-5 w-5 text-green-400" />
|
||||
<CheckCircleIcon className="h-5 w-5 text-eucalyptus-600" />
|
||||
) : (
|
||||
<div className={`w-5 h-5 rounded-full border-2 flex items-center justify-center text-xs font-medium ${
|
||||
isCurrent
|
||||
|
||||
Reference in New Issue
Block a user