1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-03 16:10:26 +00:00

feat(tag): support add child tag (#7374)

This commit is contained in:
Jerry Ren
2025-01-17 10:10:45 +08:00
committed by GitHub
parent fdf720ffd5
commit 3250ca151c
28 changed files with 264 additions and 550 deletions

View File

@@ -2,7 +2,7 @@ export const TREE_NODE_KEY = {
ID: '_id',
KEY: 'node_key',
DEPTH: 'node_depth',
HAS_SUB_NODES: 'has_sub_nodes',
HAS_CHILD_NODES: 'has_child_nodes',
};
export const LOCAL_KEY_TREE_NODE_FOLDED = 'table_key_tree_node_folded_map';

View File

@@ -25,7 +25,7 @@ const Cell = React.memo(({
height,
showRecordAsTree,
nodeDepth,
hasSubNodes,
hasChildNodes,
isFoldedNode,
checkCanModifyRecord,
toggleExpandNode,
@@ -172,7 +172,7 @@ const Cell = React.memo(({
if (showRecordAsTree && isNameColumn) {
return (
<div className="sf-table-cell-tree-node">
{hasSubNodes && <span className="sf-table-record-tree-expand-icon" style={{ left: nodeDepth * NODE_ICON_LEFT_INDENT }} onClick={toggleExpandNode}><i className={classnames('sf3-font sf3-font-down', { 'rotate-270': isFoldedNode })}></i></span>}
{hasChildNodes && <span className="sf-table-record-tree-expand-icon" style={{ left: nodeDepth * NODE_ICON_LEFT_INDENT }} onClick={toggleExpandNode}><i className={classnames('sf3-font sf3-font-down', { 'rotate-270': isFoldedNode })}></i></span>}
<div className="sf-table-cell-tree-node-content" style={{ paddingLeft: NODE_CONTENT_LEFT_INDENT + nodeDepth * NODE_ICON_LEFT_INDENT }}>
{columnFormatter}
</div>
@@ -180,7 +180,7 @@ const Cell = React.memo(({
);
}
return columnFormatter;
}, [isNameColumn, column, isCellSelected, cellValue, record, showRecordAsTree, nodeDepth, hasSubNodes, isFoldedNode, modifyRecord, toggleExpandNode]);
}, [isNameColumn, column, isCellSelected, cellValue, record, showRecordAsTree, nodeDepth, hasChildNodes, isFoldedNode, modifyRecord, toggleExpandNode]);
return (
<div key={`${record._id}-${column.key}`} {...containerProps}>
@@ -213,7 +213,7 @@ Cell.propTypes = {
bgColor: PropTypes.string,
showRecordAsTree: PropTypes.bool,
nodeDepth: PropTypes.number,
hasSubNodes: PropTypes.bool,
hasChildNodes: PropTypes.bool,
isFoldedNode: PropTypes.bool,
toggleExpandNode: PropTypes.func,
};

View File

@@ -38,7 +38,7 @@ class Record extends React.Component {
nextProps.showRecordAsTree !== this.props.showRecordAsTree ||
nextProps.nodeKey !== this.props.nodeKey ||
nextProps.nodeDepth !== this.props.nodeDepth ||
nextProps.hasSubNodes !== this.props.hasSubNodes ||
nextProps.hasChildNodes !== this.props.hasChildNodes ||
nextProps.treeNodeDisplayIndex !== this.props.treeNodeDisplayIndex ||
nextProps.isFoldedNode !== this.props.isFoldedNode
);
@@ -117,7 +117,7 @@ class Record extends React.Component {
bgColor={bgColor}
showRecordAsTree={this.props.showRecordAsTree}
nodeDepth={this.props.nodeDepth}
hasSubNodes={this.props.hasSubNodes}
hasChildNodes={this.props.hasChildNodes}
isFoldedNode={this.props.isFoldedNode}
toggleExpandNode={this.props.toggleExpandNode}
/>
@@ -184,7 +184,7 @@ class Record extends React.Component {
bgColor={bgColor}
showRecordAsTree={this.props.showRecordAsTree}
nodeDepth={this.props.nodeDepth}
hasSubNodes={this.props.hasSubNodes}
hasChildNodes={this.props.hasChildNodes}
isFoldedNode={this.props.isFoldedNode}
toggleExpandNode={this.props.toggleExpandNode}
/>
@@ -318,7 +318,7 @@ Record.propTypes = {
showRecordAsTree: PropTypes.bool,
nodeKey: PropTypes.string,
nodeDepth: PropTypes.number,
hasSubNodes: PropTypes.bool,
hasChildNodes: PropTypes.bool,
treeNodeDisplayIndex: PropTypes.number,
isFoldedNode: PropTypes.bool,
toggleExpandNode: PropTypes.func,

View File

@@ -6,7 +6,7 @@ import InteractionMasks from '../../masks/interaction-masks';
import Record from './record';
import EventBus from '../../../common/event-bus';
import { EVENT_BUS_TYPE } from '../../constants/event-bus-type';
import { checkIsTreeNodeShown, getTreeNodeId, getTreeNodeKey, getValidKeyTreeNodeFoldedMap } from '../../utils/tree';
import { checkIsTreeNodeShown, checkTreeNodeHasChildNodes, getTreeNodeId, getTreeNodeKey, getValidKeyTreeNodeFoldedMap } from '../../utils/tree';
import { isShiftKeyDown } from '../../../../utils/keyboard-utils';
import { getColumnScrollPosition, getColVisibleStartIdx, getColVisibleEndIdx } from '../../utils/records-body-utils';
import { checkEditableViaClickCell, checkIsColumnSupportDirectEdit, getColumnByIndex, getColumnIndexByKey } from '../../utils/column';
@@ -535,7 +535,8 @@ class TreeBody extends Component {
const rowHeight = this.getRowHeight();
const cellMetaData = this.getCellMetaData();
let shownNodes = visibleNodes.map((node, index) => {
const { _id: recordId, node_key, node_depth, has_sub_nodes, node_display_index } = node;
const { _id: recordId, node_key, node_depth, node_display_index } = node;
const hasChildNodes = checkTreeNodeHasChildNodes(node);
const record = this.props.recordGetterById(recordId);
const isSelected = TreeMetrics.checkIsTreeNodeSelected(node_key, treeMetrics);
const recordIndex = startRenderIndex + index;
@@ -568,7 +569,7 @@ class TreeBody extends Component {
searchResult={this.props.searchResult}
nodeKey={node_key}
nodeDepth={node_depth}
hasSubNodes={has_sub_nodes}
hasChildNodes={hasChildNodes}
isFoldedNode={isFoldedNode}
checkCanModifyRecord={this.props.checkCanModifyRecord}
checkCellValueChanged={this.props.checkCellValueChanged}

View File

@@ -22,7 +22,7 @@ export const checkCellValueChanged = (oldVal, newVal) => {
export const cellCompare = (props, nextProps) => {
const {
record: oldRecord, column, isCellSelected, isLastCell, highlightClassName, height, bgColor,
showRecordAsTree, nodeDepth, hasSubNodes, isFoldedNode,
showRecordAsTree, nodeDepth, hasChildNodes, isFoldedNode,
} = props;
const {
record: newRecord, highlightClassName: newHighlightClassName, height: newHeight, column: newColumn, bgColor: newBgColor,
@@ -50,7 +50,7 @@ export const cellCompare = (props, nextProps) => {
bgColor !== newBgColor ||
showRecordAsTree !== nextProps.showRecordAsTree ||
nodeDepth !== nextProps.nodeDepth ||
hasSubNodes !== nextProps.hasSubNodes ||
hasChildNodes !== nextProps.hasChildNodes ||
isFoldedNode !== nextProps.isFoldedNode ||
props.groupRecordIndex !== nextProps.groupRecordIndex ||
props.recordIndex !== nextProps.recordIndex

View File

@@ -1,11 +1,15 @@
import { TREE_NODE_KEY } from '../constants/tree';
export const createTreeNode = (nodeId, nodeKey, depth, hasSubNodes) => {
export const generateNodeKey = (parentKey, currentNodeId) => {
return `${parentKey ? parentKey + '_' : ''}${currentNodeId}`;
};
export const createTreeNode = (nodeId, nodeKey, depth, hasChildNodes) => {
return {
[TREE_NODE_KEY.ID]: nodeId,
[TREE_NODE_KEY.KEY]: nodeKey,
[TREE_NODE_KEY.DEPTH]: depth,
[TREE_NODE_KEY.HAS_SUB_NODES]: hasSubNodes,
[TREE_NODE_KEY.HAS_CHILD_NODES]: hasChildNodes,
};
};
@@ -74,3 +78,56 @@ export const getTreeNodeId = (node) => {
export const getTreeNodeKey = (node) => {
return node ? node[TREE_NODE_KEY.KEY] : '';
};
export const getTreeNodeDepth = (node) => {
return node ? node[TREE_NODE_KEY.DEPTH] : 0;
};
export const checkTreeNodeHasChildNodes = (node) => {
return node ? node[TREE_NODE_KEY.HAS_CHILD_NODES] : false;
};
export const resetTreeHasChildNodesStatus = (tree) => {
if (!Array.isArray(tree) || tree.length === 0) {
return;
}
tree.forEach((node, index) => {
const nextNode = tree[index + 1];
const nextNodeKey = getTreeNodeKey(nextNode);
const currentNodeKey = getTreeNodeKey(node);
if (nextNode && checkTreeNodeHasChildNodes(node) && !nextNodeKey.includes(currentNodeKey)) {
tree[index][TREE_NODE_KEY.HAS_CHILD_NODES] = false;
}
});
};
export const addTreeChildNode = (newChildNode, parentNode, tree) => {
if (!parentNode || !Array.isArray(tree) || tree.length === 0) {
return;
}
const parentNodeKey = getTreeNodeKey(parentNode);
const parentNodeDepth = getTreeNodeDepth(parentNode);
const parentNodeIndex = tree.findIndex((node) => getTreeNodeKey(node) === parentNodeKey);
if (parentNodeIndex < 0) {
return;
}
if (!checkTreeNodeHasChildNodes(parentNode)) {
tree[parentNodeIndex] = { ...parentNode, [TREE_NODE_KEY.HAS_CHILD_NODES]: true };
}
const childNodeDepth = parentNodeDepth + 1;
let lastChildNodeIndex = parentNodeIndex;
for (let i = parentNodeIndex + 1, len = tree.length; i < len; i++) {
const currentNode = tree[i];
if (!getTreeNodeKey(currentNode).includes(parentNodeKey)) {
break;
}
// insert new child tag behind the last child tag
if (getTreeNodeDepth(currentNode) === childNodeDepth) {
lastChildNodeIndex = i;
}
}
tree.splice(lastChildNodeIndex + 1, 0, newChildNode);
};