@allbluecn/admin-app 0.3.2 → 0.3.3

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 (198) hide show
  1. package/package.json +19 -17
  2. package/src/components/admin/admin-user-menu.tsx +4 -4
  3. package/src/components/admin/developer-log.tsx +16 -32
  4. package/src/components/ai-memory/memory-facts-panel.tsx +30 -70
  5. package/src/components/ai-prompts/preview-panel.tsx +1 -1
  6. package/src/components/ai-prompts/prompt-editor.tsx +8 -9
  7. package/src/components/ai-prompts/prompt-table.tsx +6 -6
  8. package/src/components/ai-prompts/section-editor.tsx +3 -3
  9. package/src/components/ai-prompts/variable-panel.tsx +2 -2
  10. package/src/components/ai-prompts/version-history.tsx +21 -41
  11. package/src/components/ai-provider/model-list-editor.tsx +2 -3
  12. package/src/components/ai-provider/provider-form.tsx +7 -7
  13. package/src/components/ai-provider/provider-table.tsx +17 -40
  14. package/src/components/auth/admin-login-form.tsx +7 -7
  15. package/src/components/auth/icon-input.tsx +2 -2
  16. package/src/components/auth/password-input.tsx +2 -2
  17. package/src/components/component/component-form-dialog.tsx +10 -18
  18. package/src/components/component/component-import-dialog.tsx +6 -6
  19. package/src/components/component/component-preview.tsx +311 -0
  20. package/src/components/component/component-table.tsx +3 -3
  21. package/src/components/dependency/changelog-dialog.tsx +2 -2
  22. package/src/components/dependency/columns.tsx +3 -3
  23. package/src/components/dependency/dependency-table.tsx +7 -7
  24. package/src/components/dependency/edit-dialog.tsx +8 -8
  25. package/src/components/invitations/invitations-page.tsx +26 -49
  26. package/src/components/knowledge-public/bookmark-form-dialog.tsx +6 -6
  27. package/src/components/knowledge-public/compliance-form-dialog.tsx +6 -6
  28. package/src/components/knowledge-public/legal-form-dialog.tsx +7 -7
  29. package/src/components/layout/sidebar-02/app-sidebar.tsx +1 -2
  30. package/src/components/layout/sidebar-02/index.tsx +1 -1
  31. package/src/components/layout/sidebar-02/nav-main.tsx +2 -3
  32. package/src/components/layout/sidebar-02/nav-notifications.tsx +3 -3
  33. package/src/components/market/columns.tsx +4 -4
  34. package/src/components/market/market-app-form.tsx +6 -7
  35. package/src/components/market/market-app-list.tsx +14 -29
  36. package/src/components/monitoring/error-list.tsx +2 -2
  37. package/src/components/monitoring/metrics-stats.tsx +1 -1
  38. package/src/components/monitoring/request-log-table.tsx +2 -2
  39. package/src/components/oauth-providers/provider-page.tsx +20 -38
  40. package/src/components/permissions/assign-dialog.tsx +135 -0
  41. package/src/components/permissions/create-role-dialog.tsx +135 -0
  42. package/src/components/permissions/types.ts +49 -0
  43. package/src/components/user/columns.tsx +6 -6
  44. package/src/components/user/settings-activity-log.tsx +7 -7
  45. package/src/components/user/settings-profile/avatar-uploader.tsx +118 -0
  46. package/src/components/user/settings-profile/social-links.tsx +63 -0
  47. package/src/components/user/settings-profile.tsx +26 -125
  48. package/src/components/user/user-create-dialog.tsx +6 -6
  49. package/src/components/user/user-detail/error-boundary.tsx +19 -0
  50. package/src/components/user/user-detail/user-detail-dialogs.tsx +203 -0
  51. package/src/components/user/user-filters.tsx +4 -4
  52. package/src/lib/auth/page-gate.ts +28 -0
  53. package/src/lib/auth.config.ts +25 -9
  54. package/src/lib/i18n/detect.ts +1 -1
  55. package/src/lib/loader-serial.ts +14 -0
  56. package/src/providers/index.tsx +1 -1
  57. package/src/routeTree.gen.ts +67 -78
  58. package/src/routes/__root.tsx +4 -4
  59. package/src/routes/_nav/audit/route.lazy.tsx +1 -2
  60. package/src/routes/_nav/compliance/route.lazy.tsx +5 -3
  61. package/src/routes/_nav/components/route.lazy.tsx +14 -34
  62. package/src/routes/_nav/knowledge-public/bookmarks/route.lazy.tsx +18 -38
  63. package/src/routes/_nav/knowledge-public/compliance/route.lazy.tsx +18 -38
  64. package/src/routes/_nav/knowledge-public/legal/route.lazy.tsx +6 -6
  65. package/src/routes/_nav/licenses/$licenseId/route.lazy.tsx +3 -3
  66. package/src/routes/_nav/licenses/new/route.lazy.tsx +5 -5
  67. package/src/routes/_nav/licenses/route.lazy.tsx +1 -1
  68. package/src/routes/_nav/monitoring/ai-usage/route.lazy.tsx +2 -2
  69. package/src/routes/_nav/monitoring/errors/route.lazy.tsx +10 -10
  70. package/src/routes/_nav/monitoring/errors/route.tsx +7 -0
  71. package/src/routes/_nav/monitoring/health/route.lazy.tsx +13 -15
  72. package/src/routes/_nav/monitoring/health/route.tsx +14 -0
  73. package/src/routes/_nav/monitoring/logs/route.lazy.tsx +24 -9
  74. package/src/routes/_nav/monitoring/logs/route.tsx +13 -0
  75. package/src/routes/_nav/monitoring/metrics/route.lazy.tsx +12 -14
  76. package/src/routes/_nav/monitoring/metrics/route.tsx +7 -0
  77. package/src/routes/_nav/monitoring/overview/route.lazy.tsx +14 -13
  78. package/src/routes/_nav/monitoring/overview/route.tsx +17 -0
  79. package/src/routes/_nav/monitoring/route.lazy.tsx +6 -6
  80. package/src/routes/_nav/monitoring/sentry/route.lazy.tsx +2 -2
  81. package/src/routes/_nav/permissions/route.lazy.tsx +21 -311
  82. package/src/routes/_nav/permissions/route.tsx +1 -1
  83. package/src/routes/_nav/route.tsx +5 -13
  84. package/src/routes/_nav/sso/route.lazy.tsx +2 -3
  85. package/src/routes/_nav/users/$userId/route.lazy.tsx +91 -156
  86. package/src/routes/_nav/users/-components/users-table.tsx +1 -1
  87. package/src/routes/_nav/users/route.lazy.tsx +1 -1
  88. package/src/routes/login/route.lazy.tsx +1 -1
  89. package/src/routes/setup/route.lazy.tsx +2 -2
  90. package/src/server/__tests__/admin-billing.test.ts +191 -16
  91. package/src/server/__tests__/compliance.test.ts +44 -7
  92. package/src/server/__tests__/permissions.test.ts +10 -5
  93. package/src/server/__tests__/prompt-defaults.test.ts +3 -3
  94. package/src/server/admin-ai-alerts.ts +2 -1
  95. package/src/server/admin-ai-usage.ts +2 -1
  96. package/src/server/ai-memory/store.ts +6 -2
  97. package/src/server/{serverFns/ai-prompts → ai-prompts}/prompt-defaults.ts +5 -3
  98. package/src/server/{serverFns/dependency → dependency}/helpers.ts +4 -3
  99. package/src/server/knowledge-public/github-sync.ts +2 -1
  100. package/src/server/license-issue.ts +2 -1
  101. package/src/server/middlewares/auth-rate-limit.ts +117 -0
  102. package/src/server/observability/health-check.ts +4 -1
  103. package/src/server/observability/metrics.ts +17 -15
  104. package/src/server/observability/request-middleware.ts +2 -1
  105. package/src/server/observability/timing.ts +14 -16
  106. package/src/server/serverFns/admin-billing.ts +107 -12
  107. package/src/server/serverFns/ai-memory/list-users.ts +2 -1
  108. package/src/server/serverFns/ai-prompts/activate.ts +2 -1
  109. package/src/server/serverFns/ai-prompts/get.ts +3 -2
  110. package/src/server/serverFns/ai-prompts/list.ts +3 -2
  111. package/src/server/serverFns/ai-prompts/rollback.ts +3 -1
  112. package/src/server/serverFns/ai-prompts/save.ts +5 -3
  113. package/src/server/serverFns/ai-provider/create.ts +4 -1
  114. package/src/server/serverFns/ai-provider/delete.ts +4 -1
  115. package/src/server/serverFns/ai-provider/get.ts +4 -1
  116. package/src/server/serverFns/ai-provider/list.ts +28 -1
  117. package/src/server/serverFns/ai-provider/seed-from-seed.ts +2 -1
  118. package/src/server/serverFns/ai-provider/update.ts +4 -1
  119. package/src/server/serverFns/anyhub/market.ts +8 -1
  120. package/src/server/serverFns/audit.ts +14 -1
  121. package/src/server/serverFns/auth/setup.ts +3 -1
  122. package/src/server/serverFns/compliance.ts +32 -3
  123. package/src/server/serverFns/components/import.ts +69 -14
  124. package/src/server/serverFns/components/list.ts +4 -1
  125. package/src/server/serverFns/components/mutations.ts +9 -1
  126. package/src/server/serverFns/dependency/list.ts +28 -5
  127. package/src/server/serverFns/dependency/sync.ts +7 -2
  128. package/src/server/serverFns/dependency/update.ts +4 -1
  129. package/src/server/serverFns/developer-log-auto-generate.ts +63 -32
  130. package/src/server/serverFns/developer-logs.ts +5 -1
  131. package/src/server/serverFns/invitations.ts +7 -1
  132. package/src/server/serverFns/knowledge-public/bookmarks/create.ts +2 -1
  133. package/src/server/serverFns/knowledge-public/bookmarks/delete.ts +2 -1
  134. package/src/server/serverFns/knowledge-public/bookmarks/detail.ts +2 -1
  135. package/src/server/serverFns/knowledge-public/bookmarks/list.ts +2 -1
  136. package/src/server/serverFns/knowledge-public/bookmarks/sync-all-github.ts +2 -1
  137. package/src/server/serverFns/knowledge-public/bookmarks/update.ts +2 -1
  138. package/src/server/serverFns/knowledge-public/compliance/create.ts +2 -1
  139. package/src/server/serverFns/knowledge-public/compliance/delete.ts +2 -1
  140. package/src/server/serverFns/knowledge-public/compliance/detail.ts +2 -1
  141. package/src/server/serverFns/knowledge-public/compliance/list.ts +2 -1
  142. package/src/server/serverFns/knowledge-public/compliance/update.ts +2 -1
  143. package/src/server/serverFns/knowledge-public/legal/create.ts +2 -1
  144. package/src/server/serverFns/knowledge-public/legal/delete.ts +2 -1
  145. package/src/server/serverFns/knowledge-public/legal/detail.ts +2 -1
  146. package/src/server/serverFns/knowledge-public/legal/list.ts +2 -1
  147. package/src/server/serverFns/knowledge-public/legal/update.ts +2 -1
  148. package/src/server/serverFns/licenses.ts +8 -2
  149. package/src/server/serverFns/monitoring/get-errors.ts +2 -1
  150. package/src/server/serverFns/monitoring/get-health.ts +2 -1
  151. package/src/server/serverFns/monitoring/get-metrics.ts +2 -1
  152. package/src/server/serverFns/monitoring/get-request-logs.ts +2 -1
  153. package/src/server/serverFns/monitoring/report-error.ts +2 -1
  154. package/src/server/serverFns/monitoring/reset.ts +2 -1
  155. package/src/server/serverFns/oauth-providers.ts +4 -1
  156. package/src/server/serverFns/permissions.ts +18 -11
  157. package/src/server/serverFns/sentry/config.ts +11 -8
  158. package/src/server/serverFns/sso-config.ts +17 -2
  159. package/src/server/serverFns/user/create.ts +6 -1
  160. package/src/server/serverFns/user/delete.ts +6 -1
  161. package/src/server/serverFns/user/detail.ts +5 -2
  162. package/src/server/serverFns/user/list.ts +19 -4
  163. package/src/server/serverFns/user/reset-password.ts +10 -2
  164. package/src/server/serverFns/user/update-role.ts +10 -2
  165. package/src/server/serverFns/user/update-status.ts +10 -2
  166. package/src/styles/globals.css +4 -0
  167. package/src/components/data-table/data-table-pagination.tsx +0 -112
  168. package/src/components/data-table/data-table.tsx +0 -218
  169. package/src/components/data-table/table-detail-layout.tsx +0 -98
  170. package/src/components/ui/alert-dialog.tsx +0 -187
  171. package/src/components/ui/alert.tsx +0 -75
  172. package/src/components/ui/avatar.tsx +0 -106
  173. package/src/components/ui/badge.tsx +0 -51
  174. package/src/components/ui/button.tsx +0 -57
  175. package/src/components/ui/card.tsx +0 -102
  176. package/src/components/ui/checkbox.tsx +0 -28
  177. package/src/components/ui/collapsible.tsx +0 -19
  178. package/src/components/ui/dialog.tsx +0 -155
  179. package/src/components/ui/dropdown-menu.tsx +0 -267
  180. package/src/components/ui/field.tsx +0 -236
  181. package/src/components/ui/input-group.tsx +0 -158
  182. package/src/components/ui/input.tsx +0 -19
  183. package/src/components/ui/label.tsx +0 -17
  184. package/src/components/ui/pagination.tsx +0 -130
  185. package/src/components/ui/select.tsx +0 -234
  186. package/src/components/ui/separator.tsx +0 -22
  187. package/src/components/ui/sheet.tsx +0 -135
  188. package/src/components/ui/sidebar.tsx +0 -721
  189. package/src/components/ui/skeleton.tsx +0 -13
  190. package/src/components/ui/switch.tsx +0 -29
  191. package/src/components/ui/table.tsx +0 -115
  192. package/src/components/ui/textarea.tsx +0 -17
  193. package/src/components/ui/toast.tsx +0 -282
  194. package/src/components/ui/tooltip.tsx +0 -63
  195. package/src/hooks/use-mobile.ts +0 -19
  196. package/src/lib/avatar.ts +0 -41
  197. /package/src/routes/{api.auth.$.ts → api/auth/$.ts} +0 -0
  198. /package/src/routes/{api.sentry-test.ts → api/sentry-test.ts} +0 -0
