chore(ui): improve test connection workflow delete flow (#11912)

* chore(ui): improve test connection workflow delete flow

* delete workflow on component unmount

* add unit test

* chore: simplify the condition

* chore: refactor delete workflow method

* fix: alignment issue on server connection tab

---------

Co-authored-by: Chirag Madlani <12962843+chirag-madlani@users.noreply.github.com>
This commit is contained in:
Sachin Chaurasiya 2023-06-16 12:49:28 +05:30 committed by GitHub
parent 3f01ee938f
commit a876889924
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 42 deletions

View File

@ -18,9 +18,9 @@ import React, { FC } from 'react';
import './airflow-message-banner.less'; import './airflow-message-banner.less';
const AirflowMessageBanner: FC<SpaceProps> = ({ className }) => { const AirflowMessageBanner: FC<SpaceProps> = ({ className }) => {
const { reason, isAirflowAvailable } = useAirflowStatus(); const { reason, isAirflowAvailable, isFetchingStatus } = useAirflowStatus();
if (isAirflowAvailable) { if (isAirflowAvailable || isFetchingStatus) {
return null; return null;
} }

View File

@ -27,6 +27,7 @@ import { ConfigData } from 'interface/service.interface';
import React from 'react'; import React from 'react';
import { import {
addWorkflow, addWorkflow,
deleteWorkflowById,
getTestConnectionDefinitionByName, getTestConnectionDefinitionByName,
getWorkflowById, getWorkflowById,
triggerWorkflowById, triggerWorkflowById,
@ -476,4 +477,29 @@ describe('Test Connection Component', () => {
expect(addWorkflow).not.toHaveBeenCalled(); expect(addWorkflow).not.toHaveBeenCalled();
}); });
it('Should delete the workflow if workflow failed to trigger', async () => {
(triggerWorkflowById as jest.Mock).mockImplementationOnce(() =>
Promise.resolve(204)
);
jest.useFakeTimers();
await act(async () => {
render(<TestConnection {...mockProps} />);
});
const testConnectionButton = screen.getByTestId('test-connection-btn');
await act(async () => {
userEvent.click(testConnectionButton);
});
expect(addWorkflow).toHaveBeenCalledWith(CREATE_WORKFLOW_PAYLOAD);
expect(triggerWorkflowById).toHaveBeenCalledWith(WORKFLOW_DETAILS.id);
jest.advanceTimersByTime(2000);
// delete api should be called
expect(deleteWorkflowById).toHaveBeenCalledWith(WORKFLOW_DETAILS.id, true);
});
}); });

View File

