From 815c7b5129cfa378886c258ecfd857ca33187f2b Mon Sep 17 00:00:00 2001 From: "IGNY8 VPS (Salman)" Date: Thu, 1 Jan 2026 10:41:31 +0000 Subject: [PATCH] 12 --- .../BulkWordPressPublish.tsx | 284 ++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 frontend/src/components/BulkWordPressPublish/BulkWordPressPublish.tsx diff --git a/frontend/src/components/BulkWordPressPublish/BulkWordPressPublish.tsx b/frontend/src/components/BulkWordPressPublish/BulkWordPressPublish.tsx new file mode 100644 index 00000000..b2d94d80 --- /dev/null +++ b/frontend/src/components/BulkWordPressPublish/BulkWordPressPublish.tsx @@ -0,0 +1,284 @@ +import React, { useState } from 'react'; +import { + Button, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Typography, + Box, + LinearProgress, + Alert, + List, + ListItem, + ListItemText, + ListItemIcon, + CircularProgress, + Chip +} from '@mui/material'; +import { + Publish as PublishIcon, + CheckCircle as SuccessIcon, + Error as ErrorIcon, + Schedule as PendingIcon +} from '@mui/icons-material'; +import { api } from '../../services/api'; + +interface BulkWordPressPublishProps { + selectedContentIds: string[]; + contentItems: Array<{ + id: string; + title: string; + status: string; + }>; + onPublishComplete: () => void; + onClose: () => void; +} + +interface BulkPublishResult { + total: number; + queued: number; + skipped: number; + errors: string[]; +} + +export const BulkWordPressPublish: React.FC = ({ + selectedContentIds, + contentItems, + onPublishComplete, + onClose +}) => { + const [open, setOpen] = useState(false); + const [publishing, setPublishing] = useState(false); + const [result, setResult] = useState(null); + const [error, setError] = useState(null); + + const selectedItems = contentItems.filter(item => + selectedContentIds.includes(item.id) + ); + + const handleBulkPublish = async () => { + setPublishing(true); + setError(null); + setResult(null); + + try { + const response = await api.post('/api/v1/content/bulk-publish-to-wordpress/', { + content_ids: selectedContentIds.map(id => parseInt(id)) + }); + + if (response.data.success) { + setResult({ + total: selectedContentIds.length, + queued: response.data.data.content_count, + skipped: 0, + errors: [] + }); + + // Start polling for individual status updates + startStatusPolling(); + } else { + setError(response.data.message || 'Failed to start bulk publishing'); + } + } catch (error: any) { + setError(error.response?.data?.message || 'Error starting bulk publish'); + } finally { + setPublishing(false); + } + }; + + const startStatusPolling = () => { + // Poll for 2 minutes to check status + const pollInterval = setInterval(async () => { + try { + // Check status of all items (this could be optimized with a dedicated endpoint) + const statusPromises = selectedContentIds.map(id => + api.get(`/api/v1/content/${id}/wordpress-status/`) + ); + + const responses = await Promise.allSettled(statusPromises); + + let completedCount = 0; + let successCount = 0; + let failedCount = 0; + + responses.forEach((response) => { + if (response.status === 'fulfilled' && response.value.data.success) { + const status = response.value.data.data.wordpress_sync_status; + if (status === 'success' || status === 'failed') { + completedCount++; + if (status === 'success') successCount++; + if (status === 'failed') failedCount++; + } + } + }); + + // If all items are complete, stop polling + if (completedCount === selectedContentIds.length) { + clearInterval(pollInterval); + setResult(prev => prev ? { + ...prev, + queued: successCount, + errors: Array(failedCount).fill('Publishing failed') + } : null); + onPublishComplete(); + } + } catch (error) { + console.error('Error polling status:', error); + } + }, 5000); + + // Stop polling after 2 minutes + setTimeout(() => { + clearInterval(pollInterval); + }, 120000); + }; + + const handleOpen = () => { + setOpen(true); + setResult(null); + setError(null); + }; + + const handleClose = () => { + setOpen(false); + onClose(); + }; + + const getResultSummary = () => { + if (!result) return null; + + const { total, queued, skipped, errors } = result; + const failed = errors.length; + + return ( + + + Bulk Publish Results + + + + } + label={`${queued} Queued`} + color="success" + size="small" + /> + {skipped > 0 && ( + } + label={`${skipped} Skipped`} + color="warning" + size="small" + /> + )} + {failed > 0 && ( + } + label={`${failed} Failed`} + color="error" + size="small" + /> + )} + + + {failed > 0 && ( + + Some items failed to publish. Check individual item status for details. + + )} + + ); + }; + + return ( + <> + + + + + Bulk Publish to Site + + + + {!publishing && !result && ( + <> + + You are about to publish {selectedContentIds.length} content items to your site: + + + + {selectedItems.map((item) => ( + + + + + + + ))} + + + + This will create new posts on your WordPress site with all content, + images, categories, and SEO metadata. Items already published will be skipped. + + + )} + + {publishing && ( + + + + Queuing content for WordPress publishing... + + + + )} + + {result && getResultSummary()} + + {error && ( + + {error} + + )} + + + + + + {!publishing && !result && ( + + )} + + + + ); +}; + +export default BulkWordPressPublish; \ No newline at end of file