282 lines
7.7 KiB
JavaScript
282 lines
7.7 KiB
JavaScript
import { useState, useContext, useEffect } from 'react'
|
|
import { Form, Flex, Descriptions, Alert } from 'antd'
|
|
import PropTypes from 'prop-types'
|
|
|
|
import PrinterTemperaturePanel from '../../common/PrinterTemperaturePanel'
|
|
|
|
import { LoadingOutlined } from '@ant-design/icons'
|
|
import ObjectSelect from '../../common/ObjectSelect'
|
|
import ObjectDisplay from '../../common/ObjectDisplay'
|
|
import WizardView from '../../common/WizardView'
|
|
import { ApiServerContext } from '../../context/ApiServerContext'
|
|
|
|
const LoadFilamentStock = ({
|
|
onOk,
|
|
reset,
|
|
printer = null,
|
|
filamentStockLoaded = false
|
|
}) => {
|
|
const { connected, subscribeToObjectEvent, sendObjectAction } =
|
|
useContext(ApiServerContext)
|
|
|
|
LoadFilamentStock.propTypes = {
|
|
onOk: PropTypes.func.isRequired,
|
|
reset: PropTypes.bool.isRequired,
|
|
printer: PropTypes.object,
|
|
filamentStockLoaded: PropTypes.bool
|
|
}
|
|
|
|
const initialLoadFilamentStockForm = {
|
|
printer: printer,
|
|
filamentStock: null
|
|
}
|
|
|
|
const [loadFilamentStockLoading, setLoadFilamentStockLoading] =
|
|
useState(false)
|
|
const [formValid, setFormValid] = useState(false)
|
|
const [currentTemperature, setCurrentTemperature] = useState(-1)
|
|
const [targetTemperature, setTargetTemperature] = useState(0)
|
|
const [filamentSensorDetected, setFilamentSensorDetected] =
|
|
useState(filamentStockLoaded)
|
|
const [loadFilamentStockForm] = Form.useForm()
|
|
const [loadFilamentStockFormValues, setLoadFilamentStockFormValues] =
|
|
useState(initialLoadFilamentStockForm)
|
|
|
|
const loadFilamentStockFormUpdateValues = Form.useWatch(
|
|
[],
|
|
loadFilamentStockForm
|
|
)
|
|
|
|
useEffect(() => {
|
|
if (printer?._id && connected) {
|
|
const temperatureEventUnsubscribe = subscribeToObjectEvent(
|
|
printer._id,
|
|
'printer',
|
|
'temperature',
|
|
(event) => {
|
|
if (event.data?.extruder?.current) {
|
|
setCurrentTemperature(event.data.extruder.current)
|
|
}
|
|
if (event.data?.extruder?.target) {
|
|
setTargetTemperature(event.data.extruder.target)
|
|
}
|
|
}
|
|
)
|
|
const filamentStockEventUnsubscribe = subscribeToObjectEvent(
|
|
printer._id,
|
|
'printer',
|
|
'filamentSensor',
|
|
(event) => {
|
|
console.log('filamentSensor', event.data)
|
|
setFilamentSensorDetected(event.data.detected)
|
|
}
|
|
)
|
|
return () => {
|
|
if (temperatureEventUnsubscribe) temperatureEventUnsubscribe()
|
|
if (filamentStockEventUnsubscribe) filamentStockEventUnsubscribe()
|
|
}
|
|
}
|
|
}, [printer?._id, connected])
|
|
|
|
useEffect(() => {
|
|
// Validate form fields
|
|
loadFilamentStockForm
|
|
.validateFields({
|
|
validateOnly: true
|
|
})
|
|
.then(() => {
|
|
const hasPrinter = Boolean(loadFilamentStockFormValues.printer)
|
|
const hasFilamentStock = Boolean(
|
|
loadFilamentStockFormValues.filamentStock
|
|
)
|
|
|
|
// Step 0 (Preheat): needs printer + filament detected + (temp reached or no temp set)
|
|
const preheatReady =
|
|
hasPrinter &&
|
|
filamentSensorDetected &&
|
|
(targetTemperature === 0 || currentTemperature >= targetTemperature)
|
|
|
|
// Step 1+ (Required/Summary): needs filamentStock selected
|
|
// Form is valid if preheat is ready (for step 0) OR filamentStock is selected (for step 1+)
|
|
// This allows progression: step 0 can proceed when preheat is ready,
|
|
// and step 1+ can proceed when filamentStock is selected
|
|
setFormValid(preheatReady || (hasPrinter && hasFilamentStock))
|
|
})
|
|
.catch(() => setFormValid(false))
|
|
}, [
|
|
loadFilamentStockForm,
|
|
loadFilamentStockFormUpdateValues,
|
|
loadFilamentStockFormValues,
|
|
filamentSensorDetected,
|
|
currentTemperature,
|
|
targetTemperature
|
|
])
|
|
|
|
const summaryItems = [
|
|
{
|
|
key: 'filamentStock',
|
|
label: 'Stock',
|
|
children: loadFilamentStockFormValues.filamentStock ? (
|
|
<ObjectDisplay
|
|
objectType='filamentStock'
|
|
object={loadFilamentStockFormValues.filamentStock}
|
|
/>
|
|
) : (
|
|
'n/a'
|
|
)
|
|
},
|
|
{
|
|
key: 'printer',
|
|
label: 'Printer',
|
|
children: loadFilamentStockFormValues.printer ? (
|
|
<ObjectDisplay
|
|
objectType='printer'
|
|
object={loadFilamentStockFormValues.printer}
|
|
/>
|
|
) : (
|
|
'n/a'
|
|
)
|
|
}
|
|
]
|
|
|
|
useEffect(() => {
|
|
if (reset) {
|
|
loadFilamentStockForm.resetFields()
|
|
}
|
|
}, [reset, loadFilamentStockForm])
|
|
|
|
const handleLoadFilamentStock = async () => {
|
|
setLoadFilamentStockLoading(true)
|
|
|
|
try {
|
|
// Set the extruder temperature
|
|
await sendObjectAction(
|
|
loadFilamentStockFormValues.printer._id,
|
|
'printer',
|
|
{
|
|
type: 'loadFilamentStock',
|
|
data: {
|
|
filamentStock: loadFilamentStockFormValues.filamentStock
|
|
}
|
|
}
|
|
)
|
|
onOk()
|
|
} finally {
|
|
setLoadFilamentStockLoading(false)
|
|
}
|
|
}
|
|
|
|
const steps = [
|
|
{
|
|
title: 'Preheat',
|
|
key: 'preHeat',
|
|
content: (
|
|
<Flex vertical gap={'middle'} style={{ paddingBottom: 16 }}>
|
|
<Form.Item
|
|
label='Printer'
|
|
name='printer'
|
|
style={{ margin: 0 }}
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please select a printer'
|
|
}
|
|
]}
|
|
>
|
|
<ObjectSelect type='printer' checkable={false} />
|
|
</Form.Item>
|
|
{targetTemperature == 0 ? (
|
|
<Alert
|
|
message={'Heat the extruder to begin loading filament.'}
|
|
type='info'
|
|
showIcon
|
|
/>
|
|
) : null}
|
|
{targetTemperature > 0 && currentTemperature < targetTemperature ? (
|
|
<Alert
|
|
message={'Heating extruder...'}
|
|
type='error'
|
|
showIcon
|
|
icon={<LoadingOutlined />}
|
|
/>
|
|
) : null}
|
|
|
|
{targetTemperature > 0 &&
|
|
currentTemperature >= targetTemperature &&
|
|
filamentSensorDetected == false ? (
|
|
<Alert
|
|
message={'Insert filament to continue'}
|
|
type='success'
|
|
showIcon
|
|
/>
|
|
) : null}
|
|
|
|
{loadFilamentStockFormValues.printer ? (
|
|
<PrinterTemperaturePanel
|
|
showBed={false}
|
|
showMoreInfo={false}
|
|
id={loadFilamentStockFormValues.printer._id}
|
|
/>
|
|
) : null}
|
|
</Flex>
|
|
)
|
|
},
|
|
{
|
|
title: 'Required',
|
|
key: 'required',
|
|
content: (
|
|
<>
|
|
<Form.Item
|
|
label='Stock:'
|
|
name='filamentStock'
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please enter a G Code File.'
|
|
}
|
|
]}
|
|
>
|
|
<ObjectSelect type='filamentStock' />
|
|
</Form.Item>
|
|
</>
|
|
)
|
|
},
|
|
{
|
|
title: 'Summary',
|
|
key: 'summary',
|
|
content: (
|
|
<Form.Item>
|
|
<Descriptions column={1} items={summaryItems} size={'small'} />
|
|
</Form.Item>
|
|
)
|
|
}
|
|
]
|
|
|
|
return (
|
|
<Form
|
|
name='loadFilamentStock'
|
|
autoComplete='off'
|
|
form={loadFilamentStockForm}
|
|
onFinish={handleLoadFilamentStock}
|
|
onValuesChange={(changedValues) =>
|
|
setLoadFilamentStockFormValues((prevValues) => ({
|
|
...prevValues,
|
|
...changedValues
|
|
}))
|
|
}
|
|
initialValues={initialLoadFilamentStockForm}
|
|
>
|
|
<WizardView
|
|
title='Load Filament Stock'
|
|
steps={steps}
|
|
onSubmit={() => loadFilamentStockForm.submit()}
|
|
formValid={formValid}
|
|
loading={loadFilamentStockLoading}
|
|
submitText='Done'
|
|
/>
|
|
</Form>
|
|
)
|
|
}
|
|
|
|
export default LoadFilamentStock
|