Skip to content

Commit 2f94481

Browse files
committed
improvement(search): use standard source row navigation
1 parent 8c69ee0 commit 2f94481

3 files changed

Lines changed: 40 additions & 8 deletions

File tree

apps/sim/app/o/[organizationId]/settings/components/integrations/organization-integrations-setup.tsx

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import { useMemo, useState } from 'react'
44
import { Chip, ChipConfirmModal, ChipModalError, Switch } from '@sim/emcn'
5-
import { useRouter } from 'next/navigation'
65
import { useQueryState } from 'nuqs'
76
import { SettingsPanel } from '@/components/settings/settings-panel'
87
import type { ResourceScope } from '@/lib/core/resource-scope'
@@ -66,7 +65,6 @@ export function OrganizationIntegrationsSetup() {
6665
searchSetupParam.key,
6766
searchSetupParam.parser.withOptions({ history: 'replace' })
6867
)
69-
const router = useRouter()
7068
const membershipQueryKeys = useMemo(
7169
() => [searchSourceKeys.list({ kind: 'organization', organizationId: organization.id })],
7270
[organization.id]
@@ -210,11 +208,9 @@ export function OrganizationIntegrationsSetup() {
210208
waiting={enrollment.isAwaiting(source.connectorId)}
211209
isPending={enrollment.isPending}
212210
onConnect={() => enrollment.connect(source.knowledgeBaseId, source.connectorId)}
213-
onManage={() =>
214-
router.push(
215-
organizationRoutes(organization.id).searchSource(source.connectorId)
216-
)
217-
}
211+
manageHref={organizationRoutes(organization.id).searchSource(
212+
source.connectorId
213+
)}
218214
/>
219215
))}
220216
</div>

apps/sim/app/workspace/[workspaceId]/search/components/search-source-row.test.tsx

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ function source(overrides: Partial<SearchSourceSummary> = {}): SearchSourceSumma
3838

3939
async function render(
4040
data = source(),
41-
props: { canAdmin?: boolean; available?: boolean; waiting?: boolean; isPending?: boolean } = {}
41+
props: {
42+
canAdmin?: boolean
43+
available?: boolean
44+
waiting?: boolean
45+
isPending?: boolean
46+
manageHref?: string
47+
} = {}
4248
) {
4349
await act(async () =>
4450
root.render(
@@ -185,6 +191,29 @@ describe('Search source viewer actions', () => {
185191
expect(connect).not.toHaveBeenCalled()
186192
})
187193

194+
it('opens source details through a row link while preserving the separate connection action', async () => {
195+
const manageHref = '/o/org-1/settings/integrations/sources/source-1'
196+
await render(source(), { canAdmin: true, manageHref })
197+
const link = container.querySelector('a')
198+
expect(link?.getAttribute('href')).toBe(manageHref)
199+
expect(link?.getAttribute('aria-label')).toBe('Open engineering.atlassian.net · ENG')
200+
expect(button('Manage')).toBeUndefined()
201+
expect(button('Confluence source actions')).toBeUndefined()
202+
expect(link?.contains(button('Connect account')!)).toBe(false)
203+
await act(async () => button('Connect account')!.click())
204+
expect(connect).toHaveBeenCalledOnce()
205+
expect(manage).not.toHaveBeenCalled()
206+
})
207+
208+
it('does not expose management navigation to a non-admin', async () => {
209+
await render(source(), {
210+
canAdmin: false,
211+
manageHref: '/o/org-1/settings/integrations/sources/source-1',
212+
})
213+
expect(container.querySelector('a')).toBeNull()
214+
expect(button('Connect account')).toBeDefined()
215+
})
216+
188217
it.each([false, true])(
189218
'retains the legacy knowledge-base link for canAdmin=%s',
190219
async (canAdmin) => {

apps/sim/app/workspace/[workspaceId]/search/components/search-source-row.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface SearchSourceRowProps {
1919
waiting: boolean
2020
isPending: boolean
2121
onConnect: () => void
22+
manageHref?: string
2223
/** Opens management for the source; only a surface that offers management passes it. */
2324
onManage?: () => void
2425
}
@@ -33,6 +34,7 @@ export function SearchSourceRow({
3334
waiting,
3435
isPending,
3536
onConnect,
37+
manageHref,
3638
onManage,
3739
}: SearchSourceRowProps) {
3840
const scope = explicitScope ?? resourceScopeFromOwner({ workspaceId })
@@ -41,6 +43,7 @@ export function SearchSourceRow({
4143
const membership = source.viewerMembership
4244
const usable = available && source.availability === 'available'
4345
const supported = meta?.search === true
46+
const managementHref = canAdmin ? manageHref : undefined
4447
const connectable =
4548
usable &&
4649
supported &&
@@ -86,6 +89,9 @@ export function SearchSourceRow({
8689
}
8790
title={name}
8891
description={[source.sourceDescription, status].filter(Boolean).join(' · ')}
92+
href={managementHref}
93+
clickLabel={managementHref ? `Open ${source.sourceDescription || name}` : undefined}
94+
navigable={Boolean(managementHref)}
8995
trailing={
9096
!supported && scope.kind === 'workspace' ? (
9197
<ChipLink href={`/workspace/${scope.workspaceId}/knowledge/${source.knowledgeBaseId}`}>
@@ -103,6 +109,7 @@ export function SearchSourceRow({
103109
</Chip>
104110
)}
105111
{canAdmin &&
112+
!managementHref &&
106113
onManage &&
107114
(connectable ? (
108115
<RowActionsMenu

0 commit comments

Comments
 (0)