23
This commit is contained in:
@@ -1005,13 +1005,29 @@ class ContentIdeasViewSet(SiteSectorModelViewSet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
ideas = queryset.filter(id__in=ids, status='new') # Only queue 'new' ideas
|
# Get ALL requested ideas first (don't filter by status yet)
|
||||||
|
all_ideas = queryset.filter(id__in=ids)
|
||||||
|
|
||||||
|
# Check which ones can be queued (status='new')
|
||||||
|
queueable_ideas = all_ideas.filter(status='new')
|
||||||
|
|
||||||
from igny8_core.modules.writer.models import Tasks
|
from igny8_core.modules.writer.models import Tasks
|
||||||
|
|
||||||
created_tasks = []
|
created_tasks = []
|
||||||
errors = []
|
errors = []
|
||||||
for idea in ideas:
|
skipped = []
|
||||||
|
|
||||||
|
# Add skipped ideas (not 'new' status)
|
||||||
|
for idea in all_ideas:
|
||||||
|
if idea.status != 'new':
|
||||||
|
skipped.append({
|
||||||
|
'idea_id': idea.id,
|
||||||
|
'title': idea.idea_title,
|
||||||
|
'reason': f'Already {idea.status}'
|
||||||
|
})
|
||||||
|
|
||||||
|
# Process queueable ideas
|
||||||
|
for idea in queueable_ideas:
|
||||||
try:
|
try:
|
||||||
# Direct copy - no mapping needed
|
# Direct copy - no mapping needed
|
||||||
task = Tasks.objects.create(
|
task = Tasks.objects.create(
|
||||||
@@ -1037,23 +1053,43 @@ class ContentIdeasViewSet(SiteSectorModelViewSet):
|
|||||||
idea.status = 'scheduled'
|
idea.status = 'scheduled'
|
||||||
idea.save()
|
idea.save()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
errors.append({'idea_id': idea.id, 'error': str(e)})
|
errors.append({
|
||||||
|
'idea_id': idea.id,
|
||||||
|
'title': idea.idea_title,
|
||||||
|
'error': str(e)
|
||||||
|
})
|
||||||
|
|
||||||
if errors:
|
# Return appropriate response based on results
|
||||||
|
if len(created_tasks) == 0 and (errors or skipped):
|
||||||
|
# Complete failure
|
||||||
return error_response(
|
return error_response(
|
||||||
error=f'Failed to create {len(errors)} tasks',
|
error=f'Failed to queue any ideas: {len(errors)} errors, {len(skipped)} skipped',
|
||||||
errors=errors,
|
errors=errors if errors else skipped,
|
||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
request=request
|
||||||
|
)
|
||||||
|
elif errors:
|
||||||
|
# Partial success - some created, some failed
|
||||||
|
return success_response(
|
||||||
|
data={
|
||||||
|
'created_count': len(created_tasks),
|
||||||
|
'task_ids': created_tasks,
|
||||||
|
'errors': errors,
|
||||||
|
'skipped': skipped,
|
||||||
|
},
|
||||||
|
message=f'Queued {len(created_tasks)} ideas ({len(errors)} failed, {len(skipped)} skipped)',
|
||||||
|
request=request
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Complete success
|
||||||
|
return success_response(
|
||||||
|
data={
|
||||||
|
'created_count': len(created_tasks),
|
||||||
|
'task_ids': created_tasks,
|
||||||
|
'skipped': skipped,
|
||||||
|
},
|
||||||
|
message=f'Successfully queued {len(created_tasks)} ideas to writer' + (f' ({len(skipped)} already scheduled)' if skipped else ''),
|
||||||
request=request
|
request=request
|
||||||
)
|
)
|
||||||
|
|
||||||
return success_response(
|
|
||||||
data={
|
|
||||||
'created_count': len(created_tasks),
|
|
||||||
'task_ids': created_tasks,
|
|
||||||
},
|
|
||||||
message=f'Successfully queued {len(created_tasks)} ideas to writer',
|
|
||||||
request=request
|
|
||||||
)
|
|
||||||
|
|
||||||
# REMOVED: generate_idea action - idea generation function removed
|
# REMOVED: generate_idea action - idea generation function removed
|
||||||
|
|||||||
@@ -208,48 +208,61 @@ export const createContentPageConfig = (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'prompts_status',
|
key: 'content_status_indicators',
|
||||||
label: 'Prompts',
|
label: 'Status',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
width: '110px',
|
width: '100px',
|
||||||
|
align: 'center' as const,
|
||||||
render: (_value: any, row: Content) => {
|
render: (_value: any, row: Content) => {
|
||||||
const hasPrompts = row.has_image_prompts;
|
const hasPrompts = row.has_image_prompts || false;
|
||||||
|
const hasImages = row.has_generated_images || false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Badge color={hasPrompts ? 'success' : 'warning'} size="sm" variant="light">
|
<div className="flex items-center justify-center gap-2">
|
||||||
{hasPrompts ? (
|
{/* Prompts Icon */}
|
||||||
<span className="flex items-center gap-1">
|
<div
|
||||||
<svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
className={`w-5 h-5 flex items-center justify-center flex-shrink-0 ${
|
||||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
hasPrompts ? 'text-purple-500 dark:text-purple-400' : 'text-gray-300 dark:text-gray-600'
|
||||||
</svg>
|
}`}
|
||||||
Ready
|
title={hasPrompts ? 'Prompts ready' : 'No prompts'}
|
||||||
</span>
|
>
|
||||||
) : (
|
<svg
|
||||||
'No Prompts'
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
)}
|
viewBox="0 0 24 24"
|
||||||
</Badge>
|
fill="none"
|
||||||
);
|
stroke="currentColor"
|
||||||
},
|
strokeWidth="2"
|
||||||
},
|
strokeLinecap="round"
|
||||||
{
|
strokeLinejoin="round"
|
||||||
key: 'images_status',
|
className="w-4 h-4"
|
||||||
label: 'Images',
|
>
|
||||||
sortable: false,
|
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" />
|
||||||
width: '110px',
|
</svg>
|
||||||
render: (_value: any, row: Content) => {
|
</div>
|
||||||
const hasImages = row.has_generated_images;
|
|
||||||
return (
|
{/* Images Icon */}
|
||||||
<Badge color={hasImages ? 'success' : 'warning'} size="sm" variant="light">
|
<div
|
||||||
{hasImages ? (
|
className={`w-5 h-5 flex items-center justify-center flex-shrink-0 ${
|
||||||
<span className="flex items-center gap-1">
|
hasImages ? 'text-green-500 dark:text-green-400' : 'text-gray-300 dark:text-gray-600'
|
||||||
<svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
|
}`}
|
||||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
title={hasImages ? 'Images generated' : 'No images'}
|
||||||
</svg>
|
>
|
||||||
Generated
|
<svg
|
||||||
</span>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
) : (
|
viewBox="0 0 24 24"
|
||||||
'No Images'
|
fill="none"
|
||||||
)}
|
stroke="currentColor"
|
||||||
</Badge>
|
strokeWidth="2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
className="w-4 h-4"
|
||||||
|
>
|
||||||
|
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
|
||||||
|
<circle cx="8.5" cy="8.5" r="1.5" />
|
||||||
|
<polyline points="21 15 16 10 5 21" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user