mirror of
https://github.com/open-metadata/OpenMetadata.git
synced 2025-10-14 10:18:23 +00:00
Added new API integration for service page (#4158)
This commit is contained in:
parent
e57ad12a36
commit
a6424b2713
@ -12,7 +12,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { AxiosResponse } from 'axios';
|
import { AxiosResponse } from 'axios';
|
||||||
|
import { Operation } from 'fast-json-patch';
|
||||||
import { CreateIngestionPipeline } from '../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
import { CreateIngestionPipeline } from '../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
||||||
|
import { getURLWithQueryFields } from '../utils/APIUtils';
|
||||||
import APIClient from './index';
|
import APIClient from './index';
|
||||||
|
|
||||||
export const addIngestionPipeline = (
|
export const addIngestionPipeline = (
|
||||||
@ -20,3 +22,45 @@ export const addIngestionPipeline = (
|
|||||||
): Promise<AxiosResponse> => {
|
): Promise<AxiosResponse> => {
|
||||||
return APIClient.post('/services/ingestionPipelines', data);
|
return APIClient.post('/services/ingestionPipelines', data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getIngestionPipelines = (
|
||||||
|
arrQueryFields: Array<string>,
|
||||||
|
serviceFilter?: string,
|
||||||
|
paging?: string
|
||||||
|
): Promise<AxiosResponse> => {
|
||||||
|
const service = serviceFilter ? `service=${serviceFilter}` : '';
|
||||||
|
const url = `${getURLWithQueryFields(
|
||||||
|
'/services/ingestionPipelines',
|
||||||
|
arrQueryFields,
|
||||||
|
service
|
||||||
|
)}${paging ? paging : ''}`;
|
||||||
|
|
||||||
|
return APIClient.get(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const triggerIngestionPipelineById = (
|
||||||
|
id: string
|
||||||
|
): Promise<AxiosResponse> => {
|
||||||
|
return APIClient.post(`/services/ingestionPipelines/trigger/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteIngestionPipelineById = (
|
||||||
|
id: string
|
||||||
|
): Promise<AxiosResponse> => {
|
||||||
|
return APIClient.delete(`/services/ingestionPipelines/${id}?hardDelete=true`);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateIngestionPipeline = (
|
||||||
|
id: string,
|
||||||
|
patch: Operation[]
|
||||||
|
): Promise<AxiosResponse> => {
|
||||||
|
const configOptions = {
|
||||||
|
headers: { 'Content-type': 'application/json-patch+json' },
|
||||||
|
};
|
||||||
|
|
||||||
|
return APIClient.patch(
|
||||||
|
`/services/ingestionPipelines/${id}`,
|
||||||
|
patch,
|
||||||
|
configOptions
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isUndefined } from 'lodash';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import {
|
import {
|
||||||
INGESTION_SCHEDULER_INITIAL_VALUE,
|
INGESTION_SCHEDULER_INITIAL_VALUE,
|
||||||
@ -18,55 +19,104 @@ import {
|
|||||||
STEPS_FOR_ADD_INGESTION,
|
STEPS_FOR_ADD_INGESTION,
|
||||||
} from '../../constants/ingestion.constant';
|
} from '../../constants/ingestion.constant';
|
||||||
import { FilterPatternEnum } from '../../enums/filterPattern.enum';
|
import { FilterPatternEnum } from '../../enums/filterPattern.enum';
|
||||||
|
import { FormSubmitType } from '../../enums/form.enum';
|
||||||
import {
|
import {
|
||||||
|
ConfigClass,
|
||||||
CreateIngestionPipeline,
|
CreateIngestionPipeline,
|
||||||
PipelineType,
|
|
||||||
} from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
} from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
||||||
|
import {
|
||||||
|
FilterPattern,
|
||||||
|
IngestionPipeline,
|
||||||
|
} from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import { getCurrentDate, getCurrentUserId } from '../../utils/CommonUtils';
|
import { getCurrentDate, getCurrentUserId } from '../../utils/CommonUtils';
|
||||||
import SuccessScreen from '../common/success-screen/SuccessScreen';
|
import SuccessScreen from '../common/success-screen/SuccessScreen';
|
||||||
import IngestionStepper from '../IngestionStepper/IngestionStepper.component';
|
import IngestionStepper from '../IngestionStepper/IngestionStepper.component';
|
||||||
import { AddIngestionProps, PatternType } from './addIngestion.interface';
|
import { AddIngestionProps } from './addIngestion.interface';
|
||||||
import ConfigureIngestion from './Steps/ConfigureIngestion';
|
import ConfigureIngestion from './Steps/ConfigureIngestion';
|
||||||
import ScheduleInterval from './Steps/ScheduleInterval';
|
import ScheduleInterval from './Steps/ScheduleInterval';
|
||||||
|
|
||||||
const AddIngestion = ({
|
const AddIngestion = ({
|
||||||
|
heading,
|
||||||
|
status,
|
||||||
|
pipelineType,
|
||||||
|
data,
|
||||||
serviceData,
|
serviceData,
|
||||||
serviceCategory,
|
serviceCategory,
|
||||||
|
showSuccessScreen = true,
|
||||||
|
onUpdateIngestion,
|
||||||
|
onSuccessSave,
|
||||||
onAddIngestionSave,
|
onAddIngestionSave,
|
||||||
handleAddIngestion,
|
handleCancelClick,
|
||||||
handleViewServiceClick,
|
handleViewServiceClick,
|
||||||
}: AddIngestionProps) => {
|
}: AddIngestionProps) => {
|
||||||
const [activeStepperStep, setActiveStepperStep] = useState(1);
|
const [activeStepperStep, setActiveStepperStep] = useState(1);
|
||||||
const [ingestionName] = useState(
|
const [ingestionName] = useState(
|
||||||
`${serviceData.name}_${PipelineType.Metadata}`
|
data?.name ?? `${serviceData.name}_${pipelineType}`
|
||||||
);
|
);
|
||||||
const [repeatFrequency, setRepeatFrequency] = useState(
|
const [repeatFrequency, setRepeatFrequency] = useState(
|
||||||
INGESTION_SCHEDULER_INITIAL_VALUE
|
data?.airflowConfig.scheduleInterval ?? INGESTION_SCHEDULER_INITIAL_VALUE
|
||||||
);
|
);
|
||||||
const [startDate, setStartDate] = useState(getCurrentDate());
|
const [startDate, setStartDate] = useState(
|
||||||
const [endDate, setEndDate] = useState('');
|
data?.airflowConfig.startDate ?? getCurrentDate()
|
||||||
|
);
|
||||||
|
const [endDate, setEndDate] = useState(data?.airflowConfig?.endDate ?? '');
|
||||||
|
|
||||||
const [showDashboardFilter, setShowDashboardFilter] = useState(false);
|
const [showDashboardFilter, setShowDashboardFilter] = useState(
|
||||||
const [showSchemaFilter, setShowSchemaFilter] = useState(false);
|
!isUndefined(
|
||||||
const [showTableFilter, setShowTableFilter] = useState(false);
|
(data?.source.sourceConfig.config as ConfigClass)?.dashboardFilterPattern
|
||||||
const [showTopicFilter, setShowTopicFilter] = useState(false);
|
)
|
||||||
const [showChartFilter, setShowChartFilter] = useState(false);
|
);
|
||||||
const [includeView, setIncludeView] = useState(false);
|
const [showSchemaFilter, setShowSchemaFilter] = useState(
|
||||||
const [enableDataProfiler, setEnableDataProfiler] = useState(true);
|
!isUndefined(
|
||||||
const [ingestSampleData, setIngestSampleData] = useState(true);
|
(data?.source.sourceConfig.config as ConfigClass)?.schemaFilterPattern
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const [showTableFilter, setShowTableFilter] = useState(
|
||||||
|
!isUndefined(
|
||||||
|
(data?.source.sourceConfig.config as ConfigClass)?.tableFilterPattern
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const [showTopicFilter, setShowTopicFilter] = useState(
|
||||||
|
!isUndefined(
|
||||||
|
(data?.source.sourceConfig.config as ConfigClass)?.topicFilterPattern
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const [showChartFilter, setShowChartFilter] = useState(
|
||||||
|
!isUndefined(
|
||||||
|
(data?.source.sourceConfig.config as ConfigClass)?.chartFilterPattern
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const [includeView, setIncludeView] = useState(
|
||||||
|
(data?.source.sourceConfig.config as ConfigClass)?.includeViews ?? false
|
||||||
|
);
|
||||||
|
const [enableDataProfiler, setEnableDataProfiler] = useState(
|
||||||
|
(data?.source.sourceConfig.config as ConfigClass)?.enableDataProfiler ??
|
||||||
|
true
|
||||||
|
);
|
||||||
|
const [ingestSampleData, setIngestSampleData] = useState(
|
||||||
|
(data?.source.sourceConfig.config as ConfigClass)?.generateSampleData ??
|
||||||
|
true
|
||||||
|
);
|
||||||
const [dashboardFilterPattern, setDashboardFilterPattern] =
|
const [dashboardFilterPattern, setDashboardFilterPattern] =
|
||||||
useState<PatternType>(INITIAL_FILTER_PATTERN);
|
useState<FilterPattern>(
|
||||||
const [schemaFilterPattern, setSchemaFilterPattern] = useState<PatternType>(
|
(data?.source.sourceConfig.config as ConfigClass)
|
||||||
INITIAL_FILTER_PATTERN
|
?.dashboardFilterPattern ?? INITIAL_FILTER_PATTERN
|
||||||
|
);
|
||||||
|
const [schemaFilterPattern, setSchemaFilterPattern] = useState<FilterPattern>(
|
||||||
|
(data?.source.sourceConfig.config as ConfigClass)?.schemaFilterPattern ??
|
||||||
|
INITIAL_FILTER_PATTERN
|
||||||
);
|
);
|
||||||
const [tableFilterPattern, setTableFilterPattern] = useState<PatternType>(
|
const [tableFilterPattern, setTableFilterPattern] = useState<FilterPattern>(
|
||||||
INITIAL_FILTER_PATTERN
|
(data?.source.sourceConfig.config as ConfigClass)?.tableFilterPattern ??
|
||||||
|
INITIAL_FILTER_PATTERN
|
||||||
);
|
);
|
||||||
const [topicFilterPattern, setTopicFilterPattern] = useState<PatternType>(
|
const [topicFilterPattern, setTopicFilterPattern] = useState<FilterPattern>(
|
||||||
INITIAL_FILTER_PATTERN
|
(data?.source.sourceConfig.config as ConfigClass)?.topicFilterPattern ??
|
||||||
|
INITIAL_FILTER_PATTERN
|
||||||
);
|
);
|
||||||
const [chartFilterPattern, setChartFilterPattern] = useState<PatternType>(
|
const [chartFilterPattern, setChartFilterPattern] = useState<FilterPattern>(
|
||||||
INITIAL_FILTER_PATTERN
|
(data?.source.sourceConfig.config as ConfigClass)?.chartFilterPattern ??
|
||||||
|
INITIAL_FILTER_PATTERN
|
||||||
);
|
);
|
||||||
|
|
||||||
const getIncludeValue = (value: Array<string>, type: FilterPatternEnum) => {
|
const getIncludeValue = (value: Array<string>, type: FilterPatternEnum) => {
|
||||||
@ -74,24 +124,24 @@ const AddIngestion = ({
|
|||||||
case FilterPatternEnum.DASHBOARD:
|
case FilterPatternEnum.DASHBOARD:
|
||||||
setDashboardFilterPattern({
|
setDashboardFilterPattern({
|
||||||
...dashboardFilterPattern,
|
...dashboardFilterPattern,
|
||||||
include: value,
|
includes: value,
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.SCHEMA:
|
case FilterPatternEnum.SCHEMA:
|
||||||
setSchemaFilterPattern({ ...schemaFilterPattern, include: value });
|
setSchemaFilterPattern({ ...schemaFilterPattern, includes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.TABLE:
|
case FilterPatternEnum.TABLE:
|
||||||
setTableFilterPattern({ ...tableFilterPattern, include: value });
|
setTableFilterPattern({ ...tableFilterPattern, includes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.TOPIC:
|
case FilterPatternEnum.TOPIC:
|
||||||
setTopicFilterPattern({ ...topicFilterPattern, include: value });
|
setTopicFilterPattern({ ...topicFilterPattern, includes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.CHART:
|
case FilterPatternEnum.CHART:
|
||||||
setChartFilterPattern({ ...topicFilterPattern, include: value });
|
setChartFilterPattern({ ...topicFilterPattern, includes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -101,24 +151,24 @@ const AddIngestion = ({
|
|||||||
case FilterPatternEnum.DASHBOARD:
|
case FilterPatternEnum.DASHBOARD:
|
||||||
setDashboardFilterPattern({
|
setDashboardFilterPattern({
|
||||||
...dashboardFilterPattern,
|
...dashboardFilterPattern,
|
||||||
exclude: value,
|
excludes: value,
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.SCHEMA:
|
case FilterPatternEnum.SCHEMA:
|
||||||
setSchemaFilterPattern({ ...schemaFilterPattern, exclude: value });
|
setSchemaFilterPattern({ ...schemaFilterPattern, excludes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.TABLE:
|
case FilterPatternEnum.TABLE:
|
||||||
setTableFilterPattern({ ...tableFilterPattern, exclude: value });
|
setTableFilterPattern({ ...tableFilterPattern, excludes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.TOPIC:
|
case FilterPatternEnum.TOPIC:
|
||||||
setTopicFilterPattern({ ...topicFilterPattern, exclude: value });
|
setTopicFilterPattern({ ...topicFilterPattern, excludes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FilterPatternEnum.CHART:
|
case FilterPatternEnum.CHART:
|
||||||
setChartFilterPattern({ ...topicFilterPattern, exclude: value });
|
setChartFilterPattern({ ...topicFilterPattern, excludes: value });
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -150,7 +200,7 @@ const AddIngestion = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleConfigureIngestionCancelClick = () => {
|
const handleConfigureIngestionCancelClick = () => {
|
||||||
handleAddIngestion(false);
|
handleCancelClick();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConfigureIngestionNextClick = () => {
|
const handleConfigureIngestionNextClick = () => {
|
||||||
@ -161,22 +211,22 @@ const AddIngestion = ({
|
|||||||
setActiveStepperStep(1);
|
setActiveStepperStep(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFilterPatternData = (data: PatternType) => {
|
const getFilterPatternData = (data: FilterPattern) => {
|
||||||
const { include, exclude } = data;
|
const { includes, excludes } = data;
|
||||||
|
|
||||||
return include.length === 0 && exclude.length === 0
|
return isUndefined(includes) && isUndefined(excludes)
|
||||||
? undefined
|
? undefined
|
||||||
: {
|
: {
|
||||||
includes: include.length > 0 ? include : undefined,
|
includes: includes && includes.length > 0 ? includes : undefined,
|
||||||
excludes: exclude.length > 0 ? exclude : undefined,
|
excludes: excludes && excludes.length > 0 ? excludes : undefined,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleScheduleIntervalDeployClick = () => {
|
const createNewIngestion = () => {
|
||||||
const ingestionDetails: CreateIngestionPipeline = {
|
const ingestionDetails: CreateIngestionPipeline = {
|
||||||
airflowConfig: {
|
airflowConfig: {
|
||||||
startDate: startDate as unknown as Date,
|
startDate: startDate as unknown as Date,
|
||||||
endDate: startDate as unknown as Date,
|
endDate: endDate as unknown as Date,
|
||||||
scheduleInterval: repeatFrequency,
|
scheduleInterval: repeatFrequency,
|
||||||
forceDeploy: true,
|
forceDeploy: true,
|
||||||
},
|
},
|
||||||
@ -186,7 +236,7 @@ const AddIngestion = ({
|
|||||||
id: getCurrentUserId(),
|
id: getCurrentUserId(),
|
||||||
type: 'user',
|
type: 'user',
|
||||||
},
|
},
|
||||||
pipelineType: PipelineType.Metadata,
|
pipelineType: pipelineType,
|
||||||
service: {
|
service: {
|
||||||
id: serviceData.id as string,
|
id: serviceData.id as string,
|
||||||
type: serviceCategory.slice(0, -1),
|
type: serviceCategory.slice(0, -1),
|
||||||
@ -206,13 +256,64 @@ const AddIngestion = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
onAddIngestionSave(ingestionDetails).then(() => {
|
onAddIngestionSave(ingestionDetails).then(() => {
|
||||||
setActiveStepperStep(3);
|
if (showSuccessScreen) {
|
||||||
|
setActiveStepperStep(3);
|
||||||
|
} else {
|
||||||
|
onSuccessSave?.();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateIngestion = () => {
|
||||||
|
if (data) {
|
||||||
|
const updatedData: IngestionPipeline = {
|
||||||
|
...data,
|
||||||
|
airflowConfig: {
|
||||||
|
...data.airflowConfig,
|
||||||
|
startDate: startDate as unknown as Date,
|
||||||
|
endDate: endDate as unknown as Date,
|
||||||
|
scheduleInterval: repeatFrequency,
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
...data.source,
|
||||||
|
sourceConfig: {
|
||||||
|
config: {
|
||||||
|
...(data.source.sourceConfig.config as ConfigClass),
|
||||||
|
enableDataProfiler: enableDataProfiler,
|
||||||
|
generateSampleData: ingestSampleData,
|
||||||
|
includeViews: includeView,
|
||||||
|
schemaFilterPattern: getFilterPatternData(schemaFilterPattern),
|
||||||
|
tableFilterPattern: getFilterPatternData(tableFilterPattern),
|
||||||
|
chartFilterPattern: getFilterPatternData(chartFilterPattern),
|
||||||
|
dashboardFilterPattern: getFilterPatternData(
|
||||||
|
dashboardFilterPattern
|
||||||
|
),
|
||||||
|
topicFilterPattern: getFilterPatternData(topicFilterPattern),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
onUpdateIngestion &&
|
||||||
|
onUpdateIngestion(updatedData, data, data.id as string, data.name).then(
|
||||||
|
() => {
|
||||||
|
onSuccessSave?.();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleScheduleIntervalDeployClick = () => {
|
||||||
|
if (status === FormSubmitType.ADD) {
|
||||||
|
createNewIngestion();
|
||||||
|
} else {
|
||||||
|
updateIngestion();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="add-ingestion-container">
|
<div data-testid="add-ingestion-container">
|
||||||
<h6 className="tw-heading tw-text-base">Add New Ingestion</h6>
|
<h6 className="tw-heading tw-text-base">{heading}</h6>
|
||||||
|
|
||||||
<IngestionStepper
|
<IngestionStepper
|
||||||
activeStep={activeStepperStep}
|
activeStep={activeStepperStep}
|
||||||
@ -254,20 +355,20 @@ const AddIngestion = ({
|
|||||||
|
|
||||||
{activeStepperStep === 2 && (
|
{activeStepperStep === 2 && (
|
||||||
<ScheduleInterval
|
<ScheduleInterval
|
||||||
endDate={endDate}
|
endDate={endDate as string}
|
||||||
handleEndDateChange={(value: string) => setEndDate(value)}
|
handleEndDateChange={(value: string) => setEndDate(value)}
|
||||||
handleRepeatFrequencyChange={(value: string) =>
|
handleRepeatFrequencyChange={(value: string) =>
|
||||||
setRepeatFrequency(value)
|
setRepeatFrequency(value)
|
||||||
}
|
}
|
||||||
handleStartDateChange={(value: string) => setStartDate(value)}
|
handleStartDateChange={(value: string) => setStartDate(value)}
|
||||||
repeatFrequency={repeatFrequency}
|
repeatFrequency={repeatFrequency}
|
||||||
startDate={startDate}
|
startDate={startDate as string}
|
||||||
onBack={handleScheduleIntervalBackClick}
|
onBack={handleScheduleIntervalBackClick}
|
||||||
onDeloy={handleScheduleIntervalDeployClick}
|
onDeloy={handleScheduleIntervalDeployClick}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{activeStepperStep > 2 && (
|
{activeStepperStep > 2 && handleViewServiceClick && (
|
||||||
<SuccessScreen
|
<SuccessScreen
|
||||||
handleViewServiceClick={handleViewServiceClick}
|
handleViewServiceClick={handleViewServiceClick}
|
||||||
name={ingestionName}
|
name={ingestionName}
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
|
|
||||||
import { findByTestId, findByText, render } from '@testing-library/react';
|
import { findByTestId, findByText, render } from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { FormSubmitType } from '../../enums/form.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
|
import { PipelineType } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import { DataObj } from '../../interface/service.interface';
|
import { DataObj } from '../../interface/service.interface';
|
||||||
import AddIngestion from './AddIngestion.component';
|
import AddIngestion from './AddIngestion.component';
|
||||||
import { AddIngestionProps } from './addIngestion.interface';
|
import { AddIngestionProps } from './addIngestion.interface';
|
||||||
@ -22,10 +24,13 @@ const mockAddIngestionProps: AddIngestionProps = {
|
|||||||
serviceData: {
|
serviceData: {
|
||||||
name: 'serviceName',
|
name: 'serviceName',
|
||||||
} as DataObj,
|
} as DataObj,
|
||||||
handleAddIngestion: jest.fn(),
|
handleCancelClick: jest.fn(),
|
||||||
serviceCategory: ServiceCategory.DASHBOARD_SERVICES,
|
serviceCategory: ServiceCategory.DASHBOARD_SERVICES,
|
||||||
onAddIngestionSave: jest.fn(),
|
onAddIngestionSave: jest.fn(),
|
||||||
handleViewServiceClick: jest.fn(),
|
handleViewServiceClick: jest.fn(),
|
||||||
|
pipelineType: PipelineType.Metadata,
|
||||||
|
heading: 'add ingestion',
|
||||||
|
status: FormSubmitType.ADD,
|
||||||
};
|
};
|
||||||
|
|
||||||
jest.mock('./Steps/ConfigureIngestion', () => {
|
jest.mock('./Steps/ConfigureIngestion', () => {
|
||||||
|
@ -30,24 +30,24 @@ jest.mock('../../common/toggle-switch/ToggleSwitchV1', () => {
|
|||||||
const mockConfigureIngestion: ConfigureIngestionProps = {
|
const mockConfigureIngestion: ConfigureIngestionProps = {
|
||||||
ingestionName: '',
|
ingestionName: '',
|
||||||
dashboardFilterPattern: {
|
dashboardFilterPattern: {
|
||||||
include: [],
|
includes: [],
|
||||||
exclude: [],
|
excludes: [],
|
||||||
},
|
},
|
||||||
chartFilterPattern: {
|
chartFilterPattern: {
|
||||||
include: [],
|
includes: [],
|
||||||
exclude: [],
|
excludes: [],
|
||||||
},
|
},
|
||||||
schemaFilterPattern: {
|
schemaFilterPattern: {
|
||||||
include: [],
|
includes: [],
|
||||||
exclude: [],
|
excludes: [],
|
||||||
},
|
},
|
||||||
tableFilterPattern: {
|
tableFilterPattern: {
|
||||||
include: [],
|
includes: [],
|
||||||
exclude: [],
|
excludes: [],
|
||||||
},
|
},
|
||||||
topicFilterPattern: {
|
topicFilterPattern: {
|
||||||
include: [],
|
includes: [],
|
||||||
exclude: [],
|
excludes: [],
|
||||||
},
|
},
|
||||||
includeView: false,
|
includeView: false,
|
||||||
enableDataProfiler: false,
|
enableDataProfiler: false,
|
||||||
|
@ -52,24 +52,24 @@ const ConfigureIngestion = ({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<FilterPattern
|
<FilterPattern
|
||||||
checked={showSchemaFilter}
|
checked={showSchemaFilter}
|
||||||
excludePattern={schemaFilterPattern.exclude}
|
excludePattern={schemaFilterPattern?.excludes ?? []}
|
||||||
getExcludeValue={getExcludeValue}
|
getExcludeValue={getExcludeValue}
|
||||||
getIncludeValue={getIncludeValue}
|
getIncludeValue={getIncludeValue}
|
||||||
handleChecked={(value) =>
|
handleChecked={(value) =>
|
||||||
handleShowFilter(value, FilterPatternEnum.SCHEMA)
|
handleShowFilter(value, FilterPatternEnum.SCHEMA)
|
||||||
}
|
}
|
||||||
includePattern={schemaFilterPattern.include}
|
includePattern={schemaFilterPattern?.includes ?? []}
|
||||||
type={FilterPatternEnum.SCHEMA}
|
type={FilterPatternEnum.SCHEMA}
|
||||||
/>
|
/>
|
||||||
<FilterPattern
|
<FilterPattern
|
||||||
checked={showTableFilter}
|
checked={showTableFilter}
|
||||||
excludePattern={tableFilterPattern.exclude}
|
excludePattern={tableFilterPattern?.excludes ?? []}
|
||||||
getExcludeValue={getExcludeValue}
|
getExcludeValue={getExcludeValue}
|
||||||
getIncludeValue={getIncludeValue}
|
getIncludeValue={getIncludeValue}
|
||||||
handleChecked={(value) =>
|
handleChecked={(value) =>
|
||||||
handleShowFilter(value, FilterPatternEnum.TABLE)
|
handleShowFilter(value, FilterPatternEnum.TABLE)
|
||||||
}
|
}
|
||||||
includePattern={tableFilterPattern.include}
|
includePattern={tableFilterPattern?.includes ?? []}
|
||||||
showSeparator={false}
|
showSeparator={false}
|
||||||
type={FilterPatternEnum.TABLE}
|
type={FilterPatternEnum.TABLE}
|
||||||
/>
|
/>
|
||||||
@ -80,24 +80,24 @@ const ConfigureIngestion = ({
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<FilterPattern
|
<FilterPattern
|
||||||
checked={showDashboardFilter}
|
checked={showDashboardFilter}
|
||||||
excludePattern={dashboardFilterPattern.exclude}
|
excludePattern={dashboardFilterPattern.excludes ?? []}
|
||||||
getExcludeValue={getExcludeValue}
|
getExcludeValue={getExcludeValue}
|
||||||
getIncludeValue={getIncludeValue}
|
getIncludeValue={getIncludeValue}
|
||||||
handleChecked={(value) =>
|
handleChecked={(value) =>
|
||||||
handleShowFilter(value, FilterPatternEnum.DASHBOARD)
|
handleShowFilter(value, FilterPatternEnum.DASHBOARD)
|
||||||
}
|
}
|
||||||
includePattern={dashboardFilterPattern.include}
|
includePattern={dashboardFilterPattern.includes ?? []}
|
||||||
type={FilterPatternEnum.DASHBOARD}
|
type={FilterPatternEnum.DASHBOARD}
|
||||||
/>
|
/>
|
||||||
<FilterPattern
|
<FilterPattern
|
||||||
checked={showChartFilter}
|
checked={showChartFilter}
|
||||||
excludePattern={chartFilterPattern.exclude}
|
excludePattern={chartFilterPattern.excludes ?? []}
|
||||||
getExcludeValue={getExcludeValue}
|
getExcludeValue={getExcludeValue}
|
||||||
getIncludeValue={getIncludeValue}
|
getIncludeValue={getIncludeValue}
|
||||||
handleChecked={(value) =>
|
handleChecked={(value) =>
|
||||||
handleShowFilter(value, FilterPatternEnum.CHART)
|
handleShowFilter(value, FilterPatternEnum.CHART)
|
||||||
}
|
}
|
||||||
includePattern={chartFilterPattern.include}
|
includePattern={chartFilterPattern.includes ?? []}
|
||||||
showSeparator={false}
|
showSeparator={false}
|
||||||
type={FilterPatternEnum.CHART}
|
type={FilterPatternEnum.CHART}
|
||||||
/>
|
/>
|
||||||
@ -108,13 +108,13 @@ const ConfigureIngestion = ({
|
|||||||
return (
|
return (
|
||||||
<FilterPattern
|
<FilterPattern
|
||||||
checked={showTopicFilter}
|
checked={showTopicFilter}
|
||||||
excludePattern={topicFilterPattern.exclude}
|
excludePattern={topicFilterPattern.excludes ?? []}
|
||||||
getExcludeValue={getExcludeValue}
|
getExcludeValue={getExcludeValue}
|
||||||
getIncludeValue={getIncludeValue}
|
getIncludeValue={getIncludeValue}
|
||||||
handleChecked={(value) =>
|
handleChecked={(value) =>
|
||||||
handleShowFilter(value, FilterPatternEnum.TOPIC)
|
handleShowFilter(value, FilterPatternEnum.TOPIC)
|
||||||
}
|
}
|
||||||
includePattern={topicFilterPattern.include}
|
includePattern={topicFilterPattern.includes ?? []}
|
||||||
showSeparator={false}
|
showSeparator={false}
|
||||||
type={FilterPatternEnum.TOPIC}
|
type={FilterPatternEnum.TOPIC}
|
||||||
/>
|
/>
|
||||||
|
@ -12,31 +12,45 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { FilterPatternEnum } from '../../enums/filterPattern.enum';
|
import { FilterPatternEnum } from '../../enums/filterPattern.enum';
|
||||||
|
import { FormSubmitType } from '../../enums/form.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
import { CreateIngestionPipeline } from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
import { CreateIngestionPipeline } from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
||||||
|
import {
|
||||||
|
FilterPattern,
|
||||||
|
IngestionPipeline,
|
||||||
|
PipelineType,
|
||||||
|
} from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import { DataObj } from '../../interface/service.interface';
|
import { DataObj } from '../../interface/service.interface';
|
||||||
|
|
||||||
export interface AddIngestionProps {
|
export interface AddIngestionProps {
|
||||||
|
pipelineType: PipelineType;
|
||||||
|
heading: string;
|
||||||
|
status: FormSubmitType;
|
||||||
|
data?: IngestionPipeline;
|
||||||
serviceCategory: ServiceCategory;
|
serviceCategory: ServiceCategory;
|
||||||
serviceData: DataObj;
|
serviceData: DataObj;
|
||||||
handleAddIngestion: (value: boolean) => void;
|
showSuccessScreen?: boolean;
|
||||||
|
handleCancelClick: () => void;
|
||||||
onAddIngestionSave: (ingestion: CreateIngestionPipeline) => Promise<void>;
|
onAddIngestionSave: (ingestion: CreateIngestionPipeline) => Promise<void>;
|
||||||
handleViewServiceClick: () => void;
|
onUpdateIngestion?: (
|
||||||
|
data: IngestionPipeline,
|
||||||
|
oldData: IngestionPipeline,
|
||||||
|
id: string,
|
||||||
|
displayName: string,
|
||||||
|
triggerIngestion?: boolean
|
||||||
|
) => Promise<void>;
|
||||||
|
onSuccessSave?: () => void;
|
||||||
|
handleViewServiceClick?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PatternType = {
|
|
||||||
include: Array<string>;
|
|
||||||
exclude: Array<string>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ConfigureIngestionProps {
|
export interface ConfigureIngestionProps {
|
||||||
ingestionName: string;
|
ingestionName: string;
|
||||||
serviceCategory: ServiceCategory;
|
serviceCategory: ServiceCategory;
|
||||||
dashboardFilterPattern: PatternType;
|
dashboardFilterPattern: FilterPattern;
|
||||||
schemaFilterPattern: PatternType;
|
schemaFilterPattern: FilterPattern;
|
||||||
tableFilterPattern: PatternType;
|
tableFilterPattern: FilterPattern;
|
||||||
topicFilterPattern: PatternType;
|
topicFilterPattern: FilterPattern;
|
||||||
chartFilterPattern: PatternType;
|
chartFilterPattern: FilterPattern;
|
||||||
includeView: boolean;
|
includeView: boolean;
|
||||||
enableDataProfiler: boolean;
|
enableDataProfiler: boolean;
|
||||||
ingestSampleData: boolean;
|
ingestSampleData: boolean;
|
||||||
|
@ -11,14 +11,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isUndefined } from 'lodash';
|
import { capitalize, isUndefined } from 'lodash';
|
||||||
import { LoadingState } from 'Models';
|
import { LoadingState } from 'Models';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import { getServiceDetailsPath, ROUTES } from '../../constants/constants';
|
import { getServiceDetailsPath, ROUTES } from '../../constants/constants';
|
||||||
import { STEPS_FOR_ADD_SERVICE } from '../../constants/services.const';
|
import { STEPS_FOR_ADD_SERVICE } from '../../constants/services.const';
|
||||||
|
import { FormSubmitType } from '../../enums/form.enum';
|
||||||
import { PageLayoutType } from '../../enums/layout.enum';
|
import { PageLayoutType } from '../../enums/layout.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
|
import { PipelineType } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import {
|
import {
|
||||||
ConfigData,
|
ConfigData,
|
||||||
DataObj,
|
DataObj,
|
||||||
@ -248,10 +250,13 @@ const AddService = ({
|
|||||||
<div className="tw-form-container">
|
<div className="tw-form-container">
|
||||||
{addIngestion ? (
|
{addIngestion ? (
|
||||||
<AddIngestion
|
<AddIngestion
|
||||||
handleAddIngestion={handleAddIngestion}
|
handleCancelClick={() => handleAddIngestion(false)}
|
||||||
handleViewServiceClick={handleViewServiceClick}
|
handleViewServiceClick={handleViewServiceClick}
|
||||||
|
heading={`Add ${capitalize(PipelineType.Metadata)} Ingestion`}
|
||||||
|
pipelineType={PipelineType.Metadata}
|
||||||
serviceCategory={serviceCategory}
|
serviceCategory={serviceCategory}
|
||||||
serviceData={newServiceData as DataObj}
|
serviceData={newServiceData as DataObj}
|
||||||
|
status={FormSubmitType.ADD}
|
||||||
onAddIngestionSave={onAddIngestionSave}
|
onAddIngestionSave={onAddIngestionSave}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
@ -15,37 +15,36 @@ import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
|
|||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import cronstrue from 'cronstrue';
|
import cronstrue from 'cronstrue';
|
||||||
import { capitalize, isNil, lowerCase } from 'lodash';
|
import { capitalize, isNil, isUndefined, lowerCase } from 'lodash';
|
||||||
import React, { Fragment, useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
||||||
import {
|
import {
|
||||||
PAGE_SIZE,
|
PAGE_SIZE,
|
||||||
TITLE_FOR_NON_ADMIN_ACTION,
|
TITLE_FOR_NON_ADMIN_ACTION,
|
||||||
} from '../../constants/constants';
|
} from '../../constants/constants';
|
||||||
|
import { FormSubmitType } from '../../enums/form.enum';
|
||||||
import {
|
import {
|
||||||
AirflowPipeline,
|
IngestionPipeline,
|
||||||
ConfigClass,
|
|
||||||
PipelineType,
|
PipelineType,
|
||||||
} from '../../generated/operations/pipelines/airflowPipeline';
|
} from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import { isEven } from '../../utils/CommonUtils';
|
import { isEven } from '../../utils/CommonUtils';
|
||||||
import { getAirflowPipelineTypes } from '../../utils/ServiceUtils';
|
|
||||||
import { showInfoToast } from '../../utils/ToastUtils';
|
import { showInfoToast } from '../../utils/ToastUtils';
|
||||||
|
import AddIngestion from '../AddIngestion/AddIngestion.component';
|
||||||
import { Button } from '../buttons/Button/Button';
|
import { Button } from '../buttons/Button/Button';
|
||||||
import NextPrevious from '../common/next-previous/NextPrevious';
|
import NextPrevious from '../common/next-previous/NextPrevious';
|
||||||
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
import NonAdminAction from '../common/non-admin-action/NonAdminAction';
|
||||||
import PopOver from '../common/popover/PopOver';
|
import PopOver from '../common/popover/PopOver';
|
||||||
import Searchbar from '../common/searchbar/Searchbar';
|
import Searchbar from '../common/searchbar/Searchbar';
|
||||||
import IngestionModal from '../IngestionModal/IngestionModal.component';
|
|
||||||
import Loader from '../Loader/Loader';
|
import Loader from '../Loader/Loader';
|
||||||
import ConfirmationModal from '../Modals/ConfirmationModal/ConfirmationModal';
|
import EntityDeleteModal from '../Modals/EntityDeleteModal/EntityDeleteModal';
|
||||||
import { Props } from './ingestion.interface';
|
import { IngestionProps, ModifiedConfig } from './ingestion.interface';
|
||||||
|
|
||||||
const Ingestion: React.FC<Props> = ({
|
const Ingestion: React.FC<IngestionProps> = ({
|
||||||
serviceType = '',
|
serviceDetails,
|
||||||
serviceName,
|
serviceName,
|
||||||
|
serviceCategory,
|
||||||
ingestionList,
|
ingestionList,
|
||||||
serviceList,
|
|
||||||
isRequiredDetailsAvailable,
|
isRequiredDetailsAvailable,
|
||||||
deleteIngestion,
|
deleteIngestion,
|
||||||
triggerIngestion,
|
triggerIngestion,
|
||||||
@ -54,42 +53,45 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
paging,
|
paging,
|
||||||
pagingHandler,
|
pagingHandler,
|
||||||
currrentPage,
|
currrentPage,
|
||||||
}: Props) => {
|
}: IngestionProps) => {
|
||||||
const { isAdminUser } = useAuth();
|
const { isAdminUser } = useAuth();
|
||||||
const { isAuthDisabled } = useAuthContext();
|
const { isAuthDisabled } = useAuthContext();
|
||||||
const [searchText, setSearchText] = useState('');
|
const [searchText, setSearchText] = useState('');
|
||||||
const [currTriggerId, setCurrTriggerId] = useState({ id: '', state: '' });
|
const [currTriggerId, setCurrTriggerId] = useState({ id: '', state: '' });
|
||||||
const [isAdding, setIsAdding] = useState<boolean>(false);
|
const [showIngestionForm, setShowIngestionForm] = useState(false);
|
||||||
const [isUpdating, setIsUpdating] = useState<boolean>(false);
|
|
||||||
const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false);
|
const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false);
|
||||||
const [deleteSelection, setDeleteSelection] = useState({
|
const [deleteSelection, setDeleteSelection] = useState({
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
state: '',
|
state: '',
|
||||||
});
|
});
|
||||||
const [updateSelection, setUpdateSelection] = useState({
|
const [updateSelection, setUpdateSelection] = useState<IngestionPipeline>();
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
state: '',
|
|
||||||
ingestion: {} as AirflowPipeline,
|
|
||||||
});
|
|
||||||
const noConnectionMsg = `${serviceName} doesn't have connection details filled in. Please add the details before scheduling an ingestion job.`;
|
const noConnectionMsg = `${serviceName} doesn't have connection details filled in. Please add the details before scheduling an ingestion job.`;
|
||||||
|
|
||||||
const handleSearchAction = (searchValue: string) => {
|
const handleSearchAction = (searchValue: string) => {
|
||||||
setSearchText(searchValue);
|
setSearchText(searchValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getAirflowPipelineTypeOption = (): PipelineType[] => {
|
const getIngestionPipelineTypeOption = (): PipelineType[] => {
|
||||||
const types = getAirflowPipelineTypes(serviceType) || [];
|
if (ingestionList.length > 0) {
|
||||||
|
const ingestion = ingestionList[0]?.source?.serviceConnection
|
||||||
|
?.config as ModifiedConfig;
|
||||||
|
const pipelineType = [];
|
||||||
|
ingestion?.supportsMetadataExtraction &&
|
||||||
|
pipelineType.push(PipelineType.Metadata);
|
||||||
|
ingestion?.supportsUsageExtraction &&
|
||||||
|
pipelineType.push(PipelineType.Usage);
|
||||||
|
|
||||||
return ingestionList.reduce((prev, curr) => {
|
return pipelineType.reduce((prev, curr) => {
|
||||||
const index = prev.indexOf(curr.pipelineType);
|
if (ingestionList.find((d) => d.pipelineType === curr)) {
|
||||||
if (index > -1) {
|
return prev;
|
||||||
prev.splice(index, 1);
|
} else {
|
||||||
}
|
return [...prev, curr];
|
||||||
|
}
|
||||||
|
}, [] as PipelineType[]);
|
||||||
|
}
|
||||||
|
|
||||||
return prev;
|
return [PipelineType.Metadata, PipelineType.Usage];
|
||||||
}, types);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTriggerIngestion = (id: string, displayName: string) => {
|
const handleTriggerIngestion = (id: string, displayName: string) => {
|
||||||
@ -111,59 +113,14 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdate = (ingestion: AirflowPipeline) => {
|
const handleUpdate = (ingestion: IngestionPipeline) => {
|
||||||
setUpdateSelection({
|
setUpdateSelection(ingestion);
|
||||||
id: ingestion.id as string,
|
setShowIngestionForm(true);
|
||||||
name: ingestion.name,
|
|
||||||
state: '',
|
|
||||||
ingestion: ingestion,
|
|
||||||
});
|
|
||||||
setIsUpdating(true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancelUpdate = () => {
|
const handleCancelUpdate = () => {
|
||||||
setUpdateSelection({
|
setUpdateSelection(undefined);
|
||||||
id: '',
|
setShowIngestionForm(false);
|
||||||
name: '',
|
|
||||||
state: '',
|
|
||||||
ingestion: {} as AirflowPipeline,
|
|
||||||
});
|
|
||||||
setIsUpdating(false);
|
|
||||||
};
|
|
||||||
const handleUpdateIngestion = (
|
|
||||||
data: AirflowPipeline,
|
|
||||||
triggerIngestion?: boolean
|
|
||||||
) => {
|
|
||||||
const { pipelineConfig } = updateSelection.ingestion;
|
|
||||||
const updatedData: AirflowPipeline = {
|
|
||||||
...updateSelection.ingestion,
|
|
||||||
pipelineConfig: {
|
|
||||||
...pipelineConfig,
|
|
||||||
config: {
|
|
||||||
...(pipelineConfig.config as ConfigClass),
|
|
||||||
|
|
||||||
...(data.pipelineConfig.config as ConfigClass),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
scheduleInterval: data.scheduleInterval,
|
|
||||||
};
|
|
||||||
setUpdateSelection((prev) => ({ ...prev, state: 'waiting' }));
|
|
||||||
updateIngestion(
|
|
||||||
updatedData as AirflowPipeline,
|
|
||||||
updateSelection.ingestion,
|
|
||||||
updateSelection.id,
|
|
||||||
updateSelection.name,
|
|
||||||
triggerIngestion
|
|
||||||
)
|
|
||||||
.then(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
setUpdateSelection((prev) => ({ ...prev, state: 'success' }));
|
|
||||||
handleCancelUpdate();
|
|
||||||
}, 500);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
handleCancelUpdate();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDelete = (id: string, displayName: string) => {
|
const handleDelete = (id: string, displayName: string) => {
|
||||||
@ -190,12 +147,12 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleAddIngestionClick = () => {
|
const handleAddIngestionClick = () => {
|
||||||
if (!getAirflowPipelineTypeOption().length) {
|
if (!getIngestionPipelineTypeOption().length) {
|
||||||
showInfoToast(
|
showInfoToast(
|
||||||
`${serviceName} already has all the supported ingestion jobs added.`
|
`${serviceName} already has all the supported ingestion jobs added.`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
setIsAdding(true);
|
setShowIngestionForm(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,53 +168,59 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
: ingestionList;
|
: ingestionList;
|
||||||
}, [searchText, ingestionList]);
|
}, [searchText, ingestionList]);
|
||||||
|
|
||||||
const getStatuses = (ingestion: AirflowPipeline) => {
|
/* eslint-disable max-len */
|
||||||
const lastFiveIngestions = ingestion.pipelineStatuses
|
// TODO:- once api support status we need below function
|
||||||
?.sort((a, b) => {
|
// const getStatuses = (ingestion: AirflowPipeline) => {
|
||||||
// Turn your strings into millis, and then subtract them
|
// const lastFiveIngestions = ingestion.pipelineStatuses
|
||||||
// to get a value that is either negative, positive, or zero.
|
// ?.sort((a, b) => {
|
||||||
const date1 = new Date(a.startDate || '');
|
// // Turn your strings into millis, and then subtract them
|
||||||
const date2 = new Date(b.startDate || '');
|
// // to get a value that is either negative, positive, or zero.
|
||||||
|
// const date1 = new Date(a.startDate || '');
|
||||||
|
// const date2 = new Date(b.startDate || '');
|
||||||
|
|
||||||
return date1.getTime() - date2.getTime();
|
// return date1.getTime() - date2.getTime();
|
||||||
})
|
// })
|
||||||
.slice(Math.max(ingestion.pipelineStatuses.length - 5, 0));
|
// .slice(Math.max(ingestion.pipelineStatuses.length - 5, 0));
|
||||||
|
|
||||||
return lastFiveIngestions?.map((r, i) => {
|
// return lastFiveIngestions?.map((r, i) => {
|
||||||
return (
|
// return (
|
||||||
<PopOver
|
// <PopOver
|
||||||
html={
|
// html={
|
||||||
<div className="tw-text-left">
|
// <div className="tw-text-left">
|
||||||
{r.startDate ? (
|
// {r.startDate ? (
|
||||||
<p>Start Date: {new Date(r.startDate).toUTCString()}</p>
|
// <p>Start Date: {new Date(r.startDate).toUTCString()}</p>
|
||||||
) : null}
|
// ) : null}
|
||||||
{r.endDate ? (
|
// {r.endDate ? (
|
||||||
<p>End Date: {new Date(r.endDate).toUTCString()}</p>
|
// <p>End Date: {new Date(r.endDate).toUTCString()}</p>
|
||||||
) : null}
|
// ) : null}
|
||||||
</div>
|
// </div>
|
||||||
}
|
// }
|
||||||
key={i}
|
// key={i}
|
||||||
position="bottom"
|
// position="bottom"
|
||||||
theme="light"
|
// theme="light"
|
||||||
trigger="mouseenter">
|
// trigger="mouseenter">
|
||||||
{i === lastFiveIngestions.length - 1 ? (
|
// {i === lastFiveIngestions.length - 1 ? (
|
||||||
<p
|
// <p
|
||||||
className={`tw-h-5 tw-w-16 tw-rounded-sm tw-bg-status-${r.state} tw-mr-1 tw-px-1 tw-text-white tw-text-center`}>
|
// className={`tw-h-5 tw-w-16 tw-rounded-sm tw-bg-status-${r.state} tw-mr-1 tw-px-1 tw-text-white tw-text-center`}>
|
||||||
{capitalize(r.state)}
|
// {capitalize(r.state)}
|
||||||
</p>
|
// </p>
|
||||||
) : (
|
// ) : (
|
||||||
<p
|
// <p
|
||||||
className={`tw-w-4 tw-h-5 tw-rounded-sm tw-bg-status-${r.state} tw-mr-1`}
|
// className={`tw-w-4 tw-h-5 tw-rounded-sm tw-bg-status-${r.state} tw-mr-1`}
|
||||||
/>
|
// />
|
||||||
)}
|
// )}
|
||||||
</PopOver>
|
// </PopOver>
|
||||||
);
|
// );
|
||||||
});
|
// });
|
||||||
};
|
// };
|
||||||
|
|
||||||
return (
|
/* eslint-enable max-len */
|
||||||
<Fragment>
|
|
||||||
<div className="tw-px-4" data-testid="ingestion-container">
|
const getIngestionTab = () => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="tw-px-4 tw-mt-4"
|
||||||
|
data-testid="ingestion-details-container">
|
||||||
<div className="tw-flex">
|
<div className="tw-flex">
|
||||||
{!isRequiredDetailsAvailable && (
|
{!isRequiredDetailsAvailable && (
|
||||||
<div className="tw-rounded tw-bg-error-lite tw-text-error tw-font-medium tw-px-4 tw-py-1 tw-mb-4 tw-flex tw-items-center tw-gap-1">
|
<div className="tw-rounded tw-bg-error-lite tw-text-error tw-font-medium tw-px-4 tw-py-1 tw-mb-4 tw-flex tw-items-center tw-gap-1">
|
||||||
@ -283,10 +246,12 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
position="bottom"
|
position="bottom"
|
||||||
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
title={TITLE_FOR_NON_ADMIN_ACTION}>
|
||||||
<Button
|
<Button
|
||||||
className={classNames('tw-h-8 tw-rounded tw-mb-2', {
|
className={classNames('tw-h-8 tw-rounded tw-mb-2')}
|
||||||
'tw-opacity-40': !isAdminUser && !isAuthDisabled,
|
|
||||||
})}
|
|
||||||
data-testid="add-new-ingestion-button"
|
data-testid="add-new-ingestion-button"
|
||||||
|
disabled={
|
||||||
|
getIngestionPipelineTypeOption().length === 0 ||
|
||||||
|
(!isAdminUser && !isAuthDisabled)
|
||||||
|
}
|
||||||
size="small"
|
size="small"
|
||||||
theme="primary"
|
theme="primary"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
@ -308,7 +273,6 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
<th className="tableHead-cell">Type</th>
|
<th className="tableHead-cell">Type</th>
|
||||||
<th className="tableHead-cell">Schedule</th>
|
<th className="tableHead-cell">Schedule</th>
|
||||||
<th className="tableHead-cell">Recent Runs</th>
|
<th className="tableHead-cell">Recent Runs</th>
|
||||||
{/* <th className="tableHead-cell">Next Run</th> */}
|
|
||||||
<th className="tableHead-cell">Actions</th>
|
<th className="tableHead-cell">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -323,30 +287,35 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
<td className="tableBody-cell">{ingestion.name}</td>
|
<td className="tableBody-cell">{ingestion.name}</td>
|
||||||
<td className="tableBody-cell">{ingestion.pipelineType}</td>
|
<td className="tableBody-cell">{ingestion.pipelineType}</td>
|
||||||
<td className="tableBody-cell">
|
<td className="tableBody-cell">
|
||||||
<PopOver
|
{ingestion.airflowConfig?.scheduleInterval ? (
|
||||||
html={
|
<PopOver
|
||||||
<div>
|
html={
|
||||||
{cronstrue.toString(
|
<div>
|
||||||
ingestion.scheduleInterval || '',
|
{cronstrue.toString(
|
||||||
{
|
ingestion.airflowConfig.scheduleInterval || '',
|
||||||
use24HourTimeFormat: true,
|
{
|
||||||
verbose: true,
|
use24HourTimeFormat: true,
|
||||||
}
|
verbose: true,
|
||||||
)}
|
}
|
||||||
</div>
|
)}
|
||||||
}
|
</div>
|
||||||
position="bottom"
|
}
|
||||||
theme="light"
|
position="bottom"
|
||||||
trigger="mouseenter">
|
theme="light"
|
||||||
<span>{ingestion.scheduleInterval}</span>
|
trigger="mouseenter">
|
||||||
</PopOver>
|
<span>
|
||||||
|
{ingestion.airflowConfig.scheduleInterval ?? '--'}
|
||||||
|
</span>
|
||||||
|
</PopOver>
|
||||||
|
) : (
|
||||||
|
<span>--</span>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="tableBody-cell">
|
<td className="tableBody-cell">
|
||||||
<div className="tw-flex">{getStatuses(ingestion)}</div>
|
{/* TODO:- update this once api support pipeline status */}
|
||||||
|
{/* <div className="tw-flex">{getStatuses(ingestion)}</div> */}
|
||||||
</td>
|
</td>
|
||||||
{/* <td className="tableBody-cell">
|
|
||||||
{ingestion.nextExecutionDate || '--'}
|
|
||||||
</td> */}
|
|
||||||
<td className="tableBody-cell">
|
<td className="tableBody-cell">
|
||||||
<NonAdminAction
|
<NonAdminAction
|
||||||
position="bottom"
|
position="bottom"
|
||||||
@ -376,15 +345,7 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
data-testid="edit"
|
data-testid="edit"
|
||||||
disabled={!isRequiredDetailsAvailable}
|
disabled={!isRequiredDetailsAvailable}
|
||||||
onClick={() => handleUpdate(ingestion)}>
|
onClick={() => handleUpdate(ingestion)}>
|
||||||
{updateSelection.id === ingestion.id ? (
|
Edit
|
||||||
updateSelection.state === 'success' ? (
|
|
||||||
<FontAwesomeIcon icon="check" />
|
|
||||||
) : (
|
|
||||||
<Loader size="small" type="default" />
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
'Edit'
|
|
||||||
)}
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="link-text tw-mr-2"
|
className="link-text tw-mr-2"
|
||||||
@ -436,68 +397,60 @@ const Ingestion: React.FC<Props> = ({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isAdding ? (
|
);
|
||||||
<IngestionModal
|
};
|
||||||
addIngestion={(data, triggerIngestion) => {
|
|
||||||
setIsAdding(false);
|
const getIngestionForm = () => {
|
||||||
addIngestion(data, triggerIngestion);
|
const type = getIngestionPipelineTypeOption();
|
||||||
}}
|
let heading = '';
|
||||||
header="Add Ingestion"
|
|
||||||
ingestionList={ingestionList}
|
if (isUndefined(updateSelection)) {
|
||||||
ingestionTypes={getAirflowPipelineTypeOption()}
|
heading = `Add ${capitalize(type[0])} Ingestion`;
|
||||||
name=""
|
} else {
|
||||||
service={serviceName}
|
heading = `Edit ${capitalize(updateSelection.pipelineType)} Ingestion`;
|
||||||
serviceList={serviceList.map((s) => ({
|
}
|
||||||
name: s.name,
|
|
||||||
serviceType: s.serviceType,
|
return (
|
||||||
}))}
|
<div className="tw-bg-white tw-pt-4 tw-w-full">
|
||||||
serviceType={serviceType}
|
<div className="tw-max-w-2xl tw-mx-auto tw-pb-6">
|
||||||
type=""
|
<AddIngestion
|
||||||
onCancel={() => setIsAdding(false)}
|
data={updateSelection}
|
||||||
/>
|
handleCancelClick={handleCancelUpdate}
|
||||||
) : null}
|
heading={heading}
|
||||||
{isUpdating ? (
|
pipelineType={type[0]}
|
||||||
<IngestionModal
|
serviceCategory={serviceCategory}
|
||||||
isUpdating
|
serviceData={serviceDetails}
|
||||||
header={<span>{`Edit ${updateSelection.name}`}</span>}
|
showSuccessScreen={false}
|
||||||
ingestionList={ingestionList}
|
status={
|
||||||
ingestionTypes={getAirflowPipelineTypes(serviceType) || []}
|
isUndefined(updateSelection)
|
||||||
selectedIngestion={updateSelection.ingestion}
|
? FormSubmitType.ADD
|
||||||
service={serviceName}
|
: FormSubmitType.EDIT
|
||||||
serviceList={serviceList.map((s) => ({
|
}
|
||||||
name: s.name,
|
onAddIngestionSave={addIngestion}
|
||||||
serviceType: s.serviceType,
|
onSuccessSave={handleCancelUpdate}
|
||||||
}))}
|
onUpdateIngestion={updateIngestion}
|
||||||
serviceType={serviceType}
|
/>
|
||||||
updateIngestion={(data, triggerIngestion) => {
|
</div>
|
||||||
setIsUpdating(false);
|
</div>
|
||||||
handleUpdateIngestion(data, triggerIngestion);
|
);
|
||||||
}}
|
};
|
||||||
onCancel={() => handleCancelUpdate()}
|
|
||||||
/>
|
return (
|
||||||
) : null}
|
<div data-testid="ingestion-container">
|
||||||
|
{showIngestionForm ? getIngestionForm() : getIngestionTab()}
|
||||||
|
|
||||||
{isConfirmationModalOpen && (
|
{isConfirmationModalOpen && (
|
||||||
<ConfirmationModal
|
<EntityDeleteModal
|
||||||
bodyText={`You want to delete ingestion ${deleteSelection.name} permanently? This action cannot be reverted.`}
|
entityName={deleteSelection.name}
|
||||||
cancelText="Discard"
|
entityType="ingestion"
|
||||||
confirmButtonCss="tw-bg-error hover:tw-bg-error focus:tw-bg-error"
|
loadingState={deleteSelection.state}
|
||||||
confirmText={
|
|
||||||
deleteSelection.state === 'waiting' ? (
|
|
||||||
<Loader size="small" type="white" />
|
|
||||||
) : deleteSelection.state === 'success' ? (
|
|
||||||
<FontAwesomeIcon icon="check" />
|
|
||||||
) : (
|
|
||||||
'Delete'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
header="Are you sure?"
|
|
||||||
onCancel={handleCancelConfirmationModal}
|
onCancel={handleCancelConfirmationModal}
|
||||||
onConfirm={() =>
|
onConfirm={() =>
|
||||||
handleDelete(deleteSelection.id, deleteSelection.name)
|
handleDelete(deleteSelection.id, deleteSelection.name)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Fragment>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,51 +15,82 @@ export const mockIngestionWorkFlow = {
|
|||||||
data: {
|
data: {
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
id: '3dae41fd-0469-483b-9d48-622577f2e075',
|
id: 'c804ec51-8fcf-4040-b830-5d967c4cbf49',
|
||||||
name: 'test1',
|
name: 'test3_metadata',
|
||||||
displayName: 'Test1',
|
displayName: 'test3_metadata',
|
||||||
|
pipelineType: 'metadata',
|
||||||
owner: {
|
owner: {
|
||||||
id: '360d5fd9-ba6b-4205-a92c-8eb98286c1c5',
|
id: 'fd96fdc7-a159-4802-84be-33c68d8b7e07',
|
||||||
type: 'user',
|
type: 'user',
|
||||||
name: 'Aaron Johnson',
|
name: 'anonymous',
|
||||||
href: 'http://localhost:8585/api/v1/users/360d5fd9-ba6b-4205-a92c-8eb98286c1c5',
|
fullyQualifiedName: 'anonymous',
|
||||||
|
deleted: false,
|
||||||
|
href: 'http://localhost:8585/api/v1/users/fd96fdc7-a159-4802-84be-33c68d8b7e07',
|
||||||
},
|
},
|
||||||
fullyQualifiedName: 'bigquery.test1',
|
fullyQualifiedName: 'test3.test3_metadata',
|
||||||
ingestionType: 'bigquery',
|
source: {
|
||||||
tags: [],
|
type: 'bigquery',
|
||||||
forceDeploy: true,
|
serviceName: 'test3',
|
||||||
pauseWorkflow: false,
|
serviceConnection: {
|
||||||
concurrency: 1,
|
config: {
|
||||||
startDate: '2021-11-24',
|
type: 'BigQuery',
|
||||||
endDate: '2022-11-25',
|
scheme: 'bigquery',
|
||||||
workflowTimezone: 'UTC',
|
hostPort: 'bigquery.googleapis.com',
|
||||||
retries: 1,
|
partitionField: '_PARTITIONTIME',
|
||||||
retryDelay: 300,
|
partitionQuery: 'select * from {}.{} WHERE {} = "{}" LIMIT 1000',
|
||||||
workflowCatchup: false,
|
tagCategoryName: 'BigqueryPolicyTags',
|
||||||
scheduleInterval: '0 12 * * *',
|
connectionOptions: {},
|
||||||
workflowTimeout: 60,
|
connectionArguments: {},
|
||||||
connectorConfig: {
|
enablePolicyTagImport: true,
|
||||||
username: 'test',
|
partitionQueryDuration: 1,
|
||||||
password: 'test',
|
supportsUsageExtraction: true,
|
||||||
host: 'http://localhost:3000/ingestion',
|
supportsMetadataExtraction: true,
|
||||||
database: 'mysql',
|
},
|
||||||
includeViews: true,
|
},
|
||||||
enableDataProfiler: false,
|
sourceConfig: {
|
||||||
includeFilterPattern: [],
|
config: {
|
||||||
excludeFilterPattern: [],
|
includeViews: false,
|
||||||
|
enableDataProfiler: true,
|
||||||
|
generateSampleData: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
openMetadataServerConnection: {
|
||||||
|
hostPort: 'http://localhost:8585/api',
|
||||||
|
authProvider: 'no-auth',
|
||||||
|
apiVersion: 'v1',
|
||||||
|
},
|
||||||
|
airflowConfig: {
|
||||||
|
forceDeploy: true,
|
||||||
|
pausePipeline: false,
|
||||||
|
concurrency: 1,
|
||||||
|
startDate: '2022-04-14',
|
||||||
|
endDate: '2022-04-14',
|
||||||
|
pipelineTimezone: 'UTC',
|
||||||
|
retries: 3,
|
||||||
|
retryDelay: 300,
|
||||||
|
pipelineCatchup: false,
|
||||||
|
scheduleInterval: '5 * * * *',
|
||||||
|
pipelineTimeout: 60,
|
||||||
|
maxActiveRuns: 1,
|
||||||
|
workflowTimeout: 60,
|
||||||
|
workflowDefaultView: 'tree',
|
||||||
|
workflowDefaultViewOrientation: 'LR',
|
||||||
},
|
},
|
||||||
ingestionStatuses: [],
|
|
||||||
service: {
|
service: {
|
||||||
id: 'e7e34bc7-fc12-40d6-9478-a6297cdefe7a',
|
id: 'c68e904a-4262-4b58-84c1-8a986b4aa47d',
|
||||||
type: 'databaseService',
|
type: 'databaseService',
|
||||||
name: 'bigquery',
|
name: 'test3',
|
||||||
description: 'BigQuery service used for shopify data',
|
fullyQualifiedName: 'test3',
|
||||||
href: 'http://localhost:8585/api/v1/services/databaseServices/e7e34bc7-fc12-40d6-9478-a6297cdefe7a',
|
description: '',
|
||||||
|
deleted: false,
|
||||||
|
href: 'http://localhost:8585/api/v1/services/databaseServices/c68e904a-4262-4b58-84c1-8a986b4aa47d',
|
||||||
},
|
},
|
||||||
href: 'http://localhost:8585/api/ingestion/3dae41fd-0469-483b-9d48-622577f2e075',
|
href: 'http://localhost:8585/api/v1/services/ingestionPipelines/c804ec51-8fcf-4040-b830-5d967c4cbf49',
|
||||||
version: 0.1,
|
version: 0.1,
|
||||||
updatedAt: 1637736180218,
|
updatedAt: 1649941364738,
|
||||||
updatedBy: 'anonymous',
|
updatedBy: 'anonymous',
|
||||||
|
deleted: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
paging: {
|
paging: {
|
||||||
@ -69,25 +100,37 @@ export const mockIngestionWorkFlow = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const mockService = {
|
export const mockService = {
|
||||||
data: {
|
id: 'c68e904a-4262-4b58-84c1-8a986b4aa47d',
|
||||||
data: [
|
name: 'test3',
|
||||||
{
|
serviceType: 'BigQuery',
|
||||||
id: 'e7e34bc7-fc12-40d6-9478-a6297cdefe7a',
|
description: '',
|
||||||
name: 'bigquery',
|
connection: {
|
||||||
serviceType: 'BigQuery',
|
config: {
|
||||||
description: 'BigQuery service used for shopify data',
|
type: 'BigQuery',
|
||||||
version: 0.1,
|
scheme: 'bigquery',
|
||||||
updatedAt: 1637734235276,
|
hostPort: 'bigquery.googleapis.com',
|
||||||
updatedBy: 'anonymous',
|
partitionField: '_PARTITIONTIME',
|
||||||
href: 'http://localhost:8585/api/v1/services/databaseServices/e7e34bc7-fc12-40d6-9478-a6297cdefe7a',
|
partitionQuery: 'select * from {}.{} WHERE {} = "{}" LIMIT 1000',
|
||||||
jdbc: {
|
tagCategoryName: 'BigqueryPolicyTags',
|
||||||
driverClass: 'jdbc',
|
connectionOptions: {},
|
||||||
connectionUrl: 'jdbc://localhost',
|
connectionArguments: {},
|
||||||
},
|
enablePolicyTagImport: true,
|
||||||
},
|
partitionQueryDuration: 1,
|
||||||
],
|
supportsUsageExtraction: true,
|
||||||
paging: {
|
supportsMetadataExtraction: true,
|
||||||
total: 1,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
version: 0.1,
|
||||||
|
updatedAt: 1649941355557,
|
||||||
|
updatedBy: 'anonymous',
|
||||||
|
owner: {
|
||||||
|
id: 'fd96fdc7-a159-4802-84be-33c68d8b7e07',
|
||||||
|
type: 'user',
|
||||||
|
name: 'anonymous',
|
||||||
|
fullyQualifiedName: 'anonymous',
|
||||||
|
deleted: false,
|
||||||
|
href: 'http://localhost:8585/api/v1/users/fd96fdc7-a159-4802-84be-33c68d8b7e07',
|
||||||
|
},
|
||||||
|
href: 'http://localhost:8585/api/v1/services/databaseServices/c68e904a-4262-4b58-84c1-8a986b4aa47d',
|
||||||
|
deleted: false,
|
||||||
};
|
};
|
||||||
|
@ -20,14 +20,15 @@ import {
|
|||||||
} from '@testing-library/react';
|
} from '@testing-library/react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { MemoryRouter } from 'react-router';
|
import { MemoryRouter } from 'react-router';
|
||||||
import { AirflowPipeline } from '../../generated/operations/pipelines/airflowPipeline';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
|
import { IngestionPipeline } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import Ingestion from './Ingestion.component';
|
import Ingestion from './Ingestion.component';
|
||||||
import { mockIngestionWorkFlow } from './Ingestion.mock';
|
import { mockIngestionWorkFlow, mockService } from './Ingestion.mock';
|
||||||
|
|
||||||
jest.mock('../../authentication/auth-provider/AuthProvider', () => {
|
jest.mock('../../authentication/auth-provider/AuthProvider', () => {
|
||||||
return {
|
return {
|
||||||
useAuthContext: jest.fn(() => ({
|
useAuthContext: jest.fn(() => ({
|
||||||
isAuthDisabled: false,
|
isAuthDisabled: true,
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
isProtectedRoute: jest.fn().mockReturnValue(true),
|
isProtectedRoute: jest.fn().mockReturnValue(true),
|
||||||
isTourRoute: jest.fn().mockReturnValue(false),
|
isTourRoute: jest.fn().mockReturnValue(false),
|
||||||
@ -73,16 +74,16 @@ jest.mock('../common/next-previous/NextPrevious', () => {
|
|||||||
return jest.fn().mockImplementation(() => <div>NextPrevious</div>);
|
return jest.fn().mockImplementation(() => <div>NextPrevious</div>);
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../IngestionModal/IngestionModal.component', () => {
|
jest.mock('../AddIngestion/AddIngestion.component', () => {
|
||||||
return jest
|
return jest
|
||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(() => (
|
.mockImplementation(() => (
|
||||||
<div data-testid="ingestion-modal">IngestionModal</div>
|
<div data-testid="ingestion-form">AddIngestion</div>
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
jest.mock('../Modals/ConfirmationModal/ConfirmationModal', () => {
|
jest.mock('../Modals/EntityDeleteModal/EntityDeleteModal', () => {
|
||||||
return jest.fn().mockImplementation(() => <div>ConfirmationModal</div>);
|
return jest.fn().mockImplementation(() => <div>EntityDeleteModal</div>);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Test Ingestion page', () => {
|
describe('Test Ingestion page', () => {
|
||||||
@ -94,10 +95,12 @@ describe('Test Ingestion page', () => {
|
|||||||
currrentPage={1}
|
currrentPage={1}
|
||||||
deleteIngestion={mockDeleteIngestion}
|
deleteIngestion={mockDeleteIngestion}
|
||||||
ingestionList={
|
ingestionList={
|
||||||
mockIngestionWorkFlow.data.data as unknown as AirflowPipeline[]
|
mockIngestionWorkFlow.data.data as unknown as IngestionPipeline[]
|
||||||
}
|
}
|
||||||
paging={mockPaging}
|
paging={mockPaging}
|
||||||
pagingHandler={mockPaginghandler}
|
pagingHandler={mockPaginghandler}
|
||||||
|
serviceCategory={ServiceCategory.DASHBOARD_SERVICES}
|
||||||
|
serviceDetails={mockService}
|
||||||
serviceList={[]}
|
serviceList={[]}
|
||||||
triggerIngestion={mockTriggerIngestion}
|
triggerIngestion={mockTriggerIngestion}
|
||||||
updateIngestion={mockFunction}
|
updateIngestion={mockFunction}
|
||||||
@ -127,15 +130,17 @@ describe('Test Ingestion page', () => {
|
|||||||
it('Table should render necessary fields', async () => {
|
it('Table should render necessary fields', async () => {
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<Ingestion
|
<Ingestion
|
||||||
|
isRequiredDetailsAvailable
|
||||||
addIngestion={mockFunction}
|
addIngestion={mockFunction}
|
||||||
currrentPage={1}
|
currrentPage={1}
|
||||||
deleteIngestion={mockDeleteIngestion}
|
deleteIngestion={mockDeleteIngestion}
|
||||||
ingestionList={
|
ingestionList={
|
||||||
mockIngestionWorkFlow.data.data as unknown as AirflowPipeline[]
|
mockIngestionWorkFlow.data.data as unknown as IngestionPipeline[]
|
||||||
}
|
}
|
||||||
isRequiredDetailsAvailable={false}
|
|
||||||
paging={mockPaging}
|
paging={mockPaging}
|
||||||
pagingHandler={mockPaginghandler}
|
pagingHandler={mockPaginghandler}
|
||||||
|
serviceCategory={ServiceCategory.DASHBOARD_SERVICES}
|
||||||
|
serviceDetails={mockService}
|
||||||
serviceList={[]}
|
serviceList={[]}
|
||||||
triggerIngestion={mockTriggerIngestion}
|
triggerIngestion={mockTriggerIngestion}
|
||||||
updateIngestion={mockFunction}
|
updateIngestion={mockFunction}
|
||||||
@ -179,15 +184,17 @@ describe('Test Ingestion page', () => {
|
|||||||
};
|
};
|
||||||
const { container } = render(
|
const { container } = render(
|
||||||
<Ingestion
|
<Ingestion
|
||||||
|
isRequiredDetailsAvailable
|
||||||
addIngestion={mockFunction}
|
addIngestion={mockFunction}
|
||||||
currrentPage={1}
|
currrentPage={1}
|
||||||
deleteIngestion={mockDeleteIngestion}
|
deleteIngestion={mockDeleteIngestion}
|
||||||
ingestionList={
|
ingestionList={
|
||||||
mockIngestionWorkFlow.data.data as unknown as AirflowPipeline[]
|
mockIngestionWorkFlow.data.data as unknown as IngestionPipeline[]
|
||||||
}
|
}
|
||||||
isRequiredDetailsAvailable={false}
|
|
||||||
paging={mockPagingAfter}
|
paging={mockPagingAfter}
|
||||||
pagingHandler={mockPaginghandler}
|
pagingHandler={mockPaginghandler}
|
||||||
|
serviceCategory={ServiceCategory.DASHBOARD_SERVICES}
|
||||||
|
serviceDetails={mockService}
|
||||||
serviceList={[]}
|
serviceList={[]}
|
||||||
triggerIngestion={mockTriggerIngestion}
|
triggerIngestion={mockTriggerIngestion}
|
||||||
updateIngestion={mockFunction}
|
updateIngestion={mockFunction}
|
||||||
@ -216,12 +223,13 @@ describe('Test Ingestion page', () => {
|
|||||||
currrentPage={1}
|
currrentPage={1}
|
||||||
deleteIngestion={mockDeleteIngestion}
|
deleteIngestion={mockDeleteIngestion}
|
||||||
ingestionList={
|
ingestionList={
|
||||||
mockIngestionWorkFlow.data.data as unknown as AirflowPipeline[]
|
mockIngestionWorkFlow.data.data as unknown as IngestionPipeline[]
|
||||||
}
|
}
|
||||||
paging={mockPagingAfter}
|
paging={mockPagingAfter}
|
||||||
pagingHandler={mockPaginghandler}
|
pagingHandler={mockPaginghandler}
|
||||||
|
serviceCategory={ServiceCategory.DASHBOARD_SERVICES}
|
||||||
|
serviceDetails={mockService}
|
||||||
serviceList={[]}
|
serviceList={[]}
|
||||||
serviceType="BigQuery"
|
|
||||||
triggerIngestion={mockTriggerIngestion}
|
triggerIngestion={mockTriggerIngestion}
|
||||||
updateIngestion={mockFunction}
|
updateIngestion={mockFunction}
|
||||||
/>,
|
/>,
|
||||||
@ -234,7 +242,7 @@ describe('Test Ingestion page', () => {
|
|||||||
const editButton = await findByTestId(container, 'edit');
|
const editButton = await findByTestId(container, 'edit');
|
||||||
fireEvent.click(editButton);
|
fireEvent.click(editButton);
|
||||||
|
|
||||||
const ingestionModal = await findByTestId(container, 'ingestion-modal');
|
const ingestionModal = await findByTestId(container, 'ingestion-form');
|
||||||
|
|
||||||
expect(ingestionModal).toBeInTheDocument();
|
expect(ingestionModal).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
@ -253,12 +261,13 @@ describe('Test Ingestion page', () => {
|
|||||||
currrentPage={1}
|
currrentPage={1}
|
||||||
deleteIngestion={mockDeleteIngestion}
|
deleteIngestion={mockDeleteIngestion}
|
||||||
ingestionList={
|
ingestionList={
|
||||||
mockIngestionWorkFlow.data.data as unknown as AirflowPipeline[]
|
mockIngestionWorkFlow.data.data as unknown as IngestionPipeline[]
|
||||||
}
|
}
|
||||||
paging={mockPagingAfter}
|
paging={mockPagingAfter}
|
||||||
pagingHandler={mockPaginghandler}
|
pagingHandler={mockPaginghandler}
|
||||||
|
serviceCategory={ServiceCategory.DASHBOARD_SERVICES}
|
||||||
|
serviceDetails={mockService}
|
||||||
serviceList={[]}
|
serviceList={[]}
|
||||||
serviceType="BigQuery"
|
|
||||||
triggerIngestion={mockTriggerIngestion}
|
triggerIngestion={mockTriggerIngestion}
|
||||||
updateIngestion={mockFunction}
|
updateIngestion={mockFunction}
|
||||||
/>,
|
/>,
|
||||||
@ -267,17 +276,6 @@ describe('Test Ingestion page', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// on click of add ingestion
|
|
||||||
const addIngestionButton = await findByTestId(
|
|
||||||
container,
|
|
||||||
'add-new-ingestion-button'
|
|
||||||
);
|
|
||||||
fireEvent.click(addIngestionButton);
|
|
||||||
|
|
||||||
const ingestionModal = await findByTestId(container, 'ingestion-modal');
|
|
||||||
|
|
||||||
expect(ingestionModal).toBeInTheDocument();
|
|
||||||
|
|
||||||
// on click of run button
|
// on click of run button
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
@ -293,7 +291,18 @@ describe('Test Ingestion page', () => {
|
|||||||
fireEvent.click(deleteButton);
|
fireEvent.click(deleteButton);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
await findByText(container, /ConfirmationModal/i)
|
await findByText(container, /EntityDeleteModal/i)
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
|
|
||||||
|
// on click of add ingestion
|
||||||
|
const addIngestionButton = await findByTestId(
|
||||||
|
container,
|
||||||
|
'add-new-ingestion-button'
|
||||||
|
);
|
||||||
|
fireEvent.click(addIngestionButton);
|
||||||
|
|
||||||
|
const ingestionModal = await findByTestId(container, 'ingestion-form');
|
||||||
|
|
||||||
|
expect(ingestionModal).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -11,11 +11,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { IngestionType } from '../../enums/service.enum';
|
import { IngestionType, ServiceCategory } from '../../enums/service.enum';
|
||||||
|
import { CreateIngestionPipeline } from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
||||||
import { DatabaseService } from '../../generated/entity/services/databaseService';
|
import { DatabaseService } from '../../generated/entity/services/databaseService';
|
||||||
import { AirflowPipeline } from '../../generated/operations/pipelines/airflowPipeline';
|
import {
|
||||||
|
Connection,
|
||||||
|
IngestionPipeline,
|
||||||
|
} from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
import { EntityReference } from '../../generated/type/entityReference';
|
import { EntityReference } from '../../generated/type/entityReference';
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
|
import { DataObj } from '../../interface/service.interface';
|
||||||
|
|
||||||
export interface ConnectorConfig {
|
export interface ConnectorConfig {
|
||||||
username: string;
|
username: string;
|
||||||
@ -48,23 +53,29 @@ export interface IngestionData {
|
|||||||
endDate?: string;
|
endDate?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Props {
|
export interface IngestionProps {
|
||||||
serviceType?: string;
|
serviceDetails: DataObj;
|
||||||
serviceName?: string;
|
serviceName?: string;
|
||||||
|
serviceCategory: ServiceCategory;
|
||||||
isRequiredDetailsAvailable: boolean;
|
isRequiredDetailsAvailable: boolean;
|
||||||
paging: Paging;
|
paging: Paging;
|
||||||
ingestionList: Array<AirflowPipeline>;
|
ingestionList: Array<IngestionPipeline>;
|
||||||
serviceList: Array<DatabaseService>;
|
serviceList: Array<DatabaseService>;
|
||||||
currrentPage: number;
|
currrentPage: number;
|
||||||
pagingHandler: (value: string | number, activePage?: number) => void;
|
pagingHandler: (value: string | number, activePage?: number) => void;
|
||||||
deleteIngestion: (id: string, displayName: string) => Promise<void>;
|
deleteIngestion: (id: string, displayName: string) => Promise<void>;
|
||||||
triggerIngestion: (id: string, displayName: string) => Promise<void>;
|
triggerIngestion: (id: string, displayName: string) => Promise<void>;
|
||||||
addIngestion: (data: AirflowPipeline, triggerIngestion?: boolean) => void;
|
addIngestion: (data: CreateIngestionPipeline) => Promise<void>;
|
||||||
updateIngestion: (
|
updateIngestion: (
|
||||||
data: AirflowPipeline,
|
data: IngestionPipeline,
|
||||||
oldData: AirflowPipeline,
|
oldData: IngestionPipeline,
|
||||||
id: string,
|
id: string,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
triggerIngestion?: boolean
|
triggerIngestion?: boolean
|
||||||
) => Promise<void>;
|
) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ModifiedConfig extends Connection {
|
||||||
|
supportsMetadataExtraction: boolean;
|
||||||
|
supportsUsageExtraction: boolean;
|
||||||
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { StepperStepType } from 'Models';
|
import { StepperStepType } from 'Models';
|
||||||
import { PatternType } from '../components/AddIngestion/addIngestion.interface';
|
import { FilterPattern } from '../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
|
|
||||||
export const STEPS_FOR_ADD_INGESTION: Array<StepperStepType> = [
|
export const STEPS_FOR_ADD_INGESTION: Array<StepperStepType> = [
|
||||||
{ name: 'Configure Ingestion', step: 1 },
|
{ name: 'Configure Ingestion', step: 1 },
|
||||||
@ -21,7 +21,7 @@ export const STEPS_FOR_ADD_INGESTION: Array<StepperStepType> = [
|
|||||||
|
|
||||||
export const INGESTION_SCHEDULER_INITIAL_VALUE = '5 * * * *';
|
export const INGESTION_SCHEDULER_INITIAL_VALUE = '5 * * * *';
|
||||||
|
|
||||||
export const INITIAL_FILTER_PATTERN: PatternType = {
|
export const INITIAL_FILTER_PATTERN: FilterPattern = {
|
||||||
include: [],
|
includes: [],
|
||||||
exclude: [],
|
excludes: [],
|
||||||
};
|
};
|
||||||
|
@ -26,7 +26,7 @@ import ServicePage from './index';
|
|||||||
jest.mock('../../authentication/auth-provider/AuthProvider', () => {
|
jest.mock('../../authentication/auth-provider/AuthProvider', () => {
|
||||||
return {
|
return {
|
||||||
useAuthContext: jest.fn(() => ({
|
useAuthContext: jest.fn(() => ({
|
||||||
isAuthDisabled: false,
|
isAuthDisabled: true,
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
isProtectedRoute: jest.fn().mockReturnValue(true),
|
isProtectedRoute: jest.fn().mockReturnValue(true),
|
||||||
isTourRoute: jest.fn().mockReturnValue(false),
|
isTourRoute: jest.fn().mockReturnValue(false),
|
||||||
@ -77,8 +77,8 @@ const mockDatabase = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
jest.mock('../../axiosAPIs/airflowPipelineAPI', () => ({
|
jest.mock('../../axiosAPIs/ingestionPipelineAPI', () => ({
|
||||||
getAirflowPipelines: jest.fn().mockImplementation(() =>
|
getIngestionPipelines: jest.fn().mockImplementation(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
data: {
|
data: {
|
||||||
data: [],
|
data: [],
|
||||||
@ -86,10 +86,10 @@ jest.mock('../../axiosAPIs/airflowPipelineAPI', () => ({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
deleteAirflowPipelineById: jest.fn(),
|
deleteIngestionPipelineById: jest.fn(),
|
||||||
addAirflowPipeline: jest.fn(),
|
addIngestionPipeline: jest.fn(),
|
||||||
triggerAirflowPipelineById: jest.fn(),
|
triggerIngestionPipelineById: jest.fn(),
|
||||||
updateAirflowPipeline: jest.fn(),
|
updateIngestionPipeline: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../axiosAPIs/serviceAPI', () => ({
|
jest.mock('../../axiosAPIs/serviceAPI', () => ({
|
||||||
|
@ -25,13 +25,6 @@ import React, { Fragment, FunctionComponent, useEffect, useState } from 'react';
|
|||||||
import { Link, useHistory, useParams } from 'react-router-dom';
|
import { Link, useHistory, useParams } from 'react-router-dom';
|
||||||
import AppState from '../../AppState';
|
import AppState from '../../AppState';
|
||||||
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
import { useAuthContext } from '../../authentication/auth-provider/AuthProvider';
|
||||||
import {
|
|
||||||
addAirflowPipeline,
|
|
||||||
deleteAirflowPipelineById,
|
|
||||||
getAirflowPipelines,
|
|
||||||
triggerAirflowPipelineById,
|
|
||||||
updateAirflowPipeline,
|
|
||||||
} from '../../axiosAPIs/airflowPipelineAPI';
|
|
||||||
import { getDashboards } from '../../axiosAPIs/dashboardAPI';
|
import { getDashboards } from '../../axiosAPIs/dashboardAPI';
|
||||||
import { getDatabases } from '../../axiosAPIs/databaseAPI';
|
import { getDatabases } from '../../axiosAPIs/databaseAPI';
|
||||||
import {
|
import {
|
||||||
@ -40,6 +33,13 @@ import {
|
|||||||
postFeedById,
|
postFeedById,
|
||||||
postThread,
|
postThread,
|
||||||
} from '../../axiosAPIs/feedsAPI';
|
} from '../../axiosAPIs/feedsAPI';
|
||||||
|
import {
|
||||||
|
addIngestionPipeline,
|
||||||
|
deleteIngestionPipelineById,
|
||||||
|
getIngestionPipelines,
|
||||||
|
triggerIngestionPipelineById,
|
||||||
|
updateIngestionPipeline,
|
||||||
|
} from '../../axiosAPIs/ingestionPipelineAPI';
|
||||||
import { getPipelines } from '../../axiosAPIs/pipelineAPI';
|
import { getPipelines } from '../../axiosAPIs/pipelineAPI';
|
||||||
import { getServiceByFQN, updateService } from '../../axiosAPIs/serviceAPI';
|
import { getServiceByFQN, updateService } from '../../axiosAPIs/serviceAPI';
|
||||||
import { getTopics } from '../../axiosAPIs/topicsAPI';
|
import { getTopics } from '../../axiosAPIs/topicsAPI';
|
||||||
@ -70,20 +70,17 @@ import { TabSpecificField } from '../../enums/entity.enum';
|
|||||||
import { SearchIndex } from '../../enums/search.enum';
|
import { SearchIndex } from '../../enums/search.enum';
|
||||||
import { ServiceCategory } from '../../enums/service.enum';
|
import { ServiceCategory } from '../../enums/service.enum';
|
||||||
import { CreateThread } from '../../generated/api/feed/createThread';
|
import { CreateThread } from '../../generated/api/feed/createThread';
|
||||||
|
import { CreateIngestionPipeline } from '../../generated/api/services/ingestionPipelines/createIngestionPipeline';
|
||||||
import { Dashboard } from '../../generated/entity/data/dashboard';
|
import { Dashboard } from '../../generated/entity/data/dashboard';
|
||||||
import { Database } from '../../generated/entity/data/database';
|
import { Database } from '../../generated/entity/data/database';
|
||||||
import { Pipeline } from '../../generated/entity/data/pipeline';
|
import { Pipeline } from '../../generated/entity/data/pipeline';
|
||||||
import { Topic } from '../../generated/entity/data/topic';
|
import { Topic } from '../../generated/entity/data/topic';
|
||||||
import { DatabaseService } from '../../generated/entity/services/databaseService';
|
import { DatabaseService } from '../../generated/entity/services/databaseService';
|
||||||
import {
|
import { IngestionPipeline } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline';
|
||||||
AirflowPipeline,
|
|
||||||
PipelineType,
|
|
||||||
Schema,
|
|
||||||
} from '../../generated/operations/pipelines/airflowPipeline';
|
|
||||||
import { EntityReference } from '../../generated/type/entityReference';
|
import { EntityReference } from '../../generated/type/entityReference';
|
||||||
import { Paging } from '../../generated/type/paging';
|
import { Paging } from '../../generated/type/paging';
|
||||||
import { useAuth } from '../../hooks/authHooks';
|
import { useAuth } from '../../hooks/authHooks';
|
||||||
import { ServiceDataObj } from '../../interface/service.interface';
|
import { DataObj, ServiceDataObj } from '../../interface/service.interface';
|
||||||
import jsonData from '../../jsons/en';
|
import jsonData from '../../jsons/en';
|
||||||
import {
|
import {
|
||||||
getEntityMissingError,
|
getEntityMissingError,
|
||||||
@ -101,7 +98,6 @@ import {
|
|||||||
getCurrentServiceTab,
|
getCurrentServiceTab,
|
||||||
getIsIngestionEnable,
|
getIsIngestionEnable,
|
||||||
getServiceCategoryFromType,
|
getServiceCategoryFromType,
|
||||||
isRequiredDetailsAvailableForIngestion,
|
|
||||||
servicePageTabs,
|
servicePageTabs,
|
||||||
serviceTypeLogo,
|
serviceTypeLogo,
|
||||||
} from '../../utils/ServiceUtils';
|
} from '../../utils/ServiceUtils';
|
||||||
@ -137,7 +133,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
const [isConnectionAvailable, setConnectionAvailable] =
|
const [isConnectionAvailable, setConnectionAvailable] =
|
||||||
useState<boolean>(true);
|
useState<boolean>(true);
|
||||||
const [isError, setIsError] = useState(false);
|
const [isError, setIsError] = useState(false);
|
||||||
const [ingestions, setIngestions] = useState<AirflowPipeline[]>([]);
|
const [ingestions, setIngestions] = useState<IngestionPipeline[]>([]);
|
||||||
const [serviceList] = useState<Array<DatabaseService>>([]);
|
const [serviceList] = useState<Array<DatabaseService>>([]);
|
||||||
const [ingestionPaging, setIngestionPaging] = useState<Paging>({} as Paging);
|
const [ingestionPaging, setIngestionPaging] = useState<Paging>({} as Paging);
|
||||||
const [entityThread, setEntityThread] = useState<EntityThread[]>([]);
|
const [entityThread, setEntityThread] = useState<EntityThread[]>([]);
|
||||||
@ -298,22 +294,9 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSchemaFromType = (type: AirflowPipeline['pipelineType']) => {
|
|
||||||
switch (type) {
|
|
||||||
case PipelineType.Metadata:
|
|
||||||
return Schema.DatabaseServiceMetadataPipeline;
|
|
||||||
|
|
||||||
case PipelineType.QueryUsage:
|
|
||||||
return Schema.DatabaseServiceQueryUsagePipeline;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const getAllIngestionWorkflows = (paging?: string) => {
|
const getAllIngestionWorkflows = (paging?: string) => {
|
||||||
setIsloading(true);
|
setIsloading(true);
|
||||||
getAirflowPipelines(['owner', 'pipelineStatuses'], serviceFQN, '', paging)
|
getIngestionPipelines(['owner'], serviceFQN, paging)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data.data) {
|
if (res.data.data) {
|
||||||
setIngestions(res.data.data);
|
setIngestions(res.data.data);
|
||||||
@ -339,7 +322,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
displayName: string
|
displayName: string
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
triggerAirflowPipelineById(id)
|
triggerIngestionPipelineById(id)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
resolve();
|
resolve();
|
||||||
@ -367,7 +350,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
displayName: string
|
displayName: string
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
deleteAirflowPipelineById(id)
|
deleteIngestionPipelineById(id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
resolve();
|
resolve();
|
||||||
getAllIngestionWorkflows();
|
getAllIngestionWorkflows();
|
||||||
@ -383,8 +366,8 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateIngestion = (
|
const updateIngestion = (
|
||||||
data: AirflowPipeline,
|
data: IngestionPipeline,
|
||||||
oldData: AirflowPipeline,
|
oldData: IngestionPipeline,
|
||||||
id: string,
|
id: string,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
triggerIngestion?: boolean
|
triggerIngestion?: boolean
|
||||||
@ -392,7 +375,7 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
const jsonPatch = compare(oldData, data);
|
const jsonPatch = compare(oldData, data);
|
||||||
|
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
updateAirflowPipeline(id, jsonPatch)
|
updateIngestionPipeline(id, jsonPatch)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
resolve();
|
resolve();
|
||||||
getAllIngestionWorkflows();
|
getAllIngestionWorkflows();
|
||||||
@ -415,55 +398,33 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const addIngestionWorkflowHandler = (
|
const onAddIngestionSave = (data: CreateIngestionPipeline) => {
|
||||||
data: AirflowPipeline,
|
return new Promise<void>((resolve, reject) => {
|
||||||
triggerIngestion?: boolean
|
return addIngestionPipeline(data)
|
||||||
) => {
|
.then((res: AxiosResponse) => {
|
||||||
setIsloading(true);
|
if (res.data) {
|
||||||
|
getAllIngestionWorkflows();
|
||||||
const ingestionData: AirflowPipeline = {
|
resolve();
|
||||||
...data,
|
} else {
|
||||||
pipelineConfig: {
|
showErrorToast(
|
||||||
...data.pipelineConfig,
|
jsonData['api-error-messages']['create-ingestion-error']
|
||||||
schema: getSchemaFromType(data.pipelineType),
|
);
|
||||||
},
|
reject();
|
||||||
service: {
|
|
||||||
id: serviceDetails?.id,
|
|
||||||
type: 'databaseService',
|
|
||||||
name: data.service.name,
|
|
||||||
} as EntityReference,
|
|
||||||
};
|
|
||||||
|
|
||||||
addAirflowPipeline(ingestionData)
|
|
||||||
.then((res: AxiosResponse) => {
|
|
||||||
if (res.data) {
|
|
||||||
const { id, displayName } = res.data;
|
|
||||||
setIsloading(false);
|
|
||||||
getAllIngestionWorkflows();
|
|
||||||
if (triggerIngestion) {
|
|
||||||
triggerIngestionById(id, displayName).catch((error: AxiosError) => {
|
|
||||||
showErrorToast(
|
|
||||||
error,
|
|
||||||
`${jsonData['api-error-messages']['triggering-ingestion-error']} ${displayName}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else {
|
})
|
||||||
showErrorToast(jsonData['api-error-messages']['add-ingestion-error']);
|
.catch((error: AxiosError) => {
|
||||||
}
|
const message = getErrorText(
|
||||||
})
|
error,
|
||||||
.catch((error: AxiosError) => {
|
jsonData['api-error-messages']['create-ingestion-error']
|
||||||
const message = getErrorText(
|
);
|
||||||
error,
|
if (message.includes('Connection refused')) {
|
||||||
jsonData['api-error-messages']['add-ingestion-error']
|
setConnectionAvailable(false);
|
||||||
);
|
} else {
|
||||||
if (message.includes('Connection refused')) {
|
showErrorToast(message);
|
||||||
setConnectionAvailable(false);
|
}
|
||||||
} else {
|
reject();
|
||||||
showErrorToast(message);
|
});
|
||||||
}
|
});
|
||||||
setIsloading(false);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleConfigUpdate = (
|
const handleConfigUpdate = (
|
||||||
@ -1208,24 +1169,20 @@ const ServicePage: FunctionComponent = () => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{activeTab === 3 && (
|
{activeTab === 3 && (
|
||||||
<div
|
<div data-testid="ingestion-container">
|
||||||
className="tw-mt-4 tw-px-1"
|
|
||||||
data-testid="ingestion-container">
|
|
||||||
{isConnectionAvailable ? (
|
{isConnectionAvailable ? (
|
||||||
<Ingestion
|
<Ingestion
|
||||||
addIngestion={addIngestionWorkflowHandler}
|
isRequiredDetailsAvailable
|
||||||
|
addIngestion={onAddIngestionSave}
|
||||||
currrentPage={ingestionCurrentPage}
|
currrentPage={ingestionCurrentPage}
|
||||||
deleteIngestion={deleteIngestionById}
|
deleteIngestion={deleteIngestionById}
|
||||||
ingestionList={ingestions}
|
ingestionList={ingestions}
|
||||||
isRequiredDetailsAvailable={isRequiredDetailsAvailableForIngestion(
|
|
||||||
serviceName as ServiceCategory,
|
|
||||||
serviceDetails as ServicesData
|
|
||||||
)}
|
|
||||||
paging={ingestionPaging}
|
paging={ingestionPaging}
|
||||||
pagingHandler={ingestionPagingHandler}
|
pagingHandler={ingestionPagingHandler}
|
||||||
|
serviceCategory={serviceName as ServiceCategory}
|
||||||
|
serviceDetails={serviceDetails as DataObj}
|
||||||
serviceList={serviceList}
|
serviceList={serviceList}
|
||||||
serviceName={serviceFQN}
|
serviceName={serviceFQN}
|
||||||
serviceType={serviceDetails?.serviceType}
|
|
||||||
triggerIngestion={triggerIngestionById}
|
triggerIngestion={triggerIngestionById}
|
||||||
updateIngestion={updateIngestion}
|
updateIngestion={updateIngestion}
|
||||||
/>
|
/>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user