diff --git a/web/src/components/ui/async-tree-select.tsx b/web/src/components/ui/async-tree-select.tsx index d74ece6d25..2a29404a83 100644 --- a/web/src/components/ui/async-tree-select.tsx +++ b/web/src/components/ui/async-tree-select.tsx @@ -6,7 +6,14 @@ import { import { cn } from '@/lib/utils'; import { isEmpty } from 'lodash'; import { ChevronDown, ChevronRight, Loader2, X } from 'lucide-react'; -import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; +import { + ReactNode, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; import { useTranslation } from 'react-i18next'; import { Button } from './button'; import { SearchInput } from './input'; @@ -28,6 +35,7 @@ type AsyncTreeSelectProps = { onChange?(value: TreeId): void; loadData?(node: TreeNodeType): Promise; canSelect?(node: TreeNodeType): boolean; + defaultExpandRoot?: boolean; // When false, hides the clear button and disables re-click deselection. allowClear?: boolean; }; @@ -45,6 +53,7 @@ export function AsyncTreeSelect({ loadData, onChange, canSelect, + defaultExpandRoot = false, allowClear = true, }: AsyncTreeSelectProps) { const [open, setOpen] = useState(false); @@ -52,6 +61,7 @@ export function AsyncTreeSelect({ const { t } = useTranslation(); const [expandedKeys, setExpandedKeys] = useState([]); + const rootExpansionInitialized = useRef(false); const [loadingId, setLoadingId] = useState(''); const selectedTitle = useMemo(() => { @@ -246,8 +256,17 @@ export function AsyncTreeSelect({ useEffect(() => { if (isEmpty(treeData)) { loadData?.({ id: '', parentId: '', title: '' }); + } else if (defaultExpandRoot && !rootExpansionInitialized.current) { + rootExpansionInitialized.current = true; + setExpandedKeys( + treeData + .filter((node) => + treeData.every((parent) => node.parentId !== parent.id), + ) + .map((node) => node.id), + ); } - }, [treeData, loadData]); + }, [treeData, loadData, defaultExpandRoot]); return ( diff --git a/web/src/pages/files/move-dialog.tsx b/web/src/pages/files/move-dialog.tsx index 6bd58ef3d5..2d44d6ca59 100644 --- a/web/src/pages/files/move-dialog.tsx +++ b/web/src/pages/files/move-dialog.tsx @@ -24,15 +24,19 @@ export function MoveDialog({ hideModal, onOk, loading }: IModalProps) { const [treeValue, setTreeValue] = useState(); - const [treeData, setTreeData] = useState([]); + const [treeData, setTreeData] = useState([]); const onLoadData = useCallback( async ({ id }: TreeNodeType) => { const ret = await fetchList({ parentId: id as string }); if (ret.code === 0) { setTreeData((tree) => { + const rootNodes: TreeNodeType[] = id + ? [] + : [{ id: ret.data.parent_folder.id, parentId: '', title: '/' }]; return uniqBy( tree.concat( + rootNodes, ret.data.files .filter((x: IFile) => x.type === 'folder') .map((x: IFile) => ({ @@ -65,6 +69,7 @@ export function MoveDialog({ hideModal, onOk, loading }: IModalProps) {