@arbidocs/blocks 0.4.152 → 0.4.154
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/{ConnectedNativeDocxComparison-OFPIXNJB.js → ConnectedNativeDocxComparison-OLWRQSRS.js} +11 -11
- package/dist/{ConnectedNativeDocxComparison-OFPIXNJB.js.map → ConnectedNativeDocxComparison-OLWRQSRS.js.map} +1 -1
- package/dist/{ConnectedNativeDocxComparison-Y5BNLNH6.cjs → ConnectedNativeDocxComparison-YORMOPPN.cjs} +12 -12
- package/dist/{ConnectedNativeDocxComparison-Y5BNLNH6.cjs.map → ConnectedNativeDocxComparison-YORMOPPN.cjs.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-LRYU5HPA.js → ConnectedNativeDocxEditor-34EBIIFS.js} +10 -10
- package/dist/{ConnectedNativeDocxEditor-LRYU5HPA.js.map → ConnectedNativeDocxEditor-34EBIIFS.js.map} +1 -1
- package/dist/{ConnectedNativeDocxEditor-HTEW5JAH.cjs → ConnectedNativeDocxEditor-EHTWGGX3.cjs} +12 -12
- package/dist/{ConnectedNativeDocxEditor-HTEW5JAH.cjs.map → ConnectedNativeDocxEditor-EHTWGGX3.cjs.map} +1 -1
- package/dist/{ConnectedStreamedWordArtifact-QW74LKHN.cjs → ConnectedStreamedWordArtifact-5DK6QGYN.cjs} +12 -12
- package/dist/ConnectedStreamedWordArtifact-5DK6QGYN.cjs.map +1 -0
- package/dist/{ConnectedStreamedWordArtifact-QAUVUCSX.js → ConnectedStreamedWordArtifact-GLIDLSAS.js} +11 -11
- package/dist/{ConnectedStreamedWordArtifact-QAUVUCSX.js.map → ConnectedStreamedWordArtifact-GLIDLSAS.js.map} +1 -1
- package/dist/WorkspaceTableView-5OWX53R5.js +376 -0
- package/dist/WorkspaceTableView-5OWX53R5.js.map +1 -0
- package/dist/WorkspaceTableView-ZFMAYHUD.cjs +378 -0
- package/dist/WorkspaceTableView-ZFMAYHUD.cjs.map +1 -0
- package/dist/agents/index.cjs +282 -282
- package/dist/agents/index.js +7 -7
- package/dist/{chunk-RQ2Y7USX.cjs → chunk-2VHYOTWW.cjs} +3 -3
- package/dist/chunk-2VHYOTWW.cjs.map +1 -0
- package/dist/{chunk-DTROMMDX.cjs → chunk-3VULDTNL.cjs} +4 -4
- package/dist/{chunk-DTROMMDX.cjs.map → chunk-3VULDTNL.cjs.map} +1 -1
- package/dist/{chunk-UTTTJSQU.cjs → chunk-4RPBUMHB.cjs} +4 -4
- package/dist/{chunk-UTTTJSQU.cjs.map → chunk-4RPBUMHB.cjs.map} +1 -1
- package/dist/chunk-53RCZPMR.cjs +496 -0
- package/dist/chunk-53RCZPMR.cjs.map +1 -0
- package/dist/chunk-5TDGVOR5.js +142 -0
- package/dist/chunk-5TDGVOR5.js.map +1 -0
- package/dist/{chunk-CU2O32Z4.cjs → chunk-6QAAIDQQ.cjs} +62 -99
- package/dist/chunk-6QAAIDQQ.cjs.map +1 -0
- package/dist/chunk-7HHYMDPE.js +431 -0
- package/dist/chunk-7HHYMDPE.js.map +1 -0
- package/dist/{chunk-SMN32BQ3.cjs → chunk-7NL6WJER.cjs} +3 -160
- package/dist/chunk-7NL6WJER.cjs.map +1 -0
- package/dist/{chunk-T74Q3MCZ.cjs → chunk-BDA3RHYD.cjs} +4 -4
- package/dist/{chunk-T74Q3MCZ.cjs.map → chunk-BDA3RHYD.cjs.map} +1 -1
- package/dist/{chunk-IXWJGOM2.js → chunk-BQ77KSXU.js} +3 -3
- package/dist/{chunk-IXWJGOM2.js.map → chunk-BQ77KSXU.js.map} +1 -1
- package/dist/chunk-BTF4AZMG.js +148 -0
- package/dist/chunk-BTF4AZMG.js.map +1 -0
- package/dist/{chunk-HALD6ZB5.cjs → chunk-C3SMTA3C.cjs} +4 -4
- package/dist/{chunk-HALD6ZB5.cjs.map → chunk-C3SMTA3C.cjs.map} +1 -1
- package/dist/{chunk-GAYMJWTC.cjs → chunk-CB4TIDEX.cjs} +6 -6
- package/dist/{chunk-GAYMJWTC.cjs.map → chunk-CB4TIDEX.cjs.map} +1 -1
- package/dist/{chunk-KPZZ5FHE.cjs → chunk-CNHUJRQ4.cjs} +10 -6
- package/dist/chunk-CNHUJRQ4.cjs.map +1 -0
- package/dist/{chunk-Q4BY2CQQ.cjs → chunk-CQCNU5KT.cjs} +28 -28
- package/dist/{chunk-Q4BY2CQQ.cjs.map → chunk-CQCNU5KT.cjs.map} +1 -1
- package/dist/{chunk-GRGS5M6O.cjs → chunk-CROGFB46.cjs} +160 -3
- package/dist/chunk-CROGFB46.cjs.map +1 -0
- package/dist/{chunk-QN47Q4N7.js → chunk-CU6LDQ57.js} +3 -3
- package/dist/{chunk-QN47Q4N7.js.map → chunk-CU6LDQ57.js.map} +1 -1
- package/dist/{chunk-EF4ZLKRM.js → chunk-DEPF5LQI.js} +3 -3
- package/dist/{chunk-EF4ZLKRM.js.map → chunk-DEPF5LQI.js.map} +1 -1
- package/dist/{chunk-JAANWQGB.js → chunk-ETZ5A3GU.js} +3 -3
- package/dist/{chunk-JAANWQGB.js.map → chunk-ETZ5A3GU.js.map} +1 -1
- package/dist/{chunk-TBEVGWY3.js → chunk-F57LNUSZ.js} +10 -6
- package/dist/chunk-F57LNUSZ.js.map +1 -0
- package/dist/{chunk-GFNELPDP.cjs → chunk-FM3IRQJW.cjs} +10 -5
- package/dist/chunk-FM3IRQJW.cjs.map +1 -0
- package/dist/chunk-FPHTSNOE.js +465 -0
- package/dist/chunk-FPHTSNOE.js.map +1 -0
- package/dist/{chunk-OVR3XMYL.js → chunk-FYZXDZM7.js} +3 -3
- package/dist/{chunk-OVR3XMYL.js.map → chunk-FYZXDZM7.js.map} +1 -1
- package/dist/{chunk-2FLWPM3B.cjs → chunk-GC2FSPSQ.cjs} +7 -7
- package/dist/{chunk-2FLWPM3B.cjs.map → chunk-GC2FSPSQ.cjs.map} +1 -1
- package/dist/{chunk-DB2OXRQC.js → chunk-GO3BN76C.js} +7 -7
- package/dist/{chunk-DB2OXRQC.js.map → chunk-GO3BN76C.js.map} +1 -1
- package/dist/{chunk-XZIYRKLW.cjs → chunk-H32DV7XS.cjs} +5 -139
- package/dist/chunk-H32DV7XS.cjs.map +1 -0
- package/dist/{chunk-4236BRZK.js → chunk-HP2C4MD3.js} +29 -3
- package/dist/chunk-HP2C4MD3.js.map +1 -0
- package/dist/{chunk-ZP6Q3KXU.cjs → chunk-HUATKA3M.cjs} +4 -4
- package/dist/{chunk-ZP6Q3KXU.cjs.map → chunk-HUATKA3M.cjs.map} +1 -1
- package/dist/chunk-ISHFVKVU.js +304 -0
- package/dist/chunk-ISHFVKVU.js.map +1 -0
- package/dist/chunk-JUUOJP7I.cjs +164 -0
- package/dist/chunk-JUUOJP7I.cjs.map +1 -0
- package/dist/{chunk-4KMLM3GY.cjs → chunk-KBO75NLM.cjs} +7 -7
- package/dist/{chunk-4KMLM3GY.cjs.map → chunk-KBO75NLM.cjs.map} +1 -1
- package/dist/{chunk-Z4NQ3TED.js → chunk-KCSIX7CY.js} +3 -3
- package/dist/{chunk-Z4NQ3TED.js.map → chunk-KCSIX7CY.js.map} +1 -1
- package/dist/{chunk-DN2KI4BU.js → chunk-KDLX5AA7.js} +3 -3
- package/dist/{chunk-DN2KI4BU.js.map → chunk-KDLX5AA7.js.map} +1 -1
- package/dist/{chunk-WFA2GVZJ.js → chunk-MF5KQ4PS.js} +3 -3
- package/dist/{chunk-WFA2GVZJ.js.map → chunk-MF5KQ4PS.js.map} +1 -1
- package/dist/{chunk-YXNNNP57.js → chunk-MNG7N6M2.js} +4 -4
- package/dist/{chunk-YXNNNP57.js.map → chunk-MNG7N6M2.js.map} +1 -1
- package/dist/chunk-MSFQDELO.cjs +482 -0
- package/dist/chunk-MSFQDELO.cjs.map +1 -0
- package/dist/{chunk-KSHKTOY2.js → chunk-NUSBINUM.js} +3 -3
- package/dist/chunk-NUSBINUM.js.map +1 -0
- package/dist/{chunk-EYKISBDO.cjs → chunk-OALEDG67.cjs} +5 -5
- package/dist/{chunk-EYKISBDO.cjs.map → chunk-OALEDG67.cjs.map} +1 -1
- package/dist/{chunk-COCGRJLA.cjs → chunk-OFV3PRF2.cjs} +7 -7
- package/dist/{chunk-COCGRJLA.cjs.map → chunk-OFV3PRF2.cjs.map} +1 -1
- package/dist/chunk-OOU4QLRK.cjs +319 -0
- package/dist/chunk-OOU4QLRK.cjs.map +1 -0
- package/dist/chunk-OU3RGQFX.cjs +136 -0
- package/dist/chunk-OU3RGQFX.cjs.map +1 -0
- package/dist/{chunk-3PCBYOIZ.js → chunk-P6RIBIVN.js} +38 -7
- package/dist/chunk-P6RIBIVN.js.map +1 -0
- package/dist/{chunk-LXTOOUEN.cjs → chunk-Q7CQYYZW.cjs} +5 -5
- package/dist/{chunk-LXTOOUEN.cjs.map → chunk-Q7CQYYZW.cjs.map} +1 -1
- package/dist/{chunk-CROTH2BS.js → chunk-QKR5LWDO.js} +9 -40
- package/dist/{chunk-CROTH2BS.js.map → chunk-QKR5LWDO.js.map} +1 -1
- package/dist/{chunk-HUJF2XM2.js → chunk-RE7NULEY.js} +3 -3
- package/dist/{chunk-HUJF2XM2.js.map → chunk-RE7NULEY.js.map} +1 -1
- package/dist/chunk-REH7PX3N.cjs +145 -0
- package/dist/chunk-REH7PX3N.cjs.map +1 -0
- package/dist/chunk-RQKWYKZY.js +127 -0
- package/dist/chunk-RQKWYKZY.js.map +1 -0
- package/dist/{chunk-U6JQ4KMX.cjs → chunk-SN2GZ4ZM.cjs} +29 -2
- package/dist/chunk-SN2GZ4ZM.cjs.map +1 -0
- package/dist/{chunk-R6VCPDPF.js → chunk-SZSJGZSO.js} +156 -6
- package/dist/chunk-SZSJGZSO.js.map +1 -0
- package/dist/{chunk-US3S4DCB.js → chunk-TF7HN5EU.js} +10 -5
- package/dist/chunk-TF7HN5EU.js.map +1 -0
- package/dist/{chunk-YKQ2DPIP.js → chunk-VF5EUAIV.js} +3 -3
- package/dist/{chunk-YKQ2DPIP.js.map → chunk-VF5EUAIV.js.map} +1 -1
- package/dist/{chunk-KMZWKSKO.cjs → chunk-VZPFYZZU.cjs} +4 -4
- package/dist/{chunk-KMZWKSKO.cjs.map → chunk-VZPFYZZU.cjs.map} +1 -1
- package/dist/{chunk-ZLEYLCE4.js → chunk-WK6FVIF7.js} +6 -156
- package/dist/chunk-WK6FVIF7.js.map +1 -0
- package/dist/{chunk-COA3S3CZ.js → chunk-XI37A7HH.js} +4 -4
- package/dist/{chunk-COA3S3CZ.js.map → chunk-XI37A7HH.js.map} +1 -1
- package/dist/{chunk-LGBAZD37.js → chunk-XRL4R2TT.js} +7 -139
- package/dist/chunk-XRL4R2TT.js.map +1 -0
- package/dist/{chunk-4JNKXOFZ.cjs → chunk-YBJ4QGNH.cjs} +11 -11
- package/dist/{chunk-4JNKXOFZ.cjs.map → chunk-YBJ4QGNH.cjs.map} +1 -1
- package/dist/{chunk-GFOEWPAP.cjs → chunk-YF3QUHKN.cjs} +49 -12
- package/dist/chunk-YF3QUHKN.cjs.map +1 -0
- package/dist/{chunk-H4D7WKDY.js → chunk-YNMO3DSR.js} +3 -3
- package/dist/{chunk-H4D7WKDY.js.map → chunk-YNMO3DSR.js.map} +1 -1
- package/dist/citations/index.cjs +10 -10
- package/dist/citations/index.js +2 -2
- package/dist/collaboration/index.cjs +77 -77
- package/dist/collaboration/index.js +2 -2
- package/dist/connect/docx.cjs +14 -14
- package/dist/connect/docx.js +10 -10
- package/dist/connect/index.cjs +1577 -962
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +3 -0
- package/dist/connect/index.js +1014 -450
- package/dist/connect/index.js.map +1 -1
- package/dist/connect/viewer.cjs +66 -66
- package/dist/connect/viewer.js +10 -10
- package/dist/connection/ConnectionProvider.d.ts +7 -0
- package/dist/connection/projects/ConnectedProjectsPanel.d.ts +34 -0
- package/dist/connection/projects/index.d.ts +1 -0
- package/dist/connection/workspace-dashboard/ConnectedWorkspaceDashboard.d.ts +37 -0
- package/dist/connection/workspace-dashboard/dashboard-rows.d.ts +42 -0
- package/dist/connection/workspace-dashboard/index.d.ts +1 -0
- package/dist/connection/workspace-list/ConnectedWorkspaceList.d.ts +37 -0
- package/dist/connection/workspace-list/WorkspaceCardsView.d.ts +15 -0
- package/dist/connection/workspace-list/WorkspaceFilterMenu.d.ts +4 -0
- package/dist/connection/workspace-list/WorkspaceTableView.d.ts +13 -0
- package/dist/connection/workspace-list/index.d.ts +5 -0
- package/dist/connection/workspace-list/projectBilling.d.ts +21 -0
- package/dist/connection/workspace-list/useConnectedWorkspaceList.d.ts +251 -0
- package/dist/connection/workspace-list/workspaceTable.d.ts +58 -0
- package/dist/connection/workspace-settings/ConnectedWorkspaceMembers.d.ts +26 -0
- package/dist/connection/workspace-settings/ConnectedWorkspaceSettings.d.ts +7 -9
- package/dist/connection/workspace-settings/index.d.ts +2 -1
- package/dist/connection/workspace-settings/useConnectedWorkspaceSettings.d.ts +0 -1
- package/dist/facts/index.cjs +3 -3
- package/dist/facts/index.js +2 -2
- package/dist/files/index.cjs +169 -169
- package/dist/files/index.js +3 -3
- package/dist/home/index.cjs +119 -459
- package/dist/home/index.cjs.map +1 -1
- package/dist/home/index.js +13 -419
- package/dist/home/index.js.map +1 -1
- package/dist/index.cjs +510 -510
- package/dist/index.js +18 -18
- package/dist/provider/BlocksProvider.d.ts +9 -1
- package/dist/retrieval/index.cjs +4 -4
- package/dist/retrieval/index.js +2 -2
- package/dist/settings/index.cjs +169 -165
- package/dist/settings/index.d.ts +1 -0
- package/dist/settings/index.js +2 -2
- package/dist/settings/tri-state-filters.d.ts +13 -0
- package/dist/shell/index.cjs +44 -44
- package/dist/shell/index.js +3 -3
- package/dist/site/index.cjs +5 -5
- package/dist/site/index.js +1 -1
- package/dist/studio/index.cjs +14 -14
- package/dist/studio/index.js +6 -6
- package/dist/workflow-canvas/index.cjs +27 -27
- package/dist/workflow-canvas/index.js +9 -9
- package/dist/workspaces/index.cjs +110 -369
- package/dist/workspaces/index.cjs.map +1 -1
- package/dist/workspaces/index.d.ts +2 -0
- package/dist/workspaces/index.js +12 -350
- package/dist/workspaces/index.js.map +1 -1
- package/dist/workspaces/workspace-groups.d.ts +90 -0
- package/dist/workspaces/workspace-roles.d.ts +11 -0
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +5 -5
- package/dist/ConnectedStreamedWordArtifact-QW74LKHN.cjs.map +0 -1
- package/dist/chunk-3PCBYOIZ.js.map +0 -1
- package/dist/chunk-4236BRZK.js.map +0 -1
- package/dist/chunk-CU2O32Z4.cjs.map +0 -1
- package/dist/chunk-EV7W64B6.js +0 -134
- package/dist/chunk-EV7W64B6.js.map +0 -1
- package/dist/chunk-GFNELPDP.cjs.map +0 -1
- package/dist/chunk-GFOEWPAP.cjs.map +0 -1
- package/dist/chunk-GRGS5M6O.cjs.map +0 -1
- package/dist/chunk-KPZZ5FHE.cjs.map +0 -1
- package/dist/chunk-KSHKTOY2.js.map +0 -1
- package/dist/chunk-LGBAZD37.js.map +0 -1
- package/dist/chunk-R6VCPDPF.js.map +0 -1
- package/dist/chunk-RQ2Y7USX.cjs.map +0 -1
- package/dist/chunk-RXK3XP62.cjs +0 -144
- package/dist/chunk-RXK3XP62.cjs.map +0 -1
- package/dist/chunk-SMN32BQ3.cjs.map +0 -1
- package/dist/chunk-TBEVGWY3.js.map +0 -1
- package/dist/chunk-U6JQ4KMX.cjs.map +0 -1
- package/dist/chunk-US3S4DCB.js.map +0 -1
- package/dist/chunk-XZIYRKLW.cjs.map +0 -1
- package/dist/chunk-ZLEYLCE4.js.map +0 -1
package/dist/connect/index.js
CHANGED
|
@@ -1,46 +1,54 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
2
|
+
import { useBillingSupport, formatMoney, isProProject, useSelfExtId, addonCharge, formatPeriodEnd, quoteParts, taxDetail, money2, ANNUAL_PREMIUM_AI_NOTE, totalWithTaxWord, planBadgeView, DEFAULT_SPEND_CAP_PENCE, findProPrices, packPrice, calcSavingsPercent, parseBudgetPounds, getQuotaItems, PRO_PACKS, planNameForPacks, proTierName, STORAGE_BLOCK_GB, ADDON_BLOCK_AI_GBP, formatResetDate, quoteError, POSTCODE_COUNTRIES, addonPrice, checkoutBlockPriceText, quoteTotalLine, apiErrorDetail, checkoutItemsLabel, projectGroupBilling, SUGGESTED_DAILY_CAP_PER_USER, FREE_STORAGE_MB, FREE_AI_GBP, PRO_AI_GBP, PRO_STORAGE_GB, plusVat, planPreviewLines, PAY_TODAY_UNPRICED, aiUsageResetTimestamp, TAX_LOCATION_INVALID, FREE_COLLABORATORS, MAX_CHECKOUT_BLOCKS, reduceBounds, splitBlocks, autoRoom, isAddonBudgetZero, nextRemovedBlockSize, stepLabel, addStepCaption, blocksLabel, MIN_AUTO_TOPUP_THRESHOLD_GBP, USAGE_CAP_LABEL, CAP_REACHED_MESSAGE, USAGE_CAP_HELP, PLAN_CHOICE_PACKS, nextPeriodBody, addonSettingsBody, budgetSavedMessage } from '../chunk-7HHYMDPE.js';
|
|
3
|
+
export { BillingSupportProvider, CAP_REACHED_MESSAGE, ZERO_BUDGET_MESSAGE, aiUsageResetTimestamp, formatMoney, formatResetDate, getQuotaItems, isAddonBudgetZero, isProProject, planBadgeView, planName, projectGroupBilling, useBillingSupport, useRewardBalance } from '../chunk-7HHYMDPE.js';
|
|
4
|
+
import { getRoleBadgeClass, formatRole, getRoleDescription, PageLoading, WorkspacePageFrame, WorkspaceIdentityPanel, WorkspaceProjectSlot, WorkspaceAudienceLine, CommonWorkspaceToggle, ExpandableSection, LeaveFooter, WorkspaceList, WorkspaceGroup, WorkspaceCard } from '../chunk-FPHTSNOE.js';
|
|
5
|
+
import { isAgentAccount, workspaceConversationCount, workspaceDocumentCount, isListedWorkspace, WORKSPACE_CATEGORY_FILTERS, projectFilterId, workspaceFilterAttributes, groupWorkspacesByProject, byRecentUpdate } from '../chunk-BTF4AZMG.js';
|
|
6
|
+
import { HomeLoadError, HomeFrame, HomeMain, HomeCenteredScroll, HomeCenteredColumn, DashboardRoot, DashboardBand, DashboardColumns, RecentList, DashboardAction, FactsStrip, FactMark, CreateTile } from '../chunk-ISHFVKVU.js';
|
|
7
|
+
import { ProjectBandTitle, PlainBandTitle } from '../chunk-RQKWYKZY.js';
|
|
8
|
+
import '../chunk-5TDGVOR5.js';
|
|
9
|
+
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, InvoicesDialog, PlanDialogFrame, ProjectList, RenameDialog, SharedProjectsSection, SharedProjectRow, MoreInfo, MoreInfoList, ProjectDetailHeader, PlanBadge, ProjectDetailSection, PlanStack, PlanNotice, PlanPickerCard, PlanPickerHeader, PricingToggle, PromoCodeInput, PlanActionButton, applyTriStateFilters, PanelFrame, PanelAddButton, PanelFrameBody, PanelScroll, PanelActionsRow, ProjectRow, QuotaMeter, FilterChip, applyInvertedIndexFilter, buildInvertedIndex, serverConnectionView, ServerConnectionButton, ModelProviderLabel, SyncFolderRow, SyncFolderStatus, PlanTierOption, PlanActionRow, SubscriptionStatusView, DailyCapField, UsagePanel, UsageSummary, UsageQuotaHint, UsageToggle, UsageSection, UsageLineChart, UsageLegend, UsageProportionBar, UsageActionButton, PlanInfoPopover, PlanCardGrid, ReferralRewardSummary, CheckoutDialogFrame, ConnectionCard, ReferralRewardNote } from '../chunk-HP2C4MD3.js';
|
|
10
|
+
export { ConnectedAssistantDock, redlineStats, textToArtifact, toRedlineMarkdown, useConnectedAiTask, useConnectedChat, useSemanticSearch, useWorkspaceDocs } from '../chunk-KCSIX7CY.js';
|
|
11
|
+
import { useConnectedWorkspaceRole, ConnectedNativeDocxEditor } from '../chunk-GO3BN76C.js';
|
|
12
|
+
export { ConnectedWorkflowDocumentsField, ConnectedWorkflowLauncher, ConnectedWorkflowsTable, DEFAULT_CONNECTED_WORKFLOWS_TABLE_LABELS, NativeDocxSupportProvider, toWorkflowFieldDocument, useConnectedAgentOptions, useConnectedWorkflowScopeSource, useConnectedWorkspaceRole, useNativeDocxSupport } from '../chunk-GO3BN76C.js';
|
|
7
13
|
export { DocumentViewerSupportProvider, useDocumentViewerSupport } from '../chunk-EYJMMGXF.js';
|
|
8
14
|
import { FilterButton, FilesViewCenter, FilesFilterBar, ROW_MIN, rowHeightForLines, linesForRowHeight, RowDensityControl, FolderFilterButton, FolderPickerRow, FieldLabelsSelect } from '../chunk-JGOST4IL.js';
|
|
9
15
|
import '../chunk-RC6VTY2H.js';
|
|
10
|
-
import { useConnectedTags, useConnectedDocuments, useConnectedConversations } from '../chunk-
|
|
11
|
-
export { ConnectedWorkspaceDataProvider, useConnectedConversations, useConnectedDocuments, useConnectedTags } from '../chunk-
|
|
12
|
-
import { ConnectionProvider, useConnection, useConnectedWorkspace } from '../chunk-
|
|
13
|
-
export { ConnectionProvider, SESSION_EXPIRED_MESSAGE, isAuthenticated, useConnectedWorkspace, useConnection } from '../chunk-
|
|
16
|
+
import { useConnectedTags, useConnectedDocuments, useConnectedConversations } from '../chunk-KDLX5AA7.js';
|
|
17
|
+
export { ConnectedWorkspaceDataProvider, useConnectedConversations, useConnectedDocuments, useConnectedTags } from '../chunk-KDLX5AA7.js';
|
|
18
|
+
import { ConnectionProvider, useConnection, useConnectedWorkspace } from '../chunk-TF7HN5EU.js';
|
|
19
|
+
export { ConnectionProvider, SESSION_EXPIRED_MESSAGE, isAuthenticated, useConnectedWorkspace, useConnection } from '../chunk-TF7HN5EU.js';
|
|
14
20
|
import { SignDocumentDialog } from '../chunk-2YOVK524.js';
|
|
15
21
|
import '../chunk-MTSKK3BN.js';
|
|
16
22
|
import '../chunk-265GOG4W.js';
|
|
17
23
|
import { docIdsOf, toFactCitations, FactsToolbar, FactsFieldsButton, FactComposer, FactDateInput, FactSourcesRow, FactsLoading, FactsLoadError, FactsEmptyState, FactsCalendar, FactsGanttPane, FactsBulkBar, FactSourceGroup, EMPTY_FACT_DATE_FIELDS, withoutChunk, factDateSpanToFields, FactFieldRow, FactLabelsCell, enableFactTableColumnResize, citedVersionRef, withChunk, factDateFieldsToSpan, createFactColumns, FactRowActions, withoutDoc, withDoc, sourceDocCount, DEFAULT_FACT_COLUMN_LABELS } from '../chunk-WU34CHU5.js';
|
|
18
24
|
import { ViewToggle } from '../chunk-JJA6GQKH.js';
|
|
19
25
|
import { FactSourcesPanel, FactPassageItem } from '../chunk-HFZ45FD3.js';
|
|
20
|
-
import { WorkspaceActivityList, WorkspaceNotificationMenu, ThreadFollowMenuItem, ThreadFollowButton, TagTable, TagPicker, tagsPageNouns, entitiesPhrase, ExtractEntitiesDialog, GridRowNavigator, LoadingIndicator, EntityIdentityBar, IDENTITY_NAME_MAX_LENGTH, tagTableDocx, documentCount, tagTableLabels, TagDetail, tagDetailLabels, tagNoteLabel, tagKindDescription, glossaryEntries, glossaryDocx, glossaryMarkdown, glossaryFileName } from '../chunk-
|
|
26
|
+
import { WorkspaceActivityList, WorkspaceNotificationMenu, ThreadFollowMenuItem, ThreadFollowButton, TagTable, TagPicker, tagsPageNouns, entitiesPhrase, ExtractEntitiesDialog, GridRowNavigator, LoadingIndicator, EntityIdentityBar, IDENTITY_NAME_MAX_LENGTH, tagTableDocx, documentCount, tagTableLabels, TagDetail, tagDetailLabels, tagNoteLabel, tagKindDescription, glossaryEntries, glossaryDocx, glossaryMarkdown, glossaryFileName } from '../chunk-MNG7N6M2.js';
|
|
21
27
|
import { MemberAvatarStack } from '../chunk-XNOASBGW.js';
|
|
22
|
-
import { renderSearchSnippet, SearchGroupHeader, isMeaningMatch, extractHighlightTerms, passesRelevanceCutoff, groupSearchResults, SearchPillToggle, SearchPagination, SearchPageFrame, SearchPageHeader, ApplyLabelDialog, SearchPageBody, SearchToolbarRow, SearchBar, SearchControlsBar, RelevanceThreshold, SearchTotalsHeadline, ApplyLabelButton, getSearchMatchHint, SearchResultsMain, SearchResultsInner, SearchErrorBanner, SearchResultList, SearchGroupCard, SearchNoResults, SearchEmptyState } from '../chunk-G4IYES7G.js';
|
|
23
28
|
import { UsageMeter } from '../chunk-66TA5IBN.js';
|
|
29
|
+
import '../chunk-UJE32SST.js';
|
|
24
30
|
import '../chunk-NHZK64TQ.js';
|
|
25
|
-
import {
|
|
31
|
+
import { renderSearchSnippet, SearchGroupHeader, isMeaningMatch, extractHighlightTerms, passesRelevanceCutoff, groupSearchResults, SearchPillToggle, SearchPagination, SearchPageFrame, SearchPageHeader, ApplyLabelDialog, SearchPageBody, SearchToolbarRow, SearchBar, SearchControlsBar, RelevanceThreshold, SearchTotalsHeadline, ApplyLabelButton, getSearchMatchHint, SearchResultsMain, SearchResultsInner, SearchErrorBanner, SearchResultList, SearchGroupCard, SearchNoResults, SearchEmptyState } from '../chunk-G4IYES7G.js';
|
|
32
|
+
import { PlainMailBodyEditor, MemberNameCell, MemberMutedText, MemberRoleCell, MemberListLoading, MemberBulkActions, buildMailFolderTree, MailFolderTree, draftMailCompose, replyMailCompose, emptyMailCompose, MailGrid, MailMessageView, MailDocumentPicker, parseMailRecipients } from '../chunk-SZSJGZSO.js';
|
|
33
|
+
import '../chunk-NBV56SGU.js';
|
|
26
34
|
import '../chunk-SDOEHEJP.js';
|
|
27
35
|
import { WorkspaceIdentity, workspaceKindColor } from '../chunk-A3XPS2EU.js';
|
|
28
|
-
import '../chunk-SV65E4QW.js';
|
|
36
|
+
import { buildDeepLinkPath } from '../chunk-SV65E4QW.js';
|
|
29
37
|
import '../chunk-ZCOVDK2E.js';
|
|
30
38
|
import { isDefinitionsLabel, DOCX_MIME_TYPE, toDefinitionSource, definitionLabels } from '../chunk-DIB4JYUY.js';
|
|
31
|
-
import { SearchHit } from '../chunk-
|
|
39
|
+
import { SearchHit } from '../chunk-DEPF5LQI.js';
|
|
32
40
|
import { TimelineZoomControl } from '../chunk-4EZVCGRL.js';
|
|
33
41
|
import { decodeWhitespaceEntities } from '../chunk-AF6RDAJF.js';
|
|
34
|
-
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-
|
|
42
|
+
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, STATUS_LABELS, asTaskStatus, workflowToSkillMarkdown } from '../chunk-P6RIBIVN.js';
|
|
35
43
|
import { MultiSelect } from '../chunk-CQCC7LE7.js';
|
|
36
|
-
import { PersonPill } from '../chunk-
|
|
37
|
-
import '../chunk-
|
|
38
|
-
import { TriStateFilterMenu, DocumentPicker } from '../chunk-
|
|
44
|
+
import { PersonPill } from '../chunk-XI37A7HH.js';
|
|
45
|
+
import { SectionLabel } from '../chunk-BQ77KSXU.js';
|
|
46
|
+
import { TriStateFilterMenu, DocumentPicker } from '../chunk-NUSBINUM.js';
|
|
39
47
|
import '../chunk-P6GHJSLR.js';
|
|
40
48
|
import '../chunk-M4S75AEJ.js';
|
|
41
49
|
import '../chunk-5LXQPP2K.js';
|
|
42
50
|
import '../chunk-RLWIUUQ5.js';
|
|
43
|
-
import '../chunk-
|
|
51
|
+
import '../chunk-VF5EUAIV.js';
|
|
44
52
|
import { SelectionBar, SelectionBarAction } from '../chunk-NUNKSZKU.js';
|
|
45
53
|
import { FilterInput } from '../chunk-YU2KUMGE.js';
|
|
46
54
|
import { GridView } from '../chunk-N5YEF3LC.js';
|
|
@@ -57,21 +65,21 @@ import { splitDocRef, stepLevels, stepDocuments, stepKindOf, initialRunInputs, w
|
|
|
57
65
|
import '../chunk-TZGBRLPK.js';
|
|
58
66
|
import '../chunk-AUS3KBHJ.js';
|
|
59
67
|
import '../chunk-AA3PT6KR.js';
|
|
60
|
-
import '../chunk-SLSBJRWW.js';
|
|
68
|
+
import { useIsPhone } from '../chunk-SLSBJRWW.js';
|
|
61
69
|
import '../chunk-NPLYHR2E.js';
|
|
62
70
|
import '../chunk-7F6CBP3Z.js';
|
|
63
|
-
import { PassagePill, useCopyText } from '../chunk-
|
|
64
|
-
import { useBlocksEnvironment, useRequestedSettingsSection } from '../chunk-
|
|
71
|
+
import { PassagePill, useCopyText } from '../chunk-ETZ5A3GU.js';
|
|
72
|
+
import { useBlocksEnvironment, useRequestedSettingsSection, BlocksProvider } from '../chunk-F57LNUSZ.js';
|
|
65
73
|
import { ModalScaffold, ModalSection } from '../chunk-TX2ZICS7.js';
|
|
66
74
|
import { fmtDate, initials } from '../chunk-OXF2IFXG.js';
|
|
67
75
|
import '../chunk-VUNV25KB.js';
|
|
68
|
-
import { lazy, memo, useState, useEffect,
|
|
76
|
+
import { lazy, memo, useState, useEffect, useCallback, useMemo, useRef, Suspense, useSyncExternalStore, useLayoutEffect, useId } from 'react';
|
|
69
77
|
import { QueryClient, QueryClientProvider, useQueryClient, useQuery } from '@tanstack/react-query';
|
|
70
|
-
import { HtmlIcon, useArbiSessionState, 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, useCreateTag, useSetTagValues, useUpdateTagKindSchema, useFacts, useDeleteTag, useExtractEntities, 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,
|
|
78
|
+
import { HtmlIcon, useArbiSessionState, 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, useCreateTag, useSetTagValues, useUpdateTagKindSchema, useFacts, useDeleteTag, useExtractEntities, 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, useSetWorkspaceMemberRoles, toShellWorkspace, useEnableMailboxSync, useMailboxFolders, useEnableDriveSync, useDriveFolderChildren, connectorErrorStatus, useProjectInvoices, useProjects, useUpdateProjectFields, useUserUsageToday, formatGbp, useChargeWatch, useAddonQuote, STILL_WORKING, useProjectBillingPortal, useIsSlow, useProducts, useCreateProject, useDeleteProject, useRefreshProject, useCanCreateProjects, useDeleteWorkspaces, PROJECT_CREATION_DENIED_REASON, MAX_RETRIEVE_DOC_IDS, useSemanticSearch, useAssignDocTags, useArbiWebSocket, useWorkNotifications, describeServerNotification, 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, BOX_SEAT_REFUSED, BOX_SEAT_REFUSED_TITLE, documentActivityPhrase, isSignatureNotificationType, inputRequestTitle, WORK_NOTIFICATION_LABELS, documentDisplayName, getWorkspaceKind, formatRelativeTime, useCreateWork, useActOnStep, useConversationThreads, useUpdateTag, usePassageQuotes, useUpdateFact, useDeleteFact, useCreateFact, ProviderIcon, formatGbpPerMillionTokens, useDriveFolderDocCount, useChangeProjectPlan, useCancelProjectSubscription, usePreviewProjectPlanChange, useAddProjectAddonBlock, useProjectUsage, usePlanQuote, useCreateProjectCheckout, useInvalidateProjects, 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, useBookingPages, useDeleteBookingPage, SHAREPOINT_VENDORS, useUpdateProjectNextPeriodAddons, useUpdateProjectAddonSettings, useSyncCalendarAccount, useUpdateCalendarAccount, useDisconnectCalendarAccount, ACCOUNT_VENDOR, useCalDavProfiles, useConnectCalDavAccount, useSaveBookingPage, useCreateRoom } from '@arbidocs/react';
|
|
71
79
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
72
|
-
import { Badge, Button, Label, Input, cn, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, tagKindNouns, tagKindTitle, isImageDocument, getDocumentTitle, getEntityColor, IconToggle, VisibilityToggle, Switch, getEntityLabel, ProjectEntity, DialogFooter, EntityIcon, DocumentEntity, EntityPill, ShieldIcon, getTagTypeLabel, Popover, PopoverTrigger, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem,
|
|
80
|
+
import { Badge, Button, Label, Input, cn, Textarea, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, tagKindNouns, tagKindTitle, isImageDocument, getDocumentTitle, getEntityColor, IconToggle, VisibilityToggle, Switch, getEntityLabel, formatFriendlyDate, ProjectEntity, DialogFooter, EntityIcon, getDocIcon, Tooltip, TooltipTrigger, TooltipContent, DocumentEntity, EntityPill, ShieldIcon, getTagTypeLabel, Popover, PopoverTrigger, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, UserEntity, PopoverContent, Tabs, TabsList, TabsTrigger, TabsContent, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, VerifiedToggle, Progress } from '@arbidocs/react/ui';
|
|
73
81
|
import { useNotify, notify, sharedSearchSession, takePendingSearch } from '@arbidocs/react/shell';
|
|
74
|
-
import { Bell, Activity, Info, UserCheck, Trash2, Loader2, Upload, Link2, Search, Plus, ArrowLeft, ExternalLink, Tags, CheckCircle2, Milestone, Monitor, UserCircle, KeyRound, Radio, LogOut, Wifi, RotateCcw, Mail, User, HatGlasses, MessageSquare, PlugZap, FolderInput,
|
|
82
|
+
import { Bell, Activity, Info, UserCheck, Trash2, Loader2, Upload, Link2, Search, Plus, ArrowLeft, ExternalLink, Tags, CheckCircle2, Milestone, Monitor, UserCircle, KeyRound, Radio, LogOut, Wifi, RotateCcw, Mail, User, HatGlasses, MessageSquare, PlugZap, FolderInput, SquareStack, Table, FileText, MessagesSquare, Tag, Settings, Video, Printer, CalendarDays, Clock, MapPin, Globe, Sparkles, ArrowUpCircle, Building2, Contact, Scale, NotebookPen, Check, X, Pencil, BookA, ChevronDown, Users, Paperclip, Quote, Download, Send, Inbox, CalendarX, CalendarCheck, Minimize2, Maximize2, Minus, CalendarSearch, DoorOpen, RefreshCw, AlertTriangle } from 'lucide-react';
|
|
75
83
|
import { downloadBlob, useIsOnline, useOptionalDocumentTools, fetchDocumentPdf, DocumentToolsProvider } from '@arbidocs/react/document-tools';
|
|
76
84
|
import { useStreamedArtifact } from '@arbidocs/react/artifacts';
|
|
77
85
|
import { FLAT_TAG_KINDS, TAG_KINDS, refusalReason, getChildTags, tagUseCount, flattenTagTree, isFlatKind, isEntityTag, tagsForScope, filterDocumentTags, isLabelTag, getTagDescendantIds, getEligibleParentTags, canTagHaveParent } from '@arbidocs/sdk/browser';
|
|
@@ -672,13 +680,13 @@ function NotificationCenter({
|
|
|
672
680
|
var PAGE_SIZE = 100;
|
|
673
681
|
function localTime(timestamp) {
|
|
674
682
|
const date = new Date(timestamp);
|
|
675
|
-
const
|
|
683
|
+
const time2 = date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
676
684
|
const today = /* @__PURE__ */ new Date();
|
|
677
685
|
const yesterday = new Date(today);
|
|
678
686
|
yesterday.setDate(today.getDate() - 1);
|
|
679
|
-
if (date.toDateString() === today.toDateString()) return `Today, ${
|
|
680
|
-
if (date.toDateString() === yesterday.toDateString()) return `Yesterday, ${
|
|
681
|
-
return `${date.toLocaleDateString([], { month: "short", day: "numeric" })}, ${
|
|
687
|
+
if (date.toDateString() === today.toDateString()) return `Today, ${time2}`;
|
|
688
|
+
if (date.toDateString() === yesterday.toDateString()) return `Yesterday, ${time2}`;
|
|
689
|
+
return `${date.toLocaleDateString([], { month: "short", day: "numeric" })}, ${time2}`;
|
|
682
690
|
}
|
|
683
691
|
function DefaultUser({ user }) {
|
|
684
692
|
const arbi = useArbi();
|
|
@@ -6660,27 +6668,11 @@ function useConnectedWorkspaceSettings(workspaceId, { onLeft } = {}) {
|
|
|
6660
6668
|
}
|
|
6661
6669
|
return "cancelled";
|
|
6662
6670
|
}
|
|
6663
|
-
const
|
|
6664
|
-
if (!
|
|
6671
|
+
const quota = status === 402 || lower.includes("limit reached") || lower.includes("quota") || lower.includes("upgrade");
|
|
6672
|
+
if (!quota) notify14(detail, "error");
|
|
6665
6673
|
return "error";
|
|
6666
6674
|
}
|
|
6667
6675
|
};
|
|
6668
|
-
const removeMember = async (userExtId, email, name) => {
|
|
6669
|
-
if (!workspace || !isOwner) return;
|
|
6670
|
-
const ok = await confirm({
|
|
6671
|
-
message: `Remove ${name} (${email}) from the "${workspace.name}" ${getEntityLabel("WORKSPACE")}?
|
|
6672
|
-
|
|
6673
|
-
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()}.`,
|
|
6674
|
-
title: `Remove ${getEntityLabel("WORKSPACEUSER")}`
|
|
6675
|
-
});
|
|
6676
|
-
if (!ok) return;
|
|
6677
|
-
try {
|
|
6678
|
-
await remove.mutateAsync([userExtId]);
|
|
6679
|
-
notify14(`Successfully removed ${name} from workspace`, "success");
|
|
6680
|
-
} catch {
|
|
6681
|
-
notify14(`Failed to remove ${name} from workspace`, "error");
|
|
6682
|
-
}
|
|
6683
|
-
};
|
|
6684
6676
|
const leave = async () => {
|
|
6685
6677
|
if (!workspace || !userId || isOwner) return;
|
|
6686
6678
|
const name = workspace.name;
|
|
@@ -6708,19 +6700,246 @@ You will lose access to all content in this ${workspaceWord()}.`,
|
|
|
6708
6700
|
updateIdentity,
|
|
6709
6701
|
setPublic,
|
|
6710
6702
|
share,
|
|
6711
|
-
removeMember,
|
|
6712
6703
|
leave,
|
|
6713
6704
|
isSharing: add.isPending,
|
|
6714
6705
|
isRemoving: remove.isPending
|
|
6715
6706
|
};
|
|
6716
6707
|
}
|
|
6708
|
+
var memberName = (user) => user.family_name ? `${user.given_name} ${user.family_name}` : user.given_name;
|
|
6709
|
+
var ALL_ROLES = ["owner", "collaborator", "guest"].map((value) => ({ value, label: formatRole(value), badgeClass: getRoleBadgeClass(value) }));
|
|
6710
|
+
var BULK_ROLES = ALL_ROLES.filter((r) => r.value !== "owner");
|
|
6711
|
+
var ROLE_ORDER = { owner: 0, collaborator: 1, guest: 2 };
|
|
6712
|
+
function roleLock(targetId, selfId, isOwner) {
|
|
6713
|
+
if (!isOwner) return "Only owners can change roles";
|
|
6714
|
+
if (targetId === selfId) return "Your role can only be changed by another owner";
|
|
6715
|
+
return null;
|
|
6716
|
+
}
|
|
6717
|
+
var defaultRenderMember = (member) => {
|
|
6718
|
+
const name = memberName(member.user);
|
|
6719
|
+
return /* @__PURE__ */ jsx(
|
|
6720
|
+
UserEntity,
|
|
6721
|
+
{
|
|
6722
|
+
size: "xs",
|
|
6723
|
+
variant: "pill",
|
|
6724
|
+
showTooltip: false,
|
|
6725
|
+
interactive: false,
|
|
6726
|
+
displayName: name,
|
|
6727
|
+
initials: initials(name || member.user.email),
|
|
6728
|
+
picture: member.user.picture
|
|
6729
|
+
}
|
|
6730
|
+
);
|
|
6731
|
+
};
|
|
6732
|
+
function ConnectedWorkspaceMembers({
|
|
6733
|
+
workspace,
|
|
6734
|
+
members,
|
|
6735
|
+
selfId,
|
|
6736
|
+
isOwner: isOwnerRaw,
|
|
6737
|
+
isLoading = false,
|
|
6738
|
+
readOnly = false,
|
|
6739
|
+
renderMember = defaultRenderMember,
|
|
6740
|
+
gridState,
|
|
6741
|
+
onGridStateChange
|
|
6742
|
+
}) {
|
|
6743
|
+
const { confirm, notify: notify14 } = useBlocksEnvironment();
|
|
6744
|
+
const isOwner = isOwnerRaw && !readOnly;
|
|
6745
|
+
const [selected, setSelected] = useState([]);
|
|
6746
|
+
const updateRoles = useSetWorkspaceMemberRoles();
|
|
6747
|
+
const remove = useRemoveWorkspaceMembers();
|
|
6748
|
+
const memberWord = (count) => getEntityLabel("WORKSPACEUSER", count === 1 ? "SINGULAR" : "PLURAL");
|
|
6749
|
+
const workspaceWord2 = getEntityLabel("WORKSPACE").toLowerCase();
|
|
6750
|
+
const inWorkspace = `"${workspace.name}"`;
|
|
6751
|
+
const setRoles = async (rows2, role) => {
|
|
6752
|
+
const single = rows2.length === 1 ? memberName(rows2[0].user) : null;
|
|
6753
|
+
try {
|
|
6754
|
+
await updateRoles.mutateAsync({ userIds: rows2.map((r) => r.user.external_id), role });
|
|
6755
|
+
notify14(
|
|
6756
|
+
single ? `${single}'s role updated to ${formatRole(role)} in "${workspace.name}"` : `Updated ${rows2.length} users to ${formatRole(role)} in "${workspace.name}"`,
|
|
6757
|
+
"success"
|
|
6758
|
+
);
|
|
6759
|
+
return true;
|
|
6760
|
+
} catch {
|
|
6761
|
+
notify14(
|
|
6762
|
+
single ? `Failed to update ${single}'s role` : `Failed to update roles in "${workspace.name}"`,
|
|
6763
|
+
"error"
|
|
6764
|
+
);
|
|
6765
|
+
return false;
|
|
6766
|
+
}
|
|
6767
|
+
};
|
|
6768
|
+
const rows = useMemo(
|
|
6769
|
+
() => [...members].sort((a, b) => {
|
|
6770
|
+
if (a.user.external_id === selfId) return -1;
|
|
6771
|
+
if (b.user.external_id === selfId) return 1;
|
|
6772
|
+
return (ROLE_ORDER[a.role] ?? 3) - (ROLE_ORDER[b.role] ?? 3);
|
|
6773
|
+
}),
|
|
6774
|
+
[members, selfId]
|
|
6775
|
+
);
|
|
6776
|
+
const columnDefs = useMemo(
|
|
6777
|
+
() => [
|
|
6778
|
+
{
|
|
6779
|
+
colId: "name",
|
|
6780
|
+
headerName: "Name",
|
|
6781
|
+
flex: 1,
|
|
6782
|
+
minWidth: 150,
|
|
6783
|
+
sortable: true,
|
|
6784
|
+
valueGetter: (p) => p.data ? memberName(p.data.user) : "",
|
|
6785
|
+
cellRenderer: (p) => p.data ? /* @__PURE__ */ jsx(MemberNameCell, { children: renderMember(p.data) }) : null
|
|
6786
|
+
},
|
|
6787
|
+
{
|
|
6788
|
+
colId: "email",
|
|
6789
|
+
headerName: "Email",
|
|
6790
|
+
flex: 1,
|
|
6791
|
+
minWidth: 180,
|
|
6792
|
+
sortable: true,
|
|
6793
|
+
valueGetter: (p) => p.data?.user.email ?? "",
|
|
6794
|
+
// Plain text, not a mailto: the row's click selects it.
|
|
6795
|
+
cellRenderer: (p) => p.data?.user.email ? /* @__PURE__ */ jsx(MemberMutedText, { className: "truncate", title: p.data.user.email, children: p.data.user.email }) : null
|
|
6796
|
+
},
|
|
6797
|
+
{
|
|
6798
|
+
colId: "role",
|
|
6799
|
+
headerName: "Role",
|
|
6800
|
+
width: 145,
|
|
6801
|
+
minWidth: 130,
|
|
6802
|
+
sortable: true,
|
|
6803
|
+
valueGetter: (p) => p.data?.role ?? "",
|
|
6804
|
+
cellRenderer: (p) => {
|
|
6805
|
+
const row = p.data;
|
|
6806
|
+
if (!row) return null;
|
|
6807
|
+
const lock = roleLock(row.user.external_id, selfId, isOwner);
|
|
6808
|
+
return /* @__PURE__ */ jsx(
|
|
6809
|
+
MemberRoleCell,
|
|
6810
|
+
{
|
|
6811
|
+
role: row.role,
|
|
6812
|
+
roles: ALL_ROLES,
|
|
6813
|
+
tooltip: lock ?? getRoleDescription(row.role),
|
|
6814
|
+
canChange: !lock,
|
|
6815
|
+
isPending: updateRoles.isPending,
|
|
6816
|
+
onChange: (value) => void setRoles([row], value),
|
|
6817
|
+
temporaryHint: row.is_temporary ? "Temporary, session-scoped grant \u2014 expires with the session." : void 0
|
|
6818
|
+
}
|
|
6819
|
+
);
|
|
6820
|
+
}
|
|
6821
|
+
},
|
|
6822
|
+
{
|
|
6823
|
+
colId: "joined_at",
|
|
6824
|
+
headerName: "Joined",
|
|
6825
|
+
width: 145,
|
|
6826
|
+
minWidth: 125,
|
|
6827
|
+
sortable: true,
|
|
6828
|
+
valueGetter: (p) => p.data ? new Date(p.data.joined_at).getTime() : "",
|
|
6829
|
+
cellRenderer: (p) => p.data ? /* @__PURE__ */ jsx(MemberMutedText, { className: "cursor-default", children: formatFriendlyDate(p.data.joined_at) }) : null
|
|
6830
|
+
},
|
|
6831
|
+
{
|
|
6832
|
+
colId: "conversation_count",
|
|
6833
|
+
headerName: getEntityLabel("CONVERSATION", "PLURAL"),
|
|
6834
|
+
width: 95,
|
|
6835
|
+
minWidth: 85,
|
|
6836
|
+
sortable: true,
|
|
6837
|
+
type: "numericColumn",
|
|
6838
|
+
valueGetter: (p) => p.data?.conversation_count ?? 0,
|
|
6839
|
+
cellRenderer: (p) => p.data ? /* @__PURE__ */ jsx(MemberMutedText, { children: p.data.conversation_count }) : null
|
|
6840
|
+
},
|
|
6841
|
+
{
|
|
6842
|
+
colId: "document_count",
|
|
6843
|
+
headerName: "Docs",
|
|
6844
|
+
width: 90,
|
|
6845
|
+
minWidth: 80,
|
|
6846
|
+
sortable: true,
|
|
6847
|
+
type: "numericColumn",
|
|
6848
|
+
valueGetter: (p) => p.data?.document_count ?? 0,
|
|
6849
|
+
cellRenderer: (p) => p.data ? /* @__PURE__ */ jsx(MemberMutedText, { children: p.data.document_count }) : null
|
|
6850
|
+
},
|
|
6851
|
+
{
|
|
6852
|
+
colId: "files_mb",
|
|
6853
|
+
headerName: "Storage",
|
|
6854
|
+
width: 110,
|
|
6855
|
+
minWidth: 95,
|
|
6856
|
+
sortable: true,
|
|
6857
|
+
type: "numericColumn",
|
|
6858
|
+
valueGetter: (p) => p.data?.files_mb ?? 0,
|
|
6859
|
+
cellRenderer: (p) => {
|
|
6860
|
+
if (!p.data) return null;
|
|
6861
|
+
const mb = p.data.files_mb ?? 0;
|
|
6862
|
+
return /* @__PURE__ */ jsxs(MemberMutedText, { children: [
|
|
6863
|
+
mb >= 100 ? Math.round(mb).toLocaleString("en-US") : mb.toFixed(1),
|
|
6864
|
+
" MB"
|
|
6865
|
+
] });
|
|
6866
|
+
}
|
|
6867
|
+
}
|
|
6868
|
+
],
|
|
6869
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
6870
|
+
[selfId, isOwner, updateRoles.isPending, renderMember, workspace.name]
|
|
6871
|
+
);
|
|
6872
|
+
const removeSelected = async () => {
|
|
6873
|
+
const count = selected.length;
|
|
6874
|
+
if (count === 0) return;
|
|
6875
|
+
const names = count === 1 ? `"${memberName(selected[0].user)}"` : `${count} ${memberWord(count).toLowerCase()}`;
|
|
6876
|
+
const members2 = getEntityLabel("WORKSPACEUSER", "PLURAL").toLowerCase();
|
|
6877
|
+
const confirmed = await confirm({
|
|
6878
|
+
title: `Remove ${count} ${memberWord(count)}`,
|
|
6879
|
+
message: `Remove ${names} from ${inWorkspace}?
|
|
6880
|
+
|
|
6881
|
+
Note that ${members2} may have saved private content in the ${workspaceWord2} that you cannot see. Once removed they immediately lose access to any content in the ${workspaceWord2}.`
|
|
6882
|
+
});
|
|
6883
|
+
if (!confirmed) return;
|
|
6884
|
+
try {
|
|
6885
|
+
await remove.mutateAsync(selected.map((m) => m.user.external_id));
|
|
6886
|
+
setSelected([]);
|
|
6887
|
+
notify14(`Removed ${names} from ${inWorkspace}`, "success");
|
|
6888
|
+
} catch {
|
|
6889
|
+
notify14(`Failed to remove some users from ${inWorkspace}`, "error");
|
|
6890
|
+
}
|
|
6891
|
+
};
|
|
6892
|
+
const changeSelectedRoles = async (role) => {
|
|
6893
|
+
const changeable = selected.filter((m) => !roleLock(m.user.external_id, selfId, isOwner));
|
|
6894
|
+
if (changeable.length === 0) return;
|
|
6895
|
+
if (await setRoles(changeable, role)) setSelected([]);
|
|
6896
|
+
};
|
|
6897
|
+
const canRemoveSelected = selected.every(
|
|
6898
|
+
(m) => m.role !== "owner" && m.user.external_id !== selfId
|
|
6899
|
+
);
|
|
6900
|
+
const canChangeRoleSelected = selected.some((m) => !roleLock(m.user.external_id, selfId, isOwner));
|
|
6901
|
+
const ownerOnly = `Only available to ${workspaceWord2} owner`;
|
|
6902
|
+
if (isLoading) return /* @__PURE__ */ jsx(MemberListLoading, {});
|
|
6903
|
+
return /* @__PURE__ */ jsxs("div", { "data-testid": "workspace-users", className: "relative flex flex-col", children: [
|
|
6904
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsx(
|
|
6905
|
+
GridView,
|
|
6906
|
+
{
|
|
6907
|
+
items: rows,
|
|
6908
|
+
columnDefs,
|
|
6909
|
+
getItemId: (m) => m.user.external_id,
|
|
6910
|
+
selection: { mode: "multiple", selected, onSelectionChange: setSelected },
|
|
6911
|
+
persistState: !!onGridStateChange,
|
|
6912
|
+
gridId: `workspace-users-${workspace.external_id}-v6`,
|
|
6913
|
+
gridState,
|
|
6914
|
+
onGridStateChange,
|
|
6915
|
+
height: "300px",
|
|
6916
|
+
className: "w-full grid-sort-left"
|
|
6917
|
+
}
|
|
6918
|
+
) }),
|
|
6919
|
+
!readOnly && /* @__PURE__ */ jsx(SelectionBar, { count: selected.length, onClear: () => setSelected([]), children: /* @__PURE__ */ jsx(
|
|
6920
|
+
MemberBulkActions,
|
|
6921
|
+
{
|
|
6922
|
+
roles: BULK_ROLES,
|
|
6923
|
+
onChangeRole: (value) => void changeSelectedRoles(value),
|
|
6924
|
+
isRoleDisabled: !isOwner || !canChangeRoleSelected || updateRoles.isPending,
|
|
6925
|
+
roleTooltip: !isOwner ? ownerOnly : selected.length === 0 ? "Select users to change their role" : !canChangeRoleSelected ? "You cannot change your own role" : "Change role for selected users",
|
|
6926
|
+
isOwner,
|
|
6927
|
+
onRemove: () => void removeSelected(),
|
|
6928
|
+
isRemoveDisabled: !isOwner || !canRemoveSelected || remove.isPending,
|
|
6929
|
+
removeTooltip: !isOwner ? ownerOnly : "Remove selected from workspace"
|
|
6930
|
+
}
|
|
6931
|
+
) })
|
|
6932
|
+
] });
|
|
6933
|
+
}
|
|
6717
6934
|
var isAgentMember = (member) => member.user.external_id.startsWith("agt-");
|
|
6718
|
-
var
|
|
6935
|
+
var memberName2 = (member) => member.user.family_name ? `${member.user.given_name} ${member.user.family_name}` : member.user.given_name;
|
|
6719
6936
|
function ConnectedWorkspaceSettings({
|
|
6720
6937
|
workspaceId,
|
|
6721
6938
|
project,
|
|
6722
6939
|
projectLine,
|
|
6723
|
-
|
|
6940
|
+
renderMember,
|
|
6941
|
+
membersGridState,
|
|
6942
|
+
onMembersGridStateChange,
|
|
6724
6943
|
shareDialog,
|
|
6725
6944
|
children,
|
|
6726
6945
|
onExport,
|
|
@@ -6730,6 +6949,7 @@ function ConnectedWorkspaceSettings({
|
|
|
6730
6949
|
}) {
|
|
6731
6950
|
const settings = useConnectedWorkspaceSettings(workspaceId, { onLeft });
|
|
6732
6951
|
const { workspace, members, isOwner, isMember } = settings;
|
|
6952
|
+
const { userId } = useConnectedWorkspace();
|
|
6733
6953
|
const { data: userSettings } = useUserSettings();
|
|
6734
6954
|
const isDeveloper = userSettings?.developer === true;
|
|
6735
6955
|
const showAgents = userSettings?.show_agent_sessions ?? false;
|
|
@@ -6817,7 +7037,7 @@ function ConnectedWorkspaceSettings({
|
|
|
6817
7037
|
MemberAvatarStack,
|
|
6818
7038
|
{
|
|
6819
7039
|
members: visibleMembers.map((m) => ({
|
|
6820
|
-
name:
|
|
7040
|
+
name: memberName2(m),
|
|
6821
7041
|
picture: m.user.picture
|
|
6822
7042
|
})),
|
|
6823
7043
|
total: visibleMembers.length,
|
|
@@ -6838,17 +7058,23 @@ function ConnectedWorkspaceSettings({
|
|
|
6838
7058
|
]
|
|
6839
7059
|
}
|
|
6840
7060
|
),
|
|
6841
|
-
isMember &&
|
|
7061
|
+
isMember && /* @__PURE__ */ jsx(
|
|
6842
7062
|
ExpandableSection,
|
|
6843
7063
|
{
|
|
6844
7064
|
expanded: membersExpanded,
|
|
6845
7065
|
testId: "workspace-settings-members-section",
|
|
6846
|
-
children:
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
7066
|
+
children: /* @__PURE__ */ jsx(
|
|
7067
|
+
ConnectedWorkspaceMembers,
|
|
7068
|
+
{
|
|
7069
|
+
workspace,
|
|
7070
|
+
members: visibleMembers,
|
|
7071
|
+
selfId: userId,
|
|
7072
|
+
isOwner,
|
|
7073
|
+
renderMember,
|
|
7074
|
+
gridState: membersGridState,
|
|
7075
|
+
onGridStateChange: onMembersGridStateChange
|
|
7076
|
+
}
|
|
7077
|
+
)
|
|
6852
7078
|
}
|
|
6853
7079
|
)
|
|
6854
7080
|
] }),
|
|
@@ -7516,20 +7742,6 @@ function ConnectedDriveSyncDialog({
|
|
|
7516
7742
|
}
|
|
7517
7743
|
);
|
|
7518
7744
|
}
|
|
7519
|
-
var BillingSupportContext = createContext({ stripeEnabled: false });
|
|
7520
|
-
function BillingSupportProvider({
|
|
7521
|
-
value,
|
|
7522
|
-
children
|
|
7523
|
-
}) {
|
|
7524
|
-
return /* @__PURE__ */ jsx(BillingSupportContext.Provider, { value, children });
|
|
7525
|
-
}
|
|
7526
|
-
function useBillingSupport() {
|
|
7527
|
-
return useContext(BillingSupportContext);
|
|
7528
|
-
}
|
|
7529
|
-
function useSelfExtId() {
|
|
7530
|
-
const arbi = useArbi();
|
|
7531
|
-
return arbi.isLoggedIn ? arbi.user.identity()?.externalId ?? void 0 : void 0;
|
|
7532
|
-
}
|
|
7533
7745
|
var focus = null;
|
|
7534
7746
|
var listeners = /* @__PURE__ */ new Set();
|
|
7535
7747
|
function requestProjectBillingFocus(next) {
|
|
@@ -7549,363 +7761,8 @@ function BillingProjectEntity({
|
|
|
7549
7761
|
...props
|
|
7550
7762
|
}) {
|
|
7551
7763
|
const { stripeEnabled } = useBillingSupport();
|
|
7552
|
-
const
|
|
7553
|
-
return /* @__PURE__ */ jsx(ProjectEntity, { ...props, subscription, isPaid });
|
|
7554
|
-
}
|
|
7555
|
-
|
|
7556
|
-
// src/connection/billing/plan-constants.ts
|
|
7557
|
-
var PRO_AI_GBP = 10;
|
|
7558
|
-
var PRO_STORAGE_GB = 5;
|
|
7559
|
-
var ADDON_BLOCK_AI_GBP = 25;
|
|
7560
|
-
var STORAGE_BLOCK_GB = 25;
|
|
7561
|
-
var DEFAULT_SPEND_CAP_PENCE = 1e4;
|
|
7562
|
-
var MIN_AUTO_TOPUP_THRESHOLD_GBP = 1;
|
|
7563
|
-
var FREE_AI_GBP = 1;
|
|
7564
|
-
var FREE_STORAGE_MB = 50;
|
|
7565
|
-
var UNLIMITED_COLLABORATORS = 999;
|
|
7566
|
-
var SUGGESTED_DAILY_CAP_PER_USER = 10;
|
|
7567
|
-
|
|
7568
|
-
// src/connection/billing/quota-items.ts
|
|
7569
|
-
var fmt = (v) => Math.round(v).toLocaleString("en-US");
|
|
7570
|
-
function formatResetDate(unixTimestamp) {
|
|
7571
|
-
if (!unixTimestamp) return null;
|
|
7572
|
-
const date = new Date(unixTimestamp * 1e3);
|
|
7573
|
-
return date.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
7574
|
-
}
|
|
7575
|
-
function aiUsageResetTimestamp(project) {
|
|
7576
|
-
const periodEnd = project.plan_interval === "year" ? null : project.current_period_end;
|
|
7577
|
-
const ts = project.addons?.ai_usage_reset_at ?? periodEnd ?? project.quotas?.budget_reset_at ?? null;
|
|
7578
|
-
return ts && ts * 1e3 > Date.now() ? ts : null;
|
|
7579
|
-
}
|
|
7580
|
-
var quota = (q) => ({
|
|
7581
|
-
used: q?.used ?? 0,
|
|
7582
|
-
limit: q?.limit ?? 0
|
|
7583
|
-
});
|
|
7584
|
-
function storageText(gbValue, limitGb, unit = true) {
|
|
7585
|
-
if (limitGb >= 1) {
|
|
7586
|
-
const n = Math.round(gbValue * 10) / 10;
|
|
7587
|
-
return `${n.toLocaleString("en-US")}${unit ? " GB" : ""}`;
|
|
7588
|
-
}
|
|
7589
|
-
return `${fmt(gbValue * 1e3)}${unit ? " MB" : ""}`;
|
|
7590
|
-
}
|
|
7591
|
-
var pctOf = (used, limit) => limit > 0 ? used / limit * 100 : 0;
|
|
7592
|
-
function getQuotaItems(quotas) {
|
|
7593
|
-
const aiUsage = quota(quotas?.ai_usage);
|
|
7594
|
-
const storage = quota(quotas?.storage_gb);
|
|
7595
|
-
const collaborators = quota(quotas?.collaborators);
|
|
7596
|
-
const unlimitedCollaborators = collaborators.limit >= UNLIMITED_COLLABORATORS;
|
|
7597
|
-
return [
|
|
7598
|
-
{
|
|
7599
|
-
key: "ai-usage",
|
|
7600
|
-
icon: PoundSterling,
|
|
7601
|
-
label: "AI usage",
|
|
7602
|
-
used: formatGbp(aiUsage.used),
|
|
7603
|
-
usedOfLimit: `${formatGbp(aiUsage.used)} / ${formatGbp(aiUsage.limit)}`,
|
|
7604
|
-
pct: pctOf(aiUsage.used, aiUsage.limit)
|
|
7605
|
-
},
|
|
7606
|
-
{
|
|
7607
|
-
key: "storage",
|
|
7608
|
-
icon: HardDrive,
|
|
7609
|
-
label: "Storage",
|
|
7610
|
-
used: storageText(storage.used, storage.limit),
|
|
7611
|
-
usedOfLimit: `${storageText(storage.used, storage.limit, false)} / ${storageText(
|
|
7612
|
-
storage.limit,
|
|
7613
|
-
storage.limit
|
|
7614
|
-
)}`,
|
|
7615
|
-
pct: pctOf(storage.used, storage.limit)
|
|
7616
|
-
},
|
|
7617
|
-
{
|
|
7618
|
-
key: "collaborators",
|
|
7619
|
-
icon: Users,
|
|
7620
|
-
label: "Collaborators",
|
|
7621
|
-
used: fmt(collaborators.used),
|
|
7622
|
-
usedOfLimit: unlimitedCollaborators ? `${fmt(collaborators.used)} / Unlimited` : `${fmt(collaborators.used)} / ${fmt(collaborators.limit)}`,
|
|
7623
|
-
// Zero seats (Free) IS the cap: 0 / 0 shows a full destructive bar,
|
|
7624
|
-
// because you can't add anyone — the truth the upgrade door answers.
|
|
7625
|
-
// (Only when the quota is actually present; a missing field on a
|
|
7626
|
-
// partial payload stays an empty bar, not a false alarm.)
|
|
7627
|
-
pct: unlimitedCollaborators ? 0 : quotas?.collaborators && collaborators.limit === 0 ? 100 : pctOf(collaborators.used, collaborators.limit)
|
|
7628
|
-
}
|
|
7629
|
-
];
|
|
7630
|
-
}
|
|
7631
|
-
function useRewardBalance() {
|
|
7632
|
-
const { data } = useUserSettings();
|
|
7633
|
-
const ed = data?.extra_discount;
|
|
7634
|
-
if (!ed || !ed.amount || ed.amount <= 0) return null;
|
|
7635
|
-
return { amount: ed.amount, currency: ed.currency || "gbp" };
|
|
7636
|
-
}
|
|
7637
|
-
function formatMoney(cents, currency = "gbp") {
|
|
7638
|
-
const value = cents / 100;
|
|
7639
|
-
const isWhole = Number.isInteger(value);
|
|
7640
|
-
const c = currency.toLowerCase();
|
|
7641
|
-
const symbol = c === "usd" ? "$" : c === "gbp" ? "\xA3" : c === "eur" ? "\u20AC" : currency.toUpperCase() + " ";
|
|
7642
|
-
return `${symbol}${value.toLocaleString("en-US", {
|
|
7643
|
-
minimumFractionDigits: isWhole ? 0 : 2,
|
|
7644
|
-
maximumFractionDigits: isWhole ? 0 : 2
|
|
7645
|
-
})}`;
|
|
7646
|
-
}
|
|
7647
|
-
var gbp = (pence) => formatMoney(pence, "gbp");
|
|
7648
|
-
function formatPeriodEnd(unix) {
|
|
7649
|
-
if (!unix) return null;
|
|
7650
|
-
return new Date(unix * 1e3).toLocaleDateString("en-GB", {
|
|
7651
|
-
day: "numeric",
|
|
7652
|
-
month: "short",
|
|
7653
|
-
year: "numeric"
|
|
7654
|
-
});
|
|
7655
|
-
}
|
|
7656
|
-
function addonPricePence(kind, addons) {
|
|
7657
|
-
return kind === "ai_usage" ? addons.ai_block_price_pence : addons.storage_block_price_pence;
|
|
7658
|
-
}
|
|
7659
|
-
function addonPriceExVatPence(kind, addons) {
|
|
7660
|
-
return kind === "ai_usage" ? addons.ai_block_price_ex_vat_pence : addons.storage_block_price_ex_vat_pence;
|
|
7661
|
-
}
|
|
7662
|
-
function addonSettingsBody(addons, change = {}) {
|
|
7663
|
-
return {
|
|
7664
|
-
spend_cap_pence: addons.spend_cap_pence ?? null,
|
|
7665
|
-
auto_topup_threshold_gbp: addons.auto_topup_threshold_gbp,
|
|
7666
|
-
...change
|
|
7667
|
-
};
|
|
7668
|
-
}
|
|
7669
|
-
function splitBlocks(kind, count, addons) {
|
|
7670
|
-
const granted = (kind === "ai_usage" ? addons.legacy_ai_blocks : addons.legacy_storage_blocks) ?? 0;
|
|
7671
|
-
const legacy = Math.max(0, Math.min(granted, count));
|
|
7672
|
-
return { legacy, current: count - legacy };
|
|
7673
|
-
}
|
|
7674
|
-
function blockSize(kind, addons, legacy) {
|
|
7675
|
-
if (kind === "ai_usage") {
|
|
7676
|
-
return formatGbp(legacy ? addons.legacy_block_ai_gbp ?? 10 : addons.block_ai_gbp);
|
|
7677
|
-
}
|
|
7678
|
-
return `${legacy ? addons.legacy_block_storage_gb ?? 10 : addons.block_storage_gb} GB`;
|
|
7679
|
-
}
|
|
7680
|
-
function blocksLabel(kind, count, addons) {
|
|
7681
|
-
const { legacy, current } = splitBlocks(kind, count, addons);
|
|
7682
|
-
const parts = [
|
|
7683
|
-
...legacy > 0 ? [`${legacy} \xD7 ${blockSize(kind, addons, true)}`] : [],
|
|
7684
|
-
...current > 0 || legacy === 0 ? [`${current} \xD7 ${blockSize(kind, addons, false)}`] : []
|
|
7685
|
-
];
|
|
7686
|
-
return `${parts.join(" + ")}${kind === "ai_usage" ? " of AI usage" : ""}`;
|
|
7687
|
-
}
|
|
7688
|
-
function reduceBounds(kind, addons) {
|
|
7689
|
-
const current = kind === "ai_usage" ? addons.ai_blocks : addons.storage_blocks;
|
|
7690
|
-
const pending = kind === "ai_usage" ? addons.ai_blocks_next : addons.storage_blocks_next;
|
|
7691
|
-
const min = kind === "ai_usage" ? 0 : Math.min(addons.storage_blocks_min, current);
|
|
7692
|
-
return { min, current, next: pending ?? current };
|
|
7693
|
-
}
|
|
7694
|
-
function blockMonthlyExVatPence(kind, addons) {
|
|
7695
|
-
return kind === "ai_usage" ? addons.ai_block_monthly_ex_vat_pence : addons.storage_block_monthly_ex_vat_pence;
|
|
7696
|
-
}
|
|
7697
|
-
function blockPeriodExVatPence(kind, addons) {
|
|
7698
|
-
return kind === "ai_usage" ? addons.ai_block_period_ex_vat_pence : addons.storage_block_period_ex_vat_pence;
|
|
7699
|
-
}
|
|
7700
|
-
function blockRenewalShort(kind, addons, isAnnual) {
|
|
7701
|
-
return `${gbp(blockPeriodExVatPence(kind, addons))}/${isAnnual ? "year" : "month"} + VAT`;
|
|
7702
|
-
}
|
|
7703
|
-
var ANNUAL_PREMIUM_AI_NOTE = "No markup on Premium AI on annual plans";
|
|
7704
|
-
function addonCharge(kind, addons, isAnnual, periodEnd) {
|
|
7705
|
-
return {
|
|
7706
|
-
now: gbp(addonPricePence(kind, addons)),
|
|
7707
|
-
nowExVat: gbp(addonPriceExVatPence(kind, addons)),
|
|
7708
|
-
nowVat: gbp(addonPricePence(kind, addons) - addonPriceExVatPence(kind, addons)),
|
|
7709
|
-
until: isAnnual ? formatPeriodEnd(periodEnd) : null,
|
|
7710
|
-
then: blockRenewalShort(kind, addons, isAnnual)
|
|
7711
|
-
};
|
|
7712
|
-
}
|
|
7713
|
-
var CAP_REACHED_MESSAGE = "Usage cap reached: no more automatic top-ups this month.";
|
|
7714
|
-
var ZERO_BUDGET_MESSAGE = "Automatic top-ups are off (\xA30 usage cap).";
|
|
7715
|
-
var USAGE_CAP_LABEL = "Usage cap";
|
|
7716
|
-
var USAGE_CAP_HELP = "The most automatic top-ups (AI usage added when it runs low, storage added when an upload needs it) may cost in a month. Adding or removing by hand is never limited by it; the plan and renewals are not counted. \xA30 = no automatic top-ups: AI usage and uploads stop at your allowance unless you add more. No limit = no cap.";
|
|
7717
|
-
function isAddonBudgetZero(addons) {
|
|
7718
|
-
return addons.spend_cap_pence === 0;
|
|
7719
|
-
}
|
|
7720
|
-
function autoRoom(kind, addons) {
|
|
7721
|
-
const left = addons.cap_left_pence;
|
|
7722
|
-
if (left == null) return addons.spend_cap_pence === 0 ? 0 : null;
|
|
7723
|
-
const price = addonPriceExVatPence(kind, addons);
|
|
7724
|
-
if (price <= 0) return 0;
|
|
7725
|
-
const blocks = Math.floor(left / price);
|
|
7726
|
-
return blocks * (kind === "ai_usage" ? addons.block_ai_gbp : addons.block_storage_gb);
|
|
7727
|
-
}
|
|
7728
|
-
function nextRemovedBlockSize(kind, addons) {
|
|
7729
|
-
const { next } = reduceBounds(kind, addons);
|
|
7730
|
-
const { current } = splitBlocks(kind, next, addons);
|
|
7731
|
-
if (kind === "ai_usage") {
|
|
7732
|
-
return current > 0 ? addons.block_ai_gbp : addons.legacy_block_ai_gbp ?? 10;
|
|
7733
|
-
}
|
|
7734
|
-
return current > 0 ? addons.block_storage_gb : addons.legacy_block_storage_gb ?? 10;
|
|
7735
|
-
}
|
|
7736
|
-
function parseBudgetPounds(value) {
|
|
7737
|
-
if (value.trim() === "") return null;
|
|
7738
|
-
const n = Number(value);
|
|
7739
|
-
if (!Number.isFinite(n) || n < 0) return void 0;
|
|
7740
|
-
return Math.round(n * 100);
|
|
7741
|
-
}
|
|
7742
|
-
function budgetSavedMessage(capPence) {
|
|
7743
|
-
if (capPence == null) return "Usage cap: no limit";
|
|
7744
|
-
if (capPence === 0) return "Usage cap: \xA30 (no automatic top-ups)";
|
|
7745
|
-
return `Usage cap: ${gbp(capPence)} a month`;
|
|
7746
|
-
}
|
|
7747
|
-
var gbText = (n) => `${Math.round(n * 10) / 10} GB`;
|
|
7748
|
-
function stepLabel(kind, size) {
|
|
7749
|
-
return kind === "ai_usage" ? `${formatGbp(size)} of AI usage` : gbText(size);
|
|
7750
|
-
}
|
|
7751
|
-
function nextPeriodBody(kind, keep) {
|
|
7752
|
-
return kind === "ai_usage" ? { ai_blocks: keep, storage_blocks: null } : { ai_blocks: null, storage_blocks: keep };
|
|
7753
|
-
}
|
|
7754
|
-
function addStepCaption(kind, addons) {
|
|
7755
|
-
const now = gbp(addonPriceExVatPence(kind, addons));
|
|
7756
|
-
const today = kind === "storage" ? `prorated today ${now}` : `today ${now}`;
|
|
7757
|
-
return `${gbp(blockMonthlyExVatPence(kind, addons))}/month \xB7 ${today}`;
|
|
7758
|
-
}
|
|
7759
|
-
|
|
7760
|
-
// src/connection/billing/api-error.ts
|
|
7761
|
-
function apiErrorDetail(error) {
|
|
7762
|
-
const body = error?.apiError ?? error;
|
|
7763
|
-
return body?.detail;
|
|
7764
|
-
}
|
|
7765
|
-
|
|
7766
|
-
// src/connection/billing/tax-quote.ts
|
|
7767
|
-
var POSTCODE_COUNTRIES = ["US", "CA"];
|
|
7768
|
-
var TAX_LOCATION_INVALID = "TAX_LOCATION_INVALID";
|
|
7769
|
-
function money2(pence, currency = "gbp") {
|
|
7770
|
-
const symbol = { gbp: "\xA3", usd: "$", eur: "\u20AC" }[currency.toLowerCase()] ?? `${currency} `;
|
|
7771
|
-
return `${symbol}${(pence / 100).toLocaleString("en-GB", {
|
|
7772
|
-
minimumFractionDigits: 2,
|
|
7773
|
-
maximumFractionDigits: 2
|
|
7774
|
-
})}`;
|
|
7775
|
-
}
|
|
7776
|
-
function taxKind(label) {
|
|
7777
|
-
return /^vat\b/i.test(label ?? "") ? "VAT" : "tax";
|
|
7778
|
-
}
|
|
7779
|
-
function taxDetail({ subtotal, tax, label, reverseCharge }) {
|
|
7780
|
-
if (reverseCharge) return "\xB7 no VAT (reverse charge)";
|
|
7781
|
-
if (tax <= 0) return "\xB7 no tax";
|
|
7782
|
-
return `incl. ${taxKind(label)} (${money2(subtotal)} + ${money2(tax)} ${label ?? "tax"})`;
|
|
7783
|
-
}
|
|
7784
|
-
function taxSummary(parts) {
|
|
7785
|
-
return `${money2(parts.total)} ${taxDetail(parts)}`;
|
|
7786
|
-
}
|
|
7787
|
-
function totalWithTaxWord({ total, tax, label }) {
|
|
7788
|
-
return tax > 0 ? `${money2(total)} incl. ${taxKind(label)}` : money2(total);
|
|
7789
|
-
}
|
|
7790
|
-
function quoteParts(quote) {
|
|
7791
|
-
return {
|
|
7792
|
-
subtotal: quote.subtotal_pence,
|
|
7793
|
-
tax: quote.tax_pence,
|
|
7794
|
-
total: quote.total_pence,
|
|
7795
|
-
label: quote.tax_label,
|
|
7796
|
-
reverseCharge: quote.reverse_charge
|
|
7797
|
-
};
|
|
7798
|
-
}
|
|
7799
|
-
function quoteTotalLine(quote) {
|
|
7800
|
-
return `Total today ${taxSummary(quoteParts(quote))}`;
|
|
7801
|
-
}
|
|
7802
|
-
function quoteError(error) {
|
|
7803
|
-
const detail = apiErrorDetail(error);
|
|
7804
|
-
if (detail && typeof detail === "object") {
|
|
7805
|
-
const { code, message } = detail;
|
|
7806
|
-
return {
|
|
7807
|
-
code: typeof code === "string" ? code : void 0,
|
|
7808
|
-
message: typeof message === "string" ? message : void 0
|
|
7809
|
-
};
|
|
7810
|
-
}
|
|
7811
|
-
return { message: typeof detail === "string" ? detail : void 0 };
|
|
7812
|
-
}
|
|
7813
|
-
|
|
7814
|
-
// src/connection/billing/plan-pricing.ts
|
|
7815
|
-
var gbp2 = (pence) => formatMoney(pence, "gbp");
|
|
7816
|
-
function plusVat(exVatPence, currency = "gbp") {
|
|
7817
|
-
return `${formatMoney(exVatPence, currency)} + VAT`;
|
|
7818
|
-
}
|
|
7819
|
-
var PRO_PACKS = 1;
|
|
7820
|
-
var PLAN_CHOICE_PACKS = {
|
|
7821
|
-
pro: PRO_PACKS
|
|
7822
|
-
};
|
|
7823
|
-
function planNameForPacks(packs) {
|
|
7824
|
-
const n = packs ?? 0;
|
|
7825
|
-
if (n <= 0) return "Free";
|
|
7826
|
-
if (n === PRO_PACKS) return "Pro";
|
|
7827
|
-
return `Pro \xD7${n}`;
|
|
7828
|
-
}
|
|
7829
|
-
function planPreviewLines(preview) {
|
|
7830
|
-
if (preview.unchanged) return [{ id: "no-change", text: "No change" }];
|
|
7831
|
-
const date = formatPeriodEnd(preview.next_renewal_at);
|
|
7832
|
-
const cadence = preview.interval === "year" ? "year" : "month";
|
|
7833
|
-
const lines = [
|
|
7834
|
-
preview.awaiting_confirmation ? { id: "awaiting-bank", text: "Waiting for your bank" } : {
|
|
7835
|
-
id: "pay-today",
|
|
7836
|
-
text: preview.effective_now ? `Pay today ${taxSummary({
|
|
7837
|
-
subtotal: preview.due_now_ex_vat_pence,
|
|
7838
|
-
tax: preview.due_now_tax_pence,
|
|
7839
|
-
total: preview.due_now_pence,
|
|
7840
|
-
label: preview.tax_label
|
|
7841
|
-
})}` : `Pay today ${gbp2(0)}`
|
|
7842
|
-
},
|
|
7843
|
-
{
|
|
7844
|
-
id: "from",
|
|
7845
|
-
text: `${date ? `From ${date}` : "From renewal"}: ${taxSummary({
|
|
7846
|
-
subtotal: preview.next_renewal_ex_vat_pence,
|
|
7847
|
-
tax: preview.next_renewal_tax_pence,
|
|
7848
|
-
total: preview.next_renewal_pence,
|
|
7849
|
-
label: preview.tax_label
|
|
7850
|
-
})} a ${cadence}`
|
|
7851
|
-
}
|
|
7852
|
-
];
|
|
7853
|
-
if (!preview.effective_now) {
|
|
7854
|
-
lines.push({ id: "current-until", text: `Current plan until ${date ?? "renewal"}` });
|
|
7855
|
-
}
|
|
7856
|
-
return lines;
|
|
7857
|
-
}
|
|
7858
|
-
var PAY_TODAY_UNPRICED = "Pay today: the difference for the rest of this period";
|
|
7859
|
-
function addonPrice(price, kind = "ai_usage") {
|
|
7860
|
-
return price?.addon_prices?.find((p) => p.kind === kind);
|
|
7861
|
-
}
|
|
7862
|
-
function checkoutItemsLabel(aiBlocks, storageBlocks) {
|
|
7863
|
-
return [
|
|
7864
|
-
"Pro",
|
|
7865
|
-
aiBlocks > 0 && `${aiBlocks} \xD7 ${formatGbp(ADDON_BLOCK_AI_GBP)} of AI usage`,
|
|
7866
|
-
storageBlocks > 0 && `${storageBlocks} \xD7 ${STORAGE_BLOCK_GB} GB`
|
|
7867
|
-
].filter(Boolean).join(" + ");
|
|
7868
|
-
}
|
|
7869
|
-
function packPrice(price, packs = PRO_PACKS) {
|
|
7870
|
-
return price?.pack_prices?.find((p) => p.packs === packs);
|
|
7871
|
-
}
|
|
7872
|
-
function findProPrices(products) {
|
|
7873
|
-
const prices = products?.[0]?.prices ?? [];
|
|
7874
|
-
const pick = (interval) => prices.find((p) => p.interval === interval && p.default_price) ?? prices.find((p) => p.interval === interval);
|
|
7875
|
-
return { monthly: pick("month"), annual: pick("year") };
|
|
7876
|
-
}
|
|
7877
|
-
function calcSavingsPercent(monthlyPrice, annualPrice) {
|
|
7878
|
-
const monthly = packPrice(monthlyPrice)?.amount ?? monthlyPrice?.amount;
|
|
7879
|
-
const annual = packPrice(annualPrice)?.amount ?? annualPrice?.amount;
|
|
7880
|
-
if (monthly == null || annual == null || monthly === 0) return null;
|
|
7881
|
-
const savings = Math.round((monthly * 12 - annual) / (monthly * 12) * 100);
|
|
7882
|
-
return savings > 0 ? savings : null;
|
|
7883
|
-
}
|
|
7884
|
-
var MAX_CHECKOUT_BLOCKS = 100;
|
|
7885
|
-
function checkoutBlockPriceText(price, kind) {
|
|
7886
|
-
const block = addonPrice(price, kind);
|
|
7887
|
-
if (!block) return null;
|
|
7888
|
-
const currency = price?.currency ?? "gbp";
|
|
7889
|
-
return price?.interval === "year" ? `${formatMoney(block.amount_ex_vat, currency)}/year + VAT each` : `${formatMoney(block.amount_ex_vat, currency)}/month + VAT each`;
|
|
7890
|
-
}
|
|
7891
|
-
|
|
7892
|
-
// src/connection/billing/plan-badge.ts
|
|
7893
|
-
function isProProject(project) {
|
|
7894
|
-
return project.plan_interval != null;
|
|
7895
|
-
}
|
|
7896
|
-
function proTierName(project) {
|
|
7897
|
-
return project.addons?.plan_name || planNameForPacks(Math.max(project.packs ?? 1, 1));
|
|
7898
|
-
}
|
|
7899
|
-
function planName(project) {
|
|
7900
|
-
if (project.subscription === "dev") return "Dev";
|
|
7901
|
-
if (!isProProject(project)) return "Free";
|
|
7902
|
-
return `${proTierName(project)} ${project.plan_interval === "year" ? "annual" : "monthly"}`;
|
|
7903
|
-
}
|
|
7904
|
-
function planBadgeView(project) {
|
|
7905
|
-
const { subscription } = project;
|
|
7906
|
-
const label = subscription === "canceled" ? "Cancelling" : subscription === "dev" ? "Dev" : isProProject(project) ? proTierName(project) : "Free";
|
|
7907
|
-
const tone = subscription === "dev" ? "dev" : subscription === "canceled" || subscription === "past_due" ? "pending" : isProProject(project) ? "paid" : "free";
|
|
7908
|
-
return { label, tone };
|
|
7764
|
+
const isPaid2 = stripeEnabled && (subscription === "active" || subscription === "past_due" || subscription === "dev");
|
|
7765
|
+
return /* @__PURE__ */ jsx(ProjectEntity, { ...props, subscription, isPaid: isPaid2 });
|
|
7909
7766
|
}
|
|
7910
7767
|
function formatInvoiceDate(iso) {
|
|
7911
7768
|
const d = /* @__PURE__ */ new Date(`${iso}T00:00:00`);
|
|
@@ -7925,7 +7782,7 @@ function InvoicesModal({
|
|
|
7925
7782
|
const { data, isLoading } = useProjectInvoices(open ? projectExtId : void 0);
|
|
7926
7783
|
const invoices = data?.invoices;
|
|
7927
7784
|
const invoiceViews = (invoices ?? []).map((inv, i) => {
|
|
7928
|
-
const
|
|
7785
|
+
const isPaid2 = inv.status === "paid";
|
|
7929
7786
|
return {
|
|
7930
7787
|
key: inv.number ?? String(i),
|
|
7931
7788
|
date: formatInvoiceDate(inv.date),
|
|
@@ -7933,9 +7790,9 @@ function InvoicesModal({
|
|
|
7933
7790
|
amount: formatMoney(inv.amount, inv.currency),
|
|
7934
7791
|
amountNote: inv.amount_ex_vat != null && inv.amount_ex_vat !== inv.amount ? `${formatMoney(inv.amount_ex_vat, inv.currency)} ex VAT` : void 0,
|
|
7935
7792
|
status: inv.status,
|
|
7936
|
-
isPaid,
|
|
7793
|
+
isPaid: isPaid2,
|
|
7937
7794
|
href: inv.hosted_invoice_url ?? inv.url ?? inv.pdf_url ?? void 0,
|
|
7938
|
-
linkLabel:
|
|
7795
|
+
linkLabel: isPaid2 ? "Receipt" : "Invoice"
|
|
7939
7796
|
};
|
|
7940
7797
|
});
|
|
7941
7798
|
return /* @__PURE__ */ jsx(
|
|
@@ -8134,7 +7991,7 @@ function buildPlanCards(selected, isAnnual, prices, isOnFree) {
|
|
|
8134
7991
|
features: [
|
|
8135
7992
|
`${formatGbp(FREE_AI_GBP)} of AI usage / month`,
|
|
8136
7993
|
`${FREE_STORAGE_MB.toLocaleString("en-US")} MB storage`,
|
|
8137
|
-
"Just you"
|
|
7994
|
+
FREE_COLLABORATORS === 0 ? "Just you" : `${FREE_COLLABORATORS} collaborators`
|
|
8138
7995
|
]
|
|
8139
7996
|
};
|
|
8140
7997
|
return [free, proCard(selected, isAnnual, prices)];
|
|
@@ -9349,7 +9206,7 @@ function ReduceAddonDialog({
|
|
|
9349
9206
|
}
|
|
9350
9207
|
) });
|
|
9351
9208
|
}
|
|
9352
|
-
var
|
|
9209
|
+
var gbp = (pence) => formatMoney(pence, "gbp");
|
|
9353
9210
|
var gb2 = (n) => `${Math.round(n * 10) / 10} GB`;
|
|
9354
9211
|
var pct = (used, limit) => limit > 0 ? Math.min(100, used / limit * 100) : 0;
|
|
9355
9212
|
function formatShortDate(unix) {
|
|
@@ -9475,7 +9332,7 @@ function ResourceMeter({
|
|
|
9475
9332
|
const from = periodEnd ?? "your next renewal";
|
|
9476
9333
|
const fromShort = formatShortDate(addons.period_end ?? project.current_period_end) ?? "renewal";
|
|
9477
9334
|
const { min, current, next } = reduceBounds(kind, addons);
|
|
9478
|
-
const
|
|
9335
|
+
const fmt = (n) => isAi ? formatGbp(n) : gb2(n);
|
|
9479
9336
|
const used = isAi ? addons.ai_used_gbp : addons.storage_used_gb;
|
|
9480
9337
|
const allowance = isAi ? addons.ai_allowance_gbp : addons.storage_allowance_gb;
|
|
9481
9338
|
const allowanceNext = isAi ? addons.ai_allowance_next_gbp : addons.storage_allowance_next_gb;
|
|
@@ -9503,12 +9360,12 @@ function ResourceMeter({
|
|
|
9503
9360
|
{
|
|
9504
9361
|
label: isAi ? "AI usage" : "Storage",
|
|
9505
9362
|
hint: resets ? `resets ${resets}` : void 0,
|
|
9506
|
-
value: `${
|
|
9363
|
+
value: `${fmt(used)} of ${fmt(allowance)}`,
|
|
9507
9364
|
allowance: { used, plan, topUps, autoRoom: capZero ? 0 : room },
|
|
9508
9365
|
legend: {
|
|
9509
|
-
plan: `Plan ${
|
|
9510
|
-
topUps: topUps > 0 ? `Top-ups ${
|
|
9511
|
-
autoRoom: room != null && room > 0 && !capZero ? `Automatic up to ${
|
|
9366
|
+
plan: `Plan ${fmt(plan)}`,
|
|
9367
|
+
topUps: topUps > 0 ? `Top-ups ${fmt(topUps)}${hasLegacy ? ` (${blocksLabel(kind, blocks, addons)})` : ""}` : void 0,
|
|
9368
|
+
autoRoom: room != null && room > 0 && !capZero ? `Automatic up to ${fmt(room)}` : void 0
|
|
9512
9369
|
},
|
|
9513
9370
|
testId: `usage-meter-${slug}`,
|
|
9514
9371
|
details: autoLine || allowanceNext !== allowance || children ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -9596,7 +9453,7 @@ function UsageCapEditor({ project, addons }) {
|
|
|
9596
9453
|
}
|
|
9597
9454
|
);
|
|
9598
9455
|
};
|
|
9599
|
-
const readout = savedCap == null ? `${
|
|
9456
|
+
const readout = savedCap == null ? `${gbp(spent)} this month \xB7 no limit` : savedCap === 0 ? "\xA30 \xB7 no automatic top-ups" : `${gbp(spent)} of ${gbp(savedCap)} used`;
|
|
9600
9457
|
const inputId = `spend-cap-${project.external_id}`;
|
|
9601
9458
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", ref: sectionRef, "data-testid": "project-spend-cap", children: [
|
|
9602
9459
|
/* @__PURE__ */ jsx(
|
|
@@ -9612,7 +9469,7 @@ function UsageCapEditor({ project, addons }) {
|
|
|
9612
9469
|
addons.cap_reached && savedCap != null && savedCap > 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", "data-testid": "addon-cap-reached", children: CAP_REACHED_MESSAGE }),
|
|
9613
9470
|
addons.manual_spent_pence > 0 && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", "data-testid": "addon-manual-spend", children: [
|
|
9614
9471
|
"Added by hand this month: ",
|
|
9615
|
-
|
|
9472
|
+
gbp(addons.manual_spent_pence),
|
|
9616
9473
|
" \xB7 not capped"
|
|
9617
9474
|
] }),
|
|
9618
9475
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-3", children: [
|
|
@@ -9788,7 +9645,7 @@ function formatShortDate2(unix) {
|
|
|
9788
9645
|
if (!unix) return null;
|
|
9789
9646
|
return new Date(unix * 1e3).toLocaleDateString("en-GB", { day: "numeric", month: "short" });
|
|
9790
9647
|
}
|
|
9791
|
-
var
|
|
9648
|
+
var gbp2 = (pence) => formatMoney(pence, "gbp");
|
|
9792
9649
|
var gbNum = (n) => `${Math.round(n * 10) / 10}`;
|
|
9793
9650
|
var pct2 = (used, limit) => limit > 0 ? Math.min(100, used / limit * 100) : 0;
|
|
9794
9651
|
function Meter({
|
|
@@ -9819,7 +9676,7 @@ function usePlanPrice(project) {
|
|
|
9819
9676
|
}
|
|
9820
9677
|
function paidLine(payment, addons) {
|
|
9821
9678
|
const what = payment.kind === "storage" ? `${addons.block_storage_gb} GB added` : payment.kind === "ai_usage" ? `${formatGbp(addons.block_ai_gbp)} of AI usage added` : null;
|
|
9822
|
-
const paid = payment.amount_pence != null ? `Paid ${
|
|
9679
|
+
const paid = payment.amount_pence != null ? `Paid ${gbp2(payment.amount_pence)}` : "Paid";
|
|
9823
9680
|
return what ? `${paid} \xB7 ${what}` : paid;
|
|
9824
9681
|
}
|
|
9825
9682
|
function ProjectPlanCard({
|
|
@@ -9890,11 +9747,11 @@ function ProjectPlanCard({
|
|
|
9890
9747
|
] }),
|
|
9891
9748
|
price && /* @__PURE__ */ jsxs("div", { className: "ml-auto text-right", "data-testid": "project-plan-price", children: [
|
|
9892
9749
|
/* @__PURE__ */ jsxs("div", { className: "text-lg font-semibold tabular-nums text-foreground", children: [
|
|
9893
|
-
price.ex != null ? plusVat(price.ex) :
|
|
9750
|
+
price.ex != null ? plusVat(price.ex) : gbp2(price.incl),
|
|
9894
9751
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-normal text-muted-foreground", children: price.isAnnual ? "/year" : "/month" })
|
|
9895
9752
|
] }),
|
|
9896
9753
|
price.ex != null && /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
9897
|
-
|
|
9754
|
+
gbp2(price.incl),
|
|
9898
9755
|
" incl. VAT"
|
|
9899
9756
|
] })
|
|
9900
9757
|
] })
|
|
@@ -9976,7 +9833,7 @@ function ProjectPlanCard({
|
|
|
9976
9833
|
addons?.billing_error && /* @__PURE__ */ jsx(PlanNotice, { tone: "error", testId: "plan-billing-error", children: addons.billing_error }),
|
|
9977
9834
|
confirmUrl ? /* @__PURE__ */ jsxs(PlanNotice, { testId: "plan-payment-state", children: [
|
|
9978
9835
|
"Waiting for your bank",
|
|
9979
|
-
pendingPayment?.amount_pence ? ` \xB7 ${
|
|
9836
|
+
pendingPayment?.amount_pence ? ` \xB7 ${gbp2(pendingPayment.amount_pence)}` : "",
|
|
9980
9837
|
" \xB7",
|
|
9981
9838
|
" ",
|
|
9982
9839
|
/* @__PURE__ */ jsxs(
|
|
@@ -10646,6 +10503,713 @@ function useAutoRefreshPendingProjects() {
|
|
|
10646
10503
|
}
|
|
10647
10504
|
}, [projects, refreshProject, currentUserExtId]);
|
|
10648
10505
|
}
|
|
10506
|
+
function toWorkspaceSummary(workspace, selfId) {
|
|
10507
|
+
const people = (workspace.users ?? []).filter((m) => !isAgentAccount(m.user));
|
|
10508
|
+
const ordered = [
|
|
10509
|
+
...people.filter((m) => m.role === "owner"),
|
|
10510
|
+
...people.filter((m) => m.role !== "owner")
|
|
10511
|
+
];
|
|
10512
|
+
const members = ordered.map((m) => ({
|
|
10513
|
+
name: m.user.family_name ? `${m.user.given_name} ${m.user.family_name}` : m.user.given_name,
|
|
10514
|
+
picture: m.user.picture
|
|
10515
|
+
}));
|
|
10516
|
+
const isMember = people.some((m) => m.user.external_id === selfId);
|
|
10517
|
+
return {
|
|
10518
|
+
id: workspace.external_id,
|
|
10519
|
+
name: workspace.name,
|
|
10520
|
+
description: workspace.description,
|
|
10521
|
+
docCount: workspaceDocumentCount(workspace),
|
|
10522
|
+
chatCount: workspaceConversationCount(workspace),
|
|
10523
|
+
memberCount: members.length,
|
|
10524
|
+
members,
|
|
10525
|
+
// A public workspace's members are hidden from someone who has not joined it.
|
|
10526
|
+
membersHidden: workspace.is_public && !isMember,
|
|
10527
|
+
updatedAt: workspace.updated_at
|
|
10528
|
+
};
|
|
10529
|
+
}
|
|
10530
|
+
function WorkspaceCardsView({
|
|
10531
|
+
list,
|
|
10532
|
+
currentWorkspaceId,
|
|
10533
|
+
onOpenWorkspace,
|
|
10534
|
+
onOpenProject,
|
|
10535
|
+
onCreateWorkspace,
|
|
10536
|
+
createDisabledReason
|
|
10537
|
+
}) {
|
|
10538
|
+
const { stripeEnabled } = useBillingSupport();
|
|
10539
|
+
const workspaceLabel = getEntityLabel("WORKSPACE");
|
|
10540
|
+
const projectLabel = getEntityLabel("PROJECT").toLowerCase();
|
|
10541
|
+
const { groups, projects, selfId } = list;
|
|
10542
|
+
if (groups.length === 0) {
|
|
10543
|
+
return /* @__PURE__ */ jsx(WorkspaceList, { testId: "workspace-cards-list", className: "gap-0", children: /* @__PURE__ */ jsx(
|
|
10544
|
+
CreateTile,
|
|
10545
|
+
{
|
|
10546
|
+
label: `New ${workspaceLabel.toLowerCase()}`,
|
|
10547
|
+
ariaLabel: `Create ${workspaceLabel}`,
|
|
10548
|
+
onSelect: () => onCreateWorkspace(),
|
|
10549
|
+
disabledReason: createDisabledReason,
|
|
10550
|
+
help: `A ${workspaceLabel.toLowerCase()} holds the documents and conversations for one matter or case.`,
|
|
10551
|
+
testId: "create-workspace-card"
|
|
10552
|
+
}
|
|
10553
|
+
) });
|
|
10554
|
+
}
|
|
10555
|
+
return /* @__PURE__ */ jsx(WorkspaceList, { testId: "workspace-cards-list", children: groups.map((group) => {
|
|
10556
|
+
const project = projects.find((p) => p.external_id === group.projectExtId);
|
|
10557
|
+
const { breakdown, readout } = projectGroupBilling(project, {
|
|
10558
|
+
isOwned: group.isOwned,
|
|
10559
|
+
stripeEnabled
|
|
10560
|
+
});
|
|
10561
|
+
const count = group.workspaces.length;
|
|
10562
|
+
return /* @__PURE__ */ jsxs(
|
|
10563
|
+
WorkspaceGroup,
|
|
10564
|
+
{
|
|
10565
|
+
title: group.projectExtId ? /* @__PURE__ */ jsx(
|
|
10566
|
+
ProjectBandTitle,
|
|
10567
|
+
{
|
|
10568
|
+
name: group.title,
|
|
10569
|
+
count,
|
|
10570
|
+
nameTestId: `project-name-${group.projectExtId}`,
|
|
10571
|
+
breakdown,
|
|
10572
|
+
readout
|
|
10573
|
+
}
|
|
10574
|
+
) : /* @__PURE__ */ jsx(
|
|
10575
|
+
PlainBandTitle,
|
|
10576
|
+
{
|
|
10577
|
+
title: group.title,
|
|
10578
|
+
count,
|
|
10579
|
+
hint: group.isCommon ? "Shared with everyone" : void 0
|
|
10580
|
+
}
|
|
10581
|
+
),
|
|
10582
|
+
onOpen: group.projectExtId ? () => onOpenProject(group.projectExtId) : void 0,
|
|
10583
|
+
openLabel: "Plans & Usage",
|
|
10584
|
+
collapsedHint: group.isCommon ? `Show ${count} shared ${getEntityLabel("WORKSPACE", "PLURAL").toLowerCase()}` : void 0,
|
|
10585
|
+
isExpanded: !list.isCollapsed(group.key),
|
|
10586
|
+
onToggle: () => list.toggleGroup(group.key),
|
|
10587
|
+
children: [
|
|
10588
|
+
group.isOwned && group.projectExtId && /* @__PURE__ */ jsx(
|
|
10589
|
+
CreateTile,
|
|
10590
|
+
{
|
|
10591
|
+
label: `New ${workspaceLabel.toLowerCase()}`,
|
|
10592
|
+
ariaLabel: `Create ${workspaceLabel}`,
|
|
10593
|
+
onSelect: () => onCreateWorkspace(group.projectExtId),
|
|
10594
|
+
disabledReason: createDisabledReason,
|
|
10595
|
+
help: count === 0 ? `Already have one? Open it and change its ${projectLabel} to move it here.` : void 0,
|
|
10596
|
+
testId: "add-workspace-button"
|
|
10597
|
+
}
|
|
10598
|
+
),
|
|
10599
|
+
[...group.workspaces].sort(byRecentUpdate).map((workspace) => /* @__PURE__ */ jsx(
|
|
10600
|
+
WorkspaceCard,
|
|
10601
|
+
{
|
|
10602
|
+
workspace: toWorkspaceSummary(workspace, selfId),
|
|
10603
|
+
current: currentWorkspaceId === workspace.external_id,
|
|
10604
|
+
onSelect: () => onOpenWorkspace(workspace),
|
|
10605
|
+
href: buildDeepLinkPath({ workspaceId: workspace.external_id }),
|
|
10606
|
+
mark: /* @__PURE__ */ jsx(
|
|
10607
|
+
ShieldIcon,
|
|
10608
|
+
{
|
|
10609
|
+
char: workspace.name.charAt(0),
|
|
10610
|
+
workspaceColor: workspaceKindColor(getWorkspaceKind(workspace)),
|
|
10611
|
+
size: 28,
|
|
10612
|
+
isSelected: true
|
|
10613
|
+
}
|
|
10614
|
+
),
|
|
10615
|
+
testId: `workspace-card-${workspace.external_id}`,
|
|
10616
|
+
openCueTestId: `workspace-open-${workspace.external_id}`
|
|
10617
|
+
},
|
|
10618
|
+
workspace.external_id
|
|
10619
|
+
))
|
|
10620
|
+
]
|
|
10621
|
+
},
|
|
10622
|
+
group.key
|
|
10623
|
+
);
|
|
10624
|
+
}) });
|
|
10625
|
+
}
|
|
10626
|
+
function WorkspaceFilterMenu({ list }) {
|
|
10627
|
+
const [open, setOpen] = useState(false);
|
|
10628
|
+
const { workspaces, projects, selfId, pinned, filters, setFilters } = list;
|
|
10629
|
+
const { options: options2, groups } = useMemo(() => {
|
|
10630
|
+
const attributes = workspaces.map((w) => workspaceFilterAttributes(w, { selfId, pinned }));
|
|
10631
|
+
const countOf = (id) => attributes.filter((a) => a[id]).length;
|
|
10632
|
+
const projectIds = projects.map((p) => projectFilterId(p.external_id));
|
|
10633
|
+
const options3 = [
|
|
10634
|
+
...projects.map((p) => ({
|
|
10635
|
+
id: projectFilterId(p.external_id),
|
|
10636
|
+
label: p.name,
|
|
10637
|
+
count: countOf(projectFilterId(p.external_id))
|
|
10638
|
+
})),
|
|
10639
|
+
...WORKSPACE_CATEGORY_FILTERS.map(({ id, label }) => ({ id, label, count: countOf(id) }))
|
|
10640
|
+
];
|
|
10641
|
+
const groups2 = [
|
|
10642
|
+
{ label: "Projects", options: projectIds },
|
|
10643
|
+
{ label: "Workspaces", options: WORKSPACE_CATEGORY_FILTERS.map((f) => f.id) }
|
|
10644
|
+
];
|
|
10645
|
+
return { options: options3, groups: groups2 };
|
|
10646
|
+
}, [workspaces, projects, selfId, pinned]);
|
|
10647
|
+
return /* @__PURE__ */ jsx(
|
|
10648
|
+
TriStateFilterMenu,
|
|
10649
|
+
{
|
|
10650
|
+
testId: "workspace-filter-button",
|
|
10651
|
+
open,
|
|
10652
|
+
onOpenChange: setOpen,
|
|
10653
|
+
title: "Filter workspaces",
|
|
10654
|
+
triggerLabel: "Filter",
|
|
10655
|
+
renderChevron: true,
|
|
10656
|
+
filterStates: filters,
|
|
10657
|
+
onFiltersChange: setFilters,
|
|
10658
|
+
options: options2,
|
|
10659
|
+
groups
|
|
10660
|
+
}
|
|
10661
|
+
);
|
|
10662
|
+
}
|
|
10663
|
+
var DEFAULT_WORKSPACE_LIST_LABELS = {
|
|
10664
|
+
recentlyDeletedHint: (count) => `You can restore ${count === 1 ? "it" : "them"} from Recently deleted (Settings > Storage) for at least 30 days.`
|
|
10665
|
+
};
|
|
10666
|
+
function useConnectedWorkspaceList({
|
|
10667
|
+
filters: controlledFilters,
|
|
10668
|
+
onFiltersChange,
|
|
10669
|
+
labels
|
|
10670
|
+
} = {}) {
|
|
10671
|
+
const recentlyDeletedHint = labels?.recentlyDeletedHint ?? DEFAULT_WORKSPACE_LIST_LABELS.recentlyDeletedHint;
|
|
10672
|
+
const { confirm, notify: notify14 } = useBlocksEnvironment();
|
|
10673
|
+
const { userId: selfId } = useConnectedWorkspace();
|
|
10674
|
+
const workspacesQuery = useWorkspaces();
|
|
10675
|
+
const { data: projects } = useProjects();
|
|
10676
|
+
const { data: settings } = useUserSettings();
|
|
10677
|
+
const canCreateProjects = useCanCreateProjects();
|
|
10678
|
+
const deleteWorkspaces = useDeleteWorkspaces();
|
|
10679
|
+
const workspaces = useMemo(
|
|
10680
|
+
() => (workspacesQuery.data ?? []).filter(isListedWorkspace),
|
|
10681
|
+
[workspacesQuery.data]
|
|
10682
|
+
);
|
|
10683
|
+
const pinned = useMemo(
|
|
10684
|
+
() => new Set(settings?.pinned_workspaces ?? []),
|
|
10685
|
+
[settings?.pinned_workspaces]
|
|
10686
|
+
);
|
|
10687
|
+
const [localFilters, setLocalFilters] = useState({});
|
|
10688
|
+
const filters = controlledFilters ?? localFilters;
|
|
10689
|
+
const filterMap = useMemo(() => {
|
|
10690
|
+
const known = new Set(WORKSPACE_CATEGORY_FILTERS.map((f) => f.id));
|
|
10691
|
+
for (const p of projects ?? []) known.add(projectFilterId(p.external_id));
|
|
10692
|
+
for (const w of workspaces) if (w.project_ext_id) known.add(projectFilterId(w.project_ext_id));
|
|
10693
|
+
return new Map(Object.entries(filters).filter(([id, state]) => state !== null && known.has(id)));
|
|
10694
|
+
}, [filters, projects, workspaces]);
|
|
10695
|
+
const setFilters = useCallback(
|
|
10696
|
+
(next) => {
|
|
10697
|
+
const record = Object.fromEntries(next);
|
|
10698
|
+
if (onFiltersChange) onFiltersChange(record);
|
|
10699
|
+
if (controlledFilters === void 0) setLocalFilters(record);
|
|
10700
|
+
},
|
|
10701
|
+
[controlledFilters, onFiltersChange]
|
|
10702
|
+
);
|
|
10703
|
+
const attributesOf = useCallback(
|
|
10704
|
+
(workspace) => workspaceFilterAttributes(workspace, { selfId, pinned }),
|
|
10705
|
+
[selfId, pinned]
|
|
10706
|
+
);
|
|
10707
|
+
const filtered = useMemo(
|
|
10708
|
+
() => applyTriStateFilters(workspaces, filterMap, attributesOf),
|
|
10709
|
+
[workspaces, filterMap, attributesOf]
|
|
10710
|
+
);
|
|
10711
|
+
const groups = useMemo(
|
|
10712
|
+
() => groupWorkspacesByProject(filtered, {
|
|
10713
|
+
selfId,
|
|
10714
|
+
pinned,
|
|
10715
|
+
projects: projects ?? [],
|
|
10716
|
+
workspacesLabel: getEntityLabel("WORKSPACE", "PLURAL")
|
|
10717
|
+
}),
|
|
10718
|
+
[filtered, selfId, pinned, projects]
|
|
10719
|
+
);
|
|
10720
|
+
const [toggled, setToggled] = useState({});
|
|
10721
|
+
const isCollapsed = useCallback(
|
|
10722
|
+
(key) => toggled[key] ?? groups.some((g) => g.key === key && g.isCommon),
|
|
10723
|
+
[toggled, groups]
|
|
10724
|
+
);
|
|
10725
|
+
const toggleGroup = useCallback(
|
|
10726
|
+
(key) => setToggled((prev) => ({ ...prev, [key]: !isCollapsed(key) })),
|
|
10727
|
+
[isCollapsed]
|
|
10728
|
+
);
|
|
10729
|
+
const [selected, setSelected] = useState([]);
|
|
10730
|
+
const canDeleteSelected = selected.every((w) => !!selfId && w.created_by_ext_id === selfId);
|
|
10731
|
+
const deleteSelected = useCallback(async () => {
|
|
10732
|
+
const count = selected.length;
|
|
10733
|
+
if (count === 0) return;
|
|
10734
|
+
const noun = getEntityLabel("WORKSPACE", count === 1 ? "SINGULAR" : "PLURAL");
|
|
10735
|
+
const confirmed = await confirm({
|
|
10736
|
+
title: `Delete ${count} ${noun}`,
|
|
10737
|
+
message: `Delete ${count} ${noun.toLowerCase()}? ${recentlyDeletedHint(count)}`
|
|
10738
|
+
});
|
|
10739
|
+
if (!confirmed) return;
|
|
10740
|
+
try {
|
|
10741
|
+
await deleteWorkspaces.mutateAsync(selected.map((w) => w.external_id));
|
|
10742
|
+
setSelected([]);
|
|
10743
|
+
notify14(`Deleted ${count} ${noun.toLowerCase()}`, "success");
|
|
10744
|
+
} catch {
|
|
10745
|
+
notify14("Failed to delete some workspaces", "error");
|
|
10746
|
+
}
|
|
10747
|
+
}, [selected, confirm, notify14, deleteWorkspaces, recentlyDeletedHint]);
|
|
10748
|
+
return {
|
|
10749
|
+
selfId,
|
|
10750
|
+
/** Every listed workspace (unfiltered): the filter menu's counts. */
|
|
10751
|
+
workspaces,
|
|
10752
|
+
projects: projects ?? [],
|
|
10753
|
+
pinned,
|
|
10754
|
+
/** The filtered workspaces grouped by project, in list order. */
|
|
10755
|
+
groups,
|
|
10756
|
+
/** How many workspaces the filters let through. */
|
|
10757
|
+
shownCount: filtered.length,
|
|
10758
|
+
isLoading: workspacesQuery.isLoading,
|
|
10759
|
+
error: workspacesQuery.error,
|
|
10760
|
+
canCreateProjects,
|
|
10761
|
+
filters: filterMap,
|
|
10762
|
+
setFilters,
|
|
10763
|
+
isCollapsed,
|
|
10764
|
+
toggleGroup,
|
|
10765
|
+
selected,
|
|
10766
|
+
setSelected,
|
|
10767
|
+
canDeleteSelected,
|
|
10768
|
+
deleteSelected,
|
|
10769
|
+
isDeleting: deleteWorkspaces.isPending
|
|
10770
|
+
};
|
|
10771
|
+
}
|
|
10772
|
+
var WorkspaceTableView = lazy(
|
|
10773
|
+
() => import('../WorkspaceTableView-5OWX53R5.js').then((m) => ({ default: m.WorkspaceTableView }))
|
|
10774
|
+
);
|
|
10775
|
+
var WORKSPACES_TAB_ID = "workspaces";
|
|
10776
|
+
var defaultRenderMember2 = (user, size) => {
|
|
10777
|
+
const name = user.family_name ? `${user.given_name} ${user.family_name}` : user.given_name;
|
|
10778
|
+
return /* @__PURE__ */ jsx(
|
|
10779
|
+
UserEntity,
|
|
10780
|
+
{
|
|
10781
|
+
size,
|
|
10782
|
+
variant: "icon",
|
|
10783
|
+
showTooltip: false,
|
|
10784
|
+
interactive: false,
|
|
10785
|
+
displayName: name,
|
|
10786
|
+
initials: initials(name || user.email),
|
|
10787
|
+
picture: user.picture
|
|
10788
|
+
}
|
|
10789
|
+
);
|
|
10790
|
+
};
|
|
10791
|
+
function ConnectedWorkspaceList({
|
|
10792
|
+
onCreateWorkspace,
|
|
10793
|
+
view: controlledView,
|
|
10794
|
+
onViewChange,
|
|
10795
|
+
filters,
|
|
10796
|
+
onFiltersChange,
|
|
10797
|
+
gridState,
|
|
10798
|
+
onGridStateChange,
|
|
10799
|
+
renderMember = defaultRenderMember2,
|
|
10800
|
+
extraTabs = [],
|
|
10801
|
+
activeTab = WORKSPACES_TAB_ID,
|
|
10802
|
+
onTabChange,
|
|
10803
|
+
children,
|
|
10804
|
+
labels
|
|
10805
|
+
}) {
|
|
10806
|
+
const list = useConnectedWorkspaceList({ filters, onFiltersChange, labels });
|
|
10807
|
+
const { openProject } = useBlocksEnvironment();
|
|
10808
|
+
const { workspaceId: currentWorkspaceId, openWorkspace } = useConnectedWorkspace();
|
|
10809
|
+
const [localView, setLocalView] = useState("cards");
|
|
10810
|
+
const view = controlledView ?? localView;
|
|
10811
|
+
const isPhone = useIsPhone();
|
|
10812
|
+
const shownView = view === "table" && !isPhone ? "table" : "cards";
|
|
10813
|
+
const showList = activeTab === WORKSPACES_TAB_ID || !extraTabs.some((t) => t.id === activeTab);
|
|
10814
|
+
const setView = (next) => {
|
|
10815
|
+
onViewChange?.(next);
|
|
10816
|
+
if (controlledView === void 0) setLocalView(next);
|
|
10817
|
+
};
|
|
10818
|
+
const open = (workspace) => void openWorkspace(workspace.external_id, { name: workspace.name });
|
|
10819
|
+
const createDisabledReason = list.canCreateProjects === false ? PROJECT_CREATION_DENIED_REASON : void 0;
|
|
10820
|
+
if (list.isLoading) return /* @__PURE__ */ jsx(LoadingIndicator, { message: "Loading workspaces..." });
|
|
10821
|
+
if (list.error) {
|
|
10822
|
+
return /* @__PURE__ */ jsx(
|
|
10823
|
+
HomeLoadError,
|
|
10824
|
+
{
|
|
10825
|
+
title: "Unable to load workspaces",
|
|
10826
|
+
body: "Failed to connect to the server. Please check your connection and try again."
|
|
10827
|
+
}
|
|
10828
|
+
);
|
|
10829
|
+
}
|
|
10830
|
+
const newButton = createDisabledReason ? (
|
|
10831
|
+
// A disabled button emits no pointer events: the span carries the tooltip.
|
|
10832
|
+
/* @__PURE__ */ jsxs(Tooltip, { delayDuration: 50, children: [
|
|
10833
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { tabIndex: 0, "data-testid": "home-new-workspace-disabled", children: /* @__PURE__ */ jsxs(Button, { disabled: true, "data-testid": "home-new-workspace", children: [
|
|
10834
|
+
/* @__PURE__ */ jsx(Plus, { className: "mr-0.5 size-4" }),
|
|
10835
|
+
"New"
|
|
10836
|
+
] }) }) }),
|
|
10837
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: createDisabledReason })
|
|
10838
|
+
] })
|
|
10839
|
+
) : /* @__PURE__ */ jsxs(Button, { onClick: () => onCreateWorkspace(), "data-testid": "home-new-workspace", children: [
|
|
10840
|
+
/* @__PURE__ */ jsx(Plus, { className: "mr-0.5 size-4" }),
|
|
10841
|
+
"New"
|
|
10842
|
+
] });
|
|
10843
|
+
return /* @__PURE__ */ jsxs(HomeFrame, { children: [
|
|
10844
|
+
/* @__PURE__ */ jsx(
|
|
10845
|
+
TabHeader,
|
|
10846
|
+
{
|
|
10847
|
+
testId: "home-header",
|
|
10848
|
+
tabs: [
|
|
10849
|
+
{
|
|
10850
|
+
id: WORKSPACES_TAB_ID,
|
|
10851
|
+
label: getEntityLabel("WORKSPACE", "PLURAL"),
|
|
10852
|
+
count: list.shownCount,
|
|
10853
|
+
icon: /* @__PURE__ */ jsx(SquareStack, { className: "size-4" })
|
|
10854
|
+
},
|
|
10855
|
+
...extraTabs
|
|
10856
|
+
],
|
|
10857
|
+
activeTabId: showList ? WORKSPACES_TAB_ID : activeTab,
|
|
10858
|
+
onTabChange: (id) => onTabChange?.(id),
|
|
10859
|
+
centerContent: showList && !isPhone ? /* @__PURE__ */ jsx(
|
|
10860
|
+
ViewToggle,
|
|
10861
|
+
{
|
|
10862
|
+
options: [
|
|
10863
|
+
{ value: "cards", icon: /* @__PURE__ */ jsx(SquareStack, { className: "size-4" }), label: "Cards" },
|
|
10864
|
+
{ value: "grid", icon: /* @__PURE__ */ jsx(Table, { className: "size-4" }), label: "Table" }
|
|
10865
|
+
],
|
|
10866
|
+
value: shownView === "table" ? "grid" : "cards",
|
|
10867
|
+
onChange: (value) => setView(value === "grid" ? "table" : "cards"),
|
|
10868
|
+
testIdPrefix: "workspaces",
|
|
10869
|
+
size: "sm",
|
|
10870
|
+
showLabels: true,
|
|
10871
|
+
hideTooltips: true
|
|
10872
|
+
}
|
|
10873
|
+
) : void 0,
|
|
10874
|
+
rightContent: showList ? newButton : void 0
|
|
10875
|
+
}
|
|
10876
|
+
),
|
|
10877
|
+
showList && // Above whichever view shows: both draw the same filtered groups.
|
|
10878
|
+
/* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-6xl px-4 pb-3 sm:px-8", children: /* @__PURE__ */ jsx(WorkspaceFilterMenu, { list }) }),
|
|
10879
|
+
/* @__PURE__ */ jsx(HomeMain, { children: !showList ? children : shownView === "cards" ? (
|
|
10880
|
+
// Full-width scroller (its scrollbar rides the window edge) around a centred column.
|
|
10881
|
+
/* @__PURE__ */ jsx(HomeCenteredScroll, { children: /* @__PURE__ */ jsx(
|
|
10882
|
+
WorkspaceCardsView,
|
|
10883
|
+
{
|
|
10884
|
+
list,
|
|
10885
|
+
currentWorkspaceId,
|
|
10886
|
+
onOpenWorkspace: open,
|
|
10887
|
+
onOpenProject: openProject,
|
|
10888
|
+
onCreateWorkspace,
|
|
10889
|
+
createDisabledReason
|
|
10890
|
+
}
|
|
10891
|
+
) })
|
|
10892
|
+
) : /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx(LoadingIndicator, { message: "Loading grid..." }), children: /* @__PURE__ */ jsx(HomeCenteredColumn, { children: /* @__PURE__ */ jsx(
|
|
10893
|
+
WorkspaceTableView,
|
|
10894
|
+
{
|
|
10895
|
+
list,
|
|
10896
|
+
onOpenWorkspace: open,
|
|
10897
|
+
onOpenProject: openProject,
|
|
10898
|
+
renderMember,
|
|
10899
|
+
gridState,
|
|
10900
|
+
onGridStateChange
|
|
10901
|
+
}
|
|
10902
|
+
) }) }) })
|
|
10903
|
+
] });
|
|
10904
|
+
}
|
|
10905
|
+
var PROJECTS_BASE_TAB_ID = "projects";
|
|
10906
|
+
var isPaid = (p) => p.subscription === "active" || p.subscription === "past_due";
|
|
10907
|
+
function useLocalProjectTabs() {
|
|
10908
|
+
const [openProjectIds, setOpen] = useState([]);
|
|
10909
|
+
const [activeProjectId, setActive] = useState(null);
|
|
10910
|
+
return {
|
|
10911
|
+
openProjectIds,
|
|
10912
|
+
activeProjectId,
|
|
10913
|
+
onSelect: (id) => {
|
|
10914
|
+
if (id) setOpen((open) => open.includes(id) ? open : [...open, id]);
|
|
10915
|
+
setActive(id);
|
|
10916
|
+
},
|
|
10917
|
+
onClose: (id) => {
|
|
10918
|
+
setOpen((open) => open.filter((openId) => openId !== id));
|
|
10919
|
+
setActive((active) => active === id ? null : active);
|
|
10920
|
+
}
|
|
10921
|
+
};
|
|
10922
|
+
}
|
|
10923
|
+
function ConnectedProjectsPanel({
|
|
10924
|
+
tabs: hostTabs,
|
|
10925
|
+
projectStorage,
|
|
10926
|
+
footer,
|
|
10927
|
+
headerRight,
|
|
10928
|
+
className
|
|
10929
|
+
}) {
|
|
10930
|
+
const localTabs = useLocalProjectTabs();
|
|
10931
|
+
const tabs = hostTabs ?? localTabs;
|
|
10932
|
+
const { data: projects } = useProjects();
|
|
10933
|
+
const canCreateProjects = useCanCreateProjects();
|
|
10934
|
+
const { userId } = useConnectedWorkspace();
|
|
10935
|
+
const { stripeEnabled } = useBillingSupport();
|
|
10936
|
+
const billingPortal = useOpenBillingPortal();
|
|
10937
|
+
const [newProjectOpen, setNewProjectOpen] = useState(false);
|
|
10938
|
+
useAutoRefreshPendingProjects();
|
|
10939
|
+
const ownedCount = (projects ?? []).filter((p) => p.created_by === userId).length;
|
|
10940
|
+
const activeProjectId = tabs.activeProjectId && tabs.openProjectIds.includes(tabs.activeProjectId) ? tabs.activeProjectId : null;
|
|
10941
|
+
const headerTabs = useMemo(
|
|
10942
|
+
() => [
|
|
10943
|
+
{
|
|
10944
|
+
id: PROJECTS_BASE_TAB_ID,
|
|
10945
|
+
// Named by its job; "project" is for the per-project tabs, where owning several matters.
|
|
10946
|
+
label: "Plan & Usage",
|
|
10947
|
+
icon: /* @__PURE__ */ jsx(EntityIcon, { entityType: "PROJECT" }),
|
|
10948
|
+
// Most users own one project: a count only once there are several.
|
|
10949
|
+
count: ownedCount > 1 ? ownedCount : void 0
|
|
10950
|
+
},
|
|
10951
|
+
...tabs.openProjectIds.map((id) => ({
|
|
10952
|
+
id,
|
|
10953
|
+
label: projects?.find((p) => p.external_id === id)?.name ?? "Project",
|
|
10954
|
+
icon: /* @__PURE__ */ jsx(EntityIcon, { entityType: "PROJECT" }),
|
|
10955
|
+
onClose: () => tabs.onClose(id),
|
|
10956
|
+
closeTooltip: "Close project"
|
|
10957
|
+
}))
|
|
10958
|
+
],
|
|
10959
|
+
[ownedCount, tabs, projects]
|
|
10960
|
+
);
|
|
10961
|
+
const paidProject = projects?.find(isPaid);
|
|
10962
|
+
const panel = /* @__PURE__ */ jsxs(PanelFrame, { className, testId: "projects-panel", children: [
|
|
10963
|
+
/* @__PURE__ */ jsx(DraggableHeader, { children: /* @__PURE__ */ jsx(
|
|
10964
|
+
TabHeader,
|
|
10965
|
+
{
|
|
10966
|
+
tabs: headerTabs,
|
|
10967
|
+
activeTabId: activeProjectId ?? PROJECTS_BASE_TAB_ID,
|
|
10968
|
+
onTabChange: (id) => tabs.onSelect(id === PROJECTS_BASE_TAB_ID ? null : id),
|
|
10969
|
+
afterTabs: (isCompact) => /* @__PURE__ */ jsx(
|
|
10970
|
+
PanelAddButton,
|
|
10971
|
+
{
|
|
10972
|
+
label: "New project",
|
|
10973
|
+
onClick: () => setNewProjectOpen(true),
|
|
10974
|
+
icon: /* @__PURE__ */ jsx(Plus, { className: "size-4" }),
|
|
10975
|
+
isCompact,
|
|
10976
|
+
testId: "new-project-button",
|
|
10977
|
+
disabledReason: canCreateProjects === false ? PROJECT_CREATION_DENIED_REASON : void 0
|
|
10978
|
+
}
|
|
10979
|
+
),
|
|
10980
|
+
rightContent: headerRight,
|
|
10981
|
+
variant: "underline",
|
|
10982
|
+
compactBreakpoint: 360
|
|
10983
|
+
}
|
|
10984
|
+
) }),
|
|
10985
|
+
/* @__PURE__ */ jsx(PanelFrameBody, { children: activeProjectId ? /* @__PURE__ */ jsx(PanelScroll, { children: /* @__PURE__ */ jsx(
|
|
10986
|
+
ProjectDetail,
|
|
10987
|
+
{
|
|
10988
|
+
projectExtId: activeProjectId,
|
|
10989
|
+
storage: projectStorage?.(activeProjectId)
|
|
10990
|
+
}
|
|
10991
|
+
) }) : /* @__PURE__ */ jsxs(PanelScroll, { variant: "padded", children: [
|
|
10992
|
+
/* @__PURE__ */ jsx(ProjectsTable, {}),
|
|
10993
|
+
stripeEnabled && paidProject && /* @__PURE__ */ jsx(PanelActionsRow, { children: /* @__PURE__ */ jsxs(
|
|
10994
|
+
Button,
|
|
10995
|
+
{
|
|
10996
|
+
onClick: () => billingPortal.open(paidProject.external_id),
|
|
10997
|
+
size: "sm",
|
|
10998
|
+
variant: "outline",
|
|
10999
|
+
disabled: billingPortal.isPending,
|
|
11000
|
+
className: "flex items-center gap-1",
|
|
11001
|
+
children: [
|
|
11002
|
+
billingPortal.isPending ? "Opening\u2026" : "Billing portal",
|
|
11003
|
+
!billingPortal.isPending && /* @__PURE__ */ jsx(ExternalLink, { className: "h-3.5 w-3.5" })
|
|
11004
|
+
]
|
|
11005
|
+
}
|
|
11006
|
+
) }),
|
|
11007
|
+
/* @__PURE__ */ jsx(SharedProjects, {}),
|
|
11008
|
+
footer
|
|
11009
|
+
] }) }),
|
|
11010
|
+
/* @__PURE__ */ jsx(
|
|
11011
|
+
NewProjectFlow,
|
|
11012
|
+
{
|
|
11013
|
+
open: newProjectOpen,
|
|
11014
|
+
onOpenChange: setNewProjectOpen,
|
|
11015
|
+
defaultName: `Project ${(projects?.length ?? 0) + 1}`
|
|
11016
|
+
}
|
|
11017
|
+
)
|
|
11018
|
+
] });
|
|
11019
|
+
return hostTabs ? panel : /* @__PURE__ */ jsx(BlocksProvider, { openProject: localTabs.onSelect, children: panel });
|
|
11020
|
+
}
|
|
11021
|
+
|
|
11022
|
+
// src/connection/workspace-dashboard/dashboard-rows.ts
|
|
11023
|
+
var RECENT_ROWS = 5;
|
|
11024
|
+
var FACT_ROWS = 3;
|
|
11025
|
+
function shortDate(iso) {
|
|
11026
|
+
return new Date(iso).toLocaleDateString(void 0, { day: "numeric", month: "short" });
|
|
11027
|
+
}
|
|
11028
|
+
function timeAndDate(iso) {
|
|
11029
|
+
if (!iso) return "";
|
|
11030
|
+
const d = new Date(iso);
|
|
11031
|
+
if (Number.isNaN(d.getTime())) return "";
|
|
11032
|
+
const time2 = d.toLocaleTimeString(void 0, {
|
|
11033
|
+
hour: "2-digit",
|
|
11034
|
+
minute: "2-digit",
|
|
11035
|
+
hour12: false
|
|
11036
|
+
});
|
|
11037
|
+
return `${time2} \xB7 ${shortDate(iso)}`;
|
|
11038
|
+
}
|
|
11039
|
+
function humanizeStatus(status) {
|
|
11040
|
+
const words = status.replace(/[-_]/g, " ");
|
|
11041
|
+
return words.charAt(0).toUpperCase() + words.slice(1);
|
|
11042
|
+
}
|
|
11043
|
+
var time = (iso) => +new Date(iso ?? 0);
|
|
11044
|
+
function recentConversations(conversations) {
|
|
11045
|
+
return [...conversations].sort((a, b) => time(b.updated_at) - time(a.updated_at)).slice(0, RECENT_ROWS).map((c) => ({
|
|
11046
|
+
id: c.external_id,
|
|
11047
|
+
title: c.title?.trim() || "Untitled thread",
|
|
11048
|
+
subtitle: c.status ? [STATUS_LABELS[asTaskStatus(c.status)], c.due_at ? `due ${shortDate(c.due_at)}` : null].filter(Boolean).join(" \xB7 ") : `${c.message_count} ${c.message_count === 1 ? "message" : "messages"}`,
|
|
11049
|
+
time: timeAndDate(c.updated_at)
|
|
11050
|
+
}));
|
|
11051
|
+
}
|
|
11052
|
+
function recentDocuments(documents) {
|
|
11053
|
+
return [...documents].sort((a, b) => time(b.updated_at ?? b.created_at) - time(a.updated_at ?? a.created_at)).slice(0, RECENT_ROWS).map((d) => ({
|
|
11054
|
+
id: d.external_id,
|
|
11055
|
+
fileName: d.file_name,
|
|
11056
|
+
title: d.file_name || "Untitled document",
|
|
11057
|
+
subtitle: d.status && d.status !== "ready" && d.status !== "completed" ? humanizeStatus(d.status) : d.n_pages ? `${d.n_pages} ${d.n_pages === 1 ? "page" : "pages"}` : d.file_type ?? "Document",
|
|
11058
|
+
time: timeAndDate(d.updated_at ?? d.created_at)
|
|
11059
|
+
}));
|
|
11060
|
+
}
|
|
11061
|
+
function splitFacts(facts, now = /* @__PURE__ */ new Date()) {
|
|
11062
|
+
const startOfToday = new Date(now);
|
|
11063
|
+
startOfToday.setHours(0, 0, 0, 0);
|
|
11064
|
+
const dated = facts.filter((f) => f.date_start && new Date(f.date_start) >= startOfToday).sort((a, b) => time(a.date_start) - time(b.date_start)).slice(0, FACT_ROWS);
|
|
11065
|
+
const datedIds = new Set(dated.map((f) => f.external_id));
|
|
11066
|
+
const rest = facts.filter((f) => !datedIds.has(f.external_id)).sort((a, b) => time(b.created_at) - time(a.created_at)).slice(0, FACT_ROWS);
|
|
11067
|
+
const row = (f, stamp) => ({
|
|
11068
|
+
id: f.external_id,
|
|
11069
|
+
title: f.text,
|
|
11070
|
+
time: stamp
|
|
11071
|
+
});
|
|
11072
|
+
return {
|
|
11073
|
+
upcoming: dated.map((f) => row(f, f.date_start ? shortDate(f.date_start) : "")),
|
|
11074
|
+
recent: rest.map((f) => row(f, timeAndDate(f.created_at)))
|
|
11075
|
+
};
|
|
11076
|
+
}
|
|
11077
|
+
function ConnectedWorkspaceDashboard({
|
|
11078
|
+
actions,
|
|
11079
|
+
start,
|
|
11080
|
+
addFilesAction,
|
|
11081
|
+
aside,
|
|
11082
|
+
testId = "workspace-dashboard"
|
|
11083
|
+
}) {
|
|
11084
|
+
const { openDocument, openConversation } = useBlocksEnvironment();
|
|
11085
|
+
const { workspaceId } = useConnectedWorkspace();
|
|
11086
|
+
const { data: documents } = useConnectedDocuments();
|
|
11087
|
+
const { data: conversations } = useConnectedConversations();
|
|
11088
|
+
const { data: facts = [] } = useFacts(workspaceId);
|
|
11089
|
+
const conversationIcon = /* @__PURE__ */ jsx(EntityIcon, { entityType: "CONVERSATION", className: "mt-0.5 size-5 shrink-0" });
|
|
11090
|
+
const chatRows = useMemo(
|
|
11091
|
+
() => recentConversations(conversations).map((row) => ({
|
|
11092
|
+
...row,
|
|
11093
|
+
leading: conversationIcon,
|
|
11094
|
+
href: workspaceId ? buildDeepLinkPath({ workspaceId, conversationId: row.id }) : void 0,
|
|
11095
|
+
onSelect: () => openConversation(row.id)
|
|
11096
|
+
})),
|
|
11097
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11098
|
+
[conversations, workspaceId, openConversation]
|
|
11099
|
+
);
|
|
11100
|
+
const docRows = useMemo(
|
|
11101
|
+
() => recentDocuments(documents).map(({ fileName, ...row }) => ({
|
|
11102
|
+
...row,
|
|
11103
|
+
// The file-type mark, bare: it carries its own identity.
|
|
11104
|
+
leading: /* @__PURE__ */ jsx("span", { className: "mt-0.5 shrink-0", children: getDocIcon(fileName, 20) }),
|
|
11105
|
+
href: workspaceId ? buildDeepLinkPath({ workspaceId, documentId: row.id }) : void 0,
|
|
11106
|
+
onSelect: () => openDocument(row.id)
|
|
11107
|
+
})),
|
|
11108
|
+
[documents, workspaceId, openDocument]
|
|
11109
|
+
);
|
|
11110
|
+
const { upcoming, recent } = useMemo(() => {
|
|
11111
|
+
const { upcoming: upcoming2, recent: recent2 } = splitFacts(facts);
|
|
11112
|
+
const toRow = (row) => ({
|
|
11113
|
+
...row,
|
|
11114
|
+
leading: /* @__PURE__ */ jsx(FactMark, {}),
|
|
11115
|
+
// The item, not the list: the Facts page scrolls to this fact.
|
|
11116
|
+
onSelect: () => actions.openFact(row.id)
|
|
11117
|
+
});
|
|
11118
|
+
return { upcoming: upcoming2.map(toRow), recent: recent2.map(toRow) };
|
|
11119
|
+
}, [facts, actions]);
|
|
11120
|
+
return /* @__PURE__ */ jsxs(DashboardRoot, { testId, children: [
|
|
11121
|
+
start && /* @__PURE__ */ jsx(DashboardBand, { kind: "start", children: start }),
|
|
11122
|
+
/* @__PURE__ */ jsxs(DashboardBand, { kind: "recent", children: [
|
|
11123
|
+
/* @__PURE__ */ jsx(SectionLabel, { testId: `${testId}-recent-caption`, children: "Recent" }),
|
|
11124
|
+
/* @__PURE__ */ jsxs(DashboardColumns, { children: [
|
|
11125
|
+
/* @__PURE__ */ jsx(
|
|
11126
|
+
RecentList,
|
|
11127
|
+
{
|
|
11128
|
+
testId: `${testId}-docs`,
|
|
11129
|
+
icon: FileText,
|
|
11130
|
+
title: getEntityLabel("DOCUMENT", "PLURAL"),
|
|
11131
|
+
count: documents.length,
|
|
11132
|
+
onOpen: () => actions.openSection("documents"),
|
|
11133
|
+
action: addFilesAction,
|
|
11134
|
+
rows: docRows,
|
|
11135
|
+
caption: "Added",
|
|
11136
|
+
empty: {
|
|
11137
|
+
icon: Upload,
|
|
11138
|
+
label: "Add files or emails",
|
|
11139
|
+
description: "From your computer, a web link, or a connected mailbox.",
|
|
11140
|
+
onSelect: actions.addFiles
|
|
11141
|
+
}
|
|
11142
|
+
}
|
|
11143
|
+
),
|
|
11144
|
+
/* @__PURE__ */ jsx(
|
|
11145
|
+
RecentList,
|
|
11146
|
+
{
|
|
11147
|
+
testId: `${testId}-chats`,
|
|
11148
|
+
icon: MessagesSquare,
|
|
11149
|
+
title: getEntityLabel("CONVERSATION", "PLURAL"),
|
|
11150
|
+
count: conversations.length,
|
|
11151
|
+
onOpen: () => actions.openSection("threads"),
|
|
11152
|
+
action: (
|
|
11153
|
+
// Quiet like every section action: the Start band is the page's first job.
|
|
11154
|
+
/* @__PURE__ */ jsx(
|
|
11155
|
+
DashboardAction,
|
|
11156
|
+
{
|
|
11157
|
+
emphasis: "quiet",
|
|
11158
|
+
icon: /* @__PURE__ */ jsx(Plus, { className: "size-4" }),
|
|
11159
|
+
label: "New",
|
|
11160
|
+
onClick: actions.newThread,
|
|
11161
|
+
testId: `${testId}-chats-new`
|
|
11162
|
+
}
|
|
11163
|
+
)
|
|
11164
|
+
),
|
|
11165
|
+
rows: chatRows,
|
|
11166
|
+
caption: "Messaged",
|
|
11167
|
+
empty: {
|
|
11168
|
+
icon: Plus,
|
|
11169
|
+
label: "Ask ARBI anything",
|
|
11170
|
+
description: "Questions are answered from this workspace's files.",
|
|
11171
|
+
onSelect: actions.ask
|
|
11172
|
+
}
|
|
11173
|
+
}
|
|
11174
|
+
)
|
|
11175
|
+
] })
|
|
11176
|
+
] }),
|
|
11177
|
+
/* @__PURE__ */ jsxs(DashboardColumns, { children: [
|
|
11178
|
+
/* @__PURE__ */ jsx(
|
|
11179
|
+
FactsStrip,
|
|
11180
|
+
{
|
|
11181
|
+
testId: `${testId}-facts`,
|
|
11182
|
+
icon: Milestone,
|
|
11183
|
+
title: getEntityLabel("FACT", "PLURAL"),
|
|
11184
|
+
count: facts.length,
|
|
11185
|
+
onOpen: () => actions.openSection("facts"),
|
|
11186
|
+
action: /* @__PURE__ */ jsx(
|
|
11187
|
+
DashboardAction,
|
|
11188
|
+
{
|
|
11189
|
+
emphasis: "quiet",
|
|
11190
|
+
icon: /* @__PURE__ */ jsx(Plus, { className: "size-4" }),
|
|
11191
|
+
label: "New fact",
|
|
11192
|
+
onClick: actions.newFact,
|
|
11193
|
+
testId: `${testId}-facts-action`
|
|
11194
|
+
}
|
|
11195
|
+
),
|
|
11196
|
+
groups: [
|
|
11197
|
+
{ caption: "Upcoming", rows: upcoming, rowTestId: `${testId}-facts-upcoming-row` },
|
|
11198
|
+
{ caption: "Created", rows: recent, rowTestId: `${testId}-facts-row` }
|
|
11199
|
+
],
|
|
11200
|
+
empty: {
|
|
11201
|
+
icon: Milestone,
|
|
11202
|
+
label: `Add your first ${getEntityLabel("FACT").toLowerCase()}`,
|
|
11203
|
+
description: "A date, a decision, a preference \u2014 anything worth remembering.",
|
|
11204
|
+
onSelect: actions.newFact,
|
|
11205
|
+
testId: `${testId}-facts-empty-action`
|
|
11206
|
+
}
|
|
11207
|
+
}
|
|
11208
|
+
),
|
|
11209
|
+
aside
|
|
11210
|
+
] })
|
|
11211
|
+
] });
|
|
11212
|
+
}
|
|
10649
11213
|
var DEFAULT_SEARCH_ROW_LABELS = {
|
|
10650
11214
|
meaningMatch: "Matched by meaning",
|
|
10651
11215
|
meaningMatchTitle: "None of your search words appear in this passage. It matched by meaning.",
|
|
@@ -15014,7 +15578,7 @@ function subscribePhone(cb) {
|
|
|
15014
15578
|
return () => mq?.removeEventListener?.("change", cb);
|
|
15015
15579
|
}
|
|
15016
15580
|
var isPhoneNow = () => typeof window !== "undefined" && !!window.matchMedia?.(PHONE_QUERY)?.matches;
|
|
15017
|
-
function
|
|
15581
|
+
function useIsPhone2() {
|
|
15018
15582
|
return useSyncExternalStore(subscribePhone, isPhoneNow, () => false);
|
|
15019
15583
|
}
|
|
15020
15584
|
var errorText3 = (err) => describeCalendarError(err);
|
|
@@ -15036,7 +15600,7 @@ function ConnectedCalendar({
|
|
|
15036
15600
|
const arbi = useArbi();
|
|
15037
15601
|
const fetchEvent = useFetchCalendarEvent();
|
|
15038
15602
|
const notifyError = (prefix, err) => notify14(`${prefix}: ${errorText3(err)}`, "error");
|
|
15039
|
-
const isPhone =
|
|
15603
|
+
const isPhone = useIsPhone2();
|
|
15040
15604
|
const { data: settingsData } = useCalendarSettings();
|
|
15041
15605
|
const settings = settingsData ?? FALLBACK_SETTINGS;
|
|
15042
15606
|
const zone = safeZone(settings.time_zone, detectTimeZone());
|
|
@@ -16318,6 +16882,6 @@ function ConnectedAgentChatPanel({
|
|
|
16318
16882
|
] });
|
|
16319
16883
|
}
|
|
16320
16884
|
|
|
16321
|
-
export { AddAddonDialog, ArbiAppProvider, BACKFILL_OPTIONS, BillingProjectEntity,
|
|
16885
|
+
export { AddAddonDialog, ArbiAppProvider, BACKFILL_OPTIONS, BillingProjectEntity, ChangePlanDialog, ConnectedAccountSettings, ConnectedAgentChatPanel, ConnectedAgentCreator, ConnectedAppsSettings, ConnectedCalendar, ConnectedDangerZone, ConnectedDriveSyncDialog, ConnectedFactsPage, ConnectedIdentityVerification, ConnectedLogoutDialog, ConnectedMailAccounts, ConnectedMailComposer, ConnectedMailInviteCard, ConnectedMailMessage, ConnectedMailSettings, ConnectedMailSetup, ConnectedMailbox, ConnectedMailboxSyncDialog, ConnectedNotificationCenter, ConnectedNotificationPreferences, ConnectedPasswordChangeDialog, ConnectedPremiumModels, ConnectedPrivacySettings, ConnectedProfileCard, ConnectedProjectsPanel, ConnectedPublicBooking, ConnectedRequireVerified, ConnectedSearchPage, ConnectedSecuritySection, ConnectedSessionsRow, ConnectedSettingsPage, ConnectedSkillUpload, ConnectedSkillsLibrary, ConnectedTagTable, ConnectedTagsPage, ConnectedTaskAccessRequest, ConnectedTaskActivityDialog, ConnectedThreadFollow, ConnectedUpcomingEvents, ConnectedWorkflowHistory, ConnectedWorkflowRunner, ConnectedWorkspaceActivity, ConnectedWorkspaceDashboard, ConnectedWorkspaceList, ConnectedWorkspaceMembers, ConnectedWorkspaceNotificationMenu, ConnectedWorkspaceSettings, DEFAULT_CONNECTED_SEARCH_PAGE_LABELS, DEFAULT_CONNECTED_SKILL_UPLOAD_LABELS, DEFAULT_CONNECTED_WORKFLOW_RUNNER_LABELS, DEFAULT_SEARCH_ROW_LABELS, DEFAULT_SETTINGS_SECTIONS, DEFAULT_TIMELINE_LABEL_WIDTH, DEFAULT_WORKSPACE_LIST_LABELS, FACTS_GRID_ID, InvoicesModal, NewProjectFlow, NotificationCenter, NotificationEvent, PROJECTS_BASE_TAB_ID, ProjectDetail, ProjectsTable, REFERRAL_OFFER, SETTINGS_SECTION_IDS, SessionStatusIcon, SharedProjects, StreamedArtifact, WORKSPACES_TAB_ID, WorkflowRunThread, accountSettingsSection, bookingCancelLink, buildNotificationCenterItems, chatSettingsSection, connectedAppsSettingsSection, countNotificationTypes, defaultUnmetPasswordRequirement, filterNotificationCenterItems, formatLastSync, mailSettingsSection, openMeetingLink, privacySettingsSection, renderSessionStatusIcon, requestCalendarComposer, requestCalendarEvent, requestProjectBillingFocus, resolveMailbox, toWorkspaceSummary, useAutoRefreshPendingProjects, useCalendarViewStore, useConnectedDocxNotifications, useConnectedShellWorkspaces, useConnectedWorkNotifications, useConnectedWorkspaceList, useConnectedWorkspaceSettings, useOpenBillingPortal, useProjectBillingFocus, useReferralReward, windowLabel, workflowRunView };
|
|
16322
16886
|
//# sourceMappingURL=index.js.map
|
|
16323
16887
|
//# sourceMappingURL=index.js.map
|