import React, { useContext, useRef } from 'react' import { Button, Flex, Space, Typography, Popover, Checkbox, Dropdown, Descriptions, Input, Badge } from 'antd' import { AuthContext } from '../context/AuthContext' import IdDisplay from '../common/IdDisplay' import ReloadIcon from '../../Icons/ReloadIcon' import useColumnVisibility from '../hooks/useColumnVisibility' import TimeDisplay from '../common/TimeDisplay' import DashboardTable from '../common/DashboardTable' import config from '../../../config' import AuditLogIcon from '../../Icons/AuditLogIcon' import XMarkIcon from '../../Icons/XMarkIcon' import CheckIcon from '../../Icons/CheckIcon' import BoolDisplay from '../common/BoolDisplay' import StateTag from '../common/StateTag' 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' && value) { return } if (propertyName === 'state' && typeof value === 'object' && value.type) { return } // 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') { return } if (isObjectId(value)) { return ( ) } if (typeof value === 'object') { return {JSON.stringify(value)} } return {value} } const AuditLogs = () => { const tableRef = useRef() // Column definitions const columns = [ { title: '', dataIndex: '', key: '', width: 40, fixed: 'left', render: () => }, { title: 'ID', dataIndex: '_id', key: 'id', fixed: 'left', width: 180, render: (text) => ( ), filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => getFilterDropdown({ setSelectedKeys, selectedKeys, confirm, clearFilters, propertyName: 'ID' }), onFilter: (value, record) => record._id.toLowerCase().includes(value.toLowerCase()), sorter: true }, { title: 'Owner Name', dataIndex: ['owner', 'name'], key: 'name', width: 200, fixed: 'left', filterDropdown: ({ setSelectedKeys, selectedKeys, confirm, clearFilters }) => getFilterDropdown({ setSelectedKeys, selectedKeys, confirm, clearFilters, propertyName: 'name' }), onFilter: (value, record) => record.owner?.name?.toLowerCase().includes(value.toLowerCase()), sorter: true }, { title: 'Owner', key: 'owner', width: 180, render: (record) => ( ) }, { title: 'Target', key: 'target', width: 180, render: (record) => ( ) }, { 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)} ))} ) } }, { title: 'Timestamp', dataIndex: 'createdAt', key: 'createdAt', width: 180, fixed: 'right', render: (createdAt) => { if (createdAt) { return } else { return 'n/a' } }, sorter: true, defaultSortOrder: 'descend' } ] const getFilterDropdown = ({ setSelectedKeys, selectedKeys, confirm, clearFilters, propertyName }) => { return (
setSelectedKeys(e.target.value ? [e.target.value] : []) } onPressEnter={() => confirm()} style={{ width: 200, display: 'block' }} />
) } const [columnVisibility, updateColumnVisibility] = useColumnVisibility( 'AuditLogs', columns ) const { authenticated } = useContext(AuthContext) const actionItems = { items: [ { label: 'Reload List', key: 'reloadList', icon: } ], onClick: ({ key }) => { if (key === 'reloadList') { tableRef.current?.reload() } } } const getViewDropdownItems = () => { const columnItems = columns .filter((col) => col.key && col.title !== '') .map((col) => ( { updateColumnVisibility(col.key, e.target.checked) }} > {col.title} )) return ( {columnItems} ) } const visibleColumns = columns.filter( (col) => !col.key || columnVisibility[col.key] ) return ( <> ) } export default AuditLogs