Skip to content

Commit da80e82

Browse files
committed
fix move submenu: use folder names with tree-ordered indentation instead of stale paths
- Compute folder depth from parentId chain client-side (avoids stale server-computed path field) - Tree-order folders so parents appear before their children, sorted by sortOrder then name - Show folder.name instead of folder.path so optimistic renames are reflected immediately - Indent each folder by depth * 12px in the submenu so po/shit renders as 'shit' indented under 'po' - MoveOption gains optional depth field; contextMenuMoveOptions is a separate memo from moveFolderOptions (modal keeps its existing path-label behavior)
1 parent aa61a67 commit da80e82

2 files changed

Lines changed: 49 additions & 2 deletions

File tree

apps/sim/app/workspace/[workspaceId]/files/components/file-row-context-menu/file-row-context-menu.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { Folder } from '@/components/emcn/icons'
2121
interface MoveOption {
2222
value: string
2323
label: string
24+
depth?: number
2425
}
2526

2627
interface FileRowContextMenuProps {
@@ -103,7 +104,13 @@ export const FileRowContextMenu = memo(function FileRowContextMenu({
103104
</DropdownMenuSubTrigger>
104105
<DropdownMenuSubContent>
105106
{moveOptions.map((option) => (
106-
<DropdownMenuItem key={option.value} onSelect={() => onMove(option.value)}>
107+
<DropdownMenuItem
108+
key={option.value}
109+
onSelect={() => onMove(option.value)}
110+
style={
111+
option.depth ? { paddingLeft: `${option.depth * 12 + 8}px` } : undefined
112+
}
113+
>
107114
<Folder />
108115
{option.label}
109116
</DropdownMenuItem>

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

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,46 @@ export function Files() {
15141514
[folders, selectedFolderIds, descendantFolderIdsByFolderId]
15151515
)
15161516

1517+
const contextMenuMoveOptions = useMemo(() => {
1518+
const depthById = new Map<string, number>()
1519+
const getDepth = (id: string): number => {
1520+
if (depthById.has(id)) return depthById.get(id)!
1521+
const f = folders.find((folder) => folder.id === id)
1522+
const d = f?.parentId ? getDepth(f.parentId) + 1 : 0
1523+
depthById.set(id, d)
1524+
return d
1525+
}
1526+
for (const f of folders) getDepth(f.id)
1527+
1528+
const treeOrdered: WorkspaceFileFolderApi[] = []
1529+
const addChildren = (parentId: string | null) => {
1530+
const children = folders
1531+
.filter((f) => f.parentId === parentId)
1532+
.sort((a, b) => a.sortOrder - b.sortOrder || a.name.localeCompare(b.name))
1533+
for (const child of children) {
1534+
treeOrdered.push(child)
1535+
addChildren(child.id)
1536+
}
1537+
}
1538+
addChildren(null)
1539+
1540+
const filtered = treeOrdered.filter((folder) => {
1541+
if (selectedFolderIds.includes(folder.id)) return false
1542+
return selectedFolderIds.every(
1543+
(selectedFolderId) => !descendantFolderIdsByFolderId.get(selectedFolderId)?.has(folder.id)
1544+
)
1545+
})
1546+
1547+
return [
1548+
{ value: '__root__', label: 'Files', depth: 0 },
1549+
...filtered.map((folder) => ({
1550+
value: folder.id,
1551+
label: folder.name,
1552+
depth: depthById.get(folder.id) ?? 0,
1553+
})),
1554+
]
1555+
}, [folders, selectedFolderIds, descendantFolderIdsByFolderId])
1556+
15171557
const sortConfig: SortConfig = useMemo(
15181558
() => ({
15191559
options: [
@@ -1821,7 +1861,7 @@ export function Files() {
18211861
onRename={handleContextMenuRename}
18221862
onDelete={handleContextMenuDelete}
18231863
onMove={handleContextMenuMove}
1824-
moveOptions={moveFolderOptions}
1864+
moveOptions={contextMenuMoveOptions}
18251865
canEdit={canEdit}
18261866
selectedCount={selectedRowIds.size}
18271867
/>

0 commit comments

Comments
 (0)