diff --git a/__tests__/pages/Metrics/Filters.spec.tsx b/__tests__/pages/Metrics/Filters.spec.tsx
index 6aff892b..e105f639 100644
--- a/__tests__/pages/Metrics/Filters.spec.tsx
+++ b/__tests__/pages/Metrics/Filters.spec.tsx
@@ -4,7 +4,7 @@ import { Server } from 'miragejs';
import processesData from '../../../mocks/data/PROCESSES.json';
import siteData from '../../../mocks/data/SITES.json';
import { loadMockServer } from '../../../mocks/server';
-import { AvailableProtocols } from '../../../src/API/REST.enum';
+import { Protocols } from '../../../src/API/REST.enum';
import { waitForElementToBeRemovedTimeout } from '../../../src/config/config';
import MetricFilters from '../../../src/pages/shared/Metrics/components/Filters';
import { MetricsLabels } from '../../../src/pages/shared/Metrics/Metrics.enum';
@@ -36,7 +36,7 @@ describe('Metrics component', () => {
{ destinationName: processesData.results[2].name },
{ destinationName: processesData.results[3].name }
]}
- availableProtocols={[AvailableProtocols.Http, AvailableProtocols.Http2, AvailableProtocols.Tcp]}
+ availableProtocols={[Protocols.Http, Protocols.Http2, Protocols.Tcp]}
configFilters={{
destinationProcesses: { disabled: false, placeholder: MetricsLabels.FilterAllDestinationProcesses },
sourceProcesses: { disabled: false, placeholder: MetricsLabels.FilterAllSourceProcesses },
@@ -99,7 +99,7 @@ describe('Metrics component', () => {
{ destinationName: processesData.results[2].name },
{ destinationName: processesData.results[3].name }
]}
- availableProtocols={[AvailableProtocols.Http, AvailableProtocols.Http2, AvailableProtocols.Tcp]}
+ availableProtocols={[Protocols.Http, Protocols.Http2, Protocols.Tcp]}
configFilters={{
destinationProcesses: { disabled: false, placeholder: MetricsLabels.FilterAllDestinationProcesses },
sourceProcesses: { disabled: false, placeholder: MetricsLabels.FilterAllSourceProcesses },
@@ -123,11 +123,11 @@ describe('Metrics component', () => {
});
fireEvent.click(screen.getByText(MetricsLabels.FilterProtocolsDefault));
- await waitFor(() => expect(screen.getByText(AvailableProtocols.Http2)).toBeInTheDocument(), {
+ await waitFor(() => expect(screen.getByText(Protocols.Http2)).toBeInTheDocument(), {
timeout: waitForElementToBeRemovedTimeout
});
- fireEvent.click(screen.getByText(AvailableProtocols.Http2));
+ fireEvent.click(screen.getByText(Protocols.Http2));
await waitFor(() => expect(screen.queryByText(MetricsLabels.FilterProtocolsDefault)).not.toBeInTheDocument(), {
timeout: waitForElementToBeRemovedTimeout
});
diff --git a/__tests__/pages/Metrics/Metrics.spec.tsx b/__tests__/pages/Metrics/Metrics.spec.tsx
index 1a11f84e..20b9e250 100644
--- a/__tests__/pages/Metrics/Metrics.spec.tsx
+++ b/__tests__/pages/Metrics/Metrics.spec.tsx
@@ -2,7 +2,7 @@ import { Suspense } from 'react';
import { act, render, renderHook } from '@testing-library/react';
-import { AvailableProtocols } from '../../../src/API/REST.enum';
+import { Protocols } from '../../../src/API/REST.enum';
import { Wrapper } from '../../../src/core/components/Wrapper';
import LoadingPage from '../../../src/pages/shared/Loading';
import Metrics, { MetricsProps, useMetrics } from '../../../src/pages/shared/Metrics';
@@ -10,7 +10,7 @@ import { configDefaultFilters } from '../../../src/pages/shared/Metrics/Metrics.
describe('useMetrics', () => {
const initialProps = {
- defaultMetricFilterValues: { protocol: AvailableProtocols.Http },
+ defaultMetricFilterValues: { protocol: Protocols.Http },
defaultOpenSections: { byterate: true },
onGetMetricFiltersConfig: jest.fn(),
onGetExpandedSectionsConfig: jest.fn()
@@ -18,7 +18,7 @@ describe('useMetrics', () => {
it('initializes with the correct state from props', () => {
const { result } = renderHook(() => useMetrics(initialProps));
- expect(result.current.queryParams).toEqual({ protocol: AvailableProtocols.Http });
+ expect(result.current.queryParams).toEqual({ protocol: Protocols.Http });
expect(result.current.shouldUpdateData).toBe(0);
});
@@ -32,7 +32,7 @@ describe('useMetrics', () => {
it('updates queryParams and calls onGetMetricFiltersConfig when handleFilterChange is invoked', () => {
const { result } = renderHook(() => useMetrics(initialProps));
- const newFilters = { protocol: AvailableProtocols.Tcp };
+ const newFilters = { protocol: Protocols.Tcp };
act(() => {
result.current.handleFilterChange(newFilters);
});
@@ -62,7 +62,7 @@ describe('Metrics Component', () => {
destSites: [],
sourceProcesses: [],
destProcesses: [],
- availableProtocols: [AvailableProtocols.Http, AvailableProtocols.Tcp, AvailableProtocols.Http2],
+ availableProtocols: [Protocols.Http, Protocols.Tcp, Protocols.Http2],
onGetMetricFiltersConfig: jest.fn(),
onGetExpandedSectionsConfig: jest.fn(),
...overrides
diff --git a/__tests__/pages/Metrics/useMetricsSessionHandler.spec.ts b/__tests__/pages/Metrics/useMetricsSessionHandler.spec.ts
new file mode 100644
index 00000000..6122de2b
--- /dev/null
+++ b/__tests__/pages/Metrics/useMetricsSessionHandler.spec.ts
@@ -0,0 +1,89 @@
+import { act } from 'react';
+
+import { renderHook } from '@testing-library/react';
+
+import { Direction, Protocols } from '@API/REST.enum';
+import { getDataFromSession, storeDataToSession } from '@core/utils/persistData';
+import { useMetricSessionHandlers } from '@pages/shared/Metrics/hooks/useMetricsSessionHandler';
+import { QueryMetricsParams, ExpandedMetricSections } from '@sk-types/Metrics.interfaces';
+
+const mockQueryMetricsParams: QueryMetricsParams = {
+ sourceSite: 'SiteA',
+ destSite: 'SiteB',
+ sourceProcess: 'ProcessA',
+ destProcess: 'ProcessB',
+ sourceComponent: 'ComponentA',
+ destComponent: 'ComponentB',
+ service: 'ServiceA',
+ protocol: Protocols.Tcp,
+ start: 1620000000,
+ end: 1620003600,
+ duration: 3600,
+ direction: Direction.Incoming
+};
+
+const mockExpandedMetricSections: ExpandedMetricSections = {
+ byterate: true,
+ latency: false,
+ request: true,
+ response: true,
+ connection: false
+};
+
+// Mock the utility functions
+jest.mock('@core/utils/persistData', () => ({
+ getDataFromSession: jest.fn(),
+ storeDataToSession: jest.fn()
+}));
+
+describe('useMetricSessionHandlers', () => {
+ const id = 'test-id';
+
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should return undefined for visibleMetrics if session data is missing', () => {
+ (getDataFromSession as jest.Mock).mockReturnValueOnce(undefined);
+
+ const { result } = renderHook(() => useMetricSessionHandlers(id));
+ expect(result.current.visibleMetrics).toBeUndefined();
+ });
+
+ it('should retrieve selectedFilters and visibleMetrics from session', () => {
+ const mockFilters: QueryMetricsParams = mockQueryMetricsParams;
+ const mockVisibleMetrics = mockExpandedMetricSections;
+
+ (getDataFromSession as jest.Mock).mockImplementation((key: string) =>
+ key.includes('metric-filters') ? mockFilters : mockVisibleMetrics
+ );
+
+ const { result } = renderHook(() => useMetricSessionHandlers(id));
+
+ expect(result.current.selectedFilters).toEqual(mockFilters);
+ expect(result.current.visibleMetrics).toEqual(mockVisibleMetrics);
+ expect(getDataFromSession).toHaveBeenCalledTimes(2);
+ });
+
+ it('should store selectedFilters to session', () => {
+ const mockFilters: QueryMetricsParams = mockQueryMetricsParams;
+ const { result } = renderHook(() => useMetricSessionHandlers(id));
+
+ act(() => {
+ result.current.setSelectedFilters(mockFilters);
+ });
+
+ expect(storeDataToSession).toHaveBeenCalledWith(`metric-filters-${id}`, mockFilters);
+ });
+
+ it('should store visibleMetrics to session', () => {
+ const mockVisibleMetrics = mockExpandedMetricSections;
+ const { result } = renderHook(() => useMetricSessionHandlers(id));
+
+ act(() => {
+ result.current.setVisibleMetrics(mockVisibleMetrics);
+ });
+
+ expect(storeDataToSession).toHaveBeenCalledWith(`metric-sections-${id}`, mockVisibleMetrics);
+ });
+});
diff --git a/__tests__/pages/Processes/ProcessPairs.spec.tsx b/__tests__/pages/Processes/ProcessPairs.spec.tsx
index 1cd4893f..154fac69 100644
--- a/__tests__/pages/Processes/ProcessPairs.spec.tsx
+++ b/__tests__/pages/Processes/ProcessPairs.spec.tsx
@@ -11,7 +11,7 @@ import { loadMockServer } from '../../../mocks/server';
import { waitForElementToBeRemovedTimeout } from '../../../src/config/config';
import { getTestsIds } from '../../../src/config/testIds';
import { Wrapper } from '../../../src/core/components/Wrapper';
-import ProcessPairs, { ProcessPairsContent } from '../../../src/pages/Processes/views/ProcessPairs';
+import ProcessPair, { ProcessPairContent } from '../../../src/pages/Processes/views/ProcessPair';
import LoadingPage from '../../../src/pages/shared/Loading';
import { ProcessPairsResponse, SitePairsResponse } from '../../../src/types/REST.interfaces';
@@ -37,7 +37,7 @@ describe('Begin testing the Processes component', () => {
render(
}>
-
+
);
@@ -54,7 +54,7 @@ describe('Begin testing the Processes component', () => {
render(
}>
-
+
);
@@ -70,7 +70,7 @@ describe('Begin testing the Processes component', () => {
const { queryByTestId, getByTestId } = render(
}>
-
+
);
@@ -86,7 +86,7 @@ describe('Begin testing the Processes component', () => {
const { queryByTestId, getByText, getByTestId } = render(
}>
-
+
);
diff --git a/__tests__/pages/Processes/ProcessPairsList.spec.tsx b/__tests__/pages/Processes/ProcessPairsList.spec.tsx
index 45ddc78d..184a292e 100644
--- a/__tests__/pages/Processes/ProcessPairsList.spec.tsx
+++ b/__tests__/pages/Processes/ProcessPairsList.spec.tsx
@@ -10,7 +10,7 @@ import { loadMockServer } from '../../../mocks/server';
import { waitForElementToBeRemovedTimeout } from '../../../src/config/config';
import { getTestsIds } from '../../../src/config/testIds';
import { Wrapper } from '../../../src/core/components/Wrapper';
-import ProcessPairsList from '../../../src/pages/Processes/components/ProcessPairsList';
+import PairsList from '../../../src/pages/Processes/components/PairsList';
import { ProcessesLabels, ProcessesRoutesPaths } from '../../../src/pages/Processes/Processes.enum';
import LoadingPage from '../../../src/pages/shared/Loading';
import { ProcessPairsResponse, ProcessResponse, SitePairsResponse } from '../../../src/types/REST.interfaces';
@@ -29,7 +29,7 @@ describe('Processes Pairs component', () => {
render(
}>
-
+
);
@@ -45,7 +45,7 @@ describe('Processes Pairs component', () => {
timeout: waitForElementToBeRemovedTimeout
});
- expect(screen.getAllByRole('link', { name: 'view pairs' })[1]).toHaveAttribute(
+ expect(screen.getAllByRole('link', { name: ProcessesLabels.GoToDetailsLink })[1]).toHaveAttribute(
'href',
`#${ProcessesRoutesPaths.Processes}/${processPairsResult.sourceName}@${processPairsResult.sourceId}/${ProcessesLabels.ProcessPairs}@${processPairsResult.identity}?type=${ProcessesLabels.ProcessPairs}`
);
diff --git a/__tests__/pages/Sites/SiteController.spec.ts b/__tests__/pages/Sites/SiteController.spec.ts
deleted file mode 100644
index df822e3d..00000000
--- a/__tests__/pages/Sites/SiteController.spec.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import { LinkResponse, SiteResponse } from '../../../src/types/REST.interfaces';
-import SitesController from '../../../src/pages/Sites/services';
-
-describe('SitesController', () => {
- const emptySites: SiteResponse[] = [];
- const emptyLinks: LinkResponse[] = [];
-
- it('should return an empty array if sites input is empty', () => {
- const result = SitesController.bindLinksWithSiteIds(emptySites, []);
- expect(result).toEqual([]);
- });
-
- it('should return an empty array if links input is empty', () => {
- const result = SitesController.bindLinksWithSiteIds([], emptyLinks);
- expect(result).toEqual([]);
- });
-
- it('should return an empty array if routers input is empty', () => {
- const result = SitesController.bindLinksWithSiteIds([], []);
- expect(result).toEqual([]);
- });
-
- it('should return an empty array if all inputs are empty', () => {
- const result = SitesController.bindLinksWithSiteIds(emptySites, emptyLinks);
- expect(result).toEqual([]);
- });
-});
diff --git a/__tests__/pages/Topology/DisplayOptions.spec.tsx b/__tests__/pages/Topology/DisplayOptions.spec.tsx
index 1e24ae85..5fe49dd4 100644
--- a/__tests__/pages/Topology/DisplayOptions.spec.tsx
+++ b/__tests__/pages/Topology/DisplayOptions.spec.tsx
@@ -1,7 +1,9 @@
import { renderHook, render, act } from '@testing-library/react';
import eventUser from '@testing-library/user-event';
-import DisplayOptions, { useDisplayOptions } from '../../../src/pages/Topology/components/DisplayOptions';
+import { useDisplayOptionsState } from '@pages/Topology/hooks/useDisplayOptionsState';
+
+import DisplayOptions from '../../../src/pages/Topology/components/DisplayOptions';
import { SHOW_DATA_LINKS, SHOW_ROUTER_LINKS } from '../../../src/pages/Topology/Topology.constants';
import { TopologyLabels } from '../../../src/pages/Topology/Topology.enum';
@@ -21,13 +23,13 @@ const options = {
describe('useDisplayOptions', () => {
it('initializes with defaultSelected values', () => {
const { result } = renderHook(() =>
- useDisplayOptions({ defaultSelected: ['option1', 'option2'], onSelected: mockOnSelected })
+ useDisplayOptionsState({ defaultSelected: ['option1', 'option2'], onSelected: mockOnSelected })
);
expect(result.current.displayOptionsSelected).toEqual(['option1', 'option2']);
});
it('adds and removes options correctly', () => {
- const { result } = renderHook(() => useDisplayOptions({ defaultSelected: [], onSelected: mockOnSelected }));
+ const { result } = renderHook(() => useDisplayOptionsState({ defaultSelected: [], onSelected: mockOnSelected }));
const { selectDisplayOptions } = result.current;
// Add an option
@@ -41,7 +43,7 @@ describe('useDisplayOptions', () => {
it('toggles between SHOW_DATA_LINKS and SHOW_ROUTER_LINKS correctly', () => {
const { result } = renderHook(() =>
- useDisplayOptions({ defaultSelected: [SHOW_DATA_LINKS], onSelected: mockOnSelected })
+ useDisplayOptionsState({ defaultSelected: [SHOW_DATA_LINKS], onSelected: mockOnSelected })
);
// Initially, SHOW_DATA_LINKS is selected
@@ -56,7 +58,7 @@ describe('useDisplayOptions', () => {
it('clicks on SHOW_DATA_LINKS already checked and SHOW_ROUTER_LINKS correctly', () => {
const { result } = renderHook(() =>
- useDisplayOptions({ defaultSelected: [SHOW_DATA_LINKS], onSelected: mockOnSelected })
+ useDisplayOptionsState({ defaultSelected: [SHOW_DATA_LINKS], onSelected: mockOnSelected })
);
// Initially, SHOW_DATA_LINKS is selected
@@ -69,7 +71,7 @@ describe('useDisplayOptions', () => {
});
it('calls onSelect callback with updated options and selected option', () => {
- const { result } = renderHook(() => useDisplayOptions({ defaultSelected: [], onSelected: mockOnSelected }));
+ const { result } = renderHook(() => useDisplayOptionsState({ defaultSelected: [], onSelected: mockOnSelected }));
const { selectDisplayOptions } = result.current;
act(() => selectDisplayOptions('option1'));
diff --git a/mocks/server.ts b/mocks/server.ts
index 3992badb..95624dce 100644
--- a/mocks/server.ts
+++ b/mocks/server.ts
@@ -1,11 +1,10 @@
import { createServer, Response } from 'miragejs';
-import { Direction } from '@API/REST.enum';
import { PrometheusMetricsV2 } from '@config/prometheus';
import {
ServiceResponse,
ProcessPairsResponse,
- LinkResponse,
+ RouterLinkResponse,
ComponentResponse,
ProcessResponse,
RouterResponse,
@@ -32,7 +31,7 @@ const sitePairs: ResponseWrapper = require(`${path}/SITE_PA
const processPairs: ResponseWrapper = require(`${path}/PROCESS_PAIRS.json`);
const services: ResponseWrapper = require(`${path}/SERVICES.json`);
const flowPairs: ResponseWrapper = require(`${path}/FLOW_PAIRS.json`);
-const links: ResponseWrapper = require(`${path}/LINKS.json`);
+const links: ResponseWrapper = require(`${path}/LINKS.json`);
interface ApiProps {
params: Record;
@@ -100,7 +99,7 @@ for (let i = 0; i < ITEM_COUNT; i++) {
});
}
-const mockLinksForPerf: LinkResponse[] = [];
+const mockLinksForPerf: RouterLinkResponse[] = [];
mockSitePairsForPerf.forEach((_, index) => {
const idx1 = Math.floor(Math.random() * ITEM_COUNT);
const idx2 = Math.floor(Math.random() * ITEM_COUNT);
@@ -111,27 +110,37 @@ mockSitePairsForPerf.forEach((_, index) => {
mockLinksForPerf.push(
{
identity: `link-out-${index}`,
- parent: '',
startTime: 1674048706622878,
endTime: 0,
- mode: 'interior',
- name: '',
- linkCost: 1,
- direction: Direction.Outgoing,
+ role: 'inter-router',
+ name: 'out link',
+ cost: 1,
+ octets: 10,
+ octetsReverse: 100,
+ peer: '',
+ routerId: '',
sourceSiteId: site1.identity,
- destinationSiteId: site2.identity
+ destinationSiteId: site2.identity,
+ sourceSiteName: site1.sourceName,
+ destinationSiteName: site2.destinationName,
+ status: 'up'
},
{
identity: `link-in-${index}`,
- parent: '',
startTime: 1674151543561656,
endTime: 0,
- mode: 'interior',
- name: '',
- linkCost: 1,
- direction: Direction.Incoming,
+ role: 'edge-router',
+ name: 'in link',
+ octets: 205,
+ octetsReverse: 1100,
+ cost: 1,
+ peer: '',
+ routerId: '',
sourceSiteId: site2.identity,
- destinationSiteId: site1.identity
+ destinationSiteId: site1.identity,
+ sourceSiteName: site2.sourceName,
+ destinationSiteName: site1.destinationName,
+ status: 'up'
}
);
});
@@ -395,7 +404,7 @@ export const MockApiPaths = {
ProcessPairs: `${prefix}/processpairs`,
ProcessPair: `${prefix}/processpairs/:id`,
Routers: `${prefix}/routers`,
- Links: `${prefix}/links`,
+ Links: `${prefix}/routerlinks`,
PrometheusQuery: `${prefix}/internal/prom/query/`,
PrometheusRangeQuery: `${prefix}/internal/prom/rangequery/`
};
diff --git a/package.json b/package.json
index 371b0d62..a9a8c6d7 100644
--- a/package.json
+++ b/package.json
@@ -59,10 +59,10 @@
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.13",
- "@types/react": "^18.3.6",
+ "@types/react": "^18.3.7",
"@types/react-dom": "^18.3.0",
- "@typescript-eslint/eslint-plugin": "^8.5.0",
- "@typescript-eslint/parser": "^8.5.0",
+ "@typescript-eslint/eslint-plugin": "^8.6.0",
+ "@typescript-eslint/parser": "^8.6.0",
"commitizen": "^4.3.0",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2",
diff --git a/src/API/Prometheus.queries.ts b/src/API/Prometheus.queries.ts
index d514b4cc..481dd693 100644
--- a/src/API/Prometheus.queries.ts
+++ b/src/API/Prometheus.queries.ts
@@ -1,7 +1,7 @@
import { PrometheusLabelsV2, PrometheusMetricsV2 } from '@config/prometheus';
import { IntervalTimePropValue } from '@sk-types/Prometheus.interfaces';
-import { AvailableProtocols, Quantiles } from './REST.enum';
+import { Protocols, Quantiles } from './REST.enum';
export const queries = {
// data transfer queries
@@ -27,7 +27,7 @@ export const queries = {
// count the number of active tcp flows in the services table
getOpenConnectionsByService() {
- return `sum by(${PrometheusLabelsV2.RoutingKey})(${PrometheusMetricsV2.TcpOpenConnections}{protocol="${AvailableProtocols.Tcp}"}-${PrometheusMetricsV2.TcpCloseCOnnections}{protocol="${AvailableProtocols.Tcp}"})`;
+ return `sum by(${PrometheusLabelsV2.RoutingKey})(${PrometheusMetricsV2.TcpOpenConnections}{protocol="${Protocols.Tcp}"}-${PrometheusMetricsV2.TcpCloseCOnnections}{protocol="${Protocols.Tcp}"})`;
},
// http request queries
diff --git a/src/API/REST.api.ts b/src/API/REST.api.ts
index 4cf0e552..1a3939a0 100644
--- a/src/API/REST.api.ts
+++ b/src/API/REST.api.ts
@@ -4,7 +4,7 @@ import {
ProcessResponse,
FlowPairsResponse,
SiteResponse,
- LinkResponse,
+ RouterLinkResponse,
ProcessPairsResponse,
QueryFilters,
ResponseWrapper,
@@ -16,7 +16,6 @@ import {
import { axiosFetch } from './apiMiddleware';
import {
getSitePATH,
- getLinksBySitePATH,
getComponentPATH,
geProcessPATH,
getLinkPATH,
@@ -63,14 +62,6 @@ export const RESTApi = {
return data;
},
- fetchLinksBySite: async (id: string, options?: QueryFilters): Promise> => {
- const data = await axiosFetch>(getLinksBySitePATH(id), {
- params: options ? mapQueryFiltersToQueryParams(options) : null
- });
-
- return data;
- },
-
// PROCESS APIs
fetchProcesses: async (options?: QueryFilters): Promise> => {
const data = await axiosFetch>(geProcessesPATH(), {
@@ -106,16 +97,16 @@ export const RESTApi = {
},
// LINKS APIs
- fetchLinks: async (options?: QueryFilters): Promise> => {
- const data = await axiosFetch>(getLinksPATH(), {
+ fetchLinks: async (options?: QueryFilters): Promise> => {
+ const data = await axiosFetch>(getLinksPATH(), {
params: options ? mapQueryFiltersToQueryParams(options) : null
});
return data;
},
- fetchLink: async (id: string, options?: QueryFilters): Promise> => {
- const data = await axiosFetch>(getLinkPATH(id), {
+ fetchLink: async (id: string, options?: QueryFilters): Promise> => {
+ const data = await axiosFetch>(getLinkPATH(id), {
params: options ? mapQueryFiltersToQueryParams(options) : null
});
diff --git a/src/API/REST.enum.ts b/src/API/REST.enum.ts
index efd3f204..afdf8dcc 100644
--- a/src/API/REST.enum.ts
+++ b/src/API/REST.enum.ts
@@ -3,7 +3,7 @@ export enum SortDirection {
DESC = 'desc'
}
-export enum AvailableProtocols {
+export enum Protocols {
Tcp = 'tcp',
Http = 'http1',
Http2 = 'http2',
diff --git a/src/API/REST.paths.ts b/src/API/REST.paths.ts
index 0ea72d49..38e119f6 100644
--- a/src/API/REST.paths.ts
+++ b/src/API/REST.paths.ts
@@ -1,14 +1,15 @@
import { API_URL } from '@config/config';
+import { composePath } from './REST.utils';
+
export const getUser = () => `${API_URL}/user`;
export const logout = () => `${API_URL}/logout?nonce=${Date.now()}`;
const SITES_PATH = `${API_URL}/sites`;
export const getSitesPATH = () => SITES_PATH;
export const getSitePATH = (id: string) => composePath([SITES_PATH, id]);
-export const getLinksBySitePATH = (id: string) => composePath([SITES_PATH, id, 'links']);
-const LINKS_PATH = `${API_URL}/links`;
+const LINKS_PATH = `${API_URL}/routerlinks`;
export const getLinksPATH = () => LINKS_PATH;
export const getLinkPATH = (id: string) => composePath([LINKS_PATH, id]);
@@ -40,7 +41,3 @@ export const getComponentPairPATH = (id: string) => composePath([COMPONENT_PAIRS
const PROCESS_PAIRS_PATH = `${API_URL}/processpairs`;
export const getProcessPairsPATH = () => PROCESS_PAIRS_PATH;
export const getProcessPairPairPATH = (id: string) => composePath([PROCESS_PAIRS_PATH, id]);
-
-function composePath(elements: string[]) {
- return elements.join('/');
-}
diff --git a/src/API/REST.utils.ts b/src/API/REST.utils.ts
index 745ba460..10850943 100644
--- a/src/API/REST.utils.ts
+++ b/src/API/REST.utils.ts
@@ -2,9 +2,6 @@ import { QueryParams, QueryFilters } from '@sk-types/REST.interfaces';
import { SortDirection } from './REST.enum';
-/**
- * Maps an options object to query parameters for an HTTP request.
- */
export function mapQueryFiltersToQueryParams({
filter,
offset,
@@ -25,3 +22,12 @@ export function mapQueryFiltersToQueryParams({
...queryParams
};
}
+
+/**
+ * Composes a path from an array of elements.
+ * @param {string[]} elements - An array of elements that will be joined together to form the path.
+ * @returns {string} - The composed path as a string.
+ */
+export function composePath(elements: string[]): string {
+ return elements.join('/');
+}
diff --git a/src/core/components/SkFlowPairsTable/FlowPair.tsx b/src/core/components/SkFlowPairsTable/FlowPair.tsx
index 04ee58b1..e10db602 100644
--- a/src/core/components/SkFlowPairsTable/FlowPair.tsx
+++ b/src/core/components/SkFlowPairsTable/FlowPair.tsx
@@ -19,7 +19,7 @@ import {
import { LaptopIcon, ServerIcon } from '@patternfly/react-icons';
import { Link } from 'react-router-dom';
-import { AvailableProtocols } from '@API/REST.enum';
+import { Protocols } from '@API/REST.enum';
import { getTestsIds } from '@config/testIds';
import ResourceIcon from '@core/components/ResourceIcon';
import { formatBytes } from '@core/utils/formatBytes';
@@ -37,7 +37,7 @@ interface FlowPairProps {
const FlowPair: FC = function ({ flowPair }) {
const { protocol, endTime: endTimeMicroSeconds, identity, traceSites, duration } = flowPair;
- const hasHttp = protocol === AvailableProtocols.Http || protocol === AvailableProtocols.Http2;
+ const hasHttp = protocol === Protocols.Http || protocol === Protocols.Http2;
return (
@@ -97,14 +97,14 @@ const FlowPair: FC = function ({ flowPair }) {
- {flowPair.protocol === AvailableProtocols.Tcp ? (
+ {flowPair.protocol === Protocols.Tcp ? (
) : (
)}
- {flowPair.protocol === AvailableProtocols.Tcp ? (
+ {flowPair.protocol === Protocols.Tcp ? (
) : (
diff --git a/src/core/components/SkGraph/services/index.ts b/src/core/components/SkGraph/services/index.ts
index f2bff0af..88ca5099 100644
--- a/src/core/components/SkGraph/services/index.ts
+++ b/src/core/components/SkGraph/services/index.ts
@@ -144,19 +144,22 @@ export const GraphController = {
edges: EdgeData[];
combos?: ComboData[];
} => {
+ // Match the combo of the node with the existing combos
+ const comboIds = combos?.map(({ id }) => id);
+
+ // find bidirectional edges
const transformedEdges = markPairs(sanitizeEdges(nodes, edges)) as (GraphEdge & {
hasPair: boolean;
})[];
- // Match the combo of the node with the existing combos
- const comboIds = combos?.map(({ id }) => id);
// calculate the visual distribution of the metrics
const edgeMetrics = transformedEdges.map(({ metricValue, source, target }) =>
- // remove metrics within the same site
source === target ? 0 : metricValue || 0
);
const maxMetricValue = Math.max(...edgeMetrics);
- const minMetricValue = Math.min(...edgeMetrics.filter((metric) => metric)) || 0;
+ //exclude metric values that are 0
+ //the fallback ensures that if the filtered result is empty, we get 0 instead of potentially Infinity or NaN
+ const minMetricValue = Math.min(...edgeMetrics.filter(Boolean)) || 0;
return {
nodes: nodes
diff --git a/src/core/utils/getIdAndNameFromUrlParams.ts b/src/core/utils/getIdAndNameFromUrlParams.ts
index 60e85b05..d64e1ab1 100644
--- a/src/core/utils/getIdAndNameFromUrlParams.ts
+++ b/src/core/utils/getIdAndNameFromUrlParams.ts
@@ -1,7 +1,7 @@
-import { AvailableProtocols } from '@API/REST.enum';
+import { Protocols } from '@API/REST.enum';
export function getIdAndNameFromUrlParams(urlParams: string) {
const params = urlParams.split('@');
- return { name: params[0], id: params[1], protocol: params[2] as AvailableProtocols };
+ return { name: params[0], id: params[1], protocol: params[2] as Protocols };
}
diff --git a/src/pages/ProcessGroups/components/Overview..tsx b/src/pages/ProcessGroups/components/Overview..tsx
index a1230927..bd1649ec 100644
--- a/src/pages/ProcessGroups/components/Overview..tsx
+++ b/src/pages/ProcessGroups/components/Overview..tsx
@@ -2,7 +2,7 @@ import { FC } from 'react';
import { extractUniqueValues } from '@core/utils/extractUniqueValues';
import Metrics from '@pages/shared/Metrics';
-import { useMetricSessionHandlers } from '@pages/shared/Metrics/hooks/useSessionHandler';
+import { useMetricSessionHandlers } from '@pages/shared/Metrics/hooks/useMetricsSessionHandler';
import { ComponentResponse, ProcessResponse } from '@sk-types/REST.interfaces';
import { useComponentOverviewData } from '../hooks/useOverviewData';
diff --git a/src/pages/ProcessGroups/components/ProcessList.tsx b/src/pages/ProcessGroups/components/ProcessList.tsx
index 1e8517c4..34381d7c 100644
--- a/src/pages/ProcessGroups/components/ProcessList.tsx
+++ b/src/pages/ProcessGroups/components/ProcessList.tsx
@@ -3,7 +3,6 @@ import { FC } from 'react';
import SkTable from '@core/components/SkTable';
import { setColumnVisibility } from '@core/components/SkTable/SkTable.utils';
import { CustomProcessCells, processesTableColumns } from '@pages/Processes/Processes.constants';
-import { ProcessesLabels } from '@pages/Processes/Processes.enum';
import { ProcessResponse } from '@sk-types/REST.interfaces';
interface ProcessListProps {
@@ -13,7 +12,6 @@ interface ProcessListProps {
const ProcessList: FC = function ({ processes }) {
return (
) =>
SkLinkCell({
...props,
@@ -28,7 +28,13 @@ export const CustomProcessPairCells = {
ByteRateFormatCell: (props: SkHighlightValueCellProps) =>
SkHighlightValueCell({ ...props, format: formatByteRate }),
LatencyFormatCell: (props: SkHighlightValueCellProps) =>
- SkHighlightValueCell({ ...props, format: formatLatency })
+ SkHighlightValueCell({ ...props, format: formatLatency }),
+ viewDetailsLinkCell: (props: SkLinkCellProps) =>
+ SkLinkCell({
+ ...props,
+ value: ProcessesLabels.GoToDetailsLink,
+ link: `${ProcessesRoutesPaths.Processes}/${props.data.sourceName}@${props.data.sourceId}/${ProcessesLabels.ProcessPairs}@${props.data.identity}?type=${ProcessesLabels.ProcessPairs}`
+ })
};
export const CustomProcessCells = {
diff --git a/src/pages/Processes/Processes.enum.ts b/src/pages/Processes/Processes.enum.ts
index b57402e4..3b88d94d 100644
--- a/src/pages/Processes/Processes.enum.ts
+++ b/src/pages/Processes/Processes.enum.ts
@@ -24,7 +24,7 @@ export enum ProcessesLabels {
Overview = 'Overview',
Description = 'A process represents running application code. On Kubernetes, a process is a pod. On Docker or Podman, a process is a container. On virtual machines or bare metal hosts',
Details = 'Details',
- ProcessPairs = 'Process pairs',
+ ProcessPairs = 'Pairs',
Processes = 'Processes',
Services = 'Routing keys',
Process = 'Process',
@@ -54,8 +54,8 @@ export enum ProcessesLabels {
OldConnections = 'Connection history',
ProcessPairsEmptyTitle = 'No connections or requests to display',
ProcessPairsEmptyMessage = 'As new connections or requests are established, they will be dynamically added to the table for display',
- GoToDetails = 'View details',
- Title = 'Process pair details',
+ GoToDetailsLink = 'View details',
+ Title = 'Pair details',
Protocol = 'Protocol',
Bytes = 'Bytes',
ByteRate = 'Byterate',
diff --git a/src/pages/Processes/Processes.utls.ts b/src/pages/Processes/Processes.utls.ts
new file mode 100644
index 00000000..811b6271
--- /dev/null
+++ b/src/pages/Processes/Processes.utls.ts
@@ -0,0 +1,32 @@
+import { Protocols } from '@API/REST.enum';
+import { ProcessPairsResponse } from '@sk-types/REST.interfaces';
+
+export const filterPairsByProtocols = (clients: ProcessPairsResponse[], servers: ProcessPairsResponse[]) => {
+ const TCPClients = clients.filter(({ protocol }) => protocol === Protocols.Tcp);
+ const TCPServers = servers.filter(({ protocol }) => protocol === Protocols.Tcp);
+
+ const HTTPClients = clients.filter(({ protocol }) => [Protocols.Http, Protocols.Http2].includes(protocol));
+ const HTTPServers = servers.filter(({ protocol }) => [Protocols.Http, Protocols.Http2].includes(protocol));
+
+ const remoteClients = clients.filter(({ protocol }) => protocol === undefined);
+ const remoteServers = servers.filter(({ protocol }) => protocol === undefined);
+
+ return {
+ TCPClients,
+ TCPServers,
+ HTTPClients,
+ HTTPServers,
+ remoteClients,
+ remoteServers
+ };
+};
+
+export function invertProcessPairsList(processPairs: ProcessPairsResponse[]): ProcessPairsResponse[] {
+ return processPairs.map((pair) => ({
+ ...pair,
+ sourceId: pair.destinationId,
+ sourceName: pair.destinationName,
+ destinationId: pair.sourceId,
+ destinationName: pair.sourceName
+ }));
+}
diff --git a/src/pages/Processes/components/FlowPairsList.tsx b/src/pages/Processes/components/FlowPairsList.tsx
index 28bb1746..f7fdaa86 100644
--- a/src/pages/Processes/components/FlowPairsList.tsx
+++ b/src/pages/Processes/components/FlowPairsList.tsx
@@ -5,7 +5,7 @@ import { ResourcesEmptyIcon } from '@patternfly/react-icons';
import { useSuspenseQuery } from '@tanstack/react-query';
import { RESTApi } from '@API/REST.api';
-import { AvailableProtocols, SortDirection, TcpStatus } from '@API/REST.enum';
+import { Protocols, SortDirection, TcpStatus } from '@API/REST.enum';
import { DEFAULT_PAGINATION_SIZE, UPDATE_INTERVAL } from '@config/config';
import SKEmptyData from '@core/components/SkEmptyData';
import SkFlowPairsTable from '@core/components/SkFlowPairsTable';
@@ -32,30 +32,30 @@ const initPaginatedFlowPairsQueryParams: QueryFilters = {
const initPaginatedHttpRequestsQueryParams: QueryFilters = {
...initPaginatedFlowPairsQueryParams,
- protocol: AvailableProtocols.Http
+ protocol: Protocols.Http
};
const initPaginatedHttp2RequestsQueryParams: QueryFilters = {
...initPaginatedFlowPairsQueryParams,
- protocol: AvailableProtocols.Http2
+ protocol: Protocols.Http2
};
const initPaginatedActiveConnectionsQueryParams: QueryFilters = {
...initPaginatedFlowPairsQueryParams,
- protocol: AvailableProtocols.Tcp,
+ protocol: Protocols.Tcp,
state: TcpStatus.Active
};
const initPaginatedOldConnectionsQueryParams: QueryFilters = {
...initPaginatedFlowPairsQueryParams,
- protocol: AvailableProtocols.Tcp,
+ protocol: Protocols.Tcp,
state: TcpStatus.Terminated
};
const initPaginatedQueryParams: QueryFiltersProtocolMap = {
- [AvailableProtocols.Http]: initPaginatedHttpRequestsQueryParams,
- [AvailableProtocols.Http2]: initPaginatedHttp2RequestsQueryParams,
- [AvailableProtocols.Tcp]: {
+ [Protocols.Http]: initPaginatedHttpRequestsQueryParams,
+ [Protocols.Http2]: initPaginatedHttp2RequestsQueryParams,
+ [Protocols.Tcp]: {
active: initPaginatedActiveConnectionsQueryParams,
old: initPaginatedOldConnectionsQueryParams
}
@@ -83,7 +83,7 @@ const useFlowPairsQuery = (
return data;
};
-const useProcessPairsContent = ({ protocol }: { protocol: AvailableProtocols | 'undefined' }) => {
+const useProcessPairsContent = ({ protocol }: { protocol: Protocols | 'undefined' }) => {
const [queryParamsPaginated, setQueryParamsPaginated] = useState(initPaginatedQueryParams);
const handleGetFilters = useCallback(
@@ -110,7 +110,7 @@ const useProcessPairsContent = ({ protocol }: { protocol: AvailableProtocols | '
interface FlowPairsListProps {
sourceProcessId: string;
destProcessId: string;
- protocol: AvailableProtocols | 'undefined';
+ protocol: Protocols | 'undefined';
}
const FlowPairsList: FC = function ({ sourceProcessId, destProcessId, protocol }) {
@@ -125,28 +125,28 @@ const FlowPairsList: FC = function ({ sourceProcessId, destP
const { results: httpRequests, count: httpRequestsCount } = extractData(
useFlowPairsQuery(
- queryParamsPaginated[AvailableProtocols.Http],
+ queryParamsPaginated[Protocols.Http],
sourceProcessId,
destProcessId,
- AvailableProtocols.Http === protocol || protocol === 'undefined'
+ Protocols.Http === protocol || protocol === 'undefined'
)
);
const { results: http2Requests, count: http2RequestsCount } = extractData(
useFlowPairsQuery(
- queryParamsPaginated[AvailableProtocols.Http2],
+ queryParamsPaginated[Protocols.Http2],
sourceProcessId,
destProcessId,
- AvailableProtocols.Http2 === protocol || protocol === 'undefined'
+ Protocols.Http2 === protocol || protocol === 'undefined'
)
);
const { results: activeConnections, count: activeConnectionsCount } = extractData(
- useFlowPairsQuery(queryParamsPaginated[AvailableProtocols.Tcp].active, sourceProcessId, destProcessId, true)
+ useFlowPairsQuery(queryParamsPaginated[Protocols.Tcp].active, sourceProcessId, destProcessId, true)
);
const { results: oldConnections, count: oldConnectionsCount } = extractData(
- useFlowPairsQuery(queryParamsPaginated[AvailableProtocols.Tcp].old, sourceProcessId, destProcessId, true)
+ useFlowPairsQuery(queryParamsPaginated[Protocols.Tcp].old, sourceProcessId, destProcessId, true)
);
const activeTab = tabSelected
@@ -161,100 +161,101 @@ const FlowPairsList: FC = function ({ sourceProcessId, destP
? TAB_4_KEY
: '';
+ if (!activeConnectionsCount && !oldConnectionsCount) {
+ return (
+
+
+
+
+
+ );
+ }
+
return (
- <>
- {!activeConnectionsCount && !oldConnectionsCount && (
-
-
-
-
-
+
+ {!!activeConnectionsCount && (
+ {ProcessesLabels.OpenConnections}}>
+ handleGetFilters(filters, 'active')}
+ />
+
+ )}
+
+ {!!oldConnectionsCount && (
+ {ProcessesLabels.OldConnections}}
+ >
+ handleGetFilters(filters, 'old')}
+ />
+
+ )}
+
+ {!!http2RequestsCount && (
+ {ProcessesLabels.Http2Requests}}
+ >
+
+
+ )}
+
+ {!!httpRequestsCount && (
+ {ProcessesLabels.HttpRequests}}
+ >
+
+
)}
-
- {!!activeConnectionsCount && (
- {ProcessesLabels.OpenConnections}}>
- handleGetFilters(filters, 'active')}
- />
-
- )}
-
- {!!oldConnectionsCount && (
- {ProcessesLabels.OldConnections}}
- >
- handleGetFilters(filters, 'old')}
- />
-
- )}
-
- {!!http2RequestsCount && (
- {ProcessesLabels.Http2Requests}}
- >
-
-
- )}
-
- {!!httpRequestsCount && (
- {ProcessesLabels.HttpRequests}}
- >
-
-
- )}
-
- >
+
);
};
diff --git a/src/pages/Processes/components/Overview.tsx b/src/pages/Processes/components/Overview.tsx
index 1dffdce0..d7d97384 100644
--- a/src/pages/Processes/components/Overview.tsx
+++ b/src/pages/Processes/components/Overview.tsx
@@ -3,7 +3,7 @@ import { FC } from 'react';
import { extractUniqueValues } from '@core/utils/extractUniqueValues';
import { mapDataToMetricFilterOptions } from '@core/utils/getResourcesFromPairs';
import Metrics from '@pages/shared/Metrics';
-import { useMetricSessionHandlers } from '@pages/shared/Metrics/hooks/useSessionHandler';
+import { useMetricSessionHandlers } from '@pages/shared/Metrics/hooks/useMetricsSessionHandler';
import { ProcessResponse } from '@sk-types/REST.interfaces';
import { useProcessOverviewData } from '../hooks/useOverviewData';
diff --git a/src/pages/Processes/components/PairsList.tsx b/src/pages/Processes/components/PairsList.tsx
new file mode 100644
index 00000000..85aceed6
--- /dev/null
+++ b/src/pages/Processes/components/PairsList.tsx
@@ -0,0 +1,84 @@
+import { FC, useMemo } from 'react';
+
+import { Card, Flex } from '@patternfly/react-core';
+import { SearchIcon } from '@patternfly/react-icons';
+
+import { SMALL_PAGINATION_SIZE } from '@config/config';
+import { PrometheusLabelsV2 } from '@config/prometheus';
+import SKEmptyData from '@core/components/SkEmptyData';
+import SkTable from '@core/components/SkTable';
+import { TopologyController } from '@pages/Topology/services';
+import { ProcessPairsResponse, ProcessResponse } from '@sk-types/REST.interfaces';
+import { SKTableColumn } from '@sk-types/SkTable.interfaces';
+
+import { useProcessPairsListData } from '../hooks/useProcessPairsListData';
+import { CustomPairsCells, processesConnectedColumns, processesHttpConnectedColumns } from '../Processes.constants';
+import { ProcessesLabels } from '../Processes.enum';
+import { filterPairsByProtocols, invertProcessPairsList } from '../Processes.utls';
+
+interface PairsListProps {
+ process: ProcessResponse;
+}
+
+const PairsList: FC = function ({ process: { identity: id, name } }) {
+ const { pairsTx, pairsRx, metricsTx, metricsRx } = useProcessPairsListData(id, name);
+
+ const clients = invertProcessPairsList(
+ TopologyController.addMetricsToPairs({
+ processesPairs: pairsRx,
+ metrics: metricsRx,
+ prometheusKey: PrometheusLabelsV2.SourceProcess,
+ processPairsKey: 'sourceName'
+ })
+ );
+
+ const servers = TopologyController.addMetricsToPairs({
+ processesPairs: pairsTx,
+ metrics: metricsTx,
+ prometheusKey: PrometheusLabelsV2.DestProcess,
+ processPairsKey: 'destinationName'
+ });
+ const { TCPClients, TCPServers, HTTPClients, HTTPServers, remoteClients, remoteServers } = useMemo(
+ () => filterPairsByProtocols(clients, servers),
+ [clients, servers]
+ );
+
+ const renderTable = (title: string, rows: ProcessPairsResponse[], columns: SKTableColumn[]) =>
+ !!rows.length && (
+
+ );
+
+ return (
+ <>
+ {!TCPClients.length &&
+ !TCPServers.length &&
+ !HTTPClients.length &&
+ !HTTPServers.length &&
+ !remoteClients.length &&
+ !remoteServers.length && (
+
+
+
+ )}
+
+
+ {renderTable(ProcessesLabels.TCPClients, TCPClients, processesConnectedColumns)}
+ {renderTable(ProcessesLabels.TCPServers, TCPServers, processesConnectedColumns)}
+ {renderTable(ProcessesLabels.HTTPClients, HTTPClients, processesHttpConnectedColumns)}
+ {renderTable(ProcessesLabels.HTTPServers, HTTPServers, processesHttpConnectedColumns)}
+ {renderTable(ProcessesLabels.RemoteClients, remoteClients, processesConnectedColumns)}
+ {renderTable(ProcessesLabels.RemoteServers, remoteServers, processesConnectedColumns)}
+
+ >
+ );
+};
+
+export default PairsList;
diff --git a/src/pages/Processes/components/ProcessPairsDetails.tsx b/src/pages/Processes/components/ProcessPairDetails.tsx
similarity index 89%
rename from src/pages/Processes/components/ProcessPairsDetails.tsx
rename to src/pages/Processes/components/ProcessPairDetails.tsx
index adfd9092..51749701 100644
--- a/src/pages/Processes/components/ProcessPairsDetails.tsx
+++ b/src/pages/Processes/components/ProcessPairDetails.tsx
@@ -10,12 +10,12 @@ import { ProcessResponse } from '@sk-types/REST.interfaces';
import Details from './Details';
import { ProcessesRoutesPaths } from '../Processes.enum';
-interface ProcessPairsDetailsProps {
+interface ProcessPairDetailsProps {
source: ProcessResponse;
destination: ProcessResponse;
}
-const ProcessPairsDetails: FC = function ({ source, destination }) {
+const ProcessPairDetails: FC = function ({ source, destination }) {
return (
@@ -51,4 +51,4 @@ const ProcessPairsDetails: FC = function ({ source, de
);
};
-export default ProcessPairsDetails;
+export default ProcessPairDetails;
diff --git a/src/pages/Processes/components/ProcessPairsList.tsx b/src/pages/Processes/components/ProcessPairsList.tsx
deleted file mode 100644
index 29db8701..00000000
--- a/src/pages/Processes/components/ProcessPairsList.tsx
+++ /dev/null
@@ -1,166 +0,0 @@
-import { FC } from 'react';
-
-import { Card, Flex } from '@patternfly/react-core';
-import { SearchIcon } from '@patternfly/react-icons';
-import { Link } from 'react-router-dom';
-
-import { AvailableProtocols } from '@API/REST.enum';
-import { SMALL_PAGINATION_SIZE } from '@config/config';
-import { PrometheusLabelsV2 } from '@config/prometheus';
-import SKEmptyData from '@core/components/SkEmptyData';
-import { SkLinkCellProps } from '@core/components/SkLinkCell';
-import SkTable from '@core/components/SkTable';
-import { TopologyController } from '@pages/Topology/services';
-import { ProcessPairsResponse, ProcessResponse } from '@sk-types/REST.interfaces';
-
-import { useProcessPairsListData } from '../hooks/useProcessPairsListData';
-import {
- CustomProcessPairCells,
- processesConnectedColumns,
- processesHttpConnectedColumns
-} from '../Processes.constants';
-import { ProcessesLabels, ProcessesRoutesPaths } from '../Processes.enum';
-
-interface ProcessesPairsListProps {
- process: ProcessResponse;
-}
-
-const ProcessPairsList: FC = function ({ process: { identity: id, name } }) {
- const { pairsTx, pairsRx, metricsTx, metricsRx } = useProcessPairsListData(id, name);
-
- const clients = TopologyController.addMetricsToTopologyDetails({
- processesPairs: pairsRx,
- metrics: metricsRx,
- prometheusKey: PrometheusLabelsV2.SourceProcess,
- processPairsKey: 'sourceName'
- });
-
- const servers = TopologyController.addMetricsToTopologyDetails({
- processesPairs: pairsTx,
- metrics: metricsTx,
- prometheusKey: PrometheusLabelsV2.DestProcess,
- processPairsKey: 'destinationName'
- });
-
- const processesPairsRxReverse =
- (clients || []).map((processPairsData) => ({
- ...processPairsData,
- sourceId: processPairsData.destinationId,
- sourceName: processPairsData.destinationName,
- destinationName: processPairsData.sourceName,
- destinationId: processPairsData.sourceId
- })) || [];
-
- const TCPServers = (servers || []).filter(({ protocol }) => protocol === AvailableProtocols.Tcp);
- const TCPClients = processesPairsRxReverse.filter(({ protocol }) => protocol === AvailableProtocols.Tcp);
-
- const HTTPServers = (servers || []).filter(
- ({ protocol }) => protocol === AvailableProtocols.Http || protocol === AvailableProtocols.Http2
- );
- const HTTPClients = processesPairsRxReverse.filter(
- ({ protocol }) => protocol === AvailableProtocols.Http || protocol === AvailableProtocols.Http2
- );
- const remoteServers = (servers || []).filter(({ protocol }) => protocol === undefined);
- const remoteClients = processesPairsRxReverse.filter(({ protocol }) => protocol === undefined);
-
- const CustomProcessPairCellsWithLinkDetail = {
- ...CustomProcessPairCells,
- viewDetailsLinkCell: ({ data }: SkLinkCellProps) => (
-
- view pairs
-
- )
- };
-
- return (
- <>
- {!TCPClients.length &&
- !TCPServers.length &&
- !HTTPClients.length &&
- !HTTPServers.length &&
- !remoteClients.length &&
- !remoteServers.length && (
-
-
-
- )}
-
- {!!TCPClients.length && (
-
- )}
-
- {!!TCPServers.length && (
-
- )}
-
- {!!HTTPClients.length && (
-
- )}
-
- {!!HTTPServers.length && (
-
- )}
-
- {!!remoteClients.length && (
-
- )}
-
- {!!remoteServers.length && (
-
- )}
-
- >
- );
-};
-
-export default ProcessPairsList;
diff --git a/src/pages/Processes/hooks/useProcessPairsData.ts b/src/pages/Processes/hooks/useProcessPairsData.ts
index 95d4c56e..28de4a3b 100644
--- a/src/pages/Processes/hooks/useProcessPairsData.ts
+++ b/src/pages/Processes/hooks/useProcessPairsData.ts
@@ -17,12 +17,8 @@ export const useProcessPairData = ({ id }: useProcessPairDataProps) => {
const sourceId = data.results.sourceId;
const destId = data.results.destinationId;
- const [{ data: processPairs }, { data: source }, { data: destination }] = useSuspenseQueries({
+ const [{ data: source }, { data: destination }] = useSuspenseQueries({
queries: [
- {
- queryKey: [QueriesProcesses.GetProcessPair, id],
- queryFn: () => RESTApi.fetchProcessesPair(id)
- },
{
queryKey: [QueriesProcesses.GetProcess, sourceId],
queryFn: () => RESTApi.fetchProcess(sourceId)
@@ -34,5 +30,5 @@ export const useProcessPairData = ({ id }: useProcessPairDataProps) => {
]
});
- return { processPairs: processPairs.results, source: source.results, destination: destination.results };
+ return { processPair: data.results, source: source.results, destination: destination.results };
};
diff --git a/src/pages/Processes/routes.tsx b/src/pages/Processes/routes.tsx
index 7ea5cce9..b2ec510a 100644
--- a/src/pages/Processes/routes.tsx
+++ b/src/pages/Processes/routes.tsx
@@ -4,7 +4,7 @@ import { ProcessesRoutesPaths } from './Processes.enum';
const Processes = lazy(() => import(/* webpackChunkName: "processes" */ './views/Processes'));
const Process = lazy(() => import(/* webpackChunkName: "process" */ './views/Process'));
-const ProcessFlowPairs = lazy(() => import(/* webpackChunkName: "process-flowpairs" */ './views/ProcessPairs'));
+const ProcessPair = lazy(() => import(/* webpackChunkName: "process-pair" */ './views/ProcessPair'));
export const processesRoutes = [
{
@@ -17,6 +17,6 @@ export const processesRoutes = [
},
{
path: `${ProcessesRoutesPaths.Processes}/:process/:id`,
- element:
+ element:
}
];
diff --git a/src/pages/Processes/views/Process.tsx b/src/pages/Processes/views/Process.tsx
index 46dac80d..5dffeff5 100644
--- a/src/pages/Processes/views/Process.tsx
+++ b/src/pages/Processes/views/Process.tsx
@@ -11,7 +11,7 @@ import useUpdateQueryStringValueWithoutNavigation from 'hooks/useUpdateQueryStri
import Details from '../components/Details';
import Overview from '../components/Overview';
-import ProcessPairsList from '../components/ProcessPairsList';
+import PairsList from '../components/PairsList';
import { useProcessData } from '../hooks/useProcessData';
import { ProcessesLabels } from '../Processes.enum';
@@ -57,7 +57,7 @@ const ProcessContent: FC = function ({ id, defaultTab }) {
<>
{tabSelected === ProcessesLabels.Overview && }
{tabSelected === ProcessesLabels.Details && }
- {tabSelected === ProcessesLabels.ProcessPairs && }
+ {tabSelected === ProcessesLabels.ProcessPairs && }
>
}
/>
diff --git a/src/pages/Processes/views/ProcessPairs.tsx b/src/pages/Processes/views/ProcessPair.tsx
similarity index 77%
rename from src/pages/Processes/views/ProcessPairs.tsx
rename to src/pages/Processes/views/ProcessPair.tsx
index 4b5158db..476736f2 100644
--- a/src/pages/Processes/views/ProcessPairs.tsx
+++ b/src/pages/Processes/views/ProcessPair.tsx
@@ -9,16 +9,16 @@ import MainContainer from '@layout/MainContainer';
import { TopologyRoutesPaths, TopologyURLQueyParams, TopologyViews } from '@pages/Topology/Topology.enum';
import FlowPairsList from '../components/FlowPairsList';
-import ProcessPairDetails from '../components/ProcessPairsDetails';
+import ProcessPairDetails from '../components/ProcessPairDetails';
import { useProcessPairData } from '../hooks/useProcessPairsData';
import { ProcessesLabels } from '../Processes.enum';
-export interface ProcessPairsProps {
+export interface ProcessPairProps {
id: string;
}
-export const ProcessPairsContent: FC = function ({ id }) {
- const { processPairs, source, destination } = useProcessPairData({ id });
+export const ProcessPairContent: FC = function ({ id }) {
+ const { processPair, source, destination } = useProcessPairData({ id });
return (
= function ({ id }) {
@@ -44,11 +44,11 @@ export const ProcessPairsContent: FC = function ({ id }) {
);
};
-const ProcessPairs = function () {
+const ProcessPair = function () {
const { id: paramId } = useParams();
const { id } = getIdAndNameFromUrlParams(paramId as string);
- return ;
+ return ;
};
-export default ProcessPairs;
+export default ProcessPair;
diff --git a/src/pages/Services/Services.constants.ts b/src/pages/Services/Services.constants.ts
index 5cc261c8..21bc80f4 100644
--- a/src/pages/Services/Services.constants.ts
+++ b/src/pages/Services/Services.constants.ts
@@ -4,7 +4,7 @@ import SkEndTimeCell from '@core/components/SkEndTimeCell';
import SkLinkCell, { SkLinkCellProps } from '@core/components/SkLinkCell';
import { sankeyMetricOptions } from '@core/components/SKSanckeyChart/SkSankey.constants';
import { ProcessesLabels } from '@pages/Processes/Processes.enum';
-import { ServiceResponse, ProcessResponse, QueryFilters } from '@sk-types/REST.interfaces';
+import { ServiceResponse, QueryFilters } from '@sk-types/REST.interfaces';
import { SKTableColumn } from 'types/SkTable.interfaces';
import { ServicesRoutesPaths, ServicesLabels } from './Services.enum';
@@ -68,31 +68,6 @@ export const ServiceColumns: SKTableColumn[] = [
}
];
-// Server Table
-export const tcpServerColumns: SKTableColumn[] = [
- {
- name: ProcessesLabels.Name,
- prop: 'name' as keyof ProcessResponse,
- customCellName: 'linkCell'
- },
- {
- name: ProcessesLabels.Site,
- prop: 'parentName' as keyof ProcessResponse,
- customCellName: 'linkCellSite'
- },
- {
- name: ProcessesLabels.Component,
- prop: 'groupName' as keyof ProcessResponse,
- customCellName: 'linkComponentCell'
- },
- {
- name: ProcessesLabels.Created,
- prop: 'startTime' as keyof ProcessResponse,
- customCellName: 'TimestampCell',
- width: 15
- }
-];
-
export const servicesSelectOptions: { name: string; id: string }[] = [
{
name: 'Routing key',
diff --git a/src/pages/Services/components/NavigationMenu.tsx b/src/pages/Services/components/NavigationMenu.tsx
index d0d5a668..c46109cc 100644
--- a/src/pages/Services/components/NavigationMenu.tsx
+++ b/src/pages/Services/components/NavigationMenu.tsx
@@ -2,7 +2,7 @@ import { FC } from 'react';
import { Tab, TabTitleText, Tabs } from '@patternfly/react-core';
-import { AvailableProtocols } from '@API/REST.enum';
+import { Protocols } from '@API/REST.enum';
import { TopologyURLQueyParams } from '@pages/Topology/Topology.enum';
import useUpdateQueryStringValueWithoutNavigation from 'hooks/useUpdateQueryStringValueWithoutNavigation';
@@ -10,7 +10,7 @@ import { TAB_0_KEY, TAB_1_KEY, TAB_2_KEY, TAB_3_KEY, TAB_4_KEY } from '../Servic
import { ServicesLabels } from '../Services.enum';
interface NavigationMenuProps {
- protocol: AvailableProtocols | undefined;
+ protocol: Protocols | undefined;
serverCount: number;
requestsCount: number;
tcpActiveConnectionCount: number;
@@ -51,7 +51,7 @@ const NavigationMenu: FC = function ({
eventKey={TAB_4_KEY}
title={{ServicesLabels.OldConnections}}
/>
- {protocol !== AvailableProtocols.Tcp && (
+ {protocol !== Protocols.Tcp && (
= function ({ id }) {
+ const { processes } = useServersData(id);
+
+ return (
+
+ );
+};
+
+export default ProcessServerList;
diff --git a/src/pages/Services/components/Servers.tsx b/src/pages/Services/components/Servers.tsx
deleted file mode 100644
index e0471c88..00000000
--- a/src/pages/Services/components/Servers.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { FC } from 'react';
-
-import { BIG_PAGINATION_SIZE } from '@config/config';
-import SkTable from '@core/components/SkTable';
-import { CustomProcessCells } from '@pages/Processes/Processes.constants';
-
-import { useServersData } from '../hooks/useServersData';
-import { tcpServerColumns } from '../Services.constants';
-
-interface ServersProps {
- id: string;
-}
-
-const Servers: FC = function ({ id }) {
- const { servers } = useServersData(id);
-
- return (
-
- );
-};
-
-export default Servers;
diff --git a/src/pages/Services/hooks/useServersData.ts b/src/pages/Services/hooks/useServersData.ts
index f090c750..72b0f9ee 100644
--- a/src/pages/Services/hooks/useServersData.ts
+++ b/src/pages/Services/hooks/useServersData.ts
@@ -8,11 +8,11 @@ import { QueriesServices } from '../Services.enum';
const initServersQueryParams = { limit: BIG_PAGINATION_SIZE };
export const useServersData = (id: string) => {
- const { data: servers } = useSuspenseQuery({
+ const { data: processes } = useSuspenseQuery({
queryKey: [QueriesServices.GetProcessesByService, { ...initServersQueryParams, addresses: [id] }],
queryFn: () => RESTApi.fetchProcesses({ ...initServersQueryParams, addresses: [id] }),
refetchInterval: UPDATE_INTERVAL
});
- return { servers: servers.results };
+ return { processes: processes.results };
};
diff --git a/src/pages/Services/hooks/useServiceData.ts b/src/pages/Services/hooks/useServiceData.ts
index 08c4e05c..ea5777d6 100644
--- a/src/pages/Services/hooks/useServiceData.ts
+++ b/src/pages/Services/hooks/useServiceData.ts
@@ -1,7 +1,7 @@
import { useQuery, useSuspenseQuery } from '@tanstack/react-query';
import { RESTApi } from '@API/REST.api';
-import { AvailableProtocols, TcpStatus } from '@API/REST.enum';
+import { Protocols, TcpStatus } from '@API/REST.enum';
import { UPDATE_INTERVAL } from '@config/config';
import { QueriesServices } from '../Services.enum';
@@ -39,7 +39,7 @@ const useServiceData = (serviceId: string) => {
const { data: requestsData } = useQuery({
queryKey: [QueriesServices.GetFlowPairsByService, initServersQueryParams],
queryFn: () => RESTApi.fetchFlowPairs({ ...initServersQueryParams, routingKey: service.results.name }),
- enabled: service.results.protocol !== AvailableProtocols.Tcp,
+ enabled: service.results.protocol !== Protocols.Tcp,
refetchInterval: UPDATE_INTERVAL
});
@@ -52,7 +52,7 @@ const useServiceData = (serviceId: string) => {
const { data: terminatedConnectionsData } = useQuery({
queryKey: [QueriesServices.GetFlowPairsByService, terminatedConnectionsQueryParams],
queryFn: () => RESTApi.fetchFlowPairs({ ...terminatedConnectionsQueryParams, routingKey: service.results.name }),
- enabled: service.results.protocol === AvailableProtocols.Tcp,
+ enabled: service.results.protocol === Protocols.Tcp,
refetchInterval: UPDATE_INTERVAL
});
diff --git a/src/pages/Services/views/Service.tsx b/src/pages/Services/views/Service.tsx
index 22687563..1bdc1b17 100644
--- a/src/pages/Services/views/Service.tsx
+++ b/src/pages/Services/views/Service.tsx
@@ -2,7 +2,7 @@ import { FC, useState } from 'react';
import { useParams, useSearchParams } from 'react-router-dom';
-import { AvailableProtocols } from '@API/REST.enum';
+import { Protocols } from '@API/REST.enum';
import { getTestsIds } from '@config/testIds';
import { getIdAndNameFromUrlParams } from '@core/utils/getIdAndNameFromUrlParams';
import MainContainer from '@layout/MainContainer';
@@ -11,7 +11,7 @@ import { TopologyRoutesPaths, TopologyURLQueyParams, TopologyViews } from '@page
import HttpRequests from '../components/HttpRequests';
import NavigationMenu from '../components/NavigationMenu';
import Overview from '../components/Overview';
-import Servers from '../components/Servers';
+import ProcessServerList from '../components/ProcessServerList';
import TcpConnections from '../components/TcpConnections';
import TcpTerminatedConnections from '../components/TcpTerminatedConnections';
import useServiceData from '../hooks/useServiceData';
@@ -49,10 +49,10 @@ const ServiceComponent: FC = function ({ id, defaultTab }) {
mainContentChildren={
<>
{menuSelected === TAB_0_KEY && }
- {menuSelected === TAB_1_KEY && }
+ {menuSelected === TAB_1_KEY && }
{menuSelected === TAB_3_KEY && }
{menuSelected === TAB_4_KEY && }
- {menuSelected === TAB_2_KEY && protocol !== AvailableProtocols.Tcp && }
+ {menuSelected === TAB_2_KEY && protocol !== Protocols.Tcp && }
>
}
/>
diff --git a/src/pages/Sites/Sites.enum.ts b/src/pages/Sites/Sites.enum.ts
index ed2fcbc8..bfe26e8b 100644
--- a/src/pages/Sites/Sites.enum.ts
+++ b/src/pages/Sites/Sites.enum.ts
@@ -6,8 +6,6 @@ export enum QueriesSites {
GetSites = 'get-sites-query',
GetSite = 'get-site-query',
GetSitesPairs = 'get-sites-pairs-query',
- GetHostsBySiteId = 'get-hosts-by-site-id-query',
- GetLinksBySiteId = 'get-links-by-site-id-query',
GetRouters = 'get-routers-query',
GetLinks = 'get-links-query',
GetProcessesBySiteId = 'get-processes-by-site-id-query'
diff --git a/src/pages/Sites/components/Details.tsx b/src/pages/Sites/components/Details.tsx
index 50f27f9a..b35687cd 100644
--- a/src/pages/Sites/components/Details.tsx
+++ b/src/pages/Sites/components/Details.tsx
@@ -22,7 +22,6 @@ import ResourceIcon from '@core/components/ResourceIcon';
import { SiteResponse } from '@sk-types/REST.interfaces';
import { useSiteDetailsData } from '../hooks/useSiteDetailsData';
-import SitesController from '../services';
import { SitesRoutesPaths, SiteLabels } from '../Sites.enum';
interface DetailsProps {
@@ -30,13 +29,7 @@ interface DetailsProps {
}
const Details: FC = function ({ site: { identity: id, nameSpace, siteVersion, platform } }) {
- const { sites, links } = useSiteDetailsData(id);
-
- const { linkSiteIds } = SitesController.bindLinksWithSiteIds(
- sites.filter(({ identity }) => identity === id),
- links
- )[0];
- const linkedSites = sites.filter(({ identity }) => linkSiteIds.map(({ targetId }) => targetId).includes(identity));
+ const { links } = useSiteDetailsData(id);
return (
@@ -57,13 +50,13 @@ const Details: FC = function ({ site: { identity: id, nameSpace, s
{SiteLabels.Links}
- {linkedSites.length
- ? linkedSites.map(({ identity, name: linkedSiteName }) => (
+ {links.length
+ ? links.map(({ identity, destinationSiteId, destinationSiteName }) => (
-
- {linkedSiteName}
+
+ {destinationSiteName}
diff --git a/src/pages/Sites/components/Overview..tsx b/src/pages/Sites/components/Overview..tsx
index 3cad27ad..3844477c 100644
--- a/src/pages/Sites/components/Overview..tsx
+++ b/src/pages/Sites/components/Overview..tsx
@@ -4,7 +4,7 @@ import { extractUniqueValues } from '@core/utils/extractUniqueValues';
import { mapDataToMetricFilterOptions } from '@core/utils/getResourcesFromPairs';
import { removeDuplicatesFromArrayOfObjects } from '@core/utils/removeDuplicatesFromArrayOfObjects';
import Metrics from '@pages/shared/Metrics';
-import { useMetricSessionHandlers } from '@pages/shared/Metrics/hooks/useSessionHandler';
+import { useMetricSessionHandlers } from '@pages/shared/Metrics/hooks/useMetricsSessionHandler';
import { SitePairsResponse, SiteResponse } from '@sk-types/REST.interfaces';
import { useSiteOverviewData } from '../hooks/useOverviewData';
diff --git a/src/pages/Sites/components/ProcessList.tsx b/src/pages/Sites/components/ProcessList.tsx
index 407d7f7c..8e67e8ba 100644
--- a/src/pages/Sites/components/ProcessList.tsx
+++ b/src/pages/Sites/components/ProcessList.tsx
@@ -3,7 +3,6 @@ import { FC } from 'react';
import SkTable from '@core/components/SkTable';
import { setColumnVisibility } from '@core/components/SkTable/SkTable.utils';
import { CustomProcessCells, processesTableColumns } from '@pages/Processes/Processes.constants';
-import { ProcessesLabels } from '@pages/Processes/Processes.enum';
import { SiteResponse } from '@sk-types/REST.interfaces';
import { useSiteProcessListData } from '../hooks/useSiteProcessListData';
@@ -17,7 +16,6 @@ const ProcessList: FC = function ({ site: { identity: id } })
return (
{
- const [{ data: sites }, { data: links }] = useSuspenseQueries({
- queries: [
- { queryKey: [QueriesSites.GetSites], queryFn: () => RESTApi.fetchSites(), refetchInterval: UPDATE_INTERVAL },
- {
- queryKey: [QueriesSites.GetLinksBySiteId, id, linkQueryParams],
- queryFn: () => RESTApi.fetchLinksBySite(id, linkQueryParams),
- refetchInterval: UPDATE_INTERVAL
- }
- ]
+ const queryParams = (idKey: keyof RouterLinkResponse) => ({ [idKey]: id });
+
+ const { data: links } = useSuspenseQuery({
+ queryKey: [QueriesSites.GetLinks, queryParams('sourceSiteId')],
+ queryFn: () => RESTApi.fetchLinks(queryParams('sourceSiteId')),
+ refetchInterval: UPDATE_INTERVAL
});
- return { sites: sites.results, links: links.results };
+ return { links: links.results };
};
diff --git a/src/pages/Sites/services/index.ts b/src/pages/Sites/services/index.ts
deleted file mode 100644
index 1a9467e5..00000000
--- a/src/pages/Sites/services/index.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { LinkResponse, SiteResponse } from '@sk-types/REST.interfaces';
-
-const SitesController = {
- // The output is an object that assigns to each source site id the ids of the connected
- bindLinksWithSiteIds: (sites: SiteResponse[], links: LinkResponse[]) => {
- const linksExtendedMap = links.reduce(
- function (acc, { sourceSiteId, destinationSiteId, linkCost }) {
- const existingLink = (acc[sourceSiteId] || []).find((link) => link.targetId === destinationSiteId);
- if (
- !existingLink ||
- (existingLink.linkCost !== undefined && linkCost !== undefined && linkCost > existingLink.linkCost)
- ) {
- acc[sourceSiteId] = acc[sourceSiteId] || [];
- acc[sourceSiteId].push({ targetId: destinationSiteId, linkCost });
- } else if (existingLink && existingLink.linkCost === undefined) {
- existingLink.linkCost = linkCost;
- }
-
- return acc;
- },
- {} as Record
- );
-
- return sites.map((site) => ({
- ...site,
- // Filters the target ids to remove duplicates
- linkSiteIds: (linksExtendedMap[site.identity] || [])
- ?.filter((obj, index, self) => index === self.findIndex((o) => o.targetId === obj.targetId))
- .filter(Boolean)
- }));
- }
-};
-
-export default SitesController;
diff --git a/src/pages/Topology/Topology.constants.ts b/src/pages/Topology/Topology.constants.ts
index 2c0db4de..77a79092 100644
--- a/src/pages/Topology/Topology.constants.ts
+++ b/src/pages/Topology/Topology.constants.ts
@@ -18,26 +18,6 @@ export const SHOW_LINK_METRIC_DISTRIBUTION = 'show-metric-distribution';
export const SHOW_LINK_METRIC_VALUE = 'show-metric-value';
export const displayOptionsForProcesses: TopologyDisplayOptionsMenu[] = [
- {
- title: TopologyLabels.TitleGroupDisplayOptionsMenuMetrics,
- items: [
- {
- key: SHOW_LINK_BYTES,
- value: SHOW_LINK_BYTES,
- label: TopologyLabels.CheckboxShowTotalBytes
- },
- {
- key: SHOW_LINK_BYTERATE,
- value: SHOW_LINK_BYTERATE,
- label: TopologyLabels.CheckboxShowCurrentByteRate
- },
- {
- key: SHOW_LINK_LATENCY,
- value: SHOW_LINK_LATENCY,
- label: TopologyLabels.CheckboxShowLatency
- }
- ]
- },
{
title: TopologyLabels.TitleGroupDisplayOptionsMenuMetricVisualization,
items: [
@@ -58,6 +38,27 @@ export const displayOptionsForProcesses: TopologyDisplayOptionsMenu[] = [
}
]
},
+ {
+ title: TopologyLabels.TitleGroupDisplayOptionsMenuMetrics,
+ items: [
+ {
+ key: SHOW_LINK_BYTES,
+ value: SHOW_LINK_BYTES,
+ label: TopologyLabels.CheckboxShowTotalBytes
+ },
+ {
+ key: SHOW_LINK_BYTERATE,
+ value: SHOW_LINK_BYTERATE,
+ label: TopologyLabels.CheckboxShowCurrentByteRate
+ },
+ {
+ key: SHOW_LINK_LATENCY,
+ value: SHOW_LINK_LATENCY,
+ label: TopologyLabels.CheckboxShowLatency
+ }
+ ]
+ },
+
{
title: TopologyLabels.TitleGroupDisplayOptionsMenuOther,
items: [
@@ -95,26 +96,6 @@ export const displayOptionsForSites: TopologyDisplayOptionsMenu[] = [
}
]
},
- {
- title: TopologyLabels.TitleGroupDisplayOptionsMenuMetrics,
- items: [
- {
- key: SHOW_LINK_BYTES,
- value: SHOW_LINK_BYTES,
- label: TopologyLabels.CheckboxShowTotalBytes
- },
- {
- key: SHOW_LINK_BYTERATE,
- value: SHOW_LINK_BYTERATE,
- label: TopologyLabels.CheckboxShowCurrentByteRate
- },
- {
- key: SHOW_LINK_LATENCY,
- value: SHOW_LINK_LATENCY,
- label: TopologyLabels.CheckboxShowLatency
- }
- ]
- },
{
title: TopologyLabels.TitleGroupDisplayOptionsMenuMetricVisualization,
items: [
@@ -134,6 +115,26 @@ export const displayOptionsForSites: TopologyDisplayOptionsMenu[] = [
label: TopologyLabels.CheckboxShowLabelReverse
}
]
+ },
+ {
+ title: TopologyLabels.TitleGroupDisplayOptionsMenuMetrics,
+ items: [
+ {
+ key: SHOW_LINK_BYTES,
+ value: SHOW_LINK_BYTES,
+ label: TopologyLabels.CheckboxShowTotalBytes
+ },
+ {
+ key: SHOW_LINK_BYTERATE,
+ value: SHOW_LINK_BYTERATE,
+ label: TopologyLabels.CheckboxShowCurrentByteRate
+ },
+ {
+ key: SHOW_LINK_LATENCY,
+ value: SHOW_LINK_LATENCY,
+ label: TopologyLabels.CheckboxShowLatency
+ }
+ ]
}
];
diff --git a/src/pages/Topology/components/DisplayOptions.tsx b/src/pages/Topology/components/DisplayOptions.tsx
index d8e09905..79736768 100644
--- a/src/pages/Topology/components/DisplayOptions.tsx
+++ b/src/pages/Topology/components/DisplayOptions.tsx
@@ -1,71 +1,17 @@
-import { FC, Ref, useCallback, useState } from 'react';
+import { FC, MouseEvent as ReactMouseEvent, Ref, useCallback, useState } from 'react';
import { MenuToggle, MenuToggleElement, Select, SelectGroup, SelectOption } from '@patternfly/react-core';
import { TopologyDisplayOptionsMenu } from '@sk-types/Topology.interfaces';
-import {
- SHOW_DATA_LINKS,
- SHOW_LINK_BYTERATE,
- SHOW_LINK_BYTES,
- SHOW_LINK_LATENCY,
- SHOW_ROUTER_LINKS
-} from '../Topology.constants';
+import { DisplayUseOptionsStateProps, useDisplayOptionsState } from '../hooks/useDisplayOptionsState';
import { TopologyLabels } from '../Topology.enum';
-interface DisplayUseOptionsProps {
- defaultSelected?: string[];
- onSelected: (items: string[], item: string) => void;
-}
-
-interface DisplayOptionsProps extends DisplayUseOptionsProps {
+interface DisplayOptionsProps extends DisplayUseOptionsStateProps {
options: TopologyDisplayOptionsMenu[];
optionsDisabled?: Record;
}
-export const useDisplayOptions = ({ defaultSelected = [], onSelected }: DisplayUseOptionsProps) => {
- const [displayOptionsSelected, setDisplayOptions] = useState(defaultSelected);
-
- const selectDisplayOptions = useCallback(
- (selectedOption: string) => {
- const isOptionSelected = displayOptionsSelected.includes(selectedOption);
-
- let updatedDisplayOptions = isOptionSelected
- ? displayOptionsSelected.filter((option) => option !== selectedOption)
- : [...displayOptionsSelected, selectedOption];
-
- if (
- selectedOption === SHOW_LINK_BYTES ||
- selectedOption === SHOW_LINK_BYTERATE ||
- selectedOption === SHOW_LINK_LATENCY
- ) {
- updatedDisplayOptions = isOptionSelected
- ? displayOptionsSelected.filter((option) => option !== selectedOption)
- : [
- ...displayOptionsSelected.filter(
- (option) => option !== SHOW_LINK_BYTES && option !== SHOW_LINK_BYTERATE && option !== SHOW_LINK_LATENCY
- ),
- selectedOption
- ];
- }
-
- if (selectedOption === SHOW_DATA_LINKS || selectedOption === SHOW_ROUTER_LINKS) {
- const otherOption = selectedOption === SHOW_DATA_LINKS ? SHOW_ROUTER_LINKS : SHOW_DATA_LINKS;
-
- updatedDisplayOptions = isOptionSelected
- ? [...updatedDisplayOptions, otherOption]
- : updatedDisplayOptions.filter((option) => option !== otherOption);
- }
-
- setDisplayOptions(updatedDisplayOptions);
- onSelected(updatedDisplayOptions, selectedOption);
- },
- [displayOptionsSelected, onSelected]
- );
-
- return { displayOptionsSelected, selectDisplayOptions };
-};
-
const DisplayOptions: FC = function ({
defaultSelected,
options,
@@ -73,41 +19,45 @@ const DisplayOptions: FC = function ({
optionsDisabled = {}
}) {
const [isDisplayMenuOpen, setIsDisplayMenuOpen] = useState(false);
- const { displayOptionsSelected, selectDisplayOptions } = useDisplayOptions({
+ const { displayOptionsSelected, selectDisplayOptions } = useDisplayOptionsState({
defaultSelected,
onSelected
});
- function toggleDisplayMenu() {
- setIsDisplayMenuOpen(!isDisplayMenuOpen);
- }
+ const toggleDisplayMenu = useCallback(() => {
+ setIsDisplayMenuOpen((prev) => !prev);
+ }, []);
- const toggle = (toggleRef: Ref) => (
-
- {TopologyLabels.DisplayPlaceholderText}
-
+ const handleSelect = useCallback(
+ (_?: ReactMouseEvent, selection?: string | number) =>
+ selectDisplayOptions(selection!.toString()),
+ [selectDisplayOptions]
);
+ const handleOpenChange = useCallback((open: boolean) => {
+ if (!open) {
+ setIsDisplayMenuOpen(false);
+ }
+ }, []);
+
return (