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:
@@ -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';
|
||||
|
@@ -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,
|
||||
};
|
||||
|
@@ -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,
|
||||
|
@@ -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}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
};
|
||||
|
Reference in New Issue
Block a user