diff --git a/frontend/webapp/containers/main/destinations/add-destination/choose-destination-modal-body/index.tsx b/frontend/webapp/containers/main/destinations/add-destination/choose-destination-modal-body/index.tsx index 160e9b77e..a0e09537f 100644 --- a/frontend/webapp/containers/main/destinations/add-destination/choose-destination-modal-body/index.tsx +++ b/frontend/webapp/containers/main/destinations/add-destination/choose-destination-modal-body/index.tsx @@ -1,19 +1,11 @@ -import React, { useEffect, useMemo, useState } from 'react'; - +import React, { useMemo, useState } from 'react'; import { SideMenu } from '@/components'; -import { useQuery } from '@apollo/client'; -import { GET_DESTINATION_TYPE } from '@/graphql'; +import { useDestinationTypes } from '@/hooks'; import { DestinationsList } from '../destinations-list'; import { Body, Container, SideMenuWrapper } from '../styled'; import { Divider, SectionTitle } from '@/reuseable-components'; import { DestinationFilterComponent } from '../choose-destination-menu'; -import { - StepProps, - DropdownOption, - DestinationTypeItem, - DestinationsCategory, - GetDestinationTypesResponse, -} from '@/types'; +import { StepProps, DropdownOption, DestinationTypeItem } from '@/types'; interface ChooseDestinationModalBodyProps { onSelect: (item: DestinationTypeItem) => void; @@ -34,42 +26,18 @@ const SIDE_MENU_DATA: StepProps[] = [ const DEFAULT_MONITORS = ['logs', 'metrics', 'traces']; const DEFAULT_DROPDOWN_VALUE = { id: 'all', value: 'All types' }; -const CATEGORIES_DESCRIPTION = { - managed: 'Effortless Monitoring with Scalable Performance Management', - 'self hosted': - 'Full Control and Customization for Advanced Application Monitoring', -}; - -export interface IDestinationListItem extends DestinationsCategory { - description: string; -} export function ChooseDestinationModalBody({ onSelect, }: ChooseDestinationModalBodyProps) { const [searchValue, setSearchValue] = useState(''); - const [destinations, setDestinations] = useState([]); const [selectedMonitors, setSelectedMonitors] = useState(DEFAULT_MONITORS); const [dropdownValue, setDropdownValue] = useState( DEFAULT_DROPDOWN_VALUE ); - const { data } = useQuery(GET_DESTINATION_TYPE); - useEffect(() => { - if (data) { - const destinationsCategories = data.destinationTypes.categories.map( - (category) => { - return { - name: category.name, - description: CATEGORIES_DESCRIPTION[category.name], - items: category.items, - }; - } - ); - setDestinations(destinationsCategories); - } - }, [data]); + const { destinations } = useDestinationTypes(); function handleTagSelect(option: DropdownOption) { setDropdownValue(option); diff --git a/frontend/webapp/containers/main/destinations/add-destination/connect-destination-modal-body/index.tsx b/frontend/webapp/containers/main/destinations/add-destination/connect-destination-modal-body/index.tsx index 0989e7173..e1954ce8e 100644 --- a/frontend/webapp/containers/main/destinations/add-destination/connect-destination-modal-body/index.tsx +++ b/frontend/webapp/containers/main/destinations/add-destination/connect-destination-modal-body/index.tsx @@ -1,5 +1,6 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useEffect, useLayoutEffect, useMemo, useState } from 'react'; import { useAppStore } from '@/store'; +import { INPUT_TYPES } from '@/utils'; import { SideMenu } from '@/components'; import { useQuery } from '@apollo/client'; import { FormContainer } from './form-container'; @@ -52,14 +53,16 @@ export function ConnectDestinationModalBody({ const { dynamicFields, exportedSignals, - setExportedSignals, setDynamicFields, + setExportedSignals, } = useDestinationFormData(); const { connectEnv } = useConnectEnv(); const { buildFormDynamicFields } = useConnectDestinationForm(); + const { handleDynamicFieldChange, handleSignalChange } = useEditDestinationFormHandlers(setExportedSignals, setDynamicFields); + const addConfiguredDestination = useAppStore( ({ addConfiguredDestination }) => addConfiguredDestination ); @@ -72,22 +75,15 @@ export function ConnectDestinationModalBody({ } ); - const monitors = useMemo(() => { - if (!destination) return []; + useLayoutEffect(() => { + if (!destination) return; const { logs, metrics, traces } = destination.supportedSignals; - setExportedSignals({ logs: logs.supported, metrics: metrics.supported, traces: traces.supported, }); - - return [ - logs.supported && { id: 'logs', title: 'Logs' }, - metrics.supported && { id: 'metrics', title: 'Metrics' }, - traces.supported && { id: 'traces', title: 'Traces' }, - ].filter(Boolean); - }, [destination]); + }, [destination, setExportedSignals]); useEffect(() => { if (data && destination) { @@ -116,22 +112,31 @@ export function ConnectDestinationModalBody({ const isFormValid = dynamicFields.every((field) => field.required ? field.value : true ); - onFormValidChange(isFormValid); }, [dynamicFields]); + const monitors = useMemo(() => { + if (!destination) return []; + const { logs, metrics, traces } = destination.supportedSignals; + + return [ + logs.supported && { id: 'logs', title: 'Logs' }, + metrics.supported && { id: 'metrics', title: 'Metrics' }, + traces.supported && { id: 'traces', title: 'Traces' }, + ].filter(Boolean); + }, [destination]); + function onDynamicFieldChange(name: string, value: any) { setShowConnectionError(false); handleDynamicFieldChange(name, value); } + function processFieldValue(field) { + return field.componentType === INPUT_TYPES.DROPDOWN + ? field.value.value + : field.value; + } function processFormFields() { - function processFieldValue(field) { - return field.componentType === 'dropdown' - ? field.value.value - : field.value; - } - // Prepare fields for the request body return dynamicFields.map((field) => ({ key: field.name, @@ -140,17 +145,10 @@ export function ConnectDestinationModalBody({ } async function handleSubmit() { - // Helper function to process field values - function processFieldValue(field) { - return field.componentType === 'dropdown' - ? field.value.value - : field.value; - } - // Prepare fields for the request body const fields = processFormFields(); - // Function to store configured destination + // Function to store configured destination to display in the UI function storeConfiguredDestination() { const destinationTypeDetails = dynamicFields.map((field) => ({ title: field.title, @@ -196,6 +194,32 @@ export function ConnectDestinationModalBody({ if (!destination) return null; + const actionButton = useMemo(() => { + if (destination.testConnectionSupported) { + return ( + { + setShowConnectionError(true); + onFormValidChange(false); + }} + destination={{ + name: destinationName, + type: destination?.type || '', + exportedSignals, + fields: processFormFields(), + }} + /> + ); + } + return null; + }, [ + destination, + destinationName, + exportedSignals, + processFormFields, + onFormValidChange, + ]); + return ( @@ -206,24 +230,7 @@ export function ConnectDestinationModalBody({ { - setShowConnectionError(true); - onFormValidChange(false); - }} - destination={{ - name: destinationName, - type: destination?.type || '', - exportedSignals, - fields: processFormFields(), - }} - /> - ) : ( - <> - ) - } + actionButton={actionButton} /> = ({ onClick={() => handleSelect(option)} > {`Add = ({ )} diff --git a/frontend/webapp/hooks/destinations/index.ts b/frontend/webapp/hooks/destinations/index.ts index 01743f661..73ea9289f 100644 --- a/frontend/webapp/hooks/destinations/index.ts +++ b/frontend/webapp/hooks/destinations/index.ts @@ -7,3 +7,4 @@ export * from './useActualDestinations'; export * from './useUpdateDestination'; export * from './useDestinationFormData'; export * from './useEditDestinationFormHandlers'; +export * from './useDestinationTypes'; diff --git a/frontend/webapp/hooks/destinations/useDestinationTypes.ts b/frontend/webapp/hooks/destinations/useDestinationTypes.ts new file mode 100644 index 000000000..ed6ae8265 --- /dev/null +++ b/frontend/webapp/hooks/destinations/useDestinationTypes.ts @@ -0,0 +1,36 @@ +import { useQuery } from '@apollo/client'; +import { useEffect, useState } from 'react'; +import { GET_DESTINATION_TYPE } from '@/graphql'; +import { DestinationsCategory, GetDestinationTypesResponse } from '@/types'; + +const CATEGORIES_DESCRIPTION = { + managed: 'Effortless Monitoring with Scalable Performance Management', + 'self hosted': + 'Full Control and Customization for Advanced Application Monitoring', +}; + +export interface IDestinationListItem extends DestinationsCategory { + description: string; +} + +export function useDestinationTypes() { + const [destinations, setDestinations] = useState([]); + const { data } = useQuery(GET_DESTINATION_TYPE); + + useEffect(() => { + if (data) { + const destinationsCategories = data.destinationTypes.categories.map( + (category) => { + return { + name: category.name, + description: CATEGORIES_DESCRIPTION[category.name], + items: category.items, + }; + } + ); + setDestinations(destinationsCategories); + } + }, [data]); + + return { destinations }; +}