-
Notifications
You must be signed in to change notification settings - Fork 167
Integration detail: explain how to unlock tools when there are no connections #1264
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -90,6 +90,8 @@ export function IntegrationDetailPage(props: { namespace: string }) { | |||||
| const [refreshing, setRefreshing] = useState(false); | ||||||
| const [editSheetOpen, setEditSheetOpen] = useState(false); | ||||||
| const [activeTab, setActiveTab] = useState<"accounts" | "tools">("accounts"); | ||||||
| const [manualAccountHandoff, setManualAccountHandoff] = | ||||||
| useState<IntegrationAccountHandoff | null>(null); | ||||||
| const [locationSearch] = useState(() => | ||||||
| typeof window === "undefined" ? "" : window.location.search, | ||||||
| ); | ||||||
|
|
@@ -105,7 +107,7 @@ export function IntegrationDetailPage(props: { namespace: string }) { | |||||
| const currentTab = isBuiltInIntegration ? "tools" : activeTab; | ||||||
| const canRefresh = integrationData?.canRefresh ?? false; | ||||||
| const canRemove = integrationData?.canRemove ?? false; | ||||||
| const accountHandoff = useMemo<IntegrationAccountHandoff | null>(() => { | ||||||
| const urlAccountHandoff = useMemo<IntegrationAccountHandoff | null>(() => { | ||||||
| if (locationSearch.length === 0) return null; | ||||||
| const search = new URLSearchParams(locationSearch); | ||||||
| if (search.get("addAccount") !== "1") return null; | ||||||
|
|
@@ -140,6 +142,8 @@ export function IntegrationDetailPage(props: { namespace: string }) { | |||||
| ...(oauthClient !== undefined ? { oauthClient } : {}), | ||||||
| }; | ||||||
| }, [locationSearch]); | ||||||
| const accountHandoff = manualAccountHandoff ?? urlAccountHandoff; | ||||||
|
|
||||||
| useEffect(() => { | ||||||
| if (accountHandoff && !isBuiltInIntegration) { | ||||||
| setActiveTab("accounts"); | ||||||
|
|
@@ -338,6 +342,11 @@ export function IntegrationDetailPage(props: { namespace: string }) { | |||||
| setRefreshing(false); | ||||||
| }; | ||||||
|
|
||||||
| const handleOpenAddConnection = () => { | ||||||
| setActiveTab("accounts"); | ||||||
| setManualAccountHandoff({ key: `manual:${String(slug)}:${Date.now()}` }); | ||||||
| }; | ||||||
|
|
||||||
| return ( | ||||||
| <div className="flex min-h-0 flex-1 flex-col overflow-hidden"> | ||||||
| {/* Header bar */} | ||||||
|
|
@@ -491,6 +500,11 @@ export function IntegrationDetailPage(props: { namespace: string }) { | |||||
| } | ||||||
| : {})} | ||||||
| /> | ||||||
| ) : !isBuiltInIntegration && integrationConnections.length === 0 ? ( | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| <NoConnectionToolsEmptyState | ||||||
| onAddConnection={handleOpenAddConnection} | ||||||
| canAddConnection={accountsMethods.length > 0} | ||||||
| /> | ||||||
| ) : ( | ||||||
| <ToolDetailEmpty hasTools={integrationTools.length > 0} /> | ||||||
| )} | ||||||
|
|
@@ -514,6 +528,31 @@ export function IntegrationDetailPage(props: { namespace: string }) { | |||||
| ); | ||||||
| } | ||||||
|
|
||||||
| function NoConnectionToolsEmptyState(props: { | ||||||
| readonly onAddConnection: () => void; | ||||||
| readonly canAddConnection: boolean; | ||||||
| }) { | ||||||
| return ( | ||||||
| <div className="flex h-full items-center justify-center"> | ||||||
| <div className="max-w-sm text-center"> | ||||||
| <p className="text-sm font-medium text-foreground">No tools yet</p> | ||||||
| <p className="mt-1.5 text-sm text-muted-foreground"> | ||||||
| Add a connection to unlock this integration's tools. | ||||||
| </p> | ||||||
| <Button | ||||||
| type="button" | ||||||
| size="sm" | ||||||
| className="mt-4" | ||||||
| onClick={props.onAddConnection} | ||||||
| disabled={!props.canAddConnection} | ||||||
| > | ||||||
| Add connection | ||||||
| </Button> | ||||||
| </div> | ||||||
| </div> | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| function IntegrationDetailSkeleton() { | ||||||
| return ( | ||||||
| <div className="flex min-h-0 flex-1 overflow-hidden"> | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
manualAccountHandoffcan re-open the dialog after dismissalhandleOpenAddConnectionsetsmanualAccountHandoffwith aDate.now()key, but it is never reset tonullafter the user dismisses the dialog.AccountsSectioncallssetAdding(true)inside auseEffect([accountHandoff]), so any future re-mount of the Accounts panel (e.g. due to a parent re-render that drops and recreates theTabsContentsubtree) would fire that effect again with the stale handoff and reopen the modal unexpectedly. ClearingmanualAccountHandoffwhen the user leaves the Accounts dialog — or at minimum after the tab switch completes — would prevent this.