foreman_remote_execution 6.2.0 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/job_invocations_controller.rb +1 -0
  3. data/app/helpers/hosts_extensions_helper.rb +62 -0
  4. data/app/lib/actions/remote_execution/run_host_job.rb +4 -0
  5. data/app/lib/actions/remote_execution/run_hosts_job.rb +4 -0
  6. data/app/models/job_invocation_composer.rb +6 -2
  7. data/app/models/job_template.rb +4 -1
  8. data/app/models/ssh_execution_provider.rb +3 -3
  9. data/app/views/api/v2/job_invocations/base.json.rabl +1 -1
  10. data/app/views/job_invocations/_card_target_hosts.html.erb +8 -0
  11. data/app/views/job_invocations/_form.html.erb +2 -0
  12. data/db/migrate/20220331112719_add_ssh_user_to_job_invocation.rb +5 -0
  13. data/lib/foreman_remote_execution/engine.rb +6 -3
  14. data/lib/foreman_remote_execution/version.rb +1 -1
  15. data/locale/action_names.rb +3 -3
  16. data/locale/de/foreman_remote_execution.po +23 -23
  17. data/locale/en/foreman_remote_execution.po +23 -23
  18. data/locale/en_GB/foreman_remote_execution.po +23 -23
  19. data/locale/es/foreman_remote_execution.po +23 -23
  20. data/locale/foreman_remote_execution.pot +64 -66
  21. data/locale/fr/foreman_remote_execution.po +23 -23
  22. data/locale/ja/foreman_remote_execution.po +23 -23
  23. data/locale/ko/foreman_remote_execution.po +23 -23
  24. data/locale/pt_BR/foreman_remote_execution.po +23 -23
  25. data/locale/ru/foreman_remote_execution.po +23 -23
  26. data/locale/zh_CN/foreman_remote_execution.po +23 -23
  27. data/locale/zh_TW/foreman_remote_execution.po +23 -23
  28. data/webpack/JobWizard/JobWizardConstants.js +2 -2
  29. data/webpack/JobWizard/__tests__/fixtures.js +8 -4
  30. data/webpack/JobWizard/steps/AdvancedFields/__tests__/AdvancedFields.test.js +2 -2
  31. data/webpack/JobWizard/steps/HostsAndInputs/SelectGQL.js +2 -1
  32. data/webpack/JobWizard/steps/HostsAndInputs/SelectedChips.js +1 -1
  33. data/webpack/JobWizard/steps/HostsAndInputs/buildHostQuery.js +1 -1
  34. data/webpack/JobWizard/steps/HostsAndInputs/hostgroups.gql +1 -0
  35. data/webpack/JobWizard/steps/HostsAndInputs/hosts.gql +1 -0
  36. data/webpack/JobWizard/steps/ReviewDetails/index.js +1 -1
  37. data/webpack/JobWizard/steps/Schedule/__tests__/Schedule.test.js +15 -15
  38. data/webpack/JobWizard/steps/form/SearchSelect.js +0 -1
  39. data/webpack/__mocks__/foremanReact/common/globalIdHelpers.js +1 -0
  40. data/webpack/global_index.js +2 -8
  41. data/webpack/react_app/components/HostKebab/KebabItems.js +6 -1
  42. data/webpack/react_app/components/RecentJobsCard/RecentJobsCard.js +4 -4
  43. data/webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js +1 -0
  44. data/webpack/react_app/components/TargetingHosts/TargetingHostsPage.js +8 -3
  45. data/webpack/react_app/components/TargetingHosts/__tests__/__snapshots__/TargetingHostsPage.test.js.snap +9 -1
  46. data/webpack/react_app/components/TargetingHosts/__tests__/fixtures.js +1 -4
  47. data/webpack/react_app/components/TargetingHosts/index.js +1 -0
  48. data/webpack/react_app/extend/Fills.js +48 -0
  49. metadata +6 -7
  50. data/app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb +0 -62
  51. data/webpack/react_app/extend/fillKebabItems.js +0 -11
  52. data/webpack/react_app/extend/fillRecentJobsCard.js +0 -11
  53. data/webpack/react_app/extend/fillRexFeaturesDropdown.js +0 -11
  54. data/webpack/react_app/extend/fillregistrationAdvanced.js +0 -11
