Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions src/components/chatAssistance/SpiderMan.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export function SpiderMan({ animationTrigger }) {
const { actions } = useAnimations(animations, spidermanRef);
const [currentAnimation, setCurrentAnimation] = useState("idle");
const [isAnimating, setIsAnimating] = useState(false);
const [isVisible, setIsVisible] = useState(true);
const animationQueue = useRef([]);

// Map animation triggers to actual animation names
Expand Down Expand Up @@ -51,17 +52,41 @@ export function SpiderMan({ animationTrigger }) {
const animationList = Object.keys(animationMap);

for (const anim of animationList) {
if (!isVisible) break; // Stop if component is set to invisible
setCurrentAnimation(anim);
await playAnimation(anim);
// Shorter delay between animations
await new Promise(resolve => setTimeout(resolve, 300));
}

setIsAnimating(false);
// Return to idle animation
playAnimation('idle');
// Fade out effect before disappearing
if (spidermanRef.current) {
const material = spidermanRef.current.material;
const startOpacity = 1;
const duration = 1000; // 1 second fade
const startTime = Date.now();

const fadeOut = () => {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);

if (progress < 1) {
const newOpacity = startOpacity * (1 - progress);
spidermanRef.current.traverse((child) => {
if (child.isMesh) {
child.material.transparent = true;
child.material.opacity = newOpacity;
}
});
requestAnimationFrame(fadeOut);
} else {
setIsVisible(false);
}
};

fadeOut();
}
};
// Updated effect to handle animation triggers
useEffect(() => {
if (!animationTrigger || isAnimating) return;

Expand All @@ -72,19 +97,18 @@ export function SpiderMan({ animationTrigger }) {
setIsAnimating(true);
await playAnimation(animationTrigger);
setIsAnimating(false);
// Return to idle after single animation
playAnimation('idle');
}
};

handleAnimation();
}, [animationTrigger]);
// Initial idle animation
useEffect(() => {
if (actions && Object.keys(actions).length > 0) {
playAnimation('idle');
}
}, [actions]);
if (!isVisible) return null;
return (
<primitive
ref={spidermanRef}
Expand Down
157 changes: 103 additions & 54 deletions src/components/deployment/AIAnalysis.jsx
Original file line number Diff line number Diff line change
@@ -1,64 +1,113 @@
import { motion } from "framer-motion";
import { StreamingText } from "../chatAssistance/StreamingText";
import React, { useState, useEffect } from "react";

export const AIAnalysis = ({ logs }) => {
return (
<div className="rounded-2xl backdrop-blur-xl bg-slate-800/30 border border-blue-500/10 hover:border-blue-500/30 transition-all duration-500 p-6">
<div className="flex items-center gap-4 mb-6">
<div className="relative">
<motion.div
className="w-10 h-10 rounded-full bg-gradient-to-r from-blue-500 to-cyan-500"
animate={{
scale: [1, 1.1, 1],
opacity: [0.5, 1, 0.5],
}}
transition={{ duration: 2, repeat: Infinity }}
/>
<div className="absolute inset-0 backdrop-blur-sm rounded-full" />
</div>
<div>
<h3 className="text-xl font-semibold bg-gradient-to-r from-blue-400 to-cyan-400 bg-clip-text text-transparent">
AI Analysis
</h3>
<p className="text-sm text-blue-300/60">Real-time deployment insights</p>
</div>
</div>
export const AIAnalysis = ({ analysisData = [] }) => {
const [displayedAnalysis, setDisplayedAnalysis] = useState([]);
const [isStreaming, setIsStreaming] = useState(false);
const [currentItem, setCurrentItem] = useState(null);

<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div className="p-4 rounded-xl bg-slate-900/50 border border-blue-500/10">
<h4 className="text-sm font-medium text-blue-300/80 mb-2">Performance Metrics</h4>
<motion.div
className="h-2 rounded-full bg-gradient-to-r from-green-500 to-blue-500 mb-2"
initial={{ width: 0 }}
animate={{ width: "80%" }}
transition={{ duration: 1 }}
/>
<p className="text-xs text-blue-300/60">Build optimization: 80%</p>
</div>
<div className="p-4 rounded-xl bg-slate-900/50 border border-blue-500/10">
<h4 className="text-sm font-medium text-blue-300/80 mb-2">Security Check</h4>
<motion.div
className="h-2 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 mb-2"
initial={{ width: 0 }}
animate={{ width: "95%" }}
transition={{ duration: 1 }}
/>
<p className="text-xs text-blue-300/60">Vulnerability scan: 95% safe</p>
useEffect(() => {
if (analysisData.length > displayedAnalysis.length) {
setCurrentItem(analysisData[displayedAnalysis.length]);
setIsStreaming(true);
}
}, [analysisData, displayedAnalysis]);

const handleStreamComplete = () => {
if (currentItem) {
setDisplayedAnalysis(prev => [...prev, currentItem]);
setIsStreaming(false);
setCurrentItem(null);
}
};

const getClassificationColor = (classification) => {
switch (classification) {
case "ERROR":
return "text-red-400 bg-red-500/10 border-red-500/30";
case "WARNING":
return "text-yellow-400 bg-yellow-500/10 border-yellow-500/30";
case "INFO":
return "text-blue-400 bg-blue-500/10 border-blue-500/30";
case "SUCCESS":
case "UPLOAD_SUCCESS":
return "text-green-400 bg-green-500/10 border-green-500/30";
default:
return "text-gray-400 bg-gray-500/10 border-gray-500/30";
}
};

return (
<div className="rounded-2xl backdrop-blur-xl bg-slate-800/30 border border-blue-500/10
hover:border-blue-500/30 transition-all duration-500 p-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-xl font-semibold bg-gradient-to-r from-blue-400 to-cyan-400
bg-clip-text text-transparent">AI Analysis</h3>
<div className="flex items-center gap-2">
<span className="px-3 py-1 rounded-full bg-purple-500/20 text-purple-400
border border-purple-500/30 text-sm">INSIGHTS</span>
{isStreaming && (
<motion.div
animate={{ opacity: [0.4, 1, 0.4] }}
transition={{ duration: 1.5, repeat: Infinity }}
className="flex items-center gap-1"
>
<div className="w-2 h-2 rounded-full bg-blue-400" />
<div className="w-2 h-2 rounded-full bg-blue-400" />
<div className="w-2 h-2 rounded-full bg-blue-400" />
</motion.div>
)}
</div>
</div>

<div className="h-[400px] overflow-y-auto rounded-xl bg-slate-900/50 p-4 space-y-3">
{displayedAnalysis.map((item, index) => (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5 }}
key={item.log_event_id || index}
className={`p-4 rounded-lg border ${getClassificationColor(item.classification)}`}
>
<div className="flex justify-between items-center mb-2">
<span className="font-semibold">{item.classification}</span>
<span className="text-xs opacity-70">{new Date(item.timestamp).toLocaleString()}</span>
</div>
<p className="text-sm">{item.reasoning}</p>
</motion.div>
))}

{isStreaming && currentItem && (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
className={`p-4 rounded-lg border ${getClassificationColor(currentItem.classification)}`}
>
<div className="flex justify-between items-center mb-2">
<span className="font-semibold">{currentItem.classification}</span>
<span className="text-xs opacity-70">
{new Date(currentItem.timestamp).toLocaleString()}
</span>
</div>
<p className="text-sm">
<StreamingText text={currentItem.reasoning} onComplete={handleStreamComplete} />
</p>
</motion.div>
)}

<div className="rounded-xl bg-slate-900/50 border border-blue-500/10 p-4">
<div className="flex items-center justify-between mb-4">
<h4 className="text-sm font-medium text-blue-300/80">AI Insights</h4>
<span className="px-2 py-1 rounded-full bg-blue-500/20 text-blue-400 text-xs">
Live Analysis
</span>
</div>
<div className="space-y-3">
<StreamingText text="Analyzing deployment patterns and optimizing resource allocation..." />
<div className="h-px bg-gradient-to-r from-transparent via-blue-500/20 to-transparent" />
<StreamingText text="Build process completed successfully. No critical issues detected." />
</div>
{!isStreaming && displayedAnalysis.length === 0 && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="flex flex-col items-center justify-center h-full text-gray-400"
>
<svg className="w-12 h-12 mb-4 animate-pulse" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
</svg>
<p className="text-center">AI is analyzing your deployment logs...</p>
</motion.div>
)}
</div>
</div>
);
Expand Down
69 changes: 63 additions & 6 deletions src/components/pages/DeploymentProgress.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from "recharts";
import axios from "axios";
import { AIAnalysis } from "../deployment/AIAnalysis";
import { LogTerminal } from "../deployment/LogTerminal";
import { Canvas } from "@react-three/fiber";
import { SpiderMan } from "../chatAssistance/SpiderMan";
import { ChatInterface } from "../chatAssistance/ChaatInterface";
import { Environment } from "@react-three/drei";

const DeploymentProgress = () => {
const API_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000';
Expand All @@ -15,6 +19,8 @@ const DeploymentProgress = () => {
const [isDeploying, setIsDeploying] = useState(true);
const [progress, setProgress] = useState(0);
const [deploymentStats, setDeploymentStats] = useState({ success: 70, failure: 30, total: 100 });
const [aiAnalysisData, setAiAnalysisData] = useState([]);

const navigate = useNavigate();
const { id } = useParams();

Expand Down Expand Up @@ -90,17 +96,67 @@ const DeploymentProgress = () => {
}
};

const interval = setInterval(fetchLogs, 2000);
return () => clearInterval(interval);
//fetch llm logs
const fetchAiAnalysis = async () => {
try {
const response = await axios.get(`https://api.dataflarenet.com/api/ai-analysis/${id}`);
if (response.data.success) {
setAiAnalysisData(response.data.data);
}
} catch (error) {
console.error("Error fetching AI analysis:", error.message);
}
};

const logsInterval = setInterval(fetchLogs, 2000);
const aiAnalysisInterval = setInterval(fetchAiAnalysis, 3000); // Poll AI analysis every 5 seconds

return () => {
clearInterval(logsInterval);
clearInterval(aiAnalysisInterval);
};
}, [id]);



