diff --git a/backend/igny8_core/modules/writer/views.py b/backend/igny8_core/modules/writer/views.py index ae4da5a3..03f8539b 100644 --- a/backend/igny8_core/modules/writer/views.py +++ b/backend/igny8_core/modules/writer/views.py @@ -756,6 +756,22 @@ class ContentViewSet(SiteSectorModelViewSet): else: serializer.save() + @action(detail=False, methods=['POST'], url_path='bulk_delete', url_name='bulk_delete') + def bulk_delete(self, request): + """Bulk delete content""" + ids = request.data.get('ids', []) + if not ids: + return error_response( + error='No IDs provided', + status_code=status.HTTP_400_BAD_REQUEST, + request=request + ) + + queryset = self.get_queryset() + deleted_count, _ = queryset.filter(id__in=ids).delete() + + return success_response(data={'deleted_count': deleted_count}, request=request) + @action(detail=True, methods=['post'], url_path='publish', url_name='publish', permission_classes=[IsAuthenticatedAndActive, IsEditorOrAbove]) def publish(self, request, pk=None): """ diff --git a/frontend/src/pages/Writer/Content.tsx b/frontend/src/pages/Writer/Content.tsx index 3eb21c7b..a52f716b 100644 --- a/frontend/src/pages/Writer/Content.tsx +++ b/frontend/src/pages/Writer/Content.tsx @@ -10,6 +10,8 @@ import { Content as ContentType, ContentFilters, generateImagePrompts, + deleteContent, + bulkDeleteContent, } from '../../services/api'; import { optimizerApi } from '../../api/optimizer.api'; import { useNavigate } from 'react-router'; @@ -210,6 +212,17 @@ export default function Content() { } }, [toast, progressModal, loadContent, navigate]); + const handleDelete = useCallback(async (id: number) => { + await deleteContent(id); + loadContent(); + }, [loadContent]); + + const handleBulkDelete = useCallback(async (ids: number[]) => { + const result = await bulkDeleteContent(ids); + loadContent(); + return result; + }, [loadContent]); + // Writer navigation tabs const writerTabs = [ { label: 'Tasks', path: '/writer/tasks', icon: }, @@ -265,6 +278,8 @@ export default function Content() { }} headerMetrics={headerMetrics} onRowAction={handleRowAction} + onDelete={handleDelete} + onBulkDelete={handleBulkDelete} getItemDisplayName={(row: ContentType) => row.title || `Content #${row.id}`} /> diff --git a/frontend/src/pages/Writer/Published.tsx b/frontend/src/pages/Writer/Published.tsx index e8c0bb7e..303ac742 100644 --- a/frontend/src/pages/Writer/Published.tsx +++ b/frontend/src/pages/Writer/Published.tsx @@ -12,6 +12,8 @@ import { ContentFilters, fetchAPI, fetchWordPressStatus, + deleteContent, + bulkDeleteContent, } from '../../services/api'; import { useNavigate } from 'react-router'; import { useToast } from '../../components/ui/toast/ToastContainer'; @@ -190,6 +192,17 @@ export default function Published() { } }, [toast, loadContent, navigate]); + const handleDelete = useCallback(async (id: number) => { + await deleteContent(id); + loadContent(); + }, [loadContent]); + + const handleBulkDelete = useCallback(async (ids: number[]) => { + const result = await bulkDeleteContent(ids); + loadContent(); + return result; + }, [loadContent]); + // Bulk WordPress publish const handleBulkPublishWordPress = useCallback(async (ids: string[]) => { try { @@ -347,6 +360,8 @@ export default function Published() { }} headerMetrics={headerMetrics} onRowAction={handleRowAction} + onDelete={handleDelete} + onBulkDelete={handleBulkDelete} onBulkAction={handleBulkAction} onBulkUpdateStatus={handleBulkUpdateStatus} onBulkExport={handleBulkExport}