@@ -17,18 +17,18 @@
17
17
 
18
18
  import { useState, useEffect } from 'react'
19
19
  import { Loader2 } from 'lucide-react'
20
- import { toast } from '@/components/ui/toast'
21
- import { Button } from '@/components/ui/button'
22
- import { Input } from '@/components/ui/input'
23
- import { Label } from '@/components/ui/label'
24
- import { Textarea } from '@/components/ui/textarea'
20
+ import { toast } from '@allbluecn/ui/toast'
21
+ import { Button } from '@allbluecn/ui/button'
22
+ import { Input } from '@allbluecn/ui/input'
23
+ import { Label } from '@allbluecn/ui/label'
24
+ import { Textarea } from '@allbluecn/ui/textarea'
25
25
  import {
26
26
  Dialog,
27
27
  DialogContent,
28
28
  DialogFooter,
29
29
  DialogHeader,
30
30
  DialogTitle,
31
- } from '@/components/ui/dialog'
31
+ } from '@allbluecn/ui/dialog'
32
32
  import { adminCreateBookmarkFn } from '@/server/serverFns/knowledge-public/bookmarks/create'
33
33
  import { adminUpdateBookmarkFn } from '@/server/serverFns/knowledge-public/bookmarks/update'
34
34
  import { adminGetBookmarkDetailFn } from '@/server/serverFns/knowledge-public/bookmarks/detail'
