katello 3.7.1.1 → 3.8.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 (187) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -7
  3. data/app/assets/javascripts/katello/common/index.js +0 -1
  4. data/app/assets/javascripts/katello/sync_management/index.js +0 -1
  5. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +477 -0
  6. data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +1 -1
  7. data/app/controllers/katello/api/v2/activation_keys_controller.rb +2 -2
  8. data/app/controllers/katello/api/v2/api_controller.rb +3 -1
  9. data/app/controllers/katello/api/v2/content_credentials_controller.rb +1 -1
  10. data/app/controllers/katello/api/v2/content_view_filter_rules_controller.rb +1 -1
  11. data/app/controllers/katello/api/v2/content_view_versions_controller.rb +15 -1
  12. data/app/controllers/katello/api/v2/environments_controller.rb +5 -2
  13. data/app/controllers/katello/api/v2/errata_controller.rb +48 -34
  14. data/app/controllers/katello/api/v2/gpg_keys_controller.rb +1 -1
  15. data/app/controllers/katello/api/v2/host_collections_controller.rb +1 -1
  16. data/app/controllers/katello/api/v2/host_packages_controller.rb +5 -1
  17. data/app/controllers/katello/api/v2/organizations_controller.rb +1 -1
  18. data/app/controllers/katello/api/v2/packages_controller.rb +33 -22
  19. data/app/controllers/katello/api/v2/products_controller.rb +1 -1
  20. data/app/controllers/katello/api/v2/repositories_controller.rb +6 -5
  21. data/app/controllers/katello/api/v2/repository_sets_controller.rb +1 -10
  22. data/app/controllers/katello/api/v2/sync_plans_controller.rb +1 -1
  23. data/app/controllers/katello/concerns/api/v2/repository_content_controller.rb +20 -12
  24. data/app/controllers/katello/remote_execution_controller.rb +6 -6
  25. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +9 -37
  26. data/app/lib/actions/katello/content_view/promote.rb +6 -2
  27. data/app/lib/actions/katello/content_view_version/after_promote_hook.rb +11 -0
  28. data/app/lib/actions/katello/content_view_version/before_promote_hook.rb +11 -0
  29. data/app/lib/actions/katello/host/remove_subscriptions.rb +1 -1
  30. data/app/lib/actions/pulp/consumer/abstract_content_action.rb +0 -12
  31. data/app/lib/actions/pulp/consumer/content_install.rb +1 -1
  32. data/app/lib/actions/pulp/consumer/content_uninstall.rb +1 -1
  33. data/app/lib/actions/pulp/consumer/content_update.rb +1 -1
  34. data/app/lib/katello/resources/registry.rb +40 -0
  35. data/app/lib/katello/util/package.rb +9 -4
  36. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +1 -1
  37. data/app/models/katello/content_view.rb +4 -12
  38. data/app/models/katello/content_view_version.rb +26 -0
  39. data/app/models/katello/glue/candlepin/owner.rb +8 -0
  40. data/app/models/katello/glue/candlepin/pool.rb +11 -11
  41. data/app/models/katello/glue/candlepin/repository.rb +1 -1
  42. data/app/models/katello/glue/pulp/repos.rb +1 -0
  43. data/app/models/katello/host/content_facet.rb +1 -2
  44. data/app/models/katello/kt_environment.rb +6 -0
  45. data/app/models/katello/product_content.rb +1 -4
  46. data/app/models/katello/repository.rb +2 -0
  47. data/app/models/katello/rpm.rb +118 -14
  48. data/app/services/katello/puppet_class_importer_extensions.rb +17 -20
  49. data/app/services/katello/ui_notifications/pulp/proxy_disk_space.rb +1 -3
  50. data/app/views/katello/api/v2/common/copy.json.rabl +3 -0
  51. data/app/views/katello/api/v2/environments/show.json.rabl +1 -1
  52. data/app/views/katello/api/v2/repositories/base.json.rabl +1 -0
  53. data/app/views/katello/api/v2/repositories/show.json.rabl +4 -2
  54. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +3 -2
  55. data/config/katello.yaml +89 -0
  56. data/config/routes.rb +0 -1
  57. data/config/routes/api/registry.rb +29 -0
  58. data/config/routes/api/v2.rb +1 -1
  59. data/db/migrate/20180612163403_add_foreign_key_to_hypervisor_id.rb +0 -3
  60. data/db/migrate/20180614184822_add_unauthenticated_pull.rb +9 -0
  61. data/db/migrate/20180618195941_add_description_to_repository.rb +5 -0
  62. data/db/seeds.d/75-job_templates.rb +2 -5
  63. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-repository-sets-modal.controller.js +3 -4
  64. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-subscriptions-modal.controller.js +1 -4
  65. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-subscriptions-modal.html +1 -1
  66. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-host-register.controller.js +1 -1
  67. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +1 -1
  68. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-add-subscriptions.controller.js +1 -1
  69. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/content-views.routes.js +1 -0
  70. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/versions/content-view-version.controller.js +32 -18
  71. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/versions/views/content-view-version-details.html +1 -1
  72. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/versions/views/content-view-version-docker.html +2 -0
  73. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-details.html +32 -23
  74. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +6 -0
  75. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +8 -0
  76. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery.controller.js +1 -1
  77. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery-create.html +1 -1
  78. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +0 -5
  79. data/lib/katello/engine.rb +1 -0
  80. data/lib/katello/permission_creator.rb +2 -0
  81. data/lib/katello/permissions/registry_permissions.rb +20 -0
  82. data/lib/katello/plugin.rb +1 -0
  83. data/lib/katello/tasks/clean_backend_objects.rake +3 -12
  84. data/lib/katello/version.rb +1 -1
  85. data/package.json +7 -10
  86. data/webpack/components/Search/Search.test.js +1 -3
  87. data/webpack/containers/Application/config.js +2 -9
  88. data/webpack/containers/Application/index.js +2 -4
  89. data/webpack/mockRequest.js +3 -3
  90. data/webpack/move_to_foreman/common/helpers.js +8 -45
  91. data/webpack/move_to_foreman/components/common/{EmptyState → emptyState}/index.js +3 -16
  92. data/webpack/move_to_foreman/components/common/table/components/Table.js +1 -1
  93. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/CollapseSubscriptionGroupButton.test.js.snap +2 -2
  94. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionCell.test.js.snap +1 -1
  95. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionHeaderCell.test.js.snap +1 -1
  96. data/webpack/move_to_pf/LoadingState/LoadingState.js +14 -27
  97. data/webpack/move_to_pf/LoadingState/LoadingState.test.js +4 -8
  98. data/webpack/move_to_pf/react-bootstrap-select/index.js +1 -12
  99. data/webpack/redux/actions/RedHatRepositories/enabled.js +1 -0
  100. data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -5
  101. data/webpack/redux/actions/RedHatRepositories/sets.js +1 -1
  102. data/webpack/redux/consts.js +0 -6
  103. data/webpack/redux/reducers/index.js +0 -2
  104. data/webpack/scenes/RedHatRepositories/components/EnabledRepository.js +23 -14
  105. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository.js +1 -1
  106. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +0 -1
  107. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/RecommendedRepositorySetsToggler.test.js.snap +1 -3
  108. data/webpack/scenes/RedHatRepositories/index.js +3 -7
  109. data/webpack/scenes/RedHatRepositories/index.scss +0 -1
  110. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailActions.js +8 -3
  111. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +1 -30
  112. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +28 -111
  113. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailReducer.test.js +1 -3
  114. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetails.test.js +1 -6
  115. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +424 -519
  116. data/webpack/scenes/Subscriptions/Details/__tests__/subscriptionDetails.fixtures.js +4 -7
  117. data/webpack/scenes/Subscriptions/Details/index.js +3 -5
  118. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +34 -78
  119. data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +24 -5
  120. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +1 -9
  121. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +0 -3
  122. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestActions.test.js +8 -20
  123. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestHistoryReducer.test.js +1 -3
  124. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +7 -34
  125. data/webpack/scenes/Subscriptions/Manifest/__tests__/manifest.fixtures.js +16 -9
  126. data/webpack/scenes/Subscriptions/Manifest/index.js +0 -1
  127. data/webpack/scenes/Subscriptions/SubscriptionActions.js +26 -5
  128. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +0 -1
  129. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +0 -3
  130. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +4 -11
  131. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +36 -31
  132. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsActions.js +12 -3
  133. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +27 -57
  134. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsReducer.js +3 -2
  135. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsTableSchema.js +5 -10
  136. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsActions.test.js +5 -10
  137. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsPage.test.js +4 -49
  138. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsReducer.test.js +3 -8
  139. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +11 -21
  140. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/upstreamSubscriptions.fixtures.js +8 -5
  141. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +0 -2
  142. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +3 -9
  143. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +2 -14
  144. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +17 -11
  145. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/EntitlementsInlineEditFormatter.js +5 -8
  146. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +58 -45
  147. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +4 -11
  148. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableSchema.js +2 -2
  149. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +3 -16
  150. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +365 -392
  151. data/webpack/scenes/Subscriptions/index.js +0 -1
  152. data/webpack/services/api/fixtures.js +353 -0
  153. data/webpack/services/api/index.js +1 -17
  154. data/webpack/test_setup.js +0 -2
  155. metadata +16 -37
  156. data/config/katello.yml +0 -59
  157. data/webpack/__mocks__/foremanReact/components/BreadcrumbBar.js +0 -3
  158. data/webpack/__mocks__/foremanReact/redux.js +0 -3
  159. data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +0 -8
  160. data/webpack/components/SelectOrg/SelectOrg.scss +0 -3
  161. data/webpack/components/SelectOrg/SelectOrgAction.js +0 -41
  162. data/webpack/components/SelectOrg/SelectOrgReducer.js +0 -33
  163. data/webpack/components/SelectOrg/SetOrganization.js +0 -116
  164. data/webpack/components/WithOrganization/withOrganization.js +0 -28
  165. data/webpack/global_test_setup.js +0 -6
  166. data/webpack/helpers/caret.js +0 -6
  167. data/webpack/move_to_pf/Select/Select.js +0 -40
  168. data/webpack/scenes/Products/ProductActions.js +0 -24
  169. data/webpack/scenes/Products/ProductConstants.js +0 -3
  170. data/webpack/scenes/Products/__tests__/ProductActions.test.js +0 -40
  171. data/webpack/scenes/Products/__tests__/products.fixtures.js +0 -90
  172. data/webpack/scenes/RedHatRepositories/components/EnabledRepositoryContent.js +0 -34
  173. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepository.test.js +0 -36
  174. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepositoryContent.test.js +0 -27
  175. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepository.test.js.snap +0 -25
  176. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepositoryContent.test.js.snap +0 -47
  177. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailEnabledProducts.js +0 -54
  178. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProduct.js +0 -29
  179. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.scss +0 -9
  180. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailEnabledProducts.test.js +0 -18
  181. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailProduct.test.js +0 -13
  182. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailEnabledProducts.test.js.snap +0 -45
  183. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailProduct.test.js.snap +0 -67
  184. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/EntitlementsInlineEditFormatter.test.js +0 -110
  185. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/EntitlementsInlineEditFormatter.test.js.snap +0 -228
  186. data/webpack/scenes/Tasks/helpers.js +0 -52
  187. data/webpack/services/api/testHelpers.js +0 -28
