@allbluecn/web-app 0.4.16 → 0.4.18

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 (78) hide show
  1. package/package.json +10 -10
  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/app-sidebar.tsx +2 -3
  5. package/src/components/layout/sidebar-03/nav-notifications.tsx +115 -35
  6. package/src/components/layout/sidebar-03/user-menu.tsx +5 -4
  7. package/src/components/notifications/notification-list.tsx +232 -0
  8. package/src/components/notifications/notification-preferences.tsx +156 -0
  9. package/src/components/settings/ai/create-custom-provider-dialog.tsx +145 -0
  10. package/src/components/settings/ai/provider-grid.tsx +46 -25
  11. package/src/components/settings/personal-team/team/team-client.tsx +118 -15
  12. package/src/components/settings/personal-team/team/team-invitations.tsx +887 -416
  13. package/src/components/settings/personal-team/team/team-member-list.tsx +122 -136
  14. package/src/components/story/display/__tests__/display-dropdown.test.tsx +30 -7
  15. package/src/components/story/display/display-dropdown.tsx +6 -7
  16. package/src/components/story/inline-editors/assignee-editor.tsx +72 -57
  17. package/src/components/story/story-list-view.tsx +13 -2
  18. package/src/hooks/__tests__/use-notifications.test.ts +41 -0
  19. package/src/hooks/use-notifications.ts +119 -0
  20. package/src/lib/app-version.ts +4 -1
  21. package/src/lib/auth/auth.config.ts +17 -1
  22. package/src/lib/changelog/sdk-versions-types.ts +1 -0
  23. package/src/lib/changelog/sdk-versions.ts +29 -19
  24. package/src/lib/collections/ai/index.ts +0 -1
  25. package/src/lib/collections/index.ts +0 -1
  26. package/src/plugins/.gen-manifest.json +13 -0
  27. package/src/plugins/modules.gen.ts +20 -0
  28. package/src/plugins/plugins.gen.ts +20 -0
  29. package/src/plugins/ui.gen.ts +10 -0
  30. package/src/routeTree.gen.ts +70 -0
  31. package/src/routes/_login/login/route.tsx +10 -1
  32. package/src/routes/_login/register/route.lazy.tsx +3 -2
  33. package/src/routes/_login/register/route.tsx +5 -0
  34. package/src/routes/_nav/inspiration/route.tsx +8 -0
  35. package/src/routes/_nav/notifications/route.lazy.tsx +23 -0
  36. package/src/routes/_nav/notifications/route.tsx +8 -0
  37. package/src/routes/_nav/prd/$id/route.tsx +9 -0
  38. package/src/routes/_nav/prd/index.tsx +9 -0
  39. package/src/routes/_nav/prd/route.tsx +8 -0
  40. package/src/routes/_nav/settings/-settings-tabs.tsx +2 -1
  41. package/src/routes/_nav/settings/design/route.lazy.tsx +1 -1
  42. package/src/routes/_nav/settings/notifications/route.lazy.tsx +37 -0
  43. package/src/routes/_nav/settings/notifications/route.tsx +20 -0
  44. package/src/routes/_nav/settings/privacy/route.lazy.tsx +2 -2
  45. package/src/routes/_nav/settings/route.lazy.tsx +1 -1
  46. package/src/routes/_nav/stories/$storyId/route.tsx +2 -3
  47. package/src/routes/_nav/tags/$id/route.tsx +8 -0
  48. package/src/routes/_nav/tags/index.tsx +8 -0
  49. package/src/routes/_nav/tags/route.tsx +8 -0
  50. package/src/routes/_nav/tags/settings/route.tsx +9 -0
  51. package/src/routes/api/notifications/stream.ts +88 -0
  52. package/src/routes/invite/$token/route.lazy.tsx +308 -44
  53. package/src/routes/invite/$token/route.tsx +16 -8
  54. package/src/routes/share/prd/$prdId/route.tsx +10 -0
  55. package/src/server/notifications/__tests__/notification-service.test.ts +114 -0
  56. package/src/server/notifications/__tests__/stream.test.ts +30 -0
  57. package/src/server/notifications/event-bus.ts +16 -0
  58. package/src/server/notifications/notification-service.ts +86 -0
  59. package/src/server/resources.ts +10 -2
  60. package/src/server/serverFns/__tests__/compliance.test.ts +6 -6
  61. package/src/server/serverFns/__tests__/notifications.test.ts +63 -0
  62. package/src/server/serverFns/__tests__/team-accept.test.ts +100 -12
  63. package/src/server/serverFns/__tests__/team-invitation.test.ts +130 -60
  64. package/src/server/serverFns/__tests__/team-join-request.test.ts +281 -0
  65. package/src/server/serverFns/__tests__/team-members.test.ts +39 -118
  66. package/src/{lib/collections/ai/ai-providers-collection.ts → server/serverFns/auth/setup.ts} +7 -12
  67. package/src/server/serverFns/billing.ts +23 -2
  68. package/src/server/serverFns/notifications.ts +155 -0
  69. package/src/server/serverFns/story/__tests__/story-groups.test.ts +4 -0
  70. package/src/server/serverFns/story/story-comments.ts +42 -0
  71. package/src/server/serverFns/story/story-crud/labels.ts +45 -6
  72. package/src/server/serverFns/story/story-crud.ts +8 -2
  73. package/src/server/serverFns/story/story-groups.ts +26 -7
  74. package/src/server/serverFns/story/story-search.ts +4 -0
  75. package/src/server/serverFns/story-display-options.ts +15 -4
  76. package/src/server/serverFns/team.ts +573 -53
  77. package/src/start.ts +23 -1
  78. package/vite.shared.ts +13 -0
