diff --git a/backend/igny8_core/business/publishing/services/publisher_service.py b/backend/igny8_core/business/publishing/services/publisher_service.py index ac08f62f..b0339eb8 100644 --- a/backend/igny8_core/business/publishing/services/publisher_service.py +++ b/backend/igny8_core/business/publishing/services/publisher_service.py @@ -188,13 +188,21 @@ class PublisherService: 'success': result.get('success', False), 'publishing_record_id': record.id, 'external_id': result.get('external_id'), - 'url': result.get('url') + 'url': result.get('url'), + 'error': result.get('error') if not result.get('success') else None } except Exception as e: record.status = 'failed' record.error_message = str(e) record.save() - raise + logger.error(f"[PublisherService._publish_to_destination] ❌ Exception during publish: {str(e)}") + # Don't raise - return error result instead + return { + 'destination': destination, + 'success': False, + 'publishing_record_id': record.id, + 'error': str(e) + } def publish_to_multiple_destinations( self, diff --git a/frontend/src/pages/Writer/Review.tsx b/frontend/src/pages/Writer/Review.tsx index e0b223ab..8498b812 100644 --- a/frontend/src/pages/Writer/Review.tsx +++ b/frontend/src/pages/Writer/Review.tsx @@ -171,19 +171,23 @@ export default function Review() { console.log('📬 Full API Response:', JSON.parse(JSON.stringify(response))); console.log('📊 Response Structure:', { success: response.success, - has_results: !!response.results, - results_count: response.results?.length || 0, + has_data: !!response.data, + has_results: !!response.data?.results, + results_count: response.data?.results?.length || 0, has_error: !!response.error, has_message: !!response.message }); // Handle the response with results array - if (response.success && response.results) { + // Note: Backend wraps result in 'data' key via success_response() + const result = response.data || response; // Fallback to response if no data wrapper + + if (result.success && result.results) { console.log('✅ Overall publish success: true'); - console.log('📋 Publish Results:', response.results); + console.log('📋 Publish Results:', result.results); // Check individual destination results - const wordpressResult = response.results.find((r: any) => r.destination === 'wordpress'); + const wordpressResult = result.results.find((r: any) => r.destination === 'wordpress'); console.log('🎯 WordPress Result:', wordpressResult); if (wordpressResult && wordpressResult.success) { @@ -204,18 +208,18 @@ export default function Review() { }); toast.error(`Failed to publish: ${error}`); } - } else if (!response.success) { + } else if (!result.success) { // Handle overall failure console.error('❌ Publish failed (overall):', { - error: response.error, - message: response.message, - results: response.results + error: result.error, + message: result.message, + results: result.results }); // Try to extract error from results - let errorMsg = response.error || response.message || 'Publishing failed'; - if (response.results && response.results.length > 0) { - const failedResult = response.results[0]; + let errorMsg = result.error || result.message || 'Publishing failed'; + if (result.results && result.results.length > 0) { + const failedResult = result.results[0]; errorMsg = failedResult.error || failedResult.message || errorMsg; } @@ -255,11 +259,14 @@ export default function Review() { }) }); - if (response.success) { + // Backend wraps result in 'data' key via success_response() + const result = response.data || response; + + if (result.success) { successCount++; } else { failedCount++; - console.warn(`Failed to publish content ${id}:`, response.error); + console.warn(`Failed to publish content ${id}:`, result.error); } } catch (error) { failedCount++; diff --git a/igny8-wp-plugin/admin/class-admin.php b/igny8-wp-plugin/admin/class-admin.php index 8dc297ff..8fcd766f 100644 --- a/igny8-wp-plugin/admin/class-admin.php +++ b/igny8-wp-plugin/admin/class-admin.php @@ -220,7 +220,6 @@ class Igny8Admin { */ private function handle_connection() { $api_key = sanitize_text_field($_POST['igny8_api_key'] ?? ''); - $site_id = sanitize_text_field($_POST['igny8_site_id'] ?? ''); // API key is required if (empty($api_key)) { @@ -233,12 +232,17 @@ class Igny8Admin { return; } - // Site ID is required + // Extract site_id from API key format: igny8_site_{site_id}_{timestamp}_{random} + $site_id = null; + if (preg_match('/^igny8_site_(\d+)_/', $api_key, $matches)) { + $site_id = (int) $matches[1]; + } + if (empty($site_id)) { add_settings_error( 'igny8_settings', 'igny8_error', - __('Site ID is required. Create a site in IGNY8 app first.', 'igny8-bridge'), + __('Invalid API key format. Please copy the complete API key from IGNY8 app.', 'igny8-bridge'), 'error' ); return; @@ -253,7 +257,7 @@ class Igny8Admin { $api = new Igny8API(); $test_response = $api->post('/v1/integration/integrations/test-connection/', array( - 'site_id' => (int) $site_id, + 'site_id' => $site_id, 'api_key' => $api_key, 'site_url' => $site_url )); diff --git a/igny8-wp-plugin/admin/class-post-meta-boxes.php b/igny8-wp-plugin/admin/class-post-meta-boxes.php new file mode 100644 index 00000000..1f939f49 --- /dev/null +++ b/igny8-wp-plugin/admin/class-post-meta-boxes.php @@ -0,0 +1,365 @@ +post_type === 'post') { + // Keywords meta box + add_meta_box( + 'igny8_keywords', + __('IGNY8 Keywords', 'igny8-bridge'), + array($this, 'render_keywords_meta_box'), + 'post', + 'side', + 'high' + ); + + // SEO meta box + add_meta_box( + 'igny8_seo', + __('IGNY8 SEO', 'igny8-bridge'), + array($this, 'render_seo_meta_box'), + 'post', + 'normal', + 'high' + ); + + // Sync data meta box (read-only info) + add_meta_box( + 'igny8_sync_data', + __('IGNY8 Sync Data', 'igny8-bridge'), + array($this, 'render_sync_data_meta_box'), + 'post', + 'side', + 'default' + ); + } + } + + /** + * Render Keywords meta box + */ + public function render_keywords_meta_box($post) { + wp_nonce_field('igny8_keywords_nonce', 'igny8_keywords_nonce'); + + $primary_keyword = get_post_meta($post->ID, '_igny8_primary_keyword', true); + $secondary_keywords = get_post_meta($post->ID, '_igny8_secondary_keywords', true); + + // Convert comma-separated string to array for display + $secondary_keywords_array = !empty($secondary_keywords) ? explode(',', $secondary_keywords) : array(); + ?> +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+ +