mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-08-27 10:26:09 +00:00
refactor : Add useAirflowStatus hook (#9473)
* chore : Add useAirflowStatus hook * Add interface for hook * Expose the fetch status method * update hook return value * refactor : use useAirflowStatus hook to get the airflow status * Update useEffect to fetch data based on airflow status * update license * fetch workflow if airflow is available * Revert "Update useEffect to fetch data based on airflow status" This reverts commit c8cea80d4d2637d1c9163f650a34783c8efe376b. * fix : cy failures * address comments * fix : unit test * fix : cy test
This commit is contained in:
parent
3c9d39e9af
commit
bdb8a55cfe
@ -6,6 +6,7 @@ import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
@ -18,6 +19,7 @@ import org.openmetadata.service.resources.alerts.AlertActionResource;
|
||||
|
||||
@Slf4j
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@Disabled
|
||||
public class AlertActionResourceTest extends EntityResourceTest<AlertAction, CreateAlertAction> {
|
||||
|
||||
public AlertActionResourceTest() {
|
||||
|
@ -54,14 +54,14 @@ export const handleIngestionRetry = (
|
||||
let timer = BASE_WAIT_TIME;
|
||||
const rowIndex = ingestionType === 'metadata' ? 1 : 2;
|
||||
|
||||
interceptURL('GET', '/api/v1/services/ingestionPipelines/*/pipelineStatus?*', 'pipelineStatuses')
|
||||
interceptURL('GET', '/api/v1/services/ingestionPipelines?fields=owner,pipelineStatuses&service=*', 'pipelineStatuses')
|
||||
interceptURL('GET', '/api/v1/services/*/name/*', 'serviceDetails')
|
||||
|
||||
// ingestions page
|
||||
let retryCount = count;
|
||||
const testIngestionsTab = () => {
|
||||
|
||||
cy.get('[data-testid="Ingestions"]').should('be.visible');
|
||||
cy.get('[data-testid="Ingestions"]').should('exist').and('be.visible');
|
||||
cy.get('[data-testid="Ingestions"] >> [data-testid="filter-count"]').should(
|
||||
'have.text',
|
||||
rowIndex
|
||||
@ -69,9 +69,10 @@ export const handleIngestionRetry = (
|
||||
// click on the tab only for the first time
|
||||
if (retryCount === 0) {
|
||||
// Wait for pipeline status to be loaded
|
||||
verifyResponseStatusCode('@pipelineStatuses', 200);
|
||||
cy.wait(1000); //adding manual wait for ingestion button to attach to DOM
|
||||
cy.get('[data-testid="Ingestions"]').click();
|
||||
}
|
||||
verifyResponseStatusCode('@pipelineStatuses', 200)
|
||||
if (isDatabaseService(type) && testIngestionButton) {
|
||||
cy.get('[data-testid="add-new-ingestion-button"]').should('be.visible');
|
||||
}
|
||||
|
@ -11,12 +11,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { checkAirflowStatus } from '@rest/ingestionPipelineAPI';
|
||||
import { createTestCase, createTestSuites } from '@rest/testAPI';
|
||||
import { Col, Row, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { isUndefined } from 'lodash';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import {
|
||||
getDatabaseDetailsPath,
|
||||
@ -68,7 +67,6 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
|
||||
const [testCaseData, setTestCaseData] = useState<TestCase>();
|
||||
const [testSuiteData, setTestSuiteData] = useState<TestSuite>();
|
||||
const [testCaseRes, setTestCaseRes] = useState<TestCase>();
|
||||
const [isAirflowRunning, setIsAirflowRunning] = useState(false);
|
||||
const [addIngestion, setAddIngestion] = useState(false);
|
||||
|
||||
const breadcrumb = useMemo(() => {
|
||||
@ -145,25 +143,6 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const handleAirflowStatusCheck = (): Promise<void> => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
setIsAirflowRunning(true);
|
||||
resolve();
|
||||
} else {
|
||||
setIsAirflowRunning(false);
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setIsAirflowRunning(false);
|
||||
reject();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const handleCancelClick = () => {
|
||||
setActiveServiceStep((pre) => pre - 1);
|
||||
};
|
||||
@ -255,13 +234,11 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
|
||||
<SuccessScreen
|
||||
handleIngestionClick={() => setAddIngestion(true)}
|
||||
handleViewServiceClick={handleViewTestSuiteClick}
|
||||
isAirflowSetup={isAirflowRunning}
|
||||
name={successName}
|
||||
showIngestionButton={selectedTestSuite?.isNewTestSuite || false}
|
||||
state={FormSubmitType.ADD}
|
||||
successMessage={successMessage}
|
||||
viewServiceText="View Test Suite"
|
||||
onCheckAirflowStatus={handleAirflowStatusCheck}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -272,11 +249,7 @@ const AddDataQualityTestV1: React.FC<AddDataQualityTestProps> = ({ table }) => {
|
||||
onSubmit={handleSelectTestSuite}
|
||||
/>
|
||||
);
|
||||
}, [activeServiceStep, isAirflowRunning, testCaseRes]);
|
||||
|
||||
useEffect(() => {
|
||||
handleAirflowStatusCheck();
|
||||
}, []);
|
||||
}, [activeServiceStep, testCaseRes]);
|
||||
|
||||
return (
|
||||
<PageLayout
|
||||
|
@ -13,14 +13,13 @@
|
||||
|
||||
import {
|
||||
addIngestionPipeline,
|
||||
checkAirflowStatus,
|
||||
deployIngestionPipelineById,
|
||||
updateIngestionPipeline as putIngestionPipeline,
|
||||
} from '@rest/ingestionPipelineAPI';
|
||||
import { Col, Row, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import { camelCase, isEmpty } from 'lodash';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import {
|
||||
DEPLOYED_PROGRESS_VAL,
|
||||
@ -82,7 +81,6 @@ const TestSuiteIngestion: React.FC<TestSuiteIngestionProps> = ({
|
||||
</span>
|
||||
);
|
||||
}, [ingestionData, showDeployButton]);
|
||||
const [isAirflowRunning, setIsAirflowRunning] = useState(false);
|
||||
|
||||
const handleIngestionDeploy = (id?: string) => {
|
||||
setShowDeployModal(true);
|
||||
@ -196,24 +194,6 @@ const TestSuiteIngestion: React.FC<TestSuiteIngestionProps> = ({
|
||||
handleIngestionDeploy();
|
||||
};
|
||||
|
||||
const handleAirflowStatusCheck = (): Promise<void> => {
|
||||
return checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
setIsAirflowRunning(true);
|
||||
} else {
|
||||
setIsAirflowRunning(false);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setIsAirflowRunning(false);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleAirflowStatusCheck();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Row className="tw-form-container" gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
@ -229,14 +209,12 @@ const TestSuiteIngestion: React.FC<TestSuiteIngestionProps> = ({
|
||||
<SuccessScreen
|
||||
handleDeployClick={handleDeployClick}
|
||||
handleViewServiceClick={handleViewTestSuiteClick}
|
||||
isAirflowSetup={isAirflowRunning}
|
||||
name={`${testSuite?.name}_${PipelineType.TestSuite}`}
|
||||
showDeployButton={showDeployButton}
|
||||
showIngestionButton={false}
|
||||
state={FormSubmitType.ADD}
|
||||
successMessage={getSuccessMessage}
|
||||
viewServiceText="View Test Suite"
|
||||
onCheckAirflowStatus={handleAirflowStatusCheck}
|
||||
/>
|
||||
) : (
|
||||
<TestSuiteScheduler
|
||||
|
@ -73,13 +73,11 @@ const AddIngestion = ({
|
||||
isIngestionDeployed = false,
|
||||
ingestionAction = '',
|
||||
showDeployButton,
|
||||
isAirflowSetup,
|
||||
setActiveIngestionStep,
|
||||
onIngestionDeploy,
|
||||
onUpdateIngestion,
|
||||
onSuccessSave,
|
||||
onAddIngestionSave,
|
||||
onAirflowStatusCheck,
|
||||
handleCancelClick,
|
||||
handleViewServiceClick,
|
||||
}: AddIngestionProps) => {
|
||||
@ -856,13 +854,11 @@ const AddIngestion = ({
|
||||
<SuccessScreen
|
||||
handleDeployClick={handleDeployClick}
|
||||
handleViewServiceClick={handleViewServiceClick}
|
||||
isAirflowSetup={isAirflowSetup}
|
||||
name={ingestionName}
|
||||
showDeployButton={showDeployButton}
|
||||
showIngestionButton={false}
|
||||
state={status}
|
||||
successMessage={getSuccessMessage()}
|
||||
onCheckAirflowStatus={onAirflowStatusCheck}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
@ -22,8 +22,6 @@ import { AddIngestionProps } from './addIngestion.interface';
|
||||
|
||||
const mockAddIngestionProps: AddIngestionProps = {
|
||||
activeIngestionStep: 1,
|
||||
isAirflowSetup: true,
|
||||
onAirflowStatusCheck: jest.fn(),
|
||||
setActiveIngestionStep: jest.fn(),
|
||||
serviceData: {
|
||||
name: 'serviceName',
|
||||
|
@ -30,7 +30,6 @@ import { DataObj } from '../../interface/service.interface';
|
||||
|
||||
export interface AddIngestionProps {
|
||||
activeIngestionStep: number;
|
||||
isAirflowSetup: boolean;
|
||||
pipelineType: PipelineType;
|
||||
heading: string;
|
||||
ingestionAction?: string;
|
||||
@ -44,7 +43,6 @@ export interface AddIngestionProps {
|
||||
handleCancelClick: () => void;
|
||||
onAddIngestionSave?: (ingestion: CreateIngestionPipeline) => Promise<void>;
|
||||
onIngestionDeploy?: () => Promise<void>;
|
||||
onAirflowStatusCheck: () => Promise<void>;
|
||||
onUpdateIngestion?: (
|
||||
data: IngestionPipeline,
|
||||
oldData: IngestionPipeline,
|
||||
|
@ -283,11 +283,9 @@ const AddService = ({
|
||||
showIngestionButton
|
||||
handleIngestionClick={() => handleAddIngestion(true)}
|
||||
handleViewServiceClick={handleViewServiceClick}
|
||||
isAirflowSetup={isAirflowRunning}
|
||||
name={serviceName}
|
||||
state={FormSubmitType.ADD}
|
||||
suffix={getServiceCreatedLabel(serviceCategory)}
|
||||
onCheckAirflowStatus={onAirflowStatusCheck}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@ -325,7 +323,6 @@ const AddService = ({
|
||||
<div className="tw-form-container">
|
||||
{addIngestion ? (
|
||||
<AddIngestion
|
||||
isAirflowSetup
|
||||
activeIngestionStep={activeIngestionStep}
|
||||
handleCancelClick={() => handleAddIngestion(false)}
|
||||
handleViewServiceClick={handleViewServiceClick}
|
||||
@ -341,7 +338,6 @@ const AddService = ({
|
||||
showDeployButton={showDeployButton}
|
||||
status={FormSubmitType.ADD}
|
||||
onAddIngestionSave={onAddIngestionSave}
|
||||
onAirflowStatusCheck={onAirflowStatusCheck}
|
||||
onIngestionDeploy={onIngestionDeploy}
|
||||
/>
|
||||
) : (
|
||||
|
@ -11,18 +11,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { checkAirflowStatus } from '@rest/ingestionPipelineAPI';
|
||||
import { TestConnection } from '@rest/serviceAPI';
|
||||
import { ISubmitEvent } from '@rjsf/core';
|
||||
import { cloneDeep, isNil } from 'lodash';
|
||||
import { LoadingState } from 'Models';
|
||||
import React, {
|
||||
Fragment,
|
||||
FunctionComponent,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import React, { Fragment, FunctionComponent, useMemo } from 'react';
|
||||
import { ServiceCategory } from '../../enums/service.enum';
|
||||
import { MetadataServiceType } from '../../generated/api/services/createMetadataService';
|
||||
import { MlModelServiceType } from '../../generated/api/services/createMlModelService';
|
||||
@ -30,6 +23,7 @@ import { DashboardServiceType } from '../../generated/entity/services/dashboardS
|
||||
import { DatabaseServiceType } from '../../generated/entity/services/databaseService';
|
||||
import { MessagingServiceType } from '../../generated/entity/services/messagingService';
|
||||
import { PipelineServiceType } from '../../generated/entity/services/pipelineService';
|
||||
import { useAirflowStatus } from '../../hooks/useAirflowStatus';
|
||||
import { ConfigData, ServicesType } from '../../interface/service.interface';
|
||||
import jsonData from '../../jsons/en';
|
||||
import { getDashboardConfig } from '../../utils/DashboardServiceUtils';
|
||||
@ -69,7 +63,7 @@ const ConnectionConfigForm: FunctionComponent<Props> = ({
|
||||
onSave,
|
||||
disableTestConnection = false,
|
||||
}: Props) => {
|
||||
const [isAirflowAvailable, setIsAirflowAvailable] = useState<boolean>(false);
|
||||
const { isAirflowAvailable } = useAirflowStatus();
|
||||
|
||||
const allowTestConn = useMemo(() => {
|
||||
return shouldTestConnection(serviceType);
|
||||
@ -174,21 +168,6 @@ const ConnectionConfigForm: FunctionComponent<Props> = ({
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
setIsAirflowAvailable(true);
|
||||
} else {
|
||||
setIsAirflowAvailable(false);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return <Fragment>{getDatabaseFields()}</Fragment>;
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,6 @@
|
||||
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
checkAirflowStatus,
|
||||
deleteIngestionPipelineById,
|
||||
deployIngestionPipelineById,
|
||||
enableDisableIngestionPipelineById,
|
||||
@ -30,6 +29,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
||||
import { Operation } from '../../generated/entity/policies/policy';
|
||||
import { IngestionPipeline } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { useAirflowStatus } from '../../hooks/useAirflowStatus';
|
||||
import { getLoadingStatus } from '../../utils/CommonUtils';
|
||||
import { checkPermission, userPermissions } from '../../utils/PermissionsUtils';
|
||||
import {
|
||||
@ -48,6 +48,7 @@ import { ResourceEntity } from '../PermissionProvider/PermissionProvider.interfa
|
||||
import TestCaseCommonTabContainer from '../TestCaseCommonTabContainer/TestCaseCommonTabContainer.component';
|
||||
|
||||
const TestSuitePipelineTab = () => {
|
||||
const { isAirflowAvailable, isFetchingStatus } = useAirflowStatus();
|
||||
const { t } = useTranslation();
|
||||
const { testSuiteFQN } = useParams<Record<string, string>>();
|
||||
const { permissions } = usePermissionProvider();
|
||||
@ -68,7 +69,6 @@ const TestSuitePipelineTab = () => {
|
||||
const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false);
|
||||
const [currTriggerId, setCurrTriggerId] = useState({ id: '', state: '' });
|
||||
const [currDeployId, setCurrDeployId] = useState({ id: '', state: '' });
|
||||
const [isAirflowRunning, setIsAirflowRunning] = useState(true);
|
||||
|
||||
const testSuitePath = useMemo(
|
||||
() => location.pathname.split('/')[1],
|
||||
@ -304,22 +304,6 @@ const TestSuitePipelineTab = () => {
|
||||
fetchAirFlowEndPoint();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setIsLoading(true);
|
||||
checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
setIsAirflowRunning(true);
|
||||
} else {
|
||||
setIsAirflowRunning(false);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setIsAirflowRunning(false);
|
||||
setIsLoading(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const pipelineColumns = useMemo(() => {
|
||||
const column: ColumnsType<IngestionPipeline> = [
|
||||
{
|
||||
@ -563,11 +547,11 @@ const TestSuitePipelineTab = () => {
|
||||
currTriggerId,
|
||||
]);
|
||||
|
||||
if (isLoading) {
|
||||
if (isLoading || isFetchingStatus) {
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
return !isAirflowRunning ? (
|
||||
return !isAirflowAvailable ? (
|
||||
<ErrorPlaceHolderIngestion />
|
||||
) : (
|
||||
<TestCaseCommonTabContainer
|
||||
|
@ -14,13 +14,21 @@
|
||||
import { findByTestId, queryByTestId, render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { FormSubmitType } from '../../../enums/form.enum';
|
||||
import { useAirflowStatus } from '../../../hooks/useAirflowStatus';
|
||||
import SuccessScreen from './SuccessScreen';
|
||||
|
||||
jest.mock('../../../hooks/useAirflowStatus', () => ({
|
||||
useAirflowStatus: jest.fn().mockImplementation(() => ({
|
||||
isAirflowAvailable: true,
|
||||
fetchAirflowStatus: jest.fn(),
|
||||
isFetchingStatus: false,
|
||||
})),
|
||||
}));
|
||||
|
||||
describe('Test SuccessScreen component', () => {
|
||||
it('SuccessScreen component should render', async () => {
|
||||
const { container } = render(
|
||||
<SuccessScreen
|
||||
isAirflowSetup
|
||||
showIngestionButton
|
||||
handleViewServiceClick={jest.fn()}
|
||||
name="NewService"
|
||||
@ -55,15 +63,19 @@ describe('Test SuccessScreen component', () => {
|
||||
});
|
||||
|
||||
it('SuccessScreen component should render with airflow helper text', async () => {
|
||||
(useAirflowStatus as jest.Mock).mockImplementation(() => ({
|
||||
isAirflowAvailable: false,
|
||||
fetchAirflowStatus: jest.fn(),
|
||||
isFetchingStatus: false,
|
||||
}));
|
||||
|
||||
const { container } = render(
|
||||
<SuccessScreen
|
||||
showIngestionButton
|
||||
handleViewServiceClick={jest.fn()}
|
||||
isAirflowSetup={false}
|
||||
name="NewService"
|
||||
state={FormSubmitType.ADD}
|
||||
successMessage={<span>title</span>}
|
||||
onCheckAirflowStatus={jest.fn()}
|
||||
/>
|
||||
);
|
||||
|
||||
|
@ -13,13 +13,11 @@
|
||||
|
||||
import classNames from 'classnames';
|
||||
import { isUndefined } from 'lodash';
|
||||
import { LoadingState } from 'Models';
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import { CUSTOM_AIRFLOW_DOCS } from '../../../constants/constants';
|
||||
import { FormSubmitType } from '../../../enums/form.enum';
|
||||
import jsonData from '../../../jsons/en';
|
||||
import { useAirflowStatus } from '../../../hooks/useAirflowStatus';
|
||||
import SVGIcons, { Icons } from '../../../utils/SvgUtils';
|
||||
import { showErrorToast } from '../../../utils/ToastUtils';
|
||||
import { Button } from '../../buttons/Button/Button';
|
||||
import Loader from '../../Loader/Loader';
|
||||
|
||||
@ -30,12 +28,10 @@ type SuccessScreenProps = {
|
||||
showIngestionButton: boolean;
|
||||
showDeployButton?: boolean;
|
||||
state: FormSubmitType;
|
||||
isAirflowSetup: boolean;
|
||||
viewServiceText?: string;
|
||||
handleIngestionClick?: () => void;
|
||||
handleViewServiceClick: () => void;
|
||||
handleDeployClick?: () => void;
|
||||
onCheckAirflowStatus?: () => Promise<void>;
|
||||
};
|
||||
|
||||
const SuccessScreen = ({
|
||||
@ -43,41 +39,21 @@ const SuccessScreen = ({
|
||||
suffix,
|
||||
showIngestionButton,
|
||||
showDeployButton = false,
|
||||
isAirflowSetup,
|
||||
|
||||
handleIngestionClick,
|
||||
handleViewServiceClick,
|
||||
handleDeployClick,
|
||||
successMessage,
|
||||
viewServiceText,
|
||||
onCheckAirflowStatus,
|
||||
}: SuccessScreenProps) => {
|
||||
const [airflowCheckState, setAirflowCheckState] =
|
||||
useState<LoadingState>('initial');
|
||||
const [isAirflowRunning, setIsAirflowRunning] =
|
||||
useState<boolean>(isAirflowSetup);
|
||||
|
||||
const handleAirflowStatusCheck = () => {
|
||||
if (onCheckAirflowStatus) {
|
||||
setAirflowCheckState('waiting');
|
||||
onCheckAirflowStatus()
|
||||
.then(() => {
|
||||
setIsAirflowRunning(true);
|
||||
setAirflowCheckState('success');
|
||||
})
|
||||
.catch(() => {
|
||||
showErrorToast(
|
||||
jsonData['api-error-messages']['check-status-airflow']
|
||||
);
|
||||
setAirflowCheckState('initial');
|
||||
});
|
||||
}
|
||||
};
|
||||
const { isAirflowAvailable, fetchAirflowStatus, isFetchingStatus } =
|
||||
useAirflowStatus();
|
||||
|
||||
const getAirflowStatusIcon = () => {
|
||||
let icon;
|
||||
if (airflowCheckState === 'waiting') {
|
||||
if (isFetchingStatus) {
|
||||
icon = <Loader size="small" type="default" />;
|
||||
} else if (isAirflowRunning) {
|
||||
} else if (isAirflowAvailable) {
|
||||
icon = (
|
||||
<SVGIcons
|
||||
alt="success"
|
||||
@ -128,7 +104,7 @@ const SuccessScreen = ({
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{!isAirflowSetup && (
|
||||
{!isAirflowAvailable && (
|
||||
<div
|
||||
className="tw-border tw-border-main tw-rounded tw-shadow tw-mt-7 tw-p-3"
|
||||
data-testid="airflow-status-msg">
|
||||
@ -138,29 +114,29 @@ const SuccessScreen = ({
|
||||
{getAirflowStatusIcon()}
|
||||
</div>
|
||||
<h6 className="tw-text-base tw-font-medium tw-mb-0.5">
|
||||
{isAirflowRunning
|
||||
{isAirflowAvailable
|
||||
? 'OpenMetadata - Managed Airflow APIs'
|
||||
: 'Failed to find OpenMetadata - Managed Airflow APIs'}
|
||||
</h6>
|
||||
</div>
|
||||
{!isUndefined(onCheckAirflowStatus) && (
|
||||
{!isUndefined(fetchAirflowStatus) && (
|
||||
<div className="tw-flex-none">
|
||||
<Button
|
||||
className={classNames('tw-self-center tw-py-1 tw-px-1.5', {
|
||||
'tw-opacity-40': airflowCheckState === 'waiting',
|
||||
'tw-opacity-40': isFetchingStatus,
|
||||
})}
|
||||
data-testid="airflow-status-check"
|
||||
disabled={airflowCheckState === 'waiting'}
|
||||
disabled={isFetchingStatus}
|
||||
size="small"
|
||||
theme="primary"
|
||||
variant="outlined"
|
||||
onClick={handleAirflowStatusCheck}>
|
||||
onClick={fetchAirflowStatus}>
|
||||
Check Status
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{!isAirflowRunning && (
|
||||
{!isAirflowAvailable && (
|
||||
<p className="tw-mt-3">
|
||||
To set up metadata extraction through UI, you first need to
|
||||
configure and connect to Airflow. For more details visit our{' '}
|
||||
@ -190,10 +166,10 @@ const SuccessScreen = ({
|
||||
{showIngestionButton && (
|
||||
<Button
|
||||
className={classNames('tw-ml-3.5', {
|
||||
'tw-opacity-40 tw-pointer-events-none': !isAirflowRunning,
|
||||
'tw-opacity-40 tw-pointer-events-none': !isAirflowAvailable,
|
||||
})}
|
||||
data-testid="add-ingestion-button"
|
||||
disabled={!isAirflowRunning}
|
||||
disabled={!isAirflowAvailable}
|
||||
size="regular"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
@ -205,10 +181,10 @@ const SuccessScreen = ({
|
||||
{showDeployButton && (
|
||||
<Button
|
||||
className={classNames('tw-ml-3.5', {
|
||||
'tw-opacity-40 tw-pointer-events-none': !isAirflowRunning,
|
||||
'tw-opacity-40 tw-pointer-events-none': !isAirflowAvailable,
|
||||
})}
|
||||
data-testid="add-ingestion-button"
|
||||
disabled={!isAirflowRunning}
|
||||
disabled={!isAirflowAvailable}
|
||||
size="regular"
|
||||
theme="primary"
|
||||
variant="contained"
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2023 Collate.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { checkAirflowStatus } from '@rest/ingestionPipelineAPI';
|
||||
import { AxiosError } from 'axios';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface UseAirflowStatusProps {
|
||||
isFetchingStatus: boolean;
|
||||
isAirflowAvailable: boolean;
|
||||
error: AxiosError | undefined;
|
||||
fetchAirflowStatus: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const useAirflowStatus = (): UseAirflowStatusProps => {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [isAirflowAvailable, setIsAirflowAvailable] = useState<boolean>(false);
|
||||
const [error, setError] = useState<AxiosError>();
|
||||
|
||||
const fetchAirflowStatus = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const response = await checkAirflowStatus();
|
||||
setIsAirflowAvailable(response.status === 200);
|
||||
} catch (error) {
|
||||
setError(error as AxiosError);
|
||||
setIsAirflowAvailable(false);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchAirflowStatus();
|
||||
}, []);
|
||||
|
||||
return {
|
||||
isFetchingStatus: isLoading,
|
||||
isAirflowAvailable,
|
||||
error,
|
||||
fetchAirflowStatus,
|
||||
};
|
||||
};
|
@ -20,7 +20,6 @@ import PageLayoutV1 from '@components/containers/PageLayoutV1';
|
||||
import Loader from '@components/Loader/Loader';
|
||||
import {
|
||||
addIngestionPipeline,
|
||||
checkAirflowStatus,
|
||||
deployIngestionPipelineById,
|
||||
getIngestionPipelineByFqn,
|
||||
} from '@rest/ingestionPipelineAPI';
|
||||
@ -45,6 +44,7 @@ import { IngestionActionMessage } from '../../enums/ingestion.enum';
|
||||
import { ServiceCategory } from '../../enums/service.enum';
|
||||
import { CreateIngestionPipeline } from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
||||
import { PipelineType } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { useAirflowStatus } from '../../hooks/useAirflowStatus';
|
||||
import { DataObj } from '../../interface/service.interface';
|
||||
import jsonData from '../../jsons/en';
|
||||
import { getEntityMissingError } from '../../utils/CommonUtils';
|
||||
@ -58,6 +58,7 @@ import {
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
|
||||
const AddIngestionPage = () => {
|
||||
const { isAirflowAvailable, fetchAirflowStatus } = useAirflowStatus();
|
||||
const { ingestionType, serviceFQN, serviceCategory } =
|
||||
useParams<{ [key: string]: string }>();
|
||||
const { t } = useTranslation();
|
||||
@ -77,7 +78,6 @@ const AddIngestionPage = () => {
|
||||
const [slashedBreadcrumb, setSlashedBreadcrumb] = useState<
|
||||
TitleBreadcrumbProps['titleLinks']
|
||||
>([]);
|
||||
const [isAirflowRunning, setIsAirflowRunning] = useState(true);
|
||||
|
||||
const fetchServiceDetails = () => {
|
||||
getServiceByFQN(serviceCategory, serviceFQN)
|
||||
@ -177,33 +177,6 @@ const AddIngestionPage = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const onAirflowStatusCheck = (): Promise<void> => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch(() => reject());
|
||||
});
|
||||
};
|
||||
|
||||
const fetchAirflowStatusCheck = () => {
|
||||
return new Promise<void>((resolve) => {
|
||||
onAirflowStatusCheck()
|
||||
.then(() => {
|
||||
setIsAirflowRunning(true);
|
||||
})
|
||||
.catch(() => {
|
||||
setIsAirflowRunning(false);
|
||||
})
|
||||
.finally(() => resolve());
|
||||
});
|
||||
};
|
||||
|
||||
const goToService = () => {
|
||||
history.push(
|
||||
getServiceDetailsPath(serviceFQN, serviceCategory, 'ingestions')
|
||||
@ -274,7 +247,6 @@ const AddIngestionPage = () => {
|
||||
)}
|
||||
ingestionAction={ingestionAction}
|
||||
ingestionProgress={ingestionProgress}
|
||||
isAirflowSetup={isAirflowRunning}
|
||||
isIngestionCreated={isIngestionCreated}
|
||||
isIngestionDeployed={isIngestionDeployed}
|
||||
pipelineType={ingestionType as PipelineType}
|
||||
@ -286,7 +258,6 @@ const AddIngestionPage = () => {
|
||||
showDeployButton={showIngestionButton}
|
||||
status={FormSubmitType.ADD}
|
||||
onAddIngestionSave={onAddIngestionSave}
|
||||
onAirflowStatusCheck={onAirflowStatusCheck}
|
||||
onIngestionDeploy={onIngestionDeploy}
|
||||
/>
|
||||
</div>
|
||||
@ -300,7 +271,7 @@ const AddIngestionPage = () => {
|
||||
ingestionType as PipelineType,
|
||||
isDeployed(),
|
||||
false,
|
||||
isAirflowRunning
|
||||
isAirflowAvailable
|
||||
)}
|
||||
</div>
|
||||
</PageLayoutV1>
|
||||
@ -310,7 +281,7 @@ const AddIngestionPage = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchAirflowStatusCheck().finally(() => {
|
||||
fetchAirflowStatus().finally(() => {
|
||||
fetchServiceDetails();
|
||||
});
|
||||
}, [serviceCategory, serviceFQN]);
|
||||
|
@ -16,7 +16,6 @@ import { TitleBreadcrumbProps } from '@components/common/title-breadcrumb/title-
|
||||
import PageContainerV1 from '@components/containers/PageContainerV1';
|
||||
import {
|
||||
addIngestionPipeline,
|
||||
checkAirflowStatus,
|
||||
deployIngestionPipelineById,
|
||||
getIngestionPipelineByFqn,
|
||||
} from '@rest/ingestionPipelineAPI';
|
||||
@ -35,6 +34,7 @@ import { GlobalSettingsMenuCategory } from '../../constants/GlobalSettings.const
|
||||
import { IngestionActionMessage } from '../../enums/ingestion.enum';
|
||||
import { ServiceCategory } from '../../enums/service.enum';
|
||||
import { CreateIngestionPipeline } from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
||||
import { useAirflowStatus } from '../../hooks/useAirflowStatus';
|
||||
import { DataObj } from '../../interface/service.interface';
|
||||
import jsonData from '../../jsons/en';
|
||||
import { getSettingPath } from '../../utils/RouterUtils';
|
||||
@ -42,6 +42,7 @@ import { getServiceRouteFromServiceType } from '../../utils/ServiceUtils';
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
|
||||
const AddServicePage = () => {
|
||||
const { fetchAirflowStatus } = useAirflowStatus();
|
||||
const { serviceCategory } = useParams<{ [key: string]: string }>();
|
||||
const [newServiceData, setNewServiceData] = useState<ServicesUpdateRequest>();
|
||||
const [ingestionProgress, setIngestionProgress] = useState(0);
|
||||
@ -61,20 +62,6 @@ const AddServicePage = () => {
|
||||
setAddIngestion(value);
|
||||
};
|
||||
|
||||
const onAirflowStatusCheck = (): Promise<void> => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch(() => reject());
|
||||
});
|
||||
};
|
||||
|
||||
const onAddServiceSave = (data: DataObj) => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
postService(serviceCategory, data)
|
||||
@ -198,7 +185,7 @@ const AddServicePage = () => {
|
||||
slashedBreadcrumb={slashedBreadcrumb}
|
||||
onAddIngestionSave={onAddIngestionSave}
|
||||
onAddServiceSave={onAddServiceSave}
|
||||
onAirflowStatusCheck={onAirflowStatusCheck}
|
||||
onAirflowStatusCheck={fetchAirflowStatus}
|
||||
onIngestionDeploy={onIngestionDeploy}
|
||||
/>
|
||||
</div>
|
||||
|
@ -19,7 +19,6 @@ import PageContainerV1 from '@components/containers/PageContainerV1';
|
||||
import PageLayoutV1 from '@components/containers/PageLayoutV1';
|
||||
import Loader from '@components/Loader/Loader';
|
||||
import {
|
||||
checkAirflowStatus,
|
||||
deployIngestionPipelineById,
|
||||
getIngestionPipelineByFqn,
|
||||
updateIngestionPipeline,
|
||||
@ -47,6 +46,7 @@ import {
|
||||
IngestionPipeline,
|
||||
PipelineType,
|
||||
} from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||
import { useAirflowStatus } from '../../hooks/useAirflowStatus';
|
||||
import { DataObj } from '../../interface/service.interface';
|
||||
import jsonData from '../../jsons/en';
|
||||
import { getEntityMissingError } from '../../utils/CommonUtils';
|
||||
@ -60,6 +60,7 @@ import {
|
||||
import { showErrorToast } from '../../utils/ToastUtils';
|
||||
|
||||
const EditIngestionPage = () => {
|
||||
const { isAirflowAvailable, fetchAirflowStatus } = useAirflowStatus();
|
||||
const { ingestionFQN, ingestionType, serviceFQN, serviceCategory } =
|
||||
useParams<{ [key: string]: string }>();
|
||||
const history = useHistory();
|
||||
@ -80,7 +81,6 @@ const EditIngestionPage = () => {
|
||||
const [slashedBreadcrumb, setSlashedBreadcrumb] = useState<
|
||||
TitleBreadcrumbProps['titleLinks']
|
||||
>([]);
|
||||
const [isAirflowRunning, setIsAirflowRunning] = useState(true);
|
||||
|
||||
const fetchServiceDetails = () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
@ -210,33 +210,6 @@ const EditIngestionPage = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const onAirflowStatusCheck = (): Promise<void> => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch(() => reject());
|
||||
});
|
||||
};
|
||||
|
||||
const fetchAirflowStatusCheck = () => {
|
||||
return new Promise<void>((resolve) => {
|
||||
onAirflowStatusCheck()
|
||||
.then(() => {
|
||||
setIsAirflowRunning(true);
|
||||
})
|
||||
.catch(() => {
|
||||
setIsAirflowRunning(false);
|
||||
})
|
||||
.finally(() => resolve());
|
||||
});
|
||||
};
|
||||
|
||||
const goToService = () => {
|
||||
history.push(
|
||||
getServiceDetailsPath(serviceFQN, serviceCategory, 'ingestions')
|
||||
@ -307,7 +280,6 @@ const EditIngestionPage = () => {
|
||||
)}
|
||||
ingestionAction={ingestionAction}
|
||||
ingestionProgress={ingestionProgress}
|
||||
isAirflowSetup={isAirflowRunning}
|
||||
isIngestionCreated={isIngestionCreated}
|
||||
isIngestionDeployed={isIngestionDeployed}
|
||||
pipelineType={ingestionType as PipelineType}
|
||||
@ -318,7 +290,6 @@ const EditIngestionPage = () => {
|
||||
}
|
||||
showDeployButton={showIngestionButton}
|
||||
status={FormSubmitType.EDIT}
|
||||
onAirflowStatusCheck={onAirflowStatusCheck}
|
||||
onIngestionDeploy={onIngestionDeploy}
|
||||
onSuccessSave={goToService}
|
||||
onUpdateIngestion={onEditIngestionSave}
|
||||
@ -334,7 +305,7 @@ const EditIngestionPage = () => {
|
||||
ingestionType as PipelineType,
|
||||
isDeployed(),
|
||||
true,
|
||||
isAirflowRunning
|
||||
isAirflowAvailable
|
||||
)}
|
||||
</div>
|
||||
</PageLayoutV1>
|
||||
@ -344,7 +315,7 @@ const EditIngestionPage = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchAirflowStatusCheck().finally(() => {
|
||||
fetchAirflowStatus().finally(() => {
|
||||
fetchData();
|
||||
});
|
||||
}, [serviceCategory, serviceFQN]);
|
||||
|
@ -21,11 +21,10 @@ import SuccessScreen from '@components/common/success-screen/SuccessScreen';
|
||||
import TitleBreadcrumb from '@components/common/title-breadcrumb/title-breadcrumb.component';
|
||||
import PageLayoutV1 from '@components/containers/PageLayoutV1';
|
||||
import IngestionStepper from '@components/IngestionStepper/IngestionStepper.component';
|
||||
import { checkAirflowStatus } from '@rest/ingestionPipelineAPI';
|
||||
import { createTestSuites } from '@rest/testAPI';
|
||||
import { Col, Row, Space, Typography } from 'antd';
|
||||
import { AxiosError } from 'axios';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
@ -46,17 +45,8 @@ const TestSuiteStepper = () => {
|
||||
const history = useHistory();
|
||||
const [activeServiceStep, setActiveServiceStep] = useState(1);
|
||||
const [testSuiteResponse, setTestSuiteResponse] = useState<TestSuite>();
|
||||
const [isAirflowRunning, setIsAirflowRunning] = useState<boolean>(false);
|
||||
const [addIngestion, setAddIngestion] = useState<boolean>(false);
|
||||
|
||||
const handleAirflowStatusCheck = async (): Promise<void> => {
|
||||
try {
|
||||
await checkAirflowStatus();
|
||||
setIsAirflowRunning(true);
|
||||
} catch (error) {
|
||||
showErrorToast(error as AxiosError);
|
||||
}
|
||||
};
|
||||
const [addIngestion, setAddIngestion] = useState<boolean>(false);
|
||||
|
||||
const handleViewTestSuiteClick = () => {
|
||||
history.push(getTestSuitePath(testSuiteResponse?.fullyQualifiedName || ''));
|
||||
@ -84,21 +74,15 @@ const TestSuiteStepper = () => {
|
||||
showIngestionButton
|
||||
handleIngestionClick={() => setAddIngestion(true)}
|
||||
handleViewServiceClick={handleViewTestSuiteClick}
|
||||
isAirflowSetup={isAirflowRunning}
|
||||
name={testSuiteResponse?.name || ''}
|
||||
state={FormSubmitType.ADD}
|
||||
viewServiceText="View Test Suite"
|
||||
onCheckAirflowStatus={handleAirflowStatusCheck}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <AddTestSuiteForm onSubmit={onSubmitTestSuite} />;
|
||||
}, [activeServiceStep, isAirflowRunning]);
|
||||
|
||||
useEffect(() => {
|
||||
handleAirflowStatusCheck();
|
||||
}, []);
|
||||
}, [activeServiceStep]);
|
||||
|
||||
return (
|
||||
<div data-testid="test-suite-stepper-container">
|
||||
|
@ -33,7 +33,6 @@ import TagsViewer from '@components/tags-viewer/tags-viewer';
|
||||
import { getDashboards } from '@rest/dashboardAPI';
|
||||
import { getDatabases } from '@rest/databaseAPI';
|
||||
import {
|
||||
checkAirflowStatus,
|
||||
deleteIngestionPipelineById,
|
||||
deployIngestionPipelineById,
|
||||
enableDisableIngestionPipelineById,
|
||||
@ -84,6 +83,7 @@ import { IngestionPipeline } from '../../generated/entity/services/ingestionPipe
|
||||
import { MetadataServiceType } from '../../generated/entity/services/metadataService';
|
||||
import { EntityReference } from '../../generated/type/entityReference';
|
||||
import { Paging } from '../../generated/type/paging';
|
||||
import { useAirflowStatus } from '../../hooks/useAirflowStatus';
|
||||
import { ConfigData, ServicesType } from '../../interface/service.interface';
|
||||
import jsonData from '../../jsons/en';
|
||||
import { getEntityMissingError, getEntityName } from '../../utils/CommonUtils';
|
||||
@ -111,6 +111,7 @@ import { showErrorToast, showSuccessToast } from '../../utils/ToastUtils';
|
||||
export type ServicePageData = Database | Topic | Dashboard | Mlmodel | Pipeline;
|
||||
|
||||
const ServicePage: FunctionComponent = () => {
|
||||
const { isAirflowAvailable } = useAirflowStatus();
|
||||
const { serviceFQN, serviceType, serviceCategory, tab } =
|
||||
useParams() as Record<string, string>;
|
||||
const { getEntityPermissionByFqn } = usePermissionProvider();
|
||||
@ -139,7 +140,6 @@ const ServicePage: FunctionComponent = () => {
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [ingestionCurrentPage, setIngestionCurrentPage] = useState(1);
|
||||
const [airflowEndpoint, setAirflowEndpoint] = useState<string>();
|
||||
const [isAirflowRunning, setIsAirflowRunning] = useState(false);
|
||||
const [connectionDetails, setConnectionDetails] = useState<ConfigData>();
|
||||
|
||||
const [schemaCount, setSchemaCount] = useState<number>(0);
|
||||
@ -460,20 +460,6 @@ const ServicePage: FunctionComponent = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const getAirflowStatus = () => {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
checkAirflowStatus()
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
})
|
||||
.catch(() => reject());
|
||||
});
|
||||
};
|
||||
|
||||
const getOtherDetails = (paging?: string) => {
|
||||
switch (serviceName) {
|
||||
case ServiceCategory.DATABASE_SERVICES: {
|
||||
@ -691,15 +677,6 @@ const ServicePage: FunctionComponent = () => {
|
||||
if (tabs[currentTabIndex]?.isProtected) {
|
||||
activeTabHandler(1);
|
||||
}
|
||||
|
||||
getAirflowStatus()
|
||||
.then(() => {
|
||||
setIsAirflowRunning(true);
|
||||
getAllIngestionWorkflows();
|
||||
})
|
||||
.catch(() => {
|
||||
setIsAirflowRunning(false);
|
||||
});
|
||||
}
|
||||
}, [servicePermission]);
|
||||
|
||||
@ -829,7 +806,7 @@ const ServicePage: FunctionComponent = () => {
|
||||
};
|
||||
|
||||
const getIngestionTab = () => {
|
||||
if (!isAirflowRunning) {
|
||||
if (!isAirflowAvailable) {
|
||||
return <ErrorPlaceHolderIngestion />;
|
||||
} else if (isUndefined(airflowEndpoint)) {
|
||||
return <Loader />;
|
||||
@ -970,6 +947,12 @@ const ServicePage: FunctionComponent = () => {
|
||||
];
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAirflowAvailable) {
|
||||
getAllIngestionWorkflows();
|
||||
}
|
||||
}, [isAirflowAvailable]);
|
||||
|
||||
return (
|
||||
<PageContainerV1>
|
||||
{isLoading ? (
|
||||
@ -1153,7 +1136,7 @@ const ServicePage: FunctionComponent = () => {
|
||||
})}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{allowTestConn && isAirflowRunning && (
|
||||
{allowTestConn && isAirflowAvailable && (
|
||||
<Tooltip
|
||||
title={
|
||||
servicePermission.EditAll
|
||||
|
Loading…
x
Reference in New Issue
Block a user