@@ -5,7 +5,6 @@ import PropTypes from 'prop-types';
5
5
  import { LinkContainer } from 'react-router-bootstrap';
6
6
  import { Grid, Row, Col } from 'react-bootstrap';
7
7
  import { bindMethods, Button } from 'patternfly-react';
8
- import BreadcrumbsBar from 'foremanReact/components/BreadcrumbBar';
9
8
  import { LoadingState } from '../../../move_to_pf/LoadingState';
10
9
  import { notify } from '../../../move_to_foreman/foreman_toast_notifications';
11
10
  import helpers from '../../../move_to_foreman/common/helpers';
@@ -23,7 +22,6 @@ class UpstreamSubscriptionsPage extends Component {
23
22
  bindMethods(this, [
24
23
  'onChange',
25
24
  'saveUpstreamSubscriptions',
26
- 'quantityValidationInput',
27
25
  ]);
28
26
  }
29
27
 
@@ -33,17 +31,18 @@ class UpstreamSubscriptionsPage extends Component {
33
31
 
34
32
  onChange(value, rowData) {
35
33
  const { selectedRows } = this.state;
34
+ const newValue = parseInt(value, 10);
36
35
  const pool = {
37
36
  ...rowData,
38
37
  id: rowData.id,
39
- updatedQuantity: value,
38
+ updatedQuantity: newValue,
40
39
  selected: true,
41
40
  };
42
41
 
43
42
  const match = this.poolInSelectedRows(pool);
44
43
  const index = _.indexOf(selectedRows, match);
45
44
 
46
- if (value) {
45
+ if (newValue > 0) {
47
46
  if (match) {
48
47
  selectedRows.splice(index, 1, pool);
49
48
  } else {
@@ -56,25 +55,6 @@ class UpstreamSubscriptionsPage extends Component {
56
55
  this.setState({ selectedRows });
57
56
  }
58
57
 
59
- // eslint-disable-next-line class-methods-use-this
60
- quantityValidation(pool) {
61
- const origQuantity = pool.updatedQuantity;
62
- if (origQuantity && helpers.stringIsInteger(origQuantity)) {
63
- const parsedQuantity = parseInt(origQuantity, 10);
64
- const aboveZeroMsg = [false, __('Please enter a positive number above zero')];
65
-
66
- if (parsedQuantity.toString().length > 10) return [false, __('Please limit number to 10 digits')];
67
- if (!pool.available) return [false, __('No pools available')];
68
- // handling unlimited subscriptions, they show as -1
69
- if (pool.available === -1) return parsedQuantity ? [true, ''] : aboveZeroMsg;
70
- if (parsedQuantity > pool.available) return [false, __(`Quantity must not be above ${pool.available}`)];
71
- if (parsedQuantity <= 0) return aboveZeroMsg;
72
- } else {
73
- return [false, __('Please enter digits only')];
74
- }
75
- return [true, ''];
76
- }
77
-
78
58
  poolInSelectedRows(pool) {
79
59
  const { selectedRows } = this.state;
80
60
 
@@ -84,30 +64,16 @@ class UpstreamSubscriptionsPage extends Component {
84
64
  );
85
65
  }
86
66
 
87
- quantityValidationInput(pool) {
88
- if (!pool || pool.updatedQuantity === undefined) return null;
89
- if (this.quantityValidation(pool)[0]) {
90
- return 'success';
91
- }
92
- return 'error';
93
- }
94
-
95
- validateSelectedRows() {
96
- return Array.isArray(this.state.selectedRows) &&
97
- this.state.selectedRows.length &&
98
- this.state.selectedRows.every(pool => this.quantityValidation(pool)[0]);
99
- }
100
-
101
67
  saveUpstreamSubscriptions() {
102
68
  const updatedPools = _.map(
103
69
  this.state.selectedRows,
104
- pool => ({ ...pool, quantity: parseInt(pool.updatedQuantity, 10) }),
70
+ pool => ({ ...pool, quantity: pool.updatedQuantity }),
105
71
  );
106
72
 
107
73
  const updatedSubscriptions = { pools: updatedPools };
108
74
 
109
75
  this.props.saveUpstreamSubscriptions(updatedSubscriptions).then(() => {
110
- const { task } = this.props.upstreamSubscriptions;
76
+ const { task, error } = this.props.upstreamSubscriptions;
111
77
 
112
78
  // TODO: could probably factor this out into a task response component
113
79
  if (task) {
@@ -122,6 +88,18 @@ class UpstreamSubscriptionsPage extends Component {
122
88
 
123
89
  notify({ message: ReactDOMServer.renderToStaticMarkup(message), type: 'success' });
124
90
  this.props.history.push('/subscriptions');
91
+ } else {
92
+ let errorMessages = [];
93
+
94
+ if (error.errors) {
95
+ errorMessages = error.errors;
96
+ } else if (error.message) {
97
+ errorMessages.push(error.message);
98
+ }
99
+
100
+ for (let i = 0; i < errorMessages.length; i += 1) {
101
+ notify({ message: errorMessages[i], type: 'error' });
102
+ }
125
103
  }
126
104
  });
127
105
  }
@@ -143,8 +121,7 @@ class UpstreamSubscriptionsPage extends Component {
143
121
  <Button
144
122
  bsStyle="primary"
145
123
  type="submit"
146
- disabled={upstreamSubscriptions.loading ||
147
- !this.validateSelectedRows()}
124
+ disabled={upstreamSubscriptions.loading}
148
125
  onClick={this.saveUpstreamSubscriptions}
149
126
  >
150
127
  {__('Submit')}
@@ -193,9 +170,13 @@ class UpstreamSubscriptionsPage extends Component {
193
170
  description: __('Subscription Allocations allow you to export subscriptions from the Red Hat Customer Portal to ' +
194
171
  'an on-premise subscription management application such as Red Hat Satellite.'),
195
172
  docUrl: 'http://redhat.com',
173
+ documentation: {
174
+ title: __('Learn more about Subscription Allocations'),
175
+ url: 'http://redhat.com',
176
+ },
196
177
  action: {
197
- title: __('Import a Manifest to Begin'),
198
- url: '/subscriptions',
178
+ title: __('New Subscription Allocation'),
179
+ url: 'http://redhat.com',
199
180
  },
200
181
  });
201
182
 
@@ -231,19 +212,7 @@ class UpstreamSubscriptionsPage extends Component {
231
212
 
232
213
  return (
233
214
  <Grid bsClass="container-fluid">
234
- <BreadcrumbsBar data={{
235
- isSwitchable: false,
236
- breadcrumbItems: [
237
- {
238
- caption: __('Subscriptions'),
239
- onClick: () => this.props.history.push('/subscriptions'),
240
- },
241
- {
242
- caption: __('Add Subscriptions'),
243
- },
244
- ],
245
- }}
246
- />
215
+ <h1>{__('Add Subscriptions')}</h1>
247
216
 
248
217
  <LoadingState loading={upstreamSubscriptions.loading} loadingText={__('Loading')}>
249
218
  <Row>
@@ -266,12 +235,13 @@ class UpstreamSubscriptionsPage extends Component {
266
235
  }
267
236
 
268
237
  UpstreamSubscriptionsPage.propTypes = {
238
+ history: PropTypes.shape({ push: PropTypes.func }).isRequired,
269
239
  loadUpstreamSubscriptions: PropTypes.func.isRequired,
270
240
  saveUpstreamSubscriptions: PropTypes.func.isRequired,
271
241
  upstreamSubscriptions: PropTypes.shape({
272
242
  task: PropTypes.shape({}),
243
+ error: PropTypes.shape({}),
273
244
  }).isRequired,
274
- history: PropTypes.shape({ push: PropTypes.func.isRequired }).isRequired,
275
245
  };
276
246
 
277
247
  export default UpstreamSubscriptionsPage;
@@ -38,7 +38,7 @@ export default (state = initialState, action) => {
38
38
 
39
39
  case UPSTREAM_SUBSCRIPTIONS_FAILURE:
40
40
  return state.merge({
41
- error: action.payload.message,
41
+ error: action.error,
42
42
  loading: false,
43
43
  });
44
44
 
@@ -49,7 +49,8 @@ export default (state = initialState, action) => {
49
49
  return state.set('task', action.response).set('loading', false);
50
50
 
51
51
  case SAVE_UPSTREAM_SUBSCRIPTIONS_FAILURE: {
52
- return state.set('error', action.payload.message).set('loading', false);
52
+ const error = action.result.response.data;
53
+ return state.set('error', error).set('loading', false);
53
54
  }
54
55
 
55
56
  default:
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { FormGroup, FormControl, ControlLabel, HelpBlock } from 'react-bootstrap';
2
+ import { FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
3
3
  import helpers from '../../../move_to_foreman/common/helpers';
4
4
  import {
5
5
  headerFormatter,
@@ -71,7 +71,7 @@ export const columns = (controller, selectionController) => [
71
71
  },
72
72
  },
73
73
  {
74
- property: 'available',
74
+ property: 'quantity',
75
75
  header: {
76
76
  label: __('Available Entitlements'),
77
77
  formatters: [headerFormatter],
@@ -96,27 +96,22 @@ export const columns = (controller, selectionController) => [
96
96
  formatters: [
97
97
  (value, { rowData }) => (
98
98
  <td>
99
- <FormGroup
100
- validationState={controller.quantityValidationInput(rowData)}
101
- >
99
+ <FormGroup>
102
100
  <ControlLabel srOnly>{__('Number to Allocate')}</ControlLabel>
103
101
  <FormControl
104
102
  type="text"
105
103
  onBlur={e => controller.onChange(e.target.value, rowData)}
106
104
  defaultValue={rowData.updatedQuantity}
107
- onChange={(e) => {
108
- controller.onChange(e.target.value, rowData);
109
- }}
110
105
  onKeyDown={(e) => {
111
106
  const key = e.charCode ? e.charCode : e.keyCode;
112
107
  if (key === 13) {
108
+ controller.onChange(e.target.value, rowData);
113
109
  controller.saveUpstreamSubscriptions();
114
110
  e.preventDefault();
115
111
  }
116
112
  }}
117
113
  />
118
- {controller.quantityValidationInput(rowData) === 'error' &&
119
- <HelpBlock>{controller.quantityValidation(rowData)[1]}</HelpBlock>}
114
+ <div>{__('Max')} {rowData.quantity}</div>
120
115
  </FormGroup>
121
116
  </td>
122
117
  ),
@@ -1,3 +1,5 @@
1
+ import axios from 'axios';
2
+ import MockAdapter from 'axios-mock-adapter';
1
3
  import configureMockStore from 'redux-mock-store';
2
4
  import thunk from 'redux-thunk';
3
5
  import Immutable from 'seamless-immutable';
@@ -11,10 +13,10 @@ import {
11
13
  import { getTaskSuccessResponse } from '../../../Tasks/__tests__/task.fixtures';
12
14
 
13
15
  import { loadUpstreamSubscriptions, saveUpstreamSubscriptions } from '../UpstreamSubscriptionsActions';
14
- import { mock as mockApi, mockErrorRequest } from '../../../../mockRequest';
15
16
 
16
17
  const mockStore = configureMockStore([thunk]);
17
18
  const store = mockStore({ subscriptions: Immutable({}) });
19
+ const mockApi = new MockAdapter(axios);
18
20
 
19
21
  afterEach(() => {
20
22
  store.clearActions();
@@ -26,10 +28,7 @@ describe('upstream subscription actions', () => {
26
28
 
27
29
  describe('creates UPSTREAM_SUBSCRIPTIONS_REQUEST', () => {
28
30
  it('and then fails with 422', () => {
29
- mockErrorRequest({
30
- url,
31
- status: 422,
32
- });
31
+ mockApi.onGet(url).reply(422);
33
32
 
34
33
  return store.dispatch(loadUpstreamSubscriptions())
35
34
  .then(() => expect(store.getActions()).toEqual(getFailureActions));
@@ -49,11 +48,7 @@ describe('upstream subscription actions', () => {
49
48
  };
50
49
 
51
50
  it('and then fails with 422', () => {
52
- mockErrorRequest({
53
- url,
54
- status: 422,
55
- method: 'POST',
56
- });
51
+ mockApi.onPost(url).reply(422);
57
52
 
58
53
  return store.dispatch(saveUpstreamSubscriptions(subscriptionData))
59
54
  .then(() => expect(store.getActions()).toEqual(saveFailureActions));
@@ -6,62 +6,17 @@ import { successState } from './upstreamSubscriptions.fixtures';
6
6
  import { loadUpstreamSubscriptions, saveUpstreamSubscriptions } from '../UpstreamSubscriptionsActions';
7
7
 
8
8
  jest.mock('../../../../move_to_foreman/foreman_toast_notifications');
9
- jest.mock('foremanReact/components/BreadcrumbBar');
10
9
 
11
10
  describe('upstream subscriptions page', () => {
12
- let shallowWrapper;
13
11
  const mockHistory = { push: () => {} };
14
- beforeEach(() => {
15
- shallowWrapper = shallow(<UpstreamSubscriptionsPage
12
+
13
+ it('should render', async () => {
14
+ const page = shallow(<UpstreamSubscriptionsPage
16
15
  upstreamSubscriptions={successState}
17
16
  loadUpstreamSubscriptions={loadUpstreamSubscriptions}
18
17
  saveUpstreamSubscriptions={saveUpstreamSubscriptions}
19
18
  history={mockHistory}
20
19
  />);
21
- });
22
-
23
- it('should render', async () => {
24
- expect(toJson(shallowWrapper)).toMatchSnapshot();
25
- });
26
-
27
- it('should validate correct subscription quantities', async () => {
28
- const validPools = [
29
- { available: 10, updatedQuantity: 5 },
30
- { available: 10, updatedQuantity: '5' },
31
- { available: 10, updatedQuantity: '10' },
32
- { available: 10, updatedQuantity: '1' },
33
- { available: -1, updatedQuantity: '1000' },
34
- ];
35
- validPools.forEach((pool, i) => {
36
- // using object with index attribute to print out index on failure,
37
- // jest doesn't support messages on failure :(
38
- const result = shallowWrapper.instance().quantityValidation(pool)[0];
39
- expect({ index: i, result }).toEqual({ index: i, result: true });
40
- });
41
- });
42
-
43
- it('should invalidate incorrect subscription quantities', async () => {
44
- const invalidPools = [
45
- { available: 10, updatedQuantity: 11 },
46
- { available: 10, updatedQuantity: 'foo' },
47
- { available: 10, updatedQuantity: 0 },
48
- { available: 10, updatedQuantity: '0' },
49
- { available: 10, updatedQuantity: '11' },
50
- { available: 10, updatedQuantity: '2.0' },
51
- { available: 10, updatedQuantity: '2/3' },
52
- { available: -1, updatedQuantity: '-1' },
53
- { available: -1, updatedQuantity: '0' },
54
- { available: -1, updatedQuantity: 'foo' },
55
- { available: -1, updatedQuantity: '2/3' },
56
- { available: -1, updatedQuantity: '2.0' },
57
- { available: -1, updatedQuantity: '99999999999' },
58
- ];
59
-
60
- invalidPools.forEach((pool, i) => {
61
- // using object with index attribute to print out index on failure,
62
- // jest doesn't support messages on failure :(
63
- const result = shallowWrapper.instance().quantityValidation(pool)[0];
64
- expect({ index: i, result }).toEqual({ index: i, result: false });
65
- });
20
+ expect(toJson(page)).toMatchSnapshot();
66
21
  });
67
22
  });
@@ -37,9 +37,7 @@ describe('upstream subscriptions reducer', () => {
37
37
  it('should have error on UPSTREAM_SUBSCRIPTIONS_FAILURE', () => {
38
38
  expect(reducer(initialState, {
39
39
  type: types.UPSTREAM_SUBSCRIPTIONS_FAILURE,
40
- payload: {
41
- message: 'Unable to process request.',
42
- },
40
+ error: 'Unable to process request.',
43
41
  })).toEqual(errorState);
44
42
  });
45
43
 
@@ -50,13 +48,10 @@ describe('upstream subscriptions reducer', () => {
50
48
  })).toEqual(saveSuccessState);
51
49
  });
52
50
 
53
- it('should have error on SAVE_UPSTREAM_SUBSCRIPTIONS_FAILURE', () => {
51
+ it('should have error on SAVE_UPSTREAM_SUBSCRIPTIONS_SUCCESS', () => {
54
52
  expect(reducer(initialSaveState, {
55
53
  type: types.SAVE_UPSTREAM_SUBSCRIPTIONS_FAILURE,
56
- payload: {
57
- message: 'Unable to process request.',
58
- result: errorResult,
59
- },
54
+ result: errorResult,
60
55
  })).toEqual(saveErrorState);
61
56
  });
62
57
  });
@@ -6,26 +6,12 @@ exports[`upstream subscriptions page should render 1`] = `
6
6
  componentClass="div"
7
7
  fluid={false}
8
8
  >
9
- <BreadcrumbsBar
10
- data={
11
- Object {
12
- "breadcrumbItems": Array [
13
- Object {
14
- "caption": "Subscriptions",
15
- "onClick": [Function],
16
- },
17
- Object {
18
- "caption": "Add Subscriptions",
19
- },
20
- ],
21
- "isSwitchable": false,
22
- }
23
- }
24
- />
9
+ <h1>
10
+ Add Subscriptions
11
+ </h1>
25
12
  <LoadingState
26
13
  loading={false}
27
14
  loadingText="Loading"
28
- timeout={300}
29
15
  >
30
16
  <Row
31
17
  bsClass="row"
@@ -121,7 +107,7 @@ exports[`upstream subscriptions page should render 1`] = `
121
107
  ],
122
108
  "label": "Available Entitlements",
123
109
  },
124
- "property": "available",
110
+ "property": "quantity",
125
111
  },
126
112
  Object {
127
113
  "cell": Object {
@@ -142,11 +128,15 @@ exports[`upstream subscriptions page should render 1`] = `
142
128
  emptyState={
143
129
  Object {
144
130
  "action": Object {
145
- "title": "Import a Manifest to Begin",
146
- "url": "/subscriptions",
131
+ "title": "New Subscription Allocation",
132
+ "url": "http://redhat.com",
147
133
  },
148
134
  "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
135
  "docUrl": "http://redhat.com",
136
+ "documentation": Object {
137
+ "title": "Learn more about Subscription Allocations",
138
+ "url": "http://redhat.com",
139
+ },
150
140
  "header": "There are no Subscription Allocations to display",
151
141
  }
152
142
  }
@@ -203,7 +193,7 @@ exports[`upstream subscriptions page should render 1`] = `
203
193
  block={false}
204
194
  bsClass="btn"
205
195
  bsStyle="primary"
206
- disabled={true}
196
+ disabled={false}
207
197
  onClick={[Function]}
208
198
  type="submit"
209
199
  >
@@ -1,6 +1,5 @@
1
1
  import Immutable from 'seamless-immutable';
2
2
  import { getTaskSuccessResponse } from '../../../Tasks/__tests__/task.fixtures';
3
- import { toastErrorAction, failureAction } from '../../../../services/api/testHelpers';
4
3
 
5
4
  export const initialState = Immutable({
6
5
  loading: true,
@@ -136,8 +135,10 @@ export const getFailureActions = [
136
135
  {
137
136
  type: 'UPSTREAM_SUBSCRIPTIONS_REQUEST',
138
137
  },
139
- failureAction('UPSTREAM_SUBSCRIPTIONS_FAILURE'),
140
- toastErrorAction(),
138
+ {
139
+ result: new Error('Request failed with status code 422'),
140
+ type: 'UPSTREAM_SUBSCRIPTIONS_FAILURE',
141
+ },
141
142
  ];
142
143
 
143
144
  export const saveSuccessActions = [
@@ -154,6 +155,8 @@ export const saveFailureActions = [
154
155
  {
155
156
  type: 'SAVE_UPSTREAM_SUBSCRIPTIONS_REQUEST',
156
157
  },
157
- failureAction('SAVE_UPSTREAM_SUBSCRIPTIONS_FAILURE'),
158
- toastErrorAction(),
158
+ {
159
+ result: new Error('Request failed with status code 422'),
160
+ type: 'SAVE_UPSTREAM_SUBSCRIPTIONS_FAILURE',
161
+ },
159
162
  ];