@allbluecn/admin-app 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -8
- package/src/components/admin/admin-user-menu.tsx +12 -6
- package/src/components/admin/developer-log.tsx +42 -44
- package/src/components/ai-provider/model-list-editor.tsx +5 -4
- package/src/components/ai-provider/provider-form.tsx +63 -64
- package/src/components/ai-provider/provider-table.tsx +35 -36
- package/src/components/auth/admin-login-form.tsx +23 -24
- package/src/components/auth/oauth-section.tsx +3 -5
- package/src/components/auth/password-input.tsx +2 -3
- package/src/components/common/placeholder-page.tsx +2 -4
- package/src/components/component/component-form-dialog.tsx +48 -49
- package/src/components/component/component-import-dialog.tsx +5 -5
- package/src/components/component/component-table.tsx +13 -14
- package/src/components/data-table/data-table-pagination.tsx +4 -6
- package/src/components/data-table/table-detail-layout.tsx +2 -3
- package/src/components/dependency/changelog-dialog.tsx +3 -4
- package/src/components/dependency/columns.tsx +32 -24
- package/src/components/dependency/dependency-table.tsx +37 -29
- package/src/components/dependency/edit-dialog.tsx +24 -25
- package/src/components/knowledge-public/bookmark-form-dialog.tsx +7 -7
- package/src/components/knowledge-public/compliance-form-dialog.tsx +13 -13
- package/src/components/knowledge-public/legal-form-dialog.tsx +51 -46
- package/src/components/layout/sidebar-02/app-sidebar.tsx +33 -34
- package/src/components/layout/sidebar-02/nav-main.tsx +1 -1
- package/src/components/market/columns.tsx +20 -21
- package/src/components/market/market-app-form.tsx +45 -38
- package/src/components/market/market-app-list.tsx +16 -17
- package/src/components/monitoring/error-list.tsx +18 -19
- package/src/components/monitoring/health-cards.tsx +11 -13
- package/src/components/monitoring/metrics-stats.tsx +11 -12
- package/src/components/monitoring/request-log-table.tsx +8 -9
- package/src/components/ui/pagination.tsx +0 -2
- package/src/components/ui/sidebar.tsx +1 -1
- package/src/components/user/columns.tsx +9 -9
- package/src/components/user/settings-activity-log.tsx +39 -29
- package/src/components/user/settings-profile.tsx +36 -36
- package/src/components/user/user-create-dialog.tsx +4 -4
- package/src/components/user/user-filters.tsx +16 -18
- package/src/lib/i18n/config.ts +0 -32
- package/src/providers/index.tsx +6 -16
- package/src/routeTree.gen.ts +1199 -0
- package/src/routes/__root.tsx +9 -23
- package/src/routes/_nav/apps/route.lazy.tsx +2 -3
- package/src/routes/_nav/audit/route.lazy.tsx +10 -11
- package/src/routes/_nav/billing/invoices/route.lazy.tsx +6 -7
- package/src/routes/_nav/billing/route.lazy.tsx +3 -4
- package/src/routes/_nav/billing/subscriptions/$subscriptionId/route.lazy.tsx +16 -17
- package/src/routes/_nav/billing/subscriptions/route.lazy.tsx +9 -10
- package/src/routes/_nav/compliance/route.lazy.tsx +34 -35
- package/src/routes/_nav/components/route.lazy.tsx +6 -6
- package/src/routes/_nav/dashboard/route.lazy.tsx +3 -5
- package/src/routes/_nav/dependencies/route.lazy.tsx +7 -8
- package/src/routes/_nav/docs/route.lazy.tsx +2 -3
- package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +40 -41
- package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +32 -33
- package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +32 -33
- package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +24 -31
- package/src/routes/_nav/licenses/new/route.lazy.tsx +25 -26
- package/src/routes/_nav/licenses/route.lazy.tsx +17 -18
- package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +26 -27
- package/src/routes/_nav/monitoring/errors/route.lazy.tsx +11 -12
- package/src/routes/_nav/monitoring/health/route.lazy.tsx +18 -20
- package/src/routes/_nav/monitoring/logs/route.lazy.tsx +12 -13
- package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +13 -15
- package/src/routes/_nav/monitoring/overview/route.lazy.tsx +12 -13
- package/src/routes/_nav/monitoring/route.lazy.tsx +8 -9
- package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +55 -57
- package/src/routes/_nav/permissions/route.lazy.tsx +48 -50
- package/src/routes/_nav/settings/route.lazy.tsx +2 -3
- package/src/routes/_nav/sso/route.lazy.tsx +20 -18
- package/src/routes/_nav/users/$userId/route.lazy.tsx +86 -82
- package/src/routes/_nav/users/route.lazy.tsx +4 -5
- package/src/routes/setup/route.lazy.tsx +15 -16
- package/src/start.ts +2 -2
- package/src/lib/i18n/client.ts +0 -32
- package/src/lib/i18n/locales/en/admin-ai.json +0 -128
- package/src/lib/i18n/locales/en/admin-billing.json +0 -56
- package/src/lib/i18n/locales/en/admin-users.json +0 -88
- package/src/lib/i18n/locales/en/common.json +0 -877
- package/src/lib/i18n/locales/en/enterprise.json +0 -208
- package/src/lib/i18n/locales/zh/admin-ai.json +0 -128
- package/src/lib/i18n/locales/zh/admin-billing.json +0 -56
- package/src/lib/i18n/locales/zh/admin-users.json +0 -88
- package/src/lib/i18n/locales/zh/common.json +0 -877
- package/src/lib/i18n/locales/zh/enterprise.json +0 -208
- package/src/lib/i18n/server.ts +0 -18
- package/src/lib/i18n/types.ts +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@allbluecn/admin-app",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -30,28 +30,27 @@
|
|
|
30
30
|
"class-variance-authority": "^0.7.1",
|
|
31
31
|
"clsx": "^2.1.1",
|
|
32
32
|
"date-fns": "^4.4.0",
|
|
33
|
-
"i18next": "^25.10.10",
|
|
34
|
-
"i18next-browser-languagedetector": "^8.2.1",
|
|
35
33
|
"lucide-react": "^1.27.0",
|
|
36
34
|
"motion": "^12.42.2",
|
|
37
35
|
"next-themes": "^0.4.6",
|
|
38
36
|
"radix-ui": "^1.4.3",
|
|
39
37
|
"react": "^19.2.4",
|
|
40
38
|
"react-dom": "^19.2.4",
|
|
41
|
-
"react-i18next": "^15.7.4",
|
|
42
39
|
"react-markdown": "^10.1.0",
|
|
43
40
|
"remark-gfm": "^4.0.1",
|
|
44
41
|
"sonner": "^2.0.7",
|
|
45
42
|
"start-authjs": "^1.0.2",
|
|
46
43
|
"tailwind-merge": "^3.5.0",
|
|
47
44
|
"zod": "^4.4.3",
|
|
48
|
-
"@allbluecn/web-app": "0.
|
|
45
|
+
"@allbluecn/web-app": "0.10.0",
|
|
49
46
|
"@allbluecn/database": "0.4.18",
|
|
50
47
|
"@allbluecn/kernel": "0.5.2"
|
|
51
48
|
},
|
|
52
49
|
"devDependencies": {
|
|
53
50
|
"@cloudflare/vite-plugin": "^1.40.1",
|
|
54
51
|
"@eslint/js": "^9.39.4",
|
|
52
|
+
"@inlang/paraglide-js": "^2.25.0",
|
|
53
|
+
"@inlang/plugin-message-format": "^4.4.4",
|
|
55
54
|
"@tailwindcss/vite": "^4.3.2",
|
|
56
55
|
"@tanstack/react-query-devtools": "5.102.8",
|
|
57
56
|
"@tanstack/react-router-devtools": "1.167.1",
|
|
@@ -62,7 +61,7 @@
|
|
|
62
61
|
"@vitejs/plugin-react": "^6.0.1",
|
|
63
62
|
"@vitest/coverage-v8": "^4.1.10",
|
|
64
63
|
"eslint": "^9",
|
|
65
|
-
"nitro": "3.0.
|
|
64
|
+
"nitro": "3.0.260903-beta",
|
|
66
65
|
"shadcn": "^4.15.0",
|
|
67
66
|
"tailwindcss": "^4",
|
|
68
67
|
"typescript": "^7",
|
|
@@ -79,8 +78,9 @@
|
|
|
79
78
|
},
|
|
80
79
|
"scripts": {
|
|
81
80
|
"dev": "NODE_OPTIONS='--import ./instrument.server.mjs' vite --port 3001",
|
|
82
|
-
"build": "vite build && if [ -d .output/server ]; then cp instrument.server.mjs .output/server; fi",
|
|
81
|
+
"build": "node scripts/i18n/compile.mjs && vite build && if [ -d .output/server ]; then cp instrument.server.mjs .output/server; fi",
|
|
83
82
|
"start": "node --import ./.output/server/instrument.server.mjs .output/server/index.mjs",
|
|
84
|
-
"lint": "eslint"
|
|
83
|
+
"lint": "eslint",
|
|
84
|
+
"typecheck": "node scripts/i18n/compile.mjs && tsc --noEmit"
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
// You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
import { useTranslation } from 'react-i18next'
|
|
20
18
|
import { LogOut } from "lucide-react";
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
21
20
|
import { Badge } from "@/components/ui/badge";
|
|
22
21
|
import {
|
|
23
22
|
SidebarMenu,
|
|
@@ -31,8 +30,15 @@ import { signOut, useSession } from "@/lib/auth-client";
|
|
|
31
30
|
import { UserAvatar } from "@allbluecn/web-app/user-avatar";
|
|
32
31
|
import type { AvatarConfig, ShapeType } from "@allbluecn/kernel";
|
|
33
32
|
|
|
33
|
+
const ROLE_LABELS: Record<string, () => string> = {
|
|
34
|
+
ADMIN: m.common_common_role_ADMIN,
|
|
35
|
+
GUEST: m.common_common_role_GUEST,
|
|
36
|
+
OPERATOR: m.common_common_role_OPERATOR,
|
|
37
|
+
SUPER_ADMIN: m.common_common_role_SUPER_ADMIN,
|
|
38
|
+
USER: m.common_common_role_USER,
|
|
39
|
+
}
|
|
40
|
+
|
|
34
41
|
export function AdminUserMenu() {
|
|
35
|
-
const { t } = useTranslation('common')
|
|
36
42
|
const router = useRouter();
|
|
37
43
|
const { data: clientSession } = useSession();
|
|
38
44
|
const matches = useMatches();
|
|
@@ -42,10 +48,10 @@ export function AdminUserMenu() {
|
|
|
42
48
|
const session = clientSession || contextSession;
|
|
43
49
|
|
|
44
50
|
const user = session?.user;
|
|
45
|
-
const userName = user?.name || user?.email ||
|
|
51
|
+
const userName = user?.name || user?.email || m.common_login_admin();
|
|
46
52
|
const userEmail = user?.email || "";
|
|
47
53
|
const userRole = (user as { role?: string })?.role || "ADMIN";
|
|
48
|
-
const roleLabel =
|
|
54
|
+
const roleLabel = (ROLE_LABELS[userRole] ?? (() => m.common_login_admin()))();
|
|
49
55
|
const avatarConfig = (user as { avatarConfig?: AvatarConfig })?.avatarConfig;
|
|
50
56
|
const bgShape = (user as { bgShape?: string })?.bgShape as ShapeType | undefined;
|
|
51
57
|
const bgColor = (user as { bgColor?: string })?.bgColor;
|
|
@@ -82,7 +88,7 @@ export function AdminUserMenu() {
|
|
|
82
88
|
<LogOut className="h-4 w-4" />
|
|
83
89
|
</SidebarMenuAction>
|
|
84
90
|
</TooltipTrigger>
|
|
85
|
-
<TooltipContent>{
|
|
91
|
+
<TooltipContent>{m.common_login_exitAdmin()}</TooltipContent>
|
|
86
92
|
</Tooltip>
|
|
87
93
|
</SidebarMenuItem>
|
|
88
94
|
</SidebarMenu>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useTranslation } from 'react-i18next'
|
|
2
1
|
import { useState, useMemo } from 'react'
|
|
2
|
+
import { m } from '@/paraglide/messages.js'
|
|
3
3
|
import { Route } from '@/routes/_nav/developer-logs/route'
|
|
4
4
|
import type { DeveloperLogEntry } from '@allbluecn/kernel'
|
|
5
5
|
import { useQueryClient } from '@tanstack/react-query'
|
|
@@ -49,7 +49,6 @@ function DeveloperLogDialog({
|
|
|
49
49
|
onOpenChange: (open: boolean) => void
|
|
50
50
|
entry?: DeveloperLogEntry
|
|
51
51
|
}) {
|
|
52
|
-
const { t } = useTranslation('common')
|
|
53
52
|
const isEdit = !!entry
|
|
54
53
|
|
|
55
54
|
const [date, setDate] = useState(entry?.date || '')
|
|
@@ -64,7 +63,7 @@ function DeveloperLogDialog({
|
|
|
64
63
|
|
|
65
64
|
const handleSave = async () => {
|
|
66
65
|
if (!title.trim()) {
|
|
67
|
-
toast.error(
|
|
66
|
+
toast.error(m.common_developerLogs_form_fillRequired())
|
|
68
67
|
return
|
|
69
68
|
}
|
|
70
69
|
|
|
@@ -77,7 +76,7 @@ function DeveloperLogDialog({
|
|
|
77
76
|
await createFn({ data: { date, year, title, desc, tags, commitSha: commitSha || undefined } })
|
|
78
77
|
}
|
|
79
78
|
|
|
80
|
-
toast.success(
|
|
79
|
+
toast.success(m.common_developerLogs_saveSuccess())
|
|
81
80
|
queryClient.invalidateQueries({ queryKey: ['DeveloperLogPage'] })
|
|
82
81
|
onOpenChange(false)
|
|
83
82
|
}
|
|
@@ -86,23 +85,23 @@ function DeveloperLogDialog({
|
|
|
86
85
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
87
86
|
<DialogContent className="max-w-lg">
|
|
88
87
|
<DialogHeader>
|
|
89
|
-
<DialogTitle>{isEdit ?
|
|
88
|
+
<DialogTitle>{isEdit ? m.common_developerLogs_editEntry() : m.common_developerLogs_addEntry()}</DialogTitle>
|
|
90
89
|
</DialogHeader>
|
|
91
90
|
<div className="grid gap-4 py-4">
|
|
92
91
|
<div className="grid gap-2">
|
|
93
|
-
<Label>{
|
|
94
|
-
<Input value={date} onChange={(e) => setDate(e.target.value)} placeholder={
|
|
92
|
+
<Label>{m.common_developerLogs_form_date_label()}</Label>
|
|
93
|
+
<Input value={date} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setDate(e.target.value)} placeholder={m.common_developerLogs_form_date_placeholder()} />
|
|
95
94
|
</div>
|
|
96
95
|
<div className="grid gap-2">
|
|
97
|
-
<Label>{
|
|
98
|
-
<Input value={title} onChange={(e) => setTitle(e.target.value)} placeholder={
|
|
96
|
+
<Label>{m.common_developerLogs_form_title_label()}</Label>
|
|
97
|
+
<Input value={title} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setTitle(e.target.value)} placeholder={m.common_developerLogs_form_title_placeholder()} />
|
|
99
98
|
</div>
|
|
100
99
|
<div className="grid gap-2">
|
|
101
|
-
<Label>{
|
|
102
|
-
<Textarea value={desc} onChange={(e) => setDesc(e.target.value)} placeholder={
|
|
100
|
+
<Label>{m.common_developerLogs_form_desc_label()}</Label>
|
|
101
|
+
<Textarea value={desc} onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setDesc(e.target.value)} placeholder={m.common_developerLogs_form_desc_placeholder()} rows={3} />
|
|
103
102
|
</div>
|
|
104
103
|
<div className="grid gap-2">
|
|
105
|
-
<Label>{
|
|
104
|
+
<Label>{m.common_developerLogs_form_tags_label()}</Label>
|
|
106
105
|
<div className="flex gap-1 flex-wrap">
|
|
107
106
|
{TAG_OPTIONS.map((tag) => {
|
|
108
107
|
const isActive = tagStr.split(',').map((s) => s.trim()).includes(tag)
|
|
@@ -127,13 +126,13 @@ function DeveloperLogDialog({
|
|
|
127
126
|
</div>
|
|
128
127
|
</div>
|
|
129
128
|
<div className="grid gap-2">
|
|
130
|
-
<Label>{
|
|
131
|
-
<Input value={commitSha} onChange={(e) => setCommitSha(e.target.value)} placeholder={
|
|
129
|
+
<Label>{m.common_developerLogs_form_commitSha_label()}</Label>
|
|
130
|
+
<Input value={commitSha} onChange={(e: React.ChangeEvent<HTMLInputElement>) => setCommitSha(e.target.value)} placeholder={m.common_developerLogs_form_commitSha_placeholder()} />
|
|
132
131
|
</div>
|
|
133
132
|
</div>
|
|
134
133
|
<DialogFooter>
|
|
135
|
-
<Button variant="outline" onClick={() => onOpenChange(false)}>{
|
|
136
|
-
<Button onClick={handleSave}>{
|
|
134
|
+
<Button variant="outline" onClick={() => onOpenChange(false)}>{m.common_button_cancel()}</Button>
|
|
135
|
+
<Button onClick={handleSave}>{m.common_button_save()}</Button>
|
|
137
136
|
</DialogFooter>
|
|
138
137
|
</DialogContent>
|
|
139
138
|
</Dialog>
|
|
@@ -141,7 +140,6 @@ function DeveloperLogDialog({
|
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
function DeveloperLogPage() {
|
|
144
|
-
const { t } = useTranslation('common')
|
|
145
143
|
const { entries } = Route.useLoaderData() as { entries: DeveloperLogEntry[] }
|
|
146
144
|
const queryClient = useQueryClient()
|
|
147
145
|
|
|
@@ -178,7 +176,7 @@ function DeveloperLogPage() {
|
|
|
178
176
|
|
|
179
177
|
const handleDelete = async (id: string) => {
|
|
180
178
|
await deleteFn({ data: { id } })
|
|
181
|
-
toast.success(
|
|
179
|
+
toast.success(m.common_developerLogs_deleteSuccess())
|
|
182
180
|
queryClient.invalidateQueries({ queryKey: ['DeveloperLogPage'] })
|
|
183
181
|
}
|
|
184
182
|
|
|
@@ -187,13 +185,13 @@ function DeveloperLogPage() {
|
|
|
187
185
|
try {
|
|
188
186
|
const result = await autoGenFn({ data: { daysBack: 60 } })
|
|
189
187
|
if (result.success) {
|
|
190
|
-
toast.success(
|
|
188
|
+
toast.success(m.common_developerLogs_autoGenerateSuccess({ count: result.count }))
|
|
191
189
|
queryClient.invalidateQueries({ queryKey: ['DeveloperLogPage'] })
|
|
192
190
|
} else {
|
|
193
|
-
toast.error(
|
|
191
|
+
toast.error(m.common_developerLogs_autoGenerateFailed())
|
|
194
192
|
}
|
|
195
193
|
} catch {
|
|
196
|
-
toast.error(
|
|
194
|
+
toast.error(m.common_developerLogs_autoGenerateFailed())
|
|
197
195
|
} finally {
|
|
198
196
|
setIsGenerating(false)
|
|
199
197
|
}
|
|
@@ -208,13 +206,13 @@ function DeveloperLogPage() {
|
|
|
208
206
|
try {
|
|
209
207
|
const result = await backfillDetailsFn()
|
|
210
208
|
if (result.success) {
|
|
211
|
-
toast.success(
|
|
209
|
+
toast.success(m.common_developerLogs_backfillSuccess({ count: result.count }))
|
|
212
210
|
queryClient.invalidateQueries({ queryKey: ['DeveloperLogPage'] })
|
|
213
211
|
} else {
|
|
214
|
-
toast.error(
|
|
212
|
+
toast.error(m.common_developerLogs_backfillFailed())
|
|
215
213
|
}
|
|
216
214
|
} catch {
|
|
217
|
-
toast.error(
|
|
215
|
+
toast.error(m.common_developerLogs_backfillFailed())
|
|
218
216
|
}
|
|
219
217
|
}
|
|
220
218
|
|
|
@@ -222,32 +220,32 @@ function DeveloperLogPage() {
|
|
|
222
220
|
<div className="h-full flex flex-col p-6 gap-4">
|
|
223
221
|
<div className="flex items-center justify-between">
|
|
224
222
|
<div>
|
|
225
|
-
<h1 className="text-2xl font-semibold">{
|
|
226
|
-
<p className="text-sm text-muted-foreground mt-1">{
|
|
223
|
+
<h1 className="text-2xl font-semibold">{m.common_developerLogs_title()}</h1>
|
|
224
|
+
<p className="text-sm text-muted-foreground mt-1">{m.common_developerLogs_description()}</p>
|
|
227
225
|
</div>
|
|
228
226
|
<div className="flex items-center gap-2">
|
|
229
227
|
<Dialog open={isGenerating} onOpenChange={setIsGenerating}>
|
|
230
228
|
<DialogContent>
|
|
231
229
|
<DialogHeader>
|
|
232
|
-
<DialogTitle>{
|
|
230
|
+
<DialogTitle>{m.common_developerLogs_autoGenerate()}</DialogTitle>
|
|
233
231
|
</DialogHeader>
|
|
234
232
|
<div className="flex items-center gap-2 py-4">
|
|
235
233
|
<Loader2 className="size-4 animate-spin" />
|
|
236
|
-
<span className="text-sm text-muted-foreground">{
|
|
234
|
+
<span className="text-sm text-muted-foreground">{m.common_developerLogs_autoGenerating()}</span>
|
|
237
235
|
</div>
|
|
238
236
|
</DialogContent>
|
|
239
237
|
</Dialog>
|
|
240
238
|
<Button variant="outline" onClick={handleAutoGenerate} disabled={isGenerating}>
|
|
241
239
|
<Loader2 className="size-4 mr-1.5 animate-spin" />
|
|
242
|
-
{
|
|
240
|
+
{m.common_developerLogs_autoGenerate()}
|
|
243
241
|
</Button>
|
|
244
242
|
<Button variant="outline" onClick={handleBackfill}>
|
|
245
243
|
<RefreshCw className="size-4 mr-1.5" />
|
|
246
|
-
{
|
|
244
|
+
{m.common_developerLogs_backfillDetails()}
|
|
247
245
|
</Button>
|
|
248
246
|
<Button onClick={() => { setEditingEntry(undefined); setEditOpen(true) }}>
|
|
249
247
|
<Plus className="size-4 mr-1.5" />
|
|
250
|
-
{
|
|
248
|
+
{m.common_developerLogs_addEntry()}
|
|
251
249
|
</Button>
|
|
252
250
|
</div>
|
|
253
251
|
</div>
|
|
@@ -257,8 +255,8 @@ function DeveloperLogPage() {
|
|
|
257
255
|
<Search className="absolute left-2.5 top-1/2 -translate-y-1/2 size-3.5 text-muted-foreground" />
|
|
258
256
|
<Input
|
|
259
257
|
value={searchQuery}
|
|
260
|
-
onChange={(e) => setSearchQuery(e.target.value)}
|
|
261
|
-
placeholder={
|
|
258
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchQuery(e.target.value)}
|
|
259
|
+
placeholder={m.common_developerLogs_searchPlaceholder()}
|
|
262
260
|
className="pl-8"
|
|
263
261
|
/>
|
|
264
262
|
</div>
|
|
@@ -267,7 +265,7 @@ function DeveloperLogPage() {
|
|
|
267
265
|
onClick={() => setActiveTag('all')}
|
|
268
266
|
className={`px-2.5 py-1 rounded text-xs font-medium transition-colors ${activeTag === 'all' ? 'bg-primary/10 text-primary' : 'text-muted-foreground hover:text-foreground'}`}
|
|
269
267
|
>
|
|
270
|
-
{
|
|
268
|
+
{m.common_developerLogs_allTags()}
|
|
271
269
|
</button>
|
|
272
270
|
{allTags.map((tag) => (
|
|
273
271
|
<button
|
|
@@ -285,18 +283,18 @@ function DeveloperLogPage() {
|
|
|
285
283
|
<table className="w-full">
|
|
286
284
|
<thead className="sticky top-0 bg-muted/50">
|
|
287
285
|
<tr>
|
|
288
|
-
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{
|
|
289
|
-
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{
|
|
290
|
-
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{
|
|
291
|
-
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{
|
|
292
|
-
<th className="text-right px-4 py-2.5 text-xs font-medium text-muted-foreground">{
|
|
286
|
+
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{m.common_developerLogs_columns_date()}</th>
|
|
287
|
+
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{m.common_developerLogs_columns_title()}</th>
|
|
288
|
+
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{m.common_developerLogs_columns_desc()}</th>
|
|
289
|
+
<th className="text-left px-4 py-2.5 text-xs font-medium text-muted-foreground">{m.common_developerLogs_columns_tags()}</th>
|
|
290
|
+
<th className="text-right px-4 py-2.5 text-xs font-medium text-muted-foreground">{m.common_developerLogs_columns_actions()}</th>
|
|
293
291
|
</tr>
|
|
294
292
|
</thead>
|
|
295
293
|
<tbody>
|
|
296
294
|
{filteredEntries.length === 0 ? (
|
|
297
295
|
<tr>
|
|
298
296
|
<td colSpan={5} className="text-center py-12 text-sm text-muted-foreground">
|
|
299
|
-
{
|
|
297
|
+
{m.common_developerLogs_empty()}
|
|
300
298
|
</td>
|
|
301
299
|
</tr>
|
|
302
300
|
) : (
|
|
@@ -325,12 +323,12 @@ function DeveloperLogPage() {
|
|
|
325
323
|
</AlertDialogTrigger>
|
|
326
324
|
<AlertDialogContent>
|
|
327
325
|
<AlertDialogHeader>
|
|
328
|
-
<AlertDialogTitle>{
|
|
329
|
-
<AlertDialogDescription>{
|
|
326
|
+
<AlertDialogTitle>{m.common_button_delete()}</AlertDialogTitle>
|
|
327
|
+
<AlertDialogDescription>{m.common_developerLogs_deleteConfirm()}</AlertDialogDescription>
|
|
330
328
|
</AlertDialogHeader>
|
|
331
329
|
<AlertDialogFooter>
|
|
332
|
-
<AlertDialogCancel>{
|
|
333
|
-
<AlertDialogAction onClick={() => handleDelete(entry.id)} className="bg-destructive hover:bg-destructive/90">{
|
|
330
|
+
<AlertDialogCancel>{m.common_button_cancel()}</AlertDialogCancel>
|
|
331
|
+
<AlertDialogAction onClick={() => handleDelete(entry.id)} className="bg-destructive hover:bg-destructive/90">{m.common_button_confirm()}</AlertDialogAction>
|
|
334
332
|
</AlertDialogFooter>
|
|
335
333
|
</AlertDialogContent>
|
|
336
334
|
</AlertDialog>
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
// apps/admin/src/components/ai-provider/model-list-editor.tsx
|
|
19
19
|
import { Plus, Trash2 } from "lucide-react"
|
|
20
|
+
import { m } from '@/paraglide/messages.js'
|
|
20
21
|
import { Button } from "@/components/ui/button"
|
|
21
22
|
import { Input } from "@/components/ui/input"
|
|
22
23
|
import { cn } from "@/lib/utils"
|
|
@@ -67,13 +68,13 @@ export function ModelListEditor({
|
|
|
67
68
|
<div className="flex items-center gap-2">
|
|
68
69
|
<Input
|
|
69
70
|
value={m.id}
|
|
70
|
-
onChange={(e) => update(idx, { id: e.target.value })}
|
|
71
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => update(idx, { id: e.target.value })}
|
|
71
72
|
placeholder="模型 ID(如 gpt-4o)"
|
|
72
73
|
className="font-mono text-xs"
|
|
73
74
|
/>
|
|
74
75
|
<Input
|
|
75
76
|
value={m.displayName}
|
|
76
|
-
onChange={(e) => update(idx, { displayName: e.target.value })}
|
|
77
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => update(idx, { displayName: e.target.value })}
|
|
77
78
|
placeholder="显示名(如 GPT-4o)"
|
|
78
79
|
className="text-xs"
|
|
79
80
|
/>
|
|
@@ -92,7 +93,7 @@ export function ModelListEditor({
|
|
|
92
93
|
<Input
|
|
93
94
|
type="number"
|
|
94
95
|
value={m.contextWindow ?? ""}
|
|
95
|
-
onChange={(e) =>
|
|
96
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
96
97
|
update(idx, {
|
|
97
98
|
contextWindow: e.target.value
|
|
98
99
|
? Number(e.target.value)
|
|
@@ -126,7 +127,7 @@ export function ModelListEditor({
|
|
|
126
127
|
<input
|
|
127
128
|
type="checkbox"
|
|
128
129
|
checked={m.defaultEnabled ?? false}
|
|
129
|
-
|
|
130
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
|
130
131
|
update(idx, { defaultEnabled: e.target.checked })
|
|
131
132
|
}
|
|
132
133
|
/>
|