@@ -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,10 @@
1
+ // AUTO-GENERATED by @allbluecn/kernel — DO NOT EDIT
2
+ import { NavTag } from '@allbluecn/plugins-core/tags/ui'
3
+ import { InspirationNavItem } from '@allbluecn/plugins-core/inspiration/ui'
4
+ import { PrdNav } from '@allbluecn/plugins-core/prd/ui'
5
+ import { type ComponentType } from 'react'
6
+ import type { SettingsTabContribution } from '@allbluecn/kernel'
7
+
8
+ export const navItems: ComponentType[] = [NavTag, InspirationNavItem, PrdNav]
9
+ export const settingsTabs: SettingsTabContribution[] = []
10
+ export const dashboardWidgets: ComponentType[] = []
@@ -31,6 +31,7 @@ import { Route as NavDashboardRouteRouteImport } from './routes/_nav/dashboard/r
31
31
  import { Route as NavDesignRouteRouteImport } from './routes/_nav/design/route'
32
32
  import { Route as NavInspirationRouteRouteImport } from './routes/_nav/inspiration/route'
33
33
  import { Route as NavKnowledgeRouteRouteImport } from './routes/_nav/knowledge/route'
34
+ import { Route as NavNotificationsRouteRouteImport } from './routes/_nav/notifications/route'
34
35
  import { Route as NavNotionLikeRouteRouteImport } from './routes/_nav/notion-like/route'
35
36
  import { Route as NavPrdRouteRouteImport } from './routes/_nav/prd/route'
36
37
  import { Route as NavPricing02RouteRouteImport } from './routes/_nav/pricing-02/route'
@@ -71,6 +72,7 @@ import { Route as NavSettingsBillingRouteRouteImport } from './routes/_nav/setti
71
72
  import { Route as NavSettingsConnectionRouteRouteImport } from './routes/_nav/settings/connection/route'
72
73
  import { Route as NavSettingsDesignRouteRouteImport } from './routes/_nav/settings/design/route'
73
74
  import { Route as NavSettingsGeneralRouteRouteImport } from './routes/_nav/settings/general/route'
75
+ import { Route as NavSettingsNotificationsRouteRouteImport } from './routes/_nav/settings/notifications/route'
74
76
  import { Route as NavSettingsPrivacyRouteRouteImport } from './routes/_nav/settings/privacy/route'
