Enhance ControlPrinter and related components with improved UI and functionality

- Added new icons for movement and settings in the ControlPrinter component.
- Refactored InfoCollapse components to include better styling and structure.
- Updated PrinterTemperaturePanel, PrinterPositionPanel, PrinterMovementPanel, and PrinterMiscPanel to support a disabled state based on connection status.
- Improved layout and styling in App.css for better visual consistency across components.
This commit is contained in:
Tom Butcher 2026-07-27 23:10:24 +01:00
parent 4fbb434103
commit f6736c9abb
7 changed files with 142 additions and 32 deletions

View File

@ -281,6 +281,11 @@ body {
margin: 8px;
}
.farmcontrol-splitter.large > .ant-splitter-bar {
margin: 11px;
opacity: 0.6;
}
.dark-mode {
--sb-track-color: #1d1d1d;
--sb-thumb-color: #848484;
@ -790,3 +795,16 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
.minimal-code-block-editor .ant-typography pre {
margin: 0;
}
.ant-splitter-panel:not(:first-child) .info-collapse .info-collapse-label {
margin-left: 4px;
}
.farmcontrol-splitter
.ant-splitter-panel:has(~ .ant-splitter-panel)
.info-collapse.ant-collapse.ant-collapse-icon-position-end
> .ant-collapse-item
> .ant-collapse-header
.ant-collapse-expand-icon {
padding-inline-end: 2px;
}

View File

@ -15,6 +15,8 @@ import PropTypes from 'prop-types'
import ObjectInfo from '../../common/ObjectInfo.jsx'
import PrinterIcon from '../../../Icons/PrinterIcon.jsx'
import MultiMotionIcon from '../../../Icons/MultiMotionIcon.jsx'
import SettingsIcon from '../../../Icons/SettingsIcon.jsx'
import PrinterTemperaturePanel from '../../common/PrinterTemperaturePanel.jsx'
import PrinterPositionPanel from '../../common/PrinterPositionPanel.jsx'
@ -27,7 +29,6 @@ import MissingPlaceholder from '../../common/MissingPlaceholder.jsx'
import { useMediaQuery } from 'react-responsive'
import AlertsDisplay from '../../common/AlertsDisplay.jsx'
import { ApiServerContext } from '../../context/ApiServerContext.jsx'
import LoadFilamentStock from '../../Inventory/FilamentStocks/LoadFilamentStock.jsx'
import UnloadFilamentStock from '../../Inventory/FilamentStocks/UnloadFilamentStock.jsx'
import ScrollBox from '../../common/ScrollBox.jsx'
@ -165,47 +166,88 @@ const ControlPrinter = ({ slicerIntegration = false }) => {
}
const sideBarItems = (
<Flex gap={isMobile ? 'large' : 'middle'} vertical>
{collapseState.temperature && (
<Flex gap={'large'} vertical>
<InfoCollapse
title={'Temperature'}
icon={<PrinterIcon />}
collapseKey='temperature'
active={collapseState.temperature}
onToggle={(expanded) => updateCollapseState('temperature', expanded)}
>
<Card
style={{ width: '100%' }}
title='Temperature'
size='small'
styles={{ body: { padding: '25px' } }}
>
<PrinterTemperaturePanel id={printerId} />
<PrinterTemperaturePanel
id={printerId}
disabled={
!objectFormState.objectData?.online || objectFormState.loading
}
/>
</Card>
)}
{collapseState.position && (
</InfoCollapse>
<InfoCollapse
title={'Position'}
icon={<PrinterIcon />}
collapseKey='position'
active={collapseState.position}
onToggle={(expanded) => updateCollapseState('position', expanded)}
>
<Card
style={{ width: '100%' }}
title='Position'
size='small'
styles={{ body: { padding: '25px' } }}
>
<PrinterPositionPanel id={printerId} />
<PrinterPositionPanel
id={printerId}
disabled={
!objectFormState.objectData?.online || objectFormState.loading
}
/>
</Card>
)}
{collapseState.movement && (
</InfoCollapse>
<InfoCollapse
title={'Movement'}
icon={<MultiMotionIcon />}
collapseKey='movement'
active={collapseState.movement}
onToggle={(expanded) => updateCollapseState('movement', expanded)}
>
<Card
style={{ width: '100%' }}
title='Movement'
size='small'
styles={{ body: { padding: '25px' } }}
>
<PrinterMovementPanel id={printerId} />
<PrinterMovementPanel
id={printerId}
disabled={
!objectFormState.objectData?.online || objectFormState.loading
}
/>
</Card>
)}
{collapseState.misc && (
</InfoCollapse>
<InfoCollapse
title={'Misc'}
icon={<SettingsIcon />}
collapseKey='misc'
active={collapseState.misc}
onToggle={(expanded) => updateCollapseState('misc', expanded)}
>
<Card
style={{ width: '100%' }}
title='Misc'
size='small'
styles={{ body: { padding: '25px' } }}
>
<PrinterMiscPanel id={printerId} />
<PrinterMiscPanel
id={printerId}
disabled={
!objectFormState.objectData?.online || objectFormState.loading
}
/>
</Card>
)}
</InfoCollapse>
</Flex>
)
@ -290,7 +332,7 @@ const ControlPrinter = ({ slicerIntegration = false }) => {
ref={actionHandlerRef}
>
<Flex vertical>
<Splitter className={'farmcontrol-splitter'}>
<Splitter className={'farmcontrol-splitter large'}>
<Splitter.Panel>
<Flex vertical gap={'large'}>
<InfoCollapse

View File

@ -21,15 +21,20 @@ const InfoCollapse = ({
activeKey={canCollapse ? (active ? [collapseKey] : []) : [collapseKey]}
onChange={(keys) => onToggle(keys.length > 0)}
expandIcon={({ isActive }) =>
canCollapse ? <CaretLeftOutlined rotate={isActive ? -90 : 0} /> : null
canCollapse ? (
<CaretLeftOutlined
rotate={isActive ? -90 : 0}
className='info-collapse-expand-icon'
/>
) : null
}
className={`no-h-padding-collapse ${className}`}
className={`no-h-padding-collapse ${className} info-collapse`}
items={[
{
key: collapseKey,
children: children,
label: (
<Flex align='center' gap={'middle'}>
<Flex align='center' gap={'middle'} className='info-collapse-label'>
{icon}
<Title level={5} style={{ margin: 0 }}>
{title}

View File

@ -7,9 +7,10 @@ import merge from 'lodash/merge'
const { Text } = Typography
const PrinterMiscPanel = ({ id, showControls = true }) => {
const PrinterMiscPanel = ({ id, showControls = true, disabled = false }) => {
const { subscribeToObjectEvent, connected, sendObjectAction } =
useContext(ApiServerContext)
const controlsDisabled = disabled || !connected
const [miscData, setMiscData] = useState({
fan: {
speed: 0,
@ -116,6 +117,7 @@ const PrinterMiscPanel = ({ id, showControls = true }) => {
min={0}
max={1}
step={0.01}
disabled={controlsDisabled}
onChange={setFanSpeed}
onAfterChange={handleSetFanSpeed}
tooltip={{ open: false }}
@ -127,6 +129,7 @@ const PrinterMiscPanel = ({ id, showControls = true }) => {
min={0}
max={1}
step={0.01}
disabled={controlsDisabled}
onChange={setLcdBrightness}
onAfterChange={handleSetLcdBrightness}
tooltip={{ open: false }}
@ -138,6 +141,7 @@ const PrinterMiscPanel = ({ id, showControls = true }) => {
min={0}
max={1}
step={0.01}
disabled={controlsDisabled}
onChange={setBeeperValue}
onAfterChange={handleSetBeeperValue}
tooltip={{ open: false }}
@ -188,7 +192,8 @@ const PrinterMiscPanel = ({ id, showControls = true }) => {
PrinterMiscPanel.propTypes = {
id: PropTypes.string.isRequired,
showControls: PropTypes.bool
showControls: PropTypes.bool,
disabled: PropTypes.bool
}
export default PrinterMiscPanel

View File

@ -19,8 +19,9 @@ import ArrowDownIcon from '../../Icons/ArrowDownIcon'
import HomeIcon from '../../Icons/HomeIcon'
import { ApiServerContext } from '../context/ApiServerContext'
const PrinterMovementPanel = ({ id }) => {
const PrinterMovementPanel = ({ id, disabled = false }) => {
const { connected, sendObjectAction } = useContext(ApiServerContext)
const controlsDisabled = disabled || !connected
const [posValue, setPosValue] = useState(10)
const [rateValue, setRateValue] = useState(1000)
const handlePosRadioChange = (e) => {
@ -108,6 +109,7 @@ const PrinterMovementPanel = ({ id }) => {
>
<Button
icon={<ArrowUpIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('Y', false)
}}
@ -115,6 +117,7 @@ const PrinterMovementPanel = ({ id }) => {
<Space>
<Button
icon={<ArrowLeftIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('X', false)
}}
@ -123,10 +126,14 @@ const PrinterMovementPanel = ({ id }) => {
menu={{ items: homeAxisButtonItems }}
placement='bottom'
>
<Button icon={<HomeIcon />}></Button>
<Button
icon={<HomeIcon />}
disabled={controlsDisabled}
></Button>
</Dropdown>
<Button
icon={<ArrowRightIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('X', true)
}}
@ -134,6 +141,7 @@ const PrinterMovementPanel = ({ id }) => {
</Space>
<Button
icon={<ArrowDownIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('Y', true)
}}
@ -150,18 +158,21 @@ const PrinterMovementPanel = ({ id }) => {
>
<Button
icon={<ArrowUpIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('Z', true)
}}
/>
<Button
icon={<LevelBedIcon />}
disabled={controlsDisabled}
onClick={() => {
handleLevelBedClick()
}}
/>
<Button
icon={<ArrowDownIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('Z', false)
}}
@ -178,12 +189,14 @@ const PrinterMovementPanel = ({ id }) => {
>
<Button
icon={<ArrowUpIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('E', true)
}}
/>
<Button
icon={<ArrowDownIcon />}
disabled={controlsDisabled}
onClick={() => {
handleMoveAxisClick('E', false)
}}
@ -197,6 +210,7 @@ const PrinterMovementPanel = ({ id }) => {
onChange={handlePosRadioChange}
value={posValue}
name='posRadio'
disabled={controlsDisabled}
style={{
display: 'flex',
justifyContent: 'center'
@ -219,6 +233,7 @@ const PrinterMovementPanel = ({ id }) => {
placeholder='10 mm'
name='posInput'
style={{ flexGrow: 1, minWidth: '125px' }}
disabled={controlsDisabled}
/>
<InputNumber
min={1}
@ -229,6 +244,7 @@ const PrinterMovementPanel = ({ id }) => {
placeholder='100 mm/s'
name='rateInput'
style={{ flexGrow: 1, minWidth: '125px' }}
disabled={controlsDisabled}
/>
</Flex>
</Flex>
@ -238,7 +254,8 @@ const PrinterMovementPanel = ({ id }) => {
}
PrinterMovementPanel.propTypes = {
id: PropTypes.string.isRequired
id: PropTypes.string.isRequired,
disabled: PropTypes.bool
}
export default PrinterMovementPanel

View File

@ -33,10 +33,12 @@ const CustomCollapse = styled(Collapse)`
const PrinterPositionPanel = ({
id,
showControls = true,
showMoreInfo = true
showMoreInfo = true,
disabled = false
}) => {
const { subscribeToObjectEvent, connected, sendObjectAction } =
useContext(ApiServerContext)
const controlsDisabled = disabled || !connected
const [positionData, setPositionData] = useState({
speedFactor: 1.0,
speed: 100,
@ -224,11 +226,13 @@ const PrinterPositionPanel = ({
onChange={(value) => setMaxVelocity(value)}
onPressEnter={handleSetMaxVelocity}
size='small'
disabled={controlsDisabled}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={handleSetMaxVelocity}
disabled={controlsDisabled}
>
Set
</Button>
@ -249,11 +253,13 @@ const PrinterPositionPanel = ({
onChange={(value) => setMaxAcceleration(value)}
onPressEnter={handleSetMaxAcceleration}
size='small'
disabled={controlsDisabled}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={handleSetMaxAcceleration}
disabled={controlsDisabled}
>
Set
</Button>
@ -275,11 +281,13 @@ const PrinterPositionPanel = ({
onChange={(value) => setSquareCornerVelocity(value)}
onPressEnter={handleSetSquareCornerVelocity}
size='small'
disabled={controlsDisabled}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={handleSetSquareCornerVelocity}
disabled={controlsDisabled}
>
Set
</Button>
@ -301,11 +309,13 @@ const PrinterPositionPanel = ({
onChange={(value) => setMinCruiseRatio(value / 100)}
onPressEnter={handleSetMinCruiseRatio}
size='small'
disabled={controlsDisabled}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={handleSetMinCruiseRatio}
disabled={controlsDisabled}
>
Set
</Button>
@ -402,11 +412,13 @@ const PrinterPositionPanel = ({
onChange={(value) => setSpeedFactor(value)}
onPressEnter={handleSetSpeedFactor}
size='small'
disabled={controlsDisabled}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={handleSetSpeedFactor}
disabled={controlsDisabled}
>
Set
</Button>
@ -426,11 +438,13 @@ const PrinterPositionPanel = ({
onChange={(value) => setExtrudeFactor(value)}
onPressEnter={handleSetExtrudeFactor}
size='small'
disabled={controlsDisabled}
/>
<Button
type='default'
style={{ width: 40 }}
onClick={handleSetExtrudeFactor}
disabled={controlsDisabled}
>
Set
</Button>
@ -494,7 +508,8 @@ const PrinterPositionPanel = ({
PrinterPositionPanel.propTypes = {
id: PropTypes.string.isRequired,
showControls: PropTypes.bool,
showMoreInfo: PropTypes.bool
showMoreInfo: PropTypes.bool,
disabled: PropTypes.bool
}
export default PrinterPositionPanel

View File

@ -37,7 +37,8 @@ const PrinterTemperaturePanel = ({
showBedControls = true,
showExtruder = true,
showBed = true,
showMoreInfo = true
showMoreInfo = true,
disabled = false
}) => {
const [temperatureData, setTemperatureData] = useState({
extruder: {
@ -56,7 +57,7 @@ const PrinterTemperaturePanel = ({
const { subscribeToObjectEvent, connected, sendObjectAction } =
useContext(ApiServerContext)
const controlsDisabled = disabled || !connected
// Sync input values with actual temperature targets
useEffect(() => {
if (temperatureData.extruder?.target !== undefined) {
@ -184,6 +185,7 @@ const PrinterTemperaturePanel = ({
extruder: { target: extruderTarget }
})
}
disabled={controlsDisabled}
/>
<Button
type='default'
@ -193,6 +195,7 @@ const PrinterTemperaturePanel = ({
extruder: { target: extruderTarget }
})
}
disabled={controlsDisabled}
>
Set
</Button>
@ -204,6 +207,7 @@ const PrinterTemperaturePanel = ({
onClick={() =>
handleSetTemperature({ extruder: { target: 0 } })
}
disabled={controlsDisabled}
>
Off
</Button>
@ -245,6 +249,7 @@ const PrinterTemperaturePanel = ({
bed: { target: bedTarget }
})
}
disabled={controlsDisabled}
/>
<Button
type='default'
@ -254,6 +259,7 @@ const PrinterTemperaturePanel = ({
bed: { target: bedTarget }
})
}
disabled={controlsDisabled}
>
Set
</Button>
@ -267,6 +273,7 @@ const PrinterTemperaturePanel = ({
bed: { target: 0 }
})
}
disabled={controlsDisabled}
>
Off
</Button>
@ -301,7 +308,8 @@ PrinterTemperaturePanel.propTypes = {
showExtruder: PropTypes.bool,
showBed: PropTypes.bool,
showMoreInfo: PropTypes.bool,
shouldUnsubscribe: PropTypes.bool
shouldUnsubscribe: PropTypes.bool,
disabled: PropTypes.bool
}
export default PrinterTemperaturePanel