// PrinterSelect.js import PropTypes from 'prop-types' import { Tree, Card, Spin, Space, Button, message } from 'antd' import { LoadingOutlined } from '@ant-design/icons' import React, { useState, useEffect, useContext, useCallback } from 'react' import { useNavigate } from 'react-router-dom' import PrinterState from './PrinterState' import axios from 'axios' import { PrintServerContext } from '../context/PrintServerContext' import PrinterIcon from '../../Icons/PrinterIcon' import SubJobState from './SubJobState' import SubJobIcon from '../../Icons/SubJobIcon' import ReloadIcon from '../../Icons/ReloadIcon' import config from '../../../config' const SubJobsTree = ({ jobData, loading }) => { const [treeData, setTreeData] = useState([]) const [treeLoading, setTreeLoading] = useState(loading) const [error, setError] = useState(null) const { printServer } = useContext(PrintServerContext) const [messageApi] = message.useMessage() const [expandedKeys, setExpandedKeys] = useState([]) const [currentJobData, setCurrentJobData] = useState(null) const navigate = useNavigate() const buildTreeData = useCallback( (jobData) => { if (!jobData?.subJobs?.length) { setTreeData([]) setExpandedKeys([]) return } // Create tree nodes for each printer const printerNodes = jobData.printers.map((printerData) => { // Find subjobs for this printer const printerSubJobs = jobData.subJobs.filter( (subJob) => subJob.printer === printerData.id ) setExpandedKeys((prev) => [...prev, `printer-${printerData.id}`]) return { title: printerData.state ? ( ) : ( } /> ), key: `printer-${printerData.id}`, children: printerSubJobs.map((subJob) => { return { title: ( {'Sub Job #' + subJob?.number.toString().padStart(2, '0')} ), key: `subjob-${subJob._id}`, isLeaf: true } }) } }) setTreeData(printerNodes) }, [expandedKeys] ) const handleNodeClick = (selectedKeys) => { const key = selectedKeys[0] if (key.startsWith('printer-')) { const printerId = key.replace('printer-', '') navigate(`/dashboard/production/printers/info?printerId=${printerId}`) } } useEffect(() => { buildTreeData(currentJobData) }, [currentJobData]) useEffect(() => { const initializeData = async () => { if (!jobData) { try { setTreeLoading(true) const response = await axios.get(`${config.backendUrl}/jobs`, { headers: { Accept: 'application/json' }, withCredentials: true }) if (response.data) { setCurrentJobData(response.data) } } catch (err) { setError('Failed to fetch print job details') messageApi.error('Failed to fetch print job details') } finally { setTreeLoading(false) } } else { setCurrentJobData(jobData) } } initializeData() // Add printServer.io event listener for deployment updates if (printServer) { printServer.on('notify_deployment_update', (updateData) => { console.log('Received deployment update:', updateData) setCurrentJobData((prevData) => { if (!prevData) return prevData // Handle printer updates if (updateData.printerId) { return { ...prevData, printers: prevData.printers.map((printer) => { if ( printer.id === updateData.printerId && updateData.state == 'deploying' ) { return { ...printer, deploymentProgress: updateData.progress } } else if ( printer.id === updateData.printerId && updateData.state == 'complete' ) { return { ...printer, deploymentProgress: undefined } } return printer }) } } return prevData }) }) printServer.on('notify_subjob_update', (updateData) => { // Handle sub-job updates if (updateData.subJobId) { console.log('Received subjob update:', updateData) setCurrentJobData((prevData) => { if (!prevData) return prevData return { ...prevData, // eslint-disable-next-line camelcase subJobs: prevData.subJobs.map((subJob) => { if (subJob._id === updateData._id) { return { ...subJob, state: updateData.state, subJobId: updateData.subJobId } } return subJob }) } }) } }) } return () => { if (printServer) { printServer.off('notify_deployment_update') } } }, [jobData, printServer]) if (error) { return (

{error}

) } return ( } spinning={treeLoading}> ) } SubJobsTree.propTypes = { jobData: PropTypes.object.isRequired, loading: PropTypes.bool } export default SubJobsTree