diff --git a/app/controllers/ui_job_wizard_controller.rb b/app/controllers/ui_job_wizard_controller.rb index 3006f5771..28108961d 100644 --- a/app/controllers/ui_job_wizard_controller.rb +++ b/app/controllers/ui_job_wizard_controller.rb @@ -55,9 +55,12 @@ def action_permission def resources resource_type = params[:resource] - resource_list = resource_type.constantize.authorized("view_#{resource_type.underscore.pluralize}").all.map { |r| {:name => r.to_s, :id => r.id } }.select { |v| v[:name] =~ /#{params[:name]}/ } - render :json => { :results => - resource_list.sort_by { |r| r[:name] }.take(100), :subtotal => resource_list.count} + attribute_name = resource_type.constantize.attribute_name + resource_list = resource_type.constantize.authorized("view_#{resource_type.underscore.pluralize}") + .search_for("#{attribute_name} ~ \"#{params[:name]}\"") + .reorder(attribute_name) + .limit(Setting[:entries_per_page] + 1).pluck(attribute_name, :id).map { |name, id| { name: name, id: id } } + render :json => { :results => resource_list, :subtotal => resource_list.count } end def job_invocation diff --git a/webpack/JobWizard/steps/form/ResourceSelect.js b/webpack/JobWizard/steps/form/ResourceSelect.js index 6ab0069f0..bb6efe0e7 100644 --- a/webpack/JobWizard/steps/form/ResourceSelect.js +++ b/webpack/JobWizard/steps/form/ResourceSelect.js @@ -3,6 +3,7 @@ import PropTypes from 'prop-types'; import { Select, SelectOption, SelectVariant } from '@patternfly/react-core'; import Immutable from 'seamless-immutable'; import { sprintf, translate as __ } from 'foremanReact/common/I18n'; +import { useForemanSettings } from 'foremanReact/Root/Context/ForemanContext'; import { useSelector, useDispatch } from 'react-redux'; import URI from 'urijs'; import { get } from 'foremanReact/redux/API'; @@ -17,7 +18,8 @@ export const ResourceSelect = ({ apiKey, url, }) => { - const maxResults = 100; + const { perPage } = useForemanSettings(); + const maxResults = perPage; const dispatch = useDispatch(); const uri = new URI(url); const onSearch = search => { @@ -50,8 +52,7 @@ export const ResourceSelect = ({ description={__('Please refine your search.')} > {sprintf( - __('You have %s results to display. Showing first %s results'), - response.subtotal, + __('You have more results to display. Showing first %s results'), maxResults )} , @@ -59,17 +60,35 @@ export const ResourceSelect = ({ } selectOptions = [ ...selectOptions, - ...Immutable.asMutable(response?.results || [])?.map((result, index) => ( - - {result.name} - - )), + ...Immutable.asMutable(response?.results || []) + ?.slice(0, maxResults) + ?.map((result, index) => ( + + {result.name} + + )), ]; const onSelect = (event, selection) => { setSelected(selection); setIsOpen(false); }; + const onFilter = (_, value) => { + if (!value) { + return selectOptions; + } + return selectOptions.filter( + o => + typeof o.props.children === 'string' && + o.props.children.toLowerCase().indexOf(value.toLowerCase()) > -1 + ); + }; + const onClear = () => { + setSelected(null); + setIsOpen(false); + if (typingTimeout) clearTimeout(typingTimeout); + onSearch({}); + }; const autoSearch = searchTerm => { if (typingTimeout) clearTimeout(typingTimeout); setTypingTimeout( @@ -86,11 +105,17 @@ export const ResourceSelect = ({ loadingVariant={isLoading ? 'spinner' : null} onSelect={onSelect} onToggle={setIsOpen} + onFilter={onFilter} + onClear={onClear} isOpen={isOpen} className="without_select2" maxHeight="45vh" onTypeaheadInputChanged={value => { - autoSearch(value || ''); + if (value) { + autoSearch(value); + } else { + onClear(); + } }} placeholderText={placeholderText} typeAheadAriaLabel={`${name} typeahead input`} diff --git a/webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js b/webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js index c4a833f21..849ccf623 100644 --- a/webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js +++ b/webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js @@ -3,3 +3,4 @@ export const useForemanLocation = () => ({ id: 2 }); export const useForemanVersion = () => '3.7'; export const useForemanHostsPageUrl = () => '/hosts'; export const useForemanHostDetailsPageUrl = () => '/hosts/'; +export const useForemanSettings = () => ({ perPage: 20 });