Skip to content

Commit

Permalink
Refactor equipment maintenance components
Browse files Browse the repository at this point in the history
  • Loading branch information
axelboc committed Sep 25, 2024
1 parent 827baa6 commit c9b6621
Show file tree
Hide file tree
Showing 9 changed files with 229 additions and 452 deletions.
2 changes: 1 addition & 1 deletion ui/src/api/harvester.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ export function sendAbortHarvester() {
return endpoint.get('/send_command/abort').res();
}

export function sendHarvesterCommand(cmdparts, args) {
export function sendHarvesterCommand(cmdparts, args = '') {
return endpoint.get(`/send_command/${cmdparts}/${args}`).safeJson();
}
2 changes: 1 addition & 1 deletion ui/src/api/sampleChanger.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function sendAbortSampleChanger() {
return endpoint.get('/send_command/abort').res();
}

export function sendSampleChangerCommand(cmdparts, args) {
export function sendSampleChangerCommand(cmdparts, args = '') {
return endpoint.get(`/send_command/${cmdparts}/${args}`).res();
}

Expand Down
19 changes: 19 additions & 0 deletions ui/src/components/Equipment/ActionButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react';
import { Button } from 'react-bootstrap';

function ActionButton(props) {
const { label, disabled, onSend } = props;
return (
<Button
className="me-2"
size="sm"
variant="outline-secondary"
disabled={disabled}
onClick={() => onSend()}
>
{label}
</Button>
);
}

export default ActionButton;
51 changes: 51 additions & 0 deletions ui/src/components/Equipment/ActionField.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<Card className="mb-2">
<Card.Header>{headerMsg}</Card.Header>
<Card.Body>
<Form
onSubmit={(evt) => {
evt.preventDefault();
onSubmit(inputValue);
}}
>
<Form.Group>
<Form.Label>{label}</Form.Label>
<InputGroup>
<Form.Control
type={inputType}
value={inputValue}
required
size="sm"
style={{ width: '13em', flex: 'none' }}
onChange={(e) => handleInputChange(e)}
/>
<Button type="submit" variant="outline-secondary">
{btnLabel}
</Button>
</InputGroup>
</Form.Group>
</Form>
</Card.Body>
</Card>
);
}

export default ActionField;
89 changes: 7 additions & 82 deletions ui/src/components/Equipment/ActionGroup.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<Card className="mb-2">
<Card.Header>{props.name}</Card.Header>
<Card.Header>{label}</Card.Header>
<Card.Body>
<ButtonGroup>{props.buttons}</ButtonGroup>
<ButtonGroup>{children}</ButtonGroup>
</Card.Body>
</Card>
);
}

export function ActionButton(props) {
let disabled;

if (props.enabled === true) {
disabled = false;
} else {
disabled = true;
}

return (
<Button
disabled={disabled}
onClick={() => props.sendCommand(props.cmd, props.args)}
size="sm"
className="me-2"
variant={props.variant || 'outline-secondary'}
>
{props.label}
</Button>
);
}

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 (
<span>
<Form
onSubmit={(e) => {
e.preventDefault();
props.sendCommand(props.cmd, inputValue);
}}
>
<Form.Group size="sm">
<Form.Label>{props.label}</Form.Label>
<br />
<InputGroup>
<Form.Control
size="sm"
required
value={inputValue}
style={{
maxWidth: '13em',
minWidth: '13em',
marginRight: '0.2em',
}}
type={props.inputType}
onChange={(e) => {
handleInputChange(e);
}}
/>
<Button type="submit" size="sm">
{props.btn_label}
</Button>
</InputGroup>
</Form.Group>
</Form>
</span>
);
}

return (
<ActionGroup
name={`${props.header_msg} : ${props.value}`}
buttons={actionComponent()}
/>
);
}
export default ActionGroup;
122 changes: 50 additions & 72 deletions ui/src/components/Equipment/HarvesterMaintenance.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<ActionButton
label={cmdInfo[1]}
cmd={cmdInfo[0]}
args={cmdInfo[3]}
enabled={commands_state[cmdInfo[0]]}
sendCommand={sendCommand}
key={cmdInfo[1]}
/>
);
}

function renderActionGroup(grpInfo) {
const butGrp = [];

for (const cmdInfo of grpInfo[1]) {
butGrp.push(renderActionButton(cmdInfo));
}
export default function HarvesterMaintenance() {
const dispatch = useDispatch();

return <ActionGroup name={grpInfo[0]} buttons={butGrp} />;
}

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 <div />;
}
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 (
<div>
{groups}
{message ? (
<>
{commandGroups.map(([grpLabel, grpCmds]) => (
<ActionGroup key={grpLabel} label={grpLabel}>
{grpCmds.map(([cmd, cmdLabel, , cmdArgs]) => (
<ActionButton
key={cmd}
label={cmdLabel}
disabled={!commands_state[cmd]}
onSend={() => dispatch(sendCommand(cmd, cmdArgs))}
/>
))}
</ActionGroup>
))}

{message && (
<Card>
<Card.Header>Status message</Card.Header>
<Card.Body>
<span className="scMessage">{message}</span>
<span className={styles.scMessage}>{message}</span>
</Card.Body>
</Card>
) : null}
)}

<ActionField
btn_label="Set"
headerMsg={`Actual Plate Barcode is : ${plateBarcode}`}
label="Plate Barcode"
cmd="loadPlateWithBarcode"
args={currentPlateBarcode}
sendCommand={sendCommand}
global_state={global_state}
header_msg="Actual Plate Barcode is"
value={plateBarcode}
inputType="text"
btnLabel="Set"
onSubmit={(val) => {
dispatch(sendCommand('loadPlateWithBarcode', val));
}}
/>

<Card className="mb-2">
<Card.Header>Temperature Mode</Card.Header>
<Card.Body>
Expand All @@ -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))}
/>
</Card.Body>
</Card>

<div>
<Card className="mb-2">
<Card.Header> Procedure </Card.Header>
Expand All @@ -115,7 +93,7 @@ export default function HarvesterMaintenance(props) {
<Button
className="mt-1"
variant="outline-secondary"
onClick={() => calibratePin()}
onClick={() => dispatch(calibratePin())}
>
Calibrate
</Button>
Expand All @@ -131,7 +109,7 @@ export default function HarvesterMaintenance(props) {
<Col sm={6}>
<Button
className="mt-1 text-nowrap"
onClick={() => validateCalibration(true)}
onClick={() => dispatch(validateCalibration(true))}
variant="outline-success"
style={{ marginRight: '2em' }}
>
Expand All @@ -141,7 +119,7 @@ export default function HarvesterMaintenance(props) {
<Col sm={6}>
<Button
className="mt-1"
onClick={() => validateCalibration(false)}
onClick={() => dispatch(validateCalibration(false))}
variant="outline-warning"
>
Cancel Calibration
Expand All @@ -156,7 +134,7 @@ export default function HarvesterMaintenance(props) {
<Button
className="mt-1"
variant="outline-secondary"
onClick={() => sendDataCollectionToCrims()}
onClick={() => dispatch(sendDataCollectionToCrims())}
title="TEST : Send latest Data collection Group and to Crims"
>
Send Data to Crims
Expand All @@ -166,6 +144,6 @@ export default function HarvesterMaintenance(props) {
</Card.Body>
</Card>
</div>
</div>
</>
);
}
Loading

0 comments on commit c9b6621

Please sign in to comment.