Skip to content

Commit

Permalink
[DOP-20046] create update delete connection
Browse files Browse the repository at this point in the history
  • Loading branch information
Zabilsya committed Dec 3, 2024
1 parent eb76bb0 commit f759056
Show file tree
Hide file tree
Showing 74 changed files with 1,091 additions and 165 deletions.
2 changes: 2 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ window.env = {
};
EOF

sed -i '/<\/head>/i \ <script src="/env-config.js"></script>' /usr/share/nginx/html/index.html

exec "$@"
15 changes: 14 additions & 1 deletion src/app/config/router/instance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import { AuthLayout, ErrorLayout, PrivateLayout } from '@app/layouts';
import { CreateGroupPage, GroupDetailPage, GroupListPage, UpdateGroupPage } from '@pages/group';
import { AuthProvider } from '@entities/auth';
import { CreateQueuePage, QueueDetailPage, QueueListPage, UpdateQueuePage } from '@pages/queue';
import { ConnectionDetailPage, ConnectionListPage } from '@pages/connection';
import {
ConnectionDetailPage,
ConnectionListPage,
CreateConnectionPage,
UpdateConnectionPage,
} from '@pages/connection';
import { TransferDetailPage, TransferListPage } from '@pages/transfer';
import { RunDetailPage } from '@pages/run';

