@allbluecn/admin-app 0.1.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 +9 -9
- 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/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
|
@@ -132,8 +132,8 @@ function ComponentsPage() {
|
|
|
132
132
|
<Search className="absolute left-2.5 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
133
133
|
<Input
|
|
134
134
|
value={searchInput}
|
|
135
|
-
onChange={(e) => setSearchInput(e.target.value)}
|
|
136
|
-
onKeyDown={(e) => { if (e.key === 'Enter') handleSearchSubmit() }}
|
|
135
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchInput(e.target.value)}
|
|
136
|
+
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => { if (e.key === 'Enter') handleSearchSubmit() }}
|
|
137
137
|
placeholder="搜索组件..."
|
|
138
138
|
className="pl-8"
|
|
139
139
|
/>
|
|
@@ -142,8 +142,8 @@ function ComponentsPage() {
|
|
|
142
142
|
|
|
143
143
|
<ComponentTable
|
|
144
144
|
items={items as unknown as ComponentItem[]}
|
|
145
|
-
onEdit={(item) => setEditing(item)}
|
|
146
|
-
onDelete={(item) => setDeleting(item)}
|
|
145
|
+
onEdit={(item: any) => setEditing(item)}
|
|
146
|
+
onDelete={(item: any) => setDeleting(item)}
|
|
147
147
|
/>
|
|
148
148
|
|
|
149
149
|
<ComponentFormDialog
|
|
@@ -154,7 +154,7 @@ function ComponentsPage() {
|
|
|
154
154
|
/>
|
|
155
155
|
<ComponentFormDialog
|
|
156
156
|
open={!!editing}
|
|
157
|
-
onOpenChange={(o) => !o && setEditing(null)}
|
|
157
|
+
onOpenChange={(o: boolean) => !o && setEditing(null)}
|
|
158
158
|
component={editing}
|
|
159
159
|
onSuccess={() => router.invalidate()}
|
|
160
160
|
/>
|
|
@@ -165,7 +165,7 @@ function ComponentsPage() {
|
|
|
165
165
|
onSuccess={() => router.invalidate()}
|
|
166
166
|
/>
|
|
167
167
|
|
|
168
|
-
<AlertDialog open={!!deleting} onOpenChange={(o) => !o && setDeleting(null)}>
|
|
168
|
+
<AlertDialog open={!!deleting} onOpenChange={(o: boolean) => !o && setDeleting(null)}>
|
|
169
169
|
<AlertDialogContent>
|
|
170
170
|
<AlertDialogHeader>
|
|
171
171
|
<AlertDialogTitle>删除组件「{deleting?.name}」?</AlertDialogTitle>
|
|
@@ -16,18 +16,16 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
19
|
-
import {
|
|
20
|
-
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
21
20
|
export const Route = createLazyFileRoute('/_nav/dashboard')({
|
|
22
21
|
component: DashboardPage,
|
|
23
22
|
})
|
|
24
23
|
|
|
25
24
|
function DashboardPage() {
|
|
26
|
-
const { t } = useTranslation('common')
|
|
27
25
|
return (
|
|
28
26
|
<div className="p-6">
|
|
29
|
-
<h2 className="text-2xl font-bold">{
|
|
30
|
-
<p className="mt-2 text-muted-foreground">{
|
|
27
|
+
<h2 className="text-2xl font-bold">{m.common_dashboard_title()}</h2>
|
|
28
|
+
<p className="mt-2 text-muted-foreground">{m.common_dashboard_subtitle()}</p>
|
|
31
29
|
</div>
|
|
32
30
|
)
|
|
33
31
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { useState } from "react"
|
|
19
|
-
import {
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
20
20
|
import { createLazyFileRoute } from "@tanstack/react-router"
|
|
21
21
|
import { Boxes, Info } from "lucide-react"
|
|
22
22
|
import type { ThirdPartyDependencyRow } from "@allbluecn/kernel"
|
|
@@ -29,7 +29,6 @@ export const Route = createLazyFileRoute("/_nav/dependencies")({
|
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
function DependenciesPage() {
|
|
32
|
-
const { t } = useTranslation('common')
|
|
33
32
|
const ctx = Route.useRouteContext() as { dependencies?: ThirdPartyDependencyRow[] }
|
|
34
33
|
const [data, setData] = useState<ThirdPartyDependencyRow[]>(ctx.dependencies ?? [])
|
|
35
34
|
|
|
@@ -45,19 +44,19 @@ function DependenciesPage() {
|
|
|
45
44
|
return (
|
|
46
45
|
<div className="p-6 space-y-5">
|
|
47
46
|
<PageHeader
|
|
48
|
-
title={
|
|
49
|
-
description={
|
|
47
|
+
title={m.common_dependencies_title()}
|
|
48
|
+
description={m.common_dependencies_description()}
|
|
50
49
|
icon={Boxes}
|
|
51
50
|
/>
|
|
52
51
|
<div className="flex items-start gap-2 rounded-md border border-blue-500/20 bg-blue-500/5 p-3 text-xs text-muted-foreground">
|
|
53
52
|
<Info className="mt-0.5 size-3.5 shrink-0 text-blue-500" />
|
|
54
53
|
<div>
|
|
55
|
-
{
|
|
54
|
+
{m.common_dependencies_hint_currentVersion()}
|
|
56
55
|
<code className="font-mono">apps/web</code>、
|
|
57
56
|
<code className="font-mono">apps/admin</code>、
|
|
58
|
-
<code className="font-mono">packages/*</code> {
|
|
59
|
-
{
|
|
60
|
-
{
|
|
57
|
+
<code className="font-mono">packages/*</code> {m.common_dependencies_hint_currentVersionSuffix()}
|
|
58
|
+
{m.common_dependencies_hint_latestVersion()}
|
|
59
|
+
{m.common_dependencies_hint_watchList()}
|
|
61
60
|
</div>
|
|
62
61
|
</div>
|
|
63
62
|
<DependencyTable data={data} onMutated={refetch} />
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { createLazyFileRoute } from '@tanstack/react-router'
|
|
19
|
-
import {
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
20
20
|
import { FileText } from 'lucide-react'
|
|
21
21
|
import { PlaceholderPage } from '@/components/common/placeholder-page'
|
|
22
22
|
|
|
@@ -25,6 +25,5 @@ export const Route = createLazyFileRoute('/_nav/docs')({
|
|
|
25
25
|
})
|
|
26
26
|
|
|
27
27
|
function DocsPage() {
|
|
28
|
-
|
|
29
|
-
return <PlaceholderPage title={t('docs.title')} icon={FileText} />
|
|
28
|
+
return <PlaceholderPage title={m.common_docs_title()} icon={FileText} />
|
|
30
29
|
}
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { createLazyFileRoute, useNavigate, useRouter } from '@tanstack/react-router'
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
19
20
|
import { useState, useTransition } from 'react'
|
|
20
|
-
import { useTranslation } from 'react-i18next'
|
|
21
21
|
import {
|
|
22
22
|
PlusIcon,
|
|
23
23
|
PencilIcon,
|
|
@@ -89,7 +89,6 @@ function FaviconCell({ faviconUrl, categoryIcon }: { faviconUrl: string | null;
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
function BookmarksPage() {
|
|
92
|
-
const { t } = useTranslation('common')
|
|
93
92
|
const { items: rawItems, total } = Route.useLoaderData()
|
|
94
93
|
const items = rawItems as unknown as BookmarkRow[]
|
|
95
94
|
const { search } = Route.useSearch()
|
|
@@ -127,11 +126,11 @@ function BookmarksPage() {
|
|
|
127
126
|
startDelete(async () => {
|
|
128
127
|
try {
|
|
129
128
|
await adminDeleteBookmarkFn({ data: { id: deleting.id } })
|
|
130
|
-
toast.success(
|
|
129
|
+
toast.success(m.common_knowledgePublic_bookmarks_deleted())
|
|
131
130
|
setDeleting(null)
|
|
132
131
|
refresh()
|
|
133
132
|
} catch (err) {
|
|
134
|
-
toast.error(err instanceof Error ? err.message :
|
|
133
|
+
toast.error(err instanceof Error ? err.message : m.common_common_deleteFailed())
|
|
135
134
|
}
|
|
136
135
|
})
|
|
137
136
|
}
|
|
@@ -141,11 +140,11 @@ function BookmarksPage() {
|
|
|
141
140
|
try {
|
|
142
141
|
const res = await adminSyncAllGithubFn({ data: { force: true } })
|
|
143
142
|
toast.success(
|
|
144
|
-
|
|
143
|
+
m.common_knowledgePublic_bookmarks_syncComplete({ total: res.total, success: res.success, failed: res.failed }),
|
|
145
144
|
)
|
|
146
145
|
refresh()
|
|
147
146
|
} catch (err) {
|
|
148
|
-
toast.error(err instanceof Error ? err.message :
|
|
147
|
+
toast.error(err instanceof Error ? err.message : m.common_knowledgePublic_bookmarks_syncFailed())
|
|
149
148
|
}
|
|
150
149
|
})
|
|
151
150
|
}
|
|
@@ -153,8 +152,8 @@ function BookmarksPage() {
|
|
|
153
152
|
const columns: AdminColumnDef<BookmarkRow>[] = [
|
|
154
153
|
{
|
|
155
154
|
accessorKey: 'title',
|
|
156
|
-
header:
|
|
157
|
-
cell: ({ row }) => {
|
|
155
|
+
header: m.common_knowledgePublic_bookmarks_columns_website(),
|
|
156
|
+
cell: ({ row }: any) => {
|
|
158
157
|
const b = row.original
|
|
159
158
|
return (
|
|
160
159
|
<div className="flex min-w-[180px] items-center gap-2">
|
|
@@ -173,8 +172,8 @@ function BookmarksPage() {
|
|
|
173
172
|
},
|
|
174
173
|
{
|
|
175
174
|
accessorKey: 'url',
|
|
176
|
-
header:
|
|
177
|
-
cell: ({ row }) => {
|
|
175
|
+
header: m.common_knowledgePublic_bookmarks_columns_url(),
|
|
176
|
+
cell: ({ row }: any) => {
|
|
178
177
|
const url = row.original.url
|
|
179
178
|
return (
|
|
180
179
|
<a
|
|
@@ -191,8 +190,8 @@ function BookmarksPage() {
|
|
|
191
190
|
},
|
|
192
191
|
{
|
|
193
192
|
accessorKey: 'categoryId',
|
|
194
|
-
header:
|
|
195
|
-
cell: ({ row }) =>
|
|
193
|
+
header: m.common_knowledgePublic_bookmarks_columns_category(),
|
|
194
|
+
cell: ({ row }: any) =>
|
|
196
195
|
row.original.categoryId ? (
|
|
197
196
|
<Badge variant="outline" className="font-mono text-xs">
|
|
198
197
|
{row.original.categoryId}
|
|
@@ -204,7 +203,7 @@ function BookmarksPage() {
|
|
|
204
203
|
{
|
|
205
204
|
id: 'github',
|
|
206
205
|
header: 'GitHub',
|
|
207
|
-
cell: ({ row }) => {
|
|
206
|
+
cell: ({ row }: any) => {
|
|
208
207
|
const b = row.original
|
|
209
208
|
if (!b.isGithub) return <span className="text-muted-foreground">-</span>
|
|
210
209
|
return (
|
|
@@ -224,13 +223,13 @@ function BookmarksPage() {
|
|
|
224
223
|
},
|
|
225
224
|
{
|
|
226
225
|
accessorKey: 'tags',
|
|
227
|
-
header:
|
|
228
|
-
cell: ({ row }) => (
|
|
226
|
+
header: m.common_knowledgePublic_bookmarks_columns_tags(),
|
|
227
|
+
cell: ({ row }: any) => (
|
|
229
228
|
<div className="flex max-w-xs flex-wrap gap-1">
|
|
230
229
|
{row.original.tags.length === 0 ? (
|
|
231
230
|
<span className="text-muted-foreground">-</span>
|
|
232
231
|
) : (
|
|
233
|
-
row.original.tags.map((tag) => (
|
|
232
|
+
row.original.tags.map((tag: string) => (
|
|
234
233
|
<Badge key={tag} variant="secondary" className="font-normal">
|
|
235
234
|
{tag}
|
|
236
235
|
</Badge>
|
|
@@ -241,8 +240,8 @@ function BookmarksPage() {
|
|
|
241
240
|
},
|
|
242
241
|
{
|
|
243
242
|
accessorKey: 'createdAt',
|
|
244
|
-
header:
|
|
245
|
-
cell: ({ row }) => (
|
|
243
|
+
header: m.common_knowledgePublic_bookmarks_columns_createdAt(),
|
|
244
|
+
cell: ({ row }: any) => (
|
|
246
245
|
<span className="text-muted-foreground">
|
|
247
246
|
{new Date(row.original.createdAt).toLocaleDateString('zh-CN')}
|
|
248
247
|
</span>
|
|
@@ -251,30 +250,30 @@ function BookmarksPage() {
|
|
|
251
250
|
{
|
|
252
251
|
id: 'actions',
|
|
253
252
|
header: '',
|
|
254
|
-
cell: ({ row }) => (
|
|
253
|
+
cell: ({ row }: any) => (
|
|
255
254
|
<div className="flex items-center gap-1">
|
|
256
255
|
<Button
|
|
257
256
|
variant="ghost"
|
|
258
257
|
size="sm"
|
|
259
|
-
onClick={(e) => {
|
|
258
|
+
onClick={(e: React.MouseEvent) => {
|
|
260
259
|
e.stopPropagation()
|
|
261
260
|
openEdit(row.original)
|
|
262
261
|
}}
|
|
263
262
|
>
|
|
264
263
|
<PencilIcon className="mr-1 size-3.5" />
|
|
265
|
-
{
|
|
264
|
+
{m.common_common_edit()}
|
|
266
265
|
</Button>
|
|
267
266
|
<Button
|
|
268
267
|
variant="ghost"
|
|
269
268
|
size="sm"
|
|
270
269
|
className="text-destructive hover:text-destructive"
|
|
271
|
-
onClick={(e) => {
|
|
270
|
+
onClick={(e: React.MouseEvent) => {
|
|
272
271
|
e.stopPropagation()
|
|
273
272
|
setDeleting(row.original)
|
|
274
273
|
}}
|
|
275
274
|
>
|
|
276
275
|
<Trash2Icon className="mr-1 size-3.5" />
|
|
277
|
-
{
|
|
276
|
+
{m.common_common_delete()}
|
|
278
277
|
</Button>
|
|
279
278
|
</div>
|
|
280
279
|
),
|
|
@@ -285,17 +284,17 @@ function BookmarksPage() {
|
|
|
285
284
|
<div className="space-y-4 p-6">
|
|
286
285
|
<div className="flex items-center justify-between">
|
|
287
286
|
<div>
|
|
288
|
-
<h2 className="text-xl font-bold">{
|
|
289
|
-
<p className="text-sm text-muted-foreground">{
|
|
287
|
+
<h2 className="text-xl font-bold">{m.common_knowledgePublic_bookmarks_title()}</h2>
|
|
288
|
+
<p className="text-sm text-muted-foreground">{m.common_knowledgePublic_bookmarks_subtitle({ total })}</p>
|
|
290
289
|
</div>
|
|
291
290
|
<div className="flex items-center gap-2">
|
|
292
291
|
<Button variant="outline" onClick={syncAllGithub} disabled={syncing}>
|
|
293
292
|
<RefreshCwIcon className={`mr-1 size-4 ${syncing ? 'animate-spin' : ''}`} />
|
|
294
|
-
{syncing ?
|
|
293
|
+
{syncing ? m.common_knowledgePublic_bookmarks_syncing() : m.common_knowledgePublic_bookmarks_syncGithub()}
|
|
295
294
|
</Button>
|
|
296
295
|
<Button onClick={openCreate}>
|
|
297
296
|
<PlusIcon className="mr-1 size-4" />
|
|
298
|
-
{
|
|
297
|
+
{m.common_common_create()}
|
|
299
298
|
</Button>
|
|
300
299
|
</div>
|
|
301
300
|
</div>
|
|
@@ -305,16 +304,16 @@ function BookmarksPage() {
|
|
|
305
304
|
<SearchIcon className="absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
306
305
|
<Input
|
|
307
306
|
value={searchInput}
|
|
308
|
-
onChange={(e) => setSearchInput(e.target.value)}
|
|
309
|
-
onKeyDown={(e) => {
|
|
307
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchInput(e.target.value)}
|
|
308
|
+
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
310
309
|
if (e.key === 'Enter') applySearch()
|
|
311
310
|
}}
|
|
312
|
-
placeholder={
|
|
311
|
+
placeholder={m.common_knowledgePublic_bookmarks_placeholder()}
|
|
313
312
|
className="pl-8"
|
|
314
313
|
/>
|
|
315
314
|
</div>
|
|
316
315
|
<Button variant="outline" onClick={applySearch}>
|
|
317
|
-
{
|
|
316
|
+
{m.common_common_search()}
|
|
318
317
|
</Button>
|
|
319
318
|
</div>
|
|
320
319
|
|
|
@@ -327,25 +326,25 @@ function BookmarksPage() {
|
|
|
327
326
|
onSuccess={refresh}
|
|
328
327
|
/>
|
|
329
328
|
|
|
330
|
-
<AlertDialog open={!!deleting} onOpenChange={(o) => !o && setDeleting(null)}>
|
|
329
|
+
<AlertDialog open={!!deleting} onOpenChange={(o: boolean) => !o && setDeleting(null)}>
|
|
331
330
|
<AlertDialogContent>
|
|
332
331
|
<AlertDialogHeader>
|
|
333
|
-
<AlertDialogTitle>{
|
|
332
|
+
<AlertDialogTitle>{m.common_knowledgePublic_bookmarks_deleteConfirmTitle()}</AlertDialogTitle>
|
|
334
333
|
<AlertDialogDescription>
|
|
335
|
-
{
|
|
334
|
+
{m.common_knowledgePublic_bookmarks_deleteConfirmDesc({ title: deleting?.title ?? '' })}
|
|
336
335
|
</AlertDialogDescription>
|
|
337
336
|
</AlertDialogHeader>
|
|
338
337
|
<AlertDialogFooter>
|
|
339
|
-
<AlertDialogCancel disabled={deletePending}>{
|
|
338
|
+
<AlertDialogCancel disabled={deletePending}>{m.common_common_cancel()}</AlertDialogCancel>
|
|
340
339
|
<AlertDialogAction
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
340
|
+
onClick={(e: React.MouseEvent) => {
|
|
341
|
+
e.preventDefault()
|
|
342
|
+
confirmDelete()
|
|
343
|
+
}}
|
|
344
|
+
disabled={deletePending}
|
|
346
345
|
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
347
346
|
>
|
|
348
|
-
{deletePending ?
|
|
347
|
+
{deletePending ? m.common_common_deleting() : m.common_common_delete()}
|
|
349
348
|
</AlertDialogAction>
|
|
350
349
|
</AlertDialogFooter>
|
|
351
350
|
</AlertDialogContent>
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
18
|
import { createLazyFileRoute, useNavigate, useRouter } from '@tanstack/react-router'
|
|
19
|
+
import { m } from '@/paraglide/messages.js'
|
|
19
20
|
import { useState, useTransition } from 'react'
|
|
20
|
-
import { useTranslation } from 'react-i18next'
|
|
21
21
|
import { PlusIcon, PencilIcon, Trash2Icon, SearchIcon } from 'lucide-react'
|
|
22
22
|
import { DataTable, type AdminColumnDef } from '@/components/data-table/data-table'
|
|
23
23
|
import { Button } from '@/components/ui/button'
|
|
@@ -50,7 +50,6 @@ export const Route = createLazyFileRoute('/_nav/knowledge-public/compliance')({
|
|
|
50
50
|
})
|
|
51
51
|
|
|
52
52
|
function CompliancePage() {
|
|
53
|
-
const { t } = useTranslation('common')
|
|
54
53
|
const { items: rawItems, total } = Route.useLoaderData()
|
|
55
54
|
const items = rawItems as unknown as ComplianceRow[]
|
|
56
55
|
const { search } = Route.useSearch()
|
|
@@ -87,11 +86,11 @@ function CompliancePage() {
|
|
|
87
86
|
startDelete(async () => {
|
|
88
87
|
try {
|
|
89
88
|
await adminDeleteComplianceFn({ data: { id: deleting.id } })
|
|
90
|
-
toast.success(
|
|
89
|
+
toast.success(m.common_knowledgePublic_compliance_deleted())
|
|
91
90
|
setDeleting(null)
|
|
92
91
|
refresh()
|
|
93
92
|
} catch (err) {
|
|
94
|
-
toast.error(err instanceof Error ? err.message :
|
|
93
|
+
toast.error(err instanceof Error ? err.message : m.common_common_deleteFailed())
|
|
95
94
|
}
|
|
96
95
|
})
|
|
97
96
|
}
|
|
@@ -99,20 +98,20 @@ function CompliancePage() {
|
|
|
99
98
|
const columns: AdminColumnDef<ComplianceRow>[] = [
|
|
100
99
|
{
|
|
101
100
|
accessorKey: 'title',
|
|
102
|
-
header:
|
|
103
|
-
cell: ({ row }) => <span className="font-medium">{row.original.title}</span>,
|
|
101
|
+
header: m.common_knowledgePublic_compliance_columns_title(),
|
|
102
|
+
cell: ({ row }: any) => <span className="font-medium">{row.original.title}</span>,
|
|
104
103
|
},
|
|
105
104
|
{
|
|
106
105
|
accessorKey: 'industry',
|
|
107
|
-
header:
|
|
108
|
-
cell: ({ row }) => (
|
|
106
|
+
header: m.common_knowledgePublic_compliance_columns_industry(),
|
|
107
|
+
cell: ({ row }: any) => (
|
|
109
108
|
<Badge variant="outline">{row.original.industry}</Badge>
|
|
110
109
|
),
|
|
111
110
|
},
|
|
112
111
|
{
|
|
113
112
|
accessorKey: 'regulatoryBody',
|
|
114
|
-
header:
|
|
115
|
-
cell: ({ row }) => (
|
|
113
|
+
header: m.common_knowledgePublic_compliance_columns_regulatoryBody(),
|
|
114
|
+
cell: ({ row }: any) => (
|
|
116
115
|
<span className="text-muted-foreground">
|
|
117
116
|
{row.original.regulatoryBody ?? '-'}
|
|
118
117
|
</span>
|
|
@@ -120,13 +119,13 @@ function CompliancePage() {
|
|
|
120
119
|
},
|
|
121
120
|
{
|
|
122
121
|
accessorKey: 'tags',
|
|
123
|
-
header:
|
|
124
|
-
cell: ({ row }) => (
|
|
122
|
+
header: m.common_knowledgePublic_compliance_columns_tags(),
|
|
123
|
+
cell: ({ row }: any) => (
|
|
125
124
|
<div className="flex max-w-xs flex-wrap gap-1">
|
|
126
125
|
{row.original.tags.length === 0 ? (
|
|
127
126
|
<span className="text-muted-foreground">-</span>
|
|
128
127
|
) : (
|
|
129
|
-
row.original.tags.map((tag) => (
|
|
128
|
+
row.original.tags.map((tag: string) => (
|
|
130
129
|
<Badge key={tag} variant="secondary" className="font-normal">
|
|
131
130
|
{tag}
|
|
132
131
|
</Badge>
|
|
@@ -137,8 +136,8 @@ function CompliancePage() {
|
|
|
137
136
|
},
|
|
138
137
|
{
|
|
139
138
|
accessorKey: 'createdAt',
|
|
140
|
-
header:
|
|
141
|
-
cell: ({ row }) => (
|
|
139
|
+
header: m.common_knowledgePublic_compliance_columns_createdAt(),
|
|
140
|
+
cell: ({ row }: any) => (
|
|
142
141
|
<span className="text-muted-foreground">
|
|
143
142
|
{new Date(row.original.createdAt).toLocaleDateString('zh-CN')}
|
|
144
143
|
</span>
|
|
@@ -147,30 +146,30 @@ function CompliancePage() {
|
|
|
147
146
|
{
|
|
148
147
|
id: 'actions',
|
|
149
148
|
header: '',
|
|
150
|
-
cell: ({ row }) => (
|
|
149
|
+
cell: ({ row }: any) => (
|
|
151
150
|
<div className="flex items-center gap-1">
|
|
152
151
|
<Button
|
|
153
152
|
variant="ghost"
|
|
154
153
|
size="sm"
|
|
155
|
-
onClick={(e) => {
|
|
154
|
+
onClick={(e: React.MouseEvent) => {
|
|
156
155
|
e.stopPropagation()
|
|
157
156
|
openEdit(row.original)
|
|
158
157
|
}}
|
|
159
158
|
>
|
|
160
159
|
<PencilIcon className="mr-1 size-3.5" />
|
|
161
|
-
{
|
|
160
|
+
{m.common_common_edit()}
|
|
162
161
|
</Button>
|
|
163
162
|
<Button
|
|
164
163
|
variant="ghost"
|
|
165
164
|
size="sm"
|
|
166
165
|
className="text-destructive hover:text-destructive"
|
|
167
|
-
onClick={(e) => {
|
|
166
|
+
onClick={(e: React.MouseEvent) => {
|
|
168
167
|
e.stopPropagation()
|
|
169
168
|
setDeleting(row.original)
|
|
170
169
|
}}
|
|
171
170
|
>
|
|
172
171
|
<Trash2Icon className="mr-1 size-3.5" />
|
|
173
|
-
{
|
|
172
|
+
{m.common_common_delete()}
|
|
174
173
|
</Button>
|
|
175
174
|
</div>
|
|
176
175
|
),
|
|
@@ -181,12 +180,12 @@ function CompliancePage() {
|
|
|
181
180
|
<div className="space-y-4 p-6">
|
|
182
181
|
<div className="flex items-center justify-between">
|
|
183
182
|
<div>
|
|
184
|
-
<h2 className="text-xl font-bold">{
|
|
185
|
-
<p className="text-sm text-muted-foreground">{
|
|
183
|
+
<h2 className="text-xl font-bold">{m.common_knowledgePublic_compliance_title()}</h2>
|
|
184
|
+
<p className="text-sm text-muted-foreground">{m.common_knowledgePublic_compliance_subtitle({ total })}</p>
|
|
186
185
|
</div>
|
|
187
186
|
<Button onClick={openCreate}>
|
|
188
187
|
<PlusIcon className="mr-1 size-4" />
|
|
189
|
-
{
|
|
188
|
+
{m.common_common_create()}
|
|
190
189
|
</Button>
|
|
191
190
|
</div>
|
|
192
191
|
|
|
@@ -195,16 +194,16 @@ function CompliancePage() {
|
|
|
195
194
|
<SearchIcon className="absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground" />
|
|
196
195
|
<Input
|
|
197
196
|
value={searchInput}
|
|
198
|
-
onChange={(e) => setSearchInput(e.target.value)}
|
|
199
|
-
onKeyDown={(e) => {
|
|
197
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchInput(e.target.value)}
|
|
198
|
+
onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
|
|
200
199
|
if (e.key === 'Enter') applySearch()
|
|
201
200
|
}}
|
|
202
|
-
placeholder={
|
|
201
|
+
placeholder={m.common_knowledgePublic_compliance_placeholder()}
|
|
203
202
|
className="pl-8"
|
|
204
203
|
/>
|
|
205
204
|
</div>
|
|
206
205
|
<Button variant="outline" onClick={applySearch}>
|
|
207
|
-
{
|
|
206
|
+
{m.common_common_search()}
|
|
208
207
|
</Button>
|
|
209
208
|
</div>
|
|
210
209
|
|
|
@@ -217,25 +216,25 @@ function CompliancePage() {
|
|
|
217
216
|
onSuccess={refresh}
|
|
218
217
|
/>
|
|
219
218
|
|
|
220
|
-
<AlertDialog open={!!deleting} onOpenChange={(o) => !o && setDeleting(null)}>
|
|
219
|
+
<AlertDialog open={!!deleting} onOpenChange={(o: boolean) => !o && setDeleting(null)}>
|
|
221
220
|
<AlertDialogContent>
|
|
222
221
|
<AlertDialogHeader>
|
|
223
|
-
<AlertDialogTitle>{
|
|
222
|
+
<AlertDialogTitle>{m.common_knowledgePublic_compliance_deleteConfirmTitle()}</AlertDialogTitle>
|
|
224
223
|
<AlertDialogDescription>
|
|
225
|
-
{
|
|
224
|
+
{m.common_knowledgePublic_compliance_deleteConfirmDesc({ title: deleting?.title ?? '' })}
|
|
226
225
|
</AlertDialogDescription>
|
|
227
226
|
</AlertDialogHeader>
|
|
228
227
|
<AlertDialogFooter>
|
|
229
|
-
<AlertDialogCancel disabled={deletePending}>{
|
|
228
|
+
<AlertDialogCancel disabled={deletePending}>{m.common_common_cancel()}</AlertDialogCancel>
|
|
230
229
|
<AlertDialogAction
|
|
231
|
-
onClick={(e) => {
|
|
230
|
+
onClick={(e: React.MouseEvent) => {
|
|
232
231
|
e.preventDefault()
|
|
233
232
|
confirmDelete()
|
|
234
233
|
}}
|
|
235
234
|
disabled={deletePending}
|
|
236
235
|
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
|
237
236
|
>
|
|
238
|
-
{deletePending ?
|
|
237
|
+
{deletePending ? m.common_common_deleting() : m.common_common_delete()}
|
|
239
238
|
</AlertDialogAction>
|
|
240
239
|
</AlertDialogFooter>
|
|
241
240
|
</AlertDialogContent>
|