@@ -23,6 +23,9 @@ msgstr "%s"
23
23
  msgid "%s ago"
24
24
  msgstr "%s 之前"
25
25
 
26
+ msgid "%s job has been invoked"
27
+ msgstr ""
28
+
26
29
  msgid "%{description} on %{host}"
27
30
  msgstr "%{description} 於 %{host} 之上"
28
31
 
@@ -67,15 +70,15 @@ msgstr "要使用執行這 script 的使用者。如果使用者與 SSH 使用
67
70
  msgid "Abort Job"
68
71
  msgstr ""
69
72
 
73
+ msgid "Action with sub plans"
74
+ msgstr ""
75
+
70
76
  msgid "Actions"
71
77
  msgstr "動作"
72
78
 
73
79
  msgid "Add Foreign Input Set"
74
80
  msgstr "新增外部輸入集"
75
81
 
76
- msgid "Advanced Fields"
77
- msgstr ""
78
-
79
82
  msgid "Advanced fields"
80
83
  msgstr ""
81
84
 
@@ -466,9 +469,15 @@ msgstr ""
466
469
  msgid "Import"
467
470
  msgstr "匯入"
468
471
 
472
+ msgid "Import Puppet classes"
473
+ msgstr ""
474
+
469
475
  msgid "Import a job template from ERB"
470
476
  msgstr ""
471
477
 
478
+ msgid "Import facts"
479
+ msgstr ""
480
+
472
481
  msgid "Include all inputs from the foreign template"
473
482
  msgstr ""
474
483
 
@@ -502,9 +511,6 @@ msgstr "祈願類型,%s 之一"
502
511
  msgid "Job"
503
512
  msgstr "工作"
504
513
 
505
- msgid "Job Category"
506
- msgstr ""
507
-
508
514
  msgid "Job Details"
509
515
  msgstr ""
510
516
 
@@ -826,7 +832,7 @@ msgstr "解析至"
826
832
  msgid "Results"
827
833
  msgstr ""
828
834
 
829
- msgid "Review Details"
835
+ msgid "Review details"
830
836
  msgstr ""
831
837
 
832
838
  msgid "Run"
@@ -850,9 +856,6 @@ msgstr ""
850
856
  msgid "Running"
851
857
  msgstr ""
852
858
 
853
- msgid "SSH"
854
- msgstr "SSH"
855
-
856
859
  msgid "SSH Port"
857
860
  msgstr ""
858
861
 
@@ -868,6 +871,9 @@ msgstr "排程"
868
871
  msgid "Schedule Remote Job"
869
872
  msgstr ""
870
873
 
874
+ msgid "Schedule a job"
875
+ msgstr ""
876
+
871
877
  msgid "Schedule for future execution"
872
878
  msgstr ""
873
879
 
@@ -889,6 +895,9 @@ msgstr ""
889
895
  msgid "Scheduled to start before"
890
896
  msgstr ""
891
897
 
898
+ msgid "Script"
899
+ msgstr ""
900
+
892
901
  msgid "Scroll to bottom"
893
902
  msgstr "捲動至底端"
894
903
 
@@ -1209,16 +1218,16 @@ msgstr "使用者輸入"
1209
1218
  msgid "Value"
1210
1219
  msgstr "值"
1211
1220
 
1212
- msgid "View All Jobs"
1221
+ msgid "View all jobs"
1213
1222
  msgstr ""
1214
1223
 
1215
- msgid "View Finished Jobs"
1224
+ msgid "View finished jobs"
1216
1225
  msgstr ""
1217
1226
 
1218
- msgid "View Running Jobs"
1227
+ msgid "View running jobs"
1219
1228
  msgstr ""
1220
1229
 