@@ -17,18 +17,18 @@
17
17
 
18
18
  import { useState, useEffect } from 'react'
19
19
  import { Loader2, PlusIcon, Trash2Icon } from 'lucide-react'
20
- import { toast } from '@/components/ui/toast'
21
- import { Button } from '@/components/ui/button'
22
- import { Input } from '@/components/ui/input'
23
- import { Label } from '@/components/ui/label'
24
- import { Textarea } from '@/components/ui/textarea'
20
+ import { toast } from '@allbluecn/ui/toast'
21
+ import { Button } from '@allbluecn/ui/button'
22
+ import { Input } from '@allbluecn/ui/input'
23
+ import { Label } from '@allbluecn/ui/label'
24
+ import { Textarea } from '@allbluecn/ui/textarea'
25
25
  import {
26
26
  Dialog,
27
27
  DialogContent,
28
28
  DialogFooter,
29
29
  DialogHeader,
30
30
  DialogTitle,
31
- } from '@/components/ui/dialog'
31
+ } from '@allbluecn/ui/dialog'
32
32
  import { adminCreateComplianceFn } from '@/server/serverFns/knowledge-public/compliance/create'
33
33
  import { adminUpdateComplianceFn } from '@/server/serverFns/knowledge-public/compliance/update'
34
34
  import { adminGetComplianceDetailFn } from '@/server/serverFns/knowledge-public/compliance/detail'
