@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.
- package/README.md +373 -373
- package/apps/admin/branding/index.tsx +39 -39
- package/apps/admin/data-requests/index.tsx +482 -480
- package/apps/admin/domains/[uid].tsx +164 -163
- package/apps/admin/escrow-scopes/[uid].tsx +348 -348
- package/apps/admin/index.tsx +127 -124
- package/apps/admin/mailboxes/[uid].tsx +269 -224
- package/apps/admin/mailboxes/new/index.tsx +28 -28
- package/apps/admin/plugins/index.tsx +15 -15
- package/apps/admin/retention-policy/index.tsx +39 -39
- package/apps/admin/signing-certificates/index.tsx +343 -343
- package/apps/escrow/audit-log/index.tsx +196 -196
- package/apps/escrow/matters/[uid].tsx +621 -621
- package/apps/shared/appearance/AppearanceForm.tsx +9 -1
- package/apps/shared/auth/adminAccess.ts +99 -99
- package/apps/shared/calendar/bookingPlugin.ts +100 -0
- package/apps/shared/calendar/calendarLiveUpdates.ts +27 -0
- package/apps/shared/components/admin/layout/AdminShell.tsx +378 -346
- package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +238 -0
- package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -152
- package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +194 -0
- package/apps/shared/components/admin/settings/BrandingForm.tsx +423 -423
- package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +119 -119
- package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +53 -4
- package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +198 -198
- package/apps/shared/components/admin/settings/PluginsManager.tsx +64 -10
- package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +182 -182
- package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +288 -288
- package/apps/shared/components/admin/setup/SetupWizard.tsx +444 -444
- package/apps/shared/components/admin/usePagedList.tsx +129 -129
- package/apps/shared/components/calendar/AppointmentQuickForm.tsx +327 -0
- package/apps/shared/components/calendar/DescriptionEditor.tsx +274 -0
- package/apps/shared/components/calendar/EventDescriptionView.tsx +70 -0
- package/apps/shared/components/calendar/EventDetails.tsx +401 -0
- package/apps/shared/components/calendar/EventEditor.tsx +635 -0
- package/apps/shared/components/calendar/EventExpandedForm.tsx +210 -0
- package/apps/shared/components/calendar/EventFormParts.tsx +591 -0
- package/apps/shared/components/calendar/EventModal.tsx +206 -946
- package/apps/shared/components/calendar/EventQuickForm.tsx +116 -0
- package/apps/shared/components/calendar/EventShell.tsx +202 -0
- package/apps/shared/components/calendar/FindATime.tsx +379 -0
- package/apps/shared/components/calendar/GuestInput.tsx +100 -0
- package/apps/shared/components/calendar/LazyDescriptionEditor.tsx +70 -0
- package/apps/shared/components/calendar/MonthView.tsx +185 -173
- package/apps/shared/components/calendar/QuickCreateFaces.tsx +87 -0
- package/apps/shared/components/calendar/QuickCreateTabs.tsx +81 -0
- package/apps/shared/components/calendar/QuickFaceFrame.tsx +81 -0
- package/apps/shared/components/calendar/RecurrenceEditor.tsx +227 -222
- package/apps/shared/components/calendar/RequestChangeForm.tsx +240 -0
- package/apps/shared/components/calendar/SplitDayView.tsx +144 -143
- package/apps/shared/components/calendar/TaskQuickForm.tsx +289 -0
- package/apps/shared/components/calendar/TimeGridView.tsx +246 -244
- package/apps/shared/components/calendar/allDay.ts +124 -124
- package/apps/shared/components/calendar/eventDialogFields.ts +86 -0
- package/apps/shared/components/calendar/eventForm.ts +108 -0
- package/apps/shared/components/calendar/eventFormat.ts +210 -0
- package/apps/shared/components/calendar/findTimeGrid.ts +90 -0
- package/apps/shared/components/calendar/layout/CalendarShell.tsx +201 -200
- package/apps/shared/components/calendar/swipeNavigation.ts +14 -0
- package/apps/shared/components/contacts/ContactForm.tsx +383 -383
- package/apps/shared/components/contacts/ContactsSidebar.tsx +1 -1
- package/apps/shared/components/contacts/ContactsToolbar.tsx +103 -98
- package/apps/shared/components/contacts/layout/ContactsShell.tsx +217 -216
- package/apps/shared/components/escrow/layout/EscrowShell.tsx +155 -155
- package/apps/shared/components/layout/AppShell.tsx +480 -480
- package/apps/shared/components/layout/FloatingActionButton.tsx +31 -0
- package/apps/shared/components/layout/KeyEnrollmentGate.tsx +398 -398
- package/apps/shared/components/layout/MailboxProvisioning.tsx +168 -168
- package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -315
- package/apps/shared/components/layout/ThemeSwitch.tsx +84 -84
- package/apps/shared/components/layout/UserMenu.tsx +439 -372
- package/apps/shared/components/mail/ConversationList.tsx +323 -271
- package/apps/shared/components/mail/ConversationThreadPane.tsx +130 -5
- package/apps/shared/components/mail/InviteCard.tsx +387 -0
- package/apps/shared/components/mail/MailSelectionBar.tsx +236 -227
- package/apps/shared/components/mail/MessageDetailPane.tsx +1559 -1537
- package/apps/shared/components/mail/SwipeRow.tsx +120 -0
- package/apps/shared/components/mail/compose/ComposeContext.tsx +312 -312
- package/apps/shared/components/mail/compose/ComposeToolbar.tsx +422 -422
- package/apps/shared/components/mail/compose/ComposeWindow.tsx +1681 -1673
- package/apps/shared/components/mail/compose/RecipientInput.tsx +54 -11
- package/apps/shared/components/mail/compose/RichTextEditor.tsx +147 -147
- package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -60
- package/apps/shared/components/mail/compose/quotedBody.ts +161 -161
- package/apps/shared/components/mail/invite/InviteRowChip.tsx +104 -0
- package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +271 -0
- package/apps/shared/components/mail/invite/InviteTimeline.tsx +200 -0
- package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +109 -0
- package/apps/shared/components/mail/invite/inviteFormat.ts +110 -0
- package/apps/shared/components/mail/invite/inviteStore.ts +114 -0
- package/apps/shared/components/mail/layout/FolderBadgeChip.tsx +21 -0
- package/apps/shared/components/mail/layout/MailShell.tsx +546 -490
- package/apps/shared/components/mail/layout/SidebarSection.tsx +66 -0
- package/apps/shared/components/mail/reading/PendingMessageCard.tsx +68 -0
- package/apps/shared/components/mail/verificationSeals.ts +125 -125
- package/apps/shared/components/rules/RuleBuilder.tsx +311 -311
- package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -344
- package/apps/shared/components/settings/layout/SettingsShell.tsx +255 -253
- package/apps/shared/components/tasks/TasksSidebar.tsx +1 -1
- package/apps/shared/components/tasks/layout/TasksShell.tsx +218 -217
- package/apps/shared/gestures/useEnterSlide.ts +54 -0
- package/apps/shared/gestures/useSwipe.ts +114 -0
- package/apps/shared/gestures/useSwipeSlide.ts +113 -0
- package/apps/shared/gestures/useWheelPaging.ts +107 -0
- package/apps/shared/keyboard/GlobalShortcuts.tsx +51 -51
- package/apps/shared/keyboard/ShortcutProvider.tsx +62 -62
- package/apps/shared/keyboard/ShortcutsDialog.tsx +84 -84
- package/apps/shared/keyboard/dispatch.ts +124 -124
- package/apps/shared/keyboard/format.ts +89 -89
- package/apps/shared/keyboard/keymap.ts +114 -114
- package/apps/shared/keyboard/registry.ts +65 -65
- package/apps/shared/keyboard/targets.ts +79 -79
- package/apps/shared/mail/folderCounts.ts +17 -0
- package/apps/shared/mail/folderTree.ts +143 -143
- package/apps/shared/mail/listAllPages.ts +39 -39
- package/apps/shared/mail/newMailNotifications.ts +3 -15
- package/apps/shared/mail/outbox/outgoingReplies.ts +192 -0
- package/apps/shared/mail/outbox/sendJob.ts +19 -1
- package/apps/shared/mail/outbox/sendOutcomes.ts +13 -4
- package/apps/shared/mail/primaryMailbox.ts +71 -0
- package/apps/shared/mail/useCollapsedSections.ts +146 -0
- package/apps/shared/mail/useMailConnection.ts +205 -203
- package/apps/shared/mail/useMailLiveUpdates.ts +277 -277
- package/apps/shared/mail/useMarkMessageRead.ts +47 -47
- package/apps/shared/mail/useNewMailNotifications.ts +2 -2
- package/apps/shared/navigation/AppRouter.tsx +300 -300
- package/apps/shared/navigation/routerContext.tsx +83 -83
- package/apps/shared/notifications/preferences.ts +36 -0
- package/apps/shared/notifications/store.ts +9 -0
- package/apps/shared/search/LocalIndexLifecycle.tsx +114 -114
- package/apps/shared/search/crossMailboxSearch.ts +169 -0
- package/apps/shared/search/localIndexBuilder.ts +481 -481
- package/apps/shared/signing/enrollmentStorage.ts +33 -33
- package/apps/shared/signing/enrollmentTracker.ts +385 -385
- package/apps/shared/signing/enrollmentView.ts +251 -251
- package/apps/shared/signing/useNow.ts +19 -19
- package/apps/shared/signing/useSigningEnrollmentWatcher.ts +90 -90
- package/apps/shared/styles/app.css +396 -386
- package/apps/www/_routes.ts +1 -0
- package/apps/www/calendar/index.tsx +578 -469
- package/apps/www/contacts/[uid].tsx +109 -109
- package/apps/www/contacts/index.tsx +6 -0
- package/apps/www/index.tsx +2847 -2332
- package/apps/www/messages/[uid].tsx +135 -108
- package/apps/www/settings/auto-reply/index.tsx +133 -133
- package/apps/www/settings/encryption/index.tsx +1287 -1287
- package/apps/www/settings/filters/[uid].tsx +176 -176
- package/apps/www/settings/filters/index.tsx +102 -102
- package/apps/www/settings/filters/new/index.tsx +140 -140
- package/apps/www/settings/labels/index.tsx +204 -204
- package/apps/www/settings/privacy/index.tsx +492 -492
- package/apps/www/settings/profile/index.tsx +248 -0
- package/apps/www/settings/read-receipts/index.tsx +147 -147
- package/apps/www/settings/sharing/index.tsx +256 -256
- package/apps/www/settings/signatures/[uid].tsx +172 -172
- package/apps/www/settings/signatures/index.tsx +88 -88
- package/apps/www/settings/signatures/new/index.tsx +135 -135
- package/apps/www/tasks/index.tsx +649 -649
- package/dist/apps/admin/data-requests/index.js +1 -1
- package/dist/apps/admin/domains/[uid].js +4 -2
- package/dist/apps/admin/index.js +2 -1
- package/dist/apps/admin/mailboxes/[uid].js +12 -2
- package/dist/apps/shared/appearance/AppearanceForm.js +9 -1
- package/dist/apps/shared/calendar/bookingPlugin.d.ts +50 -0
- package/dist/apps/shared/calendar/bookingPlugin.js +57 -0
- package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +11 -0
- package/dist/apps/shared/calendar/calendarLiveUpdates.js +23 -0
- package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
- package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -3
- package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +35 -0
- package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +115 -0
- package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.d.ts +16 -0
- package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +92 -0
- package/dist/apps/shared/components/admin/settings/BrandingForm.js +3 -3
- package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +28 -4
- package/dist/apps/shared/components/admin/settings/PluginsManager.js +40 -6
- package/dist/apps/shared/components/calendar/AppointmentQuickForm.d.ts +47 -0
- package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +135 -0
- package/dist/apps/shared/components/calendar/DescriptionEditor.d.ts +26 -0
- package/dist/apps/shared/components/calendar/DescriptionEditor.js +192 -0
- package/dist/apps/shared/components/calendar/EventDescriptionView.d.ts +14 -0
- package/dist/apps/shared/components/calendar/EventDescriptionView.js +39 -0
- package/dist/apps/shared/components/calendar/EventDetails.d.ts +33 -0
- package/dist/apps/shared/components/calendar/EventDetails.js +137 -0
- package/dist/apps/shared/components/calendar/EventEditor.d.ts +59 -0
- package/dist/apps/shared/components/calendar/EventEditor.js +544 -0
- package/dist/apps/shared/components/calendar/EventExpandedForm.d.ts +14 -0
- package/dist/apps/shared/components/calendar/EventExpandedForm.js +44 -0
- package/dist/apps/shared/components/calendar/EventFormParts.d.ts +70 -0
- package/dist/apps/shared/components/calendar/EventFormParts.js +191 -0
- package/dist/apps/shared/components/calendar/EventModal.d.ts +26 -13
- package/dist/apps/shared/components/calendar/EventModal.js +57 -459
- package/dist/apps/shared/components/calendar/EventQuickForm.d.ts +18 -0
- package/dist/apps/shared/components/calendar/EventQuickForm.js +25 -0
- package/dist/apps/shared/components/calendar/EventShell.d.ts +64 -0
- package/dist/apps/shared/components/calendar/EventShell.js +134 -0
- package/dist/apps/shared/components/calendar/FindATime.d.ts +18 -0
- package/dist/apps/shared/components/calendar/FindATime.js +190 -0
- package/dist/apps/shared/components/calendar/GuestInput.d.ts +45 -0
- package/dist/apps/shared/components/calendar/GuestInput.js +30 -0
- package/dist/apps/shared/components/calendar/LazyDescriptionEditor.d.ts +8 -0
- package/dist/apps/shared/components/calendar/LazyDescriptionEditor.js +44 -0
- package/dist/apps/shared/components/calendar/MonthView.d.ts +5 -1
- package/dist/apps/shared/components/calendar/MonthView.js +11 -5
- package/dist/apps/shared/components/calendar/QuickCreateFaces.d.ts +30 -0
- package/dist/apps/shared/components/calendar/QuickCreateFaces.js +44 -0
- package/dist/apps/shared/components/calendar/QuickCreateTabs.d.ts +24 -0
- package/dist/apps/shared/components/calendar/QuickCreateTabs.js +46 -0
- package/dist/apps/shared/components/calendar/QuickFaceFrame.d.ts +25 -0
- package/dist/apps/shared/components/calendar/QuickFaceFrame.js +19 -0
- package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +4 -1
- package/dist/apps/shared/components/calendar/RecurrenceEditor.js +2 -2
- package/dist/apps/shared/components/calendar/RequestChangeForm.d.ts +36 -0
- package/dist/apps/shared/components/calendar/RequestChangeForm.js +127 -0
- package/dist/apps/shared/components/calendar/SplitDayView.d.ts +3 -2
- package/dist/apps/shared/components/calendar/SplitDayView.js +3 -2
- package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +40 -0
- package/dist/apps/shared/components/calendar/TaskQuickForm.js +101 -0
- package/dist/apps/shared/components/calendar/TimeGridView.d.ts +4 -2
- package/dist/apps/shared/components/calendar/TimeGridView.js +3 -2
- package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +28 -0
- package/dist/apps/shared/components/calendar/eventDialogFields.js +59 -0
- package/dist/apps/shared/components/calendar/eventForm.d.ts +98 -0
- package/dist/apps/shared/components/calendar/eventForm.js +1 -0
- package/dist/apps/shared/components/calendar/eventFormat.d.ts +80 -0
- package/dist/apps/shared/components/calendar/eventFormat.js +190 -0
- package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +30 -0
- package/dist/apps/shared/components/calendar/findTimeGrid.js +83 -0
- package/dist/apps/shared/components/calendar/layout/CalendarShell.js +3 -2
- package/dist/apps/shared/components/calendar/swipeNavigation.d.ts +9 -0
- package/dist/apps/shared/components/calendar/swipeNavigation.js +8 -0
- package/dist/apps/shared/components/contacts/ContactsSidebar.js +1 -1
- package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +3 -1
- package/dist/apps/shared/components/contacts/ContactsToolbar.js +4 -2
- package/dist/apps/shared/components/contacts/layout/ContactsShell.js +4 -3
- package/dist/apps/shared/components/layout/FloatingActionButton.d.ts +13 -0
- package/dist/apps/shared/components/layout/FloatingActionButton.js +9 -0
- package/dist/apps/shared/components/layout/UserMenu.d.ts +14 -9
- package/dist/apps/shared/components/layout/UserMenu.js +74 -26
- package/dist/apps/shared/components/mail/ConversationList.d.ts +12 -1
- package/dist/apps/shared/components/mail/ConversationList.js +21 -4
- package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +4 -1
- package/dist/apps/shared/components/mail/ConversationThreadPane.js +127 -22
- package/dist/apps/shared/components/mail/InviteCard.d.ts +20 -0
- package/dist/apps/shared/components/mail/InviteCard.js +150 -0
- package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +6 -1
- package/dist/apps/shared/components/mail/MailSelectionBar.js +3 -3
- package/dist/apps/shared/components/mail/MessageDetailPane.js +13 -2
- package/dist/apps/shared/components/mail/SwipeRow.d.ts +22 -0
- package/dist/apps/shared/components/mail/SwipeRow.js +71 -0
- package/dist/apps/shared/components/mail/compose/ComposeWindow.js +16 -7
- package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +21 -1
- package/dist/apps/shared/components/mail/compose/RecipientInput.js +18 -10
- package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +23 -0
- package/dist/apps/shared/components/mail/invite/InviteRowChip.js +46 -0
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +20 -0
- package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +141 -0
- package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +27 -0
- package/dist/apps/shared/components/mail/invite/InviteTimeline.js +120 -0
- package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +17 -0
- package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +45 -0
- package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +28 -0
- package/dist/apps/shared/components/mail/invite/inviteFormat.js +94 -0
- package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +28 -0
- package/dist/apps/shared/components/mail/invite/inviteStore.js +95 -0
- package/dist/apps/shared/components/mail/layout/FolderBadgeChip.d.ts +6 -0
- package/dist/apps/shared/components/mail/layout/FolderBadgeChip.js +9 -0
- package/dist/apps/shared/components/mail/layout/MailShell.d.ts +10 -0
- package/dist/apps/shared/components/mail/layout/MailShell.js +76 -46
- package/dist/apps/shared/components/mail/layout/SidebarSection.d.ts +23 -0
- package/dist/apps/shared/components/mail/layout/SidebarSection.js +16 -0
- package/dist/apps/shared/components/mail/reading/PendingMessageCard.d.ts +14 -0
- package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +16 -0
- package/dist/apps/shared/components/settings/layout/SettingsShell.js +7 -5
- package/dist/apps/shared/components/tasks/TasksSidebar.js +1 -1
- package/dist/apps/shared/components/tasks/layout/TasksShell.js +4 -3
- package/dist/apps/shared/gestures/useEnterSlide.d.ts +14 -0
- package/dist/apps/shared/gestures/useEnterSlide.js +47 -0
- package/dist/apps/shared/gestures/useSwipe.d.ts +45 -0
- package/dist/apps/shared/gestures/useSwipe.js +90 -0
- package/dist/apps/shared/gestures/useSwipeSlide.d.ts +40 -0
- package/dist/apps/shared/gestures/useSwipeSlide.js +95 -0
- package/dist/apps/shared/gestures/useWheelPaging.d.ts +32 -0
- package/dist/apps/shared/gestures/useWheelPaging.js +85 -0
- package/dist/apps/shared/mail/folderCounts.d.ts +10 -0
- package/dist/apps/shared/mail/folderCounts.js +12 -0
- package/dist/apps/shared/mail/newMailNotifications.d.ts +3 -8
- package/dist/apps/shared/mail/newMailNotifications.js +3 -12
- package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +80 -0
- package/dist/apps/shared/mail/outbox/outgoingReplies.js +131 -0
- package/dist/apps/shared/mail/outbox/sendJob.d.ts +5 -1
- package/dist/apps/shared/mail/outbox/sendJob.js +14 -1
- package/dist/apps/shared/mail/outbox/sendOutcomes.js +13 -4
- package/dist/apps/shared/mail/primaryMailbox.d.ts +29 -0
- package/dist/apps/shared/mail/primaryMailbox.js +61 -0
- package/dist/apps/shared/mail/useCollapsedSections.d.ts +32 -0
- package/dist/apps/shared/mail/useCollapsedSections.js +110 -0
- package/dist/apps/shared/mail/useMailConnection.js +3 -1
- package/dist/apps/shared/mail/useNewMailNotifications.js +3 -2
- package/dist/apps/shared/notifications/preferences.d.ts +13 -0
- package/dist/apps/shared/notifications/preferences.js +36 -0
- package/dist/apps/shared/notifications/store.d.ts +1 -0
- package/dist/apps/shared/notifications/store.js +7 -23
- package/dist/apps/shared/search/crossMailboxSearch.d.ts +72 -0
- package/dist/apps/shared/search/crossMailboxSearch.js +136 -0
- package/dist/apps/shared/styles/app.css +396 -386
- package/dist/apps/www/_routes.js +1 -0
- package/dist/apps/www/calendar/index.js +78 -7
- package/dist/apps/www/contacts/index.js +3 -1
- package/dist/apps/www/index.js +548 -210
- package/dist/apps/www/messages/[uid].js +13 -5
- package/dist/apps/www/settings/profile/index.d.ts +4 -0
- package/dist/apps/www/settings/profile/index.js +124 -0
- package/package.json +2 -2
|
@@ -1,108 +1,135 @@
|
|
|
1
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
-
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
-
import { routedPage } from "../_routedPage.js";
|
|
6
|
-
import React, { useEffect, useState } from "react";
|
|
7
|
-
import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
|
|
8
|
-
import { Message, getMessage } from "@rapidmx/react-shared/mail/mailApi.js";
|
|
9
|
-
import { Label, listLabels } from "@rapidmx/react-shared/mail/labelsApi.js";
|
|
10
|
-
import { useMessageAttachments } from "@rapidmx/react-shared/mail/mailDetailHooks.js";
|
|
11
|
-
import { useMarkMessageRead } from "../../shared/mail/useMarkMessageRead.js";
|
|
12
|
-
import MailShell, { MailShellProps, useMailShell } from "../../shared/components/mail/layout/MailShell.js";
|
|
13
|
-
import { LazyMessageDetailPane } from "../../shared/components/mail/LazyReadingPane.js";
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { routedPage } from "../_routedPage.js";
|
|
6
|
+
import React, { useEffect, useState } from "react";
|
|
7
|
+
import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
|
|
8
|
+
import { Message, getMessage } from "@rapidmx/react-shared/mail/mailApi.js";
|
|
9
|
+
import { Label, listLabels } from "@rapidmx/react-shared/mail/labelsApi.js";
|
|
10
|
+
import { useMessageAttachments } from "@rapidmx/react-shared/mail/mailDetailHooks.js";
|
|
11
|
+
import { useMarkMessageRead } from "../../shared/mail/useMarkMessageRead.js";
|
|
12
|
+
import MailShell, { MailShellProps, useMailShell } from "../../shared/components/mail/layout/MailShell.js";
|
|
13
|
+
import { LazyConversationThreadPane, LazyMessageDetailPane } from "../../shared/components/mail/LazyReadingPane.js";
|
|
14
|
+
import { useLocationSearch } from "../../shared/navigation/AppRouter.js";
|
|
15
|
+
import { ReadingPaneSkeleton } from "../../shared/components/mail/reading/MessageCard.js";
|
|
16
|
+
import Alert from "@rapidmx/react-shared/components/feedback/Alert.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Only reached on mobile (below the `md` breakpoint) — desktop's `apps/www/index.tsx` keeps its existing
|
|
20
|
+
* inline reading pane and never navigates here; see that file's `handleSelect`. A row of the conversation list
|
|
21
|
+
* comes with `?conversation=<id>` (`handleOpenConversation`), and then this page is the whole thread, opened at this
|
|
22
|
+
* message, as the desktop's reading pane is; without it (a flat list, a link to a message) it is that one message.
|
|
23
|
+
*/
|
|
24
|
+
function MessageDetailPage(props: MailShellProps & { params: { uid: string } }) {
|
|
25
|
+
return (
|
|
26
|
+
<MailShell {...props}>
|
|
27
|
+
<MessageDetailContent uid={props.params.uid} />
|
|
28
|
+
</MailShell>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function MessageDetailContent({ uid }: { uid: string }) {
|
|
33
|
+
const { mailboxFolders, mailboxUid, onFolderCreated } = useMailShell();
|
|
34
|
+
const [message, setMessage] = useState<Message | null>(null);
|
|
35
|
+
const [loading, setLoading] = useState(true);
|
|
36
|
+
const [error, setError] = useState<string | null>(null);
|
|
37
|
+
const [labels, setLabels] = useState<Label[]>([]);
|
|
38
|
+
const conversationId: string | null = new URLSearchParams(useLocationSearch()).get("conversation");
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
setLoading(true);
|
|
42
|
+
setError(null);
|
|
43
|
+
getMessage(uid)
|
|
44
|
+
.then(setMessage)
|
|
45
|
+
.catch((err) => setError(err instanceof ApiRequestError ? err.message : "Could not load this message."))
|
|
46
|
+
.finally(() => setLoading(false));
|
|
47
|
+
}, [uid]);
|
|
48
|
+
|
|
49
|
+
// See `apps/www/index.tsx`'s identical effect's own doc comment - a failure here just hides the
|
|
50
|
+
// Labels control rather than blocking the rest of the page. Keyed on the message's own mailbox, not the
|
|
51
|
+
// shell's ambient one: this route is reached from aggregate/search rows too, where they can differ.
|
|
52
|
+
const messageMailboxUid = message?.mailboxUid;
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
if (!messageMailboxUid) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
let cancelled = false;
|
|
58
|
+
listLabels(messageMailboxUid, { limit: 200 })
|
|
59
|
+
.then((result) => {
|
|
60
|
+
if (!cancelled) {
|
|
61
|
+
setLabels(result);
|
|
62
|
+
}
|
|
63
|
+
})
|
|
64
|
+
.catch(() => undefined);
|
|
65
|
+
return () => {
|
|
66
|
+
cancelled = true;
|
|
67
|
+
};
|
|
68
|
+
}, [messageMailboxUid]);
|
|
69
|
+
|
|
70
|
+
// A thread loads, marks read and fetches the attachments of each message it opens itself.
|
|
71
|
+
const attachments = useMessageAttachments(conversationId ? null : message);
|
|
72
|
+
useMarkMessageRead(conversationId ? null : message, setMessage);
|
|
73
|
+
|
|
74
|
+
if (loading) {
|
|
75
|
+
// The pane's own frame - a header card and a message card - rather than a line of text: what is coming is known, only not yet its contents.
|
|
76
|
+
return <ReadingPaneSkeleton />;
|
|
77
|
+
}
|
|
78
|
+
if (error || !message) {
|
|
79
|
+
return <Alert>{error ?? "Message not found."}</Alert>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Looked up by the message's own mailboxUid, not the shell's ambient `mailboxUid` - the mobile detail
|
|
83
|
+
// route reaches here from an aggregate ("All Inboxes" etc.) list row too, where there's no single
|
|
84
|
+
// selected mailbox to fall back to.
|
|
85
|
+
const folders = mailboxFolders.find((mf) => mf.mailbox.uid === message.mailboxUid)?.folders ?? [];
|
|
86
|
+
const backHref = `/?mailboxUid=${encodeURIComponent(message.mailboxUid)}&folderUid=${encodeURIComponent(message.folderUid)}`;
|
|
87
|
+
const isSentItems = folders.find((f) => f.uid === message.folderUid)?.type === "sent_items";
|
|
88
|
+
const isOutbox = folders.find((f) => f.uid === message.folderUid)?.type === "outbox";
|
|
89
|
+
const draftsFolderUid = folders.find((f) => f.type === "drafts")?.uid;
|
|
90
|
+
if (conversationId) {
|
|
91
|
+
return (
|
|
92
|
+
// The thread's own height, as the single message's: it scrolls inside the page rather than growing it.
|
|
93
|
+
<div className="flex flex-col h-full min-h-0">
|
|
94
|
+
<a href={backHref} className="text-sm text-primary-dark hover:underline block px-4 pt-3">
|
|
95
|
+
← Back to messages
|
|
96
|
+
</a>
|
|
97
|
+
<LazyConversationThreadPane
|
|
98
|
+
conversation={{ conversationId, subject: message.subject, messageCount: 1 }}
|
|
99
|
+
selectedUid={message.uid}
|
|
100
|
+
mailboxUid={message.mailboxUid}
|
|
101
|
+
folders={folders}
|
|
102
|
+
labels={labels}
|
|
103
|
+
shortcuts
|
|
104
|
+
onMessagePatched={() => undefined}
|
|
105
|
+
onMessageRemoved={() => undefined}
|
|
106
|
+
onLabelCreated={(label) => setLabels((prev) => [...prev, label])}
|
|
107
|
+
onFolderCreated={onFolderCreated}
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return (
|
|
113
|
+
<LazyMessageDetailPane
|
|
114
|
+
shortcuts
|
|
115
|
+
message={message}
|
|
116
|
+
attachments={attachments}
|
|
117
|
+
backHref={backHref}
|
|
118
|
+
isSentItems={isSentItems}
|
|
119
|
+
onRecalled={setMessage}
|
|
120
|
+
isOutbox={isOutbox}
|
|
121
|
+
onReceiptHandled={setMessage}
|
|
122
|
+
draftsFolderUid={draftsFolderUid}
|
|
123
|
+
folders={folders}
|
|
124
|
+
onMoved={setMessage}
|
|
125
|
+
onFolderCreated={onFolderCreated}
|
|
126
|
+
onScheduledSendCanceled={setMessage}
|
|
127
|
+
onArchived={setMessage}
|
|
128
|
+
labels={labels}
|
|
129
|
+
onLabelsChanged={setMessage}
|
|
130
|
+
onLabelCreated={(label) => setLabels((prev) => [...prev, label])}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export default routedPage("/messages/:uid", MessageDetailPage);
|
|
@@ -1,133 +1,133 @@
|
|
|
1
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
-
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
-
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
-
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
-
import { routedPage } from "../../_routedPage.js";
|
|
6
|
-
import React, { FormEvent, useState } from "react";
|
|
7
|
-
import { toDatetimeLocal } from "@rapidmx/react-shared/util/dateInput.js";
|
|
8
|
-
import { updateMailbox } from "@rapidmx/react-shared/mail/mailApi.js";
|
|
9
|
-
import SettingsShell, { SettingsShellProps, useSettingsShell } from "../../../shared/components/settings/layout/SettingsShell.js";
|
|
10
|
-
import Button from "@rapidmx/react-shared/components/buttons/Button.js";
|
|
11
|
-
import { notifyApiError } from "../../../shared/notifications/apiErrors.js";
|
|
12
|
-
|
|
13
|
-
const INPUT_CLASS =
|
|
14
|
-
"w-full text-sm py-2 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
|
|
15
|
-
|
|
16
|
-
export type SettingsAutoReplyPageProps = Omit<SettingsShellProps, "active">;
|
|
17
|
-
|
|
18
|
-
function SettingsAutoReplyPage(props: SettingsAutoReplyPageProps) {
|
|
19
|
-
return (
|
|
20
|
-
<SettingsShell {...props} active="auto-reply">
|
|
21
|
-
<AutoReplyContent />
|
|
22
|
-
</SettingsShell>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function AutoReplyContent() {
|
|
27
|
-
const { mailboxUid, mailboxes } = useSettingsShell();
|
|
28
|
-
// `SettingsShell` only ever renders its children once `mailboxes` has loaded and `mailboxUid` has
|
|
29
|
-
// resolved to one of them (a mailbox-less caller sees `MailboxProvisioning` instead) — this lookup
|
|
30
|
-
// can't miss, same established non-null pattern as `apps/www/contacts/index.tsx`'s `mailboxUid!`.
|
|
31
|
-
const mailbox = mailboxes.find((mb) => mb.uid === mailboxUid)!;
|
|
32
|
-
|
|
33
|
-
const [oofEnabled, setOofEnabled] = useState(mailbox.oofEnabled ?? false);
|
|
34
|
-
const [oofMessage, setOofMessage] = useState(mailbox.oofMessage ?? "");
|
|
35
|
-
const [oofStartTime, setOofStartTime] = useState(mailbox.oofStartTime ? toDatetimeLocal(mailbox.oofStartTime) : "");
|
|
36
|
-
const [oofEndTime, setOofEndTime] = useState(mailbox.oofEndTime ? toDatetimeLocal(mailbox.oofEndTime) : "");
|
|
37
|
-
// `SettingsShell`'s `mailboxes` is fetched once - every save bumps the server's version, so a second
|
|
38
|
-
// save without a reload must send the version the previous save returned, not the stale original.
|
|
39
|
-
const [version, setVersion] = useState(mailbox.version);
|
|
40
|
-
const [saving, setSaving] = useState(false);
|
|
41
|
-
const [saved, setSaved] = useState(false);
|
|
42
|
-
|
|
43
|
-
async function handleSubmit(e: FormEvent) {
|
|
44
|
-
e.preventDefault();
|
|
45
|
-
setSaved(false);
|
|
46
|
-
setSaving(true);
|
|
47
|
-
try {
|
|
48
|
-
const updated = await updateMailbox({
|
|
49
|
-
uid: mailbox.uid,
|
|
50
|
-
version,
|
|
51
|
-
oofEnabled,
|
|
52
|
-
oofMessage,
|
|
53
|
-
// `null` (not omitted) clears a previously saved window - an omitted field is left as-is.
|
|
54
|
-
oofStartTime: oofStartTime ? new Date(oofStartTime).toISOString() : null,
|
|
55
|
-
oofEndTime: oofEndTime ? new Date(oofEndTime).toISOString() : null,
|
|
56
|
-
});
|
|
57
|
-
setVersion(updated.version);
|
|
58
|
-
setSaved(true);
|
|
59
|
-
} catch (err) {
|
|
60
|
-
notifyApiError(err, "Couldn't save the automatic reply settings");
|
|
61
|
-
} finally {
|
|
62
|
-
setSaving(false);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<div className="flex-1 min-w-0 overflow-y-auto p-6">
|
|
68
|
-
<div className="max-w-xl">
|
|
69
|
-
<h1 className="text-lg font-bold tracking-tight mb-1">Automatic Replies</h1>
|
|
70
|
-
<p className="text-sm text-text-muted mb-4">
|
|
71
|
-
Send an automatic reply to anyone who emails {mailbox.displayName} while you’re away. A
|
|
72
|
-
calendar event with its own automatic reply enabled takes over for its own start/end window.
|
|
73
|
-
</p>
|
|
74
|
-
|
|
75
|
-
{saved && <div className="mb-4 text-sm text-success font-medium">Saved.</div>}
|
|
76
|
-
|
|
77
|
-
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
|
78
|
-
<label className="flex items-center gap-2 text-sm font-medium">
|
|
79
|
-
<input type="checkbox" checked={oofEnabled} onChange={(e) => setOofEnabled(e.target.checked)} />
|
|
80
|
-
Automatic replies are on
|
|
81
|
-
</label>
|
|
82
|
-
|
|
83
|
-
{oofEnabled && (
|
|
84
|
-
<>
|
|
85
|
-
<label className="flex flex-col gap-1.5 text-sm">
|
|
86
|
-
<span className="font-semibold">Message</span>
|
|
87
|
-
<textarea
|
|
88
|
-
aria-label="Automatic reply message"
|
|
89
|
-
className={INPUT_CLASS}
|
|
90
|
-
rows={5}
|
|
91
|
-
value={oofMessage}
|
|
92
|
-
onChange={(e) => setOofMessage(e.target.value)}
|
|
93
|
-
/>
|
|
94
|
-
</label>
|
|
95
|
-
|
|
96
|
-
<div className="grid grid-cols-2 gap-3">
|
|
97
|
-
<label className="flex flex-col gap-1.5 text-sm">
|
|
98
|
-
<span className="font-semibold">Start (optional)</span>
|
|
99
|
-
<input
|
|
100
|
-
type="datetime-local"
|
|
101
|
-
aria-label="Automatic reply start"
|
|
102
|
-
className={INPUT_CLASS}
|
|
103
|
-
value={oofStartTime}
|
|
104
|
-
onChange={(e) => setOofStartTime(e.target.value)}
|
|
105
|
-
/>
|
|
106
|
-
</label>
|
|
107
|
-
<label className="flex flex-col gap-1.5 text-sm">
|
|
108
|
-
<span className="font-semibold">End (optional)</span>
|
|
109
|
-
<input
|
|
110
|
-
type="datetime-local"
|
|
111
|
-
aria-label="Automatic reply end"
|
|
112
|
-
className={INPUT_CLASS}
|
|
113
|
-
value={oofEndTime}
|
|
114
|
-
onChange={(e) => setOofEndTime(e.target.value)}
|
|
115
|
-
/>
|
|
116
|
-
</label>
|
|
117
|
-
</div>
|
|
118
|
-
<p className="text-xs text-text-muted -mt-2">Leave both blank to stay on indefinitely until turned off.</p>
|
|
119
|
-
</>
|
|
120
|
-
)}
|
|
121
|
-
|
|
122
|
-
<div>
|
|
123
|
-
<Button type="submit" loading={saving} disabled={saving} className="!w-auto">
|
|
124
|
-
Save
|
|
125
|
-
</Button>
|
|
126
|
-
</div>
|
|
127
|
-
</form>
|
|
128
|
-
</div>
|
|
129
|
-
</div>
|
|
130
|
-
);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export default routedPage("/settings/auto-reply", SettingsAutoReplyPage);
|
|
1
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
2
|
+
// Copyright (C) 2026 Jean-Philippe Steinmetz
|
|
3
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
4
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
5
|
+
import { routedPage } from "../../_routedPage.js";
|
|
6
|
+
import React, { FormEvent, useState } from "react";
|
|
7
|
+
import { toDatetimeLocal } from "@rapidmx/react-shared/util/dateInput.js";
|
|
8
|
+
import { updateMailbox } from "@rapidmx/react-shared/mail/mailApi.js";
|
|
9
|
+
import SettingsShell, { SettingsShellProps, useSettingsShell } from "../../../shared/components/settings/layout/SettingsShell.js";
|
|
10
|
+
import Button from "@rapidmx/react-shared/components/buttons/Button.js";
|
|
11
|
+
import { notifyApiError } from "../../../shared/notifications/apiErrors.js";
|
|
12
|
+
|
|
13
|
+
const INPUT_CLASS =
|
|
14
|
+
"w-full text-sm py-2 px-3 border border-border rounded-sm bg-surface text-text focus:outline-none focus:border-primary";
|
|
15
|
+
|
|
16
|
+
export type SettingsAutoReplyPageProps = Omit<SettingsShellProps, "active">;
|
|
17
|
+
|
|
18
|
+
function SettingsAutoReplyPage(props: SettingsAutoReplyPageProps) {
|
|
19
|
+
return (
|
|
20
|
+
<SettingsShell {...props} active="auto-reply">
|
|
21
|
+
<AutoReplyContent />
|
|
22
|
+
</SettingsShell>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function AutoReplyContent() {
|
|
27
|
+
const { mailboxUid, mailboxes } = useSettingsShell();
|
|
28
|
+
// `SettingsShell` only ever renders its children once `mailboxes` has loaded and `mailboxUid` has
|
|
29
|
+
// resolved to one of them (a mailbox-less caller sees `MailboxProvisioning` instead) — this lookup
|
|
30
|
+
// can't miss, same established non-null pattern as `apps/www/contacts/index.tsx`'s `mailboxUid!`.
|
|
31
|
+
const mailbox = mailboxes.find((mb) => mb.uid === mailboxUid)!;
|
|
32
|
+
|
|
33
|
+
const [oofEnabled, setOofEnabled] = useState(mailbox.oofEnabled ?? false);
|
|
34
|
+
const [oofMessage, setOofMessage] = useState(mailbox.oofMessage ?? "");
|
|
35
|
+
const [oofStartTime, setOofStartTime] = useState(mailbox.oofStartTime ? toDatetimeLocal(mailbox.oofStartTime) : "");
|
|
36
|
+
const [oofEndTime, setOofEndTime] = useState(mailbox.oofEndTime ? toDatetimeLocal(mailbox.oofEndTime) : "");
|
|
37
|
+
// `SettingsShell`'s `mailboxes` is fetched once - every save bumps the server's version, so a second
|
|
38
|
+
// save without a reload must send the version the previous save returned, not the stale original.
|
|
39
|
+
const [version, setVersion] = useState(mailbox.version);
|
|
40
|
+
const [saving, setSaving] = useState(false);
|
|
41
|
+
const [saved, setSaved] = useState(false);
|
|
42
|
+
|
|
43
|
+
async function handleSubmit(e: FormEvent) {
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
setSaved(false);
|
|
46
|
+
setSaving(true);
|
|
47
|
+
try {
|
|
48
|
+
const updated = await updateMailbox({
|
|
49
|
+
uid: mailbox.uid,
|
|
50
|
+
version,
|
|
51
|
+
oofEnabled,
|
|
52
|
+
oofMessage,
|
|
53
|
+
// `null` (not omitted) clears a previously saved window - an omitted field is left as-is.
|
|
54
|
+
oofStartTime: oofStartTime ? new Date(oofStartTime).toISOString() : null,
|
|
55
|
+
oofEndTime: oofEndTime ? new Date(oofEndTime).toISOString() : null,
|
|
56
|
+
});
|
|
57
|
+
setVersion(updated.version);
|
|
58
|
+
setSaved(true);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
notifyApiError(err, "Couldn't save the automatic reply settings");
|
|
61
|
+
} finally {
|
|
62
|
+
setSaving(false);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div className="flex-1 min-w-0 overflow-y-auto p-6">
|
|
68
|
+
<div className="max-w-xl">
|
|
69
|
+
<h1 className="text-lg font-bold tracking-tight mb-1">Automatic Replies</h1>
|
|
70
|
+
<p className="text-sm text-text-muted mb-4">
|
|
71
|
+
Send an automatic reply to anyone who emails {mailbox.displayName} while you’re away. A
|
|
72
|
+
calendar event with its own automatic reply enabled takes over for its own start/end window.
|
|
73
|
+
</p>
|
|
74
|
+
|
|
75
|
+
{saved && <div className="mb-4 text-sm text-success font-medium">Saved.</div>}
|
|
76
|
+
|
|
77
|
+
<form onSubmit={handleSubmit} className="flex flex-col gap-4">
|
|
78
|
+
<label className="flex items-center gap-2 text-sm font-medium">
|
|
79
|
+
<input type="checkbox" checked={oofEnabled} onChange={(e) => setOofEnabled(e.target.checked)} />
|
|
80
|
+
Automatic replies are on
|
|
81
|
+
</label>
|
|
82
|
+
|
|
83
|
+
{oofEnabled && (
|
|
84
|
+
<>
|
|
85
|
+
<label className="flex flex-col gap-1.5 text-sm">
|
|
86
|
+
<span className="font-semibold">Message</span>
|
|
87
|
+
<textarea
|
|
88
|
+
aria-label="Automatic reply message"
|
|
89
|
+
className={INPUT_CLASS}
|
|
90
|
+
rows={5}
|
|
91
|
+
value={oofMessage}
|
|
92
|
+
onChange={(e) => setOofMessage(e.target.value)}
|
|
93
|
+
/>
|
|
94
|
+
</label>
|
|
95
|
+
|
|
96
|
+
<div className="grid grid-cols-2 gap-3">
|
|
97
|
+
<label className="flex flex-col gap-1.5 text-sm">
|
|
98
|
+
<span className="font-semibold">Start (optional)</span>
|
|
99
|
+
<input
|
|
100
|
+
type="datetime-local"
|
|
101
|
+
aria-label="Automatic reply start"
|
|
102
|
+
className={INPUT_CLASS}
|
|
103
|
+
value={oofStartTime}
|
|
104
|
+
onChange={(e) => setOofStartTime(e.target.value)}
|
|
105
|
+
/>
|
|
106
|
+
</label>
|
|
107
|
+
<label className="flex flex-col gap-1.5 text-sm">
|
|
108
|
+
<span className="font-semibold">End (optional)</span>
|
|
109
|
+
<input
|
|
110
|
+
type="datetime-local"
|
|
111
|
+
aria-label="Automatic reply end"
|
|
112
|
+
className={INPUT_CLASS}
|
|
113
|
+
value={oofEndTime}
|
|
114
|
+
onChange={(e) => setOofEndTime(e.target.value)}
|
|
115
|
+
/>
|
|
116
|
+
</label>
|
|
117
|
+
</div>
|
|
118
|
+
<p className="text-xs text-text-muted -mt-2">Leave both blank to stay on indefinitely until turned off.</p>
|
|
119
|
+
</>
|
|
120
|
+
)}
|
|
121
|
+
|
|
122
|
+
<div>
|
|
123
|
+
<Button type="submit" loading={saving} disabled={saving} className="!w-auto">
|
|
124
|
+
Save
|
|
125
|
+
</Button>
|
|
126
|
+
</div>
|
|
127
|
+
</form>
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default routedPage("/settings/auto-reply", SettingsAutoReplyPage);
|