2025-01-07 12:17:57 +08:00
|
|
|
import React, { useCallback, useEffect, useRef } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import classnames from 'classnames';
|
|
|
|
import TableMain from './table-main';
|
|
|
|
|
|
|
|
import './index.css';
|
2025-01-15 16:47:12 +08:00
|
|
|
import './tree.css';
|
2025-01-07 12:17:57 +08:00
|
|
|
|
|
|
|
const SFTable = ({
|
|
|
|
table,
|
|
|
|
visibleColumns,
|
|
|
|
headerSettings,
|
2025-02-17 11:50:29 +08:00
|
|
|
recordsIds = [],
|
|
|
|
groupbys = [],
|
|
|
|
groups = [],
|
|
|
|
showSequenceColumn = true,
|
|
|
|
isGroupView = false,
|
|
|
|
showRecordAsTree = false,
|
2025-01-15 16:47:12 +08:00
|
|
|
recordsTree,
|
|
|
|
treeNodeKeyRecordIdMap,
|
|
|
|
keyTreeNodeFoldedMap,
|
2025-01-07 12:17:57 +08:00
|
|
|
noRecordsTipsText,
|
2025-02-17 11:50:29 +08:00
|
|
|
isLoadingMoreRecords = false,
|
|
|
|
hasMoreRecords = false,
|
|
|
|
showGridFooter = true,
|
2025-01-07 12:17:57 +08:00
|
|
|
onGridKeyDown,
|
|
|
|
onGridKeyUp,
|
|
|
|
loadMore,
|
|
|
|
loadAll,
|
|
|
|
...customProps
|
|
|
|
}) => {
|
|
|
|
const containerRef = useRef(null);
|
|
|
|
|
|
|
|
const getTableContentRect = useCallback(() => {
|
|
|
|
return containerRef.current?.getBoundingClientRect() || { x: 0, right: window.innerWidth };
|
|
|
|
}, [containerRef]);
|
|
|
|
|
|
|
|
const recordGetterById = useCallback((recordId) => {
|
|
|
|
return table.id_row_map[recordId];
|
|
|
|
}, [table]);
|
|
|
|
|
|
|
|
const recordGetter = useCallback((recordIndex) => {
|
|
|
|
const recordId = recordsIds[recordIndex];
|
|
|
|
return recordId && recordGetterById(recordId);
|
|
|
|
}, [recordsIds, recordGetterById]);
|
|
|
|
|
|
|
|
const groupRecordGetter = useCallback((groupRecordIndex) => {
|
|
|
|
if (!window.sfTableBody || !window.sfTableBody.getGroupRecordByIndex) return null;
|
|
|
|
const groupRecord = window.sfTableBody.getGroupRecordByIndex(groupRecordIndex);
|
|
|
|
const recordId = groupRecord.rowId;
|
|
|
|
return recordId && recordGetterById(recordId);
|
|
|
|
}, [recordGetterById]);
|
|
|
|
|
2025-01-15 16:47:12 +08:00
|
|
|
const getTreeNodeByIndex = useCallback((nodeIndex) => {
|
|
|
|
if (!window.sfTableBody || !window.sfTableBody.getTreeNodeByIndex) return null;
|
|
|
|
return window.sfTableBody.getTreeNodeByIndex(nodeIndex);
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const treeRecordGetter = useCallback((nodeIndex) => {
|
|
|
|
const node = getTreeNodeByIndex(nodeIndex);
|
|
|
|
const recordId = node && node._id;
|
|
|
|
return recordId && recordGetterById(recordId);
|
|
|
|
}, [getTreeNodeByIndex, recordGetterById]);
|
|
|
|
|
2025-01-07 12:17:57 +08:00
|
|
|
const recordGetterByIndex = useCallback(({ isGroupView, groupRecordIndex, recordIndex }) => {
|
2025-01-15 16:47:12 +08:00
|
|
|
if (showRecordAsTree) return treeRecordGetter(recordIndex);
|
2025-01-07 12:17:57 +08:00
|
|
|
if (isGroupView) return groupRecordGetter(groupRecordIndex);
|
|
|
|
return recordGetter(recordIndex);
|
2025-01-15 16:47:12 +08:00
|
|
|
}, [showRecordAsTree, groupRecordGetter, treeRecordGetter, recordGetter]);
|
2025-01-07 12:17:57 +08:00
|
|
|
|
|
|
|
const beforeUnloadHandler = useCallback(() => {
|
|
|
|
if (window.sfTableBody) {
|
|
|
|
window.sfTableBody.storeScrollPosition && window.sfTableBody.storeScrollPosition();
|
|
|
|
}
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
window.addEventListener('beforeunload', beforeUnloadHandler, false);
|
|
|
|
});
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className={classnames('sf-table-wrapper', { 'no-sequence-column': !showSequenceColumn })} ref={containerRef}>
|
|
|
|
<TableMain
|
|
|
|
{...customProps}
|
|
|
|
table={table}
|
|
|
|
visibleColumns={visibleColumns}
|
|
|
|
headerSettings={headerSettings}
|
|
|
|
recordsIds={recordsIds}
|
|
|
|
groupbys={groupbys}
|
|
|
|
groups={groups}
|
2025-01-15 16:47:12 +08:00
|
|
|
recordsTree={recordsTree}
|
|
|
|
keyTreeNodeFoldedMap={keyTreeNodeFoldedMap}
|
2025-01-07 12:17:57 +08:00
|
|
|
showSequenceColumn={showSequenceColumn}
|
|
|
|
isGroupView={isGroupView}
|
|
|
|
noRecordsTipsText={noRecordsTipsText}
|
|
|
|
hasMoreRecords={hasMoreRecords}
|
|
|
|
isLoadingMoreRecords={isLoadingMoreRecords}
|
|
|
|
showGridFooter={showGridFooter}
|
2025-01-15 16:47:12 +08:00
|
|
|
showRecordAsTree={showRecordAsTree}
|
2025-01-07 12:17:57 +08:00
|
|
|
loadMore={loadMore}
|
|
|
|
loadAll={loadAll}
|
|
|
|
getTableContentRect={getTableContentRect}
|
|
|
|
onGridKeyDown={onGridKeyDown}
|
|
|
|
onGridKeyUp={onGridKeyUp}
|
2025-01-15 16:47:12 +08:00
|
|
|
getTreeNodeByIndex={getTreeNodeByIndex}
|
2025-01-07 12:17:57 +08:00
|
|
|
recordGetterById={recordGetterById}
|
|
|
|
recordGetterByIndex={recordGetterByIndex}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
SFTable.propTypes = {
|
|
|
|
/**
|
|
|
|
* table: { _id, rows, id_row_map, columns, ... }
|
|
|
|
*/
|
|
|
|
table: PropTypes.object,
|
|
|
|
recordsIds: PropTypes.array,
|
|
|
|
/**
|
|
|
|
* columns: [column, ...]
|
|
|
|
* column: {
|
|
|
|
* key, name, width, frozen, icon_name, is_name_column, is_private, editable, formatter, editor, editable,
|
|
|
|
* editable_via_click_cell,
|
|
|
|
* is_popup_editor, e.g. options-selector
|
|
|
|
* is_support_direct_edit, e.g. checkbox
|
|
|
|
* is_support_preview, e.g. image
|
|
|
|
* ...
|
|
|
|
* }
|
|
|
|
*/
|
|
|
|
visibleColumns: PropTypes.array.isRequired,
|
|
|
|
headerSettings: PropTypes.object,
|
|
|
|
showSequenceColumn: PropTypes.bool,
|
|
|
|
groupbys: PropTypes.array,
|
|
|
|
groups: PropTypes.array,
|
|
|
|
isGroupView: PropTypes.bool,
|
|
|
|
noRecordsTipsText: PropTypes.string,
|
|
|
|
hasMoreRecords: PropTypes.bool,
|
|
|
|
isLoadingMoreRecords: PropTypes.bool,
|
|
|
|
showGridFooter: PropTypes.bool,
|
|
|
|
canModifyRecords: PropTypes.bool,
|
|
|
|
supportCopy: PropTypes.bool,
|
|
|
|
supportCut: PropTypes.bool,
|
|
|
|
supportPaste: PropTypes.bool,
|
|
|
|
supportDragFill: PropTypes.bool,
|
2025-01-15 16:47:12 +08:00
|
|
|
showRecordAsTree: PropTypes.bool,
|
|
|
|
/**
|
|
|
|
* recordsTree: [
|
|
|
|
* { _id, node_depth, node_index, node_key, ... }
|
|
|
|
* ...
|
|
|
|
* ]
|
|
|
|
* keyTreeNodeFoldedMap: { [node_key]: true, ... }
|
|
|
|
*/
|
|
|
|
recordsTree: PropTypes.array,
|
|
|
|
keyTreeNodeFoldedMap: PropTypes.object,
|
2025-01-07 12:17:57 +08:00
|
|
|
checkCanModifyRecord: PropTypes.func,
|
|
|
|
checkCellValueChanged: PropTypes.func, // for complex cell value compare
|
|
|
|
onGridKeyDown: PropTypes.func,
|
|
|
|
onGridKeyUp: PropTypes.func,
|
|
|
|
loadMore: PropTypes.func,
|
|
|
|
loadAll: PropTypes.func,
|
|
|
|
};
|
|
|
|
|
|
|
|
export default SFTable;
|