Skip to content

Commit

Permalink
Merge pull request #53 from alpaca-tc/brighten-graph-node
Browse files Browse the repository at this point in the history
Brighten node when cursor on source
  • Loading branch information
alpaca-tc authored May 31, 2024
2 parents d5978f6 + e6e44ca commit 0fe01e7
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 55 deletions.
12 changes: 12 additions & 0 deletions frontend/context/HoverMetadataContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { DotMetadata } from '@/models/combinedDefinition'
import React from 'react'

export type HoverDotMetadataContextProps = {
hoverDotMetadata: DotMetadata | null
setHoverDotMetadata: React.Dispatch<React.SetStateAction<DotMetadata | null>>
}

export const HoverDotMetadataContext = React.createContext<HoverDotMetadataContextProps>({
hoverDotMetadata: null,
setHoverDotMetadata: () => {},
})
83 changes: 44 additions & 39 deletions frontend/pages/DefinitionList/Show.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { MetadataDialog } from './components/MetadataDialog'
import type { DialogProps } from './components/dialog'
import { RecentModulesContext } from '@/context/RecentModulesContext'
import { Module } from '@/models/module'
import { HoverDotMetadataContext } from '@/context/HoverMetadataContext'
import { DotMetadata } from '@/models/combinedDefinition'

