From f7f66a307196f26ba0586a43362e3142973814c2 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Sirois Date: Sat, 27 Jul 2019 17:17:00 -0400 Subject: [PATCH] refact: extract tree build a hook --- src/components/DocsSidebar/index.tsx | 96 ++------------------- src/components/DocsSidebar/useBuildTree.tsx | 90 +++++++++++++++++++ 2 files changed, 98 insertions(+), 88 deletions(-) create mode 100644 src/components/DocsSidebar/useBuildTree.tsx diff --git a/src/components/DocsSidebar/index.tsx b/src/components/DocsSidebar/index.tsx index e3245ca..cc221ba 100644 --- a/src/components/DocsSidebar/index.tsx +++ b/src/components/DocsSidebar/index.tsx @@ -1,99 +1,25 @@ -import * as R from "ramda" import React, { useState } from "react" import Tree from "react-treeview" import { useStaticQuery, graphql } from "gatsby" +import useBuildTree from "./useBuildTree" import * as SC from "./styles" -interface IFile { +export interface IFile { title: string type: "file" path: string } -interface IFolder { +export interface IFolder { title: string type: "folder" path: string children: IFileOrFolder[] } -type IFileOrFolder = IFile | IFolder +export type IFileOrFolder = IFile | IFolder -const traverse = ( - [head, ...tail]: string[], - basePath = "/docs" -): IFileOrFolder => { - const path = basePath + "/" + head - const isFile = !tail.length - if (isFile) { - // probably not more than one dot - const [name] = head.split(".") - return { - title: name, - type: "file", - path, - } - } - return { - title: head, - type: "folder", - path, - children: [traverse(tail, path)], - } -} - -const generateFolder = ({ - title, - path, - targets, -}: { - title: IFolder["title"] - path: IFile["path"] - targets: IFolder[] -}): IFolder => { - const children = join(R.chain(target => target.children, targets)) - - return { - title, - type: "folder", - path, - children, - } -} - -const generateFile = ({ - title, - path, -}: { - title: IFile["title"] - path: IFile["path"] -}): IFile => { - return { - title, - path, - type: "file", - } -} - -const join = ([head, ...tail]: IFileOrFolder[]): IFileOrFolder[] => { - if (!head) return [] - - const [similarFs, remaining] = R.partition( - obj => obj.title === head.title && obj.type === head.type, - tail - ) - const targets = [head, ...similarFs] - const { title, path } = head - - const current = - head.type === "folder" - ? generateFolder({ title, path, targets: targets as IFolder[] }) - : generateFile({ title, path }) - - return [current, ...join(remaining)] -} - -interface IFileQuery { +export interface IFileQuery { node: { relativePath: string childMarkdownRemark: { @@ -105,7 +31,7 @@ interface IFileQuery { } } -interface IAllDocsQuery { +export interface IAllDocsQuery { allFile: { edges: IFileQuery[] } @@ -160,17 +86,11 @@ function Folder({ item }: { item: IFolder }) { const DocsSidebar = () => { const docs = useStaticQuery(ALL_DOCS) - - const objects = docs.allFile.edges.map(({ node: file }: IFileQuery) => - traverse(file.relativePath.split("/")) - ) - const results = join(objects) - - console.log(results) + const tree = useBuildTree(docs) return ( - {results.map(node => plantTree(node))} + {tree.map(node => plantTree(node))} ) } diff --git a/src/components/DocsSidebar/useBuildTree.tsx b/src/components/DocsSidebar/useBuildTree.tsx new file mode 100644 index 0000000..a3d6e5a --- /dev/null +++ b/src/components/DocsSidebar/useBuildTree.tsx @@ -0,0 +1,90 @@ +import * as R from "ramda" +import { + IFileOrFolder, + IFile, + IFolder, + IAllDocsQuery, + IFileQuery, +} from "./index" + +const traverse = ( + [head, ...tail]: string[], + basePath = "/docs" +): IFileOrFolder => { + const path = basePath + "/" + head + const isFile = !tail.length + if (isFile) { + // probably not more than one dot + const [name] = head.split(".") + return { + title: name, + type: "file", + path, + } + } + return { + title: head, + type: "folder", + path, + children: [traverse(tail, path)], + } +} + +const generateFolder = ({ + title, + path, + targets, +}: { + title: IFolder["title"] + path: IFile["path"] + targets: IFolder[] +}): IFolder => { + const children = join(R.chain(target => target.children, targets)) + + return { + title, + type: "folder", + path, + children, + } +} + +const generateFile = ({ + title, + path, +}: { + title: IFile["title"] + path: IFile["path"] +}): IFile => { + return { + title, + path, + type: "file", + } +} + +const join = ([head, ...tail]: IFileOrFolder[]): IFileOrFolder[] => { + if (!head) return [] + + const [similarFs, remaining] = R.partition( + obj => obj.title === head.title && obj.type === head.type, + tail + ) + const targets = [head, ...similarFs] + const { title, path } = head + + const current = + head.type === "folder" + ? generateFolder({ title, path, targets: targets as IFolder[] }) + : generateFile({ title, path }) + + return [current, ...join(remaining)] +} + +export default function useBuildTree(docs: IAllDocsQuery) { + const objects = docs.allFile.edges.map(({ node: file }: IFileQuery) => + traverse(file.relativePath.split("/")) + ) + + return join(objects) +}