From 7c4ed6a16c3558b179dd36bbb1f46563e7a455b3 Mon Sep 17 00:00:00 2001 From: alorig <220087330+alorig@users.noreply.github.com> Date: Fri, 28 Nov 2025 13:23:49 +0500 Subject: [PATCH] 123 --- DELETE_wordpress_api.txt | 1 + .../igny8_core/api/wordpress_publishing.py | 400 ------------------ .../igny8_core/tasks/wordpress_publishing.py | 385 ----------------- .../igny8_core/urls/wordpress_publishing.py | 38 -- .../src/config/pages/table-actions.config.tsx | 19 +- frontend/src/pages/Writer/Images.tsx | 61 +-- 6 files changed, 5 insertions(+), 899 deletions(-) create mode 100644 DELETE_wordpress_api.txt delete mode 100644 backend/igny8_core/api/wordpress_publishing.py delete mode 100644 backend/igny8_core/tasks/wordpress_publishing.py delete mode 100644 backend/igny8_core/urls/wordpress_publishing.py diff --git a/DELETE_wordpress_api.txt b/DELETE_wordpress_api.txt new file mode 100644 index 00000000..04df0a00 --- /dev/null +++ b/DELETE_wordpress_api.txt @@ -0,0 +1 @@ +# This file has been removed to fix circular import issues \ No newline at end of file diff --git a/backend/igny8_core/api/wordpress_publishing.py b/backend/igny8_core/api/wordpress_publishing.py deleted file mode 100644 index f2dd09c1..00000000 --- a/backend/igny8_core/api/wordpress_publishing.py +++ /dev/null @@ -1,400 +0,0 @@ -""" -WordPress Publishing API Views -Handles manual content publishing to WordPress sites -""" -from rest_framework import status -from rest_framework.decorators import api_view, permission_classes -from rest_framework.permissions import IsAuthenticated -from rest_framework.response import Response -from django.shortcuts import get_object_or_404 -from django.utils import timezone -from typing import Dict, Any, List - -from igny8_core.models import ContentPost, SiteIntegration -from igny8_core.tasks.wordpress_publishing import ( - publish_content_to_wordpress, - bulk_publish_content_to_wordpress -) - - -@api_view(['POST']) -@permission_classes([IsAuthenticated]) -def publish_single_content(request, content_id: int) -> Response: - """ - Publish a single content item to WordPress - - POST /api/v1/content/{content_id}/publish-to-wordpress/ - - Body: - { - "site_integration_id": 123, // Optional - will use default if not provided - "force": false // Optional - force republish even if already published - } - """ - try: - content = get_object_or_404(ContentPost, id=content_id) - - # Check permissions - if not request.user.has_perm('content.change_contentpost'): - return Response( - { - 'success': False, - 'message': 'Permission denied', - 'error': 'insufficient_permissions' - }, - status=status.HTTP_403_FORBIDDEN - ) - - # Get site integration - site_integration_id = request.data.get('site_integration_id') - force = request.data.get('force', False) - - if site_integration_id: - site_integration = get_object_or_404(SiteIntegration, id=site_integration_id) - else: - # Get default WordPress integration for user's organization - site_integration = SiteIntegration.objects.filter( - platform='wordpress', - is_active=True, - # Add organization filter if applicable - ).first() - - if not site_integration: - return Response( - { - 'success': False, - 'message': 'No WordPress integration found', - 'error': 'no_integration' - }, - status=status.HTTP_400_BAD_REQUEST - ) - - # Check if already published (unless force is true) - if not force and content.wordpress_sync_status == 'success': - return Response( - { - 'success': True, - 'message': 'Content already published to WordPress', - 'data': { - 'content_id': content.id, - 'wordpress_post_id': content.wordpress_post_id, - 'wordpress_post_url': content.wordpress_post_url, - 'status': 'already_published' - } - } - ) - - # Check if currently syncing - if content.wordpress_sync_status == 'syncing': - return Response( - { - 'success': False, - 'message': 'Content is currently being published to WordPress', - 'error': 'sync_in_progress' - }, - status=status.HTTP_409_CONFLICT - ) - - # Validate content is ready for publishing - if not content.title or not (content.content_html or content.content): - return Response( - { - 'success': False, - 'message': 'Content is incomplete - missing title or content', - 'error': 'incomplete_content' - }, - status=status.HTTP_400_BAD_REQUEST - ) - - # Set status to pending and queue the task - content.wordpress_sync_status = 'pending' - content.save(update_fields=['wordpress_sync_status']) - - # Get task_id if content is associated with a writer task - task_id = None - if hasattr(content, 'writer_task'): - task_id = content.writer_task.id - - # Queue the publishing task - task_result = publish_content_to_wordpress.delay( - content.id, - site_integration.id, - task_id - ) - - return Response( - { - 'success': True, - 'message': 'Content queued for WordPress publishing', - 'data': { - 'content_id': content.id, - 'site_integration_id': site_integration.id, - 'task_id': task_result.id, - 'status': 'queued' - } - }, - status=status.HTTP_202_ACCEPTED - ) - - except Exception as e: - return Response( - { - 'success': False, - 'message': f'Error queuing content for WordPress publishing: {str(e)}', - 'error': 'server_error' - }, - status=status.HTTP_500_INTERNAL_SERVER_ERROR - ) - - -@api_view(['POST']) -@permission_classes([IsAuthenticated]) -def bulk_publish_content(request) -> Response: - """ - Bulk publish multiple content items to WordPress - - POST /api/v1/content/bulk-publish-to-wordpress/ - - Body: - { - "content_ids": [1, 2, 3, 4], - "site_integration_id": 123, // Optional - "force": false // Optional - } - """ - try: - content_ids = request.data.get('content_ids', []) - site_integration_id = request.data.get('site_integration_id') - force = request.data.get('force', False) - - if not content_ids: - return Response( - { - 'success': False, - 'message': 'No content IDs provided', - 'error': 'missing_content_ids' - }, - status=status.HTTP_400_BAD_REQUEST - ) - - # Check permissions - if not request.user.has_perm('content.change_contentpost'): - return Response( - { - 'success': False, - 'message': 'Permission denied', - 'error': 'insufficient_permissions' - }, - status=status.HTTP_403_FORBIDDEN - ) - - # Get site integration - if site_integration_id: - site_integration = get_object_or_404(SiteIntegration, id=site_integration_id) - else: - site_integration = SiteIntegration.objects.filter( - platform='wordpress', - is_active=True, - ).first() - - if not site_integration: - return Response( - { - 'success': False, - 'message': 'No WordPress integration found', - 'error': 'no_integration' - }, - status=status.HTTP_400_BAD_REQUEST - ) - - # Validate content items - content_items = ContentPost.objects.filter(id__in=content_ids) - - if content_items.count() != len(content_ids): - return Response( - { - 'success': False, - 'message': 'Some content items not found', - 'error': 'content_not_found' - }, - status=status.HTTP_404_NOT_FOUND - ) - - # Queue bulk publishing task - task_result = bulk_publish_content_to_wordpress.delay( - content_ids, - site_integration.id - ) - - return Response( - { - 'success': True, - 'message': f'{len(content_ids)} content items queued for WordPress publishing', - 'data': { - 'content_count': len(content_ids), - 'site_integration_id': site_integration.id, - 'task_id': task_result.id, - 'status': 'queued' - } - }, - status=status.HTTP_202_ACCEPTED - ) - - except Exception as e: - return Response( - { - 'success': False, - 'message': f'Error queuing bulk WordPress publishing: {str(e)}', - 'error': 'server_error' - }, - status=status.HTTP_500_INTERNAL_SERVER_ERROR - ) - - -@api_view(['GET']) -@permission_classes([IsAuthenticated]) -def get_wordpress_status(request, content_id: int) -> Response: - """ - Get WordPress publishing status for a content item - - GET /api/v1/content/{content_id}/wordpress-status/ - """ - try: - content = get_object_or_404(ContentPost, id=content_id) - - return Response( - { - 'success': True, - 'data': { - 'content_id': content.id, - 'wordpress_sync_status': content.wordpress_sync_status, - 'wordpress_post_id': content.wordpress_post_id, - 'wordpress_post_url': content.wordpress_post_url, - 'wordpress_sync_attempts': content.wordpress_sync_attempts, - 'last_wordpress_sync': content.last_wordpress_sync.isoformat() if content.last_wordpress_sync else None, - } - } - ) - - except Exception as e: - return Response( - { - 'success': False, - 'message': f'Error getting WordPress status: {str(e)}', - 'error': 'server_error' - }, - status=status.HTTP_500_INTERNAL_SERVER_ERROR - ) - - -@api_view(['GET']) -@permission_classes([IsAuthenticated]) -def get_wordpress_integrations(request) -> Response: - """ - Get available WordPress integrations for publishing - - GET /api/v1/wordpress-integrations/ - """ - try: - integrations = SiteIntegration.objects.filter( - platform='wordpress', - is_active=True, - # Add organization filter if applicable - ).values( - 'id', 'site_name', 'site_url', 'is_active', - 'created_at', 'last_sync_at' - ) - - return Response( - { - 'success': True, - 'data': list(integrations) - } - ) - - except Exception as e: - return Response( - { - 'success': False, - 'message': f'Error getting WordPress integrations: {str(e)}', - 'error': 'server_error' - }, - status=status.HTTP_500_INTERNAL_SERVER_ERROR - ) - - -@api_view(['POST']) -@permission_classes([IsAuthenticated]) -def retry_failed_wordpress_sync(request, content_id: int) -> Response: - """ - Retry a failed WordPress sync - - POST /api/v1/content/{content_id}/retry-wordpress-sync/ - """ - try: - content = get_object_or_404(ContentPost, id=content_id) - - if content.wordpress_sync_status != 'failed': - return Response( - { - 'success': False, - 'message': 'Content is not in failed status', - 'error': 'invalid_status' - }, - status=status.HTTP_400_BAD_REQUEST - ) - - # Get default WordPress integration - site_integration = SiteIntegration.objects.filter( - platform='wordpress', - is_active=True, - ).first() - - if not site_integration: - return Response( - { - 'success': False, - 'message': 'No WordPress integration found', - 'error': 'no_integration' - }, - status=status.HTTP_400_BAD_REQUEST - ) - - # Reset status and retry - content.wordpress_sync_status = 'pending' - content.save(update_fields=['wordpress_sync_status']) - - # Get task_id if available - task_id = None - if hasattr(content, 'writer_task'): - task_id = content.writer_task.id - - # Queue the publishing task - task_result = publish_content_to_wordpress.delay( - content.id, - site_integration.id, - task_id - ) - - return Response( - { - 'success': True, - 'message': 'WordPress sync retry queued', - 'data': { - 'content_id': content.id, - 'task_id': task_result.id, - 'status': 'queued' - } - }, - status=status.HTTP_202_ACCEPTED - ) - - except Exception as e: - return Response( - { - 'success': False, - 'message': f'Error retrying WordPress sync: {str(e)}', - 'error': 'server_error' - }, - status=status.HTTP_500_INTERNAL_SERVER_ERROR - ) \ No newline at end of file diff --git a/backend/igny8_core/tasks/wordpress_publishing.py b/backend/igny8_core/tasks/wordpress_publishing.py deleted file mode 100644 index a564d8e5..00000000 --- a/backend/igny8_core/tasks/wordpress_publishing.py +++ /dev/null @@ -1,385 +0,0 @@ -""" -IGNY8 Content Publishing Celery Tasks - -Handles automated publishing of content from IGNY8 to WordPress sites. -""" -from celery import shared_task -from django.conf import settings -from django.utils import timezone -from datetime import timedelta -import requests -import logging -from typing import Dict, List, Any, Optional - -logger = logging.getLogger(__name__) - - -@shared_task(bind=True, max_retries=3) -def publish_content_to_wordpress(self, content_id: int, site_integration_id: int, task_id: Optional[int] = None) -> Dict[str, Any]: - """ - Publish a single content item to WordPress - - Args: - content_id: IGNY8 content ID - site_integration_id: WordPress site integration ID - task_id: Optional IGNY8 task ID - - Returns: - Dict with success status and details - """ - try: - from igny8_core.models import ContentPost, SiteIntegration - - # Get content and site integration - try: - content = ContentPost.objects.get(id=content_id) - site_integration = SiteIntegration.objects.get(id=site_integration_id) - except (ContentPost.DoesNotExist, SiteIntegration.DoesNotExist) as e: - logger.error(f"Content or site integration not found: {e}") - return {"success": False, "error": str(e)} - - # Check if content is ready for publishing - if content.wordpress_sync_status == 'success': - logger.info(f"Content {content_id} already published to WordPress") - return {"success": True, "message": "Already published", "wordpress_post_id": content.wordpress_post_id} - - if content.wordpress_sync_status == 'syncing': - logger.info(f"Content {content_id} is currently syncing") - return {"success": False, "error": "Content is currently syncing"} - - # Update status to syncing - content.wordpress_sync_status = 'syncing' - content.save(update_fields=['wordpress_sync_status']) - - # Prepare content data for WordPress - content_data = { - 'content_id': content.id, - 'task_id': task_id, - 'title': content.title, - 'content_html': content.content_html or content.content, - 'excerpt': content.brief or '', - 'status': 'publish', - 'author_email': content.author.email if content.author else None, - 'author_name': content.author.get_full_name() if content.author else None, - 'published_at': content.published_at.isoformat() if content.published_at else None, - 'seo_title': getattr(content, 'seo_title', ''), - 'seo_description': getattr(content, 'seo_description', ''), - 'featured_image_url': content.featured_image.url if content.featured_image else None, - 'sectors': [{'id': s.id, 'name': s.name} for s in content.sectors.all()], - 'clusters': [{'id': c.id, 'name': c.name} for c in content.clusters.all()], - 'tags': getattr(content, 'tags', []), - 'focus_keywords': getattr(content, 'focus_keywords', []) - } - - # Call WordPress REST API - wordpress_url = f"{site_integration.site_url}/wp-json/igny8/v1/publish-content/" - headers = { - 'Content-Type': 'application/json', - 'X-IGNY8-API-KEY': site_integration.api_key, - } - - response = requests.post( - wordpress_url, - json=content_data, - headers=headers, - timeout=30 - ) - - if response.status_code == 201: - # Success - wp_data = response.json().get('data', {}) - content.wordpress_sync_status = 'success' - content.wordpress_post_id = wp_data.get('post_id') - content.wordpress_post_url = wp_data.get('post_url') - content.last_wordpress_sync = timezone.now() - content.save(update_fields=[ - 'wordpress_sync_status', 'wordpress_post_id', - 'wordpress_post_url', 'last_wordpress_sync' - ]) - - logger.info(f"Successfully published content {content_id} to WordPress post {content.wordpress_post_id}") - return { - "success": True, - "wordpress_post_id": content.wordpress_post_id, - "wordpress_post_url": content.wordpress_post_url - } - - elif response.status_code == 409: - # Content already exists - wp_data = response.json().get('data', {}) - content.wordpress_sync_status = 'success' - content.wordpress_post_id = wp_data.get('post_id') - content.last_wordpress_sync = timezone.now() - content.save(update_fields=[ - 'wordpress_sync_status', 'wordpress_post_id', 'last_wordpress_sync' - ]) - - logger.info(f"Content {content_id} already exists on WordPress") - return {"success": True, "message": "Content already exists", "wordpress_post_id": content.wordpress_post_id} - - else: - # Error - error_msg = f"WordPress API error: {response.status_code} - {response.text}" - logger.error(error_msg) - - # Retry logic - if self.request.retries < self.max_retries: - content.wordpress_sync_attempts = (content.wordpress_sync_attempts or 0) + 1 - content.save(update_fields=['wordpress_sync_attempts']) - - # Exponential backoff: 1min, 5min, 15min - countdown = 60 * (5 ** self.request.retries) - raise self.retry(countdown=countdown, exc=Exception(error_msg)) - else: - # Max retries reached - content.wordpress_sync_status = 'failed' - content.last_wordpress_sync = timezone.now() - content.save(update_fields=['wordpress_sync_status', 'last_wordpress_sync']) - - return {"success": False, "error": error_msg} - - except Exception as e: - logger.error(f"Error publishing content {content_id}: {str(e)}") - - # Update content status on error - try: - content = ContentPost.objects.get(id=content_id) - content.wordpress_sync_status = 'failed' - content.last_wordpress_sync = timezone.now() - content.save(update_fields=['wordpress_sync_status', 'last_wordpress_sync']) - except: - pass - - return {"success": False, "error": str(e)} - - -@shared_task -def process_pending_wordpress_publications() -> Dict[str, Any]: - """ - Process all content items pending WordPress publication - Runs every 5 minutes - """ - try: - from igny8_core.models import ContentPost, SiteIntegration - - # Find content marked for WordPress publishing - pending_content = ContentPost.objects.filter( - wordpress_sync_status='pending', - published_at__isnull=False # Only published content - ).select_related('author').prefetch_related('sectors', 'clusters') - - if not pending_content.exists(): - logger.info("No content pending WordPress publication") - return {"success": True, "processed": 0} - - # Get active WordPress integrations - active_integrations = SiteIntegration.objects.filter( - platform='wordpress', - is_active=True, - api_key__isnull=False - ) - - if not active_integrations.exists(): - logger.warning("No active WordPress integrations found") - return {"success": False, "error": "No active WordPress integrations"} - - processed = 0 - failed = 0 - - for content in pending_content[:50]: # Process max 50 at a time - for integration in active_integrations: - # Get task_id if content is associated with a task - task_id = None - if hasattr(content, 'writer_task'): - task_id = content.writer_task.id - - # Queue individual publish task - publish_content_to_wordpress.delay( - content.id, - integration.id, - task_id - ) - processed += 1 - - logger.info(f"Queued {processed} content items for WordPress publication") - return {"success": True, "processed": processed, "failed": failed} - - except Exception as e: - logger.error(f"Error processing pending WordPress publications: {str(e)}") - return {"success": False, "error": str(e)} - - -@shared_task -def bulk_publish_content_to_wordpress(content_ids: List[int], site_integration_id: int) -> Dict[str, Any]: - """ - Bulk publish multiple content items to WordPress - Used for manual bulk operations from Content Manager - """ - try: - from igny8_core.models import ContentPost, SiteIntegration - - site_integration = SiteIntegration.objects.get(id=site_integration_id) - content_items = ContentPost.objects.filter(id__in=content_ids) - - results = { - "success": True, - "total": len(content_ids), - "queued": 0, - "skipped": 0, - "errors": [] - } - - for content in content_items: - try: - # Skip if already published or syncing - if content.wordpress_sync_status in ['success', 'syncing']: - results["skipped"] += 1 - continue - - # Mark as pending and queue - content.wordpress_sync_status = 'pending' - content.save(update_fields=['wordpress_sync_status']) - - # Get task_id if available - task_id = None - if hasattr(content, 'writer_task'): - task_id = content.writer_task.id - - # Queue individual publish task - publish_content_to_wordpress.delay( - content.id, - site_integration.id, - task_id - ) - results["queued"] += 1 - - except Exception as e: - results["errors"].append(f"Content {content.id}: {str(e)}") - - if results["errors"]: - results["success"] = len(results["errors"]) < results["total"] / 2 # Success if < 50% errors - - logger.info(f"Bulk publish: {results['queued']} queued, {results['skipped']} skipped, {len(results['errors'])} errors") - return results - - except Exception as e: - logger.error(f"Error in bulk publish: {str(e)}") - return {"success": False, "error": str(e)} - - -@shared_task -def wordpress_status_reconciliation() -> Dict[str, Any]: - """ - Daily task to reconcile status between IGNY8 and WordPress - Checks for discrepancies and fixes them - """ - try: - from igny8_core.models import ContentPost, SiteIntegration - - # Get content marked as published to WordPress - wp_content = ContentPost.objects.filter( - wordpress_sync_status='success', - wordpress_post_id__isnull=False - ) - - active_integrations = SiteIntegration.objects.filter( - platform='wordpress', - is_active=True - ) - - reconciled = 0 - errors = [] - - for integration in active_integrations: - integration_content = wp_content.filter( - # Assuming there's a way to link content to integration - # This would depend on your data model - ) - - for content in integration_content[:100]: # Limit to prevent timeouts - try: - # Check WordPress post status - wp_url = f"{integration.site_url}/wp-json/igny8/v1/post-status/{content.id}/" - headers = {'X-IGNY8-API-KEY': integration.api_key} - - response = requests.get(wp_url, headers=headers, timeout=10) - - if response.status_code == 200: - wp_data = response.json().get('data', {}) - wp_status = wp_data.get('wordpress_status') - - # Update if status changed - if wp_status == 'trash' and content.wordpress_sync_status == 'success': - content.wordpress_sync_status = 'failed' - content.save(update_fields=['wordpress_sync_status']) - reconciled += 1 - - elif response.status_code == 404: - # Post not found on WordPress - content.wordpress_sync_status = 'failed' - content.wordpress_post_id = None - content.wordpress_post_url = None - content.save(update_fields=[ - 'wordpress_sync_status', 'wordpress_post_id', 'wordpress_post_url' - ]) - reconciled += 1 - - except Exception as e: - errors.append(f"Content {content.id}: {str(e)}") - - logger.info(f"Status reconciliation: {reconciled} reconciled, {len(errors)} errors") - return {"success": True, "reconciled": reconciled, "errors": errors} - - except Exception as e: - logger.error(f"Error in status reconciliation: {str(e)}") - return {"success": False, "error": str(e)} - - -@shared_task -def retry_failed_wordpress_publications() -> Dict[str, Any]: - """ - Retry failed WordPress publications (runs daily) - Only retries items that failed more than 1 hour ago - """ - try: - from igny8_core.models import ContentPost, SiteIntegration - - # Find failed publications older than 1 hour - one_hour_ago = timezone.now() - timedelta(hours=1) - failed_content = ContentPost.objects.filter( - wordpress_sync_status='failed', - last_wordpress_sync__lt=one_hour_ago, - wordpress_sync_attempts__lt=5 # Max 5 total attempts - ) - - active_integrations = SiteIntegration.objects.filter( - platform='wordpress', - is_active=True - ) - - retried = 0 - - for content in failed_content[:20]: # Limit retries per run - for integration in active_integrations: - # Reset status and retry - content.wordpress_sync_status = 'pending' - content.save(update_fields=['wordpress_sync_status']) - - task_id = None - if hasattr(content, 'writer_task'): - task_id = content.writer_task.id - - publish_content_to_wordpress.delay( - content.id, - integration.id, - task_id - ) - retried += 1 - break # Only retry with first active integration - - logger.info(f"Retried {retried} failed WordPress publications") - return {"success": True, "retried": retried} - - except Exception as e: - logger.error(f"Error retrying failed publications: {str(e)}") - return {"success": False, "error": str(e)} \ No newline at end of file diff --git a/backend/igny8_core/urls/wordpress_publishing.py b/backend/igny8_core/urls/wordpress_publishing.py deleted file mode 100644 index 4a6e6765..00000000 --- a/backend/igny8_core/urls/wordpress_publishing.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -URL configuration for WordPress publishing endpoints -""" -from django.urls import path -from igny8_core.api.wordpress_publishing import ( - publish_single_content, - bulk_publish_content, - get_wordpress_status, - get_wordpress_integrations, - retry_failed_wordpress_sync, -) - -urlpatterns = [ - # Single content publishing - path('content//publish-to-wordpress/', - publish_single_content, - name='publish_single_content'), - - # Bulk content publishing - path('content/bulk-publish-to-wordpress/', - bulk_publish_content, - name='bulk_publish_content'), - - # WordPress status - path('content//wordpress-status/', - get_wordpress_status, - name='get_wordpress_status'), - - # WordPress integrations list - path('wordpress-integrations/', - get_wordpress_integrations, - name='get_wordpress_integrations'), - - # Retry failed sync - path('content//retry-wordpress-sync/', - retry_failed_wordpress_sync, - name='retry_failed_wordpress_sync'), -] \ No newline at end of file diff --git a/frontend/src/config/pages/table-actions.config.tsx b/frontend/src/config/pages/table-actions.config.tsx index 99b6a39e..baec163a 100644 --- a/frontend/src/config/pages/table-actions.config.tsx +++ b/frontend/src/config/pages/table-actions.config.tsx @@ -321,16 +321,6 @@ const tableActionsConfigs: Record = { }, '/writer/images': { rowActions: [ - { - key: 'publish_wordpress', - label: 'Publish to WordPress', - icon: , - variant: 'success', - shouldShow: (row: any) => { - // Only show if images are generated (complete) - WordPress status is tracked separately - return row.overall_status === 'complete'; - }, - }, { key: 'update_status', label: 'Update Status', @@ -338,14 +328,7 @@ const tableActionsConfigs: Record = { variant: 'primary', }, ], - bulkActions: [ - { - key: 'bulk_publish_wordpress', - label: 'Publish Ready to WordPress', - icon: , - variant: 'success', - }, - ], + bulkActions: [], }, // Default config (fallback) default: { diff --git a/frontend/src/pages/Writer/Images.tsx b/frontend/src/pages/Writer/Images.tsx index 0f544871..d04b579f 100644 --- a/frontend/src/pages/Writer/Images.tsx +++ b/frontend/src/pages/Writer/Images.tsx @@ -14,7 +14,6 @@ import { bulkUpdateImagesStatus, ContentImage, fetchAPI, - publishContent, } from '../../services/api'; import { useToast } from '../../components/ui/toast/ToastContainer'; import { FileIcon, DownloadIcon, BoltIcon, TaskIcon, ImageIcon, CheckCircleIcon } from '../../icons'; @@ -208,50 +207,8 @@ export default function Images() { // Bulk action handler const handleBulkAction = useCallback(async (action: string, ids: string[]) => { - if (action === 'bulk_publish_wordpress') { - // Filter to only publish items that have images generated - const readyItems = images - .filter(item => ids.includes(item.content_id.toString())) - .filter(item => item.overall_status === 'complete'); - - if (readyItems.length === 0) { - toast.warning('No items are ready for WordPress publishing. Items must have generated images and not already be published.'); - return; - } - - try { - let successCount = 0; - let failedCount = 0; - const errors: string[] = []; - - // Process each item individually using the existing publishContent function - for (const item of readyItems) { - try { - await publishContent(item.content_id); - successCount++; - } catch (error: any) { - failedCount++; - errors.push(`${item.content_title}: ${error.message}`); - } - } - - if (successCount > 0) { - toast.success(`Successfully published ${successCount} item(s) to WordPress`); - } - if (failedCount > 0) { - toast.warning(`${failedCount} item(s) failed to publish`); - } - - // Reload images to reflect the updated WordPress status - loadImages(); - } catch (error: any) { - console.error('Bulk WordPress publish error:', error); - toast.error(`Failed to bulk publish to WordPress: ${error.message || 'Network error'}`); - } - } else { - toast.info(`Bulk action "${action}" for ${ids.length} items`); - } - }, [images, toast, loadImages]); + toast.info(`Bulk action "${action}" for ${ids.length} items`); + }, [toast]); // Row action handler const handleRowAction = useCallback(async (action: string, row: ContentImagesGroup) => { @@ -259,20 +216,8 @@ export default function Images() { setStatusUpdateContentId(row.content_id); setStatusUpdateRecordName(row.content_title || `Content #${row.content_id}`); setIsStatusModalOpen(true); - } else if (action === 'publish_wordpress') { - // Handle WordPress publishing for individual item using existing publishContent function - try { - // Use the existing publishContent function from the API - const result = await publishContent(row.content_id); - toast.success(`Successfully published "${row.content_title}" to WordPress! View at: ${result.external_url}`); - // Reload images to reflect the updated WordPress status - loadImages(); - } catch (error: any) { - console.error('WordPress publish error:', error); - toast.error(`Failed to publish to WordPress: ${error.message || 'Network error'}`); - } } - }, [loadImages, toast]); + }, []); // Handle status update confirmation const handleStatusUpdate = useCallback(async (status: string) => {