Refactor NewPrinter component to utilize NewObjectForm and WizardView for improved structure and user experience; streamline printer setup process and enhance form validation.
This commit is contained in:
parent
5300874b80
commit
6c0933b797
@ -1,564 +1,109 @@
|
|||||||
import { useState, useContext, useEffect, useCallback } from 'react'
|
|
||||||
import axios from 'axios'
|
|
||||||
import {
|
|
||||||
Form,
|
|
||||||
Button,
|
|
||||||
message,
|
|
||||||
Typography,
|
|
||||||
Flex,
|
|
||||||
Steps,
|
|
||||||
Divider,
|
|
||||||
Input,
|
|
||||||
Select,
|
|
||||||
Space,
|
|
||||||
Descriptions,
|
|
||||||
List,
|
|
||||||
InputNumber,
|
|
||||||
notification,
|
|
||||||
Progress,
|
|
||||||
Modal,
|
|
||||||
Radio
|
|
||||||
} from 'antd'
|
|
||||||
import { SearchOutlined, SettingOutlined } from '@ant-design/icons'
|
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { PrintServerContext } from '../../context/PrintServerContext'
|
import ObjectInfo from '../../common/ObjectInfo'
|
||||||
import EditIcon from '../../../Icons/EditIcon.jsx'
|
import NewObjectForm from '../../common/NewObjectForm'
|
||||||
|
import WizardView from '../../common/WizardView'
|
||||||
|
|
||||||
import config from '../../../../config.js'
|
const NewPrinter = ({ onOk }) => {
|
||||||
|
return (
|
||||||
const { Title } = Typography
|
<NewObjectForm
|
||||||
|
type={'printer'}
|
||||||
const initialNewPrinterForm = {
|
defaultValues={{
|
||||||
moonraker: {
|
moonraker: {
|
||||||
protocol: 'ws',
|
port: 7125,
|
||||||
host: '',
|
protocol: 'ws'
|
||||||
port: '',
|
},
|
||||||
apiKey: ''
|
active: true
|
||||||
}
|
}}
|
||||||
|
>
|
||||||
|
{({ handleSubmit, submitLoading, objectData, formValid }) => {
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
title: 'Required',
|
||||||
|
key: 'required',
|
||||||
|
content: (
|
||||||
|
<ObjectInfo
|
||||||
|
type='printer'
|
||||||
|
column={1}
|
||||||
|
bordered={false}
|
||||||
|
isEditing={true}
|
||||||
|
required={true}
|
||||||
|
objectData={objectData}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Optional',
|
||||||
|
key: 'optional',
|
||||||
|
content: (
|
||||||
|
<ObjectInfo
|
||||||
|
type='printer'
|
||||||
|
column={1}
|
||||||
|
bordered={false}
|
||||||
|
isEditing={true}
|
||||||
|
required={false}
|
||||||
|
objectData={objectData}
|
||||||
|
visibleProperties={{
|
||||||
|
firmware: false,
|
||||||
|
currentFilamentStock: false,
|
||||||
|
'currentFilamentStock._id': false,
|
||||||
|
currentJob: false,
|
||||||
|
'currentJob._id': false,
|
||||||
|
currentSubJob: false,
|
||||||
|
'currentSubJob._id': false,
|
||||||
|
alerts: false
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Summary',
|
||||||
|
key: 'summary',
|
||||||
|
content: (
|
||||||
|
<ObjectInfo
|
||||||
|
type='printer'
|
||||||
|
column={1}
|
||||||
|
bordered={false}
|
||||||
|
visibleProperties={{
|
||||||
|
_id: false,
|
||||||
|
createdAt: false,
|
||||||
|
updatedAt: false,
|
||||||
|
connectedAt: false,
|
||||||
|
state: false,
|
||||||
|
firmware: false,
|
||||||
|
currentFilamentStock: false,
|
||||||
|
'currentFilamentStock._id': false,
|
||||||
|
currentJob: false,
|
||||||
|
'currentJob._id': false,
|
||||||
|
currentSubJob: false,
|
||||||
|
'currentSubJob._id': false,
|
||||||
|
alerts: false
|
||||||
|
}}
|
||||||
|
isEditing={false}
|
||||||
|
objectData={objectData}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<WizardView
|
||||||
|
steps={steps}
|
||||||
|
loading={submitLoading}
|
||||||
|
formValid={formValid}
|
||||||
|
title='New Printer'
|
||||||
|
onSubmit={() => {
|
||||||
|
handleSubmit()
|
||||||
|
onOk()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</NewObjectForm>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const NewPrinter = ({ onOk, reset }) => {
|
NewPrinter.propTypes = {
|
||||||
NewPrinter.propTypes = {
|
onOk: PropTypes.func.isRequired,
|
||||||
onOk: PropTypes.func.isRequired,
|
reset: PropTypes.bool
|
||||||
reset: PropTypes.bool.isRequired
|
|
||||||
}
|
|
||||||
|
|
||||||
const { printServer } = useContext(PrintServerContext)
|
|
||||||
const [messageApi, contextHolder] = message.useMessage()
|
|
||||||
const [notificationApi, notificationContextHolder] =
|
|
||||||
notification.useNotification()
|
|
||||||
const [newPrinterLoading, setNewPrinterLoading] = useState(false)
|
|
||||||
const [currentStep, setCurrentStep] = useState(0)
|
|
||||||
const [nextEnabled, setNextEnabled] = useState(false)
|
|
||||||
const [newPrinterForm] = Form.useForm()
|
|
||||||
const [newPrinterFormValues, setNewPrinterFormValues] = useState(
|
|
||||||
initialNewPrinterForm
|
|
||||||
)
|
|
||||||
const [discoveredPrinters, setDiscoveredPrinters] = useState([])
|
|
||||||
const [discovering, setDiscovering] = useState(false)
|
|
||||||
const [showManualSetup, setShowManualSetup] = useState(false)
|
|
||||||
const [scanPort, setScanPort] = useState(7125)
|
|
||||||
const [scanProtocol, setScanProtocol] = useState('ws')
|
|
||||||
const [editingHostname, setEditingHostname] = useState(null)
|
|
||||||
const [hostnameInput, setHostnameInput] = useState('')
|
|
||||||
const [initialized, setInitialized] = useState(false)
|
|
||||||
|
|
||||||
const newPrinterFormUpdateValues = Form.useWatch([], newPrinterForm)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
newPrinterForm
|
|
||||||
.validateFields({
|
|
||||||
validateOnly: true
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
if (currentStep === 0) {
|
|
||||||
const moonraker = newPrinterForm.getFieldValue('moonraker')
|
|
||||||
setNextEnabled(
|
|
||||||
!!(moonraker?.protocol && moonraker?.host && moonraker?.port)
|
|
||||||
)
|
|
||||||
} else if (currentStep === 1) {
|
|
||||||
const name = newPrinterForm.getFieldValue('name')
|
|
||||||
setNextEnabled(!!name)
|
|
||||||
} else {
|
|
||||||
setNextEnabled(true)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(() => setNextEnabled(false))
|
|
||||||
}, [newPrinterForm, newPrinterFormUpdateValues, currentStep])
|
|
||||||
|
|
||||||
const summaryItems = [
|
|
||||||
{
|
|
||||||
key: 'name',
|
|
||||||
label: 'Name',
|
|
||||||
children: newPrinterFormValues.name
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'protocol',
|
|
||||||
label: 'Protocol',
|
|
||||||
children: newPrinterFormValues.moonraker?.protocol
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'host',
|
|
||||||
label: 'Host',
|
|
||||||
children: newPrinterFormValues.moonraker?.host
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'port',
|
|
||||||
label: 'Port',
|
|
||||||
children: newPrinterFormValues.moonraker?.port
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (reset) {
|
|
||||||
newPrinterForm.resetFields()
|
|
||||||
}
|
|
||||||
}, [reset, newPrinterForm])
|
|
||||||
|
|
||||||
const handlePrinterSelect = (printer) => {
|
|
||||||
newPrinterForm.setFieldsValue({
|
|
||||||
moonraker: {
|
|
||||||
protocol: printer.protocol,
|
|
||||||
host: printer.host,
|
|
||||||
port: printer.port
|
|
||||||
}
|
|
||||||
})
|
|
||||||
setNewPrinterFormValues({
|
|
||||||
...newPrinterFormValues,
|
|
||||||
moonraker: {
|
|
||||||
protocol: printer.protocol,
|
|
||||||
host: printer.host,
|
|
||||||
port: printer.port
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleHostnameEdit = (printer, newHostname) => {
|
|
||||||
if (newHostname && newHostname.trim() !== '') {
|
|
||||||
const updatedPrinter = {
|
|
||||||
...printer,
|
|
||||||
host: newHostname.trim()
|
|
||||||
}
|
|
||||||
setDiscoveredPrinters((prev) =>
|
|
||||||
prev.map((p) => (p.host === printer.host ? updatedPrinter : p))
|
|
||||||
)
|
|
||||||
setEditingHostname(null)
|
|
||||||
setHostnameInput('')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const showEditHostnameDialog = (printer) => {
|
|
||||||
setEditingHostname(printer.host)
|
|
||||||
setHostnameInput(printer.host)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleNewPrinter = async () => {
|
|
||||||
setNewPrinterLoading(true)
|
|
||||||
try {
|
|
||||||
await axios.post(
|
|
||||||
`${config.backendUrl}/printers`,
|
|
||||||
{
|
|
||||||
...newPrinterFormValues
|
|
||||||
},
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Accept: 'application/json'
|
|
||||||
},
|
|
||||||
withCredentials: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
onOk()
|
|
||||||
} catch (error) {
|
|
||||||
messageApi.error('Error adding new printer: ' + error.message)
|
|
||||||
} finally {
|
|
||||||
setNewPrinterLoading(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const notifyScanNetworkFound = useCallback(
|
|
||||||
(data) => {
|
|
||||||
const newPrinter = {
|
|
||||||
protocol: scanProtocol,
|
|
||||||
host: data.hostname || data.ip,
|
|
||||||
port: scanPort
|
|
||||||
}
|
|
||||||
notificationApi.info({
|
|
||||||
message: 'Printer Found',
|
|
||||||
description: `Printer found: ${data.hostname || data.ip}!`
|
|
||||||
})
|
|
||||||
setDiscoveredPrinters((prev) => [...prev, newPrinter])
|
|
||||||
},
|
|
||||||
[scanProtocol, scanPort, notificationApi]
|
|
||||||
)
|
|
||||||
|
|
||||||
const notifyScanNetworkComplete = useCallback(
|
|
||||||
(data) => {
|
|
||||||
setDiscovering(false)
|
|
||||||
notificationApi.destroy('network-scan')
|
|
||||||
if (data == false) {
|
|
||||||
messageApi.error('Error discovering printers!')
|
|
||||||
} else {
|
|
||||||
messageApi.success('Finished discovering printers!')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[messageApi, notificationApi]
|
|
||||||
)
|
|
||||||
|
|
||||||
const notifyScanNetworkProgress = useCallback(
|
|
||||||
(data) => {
|
|
||||||
notificationApi.info({
|
|
||||||
message: 'Scanning Network',
|
|
||||||
description: (
|
|
||||||
<div>
|
|
||||||
<div style={{ marginBottom: 12 }}>
|
|
||||||
Scanning IP: {data.currentIP}
|
|
||||||
</div>
|
|
||||||
<Progress
|
|
||||||
percent={data.progress}
|
|
||||||
size='small'
|
|
||||||
status='active'
|
|
||||||
showInfo={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
duration: 0,
|
|
||||||
key: 'network-scan',
|
|
||||||
icon: null,
|
|
||||||
placement: 'bottomRight',
|
|
||||||
style: {
|
|
||||||
width: 360
|
|
||||||
},
|
|
||||||
className: 'network-scan-notification',
|
|
||||||
closeIcon: null,
|
|
||||||
onClose: () => {},
|
|
||||||
btn: null
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[notificationApi]
|
|
||||||
)
|
|
||||||
|
|
||||||
const discoverPrinters = useCallback(() => {
|
|
||||||
if (!discovering) {
|
|
||||||
setDiscovering(true)
|
|
||||||
setDiscoveredPrinters([])
|
|
||||||
messageApi.info('Discovering printers...')
|
|
||||||
printServer.off('notify_scan_network_found')
|
|
||||||
printServer.off('notify_scan_network_progress')
|
|
||||||
printServer.off('notify_scan_network_complete')
|
|
||||||
|
|
||||||
printServer.on('notify_scan_network_found', notifyScanNetworkFound)
|
|
||||||
printServer.on('notify_scan_network_progress', notifyScanNetworkProgress)
|
|
||||||
printServer.on('notify_scan_network_complete', notifyScanNetworkComplete)
|
|
||||||
|
|
||||||
printServer.emit('bridge.scan_network.start', {
|
|
||||||
port: scanPort,
|
|
||||||
protocol: scanProtocol
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
discovering,
|
|
||||||
printServer,
|
|
||||||
scanPort,
|
|
||||||
scanProtocol,
|
|
||||||
messageApi,
|
|
||||||
notifyScanNetworkFound,
|
|
||||||
notifyScanNetworkProgress,
|
|
||||||
notifyScanNetworkComplete
|
|
||||||
])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setInitialized(true)
|
|
||||||
if (!initialized) {
|
|
||||||
discoverPrinters()
|
|
||||||
}
|
|
||||||
}, [initialized, discoverPrinters])
|
|
||||||
|
|
||||||
const stopDiscovery = () => {
|
|
||||||
if (discovering) {
|
|
||||||
setDiscovering(false)
|
|
||||||
notificationApi.destroy('network-scan')
|
|
||||||
messageApi.info('Stopping discovery...')
|
|
||||||
printServer.off('notify_scan_network_found')
|
|
||||||
printServer.off('notify_scan_network_progress')
|
|
||||||
printServer.off('notify_scan_network_complete')
|
|
||||||
printServer.emit('bridge.scan_network.stop', (response) => {
|
|
||||||
if (response == false) {
|
|
||||||
messageApi.error('Error stopping discovery!')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePortChange = (value) => {
|
|
||||||
stopDiscovery()
|
|
||||||
setScanPort(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleProtocolChange = (value) => {
|
|
||||||
stopDiscovery()
|
|
||||||
setScanProtocol(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const steps = [
|
|
||||||
{
|
|
||||||
title: 'Discovery',
|
|
||||||
key: 'discovery',
|
|
||||||
content: (
|
|
||||||
<>
|
|
||||||
<Flex vertical style={{ width: '100%' }} gap='large'>
|
|
||||||
{!showManualSetup ? (
|
|
||||||
<>
|
|
||||||
<Flex
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
justify='space-between'
|
|
||||||
align='center'
|
|
||||||
gap='middle'
|
|
||||||
>
|
|
||||||
<Space.Compact>
|
|
||||||
<InputNumber
|
|
||||||
min={1}
|
|
||||||
max={65535}
|
|
||||||
value={scanPort}
|
|
||||||
onChange={handlePortChange}
|
|
||||||
style={{ width: '80px' }}
|
|
||||||
placeholder='Port'
|
|
||||||
/>
|
|
||||||
<Select
|
|
||||||
value={scanProtocol}
|
|
||||||
onChange={handleProtocolChange}
|
|
||||||
options={[
|
|
||||||
{ value: 'ws', label: 'ws' },
|
|
||||||
{ value: 'wss', label: 'wss' }
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
icon={<SearchOutlined />}
|
|
||||||
onClick={discoverPrinters}
|
|
||||||
loading={discovering}
|
|
||||||
>
|
|
||||||
{discovering ? 'Discovering...' : 'Discover'}
|
|
||||||
</Button>
|
|
||||||
</Space.Compact>
|
|
||||||
<Button
|
|
||||||
icon={<SettingOutlined />}
|
|
||||||
onClick={() => setShowManualSetup(true)}
|
|
||||||
>
|
|
||||||
Manual Setup
|
|
||||||
</Button>
|
|
||||||
</Flex>
|
|
||||||
<List
|
|
||||||
dataSource={discoveredPrinters}
|
|
||||||
renderItem={(printer) => (
|
|
||||||
<List.Item
|
|
||||||
key={`${printer.host}:${printer.port}`}
|
|
||||||
actions={[
|
|
||||||
<Radio
|
|
||||||
key='select'
|
|
||||||
defaultChecked={
|
|
||||||
newPrinterFormValues.moonraker?.host ===
|
|
||||||
printer.host
|
|
||||||
}
|
|
||||||
onChange={() => handlePrinterSelect(printer)}
|
|
||||||
/>
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<List.Item.Meta
|
|
||||||
title={
|
|
||||||
<Space>
|
|
||||||
{printer.host}
|
|
||||||
{!printer.hostname && (
|
|
||||||
<Button
|
|
||||||
type='text'
|
|
||||||
icon={<EditIcon />}
|
|
||||||
onClick={() => showEditHostnameDialog(printer)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Space>
|
|
||||||
}
|
|
||||||
description={`Protocol: ${printer.protocol}, Port: ${printer.port}`}
|
|
||||||
/>
|
|
||||||
</List.Item>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<Modal
|
|
||||||
title='Edit Host'
|
|
||||||
open={editingHostname !== null}
|
|
||||||
onOk={() => {
|
|
||||||
const printer = discoveredPrinters.find(
|
|
||||||
(p) => p.host === editingHostname
|
|
||||||
)
|
|
||||||
if (printer) {
|
|
||||||
handleHostnameEdit(printer, hostnameInput)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onCancel={() => {
|
|
||||||
setEditingHostname(null)
|
|
||||||
setHostnameInput('')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Form.Item label='Host' required>
|
|
||||||
<Input
|
|
||||||
value={hostnameInput}
|
|
||||||
onChange={(e) => setHostnameInput(e.target.value)}
|
|
||||||
placeholder='Enter host'
|
|
||||||
autoFocus
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<Flex style={{ width: '100%' }} justify='end'>
|
|
||||||
<Button
|
|
||||||
icon={<SearchOutlined />}
|
|
||||||
onClick={() => setShowManualSetup(false)}
|
|
||||||
>
|
|
||||||
Back to Discovery
|
|
||||||
</Button>
|
|
||||||
</Flex>
|
|
||||||
<Flex vertical>
|
|
||||||
<Form.Item
|
|
||||||
label='Protocol'
|
|
||||||
name={['moonraker', 'protocol']}
|
|
||||||
rules={[
|
|
||||||
{ required: true, message: 'Protocol is required' }
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
defaultValue='ws'
|
|
||||||
options={[
|
|
||||||
{ value: 'ws', label: 'Websocket' },
|
|
||||||
{ value: 'wss', label: 'Websocket Secure' }
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label='Host'
|
|
||||||
name={['moonraker', 'host']}
|
|
||||||
rules={[{ required: true, message: 'Host is required' }]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label='Port'
|
|
||||||
name={['moonraker', 'port']}
|
|
||||||
rules={[{ required: true, message: 'Port is required' }]}
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={1}
|
|
||||||
max={65535}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label='API Key'
|
|
||||||
name={['moonraker', 'apiKey']}
|
|
||||||
rules={[{ required: false }]}
|
|
||||||
>
|
|
||||||
<Input.Password
|
|
||||||
placeholder='Optional API key'
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Flex>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Required',
|
|
||||||
key: 'required',
|
|
||||||
content: (
|
|
||||||
<>
|
|
||||||
<Form.Item
|
|
||||||
label='Name'
|
|
||||||
name='name'
|
|
||||||
rules={[{ required: true, message: 'Name is required' }]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Summary',
|
|
||||||
key: 'summary',
|
|
||||||
content: (
|
|
||||||
<Form.Item>
|
|
||||||
<Descriptions column={1} items={summaryItems} size={'small'} />
|
|
||||||
</Form.Item>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Flex gap={'middle'}>
|
|
||||||
{contextHolder}
|
|
||||||
{notificationContextHolder}
|
|
||||||
|
|
||||||
<div style={{ minWidth: '160px' }}>
|
|
||||||
<Steps current={currentStep} items={steps} direction='vertical' />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Divider type={'vertical'} style={{ height: 'unset' }} />
|
|
||||||
|
|
||||||
<Flex vertical={'true'} style={{ flexGrow: 1 }}>
|
|
||||||
<Title level={2} style={{ marginTop: 0 }}>
|
|
||||||
New Printer
|
|
||||||
</Title>
|
|
||||||
<Form
|
|
||||||
name='basic'
|
|
||||||
autoComplete='off'
|
|
||||||
form={newPrinterForm}
|
|
||||||
onFinish={handleNewPrinter}
|
|
||||||
onValuesChange={(changedValues) =>
|
|
||||||
setNewPrinterFormValues((prevValues) => ({
|
|
||||||
...prevValues,
|
|
||||||
...changedValues
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
initialValues={initialNewPrinterForm}
|
|
||||||
>
|
|
||||||
<div style={{ minHeight: '260px' }}>{steps[currentStep].content}</div>
|
|
||||||
|
|
||||||
<Flex justify={'end'}>
|
|
||||||
<Button
|
|
||||||
style={{
|
|
||||||
margin: '0 8px'
|
|
||||||
}}
|
|
||||||
onClick={() => setCurrentStep(currentStep - 1)}
|
|
||||||
disabled={!(currentStep > 0)}
|
|
||||||
>
|
|
||||||
Previous
|
|
||||||
</Button>
|
|
||||||
{currentStep < steps.length - 1 && (
|
|
||||||
<Button
|
|
||||||
type='primary'
|
|
||||||
disabled={!nextEnabled}
|
|
||||||
onClick={() => {
|
|
||||||
setCurrentStep(currentStep + 1)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Next
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
{currentStep === steps.length - 1 && (
|
|
||||||
<Button
|
|
||||||
type='primary'
|
|
||||||
htmlType='submit'
|
|
||||||
loading={newPrinterLoading}
|
|
||||||
>
|
|
||||||
Done
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</Form>
|
|
||||||
</Flex>
|
|
||||||
</Flex>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NewPrinter
|
export default NewPrinter
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user