summaryrefslogtreecommitdiff
path: root/pages
diff options
context:
space:
mode:
authorThomas F. K. Jorna <[email protected]>2021-08-16 16:43:31 +0200
committerThomas F. K. Jorna <[email protected]>2021-08-16 16:44:36 +0200
commit733cf88bbfb172fe9c2211d2432e2b1ff2ffcc2d (patch)
tree7fe47d14255bf25315bb397e5bf17c9a74e35b82 /pages
parentd5135e1caec93b7d87b5d40f1fc911702238092a (diff)
feat: link children to parent heading #62 #53 #49
Diffstat (limited to 'pages')
-rw-r--r--pages/index.tsx133
1 files changed, 95 insertions, 38 deletions
diff --git a/pages/index.tsx b/pages/index.tsx
index 960ab5e..12f9f74 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -102,7 +102,7 @@ export function GraphPage() {
}
}, {})
- const fileLinks: OrgRoamLink[] = Object.keys(nodesByFile).flatMap((file) => {
+ const headingLinks: OrgRoamLink[] = Object.keys(nodesByFile).flatMap((file) => {
const nodesInFile = nodesByFile[file] ?? []
// "file node" as opposed to "heading node"
const fileNode = nodesInFile.find((node) => node.level === 0)
@@ -111,17 +111,55 @@ export function GraphPage() {
if (!fileNode) {
return []
}
+ return headingNodes.map((headingNode) => {
+ const smallerHeadings = nodesInFile.filter((node) => {
+ if (node.level >= headingNode.level) {
+ return false
+ }
+ return true
+ })
+ const smallerPos = smallerHeadings.map((node) => {
+ if (node.pos >= headingNode.pos) {
+ return 0
+ }
+ return node.pos
+ })
- return headingNodes.map((headingNode) => ({
- source: headingNode.id,
- target: fileNode.id,
- type: 'parent',
- }))
+ const target = nodesInFile.find((node) => {
+ return node.pos === Math.max(...smallerPos)
+ })
+
+ return {
+ source: headingNode.id,
+ target: target!.id,
+ type: 'heading',
+ }
+ })
})
- nodeByIdRef.current = Object.fromEntries(orgRoamGraphData.nodes.map((node) => [node.id, node]))
+ // we want to support both linking to only the file node and to the next heading
+ // to do this we need both links, as we can't really toggle between them without
+ // recalculating the entire graph otherwise
+ const fileLinks: OrgRoamLink[] = Object.keys(nodesByFile).flatMap((file) => {
+ const nodesInFile = nodesByFile[file] ?? []
+ // "file node" as opposed to "heading node"
+ const fileNode = nodesInFile.find((node) => node.level === 0)
+ const headingNodes = nodesInFile.filter((node) => node.level !== 0)
- const dirtyLinks = [...orgRoamGraphData.links, ...fileLinks]
+ if (!fileNode) {
+ return []
+ }
+ return headingNodes.map((headingNode) => {
+ return {
+ source: headingNode.id,
+ target: fileNode.id,
+ type: 'parent',
+ }
+ })
+ })
+
+ nodeByIdRef.current = Object.fromEntries(orgRoamGraphData.nodes.map((node) => [node.id, node]))
+ const dirtyLinks = [...orgRoamGraphData.links, ...headingLinks, ...fileLinks]
const nonExistantNodes: OrgRoamNode[] = []
const links = dirtyLinks.map((link) => {
const sourceId = link.source as string
@@ -134,6 +172,7 @@ export function GraphPage() {
file: '',
title: sourceId,
level: 0,
+ pos: 0,
})
return { ...link, type: 'bad' }
}
@@ -145,6 +184,7 @@ export function GraphPage() {
file: '',
title: targetId,
level: 0,
+ pos: 0,
})
return { ...link, type: 'bad' }
}
@@ -548,24 +588,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
setHoverNode(nodeById[emacsNodeId] as NodeObject)
}, [emacsNodeId])
- centralHighlightedNode.current = hoverNode
- const highlightedNodes = useMemo(() => {
- if (!centralHighlightedNode.current) {
- return {}
- }
-
- const links = linksByNodeId[centralHighlightedNode.current.id!]
- if (!links) {
- return {}
- }
-
- return Object.fromEntries(
- [
- centralHighlightedNode.current.id! as string,
- ...links.flatMap((link) => [link.source, link.target]),
- ].map((nodeId) => [nodeId, {}]),
- )
- }, [centralHighlightedNode.current, linksByNodeId])
+ const filteredLinksByNodeIdRef = useRef<LinksByNodeId>({})
const hiddenNodeIdsRef = useRef<NodeById>({})
const filteredGraphData = useMemo(() => {
@@ -608,7 +631,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
return true
}
- if (filter.parents) {
+ if (filter.parent) {
return unhiddenLinks.length !== 0
}
@@ -616,7 +639,7 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
return false
}
- return unhiddenLinks.some((link) => !['parent'].includes(link.type))
+ return unhiddenLinks.some((link) => !['parent', 'heading'].includes(link.type))
})
const filteredNodeIds = filteredNodes.map((node) => node.id as string)
@@ -629,8 +652,22 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
return false
}
const linkRoam = link as OrgRoamLink
- return filter.parents || linkRoam.type !== 'parent'
+ if (!filter.parent) {
+ return !['parent', 'heading'].includes(linkRoam.type)
+ }
+ return linkRoam.type !== ['parent', 'heading'].find((type) => type !== filter.parent)
})
+
+ filteredLinksByNodeIdRef.current = filteredLinks.reduce<LinksByNodeId>((acc, linkArg) => {
+ const link = linkArg as OrgRoamLink
+ const [sourceId, targetId] = normalizeLinkEnds(link)
+ return {
+ ...acc,
+ [sourceId]: [...(acc[sourceId] ?? []), link],
+ [targetId]: [...(acc[targetId] ?? []), link],
+ }
+ }, {})
+
return { nodes: filteredNodes, links: filteredLinks }
}, [filter, graphData])
@@ -691,6 +728,25 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
setScopedGraphData({ nodes: scopedNodes, links: scopedLinks })
}, [filter, scope, graphData])
+ centralHighlightedNode.current = hoverNode
+ const highlightedNodes = useMemo(() => {
+ if (!centralHighlightedNode.current) {
+ return {}
+ }
+
+ const links = filteredLinksByNodeIdRef.current[centralHighlightedNode.current.id!]
+ if (!links) {
+ return {}
+ }
+
+ return Object.fromEntries(
+ [
+ centralHighlightedNode.current.id! as string,
+ ...links.flatMap((link) => [link.source, link.target]),
+ ].map((nodeId) => [nodeId, {}]),
+ )
+ }, [centralHighlightedNode.current, linksByNodeId])
+
useEffect(() => {
;(async () => {
const fg = graphRef.current
@@ -788,18 +844,19 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
}, [JSON.stringify(hoverNode), lastHoverNode.current])
const getNodeColorById = (id: string) => {
- const linklen = linksByNodeId[id!]?.length ?? 0
- const parentCiteNeighbors = linklen
- ? linksByNodeId[id!]?.filter((link) => link.type === 'parent').length
- : 0
- const neighbors = filter.parents ? linklen : linklen - parentCiteNeighbors!
+ const linklen = filteredLinksByNodeIdRef.current[id!]?.length ?? 0
+ /* const parentCiteNeighbors = linklen
+ * ? linksByNodeId[id!]?.filter((link) => ['parent', 'heading', 'cite', 'ref'].includes(link.type)).length
+ * : 0
+ * const neighbors = filter.parent ? linklen : linklen - parentCiteNeighbors! */
return visuals.nodeColorScheme[
- numberWithinRange(neighbors, 0, visuals.nodeColorScheme.length - 1)
+ numberWithinRange(linklen, 0, visuals.nodeColorScheme.length - 1)
]
}
const getLinkNodeColor = (sourceId: string, targetId: string) => {
- return linksByNodeId[sourceId]! > linksByNodeId[targetId]!
+ return filteredLinksByNodeIdRef.current[sourceId]!.length >
+ filteredLinksByNodeIdRef.current[targetId]!.length
? getNodeColorById(sourceId)
: getNodeColorById(targetId)
}
@@ -883,10 +940,10 @@ export const Graph = forwardRef(function (props: GraphProps, graphRef: any) {
)
const nodeSize = (node: NodeObject) => {
- const links = linksByNodeId[node.id!] ?? []
+ const links = filteredLinksByNodeIdRef.current[node.id!] ?? []
const parentNeighbors = links.length ? links.filter((link) => link.type === 'parent').length : 0
const basicSize =
- 3 + links.length * visuals.nodeSizeLinks - (!filter.parents ? parentNeighbors : 0)
+ 3 + links.length * visuals.nodeSizeLinks - (!filter.parent ? parentNeighbors : 0)
if (visuals.highlightNodeSize === 1) {
return basicSize
}