feat: Add Global Module Settings and Caption to Images

- Introduced GlobalModuleSettings model for platform-wide module enable/disable settings.
- Added 'caption' field to Images model to store image captions.
- Updated GenerateImagePromptsFunction to handle new caption structure in prompts.
- Enhanced AIPromptViewSet to return global prompt types and validate active prompts.
- Modified serializers and views to accommodate new caption field and global settings.
- Updated frontend components to display captions and filter prompts based on active types.
- Created migrations for GlobalModuleSettings and added caption field to Images.
This commit is contained in:
IGNY8 VPS (Salman)
2025-12-20 21:34:59 +00:00
parent 9e8ff4fbb1
commit 7a1e952a57
16 changed files with 370 additions and 383 deletions

View File

@@ -112,7 +112,7 @@ class GenerateImagePromptsFunction(BaseAIFunction):
return prompt
def parse_response(self, response: str, step_tracker=None) -> Dict:
"""Parse AI response - same pattern as other functions"""
"""Parse AI response with new structure including captions"""
ai_core = AICore(account=getattr(self, 'account', None))
json_data = ai_core.extract_json(response)
@@ -123,9 +123,28 @@ class GenerateImagePromptsFunction(BaseAIFunction):
if 'featured_prompt' not in json_data:
raise ValueError("Missing 'featured_prompt' in AI response")
if 'featured_caption' not in json_data:
raise ValueError("Missing 'featured_caption' in AI response")
if 'in_article_prompts' not in json_data:
raise ValueError("Missing 'in_article_prompts' in AI response")
# Validate in_article_prompts structure (should be list of objects with prompt & caption)
in_article_prompts = json_data.get('in_article_prompts', [])
if in_article_prompts:
for idx, item in enumerate(in_article_prompts):
if isinstance(item, dict):
if 'prompt' not in item:
raise ValueError(f"Missing 'prompt' in in_article_prompts[{idx}]")
if 'caption' not in item:
raise ValueError(f"Missing 'caption' in in_article_prompts[{idx}]")
else:
# Legacy format (just string) - convert to new format
in_article_prompts[idx] = {
'prompt': str(item),
'caption': '' # Empty caption for legacy data
}
return json_data
def save_output(
@@ -151,23 +170,33 @@ class GenerateImagePromptsFunction(BaseAIFunction):
prompts_created = 0
with transaction.atomic():
# Save featured image prompt - use content instead of task
# Save featured image prompt with caption
Images.objects.update_or_create(
content=content,
image_type='featured',
defaults={
'prompt': parsed['featured_prompt'],
'caption': parsed.get('featured_caption', ''),
'status': 'pending',
'position': 0,
}
)
prompts_created += 1
# Save in-article image prompts
# Save in-article image prompts with captions
in_article_prompts = parsed.get('in_article_prompts', [])
h2_headings = extracted.get('h2_headings', [])
for idx, prompt_text in enumerate(in_article_prompts[:max_images]):
for idx, prompt_data in enumerate(in_article_prompts[:max_images]):
# Handle both new format (dict with prompt & caption) and legacy format (string)
if isinstance(prompt_data, dict):
prompt_text = prompt_data.get('prompt', '')
caption_text = prompt_data.get('caption', '')
else:
# Legacy format - just a string prompt
prompt_text = str(prompt_data)
caption_text = ''
heading = h2_headings[idx] if idx < len(h2_headings) else f"Section {idx + 1}"
Images.objects.update_or_create(
@@ -176,6 +205,7 @@ class GenerateImagePromptsFunction(BaseAIFunction):
position=idx + 1,
defaults={
'prompt': prompt_text,
'caption': caption_text,
'status': 'pending',
}
)