import { Spin, Descriptions, Flex } from 'antd' import { useState, useEffect } from 'react' import { LoadingOutlined } from '@ant-design/icons' import PropTypes from 'prop-types' import ObjectProperty from './ObjectProperty' import { getModelProperties } from '../../../database/ObjectModels' import mergeWith from 'lodash/mergeWith' const arrayReplaceCustomizer = (objValue, srcValue) => { if (Array.isArray(srcValue)) { return srcValue } } const ObjectInfo = ({ loading = false, isEditing = false, type = 'unknown', showHyperlink, showLabels = true, objectData = null, parentData = null, properties = [], propertyDefinitions = null, onPropertyChange = null, required = undefined, visibleProperties = {}, objectPropertyProps = {}, labelWidth = '150px', column = { xs: 1, sm: 1, md: 1, lg: 2, xl: 2, xxl: 2 }, ...rest }) => { const allItems = getModelProperties(type) const [combinedObjectData, setCombinedObjectData] = useState(objectData) useEffect(() => { setCombinedObjectData((prev) => mergeWith({}, prev, objectData, arrayReplaceCustomizer) ) }, [objectData]) // If properties array is empty, show all properties // Otherwise, filter and order by the properties array let items if (Array.isArray(propertyDefinitions) && propertyDefinitions.length > 0) { items = propertyDefinitions } else if (properties.length === 0) { items = allItems } else { items = properties .map((propName) => allItems.find((item) => item.name === propName)) .filter(Boolean) } if (required != undefined) { items = items.filter((item) => item.required === required) } if (showHyperlink) { objectPropertyProps = { ...objectPropertyProps, showHyperlink } } // Filter items based on visibleProperties // If all values in visibleProperties are true, use whitelist mode // Otherwise, use blacklist mode (hide properties set to false) const visibleValues = Object.values(visibleProperties) const isWhitelistMode = visibleValues.length > 0 && visibleValues.every((value) => value === true) items = items.filter((item) => { const propertyName = item.name // Support property.visible as a function (objectData) => boolean if (typeof item.visible === 'function') { const visible = item.visible(objectData || combinedObjectData || {}) if (!visible) return false } if (isWhitelistMode) { // Whitelist mode: only show properties that are explicitly set to true return visibleProperties[propertyName] === true } else { // Blacklist mode: hide properties that are explicitly set to false return !( propertyName in visibleProperties && visibleProperties[propertyName] === false ) } }) const isControlled = typeof onPropertyChange === 'function' // Map items to Descriptions 'items' prop format const descriptionItems = items.map((item, idx) => { const key = item.name || item.label || idx return { key, label: showLabels == true ? ( {item.label} ) : null, children: (
onPropertyChange(item.name, newVal) : objectPropertyProps.onChange } />
), span: item?.span || undefined } }) return ( }> ) } ObjectInfo.propTypes = { loading: PropTypes.bool, column: PropTypes.object, showHyperlink: PropTypes.bool, showLabels: PropTypes.bool, indicator: PropTypes.node, properties: PropTypes.array, bordered: PropTypes.bool, items: PropTypes.arrayOf(PropTypes.object), isEditing: PropTypes.bool, type: PropTypes.string, objectData: PropTypes.object, parentData: PropTypes.object, propertyDefinitions: PropTypes.array, onPropertyChange: PropTypes.func, required: PropTypes.bool, visibleProperties: PropTypes.object, objectPropertyProps: PropTypes.object, labelWidth: PropTypes.string } export default ObjectInfo