feat: Add functionality to clear finished tasks
This commit is contained in:
@@ -121,6 +121,18 @@ export const deleteContinuousDownloadTask = async (
|
||||
res.status(200).json(successMessage("Task deleted"));
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear all finished continuous download tasks
|
||||
* Errors are automatically handled by asyncHandler middleware
|
||||
*/
|
||||
export const clearFinishedTasks = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<void> => {
|
||||
await continuousDownloadService.clearFinishedTasks();
|
||||
res.status(200).json(successMessage("Finished tasks cleared"));
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a continuous download task for a playlist
|
||||
* Errors are automatically handled by asyncHandler middleware
|
||||
|
||||
@@ -133,6 +133,11 @@ router.get(
|
||||
"/subscriptions/tasks",
|
||||
asyncHandler(subscriptionController.getContinuousDownloadTasks)
|
||||
);
|
||||
// Specific routes must come before parameterized routes (:id)
|
||||
router.delete(
|
||||
"/subscriptions/tasks/clear-finished",
|
||||
asyncHandler(subscriptionController.clearFinishedTasks)
|
||||
);
|
||||
router.delete(
|
||||
"/subscriptions/tasks/:id",
|
||||
asyncHandler(subscriptionController.cancelContinuousDownloadTask)
|
||||
|
||||
@@ -170,6 +170,26 @@ export class ContinuousDownloadService {
|
||||
await this.taskRepository.deleteTask(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all finished tasks (completed or cancelled)
|
||||
*/
|
||||
async clearFinishedTasks(): Promise<void> {
|
||||
const tasks = await this.getAllTasks();
|
||||
const finishedTasks = tasks.filter(
|
||||
(task) => task.status === "completed" || task.status === "cancelled"
|
||||
);
|
||||
|
||||
logger.info(`Clearing ${finishedTasks.length} finished tasks`);
|
||||
|
||||
for (const task of finishedTasks) {
|
||||
try {
|
||||
await this.deleteTask(task.id);
|
||||
} catch (error) {
|
||||
logger.error(`Error deleting task ${task.id} during cleanup:`, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a continuous download task
|
||||
*/
|
||||
|
||||
@@ -64,6 +64,7 @@ const SubscriptionsPage: React.FC = () => {
|
||||
const [selectedSubscription, setSelectedSubscription] = useState<{ id: string; author: string } | null>(null);
|
||||
const [isCancelTaskModalOpen, setIsCancelTaskModalOpen] = useState(false);
|
||||
const [isDeleteTaskModalOpen, setIsDeleteTaskModalOpen] = useState(false);
|
||||
const [isClearFinishedModalOpen, setIsClearFinishedModalOpen] = useState(false);
|
||||
const [selectedTask, setSelectedTask] = useState<ContinuousDownloadTask | null>(null);
|
||||
|
||||
// Use React Query for better caching and memory management
|
||||
@@ -163,6 +164,23 @@ const SubscriptionsPage: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleClearFinishedClick = () => {
|
||||
setIsClearFinishedModalOpen(true);
|
||||
};
|
||||
|
||||
const handleConfirmClearFinished = async () => {
|
||||
try {
|
||||
await axios.delete(`${API_URL}/subscriptions/tasks/clear-finished`);
|
||||
showSnackbar(t('tasksCleared'));
|
||||
refetchTasks();
|
||||
} catch (error) {
|
||||
console.error('Error clearing finished tasks:', error);
|
||||
showSnackbar(t('error'));
|
||||
} finally {
|
||||
setIsClearFinishedModalOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getTaskProgress = (task: ContinuousDownloadTask) => {
|
||||
if (task.totalVideos === 0) return 0;
|
||||
return Math.round((task.currentVideoIndex / task.totalVideos) * 100);
|
||||
@@ -232,9 +250,22 @@ const SubscriptionsPage: React.FC = () => {
|
||||
|
||||
{tasks.length > 0 && (
|
||||
<Box sx={{ mt: 4 }}>
|
||||
<Typography variant="h5" component="h2" gutterBottom fontWeight="bold">
|
||||
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
||||
<Typography variant="h5" component="h2" fontWeight="bold">
|
||||
{t('continuousDownloadTasks')}
|
||||
</Typography>
|
||||
{!visitorMode && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={handleClearFinishedClick}
|
||||
startIcon={<DeleteOutline />}
|
||||
size="small"
|
||||
>
|
||||
{t('clearFinishedTasks')}
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
<TableContainer component={Paper} sx={{ mt: 2 }}>
|
||||
<Table>
|
||||
<TableHead>
|
||||
@@ -347,6 +378,16 @@ const SubscriptionsPage: React.FC = () => {
|
||||
cancelText={t('cancel')}
|
||||
isDanger
|
||||
/>
|
||||
<ConfirmationModal
|
||||
isOpen={isClearFinishedModalOpen}
|
||||
onClose={() => setIsClearFinishedModalOpen(false)}
|
||||
onConfirm={handleConfirmClearFinished}
|
||||
title={t('clearFinishedTasks')}
|
||||
message={t('confirmClearFinishedTasks')}
|
||||
confirmText={t('clear')}
|
||||
cancelText={t('cancel')}
|
||||
isDanger
|
||||
/>
|
||||
</Container >
|
||||
);
|
||||
};
|
||||
|
||||
@@ -450,6 +450,10 @@ export const ar = {
|
||||
deleteTask: "حذف المهمة",
|
||||
confirmDeleteTask: "هل أنت متأكد أنك تريد حذف سجل المهمة لـ {author}؟ لا يمكن التراجع عن هذا الإجراء.",
|
||||
taskDeleted: "تم حذف المهمة بنجاح",
|
||||
clearFinishedTasks: "مسح المهام المنتهية",
|
||||
tasksCleared: "تم مسح المهام المنتهية بنجاح",
|
||||
confirmClearFinishedTasks: "هل أنت متأكد أنك تريد مسح جميع المهام المنتهية (المكتملة، الملغاة)؟ سيؤدي هذا إلى إزالتها من القائمة ولكن لن يحذف أي ملفات تم تنزيلها.",
|
||||
clear: "مسح",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. التنزيل وإدارة المهام",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -423,6 +423,10 @@ export const de = {
|
||||
deleteTask: "Aufgabe löschen",
|
||||
confirmDeleteTask: "Sind Sie sicher, dass Sie den Aufgaben-Datensatz für {author} löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
|
||||
taskDeleted: "Aufgabe erfolgreich gelöscht",
|
||||
clearFinishedTasks: "Beendete Aufgaben löschen",
|
||||
tasksCleared: "Beendete Aufgaben erfolgreich gelöscht",
|
||||
confirmClearFinishedTasks: "Sind Sie sicher, dass Sie alle beendeten Aufgaben (abgeschlossen, abgebrochen) löschen möchten? Dies entfernt sie aus der Liste, löscht aber keine heruntergeladenen Dateien.",
|
||||
clear: "Löschen",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. Download & Aufgabenverwaltung",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -452,6 +452,11 @@ export const en = {
|
||||
confirmDeleteTask:
|
||||
"Are you sure you want to delete the task record for {author}? This action cannot be undone.",
|
||||
taskDeleted: "Task deleted successfully",
|
||||
clearFinishedTasks: "Clear Finished Tasks",
|
||||
tasksCleared: "Finished tasks cleared successfully",
|
||||
confirmClearFinishedTasks:
|
||||
"Are you sure you want to clear all finished tasks (completed, cancelled)? This will remove them from the list but will not delete any downloaded files.",
|
||||
clear: "Clear",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. Download & Task Management",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -438,6 +438,10 @@ export const es = {
|
||||
deleteTask: "Eliminar tarea",
|
||||
confirmDeleteTask: "¿Estás seguro de que quieres eliminar el registro de tarea para {author}? Esta acción no se puede deshacer.",
|
||||
taskDeleted: "Tarea eliminada exitosamente",
|
||||
clearFinishedTasks: "Borrar tareas finalizadas",
|
||||
tasksCleared: "Tareas finalizadas borradas con éxito",
|
||||
confirmClearFinishedTasks: "¿Está seguro de que desea borrar todas las tareas finalizadas (completadas, canceladas)? Esto las eliminará de la lista pero no borrará ningún archivo descargado.",
|
||||
clear: "Borrar",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. Descarga y Gestión de Tareas",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -472,6 +472,10 @@ export const fr = {
|
||||
confirmDeleteTask:
|
||||
"Êtes-vous sûr de vouloir supprimer l'enregistrement de tâche pour {author} ? Cette action ne peut pas être annulée.",
|
||||
taskDeleted: "Tâche supprimée avec succès",
|
||||
clearFinishedTasks: "Effacer les tâches terminées",
|
||||
tasksCleared: "Tâches terminées effacées avec succès",
|
||||
confirmClearFinishedTasks: "Êtes-vous sûr de vouloir effacer toutes les tâches terminées (complétées, annulées) ? Cela les supprimera de la liste mais ne supprimera aucun fichier téléchargé.",
|
||||
clear: "Effacer",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. Téléchargement et Gestion des Tâches",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -444,6 +444,10 @@ export const ja = {
|
||||
deleteTask: "タスクを削除",
|
||||
confirmDeleteTask: "{author} のタスクレコードを削除してもよろしいですか?この操作は元に戻せません。",
|
||||
taskDeleted: "タスクが正常に削除されました",
|
||||
clearFinishedTasks: "完了したタスクをクリア",
|
||||
tasksCleared: "完了したタスクを正常にクリアしました",
|
||||
confirmClearFinishedTasks: "完了したタスク(完了、キャンセル済み)をすべてクリアしてもよろしいですか?これによりリストからは削除されますが、ダウンロードされたファイルは削除されません。",
|
||||
clear: "クリア",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. ダウンロードとタスク管理",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -440,6 +440,10 @@ export const ko = {
|
||||
deleteTask: "작업 삭제",
|
||||
confirmDeleteTask: "{author}님의 작업 기록을 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.",
|
||||
taskDeleted: "작업이 성공적으로 삭제되었습니다",
|
||||
clearFinishedTasks: "완료된 작업 지우기",
|
||||
tasksCleared: "완료된 작업이 성공적으로 지워졌습니다",
|
||||
confirmClearFinishedTasks: "완료된 모든 작업(완료됨, 취소됨)을 지우시겠습니까? 목록에서 제거되지만 다운로드된 파일은 삭제되지 않습니다.",
|
||||
clear: "지우기",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. 다운로드 및 작업 관리",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -453,6 +453,10 @@ export const pt = {
|
||||
deleteTask: "Excluir tarefa",
|
||||
confirmDeleteTask: "Tem certeza de que deseja excluir o registro da tarefa para {author}? Esta ação não pode ser desfeita.",
|
||||
taskDeleted: "Tarefa excluída com sucesso",
|
||||
clearFinishedTasks: "Limpar tarefas concluídas",
|
||||
tasksCleared: "Tarefas concluídas limpas com sucesso",
|
||||
confirmClearFinishedTasks: "Tem certeza de que deseja limpar todas as tarefas concluídas (concluídas, canceladas)? Isso as removerá da lista, mas não excluirá nenhum arquivo baixado.",
|
||||
clear: "Limpar",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. Download e Gerenciamento de Tarefas",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -458,6 +458,10 @@ export const ru = {
|
||||
deleteTask: "Удалить задачу",
|
||||
confirmDeleteTask: "Вы уверены, что хотите удалить запись задачи для {author}? Это действие нельзя отменить.",
|
||||
taskDeleted: "Задача успешно удалена",
|
||||
clearFinishedTasks: "Очистить завершенные задачи",
|
||||
tasksCleared: "Завершенные задачи успешно очищены",
|
||||
confirmClearFinishedTasks: "Вы уверены, что хотите очистить все завершенные задачи (завершенные, отмененные)? Это удалит их из списка, но не удалит загруженные файлы.",
|
||||
clear: "Очистить",
|
||||
// Instruction Page
|
||||
instructionSection1Title: "1. Загрузка и управление задачами",
|
||||
instructionSection1Desc:
|
||||
|
||||
@@ -180,7 +180,8 @@ export const zh = {
|
||||
clearing: "清除中...",
|
||||
clearThumbnailCacheSuccess: "缩略图缓存清除成功。下次访问时将重新生成。",
|
||||
clearThumbnailCacheError: "清除缩略图缓存失败",
|
||||
clearThumbnailCacheConfirmMessage: "这将清除所有云端视频的本地缩略图缓存。下次访问时将从云端重新生成。确定继续吗?",
|
||||
clearThumbnailCacheConfirmMessage:
|
||||
"这将清除所有云端视频的本地缩略图缓存。下次访问时将从云端重新生成。确定继续吗?",
|
||||
|
||||
// Manage
|
||||
manageContent: "内容管理",
|
||||
@@ -440,6 +441,10 @@ export const zh = {
|
||||
deleteTask: "删除任务",
|
||||
confirmDeleteTask: "您确定要删除 {author} 的任务记录吗?此操作无法撤销。",
|
||||
taskDeleted: "任务已成功删除",
|
||||
clearFinishedTasks: "清除已完成任务",
|
||||
tasksCleared: "已成功清除已完成的任务",
|
||||
confirmClearFinishedTasks: "您确定要清除所有已完成的任务(包括已完成和已取消)吗?这只会将其从列表中移除,不会删除任何已下载的文件。",
|
||||
clear: "清除",
|
||||
|
||||
// Existing Video Detection
|
||||
existingVideoDetected: "检测到已下载视频",
|
||||
|
||||
Reference in New Issue
Block a user