import React, { useEffect, useRef, useState } from 'react'; import { runMethod } from '../socket'; import { Button, Form, Card } from 'react-bootstrap'; import { DocStringComponent } from './DocStringComponent'; import { LevelName } from './NotificationsComponent'; import { SerializedValue } from './GenericComponent'; import { FloatObject, NumberComponent, QuantityObject } from './NumberComponent'; import { StringComponent } from './StringComponent'; import { ColouredEnumComponent } from './ColouredEnumComponent'; import { EnumComponent } from './EnumComponent'; type MethodProps = { name: string; parentPath: string; parameters: Record; docString?: string; hideOutput?: boolean; addNotification: (message: string, levelname?: LevelName) => void; displayName: string; id: string; }; export const MethodComponent = React.memo((props: MethodProps) => { const { name, parentPath, docString, addNotification, displayName, id } = props; const renderCount = useRef(0); // Add a new state variable to hold the list of function calls const [functionCalls, setFunctionCalls] = useState([]); const fullAccessPath = [parentPath, name].filter((element) => element).join('.'); const triggerNotification = (args: Record) => { const argsString = Object.entries(args) .map(([key, value]) => `${key}: "${value}"`) .join(', '); let message = `Method ${fullAccessPath} was triggered`; if (argsString === '') { message += '.'; } else { message += ` with arguments {${argsString}}.`; } addNotification(message); }; const execute = async (event: React.FormEvent) => { event.preventDefault(); const kwargs = {}; Object.keys(props.parameters).forEach((name) => { kwargs[name] = event.target[name].value; }); runMethod(name, parentPath, kwargs, (ack) => { // Update the functionCalls state with the new call if we get an acknowledge msg if (ack !== undefined) { setFunctionCalls((prevCalls) => [ ...prevCalls, { name, args: kwargs, result: ack } ]); } }); triggerNotification(kwargs); }; const args = Object.entries(props.parameters).map(([name, serializedValue]) => { if (serializedValue.type == 'float' || serializedValue.type == 'int') { return ( {}} id={id + '.' + name} /> ); } else if (serializedValue.type == 'Quantity') { return ( {}} id={id + '.' + name} /> ); } else if (serializedValue.type == 'str') { return ( {}} id={id + '.' + name} /> ); } else if (serializedValue.type == 'Enum') { return ( {}} enumDict={serializedValue.enum} displayName={name} id={id + '.' + name} /> ); } else if (serializedValue.type == 'ColouredEnum') { return ( {}} enumDict={serializedValue.enum} displayName={name} id={id + '.' + name} /> ); } }); // Content conditionally rendered based on args const formContent = (
{args}
); const outputContent = (
{functionCalls.map((call, index) => (
{Object.entries(call.args) .map(([key, val]) => `${key}=${JSON.stringify(val)}`) .join(', ') + ' => ' + JSON.stringify(call.result)}
))}
); useEffect(() => { renderCount.current++; }); return (
{process.env.NODE_ENV === 'development' && (
Render count: {renderCount.current}
)} {args.length > 0 ? ( {formContent} {outputContent} ) : (
{formContent}
)}
); });