206 lines
5.7 KiB
JavaScript
206 lines
5.7 KiB
JavaScript
// 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 ? (
|
|
<PrinterState
|
|
printer={printerData}
|
|
text={printerData.name}
|
|
showProgress={false}
|
|
/>
|
|
) : (
|
|
<Spin indicator={<LoadingOutlined />} />
|
|
),
|
|
key: `printer-${printerData.id}`,
|
|
children: printerSubJobs.map((subJob) => {
|
|
return {
|
|
title: (
|
|
<SubJobState
|
|
subJob={subJob}
|
|
text={`Subjob #${subJob.number}`}
|
|
showProgress={true}
|
|
/>
|
|
),
|
|
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 (
|
|
<div style={{ textAlign: 'center', padding: '20px' }}>
|
|
<Spin indicator={<LoadingOutlined style={{ fontSize: 24 }} spin />} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<Space
|
|
direction='vertical'
|
|
style={{ width: '100%', textAlign: 'center' }}
|
|
>
|
|
<p>{error}</p>
|
|
<Button
|
|
icon={<ReloadOutlined />}
|
|
onClick={() => buildTreeData(printJobData)}
|
|
>
|
|
Retry
|
|
</Button>
|
|
</Space>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Card>
|
|
<Tree
|
|
treeData={treeData}
|
|
expandedKeys={expandedKeys}
|
|
onExpand={setExpandedKeys}
|
|
/>
|
|
</Card>
|
|
)
|
|
}
|
|
|
|
SubJobsTree.propTypes = {
|
|
printJobData: PropTypes.object.isRequired
|
|
}
|
|
|
|
export default SubJobsTree
|