diff --git a/src/components/Dashboard/common/ObjectChildTable.jsx b/src/components/Dashboard/common/ObjectChildTable.jsx
index 9aa43c4..c58b9ba 100644
--- a/src/components/Dashboard/common/ObjectChildTable.jsx
+++ b/src/components/Dashboard/common/ObjectChildTable.jsx
@@ -3,8 +3,11 @@ import PropTypes from 'prop-types'
import { Table, Skeleton, Card, Button, Flex, Typography, Modal } from 'antd'
import PlusIcon from '../../Icons/PlusIcon'
import ObjectProperty from './ObjectProperty'
+import ObjectInfo from './ObjectInfo'
import { LoadingOutlined } from '@ant-design/icons'
import BinIcon from '../../Icons/BinIcon'
+import EyeIcon from '../../Icons/EyeIcon'
+import EditIcon from '../../Icons/EditIcon'
const { Text, Link, Title } = Typography
const DEFAULT_COLUMN_WIDTHS = {
@@ -64,6 +67,7 @@ const ObjectChildTable = ({
value = [],
rollups = [],
onChange,
+ hiddenPropertyWidth = '300px',
minimal = false,
label = '',
...tableProps
@@ -73,6 +77,9 @@ const ObjectChildTable = ({
const generatedRowKeysRef = useRef(new WeakMap())
const generatedRowKeyCountRef = useRef(0)
const [minimalModelOpen, setMinimalModelOpen] = useState(false)
+ const [detailModalOpen, setDetailModalOpen] = useState(false)
+ const [detailModalRecord, setDetailModalRecord] = useState(null)
+ const [detailModalIndex, setDetailModalIndex] = useState(null)
const getFallbackRowKey = (record) => {
if (!record || typeof record !== 'object') {
return `object-child-table-row-${String(record)}`
@@ -124,15 +131,14 @@ const ObjectChildTable = ({
}, [columns, properties])
const resolvedProperties = useMemo(() => {
- const explicit = orderedPropertyNames
- .map((name) => propertyMap.get(name))
- .filter(Boolean)
+ const baseProperties =
+ columns && columns.length > 0
+ ? orderedPropertyNames
+ .map((name) => propertyMap.get(name))
+ .filter(Boolean)
+ : properties
- const remaining = properties.filter(
- (property) => !orderedPropertyNames.includes(property.name)
- )
-
- return [...explicit, ...remaining].filter((property) => {
+ return baseProperties.filter((property) => {
if (!property?.name) return false
if (
visibleColumns &&
@@ -142,13 +148,87 @@ const ObjectChildTable = ({
}
return true
})
- }, [orderedPropertyNames, propertyMap, properties, visibleColumns])
+ }, [columns, orderedPropertyNames, propertyMap, properties, visibleColumns])
+
+ const hasHiddenProperties = useMemo(() => {
+ return (
+ Array.isArray(columns) &&
+ columns.length > 0 &&
+ Array.isArray(properties) &&
+ columns.length < properties.length
+ )
+ }, [columns, properties])
// When used inside antd Form.Item without Form.List, `value` will be the controlled array.
const itemsSource = useMemo(() => {
return value ?? []
}, [value])
+ const handleRemoveItem = useCallback(
+ (record, index) => {
+ const currentItems = Array.isArray(itemsSource) ? itemsSource : []
+
+ let newItems
+ if (typeof rowKey === 'string' && record[rowKey] != null) {
+ newItems = currentItems.filter(
+ (item) => item[rowKey] !== record[rowKey]
+ )
+ } else if (typeof rowKey === 'function') {
+ const recordKey = getResolvedRecordKey(record)
+ newItems = currentItems.filter((item) => {
+ const itemKey = getResolvedRecordKey(item)
+ return itemKey !== recordKey
+ })
+ } else {
+ newItems = currentItems.filter((_, i) => i !== index)
+ }
+
+ if (typeof onChange === 'function') {
+ onChange(newItems)
+ }
+ },
+ [itemsSource, onChange, rowKey, getResolvedRecordKey]
+ )
+
+ const handleOpenDetailModal = useCallback((record, index) => {
+ setDetailModalRecord({ ...record })
+ setDetailModalIndex(index)
+ setDetailModalOpen(true)
+ }, [])
+
+ const handleDetailPropertyChange = useCallback(
+ (propName, newVal) => {
+ const property = propertyMap.get(propName)
+ const resolved = resolveChangeValue(newVal, property?.type)
+
+ setDetailModalRecord((prev) =>
+ prev ? { ...prev, [propName]: resolved } : prev
+ )
+
+ if (detailModalIndex == null) return
+
+ const currentItems = Array.isArray(itemsSource) ? [...itemsSource] : []
+ const existingRowKey =
+ currentItems[detailModalIndex] != null
+ ? getResolvedRecordKey(currentItems[detailModalIndex])
+ : null
+ const updatedItem = {
+ ...currentItems[detailModalIndex],
+ [propName]: resolved
+ }
+
+ if (existingRowKey) {
+ generatedRowKeysRef.current.set(updatedItem, existingRowKey)
+ }
+
+ currentItems[detailModalIndex] = updatedItem
+ if (typeof onChange === 'function') {
+ onChange(currentItems)
+ }
+ },
+ [propertyMap, detailModalIndex, itemsSource, onChange, getResolvedRecordKey]
+ )
+
const tableColumns = useMemo(() => {
const propertyColumns = resolvedProperties.map((property) => ({
title: property.label || property.name,
@@ -197,54 +277,44 @@ const ObjectChildTable = ({
}
}))
- const deleteColumn =
- isEditing && canAddRemove
+ const actionsColumn =
+ hasHiddenProperties || (isEditing && canAddRemove)
? {
title: '',
- key: 'delete',
- width: 10,
+ key: 'actions',
+ width: hasHiddenProperties && isEditing && canAddRemove ? 70 : 40,
fixed: 'right',
render: (_text, record, index) => {
if (record?.isSkeleton) {
return null
}
+
return (
- }
- onClick={(e) => {
- e.stopPropagation()
- const currentItems = Array.isArray(itemsSource)
- ? itemsSource
- : []
-
- // Use record's unique identifier if available, otherwise use index
- let newItems
- if (typeof rowKey === 'string' && record[rowKey] != null) {
- // Use the unique key to find and remove the item
- newItems = currentItems.filter(
- (item) => item[rowKey] !== record[rowKey]
- )
- } else if (typeof rowKey === 'function') {
- // If rowKey is a function, find the item by comparing resolved keys.
- // Ant Design deprecates index-based rowKey callbacks.
- const recordKey = getResolvedRecordKey(record)
- newItems = currentItems.filter((item) => {
- const itemKey = getResolvedRecordKey(item)
- return itemKey !== recordKey
- })
- } else {
- // Fallback to index-based removal
- newItems = currentItems.filter((_, i) => i !== index)
- }
-
- if (typeof onChange === 'function') {
- onChange(newItems)
- }
- }}
- />
+
+ {hasHiddenProperties && (
+ : }
+ onClick={(e) => {
+ e.stopPropagation()
+ handleOpenDetailModal(record, index)
+ }}
+ />
+ )}
+ {isEditing && canAddRemove && (
+ }
+ onClick={(e) => {
+ e.stopPropagation()
+ handleRemoveItem(record, index)
+ }}
+ />
+ )}
+
)
}
}
@@ -253,17 +323,20 @@ const ObjectChildTable = ({
return [
...propertyColumns,
...additionalColumns,
- ...(deleteColumn ? [deleteColumn] : [])
+ ...(actionsColumn ? [actionsColumn] : [])
]
}, [
resolvedProperties,
additionalColumns,
+ hasHiddenProperties,
isEditing,
canAddRemove,
itemsSource,
onChange,
rowKey,
- getResolvedRecordKey
+ getResolvedRecordKey,
+ handleOpenDetailModal,
+ handleRemoveItem
])
const skeletonData = useMemo(() => {
@@ -351,8 +424,8 @@ const ObjectChildTable = ({
}, [properties, rollups, objectData, value, name])
const rollupColumns = useMemo(() => {
- const propertyColumns = properties.map((property, index) => {
- const nextProperty = properties[index + 1]
+ const propertyColumns = resolvedProperties.map((property, index) => {
+ const nextProperty = resolvedProperties[index + 1]
var nextRollup = null
if (nextProperty) {
nextRollup = rollups?.find(
@@ -384,12 +457,12 @@ const ObjectChildTable = ({
}
}
})
- const blankDeleteColumn =
- isEditing && canAddRemove
+ const blankActionsColumn =
+ hasHiddenProperties || (isEditing && canAddRemove)
? {
title: '',
- key: 'delete',
- width: 40,
+ key: 'actions',
+ width: hasHiddenProperties && isEditing && canAddRemove ? 70 : 40,
fixed: 'right',
render: () => {
return
@@ -398,9 +471,15 @@ const ObjectChildTable = ({
: null
return [
...propertyColumns,
- ...(blankDeleteColumn ? [blankDeleteColumn] : [])
+ ...(blankActionsColumn ? [blankActionsColumn] : [])
]
- }, [properties, rollups, isEditing, canAddRemove])
+ }, [
+ resolvedProperties,
+ rollups,
+ isEditing,
+ canAddRemove,
+ hasHiddenProperties
+ ])
const hasRollups = useMemo(
() => Array.isArray(rollups) && rollups.length > 0,
@@ -495,25 +574,56 @@ const ObjectChildTable = ({
)
+ const detailModal = hasHiddenProperties ? (
+ setDetailModalOpen(false)}
+ footer={null}
+ width='900px'
+ >
+ {label ? (
+
+ {label}
+
+ ) : null}
+
+
+ ) : null
+
if (isEditing === true) {
return (
-
-
-
-
+ <>
+
+
+
+
- {canAddRemove && (
- }
- onClick={handleAddItem}
- />
- )}
+ {canAddRemove && (
+ }
+ onClick={handleAddItem}
+ />
+ )}
+
+
+ {tableComponent}
-
- {tableComponent}
-
-
+
+ {detailModal}
+ >
)
}
@@ -541,11 +651,17 @@ const ObjectChildTable = ({
{tableComponent}
+ {detailModal}
>
)
}
- return tableComponent
+ return (
+ <>
+ {tableComponent}
+ {detailModal}
+ >
+ )
}
ObjectChildTable.propTypes = {
@@ -574,7 +690,8 @@ ObjectChildTable.propTypes = {
rollups: PropTypes.arrayOf(PropTypes.object),
objectData: PropTypes.object,
canAddRemove: PropTypes.bool,
- minimal: PropTypes.bool
+ minimal: PropTypes.bool,
+ hiddenPropertyWidth: PropTypes.string
}
export default ObjectChildTable