@allbluecn/web-app 0.4.17 → 0.4.19

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 (56) hide show
  1. package/package.json +11 -11
  2. package/src/components/billing/checkout-redirect.ts +1 -1
  3. package/src/components/changelog/changelog-page.tsx +1 -1
  4. package/src/components/layout/sidebar-03/user-menu.tsx +1 -1
  5. package/src/components/notifications/notification-list.tsx +232 -0
  6. package/src/components/notifications/notification-preferences.tsx +156 -0
  7. package/src/components/settings/ai/create-custom-provider-dialog.tsx +145 -0
  8. package/src/components/settings/ai/provider-grid.tsx +46 -25
  9. package/src/components/settings/personal-team/team/team-client.tsx +118 -15
  10. package/src/components/settings/personal-team/team/team-invitations.tsx +887 -416
  11. package/src/components/settings/personal-team/team/team-member-list.tsx +122 -136
  12. package/src/config/sidebar-routes.tsx +16 -0
  13. package/src/hooks/use-notifications.ts +119 -0
  14. package/src/lib/app-version.ts +4 -1
  15. package/src/lib/changelog/sdk-versions-types.ts +1 -0
  16. package/src/lib/changelog/sdk-versions.ts +29 -19
  17. package/src/lib/collections/ai/index.ts +0 -1
  18. package/src/lib/collections/index.ts +0 -1
  19. package/src/plugins/.gen-manifest.json +13 -0
  20. package/src/plugins/modules.gen.ts +20 -0
  21. package/src/plugins/plugins.gen.ts +20 -0
  22. package/src/plugins/ui.gen.ts +8 -0
  23. package/src/routeTree.gen.ts +47 -0
  24. package/src/routes/_login/login/route.tsx +10 -1
  25. package/src/routes/_login/register/route.lazy.tsx +3 -2
  26. package/src/routes/_login/register/route.tsx +5 -0
  27. package/src/routes/_nav/inspiration/route.tsx +8 -0
  28. package/src/routes/_nav/prd/$id/route.tsx +9 -0
  29. package/src/routes/_nav/prd/index.tsx +9 -0
  30. package/src/routes/_nav/prd/route.tsx +8 -0
  31. package/src/routes/_nav/settings/-settings-tabs.tsx +2 -1
  32. package/src/routes/_nav/settings/design/route.lazy.tsx +1 -1
  33. package/src/routes/_nav/settings/notifications/route.lazy.tsx +37 -0
  34. package/src/routes/_nav/settings/notifications/route.tsx +20 -0
  35. package/src/routes/_nav/settings/privacy/route.lazy.tsx +2 -2
  36. package/src/routes/_nav/settings/route.lazy.tsx +1 -1
  37. package/src/routes/_nav/tags/$id/route.tsx +8 -0
  38. package/src/routes/_nav/tags/index.tsx +8 -0
  39. package/src/routes/_nav/tags/route.tsx +8 -0
  40. package/src/routes/_nav/tags/settings/route.tsx +9 -0
  41. package/src/routes/api/notifications/stream.ts +88 -0
  42. package/src/routes/invite/$token/route.lazy.tsx +308 -44
  43. package/src/routes/invite/$token/route.tsx +16 -8
  44. package/src/routes/share/prd/$prdId/route.tsx +10 -0
  45. package/src/server/notifications/event-bus.ts +16 -0
  46. package/src/server/notifications/notification-service.ts +86 -0
  47. package/src/server/resources.ts +10 -2
  48. package/src/server/serverFns/__tests__/compliance.test.ts +6 -6
  49. package/src/server/serverFns/__tests__/team-accept.test.ts +100 -12
  50. package/src/server/serverFns/__tests__/team-invitation.test.ts +130 -60
  51. package/src/server/serverFns/__tests__/team-join-request.test.ts +281 -0
  52. package/src/server/serverFns/__tests__/team-members.test.ts +39 -118
  53. package/src/{lib/collections/ai/ai-providers-collection.ts → server/serverFns/auth/setup.ts} +7 -12
  54. package/src/server/serverFns/notifications.ts +155 -0
  55. package/src/server/serverFns/team.ts +521 -53
  56. package/vite.shared.ts +13 -0
