import { forwardRef, useImperativeHandle, useRef, useEffect, useState, useCallback, useMemo, createElement } from 'react' import { Table, Skeleton, Card, Row, Col, Descriptions, Flex, Spin, Button, Input, Space, Tooltip, Form } from 'antd' import { LoadingOutlined } from '@ant-design/icons' import PropTypes from 'prop-types' import { useMediaQuery } from 'react-responsive' import { useContext } from 'react' import { ApiServerContext } from '../context/ApiServerContext' import config from '../../../config' import loglevel from 'loglevel' import { getModelProperties, getModelByName } from '../../../database/ObjectModels' import ObjectProperty from './ObjectProperty' import XMarkIcon from '../../Icons/XMarkIcon' import CheckIcon from '../../Icons/CheckIcon' import { useNavigate } from 'react-router-dom' import QuestionCircleIcon from '../../Icons/QuestionCircleIcon' import { AuthContext } from '../context/AuthContext' import { ElectronContext } from '../context/ElectronContext' import ActionsIcon from '../../Icons/ActionsIcon' const logger = loglevel.getLogger('DasboardTable') logger.setLevel(config.logLevel) const RowForm = ({ record, isEditing, onRegister, children }) => { const [form] = Form.useForm() useEffect(() => { if (isEditing && record && !record.isSkeleton) { form.setFieldsValue(record) onRegister(record._id, form) } return () => { if (record?._id) onRegister(record._id, null) } }, [isEditing, record, form, onRegister]) return (
{children}
) } RowForm.propTypes = { record: PropTypes.object, isEditing: PropTypes.bool, onRegister: PropTypes.func, children: PropTypes.node } const EditableRow = ({ record, isEditing, onRegister, ...props }) => { return ( ) } EditableRow.propTypes = { record: PropTypes.object, isEditing: PropTypes.bool, onRegister: PropTypes.func } const ObjectTable = forwardRef( ( { type, pageSize = 25, scrollHeight = 'calc(var(--unit-100vh) - 260px)', onDataChange, initialPage = 1, cards = false, visibleColumns = {}, masterFilter = {}, size = 'middle', onStateChange }, ref ) => { const { token } = useContext(AuthContext) const { isElectron } = useContext(ElectronContext) const onStateChangeRef = useRef(onStateChange) const { userProfile } = useContext(AuthContext) useEffect(() => { onStateChangeRef.current = onStateChange }, [onStateChange]) const { fetchObjects, connected, subscribeToObjectUpdates, subscribeToObjectTypeUpdates, updateMultipleObjects, lockObject, unlockObject } = useContext(ApiServerContext) const isMobile = useMediaQuery({ maxWidth: 768 }) const navigate = useNavigate() var adjustedScrollHeight = scrollHeight if (isMobile) { adjustedScrollHeight = 'calc(var(--unit-100vh) - 316px)' } if (cards) { adjustedScrollHeight = 'calc(var(--unit-100vh) - 280px)' } if (isElectron) { adjustedScrollHeight = 'calc(var(--unit-100vh) - 244px)' } if (isMobile && isElectron) { adjustedScrollHeight = 'calc(var(--unit-100vh) - 282px)' } if (cards && isElectron) { adjustedScrollHeight = 'calc(var(--unit-100vh) - 260px)' } const tableRef = useRef(null) const model = getModelByName(type) const tableFilterRef = useRef({}) const tableSorterRef = useRef({}) const [initialized, setInitialized] = useState(false) // Table state const [pages, setPages] = useState([]) const pagesRef = useRef(pages) const [hasMore, setHasMore] = useState(true) const [loading, setLoading] = useState(true) const [lazyLoading, setLazyLoading] = useState(false) const [tableData, setTableData] = useState([]) const [isEditing, setIsEditing] = useState(false) const [editLoading, setEditLoading] = useState(false) const rowFormsRef = useRef({}) const registerForm = useCallback((id, form) => { if (form) { rowFormsRef.current[id] = form } else { delete rowFormsRef.current[id] } }, []) useEffect(() => { onStateChangeRef.current?.({ isEditing, editLoading }) }, [isEditing, editLoading]) const subscribedIdsRef = useRef([]) // const [typeSubscribed, setTypeSubscribed] = useState(false) const unsubscribesRef = useRef([]) const updateEventHandlerRef = useRef() const subscribeToObjectTypeUpdatesRef = useRef(null) const prevValuesRef = useRef({ type, masterFilter }) const rowActions = model.actions?.filter((action) => action.row == true) || [] const createSkeletonData = useCallback(() => { return Array(pageSize) .fill(null) .map(() => ({ _id: `skeleton-${Math.random().toString(36).substring(2, 15)}`, isSkeleton: true })) }, [pageSize]) const renderActions = (objectData) => { return ( {rowActions.map((action, index) => { var disabled = false if (action.disabled) { if (typeof action.disabled === 'function') { disabled = action.disabled({ ...objectData, _user: userProfile }) } else { disabled = action.disabled } } return (