From 9f82a11c56fe76c4773c32a3f4d0682b57a2430e Mon Sep 17 00:00:00 2001 From: alorig <220087330+alorig@users.noreply.github.com> Date: Mon, 1 Dec 2025 10:00:51 +0500 Subject: [PATCH] 123 --- .../services/adapters/wordpress_adapter.py | 96 ++++++++++++++++++- frontend/src/config/pages/review.config.tsx | 30 ++++++ 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/backend/igny8_core/business/publishing/services/adapters/wordpress_adapter.py b/backend/igny8_core/business/publishing/services/adapters/wordpress_adapter.py index d87027ec..0039f3d0 100644 --- a/backend/igny8_core/business/publishing/services/adapters/wordpress_adapter.py +++ b/backend/igny8_core/business/publishing/services/adapters/wordpress_adapter.py @@ -136,6 +136,7 @@ class WordPressAdapter(BaseAdapter): """ import requests from django.utils.html import strip_tags + import json logger.info(f"[WordPressAdapter._publish_via_api_key] 📦 Preparing payload for {site_url}") @@ -147,7 +148,7 @@ class WordPressAdapter(BaseAdapter): excerpt += '...' logger.info(f"[WordPressAdapter._publish_via_api_key] 📝 Generated excerpt: {excerpt[:50]}...") - # Prepare payload + # Prepare base payload content_data = { 'content_id': content.id if hasattr(content, 'id') else None, 'title': title, @@ -177,6 +178,99 @@ class WordPressAdapter(BaseAdapter): if hasattr(content, 'sector') and content.sector: content_data['sector_id'] = content.sector.id optional_fields.append('sector_id') + + # STEP: Get categories from taxonomy_terms + categories = [] + if hasattr(content, 'taxonomy_terms'): + categories = [ + term.name + for term in content.taxonomy_terms.filter(taxonomy_type='category') + ] + logger.info(f"[WordPressAdapter._publish_via_api_key] 📁 Found {len(categories)} categories from taxonomy_terms") + + # FALLBACK: Use cluster as category if no categories found + if not categories and hasattr(content, 'cluster') and content.cluster: + categories.append(content.cluster.name) + logger.info(f"[WordPressAdapter._publish_via_api_key] 📁 Using cluster as category: {content.cluster.name}") + + content_data['categories'] = categories + optional_fields.append(f'categories({len(categories)})') + + # STEP: Get tags from taxonomy_terms + keywords + tags = [] + if hasattr(content, 'taxonomy_terms'): + tags = [ + term.name + for term in content.taxonomy_terms.filter(taxonomy_type='tag') + ] + logger.info(f"[WordPressAdapter._publish_via_api_key] 🏷️ Found {len(tags)} tags from taxonomy_terms") + + # Add primary keyword as tag + if hasattr(content, 'primary_keyword') and content.primary_keyword: + if content.primary_keyword not in tags: + tags.append(content.primary_keyword) + + # Add secondary keywords as tags + if hasattr(content, 'secondary_keywords') and content.secondary_keywords: + if isinstance(content.secondary_keywords, list): + for keyword in content.secondary_keywords: + if keyword and keyword not in tags: + tags.append(keyword) + elif isinstance(content.secondary_keywords, str): + try: + keywords = json.loads(content.secondary_keywords) + if isinstance(keywords, list): + for keyword in keywords: + if keyword and keyword not in tags: + tags.append(keyword) + except (json.JSONDecodeError, TypeError): + pass + + content_data['tags'] = tags + optional_fields.append(f'tags({len(tags)})') + + # STEP: Get images (featured + gallery) + featured_image_url = None + gallery_images = [] + + if hasattr(content, 'id'): + try: + from igny8_core.modules.writer.models import Images + images = Images.objects.filter(content=content).order_by('position') + logger.info(f"[WordPressAdapter._publish_via_api_key] 🖼️ Found {images.count()} images") + + def convert_image_path_to_url(image_path): + """Convert local image path to public URL""" + if not image_path: + return None + if '/frontend/public/' in image_path: + relative_path = image_path.split('/frontend/public/')[-1] + return f"https://app.igny8.com/{relative_path}" + return image_path + + for image in images: + image_url = convert_image_path_to_url(image.image_path) if hasattr(image, 'image_path') and image.image_path else None + + if image.image_type == 'featured' and image_url: + featured_image_url = image_url + logger.info(f"[WordPressAdapter._publish_via_api_key] 🖼️ Featured image: {image_url[:80]}...") + elif image.image_type == 'in_article' and image_url: + gallery_images.append({ + 'url': image_url, + 'alt': getattr(image, 'alt', '') or '', + 'caption': getattr(image, 'caption', '') or '' + }) + logger.info(f"[WordPressAdapter._publish_via_api_key] 🖼️ Gallery image {len(gallery_images)}") + except Exception as e: + logger.warning(f"[WordPressAdapter._publish_via_api_key] ⚠️ Could not load images: {e}") + + content_data['featured_image_url'] = featured_image_url + content_data['gallery_images'] = gallery_images + if featured_image_url: + optional_fields.append('featured_image') + if gallery_images: + optional_fields.append(f'gallery({len(gallery_images)})') + logger.info(f"[WordPressAdapter._publish_via_api_key] ➕ Added optional fields: {', '.join(optional_fields)}") # Call WordPress endpoint diff --git a/frontend/src/config/pages/review.config.tsx b/frontend/src/config/pages/review.config.tsx index ace86e05..88ec2a35 100644 --- a/frontend/src/config/pages/review.config.tsx +++ b/frontend/src/config/pages/review.config.tsx @@ -178,6 +178,36 @@ export function createReviewPageConfig(params: { ); }, }, + { + key: 'status', + label: 'Status', + sortable: true, + sortField: 'status', + width: '120px', + render: (value: string, row: Content) => { + const status = value || 'draft'; + const statusColors: Record = { + draft: 'gray', + review: 'blue', + published: 'green', + scheduled: 'amber', + archived: 'red', + }; + const color = statusColors[status] || 'gray'; + const label = status.charAt(0).toUpperCase() + status.slice(1); + + return ( +
+ + {label} + + {row.external_id && ( + + )} +
+ ); + }, + }, { key: 'word_count', label: 'Words',