foreman_remote_execution 5.0.0 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +7 -0
  4. data/app/controllers/ui_job_wizard_controller.rb +12 -1
  5. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +20 -9
  6. data/app/helpers/remote_execution_helper.rb +1 -1
  7. data/app/lib/actions/remote_execution/run_host_job.rb +2 -0
  8. data/app/lib/foreman_remote_execution/renderer/scope/input.rb +1 -1
  9. data/app/mailers/rex_job_mailer.rb +1 -1
  10. data/app/models/concerns/foreman_remote_execution/host_extensions.rb +4 -0
  11. data/app/models/job_invocation.rb +2 -0
  12. data/app/models/job_template.rb +3 -1
  13. data/app/models/targeting.rb +1 -1
  14. data/app/views/job_invocations/_preview_hosts_list.html.erb +1 -1
  15. data/app/views/job_templates/_custom_tabs.html.erb +4 -9
  16. data/app/views/template_invocations/show.html.erb +7 -1
  17. data/lib/foreman_remote_execution/engine.rb +7 -3
  18. data/lib/foreman_remote_execution/version.rb +1 -1
  19. data/locale/action_names.rb +3 -4
  20. data/locale/de/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  21. data/locale/de/foreman_remote_execution.po +356 -20
  22. data/locale/en/foreman_remote_execution.po +356 -20
  23. data/locale/en_GB/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  24. data/locale/en_GB/foreman_remote_execution.po +356 -20
  25. data/locale/es/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  26. data/locale/es/foreman_remote_execution.po +357 -21
  27. data/locale/foreman_remote_execution.pot +808 -296
  28. data/locale/fr/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  29. data/locale/fr/foreman_remote_execution.po +357 -21
  30. data/locale/ja/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  31. data/locale/ja/foreman_remote_execution.po +357 -21
  32. data/locale/ko/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  33. data/locale/ko/foreman_remote_execution.po +356 -20
  34. data/locale/pt_BR/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  35. data/locale/pt_BR/foreman_remote_execution.po +357 -21
  36. data/locale/ru/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  37. data/locale/ru/foreman_remote_execution.po +356 -20
  38. data/locale/zh_CN/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  39. data/locale/zh_CN/foreman_remote_execution.po +357 -21
  40. data/locale/zh_TW/LC_MESSAGES/foreman_remote_execution.mo +0 -0
  41. data/locale/zh_TW/foreman_remote_execution.po +356 -20
  42. data/package.json +3 -1
  43. data/test/unit/job_invocation_report_template_test.rb +1 -1
  44. data/test/unit/targeting_test.rb +1 -1
  45. data/webpack/JobWizard/JobWizard.js +22 -5
  46. data/webpack/JobWizard/JobWizard.scss +5 -0
  47. data/webpack/JobWizard/JobWizardConstants.js +2 -1
  48. data/webpack/JobWizard/__tests__/fixtures.js +13 -2
  49. data/webpack/JobWizard/__tests__/integration.test.js +6 -1
  50. data/webpack/JobWizard/autofill.js +34 -9
  51. data/webpack/JobWizard/index.js +0 -7
  52. data/webpack/JobWizard/steps/CategoryAndTemplate/index.js +25 -7
  53. data/webpack/JobWizard/steps/HostsAndInputs/HostSearch.js +1 -1
  54. data/webpack/JobWizard/steps/HostsAndInputs/__tests__/HostsAndInputs.test.js +28 -0
  55. data/webpack/JobWizard/steps/Schedule/RepeatOn.js +1 -1
  56. data/webpack/JobWizard/steps/form/Formatter.js +18 -3
  57. data/webpack/__mocks__/foremanReact/components/Pagination.js +2 -0
  58. data/webpack/__mocks__/foremanReact/constants.js +1 -0
  59. data/webpack/react_app/components/TargetingHosts/TargetingHostsHelpers.js +1 -1
  60. data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.js +1 -6
  61. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +1 -9
  62. data/webpack/react_app/components/TargetingHosts/index.js +2 -3
  63. metadata +3 -4
  64. data/app/views/templates/README.md +0 -6
  65. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +0 -2
data/package.json CHANGED
@@ -30,7 +30,9 @@
30
30
  "eslint": "^6.8.0",
