@allbluecn/admin-app 0.3.4 → 0.3.6

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.
Files changed (140) hide show
  1. package/package.json +15 -15
  2. package/src/components/__tests__/user-avatar.test.tsx +39 -0
  3. package/src/components/admin/admin-user-menu.tsx +6 -6
  4. package/src/components/admin/developer-log.tsx +7 -7
  5. package/src/components/ai-memory/memory-facts-panel.tsx +9 -9
  6. package/src/components/ai-prompts/preview-panel.tsx +1 -1
  7. package/src/components/ai-prompts/prompt-editor.tsx +8 -8
  8. package/src/components/ai-prompts/prompt-table.tsx +6 -6
  9. package/src/components/ai-prompts/section-editor.tsx +3 -3
  10. package/src/components/ai-prompts/variable-panel.tsx +2 -2
  11. package/src/components/ai-prompts/version-history.tsx +5 -5
  12. package/src/components/ai-provider/model-list-editor.tsx +2 -2
  13. package/src/components/ai-provider/provider-form.tsx +7 -7
  14. package/src/components/ai-provider/provider-table.tsx +6 -6
  15. package/src/components/auth/admin-login-form.tsx +8 -8
  16. package/src/components/auth/icon-input.tsx +2 -2
  17. package/src/components/auth/password-input.tsx +2 -2
  18. package/src/components/component/component-form-dialog.tsx +8 -8
  19. package/src/components/component/component-import-dialog.tsx +6 -6
  20. package/src/components/component/component-table.tsx +3 -3
  21. package/{allblue-ui/src → src}/components/confirm-dialog.tsx +2 -2
  22. package/src/components/dependency/changelog-dialog.tsx +2 -2
  23. package/src/components/dependency/columns.tsx +3 -3
  24. package/src/components/dependency/dependency-table.tsx +7 -7
  25. package/src/components/dependency/edit-dialog.tsx +8 -8
  26. package/src/components/invitations/invitations-page.tsx +13 -13
  27. package/src/components/{knowledge-public → knowledge/public}/bookmark-form-dialog.tsx +10 -10
  28. package/src/components/{knowledge-public → knowledge/public}/compliance-form-dialog.tsx +10 -10
  29. package/src/components/{knowledge-public → knowledge/public}/legal-form-dialog.tsx +11 -11
  30. package/src/components/layout/sidebar-02/app-sidebar.tsx +1 -1
  31. package/src/components/layout/sidebar-02/index.tsx +1 -1
  32. package/src/components/layout/sidebar-02/nav-main.tsx +2 -2
  33. package/src/components/layout/sidebar-02/nav-notifications.tsx +3 -3
  34. package/src/components/market/columns.tsx +4 -4
  35. package/src/components/market/market-app-form.tsx +6 -6
  36. package/src/components/market/market-app-list.tsx +4 -4
  37. package/src/components/monitoring/error-list.tsx +1 -1
  38. package/src/components/monitoring/metrics-stats.tsx +1 -1
  39. package/src/components/monitoring/request-log-table.tsx +1 -1
  40. package/src/components/oauth-providers/provider-page.tsx +9 -9
  41. package/src/components/permissions/assign-dialog.tsx +5 -5
  42. package/src/components/permissions/create-role-dialog.tsx +6 -6
  43. package/{allblue-ui/src → src/components}/ui/checkbox.tsx +4 -4
  44. package/{allblue-ui/src → src/components}/ui/sidebar.tsx +1 -1
  45. package/src/components/user/columns.tsx +5 -5
  46. package/src/components/user/settings-activity-log.tsx +7 -7
  47. package/src/components/user/settings-profile/avatar-uploader.tsx +2 -2
  48. package/src/components/user/settings-profile/social-links.tsx +2 -2
  49. package/src/components/user/settings-profile.tsx +6 -6
  50. package/src/components/user/user-create-dialog.tsx +6 -6
  51. package/src/components/user/user-detail/error-boundary.tsx +1 -1
  52. package/src/components/user/user-detail/user-detail-dialogs.tsx +6 -6
  53. package/src/components/user/user-filters.tsx +3 -3
  54. package/{allblue-ui/src → src}/components/user-avatar.tsx +7 -4
  55. package/src/lib/__tests__/avatar-shape.test.ts +44 -0
  56. package/src/lib/auth.config.ts +1 -1
  57. package/{allblue-ui/src/lib/avatar.ts → src/lib/avatar-shape.ts} +15 -21
  58. package/src/providers/index.tsx +1 -1
  59. package/src/routes/__root.tsx +1 -1
  60. package/src/routes/_nav/audit/route.lazy.tsx +1 -1
  61. package/src/routes/_nav/compliance/route.lazy.tsx +3 -3
  62. package/src/routes/_nav/components/route.lazy.tsx +4 -4
  63. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +16 -16
  64. package/src/routes/_nav/knowledge-public/bookmarks/route.tsx +1 -1
  65. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +14 -14
  66. package/src/routes/_nav/knowledge-public/compliance/route.tsx +1 -1
  67. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +14 -14
  68. package/src/routes/_nav/knowledge-public/legal/route.tsx +1 -1
  69. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +3 -3
  70. package/src/routes/_nav/licenses/new/route.lazy.tsx +5 -5
  71. package/src/routes/_nav/licenses/route.lazy.tsx +1 -1
  72. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +2 -2
  73. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +1 -1
  74. package/src/routes/_nav/monitoring/health/route.lazy.tsx +3 -3
  75. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +3 -3
  76. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +3 -3
  77. package/src/routes/_nav/monitoring/route.lazy.tsx +2 -2
  78. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +1 -1
  79. package/src/routes/_nav/permissions/route.lazy.tsx +4 -4
  80. package/src/routes/_nav/sso/route.lazy.tsx +2 -2
  81. package/src/routes/_nav/users/$userId/route.lazy.tsx +9 -9
  82. package/src/routes/_nav/users/-components/users-table.tsx +1 -1
  83. package/src/routes/_nav/users/route.lazy.tsx +1 -1
  84. package/src/routes/login/route.lazy.tsx +1 -1
  85. package/src/routes/setup/route.lazy.tsx +2 -2
  86. package/src/server/dependency/helpers.ts +0 -1
  87. package/src/server/{knowledge-public → knowledge/public}/github-sync.ts +12 -2
  88. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/create.ts +1 -1
  89. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/list.ts +2 -1
  90. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/sync-all-github.ts +3 -2
  91. package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/update.ts +3 -2
  92. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/create.ts +1 -1
  93. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/list.ts +2 -1
  94. package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/update.ts +3 -2
  95. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/create.ts +1 -1
  96. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/list.ts +2 -1
  97. package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/update.ts +3 -2
  98. package/src/styles/globals.css +3 -3
  99. package/allblue-ui/package.json +0 -6
  100. package/allblue-ui/src/components/infinite-scroll-sentinel.tsx +0 -37
  101. package/allblue-ui/src/hooks/use-load-more.ts +0 -57
  102. package/allblue-ui/src/index.ts +0 -31
  103. package/allblue-ui/src/lib/utils.ts +0 -1
  104. /package/{allblue-ui/src → src/components}/data-table/data-table-pagination.tsx +0 -0
  105. /package/{allblue-ui/src → src/components}/data-table/data-table.tsx +0 -0
  106. /package/{allblue-ui/src → src/components}/data-table/table-detail-layout.tsx +0 -0
  107. /package/{allblue-ui/src → src}/components/notion-avatar.tsx +0 -0
  108. /package/{allblue-ui/src → src/components}/ui/alert-dialog.tsx +0 -0
  109. /package/{allblue-ui/src → src/components}/ui/alert.tsx +0 -0
  110. /package/{allblue-ui/src → src/components}/ui/avatar.tsx +0 -0
  111. /package/{allblue-ui/src → src/components}/ui/badge.tsx +0 -0
  112. /package/{allblue-ui/src → src/components}/ui/button.tsx +0 -0
  113. /package/{allblue-ui/src → src/components}/ui/card.tsx +0 -0
  114. /package/{allblue-ui/src → src/components}/ui/collapsible.tsx +0 -0
  115. /package/{allblue-ui/src → src/components}/ui/dialog.tsx +0 -0
  116. /package/{allblue-ui/src → src/components}/ui/dropdown-menu.tsx +0 -0
  117. /package/{allblue-ui/src → src/components}/ui/field.tsx +0 -0
  118. /package/{allblue-ui/src → src/components}/ui/input-group.tsx +0 -0
  119. /package/{allblue-ui/src → src/components}/ui/input.tsx +0 -0
  120. /package/{allblue-ui/src → src/components}/ui/label.tsx +0 -0
  121. /package/{allblue-ui/src → src/components}/ui/pagination.tsx +0 -0
  122. /package/{allblue-ui/src → src/components}/ui/select.tsx +0 -0
  123. /package/{allblue-ui/src → src/components}/ui/separator.tsx +0 -0
  124. /package/{allblue-ui/src → src/components}/ui/sheet.tsx +0 -0
  125. /package/{allblue-ui/src → src/components}/ui/skeleton.tsx +0 -0
  126. /package/{allblue-ui/src → src/components}/ui/switch.tsx +0 -0
  127. /package/{allblue-ui/src → src/components}/ui/table.tsx +0 -0
  128. /package/{allblue-ui/src → src/components}/ui/textarea.tsx +0 -0
  129. /package/{allblue-ui/src → src/components}/ui/toast.tsx +0 -0
  130. /package/{allblue-ui/src → src/components}/ui/tooltip.tsx +0 -0
  131. /package/{allblue-ui/src → src}/hooks/use-mobile.ts +0 -0
  132. /package/{allblue-ui/src → src}/lib/datetime.ts +0 -0
  133. /package/{allblue-ui/src → src}/lib/sanitize.ts +0 -0
  134. /package/src/server/{knowledge-public → knowledge/public}/canonical-id.ts +0 -0
  135. /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/delete.ts +0 -0
  136. /package/src/server/serverFns/{knowledge-public → knowledge/public}/bookmarks/detail.ts +0 -0
  137. /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/delete.ts +0 -0
  138. /package/src/server/serverFns/{knowledge-public → knowledge/public}/compliance/detail.ts +0 -0
  139. /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/delete.ts +0 -0
  140. /package/src/server/serverFns/{knowledge-public → knowledge/public}/legal/detail.ts +0 -0
