katello 4.8.0.rc2 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of katello might be problematic. Click here for more details.

Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/lib/katello/plugin.rb +0 -12
  3. data/lib/katello/version.rb +1 -1
  4. data/webpack/components/Content/{ContentPage.js → GenericContentPage.js} +7 -4
  5. data/webpack/components/Content/__tests__/ContentTable.test.js +1 -1
  6. data/webpack/components/Content/__tests__/GenericContentPage.test.js +35 -0
  7. data/webpack/components/Search/SearchText.js +70 -0
  8. data/webpack/components/Table/EmptyStateMessage.js +2 -2
  9. data/webpack/components/Table/TableWrapper.js +4 -0
  10. data/webpack/components/extensions/HostDetails/HostDetailsConstants.js +0 -1
  11. data/webpack/components/extensions/HostDetails/HostDetailsSelectors.js +0 -6
  12. data/webpack/components/extensions/HostDetails/Tabs/__tests__/moduleStreamsTab.test.js +76 -0
  13. data/webpack/components/extensions/SearchBar/SearchBarConstants.js +3 -0
  14. data/webpack/components/extensions/SearchBar/SearchBarHooks.js +50 -0
  15. data/webpack/components/extensions/SearchBar/SearchBarReducer.js +14 -0
  16. data/webpack/components/extensions/SearchBar/SearchBarSelectors.js +5 -0
  17. data/webpack/redux/reducers/index.js +2 -2
  18. data/webpack/scenes/AlternateContentSources/Create/__tests__/acsCreate.test.js +1 -13
  19. data/webpack/scenes/AlternateContentSources/MainTable/ACSTable.js +1 -0
  20. data/webpack/scenes/Content/{ContentPage.js → GenericContentPage.js} +2 -2
  21. data/webpack/scenes/Content/__tests__/contentTable.test.js +2 -2
  22. data/webpack/scenes/Content/index.js +2 -2
  23. data/webpack/scenes/ContentViews/Details/Filters/Rules/ContainerTag/AddEditContainerTagRuleModal.js +14 -17
  24. data/webpack/scenes/ContentViews/Details/Filters/Rules/Package/AddEditPackageRuleModal.js +24 -28
  25. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVContainerImageFilterContent.test.js +11 -18
  26. data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +10 -23
  27. data/webpack/scenes/ContentViews/Details/Filters/__tests__/ContentViewPackageGroupFilter.test.js +0 -2
  28. data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +1 -7
  29. data/webpack/scenes/ContentViews/expansions/__tests__/contentViewComponentsModal.test.js +0 -2
  30. data/webpack/scenes/ModuleStreams/ModuleStreamsPage.js +2 -2
  31. data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamPage.test.js +2 -2
  32. data/webpack/scenes/ModuleStreams/__tests__/__snapshots__/ModuleStreamPage.test.js.snap +1 -1
  33. data/webpack/scenes/Settings/SettingsConstants.js +2 -3
  34. data/webpack/scenes/Settings/SettingsReducer.js +2 -16
  35. data/webpack/scenes/Settings/SettingsSelectors.js +2 -2
  36. data/webpack/test-utils/react-testing-lib-wrapper.js +0 -6
  37. metadata +12 -24
  38. data/webpack/components/Content/__tests__/ContentPage.test.js +0 -32
  39. data/webpack/components/Content/__tests__/__snapshots__/ContentPage.test.js.snap +0 -89
  40. data/webpack/components/Search/Search.js +0 -156
  41. data/webpack/components/Search/__tests__/search.test.js +0 -104
  42. data/webpack/components/Search/helpers.js +0 -6
  43. data/webpack/components/Search/index.js +0 -15
  44. data/webpack/components/TypeAhead/TypeAhead.js +0 -157
  45. data/webpack/components/TypeAhead/TypeAhead.scss +0 -7
  46. data/webpack/components/TypeAhead/helpers/commonPropTypes.js +0 -35
  47. data/webpack/components/TypeAhead/helpers/helpers.js +0 -32
  48. data/webpack/components/TypeAhead/index.js +0 -3
  49. data/webpack/components/TypeAhead/pf3Search/TypeAheadInput.js +0 -44
  50. data/webpack/components/TypeAhead/pf3Search/TypeAheadItems.js +0 -56
  51. data/webpack/components/TypeAhead/pf3Search/TypeAheadSearch.js +0 -53
  52. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.js +0 -66
  53. data/webpack/components/TypeAhead/pf4Search/TypeAheadInput.scss +0 -12
  54. data/webpack/components/TypeAhead/pf4Search/TypeAheadItems.js +0 -59
  55. data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +0 -81
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 623f96f2d316d946b9a19bbed0bd70a58c56541dfcde05261848efb7f868881d
4
- data.tar.gz: f39b3c6dca68f3b742f6a09fb5a821ab5e9d11128835023f09a5a8df30a27272
3
+ metadata.gz: 2919242e09a707d0f3a395e9aaa41cb10a5df4230c72d9fa9c9a2ea4fec084c8
4
+ data.tar.gz: 4231fadf860f0c63c5ccbd98e05f96019eae6e91c3e12abf45c22c958ad27c67
5
5
  SHA512:
