Enhance SpotlightTooltip Component and Update Styles
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good
- Refactored SpotlightTooltip component to improve action handling and data rendering. - Introduced new utility functions for value checking and nested property access. - Updated rendering logic to utilize ObjectCard for better display of spotlight data. - Added CSS styles for spotlight tooltip to ensure a transparent background.
This commit is contained in:
parent
3544ac0d89
commit
f0b0ad41a6
@ -484,6 +484,11 @@ code {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.spotlight-tooltip.ant-card,
|
||||
.spotlight-tooltip .ant-card {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.ant-popover:has(.spotlight-tooltip) {
|
||||
z-index: 1051;
|
||||
}
|
||||
|
||||
@ -1,34 +1,102 @@
|
||||
// SpotlightTooltip.js
|
||||
import PropTypes from 'prop-types'
|
||||
import { Descriptions, Card, Flex, Typography, Skeleton, Spin } from 'antd'
|
||||
import { LoadingOutlined } from '@ant-design/icons'
|
||||
import { useEffect, useState, useContext, useCallback } from 'react'
|
||||
import { Button, Card, Flex, Typography } from 'antd'
|
||||
import {
|
||||
createElement,
|
||||
useEffect,
|
||||
useState,
|
||||
useContext,
|
||||
useCallback,
|
||||
useMemo
|
||||
} from 'react'
|
||||
import { AuthContext } from '../context/AuthContext'
|
||||
import ObjectProperty from './ObjectProperty'
|
||||
import { useActions } from '../context/ActionsContext'
|
||||
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
|
||||
import QuestionCircleIcon from '../../Icons/QuestionCircleIcon'
|
||||
import { ApiServerContext } from '../context/ApiServerContext'
|
||||
import merge from 'lodash/merge'
|
||||
import {
|
||||
getModelByName,
|
||||
getModelProperty
|
||||
} from '../../../database/ObjectModels'
|
||||
import { getModelByName } from '../../../database/ObjectModels'
|
||||
import { hasActionPermission } from '../../../database/permissions'
|
||||
import ObjectCard from './ObjectCard'
|
||||
import Tooltip from './Tooltip'
|
||||
|
||||
const { Text } = Typography
|
||||
|
||||
const hasValue = (value) => value !== undefined && value !== null && value !== ''
|
||||
|
||||
const getNestedValue = (obj, path) => {
|
||||
return path.split('.').reduce((current, key) => current?.[key], obj)
|
||||
}
|
||||
|
||||
const SpotlightTooltip = ({ query, type }) => {
|
||||
const [spotlightData, setSpotlightData] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [initialized, setInitialized] = useState(false)
|
||||
|
||||
const { token } = useContext(AuthContext)
|
||||
const { token, userProfile } = useContext(AuthContext)
|
||||
const { callAction } = useActions()
|
||||
const { fetchSpotlightData, subscribeToObjectUpdates, connected } =
|
||||
useContext(ApiServerContext)
|
||||
|
||||
// Get the model for this type
|
||||
const model = getModelByName(type)
|
||||
const modelProperties = model.properties || []
|
||||
const rowActions = useMemo(
|
||||
() => model.actions?.filter((action) => action.row == true) || [],
|
||||
[model]
|
||||
)
|
||||
|
||||
const renderActions = useCallback(
|
||||
(objectData, actionsDisabled = false) => {
|
||||
return (
|
||||
<Flex gap='small' align='center' justify='center'>
|
||||
{rowActions.map((action, index) => {
|
||||
const denied = !hasActionPermission(userProfile, model, action.name)
|
||||
var disabled = denied
|
||||
if (action.disabled) {
|
||||
if (typeof action.disabled === 'function') {
|
||||
disabled =
|
||||
denied ||
|
||||
action.disabled({
|
||||
...objectData,
|
||||
_user: userProfile
|
||||
}) ||
|
||||
actionsDisabled
|
||||
} else {
|
||||
disabled = denied || action.disabled || actionsDisabled
|
||||
}
|
||||
}
|
||||
return (
|
||||
<Tooltip key={index} title={action.label}>
|
||||
<Button
|
||||
icon={
|
||||
action.icon ? (
|
||||
createElement(action.icon)
|
||||
) : (
|
||||
<QuestionCircleIcon />
|
||||
)
|
||||
}
|
||||
disabled={disabled || objectData?.isSkeleton}
|
||||
type={'text'}
|
||||
size={'small'}
|
||||
danger={action?.danger || false}
|
||||
onClick={() => {
|
||||
if (denied) return
|
||||
callAction(
|
||||
action,
|
||||
{ ...objectData, _user: userProfile },
|
||||
type
|
||||
)
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
)
|
||||
})}
|
||||
</Flex>
|
||||
)
|
||||
},
|
||||
[callAction, model, rowActions, type, userProfile]
|
||||
)
|
||||
|
||||
// Update event handler
|
||||
const updateObjectEventHandler = useCallback((value) => {
|
||||
setSpotlightData((prev) => merge({}, prev, value))
|
||||
}, [])
|
||||
@ -47,7 +115,6 @@ const SpotlightTooltip = ({ query, type }) => {
|
||||
}
|
||||
}, [token, fetchSpotlight, initialized])
|
||||
|
||||
// Subscribe to object updates when component mounts
|
||||
useEffect(() => {
|
||||
if (spotlightData?._id && type && connected && token) {
|
||||
const objectUpdatesUnsubscribe = subscribeToObjectUpdates(
|
||||
@ -69,6 +136,28 @@ const SpotlightTooltip = ({ query, type }) => {
|
||||
updateObjectEventHandler
|
||||
])
|
||||
|
||||
const visibleColumns = useMemo(() => {
|
||||
const columnNames = model.columns || []
|
||||
const columns = { name: true }
|
||||
|
||||
if (!spotlightData) {
|
||||
columnNames.slice(0, 4).forEach((colName) => {
|
||||
columns[colName] = true
|
||||
})
|
||||
columnNames.forEach((colName) => {
|
||||
if (columns[colName] == null) columns[colName] = false
|
||||
})
|
||||
return columns
|
||||
}
|
||||
|
||||
for (const colName of columnNames) {
|
||||
if (colName === 'name') continue
|
||||
columns[colName] = hasValue(getNestedValue(spotlightData, colName))
|
||||
}
|
||||
|
||||
return columns
|
||||
}, [model.columns, spotlightData])
|
||||
|
||||
if (!spotlightData && !loading) {
|
||||
return (
|
||||
<Card className='spotlight-tooltip'>
|
||||
@ -87,68 +176,24 @@ const SpotlightTooltip = ({ query, type }) => {
|
||||
)
|
||||
}
|
||||
|
||||
// Helper to get nested property value
|
||||
const getNestedValue = (obj, path) => {
|
||||
return path.split('.').reduce((current, key) => current?.[key], obj)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='spotlight-tooltip'>
|
||||
<Spin indicator={<LoadingOutlined />} spinning={loading}>
|
||||
<Descriptions bordered column={1} size='small'>
|
||||
{loading ? (
|
||||
<>
|
||||
<Descriptions.Item
|
||||
label={
|
||||
<Skeleton.Input active size='small' style={{ width: 80 }} />
|
||||
}
|
||||
>
|
||||
<Skeleton.Input active size='small' style={{ width: 120 }} />
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={
|
||||
<Skeleton.Input active size='small' style={{ width: 80 }} />
|
||||
}
|
||||
>
|
||||
<Skeleton.Input active size='small' style={{ width: 120 }} />
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item
|
||||
label={
|
||||
<Skeleton.Input active size='small' style={{ width: 80 }} />
|
||||
}
|
||||
>
|
||||
<Skeleton.Input active size='small' style={{ width: 120 }} />
|
||||
</Descriptions.Item>
|
||||
</>
|
||||
) : (
|
||||
modelProperties
|
||||
.filter((prop) => {
|
||||
const value = getNestedValue(spotlightData, prop.name)
|
||||
return value !== undefined && value !== null && value !== ''
|
||||
})
|
||||
.map((prop) => {
|
||||
const value = getNestedValue(spotlightData, prop.name)
|
||||
return (
|
||||
<Descriptions.Item key={prop.name} label={prop.label}>
|
||||
<ObjectProperty
|
||||
{...getModelProperty(type, prop.name)}
|
||||
value={value}
|
||||
objectData={spotlightData}
|
||||
objectType={prop.objectType || type}
|
||||
isEditing={false}
|
||||
longId={false}
|
||||
showSpotlight={false}
|
||||
showLabel={false}
|
||||
showName={false}
|
||||
showId={false}
|
||||
showQuantity={false}
|
||||
/>
|
||||
</Descriptions.Item>
|
||||
)
|
||||
})
|
||||
)}
|
||||
</Descriptions>
|
||||
</Spin>
|
||||
<div className='spotlight-tooltip' style={{ width: 360 }}>
|
||||
<ObjectCard
|
||||
isSkeleton={!spotlightData && loading}
|
||||
model={model}
|
||||
modelProperties={modelProperties}
|
||||
visibleColumns={visibleColumns}
|
||||
record={
|
||||
spotlightData || {
|
||||
_id: query,
|
||||
isSkeleton: true
|
||||
}
|
||||
}
|
||||
isEditing={false}
|
||||
rowActions={rowActions}
|
||||
renderActions={renderActions}
|
||||
cardStyle='borderless'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user