Skip to content

Commit 461637b

Browse files
feat: improve data structure (#20)
1 parent caa454f commit 461637b

File tree

5 files changed

+165
-155
lines changed

5 files changed

+165
-155
lines changed

package.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@
66
"type": "module",
77
"exports": {
88
".": {
9-
"import": "./dist/index.ts",
10-
"types": "./dist/index.ts",
11-
"default": "./dist/index.ts"
9+
"import": "./src/index.ts",
10+
"types": "./src/index.ts",
11+
"default": "./src/index.ts"
1212
},
1313
"./client": {
14-
"import": "./dist/exports/client.ts",
15-
"types": "./dist/exports/client.ts",
16-
"default": "./dist/exports/client.ts"
14+
"import": "./src/exports/client.ts",
15+
"types": "./src/exports/client.ts",
16+
"default": "./src/exports/client.ts"
1717
},
1818
"./rsc": {
19-
"import": "./dist/exports/rsc.ts",
20-
"types": "./dist/exports/rsc.ts",
21-
"default": "./dist/exports/rsc.ts"
19+
"import": "./src/exports/rsc.ts",
20+
"types": "./src/exports/rsc.ts",
21+
"default": "./src/exports/rsc.ts"
2222
}
2323
},
24-
"main": "./dist/index.ts",
25-
"types": "./dist/index.ts",
24+
"main": "./src/index.ts",
25+
"types": "./src/index.ts",
2626
"files": [
2727
"dist"
2828
],

src/components/TreeViewComponent.tsx

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,82 @@
1-
import type { DocType, TreeNode } from 'src/lib/buildFolderTree.js';
1+
import type { Document, FlatTree } from 'src/lib/buildFolderTree.js';
22

33
import { Link, NavGroup } from '@payloadcms/ui';
44
import React from 'react';
55

66
import styles from "./styles.module.css";
77

88
interface TreeViewClientProps {
9-
data: TreeNode[];
9+
data: FlatTree;
1010
}
1111

1212
const TreeViewComponent: React.FC<TreeViewClientProps> = ({ data }) => {
13-
// TODO: Reimplement open folder icon
14-
const buildNodeHref = (node: TreeNode) => {
15-
return `/admin/browse-by-folder/${node.id}`;
16-
};
13+
const getDocumentLabel = (id: string) => id;
14+
const getFolderLabel = (id: string) => data.items[id]?.title || id;
1715

18-
const buildDocumentHref = (doc: DocType) => {
19-
return `/admin/collections/${doc.relationTo}/${doc._id}`;
20-
};
16+
const renderDocuments = (documents: Document[], depth: number) => {
17+
if (!documents.length) {
18+
return <span className={styles.emptyState}>No documents found...</span>;
19+
}
2120

22-
const getDocumentLabel = (doc: DocType) => {
23-
return doc.title || doc._id;
24-
};
25-
26-
const renderDocuments = (docs: DocType[], depth: number) => {
2721
return (
28-
<ul data-depth={depth}>
29-
{docs.map((doc) => (
30-
<div className={styles.treeItem} data-type="document" key={doc._id}>
22+
<ul className={styles.documentList} data-depth={depth}>
23+
{documents.map(doc => (
24+
<li className={styles.treeItem} data-type="document" key={doc.id}>
3125
<Link
32-
href={buildDocumentHref(doc)}
33-
title={getDocumentLabel(doc)}
26+
href="#"
27+
title={getDocumentLabel(doc.id)}
3428
>
3529
<span className={styles.itemName}>
36-
{getDocumentLabel(doc)}
30+
{getDocumentLabel(doc.id)}
3731
</span>
3832
</Link>
39-
</div>
33+
</li>
4034
))}
4135
</ul>
4236
);
4337
};
4438

45-
const renderFolders = (nodes: TreeNode[], depth = 0) => (
46-
<ul className={styles.documentList} data-depth={depth}>
47-
{nodes.map(node => {
48-
return (
49-
<NavGroup data-depth={depth} isOpen={false} key={node.id} label={node.name}>
50-
{node.folders && node.folders.length > 0 && renderFolders(node.folders, depth + 1)}
51-
{Array.isArray(node.documents) && node.documents.length > 0 ? renderDocuments(node.documents, depth + 1) : (
52-
<span className={styles.emptyState}>
53-
No documents found...
54-
</span>
55-
)}
56-
</NavGroup>
57-
);
58-
})}
59-
</ul>
60-
);
39+
const renderFolders = (folderIds: string[], depth = 0): React.ReactNode => {
40+
if (!folderIds.length) { return null; }
41+
42+
return (
43+
<ul data-depth={depth}>
44+
{folderIds.map(folderId => {
45+
const folderNode = data.items[folderId];
46+
if (!folderNode) { return null; }
47+
48+
const childFolderIds =
49+
(folderNode.folders || []).map(f => (typeof f === 'string' ? f : f.id));
50+
51+
const documents = folderNode.documents || [];
52+
const hasFolders = childFolderIds.length > 0;
53+
const hasDocuments = documents.length > 0;
54+
55+
return (
56+
<NavGroup
57+
data-depth={depth}
58+
isOpen={false}
59+
key={folderId}
60+
label={getFolderLabel(folderId)}
61+
>
62+
{hasFolders && renderFolders(childFolderIds, depth + 1)}
63+
{hasDocuments
64+
? renderDocuments(documents, depth + 1)
65+
: !hasFolders && <span className={styles.emptyState}>Empty folder...</span>}
66+
</NavGroup>
67+
);
68+
})}
69+
</ul>
70+
);
71+
};
6172

6273
return (
6374
<div className={styles.treeView}>
6475
<NavGroup isOpen={false} label="Folders">
65-
{data.length === 0 ? (
66-
<span className={styles.emptyState}>
67-
No folders found...
68-
</span>
76+
{data.rootIds.length === 0 ? (
77+
<span className={styles.emptyState}>No folders found...</span>
6978
) : (
70-
renderFolders(data)
79+
renderFolders(data.rootIds, 0)
7180
)}
7281
</NavGroup>
7382
</div>

src/components/TreeViewServer.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1-
import type { ServerComponentProps } from "payload"
1+
import type { JsonObject, ServerComponentProps, TypeWithID } from "payload"
22
import type { PayloadFolderTreeViewConfig } from "src/index.js"
33

4-
import type { Folder } from "../lib/buildFolderTree.js";
4+
import type { FolderEntry } from "../lib/buildFolderTree.js";
55

6-
import { buildFolderTree } from "../lib/buildFolderTree.js"
6+
import { buildSimpleFolderTree } from "../lib/buildFolderTree.js"
77
import TreeViewComponent from "./TreeViewComponent.js";
88

99
export const TreeViewServer = async (props: PayloadFolderTreeViewConfig & ServerComponentProps) => {
1010
const folders = await props.payload.find({
1111
collection: 'payload-folders',
12-
})
12+
});
1313

14-
const treeData = buildFolderTree({
15-
allDocs: folders.docs as Folder[],
16-
})
14+
const folderEntries: FolderEntry[] = folders.docs.map((doc: JsonObject & TypeWithID) => ({
15+
...doc,
16+
_id: doc._id !== undefined ? String(doc._id) : undefined,
17+
id: doc.id !== undefined ? String(doc.id) : undefined,
18+
folderType: doc.folderType,
19+
value: doc.value,
20+
}));
21+
22+
const treeData = buildSimpleFolderTree(folderEntries);
1723

1824
return <TreeViewComponent data={treeData} />
1925
}

src/components/styles.module.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
width: 100%;
33
}
44

5-
.documentList {
6-
border-left: 2px solid rgba(0, 0, 0, 0.1);
5+
.treeItem {
6+
list-style: none;
77
}

0 commit comments

Comments
 (0)