From d5139a2115627e30009b67243e0c038c2a00eff2 Mon Sep 17 00:00:00 2001 From: Kirill Chernikov <72095428+Zabilsya@users.noreply.github.com> Date: Sat, 2 Nov 2024 13:22:43 +0600 Subject: [PATCH] [DOP-20065] transfer list and transfer detail (#40) Co-authored-by: Zabilsya --- .env.example | 2 +- src/app/config/router/instance.tsx | 9 +++ src/app/styles/antd.less | 6 +- src/entities/connection/api/types.ts | 22 ++--- src/entities/transfer/api/hooks/index.ts | 1 + .../api/hooks/useGetTransfer/index.ts | 13 +++ src/entities/transfer/api/index.ts | 4 + src/entities/transfer/api/keys/index.ts | 4 + src/entities/transfer/api/transferService.ts | 14 ++++ src/entities/transfer/api/types.ts | 81 +++++++++++++++++++ src/entities/transfer/index.ts | 1 + .../components/ConnectionAuthData/index.tsx | 2 +- .../utils/getDescriptionItems/index.ts | 9 ++- .../components/ConnectionData/index.tsx | 2 +- .../utils/getDescriptionItems/index.ts | 11 +-- .../connection/ConnectionDetailInfo/index.tsx | 9 ++- .../ConnectionDetailInfo/styles.module.less | 14 ++++ .../TransferFileFormatData/index.tsx | 20 +++++ .../TransferFileFormatData/types.ts | 6 ++ .../utils/getDescriptionItems/index.ts | 48 +++++++++++ .../utils/getDescriptionItems/types.ts | 5 ++ .../TransferFileFormatData/utils/index.ts | 1 + .../components/TransferParams/index.tsx | 20 +++++ .../components/TransferParams/types.ts | 6 ++ .../utils/getDescriptionItems/index.tsx | 33 ++++++++ .../utils/getDescriptionItems/types.ts | 5 ++ .../components/TransferParams/utils/index.ts | 1 + .../TransferDetailInfo/components/index.ts | 2 + .../transfer/TransferDetailInfo/index.tsx | 50 ++++++++++++ .../TransferDetailInfo/styles.module.less | 23 ++++++ .../transfer/TransferDetailInfo/types.ts | 13 +++ .../transfer/TransferList/constants.tsx | 23 ++++++ src/features/transfer/TransferList/index.tsx | 21 +++++ src/features/transfer/TransferList/types.ts | 5 ++ src/features/transfer/index.ts | 2 + .../transfer/TransferDetailPage/index.tsx | 38 +++++++++ src/pages/transfer/TransferListPage/index.tsx | 30 +++++++ src/pages/transfer/index.ts | 2 + src/shared/types/connection.ts | 7 ++ src/shared/types/file.ts | 29 +++++++ src/shared/types/index.ts | 6 +- src/shared/types/{pages.ts => page.ts} | 0 src/shared/types/{roles.ts => role.ts} | 0 src/widgets/transfer/TransferDetail/index.tsx | 20 +++++ src/widgets/transfer/TransferDetail/types.ts | 12 +++ .../transfer/TransferListWrapper/index.tsx | 9 +++ .../transfer/TransferListWrapper/types.ts | 5 ++ src/widgets/transfer/index.ts | 2 + 48 files changed, 620 insertions(+), 28 deletions(-) create mode 100644 src/entities/transfer/api/hooks/index.ts create mode 100644 src/entities/transfer/api/hooks/useGetTransfer/index.ts create mode 100644 src/entities/transfer/api/index.ts create mode 100644 src/entities/transfer/api/keys/index.ts create mode 100644 src/entities/transfer/api/transferService.ts create mode 100644 src/entities/transfer/api/types.ts create mode 100644 src/entities/transfer/index.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/index.tsx create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/types.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/index.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/types.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/index.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferParams/index.tsx create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferParams/types.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/index.tsx create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/types.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/TransferParams/utils/index.ts create mode 100644 src/features/transfer/TransferDetailInfo/components/index.ts create mode 100644 src/features/transfer/TransferDetailInfo/index.tsx create mode 100644 src/features/transfer/TransferDetailInfo/styles.module.less create mode 100644 src/features/transfer/TransferDetailInfo/types.ts create mode 100644 src/features/transfer/TransferList/constants.tsx create mode 100644 src/features/transfer/TransferList/index.tsx create mode 100644 src/features/transfer/TransferList/types.ts create mode 100644 src/features/transfer/index.ts create mode 100644 src/pages/transfer/TransferDetailPage/index.tsx create mode 100644 src/pages/transfer/TransferListPage/index.tsx create mode 100644 src/pages/transfer/index.ts create mode 100644 src/shared/types/connection.ts create mode 100644 src/shared/types/file.ts rename src/shared/types/{pages.ts => page.ts} (100%) rename src/shared/types/{roles.ts => role.ts} (100%) create mode 100644 src/widgets/transfer/TransferDetail/index.tsx create mode 100644 src/widgets/transfer/TransferDetail/types.ts create mode 100644 src/widgets/transfer/TransferListWrapper/index.tsx create mode 100644 src/widgets/transfer/TransferListWrapper/types.ts create mode 100644 src/widgets/transfer/index.ts diff --git a/.env.example b/.env.example index b1aee044..66936a88 100644 --- a/.env.example +++ b/.env.example @@ -1 +1 @@ -API_URL="https://localhost:8000/v1/" \ No newline at end of file +API_URL="http://localhost:8000/v1/" \ No newline at end of file diff --git a/src/app/config/router/instance.tsx b/src/app/config/router/instance.tsx index ea371fc7..e38b1f77 100644 --- a/src/app/config/router/instance.tsx +++ b/src/app/config/router/instance.tsx @@ -7,6 +7,7 @@ import { CreateGroupPage, GroupDetailPage, GroupListPage, UpdateGroupPage } from import { AuthProvider } from '@entities/auth'; import { CreateQueuePage, QueueDetailPage, QueueListPage, UpdateQueuePage } from '@pages/queue'; import { ConnectionDetailPage, ConnectionListPage } from '@pages/connection'; +import { TransferDetailPage, TransferListPage } from '@pages/transfer'; import { ErrorBoundary, NotFoundError } from '../errorBoundary'; @@ -86,6 +87,14 @@ export const router = createBrowserRouter([ path: '/connections/:id', element: , }, + { + path: '/transfers', + element: , + }, + { + path: '/transfers/:id', + element: , + }, ], }, { diff --git a/src/app/styles/antd.less b/src/app/styles/antd.less index e09b23ac..e326b010 100644 --- a/src/app/styles/antd.less +++ b/src/app/styles/antd.less @@ -3,8 +3,12 @@ border-radius: 0; } +.ant-descriptions { + width: 100%; +} + .ant-descriptions-item-label { - width: 300px; + width: 250px; font-weight: 700; } diff --git a/src/entities/connection/api/types.ts b/src/entities/connection/api/types.ts index 2f0d0fa0..0eb964a4 100644 --- a/src/entities/connection/api/types.ts +++ b/src/entities/connection/api/types.ts @@ -1,4 +1,4 @@ -import { PaginationRequest } from '@shared/types'; +import { ConnectionType, PaginationRequest } from '@shared/types'; export type Connection = { id: number; @@ -11,33 +11,33 @@ type ConnectionData = ConnectionHive | ConnectionHdfs | ConnectionOracle | Conne interface ConnectionHive { auth_data: { - type: 'hive'; + type: ConnectionType.HIVE; user: string; }; connection_data: { - type: 'hive'; + type: ConnectionType.HIVE; cluster: string; }; } interface ConnectionHdfs { auth_data: { - type: 'hdfs'; + type: ConnectionType.HDFS; user: string; }; connection_data: { - type: 'hdfs'; + type: ConnectionType.HDFS; cluster: string; }; } interface ConnectionOracle { auth_data: { - type: 'oracle'; + type: ConnectionType.ORACLE; user: string; }; connection_data: { - type: 'oracle'; + type: ConnectionType.ORACLE; host: string; port: number; service_name: string | null; @@ -48,11 +48,11 @@ interface ConnectionOracle { interface ConnectionPostgres { auth_data: { - type: 'postgres'; + type: ConnectionType.POSTGRES; user: string; }; connection_data: { - type: 'postgres'; + type: ConnectionType.POSTGRES; host: string; port: number; database_name: string; @@ -62,11 +62,11 @@ interface ConnectionPostgres { interface ConnectionS3 { auth_data: { - type: 's3'; + type: ConnectionType.S3; access_key: string; }; connection_data: { - type: 's3'; + type: ConnectionType.S3; host: string; bucket: string; bucket_style: 'domain' | 'path'; diff --git a/src/entities/transfer/api/hooks/index.ts b/src/entities/transfer/api/hooks/index.ts new file mode 100644 index 00000000..0f1dadc5 --- /dev/null +++ b/src/entities/transfer/api/hooks/index.ts @@ -0,0 +1 @@ +export * from './useGetTransfer'; diff --git a/src/entities/transfer/api/hooks/useGetTransfer/index.ts b/src/entities/transfer/api/hooks/useGetTransfer/index.ts new file mode 100644 index 00000000..a3a2b5a2 --- /dev/null +++ b/src/entities/transfer/api/hooks/useGetTransfer/index.ts @@ -0,0 +1,13 @@ +import { useSuspenseQuery, UseSuspenseQueryResult } from '@tanstack/react-query'; + +import { transferService } from '../../transferService'; +import { GetTransferRequest, Transfer } from '../../types'; +import { TransferQueryKey } from '../../keys'; + +/** Hook for getting transfer info from backend */ +export const useGetTransfer = ({ id }: GetTransferRequest): UseSuspenseQueryResult => { + return useSuspenseQuery({ + queryKey: [TransferQueryKey.GET_TRANSFER, id], + queryFn: () => transferService.getTransfer({ id }), + }); +}; diff --git a/src/entities/transfer/api/index.ts b/src/entities/transfer/api/index.ts new file mode 100644 index 00000000..e4e567d4 --- /dev/null +++ b/src/entities/transfer/api/index.ts @@ -0,0 +1,4 @@ +export * from './transferService'; +export * from './types'; +export * from './keys'; +export * from './hooks'; diff --git a/src/entities/transfer/api/keys/index.ts b/src/entities/transfer/api/keys/index.ts new file mode 100644 index 00000000..259d9401 --- /dev/null +++ b/src/entities/transfer/api/keys/index.ts @@ -0,0 +1,4 @@ +export const TransferQueryKey = { + GET_TRANSFERS: 'GET_TRANSFERS', + GET_TRANSFER: 'GET_TRANSFER', +} as const; diff --git a/src/entities/transfer/api/transferService.ts b/src/entities/transfer/api/transferService.ts new file mode 100644 index 00000000..dfdf9548 --- /dev/null +++ b/src/entities/transfer/api/transferService.ts @@ -0,0 +1,14 @@ +import { axiosInstance } from '@shared/config'; +import { PaginationResponse } from '@shared/types'; + +import { GetTransferRequest, GetTransfersRequest, Transfer } from './types'; + +export const transferService = { + getTransfers: (params: GetTransfersRequest): Promise> => { + return axiosInstance.get('transfers', { params }); + }, + + getTransfer: ({ id }: GetTransferRequest): Promise => { + return axiosInstance.get(`transfers/${id}`); + }, +}; diff --git a/src/entities/transfer/api/types.ts b/src/entities/transfer/api/types.ts new file mode 100644 index 00000000..bb04b138 --- /dev/null +++ b/src/entities/transfer/api/types.ts @@ -0,0 +1,81 @@ +import { ConnectionType, FileFormat, FileFormatCsv, FileFormatJsonLine, PaginationRequest } from '@shared/types'; + +export interface Transfer { + id: number; + group_id: number; + name: string; + source_connection_id: number; + target_connection_id: number; + description: string; + is_scheduled: boolean; + schedule: string; + queue_id: number; + source_params: + | TransferParamsHive + | TransferParamsOracle + | TransferParamsPostgres + | TransferSourceParamsHdfs + | TransferSourceParamsS3; + target_params: + | TransferParamsHive + | TransferParamsOracle + | TransferParamsPostgres + | TransferTargetParamsHdfs + | TransferTargetParamsS3; + strategy_params: TransferStrategyParams; +} + +interface TransferStrategyParams { + type: 'full' | 'incremental'; +} + +interface TransferParamsHive { + type: ConnectionType.HIVE; + table_name: string; +} + +interface TransferParamsOracle { + type: ConnectionType.ORACLE; + table_name: string; +} + +interface TransferParamsPostgres { + type: ConnectionType.POSTGRES; + table_name: string; +} + +interface TransferParamsHdfs { + type: ConnectionType.HDFS; + directory_path: string; + options: object; +} + +interface TransferSourceParamsHdfs extends TransferParamsHdfs { + file_format: FileFormat; +} + +interface TransferTargetParamsHdfs extends TransferParamsHdfs { + file_format: FileFormatCsv | FileFormatJsonLine; +} + +interface TransferParamsS3 { + type: ConnectionType.S3; + directory_path: string; + options: object; +} + +interface TransferSourceParamsS3 extends TransferParamsS3 { + file_format: FileFormat; +} + +interface TransferTargetParamsS3 extends TransferParamsS3 { + file_format: FileFormatCsv | FileFormatJsonLine; +} + +export interface GetTransfersRequest extends PaginationRequest { + group_id: number; +} + +export interface GetTransferRequest { + id: number; +} diff --git a/src/entities/transfer/index.ts b/src/entities/transfer/index.ts new file mode 100644 index 00000000..b1c13e73 --- /dev/null +++ b/src/entities/transfer/index.ts @@ -0,0 +1 @@ +export * from './api'; diff --git a/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/index.tsx b/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/index.tsx index 11639d2d..e02fe872 100644 --- a/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/index.tsx +++ b/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/index.tsx @@ -6,7 +6,7 @@ import { getDescriptionItems } from './utils'; export const ConnectionAuthData = ({ data, ...props }: ConnectionAuthDataProps) => { return ( - + {data.type} diff --git a/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/utils/getDescriptionItems/index.ts b/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/utils/getDescriptionItems/index.ts index 16258b2e..1f0ae5aa 100644 --- a/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/utils/getDescriptionItems/index.ts +++ b/src/features/connection/ConnectionDetailInfo/components/ConnectionAuthData/utils/getDescriptionItems/index.ts @@ -1,18 +1,21 @@ -import { DescriptionItem } from '@shared/types'; +import { ConnectionType, DescriptionItem } from '@shared/types'; import { GetDescriptionItemsProps } from './types'; /** Util for mapping data for Description component depends on connection type */ export const getDescriptionItems = ({ data }: GetDescriptionItemsProps): DescriptionItem[] => { switch (data.type) { - case 's3': + case ConnectionType.S3: return [ { label: 'Access key', content: data.access_key, }, ]; - default: + case ConnectionType.HIVE: + case ConnectionType.HDFS: + case ConnectionType.ORACLE: + case ConnectionType.POSTGRES: return [ { label: 'User', diff --git a/src/features/connection/ConnectionDetailInfo/components/ConnectionData/index.tsx b/src/features/connection/ConnectionDetailInfo/components/ConnectionData/index.tsx index 1677cfe8..6b623ff6 100644 --- a/src/features/connection/ConnectionDetailInfo/components/ConnectionData/index.tsx +++ b/src/features/connection/ConnectionDetailInfo/components/ConnectionData/index.tsx @@ -6,7 +6,7 @@ import { getDescriptionItems } from './utils'; export const ConnectionData = ({ data, ...props }: ConnectionDataProps) => { return ( - + {data.type} diff --git a/src/features/connection/ConnectionDetailInfo/components/ConnectionData/utils/getDescriptionItems/index.ts b/src/features/connection/ConnectionDetailInfo/components/ConnectionData/utils/getDescriptionItems/index.ts index 4194300b..53f0c461 100644 --- a/src/features/connection/ConnectionDetailInfo/components/ConnectionData/utils/getDescriptionItems/index.ts +++ b/src/features/connection/ConnectionDetailInfo/components/ConnectionData/utils/getDescriptionItems/index.ts @@ -1,11 +1,11 @@ -import { DescriptionItem } from '@shared/types'; +import { ConnectionType, DescriptionItem } from '@shared/types'; import { GetDescriptionItemsProps } from './types'; /** Util for mapping data for Description component depends on connection type */ export const getDescriptionItems = ({ data }: GetDescriptionItemsProps): DescriptionItem[] => { switch (data.type) { - case 'oracle': + case ConnectionType.ORACLE: return [ { label: 'Host', @@ -24,7 +24,7 @@ export const getDescriptionItems = ({ data }: GetDescriptionItemsProps): Descrip content: data.sid || '', }, ]; - case 'postgres': + case ConnectionType.POSTGRES: return [ { label: 'Host', @@ -39,7 +39,7 @@ export const getDescriptionItems = ({ data }: GetDescriptionItemsProps): Descrip content: data.database_name, }, ]; - case 's3': + case ConnectionType.S3: return [ { label: 'Host', @@ -66,7 +66,8 @@ export const getDescriptionItems = ({ data }: GetDescriptionItemsProps): Descrip content: data.region || '', }, ]; - default: + case ConnectionType.HIVE: + case ConnectionType.HDFS: return [ { label: 'Cluster', diff --git a/src/features/connection/ConnectionDetailInfo/index.tsx b/src/features/connection/ConnectionDetailInfo/index.tsx index bc102cbf..679c53bc 100644 --- a/src/features/connection/ConnectionDetailInfo/index.tsx +++ b/src/features/connection/ConnectionDetailInfo/index.tsx @@ -22,10 +22,13 @@ export const ConnectionDetailInfo = ({ connection, group, ...props }: Connection {group.name} + + + + + + - - - ); }; diff --git a/src/features/connection/ConnectionDetailInfo/styles.module.less b/src/features/connection/ConnectionDetailInfo/styles.module.less index 0f0fc6a0..43e4522c 100644 --- a/src/features/connection/ConnectionDetailInfo/styles.module.less +++ b/src/features/connection/ConnectionDetailInfo/styles.module.less @@ -2,4 +2,18 @@ display: flex; flex-direction: column; gap: 24px; + + .subDescription { + :global(+ .ant-descriptions-item-content) { + padding: 0; + } + + :global(.ant-descriptions-item) { + padding: 0; + } + + :global(.ant-descriptions-view) { + border: 0; + } + } } diff --git a/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/index.tsx b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/index.tsx new file mode 100644 index 00000000..ea13f87e --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Descriptions } from 'antd'; + +import { TransferFileFormatDataProps } from './types'; +import { getDescriptionItems } from './utils'; + +export const TransferFileFormatData = ({ data, ...props }: TransferFileFormatDataProps) => { + return ( + + + {data.type} + + {getDescriptionItems({ data }).map((item, index) => ( + + {item.content} + + ))} + + ); +}; diff --git a/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/types.ts b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/types.ts new file mode 100644 index 00000000..6284ba3e --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/types.ts @@ -0,0 +1,6 @@ +import { FileFormat } from '@shared/types'; +import { DescriptionsProps } from 'antd'; + +export interface TransferFileFormatDataProps extends DescriptionsProps { + data: FileFormat; +} diff --git a/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/index.ts b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/index.ts new file mode 100644 index 00000000..2eb37227 --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/index.ts @@ -0,0 +1,48 @@ +import { DescriptionItem, FileFormatType } from '@shared/types'; + +import { GetDescriptionItemsProps } from './types'; + +/** Util for mapping data for Description component depends on file format type */ +export const getDescriptionItems = ({ data }: GetDescriptionItemsProps): DescriptionItem[] => { + switch (data.type) { + case FileFormatType.CSV: + return [ + { + label: 'Delimiter', + content: data.delimiter, + }, + { + label: 'Encoding', + content: data.encoding, + }, + { + label: 'Quote', + content: data.quote, + }, + { + label: 'Escape', + content: data.escape, + }, + { + label: 'Header', + content: data.header, + }, + { + label: 'Line Sep', + content: data.line_sep, + }, + ]; + case FileFormatType.JSON: + case FileFormatType.JSON_LINE: + return [ + { + label: 'Encoding', + content: data.encoding, + }, + { + label: 'Line Sep', + content: data.line_sep, + }, + ]; + } +}; diff --git a/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/types.ts b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/types.ts new file mode 100644 index 00000000..f8c1737c --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/getDescriptionItems/types.ts @@ -0,0 +1,5 @@ +import { FileFormat } from '@shared/types'; + +export interface GetDescriptionItemsProps { + data: FileFormat; +} diff --git a/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/index.ts b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/index.ts new file mode 100644 index 00000000..0519775c --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferFileFormatData/utils/index.ts @@ -0,0 +1 @@ +export * from './getDescriptionItems'; diff --git a/src/features/transfer/TransferDetailInfo/components/TransferParams/index.tsx b/src/features/transfer/TransferDetailInfo/components/TransferParams/index.tsx new file mode 100644 index 00000000..e4e0d9ff --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferParams/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { Descriptions } from 'antd'; + +import { TransferParamsProps } from './types'; +import { getDescriptionItems } from './utils'; + +export const TransferParams = ({ data, ...props }: TransferParamsProps) => { + return ( + + + {data.type} + + {getDescriptionItems({ data }).map((item, index) => ( + + {item.content} + + ))} + + ); +}; diff --git a/src/features/transfer/TransferDetailInfo/components/TransferParams/types.ts b/src/features/transfer/TransferDetailInfo/components/TransferParams/types.ts new file mode 100644 index 00000000..5699d794 --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferParams/types.ts @@ -0,0 +1,6 @@ +import { Transfer } from '@entities/transfer'; +import { DescriptionsProps } from 'antd'; + +export interface TransferParamsProps extends DescriptionsProps { + data: Transfer['source_params'] | Transfer['target_params']; +} diff --git a/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/index.tsx b/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/index.tsx new file mode 100644 index 00000000..6bac868b --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/index.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { ConnectionType, DescriptionItem } from '@shared/types'; + +import { TransferFileFormatData } from '../../../TransferFileFormatData'; + +import { GetDescriptionItemsProps } from './types'; + +/** Util for mapping data for Description component depends on connection type */ +export const getDescriptionItems = ({ data }: GetDescriptionItemsProps): DescriptionItem[] => { + switch (data.type) { + case ConnectionType.HDFS: + case ConnectionType.S3: + return [ + { + label: 'Directory path', + content: data.directory_path, + }, + { + label: 'File format', + content: , + }, + ]; + case ConnectionType.HIVE: + case ConnectionType.ORACLE: + case ConnectionType.POSTGRES: + return [ + { + label: 'Table name', + content: data.table_name, + }, + ]; + } +}; diff --git a/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/types.ts b/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/types.ts new file mode 100644 index 00000000..ce28b695 --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/getDescriptionItems/types.ts @@ -0,0 +1,5 @@ +import { Transfer } from '@entities/transfer'; + +export interface GetDescriptionItemsProps { + data: Transfer['source_params']; +} diff --git a/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/index.ts b/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/index.ts new file mode 100644 index 00000000..0519775c --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/TransferParams/utils/index.ts @@ -0,0 +1 @@ +export * from './getDescriptionItems'; diff --git a/src/features/transfer/TransferDetailInfo/components/index.ts b/src/features/transfer/TransferDetailInfo/components/index.ts new file mode 100644 index 00000000..b71fed24 --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/components/index.ts @@ -0,0 +1,2 @@ +export * from './TransferParams'; +export * from './TransferFileFormatData'; diff --git a/src/features/transfer/TransferDetailInfo/index.tsx b/src/features/transfer/TransferDetailInfo/index.tsx new file mode 100644 index 00000000..b4b167db --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/index.tsx @@ -0,0 +1,50 @@ +import React from 'react'; +import { Descriptions } from 'antd'; +import { Link } from 'react-router-dom'; + +import { TransferDetailInfoProps } from './types'; +import classes from './styles.module.less'; +import { TransferParams } from './components'; + +export const TransferDetailInfo = ({ + transfer, + group, + connectionSource, + connectionTarget, + queue, + ...props +}: TransferDetailInfoProps) => { + return ( +
+ + + {transfer.id} + + + {transfer.name} + + + {transfer.description} + + + {group.name} + + + {connectionSource.name} + + + {connectionTarget.name} + + + {queue.name} + + + + + + + + +
+ ); +}; diff --git a/src/features/transfer/TransferDetailInfo/styles.module.less b/src/features/transfer/TransferDetailInfo/styles.module.less new file mode 100644 index 00000000..1ac6d167 --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/styles.module.less @@ -0,0 +1,23 @@ +.root { + display: flex; + flex-direction: column; + gap: 24px; + + .subDescription { + :global(:has(.ant-descriptions-item-content)) { + padding: 0; + } + + :global(+ .ant-descriptions-item-content) { + padding: 0; + } + + :global(.ant-descriptions-item) { + padding: 0; + } + + :global(.ant-descriptions-view) { + border: 0; + } + } +} diff --git a/src/features/transfer/TransferDetailInfo/types.ts b/src/features/transfer/TransferDetailInfo/types.ts new file mode 100644 index 00000000..e4b515bb --- /dev/null +++ b/src/features/transfer/TransferDetailInfo/types.ts @@ -0,0 +1,13 @@ +import { Transfer } from '@entities/transfer'; +import { GroupData } from '@entities/group'; +import { DescriptionsProps } from 'antd'; +import { Connection } from '@entities/connection'; +import { Queue } from '@entities/queue'; + +export interface TransferDetailInfoProps extends DescriptionsProps { + transfer: Transfer; + group: GroupData; + connectionSource: Connection; + connectionTarget: Connection; + queue: Queue; +} diff --git a/src/features/transfer/TransferList/constants.tsx b/src/features/transfer/TransferList/constants.tsx new file mode 100644 index 00000000..82efb934 --- /dev/null +++ b/src/features/transfer/TransferList/constants.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { PaginationResponse } from '@shared/types'; +import { TableColumns } from '@shared/ui'; +import { Link } from 'react-router-dom'; +import { Transfer } from '@entities/transfer'; + +export const TRANSFER_LIST_COLUMNS: TableColumns> = [ + { + title: 'Id', + dataIndex: 'id', + width: 150, + }, + { + title: 'Name', + dataIndex: 'name', + render: (name, record) => {name}, + width: 400, + }, + { + title: 'Description', + dataIndex: 'description', + }, +]; diff --git a/src/features/transfer/TransferList/index.tsx b/src/features/transfer/TransferList/index.tsx new file mode 100644 index 00000000..8459cebd --- /dev/null +++ b/src/features/transfer/TransferList/index.tsx @@ -0,0 +1,21 @@ +import React, { memo } from 'react'; +import { ManagedTable } from '@shared/ui'; +import { hasAccessByUserRole } from '@shared/utils'; +import { UserRole } from '@shared/types'; +import { TransferQueryKey, transferService } from '@entities/transfer'; + +import { TRANSFER_LIST_COLUMNS } from './constants'; +import { TransferListProps } from './types'; + +export const TransferList = memo(({ group }: TransferListProps) => { + return ( + transferService.getTransfers({ ...params, group_id: group.data.id })} + columns={TRANSFER_LIST_COLUMNS} + isRenderUpdateRowAction={() => hasAccessByUserRole(UserRole.Developer, group.role)} + isRenderDeleteRowAction={() => hasAccessByUserRole(UserRole.Maintainer, group.role)} + rowKey="id" + /> + ); +}); diff --git a/src/features/transfer/TransferList/types.ts b/src/features/transfer/TransferList/types.ts new file mode 100644 index 00000000..b7a1f643 --- /dev/null +++ b/src/features/transfer/TransferList/types.ts @@ -0,0 +1,5 @@ +import { Group } from '@entities/group'; + +export interface TransferListProps { + group: Group; +} diff --git a/src/features/transfer/index.ts b/src/features/transfer/index.ts new file mode 100644 index 00000000..ead941e9 --- /dev/null +++ b/src/features/transfer/index.ts @@ -0,0 +1,2 @@ +export * from './TransferList'; +export * from './TransferDetailInfo'; diff --git a/src/pages/transfer/TransferDetailPage/index.tsx b/src/pages/transfer/TransferDetailPage/index.tsx new file mode 100644 index 00000000..30ebaaaf --- /dev/null +++ b/src/pages/transfer/TransferDetailPage/index.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { PageDetailParams } from '@shared/types'; +import { PageContentWrapper } from '@shared/ui'; +import { Typography } from 'antd'; +import { useParams } from 'react-router-dom'; +import { useGetGroup } from '@entities/group'; +import { useGetTransfer } from '@entities/transfer'; +import { TransferDetail } from '@widgets/transfer'; +import { useGetConnection } from '@entities/connection'; +import { useGetQueue } from '@entities/queue'; + +const { Title } = Typography; + +export const TransferDetailPage = () => { + const params = useParams(); + const { data: transfer } = useGetTransfer({ id: Number(params.id) }); + const { data: group } = useGetGroup({ id: transfer.group_id }); + const { data: connectionSource } = useGetConnection({ id: transfer.source_connection_id }); + const { data: connectionTarget } = useGetConnection({ id: transfer.target_connection_id }); + const { data: queue } = useGetQueue({ id: transfer.queue_id }); + + if (!transfer || !group || !connectionSource || !connectionTarget || !queue) { + return null; + } + + return ( + + {transfer.name} + + + ); +}; diff --git a/src/pages/transfer/TransferListPage/index.tsx b/src/pages/transfer/TransferListPage/index.tsx new file mode 100644 index 00000000..fc82cea3 --- /dev/null +++ b/src/pages/transfer/TransferListPage/index.tsx @@ -0,0 +1,30 @@ +import React from 'react'; +import { PageContentWrapper } from '@shared/ui'; +import { Typography } from 'antd'; +import { GroupWarningAlert, useSelectedGroup } from '@entities/group'; +import { TransferListWrapper } from '@widgets/transfer'; + +const { Title } = Typography; + +export const TransferListPage = () => { + const { group } = useSelectedGroup(); + + const renderContent = () => { + if (!group?.data.id) { + return ; + } + + return ( + + + + ); + }; + + return ( + + Transfers + {renderContent()} + + ); +}; diff --git a/src/pages/transfer/index.ts b/src/pages/transfer/index.ts new file mode 100644 index 00000000..fbb5c1c1 --- /dev/null +++ b/src/pages/transfer/index.ts @@ -0,0 +1,2 @@ +export * from './TransferListPage'; +export * from './TransferDetailPage'; diff --git a/src/shared/types/connection.ts b/src/shared/types/connection.ts new file mode 100644 index 00000000..17b6c4c0 --- /dev/null +++ b/src/shared/types/connection.ts @@ -0,0 +1,7 @@ +export enum ConnectionType { + HIVE = 'hive', + HDFS = 'hdfs', + ORACLE = 'oracle', + POSTGRES = 'postgres', + S3 = 's3', +} diff --git a/src/shared/types/file.ts b/src/shared/types/file.ts new file mode 100644 index 00000000..874ba010 --- /dev/null +++ b/src/shared/types/file.ts @@ -0,0 +1,29 @@ +export enum FileFormatType { + CSV = 'csv', + JSON = 'json', + JSON_LINE = 'jsonline', +} + +export type FileFormat = FileFormatCsv | FileFormatJson | FileFormatJsonLine; + +export interface FileFormatCsv { + type: FileFormatType.CSV; + delimiter: string; + encoding: string; + quote: string; + escape: string; + header: boolean; + line_sep: string; +} + +export interface FileFormatJson { + type: FileFormatType.JSON; + encoding: string; + line_sep: string; +} + +export interface FileFormatJsonLine { + type: FileFormatType.JSON_LINE; + encoding: string; + line_sep: string; +} diff --git a/src/shared/types/index.ts b/src/shared/types/index.ts index 61f51d34..c0095715 100644 --- a/src/shared/types/index.ts +++ b/src/shared/types/index.ts @@ -1,4 +1,6 @@ export * from './api'; -export * from './pages'; -export * from './roles'; +export * from './page'; +export * from './role'; export * from './antd'; +export * from './connection'; +export * from './file'; diff --git a/src/shared/types/pages.ts b/src/shared/types/page.ts similarity index 100% rename from src/shared/types/pages.ts rename to src/shared/types/page.ts diff --git a/src/shared/types/roles.ts b/src/shared/types/role.ts similarity index 100% rename from src/shared/types/roles.ts rename to src/shared/types/role.ts diff --git a/src/widgets/transfer/TransferDetail/index.tsx b/src/widgets/transfer/TransferDetail/index.tsx new file mode 100644 index 00000000..292e59d4 --- /dev/null +++ b/src/widgets/transfer/TransferDetail/index.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { PageContentWrapper } from '@shared/ui'; +import { TransferDetailInfo } from '@features/transfer'; + +import { TransferDetailProps } from './types'; + +export const TransferDetail = ({ transfer, group, connectionSource, connectionTarget, queue }: TransferDetailProps) => { + return ( + + {/* //TODO: [DOP-20065] add update and delete actions for transfer */} + + + ); +}; diff --git a/src/widgets/transfer/TransferDetail/types.ts b/src/widgets/transfer/TransferDetail/types.ts new file mode 100644 index 00000000..3cd7a069 --- /dev/null +++ b/src/widgets/transfer/TransferDetail/types.ts @@ -0,0 +1,12 @@ +import { Connection } from '@entities/connection'; +import { Group } from '@entities/group'; +import { Queue } from '@entities/queue'; +import { Transfer } from '@entities/transfer'; + +export interface TransferDetailProps { + transfer: Transfer; + group: Group; + connectionSource: Connection; + connectionTarget: Connection; + queue: Queue; +} diff --git a/src/widgets/transfer/TransferListWrapper/index.tsx b/src/widgets/transfer/TransferListWrapper/index.tsx new file mode 100644 index 00000000..a6a051a5 --- /dev/null +++ b/src/widgets/transfer/TransferListWrapper/index.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { TransferList } from '@features/transfer'; + +import { TransferListWrapperProps } from './types'; + +export const TransferListWrapper = ({ group }: TransferListWrapperProps) => { + //TODO: [DOP-20065] add update and delete actions for transfer + return ; +}; diff --git a/src/widgets/transfer/TransferListWrapper/types.ts b/src/widgets/transfer/TransferListWrapper/types.ts new file mode 100644 index 00000000..142f1af5 --- /dev/null +++ b/src/widgets/transfer/TransferListWrapper/types.ts @@ -0,0 +1,5 @@ +import { Group } from '@entities/group'; + +export interface TransferListWrapperProps { + group: Group; +} diff --git a/src/widgets/transfer/index.ts b/src/widgets/transfer/index.ts new file mode 100644 index 00000000..6e384940 --- /dev/null +++ b/src/widgets/transfer/index.ts @@ -0,0 +1,2 @@ +export * from './TransferListWrapper'; +export * from './TransferDetail';