@rapidmx/web-client 0.29.0 → 0.31.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 (407) hide show
  1. package/apps/admin/audit-log/index.tsx +3 -3
  2. package/apps/admin/branding/index.tsx +3 -3
  3. package/apps/admin/data-requests/index.tsx +18 -7
  4. package/apps/admin/distribution-lists/[uid].tsx +3 -3
  5. package/apps/admin/distribution-lists/index.tsx +3 -3
  6. package/apps/admin/distribution-lists/new/index.tsx +3 -3
  7. package/apps/admin/domains/[uid].tsx +6 -5
  8. package/apps/admin/domains/index.tsx +3 -3
  9. package/apps/admin/domains/new/index.tsx +3 -3
  10. package/apps/admin/escrow-scopes/[uid].tsx +11 -5
  11. package/apps/admin/escrow-scopes/index.tsx +3 -3
  12. package/apps/admin/escrow-scopes/new/index.tsx +9 -3
  13. package/apps/admin/index.tsx +4 -4
  14. package/apps/admin/ingest-queue/index.tsx +3 -3
  15. package/apps/admin/mailboxes/[uid].tsx +15 -7
  16. package/apps/admin/quarantine/index.tsx +4 -4
  17. package/apps/admin/retention-policy/index.tsx +3 -3
  18. package/apps/admin/signing-certificates/index.tsx +3 -3
  19. package/apps/admin/transport-rules/[uid].tsx +4 -4
  20. package/apps/admin/transport-rules/index.tsx +3 -3
  21. package/apps/admin/transport-rules/new/index.tsx +3 -3
  22. package/apps/escrow/matters/[uid].tsx +26 -2
  23. package/apps/escrow/matters/new/index.tsx +4 -0
  24. package/apps/shared/calendar/calendarLiveUpdates.ts +11 -10
  25. package/apps/shared/calendar/useCalendarReminders.ts +2 -0
  26. package/apps/shared/components/admin/ActionAlert.tsx +32 -0
  27. package/apps/shared/components/admin/diagnostics/InformationPanel.tsx +1 -1
  28. package/apps/shared/components/admin/diagnostics/InstalledPlugins.tsx +1 -1
  29. package/apps/shared/components/admin/diagnostics/LogsPanel.tsx +1 -1
  30. package/apps/shared/components/admin/diagnostics/RuntimePanel.tsx +1 -1
  31. package/apps/shared/components/admin/diagnostics/SystemPanel.tsx +1 -1
  32. package/apps/shared/components/admin/distributionLists/MemberListCard.tsx +4 -4
  33. package/apps/shared/components/admin/elevation.ts +19 -0
  34. package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +58 -3
  35. package/apps/shared/components/admin/layout/AdminShell.tsx +6 -1
  36. package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +3 -3
  37. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +4 -4
  38. package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +4 -4
  39. package/apps/shared/components/admin/mailboxes/ResourceSettingsCard.tsx +3 -3
  40. package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +6 -6
  41. package/apps/shared/components/admin/settings/BrandingForm.tsx +22 -9
  42. package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +4 -4
  43. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +33 -4
  44. package/apps/shared/components/admin/settings/LoadedSettingsForm.tsx +3 -3
  45. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +8 -3
  46. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +3 -3
  47. package/apps/shared/components/admin/settings/PluginsManager.tsx +39 -17
  48. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +25 -12
  49. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +40 -7
  50. package/apps/shared/components/admin/setup/SetupWizard.tsx +8 -6
  51. package/apps/shared/components/admin/signOut.ts +3 -0
  52. package/apps/shared/components/admin/usePagedList.tsx +2 -2
  53. package/apps/shared/components/calendar/DescriptionEditor.tsx +2 -1
  54. package/apps/shared/components/calendar/EventDetails.tsx +34 -8
  55. package/apps/shared/components/calendar/EventEditor.tsx +90 -40
  56. package/apps/shared/components/calendar/EventFormParts.tsx +5 -2
  57. package/apps/shared/components/calendar/EventMatchNav.tsx +14 -2
  58. package/apps/shared/components/calendar/EventModal.tsx +25 -1
  59. package/apps/shared/components/calendar/FindATime.tsx +10 -2
  60. package/apps/shared/components/calendar/ListView.tsx +99 -25
  61. package/apps/shared/components/calendar/RecurrenceEditor.tsx +19 -8
  62. package/apps/shared/components/calendar/SplitDayView.tsx +14 -18
  63. package/apps/shared/components/calendar/TaskQuickForm.tsx +3 -2
  64. package/apps/shared/components/calendar/TimeGridView.tsx +35 -19
  65. package/apps/shared/components/calendar/gridLayout.ts +94 -0
  66. package/apps/shared/components/calendar/layout/CalendarShell.tsx +1 -1
  67. package/apps/shared/components/calendar/timePicker.ts +5 -2
  68. package/apps/shared/components/contacts/ContactCard.tsx +15 -4
  69. package/apps/shared/components/contacts/ContactDetailPane.tsx +54 -15
  70. package/apps/shared/components/contacts/ContactForm.tsx +61 -17
  71. package/apps/shared/components/contacts/ContactPhotoEditor.tsx +88 -0
  72. package/apps/shared/components/contacts/ContactPhotoField.tsx +36 -39
  73. package/apps/shared/components/contacts/layout/ContactsShell.tsx +1 -1
  74. package/apps/shared/components/contacts/participantDetails.ts +18 -1
  75. package/apps/shared/components/layout/AppShell.tsx +9 -0
  76. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +9 -4
  77. package/apps/shared/components/layout/MailboxProvisioning.tsx +31 -3
  78. package/apps/shared/components/layout/RecoveryCodeUnlock.tsx +4 -2
  79. package/apps/shared/components/mail/ConversationList.tsx +58 -8
  80. package/apps/shared/components/mail/ConversationThreadPane.tsx +1 -1
  81. package/apps/shared/components/mail/MenuButton.tsx +3 -400
  82. package/apps/shared/components/mail/MessageDetailPane.tsx +16 -13
  83. package/apps/shared/components/mail/SwipeRow.tsx +26 -4
  84. package/apps/shared/components/mail/compose/ComposeToolbar.tsx +11 -1
  85. package/apps/shared/components/mail/compose/ComposeWindow.tsx +57 -11
  86. package/apps/shared/components/mail/compose/GifPicker.tsx +10 -4
  87. package/apps/shared/components/mail/compose/RecipientInput.tsx +9 -7
  88. package/apps/shared/components/mail/compose/composeFlushRegistry.ts +14 -1
  89. package/apps/shared/components/mail/compose/encryptionRequirement.ts +5 -0
  90. package/apps/shared/components/mail/compose/quotedBody.ts +31 -6
  91. package/apps/shared/components/mail/layout/MailShell.tsx +1 -1
  92. package/apps/shared/components/mail/reading/MessageBody.tsx +13 -7
  93. package/apps/shared/components/mail/reading/bodyContent.ts +2 -0
  94. package/apps/shared/components/mail/reading/bodyHtml.ts +25 -2
  95. package/apps/shared/components/mail/writableMailboxes.ts +2 -0
  96. package/apps/shared/components/rules/RuleBuilder.tsx +11 -2
  97. package/apps/shared/components/settings/GravatarSetting.tsx +27 -0
  98. package/apps/shared/components/settings/layout/SettingsShell.tsx +1 -1
  99. package/apps/shared/components/tasks/dueDate.ts +29 -0
  100. package/apps/shared/components/tasks/layout/TasksShell.tsx +1 -1
  101. package/apps/shared/gestures/useLongPress.ts +138 -0
  102. package/apps/shared/mail/decryptedMessages.ts +51 -2
  103. package/apps/shared/mail/listSnapshots.ts +2 -0
  104. package/apps/shared/mail/outbox/sendDecision.ts +14 -3
  105. package/apps/shared/mail/outbox/sendJob.ts +5 -0
  106. package/apps/shared/mail/useMailLiveUpdates.ts +7 -1
  107. package/apps/shared/mail/usePermanentDelete.tsx +3 -1
  108. package/apps/shared/notifications/apiErrors.ts +2 -0
  109. package/apps/shared/notifications/preferences.ts +1 -1
  110. package/apps/shared/notifications/store.ts +3 -1
  111. package/apps/shared/plugins/pluginNav.ts +4 -2
  112. package/apps/www/calendar/index.tsx +24 -12
  113. package/apps/www/contacts/[uid].tsx +6 -1
  114. package/apps/www/contacts/index.tsx +66 -12
  115. package/apps/www/index.tsx +139 -43
  116. package/apps/www/messages/[uid].tsx +8 -3
  117. package/apps/www/settings/auto-reply/index.tsx +13 -0
  118. package/apps/www/settings/blocked-senders/index.tsx +4 -0
  119. package/apps/www/settings/encryption/index.tsx +66 -4
  120. package/apps/www/settings/privacy/index.tsx +4 -1
  121. package/apps/www/settings/profile/index.tsx +12 -1
  122. package/apps/www/settings/sharing/index.tsx +11 -1
  123. package/apps/www/settings/signatures/[uid].tsx +6 -4
  124. package/apps/www/tasks/index.tsx +97 -29
  125. package/dist/apps/admin/audit-log/index.js +3 -3
  126. package/dist/apps/admin/branding/index.js +3 -3
  127. package/dist/apps/admin/data-requests/index.js +17 -7
  128. package/dist/apps/admin/distribution-lists/[uid].js +3 -3
  129. package/dist/apps/admin/distribution-lists/index.js +3 -3
  130. package/dist/apps/admin/distribution-lists/new/index.js +3 -3
  131. package/dist/apps/admin/domains/[uid].js +6 -5
  132. package/dist/apps/admin/domains/index.js +3 -3
  133. package/dist/apps/admin/domains/new/index.js +3 -3
  134. package/dist/apps/admin/escrow-scopes/[uid].js +11 -6
  135. package/dist/apps/admin/escrow-scopes/index.js +3 -3
  136. package/dist/apps/admin/escrow-scopes/new/index.js +9 -4
  137. package/dist/apps/admin/index.js +4 -4
  138. package/dist/apps/admin/ingest-queue/index.js +3 -3
  139. package/dist/apps/admin/mailboxes/[uid].js +15 -7
  140. package/dist/apps/admin/quarantine/index.js +4 -4
  141. package/dist/apps/admin/retention-policy/index.js +3 -3
  142. package/dist/apps/admin/signing-certificates/index.js +3 -3
  143. package/dist/apps/admin/transport-rules/[uid].js +4 -4
  144. package/dist/apps/admin/transport-rules/index.js +3 -3
  145. package/dist/apps/admin/transport-rules/new/index.js +3 -3
  146. package/dist/apps/escrow/matters/[uid].js +8 -3
  147. package/dist/apps/escrow/matters/new/index.js +4 -0
  148. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +11 -7
  149. package/dist/apps/shared/calendar/calendarLiveUpdates.js +10 -9
  150. package/dist/apps/shared/calendar/useCalendarReminders.js +2 -0
  151. package/dist/apps/shared/components/admin/ActionAlert.d.ts +13 -0
  152. package/dist/apps/shared/components/admin/ActionAlert.js +24 -0
  153. package/dist/apps/shared/components/admin/diagnostics/InformationPanel.js +1 -1
  154. package/dist/apps/shared/components/admin/diagnostics/InstalledPlugins.js +1 -1
  155. package/dist/apps/shared/components/admin/diagnostics/LogsPanel.js +1 -1
  156. package/dist/apps/shared/components/admin/diagnostics/RuntimePanel.js +1 -1
  157. package/dist/apps/shared/components/admin/diagnostics/SystemPanel.js +1 -1
  158. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.js +4 -4
  159. package/dist/apps/shared/components/admin/elevation.d.ts +9 -0
  160. package/dist/apps/shared/components/admin/elevation.js +16 -0
  161. package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.d.ts +2 -0
  162. package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +41 -1
  163. package/dist/apps/shared/components/admin/layout/AdminShell.js +2 -1
  164. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +3 -3
  165. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +4 -4
  166. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +4 -4
  167. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +3 -3
  168. package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +6 -6
  169. package/dist/apps/shared/components/admin/settings/BrandingForm.js +17 -7
  170. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +4 -4
  171. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +17 -5
  172. package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.js +3 -3
  173. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +8 -3
  174. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +3 -3
  175. package/dist/apps/shared/components/admin/settings/PluginsManager.js +26 -12
  176. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +17 -10
  177. package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +18 -8
  178. package/dist/apps/shared/components/admin/setup/SetupWizard.js +8 -6
  179. package/dist/apps/shared/components/admin/signOut.js +3 -0
  180. package/dist/apps/shared/components/admin/usePagedList.js +2 -2
  181. package/dist/apps/shared/components/calendar/DescriptionEditor.js +2 -1
  182. package/dist/apps/shared/components/calendar/EventDetails.d.ts +3 -1
  183. package/dist/apps/shared/components/calendar/EventDetails.js +7 -4
  184. package/dist/apps/shared/components/calendar/EventEditor.js +81 -33
  185. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +3 -1
  186. package/dist/apps/shared/components/calendar/EventFormParts.js +3 -3
  187. package/dist/apps/shared/components/calendar/EventMatchNav.d.ts +1 -1
  188. package/dist/apps/shared/components/calendar/EventMatchNav.js +12 -2
  189. package/dist/apps/shared/components/calendar/EventModal.js +10 -2
  190. package/dist/apps/shared/components/calendar/FindATime.js +4 -3
  191. package/dist/apps/shared/components/calendar/ListView.d.ts +10 -4
  192. package/dist/apps/shared/components/calendar/ListView.js +92 -27
  193. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +4 -1
  194. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +15 -10
  195. package/dist/apps/shared/components/calendar/SplitDayView.js +11 -17
  196. package/dist/apps/shared/components/calendar/TaskQuickForm.js +3 -2
  197. package/dist/apps/shared/components/calendar/TimeGridView.js +23 -21
  198. package/dist/apps/shared/components/calendar/gridLayout.d.ts +41 -0
  199. package/dist/apps/shared/components/calendar/gridLayout.js +83 -0
  200. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +1 -1
  201. package/dist/apps/shared/components/calendar/timePicker.js +5 -2
  202. package/dist/apps/shared/components/contacts/ContactCard.js +9 -3
  203. package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +5 -3
  204. package/dist/apps/shared/components/contacts/ContactDetailPane.js +11 -5
  205. package/dist/apps/shared/components/contacts/ContactForm.js +54 -16
  206. package/dist/apps/shared/components/contacts/ContactPhotoEditor.d.ts +21 -0
  207. package/dist/apps/shared/components/contacts/ContactPhotoEditor.js +56 -0
  208. package/dist/apps/shared/components/contacts/ContactPhotoField.d.ts +7 -4
  209. package/dist/apps/shared/components/contacts/ContactPhotoField.js +19 -21
  210. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +1 -1
  211. package/dist/apps/shared/components/contacts/participantDetails.d.ts +4 -1
  212. package/dist/apps/shared/components/contacts/participantDetails.js +17 -1
  213. package/dist/apps/shared/components/layout/AppShell.js +9 -0
  214. package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +2 -3
  215. package/dist/apps/shared/components/layout/MailboxProvisioning.d.ts +4 -1
  216. package/dist/apps/shared/components/layout/MailboxProvisioning.js +24 -2
  217. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +4 -2
  218. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +4 -2
  219. package/dist/apps/shared/components/mail/ConversationList.d.ts +8 -3
  220. package/dist/apps/shared/components/mail/ConversationList.js +51 -8
  221. package/dist/apps/shared/components/mail/ConversationThreadPane.js +1 -1
  222. package/dist/apps/shared/components/mail/MenuButton.d.ts +2 -78
  223. package/dist/apps/shared/components/mail/MenuButton.js +2 -211
  224. package/dist/apps/shared/components/mail/MessageDetailPane.js +10 -6
  225. package/dist/apps/shared/components/mail/SwipeRow.d.ts +5 -1
  226. package/dist/apps/shared/components/mail/SwipeRow.js +17 -3
  227. package/dist/apps/shared/components/mail/compose/ComposeToolbar.d.ts +3 -0
  228. package/dist/apps/shared/components/mail/compose/ComposeToolbar.js +10 -1
  229. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +55 -10
  230. package/dist/apps/shared/components/mail/compose/GifPicker.js +10 -4
  231. package/dist/apps/shared/components/mail/compose/RecipientInput.js +9 -7
  232. package/dist/apps/shared/components/mail/compose/composeFlushRegistry.d.ts +7 -1
  233. package/dist/apps/shared/components/mail/compose/composeFlushRegistry.js +13 -1
  234. package/dist/apps/shared/components/mail/compose/encryptionRequirement.d.ts +5 -0
  235. package/dist/apps/shared/components/mail/compose/quotedBody.js +28 -5
  236. package/dist/apps/shared/components/mail/layout/MailShell.js +1 -1
  237. package/dist/apps/shared/components/mail/reading/MessageBody.js +11 -6
  238. package/dist/apps/shared/components/mail/reading/bodyContent.js +2 -0
  239. package/dist/apps/shared/components/mail/reading/bodyHtml.d.ts +5 -1
  240. package/dist/apps/shared/components/mail/reading/bodyHtml.js +23 -2
  241. package/dist/apps/shared/components/mail/writableMailboxes.js +2 -0
  242. package/dist/apps/shared/components/rules/RuleBuilder.js +9 -1
  243. package/dist/apps/shared/components/settings/GravatarSetting.d.ts +6 -0
  244. package/dist/apps/shared/components/settings/GravatarSetting.js +15 -0
  245. package/dist/apps/shared/components/settings/layout/SettingsShell.js +1 -1
  246. package/dist/apps/shared/components/tasks/dueDate.d.ts +12 -0
  247. package/dist/apps/shared/components/tasks/dueDate.js +26 -0
  248. package/dist/apps/shared/components/tasks/layout/TasksShell.js +1 -1
  249. package/dist/apps/shared/gestures/useLongPress.d.ts +41 -0
  250. package/dist/apps/shared/gestures/useLongPress.js +112 -0
  251. package/dist/apps/shared/mail/decryptedMessages.d.ts +8 -0
  252. package/dist/apps/shared/mail/decryptedMessages.js +46 -2
  253. package/dist/apps/shared/mail/listSnapshots.js +2 -0
  254. package/dist/apps/shared/mail/outbox/sendDecision.d.ts +6 -3
  255. package/dist/apps/shared/mail/outbox/sendDecision.js +13 -3
  256. package/dist/apps/shared/mail/outbox/sendJob.d.ts +1 -0
  257. package/dist/apps/shared/mail/outbox/sendJob.js +5 -1
  258. package/dist/apps/shared/mail/useMailLiveUpdates.d.ts +3 -0
  259. package/dist/apps/shared/mail/useMailLiveUpdates.js +6 -1
  260. package/dist/apps/shared/mail/usePermanentDelete.d.ts +2 -0
  261. package/dist/apps/shared/mail/usePermanentDelete.js +1 -1
  262. package/dist/apps/shared/notifications/apiErrors.js +2 -0
  263. package/dist/apps/shared/notifications/preferences.d.ts +1 -1
  264. package/dist/apps/shared/notifications/preferences.js +1 -1
  265. package/dist/apps/shared/notifications/store.js +3 -1
  266. package/dist/apps/shared/plugins/pluginNav.d.ts +2 -1
  267. package/dist/apps/shared/plugins/pluginNav.js +4 -2
  268. package/dist/apps/www/calendar/index.js +24 -12
  269. package/dist/apps/www/contacts/[uid].js +6 -2
  270. package/dist/apps/www/contacts/index.js +62 -11
  271. package/dist/apps/www/index.js +124 -40
  272. package/dist/apps/www/messages/[uid].js +8 -3
  273. package/dist/apps/www/settings/auto-reply/index.js +13 -1
  274. package/dist/apps/www/settings/blocked-senders/index.js +4 -0
  275. package/dist/apps/www/settings/encryption/index.js +29 -5
  276. package/dist/apps/www/settings/privacy/index.js +3 -2
  277. package/dist/apps/www/settings/profile/index.js +4 -1
  278. package/dist/apps/www/settings/sharing/index.js +10 -1
  279. package/dist/apps/www/settings/signatures/[uid].js +6 -4
  280. package/dist/apps/www/tasks/index.js +94 -32
  281. package/dist/lib/admin/auditLogApi.js +2 -2
  282. package/dist/lib/admin/distributionListsApi.js +2 -2
  283. package/dist/lib/admin/domainsApi.js +2 -2
  284. package/dist/lib/admin/escrowAuditLogApi.js +2 -2
  285. package/dist/lib/admin/escrowScopesApi.js +2 -2
  286. package/dist/lib/admin/pluginsApi.d.ts +13 -2
  287. package/dist/lib/admin/pluginsApi.js +8 -0
  288. package/dist/lib/admin/retentionPolicyApi.d.ts +3 -0
  289. package/dist/lib/admin/retentionPolicyApi.js +3 -0
  290. package/dist/lib/admin/transportRulesApi.js +2 -2
  291. package/dist/lib/appearance/preferencesApi.d.ts +1 -1
  292. package/dist/lib/appearance/preferencesApi.js +3 -14
  293. package/dist/lib/auth/session.d.ts +51 -12
  294. package/dist/lib/auth/session.js +214 -38
  295. package/dist/lib/branding/brandingApi.d.ts +3 -3
  296. package/dist/lib/branding/brandingApi.js +9 -21
  297. package/dist/lib/calendar/calendarApi.js +3 -1
  298. package/dist/lib/calendar/eventSearch.js +43 -6
  299. package/dist/lib/calendar/freeBusyApi.d.ts +2 -1
  300. package/dist/lib/calendar/freeBusyApi.js +13 -5
  301. package/dist/lib/calendar/recurrence.js +51 -3
  302. package/dist/lib/calendar/useDayKey.d.ts +7 -0
  303. package/dist/lib/calendar/useDayKey.js +43 -0
  304. package/dist/lib/components/avatar/ContactAvatar.d.ts +6 -2
  305. package/dist/lib/components/avatar/ContactAvatar.js +37 -8
  306. package/dist/lib/components/avatar/ContactPhotoAvatar.d.ts +11 -0
  307. package/dist/lib/components/avatar/ContactPhotoAvatar.js +18 -0
  308. package/dist/lib/components/forms/CameraCaptureModal.d.ts +17 -0
  309. package/dist/lib/components/forms/CameraCaptureModal.js +88 -0
  310. package/dist/lib/components/forms/ImageEditBadge.d.ts +28 -0
  311. package/dist/lib/components/forms/ImageEditBadge.js +62 -0
  312. package/dist/lib/components/menus/MenuButton.d.ts +78 -0
  313. package/dist/lib/components/menus/MenuButton.js +219 -0
  314. package/dist/lib/components/navigation/BottomTabBar.d.ts +3 -1
  315. package/dist/lib/components/navigation/BottomTabBar.js +22 -3
  316. package/dist/lib/components/overlays/PopoverPortal.d.ts +2 -1
  317. package/dist/lib/components/overlays/PopoverPortal.js +3 -2
  318. package/dist/lib/components/pickers/TimeZonePicker.js +13 -1
  319. package/dist/lib/contacts/contactsApi.d.ts +5 -2
  320. package/dist/lib/contacts/contactsApi.js +16 -19
  321. package/dist/lib/contacts/gravatar.d.ts +14 -3
  322. package/dist/lib/contacts/gravatar.js +42 -5
  323. package/dist/lib/contacts/preparePhoto.d.ts +24 -0
  324. package/dist/lib/contacts/preparePhoto.js +250 -0
  325. package/dist/lib/contacts/useContactPhotoSrc.d.ts +19 -0
  326. package/dist/lib/contacts/useContactPhotoSrc.js +153 -0
  327. package/dist/lib/contacts/vcard.d.ts +3 -0
  328. package/dist/lib/contacts/vcard.js +59 -7
  329. package/dist/lib/crypto/escrowKeys.d.ts +8 -0
  330. package/dist/lib/crypto/escrowKeys.js +20 -1
  331. package/dist/lib/crypto/messageSecurity.d.ts +7 -4
  332. package/dist/lib/crypto/messageSecurity.js +23 -5
  333. package/dist/lib/crypto/passwordUnlock.d.ts +6 -1
  334. package/dist/lib/crypto/passwordUnlock.js +13 -2
  335. package/dist/lib/crypto/smime.js +12 -2
  336. package/dist/lib/mail/compose/composeQuoting.js +3 -2
  337. package/dist/lib/mail/compose/quotedImages.d.ts +6 -3
  338. package/dist/lib/mail/compose/quotedImages.js +35 -9
  339. package/dist/lib/mail/labelsApi.js +2 -2
  340. package/dist/lib/mail/mailApi.d.ts +8 -5
  341. package/dist/lib/mail/mailApi.js +73 -39
  342. package/dist/lib/mail/mailDetailHooks.js +11 -3
  343. package/dist/lib/mail/mailFilterRulesApi.js +2 -2
  344. package/dist/lib/mail/mailSignaturesApi.js +2 -2
  345. package/dist/lib/mail/mailboxImportApi.d.ts +1 -1
  346. package/dist/lib/mail/mailboxImportApi.js +3 -15
  347. package/dist/lib/mail/messageBodySanitizer.d.ts +6 -0
  348. package/dist/lib/mail/messageBodySanitizer.js +44 -1
  349. package/dist/lib/search/queryGrammar.js +12 -4
  350. package/dist/lib/search/searchTier3.d.ts +6 -1
  351. package/dist/lib/search/searchTier3.js +54 -25
  352. package/dist/lib/tasks/tasksApi.js +3 -3
  353. package/dist/lib/util/api.d.ts +26 -4
  354. package/dist/lib/util/api.js +73 -16
  355. package/dist/lib/util/apiQuery.d.ts +11 -0
  356. package/dist/lib/util/apiQuery.js +11 -0
  357. package/dist/lib/util/settleWithLimit.d.ts +5 -0
  358. package/dist/lib/util/settleWithLimit.js +25 -0
  359. package/lib/admin/auditLogApi.ts +2 -2
  360. package/lib/admin/distributionListsApi.ts +2 -2
  361. package/lib/admin/domainsApi.ts +2 -2
  362. package/lib/admin/escrowAuditLogApi.ts +2 -2
  363. package/lib/admin/escrowScopesApi.ts +2 -2
  364. package/lib/admin/pluginsApi.ts +21 -2
  365. package/lib/admin/retentionPolicyApi.ts +4 -0
  366. package/lib/admin/transportRulesApi.ts +2 -2
  367. package/lib/appearance/preferencesApi.ts +3 -14
  368. package/lib/auth/session.ts +239 -39
  369. package/lib/branding/brandingApi.ts +9 -21
  370. package/lib/calendar/calendarApi.ts +3 -1
  371. package/lib/calendar/eventSearch.ts +46 -6
  372. package/lib/calendar/freeBusyApi.ts +14 -6
  373. package/lib/calendar/recurrence.ts +59 -8
  374. package/lib/calendar/useDayKey.ts +45 -0
  375. package/lib/components/avatar/ContactAvatar.tsx +46 -8
  376. package/lib/components/avatar/ContactPhotoAvatar.tsx +26 -0
  377. package/lib/components/forms/CameraCaptureModal.tsx +133 -0
  378. package/lib/components/forms/ImageEditBadge.tsx +121 -0
  379. package/lib/components/menus/MenuButton.tsx +408 -0
  380. package/lib/components/navigation/BottomTabBar.tsx +30 -8
  381. package/lib/components/overlays/PopoverPortal.tsx +3 -2
  382. package/lib/components/pickers/TimeZonePicker.tsx +17 -1
  383. package/lib/contacts/contactsApi.ts +18 -19
  384. package/lib/contacts/gravatar.ts +47 -5
  385. package/lib/contacts/preparePhoto.ts +273 -0
  386. package/lib/contacts/useContactPhotoSrc.ts +177 -0
  387. package/lib/contacts/vcard.ts +60 -7
  388. package/lib/crypto/escrowKeys.ts +21 -1
  389. package/lib/crypto/messageSecurity.ts +33 -9
  390. package/lib/crypto/passwordUnlock.ts +14 -2
  391. package/lib/crypto/smime.ts +13 -2
  392. package/lib/mail/compose/composeQuoting.ts +3 -2
  393. package/lib/mail/compose/quotedImages.ts +39 -9
  394. package/lib/mail/labelsApi.ts +2 -2
  395. package/lib/mail/mailApi.ts +96 -39
  396. package/lib/mail/mailDetailHooks.ts +11 -3
  397. package/lib/mail/mailFilterRulesApi.ts +2 -2
  398. package/lib/mail/mailSignaturesApi.ts +2 -2
  399. package/lib/mail/mailboxImportApi.ts +9 -15
  400. package/lib/mail/messageBodySanitizer.ts +47 -1
  401. package/lib/search/queryGrammar.ts +13 -4
  402. package/lib/search/searchTier3.ts +65 -32
  403. package/lib/tasks/tasksApi.ts +3 -3
  404. package/lib/util/api.ts +99 -16
  405. package/lib/util/apiQuery.ts +13 -0
  406. package/lib/util/settleWithLimit.ts +25 -0
  407. package/package.json +1 -1
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useRef, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { AuditLogEntry, AuditLogFilters, listAuditLog } from "../../../lib/admin/auditLogApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
- import Alert from "../../../lib/components/feedback/Alert.js";
8
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
9
  import Button from "../../../lib/components/buttons/Button.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  const PAGE_SIZE = 25;