@@ -18,25 +18,25 @@
18
18
  import { useState, useEffect } from 'react'
19
19
  import { m } from '@/paraglide/messages.js'
20
20
  import { Loader2 } from 'lucide-react'
21
- import { toast } from '@/components/ui/toast'
22
- import { Button } from '@/components/ui/button'
23
- import { Input } from '@/components/ui/input'
24
- import { Label } from '@/components/ui/label'
25
- import { Textarea } from '@/components/ui/textarea'
21
+ import { toast } from '@allbluecn/ui/toast'
22
+ import { Button } from '@allbluecn/ui/button'
23
+ import { Input } from '@allbluecn/ui/input'
24
+ import { Label } from '@allbluecn/ui/label'
25
+ import { Textarea } from '@allbluecn/ui/textarea'
26
26
  import {
27
27
  Select,
28
28
  SelectContent,
29
29
  SelectItem,
30
30
  SelectTrigger,
31
31
  SelectValue,
32
- } from '@/components/ui/select'
32
+ } from '@allbluecn/ui/select'
33
33
  import {
34
34
  Dialog,
35
35
  DialogContent,
36
36
  DialogFooter,
37
37
  DialogHeader,
38
38
  DialogTitle,
39
- } from '@/components/ui/dialog'
39
+ } from '@allbluecn/ui/dialog'
40
40
  import { adminCreateLegalFn } from '@/server/serverFns/knowledge-public/legal/create'
41
41
  import { adminUpdateLegalFn } from '@/server/serverFns/knowledge-public/legal/update'
42
42
  import { adminGetLegalDetailFn } from '@/server/serverFns/knowledge-public/legal/detail'
@@ -22,7 +22,7 @@ import {
22
22
  SidebarHeader,
23
23
  SidebarTrigger,
24
24
  useSidebar,
25
- } from "@/components/ui/sidebar";
25
+ } from "@allbluecn/ui/sidebar";
26
26
  import { cn } from "@/lib/utils";
27
27
  import { m } from '@/paraglide/messages.js'
28
28
  import { motion } from "motion/react";
