katello 3.9.1 → 3.10.0.rc1

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 (229) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/hosts/host_and_hostgroup_edit.js +28 -12
  3. data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -3
  4. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +4 -13
  5. data/app/controllers/katello/api/v2/content_credentials_controller.rb +1 -1
  6. data/app/controllers/katello/api/v2/content_view_filter_rules_controller.rb +1 -1
  7. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +6 -4
  8. data/app/controllers/katello/api/v2/content_views_controller.rb +8 -3
  9. data/app/controllers/katello/api/v2/gpg_keys_controller.rb +2 -1
  10. data/app/controllers/katello/api/v2/host_module_streams_controller.rb +39 -0
  11. data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +20 -11
  12. data/app/controllers/katello/api/v2/module_streams_controller.rb +2 -1
  13. data/app/controllers/katello/api/v2/repository_sets_controller.rb +17 -8
  14. data/app/controllers/katello/application_controller.rb +0 -2
  15. data/app/controllers/katello/concerns/hosts_controller_extensions.rb +5 -2
  16. data/app/lib/actions/candlepin/consumer/attach_subscription.rb +0 -2
  17. data/app/lib/actions/candlepin/consumer/remove_subscription.rb +0 -2
  18. data/app/lib/actions/katello/capsule_content/create_repos.rb +1 -25
  19. data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
  20. data/app/lib/actions/katello/content_view/promote.rb +2 -5
  21. data/app/lib/actions/katello/content_view/promote_to_environment.rb +2 -5
  22. data/app/lib/actions/katello/content_view/publish.rb +1 -4
  23. data/app/lib/actions/katello/content_view_puppet_environment/create.rb +6 -10
  24. data/app/lib/actions/katello/content_view_version/export.rb +0 -2
  25. data/app/lib/actions/katello/content_view_version/incremental_update.rb +19 -1
  26. data/app/lib/actions/katello/environment/publish_repositories.rb +2 -1
  27. data/app/lib/actions/katello/gpg_key/update.rb +17 -0
  28. data/app/lib/actions/katello/host/attach_subscriptions.rb +0 -2
  29. data/app/lib/actions/katello/host/erratum/install.rb +6 -0
  30. data/app/lib/actions/katello/host/generate_applicability.rb +0 -2
  31. data/app/lib/actions/katello/host/hypervisors_update.rb +11 -6
  32. data/app/lib/actions/katello/host/package/install.rb +6 -0
  33. data/app/lib/actions/katello/host/package/remove.rb +6 -0
  34. data/app/lib/actions/katello/host/package/update.rb +7 -1
  35. data/app/lib/actions/katello/host/package_group/install.rb +6 -0
  36. data/app/lib/actions/katello/host/package_group/remove.rb +6 -0
  37. data/app/lib/actions/katello/host/recalculate_errata_status.rb +0 -2
  38. data/app/lib/actions/katello/host/remove_subscriptions.rb +0 -2
  39. data/app/lib/actions/katello/host/update.rb +1 -0
  40. data/app/lib/actions/katello/host/update_content_overrides.rb +0 -2
  41. data/app/lib/actions/katello/host/upload_package_profile.rb +13 -12
  42. data/app/lib/actions/katello/host/upload_profiles.rb +70 -0
  43. data/app/lib/actions/katello/product/reindex_subscriptions.rb +0 -2
  44. data/app/lib/actions/katello/product/repositories_certs_reset.rb +4 -4
  45. data/app/lib/actions/katello/product/repositories_gpg_reset.rb +2 -2
  46. data/app/lib/actions/katello/repository/check_matching_content.rb +18 -6
  47. data/app/lib/actions/katello/repository/clone_deb_content.rb +1 -1
  48. data/app/lib/actions/katello/repository/clone_to_environment.rb +3 -5
  49. data/app/lib/actions/katello/repository/clone_to_version.rb +2 -3
  50. data/app/lib/actions/katello/repository/clone_yum_content.rb +1 -2
  51. data/app/lib/actions/katello/repository/clone_yum_metadata.rb +2 -2
  52. data/app/lib/actions/katello/repository/create.rb +1 -31
  53. data/app/lib/actions/katello/repository/destroy.rb +1 -2
  54. data/app/lib/actions/katello/repository/export.rb +0 -2
  55. data/app/lib/actions/katello/repository/fetch_pxe_files.rb +0 -2
  56. data/app/lib/actions/katello/repository/filtered_index_content.rb +0 -2
  57. data/app/lib/actions/katello/repository/finish_upload.rb +0 -2
  58. data/app/lib/actions/katello/repository/import_upload.rb +0 -2
  59. data/app/lib/actions/katello/repository/index_content.rb +0 -1
  60. data/app/lib/actions/katello/repository/index_package_groups.rb +0 -2
  61. data/app/lib/actions/katello/repository/instance_update.rb +21 -0
  62. data/app/lib/actions/katello/repository/remove_content.rb +0 -2
  63. data/app/lib/actions/katello/repository/sync.rb +0 -1
  64. data/app/lib/actions/katello/repository/update.rb +0 -2
  65. data/app/lib/actions/katello/upstream_subscriptions/bind_entitlement.rb +0 -2
  66. data/app/lib/actions/katello/upstream_subscriptions/bind_entitlements.rb +0 -2
  67. data/app/lib/actions/katello/upstream_subscriptions/remove_entitlement.rb +0 -1
  68. data/app/lib/actions/katello/upstream_subscriptions/remove_entitlements.rb +0 -2
  69. data/app/lib/actions/katello/upstream_subscriptions/update_entitlement.rb +0 -1
  70. data/app/lib/actions/katello/upstream_subscriptions/update_entitlements.rb +0 -2
  71. data/app/lib/actions/pulp/abstract.rb +13 -14
  72. data/app/lib/actions/pulp/repository/create.rb +13 -211
  73. data/app/lib/actions/pulp/repository/create_in_plan.rb +4 -18
  74. data/app/lib/actions/pulp/repository/refresh.rb +7 -70
  75. data/app/lib/actions/pulp/repository/sync.rb +1 -2
  76. data/app/lib/katello/capsule_content.rb +3 -3
  77. data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
  78. data/app/lib/katello/resources/candlepin/product.rb +1 -1
  79. data/app/lib/katello/validators/hostgroup_kickstart_repository_validator.rb +1 -1
  80. data/app/models/katello/available_module_stream.rb +11 -0
  81. data/app/models/katello/concerns/content_facet_host_extensions.rb +1 -0
  82. data/app/models/katello/concerns/host_managed_extensions.rb +56 -0
  83. data/app/models/katello/concerns/hostgroup_extensions.rb +17 -0
  84. data/app/models/katello/concerns/redhat_extensions.rb +20 -6
  85. data/app/models/katello/concerns/search_by_repository_name.rb +0 -1
  86. data/app/models/katello/concerns/smart_proxy_extensions.rb +26 -12
  87. data/app/models/katello/content_facet_applicable_module_stream.rb +7 -0
  88. data/app/models/katello/content_view_puppet_environment.rb +14 -35
  89. data/app/models/katello/erratum.rb +54 -24
  90. data/app/models/katello/erratum_package.rb +6 -0
  91. data/app/models/katello/glue/pulp/repo.rb +5 -228
  92. data/app/models/katello/gpg_key.rb +1 -0
  93. data/app/models/katello/host/content_facet.rb +38 -83
  94. data/app/models/katello/host_available_module_stream.rb +47 -0
  95. data/app/models/katello/module_stream.rb +18 -0
  96. data/app/models/katello/module_stream_erratum_package.rb +6 -0
  97. data/app/models/katello/product.rb +0 -2
  98. data/app/models/katello/product_content.rb +1 -0
  99. data/app/models/katello/repository.rb +15 -6
  100. data/app/models/katello/root_repository.rb +1 -1
  101. data/app/models/katello/rpm.rb +5 -17
  102. data/app/services/katello/applicable_content_helper.rb +111 -0
  103. data/app/services/katello/managed_content_medium_provider.rb +7 -0
  104. data/app/services/katello/pulp/consumer.rb +13 -7
  105. data/app/services/katello/pulp/repository.rb +157 -4
  106. data/app/services/katello/pulp/repository/deb.rb +47 -0
  107. data/app/services/katello/pulp/repository/docker.rb +43 -0
  108. data/app/services/katello/pulp/repository/file.rb +31 -0
  109. data/app/services/katello/pulp/repository/ostree.rb +40 -0
  110. data/app/services/katello/pulp/repository/puppet.rb +43 -0
  111. data/app/services/katello/pulp/repository/yum.rb +61 -0
  112. data/app/services/katello/repository_type.rb +1 -1
  113. data/app/views/katello/api/v2/content_facet/base.json.rabl +1 -0
  114. data/app/views/katello/api/v2/content_view_versions/base.json.rabl +0 -1
  115. data/app/views/katello/api/v2/errata/_counts.json.rabl +0 -1
  116. data/app/views/katello/api/v2/errata/show.json.rabl +9 -3
  117. data/app/views/katello/api/v2/host_collections/delta_activation_keys.rabl +0 -1
  118. data/app/views/katello/api/v2/host_module_streams/base.json.rabl +8 -0
  119. data/app/views/katello/api/v2/host_module_streams/index.json.rabl +7 -0
  120. data/app/views/katello/api/v2/packages/backend.json.rabl +0 -1
  121. data/app/views/katello/api/v2/repositories/show.json.rabl +6 -6
  122. data/app/views/katello/layouts/react.html.erb +2 -2
  123. data/app/views/overrides/activation_keys/_host_synced_content_select.html.erb +0 -1
  124. data/config/routes/api/rhsm.rb +1 -0
  125. data/config/routes/overrides.rb +4 -0
  126. data/db/migrate/20181008201422_add_modules_to_errata_packages.rb +29 -0
  127. data/db/migrate/20181017181806_available_module_streams.rb +34 -0
  128. data/db/migrate/20181027014323_add_applicable_modules.rb +24 -0
  129. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/common/module-stream-actions.service.js +2 -1
  130. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/details/views/content-credential-info.html +1 -1
  131. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +1 -0
  132. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-host-bulk-module-streams-modal.html +2 -2
  133. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +37 -22
  134. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-hosts.controller.js +4 -1
  135. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-module-streams.controller.js +27 -7
  136. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/content-host-module-streams.html +29 -0
  137. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/views/errata-details.html +15 -1
  138. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +1 -1
  139. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-promotion.controller.js +0 -1
  140. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-publish.controller.js +1 -2
  141. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/content-view-versions.controller.js +3 -1
  142. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/histories/content-view-history.controller.js +1 -1
  143. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-promotion.html +0 -15
  144. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-publish.html +0 -14
  145. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/erratum.controller.js +19 -0
  146. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum-info.html +0 -12
  147. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum-packages.html +36 -0
  148. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/details/views/erratum.html +7 -0
  149. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/errata.routes.js +9 -0
  150. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/hosts/host-module-streams.factory.js +18 -0
  151. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +4 -2
  152. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +2 -2
  153. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +13 -0
  154. data/lib/katello/permissions/host_permissions.rb +3 -0
  155. data/lib/katello/repository_types/deb.rb +3 -1
  156. data/lib/katello/repository_types/docker.rb +3 -1
  157. data/lib/katello/repository_types/file.rb +1 -0
  158. data/lib/katello/repository_types/ostree.rb +3 -1
  159. data/lib/katello/repository_types/puppet.rb +3 -1
  160. data/lib/katello/repository_types/yum.rb +3 -1
  161. data/lib/katello/tasks/delete_orphaned_content.rake +1 -1
  162. data/lib/katello/tasks/reset.rake +1 -0
  163. data/lib/katello/tasks/test.rake +14 -0
  164. data/lib/katello/tasks/unify_hosts.rake +2 -0
  165. data/lib/katello/tasks/virt_who_report.rake +2 -1
  166. data/lib/katello/version.rb +1 -1
  167. data/locale/Makefile +52 -17
  168. data/locale/update-i18n +22 -0
  169. data/package.json +11 -1
  170. data/webpack/__mocks__/foremanReact/components/common/EmptyState.js +8 -0
  171. data/webpack/move_to_foreman/components/common/table/components/Table.js +2 -1
  172. data/webpack/move_to_pf/react-bootstrap-select/index.js +4 -2
  173. data/webpack/move_to_pf/test-utils/testHelpers.js +9 -0
  174. data/webpack/redux/OrganizationProducts/OrganizationProductsActions.js +24 -0
  175. data/webpack/redux/OrganizationProducts/OrganizationProductsConstants.js +5 -0
  176. data/webpack/redux/OrganizationProducts/OrganizationProductsReducer.js +38 -0
  177. data/webpack/redux/OrganizationProducts/OrganizationProductsSelectors.js +7 -0
  178. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsActions.test.js +47 -0
  179. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsReducer.test.js +33 -0
  180. data/webpack/redux/OrganizationProducts/__tests__/OrganizationProductsSelectors.test.js +19 -0
  181. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsActions.test.js.snap +49 -0
  182. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsReducer.test.js.snap +36 -0
  183. data/webpack/redux/OrganizationProducts/__tests__/__snapshots__/OrganizationProductsSelectors.test.js.snap +9 -0
  184. data/webpack/redux/OrganizationProducts/index.js +13 -0
  185. data/webpack/redux/actions/RedHatRepositories/enabled.js +7 -1
  186. data/webpack/redux/actions/RedHatRepositories/helpers.js +4 -0
  187. data/webpack/redux/actions/RedHatRepositories/sets.js +2 -0
  188. data/webpack/redux/reducers/RedHatRepositories/enabled.fixtures.js +8 -2
  189. data/webpack/redux/reducers/RedHatRepositories/enabled.js +1 -1
  190. data/webpack/redux/reducers/RedHatRepositories/sets.fixtures.js +12 -3
  191. data/webpack/redux/reducers/index.js +2 -0
  192. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +68 -33
  193. data/webpack/scenes/RedHatRepositories/index.js +13 -2
  194. data/webpack/scenes/RedHatRepositories/index.scss +26 -0
  195. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +1 -1
  196. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +1 -1
  197. data/webpack/scenes/Subscriptions/SubscriptionActions.js +18 -2
  198. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +8 -0
  199. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +15 -0
  200. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +22 -14
  201. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +39 -90
  202. data/webpack/scenes/Subscriptions/SubscriptionsSelectors.js +14 -0
  203. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +1 -3
  204. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +0 -1
  205. data/webpack/scenes/Subscriptions/__tests__/SubscriptionHelpers.test.js +84 -0
  206. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsActions.test.js +26 -1
  207. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +5 -0
  208. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +177 -75
  209. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsSelectors.test.js +29 -0
  210. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionHelpers.test.js.snap +31 -0
  211. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsActions.test.js.snap +32 -0
  212. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +18 -96
  213. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsReducer.test.js.snap +511 -0
  214. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsSelectors.test.js.snap +26 -0
  215. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +6 -1
  216. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +3 -21
  217. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +113 -0
  218. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.test.js +47 -0
  219. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/__snapshots__/SubscriptionsToolbar.test.js.snap +504 -0
  220. data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/index.js +1 -0
  221. data/webpack/scenes/Subscriptions/index.js +15 -4
  222. metadata +59 -14
  223. data/app/lib/actions/pulp/repository/associate_distributor.rb +0 -20
  224. data/app/lib/actions/pulp/repository/associate_importer.rb +0 -23
  225. data/app/lib/actions/pulp/repository/delete_distributor.rb +0 -18
  226. data/app/lib/actions/pulp/repository/refresh_distributor.rb +0 -19
  227. data/app/lib/actions/pulp/repository/update_importer.rb +0 -33
  228. data/app/lib/katello/bulk_actions.rb +0 -63
  229. data/webpack/move_to_foreman/components/common/EmptyState/index.js +0 -68
