-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add search to table component (#2684)
* Add search to table component This commit adds a search capability to the table component. The search is case insensitive and respects normalises Unicode character differences. However, it is not fuzzy or can accommodate spelling mistakes. Furthermore, the change is supported via a story and several test cases, that describe the behaviour. * Functional JavaScript aka. fix ESLint Prefer array iteration methods over for loops * Implement changes proposed by Jamie Thanks for the feedback. I agree with all of it. * Ripping search out of the Table This commit removes the search API from the Table component and adds a reduced version to the @lib folder. The idea is that the components themselves are now responsible for handling search and the library just provides utilities and functions to make this simpler. * Move HostRelevantPatchesPage to new search API * Add search to UpgradablePackagesPage This commit adds search to the UpgradablePackagesPage. Furthermore, it adds a story for the page and splits the Page into a navigation and Redux independent part for easier design work. * Add inspect function This commit adds a Elixir inspired inspect function. Using this function, one can log data to the console, without breaking up long call chains. It's literally the identity function plus a "console.dir()". * Add test fro search * Add test for filtering in pages This commit adds tests for filtering the UpgradablePackagesPage and HostRelevantPatchesPage by their content via search. * Remove dead code This commit completely removes the search API from the Table. * Add search to UpgradablePackagesPage This commit adds search to the UpgradablePackagesPage. Furthermore, it adds a story for the page and splits the Page into a navigation and Redux independent part for easier design work. * Keep consistent casing * Fix case * Rename Page and UpgradablePackages * Fix ESLint * Implement changes proposed by Jamie
- Loading branch information
1 parent
af9e959
commit 2465cf4
Showing
11 changed files
with
188 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
const regularizeString = (str) => str.normalize().trim().toLowerCase(); | ||
|
||
export const containsSubstring = (str = '', substring = '') => | ||
regularizeString(str).includes(regularizeString(substring)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { faker } from '@faker-js/faker'; | ||
|
||
import { containsSubstring } from '.'; | ||
|
||
describe('search', () => { | ||
it('should always match with an empty search string', () => { | ||
expect(containsSubstring('', '')).toBe(true); | ||
expect(containsSubstring(faker.word.words(10), '')).toBe(true); | ||
}); | ||
|
||
it('should match strings case in an insensitive fashion', () => { | ||
const original = faker.word.words(1); | ||
const upper = original.toUpperCase(); | ||
const lower = original.toLowerCase(); | ||
|
||
expect(containsSubstring(original, upper)).toBe(true); | ||
expect(containsSubstring(original, lower)).toBe(true); | ||
}); | ||
|
||
it('should match substrings', () => { | ||
const original = faker.word.words(1); | ||
const sub = original.substring(original.length / 2); | ||
|
||
expect(containsSubstring(original, sub)).toBe(true); | ||
}); | ||
|
||
it('should not match not included words', () => { | ||
const words = faker.word.words(2).split(' '); | ||
|
||
expect(containsSubstring(words[0], words[1])).toBe(false); | ||
expect(containsSubstring('', words[1])).toBe(false); | ||
}); | ||
|
||
it('should match unicode in different forms', () => { | ||
const name1 = '\u0041\u006d\u00e9\u006c\u0069\u0065'; | ||
const name2 = '\u0041\u006d\u0065\u0301\u006c\u0069\u0065'; | ||
|
||
expect(containsSubstring(name1, name2)).toBe(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
assets/js/pages/UpgradablePackagesPage/UpgradablePackages.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React, { useState } from 'react'; | ||
import { EOS_SEARCH } from 'eos-icons-react'; | ||
|
||
import UpgradablePackagesList from '@common/UpgradablePackagesList'; | ||
import PageHeader from '@common/PageHeader'; | ||
import Input from '@common/Input'; | ||
import { containsSubstring } from '@lib/filter'; | ||
|
||
export default function UpgradablePackages({ hostName, upgradablePackages }) { | ||
const [search, setSearch] = useState(''); | ||
|
||
const displayedPackages = upgradablePackages.filter( | ||
({ name, patches }) => | ||
containsSubstring(name, search) || | ||
patches | ||
.map(({ advisory }) => containsSubstring(advisory, search)) | ||
.includes(true) | ||
); | ||
|
||
return ( | ||
<> | ||
<div className="flex flex-wrap"> | ||
<div className="flex w-2/3 h-auto overflow-ellipsis break-words"> | ||
<PageHeader> | ||
Upgradable packages: <span className="font-bold">{hostName}</span> | ||
</PageHeader> | ||
</div> | ||
<div className="flex w-1/3 justify-end"> | ||
<Input | ||
className="flex" | ||
onChange={(e) => setSearch(e.target.value)} | ||
placeholder="Search by Name or Patch" | ||
prefix={<EOS_SEARCH size="l" />} | ||
/> | ||
</div> | ||
</div> | ||
<UpgradablePackagesList upgradablePackages={displayedPackages} /> | ||
</> | ||
); | ||
} |
20 changes: 20 additions & 0 deletions
20
assets/js/pages/UpgradablePackagesPage/UpgradablePackages.stories.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from 'react'; | ||
|
||
import { upgradablePackageFactory } from '@lib/test-utils/factories/upgradablePackage'; | ||
import { hostFactory } from '@lib/test-utils/factories/hosts'; | ||
|
||
import UpgradablePackages from './UpgradablePackages'; | ||
|
||
export default { | ||
title: 'Layouts/UpgradablePackages', | ||
components: UpgradablePackages, | ||
argTypes: {}, | ||
render: (args) => <UpgradablePackages {...args} />, | ||
}; | ||
|
||
export const Default = { | ||
args: { | ||
hostName: hostFactory.build().hostname, | ||
upgradablePackages: upgradablePackageFactory.buildList(5), | ||
}, | ||
}; |
42 changes: 42 additions & 0 deletions
42
assets/js/pages/UpgradablePackagesPage/UpgradablePackages.test.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react'; | ||
import { screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import '@testing-library/jest-dom'; | ||
|
||
import { renderWithRouter as render } from '@lib/test-utils'; | ||
import { upgradablePackageFactory } from '@lib/test-utils/factories/upgradablePackage'; | ||
|
||
import UpgradablePackages from './UpgradablePackages'; | ||
|
||
describe('UpgradablePackages', () => { | ||
it('shows all packages by default', () => { | ||
const packages = upgradablePackageFactory.buildList(8); | ||
|
||
const { container } = render( | ||
<UpgradablePackages upgradablePackages={packages} /> | ||
); | ||
|
||
const tableRows = container.querySelectorAll('tbody > tr'); | ||
|
||
expect(tableRows.length).toBe(8); | ||
}); | ||
|
||
it('should filter package by its name', async () => { | ||
const user = userEvent.setup(); | ||
|
||
const packages = upgradablePackageFactory.buildList(8); | ||
const searchTerm = packages[0].name; | ||
|
||
const { container } = render( | ||
<UpgradablePackages upgradablePackages={packages} /> | ||
); | ||
|
||
const searchInput = screen.getByRole('textbox'); | ||
await user.click(searchInput); | ||
await user.type(searchInput, searchTerm); | ||
|
||
const tableRows = container.querySelectorAll('tbody > tr'); | ||
|
||
expect(tableRows.length).toBe(1); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters