All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Added an `isSkeleton` prop to ObjectCard for conditional rendering of skeleton loaders, improving user experience during data fetching. - Updated ObjectTable to manage skeleton boundaries, allowing for dynamic loading of pages based on visibility of skeleton cards. - Refactored scroll handling in ObjectTable to utilize IntersectionObserver for better performance and responsiveness.
173 lines
4.6 KiB
JavaScript
173 lines
4.6 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'
|
|
|
|
const ObjectCard = ({
|
|
isSkeleton = false,
|
|
model,
|
|
modelProperties,
|
|
visibleColumns = {},
|
|
record,
|
|
isEditing = false,
|
|
rowActions = [],
|
|
renderActions,
|
|
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)
|
|
}
|
|
|
|
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='flex-end' gap={10}>
|
|
{actions}
|
|
</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
|
|
}
|
|
|
|
export default ObjectCard
|