75
77
  import { Route as NavSettingsTeamRouteRouteImport } from './routes/_nav/settings/team/route'
76
78
  import { Route as NavStoriesIndexRouteImport } from './routes/_nav/stories/index'
@@ -86,6 +88,7 @@ import { Route as ApiDesignUploadRouteImport } from './routes/api/design/upload'
86
88
  import { Route as ApiKnowledgeSyncGithubRouteImport } from './routes/api/knowledge/sync-github'
87
89
  import { Route as ApiLicenseActivateRouteRouteImport } from './routes/api/license/activate/route'
88
90
  import { Route as ApiLicenseHeartbeatRouteRouteImport } from './routes/api/license/heartbeat/route'
91
+ import { Route as ApiNotificationsStreamRouteImport } from './routes/api/notifications/stream'
89
92
  import { Route as ServerAnyhubProxySplatRouteImport } from './routes/server/anyhub-proxy/$'
90
93
  import { Route as ShareComplianceIdRouteRouteImport } from './routes/share/compliance/$id/route'
91
94
  import { Route as ShareLawIdRouteRouteImport } from './routes/share/law/$id/route'
@@ -257,6 +260,13 @@ const NavKnowledgeRouteRoute = NavKnowledgeRouteRouteImport.update({
257
260
  path: '/knowledge',
258
261
  getParentRoute: () => NavRouteRoute,
259
262
  } as any)
