diff --git a/awx/ui_next/package-lock.json b/awx/ui_next/package-lock.json index db64b4ef90..91d63d9b14 100644 --- a/awx/ui_next/package-lock.json +++ b/awx/ui_next/package-lock.json @@ -13354,6 +13354,17 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2", "scheduler": "^0.13.6" + }, + "dependencies": { + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } } }, "react-codemirror2": { @@ -13370,6 +13381,17 @@ "object-assign": "^4.1.1", "prop-types": "^15.6.2", "scheduler": "^0.13.6" + }, + "dependencies": { + "scheduler": { + "version": "0.13.6", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", + "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + } } }, "react-fast-compare": { @@ -14398,15 +14420,6 @@ "xmlchars": "^2.1.1" } }, - "scheduler": { - "version": "0.13.6", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz", - "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" - } - }, "scheduler": { "version": "0.15.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.15.0.tgz", diff --git a/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx b/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx index 8f8d0ecea6..b91cdf977e 100644 --- a/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx +++ b/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx @@ -15,6 +15,8 @@ import Search from '../Search'; import Sort from '../Sort'; import VerticalSeparator from '../VerticalSeparator'; +import { QSConfig } from '@types'; + const AWXToolbar = styled.div` --awx-toolbar--BackgroundColor: var(--pf-global--BackgroundColor--light-100); --awx-toolbar--BorderColor: #ebebeb; @@ -98,6 +100,7 @@ class DataListToolbar extends React.Component { sortedColumnKey, additionalControls, i18n, + qsConfig, } = this.props; const showExpandCollapse = onCompact && onExpand; @@ -120,6 +123,7 @@ class DataListToolbar extends React.Component { )} ', () => { let toolbar; + const QS_CONFIG = { + namespace: 'organization', + dateFields: ['modified', 'created'], + defaultParams: { page: 1, page_size: 5, order_by: 'name' }, + integerFields: ['page', 'page_size'], + }; + afterEach(() => { if (toolbar) { toolbar.unmount(); @@ -28,6 +35,7 @@ describe('', () => { toolbar = mountWithContexts( ', () => { toolbar = mountWithContexts( ', () => { toolbar = mountWithContexts( ', () => { toolbar = mountWithContexts( ', () => { toolbar = mountWithContexts( ', () => { toolbar = mountWithContexts( field === searchKey).length || + qsConfig.dateFields.filter(field => field === searchKey).length; + + // TODO: this will probably become more sophisticated, where date + // fields and string fields are passed to a formatter + const actualSearchKey = isNonStringField + ? searchKey + : `${searchKey}__icontains`; + + onSearch(actualSearchKey, searchValue); this.setState({ searchValue: '' }); } @@ -202,6 +213,7 @@ class Search extends React.Component { } Search.propTypes = { + qsConfig: QSConfig.isRequired, columns: PropTypes.arrayOf(PropTypes.object).isRequired, onSearch: PropTypes.func, sortedColumnKey: PropTypes.string, diff --git a/awx/ui_next/src/components/Search/Search.test.jsx b/awx/ui_next/src/components/Search/Search.test.jsx index e611d876c3..d0ee274107 100644 --- a/awx/ui_next/src/components/Search/Search.test.jsx +++ b/awx/ui_next/src/components/Search/Search.test.jsx @@ -5,6 +5,13 @@ import Search from './Search'; describe('', () => { let search; + const QS_CONFIG = { + namespace: 'organization', + dateFields: ['modified', 'created'], + defaultParams: { page: 1, page_size: 5, order_by: 'name' }, + integerFields: ['page', 'page_size'], + }; + afterEach(() => { if (search) { search = null; @@ -22,7 +29,12 @@ describe('', () => { const onSearch = jest.fn(); search = mountWithContexts( - + ); search.find(searchTextInput).instance().value = 'test-321'; @@ -39,7 +51,12 @@ describe('', () => { ]; const onSearch = jest.fn(); const wrapper = mountWithContexts( - + ).find('Search'); expect(wrapper.state('isSearchDropdownOpen')).toEqual(false); wrapper.instance().handleDropdownToggle(true); @@ -58,7 +75,12 @@ describe('', () => { ]; const onSearch = jest.fn(); const wrapper = mountWithContexts( - + ).find('Search'); expect(wrapper.state('searchKey')).toEqual('name'); wrapper diff --git a/awx/ui_next/src/screens/Job/JobList/JobList.jsx b/awx/ui_next/src/screens/Job/JobList/JobList.jsx index 7836aabf9a..c5460b6f7b 100644 --- a/awx/ui_next/src/screens/Job/JobList/JobList.jsx +++ b/awx/ui_next/src/screens/Job/JobList/JobList.jsx @@ -183,6 +183,7 @@ class JobList extends Component { showExpandCollapse isAllSelected={isAllSelected} onSelectAll={this.handleSelectAll} + qsConfig={QS_CONFIG} additionalControls={[ ( initially renders succesfully 1`] = ` items={Array []} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, @@ -91,6 +95,10 @@ exports[` initially renders succesfully 1`] = ` items={Array []} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, @@ -157,6 +165,10 @@ exports[` initially renders succesfully 1`] = ` } qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, @@ -221,6 +233,10 @@ exports[` initially renders succesfully 1`] = ` itemCount={0} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, @@ -278,6 +294,10 @@ exports[` initially renders succesfully 1`] = ` } qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, @@ -329,6 +349,10 @@ exports[` initially renders succesfully 1`] = ` onRemoveAll={[Function]} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, @@ -353,6 +377,10 @@ exports[` initially renders succesfully 1`] = ` onRemoveAll={[Function]} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, @@ -391,6 +419,10 @@ exports[` initially renders succesfully 1`] = ` onRemoveAll={[Function]} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "first_name", "page": 1, diff --git a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx index 9138e3df9f..3bcd6ff9a5 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationList/OrganizationList.jsx @@ -181,6 +181,7 @@ class OrganizationsList extends Component { showSelectAll isAllSelected={isAllSelected} onSelectAll={this.handleSelectAll} + qsConfig={QS_CONFIG} additionalControls={[ initially renders succesfully 1`] = ` } qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, @@ -137,6 +141,10 @@ exports[` initially renders succesfully 1`] = ` } qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, @@ -222,6 +230,10 @@ exports[` initially renders succesfully 1`] = ` } qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, @@ -286,6 +298,10 @@ exports[` initially renders succesfully 1`] = ` itemCount={2} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, @@ -344,6 +360,10 @@ exports[` initially renders succesfully 1`] = ` } qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, @@ -1713,6 +1733,10 @@ exports[` initially renders succesfully 1`] = ` onRemoveAll={[Function]} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, @@ -1737,6 +1761,10 @@ exports[` initially renders succesfully 1`] = ` onRemoveAll={[Function]} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, @@ -1775,6 +1803,10 @@ exports[` initially renders succesfully 1`] = ` onRemoveAll={[Function]} qsConfig={ Object { + "dateFields": Array [ + "modified", + "created", + ], "defaultParams": Object { "order_by": "name", "page": 1, diff --git a/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.test.jsx b/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.test.jsx index 146ebfbc40..1095c7751c 100644 --- a/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.test.jsx +++ b/awx/ui_next/src/screens/Organization/OrganizationTeams/OrganizationTeams.test.jsx @@ -65,6 +65,7 @@ describe('', () => { expect(list.prop('itemCount')).toEqual(listData.data.count); expect(list.prop('qsConfig')).toEqual({ namespace: 'team', + dateFields: ['modified', 'created'], defaultParams: { page: 1, page_size: 5, diff --git a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx index 34e29329a2..90c4482936 100644 --- a/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx +++ b/awx/ui_next/src/screens/Template/TemplateList/TemplateList.jsx @@ -207,6 +207,7 @@ class TemplatesList extends Component { showExpandCollapse isAllSelected={isAllSelected} onSelectAll={this.handleSelectAll} + qsConfig={QS_CONFIG} additionalControls={[ { export function getQSConfig( namespace, defaultParams = { page: 1, page_size: 5, order_by: 'name' }, - integerFields = ['page', 'page_size'] + integerFields = ['page', 'page_size'], + dateFields = ['modified', 'created'] ) { if (!namespace) { throw new Error('a QS namespace is required'); @@ -170,6 +171,7 @@ export function getQSConfig( namespace, defaultParams, integerFields, + dateFields, }; } diff --git a/awx/ui_next/src/util/qs.test.js b/awx/ui_next/src/util/qs.test.js index 9a9bb76515..b3c459b9ba 100644 --- a/awx/ui_next/src/util/qs.test.js +++ b/awx/ui_next/src/util/qs.test.js @@ -78,6 +78,7 @@ describe('qs (qs.js)', () => { test('should get default QS config object', () => { expect(getQSConfig('organization')).toEqual({ namespace: 'organization', + dateFields: ['modified', 'created'], defaultParams: { page: 1, page_size: 5, order_by: 'name' }, integerFields: ['page', 'page_size'], }); @@ -94,6 +95,7 @@ describe('qs (qs.js)', () => { }; expect(getQSConfig('inventory', defaults)).toEqual({ namespace: 'inventory', + dateFields: ['modified', 'created'], defaultParams: { page: 1, page_size: 15 }, integerFields: ['page', 'page_size'], });