mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-05-03 09:47:29 +08:00
Release v0.1.0 agent topology and runtime refresh
This commit is contained in:
@@ -113,7 +113,7 @@ const RecursiveConfig: React.FC<RecursiveConfigProps> = ({ data, labels, path =
|
||||
if (typeof data !== 'object' || data === null) return null;
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-10">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-x-10 gap-y-8">
|
||||
{Object.entries(data).map(([key, value]) => {
|
||||
const currentPath = path ? `${path}.${key}` : key;
|
||||
const label = labels[key] || key.replace(/_/g, ' ');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { LayoutDashboard, MessageSquare, Settings, Clock, Terminal, Zap, FolderOpen, ClipboardList, BrainCircuit, Hash, Bot, Workflow, Boxes } from 'lucide-react';
|
||||
import { LayoutDashboard, MessageSquare, Settings, Clock, Terminal, Zap, FolderOpen, ClipboardList, BrainCircuit, Hash, Bot, Boxes } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAppContext } from '../context/AppContext';
|
||||
import NavItem from './NavItem';
|
||||
@@ -27,7 +27,6 @@ const Sidebar: React.FC = () => {
|
||||
{ icon: <Clock className="w-5 h-5" />, label: t('cronJobs'), to: '/cron' },
|
||||
{ icon: <FolderOpen className="w-5 h-5" />, label: t('memory'), to: '/memory' },
|
||||
{ icon: <Bot className="w-5 h-5" />, label: t('subagentProfiles'), to: '/subagent-profiles' },
|
||||
{ icon: <Workflow className="w-5 h-5" />, label: t('pipelines'), to: '/pipelines' },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
104
webui/src/components/SpaceParticles.tsx
Normal file
104
webui/src/components/SpaceParticles.tsx
Normal file
@@ -0,0 +1,104 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
export const SpaceParticles: React.FC = () => {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) return;
|
||||
|
||||
let animationFrameId: number;
|
||||
const particles: Array<{
|
||||
x: number;
|
||||
y: number;
|
||||
size: number;
|
||||
speedX: number;
|
||||
speedY: number;
|
||||
opacity: number;
|
||||
}> = [];
|
||||
|
||||
const resize = () => {
|
||||
const parent = canvas.parentElement;
|
||||
if (parent) {
|
||||
canvas.width = parent.clientWidth;
|
||||
canvas.height = parent.clientHeight;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('resize', resize);
|
||||
resize();
|
||||
|
||||
// Initialize particles
|
||||
const particleCount = Math.floor((canvas.width * canvas.height) / 12000); // Responsive count
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
particles.push({
|
||||
x: Math.random() * canvas.width,
|
||||
y: Math.random() * canvas.height,
|
||||
size: Math.random() * 1.5 + 0.5,
|
||||
speedX: (Math.random() - 0.5) * 0.4,
|
||||
speedY: (Math.random() - 0.5) * 0.4,
|
||||
opacity: Math.random() * 0.6 + 0.1,
|
||||
});
|
||||
}
|
||||
|
||||
const draw = () => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// Draw subtle background gradient
|
||||
const gradient = ctx.createRadialGradient(
|
||||
canvas.width / 2, canvas.height / 2, 0,
|
||||
canvas.width / 2, canvas.height / 2, Math.max(canvas.width, canvas.height)
|
||||
);
|
||||
gradient.addColorStop(0, 'rgba(30, 27, 75, 0.15)'); // Deep indigo tint
|
||||
gradient.addColorStop(1, 'rgba(9, 9, 11, 0.9)'); // Zinc-950
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
particles.forEach((p) => {
|
||||
p.x += p.speedX;
|
||||
p.y += p.speedY;
|
||||
|
||||
if (p.x < 0) p.x = canvas.width;
|
||||
if (p.x > canvas.width) p.x = 0;
|
||||
if (p.y < 0) p.y = canvas.height;
|
||||
if (p.y > canvas.height) p.y = 0;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2);
|
||||
ctx.fillStyle = `rgba(167, 139, 250, ${p.opacity})`; // Violet-400 tint
|
||||
ctx.fill();
|
||||
});
|
||||
|
||||
// Draw connecting lines if close
|
||||
ctx.lineWidth = 0.5;
|
||||
for (let i = 0; i < particles.length; i++) {
|
||||
for (let j = i + 1; j < particles.length; j++) {
|
||||
const dx = particles[i].x - particles[j].x;
|
||||
const dy = particles[i].y - particles[j].y;
|
||||
const dist = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
if (dist < 120) {
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = `rgba(139, 92, 246, ${0.15 * (1 - dist / 120)})`; // Violet-500
|
||||
ctx.moveTo(particles[i].x, particles[i].y);
|
||||
ctx.lineTo(particles[j].x, particles[j].y);
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
animationFrameId = requestAnimationFrame(draw);
|
||||
};
|
||||
|
||||
draw();
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('resize', resize);
|
||||
cancelAnimationFrame(animationFrameId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <canvas ref={canvasRef} className="absolute inset-0 pointer-events-none z-0 rounded-xl" />;
|
||||
};
|
||||
Reference in New Issue
Block a user