pyiron / pyiron-xyflow

react xyflow for pyiron
0 stars 0 forks source link

Float inputs from nodes #4

Open Tara-Lakshmipathy opened 2 weeks ago

Tara-Lakshmipathy commented 2 weeks ago

Whenever I try to input a decimal number x>1 from a field of type float, the decimal disappears and I am left with an int. The same thing also happens if I try to input a decimal number 0<x<1 if I start typing with 0. In other words, I can enter a decimal number only when I start typing with the decimal (.) or copy-paste a decimal number.

I think this issue may be caused by this in the CustomNode.jsx file.

I am currently trying out some solutions like using onKeyDown or step or toFixed. But I haven't yet been successful.

Tara-Lakshmipathy commented 2 weeks ago

Chatgpt-3.5 suggested the following changes to renderInputHandle in CustomNode.jsx but this doesn't seem to work either:

const renderInputHandle = (data, index, editValue = false) => {
    const label = data.target_labels[index];
    const inp_type = data.target_types[index];
    const value = data.target_values[index];
    const [inputValue, setInputValue] = useState(value ? value.toString() : ''); 
    const context = React.useContext(UpdateDataContext);

    const inputTypeMap = {
        'str': 'text',
        'int': 'text',
        'float': 'text',
        'bool': 'checkbox'
    };

    const convertInput = (value, inp_type) => {
        switch(inp_type) {
            case 'int':
                const intValue = parseInt(value, 10);
                return isNaN(intValue) ? value : intValue;
            case 'float':
                const floatValue = parseFloat(value);
                return isNaN(floatValue) ? value : floatValue;
            case 'bool':
                return value; 
            default:
                return value;
        }
    };

    const currentInputType = inputTypeMap[inp_type] || 'text';

    if (inp_type === 'NonPrimitive' || inp_type === 'None') {
        editValue = false;
    }

    const getBackgroundColor = (value, inp_type) => {
        if (value === null) {
            return 'grey';
        } else if (value === 'NotData') {
            return 'red';
        } else {
            return 'white';
        }
    };

    return (
        <>
            <div style={{ height: 16, fontSize: '10px', display: 'flex', alignItems: 'center', flexDirection: 'row-reverse', justifyContent: 'flex-end' }}>
                <span style={{ marginLeft: '5px' }}>{`${label}`}</span> 
                {editValue 
                    ? <input 
                          type={currentInputType}
                          value={inputValue}
                          className="nodrag"
                          onChange={e => {
                              const newValue = currentInputType === 'checkbox' ? e.target.checked : e.target.value;

                              // Only convert to a number when inp_type is int or float, and conversion is safe
                              const convertedValue = inp_type === 'float' || inp_type === 'int' 
                                  ? convertInput(newValue, inp_type) 
                                  : newValue;

                              setInputValue(newValue);

                              // Update context with converted value if necessary
                              if (inp_type === 'float' || inp_type === 'int') {
                                  context(data.label, index, convertedValue);
                              } else {
                                  context(data.label, index, newValue);
                              }
                          }}
                          onBlur={() => {
                              // Convert and update the context on blur (when input loses focus)
                              const finalValue = convertInput(inputValue, inp_type);
                              context(data.label, index, finalValue);
                          }}
                          style={{ 
                              width: '15px', 
                              height: '10px', 
                              fontSize: '6px', 
                              backgroundColor: getBackgroundColor(value, inp_type)
                            }} 
                      /> 
                    : '' 
                }
            </div>
            {renderCustomHandle('left', 'target', index, label)}
        </>
    );
};
Tara-Lakshmipathy commented 2 weeks ago

Chatgpt-4 suggest the following change to the case float within const convertInput in CustomNode.jsx and the issue has been partially resolved. But if the entered decimal value is a whole number (e.g. x=3.0), then the node still fails to run:

case 'float':
    // Check if value can be converted to a float
    // Only parse the float when there are digits after the decimal point
    if (/.\d+$/.test(value)){
        const floatValue = parseFloat(value);
        return isNaN(floatValue) ? value : floatValue;
    } else {
        return value;
    }