@@ -18,14 +18,14 @@
18
18
  import { createLazyFileRoute } from '@tanstack/react-router'
19
19
  import { m } from '@/paraglide/messages.js'
20
20
  import { useState, useEffect, useRef } from 'react'
21
- import { formatTimestamp } from '@allbluecn/ui/lib/datetime'
21
+ import { formatTimestamp } from '@/lib/datetime'
22
22
  import { HeartPulse, Play, Square, RefreshCw } from 'lucide-react'
23
23
  import { PageHeader } from '@/components/common/page-header'
24
24
  import { HealthCards } from '@/components/monitoring/health-cards'
25
- import { DataTable } from '@allbluecn/ui/data-table'
25
+ import { DataTable } from '@/components/data-table/data-table'
26
26
  import { getHealthStatus } from '@/server/serverFns/monitoring/get-health'
27
27
  import { getHealthCheckSettings, updateHealthCheckSettings } from '@/server/serverFns/monitoring/get-health-settings'
28
- import { toast } from '@allbluecn/ui/toast'
28
+ import { toast } from '@/components/ui/toast'
29
29
  import { jsonify } from '@/lib/loader-serial'
30
30
 
31
31
  export const Route = createLazyFileRoute('/_nav/monitoring/health')({
@@ -21,11 +21,11 @@ import { useState, useEffect, useRef } from 'react'
21
21
  import { Activity, Filter, RefreshCw, Trash2 } from 'lucide-react'
22
22
  import { PageHeader } from '@/components/common/page-header'
23
23
  import { RequestLogTable } from '@/components/monitoring/request-log-table'
24
- import { Checkbox } from '@allbluecn/ui/checkbox'
24
+ import { Checkbox } from '@/components/ui/checkbox'
25
25
  import { getRequestLogs } from '@/server/serverFns/monitoring/get-request-logs'
26
26
  import { resetMonitoring } from '@/server/serverFns/monitoring/reset'
27
- import { DataTablePagination } from '@allbluecn/ui/data-table/pagination'
28
- import { toast } from '@allbluecn/ui/toast'
27
+ import { DataTablePagination } from '@/components/data-table/data-table-pagination'
28
+ import { toast } from '@/components/ui/toast'
29
29
  import { jsonify } from '@/lib/loader-serial'
30
30
  import { RequestLogEntry } from '@/components/monitoring/request-log-table'
31
31
 
@@ -17,7 +17,7 @@
17
17
 
18
18
  import { m } from '@/paraglide/messages.js'
19
19
  import { getBenchmark, getBenchmarkSource, compareDuration } from '@/lib/monitoring-benchmarks'
20
- import { formatTimestamp } from '@allbluecn/ui/lib/datetime'
20
+ import { formatTimestamp } from '@/lib/datetime'
21
21
  import { createLazyFileRoute } from '@tanstack/react-router'
22
22
  import { useState } from 'react'
23
23
  import { BarChart3, RefreshCw, Trash2, MemoryStick } from 'lucide-react'
@@ -27,8 +27,8 @@ import { MetricsStats } from '@/components/monitoring/metrics-stats'
27
27
  import { getMetrics } from '@/server/serverFns/monitoring/get-metrics'
28
28
  import { resetMonitoring } from '@/server/serverFns/monitoring/reset'
29
29
  import { jsonify } from '@/lib/loader-serial'
30
- import { DataTable } from '@allbluecn/ui/data-table'
31
- import { toast } from '@allbluecn/ui/toast'
30
+ import { DataTable } from '@/components/data-table/data-table'
31
+ import { toast } from '@/components/ui/toast'
32
32
 
33
33
  export const Route = createLazyFileRoute('/_nav/monitoring/metrics')({
34
34
  component: MonitoringMetrics,
@@ -17,8 +17,8 @@
17
17
 
18
18
  import { createLazyFileRoute, Link, Outlet, useLocation } from '@tanstack/react-router'
19
19
  import { m } from '@/paraglide/messages.js'
20
- import { SidebarTrigger } from '@allbluecn/ui/sidebar'
21
- import { Separator } from '@allbluecn/ui/separator'
20
+ import { SidebarTrigger } from '@/components/ui/sidebar'
21
+ import { Separator } from '@/components/ui/separator'
22
22
 
23
23
  export const Route = createLazyFileRoute('/_nav/monitoring')({
24
24
  component: MonitoringLayout,
@@ -21,7 +21,7 @@ import * as Sentry from '@sentry/tanstackstart-react'
21
21
  import { BugPlay, ExternalLink, Bug, Activity, Eye, EyeOff, Save, CheckCircle2, XCircle, RefreshCw, ShieldCheck } from 'lucide-react'
22
22
  import { IconBrandSentry } from '@tabler/icons-react';
23
23
  import { useEffect, useState } from 'react'
24
- import { toast } from '@allbluecn/ui/toast'
24
+ import { toast } from '@/components/ui/toast'
25
25
  import { getSentryConfig, saveSentryConfig, reconfigureSentryServer } from '@/server/serverFns/sentry/config'
26
26
  import type { SentryConfig } from '@/server/serverFns/sentry/config'
27
27
 
@@ -2,15 +2,15 @@ import { createLazyFileRoute, Link, useLocation } from '@tanstack/react-router'
2
2
  import { m } from '@/paraglide/messages.js'
3
3
  import { getLocale } from '@/paraglide/runtime.js'
4
4
  import { useServerFn } from '@tanstack/react-start'
5
- import { toast } from '@allbluecn/ui/toast'
5
+ import { toast } from '@/components/ui/toast'
6
6
  import { useEffect, useState } from 'react'
7
7
  import type React from 'react'
8
8
  import {
9
9
  listRolesFn,
10
10
  deleteRoleFn,
11
11
  } from '@/server/serverFns/permissions'
12
- import { Badge } from '@allbluecn/ui/badge'
13
- import { Button } from '@allbluecn/ui/button'
12
+ import { Badge } from '@/components/ui/badge'
13
+ import { Button } from '@/components/ui/button'
14
14
  import {
15
15
  Table,
16
16
  TableBody,
@@ -18,7 +18,7 @@ import {
18
18
  TableHead,
19
19
  TableHeader,
20
20
  TableRow,
21
- } from '@allbluecn/ui/table'
21
+ } from '@/components/ui/table'
22
22
  import { CreateRoleDialog } from '@/components/permissions/create-role-dialog'
23
23
  import { AssignDialog } from '@/components/permissions/assign-dialog'
24
24
  import type { RoleItem } from '@/components/permissions/types'
@@ -18,10 +18,10 @@
18
18
  import { createLazyFileRoute } from '@tanstack/react-router'
19
19
  import { m } from '@/paraglide/messages.js'
20
20
  import { useServerFn } from '@tanstack/react-start'
21
- import { toast } from '@allbluecn/ui/toast'
21
+ import { toast } from '@/components/ui/toast'
22
22
  import type React from 'react'
23
23
  import { deleteSsoProviderFn, toggleSsoProviderFn } from '@/server/serverFns/sso-config'
24
- import { Badge } from '@allbluecn/ui/badge'
24
+ import { Badge } from '@/components/ui/badge'
25
25
 
26
26
  export const Route = createLazyFileRoute('/_nav/sso')({
27
27
  pendingComponent: () => (
@@ -18,17 +18,17 @@
18
18
  import { createLazyFileRoute, useNavigate } from '@tanstack/react-router'
19
19
  import { m } from '@/paraglide/messages.js'
20
20
  import { useState, useTransition } from 'react'
21
- import { formatTimestamp } from '@allbluecn/ui/lib/datetime'
21
+ import { formatTimestamp } from '@/lib/datetime'
22
22
  import { getUserDetailFn } from '@/server/serverFns/user/detail'
23
23
  import { updateUserRoleFn } from '@/server/serverFns/user/update-role'
24
24
  import { updateUserStatusFn } from '@/server/serverFns/user/update-status'
25
25
  import { resetUserPasswordFn } from '@/server/serverFns/user/reset-password'
26
26
  import { deleteUserFn } from '@/server/serverFns/user/delete'
27
- import { TableDetailLayout } from '@allbluecn/ui/data-table/table-detail-layout'
28
- import { Badge } from '@allbluecn/ui/badge'
29
- import { Separator } from '@allbluecn/ui/separator'
30
- import { Button } from '@allbluecn/ui/button'
31
- import { UserAvatar } from '@allbluecn/ui/components/user-avatar'
27
+ import { TableDetailLayout } from '@/components/data-table/table-detail-layout'
28
+ import { Badge } from '@/components/ui/badge'
29
+ import { Separator } from '@/components/ui/separator'
30
+ import { Button } from '@/components/ui/button'
31
+ import { UserAvatar } from '@/components/user-avatar'
32
32
 
33
33
  const STATUS_LABELS: Record<string, () => string> = {
34
34
  active: m['admin-users_status_active'],
@@ -48,7 +48,7 @@ import {
48
48
  ShoppingBagIcon,
49
49
  ShieldCheckIcon,
50
50
  } from 'lucide-react'
51
- import { toast } from '@allbluecn/ui/toast'
51
+ import { toast } from '@/components/ui/toast'
52
52
  import { parseUserAgent, formatParsedUA } from '@allbluecn/kernel'
53
53
  import type { AvatarConfig } from '@allbluecn/kernel'
54
54
  import SettingsActivityLog, {
@@ -61,7 +61,7 @@ import {
61
61
  CardDescription,
62
62
  CardHeader,
63
63
  CardTitle,
64
- } from '@allbluecn/ui/card'
64
+ } from '@/components/ui/card'
65
65
  import { AdminUserErrorBoundary } from '@/components/user/user-detail/error-boundary'
66
66
  import {
67
67
  UserDeleteDialog,
@@ -132,7 +132,7 @@ function UserDetailPage() {
132
132
  avatar={
133
133
  <UserAvatar
134
134
  avatarConfig={user.avatarConfig as AvatarConfig | null}
135
- bgShape={user.bgShape as 'square' | 'rounded' | null}
135
+ bgShape={user.bgShape}
136
136
  bgColor={user.bgColor}
137
137
  name={user.username}
138
138
  size="lg"
@@ -16,7 +16,7 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
 
19
- import { DataTable } from "@allbluecn/ui/data-table"
19
+ import { DataTable } from "@/components/data-table/data-table"
20
20
  import { getUserColumns } from "@/components/user/columns"
21
21
  import type { UserRow } from "@/components/user/columns"
22
22
  import { useNavigate } from "@tanstack/react-router"
@@ -21,7 +21,7 @@ import { useState } from 'react'
21
21
  import { UsersTable } from './-components/users-table'
22
22
  import { UserFilters } from '@/components/user/user-filters'
23
23
  import { UserCreateDialog } from '@/components/user/user-create-dialog'
24
- import { Button } from '@allbluecn/ui/button'
24
+ import { Button } from '@/components/ui/button'
25
25
  import { PlusIcon } from 'lucide-react'
26
26
 
27
27
  export const Route = createLazyFileRoute('/_nav/users')({
@@ -34,7 +34,7 @@ function AdminLoginPage() {
34
34
  name: session.user.name,
35
35
  email: session.user.email,
36
36
  avatarConfig: (session.user as any).avatarConfig as AvatarConfig | undefined,
37
- bgShape: (session.user as any).bgShape as string | undefined,
37
+ bgShape: (session.user as { bgShape?: string | null }).bgShape ?? undefined,
38
38
  bgColor: (session.user as any).bgColor as string | undefined,
39
39
  }
40
40
  : null
@@ -18,14 +18,14 @@
18
18
  import { createLazyFileRoute, useNavigate } from '@tanstack/react-router'
19
19
  import { m } from '@/paraglide/messages.js'
20
20
  import { useState } from 'react'
21
- import { toast } from '@allbluecn/ui/toast'
21
+ import { toast } from '@/components/ui/toast'
22
22
  import { Loader2, ShieldCheck, User, Mail, Database } from 'lucide-react'
23
23
  import { AuthLayout, AuthLayoutLeft, AuthLayoutRight } from '@/components/auth/auth-layout'
24
24
  import { AuthHeader } from '@/components/auth/auth-header'
25
25
  import { AuthBrandPanel } from '@/components/auth/auth-brand-panel'
26
26
  import { PasswordInput } from '@/components/auth/password-input'
27
27
  import { IconInput } from '@/components/auth/icon-input'
28
- import { Button } from '@allbluecn/ui/button'
28
+ import { Button } from '@/components/ui/button'
29
29
  import { setupAdminFn } from '@/server/serverFns/auth/setup'
30
30
 
31
31
  export const Route = createLazyFileRoute('/setup')({
@@ -44,7 +44,6 @@ const PACKAGE_FILES = [
44
44
  "apps/admin/package.json",
45
45
  "packages/database/package.json",
46
46
  "packages/shared/package.json",
47
- "packages/ui/package.json",
48
47
  ]
49
48
 
50
49
  interface ParsedPkgFile {
@@ -24,6 +24,16 @@ export interface GithubData {
24
24
  versionDate: Date | null
25
25
  }
26
26
 
27
+ interface GithubRepoJson {
28
+ stargazers_count?: number
29
+ updated_at?: string
30
+ }
31
+
32
+ interface GithubReleaseJson {
33
+ tag_name?: string
34
+ published_at?: string
35
+ }
36
+
27
37
  const API = 'https://api.github.com'
28
38
  const HEADERS: HeadersInit = {
29
39
  Accept: 'application/vnd.github+json',
@@ -39,14 +49,14 @@ export async function fetchGithubData(
39
49
  ): Promise<GithubData | null> {
40
50
  const repoRes = await fetch(`${API}/repos/${owner}/${repo}`, { headers: HEADERS })
41
51
  if (!repoRes.ok) return null
42
- const repoJson: any = await repoRes.json()
52
+ const repoJson: GithubRepoJson = await repoRes.json()
43
53
 
44
54
  let latestVersion: string | null = null
45
55
  let versionDate: Date | null = null
46
56
  try {
47
57
  const relRes = await fetch(`${API}/repos/${owner}/${repo}/releases/latest`, { headers: HEADERS })
48
58
  if (relRes.ok) {
49
- const relJson: any = await relRes.json()
59
+ const relJson: GithubReleaseJson = await relRes.json()
50
60
  latestVersion = relJson.tag_name ?? null
51
61
  versionDate = relJson.published_at ? new Date(relJson.published_at) : null
52
62
  }
@@ -19,7 +19,7 @@ import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
21
  import { requireAdmin } from '@/server/auth-helpers'
22
- import { bookmarkCanonicalId, parseGithubUrl } from '@/server/knowledge-public/canonical-id'
22
+ import { bookmarkCanonicalId, parseGithubUrl } from '@/server/knowledge/public/canonical-id'
23
23
 
24
24
  const createSchema = z.object({
25
25
  title: z.string().min(1).max(200),
@@ -18,6 +18,7 @@
18
18
  import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
+ import { Prisma } from '@allbluecn/database'
21
22
  import { requireAdmin } from '@/server/auth-helpers'
22
23
 
23
24
  const listSchema = z.object({
@@ -33,7 +34,7 @@ export const adminListBookmarksFn = createServerFn({ method: 'GET' })
33
34
  .handler(async ({ data }) => {
34
35
  const prisma = await getPrisma()
35
36
  await requireAdmin()
36
- const where: any = { visibility: 'public', isDeleted: false }
37
+ const where: Prisma.WebsiteBookmarkWhereInput = { visibility: 'public', isDeleted: false }
37
38
  if (data.search) {
38
39
  where.OR = [
39
40
  { title: { contains: data.search, mode: 'insensitive' } },
@@ -18,8 +18,9 @@
18
18
  import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
+ import { Prisma } from '@allbluecn/database'
21
22
  import { requireAdmin } from '@/server/auth-helpers'
22
- import { syncBookmarkGithub } from '@/server/knowledge-public/github-sync'
23
+ import { syncBookmarkGithub } from '@/server/knowledge/public/github-sync'
23
24
 
24
25
  const syncSchema = z.object({
25
26
  force: z.boolean().default(false),
@@ -30,7 +31,7 @@ export const adminSyncAllGithubFn = createServerFn({ method: 'POST' })
30
31
  .handler(async ({ data }) => {
31
32
  const prisma = await getPrisma()
32
33
  await requireAdmin()
33
- const where: any = { isGithub: true, isDeleted: false }
34
+ const where: Prisma.WebsiteBookmarkWhereInput = { isGithub: true, isDeleted: false }
34
35
  if (!data.force) {
35
36
  const sixHoursAgo = new Date(Date.now() - 6 * 60 * 60 * 1000)
36
37
  where.OR = [
@@ -18,8 +18,9 @@
18
18
  import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
+ import { Prisma } from '@allbluecn/database'
21
22
  import { requireAdmin } from '@/server/auth-helpers'
22
- import { bookmarkCanonicalId, parseGithubUrl } from '@/server/knowledge-public/canonical-id'
23
+ import { bookmarkCanonicalId, parseGithubUrl } from '@/server/knowledge/public/canonical-id'
23
24
 
24
25
  const updateSchema = z.object({
25
26
  id: z.string(),
@@ -38,7 +39,7 @@ export const adminUpdateBookmarkFn = createServerFn({ method: 'POST' })
38
39
  const { id, ...rest } = data
39
40
  const existing = await prisma.websiteBookmark.findUnique({ where: { id } })
40
41
  if (!existing) throw new Error('未找到')
41
- const updateData: any = { ...rest }
42
+ const updateData: Prisma.WebsiteBookmarkUncheckedUpdateInput = { ...rest }
42
43
  const urlChanged = data.url !== undefined && data.url !== existing.url
43
44
  if (urlChanged && data.url) {
44
45
  const gh = parseGithubUrl(data.url)
@@ -19,7 +19,7 @@ import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
21
  import { requireAdmin } from '@/server/auth-helpers'
22
- import { complianceCanonicalId } from '@/server/knowledge-public/canonical-id'
22
+ import { complianceCanonicalId } from '@/server/knowledge/public/canonical-id'
23
23
 
24
24
  const createSchema = z.object({
25
25
  title: z.string().min(1).max(200),
@@ -18,6 +18,7 @@
18
18
  import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
+ import { Prisma } from '@allbluecn/database'
21
22
  import { requireAdmin } from '@/server/auth-helpers'
22
23
 
23
24
  const listSchema = z.object({
@@ -33,7 +34,7 @@ export const adminListComplianceFn = createServerFn({ method: 'GET' })
33
34
  .handler(async ({ data }) => {
34
35
  const prisma = await getPrisma()
35
36
  await requireAdmin()
36
- const where: any = { visibility: 'public', isDeleted: false }
37
+ const where: Prisma.IndustryComplianceWhereInput = { visibility: 'public', isDeleted: false }
37
38
  if (data.search) {
38
39
  where.OR = [
39
40
  { title: { contains: data.search, mode: 'insensitive' } },
@@ -18,8 +18,9 @@
18
18
  import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
+ import { Prisma } from '@allbluecn/database'
21
22
  import { requireAdmin } from '@/server/auth-helpers'
22
- import { complianceCanonicalId } from '@/server/knowledge-public/canonical-id'
23
+ import { complianceCanonicalId } from '@/server/knowledge/public/canonical-id'
23
24
 
24
25
  const updateSchema = z.object({
25
26
  id: z.string(),
@@ -43,7 +44,7 @@ export const adminUpdateComplianceFn = createServerFn({ method: 'POST' })
43
44
  const { id, code, ...rest } = data
44
45
  const existing = await prisma.industryCompliance.findUnique({ where: { id } })
45
46
  if (!existing) throw new Error('未找到')
46
- const updateData: any = { ...rest }
47
+ const updateData: Prisma.IndustryComplianceUncheckedUpdateInput = { ...rest }
47
48
  if (code !== undefined || data.title !== undefined) {
48
49
  updateData.canonicalId = complianceCanonicalId({
49
50
  title: data.title ?? existing.title,
@@ -19,7 +19,7 @@ import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
21
  import { requireAdmin } from '@/server/auth-helpers'
22
- import { legalCanonicalId } from '@/server/knowledge-public/canonical-id'
22
+ import { legalCanonicalId } from '@/server/knowledge/public/canonical-id'
23
23
 
24
24
  const createSchema = z.object({
25
25
  title: z.string().min(1).max(200),
@@ -18,6 +18,7 @@
18
18
  import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
+ import { Prisma } from '@allbluecn/database'
21
22
  import { requireAdmin } from '@/server/auth-helpers'
22
23
 
23
24
  const listSchema = z.object({
@@ -33,7 +34,7 @@ export const adminListLegalFn = createServerFn({ method: 'GET' })
33
34
  .handler(async ({ data }) => {
34
35
  const prisma = await getPrisma()
35
36
  await requireAdmin()
36
- const where: any = { visibility: 'public', isDeleted: false }
37
+ const where: Prisma.LegalRegulationWhereInput = { visibility: 'public', isDeleted: false }
37
38
  if (data.search) {
38
39
  where.OR = [
39
40
  { title: { contains: data.search, mode: 'insensitive' } },
@@ -18,8 +18,9 @@
18
18
  import { createServerFn } from '@tanstack/react-start'
19
19
  import { z } from 'zod'
20
20
  import { getPrisma } from '@allbluecn/database/get-prisma'
21
+ import { Prisma } from '@allbluecn/database'
21
22
  import { requireAdmin } from '@/server/auth-helpers'
22
- import { legalCanonicalId } from '@/server/knowledge-public/canonical-id'
23
+ import { legalCanonicalId } from '@/server/knowledge/public/canonical-id'
23
24
 
24
25
  const updateSchema = z.object({
25
26
  id: z.string(),
@@ -45,7 +46,7 @@ export const adminUpdateLegalFn = createServerFn({ method: 'POST' })
45
46
  const { id, code, ...rest } = data
46
47
  const existing = await prisma.legalRegulation.findUnique({ where: { id } })
47
48
  if (!existing) throw new Error('未找到')
48
- const updateData: any = { ...rest }
49
+ const updateData: Prisma.LegalRegulationUncheckedUpdateInput = { ...rest }
49
50
  if (code !== undefined || data.title !== undefined) {
50
51
  updateData.canonicalId = legalCanonicalId({
51
52
  title: data.title ?? existing.title,
@@ -3,9 +3,9 @@
3
3
 
4
4
  @import "tailwindcss";
5
5
 
6
- /* 共享 UI 包源码类名扫描(Tailwind v4 自动探测不覆盖 workspace 包,
7
- 缺失则 @allbluecn/ui 内组件的全部工具类不生成) */
8
- @source "../../../../packages/ui/src/**/*.{ts,tsx}";
6
+ /* src 源码类名扫描(含 components/ui 内联组件,
7
+ Tailwind v4 自动探测不覆盖的路径由此显式声明) */
8
+ @source "../";
9
9
 
10
10
  @import "tw-animate-css";
11
11
 
@@ -1,6 +0,0 @@
1
- {
2
- "name": "@allbluecn/ui-bundled",
3
- "version": "0.1.0",
4
- "private": true,
5
- "type": "module"
6
- }
@@ -1,37 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
-
5
- import { useLoadMore } from "../hooks/use-load-more"
6
-
7
- interface InfiniteScrollSentinelProps {
8
- onLoadMore: () => void | Promise<void>
9
- hasMore: boolean
10
- rootRef?: React.RefObject<HTMLElement | null>
11
- /** 全部加载完后的提示文案(调用方传入,组件内不做 i18n) */
12
- loadedAllLabel: string
13
- }
14
-
15
- /**
16
- * 无限滚动哨兵:滚动到底部附近触发 onLoadMore,展示三点脉冲 loading 与
17
- * 「已全部加载」提示。加载状态机见 useLoadMore。
18
- */
19
- export function InfiniteScrollSentinel({ onLoadMore, hasMore, rootRef, loadedAllLabel }: InfiniteScrollSentinelProps) {
20
- const { sentinelRef, loading } = useLoadMore(onLoadMore, hasMore, rootRef)
21
-
22
- return (
23
- <div className="flex h-7 items-center justify-center">
24
- <div ref={sentinelRef} className="h-1" />
25
- {loading && (
26
- <div className="flex items-center gap-1">
27
- <div className="h-1.5 w-1.5 animate-pulse rounded-full bg-primary/60" />
28
- <div className="h-1.5 w-1.5 animate-pulse rounded-full bg-primary/60 delay-75" />
29
- <div className="h-1.5 w-1.5 animate-pulse rounded-full bg-primary/60 delay-150" />
30
- </div>
31
- )}
32
- {!loading && !hasMore && (
33
- <span className="text-xs text-muted-foreground">{loadedAllLabel}</span>
34
- )}
35
- </div>
36
- )
37
- }
@@ -1,57 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
-
5
- import { useEffect, useRef, useState } from "react";
6
-
7
- /**
8
- * 无限滚动加载状态机:IntersectionObserver 哨兵 + loading 防重入。
9
- *
10
- * 哨兵进入视口且 hasMore 时触发 onLoadMore;返回 Promise 时 resolve 后解除
11
- * loading,同步返回则由调用方经 hasMore/数据更新间接解除。供
12
- * InfiniteScrollSentinel 等无限滚动组件复用。
13
- */
14
- export function useLoadMore(
15
- onLoadMore: () => void | Promise<void>,
16
- hasMore: boolean,
17
- rootRef?: React.RefObject<HTMLElement | null>,
18
- ): {
19
- /** 挂到滚动末端哨兵元素上 */
20
- sentinelRef: React.RefObject<HTMLDivElement | null>;
21
- loading: boolean;
22
- } {
23
- const sentinelRef = useRef<HTMLDivElement>(null);
24
- const observerRef = useRef<IntersectionObserver | null>(null);
25
- const [loading, setLoading] = useState(false);
26
- const loadingRef = useRef(false);
27
-
28
- useEffect(() => {
29
- loadingRef.current = loading;
30
- }, [loading]);
31
-
32
- useEffect(() => {
33
- if (!sentinelRef.current || !hasMore) return;
34
-
35
- if (observerRef.current) observerRef.current.disconnect();
36
-
37
- const observer = new IntersectionObserver(
38
- (entries) => {
39
- if (entries[0]?.isIntersecting && !loadingRef.current) {
40
- setLoading(true);
41
- const result = onLoadMore();
42
- if (result && typeof (result as Promise<void>).then === "function") {
43
- (result as Promise<void>).then(() => setLoading(false));
44
- }
45
- }
46
- },
47
- { root: rootRef?.current ?? null, rootMargin: "80px" },
48
- );
49
-
50
- observer.observe(sentinelRef.current);
51
- observerRef.current = observer;
52
- return () => observer.disconnect();
53
- // onLoadMore 由调用方保证稳定(多为 useCallback),与原实现一致仅依赖 hasMore/rootRef
54
- }, [hasMore, rootRef]);
55
-
56
- return { sentinelRef, loading };
57
- }
@@ -1,31 +0,0 @@
1
- export * from "./ui/alert"
2
- export * from "./ui/alert-dialog"
3
- export * from "./ui/avatar"
4
- export * from "./ui/badge"
5
- export * from "./ui/button"
6
- export * from "./ui/card"
7
- export * from "./ui/checkbox"
8
- export * from "./ui/collapsible"
9
- export * from "./ui/dialog"
10
- export * from "./ui/dropdown-menu"
11
- export * from "./ui/field"
12
- export * from "./ui/input"
13
- export * from "./ui/input-group"
14
- export * from "./ui/label"
15
- export * from "./ui/pagination"
16
- export * from "./ui/select"
17
- export * from "./ui/separator"
18
- export * from "./ui/sheet"
19
- export * from "./ui/sidebar"
20
- export * from "./ui/skeleton"
21
- export * from "./ui/switch"
22
- export * from "./ui/table"
23
- export * from "./ui/textarea"
24
- export * from "./ui/toast"
25
- export * from "./ui/tooltip"
26
- export { ConfirmDialog, type ConfirmDialogProps } from "./components/confirm-dialog"
27
- export { InfiniteScrollSentinel } from "./components/infinite-scroll-sentinel"
28
- export { useLoadMore } from "./hooks/use-load-more"
29
- export { useIsMobile } from "./hooks/use-mobile"
30
- export { getBoringAvatarUrl, getAvatarFallback, type AvatarOptions } from "./lib/avatar"
31
- export { cn } from "./lib/utils"
@@ -1 +0,0 @@
1
- export { cn } from "cn"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes