foreman_ansible 7.0.3 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/ansible_playbooks_controller.rb +66 -0
  3. data/app/controllers/foreman_ansible/api/v2/hostgroups_controller_extensions.rb +5 -1
  4. data/app/controllers/foreman_ansible/api/v2/hosts_controller_extensions.rb +3 -1
  5. data/app/graphql/presenters/ansible_role_presenter.rb +4 -0
  6. data/app/graphql/types/ansible_role.rb +1 -0
  7. data/app/graphql/types/inherited_ansible_role.rb +4 -0
  8. data/app/helpers/foreman_ansible/hosts_helper.rb +19 -0
  9. data/app/jobs/sync_playbooks.rb +25 -0
  10. data/app/lib/proxy_api/ansible.rb +13 -0
  11. data/app/services/foreman_ansible/import_playbooks_error_notification.rb +38 -0
  12. data/app/services/foreman_ansible/import_playbooks_success_notification.rb +33 -0
  13. data/app/services/foreman_ansible/playbooks_importer.rb +73 -0
  14. data/app/services/foreman_ansible/proxy_api.rb +3 -4
  15. data/app/services/foreman_ansible/variables_importer.rb +9 -9
  16. data/app/views/ansible_roles/index.html.erb +2 -0
  17. data/app/views/api/v2/ansible_playbooks/sync.json.rabl +5 -0
  18. data/app/views/api/v2/hostgroups/ansible_roles.json.rabl +9 -1
  19. data/app/views/api/v2/hosts/ansible_roles.json.rabl +9 -1
  20. data/app/views/foreman_ansible/job_templates/ansible_roles_-_install_from_git.erb +4 -1
  21. data/app/views/foreman_ansible/job_templates/ansible_windows_updates.erb +160 -0
  22. data/config/routes.rb +10 -3
  23. data/db/seeds.d/90_notification_blueprints.rb +14 -0
  24. data/lib/foreman_ansible/engine.rb +0 -1
  25. data/lib/foreman_ansible/register.rb +9 -3
  26. data/lib/foreman_ansible/remote_execution.rb +0 -6
  27. data/lib/foreman_ansible/version.rb +1 -1
  28. data/locale/action_names.rb +4 -3
  29. data/locale/ca/foreman_ansible.edit.po +1162 -0
  30. data/locale/ca/foreman_ansible.po +360 -45
  31. data/{webpack/components/withPagination.js → locale/ca/foreman_ansible.po.time_stamp} +0 -0
  32. data/locale/cs_CZ/foreman_ansible.edit.po +1207 -0
  33. data/locale/cs_CZ/foreman_ansible.po +372 -57
  34. data/locale/cs_CZ/foreman_ansible.po.time_stamp +0 -0
  35. data/locale/de/foreman_ansible.edit.po +1148 -0
  36. data/locale/de/foreman_ansible.po +355 -40
  37. data/locale/de/foreman_ansible.po.time_stamp +0 -0
  38. data/locale/en/foreman_ansible.edit.po +1146 -0
  39. data/locale/en/foreman_ansible.po +355 -40
  40. data/locale/en/foreman_ansible.po.time_stamp +0 -0
  41. data/locale/en_GB/foreman_ansible.edit.po +1155 -0
  42. data/locale/en_GB/foreman_ansible.po +357 -42
  43. data/locale/en_GB/foreman_ansible.po.time_stamp +0 -0
  44. data/locale/es/foreman_ansible.edit.po +1148 -0
  45. data/locale/es/foreman_ansible.po +355 -40
  46. data/locale/es/foreman_ansible.po.time_stamp +0 -0
  47. data/locale/foreman_ansible.pot +767 -263
  48. data/locale/fr/foreman_ansible.edit.po +1148 -0
  49. data/locale/fr/foreman_ansible.po +355 -40
  50. data/locale/fr/foreman_ansible.po.time_stamp +0 -0
  51. data/locale/gl/foreman_ansible.edit.po +1156 -0
  52. data/locale/gl/foreman_ansible.po +358 -43
  53. data/locale/gl/foreman_ansible.po.time_stamp +0 -0
  54. data/locale/it/foreman_ansible.edit.po +1148 -0
  55. data/locale/it/foreman_ansible.po +355 -40
  56. data/locale/it/foreman_ansible.po.time_stamp +0 -0
  57. data/locale/ja/foreman_ansible.edit.po +1148 -0
  58. data/locale/ja/foreman_ansible.po +355 -40
  59. data/locale/ja/foreman_ansible.po.time_stamp +0 -0
  60. data/locale/ko/foreman_ansible.edit.po +1148 -0
  61. data/locale/ko/foreman_ansible.po +355 -40
  62. data/locale/ko/foreman_ansible.po.time_stamp +0 -0
  63. data/locale/nl_NL/foreman_ansible.edit.po +1168 -0
  64. data/locale/nl_NL/foreman_ansible.po +359 -44
  65. data/locale/nl_NL/foreman_ansible.po.time_stamp +0 -0
  66. data/locale/pl/foreman_ansible.edit.po +1180 -0
  67. data/locale/pl/foreman_ansible.po +363 -48
  68. data/locale/pl/foreman_ansible.po.time_stamp +0 -0
  69. data/locale/pt_BR/foreman_ansible.edit.po +1148 -0
  70. data/locale/pt_BR/foreman_ansible.po +355 -40
  71. data/locale/pt_BR/foreman_ansible.po.time_stamp +0 -0
  72. data/locale/ru/foreman_ansible.edit.po +1149 -0
  73. data/locale/ru/foreman_ansible.po +355 -40
  74. data/locale/ru/foreman_ansible.po.time_stamp +0 -0
  75. data/locale/sv_SE/foreman_ansible.edit.po +1180 -0
  76. data/locale/sv_SE/foreman_ansible.po +363 -48
  77. data/locale/sv_SE/foreman_ansible.po.time_stamp +0 -0
  78. data/locale/zh_CN/foreman_ansible.edit.po +1148 -0
  79. data/locale/zh_CN/foreman_ansible.po +355 -40
  80. data/locale/zh_CN/foreman_ansible.po.time_stamp +0 -0
  81. data/locale/zh_TW/foreman_ansible.edit.po +1148 -0
  82. data/locale/zh_TW/foreman_ansible.po +355 -40
  83. data/locale/zh_TW/foreman_ansible.po.time_stamp +0 -0
  84. data/test/fixtures/playbooks_example_output.json +1 -0
  85. data/test/fixtures/sample_playbooks.json +10 -0
  86. data/test/functional/api/v2/ansible_playbooks_controller_test.rb +65 -0
  87. data/test/functional/hosts_controller_test.rb +2 -2
  88. data/test/graphql/queries/host_ansible_roles_query_test.rb +61 -0
  89. data/test/unit/import_playbooks_test.rb +51 -0
  90. data/test/unit/lib/proxy_api/ansible_test.rb +6 -0
  91. data/webpack/components/AnsibleHostDetail/components/AnsibleVariableOverrides/AnsibleVariableOverridesTable.js +58 -75
  92. data/webpack/components/AnsibleHostDetail/components/JobsTab/PreviousJobsTable.js +44 -58
  93. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/AllRolesTable.js +43 -56
  94. data/webpack/components/AnsibleHostDetail/components/RolesTab/AllRolesModal/index.js +1 -1
  95. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/EditRolesForm.js +22 -22
  96. data/webpack/components/AnsibleHostDetail/components/RolesTab/EditRolesModal/index.js +2 -1
  97. data/webpack/components/AnsibleHostDetail/components/RolesTab/RolesTable.js +39 -43
  98. data/webpack/components/AnsibleHostDetail/components/RolesTab/__test__/RolesTab.fixtures.js +30 -0
  99. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariables.js +27 -38
  100. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesActions.js +2 -1
  101. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesConstants.js +1 -0
  102. data/webpack/components/AnsibleRolesAndVariables/AnsibleRolesAndVariablesSelectors.js +6 -0
  103. data/webpack/components/AnsibleRolesAndVariables/index.js +7 -1
  104. data/webpack/components/AnsibleRolesSwitcher/__tests__/AnsibleRolesSwitcher.test.js +0 -2
  105. data/webpack/components/AnsibleRolesSwitcher/components/AnsibleRole.js +3 -12
  106. data/webpack/components/AnsibleRolesSwitcher/components/AvailableRolesList.js +2 -2
  107. data/webpack/components/AnsibleRolesSwitcher/components/OrderedRolesTooltip.js +11 -12
  108. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AnsibleRole.test.js.snap +6 -20
  109. data/webpack/components/AnsibleRolesSwitcher/components/__snapshots__/AvailableRolesList.test.js.snap +9 -6
  110. data/webpack/components/withLoading.js +7 -12
  111. data/webpack/graphql/queries/allAnsibleRoles.gql +3 -0
  112. data/webpack/graphql/queries/hostAnsibleRoles.gql +3 -0
  113. data/webpack/helpers/pageParamsHelper.js +3 -3
  114. metadata +57 -6
  115. data/app/helpers/foreman_ansible/hosts_helper_extensions.rb +0 -30
  116. data/app/views/foreman_ansible/job_templates/configure_cloud_connector_-_ansible_default.erb +0 -37
  117. data/webpack/helpers/paginationHelper.js +0 -9
