160 lines
5.0 KiB
JavaScript
160 lines
5.0 KiB
JavaScript
// 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 { AuthContext } from '../context/AuthContext'
|
|
import ObjectProperty from './ObjectProperty'
|
|
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
|
|
import { ApiServerContext } from '../context/ApiServerContext'
|
|
import merge from 'lodash/merge'
|
|
import { getModelByName } from '../../../database/ObjectModels'
|
|
|
|
const { Text } = Typography
|
|
|
|
const SpotlightTooltip = ({ query, type }) => {
|
|
const [spotlightData, setSpotlightData] = useState(null)
|
|
const [loading, setLoading] = useState(true)
|
|
const [initialized, setInitialized] = useState(false)
|
|
|
|
const { token } = useContext(AuthContext)
|
|
const { fetchSpotlightData, subscribeToObjectUpdates, connected } =
|
|
useContext(ApiServerContext)
|
|
|
|
// Get the model for this type
|
|
const model = getModelByName(type)
|
|
const modelProperties = model.properties || []
|
|
|
|
// Update event handler
|
|
const updateObjectEventHandler = useCallback((value) => {
|
|
setSpotlightData((prev) => merge({}, prev, value))
|
|
}, [])
|
|
|
|
const fetchSpotlight = useCallback(async () => {
|
|
setLoading(true)
|
|
const data = await fetchSpotlightData(query)
|
|
setSpotlightData(data)
|
|
setLoading(false)
|
|
}, [query, fetchSpotlightData])
|
|
|
|
useEffect(() => {
|
|
if (token != null && initialized == false) {
|
|
fetchSpotlight()
|
|
console.log('Fetching spotlight...')
|
|
setInitialized(true)
|
|
}
|
|
}, [token, fetchSpotlight, initialized])
|
|
|
|
// Subscribe to object updates when component mounts
|
|
useEffect(() => {
|
|
if (spotlightData?._id && type && connected && token) {
|
|
const objectUpdatesUnsubscribe = subscribeToObjectUpdates(
|
|
spotlightData._id,
|
|
type,
|
|
updateObjectEventHandler
|
|
)
|
|
|
|
return () => {
|
|
if (objectUpdatesUnsubscribe) objectUpdatesUnsubscribe()
|
|
}
|
|
}
|
|
}, [
|
|
spotlightData?._id,
|
|
type,
|
|
subscribeToObjectUpdates,
|
|
connected,
|
|
token,
|
|
updateObjectEventHandler
|
|
])
|
|
|
|
if (!spotlightData && !loading) {
|
|
return (
|
|
<Card className='spotlight-tooltip'>
|
|
<Flex
|
|
justify='center'
|
|
gap={'small'}
|
|
style={{ height: '100%', minWidth: '270px' }}
|
|
align='center'
|
|
>
|
|
<Text type='secondary'>
|
|
<InfoCircleIcon />
|
|
</Text>
|
|
<Text type='secondary'>No spotlight data.</Text>
|
|
</Flex>
|
|
</Card>
|
|
)
|
|
}
|
|
|
|
// 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
|
|
type={prop.type}
|
|
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>
|
|
)
|
|
}
|
|
|
|
SpotlightTooltip.propTypes = {
|
|
query: PropTypes.string.isRequired,
|
|
type: PropTypes.string.isRequired
|
|
}
|
|
|
|
export default SpotlightTooltip
|