import React, { useState, useEffect } from "react"; import { DBService } from "../lib/db"; import { AutomationWorkflow, WorkflowNode, WorkflowConnection } from "../types"; import { Network, Plus, Play, Pause, Trash, Download, Upload, Settings, CheckCircle2, RefreshCw, AlertTriangle, PlayCircle } from "lucide-react"; export default function WorkflowsTab({ triggerHaptic }: { triggerHaptic: () => void }) { const [workflows, setWorkflows] = useState([]); const [selectedWorkflow, setSelectedWorkflow] = useState(null); const [runningStepIndex, setRunningStepIndex] = useState(null); const [isRunningTest, setIsRunningTest] = useState(false); const [testConsoleLogs, setTestConsoleLogs] = useState([]); // form state for adding node const [nodeType, setNodeType] = useState("trigger"); const [nodeLabel, setNodeLabel] = useState("مشغل زمني يومي"); useEffect(() => { loadWorkflows(); }, []); const loadWorkflows = async () => { const list = await DBService.getAll("workflows"); if (list.length === 0) { // Seed initial dummy workflow templates const seed: AutomationWorkflow[] = [ { id: "work_1", name: "استنساخ يومي ونشر تلقائي", description: "أتمتة ذكية تقوم بسحب كود الموقع المستهدف وحك الإعلانات منه وإعادة نشره تلقائياً على Vercel.", status: "active", nodes: [ { id: "n_1", type: "trigger", label: "مؤقت مجدول (Daily Cron)", x: 50, y: 50, config: { time: "00:00" } }, { id: "n_2", type: "fetch", label: "جلب محتويات مثال.كوم", x: 200, y: 50, config: { url: "https://example.com" } }, { id: "n_3", type: "parse", label: "تنظيف الأكواد والتعقبات", x: 350, y: 50, config: { strip_ads: true } }, { id: "n_4", type: "deploy", label: "إعادة بناء Vercel السحابي", x: 500, y: 50, config: { platform: "Vercel" } } ], connections: [ { fromId: "n_1", toId: "n_2" }, { fromId: "n_2", toId: "n_3" }, { fromId: "n_3", toId: "n_4" } ] }, { id: "work_2", name: "مراقب فشل API وتحديث المفاتيح", description: "سير عمل ذكي يبدأ بفحص سرعات الاستجابة ويقوم بتبديل كود OpenAI تلقائياً إذا انقطع المخدم.", status: "paused", nodes: [ { id: "n_1", type: "trigger", label: "فحص موقع مراقبة الأداء", x: 50, y: 150, config: { interval: "1m" } }, { id: "n_2", type: "condition", label: "هل المخدم متوقف (Down)؟", x: 220, y: 150, config: { metric: "responseTime", threshold: 1000 } }, { id: "n_3", type: "notify", label: "إرسال تقرير إيميل استنفار", x: 390, y: 100, config: { level: "urgent" } }, { id: "n_4", type: "deploy", label: "تحويل المفتاح النشط للطوارئ", x: 390, y: 200, config: { target: "backup_key" } } ], connections: [ { fromId: "n_1", toId: "n_2" }, { fromId: "n_2", toId: "n_3" }, { fromId: "n_2", toId: "n_4" } ] } ]; for (const w of seed) { await DBService.put("workflows", w); } setWorkflows(seed); setSelectedWorkflow(seed[0] || null); } else { setWorkflows(list); setSelectedWorkflow(list[0] || null); } }; const handleCreateWorkflow = async () => { triggerHaptic(); const newW: AutomationWorkflow = { id: "work_" + Date.now(), name: "سير عمل مخصص رقم " + (workflows.length + 1), description: "سير عمل مؤتمت لربط الخدمات محلياً وتعديل مسارت الويب.", status: "active", nodes: [ { id: "n_1", type: "trigger", label: "مشغل يدوي أو webhook", x: 100, y: 100, config: {} } ], connections: [] }; await DBService.put("workflows", newW); setWorkflows(prev => [...prev, newW]); setSelectedWorkflow(newW); await DBService.put("auditLog", { id: "log_" + Date.now(), timestamp: Date.now(), action: "إنشاء أتمتة جديدة", details: `تم بنجاح إنشاء سير عمل [${newW.name}] قيد التصميم المتقدم`, status: "success" }); }; const handleDeleteWorkflow = async (id: string, e: React.MouseEvent) => { e.stopPropagation(); triggerHaptic(); await DBService.delete("workflows", id); setWorkflows(prev => prev.filter(w => w.id !== id)); if (selectedWorkflow?.id === id) { setSelectedWorkflow(null); } }; const handleAddNodeToActive = async () => { if (!selectedWorkflow) return; triggerHaptic(); const newNode: WorkflowNode = { id: "n_" + Date.now(), type: nodeType, label: nodeLabel, x: 100, y: 100, config: {} }; // Auto connect to the last node to be visual const updatedNodes = [...selectedWorkflow.nodes, newNode]; const updatedConnections = [...selectedWorkflow.connections]; const lastNode = selectedWorkflow.nodes[selectedWorkflow.nodes.length - 1]; if (lastNode) { updatedConnections.push({ fromId: lastNode.id, toId: newNode.id }); } const updatedWorkflow: AutomationWorkflow = { ...selectedWorkflow, nodes: updatedNodes, connections: updatedConnections }; await DBService.put("workflows", updatedWorkflow); setSelectedWorkflow(updatedWorkflow); setWorkflows(prev => prev.map(w => w.id === selectedWorkflow.id ? updatedWorkflow : w)); }; const runLiveTestExecution = async () => { if (!selectedWorkflow || isRunningTest) return; triggerHaptic(); setIsRunningTest(true); setTestConsoleLogs(["⏳ البدء في معالجة مجمع سير العمل المجدول..."]); const steps = selectedWorkflow.nodes; for (let i = 0; i < steps.length; i++) { setRunningStepIndex(i); const step = steps[i]; if (step) { await new Promise(r => setTimeout(r, 1200)); let logMsg = `🟢 [تمت المعالجة] تشغيل النود ${step.label} (${step.type.toUpperCase()})`; if (step.type === "trigger") logMsg = `⚡ [بدء التشغيل] إشارة تشغيل من: ${step.label}`; if (step.type === "deploy") logMsg = `🚀 [نشر مكمل] تم بنجاح دفع ملفات الاستنساخ للمخدم السحابي المستهدف `; setTestConsoleLogs(prev => [...prev, logMsg]); triggerHaptic(); } } setTimeout(() => { setTestConsoleLogs(prev => [...prev, "🏁 اكتمال كافة خطوات سير العمل بنجاح ودقّة 100% 🚀"]); setIsRunningTest(false); setRunningStepIndex(null); }, 800); }; const exportTon8nJson = () => { if (!selectedWorkflow) return; triggerHaptic(); // Mapping simplified format to standard n8n style workflow json const n8nSchema = { meta: { templateId: "siteclone_pro_workflow" }, nodes: selectedWorkflow.nodes.map(n => ({ parameters: n.config, id: n.id, name: n.label, type: `n8n-nodes-base.${n.type === "trigger" ? "cron" : n.type === "fetch" ? "httpRequest" : "webhook"}`, typeVersion: 1, position: [n.x, n.y] })), connections: {} }; const blob = new Blob([JSON.stringify(n8nSchema, null, 2)], { type: "application/json" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `n8n_export_${selectedWorkflow.name.replace(/\s+/g, "_")}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); }; const getStepBgColor = (type: string, active: boolean) => { if (active) return "border-sky-500 bg-sky-500/20 text-white shadow-lg shadow-sky-500/25"; switch (type) { case "trigger": return "border-yellow-500/30 bg-yellow-500/5 text-yellow-300"; case "deploy": return "border-purple-500/30 bg-purple-500/5 text-purple-300"; case "condition": return "border-orange-500/30 bg-orange-500/5 text-orange-300"; default: return "border-slate-800 bg-slate-900/80 text-slate-300"; } }; return (
{/* Sidebar (Left) */}
{/* Workflows List */}

أتمتة العمليات (Workflows)

{workflows.map((w) => (
{ triggerHaptic(); setSelectedWorkflow(w); }} className={`p-3 rounded-xl border transition-all cursor-pointer flex justify-between items-center ${ selectedWorkflow?.id === w.id ? "bg-sky-500/10 border-sky-500/40 text-white" : "bg-slate-900/60 border-slate-800 hover:border-slate-700 text-slate-300" }`} >

{w.name}

{w.nodes.length} نودات نشطة
{w.status === "active" ? "فعال" : "موقوف"}
))}
{/* Node creation block if any active */} {selectedWorkflow && (

أضف خطوة (نود) جديدة للمخطط

setNodeLabel(e.target.value)} className="bg-slate-900 border border-slate-700 rounded-xl px-3 py-2 text-xs text-white focus:outline-none focus:border-sky-500 w-full" />
)}
{/* Editor & Board canvas (Right) */}
{selectedWorkflow ? (
{/* Header controls select */}

{selectedWorkflow.name}

{selectedWorkflow.description}

{/* Action triggers */}
{/* Visual interactive flows representation */}
{selectedWorkflow.nodes.map((n, i) => (
{n.type} {n.label}
{/* Arrow connect simulator */} {i < selectedWorkflow.nodes.length - 1 && (
)}
))}
{/* Simulated Live Console logs output */}
سجل المخرجات للأتمتة (Active automation logger system)
{testConsoleLogs.map((log, lIndex) => (

{log}

))} {testConsoleLogs.length === 0 && (

انقر على تشغيل تجريبي لرؤية نتائج الفحص المنطقي.

)}
) : (

لا يوجد مسار عمل محدد للتحرير. يرجى البدء بإنشاء سير عمل.

)}
); }