Skip to content
Closed
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
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "بدء",
"stop": "إيقاف",
"reconnect": "إعادة الاتصال",
"delete": "حذف"
"delete": "حذف",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "الجلسة جاهزة",
Expand All @@ -241,6 +242,16 @@
"sessionId": "معرّف الجلسة",
"lastActive": "آخر نشاط",
"error": "خطأ"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "فشل الحفظ"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "Start",
"stop": "Stop",
"reconnect": "Reconnect",
"delete": "Delete"
"delete": "Delete",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "Session Ready",
Expand All @@ -241,6 +242,16 @@
"sessionId": "Session ID",
"lastActive": "Last Active",
"error": "Error"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "Save Failed"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "Iniciar",
"stop": "Detener",
"reconnect": "Reconectar",
"delete": "Eliminar"
"delete": "Eliminar",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "Sesión lista",
Expand All @@ -241,6 +242,16 @@
"sessionId": "ID de sesión",
"lastActive": "Última actividad",
"error": "Error"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "Error al guardar"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "Démarrer",
"stop": "Arrêter",
"reconnect": "Reconnecter",
"delete": "Supprimer"
"delete": "Supprimer",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "Session prête",
Expand All @@ -241,6 +242,16 @@
"sessionId": "ID de session",
"lastActive": "Dernière activité",
"error": "Erreur"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "Échec de l'enregistrement"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "הפעלה",
"stop": "עצירה",
"reconnect": "התחברות מחדש",
"delete": "מחיקה"
"delete": "מחיקה",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "ה-Session מוכן",
Expand All @@ -241,6 +242,16 @@
"sessionId": "מזהה Session",
"lastActive": "פעילות אחרונה",
"error": "שגיאה"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "השמירה נכשלה"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "Avvia",
"stop": "Ferma",
"reconnect": "Riconnetti",
"delete": "Elimina"
"delete": "Elimina",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "Sessione Pronta",
Expand All @@ -241,6 +242,16 @@
"sessionId": "ID Sessione",
"lastActive": "Ultima Attività",
"error": "Errore"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "Salvataggio non riuscito"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/te.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "ప్రారంభించు",
"stop": "ఆపివేయి",
"reconnect": "మళ్లీ కనెక్ట్ చేయి",
"delete": "తొలగించు"
"delete": "తొలగించు",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "సెషన్ సిద్ధంగా ఉంది",
Expand All @@ -241,6 +242,16 @@
"sessionId": "సెషన్ ID",
"lastActive": "చివరిసారి యాక్టివ్",
"error": "లోపం"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "సేవ్ చేయడం విఫలమైంది"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "启动",
"stop": "停止",
"reconnect": "重新连接",
"delete": "删除"
"delete": "删除",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "会话就绪",
Expand All @@ -241,6 +242,16 @@
"sessionId": "会话 ID",
"lastActive": "上次活跃",
"error": "错误"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "保存失败"
}
}
}
}
15 changes: 13 additions & 2 deletions dashboard/src/i18n/locales/zh-HK.json
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@
"start": "啟動",
"stop": "停止",
"reconnect": "重新連線",
"delete": "刪除"
"delete": "刪除",
"killStuck": "Kill Stuck"
},
"toasts": {
"readyTitle": "工作階段就緒",
Expand All @@ -241,6 +242,16 @@
"sessionId": "工作階段 ID",
"lastActive": "上次活躍",
"error": "錯誤"
},
"forceKill": {
"title": "Kill Stuck Session",
"message": "Are you sure you want to force-kill session \"{{name}}\"?",
"warning": "This will forcefully terminate the WhatsApp browser process. The session may need to be re-scanned on restart.",
"confirm": "Kill Session",
"successTitle": "Session Killed",
"success": "Session has been force-killed. You can restart it now.",
"failedTitle": "Force-Kill Failed",
"failed": "Failed to force-kill the session."
}
},
"webhooks": {
Expand Down Expand Up @@ -605,4 +616,4 @@
"saveFailed": "儲存失敗"
}
}
}
}
54 changes: 53 additions & 1 deletion dashboard/src/pages/Sessions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { Trans, useTranslation } from 'react-i18next';
import { Plus, QrCode, RefreshCw, Trash2, Eye, Loader2, Play, Square, X, Search, Filter } from 'lucide-react';
import { Plus, QrCode, RefreshCw, Trash2, Eye, Loader2, Play, Square, X, Search, Filter, Skull } from 'lucide-react';
import { sessionApi, type Session } from '../services/api';
import { useDocumentTitle } from '../hooks/useDocumentTitle';
import { useToast } from '../components/Toast';
Expand All @@ -25,6 +25,7 @@
const [statusFilter, setStatusFilter] = useState('all');
const [selectedSession, setSelectedSession] = useState<Session | null>(null);
const [deleteConfirmId, setDeleteConfirmId] = useState<string | null>(null);
const [killConfirmId, setKillConfirmId] = useState<string | null>(null);

