From 031165c3e8a116246c0a6af52eac58197758faab Mon Sep 17 00:00:00 2001 From: bartoval Date: Fri, 20 Sep 2024 15:37:42 +0200 Subject: [PATCH] refactor(General): :recycle: Migrate to skSelect component --- __tests__/core/SKSankeyFIlter.spec.tsx | 20 +- __tests__/core/SkSearchFilter-service.spec.ts | 34 +- __tests__/core/SkSearchFilter.spec.tsx | 10 +- __tests__/core/SkTimeRangeFilter.spec.tsx | 17 - __tests__/core/SkUpdateDataButton.spec.tsx | 15 +- .../__snapshots__/SkSankeyChart.spec.tsx.snap | 360 ++++++++++++++++++ .../__snapshots__/Metrics.spec.tsx.snap | 4 +- .../Metrics/useMetricFiltersState.spec.ts | 12 +- __tests__/pages/Sites/Site.spec.tsx | 4 +- mocks/data/LINKS.json | 66 +--- mocks/data/PROCESS_GROUPS.json | 4 +- mocks/server.ts | 22 +- .../SKSanckeyChart/SkSankey.constants.ts | 18 +- .../SKSanckeyChart/SkSankeyFilter.tsx | 168 ++------ src/core/components/SKSanckeyChart/index.tsx | 107 +++--- .../SkBiFlowList/BiFlowList.constants.ts | 11 +- src/core/components/SkSelect/index.tsx | 85 +++-- .../SkTable/SkSearchFilter/index.tsx | 69 ++-- .../SkTable/SkSearchFilter/services/index.ts | 9 +- .../components/SkTimeRangeFilter/index.tsx | 49 --- .../components/SkUpdateDataButton/index.tsx | 98 ++--- src/pages/Processes/Processes.constants.ts | 9 +- src/pages/Services/Services.constants.ts | 11 +- .../components/ProcessPairsSankey.tsx | 4 +- .../Services/components/ServiceBiFlowList.tsx | 3 +- .../Topology/hooks/useDisplayOptionsState.ts | 18 +- src/pages/shared/Metrics/Metrics.constants.ts | 4 +- .../shared/Metrics/components/Filters.tsx | 19 +- .../Metrics/hooks/useMetricFiltersState.ts | 18 +- src/types/Metrics.interfaces.ts | 1 + src/types/SkFilter.interfaces.ts | 7 +- src/types/SkSankeyChart.interfaces.ts | 4 - 32 files changed, 669 insertions(+), 611 deletions(-) delete mode 100644 __tests__/core/SkTimeRangeFilter.spec.tsx delete mode 100644 src/core/components/SkTimeRangeFilter/index.tsx diff --git a/__tests__/core/SKSankeyFIlter.spec.tsx b/__tests__/core/SKSankeyFIlter.spec.tsx index df64e94a..e844ab5f 100644 --- a/__tests__/core/SKSankeyFIlter.spec.tsx +++ b/__tests__/core/SKSankeyFIlter.spec.tsx @@ -3,7 +3,7 @@ import { render, fireEvent, waitFor } from '@testing-library/react'; import { ServiceClientResourceOptions, ServiceServerResourceOptions, - sankeyMetricOptions + SankeyMetricOptions } from '../../src/core/components/SKSanckeyChart/SkSankey.constants'; import SankeyFilter from '../../src/core/components/SKSanckeyChart/SkSankeyFilter'; @@ -18,16 +18,16 @@ describe('SankeyFilter', () => { const { getByText } = render(); // Find and click the client resource toggle button - const clientToggle = getByText(ServiceClientResourceOptions[0].name); + const clientToggle = getByText(ServiceClientResourceOptions[0].label); fireEvent.click(clientToggle); // Find and click the "Client sites" option - const clientOption = getByText(ServiceClientResourceOptions[1].name); + const clientOption = getByText(ServiceClientResourceOptions[1].label); fireEvent.click(clientOption); await waitFor(() => { // Assert that the client resource has been selected - const selectedClient = getByText(ServiceClientResourceOptions[1].name); + const selectedClient = getByText(ServiceClientResourceOptions[1].label); expect(selectedClient).toBeInTheDocument(); }); }); @@ -36,16 +36,16 @@ describe('SankeyFilter', () => { const { getByText } = render(); // Find and click the server resource toggle button - const serverToggle = getByText(ServiceServerResourceOptions[0].name); + const serverToggle = getByText(ServiceServerResourceOptions[0].label); fireEvent.click(serverToggle); // Find and click the "Server processes" option - const serverOption = getByText(ServiceServerResourceOptions[1].name); + const serverOption = getByText(ServiceServerResourceOptions[1].label); fireEvent.click(serverOption); await waitFor(() => { // Assert that the server resource has been selected - const selectedServer = getByText(ServiceServerResourceOptions[1].name); + const selectedServer = getByText(ServiceServerResourceOptions[1].label); expect(selectedServer).toBeInTheDocument(); }); }); @@ -54,16 +54,16 @@ describe('SankeyFilter', () => { const { getByText } = render(); // Find and click the metric toggle button - const metricToggle = getByText(sankeyMetricOptions[0].name); + const metricToggle = getByText(SankeyMetricOptions[0].label); fireEvent.click(metricToggle); // Find and click a metric option - const metricOption = getByText(sankeyMetricOptions[1].name); + const metricOption = getByText(SankeyMetricOptions[1].label); fireEvent.click(metricOption); // Assert that the metric has been selected await waitFor(() => { - const selectedMetric = getByText(sankeyMetricOptions[1].name); + const selectedMetric = getByText(SankeyMetricOptions[1].label); expect(selectedMetric).toBeInTheDocument(); }); }); diff --git a/__tests__/core/SkSearchFilter-service.spec.ts b/__tests__/core/SkSearchFilter-service.spec.ts index 2a47fc4d..ef2821af 100644 --- a/__tests__/core/SkSearchFilter-service.spec.ts +++ b/__tests__/core/SkSearchFilter-service.spec.ts @@ -1,16 +1,14 @@ +import { SkSelectOption } from '@core/components/SkSelect'; + import { SkSearchFilterController } from '../../src/core/components/SkTable/SkSearchFilter/services'; // Assuming your service file path -import { - FilterType, - FilterTypeWithSearchText, - FilterSelected -} from '../../src/types/SkFilter.interfaces'; // Assuming your interface file path +import { FilterTypeWithSearchText, FilterSelected } from '../../src/types/SkFilter.interfaces'; // Assuming your interface file path describe('SkSearchFilterController', () => { describe('getFilterTypesWithSearchValues', () => { it('should return an empty array when filterValues is undefined', () => { - const selectOptions: FilterType[] = [ - { id: 'filter1', name: 'Filter 1' }, - { id: 'filter2', name: 'Filter 2' } + const selectOptions: SkSelectOption[] = [ + { id: 'filter1', label: 'Filter 1' }, + { id: 'filter2', label: 'Filter 2' } ]; const result = SkSearchFilterController.getFilterTypesWithSearchValues(selectOptions, undefined); @@ -19,9 +17,9 @@ describe('SkSearchFilterController', () => { }); it('should return all selected filters with search values', () => { - const selectOptions: FilterType[] = [ - { id: 'filter1', name: 'Filter 1' }, - { id: 'filter2', name: 'Filter 2' } + const selectOptions: SkSelectOption[] = [ + { id: 'filter1', label: 'Filter 1' }, + { id: 'filter2', label: 'Filter 2' } ]; const filterValues: FilterSelected = { @@ -30,8 +28,8 @@ describe('SkSearchFilterController', () => { }; const expectedResult: FilterTypeWithSearchText[] = [ - { id: 'filter1', name: 'Filter 1', searchValue: 'value1' }, - { id: 'filter2', name: 'Filter 2', searchValue: 'value2' } + { id: 'filter1', label: 'Filter 1', searchValue: 'value1' }, + { id: 'filter2', label: 'Filter 2', searchValue: 'value2' } ]; const result = SkSearchFilterController.getFilterTypesWithSearchValues(selectOptions, filterValues); @@ -40,10 +38,10 @@ describe('SkSearchFilterController', () => { }); it('should return only selected filters with search values', () => { - const selectOptions: FilterType[] = [ - { id: 'filter1', name: 'Filter 1' }, - { id: 'filter2', name: 'Filter 2' }, - { id: 'filter3', name: 'Filter 3' } + const selectOptions: SkSelectOption[] = [ + { id: 'filter1', label: 'Filter 1' }, + { id: 'filter2', label: 'Filter 2' }, + { id: 'filter3', label: 'Filter 3' } ]; const filterValues: FilterSelected = { @@ -51,7 +49,7 @@ describe('SkSearchFilterController', () => { filter2: undefined }; - const expectedResult: FilterTypeWithSearchText[] = [{ id: 'filter1', name: 'Filter 1', searchValue: 'value1' }]; + const expectedResult: FilterTypeWithSearchText[] = [{ id: 'filter1', label: 'Filter 1', searchValue: 'value1' }]; const result = SkSearchFilterController.getFilterTypesWithSearchValues(selectOptions, filterValues); diff --git a/__tests__/core/SkSearchFilter.spec.tsx b/__tests__/core/SkSearchFilter.spec.tsx index d4382705..855e5b6f 100644 --- a/__tests__/core/SkSearchFilter.spec.tsx +++ b/__tests__/core/SkSearchFilter.spec.tsx @@ -7,8 +7,8 @@ import { testIds } from '../../src/core/components/SkTable/SkSearchFilter/SkSear describe('SkSearchFilter', () => { const onSearchMock = jest.fn(); const selectOptions = [ - { id: 'option1', name: 'Option 1' }, - { id: 'option2', name: 'Option 2' } + { id: 'option1', label: 'Option 1' }, + { id: 'option2', label: 'Option 2' } ]; it('should handle input change', async () => { @@ -66,15 +66,15 @@ describe('SkSearchFilter', () => { const { getByTestId, getByText, getByPlaceholderText } = render( ); - let selectedFilterBtn = getByText(selectOptions[0].name); + let selectedFilterBtn = getByText(selectOptions[0].label); await eventUser.click(selectedFilterBtn); expect(getByTestId(testIds.selectFilterType)).toBeInTheDocument(); - selectedFilterBtn = getByText(selectOptions[1].name); + selectedFilterBtn = getByText(selectOptions[1].label); await eventUser.click(selectedFilterBtn); - expect(getByPlaceholderText(`Search by ${selectOptions[1].name.toLowerCase()}`)).toBeInTheDocument(); + expect(getByPlaceholderText(`Search by ${selectOptions[1].label.toLowerCase()}`)).toBeInTheDocument(); }); it('should change the filter type selection', async () => { diff --git a/__tests__/core/SkTimeRangeFilter.spec.tsx b/__tests__/core/SkTimeRangeFilter.spec.tsx deleted file mode 100644 index c6d47709..00000000 --- a/__tests__/core/SkTimeRangeFilter.spec.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import eventUser from '@testing-library/user-event'; - -import { defaultTimeInterval, timeIntervalMap } from '../../src/config/prometheus'; -import SkTimeRangeFilter from '../../src/core/components/SkTimeRangeFilter/index'; - -describe('SkTimeRangeFilter', () => { - it('should toggle isOpen state on button click', async () => { - const mockHandleToggle = jest.fn(); - render(); - - await eventUser.click(screen.getByText(timeIntervalMap.oneMinute.label)); - await eventUser.click(screen.getByText(timeIntervalMap.fiveMinutes.label)); - - expect(mockHandleToggle).toHaveBeenCalledTimes(1); - }); -}); diff --git a/__tests__/core/SkUpdateDataButton.spec.tsx b/__tests__/core/SkUpdateDataButton.spec.tsx index 5f24a125..1529c14c 100644 --- a/__tests__/core/SkUpdateDataButton.spec.tsx +++ b/__tests__/core/SkUpdateDataButton.spec.tsx @@ -24,7 +24,7 @@ describe('SkUpdateDataButton component', () => { await waitFor(() => { fireEvent.click(screen.getByText('Refresh off')); - expect(screen.getByText(refreshDataIntervalMap[1].key)).toBeInTheDocument(); + expect(screen.getByText(refreshDataIntervalMap[1].label)).toBeInTheDocument(); }); }); @@ -37,18 +37,17 @@ describe('SkUpdateDataButton component', () => { ); - fireEvent.click(screen.getByText(refreshDataIntervalMap[1].key)); - fireEvent.click(screen.getByText(refreshDataIntervalMap[2].key)); + fireEvent.click(screen.getByText(refreshDataIntervalMap[0].label)); + fireEvent.click(screen.getByText(refreshDataIntervalMap[2].label)); await waitFor(() => { // call the first one and the one inside the setInterval - expect(revalidateLiveQueriesMock).toHaveBeenCalledTimes(2); - expect(onRefreshIntervalSelectedMock).toHaveBeenCalledWith(refreshDataIntervalMap[2].value); + expect(revalidateLiveQueriesMock).toHaveBeenCalledTimes(1); + expect(onRefreshIntervalSelectedMock).toHaveBeenCalledWith(Number(refreshDataIntervalMap[2].id)); }); }); @@ -56,11 +55,11 @@ describe('SkUpdateDataButton component', () => { const revalidateLiveQueriesMock = jest.fn(); render( - + ); fireEvent.click(screen.getByTestId('update-data-click')); - await waitFor(() => expect(revalidateLiveQueriesMock).toHaveBeenCalledTimes(2)); + await waitFor(() => expect(revalidateLiveQueriesMock).toHaveBeenCalledTimes(1)); }); }); diff --git a/__tests__/core/__snapshots__/SkSankeyChart.spec.tsx.snap b/__tests__/core/__snapshots__/SkSankeyChart.spec.tsx.snap index 5a705031..26c3154a 100644 --- a/__tests__/core/__snapshots__/SkSankeyChart.spec.tsx.snap +++ b/__tests__/core/__snapshots__/SkSankeyChart.spec.tsx.snap @@ -5,6 +5,186 @@ exports[`SkSankeyChart should render the SkSankeyChart component 1`] = ` "asFragment": [Function], "baseElement":
+
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+
+ +
+
+
+
+
@@ -15,6 +195,186 @@ exports[`SkSankeyChart should render the SkSankeyChart component 1`] = `
, "container":
+
+
+
+
+
+ +
+
+
+ +
+
+ +
+
+
+ +
+
+
+
+
diff --git a/__tests__/pages/Metrics/__snapshots__/Metrics.spec.tsx.snap b/__tests__/pages/Metrics/__snapshots__/Metrics.spec.tsx.snap index 37d3e715..bbe325a0 100644 --- a/__tests__/pages/Metrics/__snapshots__/Metrics.spec.tsx.snap +++ b/__tests__/pages/Metrics/__snapshots__/Metrics.spec.tsx.snap @@ -313,9 +313,7 @@ exports[`Metrics Component renders correctly 1`] = ` - Last 1 min. - + /> diff --git a/__tests__/pages/Metrics/useMetricFiltersState.spec.ts b/__tests__/pages/Metrics/useMetricFiltersState.spec.ts index ed16b2f4..9df42c8f 100644 --- a/__tests__/pages/Metrics/useMetricFiltersState.spec.ts +++ b/__tests__/pages/Metrics/useMetricFiltersState.spec.ts @@ -12,8 +12,6 @@ describe('useMetricFiltersState', () => { sourceSite: 'site1', destSite: 'site2', protocol: Protocols.Tcp, - start: 0, - end: 100, duration: 1000 }; @@ -85,18 +83,16 @@ describe('useMetricFiltersState', () => { }) ); - const newTimeInterval = { start: 1609545600, end: 1609632000, duration: 86400 }; + const duration = 86400; act(() => { - result.current.handleSelectTimeInterval(newTimeInterval); + result.current.handleSelectTimeInterval(86400); }); - expect(result.current.selectedFilters.start).toEqual(newTimeInterval.start); - expect(result.current.selectedFilters.end).toEqual(newTimeInterval.end); - expect(result.current.selectedFilters.duration).toEqual(newTimeInterval.duration); + expect(result.current.selectedFilters.duration).toEqual(duration); expect(onSelectFiltersMock).toHaveBeenCalledWith({ ...defaultMetricFilterValues, - ...newTimeInterval + duration }); }); diff --git a/__tests__/pages/Sites/Site.spec.tsx b/__tests__/pages/Sites/Site.spec.tsx index 28a27788..52fedbc4 100644 --- a/__tests__/pages/Sites/Site.spec.tsx +++ b/__tests__/pages/Sites/Site.spec.tsx @@ -64,8 +64,10 @@ describe('Site component', () => { fireEvent.click(screen.getByText(SiteLabels.Details)); await waitFor(() => { - expect(screen.getByText(siteResults[0].name)).toBeInTheDocument(); expect(screen.getByText(siteResults[0].nameSpace)).toBeInTheDocument(); + expect(screen.getByText(siteResults[0].name)).toBeInTheDocument(); + expect(screen.getByText(siteResults[0].platform as string)).toBeInTheDocument(); + expect(screen.getByText(siteResults[0].siteVersion)).toBeInTheDocument(); }); }); diff --git a/mocks/data/LINKS.json b/mocks/data/LINKS.json index 67322bbb..edf004d7 100644 --- a/mocks/data/LINKS.json +++ b/mocks/data/LINKS.json @@ -15,21 +15,6 @@ "destinationSiteId": "site-3", "destinationSiteName": "site 3" }, - { - "recType": "LINK", - "identity": "hth7l:12", - "parent": "", - "startTime": 1674048706622878, - "endTime": 0, - "mode": "interior", - "name": "", - "linkCost": 1, - "direction": "incoming", - "sourceSiteId": "site-1", - "sourceSiteName": "site-1", - "destinationSiteId": "site-3", - "destinationSiteName": "site 3" - }, { "recType": "LINK", "identity": "52tjs:1402", @@ -45,21 +30,6 @@ "destinationSiteId": "site-2", "destinationSiteName": "site 2" }, - { - "recType": "LINK", - "identity": "6z7k6:2", - "parent": "", - "startTime": 1674048729859049, - "endTime": 0, - "mode": "interior", - "name": "", - "linkCost": 1, - "direction": "incoming", - "sourceSiteId": "site-1", - "sourceSiteName": "site-1", - "destinationSiteId": "site-2", - "destinationSiteName": "site 2" - }, { "recType": "LINK", "identity": "hth7l:31", @@ -75,36 +45,6 @@ "destinationSiteId": "site-2", "destinationSiteName": "site 2" }, - { - "recType": "LINK", - "identity": "6z7k6:1701", - "parent": "6z7k6:0", - "startTime": 1674149422366200, - "endTime": 0, - "mode": "interior", - "name": "site 3", - "linkCost": 1, - "direction": "incoming", - "sourceSiteId": "site-3", - "sourceSiteName": "site-3", - "destinationSiteId": "site-2", - "destinationSiteName": "site 2" - }, - { - "recType": "LINK", - "identity": "hth7l:39", - "parent": "", - "startTime": 1674151543581947, - "endTime": 0, - "mode": "interior", - "name": "", - "linkCost": 1, - "direction": "outgoing", - "sourceSiteId": "site-3", - "sourceSiteName": "site-3", - "destinationSiteId": "site-2", - "destinationSiteName": "site 2" - }, { "recType": "LINK", "identity": "6z7k7:231", @@ -121,8 +61,6 @@ "destinationSiteName": "site 1" } ], - "status": "", - "count": 6, - "timeRangeCount": 6, - "totalCount": 6 + "count": 4, + "timeRangeCount": 4 } diff --git a/mocks/data/PROCESS_GROUPS.json b/mocks/data/PROCESS_GROUPS.json index d8450114..2ead6f92 100644 --- a/mocks/data/PROCESS_GROUPS.json +++ b/mocks/data/PROCESS_GROUPS.json @@ -55,8 +55,6 @@ "processCount": 1 } ], - "status": "", "count": 6, - "timeRangeCount": 6, - "totalCount": 6 + "timeRangeCount": 6 } diff --git a/mocks/server.ts b/mocks/server.ts index efdd836b..310b266a 100644 --- a/mocks/server.ts +++ b/mocks/server.ts @@ -184,11 +184,20 @@ export const MockApi = { results: sites.results.find(({ identity }) => identity === id) || [] }), - getLinks: () => { + getLinks: (_: unknown, { queryParams }: ApiProps) => { const linksForPerfTests = ITEM_COUNT ? mockLinksForPerf : []; const results = [...links.results, ...linksForPerfTests]; - return { ...links, results }; + const filteredResults = results.filter( + (result) => queryParams.sourceSiteId && result.sourceSiteId === queryParams.sourceSiteId + ); + + return { + ...links, + results: filteredResults, + count: filteredResults.length, + timeRangeCount: filteredResults.length + }; }, getComponents: (_: unknown, { queryParams }: ApiProps) => { const results = [...processGroups.results]; @@ -197,13 +206,12 @@ export const MockApi = { ...processGroups, results, count: results.length, - totalCount: results.length, timeRangeCount: results.length }; } const filteredResults = results.filter( - (result) => (queryParams.processGroupRole && result.processGroupRole === queryParams.processGroupRole) || true + (result) => queryParams.processGroupRole && result.processGroupRole === queryParams.processGroupRole ); const paginatedResults = filteredResults.slice( @@ -215,7 +223,6 @@ export const MockApi = { ...processGroups, results: paginatedResults, count: filteredResults.length, - totalCount: filteredResults.length, timeRangeCount: filteredResults.length }; }, @@ -236,7 +243,6 @@ export const MockApi = { ...processes, results, count: results.length, - totalCount: results.length, timeRangeCount: results.length }; } @@ -439,10 +445,6 @@ export function loadMockServer() { this.get(MockApiPaths.PrometheusQuery, MockApi.getPrometheusQuery); this.get(MockApiPaths.PrometheusRangeQuery, MockApi.getPrometheusRangeQuery); - this.get(`${prefix}/sites/:id/links`, (_, { params: { id } }) => ({ - results: links.results.filter(() => sites.results.find((site) => site.identity === id)) - })); - this.get(`${prefix}/processgrouppairs`, () => processGroupPairs); this.get(`${prefix}/processgrouppairs/:id`, (_, { params: { id } }) => ({ diff --git a/src/core/components/SKSanckeyChart/SkSankey.constants.ts b/src/core/components/SKSanckeyChart/SkSankey.constants.ts index 0dca4359..0825fa7d 100644 --- a/src/core/components/SKSanckeyChart/SkSankey.constants.ts +++ b/src/core/components/SKSanckeyChart/SkSankey.constants.ts @@ -4,29 +4,29 @@ export const DEFAULT_SANKEY_CHART_HEIGHT = '350px'; // Themes //Filters -export const sankeyMetricOptions = [ - { id: 'none', name: 'Display only relationships' }, - { id: 'byterate', name: 'Compare avg. byterate (last hour)' } +export const SankeyMetricOptions = [ + { id: 'none', label: 'Display only pairs' }, + { id: 'byterate', label: 'Display avg. byterate (last hour)' } ]; -export const ServiceClientResourceOptions: { name: string; id: 'client' | 'clientSite' }[] = [ +export const ServiceClientResourceOptions: { label: string; id: 'client' | 'clientSite' }[] = [ { - name: 'Client sites', + label: 'Client sites', id: 'clientSite' }, { - name: 'Client processes', + label: 'Client processes', id: 'client' } ]; -export const ServiceServerResourceOptions: { name: string; id: 'server' | 'serverSite' }[] = [ +export const ServiceServerResourceOptions: { label: string; id: 'server' | 'serverSite' }[] = [ { - name: 'Server sites', + label: 'Server sites', id: 'serverSite' }, { - name: 'Server processes', + label: 'Server processes', id: 'server' } ]; diff --git a/src/core/components/SKSanckeyChart/SkSankeyFilter.tsx b/src/core/components/SKSanckeyChart/SkSankeyFilter.tsx index 0b9a36e7..bbdb1d01 100644 --- a/src/core/components/SKSanckeyChart/SkSankeyFilter.tsx +++ b/src/core/components/SKSanckeyChart/SkSankeyFilter.tsx @@ -1,63 +1,26 @@ -import { useState, MouseEvent as ReactMouseEvent, Ref, FC, useEffect, memo } from 'react'; +import { useState, FC, useEffect, memo } from 'react'; -import { - Toolbar, - ToolbarContent, - ToolbarToggleGroup, - MenuToggle, - MenuToggleElement, - Select, - SelectList, - SelectOption, - ToolbarItem -} from '@patternfly/react-core'; +import { Toolbar, ToolbarContent, ToolbarToggleGroup, ToolbarItem, ToolbarGroup } from '@patternfly/react-core'; import { FilterIcon } from '@patternfly/react-icons'; -import { SankeyFilterValues } from '@sk-types/SkSankeyChart.interfaces'; - -import { sankeyMetricOptions, ServiceClientResourceOptions, ServiceServerResourceOptions } from './SkSankey.constants'; +import { SankeyMetricOptions, ServiceClientResourceOptions, ServiceServerResourceOptions } from './SkSankey.constants'; +import SkSelect from '../SkSelect'; const SankeyFilter: FC<{ onSearch?: Function }> = memo(({ onSearch }) => { - const [isClientExpanded, setIsClientExpanded] = useState(false); - const [isServerExpanded, setIsServerExpanded] = useState(false); - const [isMetricsExpanded, setIsMetricExpanded] = useState(false); - const [clientType, setClientType] = useState(ServiceClientResourceOptions[0].id); const [serverType, setServerType] = useState(ServiceServerResourceOptions[0].id); + const [visibleMetrics, setVisibleMetrics] = useState(SankeyMetricOptions[0].id); - const [visibleMetrics, setVisibleMetrics] = useState(sankeyMetricOptions[0].id); - - const handleSelectClient = (_?: ReactMouseEvent, selected?: string | number) => { - const selection = selected as keyof SankeyFilterValues; - - setClientType(selection as 'client' | 'clientSite'); - setIsClientExpanded(false); - }; - - const handleSelectServer = (_?: ReactMouseEvent, selected?: string | number) => { - const selection = selected as keyof SankeyFilterValues; - - setServerType(selection as 'server' | 'serverSite'); - setIsServerExpanded(false); - }; - - const handleMetricSelect = (_?: ReactMouseEvent, selected?: string | number) => { - const selection = selected as keyof SankeyFilterValues; - - setVisibleMetrics(selection as string); - setIsMetricExpanded(false); - }; - - const handleClientToggle = () => { - setIsClientExpanded(!isClientExpanded); + const handleSelectClient = (selected?: string | number) => { + setClientType(selected as 'client' | 'clientSite'); }; - const handleServerToggle = () => { - setIsServerExpanded(!isServerExpanded); + const handleSelectServer = (selected?: string | number) => { + setServerType(selected as 'server' | 'serverSite'); }; - const handleMetricsToggle = () => { - setIsMetricExpanded(!isMetricsExpanded); + const handleMetricSelect = (selected?: string | number) => { + setVisibleMetrics(selected as string); }; useEffect(() => { @@ -66,100 +29,25 @@ const SankeyFilter: FC<{ onSearch?: Function }> = memo(({ onSearch }) => { } }, [onSearch, clientType, visibleMetrics, serverType]); - const clientMenuItems = ServiceClientResourceOptions.map((option) => ( - - {option.name} - - )); - - const serverMenuItems = ServiceServerResourceOptions.map((option) => ( - - {option.name} - - )); - - const metricMenuItems = sankeyMetricOptions.map((option) => ( - - {option.name} - - )); - - const filterClientSelected = ServiceClientResourceOptions.find(({ id }) => id === clientType)?.name; - const filterServerSelected = ServiceServerResourceOptions.find(({ id }) => id === serverType)?.name; - const metricNameSelected = sankeyMetricOptions.find(({ id }) => id === visibleMetrics)?.name; - - const toggleGroupItems = ( - <> - - From - - - - - - - - To - - - - - - - - - - - ); - - const toolbarItems = ( - } breakpoint="xl"> - {toggleGroupItems} - - ); - return ( - {toolbarItems} + + } breakpoint="xl"> + + + + + + + + + + + + + + + ); }); diff --git a/src/core/components/SKSanckeyChart/index.tsx b/src/core/components/SKSanckeyChart/index.tsx index 81627f49..b539dd42 100644 --- a/src/core/components/SKSanckeyChart/index.tsx +++ b/src/core/components/SKSanckeyChart/index.tsx @@ -10,17 +10,8 @@ import { SkSankeyChartLink, SkSankeyChartNode } from '@sk-types/SkSankeyChart.in import { DEFAULT_SANKEY_CHART_FLOW_VALUE, DEFAULT_SANKEY_CHART_HEIGHT } from './SkSankey.constants'; import SKEmptyData from '../SkEmptyData'; +import SankeyFilter from './SkSankeyFilter'; -interface SkSankeyChartProps { - nodes: SkSankeyChartNode[]; - links: SkSankeyChartLink[]; -} - -/** - * Adds a listener for changes to the theme class on the document element. - * @param callback - The function to be called when the theme class changes. - * @returns A function to disconnect the observer. - */ export function addThemeChangeListener(callback: Function) { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { @@ -36,32 +27,20 @@ export function addThemeChangeListener(callback: Function) { return () => observer.disconnect(); } -/** - * Returns the color of a node in the SkSankeyChart. - * If the node has a specific color defined, it returns that color. - * Otherwise, it returns the default color VarColors.Black500. - * @param nodeColor - The color defined for the node (optional). - * @returns The color of the node. - */ export function getColors({ nodeColor }: SkSankeyChartNode): string { return nodeColor || VarColors.Black500; } -/** - * Formats the given value as a string, using the `formatByteRate` function if the value is not equal to the default flow value. - * @param value The value to format. - * @returns The formatted value as a string. - */ export function valueFormat(value: number): string { return value === DEFAULT_SANKEY_CHART_FLOW_VALUE ? '' : formatByteRate(value); } -/** - * A Sankey chart component that displays data in a flow diagram format. - * @param data The data to be displayed in the chart. - * @returns A React component that displays the Sankey chart. - */ -const SkSankeyChart: FC<{ data: SkSankeyChartProps }> = function ({ data }) { +interface SkSankeyChartProps { + nodes: SkSankeyChartNode[]; + links: SkSankeyChartLink[]; +} + +const SkSankeyChart: FC<{ data: SkSankeyChartProps; onSearch: Function }> = function ({ data, onSearch }) { if (!data.links.length) { return ( = function ({ data }) { } return ( -
- -
+ <> + + +
+ +
+ ); }; diff --git a/src/core/components/SkBiFlowList/BiFlowList.constants.ts b/src/core/components/SkBiFlowList/BiFlowList.constants.ts index ea8d25d5..a1643bb4 100644 --- a/src/core/components/SkBiFlowList/BiFlowList.constants.ts +++ b/src/core/components/SkBiFlowList/BiFlowList.constants.ts @@ -10,6 +10,7 @@ import { BiFlowResponse, HttpBiflow } from '@sk-types/REST.interfaces'; import { SKTableColumn } from 'types/SkTable.interfaces'; import { BiFlowListLabels } from './BiFlowList.enum'; +import { SkSelectOption } from '../SkSelect'; export const customCells = { ProcessNameLinkCell: (props: SkLinkCellProps) => @@ -193,21 +194,21 @@ export const httpBiFlowColumns: SKTableColumn[] = [ } ]; -const defaultSelectOptions: { name: string; id: string }[] = [ +const defaultSelectOptions: SkSelectOption[] = [ { - name: BiFlowListLabels.Client, + label: BiFlowListLabels.Client, id: 'sourceProcessName' }, { - name: BiFlowListLabels.Server, + label: BiFlowListLabels.Server, id: 'destProcessName' }, { - name: BiFlowListLabels.Site, + label: BiFlowListLabels.Site, id: 'sourceSiteName' }, { - name: BiFlowListLabels.ServerSite, + label: BiFlowListLabels.ServerSite, id: 'destSiteName' } ]; diff --git a/src/core/components/SkSelect/index.tsx b/src/core/components/SkSelect/index.tsx index d95ca819..1ad6512e 100644 --- a/src/core/components/SkSelect/index.tsx +++ b/src/core/components/SkSelect/index.tsx @@ -1,12 +1,13 @@ -import { FC, ReactNode, Ref, MouseEvent as ReactMouseEvent, useState } from 'react'; +import { FC, ReactNode, Ref, MouseEvent as ReactMouseEvent, useState, useCallback } from 'react'; import { MenuToggle, MenuToggleElement, Select, SelectGroup, SelectList, SelectOption } from '@patternfly/react-core'; -type Selected = string | string[] | undefined; +type SelectParam = string | number | undefined; +type Selected = SelectParam | string[]; -interface SkSelectOption { +export interface SkSelectOption { id: string; - label: string; + label: string | number; isDisabled?: boolean; } @@ -15,8 +16,10 @@ export interface SkSelectGroupedOptions { items: SkSelectOption[]; } +type SelectOptions = SkSelectOption[] | SkSelectGroupedOptions[]; + interface SkSelectProps { - items: SkSelectOption[] | SkSelectGroupedOptions[]; + items: SelectOptions; selected: Selected; isGrouped?: boolean; placeholder?: string; @@ -27,7 +30,7 @@ interface SkSelectProps { optionsDisabled?: { [key: string]: boolean }; icon?: ReactNode; formatToggle?: (value: Selected) => Selected; - onSelect: (value: string) => void; + onSelect: (value: SelectParam) => void; } const FILTER_BY_SERVICE_MAX_HEIGHT = 400; @@ -48,31 +51,33 @@ const SkSelect: FC = function ({ }) { const [isOpen, setIsOpen] = useState(false); - const handleToggle = () => { + const handleToggle = useCallback(() => { setIsOpen((prev) => !prev); - }; + }, []); - const handleSelect = (_: ReactMouseEvent | undefined, selection: string | number | undefined) => { - if (forceClose) { - setIsOpen(false); - } + const handleSelect = useCallback( + (_: ReactMouseEvent | undefined, selection: SelectParam) => { + if (forceClose) { + setIsOpen(false); + } - onSelect(selection as string); - }; + onSelect(selection); + }, + [forceClose, onSelect] + ); return ( ) => ( - - {selectedFilter} - - )} - onSelect={handleChangeFilterType} + + - - {selectOptions.map(({ id, name }) => ( - - {name} - - ))} - - + items={selectOptions} + onSelect={handleChangeFilterType} + icon={} + /> - + void; } -const ActiveFilter: FC = function ({ id, name, searchValue, onDelete }) { +const ActiveFilter: FC = function ({ id, label, searchValue, onDelete }) { return ( - - + + {searchValue} @@ -174,10 +149,10 @@ interface ActiveFiltersProps { const ActiveFilters: FC = function ({ filterSelected, onDeleteFilter, onDeleteAll }) { return ( - + {filterSelected.map((filter) => ( onDeleteFilter(filter.id)} /> @@ -185,7 +160,7 @@ const ActiveFilters: FC = function ({ filterSelected, onDele - diff --git a/src/core/components/SkTable/SkSearchFilter/services/index.ts b/src/core/components/SkTable/SkSearchFilter/services/index.ts index 6356b871..c32a8fd6 100644 --- a/src/core/components/SkTable/SkSearchFilter/services/index.ts +++ b/src/core/components/SkTable/SkSearchFilter/services/index.ts @@ -1,8 +1,9 @@ -import { FilterType, FilterSelected, FilterTypeWithSearchText } from '@sk-types/SkFilter.interfaces'; +import { SkSelectOption } from '@core/components/SkSelect'; +import { FilterSelected, FilterTypeWithSearchText } from '@sk-types/SkFilter.interfaces'; export const SkSearchFilterController = { getFilterTypesWithSearchValues: ( - selectOptions: FilterType[], + selectOptions: SkSelectOption[], filterValues: FilterSelected | undefined ): FilterTypeWithSearchText[] => { if (!filterValues) { @@ -11,9 +12,9 @@ export const SkSearchFilterController = { return selectOptions .filter(({ id }) => filterValues[id as keyof FilterSelected]) - .map(({ id, name }) => ({ + .map(({ id, label }) => ({ id, - name, + label, searchValue: filterValues[id as keyof FilterSelected] as string })); } diff --git a/src/core/components/SkTimeRangeFilter/index.tsx b/src/core/components/SkTimeRangeFilter/index.tsx deleted file mode 100644 index 14feafc9..00000000 --- a/src/core/components/SkTimeRangeFilter/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { FC, useState } from 'react'; - -import { OutlinedClockIcon } from '@patternfly/react-icons'; - -import { defaultTimeInterval, timeIntervalMap } from '@config/prometheus'; - -import SkSelect from '../SkSelect'; - -interface TimeRangeFilterProps { - duration?: number; - onSelectTimeInterval: ({ - start, - end, - duration - }: { - start: number | undefined; - end: number | undefined; - duration: number | undefined; - }) => void; -} - -const SkTimeRangeFilter: FC = function ({ duration, onSelectTimeInterval }) { - const [startLabel, setStartLabel] = useState(duration || defaultTimeInterval.seconds); - - const handleSelectFromTimeInterval = (seconds: string) => { - setStartLabel(Number(seconds)); - - if (onSelectTimeInterval) { - onSelectTimeInterval({ start: undefined, end: undefined, duration: Number(seconds) }); - } - }; - - return ( - ({ id: seconds.toString(), label }))} - icon={} - formatToggle={() => findDurationLabel(duration)} - onSelect={handleSelectFromTimeInterval} - /> - ); -}; - -export default SkTimeRangeFilter; -function findDurationLabel(duration?: number) { - return ( - Object.values(timeIntervalMap).find(({ seconds }) => seconds === duration)?.label || timeIntervalMap.oneMinute.label - ); -} diff --git a/src/core/components/SkUpdateDataButton/index.tsx b/src/core/components/SkUpdateDataButton/index.tsx index b7a7e0ca..af846eb5 100644 --- a/src/core/components/SkUpdateDataButton/index.tsx +++ b/src/core/components/SkUpdateDataButton/index.tsx @@ -1,58 +1,45 @@ -import { FC, useMemo, MouseEvent as ReactMouseEvent, useState, useCallback, Ref, useRef, useEffect } from 'react'; - -import { - Button, - MenuToggle, - MenuToggleElement, - Select, - SelectList, - SelectOption, - debounce -} from '@patternfly/react-core'; +import { FC, useMemo, useState, useCallback, useRef, useEffect } from 'react'; + +import { Button, debounce } from '@patternfly/react-core'; import { SyncIcon } from '@patternfly/react-icons'; import { useIsFetching, useQueryClient } from '@tanstack/react-query'; import { getDataFromSession, storeDataToSession } from '@core/utils/persistData'; -type validIntervals = 'Refresh off' | '15s' | '30s' | '60s' | '120s'; - -interface RefreshDataIntervalProps { - key: validIntervals; - value: number; -} - -interface SkUpdateDataButtonProps { - isLoading?: boolean; - onClick?: Function; - onRefreshIntervalSelected?: Function; - refreshIntervalDefault?: validIntervals; -} +import SkSelect, { SkSelectOption } from '../SkSelect'; -export const refreshDataIntervalMap: RefreshDataIntervalProps[] = [ +export const refreshDataIntervalMap: SkSelectOption[] = [ { - key: 'Refresh off', - value: 0 + label: 'Refresh off', + id: `${0}` }, { - key: '15s', - value: 15 * 1000 + label: '15s', + id: `${15 * 1000}` }, { - key: '30s', - value: 30 * 1000 + label: '30s', + id: `${30 * 1000}` }, { - key: '60s', - value: 60 * 1000 + label: '60s', + id: `${60 * 1000}` }, { - key: '120s', - value: 120 * 1000 + label: '120s', + id: `${120 * 1000}` } ]; const REFRESH_INTERVAL_KEY = 'refreshIntervalSelected'; +interface SkUpdateDataButtonProps { + isLoading?: boolean; + onClick?: Function; + onRefreshIntervalSelected?: Function; + refreshIntervalDefault?: string; +} + const SkUpdateDataButton: FC = function ({ onClick, onRefreshIntervalSelected, @@ -65,23 +52,12 @@ const SkUpdateDataButton: FC = function ({ predicate: (query) => query.queryKey[0] !== 'QueriesGetUser' && query.queryKey[0] !== 'QueryLogout' }); - const [isSelectOpen, setSelectOpen] = useState(false); const [refreshIntervalSelected, setSelectIntervalSelected] = useState( - getDataFromSession(REFRESH_INTERVAL_KEY) || refreshIntervalDefault || refreshDataIntervalMap[0].key + getDataFromSession(REFRESH_INTERVAL_KEY) || refreshIntervalDefault || `${refreshDataIntervalMap[0].id}` ); const refreshIntervalId = useRef(); - const refreshIntervalOptions = useMemo( - () => - refreshDataIntervalMap.map(({ key }, index) => ( - - {key} - - )), - [] - ); - const revalidateLiveQueries = useCallback(() => { queryClient.invalidateQueries({ refetchType: 'active', @@ -94,14 +70,12 @@ const SkUpdateDataButton: FC = function ({ }, [onClick, queryClient]); const handleSelectRefreshInterval = useCallback( - (_: ReactMouseEvent | undefined, selection: string | number | undefined) => { + (selection: string | number | undefined) => { const refreshDataIntervalSelected = selection as string; setSelectIntervalSelected(refreshDataIntervalSelected); storeDataToSession('refreshIntervalSelected', refreshDataIntervalSelected); - setSelectOpen(false); - if (onRefreshIntervalSelected) { onRefreshIntervalSelected(findRefreshDataIntervalValueFromLabel(refreshDataIntervalSelected)); } @@ -128,23 +102,11 @@ const SkUpdateDataButton: FC = function ({ return (
- + />