summaryrefslogtreecommitdiff
path: root/components/contextmenu.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'components/contextmenu.tsx')
-rw-r--r--components/contextmenu.tsx237
1 files changed, 237 insertions, 0 deletions
diff --git a/components/contextmenu.tsx b/components/contextmenu.tsx
new file mode 100644
index 0000000..755bd9d
--- /dev/null
+++ b/components/contextmenu.tsx
@@ -0,0 +1,237 @@
+import React, { useRef } from 'react'
+import {
+ Box,
+ Menu,
+ MenuItem,
+ MenuList,
+ MenuGroup,
+ MenuItemOption,
+ MenuOptionGroup,
+ Heading,
+ MenuDivider,
+ Modal,
+ ModalOverlay,
+ ModalContent,
+ ModalHeader,
+ ModalFooter,
+ ModalBody,
+ ModalCloseButton,
+ useDisclosure,
+ Button,
+ PopoverTrigger,
+ PopoverContent,
+ Popover,
+ Flex,
+ PopoverBody,
+ PopoverCloseButton,
+ PopoverArrow,
+ PopoverHeader,
+ PopoverFooter,
+ Portal,
+ Text,
+ VStack,
+} from '@chakra-ui/react'
+import {
+ DeleteIcon,
+ EditIcon,
+ CopyIcon,
+ AddIcon,
+ ViewIcon,
+ ExternalLinkIcon,
+ ChevronRightIcon,
+ PlusSquareIcon,
+} from '@chakra-ui/icons'
+
+import { OrgRoamGraphReponse, OrgRoamLink, OrgRoamNode } from '../api'
+
+export default interface ContextMenuProps {
+ background: Boolean
+ node?: OrgRoamNode
+ nodeType?: string
+ coordinates: number[]
+ handleLocal: (node: OrgRoamNode, add: string) => void
+ openNodeInEmacs: (node: OrgRoamNode) => void
+ menuClose: () => void
+ scope: { nodeIds: string[] }
+ deleteNodeInEmacs: (node: OrgRoamNode) => void
+ createNodeInEmacs: (node: OrgRoamNode) => void
+}
+
+export const ContextMenu = (props: ContextMenuProps) => {
+ const {
+ background,
+ node,
+ nodeType,
+ coordinates,
+ handleLocal,
+ menuClose,
+ scope,
+ openNodeInEmacs,
+ deleteNodeInEmacs,
+ createNodeInEmacs,
+ } = props
+ const { isOpen, onOpen, onClose } = useDisclosure()
+ const copyRef = useRef<any>()
+ return (
+ <>
+ <Box
+ position="absolute"
+ zIndex="overlay"
+ left={coordinates[0] + 10}
+ top={coordinates[1] - 10}
+ padding={5}
+ >
+ <Menu closeOnBlur={false} defaultIsOpen onClose={() => menuClose()}>
+ <MenuList zIndex="overlay" bgColor="alt.100" borderColor="gray.500" maxWidth="xs">
+ {node && (
+ <>
+ <Heading size="sm" isTruncated px={3} py={1}>
+ {node.title}
+ </Heading>
+ <MenuDivider borderColor="gray.500" />
+ </>
+ )}
+ {scope.nodeIds.length !== 0 && (
+ <>
+ <MenuItem onClick={() => handleLocal(node!, 'add')} icon={<PlusSquareIcon />}>
+ Expand local graph at node
+ </MenuItem>
+ <MenuItem onClick={() => handleLocal(node!, 'replace')} icon={<ViewIcon />}>
+ Open local graph for this node
+ </MenuItem>
+ </>
+ )}
+ {!node?.properties.FILELESS ? (
+ <MenuItem icon={<EditIcon />} onClick={() => openNodeInEmacs(node as OrgRoamNode)}>
+ Open in Emacs
+ </MenuItem>
+ ) : (
+ <MenuItem icon={<AddIcon />} onClick={() => createNodeInEmacs(node)}>
+ Create node
+ </MenuItem>
+ )}
+ {node?.properties.ROAM_REFS && (
+ <MenuItem icon={<ExternalLinkIcon />}>Open in Zotero</MenuItem>
+ )}
+ {scope.nodeIds.length === 0 && (
+ <MenuItem icon={<ViewIcon />} onClick={() => handleLocal(node!, 'replace')}>
+ Open local graph
+ </MenuItem>
+ )}
+ {/* Doesn't work at the moment
+ <MenuItem closeOnSelect={false} closeOnBlur={false}>
+ <Box _hover={{ bg: 'gray.200' }} width="100%">
+ <Popover
+ initialFocusRef={copyRef}
+ trigger="hover"
+ placement="right-start"
+ gutter={0}
+ >
+ <PopoverTrigger>
+ <MenuItem closeOnSelect={false} icon={<CopyIcon />}>
+ <Flex justifyContent="space-between" alignItems="center">
+ Copy...
+ <ChevronRightIcon />
+ </Flex>
+ </MenuItem>
+ </PopoverTrigger>
+ <PopoverContent width={100}>
+ <Menu defaultIsOpen closeOnBlur={false} closeOnSelect={false}>
+ <MenuList bg="alt.100" zIndex="popover">
+ <MenuItem ref={copyRef}>ID</MenuItem>
+ <MenuItem>Title</MenuItem>
+ <MenuItem>File path</MenuItem>
+ </MenuList>
+ </Menu>
+ </PopoverContent>
+ </Popover>
+ </Box>
+ </MenuItem> */}
+ {node?.level === 0 && (
+ <MenuItem
+ closeOnSelect={false}
+ icon={<DeleteIcon color="red.500" />}
+ color="red.500"
+ onClick={onOpen}
+ >
+ Permenantly delete note
+ </MenuItem>
+ )}
+ </MenuList>
+ </Menu>
+ </Box>
+ <Modal isCentered isOpen={isOpen} onClose={onClose}>
+ <ModalOverlay />
+ <ModalContent zIndex="popover">
+ <ModalHeader>Delete node?</ModalHeader>
+ <ModalCloseButton />
+ <ModalBody>
+ <VStack spacing={4} display="flex" alignItems="flex-start">
+ <Text>This will permanently delete your note:</Text>
+ <Text fontWeight="bold">{node?.title}</Text>
+ {node?.level !== 0 && (
+ <Text>
+ This will only delete the from this heading until but not including the next node.
+ Your parent file and all other nodes will not be deleted.
+ </Text>
+ )}
+ <Text>Are you sure you want to do continue?</Text>
+ </VStack>
+ </ModalBody>
+ <ModalFooter>
+ <Button
+ mr={3}
+ onClick={() => {
+ console.log('closing')
+ onClose()
+ menuClose()
+ }}
+ >
+ Cancel
+ </Button>
+ <Button
+ variant="link"
+ colorScheme="red"
+ ml={3}
+ onClick={() => {
+ console.log('aaaaa')
+ deleteNodeInEmacs(node!)
+ onClose()
+ menuClose()
+ }}
+ >
+ Delete node
+ </Button>
+ </ModalFooter>
+ </ModalContent>
+ </Modal>
+ </>
+ )
+}
+
+/* <Box>
+ * <Popover>
+ * <PopoverTrigger>
+ * Permenantly delete node
+ * </MenuItem>
+ * </PopoverTrigger>
+ * <PopoverContent borderColor="red.500" _focus={{}}>
+ * <PopoverHeader fontWeight="semibold">Delete Node?</PopoverHeader>
+ * <PopoverArrow />
+ * <PopoverCloseButton onClick={onClose} />
+ * <PopoverBody>
+ * This will permanently delete your node! Are you sure you want to do this?
+ * </PopoverBody>
+ * <PopoverFooter>
+ * <Flex justifyContent="space-between" py={1}>
+ * <Button colorScheme="gray" bg="gray.800" color="alt.100" width={30} onClick={onClose}>
+ * Nah
+ * </Button>
+ * <Button colorScheme="red" variant="link" onClick={onClose}>
+ * Delete node
+ * </Button>
+ * </Flex>
+ * </PopoverFooter>
+ * </PopoverContent>
+ * </Popover>
+ * </Box> */