1
This commit is contained in:
@@ -89,26 +89,89 @@ class GenerateImagesFromPromptsFunction(BaseAIFunction):
|
|||||||
if not images:
|
if not images:
|
||||||
raise ValueError("No pending images found with prompts")
|
raise ValueError("No pending images found with prompts")
|
||||||
|
|
||||||
# Get image generation settings
|
# Get image generation settings - CHECK IF ENABLED
|
||||||
image_settings = {}
|
image_settings = {}
|
||||||
|
image_generation_enabled = False
|
||||||
if account:
|
if account:
|
||||||
try:
|
try:
|
||||||
from igny8_core.modules.system.models import IntegrationSettings
|
from igny8_core.modules.system.models import IntegrationSettings
|
||||||
integration = IntegrationSettings.objects.get(
|
integration = IntegrationSettings.objects.get(
|
||||||
account=account,
|
account=account,
|
||||||
integration_type='image_generation',
|
integration_type='image_generation'
|
||||||
is_active=True
|
|
||||||
)
|
)
|
||||||
|
image_generation_enabled = integration.is_active
|
||||||
image_settings = integration.config or {}
|
image_settings = integration.config or {}
|
||||||
|
logger.info(f"[generate_images_from_prompts] Image generation settings: enabled={image_generation_enabled}, config_keys={list(image_settings.keys())}")
|
||||||
|
except IntegrationSettings.DoesNotExist:
|
||||||
|
logger.warning(f"[generate_images_from_prompts] Image generation integration not found for account {account.id}")
|
||||||
|
raise ValueError("Image generation integration not configured")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Failed to load image generation settings: {e}")
|
logger.error(f"[generate_images_from_prompts] Failed to load image generation settings: {e}")
|
||||||
|
raise ValueError(f"Failed to load image generation settings: {str(e)}")
|
||||||
|
|
||||||
# Extract settings with defaults
|
if not image_generation_enabled:
|
||||||
|
raise ValueError("Image generation is not enabled in settings")
|
||||||
|
|
||||||
|
# Get provider from image_generation settings
|
||||||
provider = image_settings.get('provider') or image_settings.get('service', 'openai')
|
provider = image_settings.get('provider') or image_settings.get('service', 'openai')
|
||||||
if provider == 'runware':
|
logger.info(f"[generate_images_from_prompts] Provider from settings: {provider}")
|
||||||
|
|
||||||
|
# Get provider-specific settings (OpenAI or Runware) - CHECK IF ENABLED
|
||||||
|
provider_api_key = None
|
||||||
|
provider_enabled = False
|
||||||
|
provider_model = None
|
||||||
|
|
||||||
|
if provider == 'openai':
|
||||||
|
try:
|
||||||
|
openai_settings = IntegrationSettings.objects.get(
|
||||||
|
account=account,
|
||||||
|
integration_type='openai'
|
||||||
|
)
|
||||||
|
provider_enabled = openai_settings.is_active
|
||||||
|
provider_api_key = openai_settings.config.get('apiKey') if openai_settings.config else None
|
||||||
|
provider_model = openai_settings.config.get('model') if openai_settings.config else None
|
||||||
|
logger.info(f"[generate_images_from_prompts] OpenAI settings: enabled={provider_enabled}, has_key={bool(provider_api_key)}, model={provider_model}")
|
||||||
|
except IntegrationSettings.DoesNotExist:
|
||||||
|
logger.error(f"[generate_images_from_prompts] OpenAI integration not found")
|
||||||
|
raise ValueError("OpenAI integration not configured")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[generate_images_from_prompts] Error getting OpenAI settings: {e}")
|
||||||
|
raise ValueError(f"Failed to load OpenAI settings: {str(e)}")
|
||||||
|
elif provider == 'runware':
|
||||||
|
try:
|
||||||
|
runware_settings = IntegrationSettings.objects.get(
|
||||||
|
account=account,
|
||||||
|
integration_type='runware'
|
||||||
|
)
|
||||||
|
provider_enabled = runware_settings.is_active
|
||||||
|
provider_api_key = runware_settings.config.get('apiKey') if runware_settings.config else None
|
||||||
|
provider_model = runware_settings.config.get('model') if runware_settings.config else None
|
||||||
|
logger.info(f"[generate_images_from_prompts] Runware settings: enabled={provider_enabled}, has_key={bool(provider_api_key)}, model={provider_model}")
|
||||||
|
except IntegrationSettings.DoesNotExist:
|
||||||
|
logger.error(f"[generate_images_from_prompts] Runware integration not found")
|
||||||
|
raise ValueError("Runware integration not configured")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[generate_images_from_prompts] Error getting Runware settings: {e}")
|
||||||
|
raise ValueError(f"Failed to load Runware settings: {str(e)}")
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Invalid provider: {provider}")
|
||||||
|
|
||||||
|
# Validate provider is enabled and has API key
|
||||||
|
if not provider_enabled:
|
||||||
|
raise ValueError(f"{provider.capitalize()} integration is not enabled")
|
||||||
|
|
||||||
|
if not provider_api_key:
|
||||||
|
raise ValueError(f"{provider.capitalize()} API key not configured")
|
||||||
|
|
||||||
|
# Determine model: from provider settings, or image_generation settings, or default
|
||||||
|
if provider_model:
|
||||||
|
model = provider_model
|
||||||
|
elif provider == 'runware':
|
||||||
model = image_settings.get('model') or image_settings.get('runwareModel', 'runware:97@1')
|
model = image_settings.get('model') or image_settings.get('runwareModel', 'runware:97@1')
|
||||||
else:
|
else:
|
||||||
model = image_settings.get('model', 'dall-e-3')
|
model = image_settings.get('model') or image_settings.get('imageModel', 'dall-e-3')
|
||||||
|
|
||||||
|
logger.info(f"[generate_images_from_prompts] Final settings: provider={provider}, model={model}, enabled={provider_enabled}, has_api_key={bool(provider_api_key)}")
|
||||||
|
|
||||||
# Get prompt templates
|
# Get prompt templates
|
||||||
image_prompt_template = PromptRegistry.get_image_prompt_template(account)
|
image_prompt_template = PromptRegistry.get_image_prompt_template(account)
|
||||||
@@ -119,6 +182,7 @@ class GenerateImagesFromPromptsFunction(BaseAIFunction):
|
|||||||
'account': account,
|
'account': account,
|
||||||
'provider': provider,
|
'provider': provider,
|
||||||
'model': model,
|
'model': model,
|
||||||
|
'api_key': provider_api_key, # Include API key
|
||||||
'image_type': image_settings.get('image_type', 'realistic'),
|
'image_type': image_settings.get('image_type', 'realistic'),
|
||||||
'image_format': image_settings.get('image_format', 'webp'),
|
'image_format': image_settings.get('image_format', 'webp'),
|
||||||
'image_prompt_template': image_prompt_template,
|
'image_prompt_template': image_prompt_template,
|
||||||
@@ -167,10 +231,18 @@ class GenerateImagesFromPromptsFunction(BaseAIFunction):
|
|||||||
|
|
||||||
provider = original_data.get('provider', 'openai')
|
provider = original_data.get('provider', 'openai')
|
||||||
model = original_data.get('model', 'dall-e-3')
|
model = original_data.get('model', 'dall-e-3')
|
||||||
|
api_key = original_data.get('api_key') # Get API key from prepare
|
||||||
image_type = original_data.get('image_type', 'realistic')
|
image_type = original_data.get('image_type', 'realistic')
|
||||||
image_prompt_template = original_data.get('image_prompt_template', '')
|
image_prompt_template = original_data.get('image_prompt_template', '')
|
||||||
negative_prompt = original_data.get('negative_prompt', '')
|
negative_prompt = original_data.get('negative_prompt', '')
|
||||||
|
|
||||||
|
# Validate API key is present
|
||||||
|
if not api_key:
|
||||||
|
error_msg = f"[{function_name}] API key not found for provider {provider}"
|
||||||
|
if console_tracker:
|
||||||
|
console_tracker.error('ConfigurationError', error_msg)
|
||||||
|
raise ValueError(error_msg)
|
||||||
|
|
||||||
ai_core = AICore(account=account or original_data.get('account'))
|
ai_core = AICore(account=account or original_data.get('account'))
|
||||||
|
|
||||||
total_images = len(images)
|
total_images = len(images)
|
||||||
@@ -212,6 +284,10 @@ class GenerateImagesFromPromptsFunction(BaseAIFunction):
|
|||||||
|
|
||||||
if console_tracker:
|
if console_tracker:
|
||||||
console_tracker.prep(f"[{function_name}] Image queue initialized with {total_images} image{'s' if total_images != 1 else ''}")
|
console_tracker.prep(f"[{function_name}] Image queue initialized with {total_images} image{'s' if total_images != 1 else ''}")
|
||||||
|
console_tracker.prep(f"[{function_name}] Provider: {provider}, Model: {model}, API Key: {'***' + api_key[-4:] if api_key and len(api_key) > 4 else 'NOT SET'}")
|
||||||
|
|
||||||
|
# Queue all prompts first (TEST MODE - don't send to AI)
|
||||||
|
queued_prompts = []
|
||||||
|
|
||||||
# Process each image sequentially
|
# Process each image sequentially
|
||||||
for index, image in enumerate(images, 1):
|
for index, image in enumerate(images, 1):
|
||||||
@@ -283,114 +359,60 @@ class GenerateImagesFromPromptsFunction(BaseAIFunction):
|
|||||||
meta['image_queue'] = image_queue
|
meta['image_queue'] = image_queue
|
||||||
progress_tracker.update("AI_CALL", progress_pct, ai_msg, meta=meta)
|
progress_tracker.update("AI_CALL", progress_pct, ai_msg, meta=meta)
|
||||||
|
|
||||||
# Generate image (this is the actual API call)
|
# Queue the complete prompt (TEST MODE - don't send to AI yet)
|
||||||
# Frontend will simulate smooth progress from 50% to 95% while waiting
|
queued_prompts.append({
|
||||||
if console_tracker:
|
'image_id': image.id,
|
||||||
console_tracker.ai_call(f"[{function_name}] Calling {provider}/{model} API for image {index}/{total_images}")
|
'index': index,
|
||||||
|
'image_type': image.image_type,
|
||||||
result = ai_core.generate_image(
|
'content_title': content_title,
|
||||||
prompt=formatted_prompt,
|
'provider': provider,
|
||||||
provider=provider,
|
'model': model,
|
||||||
model=model,
|
'formatted_prompt': formatted_prompt,
|
||||||
size='1024x1024',
|
'negative_prompt': negative_prompt if provider == 'runware' else None,
|
||||||
negative_prompt=negative_prompt if provider == 'runware' else None,
|
'prompt_length': len(formatted_prompt)
|
||||||
function_name='generate_images_from_prompts'
|
})
|
||||||
)
|
|
||||||
|
|
||||||
# Update progress to 90% (API call completed, processing response)
|
|
||||||
queue_item['progress'] = 90
|
|
||||||
if progress_tracker and step_tracker:
|
|
||||||
meta = step_tracker.get_meta()
|
|
||||||
meta['image_queue'] = image_queue
|
|
||||||
progress_tracker.update("AI_CALL", progress_pct, ai_msg, meta=meta)
|
|
||||||
|
|
||||||
if result.get('error'):
|
|
||||||
# Mark as failed
|
|
||||||
queue_item['status'] = 'failed'
|
|
||||||
queue_item['progress'] = 100
|
|
||||||
queue_item['error'] = result['error']
|
|
||||||
with transaction.atomic():
|
|
||||||
image.status = 'failed'
|
|
||||||
image.save(update_fields=['status', 'updated_at'])
|
|
||||||
|
|
||||||
error_msg = f"[{function_name}] Image {index}/{total_images} failed: {result['error']}"
|
|
||||||
errors.append(error_msg)
|
|
||||||
images_failed += 1
|
|
||||||
logger.error(f"Image generation failed for image {image.id}: {result['error']}")
|
|
||||||
|
|
||||||
if console_tracker:
|
|
||||||
console_tracker.error('ImageGenerationError', error_msg)
|
|
||||||
|
|
||||||
if progress_tracker and step_tracker:
|
|
||||||
parse_msg = f"Image {index} failed: {result['error']}"
|
|
||||||
step_tracker.add_response_step("PARSE", "error", parse_msg)
|
|
||||||
meta = step_tracker.get_meta()
|
|
||||||
meta['image_queue'] = image_queue
|
|
||||||
progress_pct = 70 + int((index - 1) / total_images * 15) # 70-85% for PARSE
|
|
||||||
progress_tracker.update("PARSE", progress_pct, parse_msg, meta=meta)
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
image_url = result.get('url')
|
|
||||||
if not image_url:
|
|
||||||
# Mark as failed
|
|
||||||
queue_item['status'] = 'failed'
|
|
||||||
queue_item['progress'] = 100
|
|
||||||
queue_item['error'] = 'No URL returned'
|
|
||||||
with transaction.atomic():
|
|
||||||
image.status = 'failed'
|
|
||||||
image.save(update_fields=['status', 'updated_at'])
|
|
||||||
|
|
||||||
error_msg = f"[{function_name}] Image {index}/{total_images} failed: No URL returned"
|
|
||||||
errors.append(error_msg)
|
|
||||||
images_failed += 1
|
|
||||||
logger.error(f"No image URL returned for image {image.id}")
|
|
||||||
|
|
||||||
if console_tracker:
|
|
||||||
console_tracker.error('ImageGenerationError', error_msg)
|
|
||||||
|
|
||||||
if progress_tracker and step_tracker:
|
|
||||||
parse_msg = f"Image {index} failed: No URL returned"
|
|
||||||
step_tracker.add_response_step("PARSE", "error", parse_msg)
|
|
||||||
meta = step_tracker.get_meta()
|
|
||||||
meta['image_queue'] = image_queue
|
|
||||||
progress_pct = 70 + int((index - 1) / total_images * 15)
|
|
||||||
progress_tracker.update("PARSE", progress_pct, parse_msg, meta=meta)
|
|
||||||
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Update progress: PARSE phase (90%)
|
|
||||||
queue_item['progress'] = 90
|
|
||||||
if progress_tracker and step_tracker:
|
|
||||||
parse_msg = f"Image {index} of {total_images} generated successfully"
|
|
||||||
step_tracker.add_response_step("PARSE", "success", parse_msg)
|
|
||||||
meta = step_tracker.get_meta()
|
|
||||||
meta['image_queue'] = image_queue
|
|
||||||
progress_pct = 70 + int((index - 1) / total_images * 15) # 70-85% for PARSE
|
|
||||||
progress_tracker.update("PARSE", progress_pct, parse_msg, meta=meta)
|
|
||||||
|
|
||||||
if console_tracker:
|
if console_tracker:
|
||||||
console_tracker.parse(f"[{function_name}] Image {index}/{total_images} generated successfully: {image_url[:50]}...")
|
console_tracker.ai_call(f"[{function_name}] [TEST MODE] Queued prompt {index}/{total_images}: {image.image_type} for '{content_title}'")
|
||||||
|
console_tracker.ai_call(f"[{function_name}] [TEST MODE] Provider: {provider}, Model: {model}")
|
||||||
|
console_tracker.ai_call(f"[{function_name}] [TEST MODE] Prompt length: {len(formatted_prompt)} chars")
|
||||||
|
console_tracker.ai_call(f"[{function_name}] [TEST MODE] Prompt preview: {formatted_prompt[:150]}...")
|
||||||
|
|
||||||
# Update image record
|
# TEMPORARY: Simulate result for testing (don't actually call AI)
|
||||||
with transaction.atomic():
|
result = {
|
||||||
image.image_url = image_url
|
'url': None,
|
||||||
image.status = 'generated'
|
'error': None,
|
||||||
image.save(update_fields=['image_url', 'status', 'updated_at'])
|
'test_mode': True,
|
||||||
|
'queued': True
|
||||||
|
}
|
||||||
|
|
||||||
# Mark queue item as completed
|
# ACTUAL AI CALL (COMMENTED OUT FOR TESTING)
|
||||||
|
# if console_tracker:
|
||||||
|
# console_tracker.ai_call(f"[{function_name}] Calling {provider}/{model} API for image {index}/{total_images}")
|
||||||
|
#
|
||||||
|
# result = ai_core.generate_image(
|
||||||
|
# prompt=formatted_prompt,
|
||||||
|
# provider=provider,
|
||||||
|
# model=model,
|
||||||
|
# size='1024x1024',
|
||||||
|
# n=1,
|
||||||
|
# api_key=api_key, # Pass API key explicitly
|
||||||
|
# negative_prompt=negative_prompt if provider == 'runware' else None,
|
||||||
|
# function_name='generate_images_from_prompts'
|
||||||
|
# )
|
||||||
|
|
||||||
|
# TEST MODE: Mark as queued (not actually generated)
|
||||||
queue_item['status'] = 'completed'
|
queue_item['status'] = 'completed'
|
||||||
queue_item['progress'] = 100
|
queue_item['progress'] = 100
|
||||||
queue_item['image_url'] = image_url
|
queue_item['image_url'] = None # No URL in test mode
|
||||||
images_generated += 1
|
|
||||||
logger.info(f"Image {image.id} ({image.image_type}) generated successfully: {image_url}")
|
|
||||||
|
|
||||||
if console_tracker:
|
if console_tracker:
|
||||||
console_tracker.save(f"[{function_name}] Saved image {index}/{total_images} to database (ID: {image.id})")
|
console_tracker.parse(f"[{function_name}] [TEST MODE] Prompt queued for image {index}/{total_images}")
|
||||||
|
console_tracker.save(f"[{function_name}] [TEST MODE] Queued image {index}/{total_images} (ID: {image.id})")
|
||||||
|
|
||||||
# Update progress: SAVE phase
|
# Update progress: SAVE phase
|
||||||
if progress_tracker and step_tracker:
|
if progress_tracker and step_tracker:
|
||||||
save_msg = f"Saved image {index} of {total_images}"
|
save_msg = f"Queued prompt {index} of {total_images} (TEST MODE)"
|
||||||
step_tracker.add_request_step("SAVE", "success", save_msg)
|
step_tracker.add_request_step("SAVE", "success", save_msg)
|
||||||
meta = step_tracker.get_meta()
|
meta = step_tracker.get_meta()
|
||||||
meta['image_queue'] = image_queue
|
meta['image_queue'] = image_queue
|
||||||
@@ -416,29 +438,35 @@ class GenerateImagesFromPromptsFunction(BaseAIFunction):
|
|||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Log all queued prompts (TEST MODE)
|
||||||
|
if console_tracker:
|
||||||
|
console_tracker.save(f"[{function_name}] [TEST MODE] All prompts queued. Total: {len(queued_prompts)} prompts")
|
||||||
|
console_tracker.save(f"[{function_name}] [TEST MODE] Provider: {provider}, Model: {model}")
|
||||||
|
for qp in queued_prompts:
|
||||||
|
console_tracker.save(f"[{function_name}] [TEST MODE] Image {qp['index']}: {qp['image_type']} - '{qp['content_title']}'")
|
||||||
|
console_tracker.save(f"[{function_name}] [TEST MODE] Prompt ({qp['prompt_length']} chars): {qp['formatted_prompt'][:100]}...")
|
||||||
|
|
||||||
# Final progress update
|
# Final progress update
|
||||||
if progress_tracker and step_tracker:
|
if progress_tracker and step_tracker:
|
||||||
final_msg = f"Generated {images_generated} of {total_images} images"
|
final_msg = f"Queued {len(queued_prompts)} prompts (TEST MODE - not sent to AI)"
|
||||||
step_tracker.add_request_step("SAVE", "success", final_msg)
|
step_tracker.add_request_step("SAVE", "success", final_msg)
|
||||||
meta = step_tracker.get_meta()
|
meta = step_tracker.get_meta()
|
||||||
meta['image_queue'] = image_queue
|
meta['image_queue'] = image_queue
|
||||||
|
meta['queued_prompts'] = queued_prompts # Include queued prompts in meta
|
||||||
progress_tracker.update("SAVE", 98, final_msg, meta=meta)
|
progress_tracker.update("SAVE", 98, final_msg, meta=meta)
|
||||||
|
|
||||||
if console_tracker:
|
if console_tracker:
|
||||||
if images_generated > 0:
|
console_tracker.done(f"[{function_name}] [TEST MODE] Queued {len(queued_prompts)}/{total_images} prompts successfully (NOT sent to AI)")
|
||||||
console_tracker.save(f"[{function_name}] SUCCESS: Generated {images_generated}/{total_images} image{'s' if images_generated != 1 else ''} successfully")
|
|
||||||
if images_failed > 0:
|
|
||||||
console_tracker.error('ImageGenerationError', f"[{function_name}] FAILED: {images_failed}/{total_images} image{'s' if images_failed != 1 else ''} failed")
|
|
||||||
if images_generated == total_images:
|
|
||||||
console_tracker.done(f"[{function_name}] All {total_images} image{'s' if total_images != 1 else ''} generated successfully")
|
|
||||||
else:
|
|
||||||
console_tracker.done(f"[{function_name}] Completed: {images_generated} succeeded, {images_failed} failed out of {total_images} total")
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'count': images_generated,
|
'count': len(queued_prompts),
|
||||||
'images_generated': images_generated,
|
'images_generated': 0, # 0 because we're in test mode
|
||||||
'images_failed': images_failed,
|
'images_failed': 0,
|
||||||
'total_images': total_images,
|
'total_images': total_images,
|
||||||
|
'queued_prompts': queued_prompts, # Return queued prompts
|
||||||
|
'test_mode': True,
|
||||||
|
'provider': provider,
|
||||||
|
'model': model,
|
||||||
'errors': errors if errors else None
|
'errors': errors if errors else None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,17 +14,10 @@ import {
|
|||||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||||
import { FileIcon, DownloadIcon, BoltIcon } from '../../icons';
|
import { FileIcon, DownloadIcon, BoltIcon } from '../../icons';
|
||||||
import { createImagesPageConfig } from '../../config/pages/images.config';
|
import { createImagesPageConfig } from '../../config/pages/images.config';
|
||||||
import ProgressModal from '../../components/common/ProgressModal';
|
|
||||||
import ImageQueueModal from '../../components/common/ImageQueueModal';
|
|
||||||
import { useProgressModal } from '../../hooks/useProgressModal';
|
|
||||||
|
|
||||||
export default function Images() {
|
export default function Images() {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
|
||||||
// Progress modal for AI functions
|
|
||||||
const progressModal = useProgressModal();
|
|
||||||
const hasReloadedRef = useRef(false);
|
|
||||||
|
|
||||||
// Data state
|
// Data state
|
||||||
const [images, setImages] = useState<ContentImagesGroup[]>([]);
|
const [images, setImages] = useState<ContentImagesGroup[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
@@ -174,31 +167,24 @@ export default function Images() {
|
|||||||
|
|
||||||
const result = await generateImages(imageIds);
|
const result = await generateImages(imageIds);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
if (result.task_id) {
|
// Show toast message (no progress modal)
|
||||||
// Open progress modal for async task
|
const generated = result.images_generated || 0;
|
||||||
progressModal.openModal(
|
const failed = result.images_failed || 0;
|
||||||
result.task_id,
|
if (generated > 0) {
|
||||||
'Generate Images',
|
toast.success(`Images generated: ${generated} image${generated !== 1 ? 's' : ''} created${failed > 0 ? `, ${failed} failed` : ''}`);
|
||||||
'ai-generate-images-from-prompts-01-desktop'
|
} else if (failed > 0) {
|
||||||
);
|
toast.error(`Image generation failed: ${failed} image${failed !== 1 ? 's' : ''} failed`);
|
||||||
} else {
|
} else {
|
||||||
// Synchronous completion
|
toast.success('Image generation completed');
|
||||||
const generated = result.images_generated || 0;
|
|
||||||
const failed = result.images_failed || 0;
|
|
||||||
if (generated > 0) {
|
|
||||||
toast.success(`Images generated: ${generated} image${generated !== 1 ? 's' : ''} created${failed > 0 ? `, ${failed} failed` : ''}`);
|
|
||||||
} else {
|
|
||||||
toast.error(`Image generation failed: ${failed} image${failed !== 1 ? 's' : ''} failed`);
|
|
||||||
}
|
|
||||||
loadImages(); // Reload to show new images
|
|
||||||
}
|
}
|
||||||
|
loadImages(); // Reload to show new images
|
||||||
} else {
|
} else {
|
||||||
toast.error(result.error || 'Failed to generate images');
|
toast.error(result.error || 'Failed to generate images');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error(`Failed to generate images: ${error.message}`);
|
toast.error(`Failed to generate images: ${error.message}`);
|
||||||
}
|
}
|
||||||
}, [toast, progressModal, loadImages, images]);
|
}, [toast, loadImages, images]);
|
||||||
|
|
||||||
// Get max in-article images from the data (to determine column count)
|
// Get max in-article images from the data (to determine column count)
|
||||||
const maxInArticleImages = useMemo(() => {
|
const maxInArticleImages = useMemo(() => {
|
||||||
@@ -284,50 +270,6 @@ export default function Images() {
|
|||||||
setCurrentPage(1);
|
setCurrentPage(1);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Image Queue Modal for Image Generation */}
|
|
||||||
{progressModal.imageQueue && progressModal.imageQueue.length > 0 ? (
|
|
||||||
<ImageQueueModal
|
|
||||||
isOpen={progressModal.isOpen}
|
|
||||||
queue={progressModal.imageQueue}
|
|
||||||
onClose={() => {
|
|
||||||
const wasCompleted = progressModal.progress.status === 'completed';
|
|
||||||
progressModal.closeModal();
|
|
||||||
// Reload data after modal closes (if completed)
|
|
||||||
if (wasCompleted && !hasReloadedRef.current) {
|
|
||||||
hasReloadedRef.current = true;
|
|
||||||
loadImages();
|
|
||||||
setTimeout(() => {
|
|
||||||
hasReloadedRef.current = false;
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
/* Progress Modal for other AI Functions */
|
|
||||||
<ProgressModal
|
|
||||||
isOpen={progressModal.isOpen}
|
|
||||||
title={progressModal.title}
|
|
||||||
percentage={progressModal.progress.percentage}
|
|
||||||
status={progressModal.progress.status}
|
|
||||||
message={progressModal.progress.message}
|
|
||||||
details={progressModal.progress.details}
|
|
||||||
taskId={progressModal.taskId || undefined}
|
|
||||||
functionId={progressModal.functionId}
|
|
||||||
onClose={() => {
|
|
||||||
const wasCompleted = progressModal.progress.status === 'completed';
|
|
||||||
progressModal.closeModal();
|
|
||||||
// Reload data after modal closes (if completed)
|
|
||||||
if (wasCompleted && !hasReloadedRef.current) {
|
|
||||||
hasReloadedRef.current = true;
|
|
||||||
loadImages();
|
|
||||||
setTimeout(() => {
|
|
||||||
hasReloadedRef.current = false;
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user