Skip to content

Commit 67b7afe

Browse files
authored
Revert "feat: local graph param"
1 parent 10d7a8f commit 67b7afe

File tree

2 files changed

+186
-29
lines changed

2 files changed

+186
-29
lines changed

components/contextmenu.tsx

+99-7
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,53 @@
1-
import React from 'react'
1+
import React, { useRef } from 'react'
22
import {
3+
Box,
34
Menu,
45
MenuItem,
56
MenuList,
7+
MenuGroup,
8+
MenuItemOption,
9+
MenuOptionGroup,
610
Heading,
711
MenuDivider,
12+
Modal,
13+
ModalOverlay,
14+
ModalContent,
15+
ModalHeader,
16+
ModalFooter,
17+
ModalBody,
18+
ModalCloseButton,
19+
useDisclosure,
20+
Button,
21+
PopoverTrigger,
22+
PopoverContent,
23+
Popover,
24+
Flex,
25+
PopoverBody,
26+
PopoverCloseButton,
27+
PopoverArrow,
28+
PopoverHeader,
29+
PopoverFooter,
30+
Portal,
31+
Text,
32+
VStack,
833
} from '@chakra-ui/react'
934
import {
35+
DeleteIcon,
36+
EditIcon,
37+
CopyIcon,
38+
AddIcon,
1039
ViewIcon,
40+
ExternalLinkIcon,
41+
ChevronRightIcon,
1142
PlusSquareIcon,
1243
MinusIcon,
1344
} from '@chakra-ui/icons'
1445

15-
import { OrgRoamNode } from '../api'
46+
import { OrgRoamGraphReponse, OrgRoamLink, OrgRoamNode } from '../api'
47+
import { deleteNodeInEmacs, openNodeInEmacs, createNodeInEmacs } from '../util/webSocketFunctions'
1648
import { BiNetworkChart } from 'react-icons/bi'
1749
import { TagMenu } from './TagMenu'
1850
import { initialFilter, TagColors } from './config'
19-
import { useSearchParams } from 'next/navigation'
2051

