mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-16 10:16:49 +00:00
feat(ui): surface updates center across dashboard
- add /updates route and sidebar navigation entry - show updates spotlight on Home, API Profiles, and CLIProxy pages - export Updates page for lazy route loading consistency
This commit is contained in:
@@ -35,6 +35,7 @@ const SettingsPage = lazy(() =>
|
||||
);
|
||||
const HealthPage = lazy(() => import('@/pages/health').then((m) => ({ default: m.HealthPage })));
|
||||
const SharedPage = lazy(() => import('@/pages/shared').then((m) => ({ default: m.SharedPage })));
|
||||
const UpdatesPage = lazy(() => import('@/pages/updates').then((m) => ({ default: m.UpdatesPage })));
|
||||
|
||||
// Loading fallback for lazy components
|
||||
function PageLoader() {
|
||||
@@ -68,6 +69,14 @@ export default function App() {
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/updates"
|
||||
element={
|
||||
<Suspense fallback={<PageLoader />}>
|
||||
<UpdatesPage />
|
||||
</Suspense>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/providers"
|
||||
element={
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
BarChart3,
|
||||
Gauge,
|
||||
Github,
|
||||
Megaphone,
|
||||
} from 'lucide-react';
|
||||
import type { LucideIcon } from 'lucide-react';
|
||||
import {
|
||||
@@ -67,6 +68,7 @@ const navGroups: SidebarGroupDef[] = [
|
||||
title: 'General',
|
||||
items: [
|
||||
{ path: '/', icon: Home, label: 'Home' },
|
||||
{ path: '/updates', icon: Megaphone, label: 'Updates Center' },
|
||||
{ path: '/analytics', icon: BarChart3, label: 'Analytics' },
|
||||
],
|
||||
},
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { BellRing, ExternalLink } from 'lucide-react';
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||
import { formatCatalogDate, getLatestSupportNotice } from '@/lib/support-updates-catalog';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export function UpdatesSpotlight({
|
||||
className,
|
||||
compact = false,
|
||||
}: {
|
||||
className?: string;
|
||||
compact?: boolean;
|
||||
}) {
|
||||
const latest = getLatestSupportNotice();
|
||||
if (!latest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const primaryCommand = latest.commands[0];
|
||||
|
||||
return (
|
||||
<Alert variant="info" className={cn('border-dashed', className)}>
|
||||
<BellRing className="h-4 w-4" />
|
||||
<AlertTitle className="flex flex-wrap items-center gap-2">
|
||||
<span>{latest.title}</span>
|
||||
<span className="text-xs font-normal text-blue-700/80 dark:text-blue-300/80">
|
||||
{formatCatalogDate(latest.publishedAt)}
|
||||
</span>
|
||||
</AlertTitle>
|
||||
<AlertDescription className="space-y-2">
|
||||
<p>{latest.summary}</p>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-3 text-xs">
|
||||
<Link
|
||||
to="/updates"
|
||||
className="inline-flex items-center gap-1 font-medium text-blue-700 hover:underline dark:text-blue-300"
|
||||
>
|
||||
Open Updates Center
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
</Link>
|
||||
|
||||
{!compact && primaryCommand && (
|
||||
<code className="rounded bg-blue-100/70 px-1.5 py-0.5 font-mono text-blue-800 dark:bg-blue-900/40 dark:text-blue-200">
|
||||
{primaryCommand}
|
||||
</code>
|
||||
)}
|
||||
</div>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import { ProfileCreateDialog } from '@/components/profiles/profile-create-dialog
|
||||
import { OpenRouterBanner } from '@/components/profiles/openrouter-banner';
|
||||
import { OpenRouterQuickStart } from '@/components/profiles/openrouter-quick-start';
|
||||
import { OpenRouterPromoCard } from '@/components/profiles/openrouter-promo-card';
|
||||
import { UpdatesSpotlight } from '@/components/updates/updates-spotlight';
|
||||
import { useProfiles, useDeleteProfile } from '@/hooks/use-profiles';
|
||||
import { useOpenRouterModels } from '@/hooks/use-openrouter-models';
|
||||
import { ConfirmDialog } from '@/components/shared/confirm-dialog';
|
||||
@@ -96,6 +97,10 @@ export function ApiPage() {
|
||||
{/* OpenRouter Announcement Banner */}
|
||||
<OpenRouterBanner onCreateClick={() => setCreateDialogOpen(true)} />
|
||||
|
||||
<div className="px-4 pt-4">
|
||||
<UpdatesSpotlight compact />
|
||||
</div>
|
||||
|
||||
{/* Main Content */}
|
||||
<div className="flex-1 flex min-h-0">
|
||||
{/* Left Panel - Profiles List */}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { AccountSafetyWarningCard } from '@/components/account/account-safety-wa
|
||||
import { ProviderEditor } from '@/components/cliproxy/provider-editor';
|
||||
import { ProviderLogo } from '@/components/cliproxy/provider-logo';
|
||||
import { ProxyStatusWidget } from '@/components/monitoring/proxy-status-widget';
|
||||
import { UpdatesSpotlight } from '@/components/updates/updates-spotlight';
|
||||
import {
|
||||
useCliproxy,
|
||||
useCliproxyAuth,
|
||||
@@ -397,6 +398,7 @@ export function CliproxyPage() {
|
||||
|
||||
{/* Right Panel */}
|
||||
<div className="flex-1 flex flex-col min-w-0 bg-background">
|
||||
<UpdatesSpotlight className="mx-4 mt-4" compact />
|
||||
{showAccountSafetyWarning && <AccountSafetyWarningCard className="mx-4 mt-4" />}
|
||||
|
||||
{selectedVariantData && parentAuthForVariant ? (
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Key, Zap, Users, Activity, AlertTriangle } from 'lucide-react';
|
||||
import { useOverview } from '@/hooks/use-overview';
|
||||
import { useSharedSummary } from '@/hooks/use-shared';
|
||||
import { UpdatesSpotlight } from '@/components/updates/updates-spotlight';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { LucideIcon } from 'lucide-react';
|
||||
|
||||
@@ -165,6 +166,8 @@ export function HomePage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UpdatesSpotlight />
|
||||
|
||||
{/* Configuration Warning */}
|
||||
{shared?.symlinkStatus && !shared.symlinkStatus.valid && (
|
||||
<Alert variant="warning">
|
||||
|
||||
@@ -15,3 +15,5 @@ export { SharedPage } from './shared';
|
||||
export { AnalyticsPage } from './analytics';
|
||||
|
||||
export { CursorPage } from './cursor';
|
||||
|
||||
export { UpdatesPage } from './updates';
|
||||
|
||||
Reference in New Issue
Block a user