Files
parcer/src/components/molecules/InterpretationButtons.tsx

180 lines
6.2 KiB
TypeScript
Raw Normal View History

2024-06-24 22:33:26 +05:30
import { Box, Button, IconButton, Stack, Typography } from "@mui/material";
import { PauseCircle, PlayCircle, StopCircle } from "@mui/icons-material";
import React, { useCallback, useEffect, useState } from "react";
import { interpretCurrentRecording, stopCurrentInterpretation } from "../../api/recording";
import { useSocketStore } from "../../context/socket";
import { useGlobalInfoStore } from "../../context/globalInfo";
import { GenericModal } from "../atoms/GenericModal";
2024-07-31 22:46:38 +05:30
import { WhereWhatPair } from "maxun-core";
2024-06-24 22:33:26 +05:30
import HelpIcon from '@mui/icons-material/Help';
interface InterpretationButtonsProps {
enableStepping: (isPaused: boolean) => void;
}
interface InterpretationInfo {
running: boolean;
isPaused: boolean;
}
const interpretationInfo: InterpretationInfo = {
running: false,
isPaused: false,
}
export const InterpretationButtons = ({ enableStepping }: InterpretationButtonsProps) => {
const [info, setInfo] = React.useState<InterpretationInfo>(interpretationInfo);
const [decisionModal, setDecisionModal] = useState<{
pair: WhereWhatPair | null,
actionType: string,
selector: string,
action: string,
2024-08-30 03:19:56 +05:30
open: boolean
}>({ pair: null, actionType: '', selector: '', action: '', open: false });
2024-06-24 22:33:26 +05:30
const { socket } = useSocketStore();
const { notify } = useGlobalInfoStore();
const finishedHandler = useCallback(() => {
2024-08-30 03:19:56 +05:30
setInfo({ ...info, isPaused: false });
2024-06-24 22:33:26 +05:30
enableStepping(false);
}, [info, enableStepping]);
const breakpointHitHandler = useCallback(() => {
2024-08-30 03:19:56 +05:30
setInfo({ running: false, isPaused: true });
2024-06-24 22:33:26 +05:30
notify('warning', 'Please restart the interpretation, after updating the recording');
enableStepping(true);
}, [info, enableStepping]);
const decisionHandler = useCallback(
2024-08-30 03:19:56 +05:30
({ pair, actionType, lastData }
: { pair: WhereWhatPair | null, actionType: string, lastData: { selector: string, action: string } }) => {
const { selector, action } = lastData;
setDecisionModal((prevState) => {
return {
pair,
actionType,
selector,
action,
open: true,
}
})
}, [decisionModal]);
2024-06-24 22:33:26 +05:30
const handleDecision = (decision: boolean) => {
2024-08-30 03:19:56 +05:30
const { pair, actionType } = decisionModal;
socket?.emit('decision', { pair, actionType, decision });
setDecisionModal({ pair: null, actionType: '', selector: '', action: '', open: false });
2024-06-24 22:33:26 +05:30
}
const handleDescription = () => {
2024-08-30 03:19:56 +05:30
switch (decisionModal.actionType) {
2024-06-24 22:33:26 +05:30
case 'customAction':
return (
<React.Fragment>
2024-08-30 03:19:56 +05:30
<Typography>
Do you want to use the previously recorded selector
as a where condition for matching the action?
</Typography>
<Box style={{ marginTop: '4px' }}>
[previous action: <b>{decisionModal.action}</b>]
<pre>{decisionModal.selector}</pre>
</Box>
2024-06-24 22:33:26 +05:30
</React.Fragment>);
2024-08-30 03:19:56 +05:30
default: return null;
}
2024-06-24 22:33:26 +05:30
}
useEffect(() => {
if (socket) {
socket.on('finished', finishedHandler);
socket.on('breakpointHit', breakpointHitHandler);
socket.on('decision', decisionHandler);
}
return () => {
socket?.off('finished', finishedHandler);
socket?.off('breakpointHit', breakpointHitHandler);
socket?.off('decision', decisionHandler);
}
}, [socket, finishedHandler, breakpointHitHandler]);
const handlePlay = async () => {
if (info.isPaused) {
socket?.emit("resume");
2024-08-30 03:19:56 +05:30
setInfo({ running: true, isPaused: false });
2024-06-24 22:33:26 +05:30
enableStepping(false);
} else {
2024-08-30 03:19:56 +05:30
setInfo({ ...info, running: true });
2024-06-24 22:33:26 +05:30
const finished = await interpretCurrentRecording();
2024-08-30 03:19:56 +05:30
setInfo({ ...info, running: false });
2024-06-24 22:33:26 +05:30
if (finished) {
notify('info', 'Interpretation finished');
} else {
notify('error', 'Interpretation failed to start');
}
}
};
const handleStop = async () => {
setInfo({ running: false, isPaused: false });
enableStepping(false);
await stopCurrentInterpretation();
};
const handlePause = async () => {
if (info.running) {
socket?.emit("pause");
setInfo({ running: false, isPaused: true });
notify('warning', 'Please restart the interpretation, after updating the recording');
enableStepping(true);
}
};
return (
<Stack direction="row" spacing={3}
2024-08-30 03:19:56 +05:30
sx={{ marginTop: '10px', marginBottom: '5px', justifyContent: 'space-evenly', }} >
<IconButton disabled={!info.running} sx={{ display: 'grid', '&:hover': { color: '#1976d2', backgroundColor: 'transparent' } }}
aria-label="pause" size="small" title="Pause" onClick={handlePause}>
<PauseCircle sx={{ fontSize: 30, justifySelf: 'center' }} />
2024-06-24 22:33:26 +05:30
Pause
</IconButton>
2024-08-30 03:19:56 +05:30
<IconButton disabled={info.running} sx={{ display: 'grid', '&:hover': { color: '#1976d2', backgroundColor: 'transparent' } }}
aria-label="play" size="small" title="Play" onClick={handlePlay}>
<PlayCircle sx={{ fontSize: 30, justifySelf: 'center' }} />
2024-06-24 22:33:26 +05:30
{info.isPaused ? 'Resume' : 'Start'}
</IconButton>
2024-08-30 03:19:56 +05:30
<IconButton disabled={!info.running && !info.isPaused} sx={{ display: 'grid', '&:hover': { color: '#1976d2', backgroundColor: 'transparent' } }}
2024-06-24 22:33:26 +05:30
aria-label="stop" size="small" title="Stop" onClick={handleStop}>
2024-08-30 03:19:56 +05:30
<StopCircle sx={{ fontSize: 30, justifySelf: 'center' }} />
2024-06-24 22:33:26 +05:30
Stop
</IconButton>
2024-08-30 03:19:56 +05:30
<GenericModal onClose={() => { }} isOpen={decisionModal.open} canBeClosed={false}
modalStyle={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 500,
background: 'white',
border: '2px solid #000',
boxShadow: '24',
height: 'fit-content',
display: 'block',
overflow: 'scroll',
padding: '5px 25px 10px 25px',
}}>
<div style={{ padding: '15px' }}>
<HelpIcon />
2024-06-24 22:33:26 +05:30
{
handleDescription()
}
2024-08-30 03:19:56 +05:30
<div style={{ float: 'right' }}>
<Button onClick={() => handleDecision(true)} color='success'>yes</Button>
<Button onClick={() => handleDecision(false)} color='error'>no</Button>
2024-06-24 22:33:26 +05:30
</div>
</div>
</GenericModal>
</Stack>
);
};