From a0df3792250d7738f65cb8d26ba8cc45ac75c2e1 Mon Sep 17 00:00:00 2001 From: "Keith J. Grant" Date: Thu, 29 Jul 2021 15:40:30 -0700 Subject: [PATCH 1/6] limit advanced search options by field type --- .../DataListToolbar/DataListToolbar.js | 2 +- .../src/components/Search/AdvancedSearch.js | 201 +++--------------- .../OrganizationList/OrganizationList.js | 13 +- .../src/components/Search/LookupTypeInput.js | 141 ++++++++++++ .../Search/RelatedLookupTypeInput.js | 52 +++++ 5 files changed, 237 insertions(+), 172 deletions(-) create mode 100644 awx/ui_next/src/components/Search/LookupTypeInput.js create mode 100644 awx/ui_next/src/components/Search/RelatedLookupTypeInput.js diff --git a/awx/ui/src/components/DataListToolbar/DataListToolbar.js b/awx/ui/src/components/DataListToolbar/DataListToolbar.js index 2bcc0a1721..e412dddadc 100644 --- a/awx/ui/src/components/DataListToolbar/DataListToolbar.js +++ b/awx/ui/src/components/DataListToolbar/DataListToolbar.js @@ -200,7 +200,7 @@ DataListToolbar.propTypes = { clearAllFilters: PropTypes.func, qsConfig: QSConfig.isRequired, searchColumns: SearchColumns.isRequired, - searchableKeys: PropTypes.arrayOf(PropTypes.string), + searchableKeys: PropTypes.arrayOf(PropTypes.string), // TODO: Update relatedSearchableKeys: PropTypes.arrayOf(PropTypes.string), sortColumns: SortColumns, isAllSelected: PropTypes.bool, diff --git a/awx/ui/src/components/Search/AdvancedSearch.js b/awx/ui/src/components/Search/AdvancedSearch.js index 16e3c0bce8..6f7525b644 100644 --- a/awx/ui/src/components/Search/AdvancedSearch.js +++ b/awx/ui/src/components/Search/AdvancedSearch.js @@ -16,6 +16,8 @@ import { SearchIcon, QuestionCircleIcon } from '@patternfly/react-icons'; import styled from 'styled-components'; import { useConfig } from 'contexts/Config'; import getDocsBaseUrl from 'util/getDocsBaseUrl'; +import RelatedLookupTypeInput from './RelatedLookupTypeInput'; +import LookupTypeInput from './LookupTypeInput'; const AdvancedGroup = styled.div` display: flex; @@ -42,31 +44,36 @@ function AdvancedSearch({ // for now, I'm spreading set to get rid of duplicate keys...when they are grouped // we might want to revisit that. const allKeys = [ - ...new Set([...(searchableKeys || []), ...(relatedSearchableKeys || [])]), + ...new Set([ + ...(searchableKeys.map((k) => k.key) || []), + ...(relatedSearchableKeys || []), + ]), ]; const [isPrefixDropdownOpen, setIsPrefixDropdownOpen] = useState(false); - const [isLookupDropdownOpen, setIsLookupDropdownOpen] = useState(false); const [isKeyDropdownOpen, setIsKeyDropdownOpen] = useState(false); const [prefixSelection, setPrefixSelection] = useState(null); const [lookupSelection, setLookupSelection] = useState(null); const [keySelection, setKeySelection] = useState(null); const [searchValue, setSearchValue] = useState(''); - const [relatedSearchKeySelected, setRelatedSearchKeySelected] = - useState(false); + // const [relatedSearchKeySelected, setRelatedSearchKeySelected] = + // useState(false); const config = useConfig(); + const relatedSearchKeySelected = + keySelection && + relatedSearchableKeys.indexOf(keySelection) > -1 && + !searchableKeys.find((k) => k.key === keySelection); + const lookupKeyType = + keySelection && !relatedSearchKeySelected + ? searchableKeys.find((k) => k.key === keySelection).type + : null; + useEffect(() => { - if ( - keySelection && - relatedSearchableKeys.indexOf(keySelection) > -1 && - searchableKeys.indexOf(keySelection) === -1 - ) { + if (relatedSearchKeySelected) { setLookupSelection('name__icontains'); - setRelatedSearchKeySelected(true); } else { setLookupSelection(null); - setRelatedSearchKeySelected(false); } }, [keySelection]); // eslint-disable-line react-hooks/exhaustive-deps @@ -136,160 +143,6 @@ function AdvancedSearch({ ); - const renderRelatedLookupType = () => ( - - ); - - const renderLookupType = () => ( - - ); - return ( {lookupSelection === 'search' ? ( @@ -328,9 +181,21 @@ function AdvancedSearch({ ))} - {relatedSearchKeySelected - ? renderRelatedLookupType() - : renderLookupType()} + {relatedSearchKeySelected ? ( + + ) : ( + + )} val.slice(0, -8)), - searchableKeys: Object.keys(orgActions.data.actions?.GET || {}).filter( - (key) => orgActions.data.actions?.GET[key].filterable - ), + // searchableKeys: Object.keys(orgActions.data.actions?.GET || {}).filter( + // (key) => orgActions.data.actions?.GET[key].filterable + // ), + searchableKeys: Object.keys(keys) + .filter((key) => keys[key].filterable) + .map((key) => ({ + key, + type: keys[key].type, + })), }; }, [location]), { diff --git a/awx/ui_next/src/components/Search/LookupTypeInput.js b/awx/ui_next/src/components/Search/LookupTypeInput.js new file mode 100644 index 0000000000..4bf629f0b4 --- /dev/null +++ b/awx/ui_next/src/components/Search/LookupTypeInput.js @@ -0,0 +1,141 @@ +import React, { useState } from 'react'; +import { t } from '@lingui/macro'; +import { Select, SelectOption, SelectVariant } from '@patternfly/react-core'; + +function Option({ show, ...props }) { + if (!show) { + return null; + } + return ; +} +Option.defaultProps = { + show: true, +}; + +function LookupTypeInput({ value, type, setValue, maxSelectHeight }) { + const [isOpen, setIsOpen] = useState(false); + + return ( + + ); +} + +export default LookupTypeInput; diff --git a/awx/ui_next/src/components/Search/RelatedLookupTypeInput.js b/awx/ui_next/src/components/Search/RelatedLookupTypeInput.js new file mode 100644 index 0000000000..effbc4199a --- /dev/null +++ b/awx/ui_next/src/components/Search/RelatedLookupTypeInput.js @@ -0,0 +1,52 @@ +import React, { useState } from 'react'; +import { t } from '@lingui/macro'; +import { Select, SelectOption, SelectVariant } from '@patternfly/react-core'; + +function RelatedLookupTypeInput({ + value, + setValue, + maxSelectHeight, + enableFuzzyFiltering, +}) { + const [isOpen, setIsOpen] = useState(false); + + return ( + + ); +} + +export default RelatedLookupTypeInput; From 977164b920be70316b73e6cf51b934f04a03229d Mon Sep 17 00:00:00 2001 From: "Keith J. Grant" Date: Fri, 30 Jul 2021 11:28:14 -0700 Subject: [PATCH 2/6] cleanup tests/advanced search changes --- .../DataListToolbar/DataListToolbar.js | 4 +- .../src/components/ListHeader/ListHeader.js | 4 +- .../PaginatedTable/PaginatedTable.js | 4 +- .../src/components/Search/AdvancedSearch.js | 24 +++++------ .../components/Search/AdvancedSearch.test.js | 40 ++++++++++--------- awx/ui/src/components/Search/Search.js | 4 +- awx/ui/src/types.js | 7 ++++ .../src/components/Search/LookupTypeInput.js | 12 ++++++ 8 files changed, 61 insertions(+), 38 deletions(-) diff --git a/awx/ui/src/components/DataListToolbar/DataListToolbar.js b/awx/ui/src/components/DataListToolbar/DataListToolbar.js index e412dddadc..bd3eca8b04 100644 --- a/awx/ui/src/components/DataListToolbar/DataListToolbar.js +++ b/awx/ui/src/components/DataListToolbar/DataListToolbar.js @@ -20,7 +20,7 @@ import { AngleRightIcon, SearchIcon, } from '@patternfly/react-icons'; -import { SearchColumns, SortColumns, QSConfig } from 'types'; +import { SearchColumns, SortColumns, QSConfig, SearchableKeys } from 'types'; import { KebabifiedProvider } from 'contexts/Kebabified'; import ExpandCollapse from '../ExpandCollapse'; import Search from '../Search'; @@ -200,7 +200,7 @@ DataListToolbar.propTypes = { clearAllFilters: PropTypes.func, qsConfig: QSConfig.isRequired, searchColumns: SearchColumns.isRequired, - searchableKeys: PropTypes.arrayOf(PropTypes.string), // TODO: Update + searchableKeys: SearchableKeys, relatedSearchableKeys: PropTypes.arrayOf(PropTypes.string), sortColumns: SortColumns, isAllSelected: PropTypes.bool, diff --git a/awx/ui/src/components/ListHeader/ListHeader.js b/awx/ui/src/components/ListHeader/ListHeader.js index 965a6551ff..27055f1c45 100644 --- a/awx/ui/src/components/ListHeader/ListHeader.js +++ b/awx/ui/src/components/ListHeader/ListHeader.js @@ -10,7 +10,7 @@ import { removeParams, updateQueryString, } from 'util/qs'; -import { QSConfig, SearchColumns, SortColumns } from 'types'; +import { QSConfig, SearchColumns, SortColumns, SearchableKeys } from 'types'; import DataListToolbar from '../DataListToolbar'; const EmptyStateControlsWrapper = styled.div` @@ -146,7 +146,7 @@ ListHeader.propTypes = { itemCount: PropTypes.number.isRequired, qsConfig: QSConfig.isRequired, searchColumns: SearchColumns.isRequired, - searchableKeys: PropTypes.arrayOf(PropTypes.string), + searchableKeys: SearchableKeys, relatedSearchableKeys: PropTypes.arrayOf(PropTypes.string), sortColumns: SortColumns, renderToolbar: PropTypes.func, diff --git a/awx/ui/src/components/PaginatedTable/PaginatedTable.js b/awx/ui/src/components/PaginatedTable/PaginatedTable.js index c80b9d7ef8..37ac22c4a9 100644 --- a/awx/ui/src/components/PaginatedTable/PaginatedTable.js +++ b/awx/ui/src/components/PaginatedTable/PaginatedTable.js @@ -7,7 +7,7 @@ import { t } from '@lingui/macro'; import { useLocation, useHistory } from 'react-router-dom'; import { parseQueryString, updateQueryString } from 'util/qs'; -import { QSConfig, SearchColumns } from 'types'; +import { QSConfig, SearchColumns, SearchableKeys } from 'types'; import ListHeader from '../ListHeader'; import ContentEmpty from '../ContentEmpty'; import ContentError from '../ContentError'; @@ -184,7 +184,7 @@ PaginatedTable.propTypes = { qsConfig: QSConfig.isRequired, renderRow: PropTypes.func.isRequired, toolbarSearchColumns: SearchColumns, - toolbarSearchableKeys: PropTypes.arrayOf(PropTypes.string), + toolbarSearchableKeys: SearchableKeys, toolbarRelatedSearchableKeys: PropTypes.arrayOf(PropTypes.string), showPageSizeOptions: PropTypes.bool, renderToolbar: PropTypes.func, diff --git a/awx/ui/src/components/Search/AdvancedSearch.js b/awx/ui/src/components/Search/AdvancedSearch.js index 6f7525b644..861c0cd33a 100644 --- a/awx/ui/src/components/Search/AdvancedSearch.js +++ b/awx/ui/src/components/Search/AdvancedSearch.js @@ -1,6 +1,6 @@ import 'styled-components/macro'; import React, { useEffect, useState } from 'react'; -import PropTypes from 'prop-types'; +import { string, func, bool, arrayOf } from 'prop-types'; import { t } from '@lingui/macro'; import { Button, @@ -16,6 +16,7 @@ import { SearchIcon, QuestionCircleIcon } from '@patternfly/react-icons'; import styled from 'styled-components'; import { useConfig } from 'contexts/Config'; import getDocsBaseUrl from 'util/getDocsBaseUrl'; +import { SearchableKeys } from 'types'; import RelatedLookupTypeInput from './RelatedLookupTypeInput'; import LookupTypeInput from './LookupTypeInput'; @@ -56,18 +57,15 @@ function AdvancedSearch({ const [lookupSelection, setLookupSelection] = useState(null); const [keySelection, setKeySelection] = useState(null); const [searchValue, setSearchValue] = useState(''); - // const [relatedSearchKeySelected, setRelatedSearchKeySelected] = - // useState(false); const config = useConfig(); + const selectedKey = searchableKeys.find((k) => k.key === keySelection); const relatedSearchKeySelected = keySelection && relatedSearchableKeys.indexOf(keySelection) > -1 && - !searchableKeys.find((k) => k.key === keySelection); + !selectedKey; const lookupKeyType = - keySelection && !relatedSearchKeySelected - ? searchableKeys.find((k) => k.key === keySelection).type - : null; + keySelection && !relatedSearchKeySelected ? selectedKey?.type : null; useEffect(() => { if (relatedSearchKeySelected) { @@ -234,12 +232,12 @@ function AdvancedSearch({ } AdvancedSearch.propTypes = { - onSearch: PropTypes.func.isRequired, - searchableKeys: PropTypes.arrayOf(PropTypes.string), - relatedSearchableKeys: PropTypes.arrayOf(PropTypes.string), - maxSelectHeight: PropTypes.string, - enableNegativeFiltering: PropTypes.bool, - enableRelatedFuzzyFiltering: PropTypes.bool, + onSearch: func.isRequired, + searchableKeys: SearchableKeys, + relatedSearchableKeys: arrayOf(string), + maxSelectHeight: string, + enableNegativeFiltering: bool, + enableRelatedFuzzyFiltering: bool, }; AdvancedSearch.defaultProps = { diff --git a/awx/ui/src/components/Search/AdvancedSearch.test.js b/awx/ui/src/components/Search/AdvancedSearch.test.js index 79b63fe462..5050ff63af 100644 --- a/awx/ui/src/components/Search/AdvancedSearch.test.js +++ b/awx/ui/src/components/Search/AdvancedSearch.test.js @@ -10,22 +10,14 @@ describe('', () => { jest.clearAllMocks(); }); - test('initially renders without crashing', () => { - wrapper = mountWithContexts( - - ); - expect(wrapper.length).toBe(1); - }); - test('Remove duplicates from searchableKeys/relatedSearchableKeys list', () => { wrapper = mountWithContexts( ); @@ -42,7 +34,10 @@ describe('', () => { wrapper = mountWithContexts( ); @@ -155,7 +150,10 @@ describe('', () => { wrapper = mountWithContexts( ); @@ -239,7 +237,7 @@ describe('', () => { wrapper = mountWithContexts( ); @@ -278,7 +276,7 @@ describe('', () => { wrapper = mountWithContexts( ); @@ -375,7 +373,10 @@ describe('', () => { wrapper = mountWithContexts( @@ -399,7 +400,10 @@ describe('', () => { wrapper = mountWithContexts( diff --git a/awx/ui/src/components/Search/Search.js b/awx/ui/src/components/Search/Search.js index 3cd1fac4a4..e614314305 100644 --- a/awx/ui/src/components/Search/Search.js +++ b/awx/ui/src/components/Search/Search.js @@ -19,7 +19,7 @@ import { import { SearchIcon } from '@patternfly/react-icons'; import styled from 'styled-components'; import { parseQueryString } from 'util/qs'; -import { QSConfig, SearchColumns } from 'types'; +import { QSConfig, SearchColumns, SearchableKeys } from 'types'; import AdvancedSearch from './AdvancedSearch'; import getChipsByKey from './getChipsByKey'; @@ -276,6 +276,7 @@ Search.propTypes = { maxSelectHeight: PropTypes.string, enableNegativeFiltering: PropTypes.bool, enableRelatedFuzzyFiltering: PropTypes.bool, + searchableKeys: SearchableKeys, }; Search.defaultProps = { @@ -285,6 +286,7 @@ Search.defaultProps = { maxSelectHeight: '300px', enableNegativeFiltering: true, enableRelatedFuzzyFiltering: true, + searchableKeys: [], }; export default Search; diff --git a/awx/ui/src/types.js b/awx/ui/src/types.js index 3be7f55bc5..f0f95b1aa6 100644 --- a/awx/ui/src/types.js +++ b/awx/ui/src/types.js @@ -421,3 +421,10 @@ export const ExecutionEnvironment = shape({ description: string, pull: string, }); + +export const SearchableKeys = arrayOf( + shape({ + key: string.isRequired, + type: string.isRequired, + }) +); diff --git a/awx/ui_next/src/components/Search/LookupTypeInput.js b/awx/ui_next/src/components/Search/LookupTypeInput.js index 4bf629f0b4..b14af41703 100644 --- a/awx/ui_next/src/components/Search/LookupTypeInput.js +++ b/awx/ui_next/src/components/Search/LookupTypeInput.js @@ -1,4 +1,5 @@ import React, { useState } from 'react'; +import { string, oneOfType, arrayOf, func } from 'prop-types'; import { t } from '@lingui/macro'; import { Select, SelectOption, SelectVariant } from '@patternfly/react-core'; @@ -137,5 +138,16 @@ function LookupTypeInput({ value, type, setValue, maxSelectHeight }) { ); } +LookupTypeInput.propTypes = { + type: string, + value: oneOfType([string, arrayOf(string)]), + setValue: func.isRequired, + maxSelectHeight: string, +}; +LookupTypeInput.defaultProps = { + type: 'string', + value: '', + maxSelectHeight: '300px', +}; export default LookupTypeInput; From 262a2b70e2654f5f85a0fc531dcc4451b28a473b Mon Sep 17 00:00:00 2001 From: "Keith J. Grant" Date: Fri, 30 Jul 2021 14:20:47 -0700 Subject: [PATCH 3/6] update all lists to use getSearchableKeys helper --- .../components/AddRole/SelectResourceStep.js | 10 ++++++---- awx/ui/src/components/JobList/JobList.js | 5 ++--- .../src/components/Lookup/HostFilterLookup.js | 10 ++++++---- .../src/components/Lookup/InventoryLookup.js | 19 +++++++++++-------- .../NotificationList/NotificationList.js | 10 ++++++---- .../PaginatedTable/getSearchableKeys.js | 8 ++++++++ awx/ui/src/components/PaginatedTable/index.js | 1 + .../ResourceAccessList/ResourceAccessList.js | 5 ++--- .../Schedule/ScheduleList/ScheduleList.js | 5 ++--- .../src/components/Search/LookupTypeInput.js | 4 ++++ .../Search/RelatedLookupTypeInput.js | 0 .../components/TemplateList/TemplateList.js | 5 ++--- .../screens/ActivityStream/ActivityStream.js | 5 ++--- .../ApplicationTokens/ApplicationTokenList.js | 5 ++--- .../ApplicationsList/ApplicationsList.js | 5 ++--- .../CredentialList/CredentialList.js | 5 ++--- .../CredentialPluginPrompt/CredentialsStep.js | 5 ++--- .../CredentialTypeList/CredentialTypeList.js | 5 ++--- .../ExecutionEnvironmentList.js | 5 ++--- .../ExecutionEnvironmentTemplateList.js | 5 ++--- .../screens/Host/HostGroups/HostGroupsList.js | 5 ++--- awx/ui/src/screens/Host/HostList/HostList.js | 5 ++--- .../InstanceGroupList/InstanceGroupList.js | 5 ++--- .../InstanceGroup/Instances/InstanceList.js | 5 ++--- .../InventoryGroupHostList.js | 5 ++--- .../InventoryGroups/InventoryGroupsList.js | 5 ++--- .../InventoryHostGroupsList.js | 5 ++--- .../InventoryHosts/InventoryHostList.js | 5 ++--- .../Inventory/InventoryList/InventoryList.js | 5 ++--- .../InventoryRelatedGroupList.js | 5 ++--- .../ManagementJobList/ManagementJobList.js | 5 ++--- .../NotificationTemplateList.js | 5 ++--- .../OrganizationExecEnvList.js | 5 ++--- .../OrganizationList/OrganizationList.js | 12 ++---------- .../OrganizationTeams/OrganizationTeamList.js | 5 ++--- .../ProjectJobTemplatesList.js | 5 ++--- .../Project/ProjectList/ProjectList.js | 5 ++--- awx/ui/src/screens/Team/TeamList/TeamList.js | 5 ++--- .../screens/Team/TeamRoles/TeamRolesList.js | 5 ++--- .../NodeTypeStep/InventorySourcesList.js | 5 ++--- .../NodeTypeStep/JobTemplatesList.js | 5 ++--- .../NodeModals/NodeTypeStep/ProjectsList.js | 5 ++--- .../NodeTypeStep/SystemJobTemplatesList.jsx | 5 ++--- .../NodeTypeStep/WorkflowJobTemplatesList.js | 5 ++--- awx/ui/src/screens/User/UserList/UserList.js | 5 ++--- .../screens/User/UserRoles/UserRolesList.js | 5 ++--- .../screens/User/UserTeams/UserTeamList.js | 5 ++--- .../User/UserTokenList/UserTokenList.js | 5 ++--- .../WorkflowApprovalList.js | 5 ++--- 49 files changed, 124 insertions(+), 150 deletions(-) create mode 100644 awx/ui/src/components/PaginatedTable/getSearchableKeys.js rename awx/{ui_next => ui}/src/components/Search/LookupTypeInput.js (97%) rename awx/{ui_next => ui}/src/components/Search/RelatedLookupTypeInput.js (100%) diff --git a/awx/ui/src/components/AddRole/SelectResourceStep.js b/awx/ui/src/components/AddRole/SelectResourceStep.js index f41f179554..b0e8897320 100644 --- a/awx/ui/src/components/AddRole/SelectResourceStep.js +++ b/awx/ui/src/components/AddRole/SelectResourceStep.js @@ -8,7 +8,11 @@ import { getQSConfig, parseQueryString } from 'util/qs'; import DataListToolbar from '../DataListToolbar'; import CheckboxListItem from '../CheckboxListItem'; import { SelectedList } from '../SelectedList'; -import PaginatedTable, { HeaderCell, HeaderRow } from '../PaginatedTable'; +import PaginatedTable, { + HeaderCell, + HeaderRow, + getSearchableKeys, +} from '../PaginatedTable'; const QS_Config = (sortColumns) => getQSConfig('resource', { @@ -56,9 +60,7 @@ function SelectResourceStep({ relatedSearchableKeys: ( actionsResponse?.data?.related_search_fields || [] ).map((val) => val.slice(0, -8)), - searchableKeys: Object.keys( - actionsResponse.data.actions?.GET || {} - ).filter((key) => actionsResponse.data.actions?.GET[key].filterable), + searchableKeys: getSearchableKeys(actionsResponse.data.actions?.GET), }; }, [location, fetchItems, fetchOptions, sortColumns]), { diff --git a/awx/ui/src/components/JobList/JobList.js b/awx/ui/src/components/JobList/JobList.js index 0547212d0d..1fd918ab57 100644 --- a/awx/ui/src/components/JobList/JobList.js +++ b/awx/ui/src/components/JobList/JobList.js @@ -20,6 +20,7 @@ import PaginatedTable, { HeaderRow, HeaderCell, ToolbarDeleteButton, + getSearchableKeys, } from '../PaginatedTable'; import JobListItem from './JobListItem'; import JobListCancelButton from './JobListCancelButton'; @@ -59,9 +60,7 @@ function JobList({ defaultParams, showTypeColumn = false }) { relatedSearchableKeys: ( actionsResponse?.data?.related_search_fields || [] ).map((val) => val.slice(0, -8)), - searchableKeys: Object.keys( - actionsResponse.data.actions?.GET || {} - ).filter((key) => actionsResponse.data.actions?.GET[key].filterable), + searchableKeys: getSearchableKeys(actionsResponse.data.actions?.GET), }; }, [location] // eslint-disable-line react-hooks/exhaustive-deps diff --git a/awx/ui/src/components/Lookup/HostFilterLookup.js b/awx/ui/src/components/Lookup/HostFilterLookup.js index 4b5d3a324e..3468d5d4b7 100644 --- a/awx/ui/src/components/Lookup/HostFilterLookup.js +++ b/awx/ui/src/components/Lookup/HostFilterLookup.js @@ -21,7 +21,11 @@ import ChipGroup from '../ChipGroup'; import Popover from '../Popover'; import DataListToolbar from '../DataListToolbar'; import LookupErrorMessage from './shared/LookupErrorMessage'; -import PaginatedTable, { HeaderCell, HeaderRow } from '../PaginatedTable'; +import PaginatedTable, { + HeaderCell, + HeaderRow, + getSearchableKeys, +} from '../PaginatedTable'; import HostListItem from './HostListItem'; import { removeDefaultParams, @@ -157,9 +161,7 @@ function HostFilterLookup({ relatedSearchableKeys: (actions?.related_search_fields || []).map( parseRelatedSearchFields ), - searchableKeys: Object.keys(actions?.actions.GET || {}).filter( - (key) => actions.actions?.GET[key].filterable - ), + searchableKeys: getSearchableKeys(actions?.actions.GET), }; }, [location.search] diff --git a/awx/ui/src/components/Lookup/InventoryLookup.js b/awx/ui/src/components/Lookup/InventoryLookup.js index 71a92108f4..41991a0c1d 100644 --- a/awx/ui/src/components/Lookup/InventoryLookup.js +++ b/awx/ui/src/components/Lookup/InventoryLookup.js @@ -74,14 +74,17 @@ function InventoryLookup({ relatedSearchableKeys: ( actionsResponse?.data?.related_search_fields || [] ).map((val) => val.slice(0, -8)), - searchableKeys: Object.keys( - actionsResponse.data.actions?.GET || {} - ).filter((key) => { - if (['kind', 'host_filter'].includes(key) && hideSmartInventories) { - return false; - } - return actionsResponse.data.actions?.GET[key].filterable; - }), + searchableKeys: Object.keys(actionsResponse.data.actions?.GET || {}) + .filter((key) => { + if (['kind', 'host_filter'].includes(key) && hideSmartInventories) { + return false; + } + return actionsResponse.data.actions?.GET[key].filterable; + }) + .map((key) => ({ + key, + type: actionsResponse.data.actions?.GET[key].type, + })), canEdit: Boolean(actionsResponse.data.actions.POST) || isOverrideDisabled, }; diff --git a/awx/ui/src/components/NotificationList/NotificationList.js b/awx/ui/src/components/NotificationList/NotificationList.js index 6d3a05f682..3b4171ec90 100644 --- a/awx/ui/src/components/NotificationList/NotificationList.js +++ b/awx/ui/src/components/NotificationList/NotificationList.js @@ -9,7 +9,11 @@ import { NotificationTemplatesAPI } from 'api'; import AlertModal from '../AlertModal'; import ErrorDetail from '../ErrorDetail'; import NotificationListItem from './NotificationListItem'; -import PaginatedTable, { HeaderRow, HeaderCell } from '../PaginatedTable'; +import PaginatedTable, { + HeaderRow, + HeaderCell, + getSearchableKeys, +} from '../PaginatedTable'; const QS_CONFIG = getQSConfig('notification', { page: 1, @@ -89,9 +93,7 @@ function NotificationList({ relatedSearchableKeys: ( actionsResponse?.data?.related_search_fields || [] ).map((val) => val.slice(0, -8)), - searchableKeys: Object.keys( - actionsResponse.data.actions?.GET || {} - ).filter((key) => actionsResponse.data.actions?.GET[key].filterable), + searchableKeys: getSearchableKeys(actionsResponse.data.actions?.GET), }; if (showApprovalsToggle) { diff --git a/awx/ui/src/components/PaginatedTable/getSearchableKeys.js b/awx/ui/src/components/PaginatedTable/getSearchableKeys.js new file mode 100644 index 0000000000..ed9fe0fe0c --- /dev/null +++ b/awx/ui/src/components/PaginatedTable/getSearchableKeys.js @@ -0,0 +1,8 @@ +export default function getSearchableKeys(keys = {}) { + return Object.keys(keys) + .filter((key) => keys[key].filterable) + .map((key) => ({ + key, + type: keys[key].type, + })); +} diff --git a/awx/ui/src/components/PaginatedTable/index.js b/awx/ui/src/components/PaginatedTable/index.js index e30c1e1711..67b83c87c2 100644 --- a/awx/ui/src/components/PaginatedTable/index.js +++ b/awx/ui/src/components/PaginatedTable/index.js @@ -5,3 +5,4 @@ export { default as ActionItem } from './ActionItem'; export { default as ToolbarDeleteButton } from './ToolbarDeleteButton'; export { default as ToolbarAddButton } from './ToolbarAddButton'; export { default as ToolbarSyncSourceButton } from './ToolbarSyncSourceButton'; +export { default as getSearchableKeys } from './getSearchableKeys'; diff --git a/awx/ui/src/components/ResourceAccessList/ResourceAccessList.js b/awx/ui/src/components/ResourceAccessList/ResourceAccessList.js index c8b0254386..e4892e0371 100644 --- a/awx/ui/src/components/ResourceAccessList/ResourceAccessList.js +++ b/awx/ui/src/components/ResourceAccessList/ResourceAccessList.js @@ -11,6 +11,7 @@ import PaginatedTable, { HeaderRow, HeaderCell, ToolbarAddButton, + getSearchableKeys, } from '../PaginatedTable'; import DeleteRoleConfirmationModal from './DeleteRoleConfirmationModal'; import ResourceAccessListItem from './ResourceAccessListItem'; @@ -89,9 +90,7 @@ function ResourceAccessList({ apiModel, resource }) { relatedSearchableKeys: ( actionsResponse?.data?.related_search_fields || [] ).map((val) => val.slice(0, -8)), - searchableKeys: Object.keys( - actionsResponse.data.actions?.GET || {} - ).filter((key) => actionsResponse.data.actions?.GET[key].filterable), + searchableKeys: getSearchableKeys(actionsResponse.data.actions?.GET), organizationRoles: orgRoles, }; }, [apiModel, location, resource]), diff --git a/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js b/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js index 97b7e4ec3b..d74d9f64f7 100644 --- a/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js +++ b/awx/ui/src/components/Schedule/ScheduleList/ScheduleList.js @@ -14,6 +14,7 @@ import PaginatedTable, { HeaderCell, ToolbarAddButton, ToolbarDeleteButton, + getSearchableKeys, } from '../../PaginatedTable'; import DataListToolbar from '../../DataListToolbar'; import ScheduleListItem from './ScheduleListItem'; @@ -61,9 +62,7 @@ function ScheduleList({ relatedSearchableKeys: ( scheduleActions?.data?.related_search_fields || [] ).map((val) => val.slice(0, -8)), - searchableKeys: Object.keys( - scheduleActions.data.actions?.GET || {} - ).filter((key) => scheduleActions.data.actions?.GET[key].filterable), + searchableKeys: getSearchableKeys(scheduleActions.data.actions?.GET), }; }, [location.search, loadSchedules, loadScheduleOptions]), { diff --git a/awx/ui_next/src/components/Search/LookupTypeInput.js b/awx/ui/src/components/Search/LookupTypeInput.js similarity index 97% rename from awx/ui_next/src/components/Search/LookupTypeInput.js rename to awx/ui/src/components/Search/LookupTypeInput.js index b14af41703..bb5eea7106 100644 --- a/awx/ui_next/src/components/Search/LookupTypeInput.js +++ b/awx/ui/src/components/Search/LookupTypeInput.js @@ -104,24 +104,28 @@ function LookupTypeInput({ value, type, setValue, maxSelectHeight }) { key="gt" value="gt" description={t`Greater than comparison.`} + show={type !== 'json'} />