@@ -3,17 +3,13 @@ import PropTypes from 'prop-types';
3
3
  import Immutable from 'seamless-immutable';
4
4
  import { translate as __ } from 'foremanReact/common/I18n';
5
5
  import { isEmpty, isEqual } from 'lodash';
6
- import { LinkContainer } from 'react-router-bootstrap';
7
- import { Grid, Row, Col, Form, FormGroup } from 'react-bootstrap';
8
- import { Button } from 'patternfly-react';
9
- import TooltipButton from 'react-bootstrap-tooltip-button';
10
- import OptionTooltip from '../../move_to_pf/OptionTooltip';
6
+ import { Grid, Row, Col } from 'patternfly-react';
11
7
  import { renderTaskFinishedToast, renderTaskStartedToast } from '../Tasks/helpers';
12
8
  import ModalProgressBar from '../../move_to_foreman/components/common/ModalProgressBar';
13
9
  import ManageManifestModal from './Manifest/';
14
10
  import { SubscriptionsTable } from './components/SubscriptionsTable';
11
+ import SubscriptionsToolbar from './components/SubscriptionsToolbar';
15
12
  import { manifestExists } from './SubscriptionHelpers';
16
- import Search from '../../components/Search/index';
17
13
  import api, { orgId } from '../../services/api';
