nodes-ui-flow / src /nodes /JsonParserFlowNode.jsx
markitzeroo
Deploy updated nodes UI flow
1dd9186
import { memo, useEffect } from 'react';
import { useUpdateNodeInternals } from '@xyflow/react';
import NodeShell from '../components/NodeShell.jsx';
import { NodeDraftInput } from '../components/NodeDraftField.jsx';
import { useWorkflow } from '../context/WorkflowContext.jsx';
import { createBrowserId } from '../lib/ids.js';
import { getNodeAccent } from '../lib/nodeRegistry.js';
function JsonParserFlowNode({ id, data, selected, type }) {
const { getNodeHandles, replaceNodeData, removeHandleConnections } = useWorkflow();
const updateNodeInternals = useUpdateNodeInternals();
const handles = getNodeHandles(type, data);
const runtime = data.runtime || {};
const values = runtime.values || {};
useEffect(() => {
updateNodeInternals(id);
}, [id, data.extracts.length, updateNodeInternals]);
const addExtract = () => {
replaceNodeData(id, (current) => ({
...current,
extracts: [
...current.extracts,
{
id: createBrowserId('json-extract'),
label: `result ${current.extracts.length}`,
path: '',
fields: '',
},
],
}));
};
const updateExtract = (extractId, patch) => {
replaceNodeData(id, (current) => ({
...current,
extracts: current.extracts.map((extract) =>
extract.id === extractId ? { ...extract, ...patch } : extract,
),
}));
};
const removeExtract = (extractId) => {
if (data.extracts.length <= 1) {
return;
}
removeHandleConnections(id, extractId, 'source');
replaceNodeData(id, (current) => ({
...current,
extracts: current.extracts.filter((extract) => extract.id !== extractId),
}));
};
const filledValuesCount = Object.values(values).filter(Boolean).length;
return (
<NodeShell
nodeId={id}
title={data.title}
accent={getNodeAccent(type)}
selected={selected}
status={runtime.status}
inputs={handles.inputs}
outputs={handles.outputs}
>
<div className="field-stack">
<div className="json-parser-rule-list">
{data.extracts.map((extract, index) => (
<div key={extract.id} className="json-parser-rule">
<div className="field-row">
<label className="field-stack">
<span className="field-label">Выход</span>
<NodeDraftInput
className="nodrag node-input"
value={extract.label}
placeholder={`результат ${index + 1}`}
onCommit={(value) => updateExtract(extract.id, { label: value })}
/>
</label>
<button
type="button"
className="nodrag chip__remove"
onClick={() => removeExtract(extract.id)}
disabled={data.extracts.length <= 1}
>
x
</button>
</div>
<label className="field-stack">
<span className="field-label">Путь</span>
<NodeDraftInput
className="nodrag node-input"
value={extract.path}
placeholder="data.filter_group.items"
onCommit={(value) => updateExtract(extract.id, { path: value })}
/>
</label>
<label className="field-stack">
<span className="field-label">Поля</span>
<NodeDraftInput
className="nodrag node-input"
value={extract.fields}
placeholder="key, name"
onCommit={(value) => updateExtract(extract.id, { fields: value })}
/>
</label>
</div>
))}
</div>
<button type="button" className="nodrag node-button node-button--ghost" onClick={addExtract}>
+ Добавить извлечение
</button>
<div className="node-note">
{filledValuesCount > 0
? `Извлечено выходов: ${filledValuesCount}.`
: 'Путь использует dot notation. Поля опциональны и задаются через запятую.'}
</div>
{runtime.error ? <div className="node-error">{runtime.error}</div> : null}
</div>
</NodeShell>
);
}
export default memo(JsonParserFlowNode);