@@ -8,71 +8,81 @@ export const SDK_GROUPS: SdkGroup[] = [
8
8
  "items": [
9
9
  {
10
10
  "name": "@tanstack/react-start",
11
+ "displayName": "TanStack Start",
11
12
  "version": "v1.168.46",
12
- "lastUpdate": "Aug 24, 2026",
13
+ "lastUpdate": "Aug 28, 2026",
13
14
  "source": "apps/web/package.json#dependencies",
14
15
  "docsUrl": "https://tanstack.com/start/latest"
15
16
  },
16
17
  {
17
18
  "name": "@tanstack/react-router",
19
+ "displayName": "TanStack Router",
18
20
  "version": "v1.170.29",
19
- "lastUpdate": "Aug 24, 2026",
21
+ "lastUpdate": "Aug 28, 2026",
20
22
  "source": "apps/web/package.json#dependencies",
21
23
  "docsUrl": "https://tanstack.com/router/latest"
22
24
  },
23
25
  {
24
26
  "name": "@tanstack/react-query",
27
+ "displayName": "TanStack Query",
25
28
  "version": "v5.101.2",
26
- "lastUpdate": "Aug 24, 2026",
29
+ "lastUpdate": "Aug 28, 2026",
27
30
  "source": "apps/web/package.json#dependencies",
28
31
  "docsUrl": "https://tanstack.com/query/latest"
29
32
  },
30
33
  {
31
34
  "name": "@tanstack/ai",
35
+ "displayName": "TanStack AI",
32
36
  "version": "v0.43.0",
33
- "lastUpdate": "Aug 24, 2026",
37
+ "lastUpdate": "Aug 28, 2026",
34
38
  "source": "apps/web/package.json#dependencies",
35
39
  "docsUrl": "https://tanstack.com/ai/latest"
36
40
  },
37
41
  {
38
42
  "name": "@tanstack/react-table",
43
+ "displayName": "TanStack Table",
39
44
  "version": "v9.1.0",
40
- "lastUpdate": "Aug 24, 2026",
45
+ "lastUpdate": "Aug 28, 2026",
41
46
  "source": "apps/web/package.json#dependencies",
42
47
  "docsUrl": "https://tanstack.com/table/latest"
43
48
  },
44
49
  {
45
50
  "name": "@tanstack/react-form",
51
+ "displayName": "TanStack Form",
46
52
  "version": "v2.0.0-alpha.0",
47
- "lastUpdate": "Aug 24, 2026",
53
+ "lastUpdate": "Aug 28, 2026",
48
54
  "source": "apps/web/package.json#dependencies",
49
55
  "docsUrl": "https://tanstack.com/form/latest"
50
56
  },
51
57
  {
52
58
  "name": "@tanstack/charts",
59
+ "displayName": "TanStack Charts",
53
60
  "version": "v0.9.0",
54
- "lastUpdate": "Aug 24, 2026",
61
+ "lastUpdate": "Aug 28, 2026",
55
62
  "source": "apps/admin/package.json#dependencies",
56
63
  "docsUrl": "https://tanstack.com/charts/latest"
57
64
  },
58
65
  {
59
66
  "name": "@tanstack/react-pacer",
67
+ "displayName": "TanStack Pacer",
60
68
  "version": "v0.22.1",
61
- "lastUpdate": "Aug 24, 2026",
69
+ "lastUpdate": "Aug 28, 2026",
62
70
  "source": "apps/web/package.json#dependencies",
63
71
  "docsUrl": "https://tanstack.com/pacer/latest"
64
72
  },
65
73
  {
66
74
  "name": "@tanstack/react-hotkeys",
75
+ "displayName": "TanStack Hotkeys",
67
76
  "version": "v0.10.0",
68
- "lastUpdate": "Aug 24, 2026",
77
+ "lastUpdate": "Aug 28, 2026",
69
78
  "source": "apps/web/package.json#dependencies",
70
79
  "docsUrl": "https://tanstack.com/hotkeys/latest"
71
80
  },
72
81
  {
73
82
  "name": "@tanstack/react-virtual",
83
+ "displayName": "TanStack Virtual",
74
84
  "version": "v3.14.9",
75
- "lastUpdate": "Aug 24, 2026",
85
+ "lastUpdate": "Aug 28, 2026",
76
86
  "source": "apps/admin/package.json#dependencies",
77
87
  "docsUrl": "https://tanstack.com/virtual/latest"
78
88
  }
@@ -85,15 +95,15 @@ export const SDK_GROUPS: SdkGroup[] = [
85
95
  "items": [
86
96
  {
87
97
  "name": "@allbluecn/web-app",
88
- "version": "v0.4.17",
89
- "lastUpdate": "Aug 24, 2026",
98
+ "version": "v0.4.19",
99
+ "lastUpdate": "Aug 28, 2026",
90
100
  "source": "apps/web/package.json",
91
101
  "docsUrl": "https://github.com/allbluecn/allblue"
92
102
  },
93
103
  {
94
104
  "name": "@allbluecn/kernel",
95
105
  "version": "v0.3.0",
96
- "lastUpdate": "Aug 24, 2026",
106
+ "lastUpdate": "Aug 28, 2026",
97
107
  "source": "packages/kernel/package.json",
98
108
  "docsUrl": "https://github.com/allbluecn/allblue"
99
109
  }
@@ -107,42 +117,42 @@ export const SDK_GROUPS: SdkGroup[] = [
107
117
  {
108
118
  "name": "Vite",
109
119
  "version": "v8.1.5",
110
- "lastUpdate": "Aug 24, 2026",
120
+ "lastUpdate": "Aug 28, 2026",
111
121
  "source": "apps/web/package.json#devDependencies",
112
122
  "docsUrl": "https://vite.dev/"
113
123
  },
114
124
  {
115
125
  "name": "Node.js",
116
126
  "version": "v24.19.0",
117
- "lastUpdate": "Aug 24, 2026",
127
+ "lastUpdate": "Aug 28, 2026",
118
128
  "source": ".nvmrc",
119
129
  "docsUrl": "https://nodejs.org/"
120
130
  },
121
131
  {
122
132
  "name": "Prisma",
123
133
  "version": "v7.8.0",
124
- "lastUpdate": "Aug 24, 2026",
134
+ "lastUpdate": "Aug 28, 2026",
125
135
  "source": "packages/database/package.json#devDependencies",
126
136
  "docsUrl": "https://www.prisma.io/docs"
127
137
  },
128
138
  {
129
139
  "name": "shadcn UI",
130
140
  "version": "v1.2.4",
131
- "lastUpdate": "Aug 24, 2026",
141
+ "lastUpdate": "Aug 28, 2026",
132
142
  "source": "apps/web/package.json#dependencies",
133
143
  "docsUrl": "https://ui.shadcn.com/"
134
144
  },
135
145
  {
136
146
  "name": "TipTap",
137
147
  "version": "v3.27.4",
138
- "lastUpdate": "Aug 24, 2026",
148
+ "lastUpdate": "Aug 28, 2026",
139
149
  "source": "packages/shared/package.json#devDependencies",
140
150
  "docsUrl": "https://tiptap.dev/"
141
151
  },
142
152
  {
143
153
  "name": "Lucide React",
144
154
  "version": "v1.24.0",
145
- "lastUpdate": "Aug 24, 2026",
155
+ "lastUpdate": "Aug 28, 2026",
146
156
  "source": "packages/ui/package.json#dependencies",
147
157
  "docsUrl": "https://lucide.dev/"
148
158
  }
@@ -15,4 +15,3 @@
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
- export { aiProvidersCollection } from './ai-providers-collection'
@@ -20,5 +20,4 @@ export { projectsCollection } from './reference/projects-collection'
20
20
  export { usersBriefCollection } from './reference/users-brief-collection'
21
21
  export { labelsCollection } from './reference/labels-collection'
22
22
  export { bookmarkCategoriesCollection } from './reference/bookmark-categories-collection'
23
- export { aiProvidersCollection } from './ai/ai-providers-collection'
24
23
  export { knowledgeBasesCollection } from './knowledge/knowledge-bases-collection'
@@ -0,0 +1,13 @@
1
+ {
2
+ "routeFiles": [
3
+ "src/routes/_nav/tags/route.tsx",
4
+ "src/routes/_nav/tags/index.tsx",
5
+ "src/routes/_nav/tags/$id/route.tsx",
6
+ "src/routes/_nav/tags/settings/route.tsx",
7
+ "src/routes/_nav/inspiration/route.tsx",
8
+ "src/routes/_nav/prd/route.tsx",
9
+ "src/routes/_nav/prd/index.tsx",
10
+ "src/routes/_nav/prd/$id/route.tsx",
11
+ "src/routes/share/prd/$prdId/route.tsx"
12
+ ]
13
+ }
@@ -0,0 +1,20 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ import type { ProFeature } from '@allbluecn/kernel'
3
+
4
+ export const activePluginIds = ['@allbluecn/tags', '@allbluecn/inspiration', '@allbluecn/prd'] as const
5
+ export type ActivePluginId = (typeof activePluginIds)[number]
6
+
7
+ export const implementedModules: Record<ProFeature, boolean> = {
8
+ billing: false,
9
+ hostedAi: false,
10
+ sso: false,
11
+ audit: false,
12
+ permissions: false,
13
+ license: false,
14
+ versionHistory: false,
15
+ automation: false,
16
+ templates: false,
17
+ analytics: false,
18
+ globalSearch: false,
19
+ compliance: false,
20
+ }
@@ -0,0 +1,20 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ // profile: oss (validated: 3 plugins)
3
+ // 拓扑序:@allbluecn/tags -> @allbluecn/inspiration -> @allbluecn/prd
4
+ import tags from '@allbluecn/plugins-core/tags'
5
+ import inspiration from '@allbluecn/plugins-core/inspiration'
6
+ import prd from '@allbluecn/plugins-core/prd'
7
+ import { defineProfile, type ProfileDefinition } from '@allbluecn/kernel'
8
+
9
+ export const profile: ProfileDefinition = defineProfile({
10
+ id: 'oss',
11
+ plugins: [tags, inspiration, prd],
12
+ })
13
+
14
+ export const pluginIds: string[] = ['@allbluecn/tags', '@allbluecn/inspiration', '@allbluecn/prd']
15
+
16
+ export const pluginMiddleware: unknown[] = [
17
+ ...tags.contributes.serverMiddleware ?? [],
18
+ ...inspiration.contributes.serverMiddleware ?? [],
19
+ ...prd.contributes.serverMiddleware ?? [],
20
+ ]
@@ -0,0 +1,8 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ import { NavTag } from '@allbluecn/plugins-core/tags/ui'
3
+ import { type ComponentType } from 'react'
4
+ import type { SettingsTabContribution } from '@allbluecn/kernel'
5
+
6
+ export const navItems: ComponentType[] = [NavTag]
7
+ export const settingsTabs: SettingsTabContribution[] = []
8
+ export const dashboardWidgets: ComponentType[] = []
@@ -71,6 +71,7 @@ import { Route as NavSettingsBillingRouteRouteImport } from './routes/_nav/setti
71
71
  import { Route as NavSettingsConnectionRouteRouteImport } from './routes/_nav/settings/connection/route'
72
72
  import { Route as NavSettingsDesignRouteRouteImport } from './routes/_nav/settings/design/route'
73
73
  import { Route as NavSettingsGeneralRouteRouteImport } from './routes/_nav/settings/general/route'
74
+ import { Route as NavSettingsNotificationsRouteRouteImport } from './routes/_nav/settings/notifications/route'
74
75
  import { Route as NavSettingsPrivacyRouteRouteImport } from './routes/_nav/settings/privacy/route'
75
76
  import { Route as NavSettingsTeamRouteRouteImport } from './routes/_nav/settings/team/route'
76
77
  import { Route as NavStoriesIndexRouteImport } from './routes/_nav/stories/index'
@@ -86,6 +87,7 @@ import { Route as ApiDesignUploadRouteImport } from './routes/api/design/upload'
86
87
  import { Route as ApiKnowledgeSyncGithubRouteImport } from './routes/api/knowledge/sync-github'
87
88
  import { Route as ApiLicenseActivateRouteRouteImport } from './routes/api/license/activate/route'
88
89
  import { Route as ApiLicenseHeartbeatRouteRouteImport } from './routes/api/license/heartbeat/route'
90
+ import { Route as ApiNotificationsStreamRouteImport } from './routes/api/notifications/stream'
89
91
  import { Route as ServerAnyhubProxySplatRouteImport } from './routes/server/anyhub-proxy/$'
90
92
  import { Route as ShareComplianceIdRouteRouteImport } from './routes/share/compliance/$id/route'
91
93
  import { Route as ShareLawIdRouteRouteImport } from './routes/share/law/$id/route'
@@ -495,6 +497,16 @@ const NavSettingsGeneralRouteRoute = NavSettingsGeneralRouteRouteImport.update({
495
497
  } as any).lazy(() =>
496
498
  import('./routes/_nav/settings/general/route.lazy').then((d) => d.Route),
497
499
  )
500
+ const NavSettingsNotificationsRouteRoute =
501
+ NavSettingsNotificationsRouteRouteImport.update({
502
+ id: '/notifications',
503
+ path: '/notifications',
504
+ getParentRoute: () => NavSettingsRouteRoute,
505
+ } as any).lazy(() =>
506
+ import('./routes/_nav/settings/notifications/route.lazy').then(
507
+ (d) => d.Route,
508
+ ),
509
+ )
498
510
  const NavSettingsPrivacyRouteRoute = NavSettingsPrivacyRouteRouteImport.update({
499
511
  id: '/privacy',
500
512
  path: '/privacy',
@@ -586,6 +598,11 @@ const ApiLicenseHeartbeatRouteRoute =
586
598
  path: '/api/license/heartbeat',
587
599
  getParentRoute: () => rootRouteImport,
588
600
  } as any)
601
+ const ApiNotificationsStreamRoute = ApiNotificationsStreamRouteImport.update({
602
+ id: '/api/notifications/stream',
603
+ path: '/api/notifications/stream',
604
+ getParentRoute: () => rootRouteImport,
605
+ } as any)
589
606
  const ServerAnyhubProxySplatRoute = ServerAnyhubProxySplatRouteImport.update({
590
607
  id: '/server/anyhub-proxy/$',
591
608
  path: '/server/anyhub-proxy/$',
@@ -859,6 +876,7 @@ export interface FileRoutesByFullPath {
859
876
  '/settings/connection': typeof NavSettingsConnectionRouteRoute
860
877
  '/settings/design': typeof NavSettingsDesignRouteRoute
861
878
  '/settings/general': typeof NavSettingsGeneralRouteRoute
879
+ '/settings/notifications': typeof NavSettingsNotificationsRouteRoute
862
880
  '/settings/privacy': typeof NavSettingsPrivacyRouteRoute
863
881
  '/settings/team': typeof NavSettingsTeamRouteRoute
864
882
  '/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
@@ -875,6 +893,7 @@ export interface FileRoutesByFullPath {
875
893
  '/api/auth/desktop-callback': typeof ApiAuthDesktopCallbackRoute
876
894
  '/api/design/upload': typeof ApiDesignUploadRoute
877
895
  '/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
896
+ '/api/notifications/stream': typeof ApiNotificationsStreamRoute
878
897
  '/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
879
898
  '/design/': typeof NavDesignIndexRoute
880
899
  '/knowledge/': typeof NavKnowledgeIndexRoute
@@ -946,6 +965,7 @@ export interface FileRoutesByTo {
946
965
  '/settings/connection': typeof NavSettingsConnectionRouteRoute
947
966
  '/settings/design': typeof NavSettingsDesignRouteRoute
948
967
  '/settings/general': typeof NavSettingsGeneralRouteRoute
968
+ '/settings/notifications': typeof NavSettingsNotificationsRouteRoute
949
969
  '/settings/privacy': typeof NavSettingsPrivacyRouteRoute
950
970
  '/settings/team': typeof NavSettingsTeamRouteRoute
951
971
  '/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
@@ -962,6 +982,7 @@ export interface FileRoutesByTo {
962
982
  '/api/auth/desktop-callback': typeof ApiAuthDesktopCallbackRoute
963
983
  '/api/design/upload': typeof ApiDesignUploadRoute
964
984
  '/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
985
+ '/api/notifications/stream': typeof ApiNotificationsStreamRoute
965
986
  '/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
966
987
  '/design': typeof NavDesignIndexRoute
967
988
  '/knowledge': typeof NavKnowledgeIndexRoute
@@ -1051,6 +1072,7 @@ export interface FileRoutesById {
1051
1072
  '/_nav/settings/connection': typeof NavSettingsConnectionRouteRoute
1052
1073
  '/_nav/settings/design': typeof NavSettingsDesignRouteRoute
1053
1074
  '/_nav/settings/general': typeof NavSettingsGeneralRouteRoute
1075
+ '/_nav/settings/notifications': typeof NavSettingsNotificationsRouteRoute
1054
1076
  '/_nav/settings/privacy': typeof NavSettingsPrivacyRouteRoute
1055
1077
  '/_nav/settings/team': typeof NavSettingsTeamRouteRoute
1056
1078
  '/_nav/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
@@ -1067,6 +1089,7 @@ export interface FileRoutesById {
1067
1089
  '/api/auth/desktop-callback': typeof ApiAuthDesktopCallbackRoute
1068
1090
  '/api/design/upload': typeof ApiDesignUploadRoute
1069
1091
  '/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
1092
+ '/api/notifications/stream': typeof ApiNotificationsStreamRoute
1070
1093
  '/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
1071
1094
  '/_nav/design/': typeof NavDesignIndexRoute
1072
1095
  '/_nav/knowledge/': typeof NavKnowledgeIndexRoute
@@ -1154,6 +1177,7 @@ export interface FileRouteTypes {
1154
1177
  | '/settings/connection'
1155
1178
  | '/settings/design'
1156
1179
  | '/settings/general'
1180
+ | '/settings/notifications'
1157
1181
  | '/settings/privacy'
1158
1182
  | '/settings/team'
1159
1183
  | '/stories/$storyId'
@@ -1170,6 +1194,7 @@ export interface FileRouteTypes {
1170
1194
  | '/api/auth/desktop-callback'
1171
1195
  | '/api/design/upload'
1172
1196
  | '/api/knowledge/sync-github'
1197
+ | '/api/notifications/stream'
1173
1198
  | '/server/anyhub-proxy/$'
1174
1199
  | '/design/'
1175
1200
  | '/knowledge/'
@@ -1241,6 +1266,7 @@ export interface FileRouteTypes {
1241
1266
  | '/settings/connection'
1242
1267
  | '/settings/design'
1243
1268
  | '/settings/general'
1269
+ | '/settings/notifications'
1244
1270
  | '/settings/privacy'
1245
1271
  | '/settings/team'
1246
1272
  | '/stories/$storyId'
@@ -1257,6 +1283,7 @@ export interface FileRouteTypes {
1257
1283
  | '/api/auth/desktop-callback'
1258
1284
  | '/api/design/upload'
1259
1285
  | '/api/knowledge/sync-github'
1286
+ | '/api/notifications/stream'
1260
1287
  | '/server/anyhub-proxy/$'
1261
1288
  | '/design'
1262
1289
  | '/knowledge'
@@ -1345,6 +1372,7 @@ export interface FileRouteTypes {
1345
1372
  | '/_nav/settings/connection'
1346
1373
  | '/_nav/settings/design'
1347
1374
  | '/_nav/settings/general'
1375
+ | '/_nav/settings/notifications'
1348
1376
  | '/_nav/settings/privacy'
1349
1377
  | '/_nav/settings/team'
1350
1378
  | '/_nav/stories/$storyId'
@@ -1361,6 +1389,7 @@ export interface FileRouteTypes {
1361
1389
  | '/api/auth/desktop-callback'
1362
1390
  | '/api/design/upload'
1363
1391
  | '/api/knowledge/sync-github'
1392
+ | '/api/notifications/stream'
1364
1393
  | '/server/anyhub-proxy/$'
1365
1394
  | '/_nav/design/'
1366
1395
  | '/_nav/knowledge/'
@@ -1413,6 +1442,7 @@ export interface RootRouteChildren {
1413
1442
  ApiAuthDesktopCallbackRoute: typeof ApiAuthDesktopCallbackRoute
1414
1443
  ApiDesignUploadRoute: typeof ApiDesignUploadRoute
1415
1444
  ApiKnowledgeSyncGithubRoute: typeof ApiKnowledgeSyncGithubRoute
1445
+ ApiNotificationsStreamRoute: typeof ApiNotificationsStreamRoute
1416
1446
  ServerAnyhubProxySplatRoute: typeof ServerAnyhubProxySplatRoute
1417
1447
  DesignFilesProjectIdArtboardIdFilenameRoute: typeof DesignFilesProjectIdArtboardIdFilenameRoute
1418
1448
  ApiSharePrdPrdIdEventsRoute: typeof ApiSharePrdPrdIdEventsRoute
@@ -1840,6 +1870,13 @@ declare module '@tanstack/react-router' {
1840
1870
  preLoaderRoute: typeof NavSettingsGeneralRouteRouteImport
1841
1871
  parentRoute: typeof NavSettingsRouteRoute
1842
1872
  }
1873
+ '/_nav/settings/notifications': {
1874
+ id: '/_nav/settings/notifications'
1875
+ path: '/notifications'
1876
+ fullPath: '/settings/notifications'
1877
+ preLoaderRoute: typeof NavSettingsNotificationsRouteRouteImport
1878
+ parentRoute: typeof NavSettingsRouteRoute
1879
+ }
1843
1880
  '/_nav/settings/privacy': {
1844
1881
  id: '/_nav/settings/privacy'
1845
1882
  path: '/privacy'
@@ -1945,6 +1982,13 @@ declare module '@tanstack/react-router' {
1945
1982
  preLoaderRoute: typeof ApiLicenseHeartbeatRouteRouteImport
1946
1983
  parentRoute: typeof rootRouteImport
1947
1984
  }
1985
+ '/api/notifications/stream': {
1986
+ id: '/api/notifications/stream'
1987
+ path: '/api/notifications/stream'
1988
+ fullPath: '/api/notifications/stream'
1989
+ preLoaderRoute: typeof ApiNotificationsStreamRouteImport
1990
+ parentRoute: typeof rootRouteImport
1991
+ }
1948
1992
  '/server/anyhub-proxy/$': {
1949
1993
  id: '/server/anyhub-proxy/$'
1950
1994
  path: '/server/anyhub-proxy/$'
@@ -2408,6 +2452,7 @@ interface NavSettingsRouteRouteChildren {
2408
2452
  NavSettingsConnectionRouteRoute: typeof NavSettingsConnectionRouteRoute
2409
2453
  NavSettingsDesignRouteRoute: typeof NavSettingsDesignRouteRoute
2410
2454
  NavSettingsGeneralRouteRoute: typeof NavSettingsGeneralRouteRoute
2455
+ NavSettingsNotificationsRouteRoute: typeof NavSettingsNotificationsRouteRoute
2411
2456
  NavSettingsPrivacyRouteRoute: typeof NavSettingsPrivacyRouteRoute
2412
2457
  NavSettingsTeamRouteRoute: typeof NavSettingsTeamRouteRoute
2413
2458
  }
@@ -2420,6 +2465,7 @@ const NavSettingsRouteRouteChildren: NavSettingsRouteRouteChildren = {
2420
2465
  NavSettingsConnectionRouteRoute: NavSettingsConnectionRouteRoute,
2421
2466
  NavSettingsDesignRouteRoute: NavSettingsDesignRouteRoute,
2422
2467
  NavSettingsGeneralRouteRoute: NavSettingsGeneralRouteRoute,
2468
+ NavSettingsNotificationsRouteRoute: NavSettingsNotificationsRouteRoute,
2423
2469
  NavSettingsPrivacyRouteRoute: NavSettingsPrivacyRouteRoute,
2424
2470
  NavSettingsTeamRouteRoute: NavSettingsTeamRouteRoute,
2425
2471
  }
@@ -2586,6 +2632,7 @@ const rootRouteChildren: RootRouteChildren = {
2586
2632
  ApiAuthDesktopCallbackRoute: ApiAuthDesktopCallbackRoute,
2587
2633
  ApiDesignUploadRoute: ApiDesignUploadRoute,
2588
2634
  ApiKnowledgeSyncGithubRoute: ApiKnowledgeSyncGithubRoute,
2635
+ ApiNotificationsStreamRoute: ApiNotificationsStreamRoute,
2589
2636
  ServerAnyhubProxySplatRoute: ServerAnyhubProxySplatRoute,
2590
2637
  DesignFilesProjectIdArtboardIdFilenameRoute:
2591
2638
  DesignFilesProjectIdArtboardIdFilenameRoute,
@@ -15,9 +15,12 @@
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 { createFileRoute } from '@tanstack/react-router'
18
+ import { createFileRoute, redirect } from '@tanstack/react-router'
19
19
  import { z } from 'zod'
20
20
  import { getAuthProviders } from '@/server/serverFns/auth/providers'
21
+ import { checkAdminExistsFn } from '@/server/serverFns/auth/setup'
22
+
23
+ const ADMIN_URL = process.env.ADMIN_URL || 'http://localhost:3001'
21
24
 
22
25
  export const Route = createFileRoute('/_login/login')({
23
26
  validateSearch: z.object({
@@ -26,5 +29,11 @@ export const Route = createFileRoute('/_login/login')({
26
29
  ssoToken: z.string().optional(),
27
30
  ssoError: z.string().optional(),
28
31
  }),
32
+ beforeLoad: async () => {
33
+ const result = await checkAdminExistsFn().catch(() => null)
34
+ if (result?.hasAdmin === false) {
35
+ throw redirect({ href: `${ADMIN_URL}/setup` })
36
+ }
37
+ },
29
38
  loader: () => getAuthProviders(),
30
39
  })
@@ -41,6 +41,7 @@ function RegisterPage() {
41
41
  const router = useRouter()
42
42
  const { t } = useTranslation('auth')
43
43
  const { googleEnabled } = Route.useLoaderData()
44
+ const { invite, email: emailFromUrl } = Route.useSearch()
44
45
  const registerFeatures = [
45
46
  { icon: Users, label: t('features.userResearch'), desc: t('features.userResearchDesc') },
46
47
  { icon: BarChart3, label: t('features.dataAnalysis'), desc: t('features.dataAnalysisDesc') },
@@ -51,10 +52,10 @@ function RegisterPage() {
51
52
  const form = useForm({
52
53
  defaultValues: {
53
54
  username: '',
54
- email: '',
55
+ email: emailFromUrl ?? '',
55
56
  password: '',
56
57
  confirmPassword: '',
57
- invitationCode: '',
58
+ invitationCode: invite ?? '',
58
59
  },
59
60
  validators: [{ run: registerSchema as any, triggers: ['change'] }],
60
61
  onSubmit: async ({ value }) => {
@@ -16,8 +16,13 @@
16
16
  // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
17
 
18
18
  import { createFileRoute } from '@tanstack/react-router'
19
+ import { z } from 'zod'
19
20
  import { getAuthProviders } from '@/server/serverFns/auth/providers'
20
21
 
21
22
  export const Route = createFileRoute('/_login/register')({
23
+ validateSearch: z.object({
24
+ invite: z.string().optional(),
25
+ email: z.string().optional(),
26
+ }),
22
27
  loader: () => getAuthProviders(),
23
28
  })
@@ -0,0 +1,8 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+ import type { PluginRouteContext } from '@allbluecn/kernel'
4
+ import { inspiration_route_0 } from '@allbluecn/plugins-core/inspiration/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/inspiration')({
7
+ component: inspiration_route_0.Component as any,
8
+ })
@@ -0,0 +1,9 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+ import type { PluginRouteContext } from '@allbluecn/kernel'
4
+ import { prd_route_2 } from '@allbluecn/plugins-core/prd/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/prd/$id')({
7
+ beforeLoad: ((ctx: PluginRouteContext) => prd_route_2.beforeLoad(ctx)) as any,
8
+ component: prd_route_2.Component as any,
9
+ })
@@ -0,0 +1,9 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+ import type { PluginRouteContext } from '@allbluecn/kernel'
4
+ import { prd_route_1 } from '@allbluecn/plugins-core/prd/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/prd/')({
7
+ loader: ((ctx: PluginRouteContext) => prd_route_1.loader(ctx)) as any,
8
+ component: prd_route_1.Component as any,
9
+ })
@@ -0,0 +1,8 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+ import type { PluginRouteContext } from '@allbluecn/kernel'
4
+ import { prd_route_0 } from '@allbluecn/plugins-core/prd/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/prd')({
7
+ component: prd_route_0.Component as any,
8
+ })
@@ -17,7 +17,7 @@
17
17
 
18
18
  import { Link, useLocation } from '@tanstack/react-router'
19
19
  import { useTranslation } from 'react-i18next'
20
- import { User, Users, Bot, Palette, Settings, CreditCard, Plug, ShieldCheck, type LucideIcon } from 'lucide-react'
20
+ import { User, Users, Bot, Palette, Settings, CreditCard, Plug, ShieldCheck, Bell, type LucideIcon } from 'lucide-react'
21
21
  import { cn } from '@/lib/utils'
22
22
  import { mergeSettingsGroups } from '@/components/plugin-slots/plugin-settings-tabs'
23
23
 
@@ -37,6 +37,7 @@ const groups: SettingsGroup[] = [
37
37
  titleKey: 'tabs.general',
38
38
  tabs: [
39
39
  { labelKey: 'tabs.generalSettings', path: '/settings/general', icon: Settings },
40
+ { labelKey: 'tabs.notifications', path: '/settings/notifications', icon: Bell },
40
41
  ],
41
42
  },
42
43
  {
@@ -70,7 +70,7 @@ function DesignSettingsPage() {
70
70
  }, [])
71
71
 
72
72
  const generateMutation = useMutation({
73
- mutationFn: () => generateSketchTokenFn(),
73
+ mutationFn: () => generateSketchTokenFn({ data: {} }),
74
74
  onSuccess: (data) => {
75
75
  toast.success(t('design.tokenGenerated'))
76
76
  setToken(data.token)
@@ -0,0 +1,37 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ import { createLazyFileRoute } from '@tanstack/react-router'
19
+ import { useTranslation } from 'react-i18next'
20
+ import { NotificationPreferences } from '@/components/notifications/notification-preferences'
21
+
22
+ export const Route = createLazyFileRoute('/_nav/settings/notifications')({
23
+ component: NotificationsSettingsPage,
24
+ })
25
+
26
+ function NotificationsSettingsPage() {
27
+ const { t } = useTranslation('notifications')
28
+ return (
29
+ <div className="flex flex-col gap-6 p-6">
30
+ <div className="flex flex-col gap-1">
31
+ <h1 className="text-xl font-semibold">{t('preferences.title')}</h1>
32
+ <p className="text-sm text-muted-foreground">{t('preferences.description')}</p>
33
+ </div>
34
+ <NotificationPreferences />
35
+ </div>
36
+ )
37
+ }
@@ -0,0 +1,20 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // AllBlue - 理想之海
3
+ // Copyright (C) 2026 AllBlue Contributors
4
+ //
5
+ // This program is free software: you can redistribute it and/or modify
6
+ // it under the terms of the GNU Affero General Public License as published by
7
+ // the Free Software Foundation, either version 3 of the License, or
8
+ // (at your option) any later version.
9
+ //
10
+ // This program is distributed in the hope that it will be useful,
11
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ // GNU Affero General Public License for more details.
14
+ //
15
+ // You should have received a copy of the GNU Affero General Public License
16
+ // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+
18
+ import { createFileRoute } from '@tanstack/react-router'
19
+
20
+ export const Route = createFileRoute('/_nav/settings/notifications')({})
@@ -61,7 +61,7 @@ function PrivacySettingsPage() {
61
61
  const handleExport = async () => {
62
62
  setExporting(true)
63
63
  try {
64
- await requestMyExportFn()
64
+ await requestMyExportFn({ data: {} })
65
65
  toast.success(t('privacy.submitted'))
66
66
  } catch (err) {
67
67
  toast.error(err instanceof Error ? err.message : '操作失败')
@@ -74,7 +74,7 @@ function PrivacySettingsPage() {
74
74
  if (!userName || confirmName.trim() !== userName.trim()) return
75
75
  setDeleting(true)
76
76
  try {
77
- await requestMyDeletionFn()
77
+ await requestMyDeletionFn({ data: {} })
78
78
  toast.success(t('privacy.submitted'))
79
79
  setDialogOpen(false)
80
80
  setConfirmName('')