# Writer Module Comprehensive Refactoring Plan **Date:** December 2024 **Purpose:** Complete refactoring of Writer module pages (Tasks, Content, Images, Published) based on deep analysis and user requirements --- ## Executive Summary This document outlines a comprehensive refactoring plan for the IGNY8 Writer module. After deep analysis of all Writer pages, configurations, and data flows, we've identified critical issues and improvements needed to create a cohesive, efficient content workflow from task creation through WordPress publishing. **Key Objectives:** 1. Fix critical bugs (bulk select, delete functions) 2. Restructure Published page to show Content (not Tasks) 3. Implement proper WordPress publishing workflow 4. Add "review" status to content lifecycle 5. Improve UX with better status indicators and content viewing --- ## Current State Analysis ### Page Structure Overview ``` Writer Module Flow: Tasks (queued/completed) → Content (draft/published) → Images (pending/generated/failed) → Published (?) ``` ### 1. Tasks Page (`Tasks.tsx` - 787 lines) **Purpose:** Task queue management for content generation **Current Implementation:** - ✅ Loads Tasks table via `fetchTasks()` API - ✅ Status workflow: `queued` → `completed` - ✅ Row actions: Edit, Generate Content - ✅ Bulk actions: Update Status, Export - ✅ Progress modal for AI functions - ✅ Selection and pagination working - ✅ AI logs when Resource Debug enabled **Issues:** - None critical **Data Model:** ```typescript interface Task { id: number; title: string; cluster: string; taxonomy: string; content_type: string; content_structure: string; status: 'queued' | 'completed'; word_count: number; created_at: string; } ``` --- ### 2. Content Page (`Content.tsx` - 315 lines) **Purpose:** Content management and editing **Current Implementation:** - ✅ Loads Content table via `fetchContent()` API - ✅ Status workflow: `draft` → `published` - ✅ Row actions: Edit, View on WordPress (if published), Generate Image Prompts - ✅ Bulk actions: Update Status, Export, Publish Selected - ✅ Progress modal for image prompt generation - ✅ Selection and pagination working **Issues:** 1. ❌ **No content viewer link** - Title column not clickable to view content 2. ❌ **Missing status indicators** - No visual feedback for: - Prompt generation status (pending/complete) - Image generation status (pending/generating/complete) 3. ⚠️ **Publish action ambiguity** - Bulk "Publish Selected" action exists but unclear what it does **Data Model:** ```typescript interface ContentType { id: number; title: string; sector: string; content_type: string; content_structure: string; cluster: string; taxonomy: string; status: 'draft' | 'published'; word_count: number; source: string; created_at: string; external_id?: string | null; // WordPress post ID external_url?: string | null; // WordPress post URL sync_status?: string; } ``` **Configuration (`content.config.tsx` - 376 lines):** - Columns: title, sector, content_type, content_structure, cluster, taxonomy, status, word_count, source, created_at - Missing columns: prompts_status, images_status --- ### 3. Images Page (`Images.tsx` - 738 lines) **Purpose:** Image management grouped by content **Current Implementation:** - ✅ Loads ContentImagesGroup via `fetchContentImages()` API - ✅ Client-side filtering, sorting, pagination - ✅ Row actions: Publish to WordPress, Update Status - ✅ Bulk actions: Bulk Publish Ready to WordPress - ✅ Image generation functionality with queue modal - ✅ AI logs when Resource Debug enabled **Issues:** 1. ❌ **Bulk select checkbox not working** - Root cause: `ContentImagesGroup` interface has `content_id` but TablePageTemplate expects `id` field for selection 2. ❌ **Delete functions not working** - No delete handlers implemented 3. ⚠️ **Wrong location for WordPress publishing** - Should be on Published page, not here **Data Model:** ```typescript interface ContentImagesGroup { content_id: number; // ⚠️ No 'id' field - breaks selection! content_title: string; featured_image: ContentImage | null; in_article_images: ContentImage[]; overall_status: 'pending' | 'partial' | 'complete' | 'failed'; // Missing fields for WordPress publishing context: external_id?: string; external_url?: string; sync_status?: string; status?: 'draft' | 'published' | 'review'; } interface ContentImage { id: number; image_url: string | null; image_path: string | null; prompt: string | null; status: 'pending' | 'generated' | 'failed'; position: number; } ``` **Configuration (`images.config.tsx`):** - Columns: content_title, featured_image, in_article_1-5, overall_status, actions - Row actions: publish_wordpress, update_status - Bulk actions: bulk_publish_wordpress --- ### 4. Published Page (`Published.tsx` - 13 lines) **Purpose:** Show published content with WordPress publishing capabilities **Current Implementation:** ```tsx import Tasks from './Tasks'; export default function Published() { return ; } ``` **Issues:** 1. ❌ **Wrong table loaded** - Renders `` instead of Content table 2. ❌ **No WordPress publishing UI** - Should have edit and publish functionality 3. ❌ **No published item indicators** - Missing visual styling for published items **What It Should Be:** - Load Content table filtered by status - Show WordPress publishing actions - Allow editing before publishing - Display WordPress publish status - Show external URL links --- ### 5. Table Actions Configuration (`table-actions.config.tsx` - 359 lines) **Current Implementation:** - ✅ `/writer/tasks` - edit, generate_content - ✅ `/writer/content` - edit, view_on_wordpress, generate_image_prompts, publish - ✅ `/writer/published` - edit (minimal) - ✅ `/writer/images` - publish_wordpress, update_status **Issues:** - ⚠️ Published page actions too minimal - ⚠️ Images page has publishing (should be removed) --- ## Root Cause Analysis ### Issue #1: Images Page Bulk Select Not Working **Root Cause:** Data model mismatch - `ContentImagesGroup` uses `content_id` as primary identifier - `TablePageTemplate` expects `id` field for selection (`selectedIds` array) - No `id` field exists in `ContentImagesGroup` **Solution Options:** 1. **Option A (Recommended):** Add `id` field to `ContentImagesGroup` that mirrors `content_id` 2. **Option B:** Modify TablePageTemplate to accept custom ID field name 3. **Option C:** Transform data in Images.tsx to add `id: content_id` **Recommended Fix:** Option C (least invasive) ```typescript const transformedImages = images.map(group => ({ ...group, id: group.content_id // Add id field for TablePageTemplate })); ``` --- ### Issue #2: Images Page Delete Not Working **Root Cause:** No delete handlers implemented - TablePageTemplate supports `onDelete` and `onBulkDelete` props - Images.tsx doesn't pass these handlers - No API endpoints being called **Solution:** Implement delete handlers using Content API ```typescript const handleDelete = async (id: number) => { await deleteContent(id); // Delete content (cascade deletes images) loadImages(); }; const handleBulkDelete = async (ids: number[]) => { await bulkDeleteContent(ids); loadImages(); }; ``` --- ### Issue #3: Published Page Structure **Root Cause:** Placeholder implementation - Published.tsx is just a wrapper around Tasks component - No actual published content filtering - No WordPress publishing UI **Solution:** Complete reimplementation - Duplicate Content.tsx structure - Add WordPress-specific actions - Filter for published/review status - Add visual indicators --- ### Issue #4: Missing "Review" Status **Root Cause:** Status workflow incomplete - Current: Task (queued → completed) → Content (draft → published) - Missing: Content (draft → **review** → published) - No auto-status change when images generated **Solution:** 1. Add "review" status to Content model (backend) 2. Update API to support new status 3. Add auto-transition: when images generated, change status from draft to review 4. Update all frontend status filters and badges --- ## Detailed Implementation Plan ### Priority 1: Critical Bug Fixes #### Task 1.1: Fix Images Page Bulk Select **Files to modify:** - `frontend/src/pages/Writer/Images.tsx` **Changes:** ```typescript // In loadImages callback, transform data const transformedResults = paginatedResults.map(group => ({ ...group, id: group.content_id // Add id field for selection })); setImages(transformedResults); ``` **Testing:** - [ ] Bulk select checkbox appears and works - [ ] Can select/deselect all - [ ] Can select individual rows - [ ] Selected IDs are content_id values --- #### Task 1.2: Fix Images Page Delete Functions **Files to modify:** - `frontend/src/pages/Writer/Images.tsx` **Changes:** ```typescript // Add delete handlers const handleDelete = useCallback(async (id: number) => { try { await deleteContent(id); toast.success('Content and images deleted successfully'); loadImages(); } catch (error: any) { toast.error(`Failed to delete: ${error.message}`); throw error; } }, [loadImages, toast]); const handleBulkDelete = useCallback(async (ids: number[]) => { try { const result = await bulkDeleteContent(ids); toast.success(`Deleted ${result.deleted_count} content items and their images`); loadImages(); return result; } catch (error: any) { toast.error(`Failed to bulk delete: ${error.message}`); throw error; } }, [loadImages, toast]); // In TablePageTemplate ``` **Testing:** - [ ] Single delete works (deletes content + images) - [ ] Bulk delete works - [ ] Confirmation modals appear - [ ] Data refreshes after delete --- ### Priority 2: Published Page Restructuring #### Task 2.1: Reimplement Published Page **Files to modify:** - `frontend/src/pages/Writer/Published.tsx` (complete rewrite) **Implementation:** ```typescript /** * Published Page - Built with TablePageTemplate * Shows published/review content with WordPress publishing capabilities */ import { useState, useEffect, useMemo, useCallback, useRef } from 'react'; import TablePageTemplate from '../../templates/TablePageTemplate'; import { fetchContent, ContentType, ContentListResponse, ContentFilters, publishToWordPress, // Use unified publisher API } from '../../services/api'; import { useToast } from '../../components/ui/toast/ToastContainer'; import { FileIcon, CheckCircleIcon, TaskIcon, ImageIcon } from '../../icons'; import { createPublishedPageConfig } from '../../config/pages/published.config'; // New config file import PageHeader from '../../components/common/PageHeader'; import ModuleNavigationTabs from '../../components/navigation/ModuleNavigationTabs'; import { useNavigate } from 'react-router'; export default function Published() { const toast = useToast(); const navigate = useNavigate(); // Data state const [content, setContent] = useState([]); const [loading, setLoading] = useState(true); // Filter state - default to published/review status const [searchTerm, setSearchTerm] = useState(''); const [statusFilter, setStatusFilter] = useState('published'); // Default filter const [publishStatusFilter, setPublishStatusFilter] = useState(''); // WordPress publish status const [selectedIds, setSelectedIds] = useState([]); // Pagination state const [currentPage, setCurrentPage] = useState(1); const [totalPages, setTotalPages] = useState(1); const [totalCount, setTotalCount] = useState(0); const pageSize = 20; // Sorting state const [sortBy, setSortBy] = useState('created_at'); const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc'); const [showContent, setShowContent] = useState(false); // Load content - filtered for published/review const loadContent = useCallback(async () => { setLoading(true); setShowContent(false); try { const ordering = sortBy ? `${sortDirection === 'desc' ? '-' : ''}${sortBy}` : '-created_at'; const filters: ContentFilters = { ...(searchTerm && { search: searchTerm }), // Filter for published or review status only ...(statusFilter && { status: statusFilter }), page: currentPage, page_size: pageSize, ordering, }; const data: ContentListResponse = await fetchContent(filters); setContent(data.results || []); setTotalCount(data.count || 0); setTotalPages(Math.ceil((data.count || 0) / pageSize)); setTimeout(() => { setShowContent(true); setLoading(false); }, 100); } catch (error: any) { console.error('Error loading content:', error); toast.error(`Failed to load content: ${error.message}`); setShowContent(true); setLoading(false); } }, [currentPage, statusFilter, sortBy, sortDirection, searchTerm, toast, pageSize]); useEffect(() => { loadContent(); }, [loadContent]); // Handle sorting const handleSort = (field: string, direction: 'asc' | 'desc') => { setSortBy(field || 'created_at'); setSortDirection(direction); setCurrentPage(1); }; // Row action handler const handleRowAction = useCallback(async (action: string, row: ContentType) => { if (action === 'publish_wordpress') { try { const result = await publishToWordPress([row.id]); if (result.success) { toast.success(`Published "${row.title}" to WordPress`); loadContent(); } else { toast.error(result.error || 'Failed to publish'); } } catch (error: any) { toast.error(`Failed to publish: ${error.message}`); } } else if (action === 'view_on_wordpress') { if (row.external_url) { window.open(row.external_url, '_blank'); } } else if (action === 'edit') { // Navigate to content editor navigate(`/writer/content?id=${row.id}`); } }, [toast, loadContent, navigate]); // Bulk WordPress publish const handleBulkPublishWordPress = useCallback(async (ids: string[]) => { try { const numIds = ids.map(id => parseInt(id)); const result = await publishToWordPress(numIds); if (result.success) { toast.success(`Published ${result.published_count || ids.length} items to WordPress`); loadContent(); } else { toast.error(result.error || 'Failed to bulk publish'); } } catch (error: any) { toast.error(`Failed to bulk publish: ${error.message}`); throw error; } }, [toast, loadContent]); // Create page config const pageConfig = useMemo(() => { return createPublishedPageConfig({ searchTerm, setSearchTerm, statusFilter, setStatusFilter, publishStatusFilter, setPublishStatusFilter, setCurrentPage, }); }, [searchTerm, statusFilter, publishStatusFilter]); // Calculate header metrics const headerMetrics = useMemo(() => { if (!pageConfig?.headerMetrics) return []; return pageConfig.headerMetrics.map((metric) => ({ label: metric.label, value: metric.calculate({ content, totalCount }), accentColor: metric.accentColor, })); }, [pageConfig?.headerMetrics, content, totalCount]); // Writer navigation tabs const writerTabs = [ { label: 'Tasks', path: '/writer/tasks', icon: }, { label: 'Content', path: '/writer/content', icon: }, { label: 'Images', path: '/writer/images', icon: }, { label: 'Published', path: '/writer/published', icon: }, ]; return ( <> , color: 'green' }} navigation={} /> { if (key === 'search') { setSearchTerm(value); } else if (key === 'status') { setStatusFilter(value); setCurrentPage(1); } else if (key === 'publishStatus') { setPublishStatusFilter(value); setCurrentPage(1); } }} pagination={{ currentPage, totalPages, totalCount, onPageChange: setCurrentPage, }} selection={{ selectedIds, onSelectionChange: setSelectedIds, }} sorting={{ sortBy, sortDirection, onSort: handleSort, }} headerMetrics={headerMetrics} onRowAction={handleRowAction} onBulkAction={async (action: string, ids: string[]) => { if (action === 'bulk_publish_wordpress') { await handleBulkPublishWordPress(ids); } }} getItemDisplayName={(row: ContentType) => row.title || `Content #${row.id}`} /> ); } ``` --- #### Task 2.2: Create Published Page Configuration **Files to create:** - `frontend/src/config/pages/published.config.tsx` **Implementation:** ```typescript import { ColumnConfig } from '../../templates/TablePageTemplate'; import { ContentType } from '../../services/api'; import { Badge } from '../../components/ui/badge'; import { ExternalLinkIcon, CheckCircleIcon } from '../../icons'; export function createPublishedPageConfig(params: { searchTerm: string; setSearchTerm: (value: string) => void; statusFilter: string; setStatusFilter: (value: string) => void; publishStatusFilter: string; setPublishStatusFilter: (value: string) => void; setCurrentPage: (page: number) => void; }) { const columns: ColumnConfig[] = [ { key: 'title', label: 'Title', sortable: true, render: (value: string, row: ContentType) => (
{value} {row.external_url && ( )}
), }, { key: 'status', label: 'Content Status', sortable: true, badge: true, render: (value: string) => ( {value} ), }, { key: 'sync_status', label: 'WordPress Status', sortable: false, render: (value: string, row: ContentType) => { if (row.external_id) { return ( Published ); } return ( Not Published ); }, }, { key: 'content_type', label: 'Type', sortable: true, }, { key: 'word_count', label: 'Words', sortable: true, numeric: true, }, { key: 'created_at', label: 'Created', sortable: true, date: true, }, ]; const filters = [ { key: 'search', label: 'Search', type: 'text' as const, placeholder: 'Search published content...', }, { key: 'status', label: 'Content Status', type: 'select' as const, options: [ { value: '', label: 'All' }, { value: 'review', label: 'In Review' }, { value: 'published', label: 'Published' }, ], }, { key: 'publishStatus', label: 'WordPress Status', type: 'select' as const, options: [ { value: '', label: 'All' }, { value: 'published', label: 'Published to WP' }, { value: 'not_published', label: 'Not Published' }, ], }, ]; const headerMetrics = [ { label: 'Total Published', calculate: (data: { totalCount: number }) => data.totalCount, accentColor: 'green' as const, }, { label: 'On WordPress', calculate: (data: { content: ContentType[] }) => data.content.filter(c => c.external_id).length, accentColor: 'blue' as const, }, { label: 'In Review', calculate: (data: { content: ContentType[] }) => data.content.filter(c => c.status === 'review').length, accentColor: 'amber' as const, }, ]; return { columns, filters, headerMetrics, }; } ``` --- #### Task 2.3: Update Table Actions for Published Page **Files to modify:** - `frontend/src/config/pages/table-actions.config.tsx` **Changes:** ```typescript '/writer/published': { rowActions: [ { key: 'edit', label: 'Edit Content', icon: EditIcon, variant: 'primary', }, { key: 'publish_wordpress', label: 'Publish to WordPress', icon: , variant: 'success', shouldShow: (row: any) => !row.external_id, // Only show if not published }, { key: 'view_on_wordpress', label: 'View on WordPress', icon: , variant: 'secondary', shouldShow: (row: any) => !!row.external_id, // Only show if published }, ], bulkActions: [ { key: 'bulk_publish_wordpress', label: 'Publish to WordPress', icon: , variant: 'success', }, { key: 'update_status', label: 'Update Status', icon: , variant: 'secondary', }, { key: 'export', label: 'Export Selected', icon: , variant: 'secondary', }, ], }, ``` --- ### Priority 3: Content Page Enhancements #### Task 3.1: Add Content Viewer Link **Files to modify:** - `frontend/src/config/pages/content.config.tsx` **Changes:** ```typescript // In columns array, update title column { key: 'title', label: 'Title', sortable: true, render: (value: string, row: ContentType) => ( ), }, ``` **Files to modify:** - `frontend/src/pages/Writer/Content.tsx` **Changes:** ```typescript // Add state for content viewer modal const [isViewerModalOpen, setIsViewerModalOpen] = useState(false); const [viewerContentId, setViewerContentId] = useState(null); // Add handler const handleViewContent = useCallback((row: ContentType) => { setViewerContentId(row.id); setIsViewerModalOpen(true); }, []); // Update pageConfig call const pageConfig = useMemo(() => { return createContentPageConfig({ // ... existing params onViewContent: handleViewContent, }); }, [/* deps */, handleViewContent]); // Add ContentViewerModal component (import from shared components) { setIsViewerModalOpen(false); setViewerContentId(null); }} contentId={viewerContentId} /> ``` --- #### Task 3.2: Add Status Indicator Columns **Files to modify:** - `frontend/src/config/pages/content.config.tsx` **Changes:** ```typescript // Add after 'status' column { key: 'prompts_status', label: 'Prompts', sortable: false, render: (value: any, row: ContentType) => { // Check if prompts exist (need to add this to API response) const hasPrompts = row.image_prompts_count > 0; return ( {hasPrompts ? ( <> {row.image_prompts_count} prompts ) : ( 'No prompts' )} ); }, }, { key: 'images_status', label: 'Images', sortable: false, render: (value: any, row: ContentType) => { const generatedCount = row.images_generated_count || 0; const totalCount = row.images_total_count || 0; if (totalCount === 0) { return No images; } const isComplete = generatedCount === totalCount; const isPartial = generatedCount > 0 && generatedCount < totalCount; return ( {isComplete && } {generatedCount}/{totalCount} ); }, }, ``` **Backend Changes Needed:** - Add fields to Content API response: - `image_prompts_count` - `images_generated_count` - `images_total_count` --- ### Priority 4: Add "Review" Status Workflow #### Task 4.1: Backend Model Changes **Files to modify:** - `backend/igny8_core/modules/writer/models.py` **Changes:** ```python class Content(models.Model): STATUS_CHOICES = [ ('draft', 'Draft'), ('review', 'In Review'), # NEW STATUS ('published', 'Published'), ] status = models.CharField( max_length=20, choices=STATUS_CHOICES, default='draft', db_index=True, ) ``` **Migration:** ```bash cd backend python manage.py makemigrations writer python manage.py migrate writer ``` --- #### Task 4.2: Auto-Status Change on Image Generation **Files to modify:** - `backend/igny8_core/modules/writer/services/image_generation.py` (or wherever images are generated) **Changes:** ```python def on_images_generated(content_id): """Called when all images for content are successfully generated""" content = Content.objects.get(id=content_id) # Auto-transition draft → review when images complete if content.status == 'draft': content.status = 'review' content.save(update_fields=['status']) # Optional: Create notification/log entry logger.info(f"Content {content_id} auto-transitioned to 'review' after image generation") ``` --- #### Task 4.3: Frontend Status Updates **Files to modify:** - All status badge renderers - All status filter options - All status update modals **Changes:** ```typescript // Update status options everywhere const STATUS_OPTIONS = [ { value: 'draft', label: 'Draft' }, { value: 'review', label: 'In Review' }, // NEW { value: 'published', label: 'Published' }, ]; // Update badge variants const getStatusVariant = (status: string) => { switch (status) { case 'draft': return 'default'; case 'review': return 'warning'; // NEW case 'published': return 'success'; default: return 'default'; } }; ``` --- ### Priority 5: Remove WordPress Publishing from Images Page #### Task 5.1: Update Images Page Configuration **Files to modify:** - `frontend/src/config/pages/table-actions.config.tsx` **Changes:** ```typescript '/writer/images': { rowActions: [ { key: 'update_status', label: 'Update Status', icon: , variant: 'primary', }, // REMOVED: publish_wordpress action ], bulkActions: [ // REMOVED: bulk_publish_wordpress action ], }, ``` --- #### Task 5.2: Clean Up Images Page Code **Files to modify:** - `frontend/src/pages/Writer/Images.tsx` **Changes:** - Remove WordPress publishing handlers - Remove related imports - Simplify row action handler - Remove WordPress-related state --- ### Priority 6: Visual Indicators for Published Items #### Task 6.1: Add Published Badge to All Tables **Files to modify:** - All page configs (tasks, content, images, published) **Changes:** ```typescript // Add to title or status column render { key: 'title', label: 'Title', render: (value: string, row: any) => (
{value} {row.external_id && ( WP )}
), }, ``` --- ## Implementation Checklist ### Phase 1: Critical Bugs (Week 1) - [ ] Fix Images page bulk select (add `id` field) - [ ] Fix Images page delete functions - [ ] Test both fixes thoroughly ### Phase 2: Published Page (Week 1-2) - [ ] Create `published.config.tsx` - [ ] Rewrite `Published.tsx` component - [ ] Update table actions config - [ ] Add WordPress publishing handlers - [ ] Test all functionality ### Phase 3: Content Enhancements (Week 2) - [ ] Add content viewer link to title column - [ ] Create/import ContentViewerModal - [ ] Add backend fields for prompt/image counts - [ ] Add status indicator columns - [ ] Update content.config.tsx - [ ] Test viewer and indicators ### Phase 4: Review Status (Week 2-3) - [ ] Create Django migration for new status - [ ] Update backend model - [ ] Add auto-transition logic - [ ] Update all frontend status options - [ ] Update all status badge renders - [ ] Update filters across all pages - [ ] Test complete workflow ### Phase 5: WordPress Publishing Migration (Week 3) - [ ] Remove WordPress actions from Images page - [ ] Remove WordPress code from Images.tsx - [ ] Verify Published page has all WordPress functionality - [ ] Test end-to-end publishing workflow ### Phase 6: Visual Polish (Week 3) - [ ] Add published badges to all table titles - [ ] Add WordPress status indicators - [ ] Add color coding for statuses - [ ] Add icons for published items - [ ] Polish UI across all pages ### Phase 7: Testing & Documentation (Week 4) - [ ] Full regression testing - [ ] User acceptance testing - [ ] Update user documentation - [ ] Create migration guide for users - [ ] Deploy to staging - [ ] Final production deployment --- ## API Endpoints Required ### New Endpoints ``` POST /v1/publisher/publish/ - Publish content to WordPress - Body: { content_id, destinations: ['wordpress'] } - Response: { success, data: { external_id, external_url }, error } GET /v1/writer/content/{id}/ - Get single content with full details - Response includes: prompts_count, images_count, etc. PATCH /v1/writer/content/{id}/ - Update content status - Body: { status: 'draft' | 'review' | 'published' } ``` ### Enhanced Endpoints ``` GET /v1/writer/content/ - Add fields to response: - image_prompts_count - images_generated_count - images_total_count - sync_status - external_id - external_url ``` --- ## Data Flow Diagrams ### Current Flow ``` Tasks (queued) → Generate Content → Tasks (completed) + Content (draft) → Generate Image Prompts → Content (draft) + ImagePrompts → Generate Images → Content (draft) + Images → [Manual publish from Images page] → WordPress ``` ### New Flow (After Refactoring) ``` Tasks (queued) → Generate Content → Tasks (completed) + Content (draft) → Generate Image Prompts → Content (draft) + ImagePrompts → Generate Images → Content (review) + Images ← AUTO STATUS CHANGE → [Review in Published page] → [Edit if needed] → [Publish to WordPress from Published page] → Content (published) + WordPress Post ``` --- ## Risk Assessment ### High Risk 1. **Database Migration for Review Status** - Mitigation: Test on staging first, have rollback plan - Impact: Could affect existing content if not handled properly 2. **Breaking Changes to Content API** - Mitigation: Add new fields as optional, maintain backward compatibility - Impact: Other parts of app might depend on current response shape ### Medium Risk 1. **Auto-Status Transition Logic** - Mitigation: Make it configurable, add feature flag - Impact: Could change status unexpectedly if logic is wrong 2. **WordPress Publishing Removal from Images** - Mitigation: Ensure Published page fully functional before removing - Impact: Users might look for publish button in wrong place ### Low Risk 1. **UI Changes (badges, indicators)** - Mitigation: Can be easily reverted - Impact: Purely cosmetic 2. **Content Viewer Modal** - Mitigation: Independent feature, doesn't affect core functionality - Impact: Just adds convenience --- ## Success Metrics ### Functional Metrics - [ ] All bulk select checkboxes working across all pages - [ ] Delete functions working (single and bulk) - [ ] Published page shows Content table (not Tasks) - [ ] WordPress publishing only available on Published page - [ ] "Review" status visible and functional - [ ] Auto-status change working when images generated - [ ] Content viewer accessible from title links - [ ] Status indicators showing prompt/image progress ### User Experience Metrics - [ ] Reduced clicks to publish content (consolidated on one page) - [ ] Clear visual feedback for publish status - [ ] Intuitive workflow: draft → review → published - [ ] Easy access to content viewing - [ ] Clear status progression indicators ### Technical Metrics - [ ] No console errors - [ ] All API calls successful - [ ] Proper error handling throughout - [ ] Consistent response times - [ ] Proper loading states --- ## Rollback Plan If critical issues arise: 1. **Phase 1-2 Issues (Bugs/Published Page):** - Revert Published.tsx to `` wrapper - Disable new delete handlers - Restore selection functionality 2. **Phase 4 Issues (Review Status):** - Rollback database migration - Restore previous status options - Disable auto-transition logic 3. **Phase 5 Issues (WordPress Migration):** - Re-enable WordPress publishing on Images page - Disable on Published page temporarily --- ## Future Enhancements (Post-Refactoring) 1. **Bulk Edit Mode** - Edit multiple content items at once 2. **Scheduling** - Schedule WordPress publishing for future dates 3. **Publishing Templates** - Save WordPress settings as templates 4. **Draft Revisions** - Track content changes before publishing 5. **Publishing Analytics** - Track WordPress publish success rates 6. **Multi-destination Publishing** - Publish to multiple WordPress sites 7. **Content Preview** - Preview how content will look on WordPress 8. **SEO Checker** - Validate SEO before publishing --- ## Appendix: File Inventory ### Files to Modify ``` frontend/src/pages/Writer/ - Tasks.tsx (minor - visual indicators) - Content.tsx (major - viewer link, status columns) - Images.tsx (major - fix select, delete, remove WP) - Published.tsx (complete rewrite) frontend/src/config/pages/ - content.config.tsx (add columns, viewer link) - images.config.tsx (minor updates) - table-actions.config.tsx (update all writer sections) - published.config.tsx (NEW FILE) backend/igny8_core/modules/writer/ - models.py (add review status) - services/image_generation.py (auto-status change) - serializers.py (add new fields) - views.py (update filters) ``` ### Files to Create ``` frontend/src/config/pages/published.config.tsx frontend/src/components/common/ContentViewerModal.tsx (if doesn't exist) backend/igny8_core/modules/writer/migrations/XXXX_add_review_status.py ``` ### Total Estimated Changes - **Modified Files:** ~15 - **New Files:** ~3 - **Lines Changed:** ~2,000 - **Estimated Hours:** 40-60 hours - **Estimated Calendar Time:** 3-4 weeks --- **End of Document** *Last Updated: December 2024* *Document Version: 1.0* *Author: AI Assistant (Deep Analysis Mode)*