Tom Butcher cb49baaf93 Enhance LoadingPlaceholder and Object Components with Lazy Loading Support
- Updated LoadingPlaceholder to accept new props for border and height customization, improving flexibility in loading states.
- Integrated lazy loading functionality across ObjectCard, ObjectKanban, ObjectKanbanColumn, ObjectKanbanHeader, and ObjectTable components, enhancing user experience during data fetching.
- Adjusted rendering logic in ObjectTable to display LoadingPlaceholder when data is being fetched, providing clearer visual feedback to users.
- Refactored prop types in relevant components to include lazy loading options, ensuring consistent API across components.
2026-09-03 03:53:31 +01:00

188 lines
5.0 KiB
JavaScript

import { Descriptions, Card, Flex, Divider, Skeleton } from 'antd'
import PropTypes from 'prop-types'
import ObjectProperty from './ObjectProperty'
import { createElement } from 'react'
import Thumbnail from './Thumbnail'
import { LoadingOutlined } from '@ant-design/icons'
const ObjectCard = ({
isSkeleton = false,
model,
modelProperties,
visibleColumns = {},
record,
isEditing = false,
rowActions = [],
renderActions,
lazyLoading = false,
cardStyle = 'borderless'
}) => {
const descriptionItems = []
const modelIcon = createElement(model.icon, { style: { fontSize: 24 } })
const thumbnailProperty =
model.properties.find((p) => p.thumbnail === true) || null
const thumbnailPresent =
thumbnailProperty !== null && record?.[thumbnailProperty.name]?._id
model.columns.forEach((colName) => {
const prop = modelProperties.find((p) => p.name === colName)
if (prop) {
if (
(Object.keys(visibleColumns).length > 0 &&
visibleColumns[prop.name] === false) ||
prop.name == 'name' ||
(prop.name == 'state' && visibleColumns?.name == true) ||
(thumbnailPresent && prop.name === thumbnailProperty.name)
) {
return
}
descriptionItems.push({
key: prop.name,
label: prop.label,
span: 2,
children: isSkeleton ? (
<Skeleton.Input active size='small' style={{ height: '24px' }} />
) : (
<ObjectProperty
{...prop}
longId={false}
objectData={record}
isEditing={isEditing}
name={prop.name}
/>
)
})
}
})
var actions = undefined
if (rowActions.length > 0) {
actions = renderActions(record, lazyLoading)
}
const primaryDescriptionItems = thumbnailPresent
? descriptionItems.slice(0, 2)
: []
const remainingDescriptionItems = thumbnailPresent
? descriptionItems.slice(2)
: descriptionItems
const nameContent = (
<>
<Flex align='center' gap={12} style={{ minWidth: 0 }}>
{modelIcon}
<ObjectProperty
{...model.properties.find((p) => p.name === 'name')}
objectData={record}
isEditing={isEditing}
style={{
fontSize: 20,
fontWeight: '600',
lineHeight: 1.2,
minWidth: 0
}}
/>
{visibleColumns?.state == true && (
<ObjectProperty
{...model.properties.find((p) => p.name === 'state')}
objectData={record}
/>
)}
</Flex>
</>
)
return (
<Card
styles={{ body: { padding: 18 } }}
style={{ width: '100%' }}
variant={cardStyle}
>
<Flex gap={6} vertical>
{thumbnailPresent && (
<Flex gap={14}>
<Thumbnail
file={{
_id: record?.[thumbnailProperty.name]?._id,
type: 'image'
}}
style={{
width: 84,
height: 84,
marginBottom: 4
}}
size={128}
/>
<Flex vertical gap={10} style={{ minWidth: 0 }}>
{visibleColumns?.name == true && nameContent}
{primaryDescriptionItems.length > 0 && (
<Descriptions
column={1}
size='small'
style={{ width: '100%', tableLayout: 'fixed' }}
className='objectTableDescritions'
items={primaryDescriptionItems}
/>
)}
</Flex>
</Flex>
)}
<Flex vertical gap={8}>
{visibleColumns?.name == true && !thumbnailPresent && nameContent}
{remainingDescriptionItems.length > 0 && (
<Descriptions
column={1}
size='small'
style={{
width: '100%',
tableLayout: 'fixed'
}}
className='objectTableDescritions'
items={remainingDescriptionItems}
/>
)}
{actions && (
<>
<Divider style={{ margin: '4px 0 0 0' }} />
<Flex
align='center'
gap={10}
style={{ width: '100%' }}
justify='space-between'
>
<Flex align='center' gap={10}>
{actions}
</Flex>
{lazyLoading && (
<LoadingOutlined spin style={{ marginRight: 4 }} />
)}
</Flex>
</>
)}
</Flex>
</Flex>
</Card>
)
}
ObjectCard.propTypes = {
model: PropTypes.object.isRequired,
modelProperties: PropTypes.array.isRequired,
visibleColumns: PropTypes.object,
record: PropTypes.object.isRequired,
isEditing: PropTypes.bool,
rowActions: PropTypes.array,
renderActions: PropTypes.func.isRequired,
cardStyle: PropTypes.string,
isSkeleton: PropTypes.bool,
lazyLoading: PropTypes.bool
}
export default ObjectCard