import React, { useState, useCallback } from 'react'; import { Button, Paper, Box, TextField } from "@mui/material"; import styled from "styled-components"; import { SimpleBox } from "../atoms/Box"; import Typography from "@mui/material/Typography"; import { useGlobalInfoStore } from "../../context/globalInfo"; import { useActionContext } from '../../context/browserActions'; import { useBrowserSteps } from '../../context/browserSteps'; import { useSocketStore } from '../../context/socket'; import { ScreenshotSettings } from '../../shared/types'; export const RightSidePanel = () => { const [textLabels, setTextLabels] = useState<{ [id: number]: string }>({}); const [errors, setErrors] = useState<{ [id: number]: string }>({}); const [confirmedTextSteps, setConfirmedTextSteps] = useState<{ [id: number]: boolean }>({}); const { lastAction, notify } = useGlobalInfoStore(); const { getText, getScreenshot, startGetText, stopGetText, startGetScreenshot, stopGetScreenshot } = useActionContext(); const { browserSteps, updateBrowserTextStepLabel, deleteBrowserStep, addScreenshotStep } = useBrowserSteps(); const { socket } = useSocketStore(); const handleTextLabelChange = (id: number, label: string) => { setTextLabels(prevLabels => ({ ...prevLabels, [id]: label })); if (!label.trim()) { setErrors(prevErrors => ({ ...prevErrors, [id]: 'Label cannot be empty' })); } else { setErrors(prevErrors => ({ ...prevErrors, [id]: '' })); } }; const handleTextStepConfirm = (id: number) => { const label = textLabels[id]?.trim(); if (label) { updateBrowserTextStepLabel(id, label); setConfirmedTextSteps(prev => ({ ...prev, [id]: true })); } else { setErrors(prevErrors => ({ ...prevErrors, [id]: 'Label cannot be empty' })); } }; const handleTextStepDiscard = (id: number) => { deleteBrowserStep(id); setTextLabels(prevLabels => { const { [id]: _, ...rest } = prevLabels; return rest; }); setErrors(prevErrors => { const { [id]: _, ...rest } = prevErrors; return rest; }); }; const getTextSettingsObject = useCallback(() => { const settings: Record = {}; browserSteps.forEach(step => { if (step.type === 'text' && step.label && step.selectorObj?.selector) { settings[step.label] = step.selectorObj; } }); return settings; }, [browserSteps]); const stopCaptureAndEmitGetTextSettings = useCallback(() => { const hasUnconfirmedTextSteps = browserSteps.some(step => step.type === 'text' && !confirmedTextSteps[step.id]); if (hasUnconfirmedTextSteps) { notify('error', 'Please confirm no labels are empty'); return; } stopGetText(); const settings = getTextSettingsObject(); const hasTextSteps = browserSteps.some(step => step.type === 'text'); if (hasTextSteps) { socket?.emit('action', { action: 'scrapeSchema', settings }); } }, [stopGetText, getTextSettingsObject, socket, browserSteps, confirmedTextSteps]); const captureScreenshot = (fullPage: boolean) => { const screenshotSettings: ScreenshotSettings = { fullPage, type: 'png', timeout: 30000, animations: 'allow', caret: 'hide', scale: 'device', }; socket?.emit('action', { action: 'screenshot', settings: screenshotSettings }); addScreenshotStep(fullPage); }; return ( Last action: {` ${lastAction}`} {!getText && !getScreenshot && } {getText && <> } {!getText && !getScreenshot && } {getScreenshot && ( )} {browserSteps.map(step => ( { step.type === 'text' ? ( <> handleTextLabelChange(step.id, e.target.value)} fullWidth margin="normal" error={!!errors[step.id]} helperText={errors[step.id]} InputProps={{ readOnly: confirmedTextSteps[step.id] }} /> {!confirmedTextSteps[step.id] && ( )} ) : ( step.type === 'screenshot' && ( {`Take ${step.fullPage ? 'Fullpage' : 'Visible Part'} Screenshot`} ) ) } ))} ); }; export const ActionDescription = styled.p` margin-left: 15px; `;