import React, { forwardRef, useState } from 'react' import { Typography, Space, Descriptions, Badge, Tag, Table } from 'antd' import PropTypes from 'prop-types' import IdText from './IdText' import { AuditOutlined, LoadingOutlined } from '@ant-design/icons' import TimeDisplay from '../common/TimeDisplay' const { Text } = Typography const formatPropertyName = (name) => { return name .replace(/([A-Z])/g, ' $1') .replace(/^./, (str) => str.toUpperCase()) } const isObjectId = (value) => { return typeof value === 'string' && /^[0-9a-fA-F]{24}$/.test(value) } const formatValue = (value, propertyName) => { if (value === null || value === undefined || value === '') { return n/a } // Handle colors specifically if (propertyName === 'color') { return } if (propertyName === 'state' && typeof value === 'object' && value.type) { return ( {value.type.charAt(0).toUpperCase() + value.type.slice(1)} ) } // Check if the value is a timestamp (ISO date string) if ( typeof value === 'string' && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value) ) { return } if (typeof value === 'boolean' || value === true || value === false) { return ( {value ? 'Yes' : 'No'} ) } if (isObjectId(value)) { return ( ) } if (typeof value === 'object') { return {JSON.stringify(value)} } return {value} } const AuditLogTable = forwardRef( ({ items, loading, showTargetColumn, showOwnerColumn }, ref) => { const [sortedInfo, setSortedInfo] = useState({ columnKey: 'createdAt', order: 'descend' }) const handleChange = (pagination, filters, sorter) => { setSortedInfo(sorter) } const columns = [ { title: '', key: 'icon', width: 50, render: () => }, { title: 'ID', dataIndex: '_id', key: 'id', width: 180, render: (text) => , sorter: (a, b) => a._id.localeCompare(b._id) } ] if (showOwnerColumn) { columns.push( { title: 'Owner Name', dataIndex: ['owner', 'name'], key: 'name', width: 200, sorter: (a, b) => (a.owner?.name || '').localeCompare(b.owner?.name || '') }, { title: 'Owner', key: 'owner', width: 180, render: (record) => ( ) } ) } if (showTargetColumn) { columns.push({ title: 'Target', key: 'target', width: 180, render: (record) => ( ) }) } columns.push({ title: 'Properties', dataIndex: 'type', key: 'type', width: 550, render: (_, record) => { const oldValue = record.oldValue || {} const newValue = record.newValue || {} return ( {Object.keys(newValue).map((key) => ( {formatValue(oldValue[key], key)} {formatValue(newValue[key], key)} ))} ) } }) columns.push({ title: 'Timestamp', dataIndex: 'createdAt', key: 'createdAt', width: 180, defaultSortOrder: 'descend', sorter: (a, b) => new Date(a.createdAt) - new Date(b.createdAt), render: (createdAt) => { if (createdAt) { return } else { return 'n/a' } } }) return ( }} pagination={false} scroll={{ x: 'max-content' }} onChange={handleChange} sortDirections={['ascend', 'descend']} sortOrder={ sortedInfo.columnKey === 'createdAt' ? sortedInfo.order : null } /> ) } ) AuditLogTable.displayName = 'AuditLogTable' AuditLogTable.propTypes = { items: PropTypes.arrayOf(PropTypes.object).isRequired, loading: PropTypes.bool, showTargetColumn: PropTypes.bool, showOwnerColumn: PropTypes.bool } AuditLogTable.defaultProps = { loading: false, showTargetColumn: true, showOwnerColumn: true } export default AuditLogTable