Tom Butcher 4c19df717b Enhance SlicerIntegration layout for better responsiveness
- Wrapped the ObjectProperty component in a div with defined width properties to improve layout consistency and responsiveness within the SlicerIntegration component.
- Ensured that the display adapts better to varying screen sizes, enhancing user experience.
2026-07-26 18:37:42 +01:00

234 lines
7.1 KiB
JavaScript

import { useContext, useEffect, useState } from 'react'
import { Divider, Flex, Layout, Typography, Button, Badge, Modal } from 'antd'
import { LoadingOutlined } from '@ant-design/icons'
import { useLocation } from 'react-router-dom'
import ControlPrinter from './ControlPrinter.jsx'
import SlicerUploadFlow from './SlicerUploadFlow.jsx'
import PrinterIcon from '../../../Icons/PrinterIcon.jsx'
import ObjectForm from '../../common/ObjectForm.jsx'
import FileIcon from '../../../Icons/FileIcon.jsx'
import ObjectProperty from '../../common/ObjectProperty.jsx'
import { getModelProperty } from '../../../../database/ObjectModels.js'
import { ApiServerContext } from '../../context/ApiServerContext.jsx'
import { useThemeContext } from '../../context/ThemeContext.jsx'
const { Content } = Layout
const { Title } = Typography
const SlicerIntegration = () => {
const location = useLocation()
const printerId = new URLSearchParams(location.search).get('printerId')
const { updateObject } = useContext(ApiServerContext)
const [pendingSlicerUploads, setPendingSlicerUploads] = useState([])
const [currentPendingSlicerUpload, setCurrentPendingSlicerUpload] =
useState(null)
const { setPrimaryColorOverride } = useThemeContext()
useEffect(() => {
setPrimaryColorOverride('#00baa8')
}, [setPrimaryColorOverride])
const [objectFormState, setEditFormState] = useState({
isEditing: false,
editLoading: false,
formValid: false,
activities: [],
loading: false,
objectData: {
pendingSlicerUploads: []
}
})
const [showSlicerUploadFlow, setShowSlicerUploadFlow] = useState(false)
useEffect(() => {
setPendingSlicerUploads(
objectFormState.objectData?.pendingSlicerUploads || []
)
}, [objectFormState.objectData?.pendingSlicerUploads])
useEffect(() => {
const nextUpload = pendingSlicerUploads.find(
(upload) => upload.new === true
)
if (nextUpload) {
setCurrentPendingSlicerUpload(nextUpload)
setShowSlicerUploadFlow(true)
} else {
setCurrentPendingSlicerUpload(null)
setShowSlicerUploadFlow(false)
}
}, [pendingSlicerUploads])
const showPendingSlicerUpload = () => {
const upload =
pendingSlicerUploads.find(
(pendingUpload) => pendingUpload.new === true
) || pendingSlicerUploads[0]
if (upload) {
setCurrentPendingSlicerUpload(upload)
setShowSlicerUploadFlow(true)
}
}
const handleGCodeFileCreated = async (gcodeFile) => {
const updatedUploads = pendingSlicerUploads.map((upload) =>
upload._id === currentPendingSlicerUpload?._id
? { ...upload, gcodeFile: gcodeFile }
: upload
)
setPendingSlicerUploads(updatedUploads)
setCurrentPendingSlicerUpload((previous) => ({
...previous,
gcodeFile
}))
await updateObject(printerId, 'printer', {
...objectFormState.objectData,
pendingSlicerUploads: updatedUploads
})
}
const handleJobCreated = async (job) => {
const updatedUploads = pendingSlicerUploads.map((upload) =>
upload._id === currentPendingSlicerUpload?._id
? { ...upload, job }
: upload
)
setPendingSlicerUploads(updatedUploads)
setCurrentPendingSlicerUpload((previous) => ({
...previous,
job
}))
await updateObject(printerId, 'printer', {
...objectFormState.objectData,
pendingSlicerUploads: updatedUploads
})
}
const handleSlicerUploadComplete = async () => {
const updatedUploads = pendingSlicerUploads.filter(
(upload) => upload._id !== currentPendingSlicerUpload?._id
)
setPendingSlicerUploads(updatedUploads)
await updateObject(printerId, 'printer', {
...objectFormState.objectData,
pendingSlicerUploads: updatedUploads
})
}
const handleSlicerUploadFlowClosed = async () => {
const updatedUploads = pendingSlicerUploads.map((upload) =>
upload._id === currentPendingSlicerUpload?._id
? { ...upload, new: false }
: upload
)
setPendingSlicerUploads(updatedUploads)
await updateObject(printerId, 'printer', {
...objectFormState.objectData,
pendingSlicerUploads: updatedUploads
})
}
const slicerUploadsButton = () => {
if (pendingSlicerUploads.length > 0) {
return (
<Badge
count={pendingSlicerUploads.length}
style={{ marginTop: '8px' }}
size='small'
>
<Button
type='text'
icon={<FileIcon />}
onClick={showPendingSlicerUpload}
/>
</Badge>
)
}
return null
}
return (
<Layout style={{ height: 'var(--unit-100vh)' }}>
<Layout style={{ padding: '24px' }}>
<Content>
<Flex vertical style={{ height: '100%' }} gap='20px'>
<ObjectForm
id={printerId}
type='printer'
onStateChange={(state) =>
setEditFormState((previousState) => ({
...previousState,
...state
}))
}
>
{({ loading, objectData }) => (
<Flex justify='space-between' align='center'>
<Flex align='center' gap='middle'>
{loading ? (
<LoadingOutlined spin style={{ fontSize: '26px' }} />
) : (
<PrinterIcon style={{ fontSize: '26px' }} />
)}
<Title level={3} style={{ margin: 0 }}>
{loading
? 'Loading...'
: objectData?.name || 'Slicer Integration'}
</Title>
{!loading && (
<div
style={{
maxWidth: '400px',
width: '400px',
minWidth: '100px'
}}
>
<ObjectProperty
objectData={objectData}
{...getModelProperty('printer', 'state')}
/>
</div>
)}
</Flex>
{slicerUploadsButton()}
</Flex>
)}
</ObjectForm>
<Divider style={{ margin: '0' }} />
<ControlPrinter slicerIntegration={true} />
</Flex>
</Content>
<Modal
open={showSlicerUploadFlow}
onCancel={() => setShowSlicerUploadFlow(false)}
afterClose={handleSlicerUploadFlowClosed}
footer={null}
width={740}
destroyOnHidden={true}
>
{currentPendingSlicerUpload && (
<SlicerUploadFlow
key={currentPendingSlicerUpload._id}
currentPendingSlicerUpload={currentPendingSlicerUpload}
printer={objectFormState.objectData}
onGCodeFileCreated={handleGCodeFileCreated}
onJobCreated={handleJobCreated}
onComplete={handleSlicerUploadComplete}
/>
)}
</Modal>
</Layout>
</Layout>
)
}
export default SlicerIntegration