tbaels fitlers and plnaner writer other fixes
This commit is contained in:
@@ -47,8 +47,9 @@ export default function Ideas() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
// Total counts for footer widget (not page-filtered)
|
||||
const [totalInTasks, setTotalInTasks] = useState(0);
|
||||
const [totalPending, setTotalPending] = useState(0);
|
||||
const [totalNew, setTotalNew] = useState(0);
|
||||
const [totalQueued, setTotalQueued] = useState(0);
|
||||
const [totalCompleted, setTotalCompleted] = useState(0);
|
||||
const [totalImagesCount, setTotalImagesCount] = useState(0);
|
||||
// Actual total count (unfiltered) for header metrics - not affected by filters
|
||||
const [actualTotalIdeas, setActualTotalIdeas] = useState(0);
|
||||
@@ -182,8 +183,9 @@ export default function Ideas() {
|
||||
]);
|
||||
|
||||
setActualTotalIdeas(allRes.count || 0); // Store actual total (unfiltered) for header metrics
|
||||
setTotalInTasks((queuedRes.count || 0) + (completedRes.count || 0));
|
||||
setTotalPending(newRes.count || 0);
|
||||
setTotalNew(newRes.count || 0);
|
||||
setTotalQueued(queuedRes.count || 0);
|
||||
setTotalCompleted(completedRes.count || 0);
|
||||
setTotalImagesCount(imagesRes.count || 0);
|
||||
} catch (error) {
|
||||
console.error('Error loading total metrics:', error);
|
||||
@@ -364,7 +366,7 @@ export default function Ideas() {
|
||||
});
|
||||
}, [clusters, activeSector, formData, searchTerm, statusFilter, clusterFilter, structureFilter, typeFilter, statusOptions, contentTypeOptions, contentStructureOptions, clusterOptions]);
|
||||
|
||||
// Calculate header metrics - use actualTotalIdeas/totalInTasks/totalPending from API calls (not page data)
|
||||
// Calculate header metrics - use actual counts from API calls (not page data)
|
||||
// This ensures metrics show correct totals across all pages, not just current page
|
||||
// Note: actualTotalIdeas is NOT affected by filters - it always shows the true total
|
||||
const headerMetrics = useMemo(() => {
|
||||
@@ -380,16 +382,16 @@ export default function Ideas() {
|
||||
value = actualTotalIdeas || 0;
|
||||
break;
|
||||
case 'New':
|
||||
// Use totalPending from loadTotalMetrics() (ideas with status='new')
|
||||
value = totalPending;
|
||||
// Use totalNew from loadTotalMetrics() (ideas with status='new')
|
||||
value = totalNew;
|
||||
break;
|
||||
case 'Queued':
|
||||
// Use totalInTasks from loadTotalMetrics() (ideas with status='queued')
|
||||
value = totalInTasks;
|
||||
// Use totalQueued from loadTotalMetrics() (ideas with status='queued')
|
||||
value = totalQueued;
|
||||
break;
|
||||
case 'Completed':
|
||||
// Calculate completed from totalCount - (totalPending + totalInTasks)
|
||||
value = Math.max(0, totalCount - totalPending - totalInTasks);
|
||||
// Use totalCompleted from loadTotalMetrics() (ideas with status='completed')
|
||||
value = totalCompleted;
|
||||
break;
|
||||
default:
|
||||
value = metric.calculate({ ideas, totalCount });
|
||||
@@ -402,7 +404,7 @@ export default function Ideas() {
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
});
|
||||
}, [pageConfig?.headerMetrics, ideas, totalCount, totalPending, totalInTasks, actualTotalIdeas]);
|
||||
}, [pageConfig?.headerMetrics, ideas, totalCount, totalNew, totalQueued, totalCompleted, actualTotalIdeas]);
|
||||
|
||||
const resetForm = useCallback(() => {
|
||||
setFormData({
|
||||
@@ -565,21 +567,21 @@ export default function Ideas() {
|
||||
submoduleColor: 'amber',
|
||||
metrics: [
|
||||
{ label: 'Ideas', value: totalCount },
|
||||
{ label: 'In Tasks', value: totalInTasks, percentage: `${totalCount > 0 ? Math.round((totalInTasks / totalCount) * 100) : 0}%` },
|
||||
{ label: 'Pending', value: totalPending },
|
||||
{ label: 'In Tasks', value: totalQueued + totalCompleted, percentage: `${totalCount > 0 ? Math.round(((totalQueued + totalCompleted) / totalCount) * 100) : 0}%` },
|
||||
{ label: 'Pending', value: totalNew },
|
||||
{ label: 'From Clusters', value: clusters.length },
|
||||
],
|
||||
progress: {
|
||||
value: totalCount > 0 ? Math.round((totalInTasks / totalCount) * 100) : 0,
|
||||
value: totalCount > 0 ? Math.round(((totalQueued + totalCompleted) / totalCount) * 100) : 0,
|
||||
label: 'Converted',
|
||||
color: 'amber',
|
||||
},
|
||||
hint: totalPending > 0
|
||||
? `${totalPending} ideas ready to become tasks`
|
||||
hint: totalNew > 0
|
||||
? `${totalNew} ideas ready to become tasks`
|
||||
: 'All ideas converted!',
|
||||
statusInsight: totalPending > 0
|
||||
statusInsight: totalNew > 0
|
||||
? `Select ideas and queue them to Writer to start content generation.`
|
||||
: totalInTasks > 0
|
||||
: (totalQueued + totalCompleted) > 0
|
||||
? `Ideas queued. Go to Writer Tasks to generate content.`
|
||||
: `No ideas yet. Generate ideas from Clusters page.`,
|
||||
}}
|
||||
|
||||
@@ -52,6 +52,7 @@ export default function Approved() {
|
||||
const [totalApproved, setTotalApproved] = useState(0);
|
||||
const [totalPublished, setTotalPublished] = useState(0);
|
||||
const [totalImagesCount, setTotalImagesCount] = useState(0);
|
||||
const [generatedImagesCount, setGeneratedImagesCount] = useState(0);
|
||||
|
||||
// Dynamic filter options (loaded from backend)
|
||||
const [statusOptions, setStatusOptions] = useState<Array<{value: string; label: string}> | undefined>(undefined);
|
||||
@@ -144,13 +145,14 @@ export default function Approved() {
|
||||
const loadTotalMetrics = useCallback(async () => {
|
||||
try {
|
||||
// Fetch counts in parallel for performance
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes] = await Promise.all([
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes, generatedImagesRes] = await Promise.all([
|
||||
fetchContent({ page_size: 1, site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'draft', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'review', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'approved', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'published', site_id: activeSite?.id }),
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id }),
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id, status: 'generated' }),
|
||||
]);
|
||||
|
||||
setTotalContent(allRes.count || 0);
|
||||
@@ -159,6 +161,7 @@ export default function Approved() {
|
||||
setTotalApproved(approvedRes.count || 0);
|
||||
setTotalPublished(publishedRes.count || 0);
|
||||
setTotalImagesCount(imagesRes.count || 0);
|
||||
setGeneratedImagesCount(generatedImagesRes.count || 0);
|
||||
} catch (error) {
|
||||
console.error('Error loading total metrics:', error);
|
||||
}
|
||||
@@ -706,9 +709,15 @@ export default function Approved() {
|
||||
case 'Published':
|
||||
value = totalPublished;
|
||||
break;
|
||||
case 'Total Images':
|
||||
case 'Images':
|
||||
value = totalImagesCount;
|
||||
break;
|
||||
return {
|
||||
label: metric.label,
|
||||
displayValue: `${generatedImagesCount}/${totalImagesCount}`,
|
||||
value,
|
||||
accentColor: metric.accentColor,
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
default:
|
||||
value = metric.calculate({ content, totalCount });
|
||||
}
|
||||
@@ -720,7 +729,7 @@ export default function Approved() {
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
});
|
||||
}, [pageConfig?.headerMetrics, content, totalCount, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount]);
|
||||
}, [pageConfig?.headerMetrics, content, totalCount, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount, generatedImagesCount]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -46,6 +46,7 @@ export default function Content() {
|
||||
const [totalApproved, setTotalApproved] = useState(0);
|
||||
const [totalPublished, setTotalPublished] = useState(0);
|
||||
const [totalImagesCount, setTotalImagesCount] = useState(0);
|
||||
const [generatedImagesCount, setGeneratedImagesCount] = useState(0);
|
||||
|
||||
// Dynamic filter options (loaded from backend)
|
||||
const [sourceOptions, setSourceOptions] = useState<Array<{value: string; label: string}> | undefined>(undefined);
|
||||
@@ -122,7 +123,7 @@ export default function Content() {
|
||||
const loadTotalMetrics = useCallback(async () => {
|
||||
try {
|
||||
// Batch all API calls in parallel for better performance
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes] = await Promise.all([
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes, generatedImagesRes] = await Promise.all([
|
||||
// Get all content (site-wide)
|
||||
fetchContent({
|
||||
page_size: 1,
|
||||
@@ -152,8 +153,10 @@ export default function Content() {
|
||||
site_id: activeSite?.id,
|
||||
status: 'published',
|
||||
}),
|
||||
// Get actual total images count
|
||||
// Get total images count
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id }),
|
||||
// Get generated images count
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id, status: 'generated' }),
|
||||
]);
|
||||
|
||||
setTotalContent(allRes.count || 0);
|
||||
@@ -162,6 +165,7 @@ export default function Content() {
|
||||
setTotalApproved(approvedRes.count || 0);
|
||||
setTotalPublished(publishedRes.count || 0);
|
||||
setTotalImagesCount(imagesRes.count || 0);
|
||||
setGeneratedImagesCount(generatedImagesRes.count || 0);
|
||||
} catch (error) {
|
||||
console.error('Error loading total metrics:', error);
|
||||
}
|
||||
@@ -324,9 +328,15 @@ export default function Content() {
|
||||
case 'Published':
|
||||
value = totalPublished;
|
||||
break;
|
||||
case 'Total Images':
|
||||
case 'Images':
|
||||
value = totalImagesCount;
|
||||
break;
|
||||
return {
|
||||
label: metric.label,
|
||||
displayValue: `${generatedImagesCount}/${totalImagesCount}`,
|
||||
value,
|
||||
accentColor: metric.accentColor,
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
default:
|
||||
value = metric.calculate({ content, totalCount });
|
||||
}
|
||||
@@ -338,7 +348,7 @@ export default function Content() {
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
});
|
||||
}, [pageConfig?.headerMetrics, content, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount]);
|
||||
}, [pageConfig?.headerMetrics, content, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount, generatedImagesCount]);
|
||||
|
||||
const handleRowAction = useCallback(async (action: string, row: ContentType) => {
|
||||
if (action === 'view_on_wordpress') {
|
||||
|
||||
@@ -47,6 +47,7 @@ export default function Images() {
|
||||
const [totalApproved, setTotalApproved] = useState(0);
|
||||
const [totalPublished, setTotalPublished] = useState(0);
|
||||
const [totalImagesCount, setTotalImagesCount] = useState(0);
|
||||
const [generatedImagesCount, setGeneratedImagesCount] = useState(0);
|
||||
|
||||
// Footer widget specific counts (image-based)
|
||||
const [totalComplete, setTotalComplete] = useState(0);
|
||||
@@ -119,13 +120,14 @@ export default function Images() {
|
||||
const loadTotalMetrics = useCallback(async () => {
|
||||
try {
|
||||
// Fetch counts in parallel for performance
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes] = await Promise.all([
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes, generatedImagesRes] = await Promise.all([
|
||||
fetchContent({ page_size: 1, site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'draft', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'review', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'approved', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'published', site_id: activeSite?.id }),
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id }),
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id, status: 'generated' }),
|
||||
]);
|
||||
|
||||
setTotalContent(allRes.count || 0);
|
||||
@@ -134,6 +136,7 @@ export default function Images() {
|
||||
setTotalApproved(approvedRes.count || 0);
|
||||
setTotalPublished(publishedRes.count || 0);
|
||||
setTotalImagesCount(imagesRes.count || 0);
|
||||
setGeneratedImagesCount(generatedImagesRes.count || 0);
|
||||
} catch (error) {
|
||||
console.error('Error loading total metrics:', error);
|
||||
}
|
||||
@@ -553,7 +556,13 @@ export default function Images() {
|
||||
break;
|
||||
case 'Total Images':
|
||||
value = totalImagesCount;
|
||||
break;
|
||||
return {
|
||||
label: metric.label,
|
||||
displayValue: `${generatedImagesCount}/${totalImagesCount}`,
|
||||
value,
|
||||
accentColor: metric.accentColor,
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
default:
|
||||
value = metric.calculate({ images, totalCount });
|
||||
}
|
||||
@@ -567,7 +576,7 @@ export default function Images() {
|
||||
});
|
||||
|
||||
return baseMetrics;
|
||||
}, [pageConfig?.headerMetrics, images, totalCount, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount]);
|
||||
}, [pageConfig?.headerMetrics, images, totalCount, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount, generatedImagesCount]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { useState, useEffect, useMemo, useCallback } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import TablePageTemplate from '../../templates/TablePageTemplate';
|
||||
const { activeSector, sectors } = useSectorStore();
|
||||
import {
|
||||
fetchContent,
|
||||
fetchImages,
|
||||
fetchWriterContentFilterOptions,
|
||||
@@ -28,7 +28,7 @@ import PageHeader from '../../components/common/PageHeader';
|
||||
export default function Review() {
|
||||
const toast = useToast();
|
||||
const navigate = useNavigate();
|
||||
const { activeSector } = useSectorStore();
|
||||
const { activeSector, sectors } = useSectorStore();
|
||||
const { activeSite } = useSiteStore();
|
||||
|
||||
// Data state
|
||||
@@ -42,6 +42,7 @@ export default function Review() {
|
||||
const [totalApproved, setTotalApproved] = useState(0);
|
||||
const [totalPublished, setTotalPublished] = useState(0);
|
||||
const [totalImagesCount, setTotalImagesCount] = useState(0);
|
||||
const [generatedImagesCount, setGeneratedImagesCount] = useState(0);
|
||||
|
||||
// Dynamic filter options (loaded from backend)
|
||||
const [siteStatusOptions, setSiteStatusOptions] = useState<Array<{value: string; label: string}> | undefined>(undefined);
|
||||
@@ -144,13 +145,14 @@ export default function Review() {
|
||||
const loadTotalMetrics = useCallback(async () => {
|
||||
try {
|
||||
// Fetch counts in parallel for performance
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes] = await Promise.all([
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes, generatedImagesRes] = await Promise.all([
|
||||
fetchContent({ page_size: 1, site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'draft', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'review', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'approved', site_id: activeSite?.id }),
|
||||
fetchContent({ page_size: 1, status: 'published', site_id: activeSite?.id }),
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id }),
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id, status: 'generated' }),
|
||||
]);
|
||||
|
||||
setTotalContent(allRes.count || 0);
|
||||
@@ -159,6 +161,7 @@ export default function Review() {
|
||||
setTotalApproved(approvedRes.count || 0);
|
||||
setTotalPublished(publishedRes.count || 0);
|
||||
setTotalImagesCount(imagesRes.count || 0);
|
||||
setGeneratedImagesCount(generatedImagesRes.count || 0);
|
||||
} catch (error) {
|
||||
console.error('Error loading metrics:', error);
|
||||
}
|
||||
@@ -252,9 +255,14 @@ export default function Review() {
|
||||
case 'Published':
|
||||
value = totalPublished;
|
||||
break;
|
||||
case 'Total Images':
|
||||
case 'Images':
|
||||
value = totalImagesCount;
|
||||
break;
|
||||
return {
|
||||
...metric,
|
||||
displayValue: `${generatedImagesCount}/${totalImagesCount}`,
|
||||
value,
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
default:
|
||||
value = metric.calculate({ content, totalCount });
|
||||
}
|
||||
@@ -264,7 +272,7 @@ export default function Review() {
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
}),
|
||||
[pageConfig.headerMetrics, content, totalCount, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount]
|
||||
[pageConfig.headerMetrics, content, totalCount, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount, generatedImagesCount]
|
||||
);
|
||||
|
||||
// Export handler
|
||||
|
||||
@@ -55,6 +55,7 @@ export default function Tasks() {
|
||||
const [totalApproved, setTotalApproved] = useState(0);
|
||||
const [totalPublished, setTotalPublished] = useState(0);
|
||||
const [totalImagesCount, setTotalImagesCount] = useState(0);
|
||||
const [generatedImagesCount, setGeneratedImagesCount] = useState(0);
|
||||
|
||||
// Footer widget specific counts (task-based)
|
||||
const [totalQueued, setTotalQueued] = useState(0);
|
||||
@@ -163,7 +164,7 @@ export default function Tasks() {
|
||||
const loadTotalMetrics = useCallback(async () => {
|
||||
try {
|
||||
// Batch all API calls in parallel for better performance
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes] = await Promise.all([
|
||||
const [allRes, draftRes, reviewRes, approvedRes, publishedRes, imagesRes, generatedImagesRes] = await Promise.all([
|
||||
// Get all content (site-wide)
|
||||
fetchContent({
|
||||
page_size: 1,
|
||||
@@ -195,6 +196,8 @@ export default function Tasks() {
|
||||
}),
|
||||
// Get actual total images count
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id }),
|
||||
// Get generated images count
|
||||
fetchImages({ page_size: 1, site_id: activeSite?.id, status: 'generated' }),
|
||||
]);
|
||||
|
||||
setTotalContent(allRes.count || 0);
|
||||
@@ -203,6 +206,7 @@ export default function Tasks() {
|
||||
setTotalApproved(approvedRes.count || 0);
|
||||
setTotalPublished(publishedRes.count || 0);
|
||||
setTotalImagesCount(imagesRes.count || 0);
|
||||
setGeneratedImagesCount(generatedImagesRes.count || 0);
|
||||
} catch (error) {
|
||||
console.error('Error loading total metrics:', error);
|
||||
}
|
||||
@@ -454,9 +458,15 @@ export default function Tasks() {
|
||||
case 'Published':
|
||||
value = totalPublished;
|
||||
break;
|
||||
case 'Total Images':
|
||||
case 'Images':
|
||||
value = totalImagesCount;
|
||||
break;
|
||||
return {
|
||||
label: metric.label,
|
||||
displayValue: `${generatedImagesCount}/${totalImagesCount}`,
|
||||
value,
|
||||
accentColor: metric.accentColor,
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
default:
|
||||
value = metric.calculate({ tasks, totalCount });
|
||||
}
|
||||
@@ -468,7 +478,7 @@ export default function Tasks() {
|
||||
tooltip: (metric as any).tooltip,
|
||||
};
|
||||
});
|
||||
}, [pageConfig?.headerMetrics, tasks, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount]);
|
||||
}, [pageConfig?.headerMetrics, tasks, totalContent, totalDraft, totalReview, totalApproved, totalPublished, totalImagesCount, generatedImagesCount]);
|
||||
|
||||
const resetForm = useCallback(() => {
|
||||
setFormData({
|
||||
|
||||
Reference in New Issue
Block a user