6
- metadata.gz: 3d4e46aa5cdededbea344d58cc4dd5c43c1fcdd480e5a62594a1bf0892ff80c048e07a3a7460646b2778502849cc58d7ab6f8f22aaeb1ce3fd0ea8aa59f844c7
7
- data.tar.gz: 97fa1540ab108458032dc4a4963b9644af0a6c7207079bf2c3ef2cc895cacab6521eec73e4ed4aadc2eaf8428fc3b2d5b7bec489a03f02a2d972310344b7c07f
6
+ metadata.gz: 3c3c89ea507b6f247fb1b40b17e615c903e24475b63f9b19d19ebfe1c7d284629b089c87358b3f9a0e35f09b78109823509826c70e21a21dfb8de20ade93a574
7
+ data.tar.gz: d71b28cc37b495a5a836031b7598819070e58c881c5e77bfe292816c2639508dbf075ef5d1234f31b96480a6ea131a8fdbdec0ea4609c2fbccab1a78cc96f5cf
@@ -651,18 +651,6 @@ Foreman::Plugin.register :katello do
651
651
  full_name: N_('Applicability Batch Size'),
652
652
  description: N_("Number of host applicability calculations to process per task.")
653
653
 
654
- setting 'autosearch_while_typing',
655
- type: :boolean,
656
- default: true,
657
- full_name: N_('Autosearch'),
658
- description: N_('For pages that support it, automatically perform search while typing in search input.')
659
-
660
- setting 'autosearch_delay',
661
- type: :integer,
662
- default: 500,
663
- full_name: N_('Autosearch delay'),
664
- description: N_('If Autosearch is enabled, delay in milliseconds before executing searches while typing.')
665
-
666
654
  setting 'bulk_load_size',
667
655
  type: :integer,
668
656
  default: 2000,
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "4.8.0.rc2".freeze
2
+ VERSION = "4.8.0".freeze
3
3
  end
@@ -4,8 +4,9 @@ import { Grid, Col, Row, Form, FormGroup } from 'react-bootstrap';
4
4
  import SearchBar from 'foremanReact/components/SearchBar';
5
5
  import { getControllerSearchProps } from 'foremanReact/constants';
6
6
  import ContentTable from './ContentTable';
7
+ import { useClearSearch } from '../extensions/SearchBar/SearchBarHooks';
7
8
 