31
31
  "prettier": "^1.19.1",
32
32
  "@patternfly/react-catalog-view-extension": "^4.8.126",
33
- "redux-mock-store": "^1.2.2"
33
+ "redux-mock-store": "^1.2.2",
34
+ "graphql-tag": "^2.11.0",
35
+ "graphql": "^15.5.0"
34
36
  },
35
37
  "peerDependencies": {
36
38
  "@theforeman/vendor": "^8.16.0"
@@ -9,7 +9,7 @@ class JobReportTemplateTest < ActiveSupport::TestCase
9
9
 
10
10
  context 'with valid job invocation report template' do
11
11
  let(:job_invocation_template) do
12
- file_path = File.read(File.expand_path(Rails.root + "app/views/unattended/report_templates/jobs_-_invocation_report_template.erb"))
12
+ file_path = File.read(File.expand_path(Rails.root + "app/views/unattended/report_templates/job_invocation_-_report_template.erb"))
13
13
  template = ReportTemplate.import_without_save("Job Invocation Report Template", file_path)
14
14
  template.save!
15
15
  template
@@ -61,7 +61,7 @@ class TargetingTest < ActiveSupport::TestCase
61
61
  users(:one).destroy
62
62
  end
63
63
 
64
- it { assert targeting.reload.user.nil? }
64
+ it { assert_nil targeting.reload.user }
65
65
  it do
66
66
  -> { targeting.resolve_hosts! }.must_raise(Foreman::Exception)
67
67
  end
@@ -20,6 +20,7 @@ import {
20
20
  selectTemplateError,
21
21
  selectJobTemplate,
22
22
  selectIsSubmitting,
23
+ selectRouterSearch,
23
24
  } from './JobWizardSelectors';
24
25
  import Schedule from './steps/Schedule/';
25
26
  import HostsAndInputs from './steps/HostsAndInputs/';
@@ -41,6 +42,7 @@ export const JobWizard = () => {
41
42
  hostGroups: [],
42
43
  });
43
44
  const [hostsSearchQuery, setHostsSearchQuery] = useState('');
45
+ const [fills, setFills] = useState(useSelector(selectRouterSearch));
44
46
  const dispatch = useDispatch();
45
47
 
