diff options
Diffstat (limited to 'pages/index.tsx')
-rw-r--r-- | pages/index.tsx | 548 |
1 files changed, 3 insertions, 545 deletions
diff --git a/pages/index.tsx b/pages/index.tsx index 22adb3f..d39db81 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -10,48 +10,18 @@ import { OrgRoamGraphReponse, OrgRoamLink, OrgRoamNode } from '../api' import { GraphData, NodeObject } from 'force-graph' import { useWindowSize } from '@react-hook/window-size' -import { Scrollbars } from 'react-custom-scrollbars-2' -import { Easing } from '@tweenjs/tween.js' import { useAnimation } from '@lilib/hooks' import { - Accordion, - AccordionButton, - AccordionItem, - AccordionIcon, - AccordionPanel, - Text, - Heading, - VStack, - StackDivider, Button, - CloseButton, - Slider, - SliderThumb, - SliderTrack, - SliderFilledTrack, - Switch, - FormControl, - FormLabel, Box, - Container, - Icon, IconButton, - Tooltip, - Menu, - MenuList, - MenuButton, - MenuItem, - MenuGroup, - MenuDivider, - MenuOptionGroup, - MenuItemOption, - Flex, useTheme, - Select, } from '@chakra-ui/react' -import { InfoOutlineIcon, RepeatClockIcon, ChevronDownIcon, SettingsIcon } from '@chakra-ui/icons' +import { SettingsIcon } from '@chakra-ui/icons' +import { initialPhysics, initialFilter } from '../components/config' +import { Tweaks } from '../components/tweaks' // react-force-graph fails on import when server-rendered // https://github.com/vasturiano/react-force-graph/issues/155 @@ -72,68 +42,6 @@ export type Scope = { nodeIds: string[] } -const getAlgos = (option?: boolean) => { - const options: string[] = [] - const algorithms: { [name: string]: (percent: number) => number } = {} - for (let type in Easing) { - for (let mode in (Easing as any)[type]) { - let name = type + mode - if (name === 'LinearNone') { - name = 'Linear' - } - option ? options.push(name) : (algorithms[name] = (Easing as any)[type][mode]) - } - } - return option ? options : algorithms -} -const initialPhysics = { - enabled: true, - charge: -350, - collision: true, - collisionStrength: 0, - linkStrength: 0.1, - linkIts: 1, - particles: false, - particlesNumber: 0, - particlesWidth: 4, - linkOpacity: 0.4, - linkWidth: 1, - nodeRel: 4, - labels: true, - labelScale: 1.5, - alphaDecay: 0.02, - alphaTarget: 0, - alphaMin: 0, - velocityDecay: 0.25, - gravity: 0.5, - gravityOn: true, - colorful: true, - galaxy: true, - ticks: 1, - hover: 'highlight', - click: 'select', - doubleClick: 'local', - iterations: 0, - highlight: true, - highlightNodeSize: 2, - highlightLinkSize: 2, - highlightAnim: false, - animationSpeed: 250, - algorithms: getAlgos(false), - algorithmOptions: getAlgos(true), - algorithmName: 'CubicOut', - orphans: false, - follow: 'Local', -} - -const initialFilter = { - orphans: false, - parents: true, - tags: [], - nodes: [], - links: [], - date: [], -} export default function Home() { // only render on the client const [showPage, setShowPage] = useState(false) @@ -255,456 +163,6 @@ export function GraphPage() { ) } -export interface InfoTooltipProps { - infoText?: string | boolean -} -export const InfoTooltip = (props: InfoTooltipProps) => { - const { infoText } = props - return ( - <Box paddingLeft="1"> - <Tooltip label={infoText} placement="top" color="gray.100" bg="gray.800" hasArrow> - <InfoOutlineIcon /> - </Tooltip> - </Box> - ) -} -export interface SliderWithInfoProps { - min?: number - max?: number - step?: number - value: number - onChange: (arg0: number) => void - label: string - infoText?: string -} -export const SliderWithInfo = ({ - min = 0, - max = 10, - step = 0.1, - value = 1, - ...rest -}: SliderWithInfoProps) => { - const { onChange, label, infoText } = rest - return ( - <Box> - <Box display="flex" alignItems="flex-end"> - <Text>{label}</Text> - {infoText && <InfoTooltip infoText={infoText} />} - </Box> - <Slider - value={value} - onChange={onChange} - min={min} - max={max} - step={step} - colorScheme="purple" - > - <SliderTrack> - <SliderFilledTrack /> - </SliderTrack> - <Tooltip label={value.toFixed(1)}> - <SliderThumb /> - </Tooltip> - </Slider> - </Box> - ) -} - -export interface EnableSectionProps { - label: string - value: boolean | number - onChange: () => void - infoText?: string - children: React.ReactNode -} - -export const EnableSection = (props: EnableSectionProps) => { - const { value, onChange, label, infoText, children } = props - return ( - <Box> - <Box display="flex" justifyContent="space-between"> - <Box display="flex" alignItems="center"> - <Text>{label}</Text> - {infoText && <InfoTooltip infoText={infoText} />} - </Box> - <Switch isChecked={!!value} onChange={onChange} colorScheme="purple" /> - </Box> - {value && children} - </Box> - ) -} - -export interface DropDownMenuProps { - textArray: string[] - onClickArray: any - displayValue: string -} - -export const DropDownMenu = (props: DropDownMenuProps) => { - const { textArray, onClickArray, displayValue } = props - return ( - <Menu> - <MenuButton as={Button} rightIcon={<ChevronDownIcon />}> - {displayValue} - </MenuButton> - <MenuList> - {textArray.map((option, i) => { - ;<MenuItem onClick={onClickArray[i]}> {option} </MenuItem> - })} - </MenuList> - </Menu> - ) -} -/* style={{ - * position: "absolute", - * zIndex: 2000, - * width: 400, - * maxHeight: "70%", - * background: "alt.100", - * marginTop: "2%", - * marginLeft: "2%" - * }} */ -export interface TweakProps { - physics: typeof initialPhysics - setPhysics: any - threeDim: boolean - setThreedim: (boolean) => void - filter: typeof initialFilter - setFilter: any - onClose: () => void -} -export const Tweaks = (props: TweakProps) => { - const { physics, setPhysics, threeDim, filter, setFilter, onClose } = props - return ( - <Box - zIndex="overlay" - position="absolute" - bg="alt.100" - w="xs" - marginTop="2%" - marginLeft="2%" - borderRadius="md" - maxH={650} - paddingBottom={5} - //overflowY="scroll" - > - <Box display="flex" justifyContent="flex-end"> - <Tooltip label="Reset settings to defaults"> - <IconButton - aria-label="Reset Defaults" - icon={<RepeatClockIcon />} - onClick={() => setPhysics(initialPhysics)} - colorScheme="purple" - /> - </Tooltip> - <CloseButton onClick={onClose} /> - </Box> - <Scrollbars - autoHeight - autoHeightMax={600} - autoHide - renderThumbVertical={({ style, ...props }) => ( - <Box - {...props} - style={{ - ...style, - borderRadius: 10, - }} - bg="purple.500" - /> - )} - > - <Accordion allowMultiple allowToggle> - <AccordionItem> - <AccordionButton> - <AccordionIcon /> - <Text>Filter</Text> - </AccordionButton> - <AccordionPanel> - <Flex justifyContent="space-between"> - <Text>Kill orphans</Text> - <Switch - colorScheme="purple" - onChange={() => { - setFilter({ ...filter, orphans: !filter.orphans }) - }} - isChecked={filter.orphans} - ></Switch> - </Flex> - <Flex justifyContent="space-between"> - <Text>Link nodes with parent file</Text> - <Switch - colorScheme="purple" - onChange={() => { - setFilter({ ...filter, parents: !filter.parents }) - }} - isChecked={filter.parents} - ></Switch> - </Flex> - </AccordionPanel> - </AccordionItem> - <AccordionItem> - <AccordionButton display="flex" justifyContent="space-between"> - <Box display="flex"> - <AccordionIcon /> - <Text>Physics</Text> - </Box> - <Switch - id="physicsOn" - onChange={() => setPhysics({ ...physics, enabled: !physics.enabled })} - isChecked={physics.enabled} - colorScheme="purple" - /> - </AccordionButton> - <AccordionPanel> - <VStack - spacing={2} - justifyContent="flex-start" - divider={<StackDivider borderColor="gray.200" />} - align="stretch" - > - <EnableSection - label="Gravity" - value={physics.gravityOn} - onChange={() => setPhysics({ ...physics, gravityOn: !physics.gravityOn })} - > - <SliderWithInfo - label="Strength" - value={physics.gravity * 10} - onChange={(v) => setPhysics({ ...physics, gravity: v / 10 })} - /> - </EnableSection> - <SliderWithInfo - value={-physics.charge / 100} - onChange={(value) => setPhysics({ ...physics, charge: -100 * value })} - label="Repulsive Force" - /> - <EnableSection - label="Collision" - infoText="Perfomance sap, disable if slow" - value={physics.collision} - onChange={() => setPhysics({ ...physics, collision: !physics.collision })} - > - <SliderWithInfo - value={physics.collisionStrength * 10} - onChange={(value) => setPhysics({ ...physics, collisionStrength: value / 10 })} - label="Strength" - /> - </EnableSection> - <SliderWithInfo - value={physics.linkStrength * 5} - onChange={(value) => setPhysics({ ...physics, linkStrength: value / 5 })} - label="Link Force" - /> - <SliderWithInfo - label="Link Iterations" - value={physics.linkIts} - onChange={(value) => setPhysics({ ...physics, linkIts: value })} - min={0} - max={6} - step={1} - infoText="How many links down the line the physics of a single node affects (Slow)" - /> - <SliderWithInfo - label="Viscosity" - value={physics.velocityDecay * 10} - onChange={(value) => setPhysics({ ...physics, velocityDecay: value / 10 })} - /> - </VStack> - <Box> - <Accordion allowToggle> - <AccordionItem> - <AccordionButton> - <Text>Advanced</Text> - <AccordionIcon /> - </AccordionButton> - <AccordionPanel> - <VStack - spacing={2} - justifyContent="flex-start" - divider={<StackDivider borderColor="gray.200" />} - align="stretch" - > - <SliderWithInfo - label="Iterations per tick" - min={1} - max={10} - step={1} - value={physics.iterations} - onChange={(v) => setPhysics({ ...physics, iterations: v })} - infoText="Number of times the physics simulation iterates per simulation step" - /> - <SliderWithInfo - label="Stabilization rate" - value={physics.alphaDecay * 50} - onChange={(value) => setPhysics({ ...physics, alphaDecay: value / 50 })} - /> - </VStack> - </AccordionPanel> - </AccordionItem> - </Accordion> - </Box> - {/* </VStack> */} - </AccordionPanel> - </AccordionItem> - <AccordionItem> - <AccordionButton> - <AccordionIcon /> - Visual - </AccordionButton> - <AccordionPanel> - <VStack - spacing={2} - justifyContent="flex-start" - divider={<StackDivider borderColor="gray.200" />} - align="stretch" - > - <EnableSection - label="Colors" - onChange={() => setPhysics({ ...physics, colorful: !physics.colorful })} - value={physics.colorful} - > - <Text>Child</Text> - </EnableSection> - <SliderWithInfo - label="Node size" - value={physics.nodeRel} - onChange={(value) => setPhysics({ ...physics, nodeRel: value })} - /> - <SliderWithInfo - label="Link width" - value={physics.linkWidth} - onChange={(value) => setPhysics({ ...physics, linkWidth: value })} - /> - <EnableSection - label="Labels" - value={physics.labels} - onChange={() => setPhysics({ ...physics, labels: !physics.labels })} - > - <SliderWithInfo - label="Label Appearance Scale" - value={physics.labelScale * 5} - onChange={(value) => setPhysics({ ...physics, labelScale: value / 5 })} - /> - </EnableSection> - <EnableSection - label="Directional Particles" - value={physics.particles} - onChange={() => setPhysics({ ...physics, particles: !physics.particles })} - > - <SliderWithInfo - label="Particle Number" - value={physics.particlesNumber} - max={5} - step={1} - onChange={(value) => setPhysics({ ...physics, particlesNumber: value })} - /> - <SliderWithInfo - label="Particle Size" - value={physics.particlesWidth} - onChange={(value) => setPhysics({ ...physics, particlesWidth: value })} - /> - </EnableSection> - <EnableSection - label="Highlight Animation" - onChange={() => { - setPhysics({ ...physics, highlightAnim: !physics.highlightAnim }) - }} - value={physics.highlightAnim} - > - <SliderWithInfo - label="Animation speed" - onChange={(v) => setPhysics({ ...physics, animationSpeed: v })} - value={physics.animationSpeed} - infoText="Slower speed has a chance of being buggy" - min={50} - max={1000} - step={10} - /> - <Select - placeholder={physics.algorithmName} - onChange={(v) => { - setPhysics({ ...physics, algorithmName: v.target.value }) - }} - > - {physics.algorithmOptions.map((opt, i) => ( - <option key={i} value={physics.algorithmOptions[i]}> - {physics.algorithmOptions[i]} - </option> - ))} - </Select> - {/* <DropDownMenu - displayValue={physics.algorithmName} - textArray={physics.algorithmOptions} - onClickArray={physics.algorithmOptions.map((option) => - setPhysics({ ...physics, algorithmName: { option } }), - )} - /> */} - </EnableSection> - <EnableSection - label="Highlight" - onChange={() => setPhysics({ ...physics, highlight: !physics.highlight })} - value={physics.highlight} - > - <SliderWithInfo - label="Highlight Link Thickness Multiplier" - value={physics.highlightLinkSize} - onChange={(value) => setPhysics({ ...physics, highlightLinkSize: value })} - /> - <SliderWithInfo - label="Highlight Node Size Multiplier" - value={physics.highlightNodeSize} - onChange={(value) => setPhysics({ ...physics, highlightNodeSize: value })} - /> - <Flex justifyContent="space-between"> - <Text> Highlight node color </Text> - </Flex> - <Flex justifyContent="space-between"> - <Text> Highlight link color </Text> - </Flex> - </EnableSection> - </VStack> - </AccordionPanel> - </AccordionItem> - <AccordionItem> - <AccordionButton> - <AccordionIcon /> - Behavior - </AccordionButton> - <AccordionPanel> - <VStack - spacing={2} - justifyContent="flex-start" - divider={<StackDivider borderColor="gray.200" />} - align="stretch" - > - <Box display="flex" justifyContent="space-between" alignItems="center"> - <Text>Hover Higlight</Text> - <Menu> - <MenuButton as={Button} rightIcon={<ChevronDownIcon />}> - {physics.hover} - </MenuButton> - <MenuList> - <MenuItem>Off</MenuItem> - <MenuItem>On</MenuItem> - </MenuList> - </Menu> - </Box> - <Box display="flex" justifyContent="space-between"> - <Text>Click</Text> - </Box> - <Box display="flex" justifyContent="space-between"> - <Text>Double-click</Text> - </Box> - </VStack> - </AccordionPanel> - </AccordionItem> - </Accordion> - </Scrollbars> - </Box> - ) -} - export interface GraphProps { nodeById: NodeById linksByNodeId: LinksByNodeId |