@@ -27,7 +27,7 @@ const AllRolesModal = ({ hostGlobalId, onClose, history }) => {
27
27
  ),
28
28
  };
29
29
 
30
- const paginationKeys = { page: 'allPage', perPage: 'allPerPage' };
30
+ const paginationKeys = { page: 'page', perPage: 'per_page' };
31
31
 
32
32
  const wrapper = child => <Modal {...baseModalProps}>{child}</Modal>;
33
33
 
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { translate as __ } from 'foremanReact/common/I18n';
3
3
  import PropTypes from 'prop-types';
4
4
 
@@ -21,17 +21,17 @@ const EditRolesForm = props => {
21
21
  actions,
22
22
  } = props;
23
23
 
24
- const [formState, setFormState] = useState({
25
- availableOptions: [],
26
- chosenOptions: [],
27
- });
24
+ const [availableOptions, setAvailableOptions] = useState(
25
+ availableRoles.map(item => item.name)
26
+ );
27
+ const [chosenOptions, setChosenOptions] = useState(
28
+ assignedRoles.map(item => item.name)
29
+ );
28
30
 
29
- useEffect(() => {
30
- setFormState({
31
- availableOptions: availableRoles.map(item => item.name),
32
- chosenOptions: assignedRoles.map(item => item.name) || [],
33
- });
34
- }, [availableRoles, assignedRoles]);
31
+ const onListChange = (nextAvailable, nextChosen) => {
32
+ setAvailableOptions(nextAvailable);
33
+ setChosenOptions(nextChosen);
34
+ };
35
35
 
