-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Change sidebar tree creation to use path instead of parentId. Also move
sidebar to web-ui
- Loading branch information
1 parent
6d93bf1
commit 5f4611f
Showing
8 changed files
with
689 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
packages/web-ui/postcss.config.js → packages/web-ui/postcss.config.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
module.exports = { | ||
export default { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export { default as FocusLayout } from './FocusLayout' | ||
export { default as AppLayout } from './AppLayout' | ||
export { default as AppHeader } from './AppLayout/Header' | ||
export { default as DocumentsSidebar } from './DocumentsSidebar' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use client' | ||
|
||
import { SidebarDocument, useTree, Node } from '$ui/sections/DocumentsSidebar/useTree' | ||
|
||
function TreeNode({ node, level = 0 }: { node: Node; level?: number }) { | ||
return ( | ||
<div key={node.doc?.id || 'root'}> | ||
<div className='flex flex-col gap-2' style={{ paddingLeft: level * 2 }}> | ||
{!!node.doc && ( | ||
<div className='flex flex-row align-items justify-between'> | ||
{node.doc.documentType === 'folder' ? ( | ||
<> | ||
<p>{node.doc.name}</p> | ||
<CreateNode parentId={node.doc.id} /> | ||
</> | ||
) : ( | ||
<p className='font-bold'>{node.doc.name}</p> | ||
)} | ||
</div> | ||
)} | ||
{node.children.map((node, idx) => ( | ||
<TreeNode key={idx} node={node} level={level + 1} /> | ||
))} | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
export default function DocumentTree({ | ||
documents, | ||
}: { | ||
documents: SidebarDocument[] | ||
}) { | ||
const rootNode = useTree({ documents }) | ||
|
||
return <TreeNode node={rootNode} /> | ||
} |
64 changes: 64 additions & 0 deletions
64
packages/web-ui/src/sections/DocumentsSidebar/useTree/index.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { renderHook } from '@testing-library/react' | ||
import { describe, expect, it } from 'vitest' | ||
|
||
import { Node, useTree } from './index' | ||
|
||
let list = [ | ||
{ path: 'things/doc1', doumentUuid: '1' }, | ||
{ path: 'things/doc2', doumentUuid: '2' }, | ||
{ path: 'things/other-things/doc3', doumentUuid: '3' }, | ||
{ path: 'something-else/doc4', doumentUuid: '4' }, | ||
] | ||
|
||
describe('useTree', () => { | ||
it('should return a tree with children', () => { | ||
const { result } = renderHook(() => useTree({ documents: list })) | ||
expect(result.current).toEqual( | ||
new Node({ | ||
doc: undefined, | ||
isRoot: true, | ||
name: 'root', | ||
children: [ | ||
new Node({ | ||
doc: undefined, | ||
name: 'things', | ||
children: [ | ||
new Node({ | ||
doc: { path: 'things/doc1', doumentUuid: '1' }, | ||
name: 'doc1', | ||
children: [], | ||
}), | ||
new Node({ | ||
doc: { path: 'things/doc2', doumentUuid: '2' }, | ||
name: 'doc2', | ||
children: [], | ||
}), | ||
new Node({ | ||
doc: undefined, | ||
name: 'other-things', | ||
children: [ | ||
new Node({ | ||
doc: { path: 'things/other-things/doc3', doumentUuid: '3' }, | ||
name: 'doc3', | ||
children: [], | ||
}), | ||
], | ||
}), | ||
], | ||
}), | ||
new Node({ | ||
doc: undefined, | ||
name: 'something-else', | ||
children: [ | ||
new Node({ | ||
doc: { path: 'something-else/doc4', doumentUuid: '4' }, | ||
name: 'doc4', | ||
children: [], | ||
}), | ||
], | ||
}), | ||
], | ||
}), | ||
) | ||
}) | ||
}) |
84 changes: 84 additions & 0 deletions
84
packages/web-ui/src/sections/DocumentsSidebar/useTree/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { useMemo } from 'react' | ||
|
||
export type SidebarDocument = { | ||
path: string | ||
doumentUuid: string | ||
} | ||
|
||
export class Node { | ||
public doc?: SidebarDocument | ||
public children: Node[] = [] | ||
public isRoot: boolean = false | ||
private name: string = '' | ||
|
||
constructor({ | ||
doc, | ||
children = [], | ||
isRoot = false, | ||
name = '', | ||
}: { | ||
doc?: SidebarDocument | ||
children?: Node[] | ||
isRoot?: boolean | ||
name?: string | ||
}) { | ||
this.doc = doc | ||
this.children = children | ||
this.isRoot = isRoot | ||
this.name = isRoot ? 'root' : name | ||
} | ||
} | ||
|
||
function sortByPathDepth(a: SidebarDocument, b: SidebarDocument) { | ||
const depth1 = (a.path.match(/\//g) || []).length | ||
const depth2 = (b.path.match(/\//g) || []).length | ||
return depth1 - depth2 | ||
} | ||
|
||
function buildTree({ | ||
root, | ||
nodeMap, | ||
documents, | ||
}: { | ||
root: Node | ||
nodeMap: Map<string, Node> | ||
documents: SidebarDocument[] | ||
}) { | ||
documents.forEach((doc) => { | ||
const segments = doc.path.split('/') | ||
let path = '' | ||
|
||
segments.forEach((segment, index) => { | ||
const isFile = index === segments.length - 1 | ||
path = path ? `${path}/${segment}` : segment | ||
|
||
if (!nodeMap.has(path)) { | ||
const file = isFile ? doc : undefined | ||
const node = new Node({ doc: file, name: segment }) | ||
nodeMap.set(path, node) | ||
|
||
const parentPath = path.split('/').slice(0, -1).join('/') | ||
|
||
// We force TypeScript to check that the parentPath is not empty | ||
// We pre-sorted documents by path depth, so we know | ||
// that the parent node exists | ||
const parent = nodeMap.get(parentPath)! | ||
parent.children.push(node) | ||
} | ||
}) | ||
}) | ||
|
||
return root | ||
} | ||
|
||
export function useTree({ documents }: { documents: SidebarDocument[] }) { | ||
return useMemo(() => { | ||
const root = new Node({ children: [], isRoot: true }) | ||
const nodeMap = new Map<string, Node>() | ||
nodeMap.set('', root) | ||
const sorted = documents.slice().sort(sortByPathDepth) | ||
|
||
const tree = buildTree({ root, nodeMap, documents: sorted }) | ||
return tree | ||
}, [documents]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { defineConfig } from 'vitest/config' | ||
import { resolve } from 'path' | ||
|
||
export default defineConfig({ | ||
resolve: { | ||
alias: { | ||
$ui: resolve(__dirname, './src'), | ||
}, | ||
}, | ||
test: { | ||
environment: 'jsdom', | ||
}, | ||
}) |
Oops, something went wrong.