@@ -1,114 +1,101 @@
|
||||
import { Box, HStack, Text, VStack } from '@chakra-ui/react';
|
||||
import { Box, HStack, VStack } from '@chakra-ui/react';
|
||||
import type { OrgType } from '@fastgpt/global/support/user/team/org/type';
|
||||
import Avatar from '@fastgpt/web/components/common/Avatar';
|
||||
import { useToggle } from 'ahooks';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import IconButton from './IconButton';
|
||||
|
||||
function OrgTreeNode({
|
||||
org,
|
||||
list,
|
||||
selectedOrg,
|
||||
selectOrg,
|
||||
indent = 0
|
||||
setSelectedOrg,
|
||||
index = 0
|
||||
}: {
|
||||
org: OrgType;
|
||||
list: OrgType[];
|
||||
selectedOrg?: OrgType;
|
||||
selectOrg?: (org?: OrgType) => void;
|
||||
indent?: number;
|
||||
setSelectedOrg: (org?: OrgType) => void;
|
||||
index?: number;
|
||||
}) {
|
||||
const children = useMemo(
|
||||
() => list.filter((item) => item.path === `${org.path}/${org._id}`),
|
||||
[org, list]
|
||||
);
|
||||
const [isExpanded, toggleIsExpanded] = useToggle(false);
|
||||
const [isExpanded, toggleIsExpanded] = useToggle(index === 0);
|
||||
|
||||
return (
|
||||
<VStack alignItems={'start'} w="full" gap={'8px'}>
|
||||
<Box userSelect={'none'}>
|
||||
<HStack
|
||||
w="full"
|
||||
_hover={{ bgColor: selectedOrg === org ? 'blue.200' : 'gray.100' }}
|
||||
borderRadius="4px"
|
||||
boxSizing="border-box"
|
||||
py="4px"
|
||||
pl={`calc(${indent}rem + 4px)`}
|
||||
transition={'background 0.1s'}
|
||||
{...(selectedOrg === org ? { bgColor: 'blue.100' } : {})}
|
||||
borderRadius="sm"
|
||||
_hover={{ bg: 'myGray.100' }}
|
||||
py={1}
|
||||
pr={2}
|
||||
pl={index === 0 ? '0.5rem' : `${1.75 * (index - 1) + 0.5}rem`}
|
||||
cursor={'pointer'}
|
||||
{...(selectedOrg === org
|
||||
? {
|
||||
bg: 'primary.50 !important',
|
||||
onClick: () => setSelectedOrg(undefined)
|
||||
}
|
||||
: {
|
||||
onClick: () => setSelectedOrg(org)
|
||||
})}
|
||||
>
|
||||
{children.length > 0 ? (
|
||||
{index > 0 && (
|
||||
<IconButton
|
||||
name={isExpanded ? 'common/downArrowFill' : 'common/rightArrowFill'}
|
||||
onClick={() => toggleIsExpanded.toggle()}
|
||||
color={'myGray.500'}
|
||||
p={0}
|
||||
w={'1.25rem'}
|
||||
visibility={children.length > 0 ? 'visible' : 'hidden'}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
toggleIsExpanded.toggle();
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<Box w={'1rem'} h={'1rem'} m="1" />
|
||||
)}
|
||||
<HStack onClick={() => selectOrg?.(org)} cursor="pointer">
|
||||
<Avatar src={org.avatar} w="20px" h="20px" rounded={'50%'} />
|
||||
<Text>{org.name}</Text>
|
||||
<HStack
|
||||
flex={'1 0 0'}
|
||||
onClick={() => setSelectedOrg(org)}
|
||||
cursor={'pointer'}
|
||||
borderRadius={'xs'}
|
||||
>
|
||||
<Avatar src={org.avatar} w={'1.25rem'} borderRadius={'xs'} />
|
||||
<Box>{org.name}</Box>
|
||||
</HStack>
|
||||
</HStack>
|
||||
{isExpanded &&
|
||||
children.length > 0 &&
|
||||
children.map((child) => (
|
||||
<OrgTreeNode
|
||||
key={child._id}
|
||||
org={child}
|
||||
indent={indent + 1}
|
||||
list={list}
|
||||
selectedOrg={selectedOrg}
|
||||
selectOrg={selectOrg}
|
||||
/>
|
||||
<Box key={child._id} mt={0.5}>
|
||||
<OrgTreeNode
|
||||
org={child}
|
||||
index={index + 1}
|
||||
list={list}
|
||||
selectedOrg={selectedOrg}
|
||||
setSelectedOrg={setSelectedOrg}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
</VStack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function OrgTree({
|
||||
orgs,
|
||||
teamName,
|
||||
teamAvatar,
|
||||
selectedOrg,
|
||||
selectOrg
|
||||
setSelectedOrg
|
||||
}: {
|
||||
orgs: OrgType[];
|
||||
teamAvatar: string;
|
||||
teamName: string;
|
||||
selectedOrg?: OrgType;
|
||||
selectOrg?: (org?: OrgType) => void;
|
||||
setSelectedOrg: (org?: OrgType) => void;
|
||||
}) {
|
||||
const root = orgs[0];
|
||||
if (!root) return null;
|
||||
const children = useMemo(
|
||||
() => orgs.filter((item) => item.path === `${root.path}/${root._id}`),
|
||||
[root, orgs]
|
||||
);
|
||||
if (!root) return;
|
||||
|
||||
return (
|
||||
<VStack alignItems={'start'} gap={'8px'}>
|
||||
<HStack
|
||||
w="full"
|
||||
onClick={() => selectOrg?.(root)}
|
||||
cursor="pointer"
|
||||
_hover={{ bgColor: selectedOrg === root ? 'blue.200' : 'gray.100' }}
|
||||
borderRadius="4px"
|
||||
p="4px"
|
||||
transition={'background 0.1s'}
|
||||
{...(selectedOrg === root ? { bgColor: 'blue.100' } : {})}
|
||||
>
|
||||
<Avatar src={teamAvatar} w="20px" h="20px" rounded={'50%'} />
|
||||
<Text>{teamName}</Text>
|
||||
</HStack>
|
||||
{children.map((child) => (
|
||||
<OrgTreeNode
|
||||
key={child._id}
|
||||
org={child}
|
||||
list={orgs}
|
||||
selectOrg={selectOrg}
|
||||
selectedOrg={selectedOrg}
|
||||
/>
|
||||
))}
|
||||
</VStack>
|
||||
<OrgTreeNode org={root} list={orgs} setSelectedOrg={setSelectedOrg} selectedOrg={selectedOrg} />
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user