Refactor PrinterProfiles and PrinterInfo components to streamline modal handling for new printer profiles. Removed the EditPrinterProfile component and simplified state management for profile modals. Updated NewPrinterProfile to accept default values and reset functionality, enhancing user experience when creating new profiles.
All checks were successful
farmcontrol/farmcontrol-ui/pipeline/head This commit looks good

This commit is contained in:
Tom Butcher 2026-07-24 21:13:41 +01:00
parent 2b24812723
commit 80ecc8a175
4 changed files with 183 additions and 311 deletions

View File

@ -1,8 +1,6 @@
import { useContext, useRef, useState } from 'react'
import { Button, Dropdown, Flex, Modal, Space } from 'antd'
import NewPrinterProfile, {
EditPrinterProfile
} from './PrinterProfiles/NewPrinterProfile'
import NewPrinterProfile from './PrinterProfiles/NewPrinterProfile'
import ColumnViewButton from '../common/ColumnViewButton'
import ExportListButton from '../common/ExportListButton'
import FilterSidebarButton from '../common/FilterSidebarButton'
@ -16,10 +14,7 @@ import useFilterSidebarVisibility from '../hooks/useFilterSidebarVisibility'
import useViewMode from '../hooks/useViewMode'
const PrinterProfiles = () => {
const { deleteObject } = useContext(ApiServerContext)
const [profileModal, setProfileModal] = useState({
open: false,
profileId: null
})
const [newProfileOpen, setNewProfileOpen] = useState(false)
const tableRef = useRef()
const [viewMode, setViewMode] = useViewMode('PrinterProfiles')
const [columnVisibility, setColumnVisibility] =
@ -45,17 +40,12 @@ const PrinterProfiles = () => {
if (key === 'reloadList') {
tableRef.current?.reload()
} else if (key === 'newPrinterProfile') {
setProfileModal({ open: true, profileId: null })
setNewProfileOpen(true)
}
}
}
const handleRowAction = (action, profile) => {
if (action.name === 'edit') {
setProfileModal({ open: true, profileId: profile._id })
return true
}
if (action.name === 'delete') {
Modal.confirm({
title: 'Delete printer profile?',
@ -112,29 +102,20 @@ const PrinterProfiles = () => {
</Flex>
<Modal
open={profileModal.open}
open={newProfileOpen}
footer={null}
width={800}
onCancel={() => setProfileModal({ open: false, profileId: null })}
onCancel={() => setNewProfileOpen(false)}
destroyOnHidden
>
{profileModal.open &&
(profileModal.profileId ? (
<EditPrinterProfile
profileId={profileModal.profileId}
onOk={() => {
setProfileModal({ open: false, profileId: null })
tableRef.current?.reload()
}}
/>
) : (
<NewPrinterProfile
onOk={() => {
setProfileModal({ open: false, profileId: null })
tableRef.current?.reload()
}}
/>
))}
{newProfileOpen && (
<NewPrinterProfile
onOk={() => {
setNewProfileOpen(false)
tableRef.current?.reload()
}}
/>
)}
</Modal>
</>
)

View File

@ -1,7 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import { useMemo } from 'react'
import PropTypes from 'prop-types'
import NewObjectForm from '../../common/NewObjectForm'
import ObjectForm from '../../common/ObjectForm'
import ObjectInfo from '../../common/ObjectInfo'
import WizardView from '../../common/WizardView'
@ -144,229 +143,140 @@ const SUMMARY_PROPERTIES = [
...OPTIONAL_PROPERTIES
]
const PrinterProfileWizard = ({
objectData,
formValid,
loading,
onSubmit,
editing,
printerId = null
}) => {
const visibleProperties = useMemo(() => {
if (!printerId) return undefined
return { printer: false, 'printer._id': false }
}, [printerId])
const steps = useMemo(
() => [
{
title: 'Required',
key: 'required',
content: (
<ObjectInfo
type='printerProfile'
properties={REQUIRED_PROPERTIES}
column={1}
bordered={false}
isEditing
labelWidth='75px'
required={true}
objectData={objectData}
visibleProperties={visibleProperties}
/>
)
},
{
title: 'Dimensions',
key: 'dimensions',
content: (
<ObjectInfo
type='printerProfile'
properties={DIMENSION_PROPERTIES}
column={1}
bordered={false}
isEditing
labelWidth='190px'
objectData={objectData}
/>
)
},
{
title: 'Extruders',
key: 'extruders',
content: (
<ObjectInfo
type='printerProfile'
properties={EXTRUDER_STEP_PROPERTIES}
column={1}
bordered={false}
isEditing
showLabels={false}
labelWidth='90px'
objectData={objectData}
/>
)
},
{
title: 'Motion',
key: 'motion',
content: (
<ObjectInfo
type='printerProfile'
properties={MOTION_PROPERTIES}
column={1}
bordered={false}
isEditing
labelWidth='185px'
objectData={objectData}
/>
)
},
{
title: 'Optional',
key: 'optional',
content: (
<ObjectInfo
type='printerProfile'
properties={OPTIONAL_PROPERTIES}
column={1}
labelWidth='170px'
bordered={false}
isEditing
objectData={objectData}
/>
)
},
{
title: 'Summary',
key: 'summary',
content: (
<ObjectInfo
type='printerProfile'
properties={SUMMARY_PROPERTIES}
column={1}
bordered={false}
isEditing={false}
labelWidth='210px'
objectData={objectData}
visibleProperties={visibleProperties}
/>
)
}
],
[objectData, visibleProperties]
const NewPrinterProfile = ({ onOk, reset, defaultValues = {} }) => {
const mergedDefaultValues = useMemo(
() => ({
...PRUSA_MK3S_PROFILE_DEFAULTS,
...defaultValues
}),
[defaultValues]
)
return (
<WizardView
sizeBarWidth='160px'
steps={steps}
loading={loading}
formValid={formValid}
title={editing ? 'Edit Printer Profile' : 'New Printer Profile'}
submitText={editing ? 'Save' : 'Create'}
onSubmit={onSubmit}
/>
<NewObjectForm
type='printerProfile'
reset={reset}
defaultValues={mergedDefaultValues}
>
{({ handleSubmit, submitLoading, objectData, formValid }) => {
const steps = [
{
title: 'Required',
key: 'required',
content: (
<ObjectInfo
type='printerProfile'
properties={REQUIRED_PROPERTIES}
column={1}
bordered={false}
isEditing
labelWidth='75px'
required={true}
objectData={objectData}
/>
)
},
{
title: 'Dimensions',
key: 'dimensions',
content: (
<ObjectInfo
type='printerProfile'
properties={DIMENSION_PROPERTIES}
column={1}
bordered={false}
isEditing
labelWidth='190px'
objectData={objectData}
/>
)
},
{
title: 'Extruders',
key: 'extruders',
content: (
<ObjectInfo
type='printerProfile'
properties={EXTRUDER_STEP_PROPERTIES}
column={1}
bordered={false}
isEditing
showLabels={false}
labelWidth='90px'
objectData={objectData}
/>
)
},
{
title: 'Motion',
key: 'motion',
content: (
<ObjectInfo
type='printerProfile'
properties={MOTION_PROPERTIES}
column={1}
bordered={false}
isEditing
labelWidth='185px'
objectData={objectData}
/>
)
},
{
title: 'Optional',
key: 'optional',
content: (
<ObjectInfo
type='printerProfile'
properties={OPTIONAL_PROPERTIES}
column={1}
labelWidth='170px'
bordered={false}
isEditing
objectData={objectData}
/>
)
},
{
title: 'Summary',
key: 'summary',
content: (
<ObjectInfo
type='printerProfile'
properties={SUMMARY_PROPERTIES}
column={1}
bordered={false}
isEditing={false}
labelWidth='210px'
objectData={objectData}
/>
)
}
]
return (
<WizardView
sizeBarWidth='160px'
steps={steps}
loading={submitLoading}
formValid={formValid}
title='New Printer Profile'
submitText='Create'
onSubmit={async () => {
const result = await handleSubmit()
if (result?._id) onOk(result)
}}
/>
)
}}
</NewObjectForm>
)
}
PrinterProfileWizard.propTypes = {
objectData: PropTypes.object,
formValid: PropTypes.bool.isRequired,
loading: PropTypes.bool,
onSubmit: PropTypes.func.isRequired,
editing: PropTypes.bool,
printerId: PropTypes.string
}
const NewPrinterProfile = ({ onOk, printerId = null }) => (
<NewObjectForm
type='printerProfile'
defaultValues={{
...PRUSA_MK3S_PROFILE_DEFAULTS,
...(printerId ? { printer: printerId } : {})
}}
>
{({ handleSubmit, submitLoading, objectData, formValid }) => (
<PrinterProfileWizard
objectData={objectData}
formValid={formValid}
loading={submitLoading}
printerId={printerId}
onSubmit={async () => {
const result = await handleSubmit()
if (result?._id) onOk(result)
}}
/>
)}
</NewObjectForm>
)
NewPrinterProfile.propTypes = {
onOk: PropTypes.func.isRequired,
printerId: PropTypes.string
}
export const EditPrinterProfile = ({ profileId, onOk, printerId = null }) => {
const formRef = useRef(null)
const startedEditingRef = useRef(false)
const saveRequestedRef = useRef(false)
const stateRef = useRef({})
const [formState, setFormState] = useState({
loading: true,
editLoading: false,
formValid: false,
isEditing: false,
objectData: {}
})
useEffect(() => {
if (
!formState.loading &&
!formState.isEditing &&
!startedEditingRef.current
) {
startedEditingRef.current = true
formRef.current?.startEditing()
}
}, [formState.isEditing, formState.loading])
return (
<ObjectForm
id={profileId}
type='printerProfile'
ref={formRef}
onStateChange={(nextState) => {
stateRef.current = { ...stateRef.current, ...nextState }
setFormState((current) => ({ ...current, ...nextState }))
if (saveRequestedRef.current && nextState.isEditing === false) {
saveRequestedRef.current = false
onOk(stateRef.current.objectData)
}
}}
>
{({ objectData, formValid, editLoading, handleUpdate }) => (
<PrinterProfileWizard
editing
objectData={objectData}
formValid={formValid}
loading={formState.loading || editLoading}
printerId={printerId}
onSubmit={() => {
saveRequestedRef.current = true
handleUpdate()
}}
/>
)}
</ObjectForm>
)
}
EditPrinterProfile.propTypes = {
profileId: PropTypes.string.isRequired,
onOk: PropTypes.func.isRequired,
printerId: PropTypes.string
reset: PropTypes.bool,
defaultValues: PropTypes.object
}
export default NewPrinterProfile

View File

@ -1,9 +1,7 @@
import { useRef, useState } from 'react'
import { useLocation } from 'react-router-dom'
import { Space, Flex, Card, Button, Modal } from 'antd'
import NewPrinterProfile, {
EditPrinterProfile
} from '../PrinterProfiles/NewPrinterProfile'
import { Space, Flex, Card, Modal } from 'antd'
import NewPrinterProfile from '../PrinterProfiles/NewPrinterProfile'
import { LoadingOutlined } from '@ant-design/icons'
import loglevel from 'loglevel'
import config from '../../../../config.js'
@ -25,7 +23,6 @@ import InfoCollapsePlaceholder from '../../common/InfoCollapsePlaceholder.jsx'
import DocumentPrintButton from '../../common/DocumentPrintButton.jsx'
import UserNotifierToggle from '../../common/UserNotifierToggle.jsx'
import ScrollBox from '../../common/ScrollBox.jsx'
import PlusIcon from '../../../Icons/PlusIcon.jsx'
import PrinterProfileIcon from '../../../Icons/PrinterProfileIcon.jsx'
const log = loglevel.getLogger('PrinterInfo')
log.setLevel(config.logLevel)
@ -52,15 +49,7 @@ const PrinterInfo = () => {
loading: false,
objectData: {}
})
const [profileModal, setProfileModal] = useState({
open: false,
profileId: null
})
const handleProfileSaved = () => {
setProfileModal({ open: false, profileId: null })
profilesTableRef.current?.reload()
}
const [newPrinterProfileOpen, setNewPrinterProfileOpen] = useState(false)
const actions = {
edit: () => {
@ -74,6 +63,10 @@ const PrinterInfo = () => {
finishEdit: () => {
objectFormRef?.current.handleUpdate()
return true
},
newPrinterProfile: () => {
setNewPrinterProfileOpen(true)
return true
}
}
@ -196,37 +189,15 @@ const PrinterInfo = () => {
{objectFormState.loading ? (
<InfoCollapsePlaceholder />
) : (
<Flex vertical gap='middle'>
<Flex>
<Button
icon={<PlusIcon />}
onClick={() =>
setProfileModal({ open: true, profileId: null })
}
>
New Printer Profile
</Button>
</Flex>
<ObjectTable
ref={profilesTableRef}
type='printerProfile'
masterFilter={{ printer: printerId }}
visibleColumns={{
printer: false,
'printer._id': false
}}
onRowAction={(action, profile) => {
if (action.name === 'edit') {
setProfileModal({
open: true,
profileId: profile._id
})
return true
}
return false
}}
/>
</Flex>
<ObjectTable
ref={profilesTableRef}
type='printerProfile'
masterFilter={{ printer: printerId }}
visibleColumns={{
printer: false,
'printer._id': false
}}
/>
)}
</InfoCollapse>
@ -265,25 +236,25 @@ const PrinterInfo = () => {
</ScrollBox>
</Flex>
<Modal
open={profileModal.open}
open={newPrinterProfileOpen}
styles={{ content: { paddingBottom: '24px' } }}
footer={null}
width={1000}
onCancel={() => setProfileModal({ open: false, profileId: null })}
destroyOnHidden
width={800}
onCancel={() => {
setNewPrinterProfileOpen(false)
}}
destroyOnHidden={true}
>
{profileModal.open &&
(profileModal.profileId ? (
<EditPrinterProfile
profileId={profileModal.profileId}
printerId={printerId}
onOk={handleProfileSaved}
/>
) : (
<NewPrinterProfile
printerId={printerId}
onOk={handleProfileSaved}
/>
))}
<NewPrinterProfile
onOk={() => {
setNewPrinterProfileOpen(false)
profilesTableRef.current?.reload()
}}
reset={newPrinterProfileOpen}
defaultValues={{
printer: { ...objectFormState.objectData }
}}
/>
</Modal>
</>
)

View File

@ -10,6 +10,7 @@ import StopCircleIcon from '../../components/Icons/StopCircleIcon'
import FilamentStockIcon from '../../components/Icons/FilamentStockIcon'
import ControlIcon from '../../components/Icons/ControlIcon'
import JobIcon from '../../components/Icons/JobIcon'
import PlusIcon from '../../components/Icons/PlusIcon'
export const Printer = {
name: 'printer',
@ -67,6 +68,15 @@ export const Printer = {
}
},
{ type: 'divider' },
{
name: 'newPrinterProfile',
label: 'New Printer Profile',
type: 'button',
icon: PlusIcon,
url: (_id) =>
`/dashboard/production/printers/info?printerId=${_id}&action=newPrinterProfile`
},
{ type: 'divider' },
{
name: 'restartSubmenu',
label: 'Restart',