content calendar fixed
This commit is contained in:
@@ -192,52 +192,45 @@ export default function ContentCalendar() {
|
|||||||
|
|
||||||
// IMPORTANT: Since content is ordered by -created_at, we need to fetch items by specific site_status
|
// IMPORTANT: Since content is ordered by -created_at, we need to fetch items by specific site_status
|
||||||
// Otherwise old scheduled/failed items will be on later pages and won't load
|
// Otherwise old scheduled/failed items will be on later pages and won't load
|
||||||
|
// NOTE: fetchAPI doesn't support params object - must use URL query strings
|
||||||
|
|
||||||
|
const siteId = activeSite.id;
|
||||||
|
|
||||||
console.log('[ContentCalendar] ========== SITE FILTERING DEBUG ==========');
|
console.log('[ContentCalendar] ========== SITE FILTERING DEBUG ==========');
|
||||||
console.log('[ContentCalendar] Active site ID:', activeSite.id);
|
console.log('[ContentCalendar] Active site ID:', siteId);
|
||||||
console.log('[ContentCalendar] Active site name:', activeSite.name);
|
console.log('[ContentCalendar] Active site name:', activeSite.name);
|
||||||
console.log('[ContentCalendar] Fetching content with multiple targeted queries...');
|
console.log('[ContentCalendar] Fetching content with multiple targeted queries...');
|
||||||
|
|
||||||
// Fetch scheduled items (all of them, regardless of page)
|
// Fetch scheduled items (all of them, regardless of page)
|
||||||
const scheduledResponse = await fetchAPI('/v1/writer/content/', {
|
const scheduledResponse = await fetchAPI(
|
||||||
params: {
|
`/v1/writer/content/?site_id=${siteId}&page_size=1000&site_status=scheduled`
|
||||||
site_id: activeSite.id,
|
);
|
||||||
page_size: 1000,
|
|
||||||
site_status: 'scheduled', // Filter specifically for scheduled
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fetch failed items (all of them)
|
// Fetch failed items (all of them)
|
||||||
const failedResponse = await fetchAPI('/v1/writer/content/', {
|
const failedResponse = await fetchAPI(
|
||||||
params: {
|
`/v1/writer/content/?site_id=${siteId}&page_size=1000&site_status=failed`
|
||||||
site_id: activeSite.id,
|
);
|
||||||
page_size: 1000,
|
|
||||||
site_status: 'failed', // Filter specifically for failed
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fetch approved items (for sidebar drag-drop)
|
// Fetch review items (for review count display)
|
||||||
const approvedResponse = await fetchAPI('/v1/writer/content/', {
|
const reviewResponse = await fetchAPI(
|
||||||
params: {
|
`/v1/writer/content/?site_id=${siteId}&page_size=100&status=review`
|
||||||
site_id: activeSite.id,
|
);
|
||||||
page_size: 100,
|
|
||||||
status: 'approved', // Approved workflow status
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fetch published items (with external_id) for display
|
// Fetch approved items (for sidebar drag-drop) - not yet published to site
|
||||||
const publishedResponse = await fetchAPI('/v1/writer/content/', {
|
const approvedResponse = await fetchAPI(
|
||||||
params: {
|
`/v1/writer/content/?site_id=${siteId}&page_size=100&status=approved&site_status=not_published`
|
||||||
site_id: activeSite.id,
|
);
|
||||||
page_size: 100,
|
|
||||||
ordering: '-updated_at', // Most recently published first
|
// Fetch published items (site_status=published) for display
|
||||||
}
|
const publishedResponse = await fetchAPI(
|
||||||
});
|
`/v1/writer/content/?site_id=${siteId}&page_size=100&site_status=published&ordering=-updated_at`
|
||||||
|
);
|
||||||
|
|
||||||
// Combine all results, removing duplicates by ID
|
// Combine all results, removing duplicates by ID
|
||||||
const allItems = [
|
const allItems = [
|
||||||
...(scheduledResponse.results || []),
|
...(scheduledResponse.results || []),
|
||||||
...(failedResponse.results || []),
|
...(failedResponse.results || []),
|
||||||
|
...(reviewResponse.results || []),
|
||||||
...(approvedResponse.results || []),
|
...(approvedResponse.results || []),
|
||||||
...(publishedResponse.results || []),
|
...(publishedResponse.results || []),
|
||||||
];
|
];
|
||||||
@@ -251,6 +244,7 @@ export default function ContentCalendar() {
|
|||||||
console.log('[ContentCalendar] ========== DATA LOAD DEBUG ==========');
|
console.log('[ContentCalendar] ========== DATA LOAD DEBUG ==========');
|
||||||
console.log('[ContentCalendar] Scheduled query returned:', scheduledResponse.results?.length, 'items');
|
console.log('[ContentCalendar] Scheduled query returned:', scheduledResponse.results?.length, 'items');
|
||||||
console.log('[ContentCalendar] Failed query returned:', failedResponse.results?.length, 'items');
|
console.log('[ContentCalendar] Failed query returned:', failedResponse.results?.length, 'items');
|
||||||
|
console.log('[ContentCalendar] Review query returned:', reviewResponse.results?.length, 'items');
|
||||||
console.log('[ContentCalendar] Approved query returned:', approvedResponse.results?.length, 'items');
|
console.log('[ContentCalendar] Approved query returned:', approvedResponse.results?.length, 'items');
|
||||||
console.log('[ContentCalendar] Published query returned:', publishedResponse.results?.length, 'items');
|
console.log('[ContentCalendar] Published query returned:', publishedResponse.results?.length, 'items');
|
||||||
console.log('[ContentCalendar] Total unique items after deduplication:', uniqueItems.length);
|
console.log('[ContentCalendar] Total unique items after deduplication:', uniqueItems.length);
|
||||||
|
|||||||
@@ -290,8 +290,10 @@ export default function Approved() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.success && response.data?.results?.[0]?.success) {
|
// Note: fetchAPI unwraps the response, so response IS the data object
|
||||||
const result = response.data.results[0];
|
// Response format: { success: true, results: [{ success: true, url: '...', external_id: '...' }] }
|
||||||
|
if (response.success && response.results?.[0]?.success) {
|
||||||
|
const result = response.results[0];
|
||||||
|
|
||||||
// Phase 3: Processing (50-75%)
|
// Phase 3: Processing (50-75%)
|
||||||
setSinglePublishState(prev => prev ? { ...prev, progress: 50, statusMessage: 'Processing response...' } : null);
|
setSinglePublishState(prev => prev ? { ...prev, progress: 50, statusMessage: 'Processing response...' } : null);
|
||||||
@@ -313,7 +315,7 @@ export default function Approved() {
|
|||||||
|
|
||||||
loadContent();
|
loadContent();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.error || 'Failed to publish');
|
throw new Error(response.error || response.results?.[0]?.error || 'Failed to publish');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Publish error:', error);
|
console.error('Publish error:', error);
|
||||||
@@ -412,6 +414,8 @@ export default function Approved() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const contentIds = selectedIds.map(id => parseInt(id));
|
const contentIds = selectedIds.map(id => parseInt(id));
|
||||||
|
// Note: fetchAPI unwraps success_response, so response IS the data object
|
||||||
|
// Response format: { scheduled_count: N, schedule_preview: [...], site_settings: {...} }
|
||||||
const response = await fetchAPI('/v1/writer/content/bulk_schedule_preview/', {
|
const response = await fetchAPI('/v1/writer/content/bulk_schedule_preview/', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -420,11 +424,13 @@ export default function Approved() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.success) {
|
// fetchAPI throws on error, so if we get here, response is successful
|
||||||
setBulkSchedulePreview(response.data);
|
// Response is the unwrapped data object
|
||||||
|
if (response && response.schedule_preview) {
|
||||||
|
setBulkSchedulePreview(response);
|
||||||
setShowBulkSchedulePreviewModal(true);
|
setShowBulkSchedulePreviewModal(true);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.error || 'Failed to generate preview');
|
throw new Error('Invalid response from server');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error(`Failed to generate schedule preview: ${error.message}`);
|
toast.error(`Failed to generate schedule preview: ${error.message}`);
|
||||||
@@ -437,6 +443,7 @@ export default function Approved() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const contentIds = selectedIds.map(id => parseInt(id));
|
const contentIds = selectedIds.map(id => parseInt(id));
|
||||||
|
// Note: fetchAPI unwraps success_response, so response IS the data object
|
||||||
const response = await fetchAPI('/v1/writer/content/bulk_schedule/', {
|
const response = await fetchAPI('/v1/writer/content/bulk_schedule/', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -446,14 +453,15 @@ export default function Approved() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.success) {
|
// fetchAPI throws on error, so if we get here, response is successful
|
||||||
toast.success(`Scheduled ${response.data.scheduled_count} item(s)`);
|
if (response && response.scheduled_count !== undefined) {
|
||||||
|
toast.success(`Scheduled ${response.scheduled_count} item(s)`);
|
||||||
setShowBulkSchedulePreviewModal(false);
|
setShowBulkSchedulePreviewModal(false);
|
||||||
setBulkSchedulePreview(null);
|
setBulkSchedulePreview(null);
|
||||||
setSelectedIds([]);
|
setSelectedIds([]);
|
||||||
loadContent();
|
loadContent();
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.error || 'Failed to schedule');
|
throw new Error('Invalid response from server');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
toast.error(`Failed to schedule: ${error.message}`);
|
toast.error(`Failed to schedule: ${error.message}`);
|
||||||
@@ -568,9 +576,10 @@ export default function Approved() {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle response
|
// Handle response - fetchAPI unwraps the data object
|
||||||
if (response.success && response.data?.results?.[0]?.success) {
|
// Response format: { success: true, results: [{ success: true, url: '...', external_id: '...' }] }
|
||||||
const result = response.data.results[0];
|
if (response.success && response.results?.[0]?.success) {
|
||||||
|
const result = response.results[0];
|
||||||
|
|
||||||
// Animate to completion
|
// Animate to completion
|
||||||
setBulkPublishQueue(prev => prev.map((item, idx) =>
|
setBulkPublishQueue(prev => prev.map((item, idx) =>
|
||||||
@@ -589,7 +598,7 @@ export default function Approved() {
|
|||||||
} : item
|
} : item
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.error || 'Unknown error');
|
throw new Error(response.error || response.results?.[0]?.error || 'Unknown error');
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error(`Error publishing content ${queue[i].contentId}:`, error);
|
console.error(`Error publishing content ${queue[i].contentId}:`, error);
|
||||||
|
|||||||
Reference in New Issue
Block a user