diff --git a/src/features/transfer/MutateTransferForm/components/FilterRows/index.tsx b/src/features/transfer/MutateTransferForm/components/FilterRows/index.tsx new file mode 100644 index 00000000..c6725e80 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/FilterRows/index.tsx @@ -0,0 +1,6 @@ +import React, { memo } from 'react'; + +/** TODO: [DOP-22361] Add component content */ +export const FilterRows = memo(() => { + return
FilterRowsNode
; +}); diff --git a/src/features/transfer/MutateTransferForm/components/FilterRowsNode/FilterRowsNode.tsx b/src/features/transfer/MutateTransferForm/components/FilterRowsNode/FilterRowsNode.tsx new file mode 100644 index 00000000..d6f5d156 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/FilterRowsNode/FilterRowsNode.tsx @@ -0,0 +1,31 @@ +import React, { useMemo } from 'react'; +import { CanvasNode } from '@shared/ui'; +import { Handle, Position } from '@xyflow/react'; +import { FilterOutlined } from '@ant-design/icons'; + +import { FilterRows } from '../FilterRows'; +import { TransferCanvasEdge } from '../TransferConnectionsCanvas'; + +import { FilterRowsNodeProps } from './types'; + +export const FilterRowsNode = ({}: FilterRowsNodeProps) => { + const icon = useMemo(() => { + return ; + }, []); + + const children = useMemo(() => { + return ( + <> + + + + + ); + }, []); + + return ( + + {children} + + ); +}; diff --git a/src/features/transfer/MutateTransferForm/components/FilterRowsNode/index.ts b/src/features/transfer/MutateTransferForm/components/FilterRowsNode/index.ts new file mode 100644 index 00000000..7a06d705 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/FilterRowsNode/index.ts @@ -0,0 +1,2 @@ +export * from './FilterRowsNode'; +export * from './types'; diff --git a/src/features/transfer/MutateTransferForm/components/FilterRowsNode/types.ts b/src/features/transfer/MutateTransferForm/components/FilterRowsNode/types.ts new file mode 100644 index 00000000..5101e834 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/FilterRowsNode/types.ts @@ -0,0 +1,8 @@ +import { Node, NodeProps } from '@xyflow/react'; + +import { TransferCanvasTransformNodeType } from '../TransferConnectionsCanvas'; + +export interface FilterRowsNodeData + extends Node, TransferCanvasTransformNodeType.FILTER_ROWS> {} + +export interface FilterRowsNodeProps extends NodeProps {} diff --git a/src/features/transfer/MutateTransferForm/components/SourceParamsNode/SourceParamsNode.tsx b/src/features/transfer/MutateTransferForm/components/SourceParamsNode/SourceParamsNode.tsx index ade8579c..e717aca1 100644 --- a/src/features/transfer/MutateTransferForm/components/SourceParamsNode/SourceParamsNode.tsx +++ b/src/features/transfer/MutateTransferForm/components/SourceParamsNode/SourceParamsNode.tsx @@ -9,7 +9,6 @@ import { SourceParams } from '../SourceParams'; import { TransferCanvasEdge } from '../TransferConnectionsCanvas'; import { SourceParamsNodeProps } from './types'; -import classes from './styles.module.less'; export const SourceParamsNode = ({ data }: SourceParamsNodeProps) => { const connectionType = Form.useWatch(['source_params', 'type']); @@ -28,7 +27,7 @@ export const SourceParamsNode = ({ data }: SourceParamsNodeProps) => { }, [data.groupId, data.initialSourceConnectionType]); return ( - + {children} ); diff --git a/src/features/transfer/MutateTransferForm/components/SourceParamsNode/styles.module.less b/src/features/transfer/MutateTransferForm/components/SourceParamsNode/styles.module.less deleted file mode 100644 index c6b6dd45..00000000 --- a/src/features/transfer/MutateTransferForm/components/SourceParamsNode/styles.module.less +++ /dev/null @@ -1,3 +0,0 @@ -.root { - width: 300px; -} diff --git a/src/features/transfer/MutateTransferForm/components/SourceParamsNode/types.ts b/src/features/transfer/MutateTransferForm/components/SourceParamsNode/types.ts index a7c959ce..5d38a69c 100644 --- a/src/features/transfer/MutateTransferForm/components/SourceParamsNode/types.ts +++ b/src/features/transfer/MutateTransferForm/components/SourceParamsNode/types.ts @@ -1,8 +1,8 @@ import { Node, NodeProps } from '@xyflow/react'; import { SourceParamsProps } from '../SourceParams'; -import { TransferCanvasNode } from '../TransferConnectionsCanvas'; +import { TransferCanvasDefaultNodeType } from '../TransferConnectionsCanvas'; -export interface SourceParamsNodeData extends Node {} +export interface SourceParamsNodeData extends Node {} export interface SourceParamsNodeProps extends NodeProps {} diff --git a/src/features/transfer/MutateTransferForm/components/TargetParamsNode/TargetParamsNode.tsx b/src/features/transfer/MutateTransferForm/components/TargetParamsNode/TargetParamsNode.tsx index db66eb4c..9827c3bd 100644 --- a/src/features/transfer/MutateTransferForm/components/TargetParamsNode/TargetParamsNode.tsx +++ b/src/features/transfer/MutateTransferForm/components/TargetParamsNode/TargetParamsNode.tsx @@ -9,7 +9,6 @@ import { TargetParams } from '../TargetParams'; import { TransferCanvasEdge } from '../TransferConnectionsCanvas'; import { TargetParamsNodeProps } from './types'; -import classes from './styles.module.less'; export const TargetParamsNode = ({ data }: TargetParamsNodeProps) => { const connectionType = Form.useWatch(['target_params', 'type']); @@ -28,7 +27,7 @@ export const TargetParamsNode = ({ data }: TargetParamsNodeProps) => { }, [data.groupId, data.initialTargetConnectionType]); return ( - + {children} ); diff --git a/src/features/transfer/MutateTransferForm/components/TargetParamsNode/styles.module.less b/src/features/transfer/MutateTransferForm/components/TargetParamsNode/styles.module.less deleted file mode 100644 index c6b6dd45..00000000 --- a/src/features/transfer/MutateTransferForm/components/TargetParamsNode/styles.module.less +++ /dev/null @@ -1,3 +0,0 @@ -.root { - width: 300px; -} diff --git a/src/features/transfer/MutateTransferForm/components/TargetParamsNode/types.ts b/src/features/transfer/MutateTransferForm/components/TargetParamsNode/types.ts index 0be51b22..2073f923 100644 --- a/src/features/transfer/MutateTransferForm/components/TargetParamsNode/types.ts +++ b/src/features/transfer/MutateTransferForm/components/TargetParamsNode/types.ts @@ -1,8 +1,8 @@ import { Node, NodeProps } from '@xyflow/react'; import { TargetParamsProps } from '../TargetParams'; -import { TransferCanvasNode } from '../TransferConnectionsCanvas'; +import { TransferCanvasDefaultNodeType } from '../TransferConnectionsCanvas'; -export interface TargetParamsNodeData extends Node {} +export interface TargetParamsNodeData extends Node {} export interface TargetParamsNodeProps extends NodeProps {} diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx index 3d871f12..7d92f4d5 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx @@ -2,10 +2,13 @@ import React, { useMemo } from 'react'; import { Canvas, Fieldset } from '@shared/ui'; import { ReactFlowProvider, useEdgesState, useNodesState } from '@xyflow/react'; +import { TransformButtons } from '../TransformButtons'; + import { TransferCanvasProps } from './types'; import { getInitialNodes } from './utils'; import { INITIAL_EDGES, NODE_TYPES } from './constants'; import classes from './styles.module.less'; + import '@xyflow/react/dist/style.css'; export const TransferConnectionsCanvas = (props: TransferCanvasProps) => { @@ -29,7 +32,9 @@ export const TransferConnectionsCanvas = (props: TransferCanvasProps) => { edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} - /> + > + + diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts index fc5c9896..e3b9a488 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts @@ -2,19 +2,21 @@ import { Edge, NodeTypes } from '@xyflow/react'; import { SourceParamsNode } from '../SourceParamsNode'; import { TargetParamsNode } from '../TargetParamsNode'; +import { FilterRowsNode } from '../FilterRowsNode'; -import { TransferCanvasNode } from './types'; +import { TransferCanvasDefaultNodeType, TransferCanvasTransformNodeType } from './types'; export const INITIAL_EDGES: Edge[] = [ { id: 'edge-1', - source: TransferCanvasNode.SOURCE, - target: TransferCanvasNode.TARGET, + source: TransferCanvasDefaultNodeType.SOURCE, + target: TransferCanvasDefaultNodeType.TARGET, animated: true, }, ]; export const NODE_TYPES: NodeTypes = { - [TransferCanvasNode.SOURCE]: SourceParamsNode, - [TransferCanvasNode.TARGET]: TargetParamsNode, + [TransferCanvasDefaultNodeType.SOURCE]: SourceParamsNode, + [TransferCanvasDefaultNodeType.TARGET]: TargetParamsNode, + [TransferCanvasTransformNodeType.FILTER_ROWS]: FilterRowsNode, }; diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts index efc71617..f119895f 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts @@ -1,18 +1,26 @@ +import { FilterRowsNodeData } from '../FilterRowsNode'; import { SourceParamsNodeData } from '../SourceParamsNode'; import { TargetParamsNodeData } from '../TargetParamsNode'; import { GetInitialNodesProps } from './utils'; -export interface TransferCanvasProps extends GetInitialNodesProps {} +export interface TransferCanvasProps + extends Pick {} -export type TransferCanvasNodeData = SourceParamsNodeData | TargetParamsNodeData; +export type TransferCanvasNodeData = SourceParamsNodeData | TargetParamsNodeData | FilterRowsNodeData; -export enum TransferCanvasNode { +export enum TransferCanvasDefaultNodeType { SOURCE = 'SOURCE', TARGET = 'TARGET', } +export enum TransferCanvasTransformNodeType { + FILTER_ROWS = 'FILTER_ROWS', +} + export enum TransferCanvasEdge { SOURCE = 'SOURCE', TARGET = 'TARGET', + FILTER_ROWS_SOURCE = 'FILTER_ROWS_SOURCE', + FILTER_ROWS_TARGET = 'FILTER_ROWS_TARGET', } diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/utils/getInitialNodes/getInitialNodes.ts b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/utils/getInitialNodes/getInitialNodes.ts index 909e00c5..5523598a 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/utils/getInitialNodes/getInitialNodes.ts +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/utils/getInitialNodes/getInitialNodes.ts @@ -1,4 +1,4 @@ -import { TransferCanvasNodeData, TransferCanvasNode } from '../../types'; +import { TransferCanvasNodeData, TransferCanvasDefaultNodeType } from '../../types'; import { GetInitialNodesProps } from './types'; @@ -8,15 +8,15 @@ export const getInitialNodes = ({ initialTargetConnectionType, }: GetInitialNodesProps): TransferCanvasNodeData[] => [ { - id: TransferCanvasNode.SOURCE, - type: TransferCanvasNode.SOURCE, + id: TransferCanvasDefaultNodeType.SOURCE, + type: TransferCanvasDefaultNodeType.SOURCE, data: { groupId, initialSourceConnectionType }, position: { x: 0, y: 0 }, }, { - id: TransferCanvasNode.TARGET, - type: TransferCanvasNode.TARGET, + id: TransferCanvasDefaultNodeType.TARGET, + type: TransferCanvasDefaultNodeType.TARGET, data: { groupId, initialTargetConnectionType }, - position: { x: 600, y: 0 }, + position: { x: 500, y: 0 }, }, ]; diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/TransformButtons.tsx b/src/features/transfer/MutateTransferForm/components/TransformButtons/TransformButtons.tsx new file mode 100644 index 00000000..e6e9bcd2 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/TransformButtons/TransformButtons.tsx @@ -0,0 +1,28 @@ +import React, { memo } from 'react'; +import { Button, Typography } from 'antd'; + +import { TransferCanvasTransformNodeType } from '../TransferConnectionsCanvas'; + +import classes from './styles.module.less'; +import { useHandleNodes } from './hooks'; + +const { Text } = Typography; + +export const TransformButtons = memo(() => { + const { transformNodeTypes, handleAddTransformNode } = useHandleNodes(); + + return ( +
+ You can add some data transforms: +
+ +
+
+ ); +}); diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/hooks/index.ts b/src/features/transfer/MutateTransferForm/components/TransformButtons/hooks/index.ts new file mode 100644 index 00000000..0d21cc47 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/TransformButtons/hooks/index.ts @@ -0,0 +1 @@ +export * from './useHandleNodes'; diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/hooks/useHandleNodes/index.ts b/src/features/transfer/MutateTransferForm/components/TransformButtons/hooks/useHandleNodes/index.ts new file mode 100644 index 00000000..69467511 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/TransformButtons/hooks/useHandleNodes/index.ts @@ -0,0 +1,52 @@ +import { useReactFlow } from '@xyflow/react'; +import { useState } from 'react'; + +import { TransferCanvasDefaultNodeType, TransferCanvasTransformNodeType } from '../../../TransferConnectionsCanvas'; + +/** Hook for handling nodes and edges data (add, delete) */ +export const useHandleNodes = () => { + const [transformNodeTypes, setTransformNodeTypes] = useState>(); + const { getNodes, getEdges, setNodes, setEdges } = useReactFlow(); + + const addNewNode = (nodeType: TransferCanvasTransformNodeType) => { + const newNode = { + id: nodeType, + type: nodeType, + position: { x: 0, y: 0 }, + data: {}, + }; + + const nodes = getNodes(); + + const firstNodes = nodes.slice(0, nodes.length - 1); + const lastNode = nodes[nodes.length - 1]; + const newNodes = firstNodes.concat(newNode).concat(lastNode); + + setNodes(newNodes.map((node, index) => ({ ...node, position: { x: index * 500, y: 0 } }))); + }; + + const addNewEdge = (nodeType: TransferCanvasTransformNodeType) => { + const edges = getEdges(); + + const newEdge = { + id: `edge-${edges.length + 1}`, + source: nodeType, + target: TransferCanvasDefaultNodeType.TARGET, + animated: true, + }; + + const firstEdges = edges.slice(0, edges.length - 1); + const lastEdge = { ...edges[edges.length - 1], target: nodeType }; + const newEdges = firstEdges.concat(lastEdge).concat(newEdge); + + setEdges(newEdges); + }; + + const handleAddTransformNode = (nodeType: TransferCanvasTransformNodeType) => { + setTransformNodeTypes((state) => ({ ...state, [nodeType]: true })); + addNewNode(nodeType); + addNewEdge(nodeType); + }; + + return { transformNodeTypes, handleAddTransformNode }; +}; diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/index.ts b/src/features/transfer/MutateTransferForm/components/TransformButtons/index.ts new file mode 100644 index 00000000..cd35d2b9 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/TransformButtons/index.ts @@ -0,0 +1 @@ +export * from './TransformButtons'; diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/styles.module.less b/src/features/transfer/MutateTransferForm/components/TransformButtons/styles.module.less new file mode 100644 index 00000000..d825a71c --- /dev/null +++ b/src/features/transfer/MutateTransferForm/components/TransformButtons/styles.module.less @@ -0,0 +1,20 @@ +.root { + display: flex; + flex-direction: column; + gap: 8px; + position: absolute; + bottom: 0; + left: 50%; + transform: translateX(-50%); + background-color: @white; + margin-bottom: 15px; + border-radius: 16px; + padding: 16px; + z-index: 5; + + .buttons { + display: flex; + align-items: center; + gap: 12px; + } +} diff --git a/src/shared/ui/Canvas/index.tsx b/src/shared/ui/Canvas/index.tsx index 794a0feb..4aae0865 100644 --- a/src/shared/ui/Canvas/index.tsx +++ b/src/shared/ui/Canvas/index.tsx @@ -1,10 +1,17 @@ -import { Background, BackgroundVariant, Controls, Edge, MiniMap, Node, ReactFlow } from '@xyflow/react'; -import React from 'react'; +import { Background, BackgroundVariant, Controls, Edge, MiniMap, Node, ReactFlow, useReactFlow } from '@xyflow/react'; +import React, { useEffect } from 'react'; import classes from './styles.module.less'; import { CanvasProps } from './types'; -export const Canvas = (props: CanvasProps) => { +export const Canvas = ({ children, nodes, ...props }: CanvasProps) => { + const { fitView } = useReactFlow(); + + /** Set appropriate zoom of canvas when nodes count has changed */ + useEffect(() => { + fitView({ duration: 200 }); + }, [nodes?.length, fitView]); + return ( (props: CanvasProps) nodesFocusable elementsSelectable nodesConnectable={false} + nodes={nodes} nodesDraggable panOnScroll={false} panOnDrag zoomOnScroll zoomOnPinch zoomOnDoubleClick={false} - fitViewOptions={{ duration: 200, padding: 1 }} + fitViewOptions={{ duration: 200, padding: 0.5 }} fitView {...props} > + {children} ); }; diff --git a/src/shared/ui/Canvas/styles.module.less b/src/shared/ui/Canvas/styles.module.less index 75413e6c..46d14d57 100644 --- a/src/shared/ui/Canvas/styles.module.less +++ b/src/shared/ui/Canvas/styles.module.less @@ -1,10 +1,13 @@ .root { :global(.react-flow__minimap) { - transform: scale(70%); + svg { + width: 140px; + height: 105px; + } } :global(.react-flow__node) { - width: fit-content; + width: 300px; background-color: @white; border: 1px solid fade(@black, 25%); border-radius: 16px;