Skip to content
Closed
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
30 changes: 22 additions & 8 deletions app/assets/javascripts/filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,34 @@ $(document).ready(function () {
$.ajax({
url: $(this).data('url'),
data: {
resource_type: $('#filter_resource_type').val()
resource_type: $('#filter_resource_type').val(),
},
dataType: "script"
dataType: 'script',
});
});

$('#filter_unlimited').change(function () {
$('#search').prop('disabled', $(this).prop('checked'));
$('#filter_unlimited').change(function() {
var isChecked = $(this).prop('checked');
var autocompleteID = $('.search-input').data('autocompleteId');
if (isChecked) {
tfm.autocomplete.disableAutocomplete(autocompleteID);
} else {
tfm.autocomplete.enableAutocomplete(autocompleteID);
}
});

$('#override_taxonomy_checkbox').change(function () {
$('li a[href="#organizations"],li a[href="#locations"]').toggle($(this).prop('checked'));
$('#override_taxonomy_checkbox').change(function() {
$('li a[href="#organizations"],li a[href="#locations"]').toggle(
$(this).prop('checked')
);
});

$('li a[href="#organizations"]').toggle($('#filter_resource_type').data('allow-organizations') && $('#override_taxonomy_checkbox').prop('checked'));
$('li a[href="#locations"]').toggle($('#filter_resource_type').data('allow-locations') && $('#override_taxonomy_checkbox').prop('checked'));
$('li a[href="#organizations"]').toggle(
$('#filter_resource_type').data('allow-organizations') &&
$('#override_taxonomy_checkbox').prop('checked')
);
$('li a[href="#locations"]').toggle(
$('#filter_resource_type').data('allow-locations') &&
$('#override_taxonomy_checkbox').prop('checked')
);
});
1 change: 1 addition & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ def auto_complete_controller_name
end

def auto_complete_search(name, val, options = {})
Foreman::Deprecation.deprecation_warning("1.23", "auto_complete_search has been deprecated, please switch to the React implementation.")
path = options[:full_path]
path ||= (options[:path] || send("#{auto_complete_controller_name}_path")) + "/auto_complete_#{name}"
options[:class] = "autocomplete-input form-control"
Expand Down
18 changes: 7 additions & 11 deletions app/helpers/form_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,17 +198,13 @@ def file_field_f(f, attr, options = {})
end

def autocomplete_f(f, attr, options = {})
field(f, attr, options) do
path = options.delete(:path) || send("#{f.object.class.pluralize.underscore}_path") if options[:full_path].nil?
auto_complete_search(attr,
f.object.send(attr).try(:squeeze, " "),
options.merge(
:placeholder => _("Filter") + ' ...',
:path => path,
:name => "#{f.object_name}[#{attr}]"
)
).html_safe
end
props = { name: "#{f.object_name}[#{attr}]",
controller: options[:path] || auto_complete_controller_name,
url: options[:path] || '',
isDisabled: options[:disabled] || false,
initialQuery: f.object.search || '',
initialError: f.object.errors[attr] && f.object.errors[attr][0]}
render('common/form_autocomplete', props: props)
end

def byte_size_f(f, attr, options = {})
Expand Down
24 changes: 15 additions & 9 deletions app/helpers/search_bar_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ def mount_search_bar(
url: send("auto_complete_search_#{auto_complete_controller_name}_path"),
search_query: params[:search],
use_bookmarks: true,
use_key_shortcuts: true
use_key_shortcuts: true,
disabled: false
)
bookmarks = {}
if use_bookmarks
Expand All @@ -15,14 +16,19 @@ def mount_search_bar(
documentationUrl: documentation_url("4.1.5Searching")
}
end
mount_react_component('SearchBar', "##{id}", {
controller: controller,
autocomplete: {
searchQuery: search_query,
url: url,
useKeyShortcuts: use_key_shortcuts
},
bookmarks: bookmarks
mount_react_component('ComponentWrapper', "##{id}", {
component: 'SearchBar',
componentProps: {
controller: controller,
autocomplete: {
id: id,
searchQuery: search_query,
url: url,
useKeyShortcuts: use_key_shortcuts,
isDisabled: disabled
},
bookmarks: bookmarks
}
}.to_json)
end

Expand Down
5 changes: 5 additions & 0 deletions app/views/common/_form_autocomplete.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div id="foreman_filter_autocomplete"></div>
<%=mount_react_component('ComponentWrapper', "#foreman_filter_autocomplete", {
component: 'FormAutocomplete',
componentProps: props
}.to_json) %>
4 changes: 2 additions & 2 deletions app/views/filters/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@

<%= autocomplete_f f, :search,
:disabled => f.object.unlimited?,
:full_path => search_path(f.object.resource_type),
:control_group_id => 'search_group' %>
:path => search_path(f.object.resource_type)
%>
</div>
</div>

Expand Down
16 changes: 8 additions & 8 deletions app/views/permissions/index.js.erb
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
var permissions = $('#filter_permission_ids');
permissions.html("<%= escape_javascript(options_for_select(@permissions.map {|p| [p.name, p.id] })) %>");
permissions.multiSelect('refresh');

var search = $('#search');
var path = '<%= escape_javascript(@search_path) %>'
search.attr('data-url', path);
search.val('');
search.catcomplete({source: function( request, response ) {
$.getJSON( search.attr('data-url'), { search: request.term }, response );
}})

var resource = $('#filter_resource_type').val();
var autocompleteID = $('.search-input').data('autocompleteId');
tfm.autocomplete.updateController({
url: path,
controller: resource,
id: autocompleteID,
trigger: tfm.autocomplete.TRIGGERS.RESOURCE_TYPE_CHANGED
});
<% if @granular %>
$('#granular_warning').hide();
$('#granular_form').show();
Expand Down
2 changes: 2 additions & 0 deletions webpack/assets/javascripts/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import compute from './foreman_compute_resource';
import componentRegistry from './react_app/components/componentRegistry';
import i18n from './react_app/common/I18n';
import * as foremanDocument from './react_app/common/document';
import * as autocomplete from './foreman_autocomplete';

window.tfm = Object.assign(window.tfm || {}, {
authSource: require('./foreman_auth_source'),
Expand All @@ -54,4 +55,5 @@ window.tfm = Object.assign(window.tfm || {}, {
i18n,
document: foremanDocument,
componentRegistry,
autocomplete,
});
29 changes: 29 additions & 0 deletions webpack/assets/javascripts/foreman_autocomplete.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import store from './react_app/redux';
import {
getResults,
resetData,
updateDisability,
} from './react_app/components/AutoComplete/AutoCompleteActions';

export {
TRIGGERS,
} from './react_app/components/AutoComplete/AutoCompleteConstants';

export const updateController = ({ url, controller, id, trigger }) => {
store.dispatch(resetData({ controller, id }));
store.dispatch(
getResults({
trigger,
url,
controller,
searchQuery: '',
id,
})
);
};

export const disableAutocomplete = autocompleteID =>
store.dispatch(updateDisability(true, autocompleteID));

export const enableAutocomplete = autocompleteID =>
store.dispatch(updateDisability(false, autocompleteID));
62 changes: 62 additions & 0 deletions webpack/assets/javascripts/foreman_autocomplete.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import store from './react_app/redux';
import {
updateController,
disableAutocomplete,
enableAutocomplete,
} from './foreman_autocomplete';
import {
getResults,
resetData,
updateDisability,
} from './react_app/components/AutoComplete/AutoCompleteActions';
import { TRIGGERS } from './react_app/components/AutoComplete/AutoCompleteConstants';

jest.unmock('./foreman_autocomplete');
jest.mock('./react_app/redux', () => ({ dispatch: jest.fn() }));
jest.mock('./react_app/components/AutoComplete/AutoCompleteActions');

const fixtures = {
url: 'some-url',
controller: 'some-controller',
id: 'some-id',
trigger: TRIGGERS.RESOURCE_TYPE_CHANGED,
searchQuery: '',
isDisabled: false,
};
describe('foreman_autocomplete', () => {
beforeEach(() => jest.resetAllMocks());

describe('updateController', () => {
it('should dispatch two actions', () => {
const { url, controller, id, trigger, searchQuery } = fixtures;
updateController({ url, controller, id, trigger });
expect(resetData).toHaveBeenCalledWith({ controller, id });
expect(getResults).toHaveBeenCalledWith({
trigger,
url,
controller,
searchQuery,
id,
});
expect(store.dispatch).toHaveBeenCalledTimes(2);
});
});

describe('disableAutocomplete', () => {
it('should dispatch an action', () => {
const { id } = fixtures;
disableAutocomplete(id);
expect(updateDisability).toHaveBeenCalledWith(true, id);
expect(store.dispatch).toHaveBeenCalledTimes(1);
});
});

describe('enableAutocomplete', () => {
it('should dispatch an action', () => {
const { id } = fixtures;
enableAutocomplete(id);
expect(updateDisability).toHaveBeenCalledWith(false, id);
expect(store.dispatch).toHaveBeenCalledTimes(1);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ export const results = [{ label: 'some results', category: 'category' }];
export const APIError = [{ error }];
export const APISuccessMock = { data: results };
export const APIFailMock = { data: APIError };
export const id = 'search-input';
export const isDisabled = false;

export const AutoCompleteProps = {
controller,
searchQuery,
initialQuery,
status,
results,
url,
initialUrl: url,
id,
isDisabled,
};

export const initialState = {
Expand All @@ -29,6 +33,9 @@ export const initialState = {
searchQuery: '',
status: null,
trigger: null,
url: null,
id,
isDisabled,
};

export const initialValues = {
Expand All @@ -37,6 +44,9 @@ export const initialValues = {
trigger: TRIGGERS.COMPONENT_DID_MOUNT,
results,
status: STATUS.RESOLVED,
url: undefined,
id,
isDisabled,
};

export const request = {
Expand All @@ -45,6 +55,7 @@ export const request = {
searchQuery,
status: STATUS.PENDING,
trigger,
id,
};

export const success = {
Expand All @@ -54,10 +65,19 @@ export const success = {
searchQuery,
controller,
trigger,
url,
id,
isDisabled,
};

export const failure = {
error,
results: [],
status: STATUS.ERROR,
id,
};

export const disabledChange = {
isDisabled: true,
id,
};
Loading