Skip to content

Commit

Permalink
feat: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andresgutgon committed Jul 24, 2024
1 parent 7723b56 commit d654a61
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 50 deletions.
49 changes: 31 additions & 18 deletions packages/web-ui/src/sections/Document/Sidebar/Files/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ type IndentType = { isLast: boolean }

function IndentationBar({
indentation,
open,
hasChildren,
}: {
open: boolean
hasChildren: boolean
indentation: IndentType[]
}) {
return indentation.map((indent, index) => {
Expand All @@ -45,13 +45,13 @@ function IndentationBar({
<div key={index} className='h-6 w-6'>
{index > 0 ? (
<div className='-ml-px relative w-6 h-full flex justify-center'>
{!open && showBorder ? (
{hasChildren || !showBorder ? (
<div className='bg-border w-px h-8 -mt-1' />
) : (
<div className='relative -mt-1'>
<div className='border-l h-3' />
<div className='absolute top-3 border-l border-b h-2 w-2 rounded-bl-sm' />
</div>
) : (
<div className='bg-border w-px h-8 -mt-1' />
)}
</div>
) : null}
Expand All @@ -62,13 +62,14 @@ function IndentationBar({

type WrapperProps = {
open: boolean
node: Node
selected?: boolean
onClick?: () => void
children: ReactNode
indentation: IndentType[]
}
const NodeHeaderWrapper = forwardRef<HTMLDivElement, WrapperProps>(function Foo(
{ open, selected = false, onClick, children, indentation },
{ node, open, selected = false, onClick, children, indentation },
ref,
) {
return (
Expand All @@ -80,7 +81,10 @@ const NodeHeaderWrapper = forwardRef<HTMLDivElement, WrapperProps>(function Foo(
'bg-accent': selected,
})}
>
<IndentationBar indentation={indentation} open={open} />
<IndentationBar
indentation={indentation}
hasChildren={open && node.children.length > 0}
/>
{children}
</div>
)
Expand Down Expand Up @@ -133,7 +137,7 @@ function FolderHeader({
if (!open) {
togglePath(node.path)
}
addFolder({ parentPath: node.path })
addFolder({ parentPath: node.path, parentId: node.id })
},
},
{
Expand Down Expand Up @@ -163,7 +167,12 @@ function FolderHeader({
],
)
return (
<NodeHeaderWrapper ref={nodeRef} open={open} indentation={indentation}>
<NodeHeaderWrapper
ref={nodeRef}
node={node}
open={open}
indentation={indentation}
>
<div className='flex-1 flex flex-row justify-between items-center gap-x-1'>
<div
onClick={onToggleOpen}
Expand Down Expand Up @@ -236,6 +245,7 @@ function FileHeader({
return (
<NodeHeaderWrapper
open={open}
node={node}
selected={selected}
indentation={indentation}
onClick={handleClick}
Expand Down Expand Up @@ -308,7 +318,8 @@ function FileNode({
const tmpNodes = allTmpFolders[node.path] ?? []
const { currentPath } = useFileTreeContext()
const [selected, setSelected] = useState(currentPath === node.path)
const lastIdx = node.children.length - 1
const allNodes = [...tmpNodes, ...node.children]
const lastIdx = allNodes.length - 1
const { togglePath, openPaths } = useOpenPaths((state) => ({
openPaths: state.openPaths,
togglePath: state.togglePath,
Expand Down Expand Up @@ -341,14 +352,16 @@ function FileNode({
hidden: !open && !node.isRoot,
})}
>
{[...tmpNodes, ...node.children].map((node, idx) => (
<li key={node.id}>
<FileNode
indentation={[...indentation, { isLast: idx === lastIdx }]}
node={node}
/>
</li>
))}
{allNodes.map((node, idx) => {
return (
<li key={node.id}>
<FileNode
indentation={[...indentation, { isLast: idx === lastIdx }]}
node={node}
/>
</li>
)
})}
</ul>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export function useNodeValidator({
const onClickOutside = useCallback(async () => {
const val = inputRef.current?.value ?? ''
const value = val.trim()
setValue(value)

if (!value) {
leaveWithoutSave?.()
Expand Down Expand Up @@ -117,6 +118,6 @@ export function useNodeValidator({
onInputChange,
onInputKeyDown,
error: validationError,
keepFocused: !value.trim(),
keepFocused: !value,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ describe('useTempNodes', () => {

it('should add a folder', async () => {
const { result } = renderHook(() => useTempNodes((state) => state))
act(() => result.current.addFolder({ parentPath: 'some-folder' }))
act(() =>
result.current.addFolder({
parentPath: 'some-folder',
parentId: 'fake-id',
}),
)

expect(result.current.tmpFolders).toEqual({
'some-folder': [
Expand All @@ -27,7 +32,12 @@ describe('useTempNodes', () => {

it('should update a folder', async () => {
const { result } = renderHook(() => useTempNodes((state) => state))
act(() => result.current.addFolder({ parentPath: 'some-folder' }))
act(() =>
result.current.addFolder({
parentPath: 'some-folder',
parentId: 'fake-id',
}),
)
const id = result?.current?.tmpFolders?.['some-folder']?.[0]?.id
act(() => result.current.updateFolder({ id: id!, path: 'new-name' }))

Expand All @@ -45,10 +55,62 @@ describe('useTempNodes', () => {

it('should delete a folder', async () => {
const { result } = renderHook(() => useTempNodes((state) => state))
act(() => result.current.addFolder({ parentPath: 'some-folder' }))
act(() =>
result.current.addFolder({
parentPath: 'some-folder',
parentId: 'fake-id',
}),
)
const id = result?.current?.tmpFolders?.['some-folder']?.[0]?.id
act(() => result.current.deleteTmpFolder({ id: id! }))

expect(result.current.tmpFolders).toEqual({ 'some-folder': [] })
})

it.only('should update the parent folder children', async () => {
const { result } = renderHook(() => useTempNodes((state) => state))
act(() =>
result.current.addFolder({
parentPath: 'some-folder',
parentId: 'fake-id',
}),
)
const id = result?.current?.tmpFolders?.['some-folder']?.[0]?.id
act(() =>
result.current.updateFolder({ id: id!, path: 'parent-tmp-folder' }),
)

act(() =>
result.current.addFolder({
parentPath: 'some-folder/parent-tmp-folder',
parentId: id!,
}),
)

const childId =
result?.current?.tmpFolders?.['some-folder']?.[0]?.children?.[0]?.id

act(() =>
result.current.updateFolder({ id: childId!, path: 'child-tmp-folder' }),
)

expect(result.current.tmpFolders).toEqual({
'some-folder': [
new Node({
id: expect.any(String),
path: 'some-folder/parent-tmp-folder',
name: 'parent-tmp-folder',
isPersisted: false,
children: [
new Node({
id: expect.any(String),
path: 'some-folder/parent-tmp-folder/child-tmp-folder',
name: 'child-tmp-folder',
isPersisted: false,
}),
],
}),
],
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,30 @@ import { defaultGenerateNodeUuid, Node } from '../useTree'

type OpenPathsState = {
tmpFolders: Record<string, Node[]>
addFolder: (args: { parentPath: string }) => void
addFolder: (args: { parentPath: string; parentId: string }) => void
updateFolder: (args: { id: string; path: string }) => void
deleteTmpFolder: (args: { id: string }) => void
reset: () => void
}

function nodeAndChildren(node: Node): Node[] {
return [node, ...node.children.flatMap(nodeAndChildren)]
}

function allTmpNodes(tmpFolders: OpenPathsState['tmpFolders']) {
return Object.values(tmpFolders).flatMap((nodes) => nodes)
return Object.values(tmpFolders)
.flatMap((nodes) => nodes.map(nodeAndChildren))
.flat()
}

function createEmptyNode({ parentPath }: { parentPath: string }) {
const emptyName = ' '
return new Node({
id: defaultGenerateNodeUuid(),
name: emptyName,
path: `${parentPath}/${emptyName}`,
isPersisted: false,
})
}

export const useTempNodes = create<OpenPathsState>((set) => ({
Expand All @@ -21,16 +37,37 @@ export const useTempNodes = create<OpenPathsState>((set) => ({
tmpFolders: {},
})
},
addFolder: ({ parentPath }) => {
addFolder: ({ parentPath, parentId }) => {
set((state) => {
const prevNodes = state.tmpFolders[parentPath]
const emptyName = ' '
const node = new Node({
id: defaultGenerateNodeUuid(),
name: emptyName,
path: `${parentPath}/${emptyName}`,
isPersisted: false,
const allNodes = allTmpNodes(state.tmpFolders)
const parentNode = allNodes.find((node) => node.id === parentId)

const node = createEmptyNode({
parentPath: parentNode ? parentNode.path : parentPath,
})

if (parentNode) {
parentNode.children = [node, ...parentNode.children]
const grandParentPath = parentNode.path
.split('/')
.slice(0, -1)
.join('/')
const grandParent = state.tmpFolders[grandParentPath]
if (!grandParent) return state
const idx = grandParent.findIndex((n) => n.id === parentId)
return {
tmpFolders: {
...state.tmpFolders,
[grandParentPath]: [
...grandParent.slice(0, idx),
parentNode,
...grandParent.slice(idx + 1),
],
},
}
}

const prevNodes = state.tmpFolders[parentPath]
return {
tmpFolders: {
...state.tmpFolders,
Expand All @@ -46,26 +83,11 @@ export const useTempNodes = create<OpenPathsState>((set) => ({
if (!node) return state

const parentPath = node.path.split('/').slice(0, -1).join('/')
const parent = state.tmpFolders[parentPath]
if (!parent) return state

const idx = parent.findIndex((n) => n.id === id)
const existingNode = parent[idx]
if (!existingNode) return state
node.name = path
node.path = `${parentPath}/${path}`

existingNode.name = path
existingNode.path = `${parentPath}/${path}`

return {
tmpFolders: {
...state.tmpFolders,
[parentPath]: [
...parent.slice(0, idx),
existingNode,
...parent.slice(idx + 1),
],
},
}
return state
})
},
deleteTmpFolder: ({ id }) => {
Expand Down

0 comments on commit d654a61

Please sign in to comment.