import { useCollection, useIdentity } from '@deplixo/sdk'; import Header from './components/Header.jsx'; import Overview from './components/Overview.jsx'; import Deployments from './components/Deployments.jsx'; import Logs from './components/Logs.jsx'; import Config from './components/Config.jsx'; function App() { const [tab, setTab] = useState('overview'); const { user } = useIdentity(); const deploymentsCol = useCollection('deployments'); const logsCol = useCollection('logs'); const configCol = useCollection('config'); const allDeployments = deploymentsCol.items || []; const allLogs = logsCol.items || []; const allConfig = configCol.items || []; // Per-user filtering const deployments = allDeployments .filter((d) => d.author?.id === user?.id) .sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0)); const logs = allLogs .filter((l) => l.author?.id === user?.id) .sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0)); const userConfig = allConfig.find((c) => c.author?.id === user?.id); // Seed config on first load useEffect(() => { if (!user || configCol.loading) return; if (!userConfig) { configCol.add({ repoUrl: 'https://github.com/spring-projects/spring-petclinic', branch: 'main', buildCommand: 'mvn clean package -DskipTests', artifactPath: 'target/*.war', runtime: 'tomcat:10.1-jdk17', port: 8080, contextPath: '/', envVars: 'SPRING_PROFILES_ACTIVE=production\nJAVA_OPTS=-Xmx512m', autoDeploy: true, }); } }, [user, configCol.loading, userConfig]); const addLog = (deploymentId, level, message) => { logsCol.add({ deploymentId, level, message, ts: Date.now() }); }; const latestDeployment = deployments[0]; const activeDeployment = deployments.find((d) => ['queued', 'cloning', 'building', 'deploying', 'running'].includes(d.status) ); return (
{tab === 'overview' && ( { if (!userConfig) return; const id = deploymentsCol.add({ status: 'queued', commitSha: Math.random().toString(16).slice(2, 9), commitMessage: 'Trigger: manual deploy from dashboard', repoUrl: userConfig.repoUrl, branch: userConfig.branch, port: userConfig.port, startedAt: Date.now(), phases: { queued: Date.now(), }, }); // Simulate pipeline progression const stages = [ { delay: 400, status: 'cloning', msg: `Cloning ${userConfig.repoUrl} (branch: ${userConfig.branch})` }, { delay: 1200, status: 'building', msg: `Running build: ${userConfig.buildCommand}` }, { delay: 2400, status: 'building', msg: 'BUILD SUCCESS — artifact: app.war (23.4 MB)' }, { delay: 3200, status: 'deploying', msg: `Pushing WAR to ${userConfig.runtime}` }, { delay: 4000, status: 'deploying', msg: `Starting Tomcat on port ${userConfig.port}` }, { delay: 4800, status: 'running', msg: `✓ Health check passed — listening on :${userConfig.port}` }, ]; stages.forEach(({ delay, status, msg }, i) => { setTimeout(() => { addLog(null, status === 'running' ? 'success' : 'info', msg); }, delay); }); }} /> )} {tab === 'deployments' && ( { deploymentsCol.add({ status: 'running', commitSha: dep.commitSha, commitMessage: `Rollback to ${dep.commitSha}`, repoUrl: dep.repoUrl, branch: dep.branch, port: dep.port, startedAt: Date.now(), rollback: true, }); addLog(null, 'warning', `Rolled back to commit ${dep.commitSha}`); }} onDelete={(id) => deploymentsCol.remove(id)} /> )} {tab === 'logs' && ( { logs.forEach((l) => logsCol.remove(l.id)); }} /> )} {tab === 'config' && ( { if (userConfig) configCol.update(userConfig.id, { ...userConfig, ...patch }); }} /> )}
); } ReactDOM.createRoot(document.getElementById('root')).render();