From b75598d879e1b9153d89a96f7b0f66ad8d641f71 Mon Sep 17 00:00:00 2001 From: "Thomas F. K. Jorna" Date: Mon, 11 Oct 2021 20:50:51 +0200 Subject: feat(preview): tag display and scroll fix --- components/Sidebar/Backlinks.tsx | 2 +- components/Sidebar/Note.tsx | 2 +- components/Sidebar/TagBar.tsx | 79 ++++++++++++++ components/Sidebar/Toolbar.tsx | 2 +- components/Sidebar/index.tsx | 127 ++++++++++++++-------- components/TagMenu.tsx | 117 ++++++++++++++++++++ components/Tweaks/ColorMenu.tsx | 73 ++++++++----- components/Tweaks/index.tsx | 2 +- components/config.ts | 4 +- components/contextmenu.tsx | 227 +++++++++++++++++++++------------------ 10 files changed, 452 insertions(+), 183 deletions(-) create mode 100644 components/Sidebar/TagBar.tsx create mode 100644 components/TagMenu.tsx (limited to 'components') diff --git a/components/Sidebar/Backlinks.tsx b/components/Sidebar/Backlinks.tsx index 68ab551..d82fbba 100644 --- a/components/Sidebar/Backlinks.tsx +++ b/components/Sidebar/Backlinks.tsx @@ -43,7 +43,7 @@ export const Backlinks = (props: BacklinksProps) => { {`Backlinks (${backLinks.length})`} } diff --git a/components/Sidebar/Note.tsx b/components/Sidebar/Note.tsx index e425559..37e836d 100644 --- a/components/Sidebar/Note.tsx +++ b/components/Sidebar/Note.tsx @@ -35,7 +35,7 @@ export const Note = (props: NoteProps) => { { + const { filter, setFilter, tagColors, setTagColors, openContextMenu, previewNode } = props + + const node = previewNode as OrgRoamNode + if (!node.tags || node?.tags[0] === null) { + return null + } + return ( + + {node?.tags?.map((tag: string) => { + const bl: string[] = filter.tagsBlacklist ?? [] + const wl: string[] = filter.tagsWhitelist ?? [] + const blackList: boolean = bl.includes(tag) + const whiteList = wl.includes(tag) + return ( + { + e.preventDefault() + openContextMenu(tag, e) + }} + cursor="pointer" + onClick={() => { + if (blackList) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: filter.tagsBlacklist.filter((t) => t !== tag), + tagsWhitelist: [...filter.tagsWhitelist, tag], + })) + return + } + if (whiteList) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsWhitelist: filter.tagsWhitelist.filter((t) => t !== tag), + })) + return + } + + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: [...filter.tagsBlacklist, tag], + })) + }} + size="sm" + key={tag} + variant="outline" + colorScheme={tagColors[tag]?.replaceAll(/(.*?)\..*/g, '$1') || undefined} + > + {tag} + {blackList ? ( + + ) : whiteList ? ( + + ) : null} + + ) + })} + + ) +} diff --git a/components/Sidebar/Toolbar.tsx b/components/Sidebar/Toolbar.tsx index 8741da5..6cbecae 100644 --- a/components/Sidebar/Toolbar.tsx +++ b/components/Sidebar/Toolbar.tsx @@ -38,7 +38,7 @@ export const Toolbar = (props: ToolbarProps) => { nextPreviewNode, } = props return ( - + diff --git a/components/Sidebar/index.tsx b/components/Sidebar/index.tsx index cbc0cc9..957669c 100644 --- a/components/Sidebar/index.tsx +++ b/components/Sidebar/index.tsx @@ -1,12 +1,33 @@ import React, { useContext, useEffect, useRef, useState } from 'react' import { Toolbar } from './Toolbar' +import { TagBar } from './TagBar' import { Note } from './Note' -import { Button, Slide, VStack, Flex, Heading, Box, IconButton, Tooltip } from '@chakra-ui/react' +import { + Button, + Slide, + VStack, + Flex, + Heading, + Box, + IconButton, + Tooltip, + HStack, + TagLabel, + Tag, + TagRightIcon, +} from '@chakra-ui/react' import { Collapse } from './Collapse' import { Scrollbars } from 'react-custom-scrollbars-2' -import { ChevronLeftIcon, ChevronRightIcon, CloseIcon, HamburgerIcon } from '@chakra-ui/icons' +import { + ChevronLeftIcon, + ChevronRightIcon, + CloseIcon, + HamburgerIcon, + ViewIcon, + ViewOffIcon, +} from '@chakra-ui/icons' import { BiDotsVerticalRounded, BiFile, BiNetworkChart } from 'react-icons/bi' import { BsReverseLayoutSidebarInsetReverse } from 'react-icons/bs' @@ -16,6 +37,7 @@ import { ThemeContext } from '../../util/themecontext' import { LinksByNodeId, NodeByCite, NodeById, Scope } from '../../pages/index' import { Resizable } from 're-resizable' import { usePersistantState } from '../../util/persistant-state' +import { initialFilter, TagColors } from '../config' export interface SidebarProps { isOpen: boolean @@ -36,6 +58,10 @@ export interface SidebarProps { scope: Scope setScope: any windowWidth: number + filter: typeof initialFilter + setFilter: any + tagColors: TagColors + setTagColors: any } const Sidebar = (props: SidebarProps) => { @@ -58,6 +84,10 @@ const Sidebar = (props: SidebarProps) => { scope, setScope, windowWidth, + filter, + setFilter, + tagColors, + setTagColors, } = props const { highlightColor } = useContext(ThemeContext) @@ -90,7 +120,7 @@ const Sidebar = (props: SidebarProps) => { style={{ height: '100vh' }} > { setSidebarWidth((curr: number) => curr + d.width) }} @@ -107,22 +137,24 @@ const Sidebar = (props: SidebarProps) => { minWidth="220px" maxWidth={windowWidth - 200} > - + - { - e.preventDefault() - openContextMenu(previewNode, e) - }} - /> + + { + e.preventDefault() + openContextMenu(previewNode, e) + }} + /> + { nextPreviewNode, }} /> - ( - - )} - > - - - - - + {/* ( + * + * )} + * > */} + + + + + {/**/} + ) diff --git a/components/TagMenu.tsx b/components/TagMenu.tsx new file mode 100644 index 0000000..432e9a2 --- /dev/null +++ b/components/TagMenu.tsx @@ -0,0 +1,117 @@ +import { MinusIcon, AddIcon, ViewOffIcon, ViewIcon } from '@chakra-ui/icons' +import { + Text, + Box, + Button, + Flex, + Menu, + MenuButton, + MenuItem, + MenuList, + Portal, + useDisclosure, +} from '@chakra-ui/react' +import React from 'react' +import { colorList, initialFilter, TagColors } from './config' +import { Collapse } from './Sidebar/Collapse' +import { ColorMenu } from './Tweaks/ColorMenu' + +export interface TagMenuProps { + setTagColors: any + tagColors: TagColors + setFilter: any + filter: typeof initialFilter + target: string | null +} + +export const TagMenu = (props: TagMenuProps) => { + const { setTagColors, setFilter, filter, tagColors, target } = props + const bl: string[] = filter.tagsBlacklist + const wl: string[] = filter.tagsWhitelist + const blacklist = bl.indexOf(target as string) > -1 + const whitelist = wl.indexOf(target as string) > -1 + const colors = useDisclosure() + return ( + <> + + } + closeOnSelect={false} + onClick={colors.onToggle} + > + Change color + + + + {colorList.map((color: string) => ( + + + setTagColors({ + ...tagColors, + [target as string]: color, + }) + } + bgColor={color} + m={1} + borderRadius="sm" + height={3} + width={3} + > + + ))} + + + {!whitelist && ( + { + if (!blacklist) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: [...filter.tagsBlacklist, target], + })) + return + } + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsBlacklist: filter.tagsBlacklist.filter((t) => t !== target), + })) + }} + icon={blacklist ? : } + > + {blacklist ? 'Remove from blacklist' : 'Add to blacklist'} + + )} + {!blacklist && ( + { + if (!whitelist) { + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsWhitelist: [...filter.tagsWhitelist, target], + })) + return + } + setFilter((filter: typeof initialFilter) => ({ + ...filter, + tagsWhitelist: filter.tagsWhitelist.filter((t) => t !== target), + })) + }} + icon={whitelist ? : } + > + {whitelist ? 'Remove from whitelist' : 'Add to whitelist'} + + )} + + ) +} diff --git a/components/Tweaks/ColorMenu.tsx b/components/Tweaks/ColorMenu.tsx index 3d90e36..b87f76b 100644 --- a/components/Tweaks/ColorMenu.tsx +++ b/components/Tweaks/ColorMenu.tsx @@ -9,6 +9,9 @@ import { MenuItem, MenuList, Portal, + PopoverTrigger, + PopoverContent, + Popover, } from '@chakra-ui/react' import React, { useCallback } from 'react' import { initialVisuals } from '../config' @@ -19,10 +22,11 @@ export interface ColorMenuProps { value: string visValue: string setVisuals?: any + noEmpty?: boolean } export const ColorMenu = (props: ColorMenuProps) => { - const { label, colorList, value, visValue, setVisuals } = props + const { label, colorList, value, visValue, setVisuals, noEmpty } = props const clickCallback = useCallback( (color) => @@ -37,35 +41,48 @@ export const ColorMenu = (props: ColorMenuProps) => { return ( {label} - - }> - {} - + + + + - {' '} - - clickCallback('')} - justifyContent="space-between" - alignItems="center" - display="flex" - > - - - {colorList.map((color: string) => ( - clickCallback(color)} - justifyContent="space-between" - alignItems="center" - display="flex" - > - - - ))} - + + + {!noEmpty && ( + clickCallback('')} + justifyContent="space-between" + alignItems="center" + display="flex" + m={1} + > + + + )} + {colorList.map((color: string) => ( + clickCallback(color)} + justifyContent="space-between" + alignItems="center" + display="flex" + > + + + ))} + + - + ) } diff --git a/components/Tweaks/index.tsx b/components/Tweaks/index.tsx index 33f11ee..62252b0 100644 --- a/components/Tweaks/index.tsx +++ b/components/Tweaks/index.tsx @@ -96,7 +96,7 @@ export const Tweaks = (props: TweakProps) => { marginLeft={2} borderRadius="lg" paddingBottom={5} - zIndex="overlay" + zIndex={4} boxShadow="xl" maxH={'95vh'} fontSize="sm" diff --git a/components/config.ts b/components/config.ts index 0ae654e..ec1c691 100644 --- a/components/config.ts +++ b/components/config.ts @@ -60,7 +60,7 @@ export const initialVisuals = { nodeResolution: 12, labels: 2, labelScale: 1, - labelFontSize: 13, + labelFontSize: 10, labelLength: 40, labelWordWrap: 25, labelLineSpace: 1, @@ -88,7 +88,7 @@ export const initialVisuals = { linkHighlight: 'purple.500', backgroundColor: 'white', emacsNodeColor: 'gray.800', - labelTextColor: 'gray.900', + labelTextColor: 'black', labelBackgroundColor: '', labelBackgroundOpacity: 0.7, citeDashes: true, diff --git a/components/contextmenu.tsx b/components/contextmenu.tsx index 118b8bb..77deb48 100644 --- a/components/contextmenu.tsx +++ b/components/contextmenu.tsx @@ -45,10 +45,12 @@ import { import { OrgRoamGraphReponse, OrgRoamLink, OrgRoamNode } from '../api' import { deleteNodeInEmacs, openNodeInEmacs, createNodeInEmacs } from '../util/webSocketFunctions' import { BiNetworkChart } from 'react-icons/bi' +import { TagMenu } from './TagMenu' +import { initialFilter, TagColors } from './config' export default interface ContextMenuProps { background: Boolean - target: OrgRoamNode | null + target: OrgRoamNode | string | null nodeType?: string coordinates: { [direction: string]: number | undefined } handleLocal: (node: OrgRoamNode, add: string) => void @@ -56,6 +58,10 @@ export default interface ContextMenuProps { scope: { nodeIds: string[] } webSocket: any setPreviewNode: any + setTagColors: any + tagColors: TagColors + setFilter: any + filter: typeof initialFilter } export const ContextMenu = (props: ContextMenuProps) => { @@ -69,6 +75,10 @@ export const ContextMenu = (props: ContextMenuProps) => { scope, webSocket, setPreviewNode, + setTagColors, + tagColors, + setFilter, + filter, } = props const { isOpen, onOpen, onClose } = useDisclosure() const copyRef = useRef() @@ -79,54 +89,59 @@ export const ContextMenu = (props: ContextMenuProps) => { zIndex="overlay" bgColor="white" color="black" - borderColor="gray.500" - maxWidth="xs" + //borderColor="gray.500" position="absolute" left={coordinates.left} top={coordinates.top} right={coordinates.right} bottom={coordinates.bottom} fontSize="xs" + boxShadow="xl" > - {target && ( + {typeof target !== 'string' ? ( <> - - {target.title} - - - - )} - {scope.nodeIds.length !== 0 && ( - <> - handleLocal(target!, 'add')} icon={}> - Expand local graph at node - - handleLocal(target!, 'replace')} icon={}> - Open local graph for this node - - - )} - {!target?.properties?.FILELESS ? ( - } - onClick={() => openNodeInEmacs(target as OrgRoamNode, webSocket)} - > - Open in Emacs - - ) : ( - } onClick={() => createNodeInEmacs(target, webSocket)}> - Create node - - )} - {target?.properties?.ROAM_REFS && ( - }>Open in Zotero - )} - {scope.nodeIds.length === 0 && ( - } onClick={() => handleLocal(target!, 'replace')}> - Open local graph - - )} - {/* Doesn't work at the moment + {target && ( + <> + + {target.title} + + + + )} + {scope.nodeIds.length !== 0 && ( + <> + handleLocal(target!, 'add')} icon={}> + Expand local graph at node + + handleLocal(target!, 'replace')} + icon={} + > + Open local graph for this node + + + )} + {!target?.properties?.FILELESS ? ( + } + onClick={() => openNodeInEmacs(target as OrgRoamNode, webSocket)} + > + Open in Emacs + + ) : ( + } onClick={() => createNodeInEmacs(target, webSocket)}> + Create node + + )} + {target?.properties?.ROAM_REFS && ( + }>Open in Zotero + )} + {scope.nodeIds.length === 0 && ( + } onClick={() => handleLocal(target!, 'replace')}> + Open local graph + + )} + {/* Doesn't work at the moment { */} - } - onClick={() => { - setPreviewNode(target) - }} - > - Preview - - {target?.level === 0 && ( - } - color="red.500" - onClick={onOpen} - > - Permenantly delete note - + } + onClick={() => { + setPreviewNode(target) + }} + > + Preview + + {target?.level === 0 && ( + } + color="red.500" + onClick={onOpen} + > + Permenantly delete note + + )} + + ) : ( + )} - - - - Delete node? - - - - This will permanently delete your note: - {target?.title} - {target?.level !== 0 && ( - - 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. - - )} - Are you sure you want to do continue? - - - - - - - - + {typeof target !== 'string' && ( + + + + Delete node? + + + + This will permanently delete your note: + {target?.title} + {target?.level !== 0 && ( + + 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. + + )} + Are you sure you want to do continue? + + + + + + + + + )} ) } -- cgit v1.2.3