diff --git a/locales/en/openbridge.json b/locales/en/openbridge.json index 2f322980..31d5c818 100644 --- a/locales/en/openbridge.json +++ b/locales/en/openbridge.json @@ -68,6 +68,12 @@ "value": "Value", "yes": "Yes" }, + "errorHandling": { + "errors": { + "cantFindSchema": "The information related to the error handling strategy for this Smart Events instance is currently missing.", + "schemaGenericError": "Error while retrieving the information related to the error handling strategy for this Smart Events instance." + } + }, "instance": { "createASEInstance": "Create a Smart Events instance", "createSEInstance": "Create Smart Events instance", diff --git a/mocked-api/data.ts b/mocked-api/data.ts index 77b304df..d3cbd5cb 100644 --- a/mocked-api/data.ts +++ b/mocked-api/data.ts @@ -10,6 +10,10 @@ export const instancesData = [ published_at: "2022-02-24T13:35:00Z", endpoint: "https://3543edaa-1851-4ad7-96be-ebde7d20d717.apps.openbridge-dev.fdvn.p1.openshiftapps.com/events", + error_handler: { + type: "webhook_sink_0.1", + parameters: `{"endpoint":"http://google.com","basic_auth_password":"my-password","basic_auth_username":"user","ssl_verification_disabled":false}`, + }, }, { kind: "Bridge", @@ -22,6 +26,10 @@ export const instancesData = [ published_at: "2022-02-20T11:24:00Z", endpoint: "https://830c8f0d-c677-492f-8d7e-0f81893fbba6.apps.openbridge-dev.fdvn.p1.openshiftapps.com/events", + error_handler: { + type: "kafka_topic_sink_0.1", + parameters: `{"topic":"my-topic","kafka_client_id":"my-client","kafka_broker_url":"username-c--hj---mhlksdfss-p--a.bf2.kafka.rhcloud.com:443","kafka_client_secret":"my-secret"}`, + }, }, { kind: "Bridge", @@ -32,8 +40,6 @@ export const instancesData = [ status: "accepted", submitted_at: "2022-02-15T12:03:00Z", published_at: "2022-02-15T12:04:00Z", - endpoint: - "https://ee22ce62-1f23-4dd7-b106-e4158baf8228.apps.openbridge-dev.fdvn.p1.openshiftapps.com/events", }, { kind: "Bridge", @@ -44,8 +50,6 @@ export const instancesData = [ status: "provisioning", submitted_at: "2022-02-10T16:34:00Z", published_at: "2022-02-10T16:35:00Z", - endpoint: - "https://21ac90ba-76d2-4f88-b08b-2547ef359bae.apps.openbridge-dev.fdvn.p1.openshiftapps.com/events", }, { kind: "Bridge", diff --git a/src/app/Instance/InstancePage/ErrorHandlingTabContent.tsx b/src/app/Instance/InstancePage/ErrorHandlingTabContent.tsx new file mode 100644 index 00000000..b36cc022 --- /dev/null +++ b/src/app/Instance/InstancePage/ErrorHandlingTabContent.tsx @@ -0,0 +1,153 @@ +import { + Alert, + DescriptionList, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTerm, + PageSection, + PageSectionVariants, + Skeleton, + Stack, + StackItem, + Text, + TextContent, + TextVariants, +} from "@patternfly/react-core"; +import { + ERROR_HANDLING_METHODS, + getErrorHandlingMethodByType, +} from "../../../types/ErrorHandlingMethods"; +import ProcessorDetailConfigParameters from "@app/Processor/ProcessorDetail/ProcessorDetailConfigParameters"; +import React, { useEffect, useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useGetSchemaApi } from "../../../hooks/useSchemasApi/useGetSchemaApi"; +import { ProcessorSchemaType } from "../../../types/Processor"; +import axios from "axios"; +import { + getErrorCode, + isServiceApiError, +} from "@openapi/generated/errorHelpers"; +import { APIErrorCodes } from "@openapi/generated/errors"; + +interface ErrorHandlingTabContentProps { + errorHandlingType?: string; + errorHandlingParameters?: { [p: string]: unknown }; + isBridgeLoading: boolean; +} + +export const ErrorHandlingTabContent = ({ + errorHandlingType, + errorHandlingParameters, + isBridgeLoading, +}: ErrorHandlingTabContentProps): JSX.Element => { + const { t } = useTranslation(["openbridgeTempDictionary"]); + + const [schema, setSchema] = useState(); + const [schemaError, setSchemaError] = useState(); + const [schemaLoading, setSchemaLoading] = useState(false); + + const { getSchema } = useGetSchemaApi(); + + useEffect(() => { + if (errorHandlingType) { + setSchemaLoading(true); + setSchema(undefined); + setSchemaError(undefined); + getSchema(errorHandlingType, ProcessorSchemaType.ACTION) + .then((data) => setSchema(data)) + .catch((error) => { + if (error && axios.isAxiosError(error)) { + if ( + isServiceApiError(error) && + getErrorCode(error) === APIErrorCodes.ERROR_4 + ) { + setSchemaError(t("errorHandling.errors.cantFindSchema")); + } else { + setSchemaError(t("errorHandling.errors.schemaGenericError")); + } + } + }) + .finally(() => setSchemaLoading(false)); + } + }, [errorHandlingType, getSchema, t]); + + const errorHandlingParametersSkeleton = useMemo(() => { + const parametersLength = errorHandlingParameters + ? Object.keys(errorHandlingParameters).length + : 1; + return ( + + {[...(Array(parametersLength) as unknown[])].map((_, index) => ( + + + + + + + + + ))} + + ); + }, [errorHandlingParameters]); + + const errorHandlingMethodLabel = useMemo(() => { + if (errorHandlingType) { + return getErrorHandlingMethodByType(errorHandlingType).label; + } + if (isBridgeLoading) { + return ; + } + return ERROR_HANDLING_METHODS.default.label; + }, [errorHandlingType, isBridgeLoading]); + + return ( + + + + + + {t("common.errorHandlingMethod")} + + + + + + + + {t("common.errorHandlingMethod")} + + + {errorHandlingMethodLabel} + + + {errorHandlingParameters && + schema && + !schemaLoading && + !schemaError && ( + + )} + {schemaLoading && errorHandlingParametersSkeleton} + {schemaError && ( + + )} + + + + + ); +}; diff --git a/src/app/Instance/InstancePage/InstancePage.css b/src/app/Instance/InstancePage/InstancePage.css index f1e62a42..b7f7375c 100644 --- a/src/app/Instance/InstancePage/InstancePage.css +++ b/src/app/Instance/InstancePage/InstancePage.css @@ -5,3 +5,7 @@ .instance-page__actions .pf-c-dropdown__menu { min-width: 13rem; } + +.instance-page__tabs-error-handling__section { + min-height: 37rem; +} diff --git a/src/app/Instance/InstancePage/InstancePage.tsx b/src/app/Instance/InstancePage/InstancePage.tsx index 527bb095..213a3254 100644 --- a/src/app/Instance/InstancePage/InstancePage.tsx +++ b/src/app/Instance/InstancePage/InstancePage.tsx @@ -1,7 +1,7 @@ import React, { useCallback, useEffect, useState } from "react"; import { - Button, Drawer, + DrawerColorVariant, DrawerContent, Dropdown, DropdownGroup, @@ -9,47 +9,28 @@ import { DropdownPosition, DropdownSeparator, DropdownToggle, - EmptyState, - EmptyStateIcon, PageSection, PageSectionVariants, + Skeleton, Split, SplitItem, Tab, - TabContent, Tabs, TabTitleText, Text, TextContent, - Title, } from "@patternfly/react-core"; -import { Link, useHistory, useLocation, useParams } from "react-router-dom"; +import { useHistory, useParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Breadcrumb } from "@app/components/Breadcrumb/Breadcrumb"; -import { CaretDownIcon, PlusCircleIcon } from "@patternfly/react-icons"; -import { - DEFAULT_PAGE_SIZE, - FIRST_PAGE, - TableWithPagination, -} from "@app/components/TableWithPagination/TableWithPagination"; -import { IAction, IRow, IRowData } from "@patternfly/react-table"; -import { formatDistance } from "date-fns"; +import { CaretDownIcon } from "@patternfly/react-icons"; import "./InstancePage.css"; import { InstanceDetails } from "@app/Instance/InstanceDetails/InstanceDetails"; import { useGetBridgeApi } from "../../../hooks/useBridgesApi/useGetBridgeApi"; import PageHeaderSkeleton from "@app/components/PageHeaderSkeleton/PageHeaderSkeleton"; -import { TableWithPaginationSkeleton } from "@app/components/TableWithPaginationSkeleton/TableWithPaginationSkeleton"; -import { useGetProcessorsApi } from "../../../hooks/useProcessorsApi/useGetProcessorsApi"; -import { usePolling } from "../../../hooks/usePolling/usePolling"; -import { - BridgeResponse, - ManagedResourceStatus, - ProcessorResponse, -} from "@rhoas/smart-events-management-sdk"; +import { BridgeResponse } from "@rhoas/smart-events-management-sdk"; import DeleteInstance from "@app/Instance/DeleteInstance/DeleteInstance"; -import { TableRow } from "@app/components/Table"; import { canDeleteResource } from "@utils/resourceUtils"; -import DeleteProcessor from "@app/Processor/DeleteProcessor/DeleteProcessor"; import { getErrorCode, isServiceApiError, @@ -57,29 +38,36 @@ import { import { APIErrorCodes } from "@openapi/generated/errors"; import axios from "axios"; import { ErrorWithDetail } from "../../../types/Error"; -import SEStatusLabel from "@app/components/SEStatusLabel/SEStatusLabel"; +import { ProcessorsTabContent } from "@app/Instance/InstancePage/ProcessorsTabContent"; +import { ErrorHandlingTabContent } from "@app/Instance/InstancePage/ErrorHandlingTabContent"; + +const INSTANCE_PAGE_TAB_KEYS = { + processors: 0, + "error-handling": 1, +}; export interface InstanceRouteParams { instanceId: string; + tabName?: keyof typeof INSTANCE_PAGE_TAB_KEYS; } const InstancePage = (): JSX.Element => { - const { instanceId } = useParams(); + const { instanceId, tabName = "processors" } = + useParams(); const { t } = useTranslation(["openbridgeTempDictionary"]); - const location = useLocation(); const history = useHistory(); - const processorsTabRef = React.createRef(); - - const [currentPage, setCurrentPage] = useState(FIRST_PAGE); - const [currentPageSize, setCurrentPageSize] = - useState(DEFAULT_PAGE_SIZE); - const [totalRows, setTotalRows] = useState(); - const [activeTabKey, setActiveTabKey] = useState(0); + const [activeTabKey, setActiveTabKey] = useState( + INSTANCE_PAGE_TAB_KEYS[tabName] + ); const [isDropdownActionOpen, setIsDropdownActionOpen] = useState(false); const [showInstanceDrawer, setShowInstanceDrawer] = useState(false); + useEffect(() => { + setActiveTabKey(INSTANCE_PAGE_TAB_KEYS[tabName]); + }, [tabName]); + const { getBridge, bridge, @@ -91,19 +79,6 @@ const InstancePage = (): JSX.Element => { getBridge(instanceId); }, [getBridge, instanceId]); - const { - getProcessors, - processorListResponse, - isLoading: areProcessorsLoading, - error: processorsError, - } = useGetProcessorsApi(); - - const triggerGetProcessors = useCallback( - (): void => - getProcessors(instanceId, currentPage, currentPageSize, undefined, true), - [currentPage, currentPageSize, getProcessors, instanceId] - ); - const getPageTitle = useCallback( (bridge?: BridgeResponse) => { const name = bridge ? bridge.name : t("instance.smartEventInstance"); @@ -118,20 +93,6 @@ const InstancePage = (): JSX.Element => { [t] ); - usePolling(() => triggerGetProcessors(), 10000); - - useEffect( - () => getProcessors(instanceId, FIRST_PAGE, DEFAULT_PAGE_SIZE), - [getProcessors, instanceId] - ); - - useEffect(() => { - if (processorListResponse) { - setCurrentPage(processorListResponse.page ?? FIRST_PAGE); - setTotalRows(processorListResponse.total ?? 0); - } - }, [processorListResponse]); - useEffect(() => { if (bridgeError && axios.isAxiosError(bridgeError)) { if ( @@ -153,99 +114,24 @@ const InstancePage = (): JSX.Element => { ); } } - - if (processorsError) { - throw new ErrorWithDetail( - getPageTitle(bridge), - t("instance.errors.processorsListGenericError") - ); - } - }, [bridge, bridgeError, getPageTitle, history, processorsError, t]); + }, [bridgeError, getPageTitle, history, t]); const handleTabClick = ( _: React.MouseEvent, - eventKey: number | string + tabNumber: number | string ): void => { - setActiveTabKey(eventKey); - }; - - const processorsOverviewColumns = [ - { - accessor: "name", - label: t("common.name"), - formatter: (value: IRowData, row?: IRow): JSX.Element => { - const processorId = (row as BridgeResponse)?.id ?? ""; - return ( - - {value} - - ); - }, - }, - { - accessor: "type", - label: t("common.type"), - formatter: (value: IRowData): string => { - const typeString = value as unknown as string; - return !typeString || !typeString.length - ? "" - : typeString.charAt(0).toUpperCase() + - typeString.slice(1).toLowerCase(); - }, - }, - { - accessor: "submitted_at", - label: t("common.submittedAt"), - formatter: (value: IRowData): string => { - const date = new Date(value as unknown as string); - return formatDistance(date, new Date()) + " " + t("common.ago"); - }, - }, - { - accessor: "status", - label: t("common.status"), - formatter: (value: IRowData, row?: IRow): JSX.Element => { - const statusString = value as unknown as ManagedResourceStatus; - const requestedAt = new Date( - (row as ProcessorResponse).modified_at ?? - (row as ProcessorResponse).submitted_at - ); - return ( - - ); - }, - }, - ]; - - const customToolbarElement = ( - - - - ); + setActiveTabKey(tabNumber); - const onPaginationChange = useCallback( - (pageNumber: number, pageSize: number): void => { - const correctPageNumber = - pageSize === currentPageSize ? pageNumber : FIRST_PAGE; - setCurrentPage(correctPageNumber); - setCurrentPageSize(pageSize); - getProcessors(instanceId, correctPageNumber, pageSize); - }, - [currentPageSize, getProcessors, instanceId] - ); + const selectedTabName = + Object.keys(INSTANCE_PAGE_TAB_KEYS).find( + (tabName) => + (INSTANCE_PAGE_TAB_KEYS as { [tabName: string]: number })[tabName] === + (tabNumber as number) + ) ?? ""; + history.push(`/instance/${instanceId}/${selectedTabName}`); + }; const [showInstanceDeleteModal, setShowInstanceDeleteModal] = useState(false); - const [deleteProcessorId, setDeleteProcessorId] = useState(""); - const [deleteProcessorName, setDeleteProcessorName] = useState(""); const deleteInstance = (): void => { setShowInstanceDeleteModal(true); @@ -256,210 +142,160 @@ const InstancePage = (): JSX.Element => { history.push(`/`); }, [history]); - const [showProcessorDeleteModal, setShowProcessorDeleteModal] = - useState(false); - - const deleteProcessor = (id: string, name: string): void => { - setDeleteProcessorId(id); - setDeleteProcessorName(name); - setShowProcessorDeleteModal(true); - }; - - const handleOnDeleteProcessorSuccess = useCallback((): void => { - setShowProcessorDeleteModal(false); - getProcessors(instanceId, currentPage, currentPageSize); - }, [getProcessors, instanceId, currentPage, currentPageSize]); - - const tableActions = (rowData: TableRow): IAction[] => [ - { - title: t("common.delete"), - onClick: (): void => { - const id = (rowData.originalData as BridgeResponse).id; - const name = (rowData.originalData as BridgeResponse).name; - if (id && name) { - deleteProcessor(id, name); - } - }, - isDisabled: !canDeleteResource( - (rowData.originalData as BridgeResponse).status - ), - }, - ]; - return ( - <> - {(isBridgeLoading || - (totalRows === undefined && areProcessorsLoading)) && ( - <> + + setShowInstanceDrawer(false)} + instance={bridge} + /> + ) + } + > + {isBridgeLoading && ( - - - + + - - - - )} - {bridge && processorListResponse?.items && ( - <> - - setShowInstanceDrawer(false)} - instance={bridge} - /> - } - > - - - - - - - - - {bridge.name} - - - - - setIsDropdownActionOpen(false)} - position={DropdownPosition.right} - toggle={ - - setIsDropdownActionOpen(isOpen) - } - toggleIndicator={CaretDownIcon} - > - {t("common.actions")} - - } - isOpen={isDropdownActionOpen} - dropdownItems={[ - - { - setShowInstanceDrawer(true); - }} - > - {t("common.details")} - - , - , + + + + + + + {bridge.name} + + + + + setIsDropdownActionOpen(false)} + position={DropdownPosition.right} + toggle={ + + setIsDropdownActionOpen(isOpen) + } + toggleIndicator={CaretDownIcon} + > + {t("common.actions")} + + } + isOpen={isDropdownActionOpen} + dropdownItems={[ + { + setShowInstanceDrawer(true); + }} > - {t("instance.delete")} - , - ]} - /> - - - - - - {t("common.processors")} - } + {t("common.details")} + + , + , + + {t("instance.delete")} + , + ]} /> - + + + + + )} + + + + ) : ( + {t("common.processors")} + ) + } + > + + + + + ) : ( + {t("common.errorHandling")} + ) + } + > - - ( - - )} - > - - - - {t("processor.noProcessors")} - - - - + - - - setShowInstanceDeleteModal(false)} - onDeleted={handleOnDeleteInstanceSuccess} - /> - setShowProcessorDeleteModal(false)} - onDeleted={handleOnDeleteProcessorSuccess} - /> - - )} - + + + + setShowInstanceDeleteModal(false)} + onDeleted={handleOnDeleteInstanceSuccess} + /> + + ); }; diff --git a/src/app/Instance/InstancePage/ProcessorsTabContent.tsx b/src/app/Instance/InstancePage/ProcessorsTabContent.tsx new file mode 100644 index 00000000..647762a1 --- /dev/null +++ b/src/app/Instance/InstancePage/ProcessorsTabContent.tsx @@ -0,0 +1,236 @@ +import { + DEFAULT_PAGE_SIZE, + FIRST_PAGE, + TableWithPagination, +} from "@app/components/TableWithPagination/TableWithPagination"; +import { + Button, + EmptyState, + EmptyStateIcon, + TabContent, + Title, +} from "@patternfly/react-core"; +import { PlusCircleIcon } from "@patternfly/react-icons"; +import React, { useCallback, useEffect, useState } from "react"; +import { IAction, IRow, IRowData } from "@patternfly/react-table"; +import { + BridgeResponse, + ManagedResourceStatus, + ProcessorResponse, +} from "@rhoas/smart-events-management-sdk"; +import { Link } from "react-router-dom"; +import { formatDistance } from "date-fns"; +import { useTranslation } from "react-i18next"; +import { useGetProcessorsApi } from "../../../hooks/useProcessorsApi/useGetProcessorsApi"; +import { usePolling } from "../../../hooks/usePolling/usePolling"; +import { ErrorWithDetail } from "../../../types/Error"; +import { TableWithPaginationSkeleton } from "@app/components/TableWithPaginationSkeleton/TableWithPaginationSkeleton"; +import { TableRow } from "@app/components/Table"; +import { canDeleteResource } from "@utils/resourceUtils"; +import DeleteProcessor from "@app/Processor/DeleteProcessor/DeleteProcessor"; +import SEStatusLabel from "@app/components/SEStatusLabel/SEStatusLabel"; + +interface ProcessorTabContentProps { + instanceId: string; + pageTitle: JSX.Element; +} + +export const ProcessorsTabContent = ({ + instanceId, + pageTitle, +}: ProcessorTabContentProps): JSX.Element => { + const { t } = useTranslation(["openbridgeTempDictionary"]); + + const [currentPage, setCurrentPage] = useState(FIRST_PAGE); + const [currentPageSize, setCurrentPageSize] = + useState(DEFAULT_PAGE_SIZE); + const [totalRows, setTotalRows] = useState(); + const [deleteProcessorId, setDeleteProcessorId] = useState(""); + const [deleteProcessorName, setDeleteProcessorName] = useState(""); + const [showProcessorDeleteModal, setShowProcessorDeleteModal] = + useState(false); + + const processorsOverviewColumns = [ + { + accessor: "name", + label: t("common.name"), + formatter: (value: IRowData, row?: IRow): JSX.Element => { + const processorId = (row as BridgeResponse)?.id ?? ""; + return ( + + {value} + + ); + }, + }, + { + accessor: "type", + label: t("common.type"), + formatter: (value: IRowData): string => { + const typeString = value as unknown as string; + return !typeString || !typeString.length + ? "" + : typeString.charAt(0).toUpperCase() + + typeString.slice(1).toLowerCase(); + }, + }, + { + accessor: "submitted_at", + label: t("common.submittedAt"), + formatter: (value: IRowData): string => { + const date = new Date(value as unknown as string); + return formatDistance(date, new Date()) + " " + t("common.ago"); + }, + }, + { + accessor: "status", + label: t("common.status"), + formatter: (value: IRowData, row?: IRow): JSX.Element => { + const statusString = value as unknown as ManagedResourceStatus; + const requestedAt = new Date( + (row as ProcessorResponse).modified_at ?? + (row as ProcessorResponse).submitted_at + ); + return ( + + ); + }, + }, + ]; + + const customToolbarElement = ( + + + + ); + + const deleteProcessor = (id: string, name: string): void => { + setDeleteProcessorId(id); + setDeleteProcessorName(name); + setShowProcessorDeleteModal(true); + }; + + const tableActions = (rowData: TableRow): IAction[] => [ + { + title: t("common.delete"), + onClick: (): void => { + const id = (rowData.originalData as BridgeResponse).id; + const name = (rowData.originalData as BridgeResponse).name; + if (id && name) { + deleteProcessor(id, name); + } + }, + isDisabled: !canDeleteResource( + (rowData.originalData as BridgeResponse).status + ), + }, + ]; + + const { + getProcessors, + processorListResponse, + isLoading: areProcessorsLoading, + error: processorsError, + } = useGetProcessorsApi(); + + const triggerGetProcessors = useCallback( + (): void => + getProcessors(instanceId, currentPage, currentPageSize, undefined, true), + [currentPage, currentPageSize, getProcessors, instanceId] + ); + + const onPaginationChange = useCallback( + (pageNumber: number, pageSize: number): void => { + const correctPageNumber = + pageSize === currentPageSize ? pageNumber : FIRST_PAGE; + setCurrentPage(correctPageNumber); + setCurrentPageSize(pageSize); + getProcessors(instanceId, correctPageNumber, pageSize); + }, + [currentPageSize, getProcessors, instanceId] + ); + + const handleOnDeleteProcessorSuccess = useCallback((): void => { + setShowProcessorDeleteModal(false); + getProcessors(instanceId, currentPage, currentPageSize); + }, [getProcessors, instanceId, currentPage, currentPageSize]); + + usePolling(() => triggerGetProcessors(), 10000); + + useEffect( + () => getProcessors(instanceId, FIRST_PAGE, DEFAULT_PAGE_SIZE), + [getProcessors, instanceId] + ); + + useEffect(() => { + if (processorListResponse) { + setCurrentPage(processorListResponse.page ?? FIRST_PAGE); + setTotalRows(processorListResponse.total ?? 0); + } + }, [processorListResponse]); + + useEffect(() => { + if (processorsError) { + throw new ErrorWithDetail( + pageTitle, + t("instance.errors.processorsListGenericError") + ); + } + }, [pageTitle, processorsError, t]); + + return ( + <> + {processorListResponse?.items ? ( + ( + + )} + > + + + + {t("processor.noProcessors")} + + + + ) : ( + + + + )} + setShowProcessorDeleteModal(false)} + onDeleted={handleOnDeleteProcessorSuccess} + /> + + ); +}; diff --git a/src/app/Routes/Routes.tsx b/src/app/Routes/Routes.tsx index 0b922769..72dc2df9 100644 --- a/src/app/Routes/Routes.tsx +++ b/src/app/Routes/Routes.tsx @@ -20,7 +20,12 @@ const Routes = (): JSX.Element => { - + + + + diff --git a/src/app/components/PageHeaderSkeleton/PageHeaderSkeleton.tsx b/src/app/components/PageHeaderSkeleton/PageHeaderSkeleton.tsx index eca02065..79fdc60a 100644 --- a/src/app/components/PageHeaderSkeleton/PageHeaderSkeleton.tsx +++ b/src/app/components/PageHeaderSkeleton/PageHeaderSkeleton.tsx @@ -7,8 +7,6 @@ import { SplitItem, Stack, StackItem, - Tab, - Tabs, } from "@patternfly/react-core"; interface PageHeaderSkeletonProps { @@ -16,7 +14,7 @@ interface PageHeaderSkeletonProps { hasEditButton?: boolean; hasActionDropdown: boolean; hasLabel: boolean; - totalTabs?: number; + noShadowBottom?: boolean; } const PageHeaderSkeleton = (props: PageHeaderSkeletonProps): JSX.Element => { @@ -25,13 +23,13 @@ const PageHeaderSkeleton = (props: PageHeaderSkeletonProps): JSX.Element => { hasEditButton = false, hasActionDropdown, hasLabel, - totalTabs = 0, + noShadowBottom = false, } = props; return ( <> @@ -45,7 +43,7 @@ const PageHeaderSkeleton = (props: PageHeaderSkeletonProps): JSX.Element => { @@ -76,19 +74,6 @@ const PageHeaderSkeleton = (props: PageHeaderSkeletonProps): JSX.Element => { )} - {totalTabs > 0 && ( - - - {[...Array(totalTabs).keys()].map((tabNumber) => ( - } - /> - ))} - - - )} ); }; diff --git a/src/types/ErrorHandlingMethods.ts b/src/types/ErrorHandlingMethods.ts index ae3590b1..de253f12 100644 --- a/src/types/ErrorHandlingMethods.ts +++ b/src/types/ErrorHandlingMethods.ts @@ -15,3 +15,13 @@ export const ERROR_HANDLING_METHODS: ErrorHandlingMethods = { { label: "Kafka topic", value: "kafka_topic_sink_0.1" }, ], }; + +export const getErrorHandlingMethodByType = ( + type?: string +): ErrorHandlingMethod => { + return ( + ERROR_HANDLING_METHODS.deadLetterQueue.find( + (method) => type === method.value + ) ?? ERROR_HANDLING_METHODS.default + ); +};