@ -23,7 +23,7 @@ import {
WorkflowType, WorkflowType,
} from 'generated/entity/automations/workflow'; } from 'generated/entity/automations/workflow';
import { TestConnectionStep } from 'generated/entity/services/connections/testConnectionDefinition'; import { TestConnectionStep } from 'generated/entity/services/connections/testConnectionDefinition';
import { toNumber } from 'lodash'; import { isEmpty, toNumber } from 'lodash';
import React, { FC, useEffect, useMemo, useRef, useState } from 'react'; import React, { FC, useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import {
@ -169,9 +169,12 @@ const TestConnection: FC<TestConnectionProps> = ({
}; };
const handleDeleteWorkflow = async (workflowId: string) => { const handleDeleteWorkflow = async (workflowId: string) => {
if (isEmpty(workflowId)) {
return;
}
try { try {
const response = await deleteWorkflowById(workflowId, true); await deleteWorkflowById(workflowId, true);
setCurrentWorkflow(response);
} catch (error) { } catch (error) {
// do not throw error for this API // do not throw error for this API
} }
@ -218,6 +221,9 @@ const TestConnection: FC<TestConnectionProps> = ({
setMessage(TEST_CONNECTION_FAILURE_MESSAGE); setMessage(TEST_CONNECTION_FAILURE_MESSAGE);
setIsTestingConnection(false); setIsTestingConnection(false);
// delete the workflow if workflow is not triggered successfully
await handleDeleteWorkflow(response.id);
return; return;
} }
@ -301,6 +307,12 @@ const TestConnection: FC<TestConnectionProps> = ({
setMessage(TEST_CONNECTION_FAILURE_MESSAGE); setMessage(TEST_CONNECTION_FAILURE_MESSAGE);
setTestStatus(StatusType.Failed); setTestStatus(StatusType.Failed);
showErrorToast(error as AxiosError); showErrorToast(error as AxiosError);
// delete the workflow if there is an exception
const workflowId = currentWorkflowRef.current?.id;
if (workflowId) {
await handleDeleteWorkflow(workflowId);
}
} }
}; };
@ -320,6 +332,18 @@ const TestConnection: FC<TestConnectionProps> = ({
currentWorkflowRef.current = currentWorkflow; // update ref with latest value of currentWorkflow state variable currentWorkflowRef.current = currentWorkflow; // update ref with latest value of currentWorkflow state variable
}, [currentWorkflow]); }, [currentWorkflow]);
useEffect(() => {
return () => {
/**
* if workflow is present then delete the workflow when component unmount
*/
const workflowId = currentWorkflowRef.current?.id;
if (workflowId) {
handleDeleteWorkflow(workflowId);
}
};
}, []);
// rendering // rendering
return ( return (

View File

@ -900,51 +900,55 @@ const ServicePage: FunctionComponent = () => {
const testConnectionTab = useMemo(() => { const testConnectionTab = useMemo(() => {
return ( return (
<> <>
<Space className="w-full my-4 justify-between"> <Row className="my-4">
<AirflowMessageBanner /> <Col span={12}>
<div> <AirflowMessageBanner />
<Tooltip </Col>
title={ <Col span={12}>
servicePermission.EditAll <Space className="w-full justify-end">
? t('label.edit-entity', {
entity: t('label.connection'),
})
: t('message.no-permission-for-action')
}>
<Button
ghost
data-testid="edit-connection-button"
disabled={!servicePermission.EditAll}
type="primary"
onClick={goToEditConnection}>
{t('label.edit-entity', {
entity: t('label.connection'),
})}
</Button>
</Tooltip>
{allowTestConn && isAirflowAvailable && (
<Tooltip <Tooltip
title={ title={
servicePermission.EditAll servicePermission.EditAll
? t('label.test-entity', { ? t('label.edit-entity', {
entity: t('label.connection'), entity: t('label.connection'),
}) })
: t('message.no-permission-for-action') : t('message.no-permission-for-action')
}> }>
<TestConnection <Button
connectionType={serviceDetails?.serviceType ?? ''} ghost
formData={connectionDetails as ConfigData} data-testid="edit-connection-button"
isTestingDisabled={isTestingDisabled} disabled={!servicePermission.EditAll}
serviceCategory={serviceCategory as ServiceCategory} type="primary"
serviceName={serviceDetails?.name} onClick={goToEditConnection}>
// validation is not required as we have all the data available and not in edit mode {t('label.edit-entity', {
shouldValidateForm={false} entity: t('label.connection'),
showDetails={false} })}
/> </Button>
</Tooltip> </Tooltip>
)} {allowTestConn && isAirflowAvailable && (
</div> <Tooltip
</Space> title={
servicePermission.EditAll
? t('label.test-entity', {
entity: t('label.connection'),
})
: t('message.no-permission-for-action')
}>
<TestConnection
connectionType={serviceDetails?.serviceType ?? ''}
formData={connectionDetails as ConfigData}
isTestingDisabled={isTestingDisabled}
serviceCategory={serviceCategory as ServiceCategory}
serviceName={serviceDetails?.name}
// validation is not required as we have all the data available and not in edit mode
shouldValidateForm={false}
showDetails={false}
/>
</Tooltip>
)}
</Space>
</Col>
</Row>
<ServiceConnectionDetails <ServiceConnectionDetails
connectionDetails={connectionDetails || {}} connectionDetails={connectionDetails || {}}
serviceCategory={serviceCategory} serviceCategory={serviceCategory}