diff --git a/.changeset/rich-lions-carry.md b/.changeset/rich-lions-carry.md new file mode 100644 index 0000000..afb39a7 --- /dev/null +++ b/.changeset/rich-lions-carry.md @@ -0,0 +1,5 @@ +--- +"@aonic-ui/pipelines": patch +--- + +add tab auto selection based on the availability of the tab data diff --git a/packages/pipelines/src/components/Output/Tabs/AdvancedClusterSecurity/AdvancedClusterSecurity.tsx b/packages/pipelines/src/components/Output/Tabs/AdvancedClusterSecurity/AdvancedClusterSecurity.tsx index 7a19a88..1d34336 100644 --- a/packages/pipelines/src/components/Output/Tabs/AdvancedClusterSecurity/AdvancedClusterSecurity.tsx +++ b/packages/pipelines/src/components/Output/Tabs/AdvancedClusterSecurity/AdvancedClusterSecurity.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; import { Tab, Tabs, TabTitleText } from '@patternfly/react-core'; +import { useFirstLoadedInput } from '../../hooks/useFirstLoadedInput'; +import { SubTab } from '../../Toolbar/types'; import { ACSCheckResults, ACSImageScanResult } from '../../types'; import { isEmpty } from '../../utils/helper-utils'; import ACSContextProvider from './AdvancedClusterSecurityContext'; @@ -27,13 +29,24 @@ const AdvancedClusterSecurity: React.FC = (acsProp [acsImageScanResult, acsImageCheckResults, acsDeploymentCheckResults].filter((a) => !isEmpty(a)) .length > 0; + const tabOrder: SubTab[] = [SubTab.imageScan, SubTab.imageCheck, SubTab.deploymentCheck]; + const firstLoadedTab = useFirstLoadedInput([ + { name: SubTab.imageScan, value: acsImageScanResult }, + { name: SubTab.imageCheck, value: acsImageCheckResults }, + { name: SubTab.deploymentCheck, value: acsDeploymentCheckResults }, + ]); + if (!showACSTab) { return null; } return ( - + {!isEmpty(acsImageScanResult) && ( Image Scan}>
diff --git a/packages/pipelines/src/components/Output/hooks/__tests__/useFirstLoadedInput.test.ts b/packages/pipelines/src/components/Output/hooks/__tests__/useFirstLoadedInput.test.ts new file mode 100644 index 0000000..9d4866f --- /dev/null +++ b/packages/pipelines/src/components/Output/hooks/__tests__/useFirstLoadedInput.test.ts @@ -0,0 +1,51 @@ +import { renderHook } from '@testing-library/react'; +import { useFirstLoadedInput } from '../useFirstLoadedInput'; + +describe('useFirstLoadedInput', () => { + test('should handle the invalid value', () => { + const { result } = renderHook(() => useFirstLoadedInput([])); + expect(result.current).toBeUndefined(); + }); + + test('should return the default value if the input value is empty', () => { + const { result } = renderHook(() => useFirstLoadedInput([{ name: 'tab-1', value: [] }])); + expect(result.current).toBe('tab-1'); + }); + test('should return the default value if the input value is undefined', () => { + const { result } = renderHook(() => + useFirstLoadedInput([{ name: 'tab-1', value: undefined as any }]), + ); + expect(result.current).toBe('tab-1'); + }); + + test('should identify the first input with some data in it', () => { + const { result } = renderHook(() => + useFirstLoadedInput([ + { name: 'tab-1', value: [] }, + { name: 'tab-2', value: ['data'] }, + ]), + ); + + expect(result.current).toBe('tab-2'); + }); + + test('should work with object values', () => { + const { result } = renderHook(() => + useFirstLoadedInput([ + { name: 'tab-1', value: [] }, + { name: 'tab-2', value: { key: 'data' } }, + ]), + ); + expect(result.current).toBe('tab-2'); + }); + + test('should work with string values', () => { + const { result } = renderHook(() => + useFirstLoadedInput([ + { name: 'tab-1', value: [] }, + { name: 'tab-2', value: 'data streaming' }, + ]), + ); + expect(result.current).toBe('tab-2'); + }); +}); diff --git a/packages/pipelines/src/components/Output/hooks/useFirstLoadedInput.ts b/packages/pipelines/src/components/Output/hooks/useFirstLoadedInput.ts new file mode 100644 index 0000000..bce2896 --- /dev/null +++ b/packages/pipelines/src/components/Output/hooks/useFirstLoadedInput.ts @@ -0,0 +1,25 @@ +import React from 'react'; + +export const useFirstLoadedInput = (inputs: { name: T; value: any }[]): T => { + const [firstLoadedInput, setFirstLoadedInput] = React.useState(); + + React.useEffect(() => { + for (let i = 0; i < inputs.length; i++) { + const inputValue = inputs[i].value; + if (typeof inputValue === 'object') { + if (Array.isArray(inputValue) && inputValue.length > 0) { + setFirstLoadedInput(inputs[i].name); + break; + } else if (!Array.isArray(inputValue) && Object.keys(inputValue).length > 0) { + setFirstLoadedInput(inputs[i].name); + break; + } + } else if (inputValue !== undefined && inputValue !== '') { + setFirstLoadedInput(inputs[i].name); + break; + } + } + }, [inputs]); + + return firstLoadedInput ?? inputs?.[0]?.name; +};