Improved card design for object table.
This commit is contained in:
parent
4f0fe89398
commit
b4512a1948
@ -11,7 +11,7 @@ const EmailDisplay = ({ email, showCopy = true, showLink = false }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex>
|
||||
<Flex style={{ minWidth: 0 }}>
|
||||
{showLink ? (
|
||||
<Link href={`mailto:${email}`} style={{ marginRight: 8 }}>
|
||||
{email}
|
||||
|
||||
111
src/components/Dashboard/common/ObjectCard.jsx
Normal file
111
src/components/Dashboard/common/ObjectCard.jsx
Normal file
@ -0,0 +1,111 @@
|
||||
import { Descriptions, Card, Flex, Divider } from 'antd'
|
||||
import PropTypes from 'prop-types'
|
||||
import ObjectProperty from './ObjectProperty'
|
||||
import { createElement } from 'react'
|
||||
|
||||
const ObjectCard = ({
|
||||
model,
|
||||
modelProperties,
|
||||
visibleColumns = {},
|
||||
record,
|
||||
isEditing = false,
|
||||
rowActions = [],
|
||||
renderActions,
|
||||
cardStyle = 'borderless'
|
||||
}) => {
|
||||
const descriptionItems = []
|
||||
const modelIcon = createElement(model.icon, { style: { fontSize: 24 } })
|
||||
|
||||
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'
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
descriptionItems.push(
|
||||
<Descriptions.Item label={prop.label} key={prop.name} colspan={2}>
|
||||
<ObjectProperty
|
||||
{...prop}
|
||||
longId={false}
|
||||
objectData={record}
|
||||
isEditing={isEditing}
|
||||
name={prop.name}
|
||||
/>
|
||||
</Descriptions.Item>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
var actions = undefined
|
||||
|
||||
if (rowActions.length > 0) {
|
||||
actions = renderActions(record)
|
||||
}
|
||||
|
||||
return (
|
||||
<Card
|
||||
styles={{ body: { padding: 18 } }}
|
||||
style={{ width: '100%' }}
|
||||
variant={cardStyle}
|
||||
>
|
||||
<Flex vertical gap={8}>
|
||||
{visibleColumns?.name == true && (
|
||||
<Flex align='center' gap={12}>
|
||||
{modelIcon}
|
||||
<ObjectProperty
|
||||
{...model.properties.find((p) => p.name === 'name')}
|
||||
objectData={record}
|
||||
isEditing={isEditing}
|
||||
style={{
|
||||
fontSize: 20,
|
||||
fontWeight: '600',
|
||||
lineHeight: 1,
|
||||
overflow: 'visible'
|
||||
}}
|
||||
/>
|
||||
{visibleColumns?.state == true && (
|
||||
<ObjectProperty
|
||||
{...model.properties.find((p) => p.name === 'state')}
|
||||
objectData={record}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
)}
|
||||
<Descriptions
|
||||
column={1}
|
||||
size='small'
|
||||
style={{ width: '100%', tableLayout: 'fixed' }}
|
||||
className='objectTableDescritions'
|
||||
>
|
||||
{descriptionItems}
|
||||
</Descriptions>
|
||||
{actions && (
|
||||
<>
|
||||
<Divider style={{ margin: '2px 0 0 0' }} />
|
||||
<Flex align='flex-end' gap={10}>
|
||||
{actions}
|
||||
</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
|
||||
}
|
||||
|
||||
export default ObjectCard
|
||||
@ -92,6 +92,7 @@ const ObjectProperty = ({
|
||||
loading = false,
|
||||
rollups = [],
|
||||
showCard = true,
|
||||
style = {},
|
||||
...rest
|
||||
}) => {
|
||||
if (value && typeof value == 'function' && objectData) {
|
||||
@ -310,7 +311,7 @@ const ObjectProperty = ({
|
||||
case 'text':
|
||||
if (value != null && value != '') {
|
||||
return (
|
||||
<Text ellipsis>
|
||||
<Text ellipsis style={style}>
|
||||
{prefix}
|
||||
{value}
|
||||
{suffix}
|
||||
@ -888,7 +889,8 @@ ObjectProperty.propTypes = {
|
||||
loading: PropTypes.bool,
|
||||
rollups: PropTypes.arrayOf(PropTypes.object),
|
||||
canAddRemove: PropTypes.bool,
|
||||
showCard: PropTypes.bool
|
||||
showCard: PropTypes.bool,
|
||||
style: PropTypes.object
|
||||
}
|
||||
|
||||
export default ObjectProperty
|
||||
|
||||
@ -11,10 +11,8 @@ import {
|
||||
import {
|
||||
Table,
|
||||
Skeleton,
|
||||
Card,
|
||||
Row,
|
||||
Col,
|
||||
Descriptions,
|
||||
Flex,
|
||||
Spin,
|
||||
Button,
|
||||
@ -35,6 +33,7 @@ import {
|
||||
getModelByName
|
||||
} from '../../../database/ObjectModels'
|
||||
import ObjectProperty from './ObjectProperty'
|
||||
import ObjectCard from './ObjectCard'
|
||||
import FilterSidebar from './FilterSidebar'
|
||||
import XMarkIcon from '../../Icons/XMarkIcon'
|
||||
import CheckIcon from '../../Icons/CheckIcon'
|
||||
@ -128,7 +127,7 @@ const ObjectTable = forwardRef(
|
||||
adjustedScrollHeight = 'calc(var(--unit-100vh) - 316px)'
|
||||
}
|
||||
if (cards) {
|
||||
adjustedScrollHeight = 'calc(var(--unit-100vh) - 280px)'
|
||||
adjustedScrollHeight = 'calc(var(--unit-100vh) - 210px)'
|
||||
}
|
||||
if (isElectron) {
|
||||
adjustedScrollHeight = 'calc(var(--unit-100vh) - 244px)'
|
||||
@ -857,78 +856,25 @@ const ObjectTable = forwardRef(
|
||||
>
|
||||
{tableData.map((record) => (
|
||||
<Col xs={24} sm={12} md={12} lg={8} xl={6} xxl={6} key={record._id}>
|
||||
<Card
|
||||
style={{ width: '100%', overflow: 'hidden' }}
|
||||
styles={{ body: { padding: 0 } }}
|
||||
loading={record.isSkeleton}
|
||||
variant={'borderless'}
|
||||
>
|
||||
<div style={{ width: '100%', overflow: 'hidden' }}>
|
||||
<RowForm
|
||||
record={record}
|
||||
isEditing={isEditing}
|
||||
onRegister={registerForm}
|
||||
>
|
||||
<Flex align={'center'} vertical gap={'middle'}>
|
||||
<Descriptions
|
||||
column={1}
|
||||
size='small'
|
||||
bordered={true}
|
||||
style={{ width: '100%', tableLayout: 'fixed' }}
|
||||
className='objectTableDescritions'
|
||||
>
|
||||
{(() => {
|
||||
const descriptionItems = []
|
||||
|
||||
// Add columns in the order specified by model.columns (same logic as table)
|
||||
model.columns.forEach((colName) => {
|
||||
const prop = modelProperties.find(
|
||||
(p) => p.name === colName
|
||||
)
|
||||
if (prop) {
|
||||
// Check if column should be visible based on visibleColumns prop
|
||||
if (
|
||||
Object.keys(visibleColumns).length > 0 &&
|
||||
visibleColumns[prop.name] === false
|
||||
) {
|
||||
return // Skip this column if it's not visible
|
||||
}
|
||||
|
||||
descriptionItems.push(
|
||||
<Descriptions.Item
|
||||
label={prop.label}
|
||||
key={prop.name}
|
||||
colspan={2}
|
||||
>
|
||||
<ObjectProperty
|
||||
{...prop}
|
||||
longId={false}
|
||||
objectData={record}
|
||||
isEditing={isEditing}
|
||||
name={prop.name}
|
||||
/>
|
||||
</Descriptions.Item>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
// Add actions if they exist (same as table)
|
||||
if (rowActions.length > 0) {
|
||||
descriptionItems.push(
|
||||
<Descriptions.Item
|
||||
label={'Actions'}
|
||||
key={'actions'}
|
||||
>
|
||||
{renderActions(record)}
|
||||
</Descriptions.Item>
|
||||
)
|
||||
}
|
||||
|
||||
return descriptionItems
|
||||
})()}
|
||||
</Descriptions>
|
||||
<ObjectCard
|
||||
model={model}
|
||||
modelProperties={modelProperties}
|
||||
visibleColumns={visibleColumns}
|
||||
record={record}
|
||||
isEditing={isEditing}
|
||||
rowActions={rowActions}
|
||||
renderActions={renderActions}
|
||||
/>
|
||||
</Flex>
|
||||
</RowForm>
|
||||
</Card>
|
||||
</div>
|
||||
</Col>
|
||||
))}
|
||||
</Row>
|
||||
@ -955,28 +901,29 @@ const ObjectTable = forwardRef(
|
||||
|
||||
const tableContent = (
|
||||
<Flex gap={'middle'} vertical style={{ flex: 1, minWidth: 0 }}>
|
||||
<Table
|
||||
ref={tableRef}
|
||||
dataSource={tableData}
|
||||
columns={columnsWithSkeleton}
|
||||
className={cards ? 'dashboard-cards-header' : 'dashboard-table'}
|
||||
pagination={false}
|
||||
scroll={{ y: adjustedScrollHeight }}
|
||||
rowKey='_id'
|
||||
loading={{ spinning: loading, indicator: <LoadingOutlined spin /> }}
|
||||
onScroll={handleScroll}
|
||||
onChange={handleTableChange}
|
||||
showSorterTooltip={false}
|
||||
style={{ height: '100%' }}
|
||||
size={size}
|
||||
components={components}
|
||||
onRow={onRow}
|
||||
/>
|
||||
{cards ? (
|
||||
<Spin indicator={<LoadingOutlined />} spinning={loading}>
|
||||
{renderCards()}
|
||||
</Spin>
|
||||
) : null}
|
||||
) : (
|
||||
<Table
|
||||
ref={tableRef}
|
||||
dataSource={tableData}
|
||||
columns={columnsWithSkeleton}
|
||||
className='dashboard-table'
|
||||
pagination={false}
|
||||
scroll={{ y: adjustedScrollHeight }}
|
||||
rowKey='_id'
|
||||
loading={{ spinning: loading, indicator: <LoadingOutlined spin /> }}
|
||||
onScroll={handleScroll}
|
||||
onChange={handleTableChange}
|
||||
showSorterTooltip={false}
|
||||
style={{ height: '100%' }}
|
||||
size={size}
|
||||
components={components}
|
||||
onRow={onRow}
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user