diff --git a/src/lib/components/SearchBar/QueryBuildHelper.js b/src/lib/components/SearchBar/QueryBuildHelper.js index 302ecd9b9..35a947cad 100644 --- a/src/lib/components/SearchBar/QueryBuildHelper.js +++ b/src/lib/components/SearchBar/QueryBuildHelper.js @@ -1,18 +1,23 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { List, Grid } from 'semantic-ui-react'; +import { withState } from 'react-searchkit'; -export class QueryBuildHelper extends Component { +class _QueryBuildHelper extends Component { addToQuery = field => { - const { currentQueryString, updateQueryString } = this.props; + const { currentQueryState, updateQueryState } = this.props; + const { queryString } = currentQueryState; + const defaultVal = field.defaultValue ? field.defaultValue : '*'; const newCriteriaString = `${field.field}:${defaultVal}`; - const previousQueryString = currentQueryString; + const previousQueryString = queryString; if (previousQueryString === '') { - updateQueryString(newCriteriaString); + updateQueryState({ queryString: newCriteriaString }); } else { - updateQueryString(`${previousQueryString} AND ${newCriteriaString}`); + updateQueryState({ + queryString: `${previousQueryString} AND ${newCriteriaString}`, + }); } }; @@ -46,6 +51,7 @@ export class QueryBuildHelper extends Component { render() { const { fields } = this.props; + return ( @@ -58,10 +64,10 @@ export class QueryBuildHelper extends Component { } } -QueryBuildHelper.propTypes = { +_QueryBuildHelper.propTypes = { fields: PropTypes.array.isRequired, - currentQueryString: PropTypes.string.isRequired, - updateQueryString: PropTypes.func.isRequired, + updateQueryState: PropTypes.func.isRequired, + currentQueryState: PropTypes.object.isRequired, }; -QueryBuildHelper.defaultProps = {}; +export const QueryBuildHelper = withState(_QueryBuildHelper); diff --git a/src/lib/components/SearchBar/SearchBar.js b/src/lib/components/SearchBar/SearchBar.js deleted file mode 100644 index d501dfa1e..000000000 --- a/src/lib/components/SearchBar/SearchBar.js +++ /dev/null @@ -1,116 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; -import { Input } from 'semantic-ui-react'; -import { QueryBuildHelper } from './QueryBuildHelper'; - -class SearchBar extends Component { - constructor(props) { - super(props); - const { queryString } = this.props; - this.state = { - currentValue: queryString || '', - }; - } - - componentDidMount() { - if (this.searchInput) { - this.searchInput.focus(); - } - } - - onInputChange = queryString => { - const { updateQueryOnChange, updateQueryString } = this.props; - if (updateQueryOnChange) { - updateQueryString(queryString); - } - this.setState({ - currentValue: queryString, - }); - }; - - onKeyPressHandler = event => { - if (event.key === 'Enter') { - this.executeSearch(); - } - }; - - executeSearch = () => { - const { updateQueryString } = this.props; - const { currentValue } = this.state; - updateQueryString(currentValue); - }; - - render() { - const { - buttonColor, - currentQueryString, - executeSearch: parentSearch, - onKeyPressHandler, - placeholder, - queryHelperFields, - queryString, - updateQueryOnChange, - updateQueryString, - ...otherProps - } = this.props; - const { currentValue } = this.state; - return ( - <> - this.onInputChange(value)} - value={currentValue} - onKeyPress={event => - onKeyPressHandler - ? onKeyPressHandler(event) - : this.onKeyPressHandler(event) - } - ref={input => { - this.searchInput = input; - }} - {...otherProps} - className={`${otherProps.className} ils-searchbar`} - /> - {queryHelperFields.length > 0 && ( - - )} - - ); - } -} - -SearchBar.propTypes = { - buttonColor: PropTypes.string, - executeSearch: PropTypes.func, - currentQueryString: PropTypes.string, - onKeyPressHandler: PropTypes.func, - placeholder: PropTypes.string, - queryHelperFields: PropTypes.array, - queryString: PropTypes.string, - updateQueryOnChange: PropTypes.bool, - updateQueryString: PropTypes.func.isRequired, -}; - -SearchBar.defaultProps = { - buttonColor: null, - currentQueryString: null, - executeSearch: null, - onKeyPressHandler: null, - placeholder: 'Search for books, series, articles, publications...', - queryHelperFields: [], - queryString: '', - updateQueryOnChange: false, -}; - -export default SearchBar; diff --git a/src/lib/components/SearchBar/SearchBar.test.js b/src/lib/components/SearchBar/SearchBar.test.js deleted file mode 100644 index c2d33e845..000000000 --- a/src/lib/components/SearchBar/SearchBar.test.js +++ /dev/null @@ -1,95 +0,0 @@ -import React from 'react'; -import { mount } from 'enzyme'; -import SearchBar from './SearchBar'; - -describe('LoansSearch SearchBar tests', () => { - let component; - afterEach(() => { - component.unmount(); - }); - - const currentQueryString = 'The Gulf: The Making of An American Sea'; - - it('should render the current query string', () => { - component = mount( - {}} - placeholder="Search" - /> - ); - expect(component).toMatchSnapshot(); - }); - - it('should call executeSearch on key `enter` pressed only', () => { - const mockedExecuteSearch = jest.fn(); - component = mount( - - ); - - const input = component.find('Input').find('input'); - input.simulate('keypress', { key: 'Enter' }); - expect(mockedExecuteSearch).toHaveBeenCalled(); - - mockedExecuteSearch.mockClear(); - - input.simulate('keypress', { key: 'Backspace' }); - expect(mockedExecuteSearch).not.toHaveBeenCalled(); - }); - - it('should call executeSearch on button click', () => { - const mockedExecuteSearch = jest.fn(); - component = mount( - - ); - const input = component - .find('Input') - .find('Icon') - .find('i'); - input.simulate('click'); - expect(mockedExecuteSearch).toHaveBeenCalled(); - }); - - it('should render search bar with query helper', () => { - const helperFields = [ - { - name: 'author', - field: 'authors.full_name', - defaultValue: 'Doe, John', - }, - { - name: 'created', - field: '_created', - }, - ]; - const mockedExecuteSearch = jest.fn(); - component = mount( - - ); - - expect(component).toMatchSnapshot(); - - const listItem = component.find('ListItem'); - expect(listItem).toHaveLength(2); - - expect( - component - .find('ListItem') - .at(0) - .text() - ).toEqual('author'); - }); -}); diff --git a/src/lib/components/SearchBar/SearchBarILS.js b/src/lib/components/SearchBar/SearchBarILS.js new file mode 100644 index 000000000..378b1a45e --- /dev/null +++ b/src/lib/components/SearchBar/SearchBarILS.js @@ -0,0 +1,77 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import { Input } from 'semantic-ui-react'; + +export class SearchBarILS extends Component { + state = { currentValue: '' }; + + componentDidMount() { + if (this.focusInput) { + this.focusInput.focus(); + } + } + + onKeyPressHandler = (event, input) => { + const { onSearchHandler } = this.props; + if (event.key === 'Enter') { + const { currentValue } = this.state; + onSearchHandler(currentValue); + } + }; + + onPasteHandler = event => { + const { onSearchHandler } = this.props; + const queryString = (event.clipboardData || window.clipboardData).getData( + 'text' + ); + onSearchHandler(queryString); + }; + + render() { + const { + className: parentClass, + onKeyPressHandler: parentKeyPressHandler, + onSearchHandler, + onPasteHandler, + placeholder, + ...rest + } = this.props; + const { currentValue } = this.state; + return ( + onSearchHandler(currentValue), + }} + onChange={(event, { value }) => { + this.setState({ currentValue: value }); + }} + onKeyPress={parentKeyPressHandler || this.onKeyPressHandler} + onPaste={onPasteHandler || this.onPasteHandler} + fluid + size="big" + placeholder={placeholder} + className={`${parentClass} ils-searchbar`} + ref={input => { + this.focusInput = input; + }} + {...rest} + /> + ); + } +} + +SearchBarILS.propTypes = { + onKeyPressHandler: PropTypes.func, + onPasteHandler: PropTypes.func, + onSearchHandler: PropTypes.func.isRequired, + placeholder: PropTypes.string, + className: PropTypes.string, +}; + +SearchBarILS.defaultProps = { + onKeyPressHandler: null, + onPasteHandler: null, + placeholder: '', + className: '', +}; diff --git a/src/lib/components/SearchBar/SearchBarILS.test.js b/src/lib/components/SearchBar/SearchBarILS.test.js new file mode 100644 index 000000000..f9b733065 --- /dev/null +++ b/src/lib/components/SearchBar/SearchBarILS.test.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { mount } from 'enzyme'; +import { SearchBarILS as SearchBar } from './SearchBarILS'; + +const mockedOnSearchHandler = jest.fn(); + +describe('SearchBar tests', () => { + let component; + afterEach(() => { + mockedOnSearchHandler.mockClear(); + component.unmount(); + }); + + it('should match snapshot', () => { + component = mount( + {}} placeholder="Search" /> + ); + expect(component).toMatchSnapshot(); + }); + + it('should call onSearchHandler only on `enter` key press', () => { + component = mount( + + ); + + const input = component.find('Input').find('input'); + input.simulate('keypress', { key: 'Enter' }); + expect(mockedOnSearchHandler).toHaveBeenCalled(); + + mockedOnSearchHandler.mockClear(); + + input.simulate('keypress', { key: 'Backspace' }); + expect(mockedOnSearchHandler).not.toHaveBeenCalled(); + }); + + it('should call executeSearch on button click', () => { + component = mount( + + ); + const input = component + .find('Input') + .find('Icon') + .find('i'); + input.simulate('click'); + expect(mockedOnSearchHandler).toHaveBeenCalled(); + }); +}); diff --git a/src/lib/components/SearchBar/__snapshots__/SearchBar.test.js.snap b/src/lib/components/SearchBar/__snapshots__/SearchBar.test.js.snap deleted file mode 100644 index 3e6e411d6..000000000 --- a/src/lib/components/SearchBar/__snapshots__/SearchBar.test.js.snap +++ /dev/null @@ -1,282 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`LoansSearch SearchBar tests should render search bar with query helper 1`] = ` - - -
- -