218 lines
6.3 KiB
JavaScript
218 lines
6.3 KiB
JavaScript
// 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 ? (
|
|
<Space size={5}>
|
|
<PrinterIcon />
|
|
<PrinterState
|
|
printer={printerData}
|
|
text={printerData.name}
|
|
showProgress={false}
|
|
/>
|
|
</Space>
|
|
) : (
|
|
<Spin indicator={<LoadingOutlined />} />
|
|
),
|
|
key: `printer-${printerData.id}`,
|
|
children: printerSubJobs.map((subJob) => {
|
|
return {
|
|
title: (
|
|
<Space>
|
|
<SubJobIcon />
|
|
{'Sub Job #' + subJob?.number.toString().padStart(2, '0')}
|
|
<SubJobState subJob={subJob} showProgress={true} />
|
|
</Space>
|
|
),
|
|
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 (
|
|
<Space
|
|
direction='vertical'
|
|
style={{ width: '100%', textAlign: 'center' }}
|
|
>
|
|
<p>{error}</p>
|
|
<Button icon={<ReloadIcon />} onClick={() => buildTreeData(jobData)}>
|
|
Retry
|
|
</Button>
|
|
</Space>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<Spin indicator={<LoadingOutlined />} spinning={treeLoading}>
|
|
<Card style={{ minHeight: 160 }}>
|
|
<Tree
|
|
treeData={treeData}
|
|
expandedKeys={expandedKeys}
|
|
onExpand={setExpandedKeys}
|
|
onSelect={handleNodeClick}
|
|
showLine={true}
|
|
/>
|
|
</Card>
|
|
</Spin>
|
|
)
|
|
}
|
|
|
|
SubJobsTree.propTypes = {
|
|
jobData: PropTypes.object.isRequired,
|
|
loading: PropTypes.bool
|
|
}
|
|
|
|
export default SubJobsTree
|