Expand Down Expand Up @@ -92,6 +97,14 @@ export const router = createBrowserRouter([
path: '/connections/:id',
element: <ConnectionDetailPage />,
},
{
path: '/connections/create',
element: <CreateConnectionPage />,
},
{
path: '/connections/:id/update',
element: <UpdateConnectionPage />,
},
{
path: '/transfers',
element: <TransferListPage />,
Expand Down
8 changes: 3 additions & 5 deletions src/app/styles/antd.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
border-radius: 0;
}

.ant-descriptions {
width: 100%;
}

.ant-descriptions-item-label {
width: 250px;
font-weight: 700;
Expand All @@ -16,7 +12,9 @@
background-color: @white;
}

.ant-select {
.ant-descriptions,
.ant-select,
.ant-input-number {
width: 100%;
}

Expand Down
2 changes: 1 addition & 1 deletion src/entities/auth/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ export interface LoginRequest {

export interface LoginResponse {
access_token: string;
refresh_token: string;
token_type: string;
}
21 changes: 20 additions & 1 deletion src/entities/connection/api/connectionService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { axiosInstance } from '@shared/config';
import { PaginationResponse } from '@shared/types';

import { GetConnectionsRequest, Connection, GetConnectionRequest } from './types';
import {
GetConnectionsRequest,
Connection,
GetConnectionRequest,
CreateConnectionRequest,
UpdateConnectionRequest,
DeleteConnectionRequest,
} from './types';

export const connectionService = {
getConnections: (params: GetConnectionsRequest): Promise<PaginationResponse<Connection>> => {
Expand All @@ -11,4 +18,16 @@ export const connectionService = {
getConnection: ({ id }: GetConnectionRequest): Promise<Connection> => {
return axiosInstance.get(`connections/${id}`);
},

createConnection: (data: CreateConnectionRequest): Promise<Connection> => {
return axiosInstance.post(`connections`, data);
},

updateConnection: ({ id, ...data }: UpdateConnectionRequest): Promise<Connection> => {
return axiosInstance.patch(`connections/${id}`, data);
},

deleteConnection: ({ id }: DeleteConnectionRequest): Promise<null> => {
return axiosInstance.delete(`connections/${id}`);
},
};
1 change: 1 addition & 0 deletions src/entities/connection/api/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './useGetConnection';
export * from './useDeleteConnection';
25 changes: 25 additions & 0 deletions src/entities/connection/api/hooks/useDeleteConnection/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useMutation, UseMutationResult, useQueryClient } from '@tanstack/react-query';
import { notification } from 'antd';
import { getErrorMessage } from '@shared/config';

import { connectionService } from '../../connectionService';
import { DeleteConnectionRequest } from '../../types';
import { ConnectionQueryKey } from '../../keys';

/** Hook for deleting connection */
export const useDeleteConnection = (data: DeleteConnectionRequest): UseMutationResult => {
const queryClient = useQueryClient();

return useMutation({
mutationFn: () => connectionService.deleteConnection(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [ConnectionQueryKey.GET_CONNECTIONS] });
queryClient.removeQueries({ queryKey: [ConnectionQueryKey.GET_CONNECTION, data.id] });
},
onError: (error) => {
notification.error({
message: getErrorMessage(error),
});
},
});
};
31 changes: 27 additions & 4 deletions src/entities/connection/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ export type Connection = {

type ConnectionData = ConnectionHive | ConnectionHdfs | ConnectionOracle | ConnectionPostgres | ConnectionS3;

export type ConnectionBucketStyle = 'domain' | 'path';

export type ConnectionProtocol = 'https' | 'http';

interface ConnectionHive {
auth_data: {
type: ConnectionType.HIVE;
user: string;
password?: string;
};
connection_data: {
type: ConnectionType.HIVE;
Expand All @@ -24,6 +29,7 @@ interface ConnectionHdfs {
auth_data: {
type: ConnectionType.HDFS;
user: string;
password?: string;
};
connection_data: {
type: ConnectionType.HDFS;
Expand All @@ -35,44 +41,45 @@ interface ConnectionOracle {
auth_data: {
type: ConnectionType.ORACLE;
user: string;
password?: string;
};
connection_data: {
type: ConnectionType.ORACLE;
host: string;
port: number;
service_name: string | null;
sid: string | null;
additional_params: object;
};
}

interface ConnectionPostgres {
auth_data: {
type: ConnectionType.POSTGRES;
user: string;
password?: string;
};
connection_data: {
type: ConnectionType.POSTGRES;
host: string;
port: number;
database_name: string;
additional_params: object;
};
}

interface ConnectionS3 {
auth_data: {
type: ConnectionType.S3;
access_key: string;
secret_key?: string;
};
connection_data: {
type: ConnectionType.S3;
host: string;
bucket: string;
bucket_style: 'domain' | 'path';
bucket_style: ConnectionBucketStyle;
port: number | null;
region: string | null;
protocol: 'http' | 'https';
protocol: ConnectionProtocol;
};
}

Expand All @@ -83,3 +90,19 @@ export interface GetConnectionsRequest extends PaginationRequest {
export interface GetConnectionRequest {
id: number;
}

export type CreateConnectionRequest = {
group_id: number;
name: string;
description: string;
} & ConnectionData;

export type UpdateConnectionRequest = {
id: number;
name: string;
description: string;
} & ConnectionData;

export interface DeleteConnectionRequest {
id: number;
}
22 changes: 22 additions & 0 deletions src/entities/connection/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ConnectionType } from '@shared/types';
import { prepareOptionsForSelect } from '@shared/ui';

import { ConnectionBucketStyle, ConnectionProtocol } from './api';

export const CONNECTION_TYPE_SELECT_OPTIONS = prepareOptionsForSelect<ConnectionType>({
data: Object.values(ConnectionType),
renderLabel: (data) => data,
renderValue: (data) => data,
});

export const CONNECTION_BUCKET_STYLE_SELECT_OPTIONS = prepareOptionsForSelect<ConnectionBucketStyle>({
data: ['domain', 'path'],
renderLabel: (data) => data,
renderValue: (data) => data,
});

export const CONNECTION_PROTOCOL_SELECT_OPTIONS = prepareOptionsForSelect<ConnectionProtocol>({
data: ['https', 'http'],
renderLabel: (data) => data,
renderValue: (data) => data,
});
2 changes: 2 additions & 0 deletions src/entities/connection/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './api';
export * from './constants';
export * from './ui';
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import { Form, Input } from 'antd';

import { useSensitiveFields } from '../../hooks';

export const ConnectionHdfs = () => {
const { isRequired } = useSensitiveFields();

return (
<>
<Form.Item label="Cluster" name="cluster" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="User" name="user" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="Password" name="password" rules={[{ required: isRequired }]}>
<Input.Password size="large" />
</Form.Item>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';
import { Form, Input } from 'antd';

import { useSensitiveFields } from '../../hooks';

export const ConnectionHive = () => {
const { isRequired } = useSensitiveFields();

return (
<>
<Form.Item label="Cluster" name="cluster" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="User" name="user" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="Password" name="password" rules={[{ required: isRequired }]}>
<Input.Password size="large" />
</Form.Item>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useCallback, useEffect, useState } from 'react';
import { Form, Input, InputNumber } from 'antd';

import { useSensitiveFields } from '../../hooks';
import { MAX_ALLOWED_PORT, MIN_ALLOWED_PORT } from '../../constants';

export const ConnectionOracle = () => {
const { isRequired } = useSensitiveFields();
const form = Form.useFormInstance();

const [isServiceNameDisabled, setServiceNameDisabled] = useState(false);
const [isSidDisabled, setSidDisabled] = useState(false);

const changeDisabledFields = useCallback(() => {
const serviceName = form.getFieldValue('service_name');
const sid = form.getFieldValue('sid');
setServiceNameDisabled(!!sid);
setSidDisabled(!!serviceName);
}, [form]);

const handleFieldChange = () => {
changeDisabledFields();
form.validateFields(['service_name', 'sid']);
};

//* It needs to validate required fields service_name and sid correctly if they have initial values
useEffect(() => {
changeDisabledFields();
}, [changeDisabledFields]);

return (
<>
<Form.Item label="Host" name="host" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="Port" name="port" rules={[{ required: true }]}>
<InputNumber size="large" min={MIN_ALLOWED_PORT} max={MAX_ALLOWED_PORT} />
</Form.Item>
<Form.Item
label="Service name"
name="service_name"
rules={[
{
required: !isServiceNameDisabled,
message: 'Either Service name or Sid is required',
},
]}
>
<Input size="large" disabled={isServiceNameDisabled} onChange={handleFieldChange} />
</Form.Item>
<Form.Item
label="Sid"
name="sid"
rules={[
{
required: !isSidDisabled,
message: 'Either Service name or Sid is required',
},
]}
>
<Input size="large" disabled={isSidDisabled} onChange={handleFieldChange} />
</Form.Item>
<Form.Item label="User" name="user" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="Password" name="password" rules={[{ required: isRequired }]}>
<Input.Password size="large" />
</Form.Item>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { Form, Input, InputNumber } from 'antd';

import { useSensitiveFields } from '../../hooks';
import { MAX_ALLOWED_PORT, MIN_ALLOWED_PORT } from '../../constants';

export const ConnectionPostgres = () => {
const { isRequired } = useSensitiveFields();

return (
<>
<Form.Item label="Database name" name="database_name" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="Host" name="host" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="Port" name="port" rules={[{ required: true }]}>
<InputNumber size="large" min={MIN_ALLOWED_PORT} max={MAX_ALLOWED_PORT} />
</Form.Item>
<Form.Item label="User" name="user" rules={[{ required: true }]}>
<Input size="large" />
</Form.Item>
<Form.Item label="Password" name="password" rules={[{ required: isRequired }]}>
<Input.Password size="large" />
</Form.Item>
</>
);
};
Loading

0 comments on commit f759056

Please sign in to comment.