2152
export default interface ContextMenuProps {
2253
background: Boolean
@@ -36,25 +67,30 @@ export default interface ContextMenuProps {
3667

3768
export const ContextMenu = (props: ContextMenuProps) => {
3869
const {
70+
background,
3971
target,
72+
nodeType,
4073
coordinates,
4174
handleLocal,
4275
menuClose,
4376
scope,
77+
webSocket,
4478
setPreviewNode,
4579
setTagColors,
4680
tagColors,
4781
setFilter,
4882
filter,
49-
} = props;
50-
const param = useSearchParams();
83+
} = props
84+
const { isOpen, onOpen, onClose } = useDisclosure()
85+
const copyRef = useRef<any>()
5186
return (
5287
<>
5388
<Menu defaultIsOpen closeOnBlur={false} onClose={() => menuClose()}>
5489
<MenuList
5590
zIndex="overlay"
5691
bgColor="white"
5792
color="black"
93+
//borderColor="gray.500"
5894
position="absolute"
5995
left={coordinates.left}
6096
top={coordinates.top}
@@ -94,13 +130,42 @@ export const ContextMenu = (props: ContextMenuProps) => {
94130
Open local graph
95131
</MenuItem>
96132
)}
133+
{/* Doesn't work at the moment
134+
<MenuItem closeOnSelect={false} closeOnBlur={false}>
135+
<Box _hover={{ bg: 'gray.200' }} width="100%">
136+
<Popover
137+
initialFocusRef={copyRef}
138+
trigger="hover"
139+
placement="right-start"
140+
gutter={0}
141+
>
142+
<PopoverTrigger>
143+
<MenuItem closeOnSelect={false} icon={<CopyIcon />}>
144+
<Flex justifyContent="space-between" alignItems="center">
145+
Copy...
146+
<ChevronRightIcon />
147+
</Flex>
148+
</MenuItem>
149+
</PopoverTrigger>
150+
<PopoverContent width={100}>
151+
<Menu defaultIsOpen closeOnBlur={false} closeOnSelect={false}>
152+
<MenuList bg="alt.100" zIndex="popover">
153+
<MenuItem ref={copyRef}>ID</MenuItem>
154+
<MenuItem>Title</MenuItem>
155+
<MenuItem>File path</MenuItem>
156+
</MenuList>
157+
</Menu>
158+
</PopoverContent>
159+
</Popover>
160+
</Box>
161+
</MenuItem> */}
162+
97163
<MenuItem
98164
icon={<ViewIcon />}
99165
onClick={() => {
100166
setPreviewNode(target)
101167
if (target) {
102-
console.log("search is ", window.location.search)
103-
history.replaceState(null, '', window.location.pathname + window.location.search + `#${target.id}`);
168+
history.replaceState(null, '', window.location.pathname + `#${target.id}`)
104169
}
105170
}}
106171
>
@@ -115,3 +180,30 @@ export const ContextMenu = (props: ContextMenuProps) => {
115180
</>
116181
)
117182
}
183+
184+
/* <Box>
185+
* <Popover>
186+
* <PopoverTrigger>
187+
* Permenantly delete node
188+
* </MenuItem>
189+
* </PopoverTrigger>
190+
* <PopoverContent borderColor="red.500" _focus={{}}>
191+
* <PopoverHeader fontWeight="semibold">Delete Node?</PopoverHeader>
192+
* <PopoverArrow />
193+
* <PopoverCloseButton onClick={onClose} />
194+
* <PopoverBody>
195+
* This will permanently delete your node! Are you sure you want to do this?
196+
* </PopoverBody>
197+
* <PopoverFooter>
198+
* <Flex justifyContent="space-between" py={1}>
199+
* <Button colorScheme="gray" bg="gray.800" color="alt.100" width={30} onClick={onClose}>
200+
* Nah
201+
* </Button>
202+
* <Button colorScheme="red" variant="link" onClick={onClose}>
203+
* Delete node
204+
* </Button>
205+
* </Flex>
206+
* </PopoverFooter>
207+
* </PopoverContent>
208+
* </Popover>
209+
* </Box> */

pages/index.tsx

+87-22
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1+
import { HamburgerIcon } from '@chakra-ui/icons'
12
import graphDataJson from '../graphdata.json'
23
import {
34
Box,
45
Flex,
6+
Heading,
57
IconButton,
8+
Slide,
69
Tooltip,
710
useDisclosure,
811
useOutsideClick,
912
useTheme,
1013
} from '@chakra-ui/react'
1114
import { useAnimation } from '@lilib/hooks'
12-
import { useWindowSize } from '@react-hook/window-size'
15+
import { useWindowSize, useWindowWidth } from '@react-hook/window-size'
1316
import * as d3int from 'd3-interpolate'
14-
import { GraphData, NodeObject } from 'force-graph'
17+
import { GraphData, LinkObject, NodeObject } from 'force-graph'
1518
import Head from 'next/head'
1619
import React, {
1720
ComponentPropsWithoutRef,
@@ -61,7 +64,8 @@ import { getNodeColor } from '../util/getNodeColor'
6164
import { isLinkRelatedToNode } from '../util/isLinkRelatedToNode'
6265
import { getLinkColor } from '../util/getLinkColor'
6366
import { Search } from '../components/Search'
64-
import { useRouter, useSearchParams } from 'next/navigation'
67+
import { useRouter } from "next/router";
68+
import { usePathname, useSearchParams } from 'next/navigation'
6569
import { TITLE_NAME } from '../constants/action'
6670

6771
const d3promise = import('d3-force-3d')
@@ -119,8 +123,7 @@ export function GraphPage() {
119123
const [threeDim, setThreeDim] = usePersistantState('3d', false)
120124
const [tagColors, setTagColors] = usePersistantState<TagColors>('tagCols', {})
121125
const [scope, setScope] = useState<Scope>({ nodeIds: [], excludedNodeIds: [] })
122-
const params = useSearchParams();
123-
const graphParam = params.get('graph');
126+
124127
const [physics, setPhysics] = usePersistantState('physics', initialPhysics)
125128
const [filter, setFilter] = usePersistantState('filter', initialFilter)
126129
const [visuals, setVisuals] = usePersistantState('visuals', initialVisuals)
@@ -130,13 +133,6 @@ export function GraphPage() {
130133
const [mouse, setMouse] = usePersistantState('mouse', initialMouse)
131134
const [coloring, setColoring] = usePersistantState('coloring', initialColoring)
132135
const [local, setLocal] = usePersistantState('local', initialLocal)
133-
const router = useRouter();
134-
135-
useEffect(() => {
136-
if (graphParam === 'local' && window.location.hash) {
137-
setScope({ nodeIds: [window.location.hash.replace('#', '')], excludedNodeIds: [] })
138-
}
139-
}, [graphParam]);
140136

141137
const [
142138
previewNodeState,
@@ -370,6 +366,75 @@ export function GraphPage() {
370366
const WebSocketRef = useRef<ReconnectingWebSocket | null>(null)
371367

372368
scopeRef.current = scope
369+
const followBehavior = (
370+
command: string,
371+
emacsNode: string,
372+
speed: number = 2000,
373+
padding: number = 200,
374+
) => {
375+
if (command === 'color') {
376+
return
377+
}
378+
const fg = graphRef.current
379+
const sr = scopeRef.current
380+
const bh = behaviorRef.current
381+
const links = linksByNodeIdRef.current[emacsNode] ?? []
382+
const nodes = Object.fromEntries(
383+
[emacsNode as string, ...links.flatMap((link) => [link.source, link.target])].map(
384+
(nodeId) => [nodeId, {}],
385+
),
386+
)
387+
if (command === 'zoom') {
388+
if (sr.nodeIds.length) {
389+
setScope({ nodeIds: [], excludedNodeIds: [] })
390+
}
391+
setTimeout(
392+
() => fg.zoomToFit(speed, padding, (node: NodeObject) => nodes[node.id as string]),
393+
50,
394+
)
395+
return
396+
}
397+
if (!sr.nodeIds.length) {
398+
setScope((current: Scope) => ({ ...current, nodeIds: [emacsNode] }))
399+
setTimeout(() => {
400+
fg.centerAt(0, 0, 10)
401+
fg.zoomToFit(1, padding)
402+
}, 50)
403+
return
404+
}
405+
if (bh.localSame !== 'add') {
406+
setScope((current: Scope) => ({ ...current, nodeIds: [emacsNode] }))
407+
setTimeout(() => {
408+
fg.centerAt(0, 0, 10)
409+
fg.zoomToFit(1, padding)
410+
}, 50)
411+
return
412+
}
413+
414+
// if the node is in the scoped nodes, add it to scope instead of replacing it
415+
if (
416+
!sr.nodeIds.includes(emacsNode) ||
417+
!sr.nodeIds.some((scopeId: string) => {
418+
return nodes[scopeId]
419+
})
420+
) {
421+
setScope((current: Scope) => ({ ...current, nodeIds: [emacsNode] }))
422+
setTimeout(() => {
423+
fg.centerAt(0, 0, 10)
424+
fg.zoomToFit(1, padding)
425+
}, 50)
426+
return
427+
}
428+
setScope((currentScope: Scope) => ({
429+
...currentScope,
430+
nodeIds: [...currentScope.nodeIds, emacsNode as string],
431+
}))
432+
setTimeout(() => {
433+
fg.centerAt(0, 0, 10)
434+
fg.zoomToFit(1, padding)
435+
}, 50)
436+
}
437+
373438

374439
useEffect(() => {
375440
const fg = graphRef.current
@@ -383,7 +448,7 @@ export function GraphPage() {
383448
setTimeout(() => {
384449
fg.zoomToFit(5, 200)
385450
}, 50)
386-
}, [physics.gravityOn, scope.nodeIds])
451+
}, [scope.nodeIds])
387452

388453
const [windowWidth, windowHeight] = useWindowSize()
389454

@@ -427,9 +492,6 @@ export function GraphPage() {
427492
return
428493
}
429494
if (command === 'replace') {
430-
const newParams = new URLSearchParams({ graph: 'local' });
431-
const newUrl = `${window.location.pathname}?${newParams.toString()}#${node.id}`;
432-
history.replaceState(null, '', newUrl);
433495
setScope({ nodeIds: [node.id], excludedNodeIds: [] })
434496
return
435497
}
@@ -538,21 +600,25 @@ export function GraphPage() {
538600
<Box position="relative" zIndex={4} width="100%">
539601
<Flex className="headerBar" h={10} flexDir="column">
540602
<Flex alignItems="center" h={10} justifyContent="flex-end">
603+
{/* <Flex flexDir="row" alignItems="center">
604+
* <Box color="blue.500" bgColor="alt.100" h="100%" p={3} mr={4}>
605+
* {mainItem.icon}
606+
* </Box>
607+
* <Heading size="sm">{mainItem.title}</Heading>
608+
* </Flex> */}
541609
<Flex height="100%" flexDirection="row">
542610
{scope.nodeIds.length > 0 && (
543611
<Tooltip label="Return to main graph">
544612
<IconButton
545613
m={1}
546614
icon={<BiNetworkChart />}
547615
aria-label="Exit local mode"
548-
onClick={() => {
549-
const hash = window.location.hash;
550-
history.replaceState(null, '', hash ? window.location.pathname : window.location.pathname + `#${hash}`);
616+
onClick={() =>
551617
setScope((currentScope: Scope) => ({
552618
...currentScope,
553619
nodeIds: [],
554620
}))
555-
}}
621+
}
556622
variant="subtle"
557623
/>
558624
</Tooltip>
@@ -562,7 +628,6 @@ export function GraphPage() {
562628
setPreviewNode={setPreviewNode}
563629
onClickResultItem={(id) => {
564630
setEmacsNodeId(id)
565-
setScope({ nodeIds: [], excludedNodeIds: [] })
566631
}}
567632
/>
568633
<Tooltip label={isOpen ? 'Close sidebar' : 'Open sidebar'}>
@@ -710,7 +775,7 @@ export const Graph = function (props: GraphProps) {
710775
switch (click) {
711776
case mouse.preview: {
712777
setPreviewNode(node)
713-
history.replaceState(null, '', window.location.pathname + window.location.search + `#${node.id}`)
778+
history.replaceState(null, '', window.location.pathname + `#${node.id}`)
714779
break
715780
}
716781
case mouse.local: {

0 commit comments

Comments
 (0)