1221
- msgid "View Scheduled Jobs"
1230
+ msgid "View scheduled jobs"
1222
1231
  msgstr ""
1223
1232
 
1224
1233
  msgid "Web Console"
@@ -1364,12 +1373,3 @@ msgstr ""
1364
1373
 
1365
1374
  msgid "using Smart Proxy"
1366
1375
  msgstr ""
1367
-
1368
- msgid "»Action with sub plans«"
1369
- msgstr ""
1370
-
1371
- msgid "»Import Puppet classes«"
1372
- msgstr ""
1373
-
1374
- msgid "»Import facts«"
1375
- msgstr ""
@@ -19,9 +19,9 @@ export const repeatTypes = {
19
19
  export const WIZARD_TITLES = {
20
20
  categoryAndTemplate: __('Category and Template'),
21
21
  hostsAndInputs: __('Target hosts and inputs'),
22
- advanced: __('Advanced Fields'),
22
+ advanced: __('Advanced fields'),
23
23
  schedule: __('Schedule'),
24
- review: __('Review Details'),
24
+ review: __('Review details'),
25
25
  };
26
26
 
27
27
  export const initialScheduleState = {
@@ -193,7 +193,11 @@ export const gqlMock = [
193
193
  data: {
194
194
  hosts: {
195
195
  totalCount: 3,
196
- nodes: [{ name: 'host1' }, { name: 'host2' }, { name: 'host3' }],
196
+ nodes: [
197
+ { id: 'MDE6SG9zdC0x', name: 'host1' },
198
+ { id: 'MDE6SG9zdC0y', name: 'host2' },
199
+ { id: 'MDE6SG9zdC0z', name: 'host3' },
200
+ ],
197
201
  },
198
202
  },
199
203
  },
@@ -211,9 +215,9 @@ export const gqlMock = [
211
215
  hostgroups: {
212
216
  totalCount: 3,
213
217
  nodes: [
214
- { name: 'host_group1' },
215
- { name: 'host_group2' },
216
- { name: 'host_group3' },
218
+ { id: 'MDE6SG9zdGdyb3VwLTE=', name: 'host_group1' },
219
+ { id: 'MDE6SG9zdGdyb3VwLTI=', name: 'host_group2' },
220
+ { id: 'MDE6SG9zdGdyb3VwLTM=', name: 'host_group3' },
217
221
  ],
218
222
  },
219
223
  },
@@ -143,7 +143,7 @@ describe('AdvancedFields', () => {
143
143
  );
144
144
 
145
145
  await act(async () => {
146
- fireEvent.click(screen.getByText('Advanced Fields'));
146
+ fireEvent.click(screen.getByText('Advanced fields'));
147
147
  });
148
148
  expect(textField.value).toBe(textValue);
149
149
  expect(searchField.value).toBe(searchValue);
@@ -162,7 +162,7 @@ describe('AdvancedFields', () => {
162
162
  </MockedProvider>
163
163
  );
164
164
  await act(async () => {
165
- fireEvent.click(screen.getByText('Advanced Fields'));
165
+ fireEvent.click(screen.getByText('Advanced fields'));
166
166
  });
167
167
 
168
168
  expect(
@@ -5,6 +5,7 @@ import {
5
5
  useForemanOrganization,
6
6
  useForemanLocation,
7
7
  } from 'foremanReact/Root/Context/ForemanContext';
8
+ import { decodeId } from 'foremanReact/common/globalIdHelpers';
8
9
  import { HOSTS, HOST_GROUPS, dataName } from '../../JobWizardConstants';
9
10
  import { SearchSelect } from '../form/SearchSelect';
10
11
  import hostsQuery from './hosts.gql';
@@ -35,7 +36,7 @@ export const useNameSearchGQL = apiKey => {
35
36
  subtotal: data?.[dataName[apiKey]]?.totalCount,
36
37
  results:
37
38
  data?.[dataName[apiKey]]?.nodes.map(node => ({
38
- id: node.name,
39
+ id: decodeId(node.id),
39
40
  name: node.name,
40
41
  })) || [],
41
42
  },
@@ -15,7 +15,7 @@ const SelectedChip = ({ selected, setSelected, categoryName }) => {
15
15
  {selected.map(({ name, id }, index) => (
16
16
  <Chip
17
17
  key={index}
18
- id={id}
18
+ id={`${categoryName}-${id}`}
19
19
  onClick={() => deleteItem(id)}
20
20
  closeBtnAriaLabel={`Close ${name}`}
21
21
  >
@@ -1,6 +1,6 @@
1
1
  export const buildHostQuery = (selected, search) => {
2
2
  const { hosts, hostCollections, hostGroups } = selected;
3
- const hostsSearch = `(name ^ (${hosts.map(({ id }) => id).join(',')}))`;
3
+ const hostsSearch = `(id ^ (${hosts.map(({ id }) => id).join(',')}))`;
4
4
  const hostCollectionsSearch = `(host_collection_id ^ (${hostCollections
5
5
  .map(({ id }) => id)
6
6
  .join(',')}))`;
@@ -2,6 +2,7 @@ query($search: String!) {
2
2
  hostgroups(first: 100, last: 100, search: $search) {
3
3
  totalCount
4
4
  nodes {
5
+ id
5
6
  name
6
7
  }
7
8
  }
@@ -2,6 +2,7 @@ query($search: String!) {
2
2
  hosts(first: 100, last: 100, search: $search) {
3
3
  totalCount
4
4
  nodes {
5
+ id
5
6
  name
6
7
  }
7
8
  }
@@ -72,7 +72,7 @@ const ReviewDetails = ({
72
72
  };
73
73
  const [isAdvancedShown, setIsAdvancedShown] = useState(false);
74
74
  const detailsFirstHalf = [
75
- { label: __('Job Category'), value: jobCategory },
75
+ { label: __('Job category'), value: jobCategory },
76
76
  { label: __('Job template'), value: jobTemplate },
77
77
  { label: __('Target hosts'), value: stringHosts() },
78
78
  ...templateInputs.map(({ name }) => ({
@@ -186,7 +186,7 @@ describe('Schedule', () => {
186
186
  expect(
187
187
  screen.getByPlaceholderText('Repeat N times').hasAttribute('disabled')
188
188
  ).toBeTruthy();
189
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
189
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
190
190
  await act(async () => {
191
191
  fireEvent.click(
192
192
  screen.getByLabelText('Does not repeat', { selector: 'button' })
@@ -196,7 +196,7 @@ describe('Schedule', () => {
196
196
  await act(async () => {
197
197
  fireEvent.click(screen.getByText('Cronline'));
198
198
  });
199
- expect(screen.getByText('Review Details').disabled).toBeTruthy();
199
+ expect(screen.getByText('Review details').disabled).toBeTruthy();
200
200
  const newRepeatTimes = '3';
201
201
  const repeatNTimes = screen.getByPlaceholderText('Repeat N times');
202
202
  expect(repeatNTimes.value).toBe('');
@@ -216,7 +216,7 @@ describe('Schedule', () => {
216
216
  });
217
217
  });
218
218
  expect(cronline.value).toBe(newCronline);
219
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
219
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
220
220
 
221
221
  await act(async () => {
222
222
  fireEvent.click(screen.getByText('Category and Template'));
@@ -236,7 +236,7 @@ describe('Schedule', () => {
236
236
  fireEvent.click(screen.getByText('Monthly'));
237
237
  });
238
238
 
239
- expect(screen.getByText('Review Details').disabled).toBeTruthy();
239
+ expect(screen.getByText('Review details').disabled).toBeTruthy();
240
240
  const newDays = '1,2,3';
241
241
  const days = screen.getByLabelText('days');
242
242
  expect(days.value).toBe('');
@@ -248,7 +248,7 @@ describe('Schedule', () => {
248
248
  });
249
249
  expect(days.value).toBe(newDays);
250
250
 
251
- expect(screen.getByText('Review Details').disabled).toBeTruthy();
251
+ expect(screen.getByText('Review details').disabled).toBeTruthy();
252
252
  const newAtMonthly = '13:07';
253
253
  const at = () => screen.getByLabelText('repeat-at');
254
254
  expect(at().value).toBe('');
@@ -259,13 +259,13 @@ describe('Schedule', () => {
259
259
  });
260
260
  expect(at().value).toBe(newAtMonthly);
261
261
 
262
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
262
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
263
263
  fireEvent.click(screen.getByText('Monthly'));
264
264
  await act(async () => {
265
265
  fireEvent.click(screen.getByText('Weekly'));
266
266
  });
267
267
 
268
- expect(screen.getByText('Review Details').disabled).toBeTruthy();
268
+ expect(screen.getByText('Review details').disabled).toBeTruthy();
269
269
  const dayTue = screen.getByLabelText('Tue checkbox');
270
270
  const daySat = screen.getByLabelText('Sat checkbox');
271
271
  expect(dayTue.checked).toBe(false);
@@ -293,19 +293,19 @@ describe('Schedule', () => {
293
293
  });
294
294
  expect(at().value).toBe(newAtWeekly);
295
295
 
296
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
296
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
297
297
  fireEvent.click(screen.getByText('Weekly'));
298
298
  await act(async () => {
299
299
  fireEvent.click(screen.getByText('Daily'));
300
300
  });
301
301
 
302
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
302
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
303
303
  await act(async () => {
304
304
  fireEvent.change(at(), {
305
305
  target: { value: '' },
306
306
  });
307
307
  });
308
- expect(screen.getByText('Review Details').disabled).toBeTruthy();
308
+ expect(screen.getByText('Review details').disabled).toBeTruthy();
309
309
  const newAtDaily = '17:07';
310
310
  expect(at().value).toBe('');
311
311
  await act(async () => {
@@ -314,14 +314,14 @@ describe('Schedule', () => {
314
314
  });
315
315
  });
316
316
  expect(at().value).toBe(newAtDaily);
317
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
317
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
318
318
 
319
319
  fireEvent.click(screen.getByText('Daily'));
320
320
  await act(async () => {
321
321
  fireEvent.click(screen.getByText('Hourly'));
322
322
  });
323
323
 
324
- expect(screen.getByText('Review Details').disabled).toBeTruthy();
324
+ expect(screen.getByText('Review details').disabled).toBeTruthy();
325
325
  const newMinutes = '6';
326
326
  const atHourly = screen.getByLabelText('repeat-at-minute-typeahead');
327
327
  expect(atHourly.value).toBe('');
@@ -331,7 +331,7 @@ describe('Schedule', () => {
331
331
  await act(async () => {
332
332
  fireEvent.click(screen.getByText(newMinutes));
333
333
  });
334
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
334
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
335
335
  expect(atHourly.value).toBe(newMinutes);
336
336
  });
337
337
  it('should show invalid error on start date after end', async () => {
@@ -353,7 +353,7 @@ describe('Schedule', () => {
353
353
  expect(
354
354
  screen.queryAllByText('End time needs to be after start time')
355
355
  ).toHaveLength(0);
356
- expect(screen.getByText('Review Details').disabled).toBeFalsy();
356
+ expect(screen.getByText('Review details').disabled).toBeFalsy();
357
357
  await act(async () => {
358
358
  await fireEvent.change(startsDateField, {
359
359
  target: { value: '2020/10/15' },
@@ -368,7 +368,7 @@ describe('Schedule', () => {
368
368
  screen.queryAllByText('End time needs to be after start time')
369
369
  ).toHaveLength(1);
370
370
 
371
- expect(screen.getByText('Review Details').disabled).toBeTruthy();
371
+ expect(screen.getByText('Review details').disabled).toBeTruthy();
372
372
  });
373
373
  it('purpose and ends should be disabled when no reaccurence ', async () => {
374
374
  render(
@@ -93,7 +93,6 @@ export const SearchSelect = ({
93
93
  autoSearch(value || '');
94
94
  }}
95
95
  placeholderText={placeholderText}
96
- onFilter={() => null} // https://github.com/patternfly/patternfly-react/issues/6321
97
96
  typeAheadAriaLabel={`${name} typeahead input`}
98
97
  >
99
98
  {selectOptions}
@@ -0,0 +1 @@
1
+ export const decodeId = whatever => whatever;
@@ -1,14 +1,8 @@
1
1
  import { registerRoutes } from 'foremanReact/routes/RoutingService';
2
2
  import routes from './Routes/routes';
3
- import fillregistrationAdvanced from './react_app/extend/fillregistrationAdvanced';
4
- import fillRecentJobsCard from './react_app/extend/fillRecentJobsCard';
5
- import fillFeaturesDropdown from './react_app/extend/fillRexFeaturesDropdown';
6
- import fillKebabItems from './react_app/extend/fillKebabItems';
7
3
  import registerReducers from './react_app/extend/reducers';
4
+ import registerFills from './react_app/extend/Fills';
8
5
 
9
6
  registerReducers();
10
7
  registerRoutes('foreman_remote_execution', routes);
11
- fillFeaturesDropdown();
12
- fillRecentJobsCard();
13
- fillregistrationAdvanced();
14
- fillKebabItems();
8
+ registerFills();
@@ -13,7 +13,12 @@ const HostKebabItems = () => {
13
13
 
14
14
  if (!consoleUrl) return null;
15
15
  return (
16
- <DropdownItem icon={<CodeIcon />} href={consoleUrl}>
16
+ <DropdownItem
17
+ icon={<CodeIcon />}
18
+ href={consoleUrl}
19
+ target="_blank"
20
+ rel="noreferrer"
21
+ >
17
22
  {__('Web Console')}
18
23
  </DropdownItem>
19
24
  );
@@ -28,7 +28,7 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
28
28
  href={foremanUrl(`${JOB_BASE_URL}${name}`)}
29
29
  key="link-to-all"
30
30
  >
31
- {__('View All Jobs')}
31
+ {__('View all jobs')}
32
32
  </DropdownItem>,
33
33
  <DropdownItem
34
34
  href={foremanUrl(
@@ -36,19 +36,19 @@ const RecentJobsCard = ({ hostDetails: { name, id } }) => {
36
36
  )}
37
37
  key="link-to-finished"
38
38
  >
39
- {__('View Finished Jobs')}
39
+ {__('View finished jobs')}
40
40
  </DropdownItem>,
41
41
  <DropdownItem
42
42
  href={foremanUrl(`${JOB_BASE_URL}${name}+and+status+%3D+running`)}
43
43
  key="link-to-running"
44
44
  >
45
- {__('View Running Jobs')}
45
+ {__('View running jobs')}
46
46
  </DropdownItem>,
47
47
  <DropdownItem
48
48
  href={foremanUrl(`${JOB_BASE_URL}${name}+and+status+%3D+queued`)}
49
49
  key="link-to-scheduled"
50
50
  >
51
- {__('View Scheduled Jobs')}
51
+ {__('View scheduled jobs')}
52
52
  </DropdownItem>,
53
53
  ]}
54
54
  >
@@ -1 +1,2 @@
1
1
  export const TARGETING_HOSTS = 'TARGETING_HOSTS';
2
+ export const TARGETING_HOSTS_AUTOCOMPLETE = 'targeting_hosts_search';
@@ -7,6 +7,7 @@ import Pagination from 'foremanReact/components/Pagination';
7
7
  import { getControllerSearchProps } from 'foremanReact/constants';
8
8
 
9
9
  import TargetingHosts from './TargetingHosts';
10
+ import { TARGETING_HOSTS_AUTOCOMPLETE } from './TargetingHostsConsts';
10
11
  import './TargetingHostsPage.scss';
11
12
 
12
13
  const TargetingHostsPage = ({
@@ -16,6 +17,7 @@ const TargetingHostsPage = ({
16
17
  items,
17
18
  totalHosts,
18
19
  handlePagination,
20
+ page,
19
21
  }) => (
20
22
  <div id="targeting_hosts">
21
23
  <Grid.Row>
@@ -23,24 +25,26 @@ const TargetingHostsPage = ({
23
25
  <SearchBar
24
26
  onSearch={query => handleSearch(query)}
25
27
  data={{
26
- ...getControllerSearchProps('hosts'),
28
+ ...getControllerSearchProps('hosts', TARGETING_HOSTS_AUTOCOMPLETE),
27
29
  autocomplete: {
28
- id: 'targeting_hosts_search',
30
+ id: TARGETING_HOSTS_AUTOCOMPLETE,
29
31
  searchQuery,
30
32
  url: '/hosts/auto_complete_search',
31
33
  useKeyShortcuts: true,
32
34
  },
33
- bookmarks: {},
34
35
  }}
36
+ onBookmarkClick={handleSearch}
35
37
  />
36
38
  </Grid.Col>
37
39
  </Grid.Row>
38
40
  <br />
39
41
  <TargetingHosts apiStatus={apiStatus} items={items} />
40
42
  <Pagination
43
+ page={page}
41
44
  itemCount={totalHosts}
42
45
  onChange={args => handlePagination(args)}
43
46
  className="targeting-hosts-pagination"
47
+ updateParamsByUrl={false}
44
48
  />
45
49
  </div>
46
50
  );
@@ -52,6 +56,7 @@ TargetingHostsPage.propTypes = {
52
56
  items: PropTypes.array.isRequired,
53
57
  totalHosts: PropTypes.number.isRequired,
54
58
  handlePagination: PropTypes.func.isRequired,
59
+ page: PropTypes.number.isRequired,
55
60
  };
56
61
 
57
62
  TargetingHostsPage.defaultProps = {
@@ -23,10 +23,16 @@ exports[`TargetingHostsPage renders 1`] = `
23
23
  "url": "/hosts/auto_complete_search",
24
24
  "useKeyShortcuts": true,
25
25
  },
26
- "bookmarks": Object {},
26
+ "bookmarks": Object {
27
+ "canCreate": true,
28
+ "documentationUrl": "4.1.5Searching",
29
+ "id": "targeting_hosts_search",
30
+ "url": "/api/bookmarks",
31
+ },
27
32
  "controller": "hosts",
28
33
  }
29
34
  }
35
+ onBookmarkClick={[Function]}
30
36
  onChange={[Function]}
31
37
  onSearch={[Function]}
32
38
  />
@@ -56,6 +62,8 @@ exports[`TargetingHostsPage renders 1`] = `
56
62
  className="targeting-hosts-pagination"
57
63
  itemCount={1}
58
64
  onChange={[Function]}
65
+ page={1}
66
+ updateParamsByUrl={false}
59
67
  />
60
68
  </div>
61
69
  `;
@@ -50,10 +50,7 @@ export const TargetingHostsPageFixtures = {
50
50
  apiStatus: 'RESOLVED',
51
51
  items,
52
52
  totalHosts: 1,
53
- pagination: {
54
- page: 1,
55
- perPage: 20,
56
- },
53
+ page: 1,
57
54
  handlePagination: () => {},
58
55
  },
59
56
  };
@@ -89,6 +89,7 @@ const WrappedTargetingHosts = () => {
89
89
  items={items}
90
90
  totalHosts={totalHosts}
91
91
  handlePagination={handlePagination}
92
+ page={pagination.page}
92
93
  />
93
94
  );
94
95
  };
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
3
+
4
+ import FeaturesDropdown from '../components/FeaturesDropdown';
5
+ import RexInterface from '../components/RegistrationExtension/RexInterface';
6
+ import RecentJobsCard from '../components/RecentJobsCard';
7
+ import KebabItems from '../components/HostKebab/KebabItems';
8
+
9
+ const fills = [
10
+ {
11
+ slot: 'host-details-kebab',
12
+ name: 'kebab-items',
13
+ component: props => <KebabItems {...props} />,
14
+ weight: 500,
15
+ },
16
+ {
17
+ slot: 'host-overview-cards',
18
+ name: 'latest-jobs',
19
+ component: props => <RecentJobsCard {...props} />,
20
+ weight: 500,
21
+ },
22
+ {
23
+ slot: 'registrationAdvanced',
24
+ name: 'interface',
25
+ component: props => <RexInterface {...props} />,
26
+ weight: 500,
27
+ },
28
+ {
29
+ slot: '_rex-host-features',
30
+ name: '_rex-host-features',
31
+ component: props => <FeaturesDropdown {...props} />,
32
+ weight: 1000,
33
+ },
34
+ ];
35
+
36
+ const registerFills = () => {
37
+ fills.forEach(({ slot, id, component: Component, weight, metadata }) =>
38
+ addGlobalFill(
39
+ slot,
40
+ id,
41
+ <Component key={`rex-fill-${id}`} />,
42
+ weight,
43
+ metadata
44
+ )
45
+ );
46
+ };
47
+
48
+ export default registerFills;
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: 6.2.0
4
+ version: 7.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: 2022-04-19 00:00:00.000000000 Z
11
+ date: 2022-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deface
@@ -142,8 +142,8 @@ files:
142
142
  - app/graphql/types/recurrence_input.rb
143
143
  - app/graphql/types/scheduling_input.rb
144
144
  - app/graphql/types/targeting_enum.rb
145
- - app/helpers/concerns/foreman_remote_execution/hosts_helper_extensions.rb
146
145
  - app/helpers/concerns/foreman_remote_execution/job_templates_extensions.rb
146
+ - app/helpers/hosts_extensions_helper.rb
147
147
  - app/helpers/job_invocation_output_helper.rb
148
148
  - app/helpers/job_invocations_chart_helper.rb
149
149
  - app/helpers/job_invocations_helper.rb
@@ -323,6 +323,7 @@ files:
323
323
  - db/migrate/2021051713291621250977_add_host_proxy_invocations.rb
324
324
  - db/migrate/20210816100932_rex_setting_category_to_dsl.rb
325
325
  - db/migrate/20220321101835_rename_ssh_provider_to_script.rb
326
+ - db/migrate/20220331112719_add_ssh_user_to_job_invocation.rb
326
327
  - db/seeds.d/100-assign_features_with_templates.rb
327
328
  - db/seeds.d/20-permissions.rb
328
329
  - db/seeds.d/50-notification_blueprints.rb
@@ -462,6 +463,7 @@ files:
462
463
  - webpack/Routes/routes.js
463
464
  - webpack/__mocks__/foremanReact/Root/Context/ForemanContext/index.js
464
465
  - webpack/__mocks__/foremanReact/common/I18n.js
466
+ - webpack/__mocks__/foremanReact/common/globalIdHelpers.js
465
467
  - webpack/__mocks__/foremanReact/common/helpers.js
466
468
  - webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteActions.js
467
469
  - webpack/__mocks__/foremanReact/components/AutoComplete/AutoCompleteConstants.js
@@ -514,10 +516,7 @@ files:
514
516
  - webpack/react_app/components/jobInvocations/AggregateStatus/index.js
515
517
  - webpack/react_app/components/jobInvocations/AggregateStatus/index.test.js
516
518
  - webpack/react_app/components/jobInvocations/index.js
517
- - webpack/react_app/extend/fillKebabItems.js
518
- - webpack/react_app/extend/fillRecentJobsCard.js
519
- - webpack/react_app/extend/fillRexFeaturesDropdown.js
520
- - webpack/react_app/extend/fillregistrationAdvanced.js
519
+ - webpack/react_app/extend/Fills.js
521
520
  - webpack/react_app/extend/reducers.js
522
521
  - webpack/react_app/redux/actions/jobInvocations/index.js
523
522
  - webpack/react_app/redux/consts.js