diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/AddIngestion.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/AddIngestion.component.tsx index da5c11712e1..1dc4d2d1e51 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/AddIngestion.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/AddIngestion.component.tsx @@ -12,6 +12,7 @@ */ import { isEmpty, isUndefined } from 'lodash'; +import { LoadingState } from 'Models'; import React, { useMemo, useState } from 'react'; import { INGESTION_SCHEDULER_INITIAL_VALUE, @@ -31,6 +32,7 @@ import { IngestionPipeline, } from '../../generated/entity/services/ingestionPipelines/ingestionPipeline'; import { getCurrentDate, getCurrentUserId } from '../../utils/CommonUtils'; +import { getIngestionName } from '../../utils/ServiceUtils'; import SuccessScreen from '../common/success-screen/SuccessScreen'; import IngestionStepper from '../IngestionStepper/IngestionStepper.component'; import { AddIngestionProps } from './addIngestion.interface'; @@ -53,9 +55,11 @@ const AddIngestion = ({ handleCancelClick, handleViewServiceClick, }: AddIngestionProps) => { - const [ingestionName] = useState( - data?.name ?? `${serviceData.name}_${pipelineType}` + const [saveState, setSaveState] = useState('initial'); + const [ingestionName, setIngestionName] = useState( + data?.name ?? getIngestionName(serviceData.name, pipelineType) ); + const [description, setDescription] = useState(data?.description ?? ''); const [repeatFrequency, setRepeatFrequency] = useState( data?.airflowConfig.scheduleInterval ?? INGESTION_SCHEDULER_INITIAL_VALUE ); @@ -89,6 +93,11 @@ const AddIngestion = ({ (data?.source.sourceConfig.config as ConfigClass)?.chartFilterPattern ) ); + const [showFqnFilter, setShowFqnFilter] = useState( + !isUndefined( + (data?.source.sourceConfig.config as ConfigClass)?.fqnFilterPattern + ) + ); const [includeView, setIncludeView] = useState( Boolean((data?.source.sourceConfig.config as ConfigClass)?.includeViews) ); @@ -121,6 +130,10 @@ const AddIngestion = ({ (data?.source.sourceConfig.config as ConfigClass)?.chartFilterPattern ?? INITIAL_FILTER_PATTERN ); + const [fqnFilterPattern, setFqnFilterPattern] = useState( + (data?.source.sourceConfig.config as ConfigClass)?.fqnFilterPattern ?? + INITIAL_FILTER_PATTERN + ); const [queryLogDuration, setQueryLogDuration] = useState( (data?.source.sourceConfig.config as ConfigClass)?.queryLogDuration ?? 1 @@ -138,6 +151,12 @@ const AddIngestion = ({ ConfigType.DatabaseUsage ); }, [data]); + const profilerIngestionType = useMemo(() => { + return ( + (data?.source.sourceConfig.config as ConfigClass)?.type ?? + ConfigType.Profiler + ); + }, [data]); const getIncludeValue = (value: Array, type: FilterPatternEnum) => { switch (type) { @@ -163,6 +182,10 @@ const AddIngestion = ({ case FilterPatternEnum.CHART: setChartFilterPattern({ ...topicFilterPattern, includes: value }); + break; + case FilterPatternEnum.FQN: + setFqnFilterPattern({ ...fqnFilterPattern, includes: value }); + break; } }; @@ -190,6 +213,10 @@ const AddIngestion = ({ case FilterPatternEnum.CHART: setChartFilterPattern({ ...topicFilterPattern, excludes: value }); + break; + case FilterPatternEnum.FQN: + setFqnFilterPattern({ ...fqnFilterPattern, excludes: value }); + break; } }; @@ -215,6 +242,10 @@ const AddIngestion = ({ case FilterPatternEnum.CHART: setShowChartFilter(value); + break; + case FilterPatternEnum.FQN: + setShowFqnFilter(value); + break; } }; @@ -246,6 +277,38 @@ const AddIngestion = ({ return filterPattern; }; + const getConfigData = (type: PipelineType): ConfigClass => { + switch (type) { + case PipelineType.Usage: { + return { + queryLogDuration, + resultLimit, + stageFileLocation, + type: usageIngestionType, + }; + } + case PipelineType.Profiler: { + return { + fqnFilterPattern: getFilterPatternData(fqnFilterPattern), + type: profilerIngestionType, + }; + } + case PipelineType.Metadata: + default: { + return { + enableDataProfiler: enableDataProfiler, + generateSampleData: ingestSampleData, + includeViews: includeView, + schemaFilterPattern: getFilterPatternData(schemaFilterPattern), + tableFilterPattern: getFilterPatternData(tableFilterPattern), + chartFilterPattern: getFilterPatternData(chartFilterPattern), + dashboardFilterPattern: getFilterPatternData(dashboardFilterPattern), + topicFilterPattern: getFilterPatternData(topicFilterPattern), + }; + } + } + }; + const createNewIngestion = () => { const ingestionDetails: CreateIngestionPipeline = { airflowConfig: { @@ -266,37 +329,23 @@ const AddIngestion = ({ type: serviceCategory.slice(0, -1), }, sourceConfig: { - config: - pipelineType === PipelineType.Usage - ? { - queryLogDuration, - resultLimit, - stageFileLocation, - type: usageIngestionType, - } - : { - enableDataProfiler: enableDataProfiler, - generateSampleData: ingestSampleData, - includeViews: includeView, - schemaFilterPattern: getFilterPatternData(schemaFilterPattern), - tableFilterPattern: getFilterPatternData(tableFilterPattern), - chartFilterPattern: getFilterPatternData(chartFilterPattern), - dashboardFilterPattern: getFilterPatternData( - dashboardFilterPattern - ), - topicFilterPattern: getFilterPatternData(topicFilterPattern), - }, + config: getConfigData(pipelineType), }, }; - onAddIngestionSave && - onAddIngestionSave(ingestionDetails).then(() => { - if (showSuccessScreen) { - setActiveIngestionStep(3); - } else { - onSuccessSave?.(); - } - }); + if (onAddIngestionSave) { + setSaveState('waiting'); + onAddIngestionSave(ingestionDetails) + .then(() => { + setSaveState('success'); + if (showSuccessScreen) { + setActiveIngestionStep(3); + } else { + onSuccessSave?.(); + } + }) + .finally(() => setTimeout(() => setSaveState('initial'), 500)); + } }; const updateIngestion = () => { @@ -314,40 +363,25 @@ const AddIngestion = ({ sourceConfig: { config: { ...(data.source.sourceConfig.config as ConfigClass), - ...(pipelineType === PipelineType.Usage - ? { - queryLogDuration, - resultLimit, - stageFileLocation, - type: usageIngestionType, - } - : { - enableDataProfiler: enableDataProfiler, - generateSampleData: ingestSampleData, - includeViews: includeView, - schemaFilterPattern: - getFilterPatternData(schemaFilterPattern), - tableFilterPattern: - getFilterPatternData(tableFilterPattern), - chartFilterPattern: - getFilterPatternData(chartFilterPattern), - dashboardFilterPattern: getFilterPatternData( - dashboardFilterPattern - ), - topicFilterPattern: - getFilterPatternData(topicFilterPattern), - }), + ...getConfigData(pipelineType), }, }, }, }; - onUpdateIngestion && - onUpdateIngestion(updatedData, data, data.id as string, data.name).then( - () => { - onSuccessSave?.(); - } - ); + if (onUpdateIngestion) { + setSaveState('waiting'); + onUpdateIngestion(updatedData, data, data.id as string, data.name) + .then(() => { + setSaveState('success'); + if (showSuccessScreen) { + setActiveIngestionStep(3); + } else { + onSuccessSave?.(); + } + }) + .finally(() => setTimeout(() => setSaveState('initial'), 500)); + } } }; @@ -375,14 +409,18 @@ const AddIngestion = ({ setDescription(val)} handleEnableDataProfiler={() => setEnableDataProfiler((pre) => !pre) } handleIncludeView={() => setIncludeView((pre) => !pre)} handleIngestSampleData={() => setIngestSampleData((pre) => !pre)} + handleIngestionName={(val) => setIngestionName(val)} handleQueryLogDuration={(val) => setQueryLogDuration(val)} handleResultLimit={(val) => setResultLimit(val)} handleShowFilter={handleShowFilter} @@ -397,6 +435,7 @@ const AddIngestion = ({ serviceCategory={serviceCategory} showChartFilter={showChartFilter} showDashboardFilter={showDashboardFilter} + showFqnFilter={showFqnFilter} showSchemaFilter={showSchemaFilter} showTableFilter={showTableFilter} showTopicFilter={showTopicFilter} @@ -418,8 +457,9 @@ const AddIngestion = ({ handleStartDateChange={(value: string) => setStartDate(value)} repeatFrequency={repeatFrequency} startDate={startDate as string} + status={saveState} onBack={handleScheduleIntervalBackClick} - onDeloy={handleScheduleIntervalDeployClick} + onDeploy={handleScheduleIntervalDeployClick} /> )} diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.test.tsx index 67a209eca5e..96a11d8feeb 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.test.tsx @@ -50,6 +50,10 @@ const mockConfigureIngestion: ConfigureIngestionProps = { includes: [], excludes: [], }, + fqnFilterPattern: { + includes: [], + excludes: [], + }, includeView: false, pipelineType: PipelineType.Metadata, queryLogDuration: 1, @@ -62,7 +66,9 @@ const mockConfigureIngestion: ConfigureIngestionProps = { showTableFilter: false, showTopicFilter: false, showChartFilter: false, + showFqnFilter: false, handleIncludeView: jest.fn(), + handleIngestionName: jest.fn(), handleEnableDataProfiler: jest.fn(), handleIngestSampleData: jest.fn(), handleQueryLogDuration: jest.fn(), diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.tsx index 1e074825f7c..3851424c0d4 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ConfigureIngestion.tsx @@ -11,23 +11,28 @@ * limitations under the License. */ -import React, { Fragment } from 'react'; +import { EditorContentRef } from 'Models'; +import React, { Fragment, useRef } from 'react'; import { FilterPatternEnum } from '../../../enums/filterPattern.enum'; import { ServiceCategory } from '../../../enums/service.enum'; import { PipelineType } from '../../../generated/entity/services/ingestionPipelines/ingestionPipeline'; import { getSeparator } from '../../../utils/CommonUtils'; import { Button } from '../../buttons/Button/Button'; import FilterPattern from '../../common/FilterPattern/FilterPattern'; +import RichTextEditor from '../../common/rich-text-editor/RichTextEditor'; import ToggleSwitchV1 from '../../common/toggle-switch/ToggleSwitchV1'; import { Field } from '../../Field/Field'; import { ConfigureIngestionProps } from '../addIngestion.interface'; const ConfigureIngestion = ({ + ingestionName, + description = '', dashboardFilterPattern, schemaFilterPattern, tableFilterPattern, topicFilterPattern, chartFilterPattern, + fqnFilterPattern, includeView, serviceCategory, enableDataProfiler, @@ -38,11 +43,14 @@ const ConfigureIngestion = ({ showTableFilter, showTopicFilter, showChartFilter, + showFqnFilter, queryLogDuration, stageFileLocation, resultLimit, getExcludeValue, getIncludeValue, + handleIngestionName, + handleDescription, handleShowFilter, handleEnableDataProfiler, handleIncludeView, @@ -53,7 +61,9 @@ const ConfigureIngestion = ({ onCancel, onNext, }: ConfigureIngestionProps) => { - const getFilterPatternField = () => { + const markdownRef = useRef(); + + const getMetadataFilterPatternField = () => { switch (serviceCategory) { case ServiceCategory.DATABASE_SERVICES: return ( @@ -132,10 +142,27 @@ const ConfigureIngestion = ({ } }; + const getProfilerFilterPatternField = () => { + return ( + + + handleShowFilter(value, FilterPatternEnum.FQN) + } + includePattern={fqnFilterPattern?.includes ?? []} + type={FilterPatternEnum.FQN} + /> + + ); + }; const getMetadataFields = () => { return ( <> -
{getFilterPatternField()}
+
{getMetadataFilterPatternField()}
{getSeparator('')}
@@ -252,14 +279,72 @@ const ConfigureIngestion = ({ ); }; + const getProfilerFields = () => { + return ( + <> +
+ + +

+ Name that identifies this pipeline instance uniquely. +

+ handleIngestionName(e.target.value)} + /> + {getSeparator('')} +
+
+
{getProfilerFilterPatternField()}
+ {getSeparator('')} +
+ + +

+ Description of the pipeline. +

+ + {getSeparator('')} +
+
+ + ); + }; + const getIngestionPipelineFields = () => { - if (pipelineType === PipelineType.Usage) { - return getUsageFields(); - } else { - return getMetadataFields(); + switch (pipelineType) { + case PipelineType.Usage: { + return getUsageFields(); + } + case PipelineType.Profiler: { + return getProfilerFields(); + } + case PipelineType.Metadata: + default: { + return getMetadataFields(); + } } }; + const handleNext = () => { + handleDescription && + handleDescription(markdownRef.current?.getEditorContent() || ''); + onNext(); + }; + return (
{getIngestionPipelineFields()} @@ -280,7 +365,7 @@ const ConfigureIngestion = ({ size="regular" theme="primary" variant="contained" - onClick={onNext}> + onClick={handleNext}> Next diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.test.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.test.tsx index 50434215ca7..25f7efcfe36 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.test.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.test.tsx @@ -27,6 +27,7 @@ jest.mock('../../common/toggle-switch/ToggleSwitchV1', () => { }); const mockScheduleIntervalProps: ScheduleIntervalProps = { + status: 'initial', repeatFrequency: '', handleRepeatFrequencyChange: jest.fn(), startDate: '', @@ -34,7 +35,7 @@ const mockScheduleIntervalProps: ScheduleIntervalProps = { endDate: '', handleEndDateChange: jest.fn(), onBack: jest.fn(), - onDeloy: jest.fn(), + onDeploy: jest.fn(), }; describe('Test ScheduleInterval component', () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.tsx b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.tsx index 938fa456cd8..c773d71ad1e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/Steps/ScheduleInterval.tsx @@ -11,13 +11,16 @@ * limitations under the License. */ +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React from 'react'; import { Button } from '../../buttons/Button/Button'; import CronEditor from '../../common/CronEditor/CronEditor'; import { Field } from '../../Field/Field'; +import Loader from '../../Loader/Loader'; import { ScheduleIntervalProps } from '../addIngestion.interface'; const ScheduleInterval = ({ + status, repeatFrequency, handleRepeatFrequencyChange, startDate, @@ -25,7 +28,7 @@ const ScheduleInterval = ({ endDate, handleEndDateChange, onBack, - onDeloy, + onDeploy, }: ScheduleIntervalProps) => { return (
@@ -75,14 +78,34 @@ const ScheduleInterval = ({ Back - + {status === 'waiting' ? ( + + ) : status === 'success' ? ( + + ) : ( + + )}
); diff --git a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/addIngestion.interface.ts b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/addIngestion.interface.ts index 9b2326fbcf6..ffc5cbaf790 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/addIngestion.interface.ts +++ b/openmetadata-ui/src/main/resources/ui/src/components/AddIngestion/addIngestion.interface.ts @@ -11,6 +11,7 @@ * limitations under the License. */ +import { LoadingState } from 'Models'; import { FilterPatternEnum } from '../../enums/filterPattern.enum'; import { FormSubmitType } from '../../enums/form.enum'; import { ServiceCategory } from '../../enums/service.enum'; @@ -47,12 +48,14 @@ export interface AddIngestionProps { export interface ConfigureIngestionProps { ingestionName: string; + description?: string; serviceCategory: ServiceCategory; dashboardFilterPattern: FilterPattern; schemaFilterPattern: FilterPattern; tableFilterPattern: FilterPattern; topicFilterPattern: FilterPattern; chartFilterPattern: FilterPattern; + fqnFilterPattern: FilterPattern; includeView: boolean; enableDataProfiler: boolean; ingestSampleData: boolean; @@ -62,9 +65,12 @@ export interface ConfigureIngestionProps { showTableFilter: boolean; showTopicFilter: boolean; showChartFilter: boolean; + showFqnFilter: boolean; queryLogDuration: number; stageFileLocation: string; resultLimit: number; + handleIngestionName: (value: string) => void; + handleDescription?: (value: string) => void; handleIncludeView: () => void; handleEnableDataProfiler: () => void; handleIngestSampleData: () => void; @@ -79,6 +85,7 @@ export interface ConfigureIngestionProps { } export type ScheduleIntervalProps = { + status: LoadingState; repeatFrequency: string; handleRepeatFrequencyChange: (value: string) => void; startDate: string; @@ -86,5 +93,5 @@ export type ScheduleIntervalProps = { endDate: string; handleEndDateChange: (value: string) => void; onBack: () => void; - onDeloy: () => void; + onDeploy: () => void; }; diff --git a/openmetadata-ui/src/main/resources/ui/src/components/Ingestion/Ingestion.component.tsx b/openmetadata-ui/src/main/resources/ui/src/components/Ingestion/Ingestion.component.tsx index 5c136b5b150..e9377e8c31e 100644 --- a/openmetadata-ui/src/main/resources/ui/src/components/Ingestion/Ingestion.component.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/components/Ingestion/Ingestion.component.tsx @@ -15,8 +15,8 @@ import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import classNames from 'classnames'; import cronstrue from 'cronstrue'; -import { capitalize, isNil, lowerCase } from 'lodash'; -import React, { useCallback, useState } from 'react'; +import { capitalize, isNil, lowerCase, startCase } from 'lodash'; +import React, { Fragment, useCallback, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { useAuthContext } from '../../authentication/auth-provider/AuthProvider'; import { @@ -33,13 +33,14 @@ import { getAddIngestionPath, getEditIngestionPath, } from '../../utils/RouterUtils'; +import { dropdownIcon as DropdownIcon } from '../../utils/svgconstant'; import SVGIcons, { Icons } from '../../utils/SvgUtils'; -import { showInfoToast } from '../../utils/ToastUtils'; import { Button } from '../buttons/Button/Button'; import NextPrevious from '../common/next-previous/NextPrevious'; import NonAdminAction from '../common/non-admin-action/NonAdminAction'; import PopOver from '../common/popover/PopOver'; import Searchbar from '../common/searchbar/Searchbar'; +import DropDownList from '../dropdown/DropDownList'; import Loader from '../Loader/Loader'; import EntityDeleteModal from '../Modals/EntityDeleteModal/EntityDeleteModal'; import { IngestionProps, ModifiedConfig } from './ingestion.interface'; @@ -61,6 +62,7 @@ const Ingestion: React.FC = ({ const { isAdminUser } = useAuth(); const { isAuthDisabled } = useAuthContext(); const [searchText, setSearchText] = useState(''); + const [showActions, setShowActions] = useState(false); const [currTriggerId, setCurrTriggerId] = useState({ id: '', state: '' }); const [currDeployId, setCurrDeployId] = useState({ id: '', state: '' }); const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false); @@ -84,9 +86,13 @@ const Ingestion: React.FC = ({ pipelineType.push(PipelineType.Metadata); ingestion?.supportsUsageExtraction && pipelineType.push(PipelineType.Usage); + ingestion?.supportsProfiler && pipelineType.push(PipelineType.Profiler); return pipelineType.reduce((prev, curr) => { - if (ingestionList.find((d) => d.pipelineType === curr)) { + if ( + curr !== PipelineType.Profiler && + ingestionList.find((d) => d.pipelineType === curr) + ) { return prev; } else { return [...prev, curr]; @@ -94,7 +100,7 @@ const Ingestion: React.FC = ({ }, [] as PipelineType[]); } - return [PipelineType.Metadata, PipelineType.Usage]; + return [PipelineType.Metadata, PipelineType.Usage, PipelineType.Profiler]; }; const handleTriggerIngestion = (id: string, displayName: string) => { @@ -160,57 +166,84 @@ const Ingestion: React.FC = ({ setIsConfirmationModalOpen(true); }; - const handleAddIngestionClick = () => { - const types = getIngestionPipelineTypeOption(); - if (!types.length) { - showInfoToast( - `${serviceName} already has all the supported ingestion jobs added.` - ); - } else { - history.push(getAddIngestionPath(serviceCategory, serviceName, types[0])); + const handleAddIngestionClick = (type?: PipelineType) => { + setShowActions(false); + if (type) { + history.push(getAddIngestionPath(serviceCategory, serviceName, type)); } }; - const getAddIngestionButton = () => { - const types = getIngestionPipelineTypeOption(); - let buttonText; + const getAddIngestionButton = (type: PipelineType) => { + return ( + + ); + }; - switch (types[0]) { - case PipelineType.Metadata: { - buttonText = 'Add Metadata Ingestion'; - - break; - } - case PipelineType.Usage: { - buttonText = 'Add Usage Ingestion'; - - break; - } - case PipelineType.Profiler: - default: { - buttonText = ''; - - break; - } - } - - return buttonText ? ( - + const getAddIngestionDropdown = (types: PipelineType[]) => { + return ( + - - ) : null; + {showActions && ( + ({ + name: `Add ${startCase(type)} Ingestion`, + value: type, + }))} + onSelect={(_e, value) => + handleAddIngestionClick(value as PipelineType) + } + /> + )} + + ); + }; + + const getAddIngestionElement = () => { + const types = getIngestionPipelineTypeOption(); + let element: JSX.Element | null = null; + + if (types.length) { + if (types[0] === PipelineType.Metadata || types.length === 1) { + element = getAddIngestionButton(types[0]); + } else { + element = getAddIngestionDropdown(types); + } + } + + return element; }; const getSearchedIngestions = useCallback(() => { @@ -324,7 +357,7 @@ const Ingestion: React.FC = ({
)}
-
+
{searchText || getSearchedIngestions().length > 0 ? ( = ({ /> ) : null}
-
- {isRequiredDetailsAvailable && getAddIngestionButton()} +
+ {isRequiredDetailsAvailable && + (isAdminUser || isAuthDisabled) && + getAddIngestionElement()}
{getSearchedIngestions().length ? ( diff --git a/openmetadata-ui/src/main/resources/ui/src/enums/filterPattern.enum.ts b/openmetadata-ui/src/main/resources/ui/src/enums/filterPattern.enum.ts index 03944c818e5..e625af7543f 100644 --- a/openmetadata-ui/src/main/resources/ui/src/enums/filterPattern.enum.ts +++ b/openmetadata-ui/src/main/resources/ui/src/enums/filterPattern.enum.ts @@ -17,4 +17,5 @@ export enum FilterPatternEnum { CHART = 'chart', DASHBOARD = 'dashboard', TOPIC = 'topic', + FQN = 'fqn', } diff --git a/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx b/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx index fc9c77ec849..735a2edd860 100644 --- a/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/pages/service/index.tsx @@ -210,6 +210,25 @@ const ServicePage: FunctionComponent = () => { } }; + const getAirflowEndpoint = () => { + fetchAirflowConfig() + .then((res) => { + if (res.data?.apiEndpoint) { + setAirflowEndpoint(res.data.apiEndpoint); + } else { + setAirflowEndpoint(''); + + throw jsonData['api-error-messages']['unexpected-server-response']; + } + }) + .catch((err: AxiosError) => { + showErrorToast( + err, + jsonData['api-error-messages']['fetch-airflow-config-error'] + ); + }); + }; + const getAllIngestionWorkflows = (paging?: string) => { setIsloading(true); getIngestionPipelines(['owner', 'pipelineStatuses'], serviceFQN, paging) @@ -230,25 +249,11 @@ const ServicePage: FunctionComponent = () => { jsonData['api-error-messages']['fetch-ingestion-error'] ); }) - .finally(() => setIsloading(false)); - }; - - const getAirflowEndpoint = () => { - fetchAirflowConfig() - .then((res) => { - if (res.data?.apiEndpoint) { - setAirflowEndpoint(res.data.apiEndpoint); - } else { - setAirflowEndpoint(''); - - throw jsonData['api-error-messages']['unexpected-server-response']; + .finally(() => { + setIsloading(false); + if (!airflowEndpoint) { + getAirflowEndpoint(); } - }) - .catch((err: AxiosError) => { - showErrorToast( - err, - jsonData['api-error-messages']['fetch-airflow-config-error'] - ); }); }; @@ -678,7 +683,6 @@ const ServicePage: FunctionComponent = () => { // getDatabaseServices(); getAllIngestionWorkflows(); } - getAirflowEndpoint(); }, []); const onCancel = () => { diff --git a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx index edf042359c5..ffdf3b2d861 100644 --- a/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx +++ b/openmetadata-ui/src/main/resources/ui/src/utils/ServiceUtils.tsx @@ -12,6 +12,7 @@ */ import { AxiosResponse } from 'axios'; +import cryptoRandomString from 'crypto-random-string-with-promisify-polyfill'; import { Bucket, DynamicFormFieldType, @@ -543,3 +544,17 @@ export const getServiceIngestionStepGuide = ( ); }; + +export const getIngestionName = ( + serviceName: string, + type: IngestionPipelineType +) => { + if (type === IngestionPipelineType.Profiler) { + return `${serviceName}_${type}_${cryptoRandomString({ + length: 8, + type: 'alphanumeric', + })}`; + } else { + return `${serviceName}_${type}`; + } +};