mirror of
https://github.com/reconurge/flowsint.git
synced 2026-03-12 01:44:42 -05:00
feat: on node click
This commit is contained in:
@@ -25,6 +25,7 @@ import { AlignCenterHorizontal, AlignCenterVertical, MaximizeIcon, RotateCcwIcon
|
||||
import { useTheme } from 'next-themes';
|
||||
import NewActions from './new-actions';
|
||||
import { IconButton, Tooltip, Spinner } from '@radix-ui/themes';
|
||||
import { usePathname, useSearchParams, useRouter } from 'next/navigation';
|
||||
|
||||
const nodeTypes = { individual: IndividualNode, phone: PhoneNode, ip: IpNode, email: EmailNode, social: SocialNode };
|
||||
const edgeTypes = {
|
||||
@@ -63,8 +64,19 @@ const LayoutFlow = ({ initialNodes, initialEdges, theme }: { initialNodes: any,
|
||||
const { fitView, zoomIn, zoomOut, addNodes } = useReactFlow();
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
const ref = useRef(null);
|
||||
const createQueryString = useCallback(
|
||||
(name: string, value: string) => {
|
||||
const params = new URLSearchParams(searchParams.toString())
|
||||
params.set(name, value)
|
||||
|
||||
return params.toString()
|
||||
},
|
||||
[searchParams]
|
||||
)
|
||||
const onLayout = useCallback(
|
||||
(direction: any) => {
|
||||
const layouted = getLayoutedElements(nodes, edges, { direction });
|
||||
@@ -90,6 +102,9 @@ const LayoutFlow = ({ initialNodes, initialEdges, theme }: { initialNodes: any,
|
||||
onLayout('LR')
|
||||
}, [initialEdges])
|
||||
|
||||
const handleOpenIndividualModal = (id: string) => router.push(pathname + '?' + createQueryString('individual_id', id))
|
||||
|
||||
|
||||
return (
|
||||
<div className='h-[calc(100vh_-_48px)]'>
|
||||
<ReactFlow
|
||||
@@ -100,6 +115,10 @@ const LayoutFlow = ({ initialNodes, initialEdges, theme }: { initialNodes: any,
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onConnect={onConnect}
|
||||
onNodeClick={(_, node) => {
|
||||
if (node.type !== "individual") return
|
||||
handleOpenIndividualModal(node.id);
|
||||
}}
|
||||
fitView
|
||||
proOptions={{
|
||||
hideAttribution: true
|
||||
|
||||
@@ -137,7 +137,7 @@ const IndividualModal = () => {
|
||||
<Flex key={index} gap="2" align="center">
|
||||
<TextField.Root
|
||||
value={email}
|
||||
onChange={(e) => handleFieldChange(index, e.target.value, setEmails)}
|
||||
onChange={(e) => handleFieldChange(index as any, e.target.value, setEmails)}
|
||||
placeholder="Email"
|
||||
type="email"
|
||||
disabled={!editMode}
|
||||
@@ -147,7 +147,7 @@ const IndividualModal = () => {
|
||||
<IconButton
|
||||
type="button"
|
||||
variant="ghost"
|
||||
onClick={() => handleRemoveField(index, setEmails)}
|
||||
onClick={() => handleRemoveField(index as any, setEmails)}
|
||||
aria-label="Remove email"
|
||||
>
|
||||
<TrashIcon />
|
||||
@@ -189,7 +189,6 @@ const IndividualModal = () => {
|
||||
)}
|
||||
</Flex>
|
||||
</Tabs.Content>
|
||||
|
||||
<Tabs.Content value="social_account">
|
||||
<Flex direction="column" gap="3">
|
||||
<TextField.Root
|
||||
|
||||
@@ -6,29 +6,16 @@ import { Avatar, Card, Box, Flex, Text, ContextMenu, Spinner, Badge, Tooltip } f
|
||||
import { AtSignIcon, CameraIcon, FacebookIcon, InstagramIcon, LocateIcon, MessageCircleDashedIcon, PhoneIcon, SendIcon, UserIcon } from 'lucide-react';
|
||||
import { NodeProvider, useNodeContext } from './node-context';
|
||||
import { cn } from '@/utils';
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
||||
|
||||
function Custom({ data }: any) {
|
||||
const { settings } = useInvestigationContext()
|
||||
const { setOpenAddNodeModal, handleDuplicateNode, handleDeleteNode, loading } = useNodeContext()
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
const createQueryString = useCallback(
|
||||
(name: string, value: string) => {
|
||||
const params = new URLSearchParams(searchParams.toString())
|
||||
params.set(name, value)
|
||||
|
||||
return params.toString()
|
||||
},
|
||||
[searchParams]
|
||||
)
|
||||
const handleOpenIndividualModal = () => router.push(pathname + '?' + createQueryString('individual_id', data.id))
|
||||
return (
|
||||
<>
|
||||
<ContextMenu.Root>
|
||||
<ContextMenu.Trigger>
|
||||
<Box onClick={handleOpenIndividualModal} className={cn(loading ? "!opacity-40" : "!opacity-100")}>{settings.showNodeLabel ?
|
||||
<Box className={cn(loading ? "!opacity-40" : "!opacity-100")}>{settings.showNodeLabel ?
|
||||
<Card className='!py-1'>
|
||||
<Flex gap="2" align="center">
|
||||
<Avatar
|
||||
@@ -49,7 +36,7 @@ function Custom({ data }: any) {
|
||||
</Flex>
|
||||
</Card> :
|
||||
<Tooltip content={data.full_name}>
|
||||
<button onClick={handleOpenIndividualModal} className='!rounded-full border-transparent'>
|
||||
<button className='!rounded-full border-transparent'>
|
||||
<Avatar
|
||||
size="3"
|
||||
src={data?.image_url}
|
||||
@@ -98,7 +85,7 @@ function Custom({ data }: any) {
|
||||
Delete
|
||||
</ContextMenu.Item>
|
||||
</ContextMenu.Content>
|
||||
</ContextMenu.Root>
|
||||
</ContextMenu.Root >
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user