@rapidmx/web-client 0.15.1 → 0.17.0

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 (318) hide show
  1. package/README.md +381 -373
  2. package/apps/admin/branding/index.tsx +39 -39
  3. package/apps/admin/data-requests/index.tsx +482 -480
  4. package/apps/admin/distribution-lists/new/index.tsx +3 -1
  5. package/apps/admin/domains/[uid].tsx +166 -164
  6. package/apps/admin/domains/new/index.tsx +3 -1
  7. package/apps/admin/escrow-scopes/[uid].tsx +350 -348
  8. package/apps/admin/escrow-scopes/new/index.tsx +3 -1
  9. package/apps/admin/index.tsx +129 -124
  10. package/apps/admin/mailboxes/[uid].tsx +271 -224
  11. package/apps/admin/mailboxes/new/index.tsx +30 -28
  12. package/apps/admin/plugins/index.tsx +15 -15
  13. package/apps/admin/retention-policy/index.tsx +39 -39
  14. package/apps/admin/signing-certificates/index.tsx +343 -343
  15. package/apps/admin/transport-rules/new/index.tsx +3 -1
  16. package/apps/escrow/audit-log/index.tsx +196 -196
  17. package/apps/escrow/matters/[uid].tsx +621 -621
  18. package/apps/escrow/matters/new/index.tsx +3 -1
  19. package/apps/shared/auth/adminAccess.ts +99 -99
  20. package/apps/shared/components/admin/layout/AdminShell.tsx +381 -378
  21. package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +238 -0
  22. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -152
  23. package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +194 -0
  24. package/apps/shared/components/admin/settings/BrandingForm.tsx +423 -423
  25. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +119 -119
  26. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +50 -3
  27. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +198 -198
  28. package/apps/shared/components/admin/settings/PluginsManager.tsx +1545 -1545
  29. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +182 -182
  30. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +288 -288
  31. package/apps/shared/components/admin/setup/SetupWizard.tsx +446 -444
  32. package/apps/shared/components/admin/usePagedList.tsx +129 -129
  33. package/apps/shared/components/calendar/EventEditor.tsx +5 -10
  34. package/apps/shared/components/calendar/EventFormParts.tsx +16 -47
  35. package/apps/shared/components/calendar/EventModal.tsx +206 -206
  36. package/apps/shared/components/calendar/GuestInput.tsx +100 -0
  37. package/apps/shared/components/calendar/MonthView.tsx +185 -185
  38. package/apps/shared/components/calendar/RecurrenceEditor.tsx +227 -227
  39. package/apps/shared/components/calendar/RequestChangeForm.tsx +23 -54
  40. package/apps/shared/components/calendar/SplitDayView.tsx +144 -144
  41. package/apps/shared/components/calendar/TimeGridView.tsx +246 -246
  42. package/apps/shared/components/calendar/allDay.ts +124 -124
  43. package/apps/shared/components/calendar/eventForm.ts +2 -2
  44. package/apps/shared/components/calendar/eventFormat.ts +49 -22
  45. package/apps/shared/components/calendar/layout/CalendarShell.tsx +201 -200
  46. package/apps/shared/components/contacts/ContactForm.tsx +383 -383
  47. package/apps/shared/components/contacts/ContactsSidebar.tsx +1 -1
  48. package/apps/shared/components/contacts/ContactsToolbar.tsx +103 -98
  49. package/apps/shared/components/contacts/layout/ContactsShell.tsx +218 -216
  50. package/apps/shared/components/escrow/layout/EscrowShell.tsx +155 -155
  51. package/apps/shared/components/layout/AppShell.tsx +461 -480
  52. package/apps/shared/components/layout/FloatingActionButton.tsx +31 -0
  53. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +398 -398
  54. package/apps/shared/components/layout/MailboxProvisioning.tsx +168 -168
  55. package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -315
  56. package/apps/shared/components/layout/ThemeSwitch.tsx +84 -84
  57. package/apps/shared/components/layout/UserMenu.tsx +439 -424
  58. package/apps/shared/components/mail/ConversationList.tsx +323 -323
  59. package/apps/shared/components/mail/ConversationThreadPane.tsx +613 -491
  60. package/apps/shared/components/mail/EmptyFolderBar.tsx +41 -0
  61. package/apps/shared/components/mail/MailSelectionBar.tsx +240 -227
  62. package/apps/shared/components/mail/MenuButton.tsx +31 -11
  63. package/apps/shared/components/mail/MessageDetailPane.tsx +1757 -1559
  64. package/apps/shared/components/mail/PermanentDeleteDialog.tsx +47 -0
  65. package/apps/shared/components/mail/compose/ComposeContext.tsx +312 -312
  66. package/apps/shared/components/mail/compose/ComposeToolbar.tsx +422 -422
  67. package/apps/shared/components/mail/compose/ComposeWindow.tsx +1681 -1677
  68. package/apps/shared/components/mail/compose/RecipientInput.tsx +54 -11
  69. package/apps/shared/components/mail/compose/RichTextEditor.tsx +147 -147
  70. package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -60
  71. package/apps/shared/components/mail/compose/quotedBody.ts +161 -161
  72. package/apps/shared/components/mail/layout/FolderBadgeChip.tsx +21 -0
  73. package/apps/shared/components/mail/layout/MailShell.tsx +161 -134
  74. package/apps/shared/components/mail/layout/SidebarSection.tsx +66 -0
  75. package/apps/shared/components/mail/reading/MessageMoreMenu.tsx +258 -0
  76. package/apps/shared/components/mail/reading/MessageSourceDialog.tsx +79 -0
  77. package/apps/shared/components/mail/reading/PendingMessageCard.tsx +68 -0
  78. package/apps/shared/components/mail/reading/messageExport.ts +59 -0
  79. package/apps/shared/components/mail/reading/printMessage.ts +99 -0
  80. package/apps/shared/components/mail/reading/useMessageActions.ts +443 -0
  81. package/apps/shared/components/mail/verificationSeals.ts +125 -125
  82. package/apps/shared/components/rules/RuleBuilder.tsx +311 -311
  83. package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -344
  84. package/apps/shared/components/settings/layout/SettingsShell.tsx +257 -254
  85. package/apps/shared/components/tasks/TasksSidebar.tsx +1 -1
  86. package/apps/shared/components/tasks/layout/TasksShell.tsx +219 -217
  87. package/apps/shared/keyboard/GlobalShortcuts.tsx +51 -51
  88. package/apps/shared/keyboard/ShortcutProvider.tsx +62 -62
  89. package/apps/shared/keyboard/ShortcutsDialog.tsx +84 -84
  90. package/apps/shared/keyboard/dispatch.ts +124 -124
  91. package/apps/shared/keyboard/format.ts +89 -89
  92. package/apps/shared/keyboard/keymap.ts +114 -114
  93. package/apps/shared/keyboard/registry.ts +65 -65
  94. package/apps/shared/keyboard/targets.ts +79 -79
  95. package/apps/shared/mail/folderCounts.ts +17 -0
  96. package/apps/shared/mail/folderOfType.ts +49 -0
  97. package/apps/shared/mail/folderTree.ts +143 -143
  98. package/apps/shared/mail/listAllPages.ts +39 -39
  99. package/apps/shared/mail/newMailNotifications.ts +171 -171
  100. package/apps/shared/mail/outbox/outgoingReplies.ts +192 -0
  101. package/apps/shared/mail/outbox/sendJob.ts +19 -1
  102. package/apps/shared/mail/outbox/sendOutcomes.ts +13 -4
  103. package/apps/shared/mail/permanentDelete.ts +160 -0
  104. package/apps/shared/mail/primaryMailbox.ts +71 -0
  105. package/apps/shared/mail/reportNotices.ts +66 -0
  106. package/apps/shared/mail/senderBlocking.ts +141 -0
  107. package/apps/shared/mail/useCollapsedSections.ts +146 -0
  108. package/apps/shared/mail/useMailConnection.ts +205 -203
  109. package/apps/shared/mail/useMailLiveUpdates.ts +277 -277
  110. package/apps/shared/mail/useMailboxUpdateAccess.ts +60 -0
  111. package/apps/shared/mail/useMarkMessageRead.ts +47 -47
  112. package/apps/shared/mail/useNewMailNotifications.ts +178 -178
  113. package/apps/shared/mail/usePermanentDelete.tsx +160 -0
  114. package/apps/shared/navigation/frameContext.tsx +1 -1
  115. package/apps/shared/navigation/index.ts +43 -0
  116. package/apps/shared/navigation/pageTitle.ts +19 -0
  117. package/apps/shared/notifications/store.ts +560 -560
  118. package/apps/shared/search/LocalIndexLifecycle.tsx +114 -114
  119. package/apps/shared/search/crossMailboxSearch.ts +169 -0
  120. package/apps/shared/search/localIndexBuilder.ts +481 -481
  121. package/apps/shared/signing/enrollmentStorage.ts +33 -33
  122. package/apps/shared/signing/enrollmentTracker.ts +385 -385
  123. package/apps/shared/signing/enrollmentView.ts +251 -251
  124. package/apps/shared/signing/useNow.ts +19 -19
  125. package/apps/shared/signing/useSigningEnrollmentWatcher.ts +90 -90
  126. package/apps/shared/styles/app.css +396 -386
  127. package/apps/www/_shell.tsx +82 -0
  128. package/apps/www/calendar/index.tsx +581 -571
  129. package/apps/www/contacts/[uid].tsx +112 -109
  130. package/apps/www/contacts/index.tsx +14 -3
  131. package/apps/www/index.tsx +2962 -2479
  132. package/apps/www/messages/[uid].tsx +139 -135
  133. package/apps/www/settings/appearance/index.tsx +5 -2
  134. package/apps/www/settings/auto-reply/index.tsx +136 -133
  135. package/apps/www/settings/blocked-senders/index.tsx +303 -0
  136. package/apps/www/settings/encryption/index.tsx +1290 -1287
  137. package/apps/www/settings/filters/[uid].tsx +179 -176
  138. package/apps/www/settings/filters/index.tsx +105 -102
  139. package/apps/www/settings/filters/new/index.tsx +165 -140
  140. package/apps/www/settings/labels/index.tsx +207 -204
  141. package/apps/www/settings/privacy/index.tsx +495 -492
  142. package/apps/www/settings/profile/index.tsx +251 -248
  143. package/apps/www/settings/read-receipts/index.tsx +150 -147
  144. package/apps/www/settings/sharing/index.tsx +259 -256
  145. package/apps/www/settings/signatures/[uid].tsx +175 -172
  146. package/apps/www/settings/signatures/index.tsx +91 -88
  147. package/apps/www/settings/signatures/new/index.tsx +138 -135
  148. package/apps/www/tasks/index.tsx +654 -649
  149. package/dist/apps/admin/data-requests/index.js +1 -1
  150. package/dist/apps/admin/distribution-lists/new/index.js +3 -1
  151. package/dist/apps/admin/domains/[uid].js +3 -1
  152. package/dist/apps/admin/domains/new/index.js +3 -1
  153. package/dist/apps/admin/escrow-scopes/[uid].js +3 -1
  154. package/dist/apps/admin/escrow-scopes/new/index.js +3 -1
  155. package/dist/apps/admin/index.js +5 -2
  156. package/dist/apps/admin/mailboxes/[uid].js +15 -3
  157. package/dist/apps/admin/mailboxes/new/index.js +3 -1
  158. package/dist/apps/admin/transport-rules/new/index.js +3 -1
  159. package/dist/apps/escrow/matters/new/index.js +3 -1
  160. package/dist/apps/shared/components/admin/layout/AdminShell.js +6 -3
  161. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +35 -0
  162. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +115 -0
  163. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.d.ts +16 -0
  164. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +92 -0
  165. package/dist/apps/shared/components/admin/settings/BrandingForm.js +3 -3
  166. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +25 -3
  167. package/dist/apps/shared/components/admin/setup/SetupWizard.js +3 -1
  168. package/dist/apps/shared/components/calendar/EventEditor.js +5 -10
  169. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +3 -2
  170. package/dist/apps/shared/components/calendar/EventFormParts.js +5 -16
  171. package/dist/apps/shared/components/calendar/GuestInput.d.ts +45 -0
  172. package/dist/apps/shared/components/calendar/GuestInput.js +30 -0
  173. package/dist/apps/shared/components/calendar/RequestChangeForm.js +11 -22
  174. package/dist/apps/shared/components/calendar/eventForm.d.ts +2 -2
  175. package/dist/apps/shared/components/calendar/eventFormat.d.ts +21 -8
  176. package/dist/apps/shared/components/calendar/eventFormat.js +50 -23
  177. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +5 -4
  178. package/dist/apps/shared/components/contacts/ContactsSidebar.js +1 -1
  179. package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +3 -1
  180. package/dist/apps/shared/components/contacts/ContactsToolbar.js +4 -2
  181. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +7 -5
  182. package/dist/apps/shared/components/layout/AppShell.d.ts +8 -11
  183. package/dist/apps/shared/components/layout/AppShell.js +24 -33
  184. package/dist/apps/shared/components/layout/FloatingActionButton.d.ts +13 -0
  185. package/dist/apps/shared/components/layout/FloatingActionButton.js +9 -0
  186. package/dist/apps/shared/components/layout/UserMenu.d.ts +4 -1
  187. package/dist/apps/shared/components/layout/UserMenu.js +6 -5
  188. package/dist/apps/shared/components/mail/ConversationThreadPane.js +127 -22
  189. package/dist/apps/shared/components/mail/EmptyFolderBar.d.ts +18 -0
  190. package/dist/apps/shared/components/mail/EmptyFolderBar.js +10 -0
  191. package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +14 -4
  192. package/dist/apps/shared/components/mail/MailSelectionBar.js +11 -13
  193. package/dist/apps/shared/components/mail/MenuButton.d.ts +9 -2
  194. package/dist/apps/shared/components/mail/MenuButton.js +15 -11
  195. package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +5 -0
  196. package/dist/apps/shared/components/mail/MessageDetailPane.js +147 -7
  197. package/dist/apps/shared/components/mail/PermanentDeleteDialog.d.ts +19 -0
  198. package/dist/apps/shared/components/mail/PermanentDeleteDialog.js +11 -0
  199. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +8 -4
  200. package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +21 -1
  201. package/dist/apps/shared/components/mail/compose/RecipientInput.js +18 -10
  202. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.d.ts +6 -0
  203. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.js +9 -0
  204. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +16 -7
  205. package/dist/apps/shared/components/mail/layout/MailShell.js +78 -65
  206. package/dist/apps/shared/components/mail/layout/SidebarSection.d.ts +23 -0
  207. package/dist/apps/shared/components/mail/layout/SidebarSection.js +16 -0
  208. package/dist/apps/shared/components/mail/reading/MessageMoreMenu.d.ts +56 -0
  209. package/dist/apps/shared/components/mail/reading/MessageMoreMenu.js +153 -0
  210. package/dist/apps/shared/components/mail/reading/MessageSourceDialog.d.ts +27 -0
  211. package/dist/apps/shared/components/mail/reading/MessageSourceDialog.js +27 -0
  212. package/dist/apps/shared/components/mail/reading/PendingMessageCard.d.ts +14 -0
  213. package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +16 -0
  214. package/dist/apps/shared/components/mail/reading/messageExport.d.ts +19 -0
  215. package/dist/apps/shared/components/mail/reading/messageExport.js +51 -0
  216. package/dist/apps/shared/components/mail/reading/printMessage.d.ts +30 -0
  217. package/dist/apps/shared/components/mail/reading/printMessage.js +70 -0
  218. package/dist/apps/shared/components/mail/reading/useMessageActions.d.ts +57 -0
  219. package/dist/apps/shared/components/mail/reading/useMessageActions.js +366 -0
  220. package/dist/apps/shared/components/settings/layout/SettingsShell.js +10 -7
  221. package/dist/apps/shared/components/tasks/TasksSidebar.js +1 -1
  222. package/dist/apps/shared/components/tasks/layout/TasksShell.js +7 -5
  223. package/dist/apps/shared/keyboard/GlobalShortcuts.js +1 -1
  224. package/dist/apps/shared/mail/folderCounts.d.ts +10 -0
  225. package/dist/apps/shared/mail/folderCounts.js +12 -0
  226. package/dist/apps/shared/mail/folderOfType.d.ts +13 -0
  227. package/dist/apps/shared/mail/folderOfType.js +40 -0
  228. package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +80 -0
  229. package/dist/apps/shared/mail/outbox/outgoingReplies.js +131 -0
  230. package/dist/apps/shared/mail/outbox/sendJob.d.ts +5 -1
  231. package/dist/apps/shared/mail/outbox/sendJob.js +14 -1
  232. package/dist/apps/shared/mail/outbox/sendOutcomes.js +13 -4
  233. package/dist/apps/shared/mail/permanentDelete.d.ts +62 -0
  234. package/dist/apps/shared/mail/permanentDelete.js +127 -0
  235. package/dist/apps/shared/mail/primaryMailbox.d.ts +29 -0
  236. package/dist/apps/shared/mail/primaryMailbox.js +61 -0
  237. package/dist/apps/shared/mail/reportNotices.d.ts +21 -0
  238. package/dist/apps/shared/mail/reportNotices.js +47 -0
  239. package/dist/apps/shared/mail/senderBlocking.d.ts +26 -0
  240. package/dist/apps/shared/mail/senderBlocking.js +92 -0
  241. package/dist/apps/shared/mail/useCollapsedSections.d.ts +32 -0
  242. package/dist/apps/shared/mail/useCollapsedSections.js +110 -0
  243. package/dist/apps/shared/mail/useMailConnection.js +3 -1
  244. package/dist/apps/shared/mail/useMailboxUpdateAccess.d.ts +11 -0
  245. package/dist/apps/shared/mail/useMailboxUpdateAccess.js +52 -0
  246. package/dist/apps/shared/mail/usePermanentDelete.d.ts +35 -0
  247. package/dist/apps/shared/mail/usePermanentDelete.js +96 -0
  248. package/dist/apps/shared/navigation/frameContext.d.ts +1 -1
  249. package/dist/apps/shared/navigation/index.d.ts +16 -0
  250. package/dist/apps/shared/navigation/index.js +34 -0
  251. package/dist/apps/shared/navigation/pageTitle.d.ts +11 -0
  252. package/dist/apps/shared/navigation/pageTitle.js +12 -0
  253. package/dist/apps/shared/search/crossMailboxSearch.d.ts +72 -0
  254. package/dist/apps/shared/search/crossMailboxSearch.js +136 -0
  255. package/dist/apps/shared/styles/app.css +396 -386
  256. package/dist/apps/www/_shell.d.ts +26 -0
  257. package/dist/apps/www/_shell.js +31 -0
  258. package/dist/apps/www/calendar/index.d.ts +7 -2
  259. package/dist/apps/www/calendar/index.js +7 -4
  260. package/dist/apps/www/contacts/[uid].d.ts +14 -3
  261. package/dist/apps/www/contacts/[uid].js +5 -3
  262. package/dist/apps/www/contacts/index.d.ts +7 -2
  263. package/dist/apps/www/contacts/index.js +8 -4
  264. package/dist/apps/www/index.d.ts +7 -2
  265. package/dist/apps/www/index.js +542 -207
  266. package/dist/apps/www/messages/[uid].d.ts +14 -3
  267. package/dist/apps/www/messages/[uid].js +7 -5
  268. package/dist/apps/www/settings/appearance/index.d.ts +8 -2
  269. package/dist/apps/www/settings/appearance/index.js +4 -2
  270. package/dist/apps/www/settings/auto-reply/index.d.ts +7 -2
  271. package/dist/apps/www/settings/auto-reply/index.js +4 -2
  272. package/dist/apps/www/settings/blocked-senders/index.d.ts +9 -0
  273. package/dist/apps/www/settings/blocked-senders/index.js +134 -0
  274. package/dist/apps/www/settings/encryption/index.d.ts +7 -2
  275. package/dist/apps/www/settings/encryption/index.js +4 -2
  276. package/dist/apps/www/settings/filters/[uid].d.ts +7 -2
  277. package/dist/apps/www/settings/filters/[uid].js +4 -2
  278. package/dist/apps/www/settings/filters/index.d.ts +7 -2
  279. package/dist/apps/www/settings/filters/index.js +4 -2
  280. package/dist/apps/www/settings/filters/new/index.d.ts +7 -2
  281. package/dist/apps/www/settings/filters/new/index.js +28 -5
  282. package/dist/apps/www/settings/labels/index.d.ts +7 -2
  283. package/dist/apps/www/settings/labels/index.js +4 -2
  284. package/dist/apps/www/settings/privacy/index.d.ts +7 -2
  285. package/dist/apps/www/settings/privacy/index.js +4 -2
  286. package/dist/apps/www/settings/profile/index.d.ts +7 -2
  287. package/dist/apps/www/settings/profile/index.js +4 -2
  288. package/dist/apps/www/settings/read-receipts/index.d.ts +7 -2
  289. package/dist/apps/www/settings/read-receipts/index.js +4 -2
  290. package/dist/apps/www/settings/sharing/index.d.ts +7 -2
  291. package/dist/apps/www/settings/sharing/index.js +4 -2
  292. package/dist/apps/www/settings/signatures/[uid].d.ts +7 -2
  293. package/dist/apps/www/settings/signatures/[uid].js +4 -2
  294. package/dist/apps/www/settings/signatures/index.d.ts +7 -2
  295. package/dist/apps/www/settings/signatures/index.js +4 -2
  296. package/dist/apps/www/settings/signatures/new/index.d.ts +7 -2
  297. package/dist/apps/www/settings/signatures/new/index.js +5 -3
  298. package/dist/apps/www/tasks/index.d.ts +7 -2
  299. package/dist/apps/www/tasks/index.js +5 -3
  300. package/package.json +4 -2
  301. package/apps/shared/navigation/AppRouter.tsx +0 -300
  302. package/apps/shared/navigation/idle.ts +0 -45
  303. package/apps/shared/navigation/routerContext.tsx +0 -83
  304. package/apps/shared/navigation/routes.ts +0 -72
  305. package/apps/www/_routedPage.tsx +0 -24
  306. package/apps/www/_routes.ts +0 -37
  307. package/dist/apps/shared/navigation/AppRouter.d.ts +0 -52
  308. package/dist/apps/shared/navigation/AppRouter.js +0 -242
  309. package/dist/apps/shared/navigation/idle.d.ts +0 -14
  310. package/dist/apps/shared/navigation/idle.js +0 -43
  311. package/dist/apps/shared/navigation/routerContext.d.ts +0 -37
  312. package/dist/apps/shared/navigation/routerContext.js +0 -56
  313. package/dist/apps/shared/navigation/routes.d.ts +0 -32
  314. package/dist/apps/shared/navigation/routes.js +0 -37
  315. package/dist/apps/www/_routedPage.d.ts +0 -12
  316. package/dist/apps/www/_routedPage.js +0 -19
  317. package/dist/apps/www/_routes.d.ts +0 -11
  318. package/dist/apps/www/_routes.js +0 -31
