diff --git a/src/entities/transformation/constants.ts b/src/entities/transformation/constants.ts index fe94bd1b..272f5db8 100644 --- a/src/entities/transformation/constants.ts +++ b/src/entities/transformation/constants.ts @@ -1,3 +1,4 @@ +import { ConnectionType } from '@shared/types'; import { createContext } from 'react'; import { @@ -17,9 +18,9 @@ const SHOW_BUTTONS_CONTEXT_INITIAL_VALUE: ShowButtonsContextProps = { export const ShowButtonsContext = createContext(SHOW_BUTTONS_CONTEXT_INITIAL_VALUE); export const TRANSFORMATIONS_FORM_DEFAULT_VALUE: TransformationsForm = { + [TransformationType.FILTER_FILE]: [], [TransformationType.FILTER_ROWS]: [], [TransformationType.FILTER_COLUMNS]: [], - [TransformationType.FILTER_FILE]: [], }; export const TRANSFORMATIONS_REQUEST_DEFAULT_VALUE: Transformations = [ @@ -65,3 +66,24 @@ export const TRANSFORMATION_FILTER_FILE_TYPE_DISPLAY = { [TransformationFilterFileType.FILE_SIZE_MIN]: 'fileSizeMin', [TransformationFilterFileType.FILE_SIZE_MAX]: 'fileSizeMax', } as const; + +const FILE_TRANSFORMATION_TYPES = Object.values(TransformationType); + +const DB_TRANSFORMATION_TYPES = FILE_TRANSFORMATION_TYPES.filter((type) => type !== TransformationType.FILTER_FILE); + +export const CONNECTION_TYPE_SUPPORT_TRANSFORMATION_TYPES: Record = { + [ConnectionType.CLICKHOUSE]: DB_TRANSFORMATION_TYPES, + [ConnectionType.FTP]: FILE_TRANSFORMATION_TYPES, + [ConnectionType.FTPS]: FILE_TRANSFORMATION_TYPES, + [ConnectionType.HDFS]: DB_TRANSFORMATION_TYPES, + [ConnectionType.HIVE]: DB_TRANSFORMATION_TYPES, + [ConnectionType.ICEBERG]: DB_TRANSFORMATION_TYPES, + [ConnectionType.MSSQL]: DB_TRANSFORMATION_TYPES, + [ConnectionType.MYSQL]: DB_TRANSFORMATION_TYPES, + [ConnectionType.ORACLE]: DB_TRANSFORMATION_TYPES, + [ConnectionType.POSTGRES]: DB_TRANSFORMATION_TYPES, + [ConnectionType.S3]: DB_TRANSFORMATION_TYPES, + [ConnectionType.SAMBA]: FILE_TRANSFORMATION_TYPES, + [ConnectionType.SFTP]: FILE_TRANSFORMATION_TYPES, + [ConnectionType.WEBDAV]: FILE_TRANSFORMATION_TYPES, +}; diff --git a/src/entities/transformation/types.ts b/src/entities/transformation/types.ts index ae4d5335..2e81e09e 100644 --- a/src/entities/transformation/types.ts +++ b/src/entities/transformation/types.ts @@ -110,9 +110,9 @@ export interface TransformationFilterFileForm { export type Transformations = Array; export interface TransformationsForm { + [TransformationType.FILTER_FILE]?: TransformationFilterFileForm['filters']; [TransformationType.FILTER_ROWS]?: TransformationFilterRows['filters']; [TransformationType.FILTER_COLUMNS]?: TransformationFilterColumns['filters']; - [TransformationType.FILTER_FILE]?: TransformationFilterFileForm['filters']; } export type TransformationsFormNestedType = diff --git a/src/entities/transformation/ui/TransformationForm/components/TransformationFormItem/hooks/useGetNestedTypesSelectOptions/index.ts b/src/entities/transformation/ui/TransformationForm/components/TransformationFormItem/hooks/useGetNestedTypesSelectOptions/index.ts index 4500bc2f..dc51bde5 100644 --- a/src/entities/transformation/ui/TransformationForm/components/TransformationFormItem/hooks/useGetNestedTypesSelectOptions/index.ts +++ b/src/entities/transformation/ui/TransformationForm/components/TransformationFormItem/hooks/useGetNestedTypesSelectOptions/index.ts @@ -37,9 +37,9 @@ export const useGetNestedTypesSelectOptions = (transformationType: Transformatio TransformationType, OptionItem[] > = { + [TransformationType.FILTER_FILE]: filterFileTypeSelectOptions, [TransformationType.FILTER_ROWS]: filterRowsTypeSelectOptions, [TransformationType.FILTER_COLUMNS]: filterColumnsTypeSelectOptions, - [TransformationType.FILTER_FILE]: filterFileTypeSelectOptions, }; return filterOptions; diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx index a0120fe1..63f42129 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/TransferConnectionsCanvas.tsx @@ -1,10 +1,11 @@ -import React, { useMemo } from 'react'; +import { useMemo } from 'react'; import { Canvas } from '@shared/ui'; import { ReactFlowProvider } from '@xyflow/react'; import { Form } from 'antd'; import { ShowButtonsContext, TransformationsForm, TransformationType } from '@entities/transformation'; import { TransformButtons } from '../TransformButtons'; +import { useSupportedTransformationTypes } from '../../hooks'; import { TransferCanvasProps } from './types'; import { getInitialEdges, getInitialNodes } from './utils'; @@ -15,6 +16,7 @@ import '@xyflow/react/dist/style.css'; export const TransferConnectionsCanvas = ({ groupId, isDisplayedButtons = true }: TransferCanvasProps) => { const formInstance = Form.useFormInstance(); + const { supportedTransformationTypes } = useSupportedTransformationTypes(); const initialTransformations = useMemo(() => { return formInstance.getFieldValue('transformations') as TransformationsForm; @@ -23,11 +25,17 @@ export const TransferConnectionsCanvas = ({ groupId, isDisplayedButtons = true } const initialNodes = useMemo(() => { return getInitialNodes({ groupId, - hasFilterRows: !!initialTransformations[TransformationType.FILTER_ROWS]?.length, - hasFilterColumns: !!initialTransformations[TransformationType.FILTER_COLUMNS]?.length, - hasFilterFile: !!initialTransformations[TransformationType.FILTER_FILE]?.length, + hasFilterFile: + supportedTransformationTypes.includes(TransformationType.FILTER_FILE) && + !!initialTransformations[TransformationType.FILTER_FILE]?.length, + hasFilterRows: + supportedTransformationTypes.includes(TransformationType.FILTER_ROWS) && + !!initialTransformations[TransformationType.FILTER_ROWS]?.length, + hasFilterColumns: + supportedTransformationTypes.includes(TransformationType.FILTER_COLUMNS) && + !!initialTransformations[TransformationType.FILTER_COLUMNS]?.length, }); - }, [groupId, initialTransformations]); + }, [groupId, supportedTransformationTypes, initialTransformations]); const initialEdges = useMemo(() => { return getInitialEdges(initialNodes); diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts index d23dc0e5..489aa904 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/constants.ts @@ -1,4 +1,5 @@ import { NodeTypes } from '@xyflow/react'; +import { TransformationType } from '@entities/transformation'; import { SourceParamsNode } from '../SourceParamsNode'; import { TargetParamsNode } from '../TargetParamsNode'; @@ -11,24 +12,24 @@ import { TransferCanvasDefaultNodeType, TransferCanvasEdgeType, TransferCanvasTr export const NODE_TYPES: NodeTypes = { [TransferCanvasDefaultNodeType.SOURCE]: SourceParamsNode, [TransferCanvasDefaultNodeType.TARGET]: TargetParamsNode, + [TransferCanvasTransformNodeType.FILTER_FILE]: FilterFileNode, [TransferCanvasTransformNodeType.FILTER_ROWS]: FilterRowsNode, [TransferCanvasTransformNodeType.FILTER_COLUMNS]: FilterColumnsNode, - [TransferCanvasTransformNodeType.FILTER_FILE]: FilterFileNode, }; export const NODE_TYPES_ID = { [TransferCanvasDefaultNodeType.SOURCE]: '1', - [TransferCanvasTransformNodeType.FILTER_ROWS]: '2', - [TransferCanvasTransformNodeType.FILTER_COLUMNS]: '3', - [TransferCanvasTransformNodeType.FILTER_FILE]: '4', + [TransferCanvasTransformNodeType.FILTER_FILE]: '2', + [TransferCanvasTransformNodeType.FILTER_ROWS]: '3', + [TransferCanvasTransformNodeType.FILTER_COLUMNS]: '4', [TransferCanvasDefaultNodeType.TARGET]: '5', }; export const EDGE_TYPES_ID = { [TransferCanvasEdgeType.SOURCE]: '1', - [TransferCanvasEdgeType.FILTER_ROWS]: '2', - [TransferCanvasEdgeType.FILTER_COLUMNS]: '3', - [TransferCanvasEdgeType.FILTER_FILE]: '4', + [TransferCanvasEdgeType.FILTER_FILE]: '2', + [TransferCanvasEdgeType.FILTER_ROWS]: '3', + [TransferCanvasEdgeType.FILTER_COLUMNS]: '4', [TransferCanvasEdgeType.TARGET]: '5', }; @@ -36,7 +37,29 @@ export const NODE_POSITION_X_GAP_DEFAULT = 500; export const NODE_POSITION_X_GAP_LARGE = 1000; export const TRANSFER_CANVAS_TRANSFORM_NODE_TYPE_NAME_DISPLAY = { + [TransferCanvasTransformNodeType.FILTER_FILE]: 'filterFile', [TransferCanvasTransformNodeType.FILTER_ROWS]: 'filterRows', [TransferCanvasTransformNodeType.FILTER_COLUMNS]: 'filterColumns', - [TransferCanvasTransformNodeType.FILTER_FILE]: 'filterFile', } as const; + +export const TRANSFER_CANVAS_NODE_TYPE_TO_TRANSFORM_TYPE_MAP: Record< + TransferCanvasTransformNodeType, + TransformationType +> = { + [TransferCanvasTransformNodeType.FILTER_FILE]: TransformationType.FILTER_FILE, + [TransferCanvasTransformNodeType.FILTER_ROWS]: TransformationType.FILTER_ROWS, + [TransferCanvasTransformNodeType.FILTER_COLUMNS]: TransformationType.FILTER_COLUMNS, +} as const; + +export const TRANSFER_TRANSFORM_TYPE_TO_CANVAS_NODE_TYPE_MAP: Record< + TransformationType, + TransferCanvasTransformNodeType +> = { + [TransformationType.FILTER_FILE]: TransferCanvasTransformNodeType.FILTER_FILE, + [TransformationType.FILTER_ROWS]: TransferCanvasTransformNodeType.FILTER_ROWS, + [TransformationType.FILTER_COLUMNS]: TransferCanvasTransformNodeType.FILTER_COLUMNS, +} as const; + +export const TRANSFER_CANVAS_FILTER_NODES = Object.values( + TransferCanvasTransformNodeType, +) as TransferCanvasTransformNodeType[]; diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts index e03e4f4f..4ddc7a16 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/types.ts @@ -23,16 +23,16 @@ export enum TransferCanvasDefaultNodeType { } export enum TransferCanvasTransformNodeType { + FILTER_FILE = 'FILTER_FILE', FILTER_ROWS = 'FILTER_ROWS', FILTER_COLUMNS = 'FILTER_COLUMNS', - FILTER_FILE = 'FILTER_FILE', } export enum TransferCanvasEdgeType { SOURCE = 'SOURCE', + FILTER_FILE = 'FILTER_FILE', FILTER_ROWS = 'FILTER_ROWS', FILTER_COLUMNS = 'FILTER_COLUMNS', - FILTER_FILE = 'FILTER_FILE', TARGET = '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 3acef657..a6ae11b8 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/utils/getInitialNodes/getInitialNodes.ts +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsCanvas/utils/getInitialNodes/getInitialNodes.ts @@ -21,30 +21,30 @@ export const getInitialNodes = ({ let nodeIndex = 1; - if (hasFilterRows) { + if (hasFilterFile) { nodes.push({ - id: NODE_TYPES_ID[TransferCanvasTransformNodeType.FILTER_ROWS], - type: TransferCanvasTransformNodeType.FILTER_ROWS, + id: NODE_TYPES_ID[TransferCanvasTransformNodeType.FILTER_FILE], + type: TransferCanvasTransformNodeType.FILTER_FILE, data: {}, position: setNodePosition(nodeIndex), }); nodeIndex++; } - if (hasFilterColumns) { + if (hasFilterRows) { nodes.push({ - id: NODE_TYPES_ID[TransferCanvasTransformNodeType.FILTER_COLUMNS], - type: TransferCanvasTransformNodeType.FILTER_COLUMNS, + id: NODE_TYPES_ID[TransferCanvasTransformNodeType.FILTER_ROWS], + type: TransferCanvasTransformNodeType.FILTER_ROWS, data: {}, position: setNodePosition(nodeIndex), }); nodeIndex++; } - if (hasFilterFile) { + if (hasFilterColumns) { nodes.push({ - id: NODE_TYPES_ID[TransferCanvasTransformNodeType.FILTER_FILE], - type: TransferCanvasTransformNodeType.FILTER_FILE, + id: NODE_TYPES_ID[TransferCanvasTransformNodeType.FILTER_COLUMNS], + type: TransferCanvasTransformNodeType.FILTER_COLUMNS, data: {}, position: setNodePosition(nodeIndex), }); diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/constants.tsx b/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/constants.tsx index 525ec9bc..a003489c 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/constants.tsx +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/constants.tsx @@ -8,6 +8,10 @@ import { FilterRowsFormItem } from '../FilterRowsFormItem'; import { FilterTypeConfig } from './types'; export const FILTER_TYPES_CONFIG: Record = { + [TransformationType.FILTER_FILE]: { + title: 'filterFile', + filter: , + }, [TransformationType.FILTER_ROWS]: { title: 'filterRows', filter: , @@ -16,8 +20,4 @@ export const FILTER_TYPES_CONFIG: Record = title: 'filterColumns', filter: , }, - [TransformationType.FILTER_FILE]: { - title: 'filterFile', - filter: , - }, } as const; diff --git a/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/index.tsx b/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/index.tsx index 97d059b0..d26aad84 100644 --- a/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/index.tsx +++ b/src/features/transfer/MutateTransferForm/components/TransferConnectionsDefault/index.tsx @@ -1,24 +1,29 @@ -import React, { useMemo } from 'react'; +import { useMemo } from 'react'; import { Fieldset } from '@shared/ui'; import { useTranslation } from 'react-i18next'; +import { TransformationType } from '@entities/transformation'; import { SourceParams } from '../SourceParams'; import { TargetParams } from '../TargetParams'; +import { useSupportedTransformationTypes } from '../../hooks'; import { TransferConnectionsDefaultProps } from './types'; import { FILTER_TYPES_CONFIG } from './constants'; export const TransferConnectionsDefault = ({ groupId }: TransferConnectionsDefaultProps) => { const { t } = useTranslation('transfer'); + const { supportedTransformationTypes } = useSupportedTransformationTypes(); const filters = useMemo( () => - Object.entries(FILTER_TYPES_CONFIG).map(([key, { title, filter }]) => ( -
- {filter} -
- )), - [t], + Object.entries(FILTER_TYPES_CONFIG) + .filter(([key]) => supportedTransformationTypes.includes(key as TransformationType)) + .map(([key, { title, filter }]) => ( +
+ {filter} +
+ )), + [supportedTransformationTypes, t], ); return ( diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/TransformButtons.tsx b/src/features/transfer/MutateTransferForm/components/TransformButtons/TransformButtons.tsx index 217b5a52..3d5a735c 100644 --- a/src/features/transfer/MutateTransferForm/components/TransformButtons/TransformButtons.tsx +++ b/src/features/transfer/MutateTransferForm/components/TransformButtons/TransformButtons.tsx @@ -1,4 +1,4 @@ -import React, { memo, useState } from 'react'; +import { memo, useState } from 'react'; import { Typography } from 'antd'; import { useModalState } from '@shared/hooks'; import { ModalWrapper } from '@shared/ui'; @@ -8,7 +8,9 @@ import { useTranslation } from 'react-i18next'; import { TransferCanvasTransformNodeType, TRANSFER_CANVAS_TRANSFORM_NODE_TYPE_NAME_DISPLAY, + TRANSFER_CANVAS_NODE_TYPE_TO_TRANSFORM_TYPE_MAP, } from '../TransferConnectionsCanvas'; +import { useSupportedTransformationTypes } from '../../hooks'; import { useHandleNodes } from './hooks'; import { DeleteNode, TransformButtonItem } from './components'; @@ -20,6 +22,8 @@ export const TransformButtons = memo(() => { const { t } = useTranslation('transformation'); const { transformNodeTypes, handleAddTransformNode, handleDeleteTransformNode } = useHandleNodes(); + const { supportedTransformationTypes } = useSupportedTransformationTypes(); + const [nodeTypeForDeleting, setNodeTypeForDeleting] = useState(null); const { isOpened: isOpenedModal, handleOpen: openModal, handleClose: handleCloseModal } = useModalState(); @@ -38,15 +42,19 @@ export const TransformButtons = memo(() => {
{t('transformations')}
- {Object.values(TransferCanvasTransformNodeType).map((item, index) => ( - - ))} + {Object.values(TransferCanvasTransformNodeType) + .filter((item) => + supportedTransformationTypes.includes(TRANSFER_CANVAS_NODE_TYPE_TO_TRANSFORM_TYPE_MAP[item]), + ) + .map((item) => ( + + ))}
{nodeTypeForDeleting && ( { const { getNodes, getEdges, setNodes, setEdges } = useReactFlow(); const formInstance = Form.useFormInstance(); + const { supportedTransformationTypes } = useSupportedTransformationTypes(); const [transformNodeTypes, setTransformNodeTypes] = useState(); @@ -85,8 +90,8 @@ export const useHandleNodes = () => { .map((node, index) => ({ ...node, position: setNodePosition(index) })), ); - const currentTransformationsFormValues = formInstance.getFieldValue('transformations'); - delete currentTransformationsFormValues[getTransformationType(nodeType)]; + const currentTransformationsFormValues = formInstance.getFieldValue('transformations') as TransformationsForm; + currentTransformationsFormValues[TRANSFER_CANVAS_NODE_TYPE_TO_TRANSFORM_TYPE_MAP[nodeType]] = []; formInstance.setFieldValue('transformations', currentTransformationsFormValues); }; @@ -141,5 +146,19 @@ export const useHandleNodes = () => { deleteEdge(nodeType); }; + /** Remove nodes that are not supported for the connection type */ + useEffect(() => { + getNodes() + .filter( + ({ type }) => + TRANSFER_CANVAS_FILTER_NODES.includes(type as TransferCanvasTransformNodeType) && + !supportedTransformationTypes.includes( + TRANSFER_CANVAS_NODE_TYPE_TO_TRANSFORM_TYPE_MAP[type as TransferCanvasTransformNodeType], + ), + ) + .forEach(({ type }) => handleDeleteTransformNode(type as TransferCanvasTransformNodeType)); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [supportedTransformationTypes]); + return { transformNodeTypes, handleAddTransformNode, handleDeleteTransformNode }; }; diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/utils/getTransformationType/index.ts b/src/features/transfer/MutateTransferForm/components/TransformButtons/utils/getTransformationType/index.ts deleted file mode 100644 index 69a7527d..00000000 --- a/src/features/transfer/MutateTransferForm/components/TransformButtons/utils/getTransformationType/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { TransformationType } from '@entities/transformation'; - -import { TransferCanvasTransformNodeType } from '../../../TransferConnectionsCanvas'; - -/** Util for matching react flow node type to transformation type from backend */ -export const getTransformationType = (nodeType: TransferCanvasTransformNodeType): TransformationType => { - switch (nodeType) { - case TransferCanvasTransformNodeType.FILTER_ROWS: - return TransformationType.FILTER_ROWS; - case TransferCanvasTransformNodeType.FILTER_COLUMNS: - return TransformationType.FILTER_COLUMNS; - case TransferCanvasTransformNodeType.FILTER_FILE: - return TransformationType.FILTER_FILE; - } -}; diff --git a/src/features/transfer/MutateTransferForm/components/TransformButtons/utils/index.ts b/src/features/transfer/MutateTransferForm/components/TransformButtons/utils/index.ts index e8af44d0..d4d08772 100644 --- a/src/features/transfer/MutateTransferForm/components/TransformButtons/utils/index.ts +++ b/src/features/transfer/MutateTransferForm/components/TransformButtons/utils/index.ts @@ -1,2 +1 @@ export * from './getInitialTransformNodeTypes'; -export * from './getTransformationType'; diff --git a/src/features/transfer/MutateTransferForm/hooks/index.ts b/src/features/transfer/MutateTransferForm/hooks/index.ts index 25a60916..461508ed 100644 --- a/src/features/transfer/MutateTransferForm/hooks/index.ts +++ b/src/features/transfer/MutateTransferForm/hooks/index.ts @@ -1 +1,2 @@ export * from './useSelectConnectionType'; +export * from './useSupportedTransformationTypes'; diff --git a/src/features/transfer/MutateTransferForm/hooks/useSupportedTransformationTypes/index.ts b/src/features/transfer/MutateTransferForm/hooks/useSupportedTransformationTypes/index.ts new file mode 100644 index 00000000..8904ed00 --- /dev/null +++ b/src/features/transfer/MutateTransferForm/hooks/useSupportedTransformationTypes/index.ts @@ -0,0 +1,13 @@ +import { CONNECTION_TYPE_SUPPORT_TRANSFORMATION_TYPES } from '@entities/transformation'; + +import { useSelectConnectionType } from '../useSelectConnectionType'; + +/** Hook to get supported transformations for selected source */ +export const useSupportedTransformationTypes = () => { + const { selectedConnectionType } = useSelectConnectionType({ + connectionParamFieldName: 'source_params', + }); + const supportedTransformationTypes = CONNECTION_TYPE_SUPPORT_TRANSFORMATION_TYPES[selectedConnectionType]; + + return { supportedTransformationTypes }; +};