From d7ad2208d44354232aab884cb805625a59984ed0 Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Mon, 20 Jul 2026 02:11:01 +0100 Subject: [PATCH] Enhance GCodeFile, DeployJob, NewJob, and ControlPrinter components with slicer integration support - Updated NewGCodeFile and NewJob components to include slicerIntegration, currentStep, and onStepChange props for improved workflow management. - Modified DeployJob to handle printer online status and added slicerIntegration support for conditional rendering of actions and steps. - Enhanced ControlPrinter to manage visibility of actions based on slicerIntegration, improving user experience in printer control. - Refactored form handling to pass result objects to onOk callbacks, ensuring better data handling upon submission. --- .../Production/GCodeFiles/NewGCodeFile.jsx | 73 +++++++---- .../Dashboard/Production/Jobs/DeployJob.jsx | 117 +++++++++++++++--- .../Dashboard/Production/Jobs/NewJob.jsx | 39 ++++-- .../Production/Printers/ControlPrinter.jsx | 53 ++++---- 4 files changed, 202 insertions(+), 80 deletions(-) diff --git a/src/components/Dashboard/Production/GCodeFiles/NewGCodeFile.jsx b/src/components/Dashboard/Production/GCodeFiles/NewGCodeFile.jsx index f5fa03d..aa83339 100644 --- a/src/components/Dashboard/Production/GCodeFiles/NewGCodeFile.jsx +++ b/src/components/Dashboard/Production/GCodeFiles/NewGCodeFile.jsx @@ -1,35 +1,49 @@ +import { useMemo } from 'react' import PropTypes from 'prop-types' import ObjectInfo from '../../common/ObjectInfo' import NewObjectForm from '../../common/NewObjectForm' import WizardView from '../../common/WizardView' -const NewGCodeFile = ({ onOk, defaultValues }) => { +const NewGCodeFile = ({ + onOk, + defaultValues, + slicerIntegration = false, + shouldPrint = false, + currentStep, + onStepChange +}) => { + const initialValues = useMemo( + () => ({ + state: { type: 'draft' }, + ...defaultValues + }), + [defaultValues] + ) + return ( - + {({ handleSubmit, submitLoading, objectData, formValid }) => { const steps = [ - { - title: 'Upload', - key: 'upload', - content: ( - - ) - }, + ...(!slicerIntegration + ? [ + { + title: 'Upload', + key: 'upload', + content: ( + + ) + } + ] + : []), { title: 'Required', key: 'required', @@ -73,10 +87,13 @@ const NewGCodeFile = ({ onOk, defaultValues }) => { loading={submitLoading} formValid={formValid} title='New GCode File' + showSteps={!slicerIntegration || !shouldPrint} + currentStep={currentStep} + onStepChange={onStepChange} onSubmit={async () => { const result = await handleSubmit() if (result) { - onOk() + onOk(result) } }} /> @@ -89,7 +106,11 @@ const NewGCodeFile = ({ onOk, defaultValues }) => { NewGCodeFile.propTypes = { onOk: PropTypes.func.isRequired, reset: PropTypes.bool, - defaultValues: PropTypes.object + defaultValues: PropTypes.object, + slicerIntegration: PropTypes.bool, + currentStep: PropTypes.number, + onStepChange: PropTypes.func, + shouldPrint: PropTypes.bool } export default NewGCodeFile diff --git a/src/components/Dashboard/Production/Jobs/DeployJob.jsx b/src/components/Dashboard/Production/Jobs/DeployJob.jsx index f58a38b..09f2bc6 100644 --- a/src/components/Dashboard/Production/Jobs/DeployJob.jsx +++ b/src/components/Dashboard/Production/Jobs/DeployJob.jsx @@ -2,17 +2,20 @@ import { useState, useContext, useEffect, useCallback } from 'react' import PropTypes from 'prop-types' import WizardView from '../../common/WizardView' import { ApiServerContext } from '../../context/ApiServerContext' -import { Flex, Typography } from 'antd' +import { Descriptions, Flex, Typography } from 'antd' import ObjectTable from '../../common/ObjectTable' -import ObjectSelect from '../../common/ObjectSelect' - +import ObjectProperty from '../../common/ObjectProperty' const { Text } = Typography - -const DeployJob = ({ onOk, objectData = undefined }) => { +const DeployJob = ({ + onOk, + objectData = undefined, + slicerIntegration = false +}) => { const [deployLoading, setDeployLoading] = useState(false) const [job, setJob] = useState(objectData) const [deployedSubJobsCount, setDeployedSubJobsCount] = useState(0) const [subJobsCount, setSubJobsCount] = useState(999) + const [allPrintersOnline, setAllPrintersOnline] = useState(false) const { sendObjectAction, fetchObjects } = useContext(ApiServerContext) const handleDeploy = useCallback(async () => { @@ -51,21 +54,94 @@ const DeployJob = ({ onOk, objectData = undefined }) => { } }, [deployedSubJobsCount, subJobsCount, deployLoading, onOk]) + useEffect(() => { + if (objectData?.printers) { + if (objectData.printers.every((printer) => printer.online)) { + setAllPrintersOnline(true) + } else { + setAllPrintersOnline(false) + } + } else { + setAllPrintersOnline(false) + } + }, [objectData]) + + console.log(objectData) + const steps = [ { title: 'Confirm', key: 'confirm', content: ( - - Job: - { - setJob(newJob) - }} + + + Job + + ), + children: ( +
+ object.job} + readOnly={true} + isEditing={true} + objectType={'job'} + onChange={(newJob) => { + setJob(newJob) + }} + /> +
+ ) + }, + { + label: ( + + Printers + + ), + children: ( +
+ object.printers} + readOnly={true} + isEditing={true} + objectType={'printer'} + /> +
+ ) + } + ]} />
@@ -74,11 +150,11 @@ const DeployJob = ({ onOk, objectData = undefined }) => { scrollHeight={'200px'} visibleColumns={{ printer: false, - 'job._id': false, - 'printer._id': false + job: false }} masterFilter={{ 'job._id': job?._id }} size={'small'} + showActions={!slicerIntegration} />
) @@ -89,9 +165,13 @@ const DeployJob = ({ onOk, objectData = undefined }) => { { + onOk() + }} submitText='Deploy' progress={(deployedSubJobsCount / subJobsCount) * 100} onSubmit={() => { @@ -104,7 +184,8 @@ const DeployJob = ({ onOk, objectData = undefined }) => { DeployJob.propTypes = { onOk: PropTypes.func.isRequired, objectData: PropTypes.object, - reset: PropTypes.bool + reset: PropTypes.bool, + slicerIntegration: PropTypes.bool } export default DeployJob diff --git a/src/components/Dashboard/Production/Jobs/NewJob.jsx b/src/components/Dashboard/Production/Jobs/NewJob.jsx index c014b51..908bc29 100644 --- a/src/components/Dashboard/Production/Jobs/NewJob.jsx +++ b/src/components/Dashboard/Production/Jobs/NewJob.jsx @@ -1,17 +1,26 @@ +import { useMemo } from 'react' import PropTypes from 'prop-types' import ObjectInfo from '../../common/ObjectInfo' import NewObjectForm from '../../common/NewObjectForm' import WizardView from '../../common/WizardView' -const NewJob = ({ onOk, defaultValues }) => { +const NewJob = ({ + onOk, + defaultValues, + slicerIntegration = false, + currentStep, + onStepChange +}) => { + const initialValues = useMemo( + () => ({ + state: { type: 'draft' }, + ...defaultValues + }), + [defaultValues] + ) + return ( - + {({ handleSubmit, submitLoading, objectData, formValid }) => { const steps = [ { @@ -59,10 +68,17 @@ const NewJob = ({ onOk, defaultValues }) => { loading={submitLoading} formValid={formValid} title='New Job' + showSteps={!slicerIntegration} + currentStep={currentStep} + onStepChange={onStepChange} + showSkipButton={slicerIntegration} + onSkip={() => { + onOk(null) + }} onSubmit={async () => { const result = await handleSubmit() if (result) { - onOk() + onOk(result) } }} /> @@ -75,7 +91,10 @@ const NewJob = ({ onOk, defaultValues }) => { NewJob.propTypes = { onOk: PropTypes.func.isRequired, reset: PropTypes.bool, - defaultValues: PropTypes.object + defaultValues: PropTypes.object, + slicerIntegration: PropTypes.bool, + currentStep: PropTypes.number, + onStepChange: PropTypes.func } export default NewJob diff --git a/src/components/Dashboard/Production/Printers/ControlPrinter.jsx b/src/components/Dashboard/Production/Printers/ControlPrinter.jsx index 06a5f6c..9249f98 100644 --- a/src/components/Dashboard/Production/Printers/ControlPrinter.jsx +++ b/src/components/Dashboard/Production/Printers/ControlPrinter.jsx @@ -9,9 +9,9 @@ import InfoCollapse from '../../common/InfoCollapse.jsx' import ViewButton from '../../common/ViewButton.jsx' import NoteIcon from '../../../Icons/NoteIcon.jsx' import ObjectForm from '../../common/ObjectForm.jsx' -import EditButtons from '../../common/EditButtons.jsx' import ActionHandler from '../../common/ActionHandler.jsx' import ObjectActions from '../../common/ObjectActions.jsx' +import PropTypes from 'prop-types' import ObjectInfo from '../../common/ObjectInfo.jsx' import PrinterIcon from '../../../Icons/PrinterIcon.jsx' @@ -35,7 +35,7 @@ import ScrollBox from '../../common/ScrollBox.jsx' const log = loglevel.getLogger('ControlPrinter') log.setLevel(config.logLevel) -const ControlPrinter = () => { +const ControlPrinter = ({ slicerIntegration = false }) => { const location = useLocation() const objectFormRef = useRef(null) const actionHandlerRef = useRef(null) @@ -226,7 +226,11 @@ const ControlPrinter = () => { type='printer' id={printerId} disabled={objectFormState.loading} - visibleActions={{ edit: false }} + visibleActions={{ + edit: false, + info: !slicerIntegration, + control: !slicerIntegration + }} objectData={objectFormState.objectData} /> { /> - - { - actionHandlerRef.current.callAction('finishEdit') - }} - cancelEditing={() => { - actionHandlerRef.current.callAction('cancelEdit') - }} - startEditing={() => { - actionHandlerRef.current.callAction('edit') - }} - editLoading={objectFormState.editLoading} - formValid={objectFormState.formValid} - disabled={objectFormState.lock?.locked || objectFormState.loading} - loading={objectFormState.editLoading} - /> - @@ -353,11 +339,16 @@ const ControlPrinter = () => { currentSubJob: false, 'currentSubJob._id': false, createdAt: false, - updatedAt: false + updatedAt: false, + state: !slicerIntegration, + name: !slicerIntegration + }} + objectPropertyProps={{ + showHyperlink: !slicerIntegration }} objectData={printerObjectData} type='printer' - labelWidth='100px' + labelWidth='120px' /> ) }} @@ -386,12 +377,15 @@ const ControlPrinter = () => { @@ -428,12 +422,15 @@ const ControlPrinter = () => { @@ -474,7 +471,7 @@ const ControlPrinter = () => { { ) } +ControlPrinter.propTypes = { + slicerIntegration: PropTypes.bool +} + export default ControlPrinter