Skip to content

Commit e5252f8

Browse files
author
catlog22
committed
feat: add useApiSettings hook for managing API settings, including providers, endpoints, cache, and model pools
- Implemented hooks for CRUD operations on providers and endpoints. - Added cache management hooks for cache stats and settings. - Introduced model pool management hooks for high availability and load balancing. - Created localization files for English and Chinese translations of API settings.
1 parent b76424f commit e5252f8

27 files changed

Lines changed: 4370 additions & 201 deletions

ccw/frontend/package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ccw/frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"react-router-dom": "^6.28.0",
4545
"rehype-highlight": "^7.0.2",
4646
"remark-gfm": "^4.0.1",
47+
"sonner": "^2.0.7",
4748
"tailwind-merge": "^2.5.0",
4849
"zod": "^3.23.8",
4950
"zustand": "^5.0.0"

ccw/frontend/src/components/codexlens/AdvancedTab.tsx

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import { useState, useEffect } from 'react';
77
import { useIntl } from 'react-intl';
8-
import { Save, RefreshCw, AlertTriangle, FileCode } from 'lucide-react';
8+
import { Save, RefreshCw, AlertTriangle, FileCode, AlertCircle } from 'lucide-react';
99
import { Card } from '@/components/ui/Card';
1010
import { Textarea } from '@/components/ui/Textarea';
1111
import { Button } from '@/components/ui/Button';
@@ -32,6 +32,7 @@ export function AdvancedTab({ enabled = true }: AdvancedTabProps) {
3232
env,
3333
settings,
3434
isLoading: isLoadingEnv,
35+
error: envError,
3536
refetch,
3637
} = useCodexLensEnv({ enabled });
3738

@@ -43,23 +44,25 @@ export function AdvancedTab({ enabled = true }: AdvancedTabProps) {
4344
const [hasChanges, setHasChanges] = useState(false);
4445
const [showWarning, setShowWarning] = useState(false);
4546

46-
// Initialize form from env
47+
// Initialize form from env - handles both undefined (loading) and empty string (empty file)
48+
// The hook returns raw directly, so we check if it's been set (not undefined means data loaded)
4749
useEffect(() => {
48-
if (raw !== undefined) {
49-
setEnvInput(raw);
50+
// Initialize when data is loaded (raw may be empty string but not undefined during loading)
51+
// Note: During initial load, raw is undefined. After load completes, raw is set (even if empty string)
52+
if (!isLoadingEnv) {
53+
setEnvInput(raw ?? ''); // Use empty string if raw is undefined/null
5054
setErrors({});
5155
setHasChanges(false);
5256
setShowWarning(false);
5357
}
54-
}, [raw]);
58+
}, [raw, isLoadingEnv]);
5559

5660
const handleEnvChange = (value: string) => {
5761
setEnvInput(value);
58-
// Check if there are changes
59-
if (raw !== undefined) {
60-
setHasChanges(value !== raw);
61-
setShowWarning(value !== raw);
62-
}
62+
// Check if there are changes - compare with raw value (handle undefined as empty)
63+
const currentRaw = raw ?? '';
64+
setHasChanges(value !== currentRaw);
65+
setShowWarning(value !== currentRaw);
6366
if (errors.env) {
6467
setErrors((prev) => ({ ...prev, env: undefined }));
6568
}
@@ -132,12 +135,11 @@ export function AdvancedTab({ enabled = true }: AdvancedTabProps) {
132135
};
133136

134137
const handleReset = () => {
135-
if (raw !== undefined) {
136-
setEnvInput(raw);
137-
setErrors({});
138-
setHasChanges(false);
139-
setShowWarning(false);
140-
}
138+
// Reset to current raw value (handle undefined as empty)
139+
setEnvInput(raw ?? '');
140+
setErrors({});
141+
setHasChanges(false);
142+
setShowWarning(false);
141143
};
142144

143145
const isLoading = isLoadingEnv;
@@ -154,6 +156,32 @@ export function AdvancedTab({ enabled = true }: AdvancedTabProps) {
154156

155157
return (
156158
<div className="space-y-6">
159+
{/* Error Card */}
160+
{envError && (
161+
<Card className="p-4 bg-destructive/10 border-destructive/20">
162+
<div className="flex items-start gap-3">
163+
<AlertCircle className="w-5 h-5 text-destructive flex-shrink-0 mt-0.5" />
164+
<div className="flex-1">
165+
<h4 className="text-sm font-medium text-destructive-foreground">
166+
{formatMessage({ id: 'codexlens.advanced.loadError' })}
167+
</h4>
168+
<p className="text-xs text-destructive-foreground/80 mt-1">
169+
{envError.message || formatMessage({ id: 'codexlens.advanced.loadErrorDesc' })}
170+
</p>
171+
<Button
172+
variant="outline"
173+
size="sm"
174+
onClick={() => refetch()}
175+
className="mt-2"
176+
>
177+
<RefreshCw className="w-3 h-3 mr-1" />
178+
{formatMessage({ id: 'common.actions.retry' })}
179+
</Button>
180+
</div>
181+
</div>
182+
</Card>
183+
)}
184+
157185
{/* Sensitivity Warning Card */}
158186
{showWarning && (
159187
<Card className="p-4 bg-warning/10 border-warning/20">

0 commit comments

Comments
 (0)