Refactor ObjectProperty component and introduce StateDisplay

- Removed unused components (PrinterState, SubJobState, JobState, FilamentStockState).
- Added new StateDisplay component for handling state representation.
- Enhanced ObjectProperty to support new properties and rendering logic for code blocks and object types.
- Updated import paths and prop types accordingly for improved clarity and functionality.
This commit is contained in:
Tom Butcher 2025-08-18 00:58:10 +01:00
parent a6a52fa81b
commit a9a2801e27
4 changed files with 83 additions and 207 deletions

View File

@ -20,14 +20,10 @@ import CountrySelect from './CountrySelect'
import TagsDisplay from './TagsDisplay' import TagsDisplay from './TagsDisplay'
import TagsInput from './TagsInput' import TagsInput from './TagsInput'
import BoolDisplay from './BoolDisplay' import BoolDisplay from './BoolDisplay'
import PrinterState from './PrinterState'
import SubJobState from './SubJobState'
import JobState from './JobState'
import ColorSelector from './ColorSelector' import ColorSelector from './ColorSelector'
import SecretDisplay from './SecretDisplay' import SecretDisplay from './SecretDisplay'
import EyeIcon from '../../Icons/EyeIcon' import EyeIcon from '../../Icons/EyeIcon'
import EyeSlashIcon from '../../Icons/EyeSlashIcon' import EyeSlashIcon from '../../Icons/EyeSlashIcon'
import FilamentStockState from './FilamentStockState'
import { getPropertyValue } from '../../../database/ObjectModels' import { getPropertyValue } from '../../../database/ObjectModels'
import PropertyChanges from './PropertyChanges' import PropertyChanges from './PropertyChanges'
import NetGrossDisplay from './NetGrossDisplay' import NetGrossDisplay from './NetGrossDisplay'
@ -38,6 +34,10 @@ import OperationDisplay from './OperationDisplay'
import MarkdownDisplay from './MarkdownDisplay' import MarkdownDisplay from './MarkdownDisplay'
import ObjectSelect from './ObjectSelect' import ObjectSelect from './ObjectSelect'
import ObjectDisplay from './ObjectDisplay' import ObjectDisplay from './ObjectDisplay'
import ObjectTypeSelect from './ObjectTypeSelect'
import ObjectTypeDisplay from './ObjectTypeDisplay'
import CodeBlockEditor from './CodeBlockEditor'
import StateDisplay from './StateDisplay'
const { Text } = Typography const { Text } = Typography
@ -65,11 +65,16 @@ const ObjectProperty = ({
name, name,
label, label,
showLabel = false, showLabel = false,
masterFilter = {},
language = '',
objectData = null, objectData = null,
objectType = 'unknown', objectType = 'unknown',
readOnly = false, readOnly = false,
disabled = false, disabled = false,
empty = false,
initial = false, initial = false,
height = 'auto',
minimal = false,
...rest ...rest
}) => { }) => {
if (value && typeof value == 'function' && objectData) { if (value && typeof value == 'function' && objectData) {
@ -84,6 +89,10 @@ const ObjectProperty = ({
disabled = disabled(objectData) disabled = disabled(objectData)
} }
if (empty && typeof empty == 'function' && objectData) {
empty = empty(objectData)
}
if (difference && typeof difference == 'function' && objectData) { if (difference && typeof difference == 'function' && objectData) {
difference = difference(objectData) difference = difference(objectData)
} }
@ -114,6 +123,9 @@ const ObjectProperty = ({
} }
const renderProperty = () => { const renderProperty = () => {
if (empty == true) {
return <Text type='secondary'>n/a</Text>
}
if (!isEditing || (readOnly && !initial)) { if (!isEditing || (readOnly && !initial)) {
switch (type) { switch (type) {
case 'netGross': case 'netGross':
@ -256,6 +268,24 @@ const ObjectProperty = ({
</Text> </Text>
) )
} }
case 'codeBlock':
if (value != null && value != '') {
return (
<CodeBlockEditor
code={value}
language={language}
height={height}
readOnly={true}
minimal={minimal}
/>
)
} else {
return (
<Text type='secondary' {...textParams}>
n/a
</Text>
)
}
case 'markdown': case 'markdown':
if (value != null && value != '') { if (value != null && value != '') {
return <MarkdownDisplay content={value} /> return <MarkdownDisplay content={value} />
@ -297,27 +327,23 @@ const ObjectProperty = ({
) )
} }
} }
case 'objectType': {
if (value) {
return <ObjectTypeDisplay objectType={value} />
} else {
return (
<Text type='secondary' {...textParams}>
n/a
</Text>
)
}
}
case 'objectList': { case 'objectList': {
return <ObjectList value={value} objectType={objectType} /> return <ObjectList value={value} objectType={objectType} />
} }
case 'state': { case 'state': {
if (value && value?.type) { if (value && value?.type) {
switch (objectType) { return <StateDisplay {...rest} state={value} />
case 'printer':
return <PrinterState state={value} {...rest} />
case 'job':
return <JobState state={value} {...rest} />
case 'subJob':
return <SubJobState state={value} {...rest} />
case 'filamentStock':
return <FilamentStockState state={value} {...rest} />
default:
return (
<Text type='secondary' {...textParams}>
No Object Type Specified
</Text>
)
}
} else { } else {
return ( return (
<Text type='secondary' {...textParams}> <Text type='secondary' {...textParams}>
@ -566,6 +592,18 @@ const ObjectProperty = ({
/> />
</Form.Item> </Form.Item>
) )
case 'codeBlock':
return (
<Form.Item name={formItemName} {...mergedFormItemProps}>
<CodeBlockEditor
code={value}
language={language}
disabled={disabled}
height={height}
minimal={minimal}
/>
</Form.Item>
)
case 'material': case 'material':
return ( return (
<Form.Item name={formItemName} {...mergedFormItemProps}> <Form.Item name={formItemName} {...mergedFormItemProps}>
@ -590,13 +628,23 @@ const ObjectProperty = ({
case 'object': case 'object':
return ( return (
<Form.Item name={formItemName} {...mergedFormItemProps}> <Form.Item name={formItemName} {...mergedFormItemProps}>
<ObjectSelect type={objectType} /> <ObjectSelect
type={objectType}
disabled={disabled}
masterFilter={masterFilter}
/>
</Form.Item>
)
case 'objectType':
return (
<Form.Item name={formItemName} {...mergedFormItemProps}>
<ObjectTypeSelect disabled={disabled} />
</Form.Item> </Form.Item>
) )
case 'objectList': case 'objectList':
return ( return (
<Form.Item name={formItemName} {...mergedFormItemProps}> <Form.Item name={formItemName} {...mergedFormItemProps}>
<ObjectSelect type={objectType} multiple /> <ObjectSelect type={objectType} multiple disabled={disabled} />
</Form.Item> </Form.Item>
) )
case 'tags': case 'tags':
@ -624,8 +672,10 @@ ObjectProperty.propTypes = {
value: PropTypes.oneOfType([PropTypes.any, PropTypes.func]), value: PropTypes.oneOfType([PropTypes.any, PropTypes.func]),
isEditing: PropTypes.bool, isEditing: PropTypes.bool,
formItemProps: PropTypes.object, formItemProps: PropTypes.object,
masterFilter: PropTypes.object,
required: PropTypes.bool, required: PropTypes.bool,
name: PropTypes.string, name: PropTypes.string,
language: PropTypes.string,
prefix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), prefix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
suffix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), suffix: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
min: PropTypes.number, min: PropTypes.number,
@ -635,8 +685,10 @@ ObjectProperty.propTypes = {
objectType: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), objectType: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
readOnly: PropTypes.bool, readOnly: PropTypes.bool,
disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]), disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
empty: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]),
difference: PropTypes.oneOfType([PropTypes.any, PropTypes.func]), difference: PropTypes.oneOfType([PropTypes.any, PropTypes.func]),
objectData: PropTypes.object objectData: PropTypes.object,
height: PropTypes.string
} }
export default ObjectProperty export default ObjectProperty

View File

@ -4,7 +4,7 @@ import { Progress, Flex, Space } from 'antd'
import React from 'react' import React from 'react'
import StateTag from './StateTag' import StateTag from './StateTag'
const PrinterState = ({ state, showProgress = true, showState = true }) => { const StateDisplay = ({ state, showProgress = true, showState = true }) => {
const currentState = state || { const currentState = state || {
type: 'unknown', type: 'unknown',
progress: 0 progress: 0
@ -17,9 +17,7 @@ const PrinterState = ({ state, showProgress = true, showState = true }) => {
<StateTag state={currentState.type} /> <StateTag state={currentState.type} />
</Space> </Space>
)} )}
{showProgress && {showProgress && currentState?.progress && currentState?.progress > 0 ? (
(currentState.type === 'printing' ||
currentState.type === 'deploying') ? (
<Progress <Progress
percent={Math.round(currentState.progress * 100)} percent={Math.round(currentState.progress * 100)}
status='active' status='active'
@ -30,10 +28,10 @@ const PrinterState = ({ state, showProgress = true, showState = true }) => {
) )
} }
PrinterState.propTypes = { StateDisplay.propTypes = {
state: PropTypes.object, state: PropTypes.object,
showProgress: PropTypes.bool, showProgress: PropTypes.bool,
showState: PropTypes.bool showState: PropTypes.bool
} }
export default PrinterState export default StateDisplay

View File

@ -1,147 +0,0 @@
import PropTypes from 'prop-types'
import { Progress, Flex, Button, Space, Tooltip } from 'antd' // eslint-disable-line
import { CaretLeftOutlined } from '@ant-design/icons' // eslint-disable-line
import React, { useContext } from 'react'
import { PrintServerContext } from '../context/PrintServerContext'
import IdDisplay from './IdDisplay'
import StateTag from './StateTag'
import XMarkIcon from '../../Icons/XMarkIcon'
import PauseIcon from '../../Icons/PauseIcon'
import BinIcon from '../../Icons/BinIcon'
import config from '../../../config'
import loglevel from 'loglevel'
const logger = loglevel.getLogger('SubJobState')
logger.setLevel(config.logLevel)
const SubJobState = ({
state,
showStatus = true,
showId = true,
showProgress = true,
showControls = true //eslint-disable-line
}) => {
const { printServer } = useContext(PrintServerContext)
const currentState = state || {
type: 'unknown',
progress: 0
}
return (
<Flex gap='small' align={'center'}>
{showId && state?._id && (
<IdDisplay
id={state._id}
showCopy={false}
type='subjob'
longId={false}
/>
)}
{showStatus && (
<Space>
<StateTag state={currentState?.type} />
</Space>
)}
{showProgress &&
(currentState.type === 'printing' ||
currentState.type === 'processing') ? (
<Progress
percent={Math.round(currentState.progress * 100)}
status='active'
style={{ width: '150px', marginBottom: '2px' }}
/>
) : null}
{showControls &&
(currentState.type === 'printing' || currentState.type === 'paused') &&
state?.printer ? (
<Space.Compact>
<Tooltip
title={currentState.type === 'printing' ? 'Pause' : 'Resume'}
arrow={false}
>
<Button
onClick={() => {
if (currentState.type === 'printing') {
printServer.emit('printer.print.pause', {
printerId: state.printer
})
} else {
printServer.emit('printer.print.resume', {
printerId: state.printer
})
}
}}
style={{ height: '22px' }}
type='text'
icon={
currentState.type === 'printing' ? (
<PauseIcon
style={{ fontSize: '12px', marginBottom: '3px' }}
/>
) : (
<CaretLeftOutlined
style={{ fontSize: '10px', marginBottom: '3px' }}
/>
)
}
></Button>
</Tooltip>
<Tooltip title='Cancel' arrow={false}>
<Button
onClick={() => {
printServer.emit('printer.print.cancel', {
printerId: state.printer
})
}}
type='text'
style={{ height: '22px' }}
icon={
<XMarkIcon style={{ fontSize: '12px', marginBottom: '3px' }} />
}
/>
</Tooltip>
</Space.Compact>
) : null}
{showControls && currentState.type === 'queued' && state?._id ? (
<Tooltip title='Cancel' arrow={false}>
<Button
onClick={() => {
printServer.emit('server.job_queue.cancel', {
subJobId: state._id
})
}}
style={{ height: '22px' }}
type='text'
icon={
<XMarkIcon style={{ fontSize: '12px', marginBottom: '3px' }} />
}
/>
</Tooltip>
) : null}
{showControls && currentState.type === 'draft' ? (
<Space>
<Tooltip title='Delete' arrow={false}>
<Button
onClick={() => {
logger.debug('Hello')
}}
type='text'
style={{ height: 'unset' }}
icon={
<BinIcon style={{ fontSize: '14px', marginBottom: '2px' }} />
}
/>
</Tooltip>
</Space>
) : null}
</Flex>
)
}
SubJobState.propTypes = {
state: PropTypes.object,
showProgress: PropTypes.bool,
showControls: PropTypes.bool,
showId: PropTypes.bool,
showStatus: PropTypes.bool
}
export default SubJobState

View File

@ -14,8 +14,7 @@ import axios from 'axios'
import { LoadingOutlined } from '@ant-design/icons' import { LoadingOutlined } from '@ant-design/icons'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import PrinterState from '../common/PrinterState' import StateDisplay from '../common/StateDisplay'
import JobState from '../common/JobState'
import IdDisplay from '../common/IdDisplay' import IdDisplay from '../common/IdDisplay'
import config from '../../../config' import config from '../../../config'
@ -24,8 +23,6 @@ import {
getModelByPrefix getModelByPrefix
} from '../../../database/ObjectModels' } from '../../../database/ObjectModels'
import InfoCircleIcon from '../../Icons/InfoCircleIcon' import InfoCircleIcon from '../../Icons/InfoCircleIcon'
import FilamentStockState from '../common/FilamentStockState'
import SubJobState from '../common/SubJobState'
const SpotlightContext = createContext() const SpotlightContext = createContext()
@ -469,38 +466,14 @@ const SpotlightProvider = ({ children }) => {
{item.name} {item.name}
</Text> </Text>
) : null} ) : null}
{model.type == 'printer' ? ( {item?.state ? (
<PrinterState <StateDisplay
printer={item} state={item.state}
showName={false} showName={false}
showProgress={false} showProgress={false}
showId={false} showId={false}
/> />
) : null} ) : null}
{model.type == 'job' ? (
<JobState
job={item}
showQuantity={false}
showProgress={false}
showId={false}
/>
) : null}
{model.type == 'subjob' ? (
<SubJobState
subJob={item}
showProgress={false}
showId={false}
/>
) : null}
{model.type == 'filamentstock' ? (
<Flex gap={'small'}>
<FilamentStockState
filamentStock={item}
showId={false}
showProgress={false}
/>
</Flex>
) : null}
<IdDisplay id={item._id} type={type} longId={false} /> <IdDisplay id={item._id} type={type} longId={false} />
</Flex> </Flex>
<Flex gap={'small'}> <Flex gap={'small'}>