36
36
  const [callMutation, { loading }] = useMutation(assignAnsibleRoles, {
37
37
  onCompleted: onCompleted(closeModal),
@@ -42,7 +42,7 @@ const EditRolesForm = props => {
42
42
 
43
43
  const variables = {
44
44
  id: encodeId('Host', hostId),
45
- ansibleRoleIds: roleNamesToIds(allRoles, formState.chosenOptions),
45
+ ansibleRoleIds: roleNamesToIds(allRoles, chosenOptions),
46
46
  };
47
47
 
48
48
  const formActions = [
@@ -65,14 +65,9 @@ const EditRolesForm = props => {
65
65
  return (
66
66
  <Modal {...baseModalProps} actions={formActions}>
67
67
  <DualList
68
- availableOptions={formState.availableOptions}
69
- chosenOptions={formState.chosenOptions}
70
- onListChange={(newAvailable, newChosen) =>
71
- setFormState({
72
- availableOptions: newAvailable,
73
- chosenOptions: newChosen,
74
- })
75
- }
68
+ availableOptions={availableOptions}
69
+ chosenOptions={chosenOptions}
70
+ onListChange={onListChange}
76
71
  />
77
72
  </Modal>
78
73
  );
@@ -80,11 +75,16 @@ const EditRolesForm = props => {
80
75
 
81
76
  EditRolesForm.propTypes = {
82
77
  closeModal: PropTypes.func.isRequired,
83
- assignedRoles: PropTypes.array.isRequired,
84
- availableRoles: PropTypes.array.isRequired,
78
+ assignedRoles: PropTypes.array,
79
+ availableRoles: PropTypes.array,
85
80
  actions: PropTypes.array.isRequired,
86
81
  hostId: PropTypes.number.isRequired,
87
82
  baseModalProps: PropTypes.object.isRequired,
88
83
  };
89
84
 
85
+ EditRolesForm.defaultProps = {
86
+ assignedRoles: [],
87
+ availableRoles: [],
88
+ };
89
+
90
90
  export default withLoading(EditRolesForm);
@@ -54,6 +54,7 @@ const EditRolesModal = ({
54
54
 
55
55
  const renameData = data => ({
56
56
  availableRoles: data.host.availableAnsibleRoles.nodes,
57
+ assignedRoles,
57
58
  });
58
59
 
59
60
  return (
@@ -64,7 +65,7 @@ const EditRolesModal = ({
64
65
  baseModalProps={baseModalProps}
65
66
  fetchFn={useFetchFn}
66
67
  renameData={renameData}
67
- renamedDataPath="availableRoles"
68
+ renamedDataPath="availableRoles.assignedRoles"
68
69
  assignedRoles={assignedRoles}
69
70
  closeModal={closeModal}
70
71
  hostId={hostId}
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { translate as __ } from 'foremanReact/common/I18n';
4
4
  import { Route, Link } from 'react-router-dom';
5
- import { usePaginationOptions } from 'foremanReact/components/Pagination/PaginationHooks';
5
+ import Pagination from 'foremanReact/components/Pagination';
6
6
 
7
7
  import {
8
8
  TableComposable,
@@ -12,37 +12,22 @@ import {
12
12
  Th,
13
13
  Td,
14
14
  } from '@patternfly/react-table';
15
- import { Flex, FlexItem, Button, Pagination } from '@patternfly/react-core';
15
+ import { Flex, FlexItem, Button } from '@patternfly/react-core';
16
16
 
17
17
  import EditRolesModal from './EditRolesModal';
18
18
 
19
19
  import withLoading from '../../../withLoading';
20
20
  import AllRolesModal from './AllRolesModal';
21
- import {
22
- preparePerPageOptions,
23
- refreshPage,
24
- } from '../../../../helpers/paginationHelper';
25
21
 
26
22
  const RolesTable = ({
27
23
  totalCount,
28
- pagination,
29
24
  history,
30
25
  ansibleRoles,
31
26
  hostId,
32
27
  hostGlobalId,
33
28
  canEditHost,
34
29
  }) => {
35
- const columns = [__('Name')];
36
-
37
- const handlePerPageSelected = (event, perPage) => {
38
- refreshPage(history, { page: 1, perPage });
39
- };
40
-
41
- const handlePageSelected = (event, page) => {
42
- refreshPage(history, { ...pagination, page });
43
- };
44
-
45
- const perPageOptions = preparePerPageOptions(usePaginationOptions());
30
+ const columns = [__('Name'), __('Variables')];
46
31
 
47
32
  const editBtn = canEditHost ? (
48
33
  <FlexItem>
@@ -67,36 +52,48 @@ const RolesTable = ({
67
52
  </Flex>
68
53
  <Flex>
69
54
  <FlexItem>{editBtn}</FlexItem>
55
+ <FlexItem align={{ default: 'alignRight' }}>
56
+ <Pagination updateParamsByUrl itemCount={totalCount} variant="top" />
57
+ </FlexItem>
58
+ </Flex>
59
+ <Flex direction={{ default: 'column' }}>
60
+ <FlexItem>
61
+ <TableComposable variant="compact">
62
+ <Thead>
63
+ <Tr>
64
+ {columns.map(col => (
65
+ <Th key={col}>{col}</Th>
66
+ ))}
67
+ </Tr>
68
+ </Thead>
69
+ <Tbody>
70
+ {ansibleRoles.map(role => (
71
+ <Tr key={role.id}>
72
+ <Td>
73
+ <a href={role.path}>{role.name}</a>
74
+ </Td>
75
+ <Td>
76
+ <a
77
+ href={`/ansible/ansible_variables?search=ansible_role=${role.name}`}
78
+ target="_blank"
79
+ rel="noreferrer"
80
+ >
81
+ {role.ansibleVariables.totalCount}
82
+ </a>
83
+ </Td>
84
+ </Tr>
85
+ ))}
86
+ </Tbody>
87
+ </TableComposable>
88
+ </FlexItem>
70
89
  <FlexItem align={{ default: 'alignRight' }}>
71
90
  <Pagination
91
+ updateParamsByUrl
72
92
  itemCount={totalCount}
73
- page={pagination.page}
74
- perPage={pagination.perPage}
75
- onSetPage={handlePageSelected}
76
- onPerPageSelect={handlePerPageSelected}
77
- perPageOptions={perPageOptions}
78
- variant="top"
93
+ variant="bottom"
79
94
  />
80
95
  </FlexItem>
81
96
  </Flex>
82
- <TableComposable variant="compact">
83
- <Thead>
84
- <Tr>
85
- {columns.map(col => (
86
- <Th key={col}>{col}</Th>
87
- ))}
88
- </Tr>
89
- </Thead>
90
- <Tbody>
91
- {ansibleRoles.map(role => (
92
- <Tr key={role.id}>
93
- <Td>
94
- <a href={role.path}>{role.name}</a>
95
- </Td>
96
- </Tr>
97
- ))}
98
- </Tbody>
99
- </TableComposable>
100
97
  <Route path="/Ansible/roles/edit">
101
98
  <EditRolesModal
102
99
  closeModal={() => history.goBack()}
@@ -123,7 +120,6 @@ RolesTable.propTypes = {
123
120
  hostId: PropTypes.number.isRequired,
124
121
  hostGlobalId: PropTypes.string.isRequired,
125
122
  history: PropTypes.object.isRequired,
126
- pagination: PropTypes.object.isRequired,
127
123
  totalCount: PropTypes.number.isRequired,
128
124
  canEditHost: PropTypes.bool.isRequired,
129
125
  };
@@ -35,6 +35,9 @@ const role1 = {
35
35
  id: 'MDE6QW5zaWJsZVJvbGUtMw==',
36
36
  name: 'aardvaark.cube',
37
37
  path: '/ansible/ansible_roles/search="name = aardvaark.cube"',
38
+ ansibleVariables: {
39
+ totalCount: 1,
40
+ },
38
41
  };
39
42
 
40
43
  const role2 = {
@@ -42,6 +45,9 @@ const role2 = {
42
45
  id: 'MDE6QW5zaWJsZVJvbGUtNQ==',
43
46
  name: 'aardvaark.sphere',
44
47
  path: '/ansible/ansible_roles/search="name = aardvaark.sphere"',
48
+ ansibleVariables: {
49
+ totalCount: 2,
50
+ },
45
51
  };
46
52
 
47
53
  const role3 = {
@@ -49,6 +55,9 @@ const role3 = {
49
55
  id: 'MDE6QW5zaWJsZVJvbGUtMzA=',
50
56
  name: 'another.role',
51
57
  path: '/ansible/ansible_roles/search="name = another.role"',
58
+ ansibleVariables: {
59
+ totalCount: 3,
60
+ },
52
61
  };
53
62
 
54
63
  const role4 = {
@@ -56,6 +65,9 @@ const role4 = {
56
65
  id: 'MDE6QW5zaWJsZVJvbGUtMzk=',
57
66
  name: 'geerlingguy.ceylon',
58
67
  path: '/ansible/ansible_roles/search="name = geerlingguy.ceylon"',
68
+ ansibleVariables: {
69
+ totalCount: 4,
70
+ },
59
71
  };
60
72
 
61
73
  const ansibleRolesMock = {
@@ -77,30 +89,45 @@ const availableRoles = {
77
89
  name: 'theforeman.foreman_scap_client',
78
90
  path:
79
91
  '/ansible/ansible_roles/search="name = theforeman.foreman_scap_client"',
92
+ ansibleVariables: {
93
+ totalCount: 23,
94
+ },
80
95
  },
81
96
  {
82
97
  __typename: 'AnsibleRole',
83
98
  id: 'MDE6QW5zaWJsZVJvbGUtMg==',
84
99
  name: 'adriagalin.motd',
85
100
  path: '/ansible/ansible_roles/search="name = adriagalin.motd"',
101
+ ansibleVariables: {
102
+ totalCount: 23,
103
+ },
86
104
  },
87
105
  {
88
106
  __typename: 'AnsibleRole',
89
107
  id: 'MDE6QW5zaWJsZVJvbGUtMjI=',
90
108
  name: 'geerlingguy.php',
91
109
  path: '/ansible/ansible_roles/search="name = geerlingguy.php"',
110
+ ansibleVariables: {
111
+ totalCount: 23,
112
+ },
92
113
  },
93
114
  {
94
115
  __typename: 'AnsibleRole',
95
116
  id: 'MDE6QW5zaWJsZVJvbGUtNTc=',
96
117
  name: 'robertdebock.epel',
97
118
  path: '/ansible/ansible_roles/search="name = robertdebock.epel"',
119
+ ansibleVariables: {
120
+ totalCount: 23,
121
+ },
98
122
  },
99
123
  {
100
124
  __typename: 'AnsibleRole',
101
125
  id: 'MDE6QW5zaWJsZVJvbGUtNTg=',
102
126
  name: 'geerlingguy.nfs',
103
127
  path: '/ansible/ansible_roles/search="name = geerlingguy.nfs"',
128
+ ansibleVariables: {
129
+ totalCount: 23,
130
+ },
104
131
  },
105
132
  ],
106
133
  };
@@ -118,6 +145,9 @@ export const allRolesMocks = allAnsibleRolesMockFactory(
118
145
  name: 'adriagalin.motd',
119
146
  path: '/ansible/ansible_roles/search="name = adriagalin.motd"',
120
147
  inherited: true,
148
+ ansibleVariables: {
149
+ totalCount: 23,
150
+ },
121
151
  },
122
152
  { ...role1, inherited: false },
123
153
  { ...role2, inherited: false },
@@ -12,9 +12,8 @@ import {
12
12
  ToolbarContent,
13
13
  ToolbarItem,
14
14
  Checkbox,
15
- Pagination,
16
15
  } from '@patternfly/react-core';
17
-
16
+ import Pagination from 'foremanReact/components/Pagination';
18
17
  import PropTypes from 'prop-types';
19
18
  import { DEFAULT_PER_PAGE } from './AnsibleRolesAndVariablesConstants';
20
19
  import './AnsibleRolesAndVariables.scss';
@@ -25,6 +24,7 @@ const ImportRolesAndVariablesTable = ({
25
24
  proxy,
26
25
  onSubmit,
27
26
  onCancel,
27
+ isImporting,
28
28
  }) => {
29
29
  const columns = columnsData.map(col => ({
30
30
  ...col,
@@ -34,10 +34,13 @@ const ImportRolesAndVariablesTable = ({
34
34
 
35
35
  const [isChecked, setIsChecked] = useState(false);
36
36
  const [selectedRowsCount, setSelectRowsCount] = useState(0);
37
-
38
- const [page, setPage] = useState();
39
- const [perPage, setPerPage] = useState(DEFAULT_PER_PAGE);
40
- const [paginatedRows, setPaginatedRows] = useState(rows.slice(0, perPage));
37
+ const [pagination, setPagination] = useState({
38
+ page: 1,
39
+ per_page: DEFAULT_PER_PAGE,
40
+ });
41
+ const [paginatedRows, setPaginatedRows] = useState(
42
+ rows.slice(0, pagination.per_page)
43
+ );
41
44
 
42
45
  const onSelect = (event, isSelected, rowId, row) => {
43
46
  const selectableRowLength = rows.filter(
@@ -68,43 +71,22 @@ const ImportRolesAndVariablesTable = ({
68
71
  onSelect(null, checked, -1);
69
72
  };
70
73
 
71
- const handleSetPage = (event, newPage) => {
72
- const startIdx = (newPage - 1) * perPage;
74
+ const handleSetPage = args => {
75
+ const startIdx = (args.page - 1) * args.per_page;
73
76
  const endIdx =
74
- rows.length < newPage * perPage ? rows.length : newPage * perPage;
75
- setPage(newPage);
77
+ rows.length < args.page * args.per_page
78
+ ? rows.length
79
+ : args.page * args.per_page;
80
+ setPagination(args);
76
81
  setPaginatedRows(rows.slice(startIdx, endIdx));
77
82
  };
78
83
 
79
- const handlePerPageSelect = (
80
- event,
81
- newPerPage,
82
- newPage,
83
- startIdx,
84
- endIdx
85
- ) => {
86
- setPerPage(newPerPage);
87
- setPage(newPage);
88
- setPaginatedRows(rows.slice(startIdx, endIdx));
89
- };
90
-
91
- const renderPagination = (variant = 'top') => (
84
+ const renderPagination = () => (
92
85
  <Pagination
93
86
  isCompact
94
87
  itemCount={rows.length}
95
- page={page}
96
- perPage={perPage}
97
- defaultToFullPage
98
- onSetPage={handleSetPage}
99
- onPerPageSelect={handlePerPageSelect}
100
- perPageOptions={[
101
- { title: '3', value: 3 },
102
- { title: '5', value: 5 },
103
- { title: '10', value: 10 },
104
- ]}
105
- titles={{
106
- paginationTitle: `${variant} pagination`,
107
- }}
88
+ perPage={pagination.per_page}
89
+ onChange={args => handleSetPage(args)}
108
90
  />
109
91
  );
110
92
 
@@ -131,10 +113,15 @@ const ImportRolesAndVariablesTable = ({
131
113
  <div className="submit-cancel-btns">
132
114
  <br />
133
115
  <br />
134
- <Button variant="primary" onClick={() => onSubmit(rows, proxy)}>
116
+ <Button
117
+ variant="primary"
118
+ onClick={() => onSubmit(rows, proxy)}
119
+ isLoading={isImporting}
120
+ isDisabled={isImporting || selectedRowsCount === 0}
121
+ >
135
122
  Submit
136
123
  </Button>
137
- <Button variant="secondary" onClick={onCancel}>
124
+ <Button variant="secondary" onClick={onCancel} isDisabled={isImporting}>
138
125
  Cancel
139
126
  </Button>
140
127
  </div>
@@ -165,6 +152,7 @@ ImportRolesAndVariablesTable.defaultProps = {
165
152
  proxy: undefined,
166
153
  onSubmit: undefined,
167
154
  onCancel: undefined,
155
+ isImporting: false,
168
156
  };
169
157
 
170
158
  ImportRolesAndVariablesTable.propTypes = {
@@ -173,6 +161,7 @@ ImportRolesAndVariablesTable.propTypes = {
173
161
  proxy: PropTypes.number,
174
162
  onSubmit: PropTypes.func,
175
163
  onCancel: PropTypes.func,
164
+ isImporting: PropTypes.bool,
176
165
  };
177
166
 
178
167
  export default ImportRolesAndVariablesTable;
@@ -4,6 +4,7 @@ import { post } from 'foremanReact/redux/API';
4
4
  import { push } from 'connected-react-router';
5
5
  import { prepareResult } from './AnsibleRolesAndVariablesHelpers';
6
6
  import {
7
+ IMPORT_ANSIBLE_V_R,
7
8
  ANSIBLE_ROLE_CONFIRM_IMPORT_PATH,
8
9
  ANSIBLE_ROLES_INDEX,
9
10
  } from './AnsibleRolesAndVariablesConstants';
@@ -14,7 +15,7 @@ export const onSubmit = (rows, proxy) => dispatch => {
14
15
  const params = prepareResult(rows);
15
16
  dispatch(
16
17
  post({
17
- key: 'import_ansible_v_r',
18
+ key: IMPORT_ANSIBLE_V_R,
18
19
  url: ANSIBLE_ROLE_CONFIRM_IMPORT_PATH,
19
20
  params: { changed: params, proxy },
20
21
  handleSuccess: () => {
@@ -1,3 +1,4 @@
1
+ export const IMPORT_ANSIBLE_V_R = 'IMPORT_ANSIBLE_V_R';
1
2
  export const ANSIBLE_ROLES_INDEX = '/ansible/ansible_roles';
2
3
  export const ANSIBLE_ROLE_CONFIRM_IMPORT_PATH =
3
4
  '/ansible/ansible_roles/confirm_import';
@@ -0,0 +1,6 @@
1
+ import { selectAPIStatus } from 'foremanReact/redux/API/APISelectors';
2
+ import { IMPORT_ANSIBLE_V_R } from './AnsibleRolesAndVariablesConstants';
3
+
4
+ // API statuses
5
+ export const selectApiImportStatus = state =>
6
+ selectAPIStatus(state, IMPORT_ANSIBLE_V_R);
@@ -1,10 +1,13 @@
1
1
  import React from 'react';
2
- import { useDispatch } from 'react-redux';
2
+ import { useDispatch, useSelector } from 'react-redux';
3
3
  import { push } from 'connected-react-router';
4
4
 
5
+ import { STATUS } from 'foremanReact/constants';
6
+
5
7
  import ImportRolesAndVariablesTable from './AnsibleRolesAndVariables';
6
8
  import { onSubmit } from './AnsibleRolesAndVariablesActions';
7
9
  import { ANSIBLE_ROLES_INDEX } from './AnsibleRolesAndVariablesConstants';
10
+ import { selectApiImportStatus } from './AnsibleRolesAndVariablesSelectors';
8
11
 
9
12
  const WrappedImportRolesAndVariables = props => {
10
13
  const cols = [
@@ -19,12 +22,15 @@ const WrappedImportRolesAndVariables = props => {
19
22
  const onCancel = () => {
20
23
  dispatch(push(ANSIBLE_ROLES_INDEX));
21
24
  };
25
+ const apiImportStatus = useSelector(selectApiImportStatus);
26
+
22
27
  return (
23
28
  <ImportRolesAndVariablesTable
24
29
  {...props}
25
30
  columnsData={cols}
26
31
  onSubmit={submit}
27
32
  onCancel={onCancel}
33
+ isImporting={apiImportStatus === STATUS.PENDING}
28
34
  />
29
35
  );
30
36
  };
@@ -2,8 +2,6 @@ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
2
2
 
3
3
  import AnsibleRolesSwitcher from '../AnsibleRolesSwitcher';
4
4
 
5
- jest.mock('foremanReact/components/Pagination/PaginationWrapper');
6
-
7
5
  const noop = () => {};
8
6
 
9
7
  const fixtures = {
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { ListView, Tooltip, OverlayTrigger } from 'patternfly-react';
3
+ import { ListView } from 'patternfly-react';
4
+ import { Tooltip } from '@patternfly/react-core';
4
5
  import classNames from 'classnames';
5
6
  import { translate as __ } from 'foremanReact/common/I18n';
6
7
 
@@ -13,12 +14,6 @@ const AnsibleRole = ({ role, icon, onClick, resourceName, index }) => {
13
14
  ? __('This Ansible role is inherited from parent host group')
14
15
  : __('This Ansible role is inherited from host group');
15
16
 
16
- const tooltip = (
17
- <Tooltip id={role.id}>
18
- <span>{text}</span>
19
- </Tooltip>
20
- );
21
-
22
17
  const clickHandler = (onClickFn, ansibleRole) => event => {
23
18
  event.preventDefault();
24
19
  onClickFn(ansibleRole);
@@ -48,11 +43,7 @@ const AnsibleRole = ({ role, icon, onClick, resourceName, index }) => {
48
43
  );
49
44
 
50
45
  if (role.inherited) {
51
- return (
52
- <OverlayTrigger overlay={tooltip} placement="top">
53
- {listItem()}
54
- </OverlayTrigger>
55
- );
46
+ return <Tooltip content={<span>{text}</span>}>{listItem()}</Tooltip>;
56
47
  }
57
48
 
58
49
  return listItem(clickHandler);
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
 
4
4
  import { ListView, LoadingState } from 'patternfly-react';
5
- import PaginationWrapper from 'foremanReact/components/Pagination/PaginationWrapper';
5
+ import Pagination from 'foremanReact/components/Pagination';
6
6
 
7
7
  import AnsibleRole from './AnsibleRole';
8
8
 
@@ -16,7 +16,7 @@ const AvailableRolesList = ({
16
16
  }) => (
17
17
  <ListView>
18
18
  <div className="sticky-pagination">
19
- <PaginationWrapper
19
+ <Pagination
20
20
  viewType="list"
21
21
  itemCount={itemCount}
22
22
  pagination={pagination}
@@ -1,22 +1,21 @@
1
1
  import React from 'react';
2
2
  import { translate as __ } from 'foremanReact/common/I18n';
3
- import { Tooltip, Icon, OverlayTrigger } from 'patternfly-react';
3
+ import { Tooltip } from '@patternfly/react-core';
4
+ import { InfoCircleIcon } from '@patternfly/react-icons';
4
5
 
5
6
  const OrderedRolesTooltip = props => {
6
- const tooltip = (
7
- <Tooltip id="assigned-ansible-roles-tooltip">
8
- <span>
9
- {__(
10
- 'Use drag and drop to change order of the roles. Ordering of roles is respected for Ansible runs, inherited roles are always before those assigned directly'
11
- )}
12
- </span>
13
- </Tooltip>
7
+ const content = (
8
+ <span>
9
+ {__(
10
+ 'Use drag and drop to change order of the roles. Ordering of roles is respected for Ansible runs, inherited roles are always before those assigned directly'
11
+ )}
12
+ </span>
14
13
  );
15
14
 
16
15
  return (
17
- <OverlayTrigger overlay={tooltip} trigger={['hover', 'focus']}>
18
- <Icon type="pf" name="info" style={{ 'margin-right': '10px' }} />
19
- </OverlayTrigger>
16
+ <Tooltip content={content}>
17
+ <InfoCircleIcon style={{ marginRight: '10px' }} />
18
+ </Tooltip>
20
19
  );
21
20
  };
22
21
 
@@ -65,25 +65,11 @@ exports[`AnsibleRole should render a role to remove 1`] = `
65
65
  `;
66
66
 
67
67
  exports[`AnsibleRole should render inherited role to remove 1`] = `
68
- <OverlayTrigger
69
- defaultOverlayShown={false}
70
- overlay={
71
- <Tooltip
72
- bsClass="tooltip"
73
- id={5}
74
- placement="right"
75
- >
76
- <span>
77
- This Ansible role is inherited from host group
78
- </span>
79
- </Tooltip>
80
- }
81
- placement="top"
82
- trigger={
83
- Array [
84
- "hover",
85
- "focus",
86
- ]
68
+ <Tooltip
69
+ content={
70
+ <span>
71
+ This Ansible role is inherited from host group
72
+ </span>
87
73
  }
88
74
  >
89
75
  <ListViewItem
@@ -104,5 +90,5 @@ exports[`AnsibleRole should render inherited role to remove 1`] = `
104
90
  onExpandClose={[Function]}
105
91
  stacked={true}
106
92
  />
107
- </OverlayTrigger>
93
+ </Tooltip>
108
94
  `;
@@ -7,21 +7,24 @@ exports[`AvailableRolesList should render 1`] = `
7
7
  <div
8
8
  className="sticky-pagination"
9
9
  >
10
- <PaginationWrapper
11
- className=""
12
- disableNext={false}
13
- disablePrev={false}
10
+ <Pagination
11
+ className={null}
14
12
  dropdownButtonId="available-ansible-roles-pagination-row-dropdown"
15
13
  itemCount={2}
14
+ noSidePadding={false}
16
15
  onChange={[Function]}
17
- onPageSet={[Function]}
18
- onPerPageSelect={[Function]}
16
+ onPerPageSelect={null}
17
+ onSetPage={null}
18
+ page={1}
19
19
  pagination={
20
20
  Object {
21
21
  "page": 1,
22
22
  "perPage": 25,
23
23
  }
24
24
  }
25
+ perPage={null}
26
+ updateParamsByUrl={true}
27
+ variant="bottom"
25
28
  viewType="list"
26
29
  />
27
30
  </div>