Skip to content

Commit c6f653a

Browse files
committed
fix(tables): keep reference navigation available to viewers
1 parent 618c89a commit c6f653a

3 files changed

Lines changed: 90 additions & 3 deletions

File tree

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/column-config-sidebar/column-config-sidebar.test.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ describe('ColumnConfigSidebar', () => {
145145
config={{ mode: 'create', proposedName: 'Related row', type: 'reference' }}
146146
onClose={vi.fn()}
147147
existingColumn={null}
148+
allColumns={[]}
149+
tableRowTtlEnabled={false}
148150
workspaceId='workspace-1'
149151
tableId='table-current'
150152
referenceColumnsEnabled
@@ -182,6 +184,8 @@ describe('ColumnConfigSidebar', () => {
182184
config={{ mode: 'create', proposedName: 'Related row', type: 'reference' }}
183185
onClose={vi.fn()}
184186
existingColumn={null}
187+
allColumns={[]}
188+
tableRowTtlEnabled={false}
185189
workspaceId='workspace-1'
186190
tableId='table-current'
187191
referenceColumnsEnabled
@@ -209,6 +213,8 @@ describe('ColumnConfigSidebar', () => {
209213
type: 'reference',
210214
referenceTableId: 'table-current',
211215
}}
216+
allColumns={[]}
217+
tableRowTtlEnabled={false}
212218
workspaceId='workspace-1'
213219
tableId='table-current'
214220
onColumnRename={onColumnRename}
@@ -248,6 +254,8 @@ describe('ColumnConfigSidebar', () => {
248254
type: 'reference',
249255
referenceTableId: 'table-current',
250256
}}
257+
allColumns={[]}
258+
tableRowTtlEnabled={false}
251259
workspaceId='workspace-1'
252260
tableId='table-current'
253261
referenceColumnsEnabled={false}
@@ -275,6 +283,8 @@ describe('ColumnConfigSidebar', () => {
275283
config={{ mode: 'create', proposedName: 'Related row', type: 'reference' }}
276284
onClose={vi.fn()}
277285
existingColumn={null}
286+
allColumns={[]}
287+
tableRowTtlEnabled={false}
278288
workspaceId='workspace-1'
279289
tableId='table-current'
280290
referenceColumnsEnabled
@@ -297,6 +307,8 @@ describe('ColumnConfigSidebar', () => {
297307
type: 'select',
298308
options: [{ id: 'option-ready', name: 'Ready' }],
299309
}}
310+
allColumns={[]}
311+
tableRowTtlEnabled={false}
300312
workspaceId='workspace-1'
301313
tableId='table-current'
302314
referenceColumnsEnabled

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/column-header-menu.tsx

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

33
import React, { useCallback, useEffect, useRef, useState } from 'react'
4-
import { cn } from '@sim/emcn'
5-
import { ChevronDown } from '@sim/emcn/icons'
4+
import { Button, cn } from '@sim/emcn'
5+
import { ChevronDown, SquareArrowUpRight } from '@sim/emcn/icons'
66
import type { SortDirection, WorkflowGroup } from '@/lib/table'
77
import { HeaderLabel } from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/header-label'
88
import type { WorkflowMetadata } from '@/stores/workflows/registry/types'
@@ -252,6 +252,7 @@ export const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
252252
// Column whose workflow source block was deleted — the header icon swaps to
253253
// `WorkflowX` with an explanatory tooltip.
254254
const blockMissing = Boolean(sourceInfo?.blockMissing)
255+
const referenceTableId = column.type === 'reference' ? column.referenceTableId : undefined
255256

256257
return (
257258
<th
@@ -313,6 +314,18 @@ export const ColumnHeaderMenu = React.memo(function ColumnHeaderMenu({
313314
label={column.workflowGroupId ? column.headerLabel : column.name}
314315
className='ml-1.5 text-[var(--text-primary)] text-small'
315316
/>
317+
{referenceTableId && onGoToReferenceTable && (
318+
<Button
319+
type='button'
320+
variant='ghost'
321+
size='icon'
322+
className='ml-auto shrink-0'
323+
onClick={() => onGoToReferenceTable(referenceTableId)}
324+
aria-label='Go to Reference Table'
325+
>
326+
<SquareArrowUpRight className='size-[14px]' />
327+
</Button>
328+
)}
316329
</div>
317330
) : (
318331
<div className='flex h-full w-full min-w-0 items-center'>

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/workflow-group-meta-cell.test.tsx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
/**
22
* @vitest-environment jsdom
33
*/
4-
import { act, type ReactNode } from 'react'
4+
import { act, type ButtonHTMLAttributes, type ReactNode } from 'react'
55
import { createRoot, type Root } from 'react-dom/client'
66
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
77
import type { ColumnDefinition } from '@/lib/table'
88

99
vi.mock('@sim/emcn', () => ({
10+
Button: ({ children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>) => (
11+
<button {...props}>{children}</button>
12+
),
1013
cn: (...values: Array<string | false | null | undefined>) => values.filter(Boolean).join(' '),
14+
FloatingTooltip: () => null,
15+
isTextClipped: () => false,
16+
useFloatingTooltip: () => ({ state: {}, handlers: {} }),
1117
DropdownMenu: ({ children, open }: { children: ReactNode; open: boolean }) =>
1218
open ? <>{children}</> : null,
1319
DropdownMenuContent: ({ children }: { children: ReactNode }) => <div>{children}</div>,
@@ -28,6 +34,7 @@ vi.mock('@sim/emcn/icons', () => ({
2834
ArrowLeft: () => null,
2935
ArrowRight: () => null,
3036
ArrowUp: () => null,
37+
ChevronDown: () => null,
3138
Eye: () => null,
3239
EyeOff: () => null,
3340
Fingerprint: () => null,
@@ -39,10 +46,12 @@ vi.mock('@sim/emcn/icons', () => ({
3946
SquareArrowUpRight: () => null,
4047
Trash: () => null,
4148
Workflow: () => null,
49+
WorkflowX: () => null,
4250
X: () => null,
4351
}))
4452

4553
vi.mock('@/lib/table/column-types', () => ({
54+
columnTypeById: () => ({ icon: () => null }),
4655
columnTypeOf: (column: ColumnDefinition) => ({
4756
icon: () => null,
4857
label: column.type === 'reference' ? 'Reference' : 'Text',
@@ -55,6 +64,7 @@ vi.mock('@/app/workspace/[workspaceId]/tables/[tableId]/components/column-config
5564

5665
vi.mock('@/enrichments/registry', () => ({ getEnrichment: () => undefined }))
5766

67+
import { ColumnHeaderMenu } from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/column-header-menu'
5868
import { ColumnOptionsMenu } from '@/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/headers/workflow-group-meta-cell'
5969

6070
let container: HTMLDivElement
@@ -134,3 +144,55 @@ describe('ColumnOptionsMenu Reference navigation', () => {
134144
expect(findButton('Go to Reference Table')).toBeUndefined()
135145
})
136146
})
147+
148+
describe('ColumnHeaderMenu read-only Reference navigation', () => {
149+
it('keeps a direct navigation action available without exposing the options menu', () => {
150+
const onGoToReferenceTable = vi.fn()
151+
152+
act(() => {
153+
root.render(
154+
<ColumnHeaderMenu
155+
column={{
156+
id: 'col-account',
157+
key: 'col-account',
158+
name: 'Account',
159+
type: 'reference',
160+
referenceTableId: 'table-accounts',
161+
groupSize: 1,
162+
groupStartColIndex: 0,
163+
headerLabel: 'Account',
164+
isGroupStart: true,
165+
}}
166+
colIndex={0}
167+
readOnly
168+
isRenaming={false}
169+
isColumnSelected={false}
170+
renameValue=''
171+
onRenameValueChange={vi.fn()}
172+
onRenameSubmit={vi.fn()}
173+
onRenameCancel={vi.fn()}
174+
onColumnSelect={vi.fn()}
175+
onInsertLeft={vi.fn()}
176+
onInsertRight={vi.fn()}
177+
onGoToReferenceTable={onGoToReferenceTable}
178+
onDeleteColumn={vi.fn()}
179+
onResizeStart={vi.fn()}
180+
onResize={vi.fn()}
181+
onResizeEnd={vi.fn()}
182+
onAutoResize={vi.fn()}
183+
onOpenConfig={vi.fn()}
184+
/>
185+
)
186+
})
187+
188+
const navigationButton = container.querySelector<HTMLButtonElement>(
189+
'button[aria-label="Go to Reference Table"]'
190+
)
191+
expect(navigationButton).not.toBeNull()
192+
193+
act(() => navigationButton?.click())
194+
195+
expect(onGoToReferenceTable).toHaveBeenCalledWith('table-accounts')
196+
expect(container.querySelector('button[aria-label="Column options"]')).toBeNull()
197+
})
198+
})

0 commit comments

Comments
 (0)