@arbidocs/blocks 0.4.145 → 0.4.147
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/dist/agents/index.cjs +266 -266
- package/dist/agents/index.js +9 -9
- package/dist/chat/index.cjs +1 -1
- package/dist/chat/index.js +1 -1
- package/dist/{chunk-ULPFRK3J.cjs → chunk-AINU3EJ6.cjs} +8 -8
- package/dist/{chunk-ULPFRK3J.cjs.map → chunk-AINU3EJ6.cjs.map} +1 -1
- package/dist/{chunk-KPO67GBR.cjs → chunk-AO7SK6WP.cjs} +32 -32
- package/dist/{chunk-KPO67GBR.cjs.map → chunk-AO7SK6WP.cjs.map} +1 -1
- package/dist/{chunk-NGDXDHLG.js → chunk-DAHCRVPM.js} +3 -3
- package/dist/{chunk-NGDXDHLG.js.map → chunk-DAHCRVPM.js.map} +1 -1
- package/dist/{chunk-FUTMU4FR.js → chunk-DGV7HQA7.js} +6 -179
- package/dist/chunk-DGV7HQA7.js.map +1 -0
- package/dist/chunk-EV7W64B6.js +134 -0
- package/dist/chunk-EV7W64B6.js.map +1 -0
- package/dist/{chunk-O6IEZDRC.cjs → chunk-GRGS5M6O.cjs} +181 -3
- package/dist/chunk-GRGS5M6O.cjs.map +1 -0
- package/dist/{chunk-J4M37SXY.js → chunk-H74HEPKT.js} +190 -7
- package/dist/chunk-H74HEPKT.js.map +1 -0
- package/dist/{chunk-NSNHRZBH.cjs → chunk-IL3WB3YX.cjs} +3 -3
- package/dist/{chunk-NSNHRZBH.cjs.map → chunk-IL3WB3YX.cjs.map} +1 -1
- package/dist/{chunk-34GDGE77.cjs → chunk-LTU35TQN.cjs} +192 -6
- package/dist/chunk-LTU35TQN.cjs.map +1 -0
- package/dist/{chunk-VVZ34A2P.js → chunk-LZRMXJIE.js} +3 -3
- package/dist/{chunk-VVZ34A2P.js.map → chunk-LZRMXJIE.js.map} +1 -1
- package/dist/{chunk-OPTBQSCV.cjs → chunk-MFY2ZNP6.cjs} +2 -181
- package/dist/{chunk-FUTMU4FR.js.map → chunk-MFY2ZNP6.cjs.map} +1 -1
- package/dist/{chunk-6HCJ3ZEU.js → chunk-R6VCPDPF.js} +178 -6
- package/dist/chunk-R6VCPDPF.js.map +1 -0
- package/dist/chunk-RXK3XP62.cjs +144 -0
- package/dist/chunk-RXK3XP62.cjs.map +1 -0
- package/dist/{chunk-KTSF4HFC.js → chunk-SUUPR735.js} +6 -6
- package/dist/{chunk-KTSF4HFC.js.map → chunk-SUUPR735.js.map} +1 -1
- package/dist/{chunk-WO7QAVTL.cjs → chunk-T5I4NRFP.cjs} +9 -9
- package/dist/{chunk-WO7QAVTL.cjs.map → chunk-T5I4NRFP.cjs.map} +1 -1
- package/dist/chunk-U37AYUPI.cjs +5371 -0
- package/dist/chunk-U37AYUPI.cjs.map +1 -0
- package/dist/{chunk-QOL3M4FJ.js → chunk-VUR63NMQ.js} +8 -8
- package/dist/{chunk-QOL3M4FJ.js.map → chunk-VUR63NMQ.js.map} +1 -1
- package/dist/chunk-WIZ7Z7FN.js +5179 -0
- package/dist/chunk-WIZ7Z7FN.js.map +1 -0
- package/dist/collaboration/index.cjs +81 -81
- package/dist/collaboration/index.js +3 -3
- package/dist/connect/docx.cjs +9 -9
- package/dist/connect/docx.js +6 -6
- package/dist/connect/index.cjs +1395 -132
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +2 -0
- package/dist/connect/index.js +1278 -24
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectedNotificationRelevance.d.ts +4 -1
- package/dist/connection/connectors/ConnectedAppsSettings.d.ts +24 -0
- package/dist/connection/connectors/ConnectedDriveSyncDialog.d.ts +12 -0
- package/dist/connection/connectors/ConnectedMailboxSyncDialog.d.ts +12 -0
- package/dist/connection/connectors/index.d.ts +4 -0
- package/dist/connection/connectors/sync-labels.d.ts +21 -0
- package/dist/connection/settings-page/ConnectedSettingsPage.d.ts +4 -0
- package/dist/connection/settings-page/index.d.ts +1 -1
- package/dist/connection/workspace-settings/ConnectedWorkspaceSettings.d.ts +53 -0
- package/dist/connection/workspace-settings/index.d.ts +2 -0
- package/dist/connection/workspace-settings/useConnectedWorkspaceSettings.d.ts +85 -0
- package/dist/document-tools/index.cjs +1 -1
- package/dist/document-tools/index.js +1 -1
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/index.cjs +3 -3
- package/dist/files/index.js +3 -3
- package/dist/index.cjs +445 -618
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +23 -205
- package/dist/index.js.map +1 -1
- package/dist/settings/PlanBadge.d.ts +1 -1
- package/dist/settings/index.cjs +551 -3716
- package/dist/settings/index.cjs.map +1 -1
- package/dist/settings/index.js +8 -3525
- package/dist/settings/index.js.map +1 -1
- package/dist/shell/index.cjs +1 -1
- package/dist/shell/index.js +1 -1
- package/dist/site/index.cjs +10 -10
- package/dist/site/index.js +2 -2
- package/dist/studio/index.cjs +3 -3
- package/dist/studio/index.js +3 -3
- package/dist/workflow-canvas/index.cjs +22 -22
- package/dist/workflow-canvas/index.js +9 -9
- package/dist/workspaces/CommonWorkspaceToggle.d.ts +15 -0
- package/dist/workspaces/index.cjs +38 -107
- package/dist/workspaces/index.cjs.map +1 -1
- package/dist/workspaces/index.d.ts +1 -0
- package/dist/workspaces/index.js +5 -102
- package/dist/workspaces/index.js.map +1 -1
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +4 -4
- package/dist/chunk-34GDGE77.cjs.map +0 -1
- package/dist/chunk-5YHEHEJT.js +0 -1667
- package/dist/chunk-5YHEHEJT.js.map +0 -1
- package/dist/chunk-6HCJ3ZEU.js.map +0 -1
- package/dist/chunk-J4M37SXY.js.map +0 -1
- package/dist/chunk-O6IEZDRC.cjs.map +0 -1
- package/dist/chunk-OPTBQSCV.cjs.map +0 -1
- package/dist/chunk-U73KPFYH.cjs +0 -1717
- package/dist/chunk-U73KPFYH.cjs.map +0 -1
package/dist/connect/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import { DraggableHeader, SettingsSection, ProfileCard, AvatarPicker, IdentityVerificationCard, IdentityVerificationDialog, RequireVerified, PasswordChangeDialog, SettingsCard, SettingsActionRow, EMAIL_NOTIFICATION_KEYS, EMAIL_NOTIFICATION_CATEGORIES, NotificationCategoryList, toNotificationCategories, toActiveSessionViews, SettingsRow, ActiveSessionsDialog, LogoutDialog, toLogoutSessionViews, SettingsDangerZone, DeleteAccountDialog, toDeleteBlockerViews, SettingsPanel, PremiumModelsFrame, SettingsPage, serverConnectionView, ServerConnectionButton, ModelProviderLabel } from '../chunk-
|
|
2
|
+
import { PageLoading, WorkspacePageFrame, WorkspaceIdentityPanel, WorkspaceProjectSlot, WorkspaceAudienceLine, CommonWorkspaceToggle, ExpandableSection, LeaveFooter } from '../chunk-EV7W64B6.js';
|
|
3
|
+
import { DraggableHeader, SettingsSection, ProfileCard, AvatarPicker, IdentityVerificationCard, IdentityVerificationDialog, RequireVerified, PasswordChangeDialog, SettingsCard, SettingsActionRow, EMAIL_NOTIFICATION_KEYS, EMAIL_NOTIFICATION_CATEGORIES, NotificationCategoryList, toNotificationCategories, toActiveSessionViews, SettingsRow, ActiveSessionsDialog, LogoutDialog, toLogoutSessionViews, SettingsDangerZone, DeleteAccountDialog, toDeleteBlockerViews, SettingsPanel, PremiumModelsFrame, ConnectionsLoading, ConnectionsError, ConnectionsEmpty, SettingsPage, SyncDialogBody, SyncField, SyncSelect, SyncSmallNote, SyncLoading, SyncReconnectNotice, SyncNote, SyncTreeFrame, SyncLinkRow, SyncLinkButton, SyncOptions, SyncOptionToggle, SyncDialogFooter, serverConnectionView, ServerConnectionButton, ModelProviderLabel, SyncFolderRow, SyncFolderStatus, ConnectionCard } from '../chunk-WIZ7Z7FN.js';
|
|
4
4
|
export { ConnectedAssistantDock, redlineStats, textToArtifact, toRedlineMarkdown, useConnectedAiTask, useConnectedChat, useSemanticSearch, useWorkspaceDocs } from '../chunk-CSI2B2H5.js';
|
|
5
|
-
import { useConnectedWorkspaceRole, ConnectedNativeDocxEditor } from '../chunk-
|
|
6
|
-
export { ConnectedWorkflowDocumentsField, ConnectedWorkflowLauncher, ConnectedWorkflowsTable, DEFAULT_CONNECTED_WORKFLOWS_TABLE_LABELS, NativeDocxSupportProvider, toWorkflowFieldDocument, useConnectedAgentOptions, useConnectedWorkflowScopeSource, useConnectedWorkspaceRole, useNativeDocxSupport } from '../chunk-
|
|
5
|
+
import { useConnectedWorkspaceRole, ConnectedNativeDocxEditor } from '../chunk-DAHCRVPM.js';
|
|
6
|
+
export { ConnectedWorkflowDocumentsField, ConnectedWorkflowLauncher, ConnectedWorkflowsTable, DEFAULT_CONNECTED_WORKFLOWS_TABLE_LABELS, NativeDocxSupportProvider, toWorkflowFieldDocument, useConnectedAgentOptions, useConnectedWorkflowScopeSource, useConnectedWorkspaceRole, useNativeDocxSupport } from '../chunk-DAHCRVPM.js';
|
|
7
7
|
export { ConnectedWorkspaceDataProvider, useConnectedConversations, useConnectedDocuments, useConnectedTags } from '../chunk-DN2KI4BU.js';
|
|
8
8
|
import { ConnectionProvider, useConnection, useConnectedWorkspace } from '../chunk-US3S4DCB.js';
|
|
9
9
|
export { ConnectionProvider, SESSION_EXPIRED_MESSAGE, isAuthenticated, useConnectedWorkspace, useConnection } from '../chunk-US3S4DCB.js';
|
|
@@ -11,24 +11,30 @@ import { SignDocumentDialog } from '../chunk-2YOVK524.js';
|
|
|
11
11
|
import '../chunk-MTSKK3BN.js';
|
|
12
12
|
import '../chunk-2FL7QJKJ.js';
|
|
13
13
|
import '../chunk-HFZ45FD3.js';
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
14
|
+
import { FilesFilterBar, FolderFilterButton, FolderPickerRow } from '../chunk-7RJTEWYM.js';
|
|
15
|
+
import '../chunk-RC6VTY2H.js';
|
|
16
|
+
import { WorkspaceActivityList, WorkspaceNotificationMenu, ThreadFollowMenuItem, ThreadFollowButton, TagTable, LoadingIndicator, EntityIdentityBar, IDENTITY_NAME_MAX_LENGTH, tagTableDocx } from '../chunk-H74HEPKT.js';
|
|
17
|
+
import { MemberAvatarStack } from '../chunk-XNOASBGW.js';
|
|
18
|
+
import '../chunk-66TA5IBN.js';
|
|
19
|
+
import { WorkspaceIdentity, workspaceKindColor } from '../chunk-A3XPS2EU.js';
|
|
20
|
+
import '../chunk-NHZK64TQ.js';
|
|
21
|
+
import { PlainMailBodyEditor, buildMailFolderTree, MailFolderTree, draftMailCompose, replyMailCompose, emptyMailCompose, MailGrid, MailMessageView, MailDocumentPicker, parseMailRecipients } from '../chunk-R6VCPDPF.js';
|
|
17
22
|
import '../chunk-SV65E4QW.js';
|
|
18
23
|
import { DOCX_MIME_TYPE } from '../chunk-QXMR5YHC.js';
|
|
19
24
|
import '../chunk-AF6RDAJF.js';
|
|
20
|
-
import { buildLibrarySkills, filterLibrarySkills, SKILL_SOURCE_LABELS, SKILL_TYPE_LABELS, SkillViewToggle, SkillFilterChips, SkillTile, SkillGenerateForm, SkillLibraryDetail, parseSkillFrontmatter, SKILL_MAIN_FILENAME, SkillEditForm, DEFAULT_AGENT_CAPABILITIES, stripPersonaPreamble, AgentCreator, DEFAULT_AGENT_TYPES, DEFAULT_AGENT_TEMPLATES, AgentAvatarField, isValidAgentName, AgentConnectInstructions, TaskRunsDialog, TaskActivityDialog, WorkflowStepBar, composePersona, importSkillFile, importSkillFromUrl, WorkflowRunner, skillSlug, serializeSkill, fromPlanSteps, toPlanSteps, useWorkflowView, workflowToSkillMarkdown } from '../chunk-
|
|
21
|
-
import '../chunk-EVUEIBNU.js';
|
|
25
|
+
import { buildLibrarySkills, filterLibrarySkills, SKILL_SOURCE_LABELS, SKILL_TYPE_LABELS, SkillViewToggle, SkillFilterChips, SkillTile, SkillGenerateForm, SkillLibraryDetail, parseSkillFrontmatter, SKILL_MAIN_FILENAME, SkillEditForm, DEFAULT_AGENT_CAPABILITIES, stripPersonaPreamble, AgentCreator, DEFAULT_AGENT_TYPES, DEFAULT_AGENT_TEMPLATES, AgentAvatarField, isValidAgentName, AgentConnectInstructions, TaskRunsDialog, TaskActivityDialog, WorkflowStepBar, composePersona, importSkillFile, importSkillFromUrl, WorkflowRunner, skillSlug, serializeSkill, fromPlanSteps, toPlanSteps, useWorkflowView, workflowToSkillMarkdown } from '../chunk-SUUPR735.js';
|
|
22
26
|
import { MultiSelect } from '../chunk-CQCC7LE7.js';
|
|
23
|
-
import { PersonPill } from '../chunk-
|
|
27
|
+
import { PersonPill } from '../chunk-LZRMXJIE.js';
|
|
28
|
+
import '../chunk-IXWJGOM2.js';
|
|
24
29
|
import { TriStateFilterMenu } from '../chunk-KSHKTOY2.js';
|
|
25
30
|
import '../chunk-RLWIUUQ5.js';
|
|
26
31
|
import '../chunk-P6GHJSLR.js';
|
|
32
|
+
import '../chunk-EVUEIBNU.js';
|
|
33
|
+
import '../chunk-5LXQPP2K.js';
|
|
34
|
+
import '../chunk-YKQ2DPIP.js';
|
|
27
35
|
import { SelectionBar, SelectionBarAction } from '../chunk-NUNKSZKU.js';
|
|
28
36
|
import { FilterInput } from '../chunk-YU2KUMGE.js';
|
|
29
37
|
import { GridView } from '../chunk-N5YEF3LC.js';
|
|
30
|
-
import '../chunk-IXWJGOM2.js';
|
|
31
|
-
import '../chunk-YKQ2DPIP.js';
|
|
32
38
|
import { StreamedArtifactFrame } from '../chunk-LOJVUGBJ.js';
|
|
33
39
|
import '../chunk-VILAPTCB.js';
|
|
34
40
|
import { upcomingOf, conferenceUrl, isWebinarConference, canJoinEvent, calendarToListItem, buildGridEvents, pendingCreateToGrid, newEventDraft, MiniMonth, CalendarList, CalendarGrid, printCalendar, EventDetails, ScopeDialog, CalendarFormDialog, ProposeTimeDialog, isCalendarAttachment, parseIcsInvite, formatEventWhen, groupSlotsByDay, publicBookingMessage, formatSlotRange, zoneOptions, buildTimeChangeRequest, eventToDraft, needsScope, validateDraft, CALENDAR_DEFAULT_LABELS, buildCreateBody, attendeeKey, buildDeleteTarget, EventEditor, toSettingsValue, CalendarSettingsForm, describeCalendarError, normalizeFeedUrl, parseOverlayLink, isAllDayDraft, draftRangeUtc, freeBusyToRows, SchedulingAssistant, applySuggestion, toSuggestionViews, RoomFinder, bookingLink, defaultRoomWindow, bookingToForm, emptyBookingForm, slugify, WeeklyHoursEditor, validateBookingForm, formToBookingBody, WEEKDAY_NAMES, formatBusy, setupSteps, buildEditRequest } from '../chunk-B3AHCIV5.js';
|
|
@@ -40,8 +46,8 @@ import '../chunk-7XF5SFJ2.js';
|
|
|
40
46
|
import { takeOpenDocumentForTurn, useRegisterOpenDocument } from '../chunk-YBLIKTJK.js';
|
|
41
47
|
import { splitDocRef, stepLevels, stepDocuments, stepKindOf, initialRunInputs, workflowSteps, stepStatesFromActivity, runThreadTitle, stepFields } from '../chunk-PDKM27DF.js';
|
|
42
48
|
import '../chunk-TZGBRLPK.js';
|
|
43
|
-
import '../chunk-AUS3KBHJ.js';
|
|
44
49
|
import '../chunk-AA3PT6KR.js';
|
|
50
|
+
import '../chunk-AUS3KBHJ.js';
|
|
45
51
|
import '../chunk-SLSBJRWW.js';
|
|
46
52
|
import '../chunk-NPLYHR2E.js';
|
|
47
53
|
import '../chunk-7F6CBP3Z.js';
|
|
@@ -52,11 +58,11 @@ import { fmtDate, initials } from '../chunk-OXF2IFXG.js';
|
|
|
52
58
|
import '../chunk-VUNV25KB.js';
|
|
53
59
|
import { lazy, useState, useMemo, useEffect, useCallback, useRef, Suspense, useSyncExternalStore, useLayoutEffect } from 'react';
|
|
54
60
|
import { QueryClient, QueryClientProvider, useQueryClient, useQuery } from '@tanstack/react-query';
|
|
55
|
-
import { ArbiProvider, useConversations, useRunConversation, useWorkspaceActivity, useWorkspaceUsers, isWorkspaceNotificationType, useArbi, useNotifications, useDeleteNotifications, useMarkNotificationsRead, useWorkspaces, useWorkspaceNotificationLevel, useFollowThread, useUploadSkillFiles, useSkills, useSetSkillVisibility, useDeleteSkill, useSkillSource, useAgentModels, useMcpTools, useAgentConfig, useAgentWorkspaces, useCreateAgent, useSaveAgentConfig, useGrantAgentAccess, useRevokeAgentAccess, useGenerateAgentAvatar, useWorkflowRuns, useConversationActivity, useAgents, ArtifactCanvas, useArbiChat, useDocuments, useTagKindSchema, useTags, useSetTagValues, useUpdateTagKindSchema, useInvalidateTagData, useShellWorkspaces, ArbiBotHeadIcon, useProfile, useUpdateProfile, useRequestEmailChange, useConfirmEmailChange, useNameEditor, useAvatarCrop, useEmailChange, ImageCropModal, useIdentityVerification, usePasswordChange, usePasswordChangeForm, useNotificationPreferences, useSessions, useCurrentSessionId, useTerminateSession, useSignOut, useDeleteAccount, useDeleteAccountFlow, useMailClient, defaultMailAlias, useClaimNativeAlias, useMailOnline, useConnectMailAccount, useDisconnectMailAccount, useMailPolicy, useMailAccounts, useUserSettings, useUpdateUserSettings, useAvailableModels, useArbiWebSocket, useWorkNotifications, mailDraftIdFromContent, useMailUnlock, useMailFolders, useMailMessages, useMailDraftCompose, useMailMessage, useMailCache, MailOfflineUnavailableError, accountPath, useCalendarEvents, useCalendars, useFetchCalendarEvent, useCalendarSettings, useCalendarOverlays, useCalendarOutbox, useCalendarAccounts, useSyncAccountsOnOpen, useResumeCalendarAccountConnect, useCreateEvent, useUpdateEvent, useDeleteEvent, useMoveEvent, useRespondToEvent, useCreateCalendar, useUpdateCalendar, useDeleteCalendar, useImportCalendar, useSaveCalendarSettings, useRefreshCalendar, useCalendarEvent, useMailAttachmentText, useCalendarEventByUid, getPublicBookingPage, bookPublicSlot, PublicBookingError, useAgentSession, useStartAgentSession, useCloseAgentSession, isQueuedCalendarWrite, isAliasTakenError, nextAliasSuggestion, aliasTakenMessage, mailJson, ArbiWebSocketProvider, isDeploymentUserNotification, getWorkspaceActionText, getWorkspaceSentPhrase, describeServerNotification, BOX_SEAT_REFUSED, BOX_SEAT_REFUSED_TITLE, documentActivityPhrase, isSignatureNotificationType, inputRequestTitle, WORK_NOTIFICATION_LABELS, useArbiSessionState, documentDisplayName, getWorkspaceKind, formatRelativeTime, useCreateWork, useActOnStep, useConversationThreads, ProviderIcon, formatGbpPerMillionTokens, fileAttachment, useMailProjects, useSaveMailDraft, useSendMail, useMailDraftReplaced, useCalendarInvitations, useDecideCounter, useSearchContacts, usePublishCalendar, useCalendarShares, useShareCalendar, useUnshareCalendar, useSubscribeCalendar, useHolidayCountries, useAddHolidayCalendar, cancelPublicBooking, AiAnswer, signatureNotificationPhrase, signatureRequestMeta, getNotificationTypeMeta, useMailDraftEditor, useFreeBusy, useRooms, useFindTime, useCalendarSupport, useStartCalendarAccountOAuth, useConnectOAuthAccount, useAppPasswords, splitAppPasswords, useBookingPages, useDeleteBookingPage, useSyncCalendarAccount, useUpdateCalendarAccount, useDisconnectCalendarAccount, ACCOUNT_VENDOR, useCalDavProfiles, useConnectCalDavAccount, useCreateAppPassword, useCreateFeed, useSaveBookingPage, useCreateRoom, useRevokeAppPassword } from '@arbidocs/react';
|
|
61
|
+
import { ArbiProvider, useConversations, useRunConversation, useWorkspaceActivity, useWorkspaceUsers, isWorkspaceNotificationType, useArbi, useNotifications, useDeleteNotifications, useMarkNotificationsRead, useWorkspaces, useWorkspaceNotificationLevel, useFollowThread, useUploadSkillFiles, useSkills, useSetSkillVisibility, useDeleteSkill, useSkillSource, useAgentModels, useMcpTools, useAgentConfig, useAgentWorkspaces, useCreateAgent, useSaveAgentConfig, useGrantAgentAccess, useRevokeAgentAccess, useGenerateAgentAvatar, useWorkflowRuns, useConversationActivity, useAgents, ArtifactCanvas, useArbiChat, useDocuments, useTagKindSchema, useTags, useSetTagValues, useUpdateTagKindSchema, useInvalidateTagData, useShellWorkspaces, ArbiBotHeadIcon, useProfile, useUpdateProfile, useRequestEmailChange, useConfirmEmailChange, useNameEditor, useAvatarCrop, useEmailChange, ImageCropModal, useIdentityVerification, usePasswordChange, usePasswordChangeForm, useNotificationPreferences, useSessions, useCurrentSessionId, useTerminateSession, useSignOut, useDeleteAccount, useDeleteAccountFlow, useMailClient, defaultMailAlias, useClaimNativeAlias, useMailOnline, useConnectMailAccount, useDisconnectMailAccount, useMailPolicy, useMailAccounts, useUserSettings, useUpdateUserSettings, useAvailableModels, useConnectorVendorVisibility, useConnectorCatalog, useMyConnectors, useDisconnectConnector, useSlackConnection, useDisconnectSlack, isMailboxSyncVendor, isSharePointVendor, useUpdateWorkspace, useAddWorkspaceMembers, useRemoveWorkspaceMembers, toShellWorkspace, useEnableMailboxSync, useMailboxFolders, useEnableDriveSync, useDriveFolderChildren, connectorErrorStatus, useArbiWebSocket, useWorkNotifications, mailDraftIdFromContent, useMailUnlock, useMailFolders, useMailMessages, useMailDraftCompose, useMailMessage, useMailCache, MailOfflineUnavailableError, accountPath, useCalendarEvents, useCalendars, useFetchCalendarEvent, useCalendarSettings, useCalendarOverlays, useCalendarOutbox, useCalendarAccounts, useSyncAccountsOnOpen, useResumeCalendarAccountConnect, useCreateEvent, useUpdateEvent, useDeleteEvent, useMoveEvent, useRespondToEvent, useCreateCalendar, useUpdateCalendar, useDeleteCalendar, useImportCalendar, useSaveCalendarSettings, useRefreshCalendar, useCalendarEvent, useMailAttachmentText, useCalendarEventByUid, getPublicBookingPage, bookPublicSlot, PublicBookingError, useAgentSession, useStartAgentSession, useCloseAgentSession, isQueuedCalendarWrite, isAliasTakenError, nextAliasSuggestion, aliasTakenMessage, mailJson, connectorReturnTo, ArbiWebSocketProvider, isDeploymentUserNotification, getWorkspaceActionText, getWorkspaceSentPhrase, describeServerNotification, BOX_SEAT_REFUSED, BOX_SEAT_REFUSED_TITLE, documentActivityPhrase, isSignatureNotificationType, inputRequestTitle, WORK_NOTIFICATION_LABELS, useArbiSessionState, documentDisplayName, getWorkspaceKind, formatRelativeTime, useCreateWork, useActOnStep, useConversationThreads, ProviderIcon, formatGbpPerMillionTokens, useDriveFolderDocCount, fileAttachment, useMailProjects, useSaveMailDraft, useSendMail, useMailDraftReplaced, useCalendarInvitations, useDecideCounter, useSearchContacts, usePublishCalendar, useCalendarShares, useShareCalendar, useUnshareCalendar, useSubscribeCalendar, useHolidayCountries, useAddHolidayCalendar, cancelPublicBooking, AiAnswer, signatureNotificationPhrase, signatureRequestMeta, getNotificationTypeMeta, useMailDraftEditor, useFreeBusy, useRooms, useFindTime, useCalendarSupport, useStartCalendarAccountOAuth, useConnectOAuthAccount, useAppPasswords, splitAppPasswords, useBookingPages, useDeleteBookingPage, SHAREPOINT_VENDORS, useSyncCalendarAccount, useUpdateCalendarAccount, useDisconnectCalendarAccount, ACCOUNT_VENDOR, useCalDavProfiles, useConnectCalDavAccount, useCreateAppPassword, useCreateFeed, useSaveBookingPage, useCreateRoom, useRevokeAppPassword } from '@arbidocs/react';
|
|
56
62
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
57
|
-
import { Button, Label, Input, cn, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Switch, DocumentEntity, EntityPill, ShieldIcon, EntityIcon, Tooltip, TooltipTrigger, TooltipContent, Popover, PopoverTrigger, PopoverContent, Tabs, TabsList, TabsTrigger, TabsContent, DialogFooter, UserEntity } from '@arbidocs/react/ui';
|
|
63
|
+
import { Button, Label, Input, cn, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Switch, Badge, getEntityLabel, DocumentEntity, EntityPill, ShieldIcon, EntityIcon, Tooltip, TooltipTrigger, TooltipContent, Popover, PopoverTrigger, PopoverContent, Tabs, TabsList, TabsTrigger, TabsContent, DialogFooter, UserEntity } from '@arbidocs/react/ui';
|
|
58
64
|
import { useNotify } from '@arbidocs/react/shell';
|
|
59
|
-
import { Bell, Activity, Info, UserCheck, Trash2, Loader2, Upload, Link2, Search, Plus, ArrowLeft, ExternalLink, Monitor, UserCircle, KeyRound, Radio, LogOut, Wifi, RotateCcw,
|
|
65
|
+
import { Bell, Activity, Info, UserCheck, Trash2, Loader2, Upload, Link2, Search, Plus, ArrowLeft, ExternalLink, Monitor, UserCircle, KeyRound, Radio, LogOut, Wifi, RotateCcw, Mail, User, HatGlasses, MessageSquare, PlugZap, FolderInput, Settings, Video, Printer, CalendarDays, Clock, MapPin, Globe, X, Paperclip, Send, Inbox, CalendarX, CalendarCheck, CalendarSearch, Pencil, DoorOpen, RefreshCw, CheckCircle2, AlertTriangle, Check, Copy } from 'lucide-react';
|
|
60
66
|
import { useIsOnline, downloadBlob, useOptionalDocumentTools, fetchDocumentPdf, DocumentToolsProvider } from '@arbidocs/react/document-tools';
|
|
61
67
|
import { useStreamedArtifact } from '@arbidocs/react/artifacts';
|
|
62
68
|
import { bytesToBase64 } from '@arbidocs/client';
|
|
@@ -806,11 +812,16 @@ function ConnectedWorkspaceNotificationMenu({
|
|
|
806
812
|
workspaceId: workspaceProp,
|
|
807
813
|
...menuProps
|
|
808
814
|
}) {
|
|
809
|
-
const {
|
|
815
|
+
const { notify } = useBlocksEnvironment();
|
|
816
|
+
const { workspaceId: selected, live } = useConnectedWorkspace();
|
|
810
817
|
const workspaceId = workspaceProp ?? selected;
|
|
811
|
-
const { level, setLevel, isLoading, isSaving } = useWorkspaceNotificationLevel(
|
|
812
|
-
|
|
813
|
-
|
|
818
|
+
const { level, setLevel, isLoading, isSaving, error } = useWorkspaceNotificationLevel(
|
|
819
|
+
workspaceId,
|
|
820
|
+
{ enabled: live }
|
|
821
|
+
);
|
|
822
|
+
useEffect(() => {
|
|
823
|
+
if (error) notify("Could not save the workspace notification setting", "error");
|
|
824
|
+
}, [error, notify]);
|
|
814
825
|
if (!workspaceId) return null;
|
|
815
826
|
return /* @__PURE__ */ jsx(
|
|
816
827
|
WorkspaceNotificationMenu,
|
|
@@ -827,9 +838,9 @@ function ConnectedThreadFollow({
|
|
|
827
838
|
as = "button",
|
|
828
839
|
...props
|
|
829
840
|
}) {
|
|
830
|
-
const {
|
|
841
|
+
const { live } = useConnectedWorkspace();
|
|
831
842
|
const { following, setFollowing, isLoading, isSaving } = useFollowThread(conversationId, {
|
|
832
|
-
enabled:
|
|
843
|
+
enabled: live
|
|
833
844
|
});
|
|
834
845
|
if (!conversationId) return null;
|
|
835
846
|
const Control = as === "menu-item" ? ThreadFollowMenuItem : ThreadFollowButton;
|
|
@@ -3653,11 +3664,269 @@ function ConnectedPremiumModels() {
|
|
|
3653
3664
|
}
|
|
3654
3665
|
) }) }) });
|
|
3655
3666
|
}
|
|
3667
|
+
var FAMILY_PRESENTATION = {
|
|
3668
|
+
microsoft: {
|
|
3669
|
+
name: "Microsoft",
|
|
3670
|
+
description: "One Microsoft connection covers both Outlook (email) and OneDrive (files) \u2014 import documents from either into a workspace.",
|
|
3671
|
+
descriptionWithSharePoint: "One Microsoft connection covers Outlook (email), OneDrive and SharePoint (files) \u2014 import documents from any of them into a workspace."
|
|
3672
|
+
},
|
|
3673
|
+
gmail: {
|
|
3674
|
+
name: "Google",
|
|
3675
|
+
description: "One Google connection covers both Gmail (email) and Google Drive (files) \u2014 import documents from either into a workspace."
|
|
3676
|
+
}
|
|
3677
|
+
};
|
|
3678
|
+
var EMAIL_AND_DRIVE_SUBTITLE = [
|
|
3679
|
+
"Connect Microsoft or Google once \u2014 a single connection lets you import documents",
|
|
3680
|
+
"from both their email (Outlook / Gmail) and their cloud storage (OneDrive / Google Drive)",
|
|
3681
|
+
"into a workspace."
|
|
3682
|
+
].join(" ");
|
|
3683
|
+
function toConnectionCardView(catalog, userConnector, options) {
|
|
3684
|
+
const isConnected = !!userConnector;
|
|
3685
|
+
const presentation = FAMILY_PRESENTATION[catalog.vendor_key];
|
|
3686
|
+
const description = (options.sharePointVisible ? presentation?.descriptionWithSharePoint : void 0) ?? presentation?.description ?? catalog.description;
|
|
3687
|
+
return {
|
|
3688
|
+
id: catalog.vendor_key,
|
|
3689
|
+
title: presentation?.name ?? catalog.display_name,
|
|
3690
|
+
description: description ?? void 0,
|
|
3691
|
+
iconUrl: catalog.icon_url,
|
|
3692
|
+
iconAlt: catalog.display_name,
|
|
3693
|
+
status: isConnected ? "connected" : catalog.requires_per_user_auth ? "available" : "organisation",
|
|
3694
|
+
justConnected: options.justConnected,
|
|
3695
|
+
identity: userConnector?.vendor_user_identity,
|
|
3696
|
+
warning: isConnected && userConnector?.token_scheme === "env" ? "Reconnect to upgrade security \u2014 your access token isn't yet bound to your session." : void 0,
|
|
3697
|
+
note: !catalog.requires_per_user_auth && !isConnected ? "Enabled for your organisation \u2014 no personal login required" : void 0,
|
|
3698
|
+
// Mailbox connectors show a read-only notice when native mail writes are disabled; sync is
|
|
3699
|
+
// configured per-workspace from the Add-files flow, not on this tab.
|
|
3700
|
+
showReadOnlyNotice: isMailboxSyncVendor(catalog.vendor_key) && !options.mailWriteEnabled,
|
|
3701
|
+
isDisconnecting: options.isDisconnecting
|
|
3702
|
+
};
|
|
3703
|
+
}
|
|
3704
|
+
function ConnectedAppsSettings({
|
|
3705
|
+
justConnectedVendor = null,
|
|
3706
|
+
onJustConnectedSeen
|
|
3707
|
+
}) {
|
|
3708
|
+
const arbi = useArbi();
|
|
3709
|
+
const { notify, navigate } = useBlocksEnvironment();
|
|
3710
|
+
const { data: mailPolicy } = useMailPolicy();
|
|
3711
|
+
const isVendorVisible = useConnectorVendorVisibility();
|
|
3712
|
+
useEffect(() => {
|
|
3713
|
+
if (!justConnectedVendor || !onJustConnectedSeen) return;
|
|
3714
|
+
const timer = setTimeout(onJustConnectedSeen, 4e3);
|
|
3715
|
+
return () => clearTimeout(timer);
|
|
3716
|
+
}, [justConnectedVendor, onJustConnectedSeen]);
|
|
3717
|
+
useEffect(() => {
|
|
3718
|
+
if (!justConnectedVendor) return;
|
|
3719
|
+
void arbi.connectors.bridgeTokens({ vendor: justConnectedVendor });
|
|
3720
|
+
}, [justConnectedVendor, arbi]);
|
|
3721
|
+
const {
|
|
3722
|
+
data: catalog = [],
|
|
3723
|
+
isLoading: catalogLoading,
|
|
3724
|
+
error: catalogError
|
|
3725
|
+
} = useConnectorCatalog();
|
|
3726
|
+
const { data: myConnectors = [], isLoading: myLoading } = useMyConnectors();
|
|
3727
|
+
const disconnect = useDisconnectConnector();
|
|
3728
|
+
const {
|
|
3729
|
+
data: slackConnection,
|
|
3730
|
+
isLoading: slackLoading,
|
|
3731
|
+
isPending: slackStatusPendingQuery,
|
|
3732
|
+
isFetching: slackStatusFetching,
|
|
3733
|
+
isError: slackStatusError,
|
|
3734
|
+
refetch: refetchSlackConnection
|
|
3735
|
+
} = useSlackConnection();
|
|
3736
|
+
const slackStatusPending = slackStatusPendingQuery || slackStatusFetching || justConnectedVendor === "slack" && !slackConnection?.connected && !slackStatusError;
|
|
3737
|
+
const disconnectSlack = useDisconnectSlack();
|
|
3738
|
+
const { data: agents = [] } = useAgents();
|
|
3739
|
+
const [slackAgentId, setSlackAgentId] = useState("");
|
|
3740
|
+
const { data: slackAgentWorkspaces = [], isLoading: slackAgentWorkspacesLoading } = useAgentWorkspaces(slackAgentId, { enabled: Boolean(slackAgentId) });
|
|
3741
|
+
const [slackAuthorizing, setSlackAuthorizing] = useState(false);
|
|
3742
|
+
const [slackAgentEditorOpen, setSlackAgentEditorOpen] = useState(false);
|
|
3743
|
+
const isLoading = catalogLoading || myLoading;
|
|
3744
|
+
const connectedByVendor = Object.fromEntries(myConnectors.map((uc) => [uc.vendor_key, uc]));
|
|
3745
|
+
const handleConnect = async (vendorKey) => {
|
|
3746
|
+
navigate(await arbi.connectors.authorize(vendorKey));
|
|
3747
|
+
};
|
|
3748
|
+
const handleSlackConnect = async () => {
|
|
3749
|
+
if (!slackAgentId) return;
|
|
3750
|
+
setSlackAuthorizing(true);
|
|
3751
|
+
try {
|
|
3752
|
+
navigate(await arbi.connectors.slack.authorize(slackAgentId));
|
|
3753
|
+
} catch (error) {
|
|
3754
|
+
notify(
|
|
3755
|
+
error instanceof Error ? error.message : "Could not start Slack authorization",
|
|
3756
|
+
"error"
|
|
3757
|
+
);
|
|
3758
|
+
setSlackAuthorizing(false);
|
|
3759
|
+
}
|
|
3760
|
+
};
|
|
3761
|
+
const handleDisconnect = (vendorKey) => {
|
|
3762
|
+
disconnect.mutate({ vendorKey });
|
|
3763
|
+
if (vendorKey === "microsoft") {
|
|
3764
|
+
for (const spVendor of SHAREPOINT_VENDORS) {
|
|
3765
|
+
if (connectedByVendor[spVendor]) {
|
|
3766
|
+
disconnect.mutate({ vendorKey: spVendor });
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
};
|
|
3771
|
+
if (isLoading) {
|
|
3772
|
+
return /* @__PURE__ */ jsx(ConnectionsLoading, { message: "Loading connected apps\u2026" });
|
|
3773
|
+
}
|
|
3774
|
+
if (catalogError) {
|
|
3775
|
+
return /* @__PURE__ */ jsx(ConnectionsError, { message: "Failed to load connector catalog. Please refresh and try again." });
|
|
3776
|
+
}
|
|
3777
|
+
const visibleCatalog = catalog.filter((c) => isVendorVisible(c.vendor_key));
|
|
3778
|
+
const sharePointVisible = isVendorVisible("microsoft_sharepoint");
|
|
3779
|
+
const emailCatalog = visibleCatalog.filter((c) => isMailboxSyncVendor(c.vendor_key));
|
|
3780
|
+
const mcpCatalog = visibleCatalog.filter(
|
|
3781
|
+
(c) => !isMailboxSyncVendor(c.vendor_key) && !isSharePointVendor(c.vendor_key)
|
|
3782
|
+
);
|
|
3783
|
+
const renderCard = (entry) => /* @__PURE__ */ jsx(
|
|
3784
|
+
ConnectionCard,
|
|
3785
|
+
{
|
|
3786
|
+
connection: toConnectionCardView(entry, connectedByVendor[entry.vendor_key], {
|
|
3787
|
+
isDisconnecting: disconnect.isPending && disconnect.variables?.vendorKey === entry.vendor_key,
|
|
3788
|
+
sharePointVisible,
|
|
3789
|
+
mailWriteEnabled: mailPolicy?.enabled_providers.includes(entry.vendor_key) ?? false,
|
|
3790
|
+
// A `?connected=microsoft_sharepoint` return has no card of its own — alias
|
|
3791
|
+
// it to the Microsoft family card so its "Just connected" badge still lights.
|
|
3792
|
+
justConnected: justConnectedVendor === entry.vendor_key || entry.vendor_key === "microsoft" && isSharePointVendor(justConnectedVendor ?? "")
|
|
3793
|
+
}),
|
|
3794
|
+
onConnect: handleConnect,
|
|
3795
|
+
onDisconnect: handleDisconnect
|
|
3796
|
+
},
|
|
3797
|
+
entry.vendor_key
|
|
3798
|
+
);
|
|
3799
|
+
const renderGroup = (title, subtitle, icon2, entries) => {
|
|
3800
|
+
if (entries.length === 0) return null;
|
|
3801
|
+
return /* @__PURE__ */ jsx(SettingsSection, { icon: icon2, title, children: /* @__PURE__ */ jsxs(SettingsCard, { className: "space-y-3", children: [
|
|
3802
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: subtitle }),
|
|
3803
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: entries.map(renderCard) })
|
|
3804
|
+
] }) });
|
|
3805
|
+
};
|
|
3806
|
+
return /* @__PURE__ */ jsxs(SettingsPanel, { className: "max-w-2xl", children: [
|
|
3807
|
+
/* @__PURE__ */ jsxs("section", { className: "rounded-xl border border-border bg-card px-5 py-4", children: [
|
|
3808
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
|
|
3809
|
+
/* @__PURE__ */ jsx("div", { className: "mt-0.5 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border border-border bg-background text-muted-foreground", children: /* @__PURE__ */ jsx(Mail, { className: "h-5 w-5" }) }),
|
|
3810
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
3811
|
+
/* @__PURE__ */ jsx("div", { className: "font-heading text-sm font-semibold text-foreground", children: "Slack" }),
|
|
3812
|
+
/* @__PURE__ */ jsx("p", { className: "mt-0.5 text-sm text-muted-foreground", children: "Connect Slack to an existing ARBI agent. The agent uses its configured default workspace." }),
|
|
3813
|
+
slackConnection?.connected && /* @__PURE__ */ jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [
|
|
3814
|
+
"Connected to ",
|
|
3815
|
+
slackConnection.agent_name
|
|
3816
|
+
] })
|
|
3817
|
+
] }),
|
|
3818
|
+
slackConnection?.connected ? /* @__PURE__ */ jsxs(
|
|
3819
|
+
Button,
|
|
3820
|
+
{
|
|
3821
|
+
variant: "outline",
|
|
3822
|
+
size: "sm",
|
|
3823
|
+
onClick: () => disconnectSlack.mutate(),
|
|
3824
|
+
disabled: disconnectSlack.isPending,
|
|
3825
|
+
className: "text-destructive hover:bg-destructive/10 hover:text-destructive",
|
|
3826
|
+
children: [
|
|
3827
|
+
disconnectSlack.isPending ? /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-3.5 w-3.5 animate-spin" }) : null,
|
|
3828
|
+
"Disconnect"
|
|
3829
|
+
]
|
|
3830
|
+
}
|
|
3831
|
+
) : slackStatusPending ? /* @__PURE__ */ jsxs(Badge, { variant: "outline", className: "gap-1.5 text-muted-foreground", children: [
|
|
3832
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 animate-spin" }),
|
|
3833
|
+
"Pending"
|
|
3834
|
+
] }) : slackStatusError ? /* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: () => void refetchSlackConnection(), children: "Retry status check" }) : slackConnection?.configured ? /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-muted-foreground", children: "Not connected" }) : /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-muted-foreground", children: "Unavailable" })
|
|
3835
|
+
] }),
|
|
3836
|
+
!slackConnection?.connected && !slackStatusPending && /* @__PURE__ */ jsxs(
|
|
3837
|
+
"div",
|
|
3838
|
+
{
|
|
3839
|
+
className: "mt-4 flex flex-wrap items-end gap-3 border-t border-border/60 pt-4",
|
|
3840
|
+
"data-testid": "slack-agent-setup",
|
|
3841
|
+
children: [
|
|
3842
|
+
/* @__PURE__ */ jsxs("label", { className: "min-w-56 flex-1 space-y-1.5", children: [
|
|
3843
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "ARBI agent" }),
|
|
3844
|
+
/* @__PURE__ */ jsxs(
|
|
3845
|
+
"select",
|
|
3846
|
+
{
|
|
3847
|
+
className: "h-10 w-full rounded-md border border-input bg-background px-3 text-sm pointer-coarse:h-11",
|
|
3848
|
+
value: slackAgentId,
|
|
3849
|
+
onChange: (event) => setSlackAgentId(event.target.value),
|
|
3850
|
+
children: [
|
|
3851
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Choose an agent" }),
|
|
3852
|
+
agents.map((agent) => /* @__PURE__ */ jsx("option", { value: agent.external_id, children: agent.given_name || agent.email }, agent.external_id))
|
|
3853
|
+
]
|
|
3854
|
+
}
|
|
3855
|
+
)
|
|
3856
|
+
] }),
|
|
3857
|
+
/* @__PURE__ */ jsx(
|
|
3858
|
+
Button,
|
|
3859
|
+
{
|
|
3860
|
+
variant: "outline",
|
|
3861
|
+
size: "sm",
|
|
3862
|
+
onClick: () => setSlackAgentEditorOpen(true),
|
|
3863
|
+
disabled: slackLoading || slackAuthorizing,
|
|
3864
|
+
children: "Create Slack agent"
|
|
3865
|
+
}
|
|
3866
|
+
),
|
|
3867
|
+
/* @__PURE__ */ jsxs(
|
|
3868
|
+
Button,
|
|
3869
|
+
{
|
|
3870
|
+
size: "sm",
|
|
3871
|
+
onClick: () => void handleSlackConnect(),
|
|
3872
|
+
disabled: !slackConnection?.configured || !slackAgentId || slackLoading || slackAuthorizing,
|
|
3873
|
+
children: [
|
|
3874
|
+
slackAuthorizing ? /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx(ExternalLink, { className: "mr-1.5 h-3.5 w-3.5" }),
|
|
3875
|
+
slackAuthorizing ? "Starting Slack authorization\u2026" : "Connect to Slack"
|
|
3876
|
+
]
|
|
3877
|
+
}
|
|
3878
|
+
),
|
|
3879
|
+
slackAgentId && /* @__PURE__ */ jsxs(
|
|
3880
|
+
"div",
|
|
3881
|
+
{
|
|
3882
|
+
className: "w-full rounded-md bg-muted/40 px-3 py-2 text-xs",
|
|
3883
|
+
"data-testid": "slack-agent-workspaces",
|
|
3884
|
+
children: [
|
|
3885
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-foreground", children: "Agent workspace access" }),
|
|
3886
|
+
slackAgentWorkspacesLoading ? /* @__PURE__ */ jsx("p", { className: "mt-1 text-muted-foreground", children: "Loading access\u2026" }) : slackAgentWorkspaces.length ? /* @__PURE__ */ jsx("ul", { className: "mt-1 space-y-1", children: slackAgentWorkspaces.map((workspace) => /* @__PURE__ */ jsxs("li", { className: "flex flex-wrap gap-x-2", children: [
|
|
3887
|
+
/* @__PURE__ */ jsx("span", { children: workspace.name }),
|
|
3888
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: workspace.role }),
|
|
3889
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: workspace.permanent ? "Standing access" : "Temporary access" }),
|
|
3890
|
+
workspace.is_default && /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Slack default" })
|
|
3891
|
+
] }, workspace.workspace_ext_id)) }) : /* @__PURE__ */ jsx("p", { className: "mt-1 text-muted-foreground", children: "No workspace access. Share a workspace with this agent in that workspace\u2019s Members settings." })
|
|
3892
|
+
]
|
|
3893
|
+
}
|
|
3894
|
+
),
|
|
3895
|
+
slackStatusError ? /* @__PURE__ */ jsx("p", { className: "w-full text-xs text-muted-foreground", children: "ARBI could not check Slack availability. Retry the status check above before connecting." }) : !slackConnection?.configured ? /* @__PURE__ */ jsx("p", { className: "w-full text-xs text-muted-foreground", children: "Slack is unavailable because this ARBI deployment has not configured its Slack app credentials. You can still create an agent and set its workspace access; an administrator must configure Slack before connecting." }) : /* @__PURE__ */ jsx("p", { className: "w-full text-xs text-muted-foreground", children: "Slack DMs wake this agent and receive replies there. It uses the marked default workspace; standing access is required." })
|
|
3896
|
+
]
|
|
3897
|
+
}
|
|
3898
|
+
),
|
|
3899
|
+
/* @__PURE__ */ jsx(
|
|
3900
|
+
ConnectedAgentCreator,
|
|
3901
|
+
{
|
|
3902
|
+
open: slackAgentEditorOpen,
|
|
3903
|
+
onOpenChange: setSlackAgentEditorOpen,
|
|
3904
|
+
initialName: "SlackAssistant",
|
|
3905
|
+
onSaved: (agentExtId) => {
|
|
3906
|
+
setSlackAgentId(agentExtId);
|
|
3907
|
+
setSlackAgentEditorOpen(false);
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
)
|
|
3911
|
+
] }),
|
|
3912
|
+
catalog.length === 0 ? /* @__PURE__ */ jsx(SettingsCard, { children: /* @__PURE__ */ jsx(ConnectionsEmpty, { message: "No connectors available yet." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3913
|
+
renderGroup("Email & Drive", EMAIL_AND_DRIVE_SUBTITLE, /* @__PURE__ */ jsx(Mail, {}), emailCatalog),
|
|
3914
|
+
renderGroup(
|
|
3915
|
+
"Apps & Integrations (MCP)",
|
|
3916
|
+
"Connect your legal tools so the ARBI agent can search them live during a conversation.",
|
|
3917
|
+
/* @__PURE__ */ jsx(PlugZap, {}),
|
|
3918
|
+
mcpCatalog
|
|
3919
|
+
)
|
|
3920
|
+
] }),
|
|
3921
|
+
/* @__PURE__ */ jsx("p", { className: "px-1 text-xs text-muted-foreground", children: "ARBI requests only the minimum permissions needed. Your credentials are encrypted and never shared. You can disconnect at any time." })
|
|
3922
|
+
] });
|
|
3923
|
+
}
|
|
3656
3924
|
var SETTINGS_SECTION_IDS = {
|
|
3657
3925
|
account: "account",
|
|
3658
3926
|
mail: "mail",
|
|
3659
3927
|
privacy: "privacy",
|
|
3660
|
-
chat: "chat"
|
|
3928
|
+
chat: "chat",
|
|
3929
|
+
connectedApps: "connected-apps"
|
|
3661
3930
|
};
|
|
3662
3931
|
function accountSettingsSection(props) {
|
|
3663
3932
|
return {
|
|
@@ -3691,6 +3960,14 @@ function chatSettingsSection() {
|
|
|
3691
3960
|
render: () => /* @__PURE__ */ jsx(ConnectedPremiumModels, {})
|
|
3692
3961
|
};
|
|
3693
3962
|
}
|
|
3963
|
+
function connectedAppsSettingsSection(props) {
|
|
3964
|
+
return {
|
|
3965
|
+
id: SETTINGS_SECTION_IDS.connectedApps,
|
|
3966
|
+
label: "Connected Apps",
|
|
3967
|
+
icon: /* @__PURE__ */ jsx(PlugZap, { className: "w-6 h-6" }),
|
|
3968
|
+
render: () => /* @__PURE__ */ jsx(ConnectedAppsSettings, { ...props })
|
|
3969
|
+
};
|
|
3970
|
+
}
|
|
3694
3971
|
var DEFAULT_SETTINGS_SECTIONS = [
|
|
3695
3972
|
accountSettingsSection(),
|
|
3696
3973
|
privacySettingsSection(),
|
|
@@ -3721,6 +3998,983 @@ function ConnectedSettingsPage({
|
|
|
3721
3998
|
}
|
|
3722
3999
|
);
|
|
3723
4000
|
}
|
|
4001
|
+
function errorDetail(err) {
|
|
4002
|
+
const e = err;
|
|
4003
|
+
const detail = e?.detail ?? e?.apiError?.detail ?? e?.response?.data?.detail ?? e?.error?.detail;
|
|
4004
|
+
if (typeof detail === "string" && detail) return detail;
|
|
4005
|
+
const message = detail?.message;
|
|
4006
|
+
return typeof message === "string" && message ? message : void 0;
|
|
4007
|
+
}
|
|
4008
|
+
function errorStatus(err) {
|
|
4009
|
+
const e = err;
|
|
4010
|
+
return e?.status ?? e?.response?.status;
|
|
4011
|
+
}
|
|
4012
|
+
var workspaceWord = () => getEntityLabel("WORKSPACE").toLowerCase();
|
|
4013
|
+
var inviteMessage = (emails) => `${emails.length === 1 ? `${emails[0]} isn't on the platform yet.` : `These users aren't on the platform yet:
|
|
4014
|
+
${emails.join("\n")}`}
|
|
4015
|
+
|
|
4016
|
+
Invite them by email? Once they sign up, they'll usually get access to this ${workspaceWord()} automatically \u2014 if not, they can request it themselves.`;
|
|
4017
|
+
function useConnectedWorkspaceSettings(workspaceId, { onLeft } = {}) {
|
|
4018
|
+
const { notify, confirm } = useBlocksEnvironment();
|
|
4019
|
+
const { workspaceId: openWorkspaceId, userId } = useConnectedWorkspace();
|
|
4020
|
+
const { data: workspaces } = useWorkspaces();
|
|
4021
|
+
const workspace = workspaces?.find((w) => w.external_id === workspaceId);
|
|
4022
|
+
const update = useUpdateWorkspace();
|
|
4023
|
+
const add = useAddWorkspaceMembers();
|
|
4024
|
+
const remove = useRemoveWorkspaceMembers();
|
|
4025
|
+
const members = workspace?.users ?? [];
|
|
4026
|
+
const role = members.find((m) => m.user.external_id === userId)?.role ?? null;
|
|
4027
|
+
const isOwner = role === "owner";
|
|
4028
|
+
const isMember = role !== null;
|
|
4029
|
+
const stillOpen = () => {
|
|
4030
|
+
if (!workspace) return false;
|
|
4031
|
+
if (openWorkspaceId === workspace.external_id) return true;
|
|
4032
|
+
notify(
|
|
4033
|
+
`Not saved: you switched to another ${workspaceWord()} first. Open "${workspace.name}" and try again.`,
|
|
4034
|
+
"warning"
|
|
4035
|
+
);
|
|
4036
|
+
return false;
|
|
4037
|
+
};
|
|
4038
|
+
const updateIdentity = async (data) => {
|
|
4039
|
+
if (!workspace || !stillOpen()) return;
|
|
4040
|
+
const changed = [
|
|
4041
|
+
...data.name !== workspace.name ? ["name"] : [],
|
|
4042
|
+
...data.description !== (workspace.description || "") ? ["description"] : []
|
|
4043
|
+
];
|
|
4044
|
+
try {
|
|
4045
|
+
await update.mutateAsync({ name: data.name, description: data.description });
|
|
4046
|
+
if (changed.length > 0) {
|
|
4047
|
+
notify(`${getEntityLabel("WORKSPACE")} ${changed.join(", ")} updated`, "success");
|
|
4048
|
+
}
|
|
4049
|
+
} catch (err) {
|
|
4050
|
+
notify(err instanceof Error ? err.message : "Failed to update workspace", "error");
|
|
4051
|
+
throw err;
|
|
4052
|
+
}
|
|
4053
|
+
};
|
|
4054
|
+
const setPublic = async (isPublic) => {
|
|
4055
|
+
if (!workspace || !stillOpen()) return;
|
|
4056
|
+
await update.mutateAsync({ is_public: isPublic });
|
|
4057
|
+
notify(`Workspace is now ${isPublic ? "common" : "members-only"}`, "success");
|
|
4058
|
+
};
|
|
4059
|
+
const invite = async (emails, memberRole) => {
|
|
4060
|
+
try {
|
|
4061
|
+
await add.mutateAsync({ emails, role: memberRole, confirmInvite: true });
|
|
4062
|
+
notify(
|
|
4063
|
+
emails.length === 1 ? `Invitation sent to ${emails[0]}` : `Invitations sent to ${emails.length} users`,
|
|
4064
|
+
"success"
|
|
4065
|
+
);
|
|
4066
|
+
} catch (err) {
|
|
4067
|
+
const detail = errorDetail(err);
|
|
4068
|
+
notify(
|
|
4069
|
+
detail ? `Couldn't send the invitation: ${detail}` : "Failed to send the invitation.",
|
|
4070
|
+
"error"
|
|
4071
|
+
);
|
|
4072
|
+
}
|
|
4073
|
+
};
|
|
4074
|
+
const share = async (emails, memberRole = "collaborator") => {
|
|
4075
|
+
if (!workspace) return "error";
|
|
4076
|
+
const current = new Set(members.map((m) => m.user.email.toLowerCase()));
|
|
4077
|
+
try {
|
|
4078
|
+
const added = new Set(
|
|
4079
|
+
(await add.mutateAsync({ emails, role: memberRole }) ?? []).map(
|
|
4080
|
+
(m) => m.user.email.toLowerCase()
|
|
4081
|
+
)
|
|
4082
|
+
);
|
|
4083
|
+
const failed = emails.filter((email) => !added.has(email.toLowerCase()));
|
|
4084
|
+
if (failed.length === 0) return "added";
|
|
4085
|
+
const already = failed.filter((email) => current.has(email.toLowerCase()));
|
|
4086
|
+
const unknown = failed.filter((email) => !current.has(email.toLowerCase()));
|
|
4087
|
+
if (added.size > 0) {
|
|
4088
|
+
notify(`Added ${added.size} ${added.size === 1 ? "member" : "members"}`, "success");
|
|
4089
|
+
}
|
|
4090
|
+
if (already.length > 0) {
|
|
4091
|
+
notify(
|
|
4092
|
+
already.length === 1 ? `${already[0]} is already a member` : `${already.length} users are already members`,
|
|
4093
|
+
"info"
|
|
4094
|
+
);
|
|
4095
|
+
}
|
|
4096
|
+
if (unknown.length > 0 && await confirm({
|
|
4097
|
+
message: inviteMessage(unknown),
|
|
4098
|
+
title: "Invite by email?",
|
|
4099
|
+
kind: "yesno"
|
|
4100
|
+
})) {
|
|
4101
|
+
await invite(unknown, memberRole);
|
|
4102
|
+
return added.size > 0 ? "partial" : "invited";
|
|
4103
|
+
}
|
|
4104
|
+
return added.size > 0 ? "partial" : "already_member";
|
|
4105
|
+
} catch (err) {
|
|
4106
|
+
const status = errorStatus(err);
|
|
4107
|
+
const detail = errorDetail(err) || "Failed to add member to workspace";
|
|
4108
|
+
const lower = detail.toLowerCase();
|
|
4109
|
+
if (lower.includes("already has access")) return "already_member";
|
|
4110
|
+
const notRegistered = status === 404 || lower.includes("not found") || lower.includes("no user") || lower.includes("does not exist") || lower.includes("user not registered");
|
|
4111
|
+
if (notRegistered) {
|
|
4112
|
+
if (await confirm({
|
|
4113
|
+
message: inviteMessage(emails),
|
|
4114
|
+
title: "Invite by email?",
|
|
4115
|
+
kind: "yesno"
|
|
4116
|
+
})) {
|
|
4117
|
+
await invite(emails, memberRole);
|
|
4118
|
+
return "invited";
|
|
4119
|
+
}
|
|
4120
|
+
return "cancelled";
|
|
4121
|
+
}
|
|
4122
|
+
const quota = status === 402 || lower.includes("limit reached") || lower.includes("quota") || lower.includes("upgrade");
|
|
4123
|
+
if (!quota) notify(detail, "error");
|
|
4124
|
+
return "error";
|
|
4125
|
+
}
|
|
4126
|
+
};
|
|
4127
|
+
const removeMember = async (userExtId, email, name) => {
|
|
4128
|
+
if (!workspace || !isOwner) return;
|
|
4129
|
+
const ok = await confirm({
|
|
4130
|
+
message: `Remove ${name} (${email}) from the "${workspace.name}" ${getEntityLabel("WORKSPACE")}?
|
|
4131
|
+
|
|
4132
|
+
Note that ${getEntityLabel("WORKSPACEUSER", "PLURAL").toLowerCase()} may have saved private content in the workspace that you cannot see. If you remove them from the ${workspaceWord()} they will immediately lose access to any content in the ${workspaceWord()}.`,
|
|
4133
|
+
title: `Remove ${getEntityLabel("WORKSPACEUSER")}`
|
|
4134
|
+
});
|
|
4135
|
+
if (!ok) return;
|
|
4136
|
+
try {
|
|
4137
|
+
await remove.mutateAsync([userExtId]);
|
|
4138
|
+
notify(`Successfully removed ${name} from workspace`, "success");
|
|
4139
|
+
} catch {
|
|
4140
|
+
notify(`Failed to remove ${name} from workspace`, "error");
|
|
4141
|
+
}
|
|
4142
|
+
};
|
|
4143
|
+
const leave = async () => {
|
|
4144
|
+
if (!workspace || !userId || isOwner) return;
|
|
4145
|
+
const name = workspace.name;
|
|
4146
|
+
const ok = await confirm({
|
|
4147
|
+
message: `Are you sure you want to leave the "${name}" ${getEntityLabel("WORKSPACE")}?
|
|
4148
|
+
|
|
4149
|
+
You will lose access to all content in this ${workspaceWord()}.`,
|
|
4150
|
+
title: "Leave Workspace"
|
|
4151
|
+
});
|
|
4152
|
+
if (!ok) return;
|
|
4153
|
+
try {
|
|
4154
|
+
await remove.mutateAsync([userId]);
|
|
4155
|
+
onLeft?.();
|
|
4156
|
+
notify(`Successfully left ${name}`, "success");
|
|
4157
|
+
} catch {
|
|
4158
|
+
notify("Failed to leave workspace", "error");
|
|
4159
|
+
}
|
|
4160
|
+
};
|
|
4161
|
+
return {
|
|
4162
|
+
workspace,
|
|
4163
|
+
members,
|
|
4164
|
+
role,
|
|
4165
|
+
isOwner,
|
|
4166
|
+
isMember,
|
|
4167
|
+
updateIdentity,
|
|
4168
|
+
setPublic,
|
|
4169
|
+
share,
|
|
4170
|
+
removeMember,
|
|
4171
|
+
leave,
|
|
4172
|
+
isSharing: add.isPending,
|
|
4173
|
+
isRemoving: remove.isPending
|
|
4174
|
+
};
|
|
4175
|
+
}
|
|
4176
|
+
var isAgentMember = (member) => member.user.external_id.startsWith("agt-");
|
|
4177
|
+
var memberName = (member) => member.user.family_name ? `${member.user.given_name} ${member.user.family_name}` : member.user.given_name;
|
|
4178
|
+
function ConnectedWorkspaceSettings({
|
|
4179
|
+
workspaceId,
|
|
4180
|
+
project,
|
|
4181
|
+
projectLine,
|
|
4182
|
+
membersTable,
|
|
4183
|
+
shareDialog,
|
|
4184
|
+
children,
|
|
4185
|
+
onExport,
|
|
4186
|
+
onOpenActivity,
|
|
4187
|
+
onLeft,
|
|
4188
|
+
testId = "workspace-settings-page"
|
|
4189
|
+
}) {
|
|
4190
|
+
const settings = useConnectedWorkspaceSettings(workspaceId, { onLeft });
|
|
4191
|
+
const { workspace, members, isOwner, isMember } = settings;
|
|
4192
|
+
const { data: userSettings } = useUserSettings();
|
|
4193
|
+
const isDeveloper = userSettings?.developer === true;
|
|
4194
|
+
const showAgents = userSettings?.show_agent_sessions ?? false;
|
|
4195
|
+
const visibleMembers = useMemo(
|
|
4196
|
+
() => showAgents ? members : members.filter((m) => !isAgentMember(m)),
|
|
4197
|
+
[members, showAgents]
|
|
4198
|
+
);
|
|
4199
|
+
const [membersExpanded, setMembersExpanded] = useState(false);
|
|
4200
|
+
const [shareOpen, setShareOpen] = useState(false);
|
|
4201
|
+
if (!workspace) {
|
|
4202
|
+
return /* @__PURE__ */ jsx(PageLoading, { children: /* @__PURE__ */ jsx(LoadingIndicator, { message: "Loading workspace..." }) });
|
|
4203
|
+
}
|
|
4204
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4205
|
+
/* @__PURE__ */ jsxs(WorkspacePageFrame, { testId, children: [
|
|
4206
|
+
/* @__PURE__ */ jsxs(WorkspaceIdentityPanel, { children: [
|
|
4207
|
+
/* @__PURE__ */ jsx(
|
|
4208
|
+
EntityIdentityBar,
|
|
4209
|
+
{
|
|
4210
|
+
testId: "workspace-identity-bar",
|
|
4211
|
+
canEdit: isOwner,
|
|
4212
|
+
actions: isMember ? /* @__PURE__ */ jsx(
|
|
4213
|
+
ConnectedWorkspaceNotificationMenu,
|
|
4214
|
+
{
|
|
4215
|
+
workspaceId: workspace.external_id,
|
|
4216
|
+
onOpenActivity,
|
|
4217
|
+
testId: "workspace-home-notification-menu"
|
|
4218
|
+
}
|
|
4219
|
+
) : void 0,
|
|
4220
|
+
fields: [
|
|
4221
|
+
{
|
|
4222
|
+
label: "Name",
|
|
4223
|
+
value: workspace.name,
|
|
4224
|
+
placeholder: "Untitled",
|
|
4225
|
+
maxLength: IDENTITY_NAME_MAX_LENGTH,
|
|
4226
|
+
valueClassName: "truncate text-base font-semibold",
|
|
4227
|
+
testId: "workspace-home-title",
|
|
4228
|
+
hideLabel: true,
|
|
4229
|
+
leading: /* @__PURE__ */ jsx(
|
|
4230
|
+
WorkspaceIdentity,
|
|
4231
|
+
{
|
|
4232
|
+
workspace: {
|
|
4233
|
+
...toShellWorkspace(workspace),
|
|
4234
|
+
projectLine: projectLine?.(workspace)
|
|
4235
|
+
},
|
|
4236
|
+
expanded: false
|
|
4237
|
+
}
|
|
4238
|
+
),
|
|
4239
|
+
trailing: project && /* @__PURE__ */ jsx(
|
|
4240
|
+
WorkspaceProjectSlot,
|
|
4241
|
+
{
|
|
4242
|
+
testId: "workspace-home-project",
|
|
4243
|
+
caption: `${getEntityLabel("PROJECT")}:`,
|
|
4244
|
+
children: project({ workspace, isOwner })
|
|
4245
|
+
}
|
|
4246
|
+
),
|
|
4247
|
+
// Both fields go up together: the endpoint takes the pair.
|
|
4248
|
+
onSave: (name) => settings.updateIdentity({ name, description: workspace.description ?? "" })
|
|
4249
|
+
},
|
|
4250
|
+
{
|
|
4251
|
+
label: "Description",
|
|
4252
|
+
value: workspace.description ?? "",
|
|
4253
|
+
placeholder: "No description",
|
|
4254
|
+
multiline: true,
|
|
4255
|
+
valueClassName: "line-clamp-2 text-sm text-muted-foreground",
|
|
4256
|
+
testId: "workspace-home-description",
|
|
4257
|
+
hideLabel: true,
|
|
4258
|
+
trailing: /* @__PURE__ */ jsx(
|
|
4259
|
+
WorkspaceAudienceLine,
|
|
4260
|
+
{
|
|
4261
|
+
visibility: {
|
|
4262
|
+
testId: "workspace-home-visibility",
|
|
4263
|
+
caption: "Visibility:",
|
|
4264
|
+
toggle: isOwner && isDeveloper ? /* @__PURE__ */ jsx(
|
|
4265
|
+
CommonWorkspaceToggle,
|
|
4266
|
+
{
|
|
4267
|
+
isCommon: workspace.is_public ?? false,
|
|
4268
|
+
onToggle: (value) => void settings.setPublic(value),
|
|
4269
|
+
"data-testid": "workspace-visibility-toggle"
|
|
4270
|
+
}
|
|
4271
|
+
) : void 0,
|
|
4272
|
+
stateText: workspace.is_public ? "Common \u2014 everyone on this deployment" : "Members only",
|
|
4273
|
+
stateHelp: workspace.is_public ? "Everyone on this deployment can see its files, not only its members." : "Only members of this workspace can see its files."
|
|
4274
|
+
},
|
|
4275
|
+
members: /* @__PURE__ */ jsx(
|
|
4276
|
+
MemberAvatarStack,
|
|
4277
|
+
{
|
|
4278
|
+
members: visibleMembers.map((m) => ({
|
|
4279
|
+
name: memberName(m),
|
|
4280
|
+
picture: m.user.picture
|
|
4281
|
+
})),
|
|
4282
|
+
total: visibleMembers.length,
|
|
4283
|
+
expanded: membersExpanded,
|
|
4284
|
+
onClick: () => setMembersExpanded((open) => !open),
|
|
4285
|
+
testId: "workspace-home-members-toggle"
|
|
4286
|
+
}
|
|
4287
|
+
),
|
|
4288
|
+
share: isOwner && shareDialog ? {
|
|
4289
|
+
label: "Share",
|
|
4290
|
+
onClick: () => setShareOpen(true),
|
|
4291
|
+
testId: "workspace-quick-add-member"
|
|
4292
|
+
} : void 0
|
|
4293
|
+
}
|
|
4294
|
+
),
|
|
4295
|
+
onSave: (description) => settings.updateIdentity({ name: workspace.name, description })
|
|
4296
|
+
}
|
|
4297
|
+
]
|
|
4298
|
+
}
|
|
4299
|
+
),
|
|
4300
|
+
isMember && membersTable && /* @__PURE__ */ jsx(
|
|
4301
|
+
ExpandableSection,
|
|
4302
|
+
{
|
|
4303
|
+
expanded: membersExpanded,
|
|
4304
|
+
testId: "workspace-settings-members-section",
|
|
4305
|
+
children: membersTable({
|
|
4306
|
+
workspace,
|
|
4307
|
+
members: visibleMembers,
|
|
4308
|
+
onRemove: settings.removeMember,
|
|
4309
|
+
isRemoving: settings.isRemoving
|
|
4310
|
+
})
|
|
4311
|
+
}
|
|
4312
|
+
)
|
|
4313
|
+
] }),
|
|
4314
|
+
children,
|
|
4315
|
+
isMember && onExport && /* @__PURE__ */ jsx("div", { className: "flex justify-end px-4 pb-4", children: /* @__PURE__ */ jsxs(
|
|
4316
|
+
Button,
|
|
4317
|
+
{
|
|
4318
|
+
variant: "outline",
|
|
4319
|
+
size: "sm",
|
|
4320
|
+
onClick: onExport,
|
|
4321
|
+
"data-testid": "workspace-transfer-button",
|
|
4322
|
+
children: [
|
|
4323
|
+
/* @__PURE__ */ jsx(FolderInput, { className: "size-4" }),
|
|
4324
|
+
"Export, copy or move\u2026"
|
|
4325
|
+
]
|
|
4326
|
+
}
|
|
4327
|
+
) }),
|
|
4328
|
+
!isOwner && /* @__PURE__ */ jsx(
|
|
4329
|
+
LeaveFooter,
|
|
4330
|
+
{
|
|
4331
|
+
testId: "workspace-settings-footer",
|
|
4332
|
+
leave: {
|
|
4333
|
+
testId: "workspace-leave-button",
|
|
4334
|
+
label: settings.isRemoving ? "Leaving\u2026" : `Leave ${getEntityLabel("WORKSPACE").toLowerCase()}`,
|
|
4335
|
+
disabled: settings.isRemoving,
|
|
4336
|
+
onClick: () => void settings.leave()
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
)
|
|
4340
|
+
] }),
|
|
4341
|
+
isOwner && shareDialog?.({
|
|
4342
|
+
open: shareOpen,
|
|
4343
|
+
onOpenChange: setShareOpen,
|
|
4344
|
+
workspace,
|
|
4345
|
+
members: visibleMembers,
|
|
4346
|
+
onShare: settings.share,
|
|
4347
|
+
isSharing: settings.isSharing
|
|
4348
|
+
})
|
|
4349
|
+
] });
|
|
4350
|
+
}
|
|
4351
|
+
|
|
4352
|
+
// src/connection/connectors/sync-labels.ts
|
|
4353
|
+
var BACKFILL_OPTIONS = [
|
|
4354
|
+
{ value: "1", label: "Last 1 day" },
|
|
4355
|
+
{ value: "7", label: "Last 7 days" },
|
|
4356
|
+
{ value: "30", label: "Last 30 days" },
|
|
4357
|
+
{ value: "90", label: "Last 90 days" },
|
|
4358
|
+
{ value: "365", label: "Last year" }
|
|
4359
|
+
];
|
|
4360
|
+
function formatLastSync(iso) {
|
|
4361
|
+
const date = new Date(iso);
|
|
4362
|
+
if (Number.isNaN(date.getTime())) return iso;
|
|
4363
|
+
const diffMs = Date.now() - date.getTime();
|
|
4364
|
+
const diffMin = Math.round(diffMs / 6e4);
|
|
4365
|
+
if (diffMin < 1) return "just now";
|
|
4366
|
+
if (diffMin < 60) return `${diffMin}m ago`;
|
|
4367
|
+
const diffHr = Math.round(diffMin / 60);
|
|
4368
|
+
if (diffHr < 24) return `${diffHr}h ago`;
|
|
4369
|
+
const diffDay = Math.round(diffHr / 24);
|
|
4370
|
+
if (diffDay < 30) return `${diffDay}d ago`;
|
|
4371
|
+
return date.toLocaleDateString();
|
|
4372
|
+
}
|
|
4373
|
+
function windowLabel(days) {
|
|
4374
|
+
return BACKFILL_OPTIONS.find((o) => o.value === String(days))?.label ?? `Last ${days} days`;
|
|
4375
|
+
}
|
|
4376
|
+
function ConnectedMailboxSyncDialog({
|
|
4377
|
+
catalog,
|
|
4378
|
+
userConnector,
|
|
4379
|
+
open,
|
|
4380
|
+
onOpenChange,
|
|
4381
|
+
lockedWorkspaceExtId,
|
|
4382
|
+
onEnabled
|
|
4383
|
+
}) {
|
|
4384
|
+
const enableSync = useEnableMailboxSync();
|
|
4385
|
+
const disconnect = useDisconnectConnector();
|
|
4386
|
+
const arbi = useArbi();
|
|
4387
|
+
const { notify, navigate } = useBlocksEnvironment();
|
|
4388
|
+
const reconnect = async () => {
|
|
4389
|
+
try {
|
|
4390
|
+
await disconnect.mutateAsync({ vendorKey: catalog.vendor_key });
|
|
4391
|
+
} catch {
|
|
4392
|
+
}
|
|
4393
|
+
try {
|
|
4394
|
+
navigate(await arbi.connectors.authorize(catalog.vendor_key, connectorReturnTo()));
|
|
4395
|
+
} catch {
|
|
4396
|
+
notify("Could not start reconnection. Please try again.", "error");
|
|
4397
|
+
}
|
|
4398
|
+
};
|
|
4399
|
+
const { data: workspaces = [] } = useWorkspaces({ enabled: open && !lockedWorkspaceExtId });
|
|
4400
|
+
const memberWorkspaces = workspaces.filter((w) => w.is_member);
|
|
4401
|
+
const [tokensBridged, setTokensBridged] = useState(false);
|
|
4402
|
+
useEffect(() => {
|
|
4403
|
+
if (!open) {
|
|
4404
|
+
setTokensBridged(false);
|
|
4405
|
+
return;
|
|
4406
|
+
}
|
|
4407
|
+
if (!userConnector?.is_connected) {
|
|
4408
|
+
setTokensBridged(true);
|
|
4409
|
+
return;
|
|
4410
|
+
}
|
|
4411
|
+
let cancelled = false;
|
|
4412
|
+
void arbi.connectors.bridgeTokens({ vendor: catalog.vendor_key }).finally(() => {
|
|
4413
|
+
if (!cancelled) setTokensBridged(true);
|
|
4414
|
+
});
|
|
4415
|
+
return () => {
|
|
4416
|
+
cancelled = true;
|
|
4417
|
+
};
|
|
4418
|
+
}, [open, arbi, userConnector?.is_connected, catalog.vendor_key]);
|
|
4419
|
+
const [workspaceExtId, setWorkspaceExtId] = useState("");
|
|
4420
|
+
const [backfill, setBackfill] = useState("1");
|
|
4421
|
+
const [backfillSince, setBackfillSince] = useState("");
|
|
4422
|
+
const [selectedFolders, setSelectedFolders] = useState([]);
|
|
4423
|
+
const [skipDuplicates, setSkipDuplicates] = useState(true);
|
|
4424
|
+
const [autoRename, setAutoRename] = useState(false);
|
|
4425
|
+
const [shared, setShared] = useState(false);
|
|
4426
|
+
const [autoSync, setAutoSync] = useState(false);
|
|
4427
|
+
useEffect(() => {
|
|
4428
|
+
if (!open) return;
|
|
4429
|
+
const target = lockedWorkspaceExtId ?? userConnector?.sync_workspace_ext_id ?? "";
|
|
4430
|
+
const workspaceSync = lockedWorkspaceExtId ? userConnector?.syncs?.find((s) => s.workspace_ext_id === lockedWorkspaceExtId) : void 0;
|
|
4431
|
+
setWorkspaceExtId(target);
|
|
4432
|
+
const since = workspaceSync?.backfill_since ?? userConnector?.backfill_since ?? null;
|
|
4433
|
+
if (since) {
|
|
4434
|
+
setBackfill("custom");
|
|
4435
|
+
setBackfillSince(since.slice(0, 10));
|
|
4436
|
+
} else {
|
|
4437
|
+
setBackfill(String(workspaceSync?.backfill_window ?? userConnector?.backfill_window ?? 1));
|
|
4438
|
+
setBackfillSince("");
|
|
4439
|
+
}
|
|
4440
|
+
setSelectedFolders(workspaceSync?.folders ?? userConnector?.sync_folders ?? []);
|
|
4441
|
+
setSkipDuplicates(workspaceSync?.skip_duplicates ?? userConnector?.skip_duplicates ?? true);
|
|
4442
|
+
setAutoRename(workspaceSync?.auto_rename ?? userConnector?.auto_rename ?? false);
|
|
4443
|
+
setShared(workspaceSync?.shared ?? userConnector?.shared ?? false);
|
|
4444
|
+
setAutoSync(workspaceSync?.auto_sync ?? userConnector?.auto_sync ?? false);
|
|
4445
|
+
}, [open, lockedWorkspaceExtId, userConnector]);
|
|
4446
|
+
const {
|
|
4447
|
+
data: folders = [],
|
|
4448
|
+
isLoading: foldersQueryLoading,
|
|
4449
|
+
error: foldersError
|
|
4450
|
+
} = useMailboxFolders(catalog.vendor_key, open && tokensBridged);
|
|
4451
|
+
const foldersLoading = !tokensBridged || foldersQueryLoading;
|
|
4452
|
+
const folderTree = buildMailFolderTree(folders);
|
|
4453
|
+
const [expandAllNonce, setExpandAllNonce] = useState(0);
|
|
4454
|
+
const [collapseAllNonce, setCollapseAllNonce] = useState(0);
|
|
4455
|
+
const selectAllIds = folderTree.flatMap(
|
|
4456
|
+
(n) => n.folder ? [n.folder.id] : n.children.flatMap((c) => c.folder ? [c.folder.id] : [])
|
|
4457
|
+
);
|
|
4458
|
+
const allSelected = selectAllIds.length > 0 && selectAllIds.every((id) => selectedFolders.includes(id));
|
|
4459
|
+
const toggleAllFolders = () => setSelectedFolders(allSelected ? [] : selectAllIds);
|
|
4460
|
+
const isCustomBackfill = backfill === "custom";
|
|
4461
|
+
const customDateMissing = isCustomBackfill && !backfillSince;
|
|
4462
|
+
const handleEnableSubmit = () => {
|
|
4463
|
+
if (!workspaceExtId || selectedFolders.length === 0 || customDateMissing) return;
|
|
4464
|
+
enableSync.mutate(
|
|
4465
|
+
{
|
|
4466
|
+
vendorKey: catalog.vendor_key,
|
|
4467
|
+
workspaceExtId,
|
|
4468
|
+
// A fixed date overrides the rolling window server-side; keep a sane
|
|
4469
|
+
// window value for backward compatibility.
|
|
4470
|
+
backfillWindow: isCustomBackfill ? 90 : Number(backfill),
|
|
4471
|
+
backfillSince: isCustomBackfill ? (/* @__PURE__ */ new Date(`${backfillSince}T00:00:00Z`)).toISOString() : null,
|
|
4472
|
+
folders: selectedFolders,
|
|
4473
|
+
skipDuplicates,
|
|
4474
|
+
autoRename,
|
|
4475
|
+
shared,
|
|
4476
|
+
autoSync
|
|
4477
|
+
},
|
|
4478
|
+
{
|
|
4479
|
+
onSuccess: () => {
|
|
4480
|
+
notify("Email settings saved", "success");
|
|
4481
|
+
onOpenChange(false);
|
|
4482
|
+
onEnabled?.(workspaceExtId);
|
|
4483
|
+
},
|
|
4484
|
+
onError: (err) => {
|
|
4485
|
+
let msg = "Could not enable email sync. Please try again.";
|
|
4486
|
+
const status = connectorErrorStatus(err);
|
|
4487
|
+
if (status !== void 0) {
|
|
4488
|
+
if (status === 403) {
|
|
4489
|
+
msg = "You are not a member of the selected workspace.";
|
|
4490
|
+
} else if (status === 404) {
|
|
4491
|
+
msg = "This connector is not available for email sync.";
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4494
|
+
notify(msg, "error");
|
|
4495
|
+
}
|
|
4496
|
+
}
|
|
4497
|
+
);
|
|
4498
|
+
};
|
|
4499
|
+
const mailboxName = catalog.vendor_key === "gmail" ? "Gmail" : catalog.vendor_key === "microsoft" ? "Outlook" : catalog.display_name;
|
|
4500
|
+
return /* @__PURE__ */ jsxs(
|
|
4501
|
+
ModalScaffold,
|
|
4502
|
+
{
|
|
4503
|
+
open,
|
|
4504
|
+
onOpenChange,
|
|
4505
|
+
title: `${mailboxName} Import Settings`,
|
|
4506
|
+
description: `Import emails from ${catalog.display_name} into a workspace so the ARBI agent can search them. This is read-only \u2014 ARBI imports a copy and never modifies or deletes anything in your mailbox.`,
|
|
4507
|
+
showDescription: true,
|
|
4508
|
+
className: "w-[92vw] sm:max-w-lg",
|
|
4509
|
+
children: [
|
|
4510
|
+
/* @__PURE__ */ jsxs(SyncDialogBody, { children: [
|
|
4511
|
+
!lockedWorkspaceExtId && /* @__PURE__ */ jsx(SyncField, { label: "Target workspace", htmlFor: "sync-workspace", children: /* @__PURE__ */ jsx(
|
|
4512
|
+
SyncSelect,
|
|
4513
|
+
{
|
|
4514
|
+
id: "sync-workspace",
|
|
4515
|
+
value: workspaceExtId,
|
|
4516
|
+
onValueChange: setWorkspaceExtId,
|
|
4517
|
+
placeholder: "Select a workspace",
|
|
4518
|
+
options: memberWorkspaces.map((w) => ({ value: w.external_id, label: w.name }))
|
|
4519
|
+
}
|
|
4520
|
+
) }),
|
|
4521
|
+
/* @__PURE__ */ jsxs(SyncField, { label: "Backfill window", htmlFor: "sync-backfill", children: [
|
|
4522
|
+
/* @__PURE__ */ jsx(
|
|
4523
|
+
SyncSelect,
|
|
4524
|
+
{
|
|
4525
|
+
id: "sync-backfill",
|
|
4526
|
+
value: backfill,
|
|
4527
|
+
onValueChange: setBackfill,
|
|
4528
|
+
options: [...BACKFILL_OPTIONS, { value: "custom", label: "Custom date\u2026" }]
|
|
4529
|
+
}
|
|
4530
|
+
),
|
|
4531
|
+
isCustomBackfill && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
4532
|
+
/* @__PURE__ */ jsx(
|
|
4533
|
+
Input,
|
|
4534
|
+
{
|
|
4535
|
+
type: "date",
|
|
4536
|
+
value: backfillSince,
|
|
4537
|
+
max: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10),
|
|
4538
|
+
onChange: (e) => setBackfillSince(e.target.value),
|
|
4539
|
+
"data-testid": "backfill-since-date",
|
|
4540
|
+
"aria-label": "Import emails since date"
|
|
4541
|
+
}
|
|
4542
|
+
),
|
|
4543
|
+
/* @__PURE__ */ jsx(SyncSmallNote, { children: "Emails are always imported from this date onward \u2014 the start point never moves." })
|
|
4544
|
+
] })
|
|
4545
|
+
] }),
|
|
4546
|
+
/* @__PURE__ */ jsx(
|
|
4547
|
+
SyncField,
|
|
4548
|
+
{
|
|
4549
|
+
label: `Folders to import${selectedFolders.length > 0 ? ` (${selectedFolders.length})` : ""}`,
|
|
4550
|
+
hint: "Select at least one folder to import.",
|
|
4551
|
+
actions: folders.length > 0 && /* @__PURE__ */ jsxs(SyncLinkRow, { children: [
|
|
4552
|
+
/* @__PURE__ */ jsx(
|
|
4553
|
+
SyncLinkButton,
|
|
4554
|
+
{
|
|
4555
|
+
onClick: () => setExpandAllNonce((n) => n + 1),
|
|
4556
|
+
testId: "mail-folders-expand-all",
|
|
4557
|
+
children: "Expand all"
|
|
4558
|
+
}
|
|
4559
|
+
),
|
|
4560
|
+
/* @__PURE__ */ jsx(
|
|
4561
|
+
SyncLinkButton,
|
|
4562
|
+
{
|
|
4563
|
+
onClick: () => setCollapseAllNonce((n) => n + 1),
|
|
4564
|
+
testId: "mail-folders-collapse-all",
|
|
4565
|
+
children: "Collapse all"
|
|
4566
|
+
}
|
|
4567
|
+
),
|
|
4568
|
+
/* @__PURE__ */ jsx(SyncLinkButton, { onClick: toggleAllFolders, children: allSelected ? "Clear all" : "Select all" })
|
|
4569
|
+
] }),
|
|
4570
|
+
children: foldersLoading ? /* @__PURE__ */ jsx(SyncLoading, { children: "Loading folders\u2026" }) : foldersError ? (
|
|
4571
|
+
// A failed fetch is not an empty mailbox: it hides auth/scope errors (e.g. a Gmail
|
|
4572
|
+
// account needing reconnect).
|
|
4573
|
+
/* @__PURE__ */ jsx(
|
|
4574
|
+
SyncReconnectNotice,
|
|
4575
|
+
{
|
|
4576
|
+
message: `Couldn\u2019t load folders from ${catalog.display_name}. Reconnect the account and try again.`,
|
|
4577
|
+
onReconnect: () => void reconnect(),
|
|
4578
|
+
isPending: disconnect.isPending,
|
|
4579
|
+
testId: "folders-reconnect"
|
|
4580
|
+
}
|
|
4581
|
+
)
|
|
4582
|
+
) : folders.length === 0 ? /* @__PURE__ */ jsx(SyncNote, { children: "No folders found." }) : /* @__PURE__ */ jsx(SyncTreeFrame, { children: /* @__PURE__ */ jsx(
|
|
4583
|
+
MailFolderTree,
|
|
4584
|
+
{
|
|
4585
|
+
nodes: folderTree,
|
|
4586
|
+
selected: selectedFolders,
|
|
4587
|
+
onChange: setSelectedFolders,
|
|
4588
|
+
expandAllNonce,
|
|
4589
|
+
collapseAllNonce
|
|
4590
|
+
}
|
|
4591
|
+
) })
|
|
4592
|
+
}
|
|
4593
|
+
),
|
|
4594
|
+
/* @__PURE__ */ jsxs(SyncOptions, { children: [
|
|
4595
|
+
/* @__PURE__ */ jsx(
|
|
4596
|
+
SyncOptionToggle,
|
|
4597
|
+
{
|
|
4598
|
+
checked: skipDuplicates,
|
|
4599
|
+
onCheckedChange: setSkipDuplicates,
|
|
4600
|
+
title: "Skip duplicates",
|
|
4601
|
+
description: "Skip files identical to ones already in the workspace.",
|
|
4602
|
+
testId: "mailbox-sync-skip-duplicates"
|
|
4603
|
+
}
|
|
4604
|
+
),
|
|
4605
|
+
/* @__PURE__ */ jsx(
|
|
4606
|
+
SyncOptionToggle,
|
|
4607
|
+
{
|
|
4608
|
+
checked: autoRename,
|
|
4609
|
+
onCheckedChange: setAutoRename,
|
|
4610
|
+
title: "Auto-rename",
|
|
4611
|
+
description: "Generate a descriptive title with AI instead of using the sender and subject.",
|
|
4612
|
+
testId: "mailbox-sync-auto-rename"
|
|
4613
|
+
}
|
|
4614
|
+
),
|
|
4615
|
+
/* @__PURE__ */ jsx(
|
|
4616
|
+
SyncOptionToggle,
|
|
4617
|
+
{
|
|
4618
|
+
checked: shared,
|
|
4619
|
+
onCheckedChange: setShared,
|
|
4620
|
+
title: "Share with the workspace",
|
|
4621
|
+
description: shared ? "Imported documents are visible to everyone in the workspace." : "Imported documents stay private to you.",
|
|
4622
|
+
testId: "mailbox-sync-shared"
|
|
4623
|
+
}
|
|
4624
|
+
),
|
|
4625
|
+
/* @__PURE__ */ jsx(
|
|
4626
|
+
SyncOptionToggle,
|
|
4627
|
+
{
|
|
4628
|
+
checked: autoSync,
|
|
4629
|
+
onCheckedChange: setAutoSync,
|
|
4630
|
+
title: "Sync automatically",
|
|
4631
|
+
description: "Check for new email when you sign in, instead of only when you click Sync now. Requires you to be signed in \u2014 nothing syncs while you are away.",
|
|
4632
|
+
testId: "mailbox-sync-auto-sync"
|
|
4633
|
+
}
|
|
4634
|
+
)
|
|
4635
|
+
] })
|
|
4636
|
+
] }),
|
|
4637
|
+
/* @__PURE__ */ jsx(
|
|
4638
|
+
SyncDialogFooter,
|
|
4639
|
+
{
|
|
4640
|
+
onCancel: () => onOpenChange(false),
|
|
4641
|
+
onSave: handleEnableSubmit,
|
|
4642
|
+
saveDisabled: !workspaceExtId || selectedFolders.length === 0 || customDateMissing,
|
|
4643
|
+
isSaving: enableSync.isPending
|
|
4644
|
+
}
|
|
4645
|
+
)
|
|
4646
|
+
]
|
|
4647
|
+
}
|
|
4648
|
+
);
|
|
4649
|
+
}
|
|
4650
|
+
var DRIVE_PRODUCT_NAMES = {
|
|
4651
|
+
gmail: "Google Drive",
|
|
4652
|
+
microsoft_sharepoint: "SharePoint",
|
|
4653
|
+
box: "Box",
|
|
4654
|
+
dropbox: "Dropbox",
|
|
4655
|
+
onenote: "OneNote",
|
|
4656
|
+
clio: "Clio"
|
|
4657
|
+
};
|
|
4658
|
+
function DriveFolderNode({
|
|
4659
|
+
vendorKey,
|
|
4660
|
+
folder,
|
|
4661
|
+
depth,
|
|
4662
|
+
selected,
|
|
4663
|
+
onToggle,
|
|
4664
|
+
enabled,
|
|
4665
|
+
ancestorSelected,
|
|
4666
|
+
expandAllNonce,
|
|
4667
|
+
collapseAllNonce
|
|
4668
|
+
}) {
|
|
4669
|
+
const isSelected = ancestorSelected || selected.includes(folder.id);
|
|
4670
|
+
const [expanded, setExpanded] = useState(() => selected.includes(folder.id) || expandAllNonce > 0);
|
|
4671
|
+
const appliedNonce = useRef(expandAllNonce);
|
|
4672
|
+
useEffect(() => {
|
|
4673
|
+
if (expandAllNonce > appliedNonce.current) {
|
|
4674
|
+
appliedNonce.current = expandAllNonce;
|
|
4675
|
+
setExpanded(true);
|
|
4676
|
+
}
|
|
4677
|
+
}, [expandAllNonce]);
|
|
4678
|
+
const appliedCollapseNonce = useRef(collapseAllNonce);
|
|
4679
|
+
useEffect(() => {
|
|
4680
|
+
if (collapseAllNonce > appliedCollapseNonce.current) {
|
|
4681
|
+
appliedCollapseNonce.current = collapseAllNonce;
|
|
4682
|
+
setExpanded(false);
|
|
4683
|
+
}
|
|
4684
|
+
}, [collapseAllNonce]);
|
|
4685
|
+
const { data: children = [], isLoading } = useDriveFolderChildren(
|
|
4686
|
+
vendorKey,
|
|
4687
|
+
folder.id,
|
|
4688
|
+
enabled && expanded
|
|
4689
|
+
);
|
|
4690
|
+
const isSelectable = folder.selectable !== false;
|
|
4691
|
+
const { data: docCount, isLoading: countLoading } = useDriveFolderDocCount(
|
|
4692
|
+
vendorKey,
|
|
4693
|
+
folder.id,
|
|
4694
|
+
enabled && isSelectable
|
|
4695
|
+
// ← disabled for site: nodes
|
|
4696
|
+
);
|
|
4697
|
+
const mightHaveChildren = docCount == null || docCount > 0;
|
|
4698
|
+
const orderedChildren = [...children].sort((a, b) => a.name.localeCompare(b.name));
|
|
4699
|
+
return /* @__PURE__ */ jsx(
|
|
4700
|
+
SyncFolderRow,
|
|
4701
|
+
{
|
|
4702
|
+
id: folder.id,
|
|
4703
|
+
name: folder.name,
|
|
4704
|
+
depth,
|
|
4705
|
+
hasChildren: mightHaveChildren,
|
|
4706
|
+
isExpanded: expanded,
|
|
4707
|
+
onToggleExpanded: () => setExpanded((e) => !e),
|
|
4708
|
+
isSelectable,
|
|
4709
|
+
checked: isSelected,
|
|
4710
|
+
disabled: ancestorSelected,
|
|
4711
|
+
onCheckedChange: () => onToggle(folder.id),
|
|
4712
|
+
count: typeof docCount === "number" ? docCount : void 0,
|
|
4713
|
+
isCountLoading: isSelectable && countLoading,
|
|
4714
|
+
children: isLoading ? /* @__PURE__ */ jsx(SyncFolderStatus, { depth, kind: "loading" }) : orderedChildren.length === 0 ? /* @__PURE__ */ jsx(SyncFolderStatus, { depth, kind: "empty" }) : orderedChildren.map((child) => /* @__PURE__ */ jsx(
|
|
4715
|
+
DriveFolderNode,
|
|
4716
|
+
{
|
|
4717
|
+
vendorKey,
|
|
4718
|
+
folder: child,
|
|
4719
|
+
depth: depth + 1,
|
|
4720
|
+
selected,
|
|
4721
|
+
onToggle,
|
|
4722
|
+
enabled,
|
|
4723
|
+
ancestorSelected: isSelected,
|
|
4724
|
+
expandAllNonce,
|
|
4725
|
+
collapseAllNonce
|
|
4726
|
+
},
|
|
4727
|
+
child.id
|
|
4728
|
+
))
|
|
4729
|
+
}
|
|
4730
|
+
);
|
|
4731
|
+
}
|
|
4732
|
+
function ConnectedDriveSyncDialog({
|
|
4733
|
+
catalog,
|
|
4734
|
+
userConnector,
|
|
4735
|
+
open,
|
|
4736
|
+
onOpenChange,
|
|
4737
|
+
lockedWorkspaceExtId,
|
|
4738
|
+
onEnabled
|
|
4739
|
+
}) {
|
|
4740
|
+
const enableSync = useEnableDriveSync();
|
|
4741
|
+
const disconnect = useDisconnectConnector();
|
|
4742
|
+
const arbi = useArbi();
|
|
4743
|
+
const { notify, navigate } = useBlocksEnvironment();
|
|
4744
|
+
const reconnect = async () => {
|
|
4745
|
+
try {
|
|
4746
|
+
await disconnect.mutateAsync({ vendorKey: catalog.vendor_key });
|
|
4747
|
+
} catch {
|
|
4748
|
+
}
|
|
4749
|
+
try {
|
|
4750
|
+
navigate(await arbi.connectors.authorize(catalog.vendor_key, connectorReturnTo()));
|
|
4751
|
+
} catch {
|
|
4752
|
+
notify("Could not start reconnection. Please try again.", "error");
|
|
4753
|
+
}
|
|
4754
|
+
};
|
|
4755
|
+
const { data: workspaces = [] } = useWorkspaces({ enabled: open && !lockedWorkspaceExtId });
|
|
4756
|
+
const memberWorkspaces = workspaces.filter((w) => w.is_member);
|
|
4757
|
+
const [tokensBridged, setTokensBridged] = useState(false);
|
|
4758
|
+
useEffect(() => {
|
|
4759
|
+
if (!open) {
|
|
4760
|
+
setTokensBridged(false);
|
|
4761
|
+
return;
|
|
4762
|
+
}
|
|
4763
|
+
if (!userConnector?.is_connected) {
|
|
4764
|
+
setTokensBridged(true);
|
|
4765
|
+
return;
|
|
4766
|
+
}
|
|
4767
|
+
let cancelled = false;
|
|
4768
|
+
void arbi.connectors.bridgeTokens({ vendor: catalog.vendor_key }).finally(() => {
|
|
4769
|
+
if (!cancelled) setTokensBridged(true);
|
|
4770
|
+
});
|
|
4771
|
+
return () => {
|
|
4772
|
+
cancelled = true;
|
|
4773
|
+
};
|
|
4774
|
+
}, [open, arbi, userConnector?.is_connected, catalog.vendor_key]);
|
|
4775
|
+
const [workspaceExtId, setWorkspaceExtId] = useState("");
|
|
4776
|
+
const [selectedFolders, setSelectedFolders] = useState([]);
|
|
4777
|
+
const [skipDuplicates, setSkipDuplicates] = useState(false);
|
|
4778
|
+
const [autoRename, setAutoRename] = useState(false);
|
|
4779
|
+
const [shared, setShared] = useState(false);
|
|
4780
|
+
const [autoSync, setAutoSync] = useState(false);
|
|
4781
|
+
useEffect(() => {
|
|
4782
|
+
if (!open) return;
|
|
4783
|
+
const target = lockedWorkspaceExtId ?? userConnector?.drive_sync_workspace_ext_id ?? "";
|
|
4784
|
+
setWorkspaceExtId(target);
|
|
4785
|
+
setSelectedFolders(userConnector?.drive_sync_folders ?? []);
|
|
4786
|
+
setSkipDuplicates(userConnector?.drive_skip_duplicates ?? false);
|
|
4787
|
+
setAutoRename(userConnector?.drive_auto_rename ?? false);
|
|
4788
|
+
setShared(userConnector?.drive_shared ?? false);
|
|
4789
|
+
setAutoSync(userConnector?.drive_auto_sync ?? false);
|
|
4790
|
+
setExpandAllNonce(0);
|
|
4791
|
+
setCollapseAllNonce(0);
|
|
4792
|
+
}, [open, lockedWorkspaceExtId, userConnector]);
|
|
4793
|
+
const [expandAllNonce, setExpandAllNonce] = useState(0);
|
|
4794
|
+
const [collapseAllNonce, setCollapseAllNonce] = useState(0);
|
|
4795
|
+
const treeEnabled = open && tokensBridged;
|
|
4796
|
+
const {
|
|
4797
|
+
data: folders = [],
|
|
4798
|
+
isLoading: foldersQueryLoading,
|
|
4799
|
+
error: foldersError
|
|
4800
|
+
} = useDriveFolderChildren(catalog.vendor_key, "root", treeEnabled);
|
|
4801
|
+
const foldersLoading = !tokensBridged || foldersQueryLoading;
|
|
4802
|
+
const needsReconnect = connectorErrorStatus(foldersError) === 409;
|
|
4803
|
+
const toggleFolder = (id) => setSelectedFolders((prev) => prev.includes(id) ? prev.filter((f) => f !== id) : [...prev, id]);
|
|
4804
|
+
const orderedFolders = [...folders].sort(
|
|
4805
|
+
(a, b) => a.name.localeCompare(b.name)
|
|
4806
|
+
);
|
|
4807
|
+
const handleEnableSubmit = () => {
|
|
4808
|
+
if (!workspaceExtId || selectedFolders.length === 0) return;
|
|
4809
|
+
const foldersToSubmit = selectedFolders.filter((id) => !id.startsWith("site:"));
|
|
4810
|
+
if (foldersToSubmit.length === 0) return;
|
|
4811
|
+
enableSync.mutate(
|
|
4812
|
+
{
|
|
4813
|
+
vendorKey: catalog.vendor_key,
|
|
4814
|
+
workspaceExtId,
|
|
4815
|
+
folders: foldersToSubmit,
|
|
4816
|
+
skipDuplicates,
|
|
4817
|
+
autoRename,
|
|
4818
|
+
shared,
|
|
4819
|
+
autoSync
|
|
4820
|
+
},
|
|
4821
|
+
{
|
|
4822
|
+
onSuccess: () => {
|
|
4823
|
+
notify(`${productName} settings saved`, "success");
|
|
4824
|
+
onOpenChange(false);
|
|
4825
|
+
onEnabled?.(workspaceExtId);
|
|
4826
|
+
},
|
|
4827
|
+
onError: (err) => {
|
|
4828
|
+
let msg = `Could not enable ${productName} sync. Please try again.`;
|
|
4829
|
+
const status = connectorErrorStatus(err);
|
|
4830
|
+
if (status !== void 0) {
|
|
4831
|
+
if (status === 403) {
|
|
4832
|
+
msg = "You are not a member of the selected workspace.";
|
|
4833
|
+
} else if (status === 409) {
|
|
4834
|
+
msg = `Reconnect needed \u2014 re-authorize your account to enable ${productName}.`;
|
|
4835
|
+
} else if (status === 404) {
|
|
4836
|
+
msg = `This connector is not available for ${productName} sync.`;
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
notify(msg, "error");
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
);
|
|
4843
|
+
};
|
|
4844
|
+
const productName = DRIVE_PRODUCT_NAMES[catalog.vendor_key] ?? "OneDrive";
|
|
4845
|
+
const reconnectButtonProps = {
|
|
4846
|
+
onReconnect: () => void reconnect(),
|
|
4847
|
+
isPending: disconnect.isPending,
|
|
4848
|
+
testId: "drive-folders-reconnect"
|
|
4849
|
+
};
|
|
4850
|
+
return /* @__PURE__ */ jsxs(
|
|
4851
|
+
ModalScaffold,
|
|
4852
|
+
{
|
|
4853
|
+
open,
|
|
4854
|
+
onOpenChange,
|
|
4855
|
+
title: `${productName} Import Settings`,
|
|
4856
|
+
description: `Import documents from ${productName} into a workspace so the ARBI agent can search them. This is read-only \u2014 ARBI imports a copy and never modifies or deletes anything in your ${productName}.`,
|
|
4857
|
+
showDescription: true,
|
|
4858
|
+
className: "w-[92vw] sm:max-w-lg",
|
|
4859
|
+
children: [
|
|
4860
|
+
/* @__PURE__ */ jsxs(SyncDialogBody, { children: [
|
|
4861
|
+
!lockedWorkspaceExtId && /* @__PURE__ */ jsx(SyncField, { label: "Target workspace", htmlFor: "drive-sync-workspace", children: /* @__PURE__ */ jsx(
|
|
4862
|
+
SyncSelect,
|
|
4863
|
+
{
|
|
4864
|
+
id: "drive-sync-workspace",
|
|
4865
|
+
value: workspaceExtId,
|
|
4866
|
+
onValueChange: setWorkspaceExtId,
|
|
4867
|
+
placeholder: "Select a workspace",
|
|
4868
|
+
options: memberWorkspaces.map((w) => ({ value: w.external_id, label: w.name }))
|
|
4869
|
+
}
|
|
4870
|
+
) }),
|
|
4871
|
+
/* @__PURE__ */ jsx(
|
|
4872
|
+
SyncField,
|
|
4873
|
+
{
|
|
4874
|
+
label: `Folders to import${selectedFolders.length > 0 ? ` (${selectedFolders.length})` : ""}`,
|
|
4875
|
+
hint: "Select at least one folder. Importing a folder includes everything inside it.",
|
|
4876
|
+
actions: orderedFolders.length > 0 && /* @__PURE__ */ jsxs(SyncLinkRow, { children: [
|
|
4877
|
+
/* @__PURE__ */ jsx(
|
|
4878
|
+
SyncLinkButton,
|
|
4879
|
+
{
|
|
4880
|
+
onClick: () => setExpandAllNonce((n) => n + 1),
|
|
4881
|
+
testId: "drive-folders-expand-all",
|
|
4882
|
+
children: "Expand all"
|
|
4883
|
+
}
|
|
4884
|
+
),
|
|
4885
|
+
/* @__PURE__ */ jsx(
|
|
4886
|
+
SyncLinkButton,
|
|
4887
|
+
{
|
|
4888
|
+
onClick: () => setCollapseAllNonce((n) => n + 1),
|
|
4889
|
+
testId: "drive-folders-collapse-all",
|
|
4890
|
+
children: "Collapse all"
|
|
4891
|
+
}
|
|
4892
|
+
)
|
|
4893
|
+
] }),
|
|
4894
|
+
children: foldersLoading ? /* @__PURE__ */ jsx(SyncLoading, { children: "Loading folders\u2026" }) : needsReconnect ? /* @__PURE__ */ jsx(
|
|
4895
|
+
SyncReconnectNotice,
|
|
4896
|
+
{
|
|
4897
|
+
...reconnectButtonProps,
|
|
4898
|
+
message: `Reconnect ${catalog.display_name} to enable ${productName} \u2014 your account needs to grant file access.`
|
|
4899
|
+
}
|
|
4900
|
+
) : foldersError ? /* @__PURE__ */ jsx(
|
|
4901
|
+
SyncReconnectNotice,
|
|
4902
|
+
{
|
|
4903
|
+
...reconnectButtonProps,
|
|
4904
|
+
message: `Couldn\u2019t load folders from ${productName}. Reconnect the account and try again.`
|
|
4905
|
+
}
|
|
4906
|
+
) : orderedFolders.length === 0 ? /* @__PURE__ */ jsx(SyncNote, { children: "No folders found." }) : /* @__PURE__ */ jsx(SyncTreeFrame, { children: /* @__PURE__ */ jsx("div", { className: "space-y-0.5", "data-testid": "drive-folder-tree", children: orderedFolders.map((f) => /* @__PURE__ */ jsx(
|
|
4907
|
+
DriveFolderNode,
|
|
4908
|
+
{
|
|
4909
|
+
vendorKey: catalog.vendor_key,
|
|
4910
|
+
folder: f,
|
|
4911
|
+
depth: 0,
|
|
4912
|
+
selected: selectedFolders,
|
|
4913
|
+
onToggle: toggleFolder,
|
|
4914
|
+
enabled: treeEnabled,
|
|
4915
|
+
ancestorSelected: false,
|
|
4916
|
+
expandAllNonce,
|
|
4917
|
+
collapseAllNonce
|
|
4918
|
+
},
|
|
4919
|
+
f.id
|
|
4920
|
+
)) }) })
|
|
4921
|
+
}
|
|
4922
|
+
),
|
|
4923
|
+
/* @__PURE__ */ jsxs(SyncOptions, { children: [
|
|
4924
|
+
/* @__PURE__ */ jsx(
|
|
4925
|
+
SyncOptionToggle,
|
|
4926
|
+
{
|
|
4927
|
+
checked: skipDuplicates,
|
|
4928
|
+
onCheckedChange: setSkipDuplicates,
|
|
4929
|
+
title: "Skip duplicates",
|
|
4930
|
+
description: "Skip files identical to ones already in the workspace."
|
|
4931
|
+
}
|
|
4932
|
+
),
|
|
4933
|
+
/* @__PURE__ */ jsx(
|
|
4934
|
+
SyncOptionToggle,
|
|
4935
|
+
{
|
|
4936
|
+
checked: autoRename,
|
|
4937
|
+
onCheckedChange: setAutoRename,
|
|
4938
|
+
title: "Auto-rename",
|
|
4939
|
+
description: "Generate a descriptive title with AI instead of using the filename."
|
|
4940
|
+
}
|
|
4941
|
+
),
|
|
4942
|
+
/* @__PURE__ */ jsx(
|
|
4943
|
+
SyncOptionToggle,
|
|
4944
|
+
{
|
|
4945
|
+
checked: shared,
|
|
4946
|
+
onCheckedChange: setShared,
|
|
4947
|
+
title: "Share with the workspace",
|
|
4948
|
+
description: shared ? "Imported documents are visible to everyone in the workspace." : "Imported documents stay private to you."
|
|
4949
|
+
}
|
|
4950
|
+
),
|
|
4951
|
+
/* @__PURE__ */ jsx(
|
|
4952
|
+
SyncOptionToggle,
|
|
4953
|
+
{
|
|
4954
|
+
checked: autoSync,
|
|
4955
|
+
onCheckedChange: setAutoSync,
|
|
4956
|
+
title: "Sync automatically",
|
|
4957
|
+
description: "Check for new files when you sign in, instead of only when you click Sync now. Requires you to be signed in \u2014 nothing syncs while you are away.",
|
|
4958
|
+
testId: "drive-sync-auto-sync"
|
|
4959
|
+
}
|
|
4960
|
+
)
|
|
4961
|
+
] })
|
|
4962
|
+
] }),
|
|
4963
|
+
/* @__PURE__ */ jsx(
|
|
4964
|
+
SyncDialogFooter,
|
|
4965
|
+
{
|
|
4966
|
+
onCancel: () => onOpenChange(false),
|
|
4967
|
+
onSave: handleEnableSubmit,
|
|
4968
|
+
saveDisabled: !workspaceExtId || selectedFolders.length === 0,
|
|
4969
|
+
isSaving: enableSync.isPending,
|
|
4970
|
+
cancelButton: { testId: "drive-sync-cancel" },
|
|
4971
|
+
saveButton: { testId: "drive-sync-save" }
|
|
4972
|
+
}
|
|
4973
|
+
)
|
|
4974
|
+
]
|
|
4975
|
+
}
|
|
4976
|
+
);
|
|
4977
|
+
}
|
|
3724
4978
|
function useConnectedDocxNotifications(onOpen) {
|
|
3725
4979
|
const arbi = useArbi();
|
|
3726
4980
|
const { status, user, apiUrl } = useConnection();
|
|
@@ -9267,6 +10521,6 @@ function ConnectedAgentChatPanel({
|
|
|
9267
10521
|
] });
|
|
9268
10522
|
}
|
|
9269
10523
|
|
|
9270
|
-
export { ArbiAppProvider, ConnectedAccountSettings, ConnectedAgentChatPanel, ConnectedAgentCreator, ConnectedCalendar, ConnectedDangerZone, ConnectedIdentityVerification, ConnectedLogoutDialog, ConnectedMailAccounts, ConnectedMailComposer, ConnectedMailInviteCard, ConnectedMailMessage, ConnectedMailSettings, ConnectedMailSetup, ConnectedMailbox, ConnectedNotificationCenter, ConnectedNotificationPreferences, ConnectedPasswordChangeDialog, ConnectedPremiumModels, ConnectedPrivacySettings, ConnectedProfileCard, ConnectedPublicBooking, ConnectedRequireVerified, ConnectedSecuritySection, ConnectedSessionsRow, ConnectedSettingsPage, ConnectedSkillUpload, ConnectedSkillsLibrary, ConnectedTagTable, ConnectedTaskAccessRequest, ConnectedTaskActivityDialog, ConnectedThreadFollow, ConnectedUpcomingEvents, ConnectedWorkflowHistory, ConnectedWorkflowRunner, ConnectedWorkspaceActivity, ConnectedWorkspaceNotificationMenu, DEFAULT_CONNECTED_SKILL_UPLOAD_LABELS, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, DEFAULT_SETTINGS_SECTIONS, NotificationCenter, NotificationEvent, SETTINGS_SECTION_IDS, SessionStatusIcon, StreamedArtifact, WorkflowRunThread, accountSettingsSection, bookingCancelLink, buildNotificationCenterItems, chatSettingsSection, countNotificationTypes, defaultUnmetPasswordRequirement, filterNotificationCenterItems, mailSettingsSection, openMeetingLink, privacySettingsSection, renderSessionStatusIcon, requestCalendarComposer, requestCalendarEvent, resolveMailbox, useCalendarViewStore, useConnectedDocxNotifications, useConnectedShellWorkspaces, useConnectedWorkNotifications, workflowRunView };
|
|
10524
|
+
export { ArbiAppProvider, BACKFILL_OPTIONS, ConnectedAccountSettings, ConnectedAgentChatPanel, ConnectedAgentCreator, ConnectedAppsSettings, ConnectedCalendar, ConnectedDangerZone, ConnectedDriveSyncDialog, ConnectedIdentityVerification, ConnectedLogoutDialog, ConnectedMailAccounts, ConnectedMailComposer, ConnectedMailInviteCard, ConnectedMailMessage, ConnectedMailSettings, ConnectedMailSetup, ConnectedMailbox, ConnectedMailboxSyncDialog, ConnectedNotificationCenter, ConnectedNotificationPreferences, ConnectedPasswordChangeDialog, ConnectedPremiumModels, ConnectedPrivacySettings, ConnectedProfileCard, ConnectedPublicBooking, ConnectedRequireVerified, ConnectedSecuritySection, ConnectedSessionsRow, ConnectedSettingsPage, ConnectedSkillUpload, ConnectedSkillsLibrary, ConnectedTagTable, ConnectedTaskAccessRequest, ConnectedTaskActivityDialog, ConnectedThreadFollow, ConnectedUpcomingEvents, ConnectedWorkflowHistory, ConnectedWorkflowRunner, ConnectedWorkspaceActivity, ConnectedWorkspaceNotificationMenu, ConnectedWorkspaceSettings, DEFAULT_CONNECTED_SKILL_UPLOAD_LABELS, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, DEFAULT_SETTINGS_SECTIONS, NotificationCenter, NotificationEvent, SETTINGS_SECTION_IDS, SessionStatusIcon, StreamedArtifact, WorkflowRunThread, accountSettingsSection, bookingCancelLink, buildNotificationCenterItems, chatSettingsSection, connectedAppsSettingsSection, countNotificationTypes, defaultUnmetPasswordRequirement, filterNotificationCenterItems, formatLastSync, mailSettingsSection, openMeetingLink, privacySettingsSection, renderSessionStatusIcon, requestCalendarComposer, requestCalendarEvent, resolveMailbox, useCalendarViewStore, useConnectedDocxNotifications, useConnectedShellWorkspaces, useConnectedWorkNotifications, useConnectedWorkspaceSettings, windowLabel, workflowRunView };
|
|
9271
10525
|
//# sourceMappingURL=index.js.map
|
|
9272
10526
|
//# sourceMappingURL=index.js.map
|