fixes integration
This commit is contained in:
@@ -237,8 +237,10 @@ class IntegrationViewSet(SiteSectorModelViewSet):
|
|||||||
issues.append(f"Cannot detect IGNY8 plugin: {str(e)}")
|
issues.append(f"Cannot detect IGNY8 plugin: {str(e)}")
|
||||||
|
|
||||||
# Check 3: Verify API keys MATCH by making authenticated request
|
# Check 3: Verify API keys MATCH by making authenticated request
|
||||||
# This is the CRITICAL check - WordPress must accept our API key
|
# This is the CRITICAL and AUTHORITATIVE check - WordPress must accept our API key
|
||||||
if health_checks['plugin_installed'] and health_checks['plugin_has_api_key']:
|
# We always try this if plugin is installed, regardless of what /status says about has_api_key
|
||||||
|
# because the /verify-key endpoint is the source of truth
|
||||||
|
if health_checks['plugin_installed']:
|
||||||
try:
|
try:
|
||||||
# Make authenticated request using Site.wp_api_key to dedicated verify endpoint
|
# Make authenticated request using Site.wp_api_key to dedicated verify endpoint
|
||||||
verify_response = http_requests.get(
|
verify_response = http_requests.get(
|
||||||
@@ -251,6 +253,8 @@ class IntegrationViewSet(SiteSectorModelViewSet):
|
|||||||
)
|
)
|
||||||
if verify_response.status_code == 200:
|
if verify_response.status_code == 200:
|
||||||
health_checks['api_key_verified'] = True
|
health_checks['api_key_verified'] = True
|
||||||
|
# If verify succeeds, plugin definitely has the matching key
|
||||||
|
health_checks['plugin_has_api_key'] = True
|
||||||
elif verify_response.status_code in [401, 403]:
|
elif verify_response.status_code in [401, 403]:
|
||||||
issues.append("API key mismatch - WordPress has different key than IGNY8. Please copy the API key from IGNY8 to WordPress plugin settings.")
|
issues.append("API key mismatch - WordPress has different key than IGNY8. Please copy the API key from IGNY8 to WordPress plugin settings.")
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -156,13 +156,22 @@ def wordpress_status_webhook(request):
|
|||||||
content.status = igny8_status
|
content.status = igny8_status
|
||||||
logger.info(f"[wordpress_status_webhook] Status updated: {old_status} → {content.status}")
|
logger.info(f"[wordpress_status_webhook] Status updated: {old_status} → {content.status}")
|
||||||
|
|
||||||
|
# Update site_status based on WordPress status
|
||||||
|
old_site_status = content.site_status
|
||||||
|
if post_status == 'publish':
|
||||||
|
content.site_status = 'published'
|
||||||
|
content.site_status_updated_at = timezone.now()
|
||||||
|
elif post_status in ['draft', 'pending', 'trash']:
|
||||||
|
content.site_status = 'not_published'
|
||||||
|
content.site_status_updated_at = timezone.now()
|
||||||
|
|
||||||
# Update WordPress status in metadata
|
# Update WordPress status in metadata
|
||||||
if not content.metadata:
|
if not content.metadata:
|
||||||
content.metadata = {}
|
content.metadata = {}
|
||||||
content.metadata['wordpress_status'] = post_status
|
content.metadata['wordpress_status'] = post_status
|
||||||
content.metadata['last_wp_sync'] = timezone.now().isoformat()
|
content.metadata['last_wp_sync'] = timezone.now().isoformat()
|
||||||
|
|
||||||
content.save(update_fields=['external_id', 'external_url', 'status', 'metadata', 'updated_at'])
|
content.save(update_fields=['external_id', 'external_url', 'status', 'site_status', 'site_status_updated_at', 'metadata', 'updated_at'])
|
||||||
|
|
||||||
logger.info(f"[wordpress_status_webhook] Updated content {content_id}:")
|
logger.info(f"[wordpress_status_webhook] Updated content {content_id}:")
|
||||||
logger.info(f" - Status: {old_status} → {content.status}")
|
logger.info(f" - Status: {old_status} → {content.status}")
|
||||||
|
|||||||
@@ -290,12 +290,14 @@ def publish_content_to_wordpress(self, content_id: int, site_integration_id: int
|
|||||||
content.external_id = str(wp_data.get('post_id'))
|
content.external_id = str(wp_data.get('post_id'))
|
||||||
content.external_url = wp_data.get('post_url')
|
content.external_url = wp_data.get('post_url')
|
||||||
content.status = 'published'
|
content.status = 'published'
|
||||||
|
content.site_status = 'published'
|
||||||
|
content.site_status_updated_at = timezone.now()
|
||||||
|
|
||||||
if not hasattr(content, 'metadata') or content.metadata is None:
|
if not hasattr(content, 'metadata') or content.metadata is None:
|
||||||
content.metadata = {}
|
content.metadata = {}
|
||||||
content.metadata['wordpress_status'] = wp_status
|
content.metadata['wordpress_status'] = wp_status
|
||||||
|
|
||||||
content.save(update_fields=['external_id', 'external_url', 'status', 'metadata', 'updated_at'])
|
content.save(update_fields=['external_id', 'external_url', 'status', 'site_status', 'site_status_updated_at', 'metadata', 'updated_at'])
|
||||||
|
|
||||||
publish_logger.info(f" ✅ Content model updated:")
|
publish_logger.info(f" ✅ Content model updated:")
|
||||||
publish_logger.info(f" - External ID: {content.external_id}")
|
publish_logger.info(f" - External ID: {content.external_id}")
|
||||||
@@ -361,12 +363,14 @@ def publish_content_to_wordpress(self, content_id: int, site_integration_id: int
|
|||||||
content.external_id = str(wp_data.get('post_id'))
|
content.external_id = str(wp_data.get('post_id'))
|
||||||
content.external_url = wp_data.get('post_url')
|
content.external_url = wp_data.get('post_url')
|
||||||
content.status = 'published'
|
content.status = 'published'
|
||||||
|
content.site_status = 'published'
|
||||||
|
content.site_status_updated_at = timezone.now()
|
||||||
|
|
||||||
if not hasattr(content, 'metadata') or content.metadata is None:
|
if not hasattr(content, 'metadata') or content.metadata is None:
|
||||||
content.metadata = {}
|
content.metadata = {}
|
||||||
content.metadata['wordpress_status'] = wp_status
|
content.metadata['wordpress_status'] = wp_status
|
||||||
|
|
||||||
content.save(update_fields=['external_id', 'external_url', 'status', 'metadata', 'updated_at'])
|
content.save(update_fields=['external_id', 'external_url', 'status', 'site_status', 'site_status_updated_at', 'metadata', 'updated_at'])
|
||||||
|
|
||||||
# Log sync event
|
# Log sync event
|
||||||
duration_ms = int((time.time() - start_time) * 1000)
|
duration_ms = int((time.time() - start_time) * 1000)
|
||||||
|
|||||||
@@ -147,18 +147,63 @@ export function createApprovedPageConfig(params: {
|
|||||||
date: true,
|
date: true,
|
||||||
width: '150px',
|
width: '150px',
|
||||||
render: (value: string, row: Content) => {
|
render: (value: string, row: Content) => {
|
||||||
if (!value) {
|
const siteStatus = row.site_status;
|
||||||
return <span className="text-gray-400 dark:text-gray-500 text-[11px]">Not scheduled</span>;
|
|
||||||
|
// For published items: show when it was published
|
||||||
|
if (siteStatus === 'published') {
|
||||||
|
// Use site_status_updated_at if available, otherwise updated_at
|
||||||
|
const publishedAt = row.site_status_updated_at || row.updated_at;
|
||||||
|
if (publishedAt) {
|
||||||
|
return (
|
||||||
|
<span className="text-success-600 dark:text-success-400 font-medium">
|
||||||
|
{formatRelativeDate(publishedAt)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
return <span className="text-success-600 dark:text-success-400 text-[11px]">Published</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For failed items: show when the failure occurred
|
||||||
|
if (siteStatus === 'failed') {
|
||||||
|
const failedAt = row.site_status_updated_at || row.updated_at;
|
||||||
|
if (failedAt) {
|
||||||
|
return (
|
||||||
|
<span className="text-red-600 dark:text-red-400 font-medium">
|
||||||
|
{formatRelativeDate(failedAt)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <span className="text-red-600 dark:text-red-400 text-[11px]">Failed</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For scheduled items: show when it will be published
|
||||||
|
if (siteStatus === 'scheduled' || siteStatus === 'publishing') {
|
||||||
|
if (value) {
|
||||||
const publishDate = new Date(value);
|
const publishDate = new Date(value);
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const isFuture = publishDate > now;
|
const isFuture = publishDate > now;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<span className={isFuture ? "text-blue-600 dark:text-blue-400 font-medium" : "text-amber-600 dark:text-amber-400 font-medium"}>
|
<span className={isFuture ? "text-blue-600 dark:text-blue-400 font-medium" : "text-amber-600 dark:text-amber-400 font-medium"}>
|
||||||
{formatRelativeDate(value)}
|
{formatRelativeDate(value)}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
return <span className="text-amber-600 dark:text-amber-400 text-[11px]">Pending</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For not_published items: show scheduled date if available
|
||||||
|
if (value) {
|
||||||
|
const publishDate = new Date(value);
|
||||||
|
const now = new Date();
|
||||||
|
const isFuture = publishDate > now;
|
||||||
|
return (
|
||||||
|
<span className={isFuture ? "text-blue-600 dark:text-blue-400 font-medium" : "text-amber-600 dark:text-amber-400 font-medium"}>
|
||||||
|
{formatRelativeDate(value)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <span className="text-gray-400 dark:text-gray-500 text-[11px]">Not scheduled</span>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user