@@ -1,224 +1,271 @@
1
- ///////////////////////////////////////////////////////////////////////////////
2
- // Copyright (C) 2026 Jean-Philippe Steinmetz
3
- // SPDX-License-Identifier: MPL-2.0
4
- ///////////////////////////////////////////////////////////////////////////////
5
- import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
7
- import { deleteMailbox, getMailbox, impersonateUser, Mailbox } from "@rapidmx/react-shared/mail/mailApi.js";
8
- import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
- import ShareAccessCard from "../../shared/components/admin/mailboxes/ShareAccessCard.js";
10
- import ResourceSettingsCard from "../../shared/components/admin/mailboxes/ResourceSettingsCard.js";
11
- import EscrowScopeCard from "../../shared/components/admin/mailboxes/EscrowScopeCard.js";
12
- import Alert from "@rapidmx/react-shared/components/feedback/Alert.js";
13
- import Button from "@rapidmx/react-shared/components/buttons/Button.js";
14
- import Modal from "@rapidmx/react-shared/components/overlays/Modal.js";
15
-
16
- function formatBytes(bytes: number): string {
17
- if (bytes >= 1_000_000_000) return `${(bytes / 1_000_000_000).toFixed(2)} GB`;
18
- if (bytes >= 1_000_000) return `${(bytes / 1_000_000).toFixed(1)} MB`;
19
- if (bytes >= 1_000) return `${(bytes / 1_000).toFixed(1)} KB`;
20
- return `${bytes} B`;
21
- }
22
-
23
- export default function MailboxDetailPage(props: Omit<AdminShellProps, "active"> & { params: { uid: string } }) {
24
- return (
25
- <AdminShell {...props} active="mailboxes">
26
- <MailboxDetailContent uid={props.params.uid} impersonationBaseUrl={props.impersonationBaseUrl} currentUserUid={props.userUid} />
27
- </AdminShell>
28
- );
29
- }
30
-
31
- function MailboxDetailContent({
32
- uid,
33
- impersonationBaseUrl,
34
- currentUserUid,
35
- }: { uid: string; currentUserUid?: string } & Pick<AdminShellProps, "impersonationBaseUrl">) {
36
- const [mailbox, setMailbox] = useState<Mailbox | null>(null);
37
- const [loading, setLoading] = useState(true);
38
- const [error, setError] = useState<string | null>(null);
39
- const [confirmingAccess, setConfirmingAccess] = useState(false);
40
- const [impersonating, setImpersonating] = useState(false);
41
- const [accessError, setAccessError] = useState<string | null>(null);
42
- const [confirmingDelete, setConfirmingDelete] = useState(false);
43
- const [deleting, setDeleting] = useState(false);
44
- const [deleteError, setDeleteError] = useState<string | null>(null);
45
-
46
- // Ignored while the action is under way (Escape/Close; Cancel is disabled then too), so its result or error
47
- // can't land on a modal reopened afterwards.
48
- function closeAccessModal() {
49
- if (impersonating) return;
50
- setConfirmingAccess(false);
51
- setAccessError(null);
52
- }
53
-
54
- // Only ever invoked from the impersonation-confirmation modal below, which only renders for a loaded mailbox that has
55
- // an owner. A failure stays in the modal rather than replacing the whole page.
56
- async function handleAccessMailbox() {
57
- setImpersonating(true);
58
- setAccessError(null);
59
- try {
60
- await impersonateUser(impersonationBaseUrl ?? "", mailbox!.ownerUserUid!);
61
- window.location.href = "/";
62
- } catch (err) {
63
- setAccessError(err instanceof ApiRequestError ? err.message : "Could not impersonate this user.");
64
- setImpersonating(false);
65
- }
66
- }
67
-
68
- function closeDeleteModal() {
69
- if (deleting) return;
70
- setConfirmingDelete(false);
71
- }
72
-
73
- // Only ever invoked from the delete-confirmation modal below, which itself only renders once
74
- // `mailbox` is resolved (the `error || !mailbox` branch below returns before this content mounts).
75
- async function handleDelete() {
76
- setDeleting(true);
77
- setDeleteError(null);
78
- try {
79
- await deleteMailbox(mailbox!.uid, mailbox!.version);
80
- window.location.href = "/admin";
81
- } catch (err) {
82
- // Most commonly a 409 if this mailbox is a custodian on an open legal hold (restapi's own
83
- // `assertNotOnLegalHold()`, naming the blocking Matter uid(s)) - surfaced as-is, same as
84
- // every other destructive-action error in this codebase, rather than special-cased here.
85
- setDeleteError(err instanceof ApiRequestError ? err.message : "Could not delete this mailbox.");
86
- setDeleting(false);
87
- }
88
- }
89
-
90
- useEffect(() => {
91
- setLoading(true);
92
- setError(null);
93
- // The administration scope: administrative metadata only - the console never shows a mailbox's mail or settings.
94
- getMailbox(uid, { scope: "admin" })
95
- .then(setMailbox)
96
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load this mailbox."))
97
- .finally(() => setLoading(false));
98
- }, [uid]);
99
-
100
- if (loading) {
101
- return <p className="text-sm text-text-muted">Loading&hellip;</p>;
102
- }
103
- if (error || !mailbox) {
104
- return <Alert>{error ?? "Mailbox not found."}</Alert>;
105
- }
106
-
107
- const quarantineHref = `/admin/quarantine?mailboxUid=${encodeURIComponent(mailbox.uid)}`;
108
- const ingestQueueHref = `/admin/ingest-queue?mailboxUid=${encodeURIComponent(mailbox.uid)}`;
109
-
110
- return (
111
- <div className="max-w-3xl flex flex-col gap-5">
112
- <div className="flex items-start justify-between gap-4">
113
- <div>
114
- <a href="/admin" className="text-sm text-primary-dark hover:underline">
115
- &larr; All mailboxes
116
- </a>
117
- <h1 className="text-xl font-bold tracking-tight mt-1">{mailbox.primarySmtpAddress}</h1>
118
- </div>
119
- <div className="flex gap-3 shrink-0">
120
- {mailbox.ownerUserUid && (
121
- <Button type="button" variant="secondary" className="!w-auto" onClick={() => setConfirmingAccess(true)}>
122
- Impersonate this user
123
- </Button>
124
- )}
125
- <Button
126
- type="button"
127
- variant="secondary"
128
- className="!w-auto !border-danger !text-danger hover:!border-danger hover:!text-danger"
129
- onClick={() => setConfirmingDelete(true)}
130
- >
131
- Delete mailbox
132
- </Button>
133
- </div>
134
- </div>
135
-
136
- <p className="text-sm text-text-muted">
137
- The console shows administrative details only - never a mailbox&rsquo;s mail or settings.
138
- {mailbox.ownerUserUid
139
- ? " To see this mailbox as its owner sees it, impersonate them: that is recorded, and you can stop at any time."
140
- : " This shared mailbox has no owner: add yourself under Shared access to open it in the mail client."}
141
- </p>
142
-
143
- <div className="bg-surface border border-border rounded-md p-6">
144
- <dl className="grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-3 text-sm">
145
- <dt className="text-text-muted">Display name</dt>
146
- <dd>{mailbox.displayName}</dd>
147
- <dt className="text-text-muted">Owner</dt>
148
- <dd>{mailbox.ownerUserUid ?? "None (shared mailbox)"}</dd>
149
- <dt className="text-text-muted">Timezone</dt>
150
- <dd>{mailbox.timezone}</dd>
151
- <dt className="text-text-muted">Quota</dt>
152
- <dd>
153
- {formatBytes(mailbox.usedBytes)} / {formatBytes(mailbox.quotaBytes)}
154
- </dd>
155
- <dt className="text-text-muted">Alias addresses</dt>
156
- <dd>{mailbox.aliasAddresses.length > 0 ? mailbox.aliasAddresses.join(", ") : "None"}</dd>
157
- {mailbox.isResource && (
158
- <>
159
- <dt className="text-text-muted">Resource type</dt>
160
- <dd className="capitalize">{mailbox.resourceType ?? "room"}</dd>
161
- </>
162
- )}
163
- <dt className="text-text-muted">Created</dt>
164
- <dd>{new Date(mailbox.dateCreated).toLocaleString()}</dd>
165
- </dl>
166
- <div className="flex gap-4 mt-5 pt-5 border-t border-border text-sm font-medium">
167
- <a href={quarantineHref} className="text-primary-dark hover:underline">
168
- View quarantine
169
- </a>
170
- <a href={ingestQueueHref} className="text-primary-dark hover:underline">
171
- View ingest queue
172
- </a>
173
- </div>
174
- </div>
175
-
176
- <ShareAccessCard mailboxUid={mailbox.uid} ownerUserUid={mailbox.ownerUserUid} currentUserUid={currentUserUid} />
177
-
178
- <EscrowScopeCard mailbox={mailbox} onUpdate={setMailbox} />
179
-
180
- {mailbox.isResource && <ResourceSettingsCard mailbox={mailbox} onUpdate={setMailbox} />}
181
-
182
- <Modal open={confirmingAccess} onClose={closeAccessModal} title="Impersonate this user">
183
- <p className="text-sm mb-3">
184
- You&rsquo;ll be signed in as <strong className="break-all">{mailbox.ownerUserUid}</strong>, the owner
185
- of <strong className="break-all">{mailbox.primarySmtpAddress}</strong>, and see everything they can -
186
- and act as them, until you stop impersonating. This is the only way an administrator sees another
187
- user&rsquo;s mail.
188
- </p>
189
- {accessError && <Alert>{accessError}</Alert>}
190
- <div className="flex gap-3 justify-end mt-5">
191
- <Button type="button" variant="secondary" className="!w-auto" disabled={impersonating} onClick={closeAccessModal}>
192
- Cancel
193
- </Button>
194
- <Button type="button" className="!w-auto" loading={impersonating} disabled={impersonating} onClick={handleAccessMailbox}>
195
- Impersonate
196
- </Button>
197
- </div>
198
- </Modal>
199
-
200
- <Modal open={confirmingDelete} onClose={closeDeleteModal} title="Delete mailbox">
201
- <p className="text-sm mb-5">
202
- Are you sure you want to delete <strong>{mailbox.primarySmtpAddress}</strong>? This permanently
203
- deletes the mailbox and everything in it, and cannot be undone. It fails if this mailbox is a
204
- custodian on an active legal hold.
205
- </p>
206
- {deleteError && <Alert>{deleteError}</Alert>}
207
- <div className="flex gap-3 justify-end mt-5">
208
- <Button type="button" variant="secondary" className="!w-auto" disabled={deleting} onClick={closeDeleteModal}>
209
- Cancel
210
- </Button>
211
- <Button
212
- type="button"
213
- className="!w-auto !bg-none !bg-danger !border-danger hover:!bg-danger"
214
- loading={deleting}
215
- disabled={deleting}
216
- onClick={handleDelete}
217
- >
218
- Delete
219
- </Button>
220
- </div>
221
- </Modal>
222
- </div>
223
- );
224
- }
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React, { useEffect, useState } from "react";
6
+ import { useRouter } from "@rapidrest/react/client";
7
+ import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
8
+ import { deleteMailbox, getMailbox, impersonateUser, Mailbox } from "@rapidmx/react-shared/mail/mailApi.js";
9
+ import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
10
+ import ShareAccessCard from "../../shared/components/admin/mailboxes/ShareAccessCard.js";
11
+ import ResourceSettingsCard from "../../shared/components/admin/mailboxes/ResourceSettingsCard.js";
12
+ import EscrowScopeCard from "../../shared/components/admin/mailboxes/EscrowScopeCard.js";
13
+ import Alert from "@rapidmx/react-shared/components/feedback/Alert.js";
14
+ import Button from "@rapidmx/react-shared/components/buttons/Button.js";
15
+ import Modal from "@rapidmx/react-shared/components/overlays/Modal.js";
16
+
17
+ function formatBytes(bytes: number): string {
18
+ if (bytes >= 1_000_000_000) return `${(bytes / 1_000_000_000).toFixed(2)} GB`;
19
+ if (bytes >= 1_000_000) return `${(bytes / 1_000_000).toFixed(1)} MB`;
20
+ if (bytes >= 1_000) return `${(bytes / 1_000).toFixed(1)} KB`;
21
+ return `${bytes} B`;
22
+ }
23
+
24
+ export default function MailboxDetailPage(props: Omit<AdminShellProps, "active"> & { params: { uid: string } }) {
25
+ return (
26
+ <AdminShell {...props} active="mailboxes">
27
+ <MailboxDetailContent uid={props.params.uid} impersonationBaseUrl={props.impersonationBaseUrl} currentUserUid={props.userUid} />
28
+ </AdminShell>
29
+ );
30
+ }
31
+
32
+ function MailboxDetailContent({
33
+ uid,
34
+ impersonationBaseUrl,
35
+ currentUserUid,
36
+ }: { uid: string; currentUserUid?: string } & Pick<AdminShellProps, "impersonationBaseUrl">) {
37
+ const [mailbox, setMailbox] = useState<Mailbox | null>(null);
38
+ const { navigate } = useRouter();
39
+ const [loading, setLoading] = useState(true);
40
+ const [error, setError] = useState<string | null>(null);
41
+ const [confirmingAccess, setConfirmingAccess] = useState(false);
42
+ const [impersonating, setImpersonating] = useState(false);
43
+ const [accessError, setAccessError] = useState<string | null>(null);
44
+ const [confirmingDelete, setConfirmingDelete] = useState(false);
45
+ const [deleting, setDeleting] = useState(false);
46
+ const [deleteError, setDeleteError] = useState<string | null>(null);
47
+ // Deleting keeps the mailbox's data; this also erases it in the same step, after the address is typed to confirm.
48
+ const [eraseData, setEraseData] = useState(false);
49
+ const [typedAddress, setTypedAddress] = useState("");
50
+
51
+ // Ignored while the action is under way (Escape/Close; Cancel is disabled then too), so its result or error
52
+ // can't land on a modal reopened afterwards.
53
+ function closeAccessModal() {
54
+ if (impersonating) return;
55
+ setConfirmingAccess(false);
56
+ setAccessError(null);
57
+ }
58
+
59
+ // Only ever invoked from the impersonation-confirmation modal below, which only renders for a loaded mailbox that has
60
+ // an owner. A failure stays in the modal rather than replacing the whole page.
61
+ async function handleAccessMailbox() {
62
+ setImpersonating(true);
63
+ setAccessError(null);
64
+ try {
65
+ await impersonateUser(impersonationBaseUrl ?? "", mailbox!.ownerUserUid!);
66
+ window.location.href = "/";
67
+ } catch (err) {
68
+ setAccessError(err instanceof ApiRequestError ? err.message : "Could not impersonate this user.");
69
+ setImpersonating(false);
70
+ }
71
+ }
72
+
73
+ function closeDeleteModal() {
74
+ if (deleting) return;
75
+ setConfirmingDelete(false);
76
+ setEraseData(false);
77
+ setTypedAddress("");
78
+ setDeleteError(null);
79
+ }
80
+
81
+ // Only ever invoked from the delete-confirmation modal below, which itself only renders once
82
+ // `mailbox` is resolved (the `error || !mailbox` branch below returns before this content mounts).
83
+ async function handleDelete() {
84
+ setDeleting(true);
85
+ setDeleteError(null);
86
+ try {
87
+ await deleteMailbox(mailbox!.uid, mailbox!.version, { erase: eraseData });
88
+ // The Mailboxes page it goes to lists what a delete without `erase` kept, and how far an erasure has got.
89
+ void navigate("/admin");
90
+ } catch (err) {
91
+ // Most commonly a 409 if this mailbox is a custodian on an open legal hold (restapi's own
92
+ // `assertNotOnLegalHold()`, naming the blocking Matter uid(s)) - surfaced as-is, same as
93
+ // every other destructive-action error in this codebase, rather than special-cased here.
94
+ setDeleteError(err instanceof ApiRequestError ? err.message : "Could not delete this mailbox.");
95
+ setDeleting(false);
96
+ }
97
+ }
98
+
99
+ useEffect(() => {
100
+ setLoading(true);
101
+ setError(null);
102
+ // The administration scope: administrative metadata only - the console never shows a mailbox's mail or settings.
103
+ getMailbox(uid, { scope: "admin" })
104
+ .then(setMailbox)
105
+ .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load this mailbox."))
106
+ .finally(() => setLoading(false));
107
+ }, [uid]);
108
+
109
+ if (loading) {
110
+ return <p className="text-sm text-text-muted">Loading&hellip;</p>;
111
+ }
112
+ if (error || !mailbox) {
113
+ return <Alert>{error ?? "Mailbox not found."}</Alert>;
114
+ }
115
+
116
+ const quarantineHref = `/admin/quarantine?mailboxUid=${encodeURIComponent(mailbox.uid)}`;
117
+ const ingestQueueHref = `/admin/ingest-queue?mailboxUid=${encodeURIComponent(mailbox.uid)}`;
118
+
119
+ return (
120
+ <div className="max-w-3xl flex flex-col gap-5">
121
+ <div className="flex items-start justify-between gap-4">
122
+ <div>
123
+ <a href="/admin" className="text-sm text-primary-dark hover:underline">
124
+ &larr; All mailboxes
125
+ </a>
126
+ <h1 className="text-xl font-bold tracking-tight mt-1">{mailbox.primarySmtpAddress}</h1>
127
+ </div>
128
+ <div className="flex gap-3 shrink-0">
129
+ {mailbox.ownerUserUid && (
130
+ <Button type="button" variant="secondary" className="!w-auto" onClick={() => setConfirmingAccess(true)}>
131
+ Impersonate this user
132
+ </Button>
133
+ )}
134
+ <Button
135
+ type="button"
136
+ variant="secondary"
137
+ className="!w-auto !border-danger !text-danger hover:!border-danger hover:!text-danger"
138
+ onClick={() => setConfirmingDelete(true)}
139
+ >
140
+ Delete mailbox
141
+ </Button>
142
+ </div>
143
+ </div>
144
+
145
+ <p className="text-sm text-text-muted">
146
+ The console shows administrative details only - never a mailbox&rsquo;s mail or settings.
147
+ {mailbox.ownerUserUid
148
+ ? " To see this mailbox as its owner sees it, impersonate them: that is recorded, and you can stop at any time."
149
+ : " This shared mailbox has no owner: add yourself under Shared access to open it in the mail client."}
150
+ </p>
151
+
152
+ <div className="bg-surface border border-border rounded-md p-6">
153
+ <dl className="grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-3 text-sm">
154
+ <dt className="text-text-muted">Display name</dt>
155
+ <dd>{mailbox.displayName}</dd>
156
+ <dt className="text-text-muted">Owner</dt>
157
+ <dd>{mailbox.ownerUserUid ?? "None (shared mailbox)"}</dd>
158
+ <dt className="text-text-muted">Timezone</dt>
159
+ <dd>{mailbox.timezone}</dd>
160
+ <dt className="text-text-muted">Quota</dt>
161
+ <dd>
162
+ {formatBytes(mailbox.usedBytes)} / {formatBytes(mailbox.quotaBytes)}
163
+ </dd>
164
+ <dt className="text-text-muted">Alias addresses</dt>
165
+ <dd>{mailbox.aliasAddresses.length > 0 ? mailbox.aliasAddresses.join(", ") : "None"}</dd>
166
+ {mailbox.isResource && (
167
+ <>
168
+ <dt className="text-text-muted">Resource type</dt>
169
+ <dd className="capitalize">{mailbox.resourceType ?? "room"}</dd>
170
+ </>
171
+ )}
172
+ <dt className="text-text-muted">Created</dt>
173
+ <dd>{new Date(mailbox.dateCreated).toLocaleString()}</dd>
174
+ </dl>
175
+ <div className="flex gap-4 mt-5 pt-5 border-t border-border text-sm font-medium">
176
+ <a href={quarantineHref} className="text-primary-dark hover:underline">
177
+ View quarantine
178
+ </a>
179
+ <a href={ingestQueueHref} className="text-primary-dark hover:underline">
180
+ View ingest queue
181
+ </a>
182
+ </div>
183
+ </div>
184
+
185
+ <ShareAccessCard mailboxUid={mailbox.uid} ownerUserUid={mailbox.ownerUserUid} currentUserUid={currentUserUid} />
186
+
187
+ <EscrowScopeCard mailbox={mailbox} onUpdate={setMailbox} />
188
+
189
+ {mailbox.isResource && <ResourceSettingsCard mailbox={mailbox} onUpdate={setMailbox} />}
190
+
191
+ <Modal open={confirmingAccess} onClose={closeAccessModal} title="Impersonate this user">
192
+ <p className="text-sm mb-3">
193
+ You&rsquo;ll be signed in as <strong className="break-all">{mailbox.ownerUserUid}</strong>, the owner
194
+ of <strong className="break-all">{mailbox.primarySmtpAddress}</strong>, and see everything they can -
195
+ and act as them, until you stop impersonating. This is the only way an administrator sees another
196
+ user&rsquo;s mail.
197
+ </p>
198
+ {accessError && <Alert>{accessError}</Alert>}
199
+ <div className="flex gap-3 justify-end mt-5">
200
+ <Button type="button" variant="secondary" className="!w-auto" disabled={impersonating} onClick={closeAccessModal}>
201
+ Cancel
202
+ </Button>
203
+ <Button type="button" className="!w-auto" loading={impersonating} disabled={impersonating} onClick={handleAccessMailbox}>
204
+ Impersonate
205
+ </Button>
206
+ </div>
207
+ </Modal>
208
+
209
+ <Modal open={confirmingDelete} onClose={closeDeleteModal} title="Delete mailbox">
210
+ <p className="text-sm mb-3">
211
+ Are you sure you want to delete <strong className="break-all">{mailbox.primarySmtpAddress}</strong>?
212
+ This cannot be undone. It fails if this mailbox is a custodian on an active legal hold.
213
+ </p>
214
+ <p className="text-sm mb-3">
215
+ Deleting removes the mailbox itself. Its mail, contacts, calendars and everything else in it are{" "}
216
+ <strong>kept</strong> until they are erased, and until then the address can&rsquo;t be used for a new
217
+ mailbox. You can erase them later from the Mailboxes page.
218
+ </p>
219
+ <label className="flex items-start gap-2 text-sm mb-3">
220
+ <input
221
+ type="checkbox"
222
+ className="mt-0.5"
223
+ checked={eraseData}
224
+ disabled={deleting}
225
+ onChange={(e) => {
226
+ setEraseData(e.target.checked);
227
+ setTypedAddress("");
228
+ }}
229
+ />
230
+ <span>Also erase all of its data now (permanent)</span>
231
+ </label>
232
+ {eraseData && (
233
+ <div className="mb-3">
234
+ <p className="text-sm font-semibold text-danger mb-2">
235
+ Everything in this mailbox will be permanently erased, and this cannot be undone.
236
+ </p>
237
+ <label className="flex flex-col gap-1.5 text-sm">
238
+ <span className="font-semibold">
239
+ Type <span className="break-all">{mailbox.primarySmtpAddress}</span> to confirm
240
+ </span>
241
+ <input
242
+ aria-label="Type the address to confirm"
243
+ className="w-full text-sm py-2.5 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary"
244
+ value={typedAddress}
245
+ disabled={deleting}
246
+ autoComplete="off"
247
+ spellCheck={false}
248
+ onChange={(e) => setTypedAddress(e.target.value)}
249
+ />
250
+ </label>
251
+ </div>
252
+ )}
253
+ {deleteError && <Alert>{deleteError}</Alert>}
254
+ <div className="flex gap-3 justify-end mt-5">
255
+ <Button type="button" variant="secondary" className="!w-auto" disabled={deleting} onClick={closeDeleteModal}>
256
+ Cancel
257
+ </Button>
258
+ <Button
259
+ type="button"
260
+ className="!w-auto !bg-none !bg-danger !border-danger hover:!bg-danger"
261
+ loading={deleting}
262
+ disabled={deleting || (eraseData && typedAddress.trim().toLowerCase() !== mailbox.primarySmtpAddress.trim().toLowerCase())}
263
+ onClick={handleDelete}
264
+ >
265
+ {eraseData ? "Delete and erase all its data" : "Delete"}
266
+ </Button>
267
+ </div>
268
+ </Modal>
269
+ </div>
270
+ );
271
+ }
@@ -1,28 +1,30 @@
1
- ///////////////////////////////////////////////////////////////////////////////
2
- // Copyright (C) 2026 Jean-Philippe Steinmetz
3
- // SPDX-License-Identifier: MPL-2.0
4
- ///////////////////////////////////////////////////////////////////////////////
5
- import React from "react";
6
- import AdminShell, { AdminShellProps } from "../../../shared/components/admin/layout/AdminShell.js";
7
- import MailboxCreateForm from "../../../shared/components/admin/settings/MailboxCreateForm.js";
8
-
9
- export default function NewMailboxPage(props: Omit<AdminShellProps, "active">) {
10
- return (
11
- <AdminShell {...props} active="mailboxes">
12
- <div className="max-w-xl">
13
- <h1 className="text-xl font-bold uppercase tracking-wide mb-1">New mailbox</h1>
14
- <p className="text-sm text-text-muted mb-5">
15
- Choose "Shared mailbox" to create a true ownerless mailbox (the Exchange "shared mailbox"
16
- concept) — access is then granted entirely to delegates afterward, not to a single owner. Choose
17
- "Owned by a specific person" and look them up to create a mailbox for a specific user instead.
18
- </p>
19
- <MailboxCreateForm
20
- cancelHref="/admin"
21
- onCreated={(mailbox) => {
22
- window.location.href = `/admin/mailboxes/${encodeURIComponent(mailbox.uid)}`;
23
- }}
24
- />
25
- </div>
26
- </AdminShell>
27
- );
28
- }
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React from "react";
6
+ import { useRouter } from "@rapidrest/react/client";
7
+ import AdminShell, { AdminShellProps } from "../../../shared/components/admin/layout/AdminShell.js";
8
+ import MailboxCreateForm from "../../../shared/components/admin/settings/MailboxCreateForm.js";
9
+
10
+ export default function NewMailboxPage(props: Omit<AdminShellProps, "active">) {
11
+ const { navigate } = useRouter();
12
+ return (
13
+ <AdminShell {...props} active="mailboxes">
14
+ <div className="max-w-xl">
15
+ <h1 className="text-xl font-bold uppercase tracking-wide mb-1">New mailbox</h1>
16
+ <p className="text-sm text-text-muted mb-5">
17
+ Choose "Shared mailbox" to create a true ownerless mailbox (the Exchange "shared mailbox"
18
+ concept) — access is then granted entirely to delegates afterward, not to a single owner. Choose
19
+ "Owned by a specific person" and look them up to create a mailbox for a specific user instead.
20
+ </p>
21
+ <MailboxCreateForm
22
+ cancelHref="/admin"
23
+ onCreated={(mailbox) => {
24
+ void navigate(`/admin/mailboxes/${encodeURIComponent(mailbox.uid)}`);
25
+ }}
26
+ />
27
+ </div>
28
+ </AdminShell>
29
+ );
30
+ }
@@ -1,15 +1,15 @@
1
- ///////////////////////////////////////////////////////////////////////////////
2
- // Copyright (C) 2026 Jean-Philippe Steinmetz
3
- // SPDX-License-Identifier: MPL-2.0
4
- ///////////////////////////////////////////////////////////////////////////////
5
- import React from "react";
6
- import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
7
- import PluginsManager from "../../shared/components/admin/settings/PluginsManager.js";
8
-
9
- export default function PluginsPage(props: Omit<AdminShellProps, "active">) {
10
- return (
11
- <AdminShell {...props} active="plugins">
12
- <PluginsManager />
13
- </AdminShell>
14
- );
15
- }
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React from "react";
6
+ import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
7
+ import PluginsManager from "../../shared/components/admin/settings/PluginsManager.js";
8
+
9
+ export default function PluginsPage(props: Omit<AdminShellProps, "active">) {
10
+ return (
11
+ <AdminShell {...props} active="plugins">
12
+ <PluginsManager />
13
+ </AdminShell>
14
+ );
15
+ }