fix(dashboard): fix empty widgets + NULL created_at on campaign tests
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
1. metrics_query_service: use NULLS LAST in get_recent_tests() so tests
with actual dates always appear before NULL-dated ones.
2. campaign_service: set created_at=datetime.utcnow() when creating tests
from campaigns (was missing, leaving 21 tests with NULL created_at).
Fixed existing NULL values directly in production DB.
3. DashboardPage: add isError handling to all V2 metric widgets
(pipeline, team activity, validation rate, recent tests).
- Add retry:2 to all secondary metric queries so transient failures
are retried before showing empty state.
- Show 'Could not load X — refresh' instead of empty/misleading
'No tests created yet' when a query actually fails.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,25 +87,29 @@ export default function DashboardPage() {
|
||||
queryFn: getCoverageByTactic,
|
||||
});
|
||||
|
||||
// V2 queries
|
||||
const { data: pipeline, isLoading: pipelineLoading } = useQuery({
|
||||
// V2 queries — retry:2 so transient failures don't leave widgets blank
|
||||
const { data: pipeline, isLoading: pipelineLoading, isError: pipelineError } = useQuery({
|
||||
queryKey: ["metrics", "test-pipeline"],
|
||||
queryFn: getTestPipeline,
|
||||
retry: 2,
|
||||
});
|
||||
|
||||
const { data: teamActivity, isLoading: teamLoading } = useQuery({
|
||||
const { data: teamActivity, isLoading: teamLoading, isError: teamError } = useQuery({
|
||||
queryKey: ["metrics", "team-activity"],
|
||||
queryFn: getTeamActivity,
|
||||
retry: 2,
|
||||
});
|
||||
|
||||
const { data: validationRates, isLoading: validationLoading } = useQuery({
|
||||
const { data: validationRates, isLoading: validationLoading, isError: validationError } = useQuery({
|
||||
queryKey: ["metrics", "validation-rate"],
|
||||
queryFn: getValidationRate,
|
||||
retry: 2,
|
||||
});
|
||||
|
||||
const { data: recentTests, isLoading: recentLoading } = useQuery({
|
||||
const { data: recentTests, isLoading: recentLoading, isError: recentError } = useQuery({
|
||||
queryKey: ["metrics", "recent-tests"],
|
||||
queryFn: getRecentTests,
|
||||
retry: 2,
|
||||
});
|
||||
|
||||
const { data: coverageEvolution, isLoading: evolutionLoading } = useQuery({
|
||||
@@ -287,6 +291,8 @@ export default function DashboardPage() {
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
|
||||
</div>
|
||||
) : pipelineError ? (
|
||||
<p className="py-8 text-center text-sm text-gray-500">Could not load pipeline data.</p>
|
||||
) : pipeline ? (
|
||||
<PipelineFunnel pipeline={pipeline} />
|
||||
) : null}
|
||||
@@ -305,6 +311,8 @@ export default function DashboardPage() {
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
|
||||
</div>
|
||||
) : teamError ? (
|
||||
<p className="py-8 text-center text-sm text-gray-500">Could not load team activity.</p>
|
||||
) : teamActivity ? (
|
||||
<div className="space-y-4">
|
||||
{teamActivity.map((team: TeamActivityItem) => {
|
||||
@@ -355,6 +363,8 @@ export default function DashboardPage() {
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
|
||||
</div>
|
||||
) : validationError ? (
|
||||
<p className="py-8 text-center text-sm text-gray-500">Could not load validation data.</p>
|
||||
) : validationRates ? (
|
||||
<div className="space-y-4">
|
||||
{validationRates.map((rate: ValidationRateItem) => {
|
||||
@@ -419,6 +429,8 @@ export default function DashboardPage() {
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
|
||||
</div>
|
||||
) : recentError ? (
|
||||
<p className="py-8 text-center text-sm text-gray-500">Could not load recent tests — refresh the page.</p>
|
||||
) : recentTests && recentTests.length > 0 ? (
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-left text-sm">
|
||||
|
||||
Reference in New Issue
Block a user