feat: demo-data parity for databases and cron tab

Adds demoDatabases fixtures (postgres/redis/clickhouse) wired into
/databases?demo=1 and demoCronJobsByService fixtures for the service
Cron tab, so demo mode no longer renders empty sections on the new
surfaces.

Authored By: TDvorak <[email protected]>

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-17 18:28:26 +02:00
1 parent d5e6bfc40d
commit 6d237eccf7
4 files changed
+112 -8

No files matched your search

@@ -47,6 +47,7 @@ import {
type DatabaseEntity,
type FailoverPolicy,
} from '@/lib/api-client';
import { demoDatabases } from '@/lib/demo-data';
import { formatRelative } from '@/lib/time';
import { getAuthBaseUrl, signOutAuthSession } from '@/lib/auth-client';
import { useBuildUpdates } from '@/lib/use-build-updates';
@@ -1535,12 +1536,15 @@ const dbStatusClass: Record<string, string> = {
export function DatabasesPage() {
const queryClient = useQueryClient();
const [searchParams] = useSearchParams();
const isDemoMode = searchParams.get('demo') === '1';
const [expandedId, setExpandedId] = useState<string | null>(null);
const [bindDb, setBindDb] = useState<DatabaseEntity | null>(null);
const databasesQuery = useQuery({
queryKey: ['databases'],
queryFn: listDatabases,
refetchInterval: 15_000,
enabled: !isDemoMode,
});
const invalidate = () => queryClient.invalidateQueries({ queryKey: ['databases'] });
@@ -1559,7 +1563,7 @@ export function DatabasesPage() {
onSuccess: () => window.setTimeout(invalidate, 3000),
});
const databases = databasesQuery.data ?? [];
const databases = isDemoMode ? demoDatabases : databasesQuery.data ?? [];
return (
<div>
@@ -30,7 +30,7 @@ import {
updateServiceVariables,
type CronJobEntity,
} from '@/lib/api-client';
import { getDemoProjectById, getDemoServiceById } from '@/lib/demo-data';
import { getDemoProjectById, getDemoServiceById, getDemoCronJobsByService } from '@/lib/demo-data';
import { parseDotenv, validateVariableRows, type VariableDraft } from '../variable-utils';
import { formatBytes, formatDate, formatRelative, seededMetric } from '@/lib/time';
import { EnhancedMetricCard, LineAreaChart, DonutChart } from '@/shared/components';
@@ -1290,14 +1290,14 @@ export function ServiceDetailPage() {
<div className="flex items-center justify-center py-12 text-[var(--text-muted)]">
<Loader2 size={20} className="animate-spin" />
</div>
) : (cronJobsQuery.data ?? []).length === 0 ? (
) : (isDemoMode ? getDemoCronJobsByService(serviceId) : cronJobsQuery.data ?? []).length === 0 ? (
<div className="panel-soft p-8 text-center">
<p className="text-sm text-[var(--text-secondary)]">No cron jobs configured.</p>
<p className="mt-1 text-xs text-[var(--text-muted)]">Create a job to run commands on a schedule inside this service's container.</p>
</div>
) : (
<div className="space-y-2">
{(cronJobsQuery.data ?? []).map((job) => (
{(isDemoMode ? getDemoCronJobsByService(serviceId) : cronJobsQuery.data ?? []).map((job) => (
<div key={job.id} className="panel-soft p-3">
<div className="flex items-center gap-3">
<button