export const Show: React.FC = () => {
const [selectedDefinitionIds, setSelectedDefinitionIds] = useBitIdHash()
Expand All @@ -26,6 +28,7 @@ export const Show: React.FC = () => {
concentrate: false,
onlyModule: false,
})
const [hoverDotMetadata, setHoverDotMetadata] = useState<DotMetadata | null>(null)
const {
data: combinedDefinition,
isLoading,
Expand All @@ -40,45 +43,47 @@ export const Show: React.FC = () => {
return (
<Wrapper>
<RecentModulesContext.Provider value={{ recentModules, setRecentModules }}>
<StyledSidebar contentsMinWidth="0px" gap={0}>
<StyledAside>
<DefinitionList selectedDefinitionIds={selectedDefinitionIds} setSelectedDefinitionIds={setSelectedDefinitionIds} />
</StyledAside>
<StyledSection>
<MetadataDialog
isOpen={visibleDialog?.type === 'metadataDialog'}
dotMetadata={visibleDialog?.type === 'metadataDialog' ? visibleDialog.metadata : null}
top={visibleDialog?.type === 'metadataDialog' ? visibleDialog.top : 0}
left={visibleDialog?.type === 'metadataDialog' ? visibleDialog.left : 0}
onClose={onCloseDialog}
setVisibleDialog={setVisibleDialog}
mutateCombinedDefinition={mutateCombinedDefinition}
/>
{isLoading ? (
<CenterStack>
<Loading text="Loading..." alt="Loading" />
</CenterStack>
) : !combinedDefinition ? (
<CenterStack>
<p>No data</p>
</CenterStack>
) : (
<StyledStack>
<DefinitionGraph
combinedDefinition={combinedDefinition}
graphOptions={graphOptions}
setGraphOptions={setGraphOptions}
visibleDialog={visibleDialog}
setVisibleDialog={setVisibleDialog}
/>
<StyledDefinitionSources
combinedDefinition={combinedDefinition}
mutateCombinedDefinition={mutateCombinedDefinition}
/>
</StyledStack>
)}
</StyledSection>
</StyledSidebar>
<HoverDotMetadataContext.Provider value={{ hoverDotMetadata, setHoverDotMetadata }}>
<StyledSidebar contentsMinWidth="0px" gap={0}>
<StyledAside>
<DefinitionList selectedDefinitionIds={selectedDefinitionIds} setSelectedDefinitionIds={setSelectedDefinitionIds} />
</StyledAside>
<StyledSection>
<MetadataDialog
isOpen={visibleDialog?.type === 'metadataDialog'}
dotMetadata={visibleDialog?.type === 'metadataDialog' ? visibleDialog.metadata : null}
top={visibleDialog?.type === 'metadataDialog' ? visibleDialog.top : 0}
left={visibleDialog?.type === 'metadataDialog' ? visibleDialog.left : 0}
onClose={onCloseDialog}
setVisibleDialog={setVisibleDialog}
mutateCombinedDefinition={mutateCombinedDefinition}
/>
{isLoading ? (
<CenterStack>
<Loading text="Loading..." alt="Loading" />
</CenterStack>
) : !combinedDefinition ? (
<CenterStack>
<p>No data</p>
</CenterStack>
) : (
<StyledStack>
<DefinitionGraph
combinedDefinition={combinedDefinition}
graphOptions={graphOptions}
setGraphOptions={setGraphOptions}
visibleDialog={visibleDialog}
setVisibleDialog={setVisibleDialog}
/>
<StyledDefinitionSources
combinedDefinition={combinedDefinition}
mutateCombinedDefinition={mutateCombinedDefinition}
/>
</StyledStack>
)}
</StyledSection>
</StyledSidebar>
</HoverDotMetadataContext.Provider>
</RecentModulesContext.Provider>
</Wrapper>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC, useCallback, useEffect, useRef, useState } from 'react'
import React, { FC, useCallback, useContext, useEffect, useRef, useState } from 'react'
import { ReactSVGPanZoom, TOOL_NONE, TOOL_PAN } from 'react-svg-pan-zoom'
import { ReactSvgPanZoomLoader } from 'react-svg-pan-zoom-loader'
import styled from 'styled-components'
Expand All @@ -11,6 +11,8 @@ import { extractSvgSize, getClosestAndSmallestElement, toSVGPoint } from '@/util
import { DialogProps } from '../dialog'

import type { Tool, Value } from 'react-svg-pan-zoom'
import { HoverDotMetadataContext } from '@/context/HoverMetadataContext'
import { color } from '@/constants/theme'

type Props = {
combinedDefinition: CombinedDefinition
Expand Down Expand Up @@ -41,7 +43,7 @@ export const ScrollableSvg: FC<Props> = ({ combinedDefinition, setVisibleDialog

const [value, setValue] = useState<Value>({} as Value) // NOTE: react-svg-pan-zoom supported blank object as a initial value. but types is not supported.
const [tool, setTool] = useState<Tool>(TOOL_PAN)
const [hoverMetadata, setHoverMetadata] = useState<DotMetadata | null>(null)
const { hoverDotMetadata, setHoverDotMetadata } = useContext(HoverDotMetadataContext)
const [svg, setSvg] = useState<string>('')

const svgSize = extractSvgSize(svg)
Expand Down Expand Up @@ -77,9 +79,9 @@ export const ScrollableSvg: FC<Props> = ({ combinedDefinition, setVisibleDialog
}

const onClickGeometry = (event: MouseEvent) => {
if (hoverMetadata) {
if (hoverDotMetadata) {
event.preventDefault()
setVisibleDialog({ type: 'metadataDialog', metadata: hoverMetadata, left: event.clientX, top: event.clientY })
setVisibleDialog({ type: 'metadataDialog', metadata: hoverDotMetadata, left: event.clientX, top: event.clientY })
}
}

Expand All @@ -88,12 +90,12 @@ export const ScrollableSvg: FC<Props> = ({ combinedDefinition, setVisibleDialog
return () => {
document.removeEventListener('click', onClickGeometry)
}
}, [tool, hoverMetadata, setVisibleDialog])
}, [tool, hoverDotMetadata, setVisibleDialog])

// On hover .node, .edge, .cluster
useEffect(() => {
if (tool !== TOOL_NONE) {
setHoverMetadata(null)
setHoverDotMetadata(null)
return
}

Expand All @@ -102,9 +104,9 @@ export const ScrollableSvg: FC<Props> = ({ combinedDefinition, setVisibleDialog

if (element) {
const metadata = combinedDefinition.dotMetadata.find(({ id }) => element.id === id)
setHoverMetadata(metadata ?? null)
setHoverDotMetadata(metadata ?? null)
} else {
setHoverMetadata(null)
setHoverDotMetadata(null)
}
}

Expand Down Expand Up @@ -136,7 +138,7 @@ export const ScrollableSvg: FC<Props> = ({ combinedDefinition, setVisibleDialog
}
}

setHoverMetadata((prev) => findNewMetadata(prev))
setHoverDotMetadata((prev) => findNewMetadata(prev))
setVisibleDialog((prev) => {
if (prev?.type === 'metadataDialog') {
const newMetadata = findNewMetadata(prev.metadata)
Expand All @@ -150,12 +152,16 @@ export const ScrollableSvg: FC<Props> = ({ combinedDefinition, setVisibleDialog
return prev
}
})
}, [combinedDefinition.dotMetadata, setVisibleDialog, setHoverMetadata])
}, [combinedDefinition.dotMetadata, setVisibleDialog, setHoverDotMetadata])

useEffect(() => {
console.log(hoverDotMetadata?.id)
}, [hoverDotMetadata])

if (!svg) return null

return (
<Wrapper ref={observeRef} $idOnHover={hoverMetadata?.id}>
<Wrapper ref={observeRef} $idOnHover={hoverDotMetadata?.id}>
<ReactSvgPanZoomLoader
svgXML={svg}
render={(content) => (
Expand Down Expand Up @@ -198,7 +204,10 @@ const Wrapper = styled.div<{ $idOnHover: string | undefined }>`
props.$idOnHover &&
`
#${props.$idOnHover} {
stroke-width: 3;
ellipse {
stroke-width: 4;
stroke: ${color.DANGER};
}
}
cursor: pointer;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useCallback, useContext, useMemo, useState } from 'react'
import { FC, useCallback, useContext, useEffect, useMemo, useState, createRef } from 'react'
import styled from 'styled-components'

import { Link } from '@/components/Link'
Expand All @@ -8,7 +8,6 @@ import {
Cluster,
EmptyTableBody,
FaCircleInfoIcon,
FaCopyIcon,
FaPencilIcon,
Table,
TableReel,
Expand All @@ -26,6 +25,8 @@ import { RecentModulesContext } from '@/context/RecentModulesContext'
import { SourceModulesComboBox } from '@/components/SourceModulesComboBox'
import { UpdateSourceModulesButton } from '@/components/UpdateSourceModulesButton'
import { SourceMemoInput } from '@/components/SourceMemoInput'
import React from 'react'
import { HoverDotMetadataContext } from '@/context/HoverMetadataContext'

const sortTypes = ['asc', 'desc', 'none'] as const

Expand All @@ -38,16 +39,48 @@ type SortState = {

type DefinitionSourceTrProps = {
source: Source
combinedDefinition: CombinedDefinition
mutateCombinedDefinition: () => void
}

const DefinitionSourceTr: FC<DefinitionSourceTrProps> = ({ source, mutateCombinedDefinition }) => {
// Return tr
const isTr = (event: MouseEvent, trRef: HTMLTableRowElement): boolean => {
const tr = (event.target as HTMLElement).closest<Element>('tr')

return tr === trRef
}

const DefinitionSourceTr: FC<DefinitionSourceTrProps> = ({ source, combinedDefinition, mutateCombinedDefinition }) => {
const ref = createRef<HTMLTableRowElement>()
const { recentModules, setRecentModules } = useContext(RecentModulesContext)
const { setHoverDotMetadata } = useContext(HoverDotMetadataContext)
const [editingMemo, setEditingMemo] = useState<boolean>(false)
const [editingModules, setEditingModules] = useState<boolean>(false)

// On hover .node, .edge, .cluster
useEffect(() => {
if (!combinedDefinition || !ref.current) return

const currentRef = ref.current

const onMouseMove = (event: MouseEvent) => {
if (!isTr(event, currentRef)) return

const dotMetadata = combinedDefinition.dotMetadata.find((d) => d.type === 'source' && d.sourceName === source.sourceName)

console.log(`set ${dotMetadata?.id}`)
setHoverDotMetadata(dotMetadata ?? null)
}

document.addEventListener('mousemove', onMouseMove)

return () => {
document.removeEventListener('mousemove', onMouseMove)
}
}, [combinedDefinition?.dotMetadata, setHoverDotMetadata])

return (
<tr>
<tr ref={ref}>
<Td>
<Link to={path.sources.show(source.sourceName)}>{source.sourceName}</Link>
</Td>
Expand Down Expand Up @@ -187,6 +220,7 @@ export const DefinitionSources: FC<DefinitionSourcesProps> = ({ combinedDefiniti
<DefinitionSourceTr
key={source.sourceName}
source={source}
combinedDefinition={combinedDefinition}
mutateCombinedDefinition={mutateCombinedDefinition}
/>
))}
Expand Down

0 comments on commit 0fe01e7

Please sign in to comment.