1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-27 19:20:53 +00:00

collapse tag node by default (#7675)

Co-authored-by: zhouwenxuan <aries@Mac.local>
This commit is contained in:
Aries 2025-03-29 10:34:10 +08:00 committed by GitHub
parent 281a81cbd2
commit 796600eef6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 59 additions and 26 deletions

View File

@ -41,6 +41,7 @@ const TagsEditor = forwardRef(({
const [maxItemNum, setMaxItemNum] = useState(0); const [maxItemNum, setMaxItemNum] = useState(0);
const [nodes, setNodes] = useState([]); const [nodes, setNodes] = useState([]);
const [keyNodeFoldedMap, setKeyNodeFoldedMap] = useState({}); const [keyNodeFoldedMap, setKeyNodeFoldedMap] = useState({});
const [searchedKeyNodeFoldedMap, setSearchedKeyNodeFoldedMap] = useState({});
const [recentlyUsed, setRecentlyUsed] = useState([]); const [recentlyUsed, setRecentlyUsed] = useState([]);
const itemHeight = 30; const itemHeight = 30;
const editorContainerRef = useRef(null); const editorContainerRef = useRef(null);
@ -243,7 +244,8 @@ const TagsEditor = forwardRef(({
} }
}, []); }, []);
const getShownNodes = useCallback((tree, keyNodeFoldedMap) => { const getShownNodes = useCallback(() => {
const tree = tagsData?.rows_tree;
if (!Array.isArray(tree)) { if (!Array.isArray(tree)) {
return []; return [];
} }
@ -253,17 +255,6 @@ const TagsEditor = forwardRef(({
const nodeId = getTreeNodeId(node); const nodeId = getTreeNodeId(node);
const row = getRowById(tagsData, nodeId); const row = getRowById(tagsData, nodeId);
if (!row) return; if (!row) return;
if (searchValue) {
const value = searchValue.toLowerCase();
const tagName = getTagName(row).toLowerCase();
const tagColor = getTagColor(row).toLowerCase();
if (!tagName.includes(value) && !tagColor.includes(value)) return;
if (showTagsAsTree) {
const nodesWithAncestors = getNodesWithAncestors(node, tree).filter(node => checkIsTreeNodeShown(getTreeNodeKey(node), keyNodeFoldedMap));
shownNodes = [...shownNodes, ...nodesWithAncestors];
return;
}
}
const nodeKey = getTreeNodeKey(node); const nodeKey = getTreeNodeKey(node);
if (row && checkIsTreeNodeShown(nodeKey, keyNodeFoldedMap)) { if (row && checkIsTreeNodeShown(nodeKey, keyNodeFoldedMap)) {
shownNodes.push({ shownNodes.push({
@ -273,19 +264,47 @@ const TagsEditor = forwardRef(({
} }
}); });
return shownNodes; return shownNodes;
}, [tagsData, searchValue, showTagsAsTree]); }, [tagsData, keyNodeFoldedMap]);
const getSearchedNodes = useCallback(() => {
const tree = tagsData?.rows_tree;
if (!Array.isArray(tree)) {
return [];
}
let searchedNodes = [];
tree.forEach((node, index) => {
const nodeId = getTreeNodeId(node);
const row = getRowById(tagsData, nodeId);
if (!row) return;
const value = searchValue.toLowerCase();
const tagName = getTagName(row).toLowerCase();
const tagColor = getTagColor(row).toLowerCase();
if (!tagName.includes(value) && !tagColor.includes(value)) return;
const nodesWithAncestors = getNodesWithAncestors(node, tree).filter(node => checkIsTreeNodeShown(getTreeNodeKey(node), searchedKeyNodeFoldedMap));
searchedNodes = [...searchedNodes, ...nodesWithAncestors];
});
return searchedNodes;
}, [tagsData, searchValue, searchedKeyNodeFoldedMap]);
const toggleExpandTreeNode = useCallback((nodeKey) => { const toggleExpandTreeNode = useCallback((nodeKey) => {
if (!searchValue) {
const updatedKeyNodeFoldedMap = { ...keyNodeFoldedMap }; const updatedKeyNodeFoldedMap = { ...keyNodeFoldedMap };
if (updatedKeyNodeFoldedMap[nodeKey]) { if (updatedKeyNodeFoldedMap[nodeKey]) {
delete updatedKeyNodeFoldedMap[nodeKey]; delete updatedKeyNodeFoldedMap[nodeKey];
} else { } else {
updatedKeyNodeFoldedMap[nodeKey] = true; updatedKeyNodeFoldedMap[nodeKey] = true;
} }
const updatedNodes = getShownNodes(tagsData.rows_tree, updatedKeyNodeFoldedMap);
setNodes(updatedNodes);
setKeyNodeFoldedMap(updatedKeyNodeFoldedMap); setKeyNodeFoldedMap(updatedKeyNodeFoldedMap);
}, [tagsData, keyNodeFoldedMap, getShownNodes]); } else {
const updatedSearchedKeyNodeFoldedMap = { ...searchedKeyNodeFoldedMap };
if (updatedSearchedKeyNodeFoldedMap[nodeKey]) {
delete updatedSearchedKeyNodeFoldedMap[nodeKey];
} else {
updatedSearchedKeyNodeFoldedMap[nodeKey] = true;
}
setSearchedKeyNodeFoldedMap(updatedSearchedKeyNodeFoldedMap);
}
}, [keyNodeFoldedMap, searchedKeyNodeFoldedMap, searchValue]);
useEffect(() => { useEffect(() => {
if (editorRef.current) { if (editorRef.current) {
@ -312,12 +331,26 @@ const TagsEditor = forwardRef(({
setRecentlyUsed(tags); setRecentlyUsed(tags);
}, [tagsData, localStorage]); }, [tagsData, localStorage]);
useEffect(() => {
if (tagsData?.rows_tree && showTagsAsTree) {
const updatedKeyNodeFoldedMap = tagsData.rows_tree.reduce((acc, node) => {
const nodeKey = getTreeNodeKey(node);
if (checkTreeNodeHasChildNodes(node)) {
acc[nodeKey] = true;
}
return acc;
}, {});
setKeyNodeFoldedMap(updatedKeyNodeFoldedMap);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => { useEffect(() => {
if (tagsData?.rows_tree) { if (tagsData?.rows_tree) {
const shownNodes = getShownNodes(tagsData.rows_tree, keyNodeFoldedMap); const shownNodes = searchValue ? getSearchedNodes() : getShownNodes();
setNodes(shownNodes); setNodes(shownNodes);
} }
}, [tagsData, keyNodeFoldedMap, getShownNodes]); }, [tagsData, searchValue, getSearchedNodes, getShownNodes]);
const renderOptions = useCallback(() => { const renderOptions = useCallback(() => {
if (displayTags.length === 0) { if (displayTags.length === 0) {
@ -394,14 +427,14 @@ const TagsEditor = forwardRef(({
onMouseLeave={onTreeMenuMouseLeave} onMouseLeave={onTreeMenuMouseLeave}
depth={getTreeNodeDepth(node)} depth={getTreeNodeDepth(node)}
hasChildren={checkTreeNodeHasChildNodes(node)} hasChildren={checkTreeNodeHasChildNodes(node)}
isFolded={keyNodeFoldedMap[nodeKey]} isFolded={!searchValue ? keyNodeFoldedMap[nodeKey] : searchedKeyNodeFoldedMap[nodeKey]}
onToggleExpand={() => toggleExpandTreeNode(nodeKey)} onToggleExpand={() => toggleExpandTreeNode(nodeKey)}
/> />
); );
})} })}
</> </>
); );
}, [nodes, tagsData, value, highlightNodeIndex, searchValue, recentlyUsedTags, renderRecentlyUsed, toggleExpandTreeNode, keyNodeFoldedMap, onSelectTag, onTreeMenuMouseEnter, onTreeMenuMouseLeave]); }, [nodes, tagsData, value, highlightNodeIndex, searchValue, recentlyUsedTags, renderRecentlyUsed, toggleExpandTreeNode, keyNodeFoldedMap, searchedKeyNodeFoldedMap, onSelectTag, onTreeMenuMouseEnter, onTreeMenuMouseLeave]);
return ( return (
<div className={classnames('sf-metadata-tags-editor', { 'tags-tree-container': showTagsAsTree })} style={style} ref={editorRef}> <div className={classnames('sf-metadata-tags-editor', { 'tags-tree-container': showTagsAsTree })} style={style} ref={editorRef}>

View File

@ -49,7 +49,7 @@ const TagItem = ({
<div className="sf-metadata-tag-color" style={{ backgroundColor: tagColor }} /> <div className="sf-metadata-tag-color" style={{ backgroundColor: tagColor }} />
<div className="sf-metadata-tag-name">{tagName}</div> <div className="sf-metadata-tag-name">{tagName}</div>
</div> </div>
<div className="sf-metadata-tags-editor-tag-check-icon"> <div className="sf-metadata-tags-editor-tag-check-icon mr-1">
{isSelected && <Icon className="sf-metadata-icon" symbol="check-mark" />} {isSelected && <Icon className="sf-metadata-icon" symbol="check-mark" />}
</div> </div>
</div> </div>