From 2e3c139c196f2479261f004e770076df10ed9af1 Mon Sep 17 00:00:00 2001 From: Axel Bocciarelli Date: Wed, 25 Sep 2024 16:15:28 +0200 Subject: [PATCH] Refactor equipment maintenance components --- ui/src/components/Equipment/ActionButton.jsx | 19 ++ ui/src/components/Equipment/ActionField.jsx | 51 ++++ ui/src/components/Equipment/ActionGroup.jsx | 89 +----- .../Equipment/HarvesterMaintenance.jsx | 122 ++++---- .../Equipment/PlateManipulatorMaintenance.jsx | 275 +++++------------- .../Equipment/SampleChangerMaintenance.jsx | 78 ++--- ui/src/containers/EquipmentContainer.jsx | 43 +-- 7 files changed, 227 insertions(+), 450 deletions(-) create mode 100644 ui/src/components/Equipment/ActionButton.jsx create mode 100644 ui/src/components/Equipment/ActionField.jsx diff --git a/ui/src/components/Equipment/ActionButton.jsx b/ui/src/components/Equipment/ActionButton.jsx new file mode 100644 index 000000000..5634d1144 --- /dev/null +++ b/ui/src/components/Equipment/ActionButton.jsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { Button } from 'react-bootstrap'; + +function ActionButton(props) { + const { label, disabled, onSend } = props; + return ( + + ); +} + +export default ActionButton; diff --git a/ui/src/components/Equipment/ActionField.jsx b/ui/src/components/Equipment/ActionField.jsx new file mode 100644 index 000000000..aee29a2a7 --- /dev/null +++ b/ui/src/components/Equipment/ActionField.jsx @@ -0,0 +1,51 @@ +import React, { useState } from 'react'; +import { Button, Card, Form, InputGroup } from 'react-bootstrap'; + +function ActionField(props) { + const { headerMsg, label, inputType = 'text', btnLabel, onSubmit } = props; + + const [inputValue, setInputValue] = useState(''); + + function handleInputChange(evt) { + const { value } = evt.target; + + if (inputType === 'number') { + setInputValue(value && Number(value)); + } else { + setInputValue(value); + } + } + + return ( + + {headerMsg} + +
{ + evt.preventDefault(); + onSubmit(inputValue); + }} + > + + {label} + + handleInputChange(e)} + /> + + + +
+
+
+ ); +} + +export default ActionField; diff --git a/ui/src/components/Equipment/ActionGroup.jsx b/ui/src/components/Equipment/ActionGroup.jsx index 5873c3ce3..fd6e0d8fc 100644 --- a/ui/src/components/Equipment/ActionGroup.jsx +++ b/ui/src/components/Equipment/ActionGroup.jsx @@ -1,91 +1,16 @@ -import React, { useState } from 'react'; -import { Button, InputGroup, ButtonGroup, Card, Form } from 'react-bootstrap'; +import React from 'react'; +import { ButtonGroup, Card } from 'react-bootstrap'; -export function ActionGroup(props) { +function ActionGroup(props) { + const { label, children } = props; return ( - {props.name} + {label} - {props.buttons} + {children} ); } -export function ActionButton(props) { - let disabled; - - if (props.enabled === true) { - disabled = false; - } else { - disabled = true; - } - - return ( - - ); -} - -export function ActionField(props) { - const [inputValue, setInputValue] = useState(null); - - function handleInputChange(e) { - if (props.inputType === 'number') { - setInputValue(Number(e.target.value)); - } else { - setInputValue(e.target.value); - } - } - - function actionComponent() { - return ( - -
{ - e.preventDefault(); - props.sendCommand(props.cmd, inputValue); - }} - > - - {props.label} -
- - { - handleInputChange(e); - }} - /> - - -
-
-
- ); - } - - return ( - - ); -} +export default ActionGroup; diff --git a/ui/src/components/Equipment/HarvesterMaintenance.jsx b/ui/src/components/Equipment/HarvesterMaintenance.jsx index 84da7ff2e..b217be115 100644 --- a/ui/src/components/Equipment/HarvesterMaintenance.jsx +++ b/ui/src/components/Equipment/HarvesterMaintenance.jsx @@ -1,88 +1,65 @@ import React from 'react'; import { Row, Col, Button, Card } from 'react-bootstrap'; +import { useDispatch, useSelector } from 'react-redux'; -import { ActionGroup, ActionButton, ActionField } from './ActionGroup'; +import ActionGroup from './ActionGroup'; +import ActionButton from './ActionButton'; +import ActionField from './ActionField'; import InOutSwitch from '../InOutSwitch/InOutSwitch'; -export default function HarvesterMaintenance(props) { - const { - contents, - message, - commands_state, - currentPlateBarcode, - global_state, - calibratePin, - validateCalibration, - sendCommand, - sendDataCollectionToCrims, - commands, - } = props; +import { + calibratePin, + sendCommand, + sendDataCollectionToCrims, + validateCalibration, +} from '../../actions/harvester'; +import styles from './equipment.module.css'; - function renderActionButton(cmdInfo) { - return ( - - ); - } - - function renderActionGroup(grpInfo) { - const butGrp = []; - - for (const cmdInfo of grpInfo[1]) { - butGrp.push(renderActionButton(cmdInfo)); - } +export default function HarvesterMaintenance() { + const dispatch = useDispatch(); - return ; - } - - const groups = []; - - if ( - Object.keys(commands).length > 0 && - commands.cmds !== 'Harvester maintenance controller not defined' - ) { - for (const cmdgrp of commands.cmds) { - groups.push(renderActionGroup(cmdgrp)); - } - } else { - return
; - } + const contents = useSelector((state) => state.harvester.contents); + const { commands, commands_state, global_state, message } = useSelector( + (state) => state.harvesterMaintenance, + ); + const commandGroups = commands.cmds || []; const plateBarcode = global_state.plate_barecode?.toString(); - - let calibrationState = false; - if (contents) { - calibrationState = contents.calibration_state; - } + const calibrationState = contents ? contents.calibration_state : false; return ( -
- {groups} - {message ? ( + <> + {commandGroups.map(([grpLabel, grpCmds]) => ( + + {grpCmds.map(([cmd, cmdLabel, , cmdArgs]) => ( + dispatch(sendCommand(cmd, cmdArgs))} + /> + ))} + + ))} + + {message && ( Status message - {message} + {message} - ) : null} + )} + { + dispatch(sendCommand('loadPlateWithBarcode', val)); + }} /> + Temperature Mode @@ -101,10 +78,11 @@ export default function HarvesterMaintenance(props) { offValue={false} value={contents.room_temperature_mode} pkey="set_room_temperature_mode" - onSave={(pkey, value) => sendCommand(pkey, value)} + onSave={(pkey, value) => dispatch(sendCommand(pkey, value))} /> +
Procedure @@ -115,7 +93,7 @@ export default function HarvesterMaintenance(props) { @@ -131,7 +109,7 @@ export default function HarvesterMaintenance(props) {
-
+ ); } diff --git a/ui/src/components/Equipment/PlateManipulatorMaintenance.jsx b/ui/src/components/Equipment/PlateManipulatorMaintenance.jsx index ee06a4f41..2a3de5593 100644 --- a/ui/src/components/Equipment/PlateManipulatorMaintenance.jsx +++ b/ui/src/components/Equipment/PlateManipulatorMaintenance.jsx @@ -1,216 +1,75 @@ import React from 'react'; -import { Card, Button, ButtonGroup, InputGroup, Form } from 'react-bootstrap'; -import styles from './equipment.module.css'; - -export class PlateManipulatorActionButton extends React.Component { - render() { - let disabled; - if (this.props.enabled === true) { - disabled = false; - } else { - disabled = true; - } - - return ( - - ); - } -} - -export class PlateManipulatorActionGroup extends React.Component { - render() { - return ( - - {this.props.name} - {this.props.actionComponent} - - ); - } -} - -export class PlateManipulatorAction extends React.Component { - constructor(props) { - super(props); - this.state = { - input_value: '', - }; - this.inputRef = React.createRef(); - this.handleInputChange = this.handleInputChange.bind(this); - } - - handleInputChange(e) { - if (this.props.inputType === 'number') { - this.setState({ input_value: Number(e.target.value) }); - } else { - this.setState({ input_value: e.target.value }); - } - } +import { Card } from 'react-bootstrap'; +import { useDispatch, useSelector } from 'react-redux'; - actionComponent() { - return ( - -
{ - e.preventDefault(); - }} - > - - {this.props.label} -
- - { - this.handleInputChange(e); - }} - ref={(ref) => { - this.inputRef = ref; - }} - /> - - -
-
-
- ); - } +import ActionField from './ActionField'; +import ActionGroup from './ActionGroup'; +import ActionButton from './ActionButton'; - render() { - return ( - - ); - } -} +import { sendCommand } from '../../actions/sampleChanger'; +import styles from './equipment.module.css'; -export default class PlateManipulatorMaintenance extends React.Component { - buildActionButton(cmdinfo) { - return ( - state.sampleChangerMaintenance, + ); + + const commandGroups = commands.cmds || []; + + const scanLimits = global_state.scan_limits + ? `[ ${global_state.scan_limits.toString().split(',').join(', ')}]` + : ''; + + const plateBarcode = global_state.plate_info + ? global_state.plate_info.plate_barcode.toString() + : ''; + + return ( + <> + {commandGroups.map(([grpLabel, grpCmds]) => ( + + {grpCmds.map(([cmd, cmdLabel, , cmdArgs]) => ( + dispatch(sendCommand(cmd, cmdArgs))} + /> + ))} + + ))} + + {message && ( + + Status message + + {message} + + + )} + + { + dispatch(sendCommand('getOmegaMotorDynamicScanLimits', val)); + }} /> - ); - } - - buildActionGroup(grpinfo) { - const butgrp = []; - - for (const cmdinfo of grpinfo[1]) { - butgrp.push(this.buildActionButton(cmdinfo)); - } - return ( - {butgrp}} - key={grpinfo[0]} + { + dispatch(sendCommand('setPlateBarcode', val)); + }} /> - ); - } - - render() { - const groups = []; - let msg = ''; - - if ( - Object.keys(this.props.commands).length > 0 && - this.props.commands.cmds !== 'SC maintenance controller not defined' - ) { - for (const cmdgrp of this.props.commands.cmds) { - groups.push(this.buildActionGroup(cmdgrp)); - } - } else { - return
; - } - - if (this.props.message !== '') { - msg = this.props.message; - } - - let scan_limits = ''; - if (this.props.global_state.scan_limits) { - scan_limits = `[ ${this.props.global_state.scan_limits - .toString() - .split(',') - .join(', ')}]`; - } - - let plateBarcode = ''; - if (this.props.global_state.plate_info) { - plateBarcode = - this.props.global_state.plate_info.plate_barcode.toString(); - } - - return ( -
- {groups} - {msg ? ( - - Status message - - {msg} - - - ) : null} - - -
- ); - } + + ); } + +export default PlateManipulatorMaintenance; diff --git a/ui/src/components/Equipment/SampleChangerMaintenance.jsx b/ui/src/components/Equipment/SampleChangerMaintenance.jsx index 456619a95..374da23ed 100644 --- a/ui/src/components/Equipment/SampleChangerMaintenance.jsx +++ b/ui/src/components/Equipment/SampleChangerMaintenance.jsx @@ -1,64 +1,46 @@ import React from 'react'; import { Card } from 'react-bootstrap'; +import { useDispatch, useSelector } from 'react-redux'; -import { ActionGroup, ActionButton } from './ActionGroup'; - +import ActionGroup from './ActionGroup'; +import ActionButton from './ActionButton'; +import { sendCommand } from '../../actions/sampleChanger'; import styles from './equipment.module.css'; -export default function SampleChangerMaintenance(props) { - function renderActionButton(cmdinfo) { - return ( - - ); - } - - function renderActionGroup(grpinfo) { - const butgrp = []; - - for (const cmdinfo of grpinfo[1]) { - butgrp.push(renderActionButton(cmdinfo)); - } - - return ; - } +function SampleChangerMaintenance() { + const dispatch = useDispatch(); - const groups = []; - let msg = ''; - - if ( - Object.keys(props.commands).length > 0 && - props.commands.cmds !== 'SC maintenance controller not defined' - ) { - for (const cmdgrp of props.commands.cmds) { - groups.push(renderActionGroup(cmdgrp)); - } - } else { - return
; - } + const { commands, commands_state, message } = useSelector( + (state) => state.sampleChangerMaintenance, + ); - if (props.message !== '') { - msg = props.message; - } + const commandGroups = commands.cmds || []; return ( -
- {groups} - {msg ? ( + <> + {commandGroups.map(([grpLabel, grpCmds]) => ( + + {grpCmds.map(([cmd, cmdLabel, , cmdArgs]) => ( + dispatch(sendCommand(cmd, cmdArgs))} + /> + ))} + + ))} + + {message && ( Status message - {msg} + {message} - ) : null} -
+ )} + ); } + +export default SampleChangerMaintenance; diff --git a/ui/src/containers/EquipmentContainer.jsx b/ui/src/containers/EquipmentContainer.jsx index 93715fff9..a6b3f4425 100644 --- a/ui/src/containers/EquipmentContainer.jsx +++ b/ui/src/containers/EquipmentContainer.jsx @@ -19,13 +19,9 @@ import { import { abort as haAbort, - sendCommand as haSendCommand, refresh as haRefresh, harvestCrystal, harvestAndLoadCrystal, - calibratePin as haCalibratePin, - validateCalibration as haValidateCalibration, - sendDataCollectionToCrims, } from '../actions/harvester'; import { showErrorPanel } from '../actions/general'; @@ -82,14 +78,7 @@ function EquipmentContainer(props) { /> - + ) : ( @@ -108,13 +97,7 @@ function EquipmentContainer(props) { /> - + )} @@ -137,17 +120,7 @@ function EquipmentContainer(props) { /> - + @@ -194,15 +167,10 @@ function mapStateToProps(state) { commands: state.sampleChangerMaintenance.commands, commands_state: state.sampleChangerMaintenance.commands_state, global_state: state.sampleChangerMaintenance.global_state, - message: state.sampleChangerMaintenance.message, beamline: state.beamline, haContents: state.harvester.contents, haState: state.harvester.state, - haCommands: state.harvesterMaintenance.commands, - haCommands_state: state.harvesterMaintenance.commands_state, - haGlobal_state: state.harvesterMaintenance.global_state, - haMessage: state.harvesterMaintenance.message, }; } @@ -225,13 +193,8 @@ function mapDispatchToProps(dispatch) { harvestCrystal: (address) => dispatch(harvestCrystal(address)), harvestAndLoadCrystal: (address) => dispatch(harvestAndLoadCrystal(address)), - haCalibratePin: () => dispatch(haCalibratePin()), - sendDataCollectionToCrims: () => dispatch(sendDataCollectionToCrims()), - haValidateCalibration: (validated) => - dispatch(haValidateCalibration(validated)), haRefresh: () => dispatch(haRefresh()), haAbort: () => dispatch(haAbort()), - haSendCommand: (cmd, args) => dispatch(haSendCommand(cmd, args)), }; }