Compare commits

..

No commits in common. "8993caeac5559a5791885ade7cc8b42ea66f3bb2" and "12a4d46da88e9bb9f47207883df5da2e528e3550" have entirely different histories.

16 changed files with 188 additions and 415 deletions

View File

@ -41,8 +41,7 @@ const DocumentTemplateDesign = () => {
editLoading: false, editLoading: false,
formValid: false, formValid: false,
locked: false, locked: false,
loading: false, loading: false
objectData: {}
}) })
const actions = { const actions = {

View File

@ -45,18 +45,10 @@ const IdDisplay = ({
} }
return ( return (
<Flex <Flex align={'end'} className='iddisplay'>
align={'end'}
className='iddisplay'
style={{ minWidth: '0px', width: '100%' }}
>
{(() => { {(() => {
const textElement = ( const textElement = (
<Text <Text code ellipsis style={showCopy ? { marginRight: 6 } : undefined}>
code
ellipsis
style={showCopy ? { marginRight: 6, minWidth: '0px' } : undefined}
>
{displayId} {displayId}
</Text> </Text>
) )

View File

@ -35,29 +35,18 @@ function filterActionsByVisibility(actions, visibleActions) {
} }
// Recursively map actions to AntD Dropdown items // Recursively map actions to AntD Dropdown items
function mapActionsToMenuItems(actions, currentUrlWithActions, id, objectData) { function mapActionsToMenuItems(actions, currentUrlWithActions, id) {
return actions.map((action) => { return actions.map((action) => {
if (action.type === 'divider') { if (action.type === 'divider') {
return { type: 'divider' } return { type: 'divider' }
} }
const actionUrl = action.url ? action.url(id) : undefined const actionUrl = action.url ? action.url(id) : undefined
var disabled = actionUrl && actionUrl === currentUrlWithActions
if (action.disabled) {
if (typeof action.disabled === 'function') {
disabled = action.disabled(objectData)
} else {
disabled = action.disabled
}
}
const item = { const item = {
key: action.key || action.name, key: action.key || action.name,
label: action.label, label: action.label,
danger: action?.danger || false, danger: action?.danger || false,
icon: action.icon ? createElement(action.icon) : undefined, icon: action.icon ? createElement(action.icon) : undefined,
disabled disabled: actionUrl && actionUrl === currentUrlWithActions
} }
if (action.children && Array.isArray(action.children)) { if (action.children && Array.isArray(action.children)) {
item.children = mapActionsToMenuItems( item.children = mapActionsToMenuItems(
@ -80,7 +69,6 @@ const stripActionParam = (pathname, search) => {
const ObjectActions = ({ const ObjectActions = ({
type, type,
id, id,
objectData,
disabled = false, disabled = false,
buttonProps = {}, buttonProps = {},
visibleActions = {}, visibleActions = {},
@ -113,12 +101,7 @@ const ObjectActions = ({
// Compose AntD Dropdown menu items // Compose AntD Dropdown menu items
const menu = { const menu = {
items: mapActionsToMenuItems( items: mapActionsToMenuItems(filteredActions, currentUrlWithActions, id),
filteredActions,
currentUrlWithActions,
id,
objectData
),
onClick: (info) => { onClick: (info) => {
// Find the action by key // Find the action by key
const findAction = (acts, key) => { const findAction = (acts, key) => {
@ -149,7 +132,6 @@ const ObjectActions = ({
ObjectActions.propTypes = { ObjectActions.propTypes = {
type: PropTypes.string.isRequired, type: PropTypes.string.isRequired,
objectData: PropTypes.object.isRequired,
id: PropTypes.string.isRequired, id: PropTypes.string.isRequired,
disabled: PropTypes.bool, disabled: PropTypes.bool,
buttonProps: PropTypes.object, buttonProps: PropTypes.object,

View File

@ -5,7 +5,6 @@ import { getModelByName } from '../../../database/ObjectModels'
import { ApiServerContext } from '../context/ApiServerContext' import { ApiServerContext } from '../context/ApiServerContext'
import { AuthContext } from '../context/AuthContext' import { AuthContext } from '../context/AuthContext'
import merge from 'lodash/merge' import merge from 'lodash/merge'
import IdDisplay from './IdDisplay'
const { Text } = Typography const { Text } = Typography
@ -56,15 +55,7 @@ const ObjectDisplay = ({ object, objectType }) => {
<Flex gap={'small'} align='center'> <Flex gap={'small'} align='center'>
<Icon /> <Icon />
{objectData?.color ? <Badge color={objectData?.color} /> : null} {objectData?.color ? <Badge color={objectData?.color} /> : null}
{objectData?.name ? <Text ellipsis>{objectData.name}</Text> : null} <Text ellipsis>{objectData?.name ? objectData.name : null}</Text>
{objectData?._id && !objectData?.name ? (
<IdDisplay
id={objectData?._id}
type={objectType}
longId={false}
showCopy={false}
/>
) : null}
</Flex> </Flex>
) )
} }

View File

@ -59,10 +59,11 @@ const ObjectForm = forwardRef(
.validateFields({ validateOnly: true }) .validateFields({ validateOnly: true })
.then(() => { .then(() => {
setFormValid(true) setFormValid(true)
onStateChange({ formValid: true, objectData: form.getFieldsValue() }) onStateChange({ formValid: true })
}) })
.catch(() => { .catch(() => {
onStateChange({ formValid: true, objectData: form.getFieldsValue() }) setFormValid(false)
onStateChange({ formValid: true })
}) })
}, [form, formUpdateValues]) }, [form, formUpdateValues])
@ -145,10 +146,6 @@ const ObjectForm = forwardRef(
updateLockEventHandler updateLockEventHandler
]) ])
useEffect(() => {
onStateChange({ objectData })
}, [objectData])
const startEditing = () => { const startEditing = () => {
setIsEditing(true) setIsEditing(true)
onStateChange({ isEditing: true }) onStateChange({ isEditing: true })

View File

@ -42,9 +42,6 @@ const ObjectInfo = ({
items = items.filter((item) => item.required === required) items = items.filter((item) => item.required === required)
} }
if (showHyperlink) {
objectPropertyProps = { ...objectPropertyProps, showHyperlink }
}
// Filter items based on visibleProperties // Filter items based on visibleProperties
// If a property key exists in visibleProperties and is false, hide it // If a property key exists in visibleProperties and is false, hide it
items = items.filter((item) => { items = items.filter((item) => {
@ -70,6 +67,7 @@ const ObjectInfo = ({
<ObjectProperty <ObjectProperty
{...item} {...item}
{...objectPropertyProps} {...objectPropertyProps}
showHyperlink={showHyperlink}
isEditing={isEditing} isEditing={isEditing}
objectData={objectData} objectData={objectData}
/> />

View File

@ -38,7 +38,6 @@ import ObjectTypeSelect from './ObjectTypeSelect'
import ObjectTypeDisplay from './ObjectTypeDisplay' import ObjectTypeDisplay from './ObjectTypeDisplay'
import CodeBlockEditor from './CodeBlockEditor' import CodeBlockEditor from './CodeBlockEditor'
import StateDisplay from './StateDisplay' import StateDisplay from './StateDisplay'
import AlertsDisplay from './AlertsDisplay'
const { Text } = Typography const { Text } = Typography
@ -106,10 +105,6 @@ const ObjectProperty = ({
suffix = suffix(objectData) suffix = suffix(objectData)
} }
if (masterFilter && typeof masterFilter == 'function' && objectData) {
masterFilter = masterFilter(objectData)
}
if (!value) { if (!value) {
value = getPropertyValue(objectData, name) value = getPropertyValue(objectData, name)
} }
@ -121,7 +116,7 @@ const ObjectProperty = ({
formItemName = name ? name.split('.') : undefined formItemName = name ? name.split('.') : undefined
} }
var textParams = { style: { whiteSpace: 'nowrap' } } var textParams = {}
if (disabled == true) { if (disabled == true) {
textParams = { ...textParams, delete: true, type: 'secondary' } textParams = { ...textParams, delete: true, type: 'secondary' }
@ -322,7 +317,7 @@ const ObjectProperty = ({
) )
} }
case 'object': { case 'object': {
if (value && value._id) { if (value && value.name) {
return <ObjectDisplay object={value} objectType={objectType} /> return <ObjectDisplay object={value} objectType={objectType} />
} else { } else {
return ( return (
@ -390,9 +385,9 @@ const ObjectProperty = ({
) )
} }
} }
case 'alerts': { case 'mm': {
if (value != null && value?.length != 0) { if (value != null) {
return <AlertsDisplay alerts={value} /> return <Text {...textParams}>{`${value} mm`}</Text>
} else { } else {
return ( return (
<Text type='secondary' {...textParams}> <Text type='secondary' {...textParams}>

View File

@ -1,11 +1,4 @@
import { import { useEffect, useState, useContext, useCallback, useMemo } from 'react'
useEffect,
useState,
useContext,
useCallback,
useMemo,
useRef
} from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { TreeSelect, Space, Button, Input } from 'antd' import { TreeSelect, Space, Button, Input } from 'antd'
import ReloadIcon from '../../Icons/ReloadIcon' import ReloadIcon from '../../Icons/ReloadIcon'
@ -79,7 +72,6 @@ const ObjectSelect = ({
}) })
return { return {
title: ( title: (
<div style={{ paddingTop: '1px' }}>
<ObjectProperty <ObjectProperty
key={object._id} key={object._id}
type='object' type='object'
@ -88,7 +80,6 @@ const ObjectSelect = ({
objectData={object} objectData={object}
isEditing={false} isEditing={false}
/> />
</div>
), ),
value: object._id, value: object._id,
key: object._id, key: object._id,
@ -208,7 +199,7 @@ const ObjectSelect = ({
return prev return prev
}) })
} }
}, [objectPropertiesTree, properties, buildTreeData]) }, [objectPropertiesTree, properties, type, buildTreeData])
useEffect(() => { useEffect(() => {
if (value && typeof value === 'object' && value !== null && !initialized) { if (value && typeof value === 'object' && value !== null && !initialized) {
@ -245,24 +236,6 @@ const ObjectSelect = ({
token token
]) ])
const prevValuesRef = useRef({ type, masterFilter })
useEffect(() => {
const prevValues = prevValuesRef.current
// Deep comparison for objects, simple comparison for primitives
const hasChanged =
prevValues.type !== type ||
JSON.stringify(prevValues.masterFilter) !== JSON.stringify(masterFilter)
if (hasChanged) {
setObjectPropertiesTree({})
setTreeData([])
setInitialized(false)
prevValuesRef.current = { type, masterFilter }
}
}, [type, masterFilter])
// --- Error UI --- // --- Error UI ---
if (error) { if (error) {
return ( return (

View File

@ -53,8 +53,7 @@ const PrinterTemperaturePanel = ({
ambiant: 0 ambiant: 0
}) })
const { subscribeToObjectEvent, connected, sendObjectAction } = const { subscribeToObjectEvent, connected } = useContext(ApiServerContext)
useContext(ApiServerContext)
// Sync input values with actual temperature targets // Sync input values with actual temperature targets
useEffect(() => { useEffect(() => {
@ -91,19 +90,10 @@ const PrinterTemperaturePanel = ({
const [extruderTarget, setExtruderTarget] = useState(0) const [extruderTarget, setExtruderTarget] = useState(0)
const [bedTarget, setBedTarget] = useState(0) const [bedTarget, setBedTarget] = useState(0)
const handleSetTemperature = async (data) => { const handleSetTemperature = (data) => {
if (id && connected == true) { if (id && connected == true) {
await sendObjectAction( console.log(data)
id, //sendObjectAction(id, 'printer', { type: 'setTemperature', data })
'printer',
{
type: 'setTemperature',
data
},
(result) => {
console.log('setTemperatureResult', result)
}
)
} }
} }
@ -179,20 +169,16 @@ const PrinterTemperaturePanel = ({
style={{ width: '120px' }} style={{ width: '120px' }}
addonAfter='°C' addonAfter='°C'
onChange={(value) => setExtruderTarget(value || 0)} onChange={(value) => setExtruderTarget(value || 0)}
onPressEnter={() => onPressEnter={handleSetTemperature({
handleSetTemperature({
extruder: { target: extruderTarget } extruder: { target: extruderTarget }
}) })}
}
/> />
<Button <Button
type='default' type='default'
style={{ width: 40 }} style={{ width: 40 }}
onClick={() => onClick={handleSetTemperature({
handleSetTemperature({
extruder: { target: extruderTarget } extruder: { target: extruderTarget }
}) })}
}
> >
Set Set
</Button> </Button>
@ -240,20 +226,16 @@ const PrinterTemperaturePanel = ({
style={{ width: '120px' }} style={{ width: '120px' }}
addonAfter='°C' addonAfter='°C'
onChange={(value) => setBedTarget(value || 0)} onChange={(value) => setBedTarget(value || 0)}
onPressEnter={() => onPressEnter={handleSetTemperature({
handleSetTemperature({
bed: { target: bedTarget } bed: { target: bedTarget }
}) })}
}
/> />
<Button <Button
type='default' type='default'
style={{ width: 40 }} style={{ width: 40 }}
onClick={() => onClick={handleSetTemperature({
handleSetTemperature({
bed: { target: bedTarget } bed: { target: bedTarget }
}) })}
}
> >
Set Set
</Button> </Button>

View File

@ -1,5 +1,5 @@
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Descriptions, Typography, Flex } from 'antd' import { Descriptions, Typography, Space } from 'antd'
import { getModelProperty } from '../../../database/ObjectModels' import { getModelProperty } from '../../../database/ObjectModels'
import ObjectProperty from './ObjectProperty' import ObjectProperty from './ObjectProperty'
import ArrowRightIcon from '../../Icons/ArrowRightIcon' import ArrowRightIcon from '../../Icons/ArrowRightIcon'
@ -51,7 +51,7 @@ const PropertyChanges = ({ type, value }) => {
} }
return ( return (
<Descriptions.Item key={key} label={changeProperty.label}> <Descriptions.Item key={key} label={changeProperty.label}>
<Flex gap={'small'}> <Space>
{value?.old ? ( {value?.old ? (
<ObjectProperty <ObjectProperty
{...changeProperty} {...changeProperty}
@ -73,7 +73,7 @@ const PropertyChanges = ({ type, value }) => {
objectData={value?.new} objectData={value?.new}
/> />
) : null} ) : null}
</Flex> </Space>
</Descriptions.Item> </Descriptions.Item>
) )
})} })}

View File

@ -1,11 +1,14 @@
import { useState } from 'react' import { useState, useContext, useEffect, useRef, useCallback } from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { Flex, Alert, Card, Spin, Splitter, Button, Modal } from 'antd' import { Flex, Alert, Card, Spin, Splitter, Button, Modal, Input } from 'antd'
import { LoadingOutlined } from '@ant-design/icons' import { LoadingOutlined } from '@ant-design/icons'
import PlusIcon from '../../Icons/PlusIcon.jsx'
import MinusIcon from '../../Icons/MinusIcon.jsx'
import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon.jsx' import ExclamationOctagonIcon from '../../Icons/ExclamationOctagonIcon.jsx'
import CheckCircleIcon from '../../Icons/CheckCircleIcon.jsx' import CheckCircleIcon from '../../Icons/CheckCircleIcon.jsx'
import ObjectProperty from '../common/ObjectProperty.jsx' import ObjectProperty from '../common/ObjectProperty.jsx'
import TemplatePreview from './TemplatePreview.jsx' import { ApiServerContext } from '../context/ApiServerContext.jsx'
import InfoCircleIcon from '../../Icons/InfoCircleIcon.jsx'
const TemplateEditor = ({ const TemplateEditor = ({
objectData, objectData,
@ -14,36 +17,134 @@ const TemplateEditor = ({
isEditing, isEditing,
style style
}) => { }) => {
const iframeRef = useRef(null)
const { fetchTemplatePreview } = useContext(ApiServerContext)
const [testObjectOpen, setTestObjectOpen] = useState(false) const [testObjectOpen, setTestObjectOpen] = useState(false)
const [previewMessage, setPreviewMessage] = useState('No issues found.') const [previewMessage, setPreviewMessage] = useState('No issues found.')
const [previewError, setPreviewError] = useState(false) const [previewError, setPreviewError] = useState(false)
const [previewContent, setPreviewContent] = useState('')
const [reloadLoading, setReloadLoading] = useState(false)
const [previewScale, setPreviewScale] = useState(1)
const handlePreviewMessage = (message, isError) => { const updatePreviewContent = (html) => {
setPreviewMessage(message) if (iframeRef.current) {
setPreviewError(isError) // Save current scroll position
const scrollY = iframeRef.current.contentWindow.scrollY
const scrollX = iframeRef.current.contentWindow.scrollX
// Update srcDoc
setPreviewContent(html)
// Restore scroll position after iframe loads new content
const handleLoad = () => {
iframeRef.current.contentWindow.scrollTo(scrollX, scrollY)
iframeRef.current.removeEventListener('load', handleLoad)
} }
iframeRef.current.addEventListener('load', handleLoad)
}
}
const reloadPreview = useCallback(
(content, testObject = {}, scale = 1) => {
fetchTemplatePreview(
objectData._id,
content,
testObject,
scale,
(result) => {
setReloadLoading(false)
if (result?.error) {
setPreviewError(true)
setPreviewMessage(result.error)
} else {
setPreviewError(false)
updatePreviewContent(result.html)
setPreviewMessage('No issues found.')
}
}
)
},
[fetchTemplatePreview, objectData?._id]
)
// Move useEffect to component level and use state to track objectData changes
useEffect(() => {
if (objectData) {
console.log('PreviewScale', previewScale)
reloadPreview(objectData.content, objectData.testObject, previewScale)
}
}, [objectData, previewScale, reloadPreview])
return ( return (
<> <>
<Splitter className={'farmcontrol-splitter'}> <Splitter className={'farmcontrol-splitter'}>
{collapseState.preview == true && ( {collapseState.preview == true && (
<Splitter.Panel style={{ height: '100%' }}> <Splitter.Panel style={{ height: '100%' }}>
<Card <Spin
spinning={loading} spinning={loading || reloadLoading}
style={style} indicator={<LoadingOutlined />}
styles={{ body: { height: '100%' } }}
> >
<TemplatePreview <Card style={style} styles={{ body: { height: '100%' } }}>
objectData={objectData?.testObject} <Flex vertical gap={'middle'} style={{ height: '100%' }}>
documentTemplate={objectData} <Flex gap={'small'}>
loading={loading} {objectData?.objectType ? (
isEditing={isEditing} <ObjectProperty
style={style} objectType={objectData?.objectType}
onTestObjectOpen={() => setTestObjectOpen(true)} name={'testObject'}
onPreviewMessage={handlePreviewMessage} isEditing={true}
showTestObject={true} objectData={objectData}
disabled={!isEditing || objectData?.global}
type={'object'}
/> />
) : (
<div style={{ flexGrow: 1 }}>
<Input disabled={true} />
</div>
)}
<Button
icon={<InfoCircleIcon />}
disabled={objectData?.global}
onClick={() => {
setTestObjectOpen(true)
}}
/>
<Button
icon={<PlusIcon />}
onClick={() => {
setPreviewScale((prev) => prev + 0.05)
}}
/>
<Button
icon={<MinusIcon />}
onClick={() => {
setPreviewScale((prev) => prev - 0.05)
}}
/>
<Button
readOnly={true}
style={{ width: '65px' }}
onClick={() => {
setPreviewScale(1)
}}
>
{previewScale.toFixed(2)}x
</Button>
</Flex>
<iframe
ref={iframeRef}
srcDoc={previewContent}
frameBorder='0'
style={{
width: '100%',
flexGrow: 1,
border: '1px solid #85858541',
overflow: 'auto'
}}
/>
</Flex>
</Card> </Card>
</Spin>
</Splitter.Panel> </Splitter.Panel>
)} )}
{collapseState.editor == true && ( {collapseState.editor == true && (

View File

@ -1,158 +0,0 @@
import { useState, useContext, useEffect, useRef, useCallback } from 'react'
import PropTypes from 'prop-types'
import { Flex, Button, Input } from 'antd'
import PlusIcon from '../../Icons/PlusIcon.jsx'
import MinusIcon from '../../Icons/MinusIcon.jsx'
import InfoCircleIcon from '../../Icons/InfoCircleIcon.jsx'
import ObjectProperty from '../common/ObjectProperty.jsx'
import { ApiServerContext } from '../context/ApiServerContext.jsx'
const TemplatePreview = ({
objectData,
documentTemplate,
loading,
isEditing,
onTestObjectOpen,
onPreviewMessage,
showTestObject = false
}) => {
const iframeRef = useRef(null)
const { fetchTemplatePreview } = useContext(ApiServerContext)
const [previewContent, setPreviewContent] = useState('')
const [reloadLoading, setReloadLoading] = useState(false)
const [previewScale, setPreviewScale] = useState(1)
const updatePreviewContent = (html) => {
if (iframeRef.current) {
// Save current scroll position
const scrollY = iframeRef.current.contentWindow.scrollY
const scrollX = iframeRef.current.contentWindow.scrollX
// Update srcDoc
setPreviewContent(html)
// Restore scroll position after iframe loads new content
const handleLoad = () => {
iframeRef.current.contentWindow.scrollTo(scrollX, scrollY)
iframeRef.current.removeEventListener('load', handleLoad)
}
iframeRef.current.addEventListener('load', handleLoad)
}
}
const reloadPreview = useCallback(
(content, testObject = {}, scale = 1) => {
if (!objectData?._id) {
onPreviewMessage('No object data available for preview.', true)
return
}
setReloadLoading(true)
fetchTemplatePreview(
documentTemplate._id,
content,
testObject,
scale,
(result) => {
setReloadLoading(false)
if (result?.error) {
// Handle error through parent component
onPreviewMessage(result.error, true)
} else {
updatePreviewContent(result.html)
onPreviewMessage('No issues found.', false)
}
}
)
},
[fetchTemplatePreview, objectData?._id, onPreviewMessage]
)
// Move useEffect to component level and use state to track objectData changes
useEffect(() => {
if (objectData && documentTemplate?.content) {
console.log('PreviewScale', previewScale)
reloadPreview(documentTemplate.content, objectData, previewScale)
}
}, [objectData, documentTemplate, previewScale, reloadPreview])
return (
<Flex vertical gap={'middle'} style={{ height: '100%' }}>
<Flex gap={'small'}>
{showTestObject == true ? (
<>
{documentTemplate?.objectType ? (
<ObjectProperty
objectType={documentTemplate?.objectType}
name={'testObject'}
isEditing={true}
objectData={objectData}
disabled={!isEditing || objectData?.global}
type={'object'}
/>
) : (
<div style={{ flexGrow: 1 }}>
<Input disabled={true} />
</div>
)}
<Button
icon={<InfoCircleIcon />}
disabled={objectData?.global}
onClick={() => {
onTestObjectOpen()
}}
/>
</>
) : null}
<Button
icon={<PlusIcon />}
onClick={() => {
setPreviewScale((prev) => prev + 0.05)
}}
/>
<Button
icon={<MinusIcon />}
onClick={() => {
setPreviewScale((prev) => prev - 0.05)
}}
/>
<Button
readOnly={true}
style={{ width: '65px' }}
loading={loading || reloadLoading}
disabled={loading || reloadLoading}
onClick={() => {
setPreviewScale(1)
}}
>
{previewScale.toFixed(2)}x
</Button>
</Flex>
<iframe
ref={iframeRef}
srcDoc={previewContent}
frameBorder='0'
style={{
width: '100%',
flexGrow: 1,
border: '1px solid #85858541',
overflow: 'auto'
}}
/>
</Flex>
)
}
TemplatePreview.propTypes = {
loading: PropTypes.bool,
objectData: PropTypes.object,
documentTemplate: PropTypes.object,
isEditing: PropTypes.bool,
style: PropTypes.object,
showTestObject: PropTypes.bool,
onTestObjectOpen: PropTypes.func.isRequired,
onPreviewMessage: PropTypes.func.isRequired
}
export default TemplatePreview

View File

@ -12,9 +12,7 @@ const WizardView = ({
title = 'Wizard View', title = 'Wizard View',
onSubmit, onSubmit,
formValid, formValid,
loading, loading
sideBar = null,
submitText = 'Done'
}) => { }) => {
const [currentStep, setCurrentStep] = useState(0) const [currentStep, setCurrentStep] = useState(0)
const isMobile = useMediaQuery({ maxWidth: 768 }) const isMobile = useMediaQuery({ maxWidth: 768 })
@ -22,9 +20,6 @@ const WizardView = ({
return ( return (
<Flex gap='middle'> <Flex gap='middle'>
{!isMobile && showSteps == true ? ( {!isMobile && showSteps == true ? (
sideBar != null ? (
sideBar
) : (
<div style={{ minWidth: '160px' }}> <div style={{ minWidth: '160px' }}>
<Steps <Steps
current={currentStep} current={currentStep}
@ -33,22 +28,19 @@ const WizardView = ({
style={{ width: 'fit-content' }} style={{ width: 'fit-content' }}
/> />
</div> </div>
)
) : null} ) : null}
{!isMobile && showSteps == true ? ( {!isMobile && showSteps == true ? (
<Divider type='vertical' style={{ height: 'unset' }} /> <Divider type='vertical' style={{ height: 'unset' }} />
) : null} ) : null}
<Flex vertical justify='space-between' gap={'middle'}>
<Flex vertical gap='middle' style={{ flexGrow: 1 }}> <Flex vertical gap='middle' style={{ flexGrow: 1 }}>
<Title level={2} style={{ margin: 0 }}> <Title level={2} style={{ margin: 0 }}>
{title} {title}
</Title> </Title>
<div style={{ minHeight: '260px', marginBottom: 4 }}> <div style={{ minHeight: '260px', marginBottom: 8 }}>
{steps[currentStep].content} {steps[currentStep].content}
</div> </div>
</Flex>
<NewObjectButtons <NewObjectButtons
currentStep={currentStep} currentStep={currentStep}
totalSteps={steps.length} totalSteps={steps.length}
@ -57,7 +49,6 @@ const WizardView = ({
onSubmit={onSubmit} onSubmit={onSubmit}
formValid={formValid} formValid={formValid}
submitLoading={loading} submitLoading={loading}
submitText={submitText}
/> />
</Flex> </Flex>
</Flex> </Flex>
@ -70,9 +61,7 @@ WizardView.propTypes = {
steps: PropTypes.array.isRequired, steps: PropTypes.array.isRequired,
showSteps: PropTypes.bool, showSteps: PropTypes.bool,
title: PropTypes.string, title: PropTypes.string,
loading: PropTypes.bool, loading: PropTypes.bool
sideBar: PropTypes.node,
submitText: PropTypes.string
} }
export default WizardView export default WizardView

View File

@ -7,7 +7,6 @@ import { Job } from './models/Job'
import { Product } from './models/Product' import { Product } from './models/Product'
import { Part } from './models/Part.js' import { Part } from './models/Part.js'
import { Vendor } from './models/Vendor' import { Vendor } from './models/Vendor'
import { File } from './models/File'
import { SubJob } from './models/SubJob' import { SubJob } from './models/SubJob'
import { Initial } from './models/Initial' import { Initial } from './models/Initial'
import { FilamentStock } from './models/FilamentStock' import { FilamentStock } from './models/FilamentStock'
@ -22,7 +21,6 @@ import { Note } from './models/Note'
import { DocumentSize } from './models/DocumentSize.js' import { DocumentSize } from './models/DocumentSize.js'
import { DocumentTemplate } from './models/DocumentTemplate.js' import { DocumentTemplate } from './models/DocumentTemplate.js'
import { DocumentPrinter } from './models/DocumentPrinter.js' import { DocumentPrinter } from './models/DocumentPrinter.js'
import { DocumentJob } from './models/DocumentJob.js'
import QuestionCircleIcon from '../components/Icons/QuestionCircleIcon' import QuestionCircleIcon from '../components/Icons/QuestionCircleIcon'
export const objectModels = [ export const objectModels = [
@ -35,7 +33,6 @@ export const objectModels = [
Product, Product,
Part, Part,
Vendor, Vendor,
File,
SubJob, SubJob,
Initial, Initial,
FilamentStock, FilamentStock,
@ -49,8 +46,7 @@ export const objectModels = [
Note, Note,
DocumentSize, DocumentSize,
DocumentTemplate, DocumentTemplate,
DocumentPrinter, DocumentPrinter
DocumentJob
] ]
// Re-export individual models for direct access // Re-export individual models for direct access
@ -64,7 +60,6 @@ export {
Product, Product,
Part, Part,
Vendor, Vendor,
File,
SubJob, SubJob,
Initial, Initial,
FilamentStock, FilamentStock,
@ -78,8 +73,7 @@ export {
Note, Note,
DocumentSize, DocumentSize,
DocumentTemplate, DocumentTemplate,
DocumentPrinter, DocumentPrinter
DocumentJob
} }
export function getModelByName(name, ignoreCase = false) { export function getModelByName(name, ignoreCase = false) {

View File

@ -1,7 +1,6 @@
import JobIcon from '../../components/Icons/JobIcon' import JobIcon from '../../components/Icons/JobIcon'
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon' import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
import ReloadIcon from '../../components/Icons/ReloadIcon' import ReloadIcon from '../../components/Icons/ReloadIcon'
import CheckIcon from '../../components/Icons/CheckIcon'
export const Job = { export const Job = {
name: 'job', name: 'job',
@ -17,19 +16,6 @@ export const Job = {
icon: InfoCircleIcon, icon: InfoCircleIcon,
url: (_id) => `/dashboard/production/jobs/info?jobId=${_id}` url: (_id) => `/dashboard/production/jobs/info?jobId=${_id}`
}, },
{
name: 'deploy',
label: 'Deploy',
default: true,
row: true,
icon: CheckIcon,
url: (_id) =>
`/dashboard/production/jobs/info?jobId=${_id}?action=deploy`,
disabled: (objectData) => {
console.log('Should be disabled', objectData?.state?.type != 'draft')
return objectData?.state?.type != 'draft'
}
},
{ {
name: 'reload', name: 'reload',
label: 'Reload', label: 'Reload',

View File

@ -76,24 +76,12 @@ export const Printer = {
showName: false, showName: false,
readOnly: true readOnly: true
}, },
{
name: 'active',
label: 'Active',
type: 'bool',
required: true
},
{
name: 'online',
label: 'Online',
type: 'bool',
readOnly: true
},
{ {
name: 'vendor', name: 'vendor',
label: 'Vendor', label: 'Vendor',
type: 'object', type: 'object',
objectType: 'vendor', objectType: 'vendor',
required: false required: true
}, },
{ {
name: 'vendor._id', name: 'vendor._id',
@ -161,7 +149,7 @@ export const Printer = {
label: 'Filament Stock', label: 'Filament Stock',
type: 'object', type: 'object',
objectType: 'filamentStock', objectType: 'filamentStock',
required: false required: true
}, },
{ {
name: 'currentFilamentStock._id', name: 'currentFilamentStock._id',
@ -170,42 +158,6 @@ export const Printer = {
objectType: 'filamentStock', objectType: 'filamentStock',
showHyperlink: true, showHyperlink: true,
readOnly: true readOnly: true
},
{
name: 'currentJob',
label: 'Current Job',
type: 'object',
objectType: 'job',
required: false
},
{
name: 'currentJob._id',
label: 'Current Job ID',
type: 'id',
objectType: 'job',
showHyperlink: true,
readOnly: true
},
{
name: 'currentSubJob',
label: 'Current Sub Job',
type: 'object',
objectType: 'subJob',
required: false
},
{
name: 'currentSubJob._id',
label: 'Current Sub Job ID',
type: 'id',
objectType: 'subJob',
showHyperlink: true,
readOnly: true
},
{
name: 'alerts',
label: 'Alerts',
type: 'alerts',
required: false
} }
] ]
} }