mirror of
https://github.com/ianarawjo/ChainForge.git
synced 2025-03-14 16:26:45 +00:00
Fixes to textfield hooks
This commit is contained in:
parent
0584600334
commit
2d519c2de3
@ -1,10 +1,10 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { Handle } from 'react-flow-renderer';
|
||||
import useStore from './store'
|
||||
|
||||
export default function TemplateHooks({ vars, nodeId, startY }) {
|
||||
|
||||
const genTemplateHooks = (temp_var_names, names_to_blink) => {
|
||||
const genTemplateHooks = useCallback((temp_var_names, names_to_blink) => {
|
||||
return temp_var_names.map((name, idx) => {
|
||||
const className = (names_to_blink.includes(name)) ? 'text-blink' : '';
|
||||
const pos = (idx * 35) + startY + 'px';
|
||||
@ -14,7 +14,7 @@ export default function TemplateHooks({ vars, nodeId, startY }) {
|
||||
<Handle type="target" position="left" id={name} style={style} />
|
||||
</div>)
|
||||
});
|
||||
};
|
||||
}, [startY]);
|
||||
|
||||
const [templateHooks, setTemplateHooks] = useState(genTemplateHooks(vars || [], []));
|
||||
const setDataPropsForNode = useStore((state) => state.setDataPropsForNode);
|
||||
@ -28,8 +28,8 @@ export default function TemplateHooks({ vars, nodeId, startY }) {
|
||||
|
||||
useEffect(() => {
|
||||
setTemplateHooks(genTemplateHooks(vars, []));
|
||||
setDataPropsForNode(nodeId, {vars: vars});
|
||||
}, [vars]);
|
||||
// setDataPropsForNode(nodeId, {vars: vars});
|
||||
}, [vars, startY, genTemplateHooks, nodeId, setDataPropsForNode]);
|
||||
|
||||
return (
|
||||
<div className="template-hooks">
|
||||
|
@ -1,56 +1,98 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useRef, useEffect, useCallback } from 'react';
|
||||
import { Handle } from 'react-flow-renderer';
|
||||
import useStore from './store';
|
||||
import NodeLabel from './NodeLabelComponent'
|
||||
import TemplateHooks from './TemplateHooksComponent';
|
||||
|
||||
const union = (setA, setB) => {
|
||||
const _union = new Set(setA);
|
||||
for (const elem of setB) {
|
||||
_union.add(elem);
|
||||
}
|
||||
return _union;
|
||||
}
|
||||
|
||||
const TextFieldsNode = ({ data, id }) => {
|
||||
|
||||
const [templateVars, setTemplateVars] = useState(data.vars || []);
|
||||
const setDataPropsForNode = useStore((state) => state.setDataPropsForNode);
|
||||
|
||||
const handleInputChange = (event) => {
|
||||
// Update the data for this text fields' id.
|
||||
if (!data.fields)
|
||||
data.fields = {}
|
||||
data['fields'][event.target.id] = event.target.value;
|
||||
let new_data = { fields: {...data.fields} };
|
||||
// Handle a change in a text fields' input.
|
||||
const handleInputChange = useCallback((event) => {
|
||||
// Update the data for this text fields' id.
|
||||
let new_data = { 'fields': {...data.fields} };
|
||||
new_data.fields[event.target.id] = event.target.value;
|
||||
setDataPropsForNode(id, new_data);
|
||||
}
|
||||
|
||||
const createInitFields = () => {
|
||||
// TODO: Optimize this check.
|
||||
let all_found_vars = new Set();
|
||||
const braces_regex = /(?<!\\){(.*?)(?<!\\)}/g; // gets all strs within braces {} that aren't escaped; e.g., ignores \{this\} but captures {this}
|
||||
Object.keys(new_data['fields']).forEach((fieldId) => {
|
||||
let found_vars = new_data['fields'][fieldId].match(braces_regex);
|
||||
if (found_vars && found_vars.length > 0) {
|
||||
found_vars = found_vars.map(name => name.substring(1, name.length-1)); // remove brackets {}
|
||||
all_found_vars = union(all_found_vars, new Set(found_vars));
|
||||
}
|
||||
});
|
||||
|
||||
// Update template var fields + handles, if there's a change in sets
|
||||
const past_vars = new Set(templateVars);
|
||||
if (all_found_vars !== past_vars) {
|
||||
setTemplateVars(Array.from(all_found_vars));
|
||||
}
|
||||
}, [data, id, setDataPropsForNode, templateVars]);
|
||||
|
||||
// Initialize fields (run once at init)
|
||||
const [fields, setFields] = useState([]);
|
||||
useEffect(() => {
|
||||
if (!data.fields)
|
||||
setDataPropsForNode(id, { fields: {f0: ''}} );
|
||||
}, []);
|
||||
|
||||
// Whenever 'data' changes, update the input fields to reflect the current state.
|
||||
useEffect(() => {
|
||||
const f = data.fields ? Object.keys(data.fields) : ['f0'];
|
||||
return f.map((i, idx) => {
|
||||
setFields(f.map((i) => {
|
||||
const val = data.fields ? data.fields[i] : '';
|
||||
return (
|
||||
<div className="input-field" key={i}>
|
||||
<textarea id={i} name={i} className="text-field-fixed nodrag" rows="3" cols="40" defaultValue={val} onChange={handleInputChange} />
|
||||
</div>
|
||||
)});
|
||||
};
|
||||
)}));
|
||||
}, [data.fields, handleInputChange]);
|
||||
|
||||
const [fields, setFields] = useState(createInitFields());
|
||||
// Add a field
|
||||
const handleAddField = useCallback(() => {
|
||||
// Update the data for this text fields' id.
|
||||
const num_fields = data.fields ? Object.keys(data.fields).length : 0;
|
||||
let new_data = { 'fields': {...data.fields} };
|
||||
new_data.fields['f'+num_fields.toString()] = "";
|
||||
setDataPropsForNode(id, new_data);
|
||||
}, [data, id, setDataPropsForNode]);
|
||||
|
||||
const handleAddField = (event) => {
|
||||
const i = fields.length;
|
||||
const f = fields.concat((
|
||||
<div className="input-field" key={i}>
|
||||
<textarea id={"f"+i} name={"f"+i} className="text-field-fixed nodrag" rows="3" cols="40" defaultValue={''} onChange={handleInputChange} />
|
||||
</div>
|
||||
));
|
||||
setFields(f);
|
||||
}
|
||||
// Dynamically update the y-position of the template hook <Handle>s
|
||||
const ref = useRef(null);
|
||||
const [hooksY, setHooksY] = useState(120);
|
||||
useEffect(() => {
|
||||
const node_height = ref.current.clientHeight;
|
||||
setHooksY(node_height + 70);
|
||||
}, [fields]);
|
||||
|
||||
return (
|
||||
<div className="text-fields-node">
|
||||
<div className="node-header">
|
||||
<NodeLabel title={data.title || 'TextFields Node'} nodeId={id} />
|
||||
</div>
|
||||
{fields}
|
||||
<div ref={ref}>
|
||||
{fields}
|
||||
</div>
|
||||
<Handle
|
||||
type="source"
|
||||
position="right"
|
||||
id="output"
|
||||
style={{ top: "50%", background: '#555' }}
|
||||
/>
|
||||
<TemplateHooks vars={templateVars} nodeId={id} startY={hooksY} />
|
||||
<div className="add-text-field-btn">
|
||||
<button onClick={handleAddField}>+</button>
|
||||
</div>
|
||||
|
@ -74,7 +74,7 @@ const useStore = create((set, get) => ({
|
||||
if (n.id === id) {
|
||||
for (const key of Object.keys(data_props))
|
||||
n.data[key] = data_props[key];
|
||||
n.data = {...n.data};
|
||||
n.data = JSON.parse(JSON.stringify(n.data)); // deep copy json
|
||||
}
|
||||
return n;
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user