Skip to content

Commit f3b47ee

Browse files
committed
refactor(tables): navigate through onNavigate and the axis, not a router
Step 5. Two `router.push` calls, both to the tables list, both hand-building `/workspace/${workspaceId}/tables`. The table now builds its own `workspaceSource` and asks it for the target — `source.hrefFor({ to: 'list' })`, the member added for exactly this — and hands the result to an `onNavigate` prop. The route table stays in one file, and a host that owns no router simply omits the prop, which makes navigation inert by construction rather than by a check at each call site. The source is built inside the table rather than taken as a prop because `page.tsx` is a Server Component and a source carries closures, which cannot cross the RSC boundary. That is why the axes reach the table through its client shell in the first place. Both hosts supply `onNavigate`: the route shell as `router.push`, the panel reusing the `navigate` callback its file and log branches already pass.
1 parent 32992f3 commit f3b47ee

3 files changed

Lines changed: 29 additions & 9 deletions

File tree

apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/resource-content.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ export const ResourceContent = memo(function ResourceContent({
315315
key={resource.id}
316316
host='panel'
317317
grants={grants}
318+
onNavigate={navigate}
318319
workspaceId={workspaceId}
319320
tableId={resource.id}
320321
viewsEnabled={tableViewsEnabled}

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table-route.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

3-
import { useMemo } from 'react'
4-
import { useParams } from 'next/navigation'
3+
import { useCallback, useMemo } from 'react'
4+
import { useParams, useRouter } from 'next/navigation'
55
import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
66
import { Table } from '@/app/workspace/[workspaceId]/tables/[tableId]/table'
77
import { grantsFromPermissions } from '@/resources'
@@ -29,13 +29,16 @@ export function TableRoute({ tableLocksEnabled, viewsEnabled }: TableRouteProps)
2929
const workspaceId = typeof params?.workspaceId === 'string' ? params.workspaceId : ''
3030
const tableId = typeof params?.tableId === 'string' ? params.tableId : ''
3131
const permissions = useUserPermissionsContext()
32+
const router = useRouter()
3233

3334
const grants = useMemo(() => grantsFromPermissions(permissions), [permissions])
35+
const navigate = useCallback((path: string) => router.push(path), [router])
3436

3537
return (
3638
<Table
3739
host='page'
3840
grants={grants}
41+
onNavigate={navigate}
3942
workspaceId={workspaceId}
4043
tableId={tableId}
4144
tableLocksEnabled={tableLocksEnabled}

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { Chip, ChipConfirmModal, toast } from '@sim/emcn'
55
import { Download, Lock, Pencil, Table as TableIcon, Trash, Upload } from '@sim/emcn/icons'
66
import { createLogger } from '@sim/logger'
77
import { getErrorMessage } from '@sim/utils/errors'
8-
import { useRouter } from 'next/navigation'
98
import { usePostHog } from 'posthog-js/react'
109
import { PresenceAvatars } from '@/components/presence'
1110
import {
@@ -57,7 +56,7 @@ import {
5756
import { useInlineRename } from '@/hooks/use-inline-rename'
5857
import { useSettingsNavigation } from '@/hooks/use-settings-navigation'
5958
import { useTableDetailState } from '@/hooks/use-table-detail-state'
60-
import { hostOwnsUrl, type ResourceGrants, type ResourceHost } from '@/resources'
59+
import { hostOwnsUrl, type ResourceGrants, type ResourceHost, workspaceSource } from '@/resources'
6160
import { useLogDetailsUIStore } from '@/stores/logs/store'
6261
import type { DeletedRowSnapshot } from '@/stores/table/types'
6362
import {
@@ -107,6 +106,12 @@ interface TableProps {
107106
* permanently loses its action.
108107
*/
109108
grants: ResourceGrants
109+
/**
110+
* How this host moves the viewer — the router half of `host`. Targets come
111+
* from `source.hrefFor`, so nothing here hand-builds a workspace path; a host
112+
* that owns no router omits this and navigation is inert by construction.
113+
*/
114+
onNavigate?: (path: string) => void
110115
/**
111116
* The table's address. Required rather than derived: both mounts know it
112117
* (`page.tsx` from its route params, the panel from the open resource), and a
@@ -232,12 +237,25 @@ function isSameViewConfig(a: TableViewConfig, b: TableViewConfig): boolean {
232237
export function Table({
233238
host,
234239
grants,
240+
onNavigate,
235241
workspaceId,
236242
tableId,
237243
tableLocksEnabled = false,
238244
viewsEnabled = false,
239245
}: TableProps) {
240-
const router = useRouter()
246+
/**
247+
* The table's address on the resource axis. Built here rather than taken as a
248+
* prop because `page.tsx` is a Server Component and a source carries closures,
249+
* which cannot cross the RSC boundary.
250+
*/
251+
const source = useMemo(
252+
() => workspaceSource({ kind: 'table' as const, workspaceId, resourceId: tableId }),
253+
[workspaceId, tableId]
254+
)
255+
const navigateToList = useCallback(() => {
256+
const list = source.hrefFor({ to: 'list' })
257+
if (list) onNavigate?.(list)
258+
}, [source, onNavigate])
241259

242260
/**
243261
* Read through {@link hostOwnsUrl} rather than comparing `host` here: that
@@ -1011,9 +1029,7 @@ export function Table({
10111029
},
10121030
})
10131031

1014-
const handleNavigateBack = useCallback(() => {
1015-
router.push(`/workspace/${workspaceId}/tables`)
1016-
}, [router, workspaceId])
1032+
const handleNavigateBack = navigateToList
10171033

10181034
const handleStartTableRename = useCallback(() => {
10191035
const data = tableDataRef.current
@@ -1269,7 +1285,7 @@ export function Table({
12691285
try {
12701286
await deleteTableMutation.mutateAsync(tableId)
12711287
setShowDeleteTableConfirm(false)
1272-
router.push(`/workspace/${workspaceId}/tables`)
1288+
navigateToList()
12731289
} catch {
12741290
setShowDeleteTableConfirm(false)
12751291
}

0 commit comments

Comments
 (0)