const handleCancel = () => {
setIsDeploying(false);
navigate("/service");
};
return (
<div className="min-h-screen bg-gradient-to-b from-gray-900 to-black text-white relative overflow-hidden pt-20">

{/* Spider-Man 3D Scene */}
<div style={{
position: 'fixed',
top: '100px',
right: '100px',
width: '600px',
height: '400px',
zIndex: 1000,
pointerEvents: 'none',
overflow: 'hidden',
}}>
<Canvas
style={{ background: 'transparent' }}
camera={{
position: [0, 1.5, 3],
fov: 45,
near: 0.1,
far: 1000
}}
>
<ambientLight intensity={1.2} />
<directionalLight position={[3, 5, 2]} intensity={1.5} />
<SpiderMan animationTrigger="all" />
<Environment preset="sunset" />
</Canvas>
</div>

{/* Chat Interface */}
<ChatInterface />


{/* Background Effects */}
<div className="absolute inset-0">
<div className="absolute inset-0 bg-grid-pattern opacity-[0.07]" />
Expand Down Expand Up @@ -148,7 +204,7 @@ const DeploymentProgress = () => {
))}
</div>

<div className="mb-8">
{/* <div className="mb-8">
<div className="rounded-2xl backdrop-blur-xl bg-slate-800/30 border border-blue-500/10
hover:border-blue-500/30 transition-all duration-500 p-6">
<div className="flex items-center justify-between mb-4">
Expand All @@ -169,7 +225,7 @@ const DeploymentProgress = () => {
))}
</div>
</div>
</div>
</div> */}

<div className="mb-8">
<div className="h-2 rounded-full bg-slate-800/50 overflow-hidden">
Expand All @@ -178,12 +234,13 @@ const DeploymentProgress = () => {
</div>
</div>

{/* //logs anf ai Analysis */}
{/* logs and ai Analysis */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<LogTerminal logs={logs} />
<AIAnalysis logs={logs} />
<AIAnalysis analysisData={aiAnalysisData} />
</div>


<div className="flex flex-wrap gap-4 justify-center mb-12">
{isDeploying ? (
<>
Expand Down