mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2026-01-06 04:26:57 +00:00
feat(ui): support test connection option for services (#8249)
* feat(ui): support test connection option for services * update button to antd * fix unit tests
This commit is contained in:
parent
3774f31ac4
commit
97cdd22729
@ -17,6 +17,9 @@ import React, { FunctionComponent } from 'react';
|
||||
import { ButtonProps, Ref } from './Button.interface';
|
||||
import { button } from './Button.styles';
|
||||
|
||||
/**
|
||||
* @deprecated use AntD button instead
|
||||
*/
|
||||
export const Button: FunctionComponent<ButtonProps> = React.forwardRef<
|
||||
Ref,
|
||||
ButtonProps
|
||||
|
||||
@ -149,6 +149,7 @@ jest.mock('../../axiosAPIs/serviceAPI', () => ({
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve(mockData)),
|
||||
updateService: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
TestConnection: jest.fn().mockImplementation(() => Promise.resolve()),
|
||||
}));
|
||||
|
||||
jest.mock('../../axiosAPIs/databaseAPI', () => ({
|
||||
@ -205,6 +206,7 @@ jest.mock('../../utils/ServiceUtils', () => ({
|
||||
serviceTypeLogo: jest.fn().mockReturnValue('img/path'),
|
||||
isRequiredDetailsAvailableForIngestion: jest.fn().mockReturnValue(true),
|
||||
getDeleteEntityMessage: jest.fn().mockReturnValue('Delete message'),
|
||||
shouldTestConnection: jest.fn().mockReturnValue(true),
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
|
||||
@ -11,12 +11,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Col, Row, Space, Tooltip } from 'antd';
|
||||
import { Button, Col, Row, Space, Tooltip } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import classNames from 'classnames';
|
||||
import { isEmpty, isNil, isUndefined, startCase } from 'lodash';
|
||||
import { ExtraInfo, ServiceOption, ServiceTypes } from 'Models';
|
||||
import React, { Fragment, FunctionComponent, useEffect, useState } from 'react';
|
||||
import React, {
|
||||
Fragment,
|
||||
FunctionComponent,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Link, useHistory, useParams } from 'react-router-dom';
|
||||
import { getDashboards } from '../../axiosAPIs/dashboardAPI';
|
||||
import { getDatabases } from '../../axiosAPIs/databaseAPI';
|
||||
@ -31,9 +37,13 @@ import {
|
||||
import { fetchAirflowConfig } from '../../axiosAPIs/miscAPI';
|
||||
import { getMlmodels } from '../../axiosAPIs/mlModelAPI';
|
||||
import { getPipelines } from '../../axiosAPIs/pipelineAPI';
|
||||
import { getServiceByFQN, updateService } from '../../axiosAPIs/serviceAPI';
|
||||
import {
|
||||
getServiceByFQN,
|
||||
TestConnection,
|
||||
updateService,
|
||||
} from '../../axiosAPIs/serviceAPI';
|
||||
import { getTopics } from '../../axiosAPIs/topicsAPI';
|
||||
import { Button } from '../../components/buttons/Button/Button';
|
||||
import { Button as LegacyButton } from '../../components/buttons/Button/Button';
|
||||
import DeleteWidgetModal from '../../components/common/DeleteWidget/DeleteWidgetModal';
|
||||
import Description from '../../components/common/description/Description';
|
||||
import EntitySummaryDetails from '../../components/common/EntitySummaryDetails/EntitySummaryDetails';
|
||||
@ -91,14 +101,16 @@ import {
|
||||
getResourceEntityFromServiceCategory,
|
||||
getServiceCategoryFromType,
|
||||
getServiceRouteFromServiceType,
|
||||
getTestConnectionType,
|
||||
servicePageTabs,
|
||||
serviceTypeLogo,
|
||||
setServiceSchemaCount,
|
||||
setServiceTableCount,
|
||||
shouldTestConnection,
|
||||
} from '../../utils/ServiceUtils';
|
||||
import { IcDeleteColored } from '../../utils/SvgUtils';
|
||||
import { getEntityLink, getUsagePercentile } from '../../utils/TableUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||
|
||||
export type ServicePageData = Database | Topic | Dashboard;
|
||||
|
||||
@ -139,6 +151,13 @@ const ServicePage: FunctionComponent = () => {
|
||||
const [servicePermission, setServicePermission] =
|
||||
useState<OperationPermission>(DEFAULT_ENTITY_PERMISSION);
|
||||
|
||||
const [isTestingConnection, setIsTestingConnection] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const allowTestConn = useMemo(() => {
|
||||
return shouldTestConnection(serviceType);
|
||||
}, [serviceType]);
|
||||
|
||||
const fetchServicePermission = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
@ -683,6 +702,34 @@ const ServicePage: FunctionComponent = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const checkTestConnect = async () => {
|
||||
if (connectionDetails) {
|
||||
setIsTestingConnection(true);
|
||||
try {
|
||||
const response = await TestConnection(
|
||||
connectionDetails,
|
||||
getTestConnectionType(serviceCategory as ServiceCategory)
|
||||
);
|
||||
// This api only responds with status 200 on success
|
||||
// No data sent on api success
|
||||
if (response.status === 200) {
|
||||
showSuccessToast(
|
||||
jsonData['api-success-messages']['test-connection-success']
|
||||
);
|
||||
} else {
|
||||
throw jsonData['api-error-messages']['unexpected-server-response'];
|
||||
}
|
||||
} catch (error) {
|
||||
showErrorToast(
|
||||
error as AxiosError,
|
||||
jsonData['api-error-messages']['test-connection-error']
|
||||
);
|
||||
} finally {
|
||||
setIsTestingConnection(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setServiceName(
|
||||
(serviceCategory as ServiceTypes) ||
|
||||
@ -964,7 +1011,7 @@ const ServicePage: FunctionComponent = () => {
|
||||
? 'Delete'
|
||||
: NO_PERMISSION_FOR_ACTION
|
||||
}>
|
||||
<Button
|
||||
<LegacyButton
|
||||
data-testid="service-delete"
|
||||
disabled={!servicePermission.Delete}
|
||||
size="small"
|
||||
@ -978,7 +1025,7 @@ const ServicePage: FunctionComponent = () => {
|
||||
width={14}
|
||||
/>
|
||||
Delete
|
||||
</Button>
|
||||
</LegacyButton>
|
||||
</Tooltip>
|
||||
<DeleteWidgetModal
|
||||
isRecursiveDelete
|
||||
@ -1130,7 +1177,7 @@ const ServicePage: FunctionComponent = () => {
|
||||
|
||||
{activeTab === 3 && (
|
||||
<>
|
||||
<div className="tw-my-4 tw-flex tw-justify-end">
|
||||
<Space className="w-full my-4 justify-end">
|
||||
<Tooltip
|
||||
title={
|
||||
servicePermission.EditAll
|
||||
@ -1138,19 +1185,35 @@ const ServicePage: FunctionComponent = () => {
|
||||
: NO_PERMISSION_FOR_ACTION
|
||||
}>
|
||||
<Button
|
||||
className={classNames(
|
||||
'tw-h-8 tw-rounded tw-px-4 tw-py-1'
|
||||
)}
|
||||
data-testid="add-new-service-button"
|
||||
ghost
|
||||
data-testid="edit-connection-button"
|
||||
disabled={!servicePermission.EditAll}
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="outlined"
|
||||
type="primary"
|
||||
onClick={handleEditConnection}>
|
||||
Edit Connection
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{allowTestConn && isAirflowRunning && (
|
||||
<Tooltip
|
||||
title={
|
||||
servicePermission.EditAll
|
||||
? 'Test Connection'
|
||||
: NO_PERMISSION_FOR_ACTION
|
||||
}>
|
||||
<Button
|
||||
data-testid="test-connection-button"
|
||||
disabled={
|
||||
!servicePermission.EditAll ||
|
||||
isTestingConnection
|
||||
}
|
||||
loading={isTestingConnection}
|
||||
type="primary"
|
||||
onClick={checkTestConnect}>
|
||||
Test Connection
|
||||
</Button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Space>
|
||||
<ServiceConnectionDetails
|
||||
connectionDetails={connectionDetails || {}}
|
||||
serviceCategory={serviceCategory}
|
||||
|
||||
@ -187,78 +187,6 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
// Margin
|
||||
|
||||
.mt-0 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.ml-4 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.ml-6 {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.mt-8 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.ml-8 {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
.mr-8 {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.m-8 {
|
||||
margin: 2rem;
|
||||
}
|
||||
.m-16 {
|
||||
margin: 4rem;
|
||||
}
|
||||
.mb-0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.mt-12 {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
.mb-12 {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
.mt-20 {
|
||||
margin-top: 5rem;
|
||||
}
|
||||
.mt-24 {
|
||||
margin-top: 6rem;
|
||||
}
|
||||
.mt-48 {
|
||||
margin-top: 12rem;
|
||||
}
|
||||
.mt-52 {
|
||||
margin-top: 13rem;
|
||||
}
|
||||
.m-52 {
|
||||
margin: 13rem;
|
||||
}
|
||||
.mr-2 {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
// padding
|
||||
.p-16 {
|
||||
padding: 4rem;
|
||||
}
|
||||
.pl-0 {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.shadow-custom {
|
||||
box-shadow: 1px 1px 8px rgb(0 0 0 / 6%);
|
||||
}
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
//xs: 8px;
|
||||
//xss: 4px;
|
||||
|
||||
// Margin
|
||||
|
||||
.m-0 {
|
||||
margin: 0 !important;
|
||||
}
|
||||
@ -154,6 +156,82 @@
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.mt-0 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.ml-4 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.ml-6 {
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.mt-8 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.ml-8 {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
.mr-8 {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
.mb-4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.m-8 {
|
||||
margin: 2rem;
|
||||
}
|
||||
.m-16 {
|
||||
margin: 4rem;
|
||||
}
|
||||
.mb-0 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.mt-12 {
|
||||
margin-top: 3rem;
|
||||
}
|
||||
.mb-12 {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
.mt-20 {
|
||||
margin-top: 5rem;
|
||||
}
|
||||
.mt-24 {
|
||||
margin-top: 6rem;
|
||||
}
|
||||
.mt-48 {
|
||||
margin-top: 12rem;
|
||||
}
|
||||
.mt-52 {
|
||||
margin-top: 13rem;
|
||||
}
|
||||
.m-52 {
|
||||
margin: 13rem;
|
||||
}
|
||||
.mr-2 {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.my-4 {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
// padding
|
||||
.p-16 {
|
||||
padding: 4rem;
|
||||
}
|
||||
.pl-0 {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.padding-r-l-l {
|
||||
padding: 0 @padding-lg;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user