13
13
  /** How long typing in a filter box has to pause before the log is re-fetched. */
@@ -71,7 +71,7 @@ function AuditLogContent() {
71
71
  if (!cancelled) setEntries(data);
72
72
  })
73
73
  .catch((err) => {
74
- if (!cancelled) setError(err instanceof ApiRequestError ? err.message : "Could not load the audit log.");
74
+ if (!cancelled) setError(actionErrorMessage(err, "Could not load the audit log."));
75
75
  })
76
76
  .finally(() => {
77
77
  if (!cancelled) setLoading(false);
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { Branding, getBranding } from "../../../lib/branding/brandingApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
8
  import BrandingForm from "../../shared/components/admin/settings/BrandingForm.js";
10
- import Alert from "../../../lib/components/feedback/Alert.js";
9
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  export default function BrandingPage(props: Omit<AdminShellProps, "active">) {
13
13
  return (
@@ -25,7 +25,7 @@ function BrandingContent() {
25
25
  useEffect(() => {
26
26
  getBranding()
27
27
  .then(setBranding)
28
- .catch((err) => setLoadError(err instanceof ApiRequestError ? err.message : "Could not load branding."))
28
+ .catch((err) => setLoadError(actionErrorMessage(err, "Could not load branding.")))
29
29
  .finally(() => setLoading(false));
30
30
  }, []);
31
31
 
@@ -3,7 +3,7 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { ChangeEvent, FormEvent, useEffect, useRef, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
6
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
7
7
  import {
8
8
  DataExportFormat,
9
9
  createExportRequest,
@@ -24,7 +24,7 @@ import {
24
24
  import { Folder, listFolders } from "../../../lib/mail/mailApi.js";
25
25
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
26
26
  import { LoadMoreButton, usePagedList } from "../../shared/components/admin/usePagedList.js";
27
- import Alert from "../../../lib/components/feedback/Alert.js";
27
+ import Alert from "../../shared/components/admin/ActionAlert.js";
28
28
  import Button from "../../../lib/components/buttons/Button.js";
29
29
  import Modal from "../../../lib/components/overlays/Modal.js";
30
30
 
@@ -90,7 +90,7 @@ function ExportRequestsSection() {
90
90
  setMailboxUid("");
91
91
  await list.reload();
92
92
  } catch (err) {
93
- setCreateError(err instanceof ApiRequestError ? err.message : "Could not start this export.");
93
+ setCreateError(actionErrorMessage(err, "Could not start this export."));
94
94
  } finally {
95
95
  setCreating(false);
96
96
  }
@@ -185,7 +185,11 @@ function ImportRequestsSection() {
185
185
  void list.reload();
186
186
  }, []);
187
187
 
188
+ // Only the latest lookup's answer is applied: a slower answer for a mailbox typed earlier would otherwise list its folders beside the mailbox now named.
189
+ const folderLookup = useRef(0);
190
+
188
191
  function handleLoadFolders() {
192
+ const lookup = ++folderLookup.current;
189
193
  const uid = mailboxUid.trim();
190
194
  setTargetFolderUid("");
191
195
  setFolders([]);
@@ -195,11 +199,18 @@ function ImportRequestsSection() {
195
199
  }
196
200
  listFolders(uid)
197
201
  .then((all) => {
202
+ if (lookup !== folderLookup.current) {
203
+ return;
204
+ }
198
205
  const mailFolders = all.filter((f) => !NON_MAIL_FOLDER_TYPES.has(f.type));
199
206
  setFolders(mailFolders);
200
207
  setTargetFolderUid(mailFolders[0]?.uid ?? "");
201
208
  })
202
- .catch((err) => setFolderError(err instanceof ApiRequestError ? err.message : "Could not load this mailbox's folders."));
209
+ .catch((err) => {
210
+ if (lookup === folderLookup.current) {
211
+ setFolderError(actionErrorMessage(err, "Could not load this mailbox's folders."));
212
+ }
213
+ });
203
214
  }
204
215
 
205
216
  function handleFileChange(e: ChangeEvent<HTMLInputElement>) {
@@ -212,7 +223,7 @@ function ImportRequestsSection() {
212
223
  setUploading(true);
213
224
  uploadMailboxImport(file, { format: importFormatFromFilename(file.name), targetFolderUid, mailboxUid: mailboxUid.trim() })
214
225
  .then(() => list.reload())
215
- .catch((err) => setUploadError(err instanceof ApiRequestError ? err.message : "Could not upload this file."))
226
+ .catch((err) => setUploadError(actionErrorMessage(err, "Could not upload this file.")))
216
227
  .finally(() => setUploading(false));
217
228
  }
218
229
 
@@ -345,7 +356,7 @@ function ErasureRequestsSection() {
345
356
  closeApproveModal();
346
357
  await list.reload();
347
358
  } catch (err) {
348
- setApproveError(err instanceof ApiRequestError ? err.message : "Could not approve this request.");
359
+ setApproveError(actionErrorMessage(err, "Could not approve this request."));
349
360
  } finally {
350
361
  setApproving(false);
351
362
  }
@@ -370,7 +381,7 @@ function ErasureRequestsSection() {
370
381
  closeDenyModal();
371
382
  await list.reload();
372
383
  } catch (err) {
373
- setDenyError(err instanceof ApiRequestError ? err.message : "Could not deny this request.");
384
+ setDenyError(actionErrorMessage(err, "Could not deny this request."));
374
385
  } finally {
375
386
  setDenying(false);
376
387
  }
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { DistributionList, getDistributionList } from "../../../lib/admin/distributionListsApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
8
  import MemberListCard from "../../shared/components/admin/distributionLists/MemberListCard.js";
10
- import Alert from "../../../lib/components/feedback/Alert.js";
9
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  export default function DistributionListDetailPage(props: Omit<AdminShellProps, "active"> & { params: { uid: string } }) {
13
13
  return (
@@ -27,7 +27,7 @@ function DistributionListDetailContent({ uid }: { uid: string }) {
27
27
  setError(null);
28
28
  getDistributionList(uid)
29
29
  .then(setList)
30
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load this distribution list."))
30
+ .catch((err) => setError(actionErrorMessage(err, "Could not load this distribution list.")))
31
31
  .finally(() => setLoading(false));
32
32
  }, [uid]);
33
33
 
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { DistributionList, listDistributionLists } from "../../../lib/admin/distributionListsApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
- import Alert from "../../../lib/components/feedback/Alert.js";
8
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
9
  import Button from "../../../lib/components/buttons/Button.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  const PAGE_SIZE = 25;
13
13
 
@@ -30,7 +30,7 @@ function DistributionListsContent() {
30
30
  setError(null);
31
31
  listDistributionLists({ page, limit: PAGE_SIZE })
32
32
  .then(setLists)
33
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load distribution lists."))
33
+ .catch((err) => setError(actionErrorMessage(err, "Could not load distribution lists.")))
34
34
  .finally(() => setLoading(false));
35
35
  }, [page]);
36
36
 
@@ -4,12 +4,12 @@
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { FormEvent, useState } from "react";
6
6
  import { useRouter } from "@rapidrest/react/client";
7
- import { ApiRequestError } from "../../../../lib/util/api.js";
8
7
  import { createDistributionList } from "../../../../lib/admin/distributionListsApi.js";
9
8
  import AdminShell, { AdminShellProps } from "../../../shared/components/admin/layout/AdminShell.js";
10
- import Alert from "../../../../lib/components/feedback/Alert.js";
9
+ import Alert from "../../../shared/components/admin/ActionAlert.js";
11
10
  import Button from "../../../../lib/components/buttons/Button.js";
12
11
  import FormField from "../../../../lib/components/forms/FormField.js";
12
+ import { actionErrorMessage } from "../../../shared/components/admin/elevation.js";
13
13
 
14
14
  const INPUT_CLASS =
15
15
  "w-full text-sm py-2.5 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
@@ -52,7 +52,7 @@ function NewDistributionListForm() {
52
52
  });
53
53
  void navigate(`/admin/distribution-lists/${encodeURIComponent(list.uid)}`);
54
54
  } catch (err) {
55
- setError(err instanceof ApiRequestError ? err.message : "Could not create the distribution list.");
55
+ setError(actionErrorMessage(err, "Could not create the distribution list."));
56
56
  } finally {
57
57
  setSaving(false);
58
58
  }
@@ -4,14 +4,14 @@
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useState } from "react";
6
6
  import { useRouter } from "@rapidrest/react/client";
7
- import { ApiRequestError } from "../../../lib/util/api.js";
8
7
  import { deleteDomain, Domain, updateDomain } from "../../../lib/admin/domainsApi.js";
9
8
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
10
9
  import DomainDnsSetup from "../../shared/components/admin/settings/DomainDnsSetup.js";
11
- import Alert from "../../../lib/components/feedback/Alert.js";
10
+ import Alert from "../../shared/components/admin/ActionAlert.js";
12
11
  import Button from "../../../lib/components/buttons/Button.js";
13
12
  import FormField from "../../../lib/components/forms/FormField.js";
14
13
  import Modal from "../../../lib/components/overlays/Modal.js";
14
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
15
15
 
16
16
  const INPUT_CLASS =
17
17
  "w-full text-sm py-2.5 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
@@ -52,7 +52,7 @@ function DomainDetailContent({ uid }: { uid: string }) {
52
52
  await deleteDomain(domain!.uid, domain!.version);
53
53
  void navigate("/admin/domains");
54
54
  } catch (err) {
55
- setDeleteError(err instanceof ApiRequestError ? err.message : "Could not delete this domain.");
55
+ setDeleteError(actionErrorMessage(err, "Could not delete this domain."));
56
56
  setDeleting(false);
57
57
  }
58
58
  }
@@ -62,18 +62,19 @@ function DomainDetailContent({ uid }: { uid: string }) {
62
62
  setAliasInput((current) => (current === null ? d?.aliasOf ?? "" : current));
63
63
  }
64
64
 
65
+ // A blank input is sent as "" (the server's way to clear an alias): an absent key (what `undefined` becomes in JSON) leaves the stored alias alone.
65
66
  async function handleSaveAlias() {
66
67
  setSavingAlias(true);
67
68
  setAliasError(null);
68
69
  setAliasSaved(false);
69
70
  try {
70
- const updated = await updateDomain({ uid: domain!.uid, version: domain!.version, aliasOf: aliasInput!.trim() || undefined });
71
+ const updated = await updateDomain({ uid: domain!.uid, version: domain!.version, aliasOf: aliasInput!.trim() });
71
72
  setDomain(updated);
72
73
  setAliasInput(updated.aliasOf ?? "");
73
74
  setAliasSaved(true);
74
75
  setRefreshCount((c) => c + 1);
75
76
  } catch (err) {
76
- setAliasError(err instanceof ApiRequestError ? err.message : "Could not update this domain.");
77
+ setAliasError(actionErrorMessage(err, "Could not update this domain."));
77
78
  } finally {
78
79
  setSavingAlias(false);
79
80
  }
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { Domain, listDomains } from "../../../lib/admin/domainsApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
- import Alert from "../../../lib/components/feedback/Alert.js";
8
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
9
  import Button from "../../../lib/components/buttons/Button.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  const PAGE_SIZE = 25;
13
13
 
@@ -30,7 +30,7 @@ function DomainsListContent() {
30
30
  setError(null);
31
31
  listDomains({ page, limit: PAGE_SIZE })
32
32
  .then(setDomains)
33
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load domains."))
33
+ .catch((err) => setError(actionErrorMessage(err, "Could not load domains.")))
34
34
  .finally(() => setLoading(false));
35
35
  }, [page]);
36
36
 
@@ -4,12 +4,12 @@
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { FormEvent, useEffect, useState } from "react";
6
6
  import { useRouter } from "@rapidrest/react/client";
7
- import { ApiRequestError } from "../../../../lib/util/api.js";
8
7
  import { createDomain, Domain, listDomains } from "../../../../lib/admin/domainsApi.js";
9
8
  import AdminShell, { AdminShellProps } from "../../../shared/components/admin/layout/AdminShell.js";
10
- import Alert from "../../../../lib/components/feedback/Alert.js";
9
+ import Alert from "../../../shared/components/admin/ActionAlert.js";
11
10
  import Button from "../../../../lib/components/buttons/Button.js";
12
11
  import FormField from "../../../../lib/components/forms/FormField.js";
12
+ import { actionErrorMessage } from "../../../shared/components/admin/elevation.js";
13
13
 
14
14
  const INPUT_CLASS =
15
15
  "w-full text-sm py-2.5 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
@@ -52,7 +52,7 @@ function NewDomainForm() {
52
52
  const domain = await createDomain({ name: name.trim(), aliasOf: aliasOf || undefined });
53
53
  void navigate(`/admin/domains/${encodeURIComponent(domain.uid)}`);
54
54
  } catch (err) {
55
- setError(err instanceof ApiRequestError ? err.message : "Could not create the domain.");
55
+ setError(actionErrorMessage(err, "Could not create the domain."));
56
56
  } finally {
57
57
  setSaving(false);
58
58
  }
@@ -4,7 +4,6 @@
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { FormEvent, useEffect, useState } from "react";
6
6
  import { useRouter } from "@rapidrest/react/client";
7
- import { ApiRequestError } from "../../../lib/util/api.js";
8
7
  import { toDatetimeLocal } from "../../../lib/util/dateInput.js";
9
8
  import {
10
9
  deleteEscrowScope,
@@ -16,12 +15,14 @@ import {
16
15
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
17
16
  import EscrowScopeKeyAndHoldersFields, {
18
17
  EscrowScopeKeyAndHoldersValue,
18
+ keyValidityError,
19
19
  selfAsHolderError,
20
20
  } from "../../shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js";
21
- import Alert from "../../../lib/components/feedback/Alert.js";
21
+ import Alert from "../../shared/components/admin/ActionAlert.js";
22
22
  import Button from "../../../lib/components/buttons/Button.js";
23
23
  import FormField from "../../../lib/components/forms/FormField.js";
24
24
  import Modal from "../../../lib/components/overlays/Modal.js";
25
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
25
26
 
26
27
  const INPUT_CLASS =
27
28
  "w-full text-sm py-2.5 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
@@ -145,7 +146,7 @@ function EscrowScopeDetailContent({ uid, adminUid }: { uid: string; adminUid?: s
145
146
  setFields(toFieldsValue(loaded));
146
147
  }
147
148
  })
148
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load this escrow scope."))
149
+ .catch((err) => setError(actionErrorMessage(err, "Could not load this escrow scope.")))
149
150
  .finally(() => setLoading(false));
150
151
  }, [uid]);
151
152
 
@@ -165,6 +166,11 @@ function EscrowScopeDetailContent({ uid, adminUid }: { uid: string; adminUid?: s
165
166
  setError("The public key, its type, and its fingerprint are all required.");
166
167
  return;
167
168
  }
169
+ const validityError = keyValidityError(fields!);
170
+ if (validityError) {
171
+ setError(validityError);
172
+ return;
173
+ }
168
174
  if (fields!.holderUserUids.length === 0) {
169
175
  setError("At least one holder is required.");
170
176
  return;
@@ -208,7 +214,7 @@ function EscrowScopeDetailContent({ uid, adminUid }: { uid: string; adminUid?: s
208
214
  setFields(toFieldsValue(updated));
209
215
  setSaved(true);
210
216
  } catch (err) {
211
- setError(err instanceof ApiRequestError ? err.message : "Could not save this escrow scope.");
217
+ setError(actionErrorMessage(err, "Could not save this escrow scope."));
212
218
  } finally {
213
219
  setSaving(false);
214
220
  }
@@ -231,7 +237,7 @@ function EscrowScopeDetailContent({ uid, adminUid }: { uid: string; adminUid?: s
231
237
  } catch (err) {
232
238
  // Most commonly a 409 ("referenced by an existing Matter") — see `deleteEscrowScope()`'s own
233
239
  // doc comment - surfaced as-is rather than special-cased.
234
- setDeleteError(err instanceof ApiRequestError ? err.message : "Could not delete this escrow scope.");
240
+ setDeleteError(actionErrorMessage(err, "Could not delete this escrow scope."));
235
241
  setDeleting(false);
236
242
  }
237
243
  }
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { EscrowScope, listEscrowScopes } from "../../../lib/admin/escrowScopesApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
- import Alert from "../../../lib/components/feedback/Alert.js";
8
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
9
  import Button from "../../../lib/components/buttons/Button.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  const PAGE_SIZE = 25;
13
13
 
@@ -30,7 +30,7 @@ function EscrowScopesContent() {
30
30
  setError(null);
31
31
  listEscrowScopes({ page, limit: PAGE_SIZE })
32
32
  .then(setScopes)
33
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load escrow scopes."))
33
+ .catch((err) => setError(actionErrorMessage(err, "Could not load escrow scopes.")))
34
34
  .finally(() => setLoading(false));
35
35
  }, [page]);
36
36
 
@@ -4,16 +4,17 @@
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { FormEvent, useState } from "react";
6
6
  import { useRouter } from "@rapidrest/react/client";
7
- import { ApiRequestError } from "../../../../lib/util/api.js";
8
7
  import { createEscrowScope } from "../../../../lib/admin/escrowScopesApi.js";
9
8
  import AdminShell, { AdminShellProps } from "../../../shared/components/admin/layout/AdminShell.js";
10
9
  import EscrowScopeKeyAndHoldersFields, {
11
10
  emptyEscrowScopeKeyAndHoldersValue,
11
+ keyValidityError,
12
12
  selfAsHolderError,
13
13
  } from "../../../shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js";
14
- import Alert from "../../../../lib/components/feedback/Alert.js";
14
+ import Alert from "../../../shared/components/admin/ActionAlert.js";
15
15
  import Button from "../../../../lib/components/buttons/Button.js";
16
16
  import FormField from "../../../../lib/components/forms/FormField.js";
17
+ import { actionErrorMessage } from "../../../shared/components/admin/elevation.js";
17
18
 
18
19
  const INPUT_CLASS =
19
20
  "w-full text-sm py-2.5 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
@@ -46,6 +47,11 @@ function NewEscrowScopeForm({ adminUid }: { adminUid?: string }) {
46
47
  setError("The public key, its type, and its fingerprint are all required.");
47
48
  return;
48
49
  }
50
+ const validityError = keyValidityError(keyAndHolders);
51
+ if (validityError) {
52
+ setError(validityError);
53
+ return;
54
+ }
49
55
  if (keyAndHolders.holderUserUids.length === 0) {
50
56
  setError("At least one holder is required.");
51
57
  return;
@@ -78,7 +84,7 @@ function NewEscrowScopeForm({ adminUid }: { adminUid?: string }) {
78
84
  });
79
85
  void navigate(`/admin/escrow-scopes/${encodeURIComponent(created.uid)}`);
80
86
  } catch (err) {
81
- setError(err instanceof ApiRequestError ? err.message : "Could not create the escrow scope.");
87
+ setError(actionErrorMessage(err, "Could not create the escrow scope."));
82
88
  } finally {
83
89
  setSaving(false);
84
90
  }
@@ -4,15 +4,15 @@
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
6
  import { useRouter } from "@rapidrest/react/client";
7
- import { ApiRequestError } from "../../lib/util/api.js";
8
7
  import { listMailboxes, Mailbox } from "../../lib/mail/mailApi.js";
9
8
  import { reopenSetup } from "../../lib/admin/setupApi.js";
10
9
  import AdminShell, { AdminShellProps } from "../shared/components/admin/layout/AdminShell.js";
11
10
  import LeftoverMailboxesSection from "../shared/components/admin/mailboxes/LeftoverMailboxesSection.js";
12
11
  import MailboxTable from "../shared/components/admin/mailboxes/MailboxTable.js";
13
- import Alert from "../../lib/components/feedback/Alert.js";
12
+ import Alert from "../shared/components/admin/ActionAlert.js";
14
13
  import Button from "../../lib/components/buttons/Button.js";
15
14
  import Modal from "../../lib/components/overlays/Modal.js";
15
+ import { actionErrorMessage } from "../shared/components/admin/elevation.js";
16
16
 
17
17
  const PAGE_SIZE = 25;
18
18
 
@@ -37,7 +37,7 @@ function MailboxesListContent() {
37
37
  // The administration scope: every mailbox as administrative metadata - the console never shows anybody's mail.
38
38
  listMailboxes({ page, limit: PAGE_SIZE, scope: "admin" })
39
39
  .then(setMailboxes)
40
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load mailboxes."))
40
+ .catch((err) => setError(actionErrorMessage(err, "Could not load mailboxes.")))
41
41
  .finally(() => setLoading(false));
42
42
  }, [page]);
43
43
 
@@ -51,7 +51,7 @@ function MailboxesListContent() {
51
51
  await reopenSetup();
52
52
  void navigate("/admin/setup");
53
53
  } catch (err) {
54
- setError(err instanceof ApiRequestError ? err.message : "Could not reopen setup.");
54
+ setError(actionErrorMessage(err, "Could not reopen setup."));
55
55
  setReopening(false);
56
56
  setConfirmingSetup(false);
57
57
  }
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { IngestQueueEntry, listIngestQueue } from "../../../lib/mail/mailApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
- import Alert from "../../../lib/components/feedback/Alert.js";
8
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
9
  import Button from "../../../lib/components/buttons/Button.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  const PAGE_SIZE = 25;
13
13
 
@@ -56,7 +56,7 @@ function IngestQueueContent() {
56
56
  if (!cancelled) setEntries(data);
57
57
  })
58
58
  .catch((err) => {
59
- if (!cancelled) setError(err instanceof ApiRequestError ? err.message : "Could not load the ingest queue.");
59
+ if (!cancelled) setError(actionErrorMessage(err, "Could not load the ingest queue."));
60
60
  })
61
61
  .finally(() => {
62
62
  if (!cancelled) setLoading(false);
@@ -4,13 +4,14 @@
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
6
  import { useRouter } from "@rapidrest/react/client";
7
- import { ApiRequestError } from "../../../lib/util/api.js";
8
7
  import { deleteMailbox, getMailbox, impersonateUser, Mailbox } from "../../../lib/mail/mailApi.js";
9
8
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
10
+ import { resetNotifications } from "../../shared/notifications/store.js";
10
11
  import ShareAccessCard from "../../shared/components/admin/mailboxes/ShareAccessCard.js";
11
12
  import ResourceSettingsCard from "../../shared/components/admin/mailboxes/ResourceSettingsCard.js";
12
13
  import EscrowScopeCard from "../../shared/components/admin/mailboxes/EscrowScopeCard.js";
13
- import Alert from "../../../lib/components/feedback/Alert.js";
14
+ import Alert from "../../shared/components/admin/ActionAlert.js";
14
15
  import Button from "../../../lib/components/buttons/Button.js";
15
16
  import { describeTimeZone } from "../../../lib/util/timeZone.js";
16
17
  import Modal from "../../../lib/components/overlays/Modal.js";
@@ -64,9 +65,11 @@ function MailboxDetailContent({
64
65
  setAccessError(null);
65
66
  try {
66
67
  await impersonateUser(impersonationBaseUrl ?? "", mailbox!.ownerUserUid!);
68
+ // The administrator's own notification history is not the impersonated user's to read.
69
+ resetNotifications();
67
70
  window.location.href = "/";
68
71
  } catch (err) {
69
- setAccessError(err instanceof ApiRequestError ? err.message : "Could not impersonate this user.");
72
+ setAccessError(actionErrorMessage(err, "Could not impersonate this user."));
70
73
  setImpersonating(false);
71
74
  }
72
75
  }
@@ -92,19 +95,24 @@ function MailboxDetailContent({
92
95
  // Most commonly a 409 if this mailbox is a custodian on an open legal hold (restapi's own
93
96
  // `assertNotOnLegalHold()`, naming the blocking Matter uid(s)) - surfaced as-is, same as
94
97
  // every other destructive-action error in this codebase, rather than special-cased here.
95
- setDeleteError(err instanceof ApiRequestError ? err.message : "Could not delete this mailbox.");
98
+ setDeleteError(actionErrorMessage(err, "Could not delete this mailbox."));
96
99
  setDeleting(false);
97
100
  }
98
101
  }
99
102
 
100
103
  useEffect(() => {
104
+ // An answer for a mailbox since replaced (another uid) must not be shown as the current one: the delete and impersonate actions act on what is shown.
105
+ let cancelled = false;
101
106
  setLoading(true);
102
107
  setError(null);
103
108
  // The administration scope: administrative metadata only - the console never shows a mailbox's mail or settings.
104
109
  getMailbox(uid, { scope: "admin" })
105
- .then(setMailbox)
106
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load this mailbox."))
107
- .finally(() => setLoading(false));
110
+ .then((loaded) => !cancelled && setMailbox(loaded))
111
+ .catch((err) => !cancelled && setError(actionErrorMessage(err, "Could not load this mailbox.")))
112
+ .finally(() => !cancelled && setLoading(false));
113
+ return () => {
114
+ cancelled = true;
115
+ };
108
116
  }, [uid]);
109
117
 
110
118
  if (loading) {
@@ -3,12 +3,12 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { listQuarantine, QuarantineEntry, releaseQuarantineEntry } from "../../../lib/mail/mailApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
- import Alert from "../../../lib/components/feedback/Alert.js";
8
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
9
  import Button from "../../../lib/components/buttons/Button.js";
11
10
  import Modal from "../../../lib/components/overlays/Modal.js";
11
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
12
12
 
13
13
  const PAGE_SIZE = 25;
14
14
 
@@ -45,7 +45,7 @@ function QuarantineContent({ userUid }: { userUid?: string }) {
45
45
  // The administration scope: any mailbox's held mail, recorded in the audit log.
46
46
  listQuarantine(uid, { page, limit: PAGE_SIZE, scope: "admin" })
47
47
  .then(setEntries)
48
- .catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load quarantine."))
48
+ .catch((err) => setError(actionErrorMessage(err, "Could not load quarantine.")))
49
49
  .finally(() => setLoading(false));
50
50
  }
51
51
 
@@ -74,7 +74,7 @@ function QuarantineContent({ userUid }: { userUid?: string }) {
74
74
  closeReleaseModal();
75
75
  reload(mailboxUid!);
76
76
  } catch (err) {
77
- setReleaseError(err instanceof ApiRequestError ? err.message : "Could not mark this message released.");
77
+ setReleaseError(actionErrorMessage(err, "Could not mark this message released."));
78
78
  } finally {
79
79
  setReleasing(false);
80
80
  }
@@ -3,11 +3,11 @@
3
3
  // SPDX-License-Identifier: MPL-2.0
4
4
  ///////////////////////////////////////////////////////////////////////////////
5
5
  import React, { useEffect, useState } from "react";
6
- import { ApiRequestError } from "../../../lib/util/api.js";
7
6
  import { RetentionPolicy, getRetentionPolicy } from "../../../lib/admin/retentionPolicyApi.js";
8
7
  import AdminShell, { AdminShellProps } from "../../shared/components/admin/layout/AdminShell.js";
9
8
  import RetentionPolicyForm from "../../shared/components/admin/settings/RetentionPolicyForm.js";
10
- import Alert from "../../../lib/components/feedback/Alert.js";
9
+ import Alert from "../../shared/components/admin/ActionAlert.js";
10
+ import { actionErrorMessage } from "../../shared/components/admin/elevation.js";
11
11
 
12
12
  export default function RetentionPolicyPage(props: Omit<AdminShellProps, "active">) {
13
13
  return (
@@ -25,7 +25,7 @@ function RetentionPolicyContent() {
25
25
  useEffect(() => {
26
26
  getRetentionPolicy()
27
27
  .then(setPolicy)
28
- .catch((err) => setLoadError(err instanceof ApiRequestError ? err.message : "Could not load the retention policy."))
28
+ .catch((err) => setLoadError(actionErrorMessage(err, "Could not load the retention policy.")))
29
29
  .finally(() => setLoading(false));
30
30
  }, []);
31
31