// PrinterSelect.js
import PropTypes from 'prop-types'
import { Tree, Card, Spin, Space, Button, message } from 'antd'
import { LoadingOutlined, ReloadOutlined } from '@ant-design/icons'
import React, { useState, useEffect, useContext, useCallback } from 'react'
import PrinterState from './PrinterState'
import axios from 'axios'
import { SocketContext } from '../context/SocketContext'
import SubJobState from './SubJobState'
const SubJobsTree = ({ printJobData }) => {
const [treeData, setTreeData] = useState([])
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
const { socket } = useContext(SocketContext)
const [messageApi] = message.useMessage()
const [expandedKeys, setExpandedKeys] = useState([])
const [currentPrintJobData, setCurrentPrintJobData] = useState(null)
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: (
),
key: `subjob-${subJob._id}`,
isLeaf: true
}
})
}
})
setTreeData(printerNodes)
},
[expandedKeys]
)
useEffect(() => {
buildTreeData(currentPrintJobData)
}, [currentPrintJobData])
useEffect(() => {
const initializeData = async () => {
if (!printJobData) {
try {
setLoading(true)
const response = await axios.get('http://localhost:8080/printjobs', {
headers: { Accept: 'application/json' },
withCredentials: true
})
if (response.data) {
setCurrentPrintJobData(response.data)
}
} catch (err) {
setError('Failed to fetch print job details')
messageApi.error('Failed to fetch print job details')
} finally {
setLoading(false)
}
} else {
setCurrentPrintJobData(printJobData)
}
}
initializeData()
// Add socket.io event listener for deployment updates
if (socket) {
socket.on('notify_deployment_update', (updateData) => {
console.log('Received deployment update:', updateData)
setCurrentPrintJobData((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
})
})
socket.on('notify_subjob_update', (updateData) => {
// Handle sub-job updates
if (updateData.subJobId) {
console.log('Received subjob update:', updateData)
setCurrentPrintJobData((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 (socket) {
socket.off('notify_deployment_update')
}
}
}, [printJobData, socket])
if (loading) {
return (
} />
)
}
if (error) {
return (
{error}
}
onClick={() => buildTreeData(printJobData)}
>
Retry
)
}
return (
)
}
SubJobsTree.propTypes = {
printJobData: PropTypes.object.isRequired
}
export default SubJobsTree