refact: extract tree build a hook

This commit is contained in:
Jean-Philippe Sirois
2019-07-27 17:32:39 -04:00
parent 04d0c19239
commit f7f66a3071
2 changed files with 98 additions and 88 deletions
+8 -88
View File
@@ -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<IAllDocsQuery>(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 (
<SC.DocsSidebarWrapper>
{results.map(node => plantTree(node))}
{tree.map(node => plantTree(node))}
</SC.DocsSidebarWrapper>
)
}
@@ -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)
}