Skip to content

Commit f96d853

Browse files
committed
improvement(folders): show the pin glyph on Files rows and pin the deploy contract
Files rows were left without the pin indicator the other two lists gained, so a pinned file or folder still sorted to the top of the Files page with nothing explaining why. Adds `lib/api/contracts/folders.test.ts`, which pins the three cases that together ARE the rolling-deploy contract: an omitted `resourceType` defaults to `workflow` (so a client predating the field keeps working), a present-but-unrecognized one is rejected rather than coerced, and every served tree is accepted.
1 parent 3aca8f0 commit f96d853

2 files changed

Lines changed: 31 additions & 1 deletion

File tree

apps/sim/app/workspace/[workspaceId]/files/files.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,7 @@ export function Files() {
505505
name: {
506506
icon: <Folder className='size-[14px]' />,
507507
label: folder.name,
508+
pinned: pinnedFolderIds.has(folder.id),
508509
},
509510
size: {
510511
label:
@@ -530,6 +531,7 @@ export function Files() {
530531
name: {
531532
icon: <Icon className='size-[14px]' />,
532533
label: file.name,
534+
pinned: pinnedFileIds.has(file.id),
533535
},
534536
size: {
535537
label: formatFileSize(file.size, { includeBytes: true }),
@@ -547,7 +549,7 @@ export function Files() {
547549
})
548550

549551
return [...folderRows, ...fileRows]
550-
}, [visibleFolders, filteredFiles, membersById, folderSizeMap])
552+
}, [visibleFolders, filteredFiles, membersById, folderSizeMap, pinnedFolderIds, pinnedFileIds])
551553

552554
const rows: ResourceRow[] = useMemo(() => {
553555
if (!listRename.editingId) return baseRows
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @vitest-environment node
3+
*/
4+
import { describe, expect, it } from 'vitest'
5+
import { servedFolderResourceTypeSchema } from '@/lib/api/contracts/folders'
6+
7+
/**
8+
* These three cases together ARE the rolling-deploy contract for the folder engine, so they
9+
* are pinned rather than left implicit in `.default()`.
10+
*/
11+
describe('servedFolderResourceTypeSchema', () => {
12+
it('defaults an omitted value to workflow, so a client that predates the field still works', () => {
13+
expect(servedFolderResourceTypeSchema.parse(undefined)).toBe('workflow')
14+
})
15+
16+
it('rejects a present-but-unrecognized value rather than coercing it to workflow', () => {
17+
// Coercing would file a knowledge-base folder into the workflow tree, where the
18+
// Knowledge page can never see it again. A 400 is the only safe answer.
19+
expect(servedFolderResourceTypeSchema.safeParse('bogus').success).toBe(false)
20+
expect(servedFolderResourceTypeSchema.safeParse('').success).toBe(false)
21+
})
22+
23+
it('accepts every tree the engine serves', () => {
24+
for (const value of ['workflow', 'file', 'knowledge_base', 'table'] as const) {
25+
expect(servedFolderResourceTypeSchema.parse(value)).toBe(value)
26+
}
27+
})
28+
})

0 commit comments

Comments
 (0)