18
14
 
19
15
 
@@ -31,11 +27,8 @@ class SubscriptionsPage extends Component {
31
27
  super(props);
32
28
 
33
29
  this.state = {
34
- manifestModalOpen: false,
35
- subscriptionDeleteModalOpen: false,
36
30
  disableDeleteButton: true,
37
31
  showTaskModal: false,
38
- searchQuery: '',
39
32
  };
40
33
  this.uploadManifest = this.uploadManifest.bind(this);
41
34
  this.deleteManifest = this.deleteManifest.bind(this);
@@ -166,6 +159,9 @@ class SubscriptionsPage extends Component {
166
159
  render() {
167
160
  const currentOrg = orgId();
168
161
  const {
162
+ manifestModalOpened, openManageManifestModal, closeManageManifestModal,
163
+ deleteModalOpened, openDeleteModal, closeDeleteModal,
164
+ searchQuery, updateSearchQuery,
169
165
  tasks = [], subscriptions, organization, subscriptionTableSettings,
170
166
  } = this.props;
171
167
  const { disconnected } = subscriptions;
@@ -189,29 +185,9 @@ class SubscriptionsPage extends Component {
189
185
  },
190
186
  });
191
187
 
192
- const updateSearchQuery = (searchQuery) => {
193
- this.setState({ searchQuery });
194
- };
195
-
196
- const showManageManifestModal = () => {
197
- this.setState({ manifestModalOpen: true });
198
- };
199
-
200
- const onManageManifestModalClose = () => {
201
- this.setState({ manifestModalOpen: false });
202
- };
203
-
204
- const showSubscriptionDeleteModal = () => {
205
- this.setState({ subscriptionDeleteModalOpen: true });
206
- };
207
-
208
- const onSubscriptionDeleteModalClose = () => {
209
- this.setState({ subscriptionDeleteModalOpen: false });
210
- };
211
-
212
188
  const onDeleteSubscriptions = (selectedRows) => {
213
189
  this.props.deleteSubscriptions(selectedRows);
214
- onSubscriptionDeleteModalClose();
190
+ closeDeleteModal();
215
191
  };
216
192
 
217
193
  const toggleDeleteButton = (rowsSelected) => {
@@ -219,7 +195,7 @@ class SubscriptionsPage extends Component {
219
195
  };
220
196
 
221
197
 
222
- const csvParams = createSubscriptionParams({ search: this.state.searchQuery });
198
+ const csvParams = createSubscriptionParams({ search: searchQuery });
223
199
  const getEnabledColumns = (columns) => {
224
200
  const enabledColumns = [];
225
201
  columns.forEach((column) => {
@@ -253,7 +229,7 @@ class SubscriptionsPage extends Component {
253
229
  header: __('There are no Subscriptions to display'),
254
230
  description: __('Import a Manifest to manage your Entitlements.'),
255
231
  action: {
256
- onClick: showManageManifestModal,
232
+ onClick: () => openManageManifestModal(),
257
233
  title: __('Import a Manifest'),
258
234
  },
259
235
  };
@@ -264,67 +240,29 @@ class SubscriptionsPage extends Component {
264
240
  <Col sm={12}>
265
241
  <h1>{__('Red Hat Subscriptions')}</h1>
266
242
 
267
- <Row className="toolbar-pf table-view-pf-toolbar-external">
268
- <Col sm={12}>
269
- <Form className="toolbar-pf-actions">
270
- <FormGroup className="toolbar-pf-filter">
271
- <Search
272
- onSearch={onSearch}
273
- getAutoCompleteParams={getAutoCompleteParams}
274
- updateSearchQuery={updateSearchQuery}
275
- />
276
- </FormGroup>
277
- <div className="option-tooltip-container">
278
- <OptionTooltip options={tableColumns} icon="fa-columns" id="subscriptionTableTooltip" onChange={toolTipOnChange} onClose={toolTipOnclose} />
279
- </div>
280
- <div className="toolbar-pf-action-right">
281
- <FormGroup>
282
- <LinkContainer
283
- to="subscriptions/add"
284
- disabled={disableManifestActions || !manifestExists(organization)}
285
- >
286
- <TooltipButton
287
- tooltipId="add-subscriptions-button-tooltip"
288
- tooltipText={this.getDisabledReason()}
289
- tooltipPlacement="top"
290
- title={__('Add Subscriptions')}
291
- disabled={disableManifestActions}
292
- bsStyle="primary"
293
- />
294
- </LinkContainer>
295
-
296
- <Button onClick={showManageManifestModal}>
297
- {__('Manage Manifest')}
298
- </Button>
299
-
300
- <Button
301
- onClick={() => { api.open('/subscriptions.csv', csvParams); }}
302
- >
303
- {__('Export CSV')}
304
- </Button>
305
-
306
- <TooltipButton
307
- bsStyle="danger"
308
- onClick={showSubscriptionDeleteModal}
309
- tooltipId="delete-subscriptions-button-tooltip"
310
- tooltipText={this.getDisabledReason(true)}
311
- tooltipPlacement="top"
312
- title={__('Delete')}
313
- disabled={disableManifestActions || this.state.disableDeleteButton}
314
- />
315
-
316
- </FormGroup>
317
- </div>
318
- </Form>
319
- </Col>
320
- </Row>
243
+ <SubscriptionsToolbar
244
+ disableManifestActions={disableManifestActions}
245
+ disableManifestReason={this.getDisabledReason()}
246
+ disableDeleteButton={this.state.disableDeleteButton}
247
+ disableDeleteReason={this.getDisabledReason(true)}
248
+ disableAddButton={!manifestExists(organization)}
249
+ getAutoCompleteParams={getAutoCompleteParams}
250
+ updateSearchQuery={updateSearchQuery}
251
+ onDeleteButtonClick={openDeleteModal}
252
+ onSearch={onSearch}
253
+ onManageManifestButtonClick={openManageManifestModal}
254
+ onExportCsvButtonClick={() => { api.open('/subscriptions.csv', csvParams); }}
255
+ tableColumns={tableColumns}
256
+ toolTipOnChange={toolTipOnChange}
257
+ toolTipOnclose={toolTipOnclose}
258
+ />
321
259
 
322
260
  <ManageManifestModal
323
- showModal={this.state.manifestModalOpen}
261
+ showModal={manifestModalOpened}
324
262
  taskInProgress={taskInProgress}
325
263
  disableManifestActions={disableManifestActions}
326
264
  disabledReason={this.getDisabledReason()}
327
- onClose={onManageManifestModalClose}
265
+ onClose={closeManageManifestModal}
328
266
  upload={this.uploadManifest}
329
267
  delete={this.deleteManifest}
330
268
  refresh={this.refreshManifest}
@@ -337,8 +275,8 @@ class SubscriptionsPage extends Component {
337
275
  updateQuantity={this.props.updateQuantity}
338
276
  emptyState={emptyStateData}
339
277
  subscriptions={this.props.subscriptions}
340
- subscriptionDeleteModalOpen={this.state.subscriptionDeleteModalOpen}
341
- onSubscriptionDeleteModalClose={onSubscriptionDeleteModalClose}
278
+ subscriptionDeleteModalOpen={deleteModalOpened}
279
+ onSubscriptionDeleteModalClose={closeDeleteModal}
342
280
  onDeleteSubscriptions={onDeleteSubscriptions}
343
281
  toggleDeleteButton={toggleDeleteButton}
344
282
  task={task}
@@ -382,6 +320,14 @@ SubscriptionsPage.propTypes = {
382
320
  tasks: PropTypes.arrayOf(PropTypes.shape({})),
383
321
  deleteSubscriptions: PropTypes.func.isRequired,
384
322
  refreshManifest: PropTypes.func.isRequired,
323
+ searchQuery: PropTypes.string,
324
+ updateSearchQuery: PropTypes.func.isRequired,
325
+ openManageManifestModal: PropTypes.func.isRequired,
326
+ closeManageManifestModal: PropTypes.func.isRequired,
327
+ manifestModalOpened: PropTypes.bool,
328
+ deleteModalOpened: PropTypes.bool,
329
+ openDeleteModal: PropTypes.func.isRequired,
330
+ closeDeleteModal: PropTypes.func.isRequired,
385
331
  };
386
332
 
387
333
  SubscriptionsPage.defaultProps = {
@@ -389,6 +335,9 @@ SubscriptionsPage.defaultProps = {
389
335
  bulkSearch: undefined,
390
336
  taskDetails: {},
391
337
  organization: undefined,
338
+ searchQuery: '',
339
+ manifestModalOpened: false,
340
+ deleteModalOpened: false,
392
341
  };
393
342
 
394
343
  export default SubscriptionsPage;
@@ -0,0 +1,14 @@
1
+ export const selectSubscriptionsState = state =>
2
+ state.katello.subscriptions;
3
+
4
+ export const selectManifestModalOpened = state =>
5
+ selectSubscriptionsState(state).manifestModalOpened;
6
+
7
+ export const selectDeleteModalOpened = state =>
8
+ selectSubscriptionsState(state).deleteModalOpened;
9
+
10
+ export const selectSearchQuery = state =>
11
+ selectSubscriptionsState(state).searchQuery;
12
+
13
+ export const selectSubscriptionsTasks = state =>
14
+ selectSubscriptionsState(state).tasks;
@@ -1,5 +1,4 @@
1
1
  import React, { Component } from 'react';
2
- import ReactDOMServer from 'react-dom/server';
3
2
  import _ from 'lodash';
4
3
  import { translate as __ } from 'foremanReact/common/I18n';
5
4
  import PropTypes from 'prop-types';
@@ -114,7 +113,7 @@ class UpstreamSubscriptionsPage extends Component {
114
113
  </span>
115
114
  );
116
115
 
117
- notify({ message: ReactDOMServer.renderToStaticMarkup(message), type: 'success' });
116
+ notify({ message, type: 'success' });
118
117
  this.props.history.push('/subscriptions');
119
118
  }
120
119
  });
@@ -186,7 +185,6 @@ class UpstreamSubscriptionsPage extends Component {
186
185
  header: __('There are no Subscription Allocations to display'),
187
186
  description: __('Subscription Allocations allow you to export subscriptions from the Red Hat Customer Portal to ' +
188
187
  'an on-premise subscription management application such as Red Hat Satellite.'),
189
- docUrl: 'http://redhat.com',
190
188
  action: {
191
189
  title: __('Import a Manifest to Begin'),
192
190
  url: '/subscriptions',
@@ -146,7 +146,6 @@ exports[`upstream subscriptions page should render 1`] = `
146
146
  "url": "/subscriptions",
147
147
  },
148
148
  "description": "Subscription Allocations allow you to export subscriptions from the Red Hat Customer Portal to an on-premise subscription management application such as Red Hat Satellite.",
149
- "docUrl": "http://redhat.com",
150
149
  "header": "There are no Subscription Allocations to display",
151
150
  }
152
151
  }
@@ -0,0 +1,84 @@
1
+ import {
2
+ quantitiesRequestSuccessResponse,
3
+ loadQuantitiesSuccessActionPayload,
4
+ } from './subscriptions.fixtures';
5
+ import {
6
+ filterRHSubscriptions,
7
+ manifestExists,
8
+ selectSubscriptionsQuantitiesFromResponse,
9
+ } from '../SubscriptionHelpers';
10
+
11
+ describe('Subscription helper', () => {
12
+ it('should filter subscriptions without upstream_pool_id', () => {
13
+ const subscriptions = [
14
+ {
15
+ key: 'sub-1',
16
+ available: 3,
17
+ },
18
+ {
19
+ key: 'sub-2',
20
+ available: 4,
21
+ upstream_pool_id: ' ',
22
+ },
23
+ {
24
+ key: 'sub-3',
25
+ available: -5,
26
+ upstream_pool_id: ' ',
27
+ },
28
+ {
29
+ key: 'sub-4',
30
+ available: -1,
31
+ },
32
+ ];
33
+
34
+ const filteredSubscriptions = filterRHSubscriptions(subscriptions);
35
+
36
+ expect(filteredSubscriptions).toMatchSnapshot();
37
+ });
38
+
39
+ it('should filter redhat subscriptions', () => {
40
+ const subscriptions = [
41
+ {
42
+ key: 'sub-1',
43
+ available: 0,
44
+ upstream_pool_id: ' ',
45
+ },
46
+ {
47
+ key: 'sub-2',
48
+ available: 4,
49
+ upstream_pool_id: ' ',
50
+ },
51
+ {
52
+ key: 'sub-3',
53
+ available: -5,
54
+ upstream_pool_id: ' ',
55
+ },
56
+ {
57
+ key: 'sub-4',
58
+ available: 100,
59
+ upstream_pool_id: ' ',
60
+ },
61
+ ];
62
+
63
+ const filteredSubscriptions = filterRHSubscriptions(subscriptions);
64
+
65
+ expect(filteredSubscriptions).toMatchSnapshot();
66
+ });
67
+
68
+ it('should check if manifest exists in an organization', () => {
69
+ const upstreamConsumer = 'some-upstream-consumer';
70
+
71
+ expect(manifestExists({
72
+ owner_details: { upstreamConsumer },
73
+ })).toBe(upstreamConsumer);
74
+
75
+ expect(manifestExists({})).toBeFalsy();
76
+ });
77
+
78
+ it('should select subscriptions-quantities from api response', () => {
79
+ const quantities =
80
+ selectSubscriptionsQuantitiesFromResponse(quantitiesRequestSuccessResponse);
81
+
82
+ expect(quantities).toEqual(loadQuantitiesSuccessActionPayload);
83
+ });
84
+ });
@@ -2,6 +2,7 @@ import thunk from 'redux-thunk';
2
2
  import Immutable from 'seamless-immutable';
3
3
  import configureMockStore from 'redux-mock-store';
4
4
  import { mockRequest, mockErrorRequest, mockReset } from '../../../mockRequest';
5
+ import { testActionSnapshotWithFixtures } from '../../../move_to_pf/test-utils/testHelpers';
5
6
  import {
6
7
  requestSuccessResponse,
7
8
  requestSuccessResponseWithRHSubscriptions,
@@ -16,7 +17,17 @@ import {
16
17
  quantitiesRequestSuccessResponse,
17
18
  loadTableColumnsSuccessAction,
18
19
  } from './subscriptions.fixtures';
19
- import { loadSubscriptions, updateQuantity, loadAvailableQuantities, loadTableColumns } from '../SubscriptionActions';
20
+ import {
21
+ loadSubscriptions,
22
+ updateQuantity,
23
+ loadAvailableQuantities,
24
+ loadTableColumns,
25
+ updateSearchQuery,
26
+ openManageManifestModal,
27
+ closeManageManifestModal,
28
+ openDeleteModal,
29
+ closeDeleteModal,
30
+ } from '../SubscriptionActions';
20
31
 
21
32
  const mockStore = configureMockStore([thunk]);
22
33
  const store = mockStore({ subscriptions: Immutable({}) });
@@ -133,4 +144,18 @@ describe('subscription actions', () => {
133
144
  },
134
145
  );
135
146
  });
147
+
148
+ describe('manageManifestModal', () => testActionSnapshotWithFixtures({
149
+ 'it should open manage-manifest modal': () => openManageManifestModal(),
150
+ 'it should close manage-manifest modal': () => closeManageManifestModal(),
151
+ }));
152
+
153
+ describe('deleteModal', () => testActionSnapshotWithFixtures({
154
+ 'it should open delete modal': () => openDeleteModal(),
155
+ 'it should close delete modal': () => closeDeleteModal(),
156
+ }));
157
+
158
+ describe('searchQuery', () => testActionSnapshotWithFixtures({
159
+ 'it should update the search-query': () => updateSearchQuery('some-query'),
160
+ }));
136
161
  });
@@ -35,6 +35,11 @@ describe('subscriptions page', () => {
35
35
  uploadManifest={noop}
36
36
  deleteManifest={noop}
37
37
  refreshManifest={noop}
38
+ updateSearchQuery={noop}
39
+ openManageManifestModal={noop}
40
+ closeManageManifestModal={noop}
41
+ openDeleteModal={noop}
42
+ closeDeleteModal={noop}
38
43
  />);
39
44
  expect(toJson(page)).toMatchSnapshot();
40
45
  });
@@ -1,85 +1,187 @@
1
- import * as types from '../SubscriptionConstants';
1
+ import { testReducerSnapshotWithFixtures } from '../../../move_to_pf/test-utils/testHelpers';
2
2
 
3
+ import { GET_SETTING_SUCCESS } from '../../../move_to_foreman/Settings/SettingsConstants';
3
4
  import {
4
- initialState,
5
- loadingState,
6
- loadingQuantitiesState,
7
- requestSuccessResponse,
8
- quantitiesSuccessState,
9
- quantitiesRequestSuccessResponse,
10
- successState,
11
- errorState,
12
- quantitiesErrorState,
13
- loadingColumnsState,
14
- tableColumns,
15
- } from './subscriptions.fixtures';
5
+ SUBSCRIPTIONS_REQUEST,
6
+ SUBSCRIPTIONS_SUCCESS,
7
+ SUBSCRIPTIONS_FAILURE,
8
+ SUBSCRIPTIONS_COLUMNS_REQUEST,
9
+ UPDATE_SUBSCRIPTION_COLUMNS,
10
+ SUBSCRIPTIONS_QUANTITIES_REQUEST,
11
+ SUBSCRIPTIONS_QUANTITIES_SUCCESS,
12
+ SUBSCRIPTIONS_QUANTITIES_FAILURE,
13
+ UPDATE_QUANTITY_REQUEST,
14
+ UPDATE_QUANTITY_SUCCESS,
15
+ UPDATE_QUANTITY_FAILURE,
16
+ DELETE_SUBSCRIPTIONS_REQUEST,
17
+ DELETE_SUBSCRIPTIONS_SUCCESS,
18
+ DELETE_SUBSCRIPTIONS_FAILURE,
19
+ SUBSCRIPTIONS_UPDATE_SEARCH_QUERY,
20
+ SUBSCRIPTIONS_OPEN_MANIFEST_MODAL,
21
+ SUBSCRIPTIONS_CLOSE_MANIFEST_MODAL,
22
+ SUBSCRIPTIONS_OPEN_DELETE_MODAL,
23
+ SUBSCRIPTIONS_CLOSE_DELETE_MODAL,
24
+ TASK_BULK_SEARCH_SUCCESS,
25
+ GET_TASK_SUCCESS,
26
+ RESET_TASKS,
27
+ } from '../SubscriptionConstants';
16
28
  import reducer from '../SubscriptionReducer';
17
29
 
18
- describe('subscriptions reducer', () => {
19
- it('should return the initial state', () => {
20
- expect(reducer(undefined, {})).toEqual(initialState);
21
- });
22
-
23
- it('should keep loading state on SUBSCRIPTIONS_REQUEST', () => {
24
- expect(reducer(initialState, {
25
- type: types.SUBSCRIPTIONS_REQUEST,
26
- })).toEqual(loadingState);
27
- });
28
-
29
- it('should flatten subscriptions response SUBSCRIPTIONS_SUCCESS', () => {
30
- expect(reducer(initialState, {
31
- type: types.SUBSCRIPTIONS_SUCCESS,
32
- response: requestSuccessResponse,
33
- })).toEqual(successState);
34
- });
35
-
36
- it('should have error on SUBSCRIPTIONS_FAILURE', () => {
37
- expect(reducer(initialState, {
38
- type: types.SUBSCRIPTIONS_FAILURE,
30
+ const fixtures = {
31
+ 'should return the initial state': {},
32
+ 'should handle SUBSCRIPTIONS_REQUEST': {
33
+ action: {
34
+ type: SUBSCRIPTIONS_REQUEST,
35
+ },
36
+ },
37
+ 'should handle UPDATE_QUANTITY_REQUEST': {
38
+ action: {
39
+ type: UPDATE_QUANTITY_REQUEST,
40
+ },
41
+ },
42
+ 'should handle DELETE_SUBSCRIPTIONS_REQUEST': {
43
+ action: {
44
+ type: DELETE_SUBSCRIPTIONS_REQUEST,
45
+ },
46
+ },
47
+ 'should handle SUBSCRIPTIONS_COLUMNS_REQUEST': {
48
+ action: {
49
+ type: SUBSCRIPTIONS_COLUMNS_REQUEST,
39
50
  payload: {
40
- message: 'Unable to process request.',
51
+ tableColumns: ['col1', 'col2', 'col3'],
41
52
  },
42
- })).toEqual(errorState);
43
- });
44
-
45
- it('should have error on UPDATE_QUANTITY_FAILURE', () => {
46
- expect(reducer(initialState, {
47
- type: types.UPDATE_QUANTITY_FAILURE,
53
+ },
54
+ },
55
+ 'should handle UPDATE_SUBSCRIPTION_COLUMNS': {
56
+ action: {
57
+ type: UPDATE_SUBSCRIPTION_COLUMNS,
48
58
  payload: {
49
- message: 'Unable to process request.',
59
+ enabledColumns: ['col1', 'col2'],
50
60
  },
51
- })).toEqual(errorState);
52
- });
53
-
54
- it('should flip quantitiesLoading on SUBSCRIPTIONS_QUANTITIES_REQUEST', () => {
55
- expect(reducer(successState, {
56
- type: types.SUBSCRIPTIONS_QUANTITIES_REQUEST,
57
- })).toEqual(loadingQuantitiesState);
58
- });
59
-
60
- it('should flatten subscriptions response SUBSCRIPTIONS_QUANTITIES_SUCCESS', () => {
61
- expect(reducer(loadingQuantitiesState, {
62
- type: types.SUBSCRIPTIONS_QUANTITIES_SUCCESS,
63
- response: quantitiesRequestSuccessResponse,
64
- })).toEqual(quantitiesSuccessState);
65
- });
66
-
67
- it('should have error on SUBSCRIPTIONS_QUANTITIES_FAILURE', () => {
68
- expect(reducer(successState, {
69
- type: types.SUBSCRIPTIONS_QUANTITIES_FAILURE,
70
- payload: {
71
- message: 'Unable to process request.',
61
+ },
62
+ },
63
+ 'should handle SUBSCRIPTIONS_SUCCESS': {
64
+ action: {
65
+ type: SUBSCRIPTIONS_SUCCESS,
66
+ response: {
67
+ page: 1,
68
+ per_page: 10, // eslint-disable-line camelcase
69
+ subtotal: 20,
70
+ results: 'some-results',
72
71
  },
73
- })).toEqual(quantitiesErrorState);
74
- });
75
-
76
- it('should load table columns on a SUBSCRIPTIONS_COLUMNS_REQUEST', () => {
77
- const successTableColumnsState = { ...successState };
78
- successTableColumnsState.tableColumns = tableColumns;
72
+ search: 'some search',
73
+ },
74
+ },
75
+ 'should handle DELETE_SUBSCRIPTIONS_SUCCESS': {
76
+ action: {
77
+ type: DELETE_SUBSCRIPTIONS_SUCCESS,
78
+ },
79
+ },
80
+ 'should handle UPDATE_QUANTITY_SUCCESS': {
81
+ action: {
82
+ type: UPDATE_QUANTITY_SUCCESS,
83
+ },
84
+ },
85
+ 'should handle SUBSCRIPTIONS_FAILURE': {
86
+ action: {
87
+ type: SUBSCRIPTIONS_FAILURE,
88
+ },
89
+ },
90
+ 'should handle UPDATE_QUANTITY_FAILURE': {
91
+ action: {
92
+ type: UPDATE_QUANTITY_FAILURE,
93
+ },
94
+ },
95
+ 'should handle DELETE_SUBSCRIPTIONS_FAILURE': {
96
+ action: {
97
+ type: DELETE_SUBSCRIPTIONS_FAILURE,
98
+ },
99
+ },
100
+ 'should handle SUBSCRIPTIONS_QUANTITIES_REQUEST': {
101
+ action: {
102
+ type: SUBSCRIPTIONS_QUANTITIES_REQUEST,
103
+ },
104
+ },
105
+ 'should handle SUBSCRIPTIONS_QUANTITIES_SUCCESS': {
106
+ action: {
107
+ type: SUBSCRIPTIONS_QUANTITIES_SUCCESS,
108
+ payload: 'some-quantities-data',
109
+ },
110
+ },
111
+ 'should handle SUBSCRIPTIONS_QUANTITIES_FAILURE': {
112
+ action: {
113
+ type: SUBSCRIPTIONS_QUANTITIES_FAILURE,
114
+ },
115
+ },
116
+ 'should handle SUBSCRIPTIONS_UPDATE_SEARCH_QUERY': {
117
+ action: {
118
+ type: SUBSCRIPTIONS_UPDATE_SEARCH_QUERY,
119
+ payload: 'some-query',
120
+ },
121
+ },
122
+ 'should handle SUBSCRIPTIONS_OPEN_MANIFEST_MODAL': {
123
+ action: {
124
+ type: SUBSCRIPTIONS_OPEN_MANIFEST_MODAL,
125
+ },
126
+ },
127
+ 'should handle SUBSCRIPTIONS_CLOSE_MANIFEST_MODAL': {
128
+ action: {
129
+ type: SUBSCRIPTIONS_CLOSE_MANIFEST_MODAL,
130
+ },
131
+ },
132
+ 'should handle SUBSCRIPTIONS_OPEN_DELETE_MODAL': {
133
+ action: {
134
+ type: SUBSCRIPTIONS_OPEN_DELETE_MODAL,
135
+ },
136
+ },
137
+ 'should handle SUBSCRIPTIONS_CLOSE_DELETE_MODAL': {
138
+ action: {
139
+ type: SUBSCRIPTIONS_CLOSE_DELETE_MODAL,
140
+ },
141
+ },
142
+ 'should handle GET_SETTING_SUCCESS with content_disconnected response': {
143
+ action: {
144
+ type: GET_SETTING_SUCCESS,
145
+ response: {
146
+ name: 'content_disconnected',
147
+ value: 'some-value',
148
+ },
149
+ },
150
+ },
151
+ 'should handle GET_SETTING_SUCCESS without content_disconnected response': {
152
+ action: {
153
+ type: GET_SETTING_SUCCESS,
154
+ response: {
155
+ name: 'some-name',
156
+ value: 'some-value',
157
+ },
158
+ },
159
+ },
160
+ 'should handle TASK_BULK_SEARCH_SUCCESS': {
161
+ action: {
162
+ type: TASK_BULK_SEARCH_SUCCESS,
163
+ response: {
164
+ results: ['result1', 'result2'],
165
+ },
166
+ },
167
+ },
168
+ 'should handle GET_TASK_SUCCESS': {
169
+ action: {
170
+ type: GET_TASK_SUCCESS,
171
+ response: {
172
+ results: 'some-result',
173
+ },
174
+ },
175
+ },
176
+ 'should handle RESET_TASKS': {
177
+ action: {
178
+ type: RESET_TASKS,
179
+ response: {
180
+ results: 'some-result',
181
+ },
182
+ },
183
+ },
184
+ };
79
185
 
80
- expect(reducer(loadingColumnsState, {
81
- type: types.SUBSCRIPTIONS_COLUMNS_REQUEST,
82
- payload: { tableColumns },
83
- })).toEqual(successTableColumnsState);
84
- });
85
- });
186
+ describe('Subscriptions reducer', () =>
187
+ testReducerSnapshotWithFixtures(reducer, fixtures));