@@ -40,7 +40,6 @@ import {
40
40
  Scale,
41
41
  ShieldCheck,
42
42
  Bookmark,
43
- BugPlay,
44
43
  Activity,
45
44
  CreditCard,
46
45
  Shield,
@@ -16,7 +16,7 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
  import type { ReactNode } from "react"
19
- import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
19
+ import { SidebarInset, SidebarProvider } from "@allbluecn/ui/sidebar";
20
20
  import { DashboardSidebar } from "@/components/layout/sidebar-02/app-sidebar";
21
21
 
22
22
  export default function Sidebar02({ children }: { children?: ReactNode }) {
@@ -19,8 +19,7 @@
19
19
  import {
20
20
  Collapsible,
21
21
  CollapsibleContent,
22
- CollapsibleTrigger,
23
- } from "@/components/ui/collapsible";
22
+ } from "@allbluecn/ui/collapsible";
24
23
  import {
25
24
  SidebarMenu,
26
25
  SidebarMenuButton,
@@ -29,7 +28,7 @@ import {
29
28
  SidebarMenuSubButton,
30
29
  SidebarMenuItem as SidebarMenuSubItem,
31
30
  useSidebar,
32
- } from "@/components/ui/sidebar";
31
+ } from "@allbluecn/ui/sidebar";
33
32
  import { cn } from "@/lib/utils";
34
33
  import { ChevronDown, ChevronUp } from "lucide-react";
35
34
  import { Link } from "@tanstack/react-router";
@@ -16,8 +16,8 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
 
19
- import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
20
- import { Button } from "@/components/ui/button";
19
+ import { Avatar, AvatarFallback, AvatarImage } from "@allbluecn/ui/avatar";
20
+ import { Button } from "@allbluecn/ui/button";
21
21
  import {
22
22
  DropdownMenu,
23
23
  DropdownMenuContent,
@@ -25,7 +25,7 @@ import {
25
25
  DropdownMenuLabel,
26
26
  DropdownMenuSeparator,
27
27
  DropdownMenuTrigger,
28
- } from "@/components/ui/dropdown-menu";
28
+ } from "@allbluecn/ui/dropdown-menu";
29
29
  import { BellIcon } from "lucide-react";
30
30
 
31
31
  type Notification = {
@@ -15,17 +15,17 @@
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
- import type { AdminColumnDef } from "@/components/data-table/data-table";
18
+ import type { AdminColumnDef } from "@allbluecn/ui/data-table";
19
19
  import { m } from '@/paraglide/messages.js'
20
- import { Badge } from "@/components/ui/badge"
21
- import { Button } from "@/components/ui/button"
20
+ import { Badge } from "@allbluecn/ui/badge"
21
+ import { Button } from "@allbluecn/ui/button"
22
22
  import {
23
23
  DropdownMenu,
24
24
  DropdownMenuContent,
25
25
  DropdownMenuItem,
26
26
  DropdownMenuSeparator,
27
27
  DropdownMenuTrigger,
28
- } from "@/components/ui/dropdown-menu"
28
+ } from "@allbluecn/ui/dropdown-menu"
29
29
  import { MoreHorizontalIcon, PencilIcon, TrashIcon, EyeIcon, EyeOffIcon } from "lucide-react"
30
30
 
31
31
  export type MarketAppRow = {
@@ -17,7 +17,6 @@
17
17
 
18
18
  import { useEffect, useState } from "react"
19
19
  import { m } from '@/paraglide/messages.js'
20
- import { useTheme } from "next-themes"
21
20
  import { MarketAppFormData } from "@/lib/anyhub/types"
22
21
  import { CAPABILITY_GROUPS } from "@/lib/anyhub/capabilities"
23
22
  import {
@@ -26,18 +25,18 @@ import {
26
25
  DialogFooter,
27
26
  DialogHeader,
28
27
  DialogTitle,
29
- } from "@/components/ui/dialog"
30
- import { Button } from "@/components/ui/button"
31
- import { Input } from "@/components/ui/input"
32
- import { Label } from "@/components/ui/label"
28
+ } from "@allbluecn/ui/dialog"
29
+ import { Button } from "@allbluecn/ui/button"
30
+ import { Input } from "@allbluecn/ui/input"
31
+ import { Label } from "@allbluecn/ui/label"
33
32
  import {
34
33
  Select,
35
34
  SelectContent,
36
35
  SelectItem,
37
36
  SelectTrigger,
38
37
  SelectValue,
39
- } from "@/components/ui/select"
40
- import { toast } from '@/components/ui/toast'
38
+ } from "@allbluecn/ui/select"
39
+ import { toast } from '@allbluecn/ui/toast'
41
40
 
42
41
  interface MarketAppFormProps {
43
42
  open: boolean
@@ -17,24 +17,15 @@
17
17
 
18
18
  import { useCallback, useEffect, useState } from "react"
19
19
  import { m } from '@/paraglide/messages.js'
20
- import { DataTable } from "@/components/data-table/data-table"
20
+ import { DataTable } from "@allbluecn/ui/data-table"
21
21
  import { getMarketColumns, MarketAppRow } from "./columns"
22
22
  import { MarketAppForm } from "./market-app-form"
23
23
  import { MarketAppFormData } from "@/lib/anyhub/types"
24
- import { Button } from "@/components/ui/button"
24
+ import { Button } from "@allbluecn/ui/button"
25
25
  import { PlusIcon } from "lucide-react"
26
- import { toast } from '@/components/ui/toast'
26
+ import { toast } from '@allbluecn/ui/toast'
27
27
  import { listMarketAppsFn, updateMarketAppFn, deleteMarketAppFn } from "@/server/serverFns/anyhub/market"
28
- import {
29
- AlertDialog,
30
- AlertDialogAction,
31
- AlertDialogCancel,
32
- AlertDialogContent,
33
- AlertDialogDescription,
34
- AlertDialogFooter,
35
- AlertDialogHeader,
36
- AlertDialogTitle,
37
- } from "@/components/ui/alert-dialog"
28
+ import { ConfirmDialog } from "@allbluecn/ui/components/confirm-dialog"
38
29
 
39
30
  export function MarketAppList() {
40
31
  const [apps, setApps] = useState<MarketAppRow[]>([])
@@ -134,22 +125,16 @@ export function MarketAppList() {
134
125
  onSuccess={fetchApps}
135
126
  />
136
127
 
137
- <AlertDialog open={!!deleteTarget} onOpenChange={(open: boolean) => !open && setDeleteTarget(null)}>
138
- <AlertDialogContent>
139
- <AlertDialogHeader>
140
- <AlertDialogTitle>{m.common_market_deleteConfirmTitle()}</AlertDialogTitle>
141
- <AlertDialogDescription>
142
- {m.common_market_deleteConfirmDesc({ name: deleteTarget?.displayName ?? '' })}
143
- </AlertDialogDescription>
144
- </AlertDialogHeader>
145
- <AlertDialogFooter>
146
- <AlertDialogCancel>{m.common_common_cancel()}</AlertDialogCancel>
147
- <AlertDialogAction onClick={handleDelete} className="bg-destructive text-white hover:bg-destructive/90">
148
- {m.common_common_delete()}
149
- </AlertDialogAction>
150
- </AlertDialogFooter>
151
- </AlertDialogContent>
152
- </AlertDialog>
128
+ <ConfirmDialog
129
+ open={!!deleteTarget}
130
+ onOpenChange={(open: boolean) => !open && setDeleteTarget(null)}
131
+ title={m.common_market_deleteConfirmTitle()}
132
+ description={m.common_market_deleteConfirmDesc({ name: deleteTarget?.displayName ?? '' })}
133
+ cancelLabel={m.common_common_cancel()}
134
+ confirmLabel={m.common_common_delete()}
135
+ confirmClassName="bg-destructive text-white hover:bg-destructive/90"
136
+ onConfirm={handleDelete}
137
+ />
153
138
  </div>
154
139
  )
155
140
  }
@@ -17,7 +17,7 @@
17
17
 
18
18
  import { useState } from 'react'
19
19
  import { m } from '@/paraglide/messages.js'
20
- import { DataTable, type AdminColumnDef } from '@/components/data-table/data-table'
20
+ import { DataTable, type AdminColumnDef } from '@allbluecn/ui/data-table'
21
21
 
22
22
  function formatRelativeTime(dateStr: string): string {
23
23
  const now = new Date()
@@ -33,7 +33,7 @@ function formatRelativeTime(dateStr: string): string {
33
33
  return m.common_common_timeAgo_days({ count: days })
34
34
  }
35
35
 
36
- interface ErrorItem {
36
+ export interface ErrorItem {
37
37
  id: string
38
38
  errorName: string
39
39
  errorMessage: string
@@ -15,7 +15,7 @@
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
- import { DataTable, type AdminColumnDef } from '@/components/data-table/data-table'
18
+ import { DataTable, type AdminColumnDef } from '@allbluecn/ui/data-table'
19
19
  import { m } from '@/paraglide/messages.js'
20
20
  import { describeMetric } from '@/lib/monitoring-descriptions'
21
21
  import { getBenchmark, getBenchmarkSource, compareDuration } from '@/lib/monitoring-benchmarks'
@@ -17,12 +17,12 @@
17
17
 
18
18
  import type React from 'react'
19
19
  import { m } from '@/paraglide/messages.js'
20
- import { DataTable, type AdminColumnDef } from '@/components/data-table/data-table'
20
+ import { DataTable, type AdminColumnDef } from '@allbluecn/ui/data-table'
21
21
  import { describePath } from '@/lib/monitoring-descriptions'
22
22
  import { getBenchmark, getBenchmarkSource, compareDuration } from '@/lib/monitoring-benchmarks'
23
23
  import { ArrowDown, ArrowUp, Info } from 'lucide-react'
24
24
 
25
- interface RequestLogEntry {
25
+ export interface RequestLogEntry {
26
26
  id: string
27
27
  timestamp: string
28
28
  method: string
@@ -19,26 +19,17 @@ import { useEffect, useState } from 'react'
19
19
  import type React from 'react'
20
20
  import { m } from '@/paraglide/messages.js'
21
21
  import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
22
- import { toast } from '@/components/ui/toast'
22
+ import { toast } from '@allbluecn/ui/toast'
23
23
  import { Eye, EyeOff, KeyRound, PlugZap, Save, Trash2 } from 'lucide-react'
24
24
  import { PageHeader } from '@/components/common/page-header'
25
- import { Button } from '@/components/ui/button'
26
- import { Badge } from '@/components/ui/badge'
27
- import { Card, CardContent } from '@/components/ui/card'
28
- import { Input } from '@/components/ui/input'
29
- import { Label } from '@/components/ui/label'
30
- import { Switch } from '@/components/ui/switch'
31
- import { Skeleton } from '@/components/ui/skeleton'
32
- import {
33
- AlertDialog,
34
- AlertDialogAction,
35
- AlertDialogCancel,
36
- AlertDialogContent,
37
- AlertDialogDescription,
38
- AlertDialogFooter,
39
- AlertDialogHeader,
40
- AlertDialogTitle,
41
- } from '@/components/ui/alert-dialog'
25
+ import { Button } from '@allbluecn/ui/button'
26
+ import { Badge } from '@allbluecn/ui/badge'
27
+ import { Card, CardContent } from '@allbluecn/ui/card'
28
+ import { Input } from '@allbluecn/ui/input'
29
+ import { Label } from '@allbluecn/ui/label'
30
+ import { Switch } from '@allbluecn/ui/switch'
31
+ import { Skeleton } from '@allbluecn/ui/skeleton'
32
+ import { ConfirmDialog } from '@allbluecn/ui/components/confirm-dialog'
42
33
  import {
43
34
  deleteOAuthProviderFn,
44
35
  listOAuthProvidersFn,
@@ -299,26 +290,17 @@ export function OAuthProviderPage(): React.ReactElement {
299
290
  </Card>
300
291
  </div>
301
292
 
302
- <AlertDialog open={pendingDelete} onOpenChange={(o: boolean) => !o && setPendingDelete(false)}>
303
- <AlertDialogContent>
304
- <AlertDialogHeader>
305
- <AlertDialogTitle>{m["admin-loginProviders_delete_confirm_title"]()}</AlertDialogTitle>
306
- <AlertDialogDescription>
307
- {m["admin-loginProviders_delete_confirm_desc"]()}
308
- </AlertDialogDescription>
309
- </AlertDialogHeader>
310
- <AlertDialogFooter>
311
- <AlertDialogCancel>{m.common_common_cancel()}</AlertDialogCancel>
312
- <AlertDialogAction
313
- className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
314
- disabled={deleteMutation.isPending}
315
- onClick={() => deleteMutation.mutate()}
316
- >
317
- {m["admin-loginProviders_action_delete"]()}
318
- </AlertDialogAction>
319
- </AlertDialogFooter>
320
- </AlertDialogContent>
321
- </AlertDialog>
293
+ <ConfirmDialog
294
+ open={pendingDelete}
295
+ onOpenChange={(o: boolean) => !o && setPendingDelete(false)}
296
+ title={m["admin-loginProviders_delete_confirm_title"]()}
297
+ description={m["admin-loginProviders_delete_confirm_desc"]()}
298
+ cancelLabel={m.common_common_cancel()}
299
+ confirmLabel={m["admin-loginProviders_action_delete"]()}
300
+ confirmClassName="bg-destructive text-destructive-foreground hover:bg-destructive/90"
301
+ confirmDisabled={deleteMutation.isPending}
302
+ onConfirm={() => deleteMutation.mutate()}
303
+ />
322
304
  </div>
323
305
  )
324
306
  }
@@ -0,0 +1,135 @@
1
+ import { useEffect, useState } from 'react'
2
+ import type React from 'react'
3
+ import { m } from '@/paraglide/messages.js'
4
+ import { useServerFn } from '@tanstack/react-start'
5
+ import { toast } from '@allbluecn/ui/toast'
6
+ import {
7
+ assignRoleFn,
8
+ unassignRoleFn,
9
+ listRoleAssignmentsFn,
10
+ } from '@/server/serverFns/permissions'
11
+ import {
12
+ Dialog,
13
+ DialogContent,
14
+ DialogDescription,
15
+ DialogFooter,
16
+ DialogHeader,
17
+ DialogTitle,
18
+ } from '@allbluecn/ui/dialog'
19
+ import { Button } from '@allbluecn/ui/button'
20
+ import { Input } from '@allbluecn/ui/input'
21
+ import {
22
+ Table,
23
+ TableBody,
24
+ TableCell,
25
+ TableHead,
26
+ TableHeader,
27
+ TableRow,
28
+ } from '@allbluecn/ui/table'
29
+ import type { AssignmentItem, RoleItem } from './types'
30
+
31
+ export function AssignDialog({
32
+ open,
33
+ onOpenChange,
34
+ role,
35
+ i18nLang,
36
+ onAssigned,
37
+ }: {
38
+ open: boolean
39
+ onOpenChange: (v: boolean) => void
40
+ role: RoleItem | null
41
+ i18nLang: string
42
+ onAssigned: () => void
43
+ }): React.ReactElement {
44
+ const assignRole = useServerFn(assignRoleFn)
45
+ const unassignRole = useServerFn(unassignRoleFn)
46
+ const listAssignments = useServerFn(listRoleAssignmentsFn)
47
+ const [assignments, setAssignments] = useState<AssignmentItem[]>([])
48
+ const [searchUser, setSearchUser] = useState('')
49
+ const isZh = i18nLang === 'zh'
50
+
51
+ useEffect(() => {
52
+ if (open && role) {
53
+ listAssignments({ data: { roleId: role.id } })
54
+ .then((result: any) => setAssignments(result))
55
+ .catch(() => setAssignments([]))
56
+ }
57
+ }, [open, role, listAssignments])
58
+
59
+ const handleAssign = async () => {
60
+ if (!searchUser.trim() || !role) return
61
+ await assignRole({ data: { userId: searchUser.trim(), roleId: role.id } })
62
+ toast.success(m.enterprise_permissions_toast_assigned())
63
+ setSearchUser('')
64
+ onAssigned()
65
+ }
66
+
67
+ const handleUnassign = async (assignmentId: string) => {
68
+ await unassignRole({ data: { assignmentId } })
69
+ toast.success(m.enterprise_permissions_toast_unassigned())
70
+ setAssignments(assignments.filter((a) => a.id !== assignmentId))
71
+ }
72
+
73
+ return (
74
+ <Dialog open={open} onOpenChange={onOpenChange}>
75
+ <DialogContent className="max-w-lg">
76
+ <DialogHeader>
77
+ <DialogTitle>
78
+ {m.enterprise_permissions_assign({ name: role?.name ?? '' })}
79
+ </DialogTitle>
80
+ <DialogDescription>{m.enterprise_permissions_assignDesc()}</DialogDescription>
81
+ </DialogHeader>
82
+
83
+ <div className="space-y-4">
84
+ <div className="flex gap-2">
85
+ <Input
86
+ value={searchUser}
87
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => setSearchUser(e.target.value)}
88
+ placeholder={m.enterprise_permissions_searchUserPlaceholder()}
89
+ />
90
+ <Button onClick={handleAssign} disabled={!searchUser.trim()}>
91
+ {m.enterprise_permissions_assignUser()}
92
+ </Button>
93
+ </div>
94
+
95
+ {assignments.length === 0 ? (
96
+ <p className="text-sm text-muted-foreground">{m.enterprise_permissions_noAssignments()}</p>
97
+ ) : (
98
+ <Table>
99
+ <TableHeader>
100
+ <TableRow>
101
+ <TableHead>{isZh ? '用户' : 'User'}</TableHead>
102
+ <TableHead>{isZh ? '邮箱' : 'Email'}</TableHead>
103
+ <TableHead>{isZh ? '操作' : 'Actions'}</TableHead>
104
+ </TableRow>
105
+ </TableHeader>
106
+ <TableBody>
107
+ {assignments.map((a) => (
108
+ <TableRow key={a.id}>
109
+ <TableCell className="font-medium">{a.user?.username || a.userId}</TableCell>
110
+ <TableCell>{a.user?.email || '-'}</TableCell>
111
+ <TableCell>
112
+ <button
113
+ type="button"
114
+ className="text-destructive hover:underline"
115
+ onClick={() => handleUnassign(a.id)}
116
+ >
117
+ {m.enterprise_permissions_unassign()}
118
+ </button>
119
+ </TableCell>
120
+ </TableRow>
121
+ ))}
122
+ </TableBody>
123
+ </Table>
124
+ )}
125
+ </div>
126
+
127
+ <DialogFooter>
128
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
129
+ {m.enterprise_permissions_dialog_close()}
130
+ </Button>
131
+ </DialogFooter>
132
+ </DialogContent>
133
+ </Dialog>
134
+ )
135
+ }
@@ -0,0 +1,135 @@
1
+ import { useCallback, useEffect, useState } from 'react'
2
+ import type React from 'react'
3
+ import { m } from '@/paraglide/messages.js'
4
+ import { useServerFn } from '@tanstack/react-start'
5
+ import { toast } from '@allbluecn/ui/toast'
6
+ import { createRoleFn } from '@/server/serverFns/permissions'
7
+ import {
8
+ Dialog,
9
+ DialogContent,
10
+ DialogDescription,
11
+ DialogFooter,
12
+ DialogHeader,
13
+ DialogTitle,
14
+ } from '@allbluecn/ui/dialog'
15
+ import { Button } from '@allbluecn/ui/button'
16
+ import { Input } from '@allbluecn/ui/input'
17
+ import { Label } from '@allbluecn/ui/label'
18
+ import {
19
+ Select,
20
+ SelectContent,
21
+ SelectItem,
22
+ SelectTrigger,
23
+ SelectValue,
24
+ } from '@allbluecn/ui/select'
25
+ import { ALL_ACTIONS, ALL_RESOURCES, LEVELS, type ResourcePermission } from './types'
26
+
27
+ export function CreateRoleDialog({
28
+ open,
29
+ onOpenChange,
30
+ workspaceId,
31
+ i18nLang,
32
+ onCreated,
33
+ }: {
34
+ open: boolean
35
+ onOpenChange: (v: boolean) => void
36
+ workspaceId: string
37
+ i18nLang: string
38
+ onCreated: () => void
39
+ }): React.ReactElement {
40
+ const createRole = useServerFn(createRoleFn)
41
+ const [name, setName] = useState('')
42
+ const [permissions, setPermissions] = useState<ResourcePermission>({})
43
+ const isZh = i18nLang === 'zh'
44
+
45
+ useEffect(() => {
46
+ if (open) {
47
+ setName('')
48
+ setPermissions({})
49
+ }
50
+ }, [open])
51
+
52
+ const handleLevelChange = useCallback((resource: string, action: string, value: string) => {
53
+ const level = (value as 'none' | 'read' | 'write' | 'admin') || 'none'
54
+ setPermissions((prev) => ({ ...prev, [`${resource}:${action}`]: level }))
55
+ }, [])
56
+
57
+ const handleSubmit = async () => {
58
+ if (!name.trim()) {
59
+ toast.warning(m.enterprise_permissions_toast_nameRequired())
60
+ return
61
+ }
62
+ await createRole({
63
+ data: {
64
+ workspaceId,
65
+ name: name.trim(),
66
+ permissions,
67
+ },
68
+ })
69
+ toast.success(m.enterprise_permissions_toast_created({ name: name.trim() }))
70
+ onOpenChange(false)
71
+ onCreated()
72
+ }
73
+
74
+ return (
75
+ <Dialog open={open} onOpenChange={onOpenChange}>
76
+ <DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
77
+ <DialogHeader>
78
+ <DialogTitle>{m.enterprise_permissions_createRole()}</DialogTitle>
79
+ <DialogDescription>{m.enterprise_permissions_createRoleDesc()}</DialogDescription>
80
+ </DialogHeader>
81
+
82
+ <div className="space-y-4">
83
+ <div className="grid gap-2">
84
+ <Label htmlFor="role-name">{m.enterprise_permissions_roleName()}</Label>
85
+ <Input
86
+ id="role-name"
87
+ value={name}
88
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => setName(e.target.value)}
89
+ placeholder={m.enterprise_permissions_roleNamePlaceholder()}
90
+ autoFocus
91
+ />
92
+ </div>
93
+
94
+ <div className="space-y-3">
95
+ <Label>{m.enterprise_permissions_permissionsMatrix()}</Label>
96
+ {ALL_RESOURCES.map((resource) => (
97
+ <div key={resource.key} className="space-y-2">
98
+ <span className="text-sm font-medium">{isZh ? resource.labelZh : resource.labelEn}</span>
99
+ <div className="grid grid-cols-4 gap-2">
100
+ {ALL_ACTIONS.map((action) => (
101
+ <Select
102
+ key={action.key}
103
+ value={permissions[`${resource.key}:${action.key}`] || 'none'}
104
+ onValueChange={(value) => handleLevelChange(resource.key, action.key, value ?? "")}
105
+ >
106
+ <SelectTrigger className="h-8">
107
+ <SelectValue>
108
+ {isZh ? resource.labelEn : resource.labelZh} / {isZh ? action.labelZh : action.labelEn}
109
+ </SelectValue>
110
+ </SelectTrigger>
111
+ <SelectContent>
112
+ {LEVELS.map((level) => (
113
+ <SelectItem key={level.value} value={level.value}>
114
+ {isZh ? level.labelZh : level.labelEn}
115
+ </SelectItem>
116
+ ))}
117
+ </SelectContent>
118
+ </Select>
119
+ ))}
120
+ </div>
121
+ </div>
122
+ ))}
123
+ </div>
124
+ </div>
125
+
126
+ <DialogFooter>
127
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
128
+ {m.enterprise_permissions_dialog_cancel()}
129
+ </Button>
130
+ <Button onClick={handleSubmit}>{m.enterprise_permissions_dialog_create()}</Button>
131
+ </DialogFooter>
132
+ </DialogContent>
133
+ </Dialog>
134
+ )
135
+ }