263
+ const NavNotificationsRouteRoute = NavNotificationsRouteRouteImport.update({
264
+ id: '/notifications',
265
+ path: '/notifications',
266
+ getParentRoute: () => NavRouteRoute,
267
+ } as any).lazy(() =>
268
+ import('./routes/_nav/notifications/route.lazy').then((d) => d.Route),
269
+ )
260
270
  const NavNotionLikeRouteRoute = NavNotionLikeRouteRouteImport.update({
261
271
  id: '/notion-like',
262
272
  path: '/notion-like',
@@ -495,6 +505,16 @@ const NavSettingsGeneralRouteRoute = NavSettingsGeneralRouteRouteImport.update({
495
505
  } as any).lazy(() =>
496
506
  import('./routes/_nav/settings/general/route.lazy').then((d) => d.Route),
497
507
  )
508
+ const NavSettingsNotificationsRouteRoute =
509
+ NavSettingsNotificationsRouteRouteImport.update({
510
+ id: '/notifications',
511
+ path: '/notifications',
512
+ getParentRoute: () => NavSettingsRouteRoute,
513
+ } as any).lazy(() =>
514
+ import('./routes/_nav/settings/notifications/route.lazy').then(
515
+ (d) => d.Route,
516
+ ),
517
+ )
498
518
  const NavSettingsPrivacyRouteRoute = NavSettingsPrivacyRouteRouteImport.update({
499
519
  id: '/privacy',
500
520
  path: '/privacy',
@@ -586,6 +606,11 @@ const ApiLicenseHeartbeatRouteRoute =
586
606
  path: '/api/license/heartbeat',
587
607
  getParentRoute: () => rootRouteImport,
588
608
  } as any)
609
+ const ApiNotificationsStreamRoute = ApiNotificationsStreamRouteImport.update({
610
+ id: '/api/notifications/stream',
611
+ path: '/api/notifications/stream',
612
+ getParentRoute: () => rootRouteImport,
613
+ } as any)
589
614
  const ServerAnyhubProxySplatRoute = ServerAnyhubProxySplatRouteImport.update({
590
615
  id: '/server/anyhub-proxy/$',
591
616
  path: '/server/anyhub-proxy/$',
@@ -824,6 +849,7 @@ export interface FileRoutesByFullPath {
824
849
  '/design': typeof NavDesignRouteRouteWithChildren
825
850
  '/inspiration': typeof NavInspirationRouteRoute
826
851
  '/knowledge': typeof NavKnowledgeRouteRouteWithChildren
852
+ '/notifications': typeof NavNotificationsRouteRoute
827
853
  '/notion-like': typeof NavNotionLikeRouteRoute
828
854
  '/prd': typeof NavPrdRouteRouteWithChildren
829
855
  '/pricing-02': typeof NavPricing02RouteRoute
@@ -859,6 +885,7 @@ export interface FileRoutesByFullPath {
859
885
  '/settings/connection': typeof NavSettingsConnectionRouteRoute
860
886
  '/settings/design': typeof NavSettingsDesignRouteRoute
861
887
  '/settings/general': typeof NavSettingsGeneralRouteRoute
888
+ '/settings/notifications': typeof NavSettingsNotificationsRouteRoute
862
889
  '/settings/privacy': typeof NavSettingsPrivacyRouteRoute
863
890
  '/settings/team': typeof NavSettingsTeamRouteRoute
864
891
  '/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
@@ -875,6 +902,7 @@ export interface FileRoutesByFullPath {
875
902
  '/api/auth/desktop-callback': typeof ApiAuthDesktopCallbackRoute
876
903
  '/api/design/upload': typeof ApiDesignUploadRoute
877
904
  '/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
905
+ '/api/notifications/stream': typeof ApiNotificationsStreamRoute
878
906
  '/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
879
907
  '/design/': typeof NavDesignIndexRoute
880
908
  '/knowledge/': typeof NavKnowledgeIndexRoute
@@ -923,6 +951,7 @@ export interface FileRoutesByTo {
923
951
  '/chat': typeof NavChatRouteRouteWithChildren
924
952
  '/dashboard': typeof NavDashboardRouteRoute
925
953
  '/inspiration': typeof NavInspirationRouteRoute
954
+ '/notifications': typeof NavNotificationsRouteRoute
926
955
  '/notion-like': typeof NavNotionLikeRouteRoute
927
956
  '/pricing-02': typeof NavPricing02RouteRoute
928
957
  '/projects': typeof NavProjectsRouteRouteWithChildren
@@ -946,6 +975,7 @@ export interface FileRoutesByTo {
946
975
  '/settings/connection': typeof NavSettingsConnectionRouteRoute
947
976
  '/settings/design': typeof NavSettingsDesignRouteRoute
948
977
  '/settings/general': typeof NavSettingsGeneralRouteRoute
978
+ '/settings/notifications': typeof NavSettingsNotificationsRouteRoute
949
979
  '/settings/privacy': typeof NavSettingsPrivacyRouteRoute
950
980
  '/settings/team': typeof NavSettingsTeamRouteRoute
951
981
  '/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
@@ -962,6 +992,7 @@ export interface FileRoutesByTo {
962
992
  '/api/auth/desktop-callback': typeof ApiAuthDesktopCallbackRoute
963
993
  '/api/design/upload': typeof ApiDesignUploadRoute
964
994
  '/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
995
+ '/api/notifications/stream': typeof ApiNotificationsStreamRoute
965
996
  '/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
966
997
  '/design': typeof NavDesignIndexRoute
967
998
  '/knowledge': typeof NavKnowledgeIndexRoute
@@ -1016,6 +1047,7 @@ export interface FileRoutesById {
1016
1047
  '/_nav/design': typeof NavDesignRouteRouteWithChildren
1017
1048
  '/_nav/inspiration': typeof NavInspirationRouteRoute
1018
1049
  '/_nav/knowledge': typeof NavKnowledgeRouteRouteWithChildren
1050
+ '/_nav/notifications': typeof NavNotificationsRouteRoute
1019
1051
  '/_nav/notion-like': typeof NavNotionLikeRouteRoute
1020
1052
  '/_nav/prd': typeof NavPrdRouteRouteWithChildren
1021
1053
  '/_nav/pricing-02': typeof NavPricing02RouteRoute
@@ -1051,6 +1083,7 @@ export interface FileRoutesById {
1051
1083
  '/_nav/settings/connection': typeof NavSettingsConnectionRouteRoute
1052
1084
  '/_nav/settings/design': typeof NavSettingsDesignRouteRoute
1053
1085
  '/_nav/settings/general': typeof NavSettingsGeneralRouteRoute
1086
+ '/_nav/settings/notifications': typeof NavSettingsNotificationsRouteRoute
1054
1087
  '/_nav/settings/privacy': typeof NavSettingsPrivacyRouteRoute
1055
1088
  '/_nav/settings/team': typeof NavSettingsTeamRouteRoute
1056
1089
  '/_nav/stories/$storyId': typeof NavStoriesStoryIdRouteRoute
@@ -1067,6 +1100,7 @@ export interface FileRoutesById {
1067
1100
  '/api/auth/desktop-callback': typeof ApiAuthDesktopCallbackRoute
1068
1101
  '/api/design/upload': typeof ApiDesignUploadRoute
1069
1102
  '/api/knowledge/sync-github': typeof ApiKnowledgeSyncGithubRoute
1103
+ '/api/notifications/stream': typeof ApiNotificationsStreamRoute
1070
1104
  '/server/anyhub-proxy/$': typeof ServerAnyhubProxySplatRoute
1071
1105
  '/_nav/design/': typeof NavDesignIndexRoute
1072
1106
  '/_nav/knowledge/': typeof NavKnowledgeIndexRoute
@@ -1119,6 +1153,7 @@ export interface FileRouteTypes {
1119
1153
  | '/design'
1120
1154
  | '/inspiration'
1121
1155
  | '/knowledge'
1156
+ | '/notifications'
1122
1157
  | '/notion-like'
1123
1158
  | '/prd'
1124
1159
  | '/pricing-02'
@@ -1154,6 +1189,7 @@ export interface FileRouteTypes {
1154
1189
  | '/settings/connection'
1155
1190
  | '/settings/design'
1156
1191
  | '/settings/general'
1192
+ | '/settings/notifications'
1157
1193
  | '/settings/privacy'
1158
1194
  | '/settings/team'
1159
1195
  | '/stories/$storyId'
@@ -1170,6 +1206,7 @@ export interface FileRouteTypes {
1170
1206
  | '/api/auth/desktop-callback'
1171
1207
  | '/api/design/upload'
1172
1208
  | '/api/knowledge/sync-github'
1209
+ | '/api/notifications/stream'
1173
1210
  | '/server/anyhub-proxy/$'
1174
1211
  | '/design/'
1175
1212
  | '/knowledge/'
@@ -1218,6 +1255,7 @@ export interface FileRouteTypes {
1218
1255
  | '/chat'
1219
1256
  | '/dashboard'
1220
1257
  | '/inspiration'
1258
+ | '/notifications'
1221
1259
  | '/notion-like'
1222
1260
  | '/pricing-02'
1223
1261
  | '/projects'
@@ -1241,6 +1279,7 @@ export interface FileRouteTypes {
1241
1279
  | '/settings/connection'
1242
1280
  | '/settings/design'
1243
1281
  | '/settings/general'
1282
+ | '/settings/notifications'
1244
1283
  | '/settings/privacy'
1245
1284
  | '/settings/team'
1246
1285
  | '/stories/$storyId'
@@ -1257,6 +1296,7 @@ export interface FileRouteTypes {
1257
1296
  | '/api/auth/desktop-callback'
1258
1297
  | '/api/design/upload'
1259
1298
  | '/api/knowledge/sync-github'
1299
+ | '/api/notifications/stream'
1260
1300
  | '/server/anyhub-proxy/$'
1261
1301
  | '/design'
1262
1302
  | '/knowledge'
@@ -1310,6 +1350,7 @@ export interface FileRouteTypes {
1310
1350
  | '/_nav/design'
1311
1351
  | '/_nav/inspiration'
1312
1352
  | '/_nav/knowledge'
1353
+ | '/_nav/notifications'
1313
1354
  | '/_nav/notion-like'
1314
1355
  | '/_nav/prd'
1315
1356
  | '/_nav/pricing-02'
@@ -1345,6 +1386,7 @@ export interface FileRouteTypes {
1345
1386
  | '/_nav/settings/connection'
1346
1387
  | '/_nav/settings/design'
1347
1388
  | '/_nav/settings/general'
1389
+ | '/_nav/settings/notifications'
1348
1390
  | '/_nav/settings/privacy'
1349
1391
  | '/_nav/settings/team'
1350
1392
  | '/_nav/stories/$storyId'
@@ -1361,6 +1403,7 @@ export interface FileRouteTypes {
1361
1403
  | '/api/auth/desktop-callback'
1362
1404
  | '/api/design/upload'
1363
1405
  | '/api/knowledge/sync-github'
1406
+ | '/api/notifications/stream'
1364
1407
  | '/server/anyhub-proxy/$'
1365
1408
  | '/_nav/design/'
1366
1409
  | '/_nav/knowledge/'
@@ -1413,6 +1456,7 @@ export interface RootRouteChildren {
1413
1456
  ApiAuthDesktopCallbackRoute: typeof ApiAuthDesktopCallbackRoute
1414
1457
  ApiDesignUploadRoute: typeof ApiDesignUploadRoute
1415
1458
  ApiKnowledgeSyncGithubRoute: typeof ApiKnowledgeSyncGithubRoute
1459
+ ApiNotificationsStreamRoute: typeof ApiNotificationsStreamRoute
1416
1460
  ServerAnyhubProxySplatRoute: typeof ServerAnyhubProxySplatRoute
1417
1461
  DesignFilesProjectIdArtboardIdFilenameRoute: typeof DesignFilesProjectIdArtboardIdFilenameRoute
1418
1462
  ApiSharePrdPrdIdEventsRoute: typeof ApiSharePrdPrdIdEventsRoute
@@ -1560,6 +1604,13 @@ declare module '@tanstack/react-router' {
1560
1604
  preLoaderRoute: typeof NavKnowledgeRouteRouteImport
1561
1605
  parentRoute: typeof NavRouteRoute
1562
1606
  }
1607
+ '/_nav/notifications': {
1608
+ id: '/_nav/notifications'
1609
+ path: '/notifications'
1610
+ fullPath: '/notifications'
1611
+ preLoaderRoute: typeof NavNotificationsRouteRouteImport
1612
+ parentRoute: typeof NavRouteRoute
1613
+ }
1563
1614
  '/_nav/notion-like': {
1564
1615
  id: '/_nav/notion-like'
1565
1616
  path: '/notion-like'
@@ -1840,6 +1891,13 @@ declare module '@tanstack/react-router' {
1840
1891
  preLoaderRoute: typeof NavSettingsGeneralRouteRouteImport
1841
1892
  parentRoute: typeof NavSettingsRouteRoute
1842
1893
  }
1894
+ '/_nav/settings/notifications': {
1895
+ id: '/_nav/settings/notifications'
1896
+ path: '/notifications'
1897
+ fullPath: '/settings/notifications'
1898
+ preLoaderRoute: typeof NavSettingsNotificationsRouteRouteImport
1899
+ parentRoute: typeof NavSettingsRouteRoute
1900
+ }
1843
1901
  '/_nav/settings/privacy': {
1844
1902
  id: '/_nav/settings/privacy'
1845
1903
  path: '/privacy'
@@ -1945,6 +2003,13 @@ declare module '@tanstack/react-router' {
1945
2003
  preLoaderRoute: typeof ApiLicenseHeartbeatRouteRouteImport
1946
2004
  parentRoute: typeof rootRouteImport
1947
2005
  }
2006
+ '/api/notifications/stream': {
2007
+ id: '/api/notifications/stream'
2008
+ path: '/api/notifications/stream'
2009
+ fullPath: '/api/notifications/stream'
2010
+ preLoaderRoute: typeof ApiNotificationsStreamRouteImport
2011
+ parentRoute: typeof rootRouteImport
2012
+ }
1948
2013
  '/server/anyhub-proxy/$': {
1949
2014
  id: '/server/anyhub-proxy/$'
1950
2015
  path: '/server/anyhub-proxy/$'
@@ -2408,6 +2473,7 @@ interface NavSettingsRouteRouteChildren {
2408
2473
  NavSettingsConnectionRouteRoute: typeof NavSettingsConnectionRouteRoute
2409
2474
  NavSettingsDesignRouteRoute: typeof NavSettingsDesignRouteRoute
2410
2475
  NavSettingsGeneralRouteRoute: typeof NavSettingsGeneralRouteRoute
2476
+ NavSettingsNotificationsRouteRoute: typeof NavSettingsNotificationsRouteRoute
2411
2477
  NavSettingsPrivacyRouteRoute: typeof NavSettingsPrivacyRouteRoute
2412
2478
  NavSettingsTeamRouteRoute: typeof NavSettingsTeamRouteRoute
2413
2479
  }
@@ -2420,6 +2486,7 @@ const NavSettingsRouteRouteChildren: NavSettingsRouteRouteChildren = {
2420
2486
  NavSettingsConnectionRouteRoute: NavSettingsConnectionRouteRoute,
2421
2487
  NavSettingsDesignRouteRoute: NavSettingsDesignRouteRoute,
2422
2488
  NavSettingsGeneralRouteRoute: NavSettingsGeneralRouteRoute,
2489
+ NavSettingsNotificationsRouteRoute: NavSettingsNotificationsRouteRoute,
2423
2490
  NavSettingsPrivacyRouteRoute: NavSettingsPrivacyRouteRoute,
2424
2491
  NavSettingsTeamRouteRoute: NavSettingsTeamRouteRoute,
2425
2492
  }
@@ -2497,6 +2564,7 @@ interface NavRouteRouteChildren {
2497
2564
  NavDesignRouteRoute: typeof NavDesignRouteRouteWithChildren
2498
2565
  NavInspirationRouteRoute: typeof NavInspirationRouteRoute
2499
2566
  NavKnowledgeRouteRoute: typeof NavKnowledgeRouteRouteWithChildren
2567
+ NavNotificationsRouteRoute: typeof NavNotificationsRouteRoute
2500
2568
  NavNotionLikeRouteRoute: typeof NavNotionLikeRouteRoute
2501
2569
  NavPrdRouteRoute: typeof NavPrdRouteRouteWithChildren
2502
2570
  NavPricing02RouteRoute: typeof NavPricing02RouteRoute
@@ -2519,6 +2587,7 @@ const NavRouteRouteChildren: NavRouteRouteChildren = {
2519
2587
  NavDesignRouteRoute: NavDesignRouteRouteWithChildren,
2520
2588
  NavInspirationRouteRoute: NavInspirationRouteRoute,
2521
2589
  NavKnowledgeRouteRoute: NavKnowledgeRouteRouteWithChildren,
2590
+ NavNotificationsRouteRoute: NavNotificationsRouteRoute,
2522
2591
  NavNotionLikeRouteRoute: NavNotionLikeRouteRoute,
2523
2592
  NavPrdRouteRoute: NavPrdRouteRouteWithChildren,
2524
2593
  NavPricing02RouteRoute: NavPricing02RouteRoute,
@@ -2586,6 +2655,7 @@ const rootRouteChildren: RootRouteChildren = {
2586
2655
  ApiAuthDesktopCallbackRoute: ApiAuthDesktopCallbackRoute,
2587
2656
  ApiDesignUploadRoute: ApiDesignUploadRoute,
2588
2657
  ApiKnowledgeSyncGithubRoute: ApiKnowledgeSyncGithubRoute,
2658
+ ApiNotificationsStreamRoute: ApiNotificationsStreamRoute,
2589
2659
  ServerAnyhubProxySplatRoute: ServerAnyhubProxySplatRoute,
2590
2660
  DesignFilesProjectIdArtboardIdFilenameRoute:
2591
2661
  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,23 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { createLazyFileRoute } from '@tanstack/react-router'
3
+ import { useTranslation } from 'react-i18next'
4
+ import { NotificationList } from '@/components/notifications/notification-list'
5
+
6
+ export const Route = createLazyFileRoute('/_nav/notifications')({
7
+ component: NotificationsPage,
8
+ })
9
+
10
+ function NotificationsPage() {
11
+ const { t } = useTranslation('notifications')
12
+ return (
13
+ <div className="h-full overflow-y-auto">
14
+ <div className="mx-auto flex max-w-3xl flex-col gap-6 p-6">
15
+ <div className="flex flex-col gap-1">
16
+ <h1 className="text-2xl font-semibold">{t('title')}</h1>
17
+ <p className="text-sm text-muted-foreground">{t('description')}</p>
18
+ </div>
19
+ <NotificationList />
20
+ </div>
21
+ </div>
22
+ )
23
+ }
@@ -0,0 +1,8 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ import { createFileRoute } from '@tanstack/react-router'
3
+
4
+ import { listNotificationsFn } from '@/server/serverFns/notifications'
5
+
6
+ export const Route = createFileRoute('/_nav/notifications')({
7
+ loader: () => listNotificationsFn({ data: {} }),
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
 
@@ -45,6 +45,7 @@ const groups: SettingsGroup[] = [
45
45
  { labelKey: 'tabs.accountProfile', path: '/settings/account', icon: User },
46
46
  { labelKey: 'tabs.teamMembers', path: '/settings/team', icon: Users },
47
47
  { labelKey: 'tabs.dataPrivacy', path: '/settings/privacy', icon: ShieldCheck },
48
+ { labelKey: 'tabs.notifications', path: '/settings/notifications', icon: Bell },
48
49
  ],
49
50
  },
50
51
  {
@@ -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('')
@@ -34,7 +34,7 @@ function SettingsLayout() {
34
34
  </div>
35
35
  </aside>
36
36
  <section className="min-w-0 flex-1 overflow-y-auto flex justify-center">
37
- <div className="max-w-3xl w-full">
37
+ <div className="max-w-4xl w-full">
38
38
  <Outlet />
39
39
  </div>
40
40
  </section>
@@ -83,8 +83,8 @@ function StoryDetailSkeleton() {
83
83
 
84
84
  export const Route = createFileRoute("/_nav/stories/$storyId")({
85
85
  loader: async ({ params }) => {
86
+ const story = await getStoryDetailFn({ data: { storyId: params.storyId } });
86
87
  const [
87
- story,
88
88
  users,
89
89
  comments,
90
90
  activities,
@@ -99,8 +99,7 @@ export const Route = createFileRoute("/_nav/stories/$storyId")({
99
99
  prds,
100
100
  docs,
101
101
  ] = await Promise.all([
102
- getStoryDetailFn({ data: { storyId: params.storyId } }),
103
- listUsersBriefFn(),
102
+ listUsersBriefFn({ data: story.projectId ? { projectId: story.projectId } : undefined }),
104
103
  listCommentsFn({ data: { storyId: params.storyId } }),
105
104
  listActivitiesFn({ data: { storyId: params.storyId, take: 50 } }),
106
105
  getStoryNeighborsFn({ data: { storyId: params.storyId } }),
@@ -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 { tags_route_2 } from '@allbluecn/plugins-core/tags/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/tags/$id')({
7
+ component: tags_route_2.Component as any,
8
+ })
@@ -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 { tags_route_1 } from '@allbluecn/plugins-core/tags/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/tags/')({
7
+ component: tags_route_1.Component as any,
8
+ })
@@ -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 { tags_route_0 } from '@allbluecn/plugins-core/tags/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/tags')({
7
+ component: tags_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 { tags_route_3 } from '@allbluecn/plugins-core/tags/routes'
5
+
6
+ export const Route = createFileRoute('/_nav/tags/settings')({
7
+ loader: ((ctx: PluginRouteContext) => tags_route_3.loader(ctx)) as any,
8
+ component: tags_route_3.Component as any,
9
+ })