2022-08-19 15:58:31 -04:00
|
|
|
import { PlusOutlined, RedoOutlined } from '@ant-design/icons';
|
2022-08-16 19:01:26 -04:00
|
|
|
import React, { useCallback, useEffect, useState } from 'react';
|
2023-12-26 16:30:24 +05:30
|
|
|
import { debounce } from 'lodash';
|
2022-05-16 13:24:56 -07:00
|
|
|
import * as QueryString from 'query-string';
|
|
|
|
import { useLocation } from 'react-router';
|
2022-08-19 15:58:31 -04:00
|
|
|
import { Button, message, Modal, Pagination, Select } from 'antd';
|
2022-01-27 10:33:12 -08:00
|
|
|
import styled from 'styled-components';
|
|
|
|
import {
|
|
|
|
useCreateIngestionExecutionRequestMutation,
|
|
|
|
useCreateIngestionSourceMutation,
|
|
|
|
useDeleteIngestionSourceMutation,
|
|
|
|
useListIngestionSourcesQuery,
|
|
|
|
useUpdateIngestionSourceMutation,
|
|
|
|
} from '../../../graphql/ingestion.generated';
|
|
|
|
import { Message } from '../../shared/Message';
|
|
|
|
import TabToolbar from '../../entity/shared/components/styled/TabToolbar';
|
|
|
|
import { IngestionSourceBuilderModal } from './builder/IngestionSourceBuilderModal';
|
2022-12-05 22:20:24 -08:00
|
|
|
import { addToListIngestionSourcesCache, CLI_EXECUTOR_ID, removeFromListIngestionSourcesCache } from './utils';
|
2023-10-21 16:20:59 +01:00
|
|
|
import { DEFAULT_EXECUTOR_ID, SourceBuilderState, StringMapEntryInput } from './builder/types';
|
2024-11-13 12:53:31 -05:00
|
|
|
import { IngestionSource, SortCriterion, SortOrder, UpdateIngestionSourceInput } from '../../../types.generated';
|
2022-05-16 13:24:56 -07:00
|
|
|
import { SearchBar } from '../../search/SearchBar';
|
|
|
|
import { useEntityRegistry } from '../../useEntityRegistry';
|
2022-08-29 19:11:59 -04:00
|
|
|
import { ExecutionDetailsModal } from './executions/ExecutionRequestDetailsModal';
|
2022-08-19 15:58:31 -04:00
|
|
|
import RecipeViewerModal from './RecipeViewerModal';
|
|
|
|
import IngestionSourceTable from './IngestionSourceTable';
|
2022-08-25 03:50:52 +05:30
|
|
|
import { scrollToTop } from '../../shared/searchUtils';
|
2022-08-29 19:11:59 -04:00
|
|
|
import useRefreshIngestionData from './executions/useRefreshIngestionData';
|
|
|
|
import { isExecutionRequestActive } from './executions/IngestionSourceExecutionList';
|
2022-10-18 15:48:10 -07:00
|
|
|
import analytics, { EventType } from '../../analytics';
|
2022-12-07 16:21:55 -08:00
|
|
|
import {
|
|
|
|
INGESTION_CREATE_SOURCE_ID,
|
|
|
|
INGESTION_REFRESH_SOURCES_ID,
|
|
|
|
} from '../../onboarding/config/IngestionOnboardingConfig';
|
2023-12-26 16:30:24 +05:30
|
|
|
import { ONE_SECOND_IN_MS } from '../../entity/shared/tabs/Dataset/Queries/utils/constants';
|
2024-07-18 08:32:46 -07:00
|
|
|
import { useCommandS } from './hooks';
|
2022-01-27 10:33:12 -08:00
|
|
|
|
2022-12-05 22:20:24 -08:00
|
|
|
const PLACEHOLDER_URN = 'placeholder-urn';
|
|
|
|
|
2022-01-27 10:33:12 -08:00
|
|
|
const SourceContainer = styled.div``;
|
|
|
|
|
|
|
|
const SourcePaginationContainer = styled.div`
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
`;
|
|
|
|
|
2022-08-19 15:58:31 -04:00
|
|
|
const StyledSelect = styled(Select)`
|
|
|
|
margin-right: 15px;
|
|
|
|
min-width: 75px;
|
2022-01-27 10:33:12 -08:00
|
|
|
`;
|
|
|
|
|
2022-08-19 15:58:31 -04:00
|
|
|
const FilterWrapper = styled.div`
|
2022-01-27 10:33:12 -08:00
|
|
|
display: flex;
|
|
|
|
`;
|
|
|
|
|
2024-07-18 08:32:46 -07:00
|
|
|
const SYSTEM_INTERNAL_SOURCE_TYPE = 'SYSTEM';
|
|
|
|
|
2022-08-19 15:58:31 -04:00
|
|
|
export enum IngestionSourceType {
|
|
|
|
ALL,
|
|
|
|
UI,
|
|
|
|
CLI,
|
|
|
|
}
|
2022-08-08 14:33:57 -07:00
|
|
|
|
2022-01-27 10:33:12 -08:00
|
|
|
const DEFAULT_PAGE_SIZE = 25;
|
|
|
|
|
|
|
|
const removeExecutionsFromIngestionSource = (source) => {
|
|
|
|
if (source) {
|
|
|
|
return {
|
|
|
|
name: source.name,
|
|
|
|
type: source.type,
|
|
|
|
schedule: source.schedule,
|
|
|
|
config: source.config,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const IngestionSourceList = () => {
|
2022-05-16 13:24:56 -07:00
|
|
|
const entityRegistry = useEntityRegistry();
|
|
|
|
const location = useLocation();
|
|
|
|
const params = QueryString.parse(location.search, { arrayFormat: 'comma' });
|
|
|
|
const paramsQuery = (params?.query as string) || undefined;
|
|
|
|
const [query, setQuery] = useState<undefined | string>(undefined);
|
|
|
|
useEffect(() => setQuery(paramsQuery), [paramsQuery]);
|
|
|
|
|
2022-01-27 10:33:12 -08:00
|
|
|
const [page, setPage] = useState(1);
|
|
|
|
|
|
|
|
const pageSize = DEFAULT_PAGE_SIZE;
|
|
|
|
const start = (page - 1) * pageSize;
|
|
|
|
|
|
|
|
const [isBuildingSource, setIsBuildingSource] = useState<boolean>(false);
|
2022-08-19 15:58:31 -04:00
|
|
|
const [isViewingRecipe, setIsViewingRecipe] = useState<boolean>(false);
|
2022-01-27 10:33:12 -08:00
|
|
|
const [focusSourceUrn, setFocusSourceUrn] = useState<undefined | string>(undefined);
|
2022-08-08 14:33:57 -07:00
|
|
|
const [focusExecutionUrn, setFocusExecutionUrn] = useState<undefined | string>(undefined);
|
2022-01-27 10:33:12 -08:00
|
|
|
const [lastRefresh, setLastRefresh] = useState(0);
|
|
|
|
// Set of removed urns used to account for eventual consistency
|
|
|
|
const [removedUrns, setRemovedUrns] = useState<string[]>([]);
|
2022-08-19 15:58:31 -04:00
|
|
|
const [sourceFilter, setSourceFilter] = useState(IngestionSourceType.ALL);
|
2024-11-13 12:53:31 -05:00
|
|
|
const [sort, setSort] = useState<SortCriterion>();
|
2024-07-18 08:32:46 -07:00
|
|
|
const [hideSystemSources, setHideSystemSources] = useState(true);
|
|
|
|
|
2025-02-11 14:42:26 -05:00
|
|
|
// When source filter changes, reset page to 1
|
|
|
|
useEffect(() => {
|
|
|
|
setPage(1);
|
|
|
|
}, [sourceFilter]);
|
|
|
|
|
2024-07-18 08:32:46 -07:00
|
|
|
/**
|
|
|
|
* Show or hide system ingestion sources using a hidden command S command.
|
|
|
|
*/
|
|
|
|
useCommandS(() => setHideSystemSources(!hideSystemSources));
|
|
|
|
|
|
|
|
// Ingestion Source Default Filters
|
|
|
|
const filters = hideSystemSources
|
|
|
|
? [{ field: 'sourceType', values: [SYSTEM_INTERNAL_SOURCE_TYPE], negated: true }]
|
2025-01-29 20:42:01 -05:00
|
|
|
: [{ field: 'sourceType', values: [SYSTEM_INTERNAL_SOURCE_TYPE] }];
|
2024-11-13 12:53:31 -05:00
|
|
|
if (sourceFilter !== IngestionSourceType.ALL) {
|
|
|
|
filters.push({
|
|
|
|
field: 'sourceExecutorId',
|
|
|
|
values: [CLI_EXECUTOR_ID],
|
|
|
|
negated: sourceFilter !== IngestionSourceType.CLI,
|
|
|
|
});
|
|
|
|
}
|
2022-01-27 10:33:12 -08:00
|
|
|
|
|
|
|
// Ingestion Source Queries
|
2022-12-05 22:20:24 -08:00
|
|
|
const { loading, error, data, client, refetch } = useListIngestionSourcesQuery({
|
2022-01-27 10:33:12 -08:00
|
|
|
variables: {
|
|
|
|
input: {
|
|
|
|
start,
|
|
|
|
count: pageSize,
|
2024-11-13 12:53:31 -05:00
|
|
|
query: query?.length ? query : undefined,
|
|
|
|
filters: filters.length ? filters : undefined,
|
|
|
|
sort,
|
2022-01-27 10:33:12 -08:00
|
|
|
},
|
|
|
|
},
|
2023-11-16 22:54:47 +05:30
|
|
|
fetchPolicy: (query?.length || 0) > 0 ? 'no-cache' : 'cache-first',
|
2022-01-27 10:33:12 -08:00
|
|
|
});
|
|
|
|
const [createIngestionSource] = useCreateIngestionSourceMutation();
|
|
|
|
const [updateIngestionSource] = useUpdateIngestionSourceMutation();
|
|
|
|
|
|
|
|
// Execution Request queries
|
|
|
|
const [createExecutionRequestMutation] = useCreateIngestionExecutionRequestMutation();
|
|
|
|
const [removeIngestionSourceMutation] = useDeleteIngestionSourceMutation();
|
|
|
|
|
|
|
|
const totalSources = data?.listIngestionSources?.total || 0;
|
|
|
|
const sources = data?.listIngestionSources?.ingestionSources || [];
|
2024-11-13 12:53:31 -05:00
|
|
|
const filteredSources = sources.filter((source) => !removedUrns.includes(source.urn)) as IngestionSource[];
|
2022-01-27 10:33:12 -08:00
|
|
|
const focusSource =
|
|
|
|
(focusSourceUrn && filteredSources.find((source) => source.urn === focusSourceUrn)) || undefined;
|
|
|
|
|
2022-08-16 19:01:26 -04:00
|
|
|
const onRefresh = useCallback(() => {
|
2022-08-05 19:36:05 -04:00
|
|
|
refetch();
|
|
|
|
// Used to force a re-render of the child execution request list.
|
2022-08-22 14:12:44 -04:00
|
|
|
setLastRefresh(new Date().getTime());
|
2022-08-16 19:01:26 -04:00
|
|
|
}, [refetch]);
|
|
|
|
|
2023-12-26 16:30:24 +05:30
|
|
|
const debouncedSetQuery = debounce((newQuery: string | undefined) => {
|
|
|
|
setQuery(newQuery);
|
|
|
|
}, ONE_SECOND_IN_MS);
|
|
|
|
|
2022-08-29 19:11:59 -04:00
|
|
|
function hasActiveExecution() {
|
|
|
|
return !!filteredSources.find((source) =>
|
2024-12-12 20:49:25 +05:30
|
|
|
source.executions?.executionRequests?.find((request) => isExecutionRequestActive(request)),
|
2022-08-16 19:01:26 -04:00
|
|
|
);
|
2022-08-29 19:11:59 -04:00
|
|
|
}
|
|
|
|
useRefreshIngestionData(onRefresh, hasActiveExecution);
|
2022-08-05 19:36:05 -04:00
|
|
|
|
|
|
|
const executeIngestionSource = (urn: string) => {
|
|
|
|
createExecutionRequestMutation({
|
|
|
|
variables: {
|
|
|
|
input: {
|
|
|
|
ingestionSourceUrn: urn,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
.then(() => {
|
2022-10-18 15:48:10 -07:00
|
|
|
analytics.event({
|
|
|
|
type: EventType.ExecuteIngestionSourceEvent,
|
|
|
|
});
|
2022-08-05 19:36:05 -04:00
|
|
|
message.success({
|
|
|
|
content: `Successfully submitted ingestion execution request!`,
|
|
|
|
duration: 3,
|
|
|
|
});
|
2022-08-16 19:01:26 -04:00
|
|
|
setTimeout(() => onRefresh(), 3000);
|
2022-08-05 19:36:05 -04:00
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
message.destroy();
|
|
|
|
message.error({
|
|
|
|
content: `Failed to submit ingestion execution request!: \n ${e.message || ''}`,
|
|
|
|
duration: 3,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-01-27 10:33:12 -08:00
|
|
|
const onCreateOrUpdateIngestionSourceSuccess = () => {
|
2025-02-18 20:56:15 -08:00
|
|
|
setTimeout(() => refetch(), 3000);
|
2022-01-27 10:33:12 -08:00
|
|
|
setIsBuildingSource(false);
|
|
|
|
setFocusSourceUrn(undefined);
|
|
|
|
};
|
|
|
|
|
2023-10-21 16:20:59 +01:00
|
|
|
const formatExtraArgs = (extraArgs): StringMapEntryInput[] => {
|
|
|
|
if (extraArgs === null || extraArgs === undefined) return [];
|
2024-11-27 03:19:14 +05:30
|
|
|
return extraArgs
|
|
|
|
.filter((entry) => entry.value !== null && entry.value !== undefined && entry.value !== '')
|
|
|
|
.map((entry) => ({ key: entry.key, value: entry.value }));
|
2023-10-21 16:20:59 +01:00
|
|
|
};
|
|
|
|
|
2022-08-05 19:36:05 -04:00
|
|
|
const createOrUpdateIngestionSource = (
|
|
|
|
input: UpdateIngestionSourceInput,
|
|
|
|
resetState: () => void,
|
|
|
|
shouldRun?: boolean,
|
|
|
|
) => {
|
2022-01-27 10:33:12 -08:00
|
|
|
if (focusSourceUrn) {
|
|
|
|
// Update:
|
|
|
|
updateIngestionSource({ variables: { urn: focusSourceUrn as string, input } })
|
|
|
|
.then(() => {
|
2022-10-18 15:48:10 -07:00
|
|
|
analytics.event({
|
|
|
|
type: EventType.UpdateIngestionSourceEvent,
|
|
|
|
sourceType: input.type,
|
|
|
|
interval: input.schedule?.interval,
|
|
|
|
});
|
2022-01-27 10:33:12 -08:00
|
|
|
message.success({
|
|
|
|
content: `Successfully updated ingestion source!`,
|
|
|
|
duration: 3,
|
|
|
|
});
|
|
|
|
onCreateOrUpdateIngestionSourceSuccess();
|
|
|
|
resetState();
|
2022-08-05 19:36:05 -04:00
|
|
|
if (shouldRun) executeIngestionSource(focusSourceUrn);
|
2022-01-27 10:33:12 -08:00
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
message.destroy();
|
|
|
|
message.error({
|
|
|
|
content: `Failed to update ingestion source!: \n ${e.message || ''}`,
|
|
|
|
duration: 3,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// Create
|
|
|
|
createIngestionSource({ variables: { input } })
|
2022-08-05 19:36:05 -04:00
|
|
|
.then((result) => {
|
|
|
|
message.loading({ content: 'Loading...', duration: 2 });
|
2022-12-20 07:57:24 -08:00
|
|
|
const newSource = {
|
|
|
|
urn: result?.data?.createIngestionSource || PLACEHOLDER_URN,
|
|
|
|
name: input.name,
|
|
|
|
type: input.type,
|
|
|
|
config: null,
|
|
|
|
schedule: {
|
|
|
|
interval: input.schedule?.interval || null,
|
|
|
|
timezone: input.schedule?.timezone || null,
|
|
|
|
},
|
|
|
|
platform: null,
|
|
|
|
executions: null,
|
|
|
|
};
|
|
|
|
addToListIngestionSourcesCache(client, newSource, pageSize, query);
|
2022-08-05 19:36:05 -04:00
|
|
|
setTimeout(() => {
|
|
|
|
refetch();
|
2022-10-18 15:48:10 -07:00
|
|
|
analytics.event({
|
|
|
|
type: EventType.CreateIngestionSourceEvent,
|
|
|
|
sourceType: input.type,
|
|
|
|
interval: input.schedule?.interval,
|
|
|
|
});
|
2022-08-05 19:36:05 -04:00
|
|
|
message.success({
|
|
|
|
content: `Successfully created ingestion source!`,
|
|
|
|
duration: 3,
|
|
|
|
});
|
|
|
|
if (shouldRun && result.data?.createIngestionSource) {
|
|
|
|
executeIngestionSource(result.data.createIngestionSource);
|
|
|
|
}
|
|
|
|
}, 2000);
|
2022-01-27 10:33:12 -08:00
|
|
|
setIsBuildingSource(false);
|
|
|
|
setFocusSourceUrn(undefined);
|
|
|
|
resetState();
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
message.destroy();
|
|
|
|
message.error({
|
|
|
|
content: `Failed to create ingestion source!: \n ${e.message || ''}`,
|
|
|
|
duration: 3,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
const onChangePage = (newPage: number) => {
|
2022-08-25 03:50:52 +05:30
|
|
|
scrollToTop();
|
2022-01-27 10:33:12 -08:00
|
|
|
setPage(newPage);
|
|
|
|
};
|
|
|
|
|
2023-05-09 15:16:11 -07:00
|
|
|
const deleteIngestionSource = (urn: string) => {
|
2022-12-05 22:20:24 -08:00
|
|
|
removeFromListIngestionSourcesCache(client, urn, page, pageSize, query);
|
2022-01-27 10:33:12 -08:00
|
|
|
removeIngestionSourceMutation({
|
|
|
|
variables: { urn },
|
|
|
|
})
|
|
|
|
.then(() => {
|
2022-10-18 15:48:10 -07:00
|
|
|
analytics.event({
|
|
|
|
type: EventType.DeleteIngestionSourceEvent,
|
|
|
|
});
|
2022-01-27 10:33:12 -08:00
|
|
|
message.success({ content: 'Removed ingestion source.', duration: 2 });
|
|
|
|
const newRemovedUrns = [...removedUrns, urn];
|
|
|
|
setRemovedUrns(newRemovedUrns);
|
2023-01-25 18:32:15 +01:00
|
|
|
setTimeout(() => {
|
2022-01-27 10:33:12 -08:00
|
|
|
refetch?.();
|
|
|
|
}, 3000);
|
|
|
|
})
|
|
|
|
.catch((e: unknown) => {
|
|
|
|
message.destroy();
|
|
|
|
if (e instanceof Error) {
|
|
|
|
message.error({ content: `Failed to remove ingestion source: \n ${e.message || ''}`, duration: 3 });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-08-05 19:36:05 -04:00
|
|
|
const onSubmit = (recipeBuilderState: SourceBuilderState, resetState: () => void, shouldRun?: boolean) => {
|
2022-01-27 10:33:12 -08:00
|
|
|
createOrUpdateIngestionSource(
|
|
|
|
{
|
|
|
|
type: recipeBuilderState.type as string,
|
|
|
|
name: recipeBuilderState.name as string,
|
|
|
|
config: {
|
|
|
|
recipe: recipeBuilderState.config?.recipe as string,
|
|
|
|
version:
|
|
|
|
(recipeBuilderState.config?.version?.length &&
|
|
|
|
(recipeBuilderState.config?.version as string)) ||
|
|
|
|
undefined,
|
|
|
|
executorId:
|
|
|
|
(recipeBuilderState.config?.executorId?.length &&
|
|
|
|
(recipeBuilderState.config?.executorId as string)) ||
|
|
|
|
DEFAULT_EXECUTOR_ID,
|
2022-08-29 16:39:14 -04:00
|
|
|
debugMode: recipeBuilderState.config?.debugMode || false,
|
2023-10-21 16:20:59 +01:00
|
|
|
extraArgs: formatExtraArgs(recipeBuilderState.config?.extraArgs || []),
|
2022-01-27 10:33:12 -08:00
|
|
|
},
|
|
|
|
schedule: recipeBuilderState.schedule && {
|
|
|
|
interval: recipeBuilderState.schedule?.interval as string,
|
|
|
|
timezone: recipeBuilderState.schedule?.timezone as string,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
resetState,
|
2022-08-05 19:36:05 -04:00
|
|
|
shouldRun,
|
2022-01-27 10:33:12 -08:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const onEdit = (urn: string) => {
|
|
|
|
setIsBuildingSource(true);
|
|
|
|
setFocusSourceUrn(urn);
|
|
|
|
};
|
|
|
|
|
2022-08-19 15:58:31 -04:00
|
|
|
const onView = (urn: string) => {
|
|
|
|
setIsViewingRecipe(true);
|
|
|
|
setFocusSourceUrn(urn);
|
|
|
|
};
|
|
|
|
|
2022-01-27 10:33:12 -08:00
|
|
|
const onExecute = (urn: string) => {
|
|
|
|
Modal.confirm({
|
|
|
|
title: `Confirm Source Execution`,
|
|
|
|
content: "Click 'Execute' to run this ingestion source.",
|
|
|
|
onOk() {
|
|
|
|
executeIngestionSource(urn);
|
|
|
|
},
|
|
|
|
onCancel() {},
|
|
|
|
okText: 'Execute',
|
|
|
|
maskClosable: true,
|
|
|
|
closable: true,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const onDelete = (urn: string) => {
|
|
|
|
Modal.confirm({
|
|
|
|
title: `Confirm Ingestion Source Removal`,
|
|
|
|
content: `Are you sure you want to remove this ingestion source? Removing will terminate any scheduled ingestion runs.`,
|
|
|
|
onOk() {
|
|
|
|
deleteIngestionSource(urn);
|
|
|
|
},
|
|
|
|
onCancel() {},
|
|
|
|
okText: 'Yes',
|
|
|
|
maskClosable: true,
|
|
|
|
closable: true,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const onCancel = () => {
|
|
|
|
setIsBuildingSource(false);
|
2022-08-19 15:58:31 -04:00
|
|
|
setIsViewingRecipe(false);
|
2022-01-27 10:33:12 -08:00
|
|
|
setFocusSourceUrn(undefined);
|
|
|
|
};
|
|
|
|
|
2024-11-13 12:53:31 -05:00
|
|
|
const onChangeSort = (field, order) => {
|
|
|
|
setSort(
|
|
|
|
order
|
|
|
|
? {
|
|
|
|
sortOrder: order === 'ascend' ? SortOrder.Ascending : SortOrder.Descending,
|
|
|
|
field,
|
|
|
|
}
|
|
|
|
: undefined,
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2022-01-27 10:33:12 -08:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{!data && loading && <Message type="loading" content="Loading ingestion sources..." />}
|
2022-08-28 20:08:25 -07:00
|
|
|
{error && (
|
|
|
|
<Message type="error" content="Failed to load ingestion sources! An unexpected error occurred." />
|
|
|
|
)}
|
2022-01-27 10:33:12 -08:00
|
|
|
<SourceContainer>
|
|
|
|
<TabToolbar>
|
|
|
|
<div>
|
2023-10-20 16:25:06 -04:00
|
|
|
<Button
|
|
|
|
id={INGESTION_CREATE_SOURCE_ID}
|
|
|
|
type="text"
|
|
|
|
onClick={() => setIsBuildingSource(true)}
|
|
|
|
data-testid="create-ingestion-source-button"
|
|
|
|
>
|
2022-01-27 10:33:12 -08:00
|
|
|
<PlusOutlined /> Create new source
|
|
|
|
</Button>
|
2022-12-07 16:21:55 -08:00
|
|
|
<Button id={INGESTION_REFRESH_SOURCES_ID} type="text" onClick={onRefresh}>
|
2022-01-27 10:33:12 -08:00
|
|
|
<RedoOutlined /> Refresh
|
|
|
|
</Button>
|
|
|
|
</div>
|
2022-08-19 15:58:31 -04:00
|
|
|
<FilterWrapper>
|
|
|
|
<StyledSelect
|
|
|
|
value={sourceFilter}
|
|
|
|
onChange={(selection) => setSourceFilter(selection as IngestionSourceType)}
|
|
|
|
>
|
|
|
|
<Select.Option value={IngestionSourceType.ALL}>All</Select.Option>
|
|
|
|
<Select.Option value={IngestionSourceType.UI}>UI</Select.Option>
|
|
|
|
<Select.Option value={IngestionSourceType.CLI}>CLI</Select.Option>
|
|
|
|
</StyledSelect>
|
|
|
|
|
|
|
|
<SearchBar
|
|
|
|
initialQuery={query || ''}
|
|
|
|
placeholderText="Search sources..."
|
|
|
|
suggestions={[]}
|
|
|
|
style={{
|
|
|
|
maxWidth: 220,
|
|
|
|
padding: 0,
|
|
|
|
}}
|
|
|
|
inputStyle={{
|
|
|
|
height: 32,
|
|
|
|
fontSize: 12,
|
|
|
|
}}
|
|
|
|
onSearch={() => null}
|
2023-11-16 22:54:47 +05:30
|
|
|
onQueryChange={(q) => {
|
|
|
|
setPage(1);
|
2023-12-26 16:30:24 +05:30
|
|
|
debouncedSetQuery(q);
|
2023-11-16 22:54:47 +05:30
|
|
|
}}
|
2022-08-19 15:58:31 -04:00
|
|
|
entityRegistry={entityRegistry}
|
2022-09-22 22:32:51 +05:30
|
|
|
hideRecommendations
|
2022-08-19 15:58:31 -04:00
|
|
|
/>
|
|
|
|
</FilterWrapper>
|
2022-01-27 10:33:12 -08:00
|
|
|
</TabToolbar>
|
2022-08-19 15:58:31 -04:00
|
|
|
<IngestionSourceTable
|
|
|
|
lastRefresh={lastRefresh}
|
|
|
|
sources={filteredSources || []}
|
|
|
|
setFocusExecutionUrn={setFocusExecutionUrn}
|
|
|
|
onExecute={onExecute}
|
|
|
|
onEdit={onEdit}
|
|
|
|
onView={onView}
|
|
|
|
onDelete={onDelete}
|
|
|
|
onRefresh={onRefresh}
|
2024-11-13 12:53:31 -05:00
|
|
|
onChangeSort={onChangeSort}
|
2022-01-27 10:33:12 -08:00
|
|
|
/>
|
|
|
|
<SourcePaginationContainer>
|
|
|
|
<Pagination
|
2025-01-29 20:42:01 -05:00
|
|
|
style={{ margin: 15 }}
|
2022-01-27 10:33:12 -08:00
|
|
|
current={page}
|
|
|
|
pageSize={pageSize}
|
|
|
|
total={totalSources}
|
|
|
|
showLessItems
|
|
|
|
onChange={onChangePage}
|
|
|
|
showSizeChanger={false}
|
|
|
|
/>
|
|
|
|
</SourcePaginationContainer>
|
|
|
|
</SourceContainer>
|
|
|
|
<IngestionSourceBuilderModal
|
|
|
|
initialState={removeExecutionsFromIngestionSource(focusSource)}
|
2024-08-28 15:31:36 +05:30
|
|
|
open={isBuildingSource}
|
2022-01-27 10:33:12 -08:00
|
|
|
onSubmit={onSubmit}
|
|
|
|
onCancel={onCancel}
|
|
|
|
/>
|
2024-12-12 20:49:25 +05:30
|
|
|
{isViewingRecipe && <RecipeViewerModal recipe={focusSource?.config?.recipe} onCancel={onCancel} />}
|
2022-08-08 14:33:57 -07:00
|
|
|
{focusExecutionUrn && (
|
2024-08-28 15:31:36 +05:30
|
|
|
<ExecutionDetailsModal urn={focusExecutionUrn} open onClose={() => setFocusExecutionUrn(undefined)} />
|
2022-08-08 14:33:57 -07:00
|
|
|
)}
|
2022-01-27 10:33:12 -08:00
|
|
|
</>
|
|
|
|
);
|
|
|
|
};
|