46
48
  const setDefaults = useCallback(
@@ -49,17 +51,26 @@ export const JobWizard = () => {
49
51
  template_inputs,
50
52
  advanced_template_inputs,
51
53
  effective_user,
52
- job_template: { name, execution_timeout_interval, description_format },
54
+ job_template: {
55
+ name,
56
+ execution_timeout_interval,
57
+ description_format,
58
+ job_category,
59
+ },
53
60
  },
54
61
  }) => {
62
+ if (!category.length) {
63
+ setCategory(current => (current.length ? current : job_category));
64
+ }
55
65
  const advancedTemplateValues = {};
56
66
  const defaultTemplateValues = {};
57
67
  const inputs = template_inputs;
58
68
  const advancedInputs = advanced_template_inputs;
59
69
  if (inputs) {
60
- setTemplateValues(() => {
70
+ setTemplateValues(prev => {
61
71
  inputs.forEach(input => {
62
- defaultTemplateValues[input.name] = input?.default || '';
72
+ defaultTemplateValues[input.name] =
73
+ prev[input.name] || input?.default || '';
63
74
  });
64
75
  return defaultTemplateValues;
65
76
  });
@@ -67,7 +78,8 @@ export const JobWizard = () => {
67
78
  setAdvancedValues(currentAdvancedValues => {
68
79
  if (advancedInputs) {
69
80
  advancedInputs.forEach(input => {
70
- advancedTemplateValues[input.name] = input?.default || '';
81
+ advancedTemplateValues[input.name] =
82
+ currentAdvancedValues[input.name] || input?.default || '';
71
83
  });
72
84
  }
73
85
  const generateDefaultDescription = () => {
@@ -89,7 +101,7 @@ export const JobWizard = () => {
89
101
  };
90
102
  });
91
103
  },
92
- []
104
+ [category.length]
93
105
  );
94
106
  useEffect(() => {
95
107
  if (jobTemplateID) {
@@ -108,8 +120,12 @@ export const JobWizard = () => {
108
120
  templateValues,
109
121
  });
110
122
  useAutoFill({
123
+ fills,
124
+ setFills,
111
125
  setSelectedTargets,
112
126
  setHostsSearchQuery,
127
+ setJobTemplateID,
128
+ setTemplateValues,
113
129
  });
114
130
  const templateError = !!useSelector(selectTemplateError);
115
131
  const templateResponse = useSelector(selectJobTemplate);
@@ -126,6 +142,7 @@ export const JobWizard = () => {
126
142
  setJobTemplate={setJobTemplateID}
127
143
  category={category}
128
144
  setCategory={setCategory}
145
+ isFeature={!!fills.feature}
129
146
  />
130
147
  ),
131
148
  enableNext: isTemplate,
@@ -103,4 +103,9 @@
103
103
  margin-left: 10px;
104
104
  }
105
105
  }
106
+ .foreman-search-field {
107
+ .autocomplete-search-btn {
108
+ display: none;
109
+ }
110
+ }
106
111
  }
@@ -47,7 +47,7 @@ export const hostMethods = {
47
47
  searchQuery: __('Search query'),
48
48
  };
49
49
 
50
- export const hostQuerySearchID = 'searchBar'; // until https://projects.theforeman.org/issues/33737 is used
50
+ export const hostQuerySearchID = 'mainHostQuery';
51
51
  export const hostsController = 'hosts';
52
52
 
53
53
  export const dataName = {
@@ -58,3 +58,4 @@ export const HOSTS_TO_PREVIEW_AMOUNT = 20;
58
58
 
59
59
  export const DEBOUNCE_HOST_COUNT = 700;
60
60
  export const HOST_IDS = 'HOST_IDS';
61
+ export const REX_FEATURE = 'REX_FEATURE';
@@ -69,6 +69,7 @@ export const jobTemplateResponse = {
69
69
  default: '',
70
70
  hidden_value: false,
71
71
  url: 'foreman_tasks/tasks',
72
+ resource_type_tableize: 'hosts',
72
73
  },
73
74
  {
74
75
  name: 'adv date',
@@ -96,7 +97,7 @@ export const jobTemplateResponse = {
96
97
  ],
97
98
  };
98
99
 
99
- export const jobCategories = ['Ansible Commands', 'Puppet', 'Services'];
100
+ export const jobCategories = ['Services', 'Ansible Commands', 'Puppet'];
100
101
 
101
102
  export const testSetup = (selectors, api) => {
102
103
  jest.spyOn(api, 'get');
@@ -149,7 +150,12 @@ export const mockApi = api => {
149
150
  api.get.mockImplementation(({ handleSuccess, ...action }) => {
150
151
  if (action.key === 'JOB_CATEGORIES') {
151
152
  handleSuccess &&
152
- handleSuccess({ data: { job_categories: jobCategories } });
153
+ handleSuccess({
154
+ data: {
155
+ job_categories: jobCategories,
156
+ default_category: 'Ansible Commands',
157
+ },
158
+ });
153
159
  } else if (action.key === 'JOB_TEMPLATE') {
154
160
  handleSuccess &&
155
161
  handleSuccess({
@@ -165,6 +171,11 @@ export const mockApi = api => {
165
171
  handleSuccess({
166
172
  data: { results: [{ name: 'host1' }, { name: 'host3' }] },
167
173
  });
174
+ } else if (action.key === 'REX_FEATURE') {
175
+ handleSuccess &&
176
+ handleSuccess({
177
+ data: { job_template_id: 178 },
178
+ });
168
179
  }
169
180
  return { type: 'get', ...action };
170
181
  });
@@ -22,7 +22,12 @@ describe('Job wizard fill', () => {
22
22
  api.get.mockImplementation(({ handleSuccess, ...action }) => {
23
23
  if (action.key === 'JOB_CATEGORIES') {
24
24
  handleSuccess &&
25
- handleSuccess({ data: { job_categories: jobCategories } });
25
+ handleSuccess({
26
+ data: {
27
+ job_categories: jobCategories,
28
+ default_category: 'Ansible Commands',
29
+ },
30
+ });
26
31
  } else if (action.key === 'JOB_TEMPLATE') {
27
32
  handleSuccess &&
28
33
  handleSuccess({
@@ -1,22 +1,29 @@
1
1
  import { useEffect } from 'react';
2
- import { useDispatch, useSelector } from 'react-redux';
2
+ import { useDispatch } from 'react-redux';
3
3
  import { get } from 'foremanReact/redux/API';
4
- import { HOST_IDS } from './JobWizardConstants';
5
- import { selectRouterSearch } from './JobWizardSelectors';
4
+ import { HOST_IDS, REX_FEATURE } from './JobWizardConstants';
6
5
  import './JobWizard.scss';
7
6
 
8
- export const useAutoFill = ({ setSelectedTargets, setHostsSearchQuery }) => {
9
- const fills = useSelector(selectRouterSearch);
7
+ export const useAutoFill = ({
8
+ fills,
9
+ setFills,
10
+ setSelectedTargets,
11
+ setHostsSearchQuery,
12
+ setJobTemplateID,
13
+ setTemplateValues,
14
+ }) => {
10
15
  const dispatch = useDispatch();
11
16
 
12
17
  useEffect(() => {
13
18
  if (Object.keys(fills).length) {
14
- if (fills['host_ids[]']) {
19
+ const { 'host_ids[]': hostIds, search, feature, ...rest } = { ...fills };
20
+ setFills({});
21
+ if (hostIds) {
15
22
  dispatch(
16
23
  get({
17
24
  key: HOST_IDS,
18
25
  url: '/api/hosts',
19
- params: { search: `id = ${fills['host_ids[]'].join(' or id = ')}` },
26
+ params: { search: `id = ${hostIds.join(' or id = ')}` },
20
27
  handleSuccess: ({ data }) => {
21
28
  setSelectedTargets(currentTargets => ({
22
29
  ...currentTargets,
@@ -29,8 +36,26 @@ export const useAutoFill = ({ setSelectedTargets, setHostsSearchQuery }) => {
29
36
  })
30
37
  );
31
38
  }
32
- if (fills.search) {
33
- setHostsSearchQuery(fills.search);
39
+ if (search) {
40
+ setHostsSearchQuery(search);
41
+ }
42
+ if (feature) {
43
+ dispatch(
44
+ get({
45
+ key: REX_FEATURE,
46
+ url: `/api/remote_execution_features/${feature}`,
47
+ handleSuccess: ({ data }) => {
48
+ setJobTemplateID(data.job_template_id);
49
+ },
50
+ })
51
+ );
52
+ Object.keys(rest).forEach(key => {
53
+ const re = /inputs\[(?<input>.*)\]/g;
54
+ const input = re.exec(key)?.groups?.input;
55
+ if (input) {
56
+ setTemplateValues(prev => ({ ...prev, [input]: rest[key] }));
57
+ }
58
+ });
34
59
  }
35
60
  }
36
61
  // eslint-disable-next-line react-hooks/exhaustive-deps
@@ -1,5 +1,4 @@
1
1
  import React from 'react';
2
- import PropTypes from 'prop-types';
3
2
  import { Title, Divider } from '@patternfly/react-core';
4
3
  import { translate as __ } from 'foremanReact/common/I18n';
5
4
  import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout';
@@ -30,10 +29,4 @@ const JobWizardPage = () => {
30
29
  );
31
30
  };
32
31
 
33
- JobWizardPage.propTypes = {
34
- location: PropTypes.shape({
35
- search: PropTypes.string,
36
- }).isRequired,
37
- };
38
-
39
32
  export default JobWizardPage;
@@ -25,6 +25,7 @@ const ConnectedCategoryAndTemplate = ({
25
25
  setJobTemplate,
26
26
  category,
27
27
  setCategory,
28
+ isFeature,
28
29
  }) => {
29
30
  const dispatch = useDispatch();
30
31
 
@@ -36,12 +37,23 @@ const ConnectedCategoryAndTemplate = ({
36
37
  get({
37
38
  key: JOB_CATEGORIES,
38
39
  url: '/ui_job_wizard/categories',
39
- handleSuccess: response =>
40
- setCategory(response.data.job_categories[0] || ''),
40
+ handleSuccess: ({
41
+ data: {
42
+ default_category: defaultCategory,
43
+ job_categories: jobCategories,
44
+ default_template: defaultTemplate,
45
+ },
46
+ }) => {
47
+ if (!isFeature) {
48
+ setCategory(defaultCategory || jobCategories[0] || '');
49
+ if (defaultTemplate) setJobTemplate(defaultTemplate);
50
+ }
51
+ },
41
52
  })
42
53
  );
43
54
  }
44
- }, [jobCategoriesStatus, dispatch, setCategory]);
55
+ // eslint-disable-next-line react-hooks/exhaustive-deps
56
+ }, [jobCategoriesStatus]);
45
57
 
46
58
  const jobCategories = useSelector(selectJobCategories);
47
59
  useEffect(() => {
@@ -55,14 +67,19 @@ const ConnectedCategoryAndTemplate = ({
55
67
  per_page: 'all',
56
68
  }),
57
69
  handleSuccess: response => {
58
- setJobTemplate(
59
- Number(filterJobTemplates(response?.data?.results)[0]?.id) || null
60
- );
70
+ if (!jobTemplate)
71
+ setJobTemplate(
72
+ current =>
73
+ current ||
74
+ Number(filterJobTemplates(response?.data?.results)[0]?.id) ||
75
+ null
76
+ );
61
77
  },
62
78
  })
63
79
  );
64
80
  }
65
- }, [category, dispatch, setJobTemplate]);
81
+ // eslint-disable-next-line react-hooks/exhaustive-deps
82
+ }, [category, dispatch]);
66
83
 
67
84
  const jobTemplates = useSelector(selectJobTemplates);
68
85
 
@@ -89,6 +106,7 @@ ConnectedCategoryAndTemplate.propTypes = {
89
106
  setJobTemplate: PropTypes.func.isRequired,
90
107
  category: PropTypes.string.isRequired,
91
108
  setCategory: PropTypes.func.isRequired,
109
+ isFeature: PropTypes.bool.isRequired,
92
110
  };
93
111
  ConnectedCategoryAndTemplate.defaultProps = { jobTemplate: null };
94
112
 
@@ -10,7 +10,7 @@ import { noop } from '../../../helpers';
10
10
 
11
11
  export const HostSearch = ({ value, setValue }) => {
12
12
  const searchQuery = useSelector(
13
- state => state.autocomplete?.hostsSearch?.searchQuery
13
+ state => state.autocomplete?.[hostQuerySearchID]?.searchQuery
14
14
  );
15
15
  useEffect(() => {
16
16
  setValue(searchQuery || '');
@@ -148,4 +148,32 @@ describe('Hosts', () => {
148
148
  });
149
149
  expect(screen.queryAllByText('os=gnome')).toHaveLength(1);
150
150
  });
151
+
152
+ it('input fill from url', async () => {
153
+ const inputText = 'test text';
154
+ routerSelectors.selectRouterLocation.mockImplementation(() => ({
155
+ search: `feature=test_feature&inputs[plain hidden]=${inputText}`,
156
+ }));
157
+ render(
158
+ <MockedProvider mocks={gqlMock} addTypename={false}>
159
+ <Provider store={store}>
160
+ <JobWizard />
161
+ </Provider>
162
+ </MockedProvider>
163
+ );
164
+ api.get.mock.calls.forEach(call => {
165
+ if (call[0].key === 'REX_FEATURE') {
166
+ expect(call[0].url).toEqual(
167
+ '/api/remote_execution_features/test_feature'
168
+ );
169
+ }
170
+ });
171
+ await act(async () => {
172
+ fireEvent.click(screen.getByText('Target hosts and inputs'));
173
+ });
174
+ const textField = screen.getByLabelText('plain hidden', {
175
+ selector: 'textarea',
176
+ });
177
+ expect(textField.value).toBe(inputText);
178
+ });
151
179
  });
@@ -21,7 +21,7 @@ export const RepeatOn = ({
21
21
  }) => {
22
22
  const [repeatValidated, setRepeatValidated] = useState('default');
23
23
  const handleRepeatInputChange = newValue => {
24
- setRepeatValidated(newValue >= 1 ? 'default' : 'error');
24
+ setRepeatValidated(!newValue || newValue >= 1 ? 'default' : 'error');
25
25
  setRepeatAmount(newValue);
26
26
  };
27
27
 
@@ -1,9 +1,11 @@
1
1
  import React, { useEffect } from 'react';
2
- import { useSelector } from 'react-redux';
2
+ import { useSelector, useDispatch } from 'react-redux';
3
3
  import { FormGroup, TextInput, TextArea } from '@patternfly/react-core';
4
4
  import PropTypes from 'prop-types';
5
5
  import SearchBar from 'foremanReact/components/SearchBar';
6
6
  import { getControllerSearchProps } from 'foremanReact/constants';
7
+ import { TRIGGERS } from 'foremanReact/components/AutoComplete/AutoCompleteConstants';
8
+ import { getResults } from 'foremanReact/components/AutoComplete/AutoCompleteActions';
7
9
  import { helpLabel } from './FormHelpers';
8
10
  import { SelectField } from './SelectField';
9
11
  import { ResourceSelectAPI } from './ResourceSelect';
@@ -22,12 +24,25 @@ const TemplateSearchField = ({
22
24
  const searchQuery = useSelector(
23
25
  state => state.autocomplete?.[name]?.searchQuery
24
26
  );
27
+ const dispatch = useDispatch();
25
28
  useEffect(() => {
26
29
  setValue({ ...values, [name]: searchQuery });
27
30
  // eslint-disable-next-line react-hooks/exhaustive-deps
28
31
  }, [searchQuery]);
29
32
  const id = name.replace(/ /g, '-');
30
33
  const props = getControllerSearchProps(controller.replace('/', '_'), name);
34
+
35
+ const setSearch = newSearchQuery => {
36
+ dispatch(
37
+ getResults({
38
+ url,
39
+ searchQuery: newSearchQuery,
40
+ controller,
41
+ trigger: TRIGGERS.INPUT_CHANGE,
42
+ id: name,
43
+ })
44
+ );
45
+ };
31
46
  return (
32
47
  <FormGroup
33
48
  label={name}
@@ -45,9 +60,9 @@ const TemplateSearchField = ({
45
60
  url,
46
61
  useKeyShortcuts: true,
47
62
  },
48
- bookmarks: null,
49
63
  }}
50
64
  onSearch={noop}
65
+ onBookmarkClick={search => setSearch(search)}
51
66
  />
52
67
  </FormGroup>
53
68
  );
@@ -152,7 +167,7 @@ export const formatter = (input, values, setValue) => {
152
167
  key={id}
153
168
  name={name}
154
169
  defaultValue={value}
155
- controller={resourceType}
170
+ controller={controller}
156
171
  url={`/${controller}/auto_complete_search`}
157
172
  labelText={labelText}
158
173
  required={required}
@@ -0,0 +1,2 @@
1
+ const Pagination = () => jest.fn();
2
+ export default Pagination;
@@ -17,6 +17,7 @@ export const getControllerSearchProps = (
17
17
  useKeyShortcuts: true,
18
18
  },
19
19
  bookmarks: {
20
+ id,
20
21
  url: '/api/bookmarks',
21
22
  canCreate,
22
23
  documentationUrl: `4.1.5Searching`,
@@ -4,7 +4,7 @@ export const getApiUrl = (searchQuery, pagination) => {
4
4
  const baseUrl = getURI()
5
5
  .search('')
6
6
  .addQuery('page', pagination.page)
7
- .addQuery('per_page', pagination.perPage);
7
+ .addQuery('per_page', pagination.per_page);
8
8
 
9
9
  return searchQuery ? baseUrl.addQuery('search', searchQuery) : baseUrl;
10
10
  };
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import { Grid } from 'patternfly-react';
4
4
 
5
5
  import SearchBar from 'foremanReact/components/SearchBar';
6
- import Pagination from 'foremanReact/components/Pagination/PaginationWrapper';
6
+ import Pagination from 'foremanReact/components/Pagination';
7
7
  import { getControllerSearchProps } from 'foremanReact/constants';
8
8
 
9
9
  import TargetingHosts from './TargetingHosts';
@@ -15,7 +15,6 @@ const TargetingHostsPage = ({
15
15
  apiStatus,
16
16
  items,
17
17
  totalHosts,
18
- pagination,
19
18
  handlePagination,
20
19
  }) => (
21
20
  <div id="targeting_hosts">
@@ -39,11 +38,8 @@ const TargetingHostsPage = ({
39
38
  <br />
40
39
  <TargetingHosts apiStatus={apiStatus} items={items} />
41
40
  <Pagination
42
- viewType="table"
43
41
  itemCount={totalHosts}
44
- pagination={pagination}
45
42
  onChange={args => handlePagination(args)}
46
- dropdownButtonId="targeting-hosts-pagination-dropdown"
47
43
  className="targeting-hosts-pagination"
48
44
  />
49
45
  </div>
@@ -55,7 +51,6 @@ TargetingHostsPage.propTypes = {
55
51
  apiStatus: PropTypes.string,
56
52
  items: PropTypes.array.isRequired,
57
53
  totalHosts: PropTypes.number.isRequired,
58
- pagination: PropTypes.object.isRequired,
59
54
  handlePagination: PropTypes.func.isRequired,
60
55
  };
61
56
 
@@ -52,18 +52,10 @@ exports[`TargetingHostsPage renders 1`] = `
52
52
  ]
53
53
  }
54
54
  />
55
- <PaginationWrapper
55
+ <Pagination
56
56
  className="targeting-hosts-pagination"
57
- dropdownButtonId="targeting-hosts-pagination-dropdown"
58
57
  itemCount={1}
59
58
  onChange={[Function]}
60
- pagination={
61
- Object {
62
- "page": 1,
63
- "perPage": 20,
64
- }
65
- }
66
- viewType="table"
67
59
  />
68
60
  </div>
69
61
  `;
@@ -30,14 +30,14 @@ const WrappedTargetingHosts = () => {
30
30
  const [searchQuery, setSearchQuery] = useState('');
31
31
  const [pagination, setPagination] = useState({
32
32
  page: 1,
33
- perPage,
33
+ per_page: perPage,
34
34
  perPageOptions,
35
35
  });
36
36
  const [apiUrl, setApiUrl] = useState(getApiUrl(searchQuery, pagination));
37
37
  const intervalExists = useSelector(selectIntervalExists);
38
38
 
39
39
  const handleSearch = query => {
40
- const defaultPagination = { page: 1, perPage: pagination.perPage };
40
+ const defaultPagination = { page: 1, per_page: pagination.per_page };
41
41
  stopApiInterval();
42
42
 
43
43
  setApiUrl(getApiUrl(query, defaultPagination));
@@ -88,7 +88,6 @@ const WrappedTargetingHosts = () => {
88
88
  apiStatus={apiStatus}
89
89
  items={items}
90
90
  totalHosts={totalHosts}
91
- pagination={pagination}
92
91
  handlePagination={handlePagination}
93
92
  />
94
93
  );
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_remote_execution
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Foreman Remote Execution team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-16 00:00:00.000000000 Z
11
+ date: 2022-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -263,7 +263,6 @@ files:
263
263
  - app/views/template_invocations/_refresh.js.erb
264
264
  - app/views/template_invocations/show.html.erb
265
265
  - app/views/template_invocations/show.js.erb
266
- - app/views/templates/README.md
267
266
  - app/views/templates/ssh/check_update.erb
268
267
  - app/views/templates/ssh/module_action.erb
269
268
  - app/views/templates/ssh/package_action.erb
@@ -463,7 +462,7 @@ files:
463
462
  - webpack/__mocks__/foremanReact/common/helpers.js
464
463
  - webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteActions.js
465
464
  - webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteConstants.js
466
- - webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js
465
+ - webpack/__mocks__/foremanReact/components/Pagination.js
467
466
  - webpack/__mocks__/foremanReact/components/SearchBar.js
468
467
  - webpack/__mocks__/foremanReact/components/common/ActionButtons/ActionButtons.js
469
468
  - webpack/__mocks__/foremanReact/constants.js
@@ -1,6 +0,0 @@
1
- # Job Templates
2
-
3
- **IMPORTANT** Do not submit pull requests here, these templates are only
4
- updated during the release process. The
5
- [community-templates](https://github.com/theforeman/community-templates) repos
6
- is the canonical source for job templates.
@@ -1,2 +0,0 @@
1
- const PaginationWrapper = () => jest.fn();
2
- export default PaginationWrapper;