Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #38131 - Use #include? instead of Regexp substring match #940

Merged
merged 2 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions app/controllers/ui_job_wizard_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
43 changes: 34 additions & 9 deletions webpack/JobWizard/steps/form/ResourceSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -17,7 +18,8 @@ export const ResourceSelect = ({
apiKey,
url,
}) => {
const maxResults = 100;
const { perPage } = useForemanSettings();
const maxResults = perPage;
Comment on lines +21 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we can just use perPage and remove maxResults?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or since max results is already used everywhere here we can keep it actually

const dispatch = useDispatch();
const uri = new URI(url);
const onSearch = search => {
Expand Down Expand Up @@ -50,26 +52,43 @@ 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
)}
</SelectOption>,
];
}
selectOptions = [
...selectOptions,
...Immutable.asMutable(response?.results || [])?.map((result, index) => (
<SelectOption key={index + 1} value={result.id}>
{result.name}
</SelectOption>
)),
...Immutable.asMutable(response?.results || [])
?.slice(0, maxResults)
?.map((result, index) => (
<SelectOption key={index + 1} value={result.id}>
{result.name}
</SelectOption>
)),
];

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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Results from API are being returned regardless of casing. This is to support case insensitivity in UI.

);
};
const onClear = () => {
setSelected(null);
setIsOpen(false);
if (typingTimeout) clearTimeout(typingTimeout);
onSearch({});
};
const autoSearch = searchTerm => {
if (typingTimeout) clearTimeout(typingTimeout);
setTypingTimeout(
Expand All @@ -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`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Loading