const fetchSessions = useCallback(async (): Promise<Session[]> => {
try {
Expand Down Expand Up @@ -104,7 +105,7 @@
fetchSessions();
}
}
}, [sessions]);

Check warning on line 108 in dashboard/src/pages/Sessions.tsx

View workflow job for this annotation

GitHub Actions / Dashboard

React Hook useCallback has a missing dependency: 'fetchSessions'. Either include it or remove the dependency array

useEffect(() => {
if (qrData) {
Expand Down Expand Up @@ -204,6 +205,20 @@
}
};

const handleForceKill = async (id: string) => {
try {
await sessionApi.forceKill(id);
setSessions(sessions.map(s => (s.id === id ? { ...s, status: 'disconnected' } : s)));
toast.success(t('sessions.forceKill.successTitle'), t('sessions.forceKill.success'));
} catch (err) {
console.error('Failed to force-kill:', err);
toast.error(t('sessions.forceKill.failedTitle'), t('sessions.forceKill.failed'));
fetchSessions();
} finally {
setKillConfirmId(null);
}
};

const formatLastActive = (date?: string) => {
if (!date) return t('common.never');
const diff = Date.now() - new Date(date).getTime();
Expand Down Expand Up @@ -462,6 +477,37 @@
</div>
)}

{killConfirmId && (
<div className="modal-overlay" onClick={() => setKillConfirmId(null)}>
<div className="modal confirm-modal" onClick={e => e.stopPropagation()}>
<div className="modal-header">
<h2>{t('sessions.forceKill.title')}</h2>
<button className="btn-icon" onClick={() => setKillConfirmId(null)}>
<X size={20} />
</button>
</div>
<div className="modal-body">
<p>
<Trans
i18nKey="sessions.forceKill.message"
values={{ name: sessions.find(s => s.id === killConfirmId)?.name }}
components={{ strong: <strong /> }}
/>
</p>
<p className="text-muted">{t('sessions.forceKill.warning')}</p>
</div>
<div className="modal-footer">
<button className="btn-secondary" onClick={() => setKillConfirmId(null)}>
{t('common.cancel')}
</button>
<button className="btn-danger" onClick={() => handleForceKill(killConfirmId)}>
{t('sessions.forceKill.confirm')}
</button>
</div>
</div>
</div>
)}

<div className="sessions-grid">
{filteredSessions.length === 0 ? (
<div className="empty-state">
Expand Down Expand Up @@ -542,6 +588,12 @@
{t('sessions.actions.delete')}
</button>
)}
{canWrite && session.status === 'failed' && (
<button className="btn-action danger" onClick={() => setKillConfirmId(session.id)}>
<Skull size={16} />
{t('sessions.actions.killStuck')}
</button>
)}
</div>
</div>
))
Expand Down
Loading
Loading