전략편집기 목록방식 오류 수정
This commit is contained in:
@@ -32,6 +32,7 @@ import {
|
||||
import StartTimeframeCheckboxes from './StartTimeframeCheckboxes';
|
||||
import LogicGateOpToggle from './LogicGateOpToggle';
|
||||
import { formatStartCandleTypesLabel } from '../../utils/strategyStartNodes';
|
||||
import { START_NODE_ID } from '../../utils/strategyFlowLayout';
|
||||
import { buildSidewaysFilterNode } from '../../utils/sidewaysFilterPaletteStorage';
|
||||
import {
|
||||
findPaletteDropKeyAtPoint,
|
||||
@@ -293,7 +294,7 @@ interface StartSectionBlockProps {
|
||||
def: DefType;
|
||||
dragOverKey: string | null;
|
||||
setDragOverKey: (key: string | null) => void;
|
||||
onRootChange: (root: LogicNode | null) => void;
|
||||
onRootChange: (root: LogicNode | null | ((prev: LogicNode | null) => LogicNode | null)) => void;
|
||||
onCandleTypesChange: (candleTypes: string[]) => void;
|
||||
onDeleteStart?: () => void;
|
||||
onAddStart?: () => void;
|
||||
@@ -324,16 +325,14 @@ function StartSectionBlock({
|
||||
return;
|
||||
}
|
||||
const newNode = makeNode(data.type, data.value, signalTab, def, makeNodeOptionsFromPalette(data));
|
||||
if (!root) {
|
||||
onRootChange(newNode);
|
||||
return;
|
||||
}
|
||||
if (!targetId) {
|
||||
onRootChange(mergeAtRoot(root, newNode, data.type === 'operator'));
|
||||
return;
|
||||
}
|
||||
onRootChange(addChild(root, targetId, newNode));
|
||||
}, [root, signalTab, def, onRootChange, onAddStart]);
|
||||
onRootChange(prev => {
|
||||
if (!prev) return newNode;
|
||||
if (!targetId) {
|
||||
return mergeAtRoot(prev, newNode, data.type === 'operator');
|
||||
}
|
||||
return addChild(prev, targetId, newNode);
|
||||
});
|
||||
}, [signalTab, def, onRootChange, onAddStart]);
|
||||
|
||||
const handleSectionDrop = (e: React.DragEvent) => {
|
||||
e.preventDefault();
|
||||
@@ -408,7 +407,9 @@ interface Props {
|
||||
editorState: EditorConditionState;
|
||||
signalTab: 'buy' | 'sell';
|
||||
def: DefType;
|
||||
onEditorStateChange: (next: EditorConditionState) => void;
|
||||
onEditorStateChange: (
|
||||
next: EditorConditionState | ((prev: EditorConditionState) => EditorConditionState),
|
||||
) => void;
|
||||
onAddStart?: () => void;
|
||||
onOrphansChange?: (nodes: LogicNode[]) => void;
|
||||
orphans?: LogicNode[];
|
||||
@@ -438,24 +439,35 @@ export default function StrategyListEditor({
|
||||
onAddStart();
|
||||
return;
|
||||
}
|
||||
onEditorStateChange(addExtraStartSection(editorState));
|
||||
}, [onAddStart, onEditorStateChange, editorState]);
|
||||
onEditorStateChange(prev => addExtraStartSection(prev));
|
||||
}, [onAddStart, onEditorStateChange]);
|
||||
|
||||
const handleRootChange = useCallback((startId: string, root: LogicNode | null) => {
|
||||
onEditorStateChange(updateBranchRoot(editorState, startId, root));
|
||||
}, [editorState, onEditorStateChange]);
|
||||
const handleRootChange = useCallback((
|
||||
startId: string,
|
||||
root: LogicNode | null | ((prev: LogicNode | null) => LogicNode | null),
|
||||
) => {
|
||||
onEditorStateChange(prev => {
|
||||
const currentRoot = startId === START_NODE_ID
|
||||
? prev.root
|
||||
: (prev.extraRoots[startId] ?? null);
|
||||
const resolved = typeof root === 'function' ? root(currentRoot) : root;
|
||||
return updateBranchRoot(prev, startId, resolved);
|
||||
});
|
||||
}, [onEditorStateChange]);
|
||||
|
||||
const handleCandleTypesChange = useCallback((startId: string, candleTypes: string[]) => {
|
||||
onEditorStateChange(updateStartCandleTypes(editorState, startId, candleTypes));
|
||||
}, [editorState, onEditorStateChange]);
|
||||
onEditorStateChange(prev => updateStartCandleTypes(prev, startId, candleTypes));
|
||||
}, [onEditorStateChange]);
|
||||
|
||||
const handleDeleteStart = useCallback((startId: string) => {
|
||||
const { state, orphanedNodes } = removeStartSection(editorState, startId);
|
||||
onEditorStateChange(state);
|
||||
if (orphanedNodes.length && onOrphansChange) {
|
||||
onOrphansChange([...orphans, ...orphanedNodes]);
|
||||
}
|
||||
}, [editorState, onEditorStateChange, onOrphansChange, orphans]);
|
||||
onEditorStateChange(prev => {
|
||||
const { state, orphanedNodes } = removeStartSection(prev, startId);
|
||||
if (orphanedNodes.length && onOrphansChange) {
|
||||
onOrphansChange([...orphans, ...orphanedNodes]);
|
||||
}
|
||||
return state;
|
||||
});
|
||||
}, [onEditorStateChange, onOrphansChange, orphans]);
|
||||
|
||||
const resolvePaletteNode = useCallback((
|
||||
data: { type: string; value: string; label: string; composite?: boolean },
|
||||
@@ -487,26 +499,25 @@ export default function StrategyListEditor({
|
||||
return;
|
||||
}
|
||||
|
||||
const section = collectStartSections(editorState).find(s => s.startId === startId);
|
||||
if (!section) return;
|
||||
|
||||
const newNode = resolvePaletteNode(data);
|
||||
if (!newNode) return;
|
||||
|
||||
const root = section.root;
|
||||
if (!root) {
|
||||
handleRootChange(startId, newNode);
|
||||
return;
|
||||
}
|
||||
if (!targetId) {
|
||||
handleRootChange(startId, mergeAtRoot(root, newNode, data.type === 'operator'));
|
||||
return;
|
||||
}
|
||||
handleRootChange(startId, addChild(root, targetId, newNode));
|
||||
onEditorStateChange(prev => {
|
||||
const section = collectStartSections(prev).find(s => s.startId === startId);
|
||||
if (!section) return prev;
|
||||
|
||||
const root = section.root;
|
||||
if (!root) {
|
||||
return updateBranchRoot(prev, startId, newNode);
|
||||
}
|
||||
if (!targetId) {
|
||||
return updateBranchRoot(prev, startId, mergeAtRoot(root, newNode, data.type === 'operator'));
|
||||
}
|
||||
return updateBranchRoot(prev, startId, addChild(root, targetId, newNode));
|
||||
});
|
||||
}, [
|
||||
editorState,
|
||||
handleAddStart,
|
||||
handleRootChange,
|
||||
onEditorStateChange,
|
||||
resolvePaletteNode,
|
||||
]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user