Skip to content

Commit

Permalink
Merge pull request #275 from liam-hq/fix-initialize-nodes
Browse files Browse the repository at this point in the history
fix: Fixed an issue where the correct table was not focused when sharing URLs in TableDetail
  • Loading branch information
hoshinotsuyoshi authored Dec 17, 2024
2 parents ab0e2dd + 4cef3ec commit c2780c0
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 44 deletions.
6 changes: 6 additions & 0 deletions frontend/.changeset/flat-bikes-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@liam-hq/erd-core": patch
"@liam-hq/cli": patch
---

fix: Fixed an issue where the correct table was not focused when sharing URLs in TableDetail
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import styles from './ERDContent.module.css'
import { ERDContentProvider, useERDContentContext } from './ERDContentContext'
import { RelationshipEdge } from './RelationshipEdge'
import { TableNode } from './TableNode'
import { useActiveTableNameFromUrl } from './useActiveTableNameFromUrl'
import { useFitViewWhenActiveTableChange } from './useFitViewWhenActiveTableChange'
import { useInitialAutoLayout } from './useInitialAutoLayout'

Expand Down Expand Up @@ -68,7 +67,6 @@ export const ERDContentInner: FC<Props> = ({
const [activeNodeId, setActiveNodeId] = useState<string | null>(null)

useInitialAutoLayout()
useActiveTableNameFromUrl()
useFitViewWhenActiveTableChange(
enabledFeatures?.fitViewWhenActiveTableChange ?? true,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import {

type ERDContentContextState = {
loading: boolean
initializeComplete: boolean
}

type ERDContentContextActions = {
setLoading: (loading: boolean) => void
setInitializeComplete: (initializeComplete: boolean) => void
}

type ERDContentConextValue = {
Expand All @@ -22,22 +24,25 @@ type ERDContentConextValue = {
const ERDContentContext = createContext<ERDContentConextValue>({
state: {
loading: true,
initializeComplete: false,
},
actions: {
setLoading: () => {},
setInitializeComplete: () => {},
},
})

export const useERDContentContext = () => useContext(ERDContentContext)

export const ERDContentProvider: FC<PropsWithChildren> = ({ children }) => {
const [loading, setLoading] = useState(true)
const [initializeComplete, setInitializeComplete] = useState(false)

return (
<ERDContentContext.Provider
value={{
state: { loading },
actions: { setLoading },
state: { loading, initializeComplete },
actions: { setLoading, setInitializeComplete },
}}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { IconButton, TidyUpIcon } from '@liam-hq/ui'
import { ToolbarButton } from '@radix-ui/react-toolbar'
import type { FC } from 'react'
import { type FC, useCallback } from 'react'
import { useAutoLayout } from '../../useAutoLayout'

export const TidyUpButton: FC = () => {
const { handleLayout } = useAutoLayout()
const handleClick = useCallback(() => {
handleLayout()
}, [handleLayout])

return (
<ToolbarButton asChild>
<IconButton
icon={<TidyUpIcon />}
tooltipContent="Tidy up"
onClick={handleLayout}
onClick={handleClick}
/>
</ToolbarButton>
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
import { useReactFlow } from '@xyflow/react'
import type { Node } from '@xyflow/react'
import type { FitViewOptions, Node } from '@xyflow/react'
import { useCallback } from 'react'
import { useERDContentContext } from '../ERDContentContext'
import { getElkLayout } from './getElkLayout'

export const useAutoLayout = () => {
const { getNodes, setNodes, getEdges, fitView } = useReactFlow()
const {
actions: { setLoading },
actions: { setLoading, setInitializeComplete },
} = useERDContentContext()

const handleLayout = useCallback(async () => {
setLoading(true)
const nodes = getNodes()
const edges = getEdges()
const visibleNodes: Node[] = nodes.filter((node) => !node.hidden)
const hiddenNodes: Node[] = nodes.filter((node) => node.hidden)
const handleLayout = useCallback(
async (fitViewOptions?: FitViewOptions) => {
setLoading(true)
const nodes = getNodes()
const edges = getEdges()
const visibleNodes: Node[] = nodes.filter((node) => !node.hidden)
const hiddenNodes: Node[] = nodes.filter((node) => node.hidden)

// NOTE: Only include edges where both the source and target are in the nodes
const nodeMap = new Map(visibleNodes.map((node) => [node.id, node]))
const visibleEdges = edges.filter((edge) => {
return nodeMap.get(edge.source) && nodeMap.get(edge.target)
})
// NOTE: Only include edges where both the source and target are in the nodes
const nodeMap = new Map(visibleNodes.map((node) => [node.id, node]))
const visibleEdges = edges.filter((edge) => {
return nodeMap.get(edge.source) && nodeMap.get(edge.target)
})

const newNodes = await getElkLayout({
nodes: visibleNodes,
edges: visibleEdges,
})
const newNodes = await getElkLayout({
nodes: visibleNodes,
edges: visibleEdges,
})

setNodes([...hiddenNodes, ...newNodes])
setLoading(false)
setTimeout(() => fitView(), 0)
}, [getNodes, setNodes, getEdges, fitView, setLoading])
setNodes([...hiddenNodes, ...newNodes])
setLoading(false)
setInitializeComplete(true)
setTimeout(() => fitView(fitViewOptions), 0)
},
[getNodes, setNodes, getEdges, fitView, setLoading, setInitializeComplete],
)

return { handleLayout }
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
import type { QueryParam } from '@/schemas/queryParam'
import { updateActiveTableName } from '@/stores'
import { useNodesInitialized } from '@xyflow/react'
import { useEffect } from 'react'
import { useERDContentContext } from './ERDContentContext'
import { useAutoLayout } from './useAutoLayout'

const getActiveTableNameFromUrl = (): string | undefined => {
const urlParams = new URLSearchParams(window.location.search)
const activeQueryParam: QueryParam = 'active'
const tableName = urlParams.get(activeQueryParam)

return tableName || undefined
}

export const useInitialAutoLayout = () => {
const nodesInitialized = useNodesInitialized()
const {
state: { initializeComplete },
} = useERDContentContext()
const { handleLayout } = useAutoLayout()

useEffect(() => {
if (initializeComplete) {
return
}

const tableNameFromUrl = getActiveTableNameFromUrl()
updateActiveTableName(tableNameFromUrl)
const fitViewOptions = tableNameFromUrl
? { maxZoom: 1, duration: 300, nodes: [{ id: tableNameFromUrl }] }
: undefined

if (nodesInitialized) {
handleLayout()
handleLayout(fitViewOptions)
}
}, [nodesInitialized, handleLayout])
}, [nodesInitialized, initializeComplete, handleLayout])
}

0 comments on commit c2780c0

Please sign in to comment.