From 5307fa459f37f72fd44509a4da3247cc835d815d Mon Sep 17 00:00:00 2001 From: PouyaKhajavi Date: Sun, 9 Aug 2026 11:29:18 +0330 Subject: [PATCH] feat(frontend): add custom confirmation modal and stop running jobs action in run history --- frontend/src/App.jsx | 171 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 136 insertions(+), 35 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index c0ae4c3..7ef03a6 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -12,7 +12,8 @@ import { Play, X, AlertTriangle, - ExternalLink + ExternalLink, + Square } from 'lucide-react'; const HOURS_LIST = Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, '0')); @@ -25,6 +26,14 @@ function App() { const [logs, setLogs] = useState([]); const [health, setHealth] = useState({ database: 'loading', redis: 'loading' }); const [errorLogModalContent, setErrorLogModalContent] = useState(null); + const [confirmModal, setConfirmModal] = useState({ + isOpen: false, + title: '', + message: '', + confirmText: 'حذف', + confirmType: 'danger', + onConfirm: () => {} + }); // Loading states const [loadingCrawlers, setLoadingCrawlers] = useState(true); @@ -271,15 +280,23 @@ function App() { } }; - const deleteCrawler = async (id) => { - if (!confirm('آیا از حذف این کرالر اطمینان دارید؟')) return; - try { - await axios.delete(`/api/crawlers/${id}/`); - showToast('کرالر با موفقیت حذف شد', 'success'); - fetchCrawlers(); - } catch (err) { - showToast('خطا در حذف کرالر', 'danger'); - } + const deleteCrawler = (id) => { + setConfirmModal({ + isOpen: true, + title: 'حذف کرالر', + message: 'آیا از حذف این کرالر اطمینان دارید؟ تمام سوابق اجرا و آگهی‌های مرتبط نیز حذف خواهند شد.', + confirmText: 'حذف کرالر', + confirmType: 'danger', + onConfirm: async () => { + try { + await axios.delete(`/api/crawlers/${id}/`); + showToast('کرالر با موفقیت حذف شد', 'success'); + fetchCrawlers(); + } catch (err) { + showToast('خطا در حذف کرالر', 'danger'); + } + } + }); }; const triggerCrawler = async (id) => { @@ -294,26 +311,61 @@ function App() { } }; - const deleteAd = async (id) => { - if (!confirm('آیا از حذف این آگهی اطمینان دارید؟')) return; - try { - await axios.delete(`/api/ads/${id}/`); - showToast('آگهی با موفقیت حذف شد', 'success'); - setAds(prev => prev.filter(item => item.id !== id)); - } catch (err) { - showToast('خطا در حذف آگهی', 'danger'); - } + const deleteAd = (id) => { + setConfirmModal({ + isOpen: true, + title: 'حذف آگهی از فید', + message: 'آیا از حذف این آگهی از فید اطمینان دارید؟ این عملیات قابل بازگشت نیست.', + confirmText: 'حذف آگهی', + confirmType: 'danger', + onConfirm: async () => { + try { + await axios.delete(`/api/ads/${id}/`); + showToast('آگهی با موفقیت حذف شد', 'success'); + setAds(prev => prev.filter(item => item.id !== id)); + } catch (err) { + showToast('خطا در حذف آگهی', 'danger'); + } + } + }); }; - const deleteRun = async (id) => { - if (!confirm('آیا از حذف این سابقه اجرا اطمینان دارید؟')) return; - try { - await axios.delete(`/api/crawlers/runs/${id}/`); - showToast('سابقه اجرا با موفقیت حذف شد', 'success'); - setLogs(prev => prev.filter(item => item.id !== id)); - } catch (err) { - showToast('خطا در حذف سابقه اجرا', 'danger'); - } + const deleteRun = (id) => { + setConfirmModal({ + isOpen: true, + title: 'حذف سابقه اجرا', + message: 'آیا از حذف این رکورد سابقه اجرا اطمینان دارید؟', + confirmText: 'حذف رکورد', + confirmType: 'danger', + onConfirm: async () => { + try { + await axios.delete(`/api/crawlers/runs/${id}/`); + showToast('سابقه اجرا با موفقیت حذف شد', 'success'); + setLogs(prev => prev.filter(item => item.id !== id)); + } catch (err) { + showToast('خطا در حذف سابقه اجرا', 'danger'); + } + } + }); + }; + + const stopRun = (id) => { + setConfirmModal({ + isOpen: true, + title: 'متوقف‌سازی اجرای کرالر', + message: 'آیا از متوقف‌سازی این اجرای فعال اطمینان دارید؟', + confirmText: 'توقف اجرا', + confirmType: 'warning', + onConfirm: async () => { + try { + await axios.post(`/api/crawlers/runs/${id}/stop/`); + showToast('اجرای کرالر متوقف شد', 'info'); + fetchLogs(); + } catch (err) { + showToast('خطا در متوقف‌سازی اجرا', 'danger'); + } + } + }); }; @@ -677,13 +729,24 @@ function App() { {run.error_log || '-'} - +
+ {run.status === 'RUNNING' && ( + + )} + +
))} @@ -882,6 +945,44 @@ function App() { )} + {/* Custom Confirmation Modal */} + {confirmModal.isOpen && ( +
+
+
+
+
+ +
+

{confirmModal.title}

+
+ +
+
+

{confirmModal.message}

+
+
+ + +
+
+
+ )} );