8
- const ContentPage = ({
9
+ const GenericContentPage = ({
9
10
  header, onSearch, bookmarkController,
10
11
  autocompleteEndpoint, autocompleteQueryParams,
11
12
  updateSearchQuery, initialInputValue,
@@ -15,6 +16,7 @@ const ContentPage = ({
15
16
  ...getControllerSearchProps(autocompleteEndpoint, `searchBar-content-page-${header}`, true, autocompleteQueryParams),
16
17
  controller: bookmarkController,
17
18
  };
19
+ const searchBarKey = useClearSearch({ updateSearchQuery });
18
20
  return (
19
21
  <Grid bsClass="container-fluid">
20
22
  <Row>
@@ -27,6 +29,7 @@ const ContentPage = ({
27
29
  <Form className="toolbar-pf-actions">
28
30
  <FormGroup className="toolbar-pf toolbar-pf-filter">
29
31
  <SearchBar
32
+ key={searchBarKey}
30
33
  data={searchDataProp}
31
34
  onSearch={onSearch}
32
35
  onSearchChange={updateSearchQuery}
@@ -49,7 +52,7 @@ const ContentPage = ({
49
52
  );
50
53
  };
51
54
 
52
- ContentPage.propTypes = {
55
+ GenericContentPage.propTypes = {
53
56
  header: PropTypes.string.isRequired,
54
57
  content: PropTypes.shape({}).isRequired,
55
58
  tableSchema: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
@@ -62,10 +65,10 @@ ContentPage.propTypes = {
62
65
  bookmarkController: PropTypes.string,
63
66
  };
64
67
 
65
- ContentPage.defaultProps = {
68
+ GenericContentPage.defaultProps = {
66
69
  autocompleteEndpoint: undefined,
67
70
  autocompleteQueryParams: undefined,
68
71
  bookmarkController: undefined,
69
72
  };
70
73
 
71
- export default ContentPage;
74
+ export default GenericContentPage;
@@ -1,9 +1,9 @@
1
1
  import React from 'react';
2
2
  import { shallow } from 'enzyme';
3
3
  import toJson from 'enzyme-to-json';
4
- import ContentTable from '../ContentTable';
5
4
  import { LoadingState } from '../../../components/LoadingState';
6
5
  import { Table } from '../../../components/pf3Table';
6
+ import ContentTable from '../ContentTable';
7
7
 
8
8
  describe('Content Table', () => {
9
9
  it('should render and contain appropriate components', async () => {
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import { act } from 'react-test-renderer';
3
+ import { renderWithRedux, patientlyWaitFor } from 'react-testing-lib-wrapper';
4
+ import { CONTENT_KEY } from '../../../scenes/Content/ContentConstants';
5
+ import GenericContentPage from '../GenericContentPage';
6
+
7
+ const renderOptions = () => ({
8
+ apiNamespace: CONTENT_KEY,
9
+ });
10
+
11
+ test('Can render the basic component with no data', async (done) => {
12
+ const contentHeader = 'Content Header';
13
+ const content = { results: [] };
14
+ const onSearch = jest.fn();
15
+ const updateSearchQuery = jest.fn();
16
+ const searchQuery = '';
17
+ const onPaginationChange = jest.fn();
18
+ const TableSchema = [];
19
+ const bookmarkController = 'module_streams';
20
+
21
+ const { getByText } = renderWithRedux(<GenericContentPage
22
+ header={contentHeader}
23
+ content={content}
24
+ tableSchema={TableSchema}
25
+ onSearch={onSearch}
26
+ updateSearchQuery={updateSearchQuery}
27
+ initialInputValue={searchQuery}
28
+ onPaginationChange={onPaginationChange}
29
+ bookmarkController={bookmarkController}
30
+ />, renderOptions());
31
+
32
+ await patientlyWaitFor(() =>
33
+ expect(getByText(contentHeader)).toBeInTheDocument());
34
+ act(done);
35
+ });
@@ -0,0 +1,70 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { SearchAutocomplete } from 'foremanReact/components/SearchBar/SearchAutocomplete';
4
+ import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
5
+ import { STATUS } from 'foremanReact/constants';
6
+ import { noop } from 'foremanReact/common/helpers';
7
+
8
+ const SearchText = ({
9
+ data: {
10
+ autocomplete: { url, apiParams } = { url: '' },
11
+ disabled,
12
+ },
13
+ initialQuery,
14
+ onSearchChange,
15
+ name,
16
+ }) => {
17
+ const [search, setSearch] = useState(initialQuery || '');
18
+ const getAPIparams = input => ({ ...apiParams(input) });
19
+ const { response, status, setAPIOptions } = useAPI('get', url, {
20
+ params: getAPIparams(search),
21
+ });
22
+ const onChange = (newValue) => {
23
+ onSearchChange(newValue);
24
+ setSearch(newValue);
25
+ setAPIOptions({ params: { ...getAPIparams(newValue) } });
26
+ };
27
+ const error =
28
+ status === STATUS.ERROR || response?.[0]?.error
29
+ ? response?.[0]?.error || response.message
30
+ : null;
31
+
32
+ let results = [];
33
+ if (Array.isArray(response) && !error) {
34
+ results = response.map(item => ({ label: item, category: '' }));
35
+ }
36
+
37
+ return (
38
+ <div className="foreman-search-text">
39
+ <SearchAutocomplete
40
+ results={results}
41
+ onSearchChange={onChange}
42
+ value={search}
43
+ disabled={disabled}
44
+ error={error}
45
+ name={name}
46
+ />
47
+ </div>
48
+ );
49
+ };
50
+
51
+ SearchText.propTypes = {
52
+ data: PropTypes.shape({
53
+ autocomplete: PropTypes.shape({
54
+ url: PropTypes.string.isRequired,
55
+ apiParams: PropTypes.func,
56
+ }).isRequired,
57
+ disabled: PropTypes.bool,
58
+ }).isRequired,
59
+ initialQuery: PropTypes.string,
60
+ onSearchChange: PropTypes.func,
61
+ name: PropTypes.string,
62
+ };
63
+
64
+ SearchText.defaultProps = {
65
+ initialQuery: '',
66
+ onSearchChange: noop,
67
+ name: null,
68
+ };
69
+
70
+ export default SearchText;
@@ -14,7 +14,7 @@ import { translate as __ } from 'foremanReact/common/I18n';
14
14
  import { CubeIcon, ExclamationCircleIcon, SearchIcon, CheckCircleIcon, PlusCircleIcon } from '@patternfly/react-icons';
15
15
  import { global_danger_color_200 as dangerColor, global_success_color_100 as successColor } from '@patternfly/react-tokens';
16
16
  import { useDispatch, useSelector } from 'react-redux';
17
- import { selectHostDetailsClearSearch } from '../extensions/HostDetails/HostDetailsSelectors';
17
+ import { selectSearchBarClearSearch } from '../extensions/SearchBar/SearchBarSelectors';
18
18
 
19
19
  const KatelloEmptyStateIcon = ({
20
20
  error, search, customIcon, happyIcon,
@@ -51,7 +51,7 @@ const EmptyStateMessage = ({
51
51
  const defaultSecondaryActionText = searchIsActive ? __('Clear search') : __('Clear filters');
52
52
  const secondaryActionText = secondaryActionTextOverride || defaultSecondaryActionText;
53
53
  const dispatch = useDispatch();
54
- const clearSearch = useSelector(selectHostDetailsClearSearch);
54
+ const clearSearch = useSelector(selectSearchBarClearSearch);
55
55
  const showSecondaryActionAnchor = showSecondaryAction && secondaryActionLink;
56
56
  const handleClick = () => {
57
57
  if (searchIsActive) {
@@ -14,6 +14,7 @@ import MainTable from './MainTable';
14
14
  import { getPageStats } from './helpers';
15
15
  import SelectAllCheckbox from '../SelectAllCheckbox';
16
16
  import { orgId } from '../../services/api';
17
+ import { useClearSearch } from '../extensions/SearchBar/SearchBarHooks';
17
18
 
18
19
  /* Patternfly 4 table wrapper */
19
20
  const TableWrapper = ({
@@ -132,6 +133,8 @@ const TableWrapper = ({
132
133
  spawnFetch();
133
134
  }, [searchQuery, spawnFetch, additionalListeners]);
134
135
 
136
+ const searchBarKey = useClearSearch({ updateSearchQuery });
137
+
135
138
  // If the new page wouldn't exist because of a perPage change,
136
139
  // we should set the current page to the last page.
137
140
  const validatePagination = (data) => {
@@ -194,6 +197,7 @@ const TableWrapper = ({
194
197
  data={searchDataProp}
195
198
  initialQuery={searchQuery}
196
199
  onSearch={search => updateSearchQuery(search)}
200
+ key={searchBarKey}
197
201
  />
198
202
  </FlexItem>
199
203
  }
@@ -1,3 +1,2 @@
1
- export const SET_CLEAR_SEARCH = 'SET_CLEAR_SEARCH';
2
1
  const HOST_DETAILS = 'HOST_DETAILS';
3
2
  export default HOST_DETAILS;
@@ -14,9 +14,3 @@ export const selectHostDetailsStatus = state =>
14
14
 
15
15
  export const selectHostDetailsError = state =>
16
16
  selectAPIError(state, HOST_DETAILS_KEY);
17
-
18
- export const selectHostDetailsState = state =>
19
- state.katello.hostDetails;
20
-
21
- export const selectHostDetailsClearSearch = state =>
22
- selectHostDetailsState(state).clearSearch;
@@ -93,6 +93,82 @@ test('Can handle no Module streams being present', async (done) => {
93
93
  act(done);
94
94
  });
95
95
 
96
+ test('When there are no search results, can display an empty state with a clear search link that works', async (done) => {
97
+ // Setup autocomplete with mockForemanAutoComplete since we aren't adding /katello
98
+ const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
99
+ const noResults = {
100
+ total: 0,
101
+ subtotal: 0,
102
+ page: 1,
103
+ search: 'bad search',
104
+ per_page: 20,
105
+ results: [],
106
+ };
107
+
108
+ const initialScope = nockInstance
109
+ .get(hostModuleStreams)
110
+ .query(true)
111
+ .times(1)
112
+ .reply(200, mockModuleStreams);
113
+
114
+ const badSearchScope = nockInstance
115
+ .get(hostModuleStreams)
116
+ .query({
117
+ sort_by: 'name',
118
+ sort_order: 'asc',
119
+ per_page: '20',
120
+ page: '1',
121
+ search: 'bad search',
122
+ })
123
+ .reply(200, noResults);
124
+
125
+ const badAutoCompleteScope =
126
+ mockForemanAutocomplete(
127
+ nockInstance,
128
+ autocompleteUrl,
129
+ true,
130
+ [],
131
+ 2, // times
132
+ );
133
+
134
+ const scopeWithoutSearch = nockInstance
135
+ .get(hostModuleStreams)
136
+ .query(true)
137
+ .reply(200, mockModuleStreams);
138
+
139
+ const { queryByText, getByRole } = renderWithRedux(<ModuleStreamsTab />, renderOptions());
140
+
141
+
142
+ await patientlyWaitFor(() => expect(queryByText(firstModuleStreams.name)).toBeInTheDocument());
143
+
144
+ const searchInput = getByRole('textbox', { name: 'Search input' });
145
+ // Foreman SearchAutocomplete doesn't run onSearchChange unless the element is focused!
146
+ searchInput.focus();
147
+
148
+ fireEvent.change(searchInput, { target: { value: 'bad search' } });
149
+ expect(searchInput.value).toBe('bad search');
150
+ const searchButton = getByRole('button', { name: 'Search' });
151
+ expect(searchButton).not.toHaveAttribute('aria-disabled', true);
152
+ fireEvent.click(searchButton);
153
+
154
+ await patientlyWaitFor(() => expect(queryByText('Your search returned no matching Module streams.')).toBeInTheDocument());
155
+ // Now click the clear search link and assert that the search is cleared and the results are back
156
+ const clearSearchLink = getByRole('button', { name: 'Clear search' });
157
+ fireEvent.click(clearSearchLink);
158
+
159
+ await patientlyWaitFor(() => {
160
+ expect(queryByText(firstModuleStreams.name)).toBeInTheDocument();
161
+ expect(getByRole('textbox', { name: 'Search input' }).value).toBe('');
162
+ expect(queryByText('Clear search')).not.toBeInTheDocument();
163
+ });
164
+
165
+ assertNockRequest(initialScope);
166
+ assertNockRequest(badAutoCompleteScope);
167
+ assertNockRequest(badSearchScope);
168
+ assertNockRequest(scopeWithoutSearch);
169
+ assertNockRequest(autocompleteScope, done);
170
+ });
171
+
96
172
  test('Can filter results based on status', async (done) => {
97
173
  const autocompleteScope = mockForemanAutocomplete(nockInstance, autocompleteUrl);
98
174
  const scope = nockInstance
@@ -0,0 +1,3 @@
1
+ export const SET_CLEAR_SEARCH = 'SET_CLEAR_SEARCH';
2
+
3
+ export default SET_CLEAR_SEARCH;
@@ -0,0 +1,50 @@
1
+ import { useEffect, useCallback, useRef } from 'react';
2
+ import { useDispatch, useSelector } from 'react-redux';
3
+ import { selectSearchBarClearSearch } from './SearchBarSelectors';
4
+
5
+ export const useClearSearch = ({
6
+ updateSearchQuery,
7
+ }) => {
8
+ const dispatch = useDispatch();
9
+ // We keep the clearSearch function in Redux to avoid prop drilling and make EmptyStateMessage
10
+ // more reusable both with and without TableWrapper.
11
+ const existingClearSearch = useSelector(selectSearchBarClearSearch);
12
+ // In Katello we don't have access to Foreman <SearchBar /> component's internal state,
13
+ // so we don't have an easy way to clear the search input. We can use a counter to
14
+ // pass as a key prop to the <SearchBar /> component, which will force it to reset
15
+ // its internal state when clearSearch is called.
16
+ const counter = useRef(0);
17
+
18
+ const clearSearch = useCallback(() => {
19
+ counter.current += 1; // reset the text input
20
+ if (typeof updateSearchQuery !== 'function') {
21
+ // eslint-disable-next-line no-console
22
+ console.error('You must pass the updateSearchQuery function to useClearSearch');
23
+ return;
24
+ }
25
+ updateSearchQuery(''); // make a new API call with blank search query
26
+ }, [updateSearchQuery]);
27
+
28
+ useEffect(() => {
29
+ if (typeof existingClearSearch !== 'function') {
30
+ dispatch({
31
+ type: 'SET_CLEAR_SEARCH',
32
+ payload: clearSearch,
33
+ });
34
+ }
35
+ }, [dispatch, existingClearSearch, clearSearch]);
36
+
37
+ // eslint-disable-next-line arrow-body-style
38
+ useEffect(() => {
39
+ return function cleanupClearSearch() {
40
+ dispatch({
41
+ type: 'SET_CLEAR_SEARCH',
42
+ payload: {},
43
+ });
44
+ };
45
+ }, [dispatch]);
46
+
47
+ return `search-bar-${counter.current}`;
48
+ };
49
+
50
+ export default useClearSearch;
@@ -0,0 +1,14 @@
1
+ import Immutable from 'seamless-immutable';
2
+
3
+ import { SET_CLEAR_SEARCH } from './SearchBarConstants';
4
+
5
+ const initialState = Immutable({ clearSearch: undefined });
6
+
7
+ export default (state = initialState, action) => {
8
+ switch (action.type) {
9
+ case SET_CLEAR_SEARCH:
10
+ return state.set('clearSearch', action.payload);
11
+ default:
12
+ return state;
13
+ }
14
+ };
@@ -0,0 +1,5 @@
1
+ export const selectSearchBarState = state =>
2
+ state.katello.searchBar;
3
+
4
+ export const selectSearchBarClearSearch = state =>
5
+ selectSearchBarState(state)?.clearSearch;
@@ -4,7 +4,6 @@ import redHatRepositories from './RedHatRepositories';
4
4
  import { subscriptions } from '../../scenes/Subscriptions';
5
5
  import { upstreamSubscriptions } from '../../scenes/Subscriptions/UpstreamSubscriptions';
6
6
  import { manifestHistory } from '../../scenes/Subscriptions/Manifest';
7
- import settings from '../../scenes/Settings';
8
7
  import { subscriptionDetails } from '../../scenes/Subscriptions/Details';
9
8
  import { setOrganization } from '../../components/SelectOrg/SetOrganization';
10
9
  import { moduleStreams } from '../../scenes/ModuleStreams';
@@ -13,6 +12,7 @@ import { moduleStreamDetails } from '../../scenes/ModuleStreams/Details';
13
12
  import { reducers as systemStatuses } from '../../components/extensions/about';
14
13
  import { contentViewDetails } from '../../scenes/ContentViews/Details';
15
14
  import hostDetails from '../../components/extensions/HostDetails/HostDetailsReducer';
15
+ import searchBar from '../../components/extensions/SearchBar/SearchBarReducer';
16
16
 
17
17
  export default combineReducers({
18
18
  organization,
@@ -20,13 +20,13 @@ export default combineReducers({
20
20
  subscriptions,
21
21
  upstreamSubscriptions,
22
22
  manifestHistory,
23
- settings,
24
23
  subscriptionDetails,
25
24
  setOrganization,
26
25
  moduleStreams,
27
26
  moduleStreamDetails,
28
27
  contentViewDetails,
29
28
  hostDetails,
29
+ searchBar,
30
30
  ...organizationProductsReducers,
31
31
  ...systemStatuses,
32
32
  });
@@ -3,7 +3,7 @@ import * as reactRedux from 'react-redux';
3
3
  import { Route } from 'react-router-dom';
4
4
  import { act, fireEvent, patientlyWaitFor, renderWithRedux } from 'react-testing-lib-wrapper';
5
5
  import api, { foremanApi } from '../../../../services/api';
6
- import { assertNockRequest, mockAutocomplete, mockSetting, nockInstance } from '../../../../test-utils/nockWrapper';
6
+ import { assertNockRequest, mockAutocomplete, nockInstance } from '../../../../test-utils/nockWrapper';
7
7
  import ACSTable from '../../MainTable/ACSTable';
8
8
  import contentCredentialResult from './contentCredentials.fixtures';
9
9
  import smartProxyResult from './smartProxy.fixtures';
@@ -70,18 +70,6 @@ const renderOptions = {
70
70
  },
71
71
  };
72
72
 
73
- let searchDelayScope;
74
- let autoSearchScope;
75
- beforeEach(() => {
76
- searchDelayScope = mockSetting(nockInstance, 'autosearch_delay', 0);
77
- autoSearchScope = mockSetting(nockInstance, 'autosearch_while_typing');
78
- });
79
-
80
- afterEach(() => {
81
- assertNockRequest(searchDelayScope);
82
- assertNockRequest(autoSearchScope);
83
- });
84
-
85
73
  test('Can show add ACS button if can_create is true', async (done) => {
86
74
  const autocompleteScope = mockAutocomplete(nockInstance, autocompleteUrl);
87
75
  const scope = nockInstance
@@ -107,6 +107,7 @@ const ACSTable = () => {
107
107
  const onBulkDelete = (ids) => {
108
108
  setDeleting(true);
109
109
  dispatch(bulkDeleteACS({ ids }, () => {
110
+ setDeleting(false);
110
111
  if (acsId && ids.has(Number(acsId))) {
111
112
  push('/alternate_content_sources');
112
113
  } else {
@@ -12,7 +12,7 @@ import { getContentTypes } from './ContentActions';
12
12
  import Loading from '../../components/Loading';
13
13
  import EmptyStateMessage from '../../components/Table/EmptyStateMessage';
14
14
 
15
- const ContentPage = () => {
15
+ const GenericContentPage = () => {
16
16
  const dispatch = useDispatch();
17
17
  const contentTypesResponse = useSelector(selectContentTypes);
18
18
  const contentTypesStatus = useSelector(selectContentTypesStatus);
@@ -86,4 +86,4 @@ const ContentPage = () => {
86
86
  );
87
87
  };
88
88
 
89
- export default ContentPage;
89
+ export default GenericContentPage;
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { renderWithRedux, patientlyWaitFor } from 'react-testing-lib-wrapper';
3
3
  import { nockInstance, assertNockRequest, mockAutocomplete } from '../../../test-utils/nockWrapper';
4
4
  import api from '../../../services/api';
5
- import ContentPage from '../ContentPage';
5
+ import GenericContentPage from '../GenericContentPage';
6
6
  import ansibleCollectionsResponse from './ansibleCollections.fixtures';
7
7
  import contentTypesResponse from './contentTypes.fixtures.json';
8
8
  import pythonPackagesResponse from './pythonPackages.fixtures.json';
@@ -29,7 +29,7 @@ test('Can call API for Python Packages and show table on page load', async (done
29
29
  .reply(200, contentTypesResponse);
30
30
 
31
31
  const { queryByText, getAllByText } =
32
- renderWithRedux(<ContentPage />);
32
+ renderWithRedux(<GenericContentPage />);
33
33
 
34
34
  expect(queryByText(firstPackage.name)).toBeNull();
35
35
  await patientlyWaitFor(() => {
@@ -1,4 +1,4 @@
1
1
  import { withRouter } from 'react-router-dom';
2
- import ContentPage from './ContentPage';
2
+ import GenericContentPage from './GenericContentPage';
3
3
 
4
- export default withRouter(ContentPage);
4
+ export default withRouter(GenericContentPage);
@@ -5,7 +5,7 @@ import { translate as __ } from 'foremanReact/common/I18n';
5
5
  import { Modal, ModalVariant, Form, FormGroup, ActionGroup, Button } from '@patternfly/react-core';
6
6
  import { addCVFilterRule, editCVFilterRule, getCVFilterRules } from '../../../ContentViewDetailActions';
7
7
  import { orgId } from '../../../../../../services/api';
8
- import Search from '../../../../../../components/Search/Search';
8
+ import SearchText from '../../../../../../components/Search/SearchText';
9
9
 
10
10
  const AddEditContainerTagRuleModal = ({
11
11
  onClose, filterId, selectedFilterRuleData, repositoryIds,
@@ -16,7 +16,7 @@ const AddEditContainerTagRuleModal = ({
16
16
  const [saving, setSaving] = useState(false);
17
17
  const isEditing = name && id;
18
18
 
19
- const autoCompleteEndpoint = '/docker_tags/auto_complete_name';
19
+ const autoCompleteEndpoint = '/katello/api/v2/docker_tags/auto_complete_name';
20
20
 
21
21
  const onSubmit = () => {
22
22
  setSaving(true);
@@ -36,13 +36,10 @@ const AddEditContainerTagRuleModal = ({
36
36
  onClose();
37
37
  };
38
38
 
39
- const getAutoCompleteParams = term => ({
40
- endpoint: autoCompleteEndpoint,
41
- params: {
42
- organization_id: orgId(),
43
- term,
44
- repoids: repositoryIds,
45
- },
39
+ const searchDataProp = term => ({
40
+ organization_id: orgId(),
41
+ term,
42
+ repoids: repositoryIds,
46
43
  });
47
44
 
48
45
  return (
@@ -59,14 +56,14 @@ const AddEditContainerTagRuleModal = ({
59
56
  }}
60
57
  >
61
58
  <FormGroup label={__('Tag name')} isRequired fieldId="tag_name">
62
- <Search
63
- patternfly4
64
- initialInputValue={tagName}
65
- onSearch={() => {}}
66
- getAutoCompleteParams={getAutoCompleteParams}
67
- foremanApiAutoComplete={false}
68
- isTextInput
69
- setTextInputValue={setTagName}
59
+ <SearchText
60
+ data={{
61
+ autocomplete: {
62
+ url: autoCompleteEndpoint,
63
+ apiParams: tag => searchDataProp(tag),
64
+ },
65
+ }}
66
+ onSearchChange={setTagName}
70
67
  />
71
68
  </FormGroup>
72
69
  <ActionGroup>