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