Spaces:
Sleeping
Sleeping
File size: 4,473 Bytes
1dd9186 cfaaa6c 1dd9186 cfaaa6c 1dd9186 cfaaa6c 1dd9186 cfaaa6c 1dd9186 cfaaa6c 1dd9186 cfaaa6c 1dd9186 cfaaa6c 1dd9186 cfaaa6c 1dd9186 cfaaa6c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 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);
|