@vertesia/ui 1.0.0 → 1.1.0-dev.20260427.060440Z
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/lib/esm/core/components/ComboBox.js +23 -24
- package/lib/esm/core/components/ComboBox.js.map +1 -1
- package/lib/esm/core/components/FormItem.js +2 -2
- package/lib/esm/core/components/FormItem.js.map +1 -1
- package/lib/esm/core/components/SidePanel.js +1 -1
- package/lib/esm/core/components/SidePanel.js.map +1 -1
- package/lib/esm/core/components/shadcn/collaspible.js +3 -4
- package/lib/esm/core/components/shadcn/collaspible.js.map +1 -1
- package/lib/esm/core/components/shadcn/dropdown.js +37 -12
- package/lib/esm/core/components/shadcn/dropdown.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/comboBox/DateCombobox.js +6 -6
- package/lib/esm/core/components/shadcn/filters/comboBox/DateCombobox.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js +5 -3
- package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/esm/core/components/shadcn/radioGroup.js +1 -2
- package/lib/esm/core/components/shadcn/radioGroup.js.map +1 -1
- package/lib/esm/core/components/shadcn/switch.js +0 -1
- package/lib/esm/core/components/shadcn/switch.js.map +1 -1
- package/lib/esm/core/components/shadcn/tabs.js +2 -2
- package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
- package/lib/esm/core/components/shadcn/tooltip.js +17 -1
- package/lib/esm/core/components/shadcn/tooltip.js.map +1 -1
- package/lib/esm/core/hooks/PortalContainerProvider.js +9 -3
- package/lib/esm/core/hooks/PortalContainerProvider.js.map +1 -1
- package/lib/esm/env/index.js +5 -8
- package/lib/esm/env/index.js.map +1 -1
- package/lib/esm/features/agent/chat/AgentRightPanel.js +21 -11
- package/lib/esm/features/agent/chat/AgentRightPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/AskUserWidget.js +2 -6
- package/lib/esm/features/agent/chat/AskUserWidget.js.map +1 -1
- package/lib/esm/features/agent/chat/DocumentPanel.js +8 -5
- package/lib/esm/features/agent/chat/DocumentPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/DocumentTabBar.js +5 -13
- package/lib/esm/features/agent/chat/DocumentTabBar.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentConversation.js +57 -26
- package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +20 -16
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +56 -45
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/esm/features/agent/chat/SlidingThinkingIndicator.js +3 -9
- package/lib/esm/features/agent/chat/SlidingThinkingIndicator.js.map +1 -1
- package/lib/esm/features/agent/chat/hooks/useAgentStream.js +9 -5
- package/lib/esm/features/agent/chat/hooks/useAgentStream.js.map +1 -1
- package/lib/esm/features/agent/chat/hooks/useDocumentPanel.js +4 -0
- package/lib/esm/features/agent/chat/hooks/useDocumentPanel.js.map +1 -1
- package/lib/esm/features/facets/AgentRunnerFacetsNav.js +1 -1
- package/lib/esm/features/facets/AgentRunnerFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/DocumentsFacetsNav.js +3 -2
- package/lib/esm/features/facets/DocumentsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/RunsFacetsNav.js +8 -1
- package/lib/esm/features/facets/RunsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/WorkflowExecutionsFacetsNav.js +1 -1
- package/lib/esm/features/facets/WorkflowExecutionsFacetsNav.js.map +1 -1
- package/lib/esm/features/facets/index.js +1 -0
- package/lib/esm/features/facets/index.js.map +1 -1
- package/lib/esm/features/facets/utils/VInteractionFacet.js +5 -5
- package/lib/esm/features/facets/utils/VInteractionFacet.js.map +1 -1
- package/lib/esm/features/index.js +1 -0
- package/lib/esm/features/index.js.map +1 -1
- package/lib/esm/features/oauth/OAuthProviderConnectButton.js +85 -0
- package/lib/esm/features/oauth/OAuthProviderConnectButton.js.map +1 -0
- package/lib/esm/features/oauth/RemoteMcpConnectionButton.js +119 -0
- package/lib/esm/features/oauth/RemoteMcpConnectionButton.js.map +1 -0
- package/lib/esm/features/oauth/index.js +4 -0
- package/lib/esm/features/oauth/index.js.map +1 -0
- package/lib/esm/features/oauth/useOAuthPopup.js +89 -0
- package/lib/esm/features/oauth/useOAuthPopup.js.map +1 -0
- package/lib/esm/features/store/collections/BrowseCollectionView.js.map +1 -1
- package/lib/esm/features/store/collections/EditCollectionView.js +9 -2
- package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/esm/features/store/objects/components/ContentOverview.js +19 -7
- package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js +35 -15
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js.map +1 -1
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js +3 -3
- package/lib/esm/features/store/objects/selection/ObjectsActionContext.js.map +1 -1
- package/lib/esm/features/store/objects/selection/SelectionActions.js +4 -3
- package/lib/esm/features/store/objects/selection/SelectionActions.js.map +1 -1
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js +11 -3
- package/lib/esm/features/store/objects/selection/actions/ExportPropertiesAction.js.map +1 -1
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js +1 -5
- package/lib/esm/features/store/objects/upload/DocumentUploadModal.js.map +1 -1
- package/lib/esm/features/user/UserInfo.js +33 -10
- package/lib/esm/features/user/UserInfo.js.map +1 -1
- package/lib/esm/i18n/locales/ar.json +81 -98
- package/lib/esm/i18n/locales/de.json +44 -73
- package/lib/esm/i18n/locales/en.json +31 -61
- package/lib/esm/i18n/locales/es.json +55 -79
- package/lib/esm/i18n/locales/fr.json +55 -81
- package/lib/esm/i18n/locales/it.json +55 -79
- package/lib/esm/i18n/locales/ja.json +46 -75
- package/lib/esm/i18n/locales/ko.json +44 -73
- package/lib/esm/i18n/locales/pt.json +55 -79
- package/lib/esm/i18n/locales/ru.json +58 -81
- package/lib/esm/i18n/locales/tr.json +46 -75
- package/lib/esm/i18n/locales/zh-TW.json +46 -75
- package/lib/esm/i18n/locales/zh.json +46 -75
- package/lib/esm/session/UserSession.js +2 -4
- package/lib/esm/session/UserSession.js.map +1 -1
- package/lib/esm/session/UserSessionProvider.js +22 -17
- package/lib/esm/session/UserSessionProvider.js.map +1 -1
- package/lib/esm/session/auth/composable.js +20 -2
- package/lib/esm/session/auth/composable.js.map +1 -1
- package/lib/esm/session/auth/domainRouting.js +7 -0
- package/lib/esm/session/auth/domainRouting.js.map +1 -0
- package/lib/esm/shell/login/InviteAcceptModal.js +1 -0
- package/lib/esm/shell/login/InviteAcceptModal.js.map +1 -1
- package/lib/esm/widgets/form/Form.js +2 -2
- package/lib/esm/widgets/form/Form.js.map +1 -1
- package/lib/esm/widgets/markdown/MarkdownRenderer.js +2 -1
- package/lib/esm/widgets/markdown/MarkdownRenderer.js.map +1 -1
- package/lib/esm/widgets/markdown/preprocessMathDelimiters.js +226 -0
- package/lib/esm/widgets/markdown/preprocessMathDelimiters.js.map +1 -0
- package/lib/esm/widgets/monacoEditor/MonacoEditor.js +40 -5
- package/lib/esm/widgets/monacoEditor/MonacoEditor.js.map +1 -1
- package/lib/esm/widgets/monacoEditor/foldingProviders.js +132 -0
- package/lib/esm/widgets/monacoEditor/foldingProviders.js.map +1 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core/components/ComboBox.d.ts +12 -2
- package/lib/types/core/components/ComboBox.d.ts.map +1 -1
- package/lib/types/core/components/FormItem.d.ts +5 -2
- package/lib/types/core/components/FormItem.d.ts.map +1 -1
- package/lib/types/core/components/SidePanel.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/badge.d.ts +2 -2
- package/lib/types/core/components/shadcn/collaspible.d.ts +3 -3
- package/lib/types/core/components/shadcn/collaspible.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/dropdown.d.ts +11 -3
- package/lib/types/core/components/shadcn/dropdown.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/filters/filterBar.d.ts +2 -1
- package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/input.d.ts +1 -1
- package/lib/types/core/components/shadcn/radioGroup.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/switch.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/tabs.d.ts +4 -2
- package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/text.d.ts +1 -1
- package/lib/types/core/components/shadcn/tooltip.d.ts +1 -1
- package/lib/types/core/components/shadcn/tooltip.d.ts.map +1 -1
- package/lib/types/core/hooks/PortalContainerProvider.d.ts +1 -0
- package/lib/types/core/hooks/PortalContainerProvider.d.ts.map +1 -1
- package/lib/types/env/index.d.ts +2 -2
- package/lib/types/env/index.d.ts.map +1 -1
- package/lib/types/features/agent/chat/AgentChart.d.ts +1 -1
- package/lib/types/features/agent/chat/AgentChart.d.ts.map +1 -1
- package/lib/types/features/agent/chat/AgentRightPanel.d.ts +7 -2
- package/lib/types/features/agent/chat/AgentRightPanel.d.ts.map +1 -1
- package/lib/types/features/agent/chat/DocumentPanel.d.ts +2 -2
- package/lib/types/features/agent/chat/DocumentPanel.d.ts.map +1 -1
- package/lib/types/features/agent/chat/DocumentTabBar.d.ts +1 -2
- package/lib/types/features/agent/chat/DocumentTabBar.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts +5 -3
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +4 -2
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts +4 -4
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/types/features/agent/chat/VegaLiteChart.d.ts +1 -1
- package/lib/types/features/agent/chat/VegaLiteChart.d.ts.map +1 -1
- package/lib/types/features/agent/chat/hooks/useAgentStream.d.ts +4 -2
- package/lib/types/features/agent/chat/hooks/useAgentStream.d.ts.map +1 -1
- package/lib/types/features/agent/chat/hooks/useDocumentPanel.d.ts +1 -0
- package/lib/types/features/agent/chat/hooks/useDocumentPanel.d.ts.map +1 -1
- package/lib/types/features/facets/DocumentsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/facets/RunsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/facets/index.d.ts +1 -0
- package/lib/types/features/facets/index.d.ts.map +1 -1
- package/lib/types/features/index.d.ts +1 -0
- package/lib/types/features/index.d.ts.map +1 -1
- package/lib/types/features/oauth/OAuthProviderConnectButton.d.ts +11 -0
- package/lib/types/features/oauth/OAuthProviderConnectButton.d.ts.map +1 -0
- package/lib/types/features/oauth/RemoteMcpConnectionButton.d.ts +25 -0
- package/lib/types/features/oauth/RemoteMcpConnectionButton.d.ts.map +1 -0
- package/lib/types/features/oauth/index.d.ts +4 -0
- package/lib/types/features/oauth/index.d.ts.map +1 -0
- package/lib/types/features/oauth/useOAuthPopup.d.ts +12 -0
- package/lib/types/features/oauth/useOAuthPopup.d.ts.map +1 -0
- package/lib/types/features/store/collections/BrowseCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts +3 -3
- package/lib/types/features/store/objects/selection/ObjectsActionContext.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/ObjectsActionSpec.d.ts +2 -1
- package/lib/types/features/store/objects/selection/ObjectsActionSpec.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/SelectionActions.d.ts +3 -3
- package/lib/types/features/store/objects/selection/SelectionActions.d.ts.map +1 -1
- package/lib/types/features/store/objects/selection/actions/ExportPropertiesAction.d.ts.map +1 -1
- package/lib/types/features/user/UserInfo.d.ts +2 -1
- package/lib/types/features/user/UserInfo.d.ts.map +1 -1
- package/lib/types/session/UserSession.d.ts.map +1 -1
- package/lib/types/session/UserSessionProvider.d.ts +0 -1
- package/lib/types/session/UserSessionProvider.d.ts.map +1 -1
- package/lib/types/session/auth/composable.d.ts +4 -0
- package/lib/types/session/auth/composable.d.ts.map +1 -1
- package/lib/types/session/auth/domainRouting.d.ts +8 -0
- package/lib/types/session/auth/domainRouting.d.ts.map +1 -0
- package/lib/types/shell/login/InviteAcceptModal.d.ts.map +1 -1
- package/lib/types/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
- package/lib/types/widgets/markdown/preprocessMathDelimiters.d.ts +24 -0
- package/lib/types/widgets/markdown/preprocessMathDelimiters.d.ts.map +1 -0
- package/lib/types/widgets/monacoEditor/MonacoEditor.d.ts +2 -1
- package/lib/types/widgets/monacoEditor/MonacoEditor.d.ts.map +1 -1
- package/lib/types/widgets/monacoEditor/foldingProviders.d.ts +2 -0
- package/lib/types/widgets/monacoEditor/foldingProviders.d.ts.map +1 -0
- package/lib/vertesia-ui-core.js +1 -1
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +1 -1
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-i18n.js +1 -1
- package/lib/vertesia-ui-i18n.js.map +1 -1
- package/lib/vertesia-ui-layout.js +1 -1
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +1 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +15 -15
- package/src/core/components/ComboBox.tsx +66 -29
- package/src/core/components/FormItem.tsx +9 -6
- package/src/core/components/SidePanel.tsx +5 -3
- package/src/core/components/shadcn/collaspible.tsx +5 -7
- package/src/core/components/shadcn/dropdown.tsx +68 -13
- package/src/core/components/shadcn/filters/comboBox/DateCombobox.tsx +6 -6
- package/src/core/components/shadcn/filters/filterBar.tsx +5 -3
- package/src/core/components/shadcn/radioGroup.tsx +1 -3
- package/src/core/components/shadcn/switch.tsx +0 -2
- package/src/core/components/shadcn/tabs.tsx +15 -2
- package/src/core/components/shadcn/tooltip.tsx +20 -3
- package/src/core/hooks/PortalContainerProvider.tsx +11 -3
- package/src/env/index.ts +7 -10
- package/src/features/agent/chat/AgentRightPanel.tsx +43 -23
- package/src/features/agent/chat/DocumentPanel.tsx +21 -19
- package/src/features/agent/chat/DocumentTabBar.tsx +21 -32
- package/src/features/agent/chat/ModernAgentConversation.tsx +72 -27
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +21 -9
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +136 -115
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +0 -3
- package/src/features/agent/chat/hooks/useAgentStream.ts +13 -7
- package/src/features/agent/chat/hooks/useDocumentPanel.ts +8 -0
- package/src/features/facets/AgentRunnerFacetsNav.tsx +1 -1
- package/src/features/facets/DocumentsFacetsNav.tsx +3 -1
- package/src/features/facets/RunsFacetsNav.tsx +9 -1
- package/src/features/facets/WorkflowExecutionsFacetsNav.tsx +1 -1
- package/src/features/facets/index.ts +1 -0
- package/src/features/facets/utils/VInteractionFacet.tsx +12 -12
- package/src/features/index.ts +1 -0
- package/src/features/oauth/OAuthProviderConnectButton.tsx +125 -0
- package/src/features/oauth/RemoteMcpConnectionButton.tsx +274 -0
- package/src/features/oauth/index.ts +3 -0
- package/src/features/oauth/useOAuthPopup.ts +125 -0
- package/src/features/store/collections/BrowseCollectionView.tsx +3 -3
- package/src/features/store/collections/EditCollectionView.tsx +10 -1
- package/src/features/store/objects/components/ContentOverview.tsx +108 -87
- package/src/features/store/objects/components/useContentPanelHooks.ts +50 -15
- package/src/features/store/objects/selection/ObjectsActionContext.tsx +5 -5
- package/src/features/store/objects/selection/ObjectsActionSpec.ts +2 -1
- package/src/features/store/objects/selection/SelectionActions.tsx +6 -5
- package/src/features/store/objects/selection/actions/ExportPropertiesAction.tsx +12 -3
- package/src/features/user/UserInfo.tsx +82 -10
- package/src/i18n/locales/ar.json +81 -98
- package/src/i18n/locales/de.json +44 -73
- package/src/i18n/locales/en.json +31 -61
- package/src/i18n/locales/es.json +55 -79
- package/src/i18n/locales/fr.json +55 -81
- package/src/i18n/locales/it.json +55 -79
- package/src/i18n/locales/ja.json +46 -75
- package/src/i18n/locales/ko.json +44 -73
- package/src/i18n/locales/pt.json +55 -79
- package/src/i18n/locales/ru.json +58 -81
- package/src/i18n/locales/tr.json +46 -75
- package/src/i18n/locales/zh-TW.json +46 -75
- package/src/i18n/locales/zh.json +46 -75
- package/src/session/UserSession.ts +2 -5
- package/src/session/UserSessionProvider.tsx +23 -18
- package/src/session/auth/auth-flow.md +1 -1
- package/src/session/auth/composable.ts +21 -2
- package/src/session/auth/domainRouting.test.ts +26 -0
- package/src/session/auth/domainRouting.ts +13 -0
- package/src/shell/login/InviteAcceptModal.tsx +1 -0
- package/src/widgets/form/Form.tsx +2 -2
- package/src/widgets/markdown/MarkdownRenderer.tsx +2 -1
- package/src/widgets/markdown/markdown.css +12 -0
- package/src/widgets/markdown/preprocessMathDelimiters.test.ts +87 -0
- package/src/widgets/markdown/preprocessMathDelimiters.ts +229 -0
- package/src/widgets/monacoEditor/MonacoEditor.tsx +47 -4
- package/src/widgets/monacoEditor/foldingProviders.ts +122 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { OAuthProviderAuthStatus } from '@vertesia/common';
|
|
2
|
+
import { useUserSession } from '@vertesia/ui/session';
|
|
3
|
+
import { CheckCircle2, ExternalLink } from 'lucide-react';
|
|
4
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
5
|
+
import { Button, Spinner } from '../../core/index.js';
|
|
6
|
+
import { useUITranslation } from '../../i18n/index.js';
|
|
7
|
+
import { useOAuthPopup } from './useOAuthPopup.js';
|
|
8
|
+
|
|
9
|
+
interface OAuthProviderConnectButtonProps {
|
|
10
|
+
oauthProviderId: string;
|
|
11
|
+
onAuthChange?: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Connect button for generic OAuth Providers (not MCP-specific).
|
|
16
|
+
* Uses the OAuth Providers API for authorize/status/disconnect.
|
|
17
|
+
*/
|
|
18
|
+
export function OAuthProviderConnectButton({ oauthProviderId, onAuthChange }: OAuthProviderConnectButtonProps) {
|
|
19
|
+
const { client } = useUserSession();
|
|
20
|
+
const { t } = useUITranslation();
|
|
21
|
+
const [status, setStatus] = useState<OAuthProviderAuthStatus | null>(null);
|
|
22
|
+
const [loading, setLoading] = useState(true);
|
|
23
|
+
const [authenticating, setAuthenticating] = useState(false);
|
|
24
|
+
const [disconnecting, setDisconnecting] = useState(false);
|
|
25
|
+
|
|
26
|
+
const loadStatus = useCallback(async () => {
|
|
27
|
+
try {
|
|
28
|
+
setLoading(true);
|
|
29
|
+
const data = await client.oauthProviders.getStatus(oauthProviderId);
|
|
30
|
+
setStatus(data);
|
|
31
|
+
} catch (err: unknown) {
|
|
32
|
+
console.error('Failed to load OAuth provider status:', err);
|
|
33
|
+
} finally {
|
|
34
|
+
setLoading(false);
|
|
35
|
+
}
|
|
36
|
+
}, [client, oauthProviderId]);
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
loadStatus();
|
|
40
|
+
}, [loadStatus]);
|
|
41
|
+
|
|
42
|
+
const { openOAuthPopup } = useOAuthPopup({
|
|
43
|
+
onComplete: () => {
|
|
44
|
+
setAuthenticating(false);
|
|
45
|
+
loadStatus();
|
|
46
|
+
onAuthChange?.();
|
|
47
|
+
},
|
|
48
|
+
onError: (error) => {
|
|
49
|
+
console.error('OAuth provider auth failed:', error);
|
|
50
|
+
setAuthenticating(false);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const handleConnect = async () => {
|
|
55
|
+
if (authenticating) return;
|
|
56
|
+
try {
|
|
57
|
+
setAuthenticating(true);
|
|
58
|
+
const response = await client.oauthProviders.authorize(oauthProviderId);
|
|
59
|
+
if (response.authorization_url) {
|
|
60
|
+
openOAuthPopup(response.authorization_url);
|
|
61
|
+
}
|
|
62
|
+
} catch (err: unknown) {
|
|
63
|
+
console.error('Failed to authorize OAuth provider:', err);
|
|
64
|
+
setAuthenticating(false);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const handleDisconnect = async () => {
|
|
69
|
+
if (disconnecting) return;
|
|
70
|
+
try {
|
|
71
|
+
setDisconnecting(true);
|
|
72
|
+
await client.oauthProviders.disconnect(oauthProviderId);
|
|
73
|
+
await loadStatus();
|
|
74
|
+
onAuthChange?.();
|
|
75
|
+
} catch (err: unknown) {
|
|
76
|
+
console.error('Failed to disconnect OAuth provider:', err);
|
|
77
|
+
} finally {
|
|
78
|
+
setDisconnecting(false);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
if (loading) {
|
|
83
|
+
return <Spinner className="size-4" />;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (status?.authenticated) {
|
|
87
|
+
return (
|
|
88
|
+
<div className="flex items-center gap-2">
|
|
89
|
+
<div className="flex items-center gap-1 text-success text-sm">
|
|
90
|
+
<CheckCircle2 className="size-4" />
|
|
91
|
+
<span>{t('oauthProvider.connected')}</span>
|
|
92
|
+
</div>
|
|
93
|
+
<Button
|
|
94
|
+
variant="outline"
|
|
95
|
+
size="sm"
|
|
96
|
+
onClick={handleDisconnect}
|
|
97
|
+
disabled={disconnecting}
|
|
98
|
+
>
|
|
99
|
+
{disconnecting ? <Spinner className="size-3" /> : t('oauthProvider.disconnect')}
|
|
100
|
+
</Button>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<Button
|
|
107
|
+
variant="outline"
|
|
108
|
+
size="sm"
|
|
109
|
+
onClick={handleConnect}
|
|
110
|
+
disabled={authenticating}
|
|
111
|
+
>
|
|
112
|
+
{authenticating ? (
|
|
113
|
+
<>
|
|
114
|
+
<Spinner className="size-4" />
|
|
115
|
+
<span>{t('oauthProvider.authenticating')}</span>
|
|
116
|
+
</>
|
|
117
|
+
) : (
|
|
118
|
+
<>
|
|
119
|
+
<ExternalLink className="size-4 mr-1" />
|
|
120
|
+
<span>{t('oauthProvider.authenticate')}</span>
|
|
121
|
+
</>
|
|
122
|
+
)}
|
|
123
|
+
</Button>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { useUserSession } from '@vertesia/ui/session';
|
|
2
|
+
import { Button, Spinner } from '../../core/index.js';
|
|
3
|
+
import { useUITranslation } from '../../i18n/index.js';
|
|
4
|
+
import { CheckCircle2, ExternalLink, ShieldAlertIcon } from 'lucide-react';
|
|
5
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
6
|
+
import { useOAuthPopup } from './useOAuthPopup.js';
|
|
7
|
+
|
|
8
|
+
interface RemoteMcpConnectionButtonProps {
|
|
9
|
+
appId: string;
|
|
10
|
+
collectionId: string;
|
|
11
|
+
collectionName?: string;
|
|
12
|
+
/** Pre-fetched authentication status. If not provided, will fetch automatically. */
|
|
13
|
+
authenticated?: boolean;
|
|
14
|
+
onAuthChange?: () => void;
|
|
15
|
+
onError?: (error: string | null) => void;
|
|
16
|
+
variant?: 'default' | 'compact' | 'full';
|
|
17
|
+
/** Show collection name label */
|
|
18
|
+
showLabel?: boolean;
|
|
19
|
+
/** Show disconnect button when authenticated */
|
|
20
|
+
showDisconnect?: boolean;
|
|
21
|
+
/** Read-only mode - only show status, no interactive buttons */
|
|
22
|
+
readOnly?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface OAuthStatus {
|
|
26
|
+
authenticated: boolean;
|
|
27
|
+
collection_id: string;
|
|
28
|
+
collection_name: string;
|
|
29
|
+
expires_at?: string;
|
|
30
|
+
mcp_server_url: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Flexible connect button for remote MCP tool collections.
|
|
35
|
+
* - 'compact': minimal size for lists (no disconnect)
|
|
36
|
+
* - 'default': standard button size (no disconnect)
|
|
37
|
+
* - 'full': with label, status, and disconnect button
|
|
38
|
+
*/
|
|
39
|
+
export function RemoteMcpConnectionButton({
|
|
40
|
+
appId,
|
|
41
|
+
collectionId,
|
|
42
|
+
collectionName,
|
|
43
|
+
authenticated: providedAuthenticated,
|
|
44
|
+
onAuthChange,
|
|
45
|
+
onError,
|
|
46
|
+
variant = 'default',
|
|
47
|
+
showLabel = false,
|
|
48
|
+
showDisconnect = false,
|
|
49
|
+
readOnly = false
|
|
50
|
+
}: RemoteMcpConnectionButtonProps) {
|
|
51
|
+
const { client } = useUserSession();
|
|
52
|
+
const { t } = useUITranslation();
|
|
53
|
+
const [status, setStatus] = useState<OAuthStatus | null>(null);
|
|
54
|
+
const [loading, setLoading] = useState(providedAuthenticated === undefined);
|
|
55
|
+
const [authenticating, setAuthenticating] = useState(false);
|
|
56
|
+
const [disconnecting, setDisconnecting] = useState(false);
|
|
57
|
+
|
|
58
|
+
const authenticated = providedAuthenticated ?? status?.authenticated ?? false;
|
|
59
|
+
const displayName = collectionName ?? collectionId;
|
|
60
|
+
|
|
61
|
+
const loadStatus = useCallback(async () => {
|
|
62
|
+
if (providedAuthenticated !== undefined) {
|
|
63
|
+
setLoading(false);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
setLoading(true);
|
|
69
|
+
const data = await client.remoteMcpConnections.getCollectionStatus(appId, collectionId);
|
|
70
|
+
setStatus(data);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error('[RemoteMcpConnectionButton] Failed to load OAuth status:', error);
|
|
73
|
+
} finally {
|
|
74
|
+
setLoading(false);
|
|
75
|
+
}
|
|
76
|
+
}, [client, appId, collectionId, providedAuthenticated]);
|
|
77
|
+
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
loadStatus();
|
|
80
|
+
}, [loadStatus]);
|
|
81
|
+
|
|
82
|
+
const { openOAuthPopup } = useOAuthPopup({
|
|
83
|
+
onComplete: () => {
|
|
84
|
+
setAuthenticating(false);
|
|
85
|
+
loadStatus();
|
|
86
|
+
onAuthChange?.();
|
|
87
|
+
},
|
|
88
|
+
onError: (error) => {
|
|
89
|
+
console.error('OAuth failed:', error);
|
|
90
|
+
setAuthenticating(false);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const handleConnect = async () => {
|
|
95
|
+
try {
|
|
96
|
+
setAuthenticating(true);
|
|
97
|
+
onError?.(null);
|
|
98
|
+
const response = await client.remoteMcpConnections.authorize(appId, collectionId);
|
|
99
|
+
if (response.connected) {
|
|
100
|
+
setAuthenticating(false);
|
|
101
|
+
await loadStatus();
|
|
102
|
+
onAuthChange?.();
|
|
103
|
+
} else if (response.authorization_url) {
|
|
104
|
+
openOAuthPopup(response.authorization_url);
|
|
105
|
+
} else {
|
|
106
|
+
onError?.(`${displayName}: Authorization URL not provided by server`);
|
|
107
|
+
setAuthenticating(false);
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.error('Failed to authorize:', error);
|
|
111
|
+
const raw = error instanceof Error
|
|
112
|
+
? ((error as { original_message?: string }).original_message ?? error.message)
|
|
113
|
+
: 'Failed to connect';
|
|
114
|
+
const detail = raw.replace(/^[A-Za-z\s]+:\s/, '');
|
|
115
|
+
onError?.(`${displayName}: ${detail}`);
|
|
116
|
+
setAuthenticating(false);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const handleDisconnect = async () => {
|
|
121
|
+
try {
|
|
122
|
+
setDisconnecting(true);
|
|
123
|
+
await client.remoteMcpConnections.disconnect(appId, collectionId);
|
|
124
|
+
await loadStatus();
|
|
125
|
+
onAuthChange?.();
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('Failed to disconnect:', error);
|
|
128
|
+
} finally {
|
|
129
|
+
setDisconnecting(false);
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
if (loading) {
|
|
134
|
+
return (
|
|
135
|
+
<div className="flex items-center gap-2 text-sm">
|
|
136
|
+
<Spinner className="size-4" />
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (variant === 'full') {
|
|
142
|
+
if (!authenticated) {
|
|
143
|
+
return (
|
|
144
|
+
<div className="flex items-center gap-2 text-sm">
|
|
145
|
+
{showLabel && <span className="font-medium text-foreground">{displayName}:</span>}
|
|
146
|
+
<Button variant="ghost" size="sm" onClick={handleConnect} disabled={authenticating}>
|
|
147
|
+
{authenticating ? (
|
|
148
|
+
<>
|
|
149
|
+
<Spinner className="size-4" />
|
|
150
|
+
<span>{t('mcpOAuth.authenticating')}</span>
|
|
151
|
+
</>
|
|
152
|
+
) : (
|
|
153
|
+
<>
|
|
154
|
+
<ShieldAlertIcon className="size-4" />
|
|
155
|
+
<span>{t('mcpOAuth.authenticate')}</span>
|
|
156
|
+
</>
|
|
157
|
+
)}
|
|
158
|
+
</Button>
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<div className="flex items-center gap-2">
|
|
165
|
+
{showLabel && <span className="font-medium text-sm text-foreground">{displayName}:</span>}
|
|
166
|
+
<div className="flex items-center gap-1 text-success text-sm">
|
|
167
|
+
<CheckCircle2 className="size-4" />
|
|
168
|
+
<span>{t('mcpOAuth.connected')}</span>
|
|
169
|
+
</div>
|
|
170
|
+
{showDisconnect && (
|
|
171
|
+
<Button
|
|
172
|
+
variant="ghost"
|
|
173
|
+
size="sm"
|
|
174
|
+
onClick={handleDisconnect}
|
|
175
|
+
disabled={disconnecting}
|
|
176
|
+
>
|
|
177
|
+
{disconnecting ? <Spinner className="size-4" /> : t('mcpOAuth.disconnect')}
|
|
178
|
+
</Button>
|
|
179
|
+
)}
|
|
180
|
+
</div>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (authenticated) {
|
|
185
|
+
if (variant === 'compact') {
|
|
186
|
+
return (
|
|
187
|
+
<div className="flex items-center gap-2">
|
|
188
|
+
{showLabel && <span className="font-medium text-xs text-foreground">{displayName}:</span>}
|
|
189
|
+
<div className="flex items-center gap-1 text-success">
|
|
190
|
+
<CheckCircle2 className="size-3" />
|
|
191
|
+
<span className="text-xs">{t('mcpOAuth.connected')}</span>
|
|
192
|
+
</div>
|
|
193
|
+
{!readOnly && showDisconnect && (
|
|
194
|
+
<Button
|
|
195
|
+
variant="ghost"
|
|
196
|
+
size="sm"
|
|
197
|
+
onClick={handleDisconnect}
|
|
198
|
+
disabled={disconnecting}
|
|
199
|
+
className="h-6 px-2 text-xs"
|
|
200
|
+
>
|
|
201
|
+
{disconnecting ? <Spinner className="size-3" /> : t('mcpOAuth.disconnect')}
|
|
202
|
+
</Button>
|
|
203
|
+
)}
|
|
204
|
+
</div>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return (
|
|
209
|
+
<div className="flex items-center gap-1 text-success">
|
|
210
|
+
<CheckCircle2 className="size-4" />
|
|
211
|
+
<span className="text-sm">{t('mcpOAuth.connected')}</span>
|
|
212
|
+
</div>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (variant === 'compact') {
|
|
217
|
+
if (readOnly) {
|
|
218
|
+
return (
|
|
219
|
+
<div className="flex items-center gap-2">
|
|
220
|
+
{showLabel && <span className="font-medium text-xs text-foreground">{collectionName}:</span>}
|
|
221
|
+
<div className="flex items-center gap-1 text-muted">
|
|
222
|
+
<span className="text-xs">{t('mcpOAuth.notConnected')}</span>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<div className="flex items-center gap-2">
|
|
230
|
+
{showLabel && <span className="font-medium text-xs text-foreground">{displayName}:</span>}
|
|
231
|
+
<Button
|
|
232
|
+
variant="outline"
|
|
233
|
+
size="sm"
|
|
234
|
+
onClick={handleConnect}
|
|
235
|
+
disabled={authenticating}
|
|
236
|
+
className="h-6 px-2 text-xs"
|
|
237
|
+
>
|
|
238
|
+
{authenticating ? (
|
|
239
|
+
<>
|
|
240
|
+
<Spinner className="size-3" />
|
|
241
|
+
<span>{t('mcpOAuth.connecting')}</span>
|
|
242
|
+
</>
|
|
243
|
+
) : (
|
|
244
|
+
<>
|
|
245
|
+
<ExternalLink className="size-3 mr-1" />
|
|
246
|
+
<span>{t('mcpOAuth.connect')}</span>
|
|
247
|
+
</>
|
|
248
|
+
)}
|
|
249
|
+
</Button>
|
|
250
|
+
</div>
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return (
|
|
255
|
+
<Button
|
|
256
|
+
variant="outline"
|
|
257
|
+
size="sm"
|
|
258
|
+
onClick={handleConnect}
|
|
259
|
+
disabled={authenticating}
|
|
260
|
+
>
|
|
261
|
+
{authenticating ? (
|
|
262
|
+
<>
|
|
263
|
+
<Spinner className="size-4" />
|
|
264
|
+
<span>{t('mcpOAuth.connecting')}</span>
|
|
265
|
+
</>
|
|
266
|
+
) : (
|
|
267
|
+
<>
|
|
268
|
+
<ExternalLink className="size-4 mr-1" />
|
|
269
|
+
<span>{t('mcpOAuth.connect')}</span>
|
|
270
|
+
</>
|
|
271
|
+
)}
|
|
272
|
+
</Button>
|
|
273
|
+
);
|
|
274
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface UseOAuthPopupOptions {
|
|
4
|
+
onComplete: () => void;
|
|
5
|
+
onError?: (error: string) => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* OAuth message structure from callback page
|
|
10
|
+
*/
|
|
11
|
+
interface OAuthMessage {
|
|
12
|
+
type: 'oauth-complete';
|
|
13
|
+
success: boolean;
|
|
14
|
+
error?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Type guard to validate OAuth message structure
|
|
19
|
+
*/
|
|
20
|
+
function isOAuthMessage(data: unknown): data is OAuthMessage {
|
|
21
|
+
return (
|
|
22
|
+
typeof data === 'object' &&
|
|
23
|
+
data !== null &&
|
|
24
|
+
'type' in data &&
|
|
25
|
+
data.type === 'oauth-complete' &&
|
|
26
|
+
'success' in data &&
|
|
27
|
+
typeof (data as OAuthMessage).success === 'boolean'
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Hook to manage OAuth popup window with proper cleanup
|
|
33
|
+
* Handles window.postMessage communication and fallback polling
|
|
34
|
+
*/
|
|
35
|
+
export function useOAuthPopup({ onComplete, onError }: UseOAuthPopupOptions) {
|
|
36
|
+
const cleanupRef = useRef<(() => void) | null>(null);
|
|
37
|
+
const onCompleteRef = useRef(onComplete);
|
|
38
|
+
const onErrorRef = useRef(onError);
|
|
39
|
+
|
|
40
|
+
// Keep refs up to date
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
onCompleteRef.current = onComplete;
|
|
43
|
+
onErrorRef.current = onError;
|
|
44
|
+
}, [onComplete, onError]);
|
|
45
|
+
|
|
46
|
+
// Cleanup on unmount
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
return () => {
|
|
49
|
+
if (cleanupRef.current) {
|
|
50
|
+
cleanupRef.current();
|
|
51
|
+
cleanupRef.current = null;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
}, []);
|
|
55
|
+
|
|
56
|
+
const openOAuthPopup = (authorizationUrl: string) => {
|
|
57
|
+
// Clean up any previous OAuth flow
|
|
58
|
+
if (cleanupRef.current) {
|
|
59
|
+
cleanupRef.current();
|
|
60
|
+
cleanupRef.current = null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Open OAuth authorization in centered popup window.
|
|
64
|
+
const width = 600;
|
|
65
|
+
const height = 700;
|
|
66
|
+
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
67
|
+
const top = window.screenY + (window.outerHeight - height) / 2;
|
|
68
|
+
|
|
69
|
+
const popup = window.open(
|
|
70
|
+
authorizationUrl,
|
|
71
|
+
'oauth_popup',
|
|
72
|
+
`width=${width},height=${height},left=${left},top=${top},popup=yes`
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
let messageReceived = false;
|
|
76
|
+
let intervalId: ReturnType<typeof setInterval> | null = null;
|
|
77
|
+
|
|
78
|
+
// BroadcastChannel is same-origin by spec — no origin check required.
|
|
79
|
+
const channel = new BroadcastChannel('oauth-callback');
|
|
80
|
+
|
|
81
|
+
const handleMessage = (event: MessageEvent) => {
|
|
82
|
+
if (!isOAuthMessage(event.data)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
messageReceived = true;
|
|
87
|
+
channel.close();
|
|
88
|
+
if (intervalId) clearInterval(intervalId);
|
|
89
|
+
|
|
90
|
+
onCompleteRef.current();
|
|
91
|
+
|
|
92
|
+
if (!event.data.success && event.data.error) {
|
|
93
|
+
onErrorRef.current?.(event.data.error);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
cleanupRef.current = null;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
channel.addEventListener('message', handleMessage);
|
|
100
|
+
|
|
101
|
+
// Poll for popup closure so the button resets if the user dismisses the popup early.
|
|
102
|
+
if (popup) {
|
|
103
|
+
intervalId = setInterval(() => {
|
|
104
|
+
if (popup.closed) {
|
|
105
|
+
if (intervalId) clearInterval(intervalId);
|
|
106
|
+
channel.close();
|
|
107
|
+
|
|
108
|
+
if (!messageReceived) {
|
|
109
|
+
onCompleteRef.current();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
cleanupRef.current = null;
|
|
113
|
+
}
|
|
114
|
+
}, 1000);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Store cleanup function
|
|
118
|
+
cleanupRef.current = () => {
|
|
119
|
+
channel.close();
|
|
120
|
+
if (intervalId) clearInterval(intervalId);
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return { openOAuthPopup };
|
|
125
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Collection, getContentTypeRefId } from "@vertesia/common";
|
|
1
|
+
import { Collection, getContentTypeRefId, ColumnLayout } from "@vertesia/common";
|
|
2
2
|
import { useToast } from "@vertesia/ui/core";
|
|
3
3
|
import { useUserSession } from "@vertesia/ui/session";
|
|
4
4
|
import { TypeRegistry } from "../types/TypeRegistry.js";
|
|
5
5
|
import { useTypeRegistry } from "../types/TypeRegistryProvider.js";
|
|
6
6
|
import { DocumentSearchResults, DocumentSearchResultsWithDropZone } from "../objects/DocumentSearchResults";
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
|
|
9
9
|
const collectionDefaultLayout: ColumnLayout[] = [
|
|
10
10
|
{ name: "ID", field: "id", type: "objectId?slice=-7" },
|
|
@@ -56,4 +56,4 @@ function getTableLayout(collection: Collection, typeRegistry?: TypeRegistry | un
|
|
|
56
56
|
} else {
|
|
57
57
|
return collectionDefaultLayout;
|
|
58
58
|
}
|
|
59
|
-
}
|
|
59
|
+
}
|
|
@@ -4,8 +4,9 @@ import { SharedPropsEditor, SyncMemberHeadsToggle, UserInfo } from "@vertesia/ui
|
|
|
4
4
|
import { useUserSession } from "@vertesia/ui/session";
|
|
5
5
|
import { MonacoEditor, EditorApi, GeneratedForm, ManagedObject, Node } from "@vertesia/ui/widgets";
|
|
6
6
|
import dayjs from "dayjs";
|
|
7
|
-
import { useMemo, useRef, useState } from "react";
|
|
7
|
+
import { useContext, useMemo, useRef, useState } from "react";
|
|
8
8
|
import { useUITranslation } from '../../../i18n/index.js';
|
|
9
|
+
import { SearchContext } from "../objects/search/DocumentSearchContext";
|
|
9
10
|
import { SelectContentType, stringifyTableLayout } from "../types";
|
|
10
11
|
|
|
11
12
|
interface UpdateData {
|
|
@@ -28,6 +29,7 @@ export function EditCollectionView({ refetch, collection }: EditCollectionViewPr
|
|
|
28
29
|
const toast = useToast();
|
|
29
30
|
const { theme } = useTheme();
|
|
30
31
|
const { client } = useUserSession();
|
|
32
|
+
const search = useContext(SearchContext);
|
|
31
33
|
const [isUpdating, setUpdating] = useState(false);
|
|
32
34
|
const [metadata, setMetadata] = useState<UpdateData>({
|
|
33
35
|
name: collection.name,
|
|
@@ -103,6 +105,11 @@ export function EditCollectionView({ refetch, collection }: EditCollectionViewPr
|
|
|
103
105
|
.update(collection.id, payload)
|
|
104
106
|
.then(() => {
|
|
105
107
|
refetch();
|
|
108
|
+
// Update search query on provider if it's a dynamic collection to reflect in UI immediately
|
|
109
|
+
if (collection.dynamic && search) {
|
|
110
|
+
search.reset();
|
|
111
|
+
void search.search();
|
|
112
|
+
}
|
|
106
113
|
toast({
|
|
107
114
|
title: t('store.collectionUpdated'),
|
|
108
115
|
description: t('store.collectionUpdatedSuccess'),
|
|
@@ -184,6 +191,8 @@ export function EditCollectionView({ refetch, collection }: EditCollectionViewPr
|
|
|
184
191
|
<FormItem label={t('store.query')} description={t('store.queryDescription')}>
|
|
185
192
|
<Textarea
|
|
186
193
|
className={Styles.INPUT}
|
|
194
|
+
minLines={1}
|
|
195
|
+
maxLines={12}
|
|
187
196
|
value={metadata.query}
|
|
188
197
|
onChange={(e) => setField("query", e.target.value)}
|
|
189
198
|
/>
|