Skip to content

Commit

Permalink
Merge pull request #44 from alonkeyval/gen-1538-create-destination-re…
Browse files Browse the repository at this point in the history
…factor

[GEN-1538] Refactor destinations types query
  • Loading branch information
alonkeyval authored Oct 21, 2024
2 parents 5e8f0c3 + 48c193a commit 2bd63d2
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 90 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<IDestinationListItem[]>([]);
const [selectedMonitors, setSelectedMonitors] =
useState<string[]>(DEFAULT_MONITORS);
const [dropdownValue, setDropdownValue] = useState<DropdownOption>(
DEFAULT_DROPDOWN_VALUE
);

const { data } = useQuery<GetDestinationTypesResponse>(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);
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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
);
Expand All @@ -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) {
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -196,6 +194,32 @@ export function ConnectDestinationModalBody({

if (!destination) return null;

const actionButton = useMemo(() => {
if (destination.testConnectionSupported) {
return (
<TestConnection
onError={() => {
setShowConnectionError(true);
onFormValidChange(false);
}}
destination={{
name: destinationName,
type: destination?.type || '',
exportedSignals,
fields: processFormFields(),
}}
/>
);
}
return null;
}, [
destination,
destinationName,
exportedSignals,
processFormFields,
onFormValidChange,
]);

return (
<Container>
<SideMenuWrapper>
Expand All @@ -206,24 +230,7 @@ export function ConnectDestinationModalBody({
<SectionTitle
title="Create connection"
description="Connect selected destination with Odigos."
actionButton={
destination.testConnectionSupported ? (
<TestConnection // TODO: refactor this after add form validation
onError={() => {
setShowConnectionError(true);
onFormValidChange(false);
}}
destination={{
name: destinationName,
type: destination?.type || '',
exportedSignals,
fields: processFormFields(),
}}
/>
) : (
<></>
)
}
actionButton={actionButton}
/>
<ConnectionNotification
showConnectionError={showConnectionError}
Expand Down
18 changes: 9 additions & 9 deletions frontend/webapp/containers/main/overview/add-entity/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useState, useRef, useCallback } from 'react';
import Image from 'next/image';
import theme from '@/styles/theme';
import { DropdownOption } from '@/types';
import { AddActionModal } from '../../actions';
import styled, { css } from 'styled-components';
import { useActualSources, useOnClickOutside } from '@/hooks';
import { DropdownOption, OVERVIEW_ENTITY_TYPES } from '@/types';
import { Button, FadeLoader, Text } from '@/reuseable-components';
import { AddSourceModal } from '../../sources/choose-sources/choose-source-modal';
import { AddDestinationModal } from '../../destinations/add-destination/add-destination-modal';
import { AddActionModal } from '../../actions';

// Styled components for the dropdown UI
const Container = styled.div`
Expand Down Expand Up @@ -61,9 +61,9 @@ const ButtonText = styled(Text)`

// Default options for the dropdown
const DEFAULT_OPTIONS: DropdownOption[] = [
{ id: 'sources', value: 'Source' },
{ id: 'actions', value: 'Action' },
{ id: 'destinations', value: 'Destination' },
{ id: 'source', value: 'Source' },
{ id: 'action', value: 'Action' },
{ id: 'destination', value: 'Destination' },
];

interface AddEntityButtonDropdownProps {
Expand Down Expand Up @@ -121,7 +121,7 @@ const AddEntityButtonDropdown: React.FC<AddEntityButtonDropdownProps> = ({
onClick={() => handleSelect(option)}
>
<Image
src={`/icons/overview/${option.id}.svg`}
src={`/icons/overview/${option.id}s.svg`}
width={16}
height={16}
alt={`Add ${option.value}`}
Expand All @@ -132,17 +132,17 @@ const AddEntityButtonDropdown: React.FC<AddEntityButtonDropdownProps> = ({
</DropdownListContainer>
)}
<AddSourceModal
isOpen={currentModal === 'sources'}
isOpen={currentModal === OVERVIEW_ENTITY_TYPES.SOURCE}
onClose={handleCloseModal}
createSourcesForNamespace={createSourcesForNamespace}
persistNamespaceItems={persistNamespaceItems}
/>
<AddDestinationModal
isModalOpen={currentModal === 'destinations'}
isModalOpen={currentModal === OVERVIEW_ENTITY_TYPES.DESTINATION}
handleCloseModal={handleCloseModal}
/>
<AddActionModal
isModalOpen={currentModal === 'actions'}
isModalOpen={currentModal === OVERVIEW_ENTITY_TYPES.ACTION}
handleCloseModal={handleCloseModal}
/>
</Container>
Expand Down
1 change: 1 addition & 0 deletions frontend/webapp/hooks/destinations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export * from './useActualDestinations';
export * from './useUpdateDestination';
export * from './useDestinationFormData';
export * from './useEditDestinationFormHandlers';
export * from './useDestinationTypes';
36 changes: 36 additions & 0 deletions frontend/webapp/hooks/destinations/useDestinationTypes.ts
Original file line number Diff line number Diff line change
@@ -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<IDestinationListItem[]>([]);
const { data } = useQuery<GetDestinationTypesResponse>(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 };
}

0 comments on commit 2bd63d2

Please sign in to comment.