16 KiB
Image Generation Implementation Changelog
Stage 1: Pre-Queue Modal Display - Completed ✅
Date: 2025-01-XX
Status: Completed
Goal: Open modal immediately showing all progress bars before any API calls
Changes Made
1. Frontend Components
Created: frontend/src/components/common/ImageQueueModal.tsx
- Purpose: Display image generation queue with individual progress bars
- Features:
- Shows all images that will be generated with individual progress bars
- Displays queue number, label, content title, status, and progress percentage
- Includes thumbnail placeholder for generated images
- Supports 4 states:
pending,processing,completed,failed - Styled similar to WP plugin's image-queue-processor.js modal
- Responsive design with dark mode support
- Prevents closing while processing
- Shows completion summary in footer
Key Props:
isOpen: Boolean to control modal visibilityonClose: Callback when modal is closedqueue: Array ofImageQueueItemobjectstotalImages: Total number of images in queueonUpdateQueue: Optional callback to update queue state
ImageQueueItem Interface:
{
imageId: number | null;
index: number;
label: string;
type: 'featured' | 'in_article';
position?: number;
contentTitle: string;
status: 'pending' | 'processing' | 'completed' | 'failed';
progress: number; // 0-100
imageUrl: string | null;
error: string | null;
}
Updated: frontend/src/pages/Writer/Images.tsx
-
Added Imports:
fetchImageGenerationSettingsfrom../../services/apiImageQueueModalandImageQueueItemfrom../../components/common/ImageQueueModal
-
Added State:
const [isQueueModalOpen, setIsQueueModalOpen] = useState(false); const [imageQueue, setImageQueue] = useState<ImageQueueItem[]>([]); const [currentContentId, setCurrentContentId] = useState<number | null>(null); -
Added Function:
buildImageQueue()- Builds image queue structure from content images
- Includes featured image (if pending and has prompt)
- Includes in-article images (up to
max_in_article_imagesfrom settings) - Sorts in-article images by position
- Returns array of
ImageQueueItemobjects
-
Updated Function:
handleGenerateImages()- Stage 1 Implementation:
- Fetches image generation settings to get
max_in_article_images - Builds image queue using
buildImageQueue() - Opens modal immediately with all progress bars at 0%
- Collects image IDs for future API call (Stage 2)
- Logs Stage 1 completion
- Fetches image generation settings to get
- Stage 1 Implementation:
-
Added Modal Component:
- Renders
ImageQueueModalat end of component - Handles modal close with image reload
- Passes queue state and update callback
- Renders
2. API Services
Updated: frontend/src/services/api.ts
-
Added Interface:
ImageGenerationSettings{ success: boolean; config: { provider: string; model: string; image_type: string; max_in_article_images: number; image_format: string; desktop_enabled: boolean; mobile_enabled: boolean; }; } -
Added Function:
fetchImageGenerationSettings()- Fetches image generation settings from backend
- Endpoint:
/v1/system/integrations/image_generation/ - Returns settings including
max_in_article_images
3. Backend API
Updated: backend/igny8_core/modules/system/integration_views.py
- Added Method:
get_image_generation_settings()- Action decorator:
@action(detail=False, methods=['get'], url_path='image_generation') - Gets account from request (with fallbacks)
- Retrieves
IntegrationSettingsforimage_generationtype - Returns formatted config with defaults if not found
- Default values:
provider: 'openai'model: 'dall-e-3'image_type: 'realistic'max_in_article_images: 2image_format: 'webp'desktop_enabled: Truemobile_enabled: True
- Action decorator:
Updated: backend/igny8_core/modules/system/urls.py
- Added URL Route:
path('integrations/image_generation/', integration_image_gen_settings_viewset, name='integration-image-gen-settings') - Added ViewSet:
integration_image_gen_settings_viewset = IntegrationSettingsViewSet.as_view({ 'get': 'get_image_generation_settings', })
How It Works
User Flow:
- User clicks "Generate Images" button on Images page
- System fetches
max_in_article_imagesfrom IntegrationSettings - System builds queue:
- 1 Featured Image (if pending and has prompt)
- N In-Article Images (up to
max_in_article_images, if pending and have prompts)
- Modal opens immediately showing all progress bars at 0%
- Each progress bar displays:
- Queue number (1, 2, 3...)
- Label (Featured Image, In-Article Image 1, etc.)
- Content title
- Status: "⏳ Pending"
- Progress: 0%
- Thumbnail placeholder: "No image"
Queue Calculation:
Total Images = 1 (featured) + min(pending_in_article_count, max_in_article_images)
Example:
- Settings:
max_in_article_images = 3 - Content has: 1 featured (pending), 5 in-article (pending)
- Queue: 1 featured + 3 in-article = 4 total progress bars
Files Modified
Frontend:
- ✅
frontend/src/components/common/ImageQueueModal.tsx(NEW) - ✅
frontend/src/pages/Writer/Images.tsx(UPDATED) - ✅
frontend/src/services/api.ts(UPDATED)
Backend:
- ✅
backend/igny8_core/modules/system/integration_views.py(UPDATED) - ✅
backend/igny8_core/modules/system/urls.py(UPDATED)
Testing Checklist
- Modal opens immediately when "Generate Images" button is clicked
- Modal shows correct number of progress bars (1 featured + N in-article)
- Progress bars display correct labels and content titles
- All progress bars start at 0% with "Pending" status
- Modal can be closed (when not processing)
- API endpoint returns correct
max_in_article_imagesvalue - Queue respects
max_in_article_imagessetting - Only pending images with prompts are included in queue
Next Steps (Stage 2)
Planned Features:
-
Start Actual Generation
- Call
generateImages()API with image IDs - Handle async task response with
task_id
- Call
-
Real-Time Progress Updates
- Poll task progress or use WebSocket
- Update individual progress bars as images are generated
- Implement progressive loading (0-50% in 7s, 50-75% in 5s, etc.)
-
Sequential Processing
- Process images one at a time (sequential)
- Update status: pending → processing → completed/failed
- Update progress percentage for each image
-
Error Handling
- Mark failed images with error message
- Continue processing other images if one fails
- Display error in queue item
-
Completion Handling
- Show generated image thumbnails
- Update all statuses to completed/failed
- Reload images list on modal close
Notes
- Stage 1 focuses on immediate visual feedback - modal opens instantly
- No API calls are made in Stage 1 (only settings fetch)
- Queue structure is built client-side from existing image data
- Modal is ready to receive progress updates in Stage 2
- Design matches WP plugin's image-queue-processor.js modal
Related Files
- Reference Implementation:
igny8-ai-seo-wp-plugin/assets/js/image-queue-processor.js - Implementation Plan:
docs/IMAGE_GENERATION_IMPLEMENTATION_PLAN.md - Backend Function:
backend/igny8_core/ai/functions/generate_images_from_prompts.py
Stage 1 Updates: Modal Styling Improvements
Date: 2025-01-XX
Status: Completed
Changes Made:
-
Updated Modal Background
- Changed from
bg-black bg-opacity-50to standard modal backdrop - Now uses
Modalcomponent withbg-gray-400/50 backdrop-blur-[32px](standard glass effect) - Matches all other modals in the system
- Changed from
-
Replaced Emojis with React Icons
- Header: Replaced 🎨 emoji with
FileIconcomponent - Pending status: Replaced ⏳ emoji with
TimeIconcomponent - Processing status: Added spinning SVG icon
- Completed status: Uses
CheckCircleIconcomponent - Failed status: Uses
ErrorIconcomponent
- Header: Replaced 🎨 emoji with
-
Standard Modal Width
- Changed from custom width to
max-w-4xl(standard modal width) - Uses
Modalcomponent which provides consistent styling across system
- Changed from custom width to
Files Modified:
- ✅
frontend/src/components/common/ImageQueueModal.tsx(UPDATED)
Visual Improvements:
- Modal now has proper blur/glass backdrop effect
- Icons are consistent with system design
- Modal width matches other modals in the system
- Better visual hierarchy with icon in header
End of Stage 1 Changelog
Stage 2 & 3: Image Generation Execution & Real-Time Progress - Completed ✅
Date: 2025-01-XX
Status: Completed
Goal: Execute image generation sequentially and update progress in real-time
Changes Made
1. Backend API
Updated: backend/igny8_core/modules/writer/views.py
- Added Method:
generate_images()- Action decorator:
@action(detail=False, methods=['post'], url_path='generate_images') - Accepts
ids(image IDs array) andcontent_id(optional) - Queues
process_image_generation_queueCelery task - Returns
task_idfor progress tracking - Handles validation errors and execution errors
- Action decorator:
2. Celery Task
Updated: backend/igny8_core/ai/tasks.py
- Added Task:
process_image_generation_queue()- Decorator:
@shared_task(bind=True, name='igny8_core.ai.tasks.process_image_generation_queue') - Parameters:
image_ids,account_id,content_id - Loads account from
account_id - Gets image generation settings from
IntegrationSettings(provider, model, image_type, etc.) - Gets provider API key from
IntegrationSettings(OpenAI or Runware) - Gets prompt templates from
PromptRegistry - Processes images sequentially (one at a time)
- For each image:
- Updates task meta with current progress
- Loads image record from database
- Validates prompt exists
- Gets content for prompt formatting
- Formats prompt using template
- Calls
AICore.generate_image() - Updates
Imagesmodel:image_url,status - Handles errors per image (continues on failure)
- Returns final result with counts and per-image results
- Decorator:
3. Frontend API
Updated: frontend/src/services/api.ts
- Updated Function:
generateImages()- Added
contentIdparameter (optional) - Sends both
idsandcontent_idto backend - Returns task response with
task_id
- Added
4. Frontend Components
Updated: frontend/src/pages/Writer/Images.tsx
- Added State:
taskId: Stores Celery task ID for polling
- Updated Function:
handleGenerateImages()- Stage 2: Calls
generateImages()API after opening modal - Stores
task_idin state - Handles API errors
- Stage 2: Calls
- Updated Modal Props:
- Passes
taskIdtoImageQueueModal
- Passes
Updated: frontend/src/components/common/ImageQueueModal.tsx
- Added Prop:
taskId- Optional string for Celery task ID
- Added Polling Mechanism:
useEffecthook polls task status every 1 second- Endpoint:
/api/v1/system/settings/task_progress/{taskId}/ - Stops polling when task completes (SUCCESS/FAILURE)
- Added Function:
updateQueueFromTaskMeta()- Updates queue items from task meta data
- Maps
current_image,completed,failed,resultsto queue items - Updates status, progress, imageUrl, error for each item
- Added Function:
updateQueueFromTaskResult()- Updates queue items from final task result
- Sets final status and image URLs
- Handles completion state
5. Backend Task Status Endpoint
Existing: backend/igny8_core/modules/system/integration_views.py
- Method:
task_progress()- Already exists and handles Celery task status polling
- Returns task state (PENDING, PROGRESS, SUCCESS, FAILURE)
- Returns task meta for progress updates
- Returns task result on completion
How It Works
User Flow:
- User clicks "Generate Images" button
- Stage 1: Modal opens immediately with all progress bars
- Stage 2: Frontend calls
generate_images()API - Backend queues
process_image_generation_queueCelery task - Stage 3: Frontend polls task status every 1 second
- Celery task processes images sequentially:
- Image 1: Load → Format Prompt → Generate → Save
- Image 2: Load → Format Prompt → Generate → Save
- ... (continues for all images)
- Task updates meta with progress after each image
- Frontend receives updates and updates modal progress bars
- On completion, modal shows final status for all images
- User closes modal → Images list reloads
Data Flow:
Frontend (Images.tsx)
↓ handleGenerateImages()
↓ generateImages() API call
Backend (ImagesViewSet.generate_images)
↓ process_image_generation_queue.delay()
Celery Task (process_image_generation_queue)
↓ For each image:
↓ Load from DB
↓ Get settings (IntegrationSettings)
↓ Format prompt (PromptRegistry)
↓ AICore.generate_image()
↓ Update Images model (image_url, status)
↓ Update task meta
Frontend (ImageQueueModal)
↓ Poll task_progress endpoint
↓ Update queue from meta/result
↓ Display progress bars
Progress Updates:
- Task Meta Structure:
current_image: Index of image being processedtotal_images: Total images in queuecompleted: Number of completed imagesfailed: Number of failed imagesresults: Array of per-image results
- Per-Image Result:
image_id: Image record IDstatus: 'completed' or 'failed'image_url: Generated image URL (if successful)error: Error message (if failed)
Files Modified
Backend:
-
✅
backend/igny8_core/modules/writer/views.py(UPDATED)generate_images()method
-
✅
backend/igny8_core/ai/tasks.py(UPDATED)process_image_generation_queue()task
Frontend:
-
✅
frontend/src/services/api.ts(UPDATED)generateImages()function
-
✅
frontend/src/pages/Writer/Images.tsx(UPDATED)handleGenerateImages()functiontaskIdstate- Modal props
-
✅
frontend/src/components/common/ImageQueueModal.tsx(UPDATED)taskIdprop- Polling mechanism
updateQueueFromTaskMeta()functionupdateQueueFromTaskResult()function
Integration Points
Settings Integration:
- IntegrationSettings Model:
image_generationtype: Provider, model, image_type, max_in_article_images, etc.openaitype: API key, modelrunwaretype: API key, model
Prompt Templates:
- PromptRegistry:
get_image_prompt_template(): Formats prompt with post_title, image_prompt, image_typeget_negative_prompt(): Returns negative prompt for Runware
Image Storage:
- Images Model:
image_url: Updated with generated image URLstatus: Updated to 'generated' or 'failed'prompt: Used for generation (already set)
Testing Checklist
- API endpoint accepts image IDs and content ID
- Celery task queues successfully
- Task processes images sequentially
- Task reads settings from IntegrationSettings
- Task formats prompts using PromptRegistry
- Task calls AICore.generate_image() correctly
- Task updates Images model with URLs and status
- Task updates meta with progress
- Frontend polls task status correctly
- Modal updates progress bars in real-time
- Modal shows generated image thumbnails
- Modal handles errors per image
- Modal shows completion summary
- Images list reloads after modal close
Notes
- Images are processed sequentially (one at a time) to respect API rate limits
- Each image failure is handled independently (doesn't stop other images)
- Progress updates are sent via Celery task meta (polled every 1 second)
- Task status endpoint already exists and is reused
- Integration settings are read from database (not hardcoded)
- Prompt templates support fallback if formatting fails
- Image URLs are saved directly to Images model
- Status is updated to 'generated' or 'failed' per image
End of Stage 2 & 3 Changelog