diff --git a/client/src/app/pages/search/components/SearchMenu.stories.tsx b/client/src/app/pages/search/components/SearchMenu.stories.tsx new file mode 100644 index 00000000..b05c1509 --- /dev/null +++ b/client/src/app/pages/search/components/SearchMenu.stories.tsx @@ -0,0 +1,72 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { IEntity, SearchMenu } from "./SearchMenu"; +import { Label, MenuItem } from "@patternfly/react-core"; +import React from "react"; + +const meta = { + title: "Components/Search/SearchMenu", + component: SearchMenu, + tags: ["autodocs"], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +function customFilterIncludes(list: IEntity[], searchString: string) { + let options: React.JSX.Element[] = list + .filter( + (option) => + option.id.toLowerCase().includes(searchString.toLowerCase()) || + option.title?.toLowerCase().includes(searchString.toLowerCase()) || + option.description?.toLowerCase().includes(searchString.toLowerCase()) + ) + .map((option) => ( + + {option.title} + + )); + + if (options.length > 10) { + options = options.slice(0, 10); + } else { + options = [ + ...options, + ...list + .filter( + (option: IEntity) => + !option.id.startsWith(searchString.toLowerCase()) && + option.id.includes(searchString.toLowerCase()) + ) + .map((option: IEntity) => ( + + {option.title} + + )), + ].slice(0, 10); + } + + return options; +} + +export const DefaultState: Story = { + args: { + onChangeSearch: jest.fn(), + }, +}; + +export const WithCustomFilter: Story = { + args: { + filterFunction: customFilterIncludes, + onChangeSearch: jest.fn(), + }, +}; diff --git a/client/src/app/pages/search/components/SearchMenu.tsx b/client/src/app/pages/search/components/SearchMenu.tsx index 19091806..67c14d8e 100644 --- a/client/src/app/pages/search/components/SearchMenu.tsx +++ b/client/src/app/pages/search/components/SearchMenu.tsx @@ -14,6 +14,7 @@ import { HubRequestParams } from "@app/api/models"; import { useFetchPackages } from "@app/queries/packages"; import { useFetchSBOMs } from "@app/queries/sboms"; import { useFetchVulnerabilities } from "@app/queries/vulnerabilities"; +import { Link } from "react-router-dom"; export interface IEntity { id: string; @@ -50,9 +51,10 @@ export function filterEntityListByValue(list: IEntity[], searchString: string) { itemId={option.id} key={option.id} description={option.description} - to={option.navLink} > - {option.title} + + {option.title} + )); @@ -120,8 +122,7 @@ function useAllEntities(filterText: string) { const transformedPackages: IEntity[] = packages.map((item) => ({ id: item.uuid, - title: "item.decomposedPurl ? item.decomposedPurl?.name : item.purl", - description: "item.decomposedPurl?.namespace", + title: item.purl, navLink: `/packages/${item.uuid}`, type: "Package", typeColor: "cyan", @@ -193,10 +194,7 @@ export const SearchMenu: React.FC = ({ ) { setIsAutocompleteOpen(true); - console.table(entityList); - console.log(newValue); const options = filterFunction(entityList, newValue); - console.log(options); // The menu is hidden if there are no options setIsAutocompleteOpen(options.length > 0); diff --git a/client/tsconfig.json b/client/tsconfig.json index c2d176d5..38dd6ff4 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "include": ["src/**/*", "config/**/*", "types/**/*", "setupTests.ts"], + "include": ["src/**/*", "config/**/*", "types/**/*"], "compilerOptions": { "outDir": "dist", "baseUrl": ".",