fix: fix maintenance mode

This commit is contained in:
Saumya 2025-09-10 11:10:11 +05:30
parent 3ff1b99bd4
commit 43aacce5e2
5 changed files with 46 additions and 53 deletions

View File

@ -3,7 +3,11 @@ import { maintenanceNoticeFlag } from '@/lib/edge-flags';
export const runtime = 'edge';
export async function GET() {
const maintenanceNotice = await maintenanceNoticeFlag();
return Response.json(maintenanceNotice);
try {
const maintenanceNotice = await maintenanceNoticeFlag();
return Response.json(maintenanceNotice);
} catch (error) {
console.error('[API] Error in edge flags route:', error);
return Response.json({ enabled: false }, { status: 500 });
}
}

View File

@ -1,10 +1,8 @@
'use client';
import { useEffect, useState } from 'react';
import { useEffect } from 'react';
import { SidebarLeft, FloatingMobileMenuButton } from '@/components/sidebar/sidebar-left';
import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar';
// import { PricingAlert } from "@/components/billing/pricing-alert"
import { MaintenanceAlert } from '@/components/maintenance-alert';
import { useAccounts } from '@/hooks/use-accounts';
import { useAuth } from '@/components/AuthProvider';
import { useMaintenanceNoticeQuery } from '@/hooks/react-query/edge-flags';
@ -14,13 +12,12 @@ import { useApiHealth } from '@/hooks/react-query';
import { MaintenancePage } from '@/components/maintenance/maintenance-page';
import { DeleteOperationProvider } from '@/contexts/DeleteOperationContext';
import { StatusOverlay } from '@/components/ui/status-overlay';
import { MaintenanceNotice } from './maintenance-notice';
import { MaintenanceBanner } from './maintenance-banner';
import { useProjects, useThreads } from '@/hooks/react-query/sidebar/use-sidebar';
import { useIsMobile } from '@/hooks/use-mobile';
import { useAgents } from '@/hooks/react-query/agents/use-agents';
import { SubscriptionProvider } from '@/contexts/SubscriptionContext';
import { MaintenanceAlert } from '../maintenance-alert';
interface DashboardLayoutContentProps {
children: React.ReactNode;
@ -29,21 +26,18 @@ interface DashboardLayoutContentProps {
export default function DashboardLayoutContent({
children,
}: DashboardLayoutContentProps) {
// const [showPricingAlert, setShowPricingAlert] = useState(false)
const [showMaintenanceAlert, setShowMaintenanceAlert] = useState(false);
const { data: accounts } = useAccounts();
const personalAccount = accounts?.find((account) => account.personal_account);
const { user, isLoading } = useAuth();
const router = useRouter();
const isMobile = useIsMobile();
const { data: maintenanceNotice } = useMaintenanceNoticeQuery();
const { data: maintenanceNotice, isLoading: maintenanceLoading } = useMaintenanceNoticeQuery();
const {
data: healthData,
isLoading: isCheckingHealth,
error: healthError,
} = useApiHealth();
// Prefetch sidebar data for better mobile experience
const { data: projects } = useProjects();
const { data: threads } = useThreads();
const { data: agentsResponse } = useAgents({
@ -53,11 +47,10 @@ export default function DashboardLayoutContent({
});
useEffect(() => {
// setShowPricingAlert(false)
if (maintenanceNotice?.enabled) {
setShowMaintenanceAlert(true);
// setShowMaintenanceAlert(true); // This line was removed
} else {
setShowMaintenanceAlert(false);
// setShowMaintenanceAlert(false); // This line was removed
}
}, [maintenanceNotice]);
@ -86,8 +79,8 @@ export default function DashboardLayoutContent({
let mantenanceBanner: React.ReactNode | null = null;
// Show loading state while checking auth or health
if (isLoading || isCheckingHealth) {
// Show loading state while checking auth, health, or maintenance status
if (isLoading || isCheckingHealth || maintenanceLoading) {
return (
<div className="flex items-center justify-center min-h-screen">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
@ -100,6 +93,11 @@ export default function DashboardLayoutContent({
return null;
}
// Show maintenance page if maintenance mode is enabled
if (maintenanceNotice?.enabled) {
return <MaintenanceAlert open={true} onOpenChange={() => {}} closeable={false} />;
}
// Show maintenance page if API is not healthy (but not during initial loading)
if (!isCheckingHealth && !isApiHealthy) {
return <MaintenancePage />;
@ -122,11 +120,11 @@ export default function DashboardLayoutContent({
accountId={personalAccount?.account_id}
/> */}
<MaintenanceAlert
{/* <MaintenanceAlert
open={showMaintenanceAlert}
onOpenChange={setShowMaintenanceAlert}
closeable={true}
/>
/> */}
{/* Status overlay for deletion operations */}
<StatusOverlay />

View File

@ -37,11 +37,6 @@ export function MaintenanceAlert({
animate={{ opacity: 1, scale: 1 }}
transition={{ type: 'spring', damping: 30, stiffness: 300 }}
>
{/* Background pattern */}
<div className="absolute inset-0 bg-accent/20 opacity-20">
<div className="absolute inset-0 bg-grid-white/10 [mask-image:radial-gradient(white,transparent_85%)]" />
</div>
{closeable && (
<Button
variant="ghost"
@ -53,7 +48,6 @@ export function MaintenanceAlert({
<span className="sr-only">Close</span>
</Button>
)}
<AlertDialogHeader className="gap-6 px-8 pt-10 pb-6 relative z-10">
<motion.div
className="flex items-center justify-center"
@ -61,8 +55,8 @@ export function MaintenanceAlert({
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.1 }}
>
<div className="flex size-16 items-center justify-center rounded-full bg-gradient-to-t from-primary/20 to-secondary/10 backdrop-blur-md">
<div className="flex size-12 items-center justify-center rounded-full bg-gradient-to-t from-primary to-primary/80 shadow-md">
<div className="flex size-16 items-center justify-center rounded-full bg-gradient-to-t from-amber-500/20 to-amber-600/10 backdrop-blur-md">
<div className="flex size-12 items-center justify-center rounded-full bg-gradient-to-t from-amber-500 to-amber-600 shadow-md">
<Clock className="h-6 w-6 text-white" />
</div>
</div>
@ -74,7 +68,7 @@ export function MaintenanceAlert({
transition={{ delay: 0.2 }}
>
<AlertDialogTitle className="text-2xl font-bold text-center text-primary bg-clip-text">
High Demand Notice
Maintenance Notice
</AlertDialogTitle>
</motion.div>
@ -84,28 +78,11 @@ export function MaintenanceAlert({
transition={{ delay: 0.3 }}
>
<AlertDialogDescription className="text-base text-center leading-relaxed">
Due to exceptionally high demand, our service is currently
experiencing slower response times. We recommend returning
tomorrow when our systems will be operating at normal capacity.
<span className="mt-4 block font-medium text-primary">
Thank you for your understanding. We will notify you via email
once the service is fully operational again.
</span>
We are currently performing maintenance on our system. Please
check back later.
</AlertDialogDescription>
</motion.div>
</AlertDialogHeader>
<AlertDialogFooter className="p-8 pt-4 border-t border-border/40 bg-background/40 backdrop-blur-sm">
<Link
href="https://github.com/kortix-ai/suna"
target="_blank"
rel="noopener noreferrer"
className="mx-auto w-full flex items-center justify-center gap-3 bg-gradient-to-tr from-primary to-primary/80 hover:opacity-90 text-white font-medium rounded-full px-8 py-3 transition-all hover:shadow-md"
>
<Github className="h-5 w-5 transition-transform group-hover:scale-110" />
<span>Explore Self-Hosted Version</span>
</Link>
</AlertDialogFooter>
</motion.div>
</AlertDialogContent>
</AlertDialog>

View File

@ -3,7 +3,7 @@
import { createQueryHook, createQueryKeys } from '@/hooks/use-query';
import { IMaintenanceNotice } from '@/lib/edge-flags';
const maintenanceNoticeKeysBase = ['maintenance-notice'] as const;
const maintenanceNoticeKeysBase = ['maintenanceNotice'] as const;
export const maintenanceNoticeKeys = createQueryKeys({
all: maintenanceNoticeKeysBase,
@ -13,7 +13,8 @@ export const useMaintenanceNoticeQuery = createQueryHook(
maintenanceNoticeKeys.all,
async (): Promise<IMaintenanceNotice> => {
const response = await fetch('/api/edge-flags');
return response.json();
const data = await response.json();
return data;
},
{
staleTime: 30 * 1000,

View File

@ -27,16 +27,29 @@ export const maintenanceNoticeFlag = flag({
'maintenance-notice_enabled',
]);
if (!flags['maintenance-notice_enabled']) {
if (!flags || Object.keys(flags).length === 0) {
return { enabled: false } as const;
}
const startTime = new Date(flags['maintenance-notice_start-time']);
const endTime = new Date(flags['maintenance-notice_end-time']);
const enabled = flags['maintenance-notice_enabled'];
if (!enabled) {
return { enabled: false } as const;
}
const startTimeRaw = flags['maintenance-notice_start-time'];
const endTimeRaw = flags['maintenance-notice_end-time'];
if (!startTimeRaw || !endTimeRaw) {
return { enabled: false } as const;
}
const startTime = new Date(startTimeRaw);
const endTime = new Date(endTimeRaw);
if (isNaN(startTime.getTime()) || isNaN(endTime.getTime())) {
throw new Error(
`Invalid maintenance notice start or end time: ${flags['maintenance-notice_start-time']} or ${flags['maintenance-notice_end-time']}`,
`Invalid maintenance notice start or end time: ${startTimeRaw} or ${endTimeRaw}`,
);
}