katello 3.8.0.rc1 → 3.8.0.rc2

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 (123) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/katello/common/index.js +1 -0
  3. data/app/assets/javascripts/katello/sync_management/index.js +1 -0
  4. data/app/controllers/katello/api/registry/registry_proxies_controller.rb +1 -1
  5. data/app/controllers/katello/api/v2/environments_controller.rb +0 -1
  6. data/app/controllers/katello/api/v2/ostree_branches_controller.rb +1 -1
  7. data/app/controllers/katello/api/v2/repository_sets_controller.rb +10 -1
  8. data/app/controllers/katello/remote_execution_controller.rb +6 -6
  9. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +37 -9
  10. data/app/lib/katello/resources/registry.rb +4 -4
  11. data/app/models/katello/authorization/repository.rb +2 -1
  12. data/app/models/katello/content_view.rb +12 -4
  13. data/app/models/katello/glue/candlepin/owner.rb +0 -8
  14. data/app/models/katello/glue/candlepin/pool.rb +11 -11
  15. data/app/models/katello/kt_environment.rb +0 -6
  16. data/app/models/katello/product_content.rb +4 -1
  17. data/app/models/katello/rpm.rb +13 -5
  18. data/app/services/katello/ui_notifications/pulp/proxy_disk_space.rb +3 -1
  19. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +2 -3
  20. data/config/katello.yaml.example +5 -0
  21. data/config/routes.rb +1 -0
  22. data/db/seeds.d/75-job_templates.rb +5 -2
  23. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-details.html +43 -8
  24. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/discovery.controller.js +17 -2
  25. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery-create.html +1 -1
  26. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery.html +1 -1
  27. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +5 -0
  28. data/lib/katello/version.rb +1 -1
  29. data/package.json +11 -7
  30. data/webpack/__mocks__/foremanReact/components/BreadcrumbBar.js +3 -0
  31. data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +8 -0
  32. data/webpack/__mocks__/foremanReact/redux.js +3 -0
  33. data/webpack/components/Search/Search.test.js +3 -1
  34. data/webpack/components/SelectOrg/SelectOrg.scss +3 -0
  35. data/webpack/components/SelectOrg/SelectOrgAction.js +41 -0
  36. data/webpack/components/SelectOrg/SelectOrgReducer.js +33 -0
  37. data/webpack/components/SelectOrg/SetOrganization.js +116 -0
  38. data/webpack/components/WithOrganization/withOrganization.js +28 -0
  39. data/webpack/containers/Application/config.js +9 -2
  40. data/webpack/containers/Application/index.js +4 -2
  41. data/webpack/global_test_setup.js +6 -0
  42. data/webpack/helpers/caret.js +6 -0
  43. data/webpack/mockRequest.js +3 -3
  44. data/webpack/move_to_foreman/common/helpers.js +45 -8
  45. data/webpack/move_to_foreman/components/common/{emptyState → EmptyState}/index.js +16 -3
  46. data/webpack/move_to_foreman/components/common/table/components/Table.js +1 -1
  47. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/CollapseSubscriptionGroupButton.test.js.snap +2 -2
  48. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionCell.test.js.snap +1 -1
  49. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionHeaderCell.test.js.snap +1 -1
  50. data/webpack/move_to_pf/LoadingState/LoadingState.js +27 -14
  51. data/webpack/move_to_pf/LoadingState/LoadingState.test.js +8 -4
  52. data/webpack/move_to_pf/Select/Select.js +40 -0
  53. data/webpack/move_to_pf/react-bootstrap-select/index.js +12 -1
  54. data/webpack/redux/actions/RedHatRepositories/enabled.js +0 -1
  55. data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -5
  56. data/webpack/redux/actions/RedHatRepositories/sets.js +1 -1
  57. data/webpack/redux/consts.js +6 -0
  58. data/webpack/redux/reducers/index.js +2 -0
  59. data/webpack/scenes/RedHatRepositories/components/EnabledRepository.js +14 -23
  60. data/webpack/scenes/RedHatRepositories/components/EnabledRepositoryContent.js +34 -0
  61. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository.js +1 -1
  62. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +1 -0
  63. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepository.test.js +36 -0
  64. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepositoryContent.test.js +27 -0
  65. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepository.test.js.snap +25 -0
  66. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepositoryContent.test.js.snap +47 -0
  67. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/RecommendedRepositorySetsToggler.test.js.snap +3 -1
  68. data/webpack/scenes/RedHatRepositories/index.js +7 -3
  69. data/webpack/scenes/RedHatRepositories/index.scss +1 -0
  70. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailActions.js +3 -8
  71. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +5 -3
  72. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +1 -1
  73. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +44 -6
  74. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.scss +4 -0
  75. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailReducer.test.js +3 -1
  76. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetails.test.js +2 -1
  77. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailProducts.test.js.snap +113 -23
  78. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +23 -14
  79. data/webpack/scenes/Subscriptions/Details/__tests__/subscriptionDetails.fixtures.js +3 -4
  80. data/webpack/scenes/Subscriptions/Details/index.js +2 -2
  81. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +78 -34
  82. data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +5 -24
  83. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +9 -1
  84. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +3 -0
  85. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestActions.test.js +20 -8
  86. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestHistoryReducer.test.js +3 -1
  87. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +34 -7
  88. data/webpack/scenes/Subscriptions/Manifest/__tests__/manifest.fixtures.js +9 -16
  89. data/webpack/scenes/Subscriptions/Manifest/index.js +1 -0
  90. data/webpack/scenes/Subscriptions/SubscriptionActions.js +5 -26
  91. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -0
  92. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +3 -0
  93. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +11 -4
  94. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +31 -36
  95. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsActions.js +3 -12
  96. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +57 -27
  97. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsReducer.js +2 -3
  98. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsTableSchema.js +10 -5
  99. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsActions.test.js +10 -5
  100. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsPage.test.js +50 -5
  101. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsReducer.test.js +8 -3
  102. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +21 -11
  103. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/upstreamSubscriptions.fixtures.js +5 -8
  104. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +2 -0
  105. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsReducer.test.js +9 -3
  106. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +14 -2
  107. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +11 -17
  108. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/EntitlementsInlineEditFormatter.js +8 -5
  109. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +45 -58
  110. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +11 -4
  111. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableSchema.js +2 -2
  112. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/EntitlementsInlineEditFormatter.test.js +110 -0
  113. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +16 -3
  114. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/EntitlementsInlineEditFormatter.test.js.snap +228 -0
  115. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +392 -365
  116. data/webpack/scenes/Subscriptions/index.js +1 -0
  117. data/webpack/scenes/Tasks/helpers.js +52 -0
  118. data/webpack/services/api/index.js +17 -1
  119. data/webpack/services/api/testHelpers.js +28 -0
  120. data/webpack/test_setup.js +2 -0
  121. metadata +24 -5
  122. data/config/katello.yaml +0 -89
  123. data/webpack/services/api/fixtures.js +0 -353
@@ -5,72 +5,162 @@ exports[`subscription detail product page renders correctly 1`] = `
5
5
  <h2>
6
6
  Provided Products
7
7
  </h2>
8
- <ul>
9
- <li>
8
+ <ul
9
+ className="scrolld-list list-group"
10
+ >
11
+ <li
12
+ className="list-group-item"
13
+ >
14
+
10
15
  Red Hat OpenShift Container Platform
16
+
11
17
  </li>
12
- <li>
18
+ <li
19
+ className="list-group-item"
20
+ >
21
+
13
22
  Oracle Java for RHEL Server
23
+
14
24
  </li>
15
- <li>
25
+ <li
26
+ className="list-group-item"
27
+ >
28
+
16
29
  Red Hat OpenShift Enterprise JBoss EAP add-on
30
+
17
31
  </li>
18
- <li>
32
+ <li
33
+ className="list-group-item"
34
+ >
35
+
19
36
  Red Hat CloudForms Beta
37
+
20
38
  </li>
21
- <li>
39
+ <li
40
+ className="list-group-item"
41
+ >
42
+
22
43
  Red Hat CloudForms
44
+
23
45
  </li>
24
- <li>
46
+ <li
47
+ className="list-group-item"
48
+ >
49
+
25
50
  Red Hat OpenShift Enterprise Client Tools
51
+
26
52
  </li>
27
- <li>
53
+ <li
54
+ className="list-group-item"
55
+ >
56
+
28
57
  Red Hat Enterprise Linux Atomic Host
58
+
29
59
  </li>
30
- <li>
60
+ <li
61
+ className="list-group-item"
62
+ >
63
+
31
64
  JBoss Enterprise Application Platform
65
+
32
66
  </li>
33
- <li>
67
+ <li
68
+ className="list-group-item"
69
+ >
70
+
34
71
  Red Hat JBoss AMQ Clients
72
+
35
73
  </li>
36
- <li>
74
+ <li
75
+ className="list-group-item"
76
+ >
77
+
37
78
  Red Hat Beta
79
+
38
80
  </li>
39
- <li>
81
+ <li
82
+ className="list-group-item"
83
+ >
84
+
40
85
  Red Hat OpenShift Enterprise Infrastructure
86
+
41
87
  </li>
42
- <li>
88
+ <li
89
+ className="list-group-item"
90
+ >
91
+
43
92
  Red Hat Enterprise Linux Fast Datapath Beta
93
+
44
94
  </li>
45
- <li>
95
+ <li
96
+ className="list-group-item"
97
+ >
98
+
46
99
  Red Hat Ansible Engine
100
+
47
101
  </li>
48
- <li>
102
+ <li
103
+ className="list-group-item"
104
+ >
105
+
49
106
  Red Hat OpenShift Enterprise Application Node
107
+
50
108
  </li>
51
- <li>
109
+ <li
110
+ className="list-group-item"
111
+ >
112
+
52
113
  Red Hat OpenShift Enterprise JBoss FUSE add-on
114
+
53
115
  </li>
54
- <li>
116
+ <li
117
+ className="list-group-item"
118
+ >
119
+
55
120
  Red Hat Software Collections Beta for RHEL Server
121
+
56
122
  </li>
57
- <li>
123
+ <li
124
+ className="list-group-item"
125
+ >
126
+
58
127
  Red Hat Software Collections for RHEL Server
128
+
59
129
  </li>
60
- <li>
130
+ <li
131
+ className="list-group-item"
132
+ >
133
+
61
134
  Red Hat Enterprise Linux Fast Datapath
135
+
62
136
  </li>
63
- <li>
137
+ <li
138
+ className="list-group-item"
139
+ >
140
+
64
141
  Red Hat Enterprise Linux Server
142
+
65
143
  </li>
66
- <li>
144
+ <li
145
+ className="list-group-item"
146
+ >
147
+
67
148
  Red Hat OpenShift Enterprise JBoss A-MQ add-on
149
+
68
150
  </li>
69
- <li>
151
+ <li
152
+ className="list-group-item"
153
+ >
154
+
70
155
  JBoss Enterprise Web Server
156
+
71
157
  </li>
72
- <li>
158
+ <li
159
+ className="list-group-item"
160
+ >
161
+
73
162
  Red Hat JBoss Core Services
163
+
74
164
  </li>
75
165
  </ul>
76
166
  </div>
@@ -6,25 +6,34 @@ exports[`subscriptions details page should render and contain appropiate compone
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": "OpenShift Employee Subscription",
19
+ },
20
+ ],
21
+ "isSwitchable": true,
22
+ "resource": Object {
23
+ "nameField": "name",
24
+ "resourceUrl": "/katello/api/v2/subscriptions",
25
+ "switcherItemUrl": "/subscriptions/:id",
26
+ },
27
+ }
28
+ }
29
+ onSwitcherItemClick={[Function]}
30
+ />
9
31
  <div>
10
32
  <LoadingState
11
33
  loading={false}
12
34
  loadingText="Loading"
35
+ timeout={300}
13
36
  >
14
- <Row
15
- bsClass="row"
16
- componentClass="div"
17
- >
18
- <Col
19
- bsClass="col"
20
- componentClass="div"
21
- sm={12}
22
- >
23
- <h1>
24
- OpenShift Employee Subscription
25
- </h1>
26
- </Col>
27
- </Row>
28
37
  <Row
29
38
  bsClass="row"
30
39
  componentClass="div"
@@ -1,4 +1,5 @@
1
1
  import Immutable from 'seamless-immutable';
2
+ import { toastErrorAction, failureAction } from '../../../../services/api/testHelpers';
2
3
 
3
4
  export const initialState = Immutable({
4
5
  loading: false,
@@ -148,10 +149,8 @@ export const loadSubscriptionsDetailsFailureActions = [
148
149
  {
149
150
  type: 'SUBSCRIPTION_DETAILS_REQUEST',
150
151
  },
151
- {
152
- error: 'Request failed with status code 500',
153
- type: 'SUBSCRIPTION_DETAILS_FAILURE',
154
- },
152
+ failureAction('SUBSCRIPTION_DETAILS_FAILURE', 'Request failed with status code 500'),
153
+ toastErrorAction('Request failed with status code 500'),
155
154
  ];
156
155
 
157
156
  export const loadSubscriptionsDetailsSuccessActions = [
@@ -1,6 +1,6 @@
1
1
  import { bindActionCreators } from 'redux';
2
2
  import { connect } from 'react-redux';
3
-
3
+ import { withRouter } from 'react-router';
4
4
  import reducer from './SubscriptionDetailReducer';
5
5
  import * as subscriptionDetailActions from './SubscriptionDetailActions';
6
6
  import SubscriptionDetails from './SubscriptionDetails';
@@ -16,4 +16,4 @@ const mapDispatchToProps = dispatch => bindActionCreators(subscriptionDetailActi
16
16
  export const subscriptionDetails = reducer;
17
17
 
18
18
  // export connected component
19
- export default connect(mapStateToProps, mapDispatchToProps)(SubscriptionDetails);
19
+ export default connect(mapStateToProps, mapDispatchToProps)(withRouter(SubscriptionDetails));
@@ -1,13 +1,15 @@
1
1
  import React, { Component } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Col, Tabs, Tab, Form, FormGroup, FormControl, ControlLabel } from 'react-bootstrap';
3
+ import { Col, Tabs, Tab, Form, FormGroup, FormControl, ControlLabel, Row } from 'react-bootstrap';
4
4
  import { bindMethods, Button, Icon, Modal, Spinner, OverlayTrigger, Tooltip } from 'patternfly-react';
5
5
  import { isEqual } from 'lodash';
6
6
  import TooltipButton from 'react-bootstrap-tooltip-button';
7
7
  import { LoadingState } from '../../../move_to_pf/LoadingState';
8
8
  import { Table } from '../../../move_to_foreman/components/common/table';
9
- import { columns } from './ManifestHistoryTableSchema';
10
9
  import ConfirmDialog from '../../../move_to_foreman/components/common/ConfirmDialog';
10
+ import { manifestExists } from '../SubscriptionHelpers';
11
+ import { columns } from './ManifestHistoryTableSchema';
12
+ import { renderTaskStartedToast } from '../../Tasks/helpers';
11
13
  import DeleteManifestModalText from './DeleteManifestModalText';
12
14
  import {
13
15
  BLOCKING_FOREMAN_TASK_TYPES,
@@ -30,15 +32,11 @@ class ManageManifestModal extends Component {
30
32
  'uploadManifest',
31
33
  'refreshManifest',
32
34
  'deleteManifest',
33
- 'manifestExists',
34
35
  'disabledTooltipText',
36
+ 'updateRepositoryUrl',
35
37
  ]);
36
38
  }
37
39
 
38
- componentDidMount() {
39
- this.loadData();
40
- }
41
-
42
40
  static getDerivedStateFromProps(newProps, prevState) {
43
41
  if (
44
42
  !isEqual(newProps.showModal, prevState.showModal) ||
@@ -52,6 +50,10 @@ class ManageManifestModal extends Component {
52
50
  return null;
53
51
  }
54
52
 
53
+ componentDidMount() {
54
+ this.loadData();
55
+ }
56
+
55
57
  componentDidUpdate(prevProp, prevState) {
56
58
  const { actionInProgress } = this.state;
57
59
 
@@ -69,14 +71,27 @@ class ManageManifestModal extends Component {
69
71
  this.props.onClose();
70
72
  }
71
73
 
72
- saveOrganization(event) {
73
- this.props.saveOrganization({ redhat_repository_url: event.target.value });
74
+ updateRepositoryUrl(event) {
75
+ this.setState({ redhat_repository_url: event.target.value });
76
+ }
77
+
78
+ saveOrganization() {
79
+ this.props.saveOrganization({ redhat_repository_url: this.state.redhat_repository_url });
74
80
  }
75
81
 
76
82
  uploadManifest(fileList) {
77
83
  this.setState({ actionInProgress: true });
78
84
  if (fileList.length > 0) {
79
- this.props.uploadManifest(fileList[0]);
85
+ this.props
86
+ .uploadManifest(fileList[0])
87
+ .then(() =>
88
+ this.props.bulkSearch({
89
+ search_id: MANIFEST_TASKS_BULK_SEARCH_ID,
90
+ type: 'all',
91
+ active_only: true,
92
+ action_types: BLOCKING_FOREMAN_TASK_TYPES,
93
+ }))
94
+ .then(() => renderTaskStartedToast(this.props.taskDetails));
80
95
  }
81
96
  }
82
97
 
@@ -87,14 +102,16 @@ class ManageManifestModal extends Component {
87
102
 
88
103
  deleteManifest() {
89
104
  this.setState({ actionInProgress: true });
90
- this.props.deleteManifest()
105
+ this.props
106
+ .deleteManifest()
91
107
  .then(() =>
92
108
  this.props.bulkSearch({
93
109
  search_id: MANIFEST_TASKS_BULK_SEARCH_ID,
94
110
  type: 'all',
95
111
  active_only: true,
96
112
  action_types: BLOCKING_FOREMAN_TASK_TYPES,
97
- }));
113
+ }))
114
+ .then(() => renderTaskStartedToast(this.props.taskDetails));
98
115
  this.showDeleteManifestModal(false);
99
116
  }
100
117
 
@@ -111,15 +128,12 @@ class ManageManifestModal extends Component {
111
128
  return __('This is disabled because no manifest exists');
112
129
  }
113
130
 
114
- manifestExists() {
115
- const { organization } = this.props;
116
-
117
- return organization.owner_details && organization.owner_details.upstreamConsumer;
118
- }
119
-
120
131
  render() {
121
132
  const {
122
- manifestHistory, organization, disableManifestActions, disabledReason,
133
+ manifestHistory,
134
+ organization,
135
+ disableManifestActions,
136
+ disabledReason,
123
137
  } = this.props;
124
138
 
125
139
  const { actionInProgress } = this.state;
@@ -132,13 +146,23 @@ class ManageManifestModal extends Component {
132
146
  url: 'http://redhat.com',
133
147
  },
134
148
  });
135
-
149
+ const buttonLoading = (
150
+ <span>
151
+ {__('Updating...')}
152
+ <span className="fa fa-spinner fa-spin" />
153
+ </span>);
136
154
  const getManifestName = () => {
137
155
  let name = __('No Manifest Uploaded');
138
156
 
139
- if (organization.owner_details && organization.owner_details.upstreamConsumer) {
140
- const link = ['https://', organization.owner_details.upstreamConsumer.webUrl,
141
- organization.owner_details.upstreamConsumer.uuid].join('/');
157
+ if (
158
+ organization.owner_details &&
159
+ organization.owner_details.upstreamConsumer
160
+ ) {
161
+ const link = [
162
+ 'https://',
163
+ organization.owner_details.upstreamConsumer.webUrl,
164
+ organization.owner_details.upstreamConsumer.uuid,
165
+ ].join('/');
142
166
 
143
167
  name = (
144
168
  <a href={link}>{organization.owner_details.upstreamConsumer.name}</a>
@@ -151,7 +175,11 @@ class ManageManifestModal extends Component {
151
175
  return (
152
176
  <Modal show={this.state.showModal} onHide={this.hideModal}>
153
177
  <Modal.Header>
154
- <button className="close" onClick={this.hideModal} aria-label={__('Close')}>
178
+ <button
179
+ className="close"
180
+ onClick={this.hideModal}
181
+ aria-label={__('Close')}
182
+ >
155
183
  <Icon type="pf" name="close" />
156
184
  </button>
157
185
  <Modal.Title>{__('Manage Manifest')}</Modal.Title>
@@ -163,29 +191,43 @@ class ManageManifestModal extends Component {
163
191
  <h5>{__('Red Hat Provider Details')}</h5>
164
192
  <hr />
165
193
  <FormGroup>
166
- <ControlLabel className="col-sm-3" htmlFor="cdnUrl">
167
- {__('Red Hat CDN URL')}
168
- </ControlLabel>
194
+ <Col sm={3}>
195
+ <ControlLabel htmlFor="cdnUrl">
196
+ {__('Red Hat CDN URL')}
197
+ </ControlLabel>
198
+ </Col>
169
199
  <Col sm={9}>
170
200
  <FormControl
171
201
  id="cdnUrl"
172
202
  type="text"
173
- value={organization.redhat_repository_url || ''}
174
- onChange={this.saveOrganization}
203
+ value={this.state.redhat_repository_url || organization.redhat_repository_url || ''}
204
+ onChange={this.updateRepositoryUrl}
175
205
  />
176
206
  </Col>
177
207
  </FormGroup>
208
+ <FormGroup>
209
+ <Col smOffset={3} sm={3}>
210
+ <Button onClick={this.saveOrganization} disabled={organization.loading}>
211
+ {organization.loading ? buttonLoading : __('Update')}
212
+ </Button>
213
+ </Col>
214
+ </FormGroup>
178
215
  <br />
179
216
 
180
217
  <h5>{__('Subscription Manifest')}</h5>
181
218
  <hr />
182
219
 
183
220
  <FormGroup>
184
- <ControlLabel className="col-sm-3 control-label" htmlFor="usmaFile">
221
+ <ControlLabel
222
+ className="col-sm-3 control-label"
223
+ htmlFor="usmaFile"
224
+ >
185
225
  <OverlayTrigger
186
226
  overlay={
187
- <Tooltip id="usma-tooltip">{__('Upstream Subscription Management Application')}</Tooltip>
188
- }
227
+ <Tooltip id="usma-tooltip">
228
+ {__('Upstream Subscription Management Application')}
229
+ </Tooltip>
230
+ }
189
231
  placement="bottom"
190
232
  trigger={['hover', 'focus']}
191
233
  rootClose={false}
@@ -213,7 +255,7 @@ class ManageManifestModal extends Component {
213
255
  tooltipText={disabledReason}
214
256
  tooltipPlacement="top"
215
257
  title={__('Refresh')}
216
- disabled={!this.manifestExists() ||
258
+ disabled={!manifestExists(organization) ||
217
259
  actionInProgress || disableManifestActions}
218
260
  />
219
261
 
@@ -223,7 +265,7 @@ class ManageManifestModal extends Component {
223
265
  tooltipText={this.disabledTooltipText()}
224
266
  tooltipPlacement="top"
225
267
  title={__('Delete')}
226
- disabled={!this.manifestExists() || actionInProgress}
268
+ disabled={!manifestExists(organization) || actionInProgress}
227
269
  />
228
270
 
229
271
  <ConfirmDialog
@@ -278,9 +320,11 @@ ManageManifestModal.propTypes = {
278
320
  showModal: PropTypes.bool.isRequired,
279
321
  onClose: PropTypes.func,
280
322
  bulkSearch: PropTypes.func.isRequired,
323
+ taskDetails: PropTypes.shape({}),
281
324
  };
282
325
 
283
326
  ManageManifestModal.defaultProps = {
327
+ taskDetails: undefined,
284
328
  disableManifestActions: false,
285
329
  disabledReason: '',
286
330
  onClose() {},
@@ -1,5 +1,6 @@
1
1
  import api, { orgId } from '../../../services/api';
2
2
  import { propsToSnakeCase } from '../../../services/index';
3
+ import { apiError } from '../../../move_to_foreman/common/helpers.js';
3
4
 
4
5
  import {
5
6
  UPLOAD_MANIFEST_REQUEST,
@@ -34,12 +35,7 @@ export const uploadManifest = file => (dispatch) => {
34
35
  response: data,
35
36
  });
36
37
  })
37
- .catch((result) => {
38
- dispatch({
39
- type: UPLOAD_MANIFEST_FAILURE,
40
- result,
41
- });
42
- });
38
+ .catch(result => dispatch(apiError(UPLOAD_MANIFEST_FAILURE, result)));
43
39
  };
44
40
 
45
41
  export const refreshManifest = (extendedParams = {}) => (dispatch) => {
@@ -57,12 +53,7 @@ export const refreshManifest = (extendedParams = {}) => (dispatch) => {
57
53
  response: data,
58
54
  });
59
55
  })
60
- .catch((result) => {
61
- dispatch({
62
- type: REFRESH_MANIFEST_FAILURE,
63
- result,
64
- });
65
- });
56
+ .catch(result => dispatch(apiError(REFRESH_MANIFEST_FAILURE, result)));
66
57
  };
67
58
 
68
59
  export const deleteManifest = (extendedParams = {}) => (dispatch) => {
@@ -80,12 +71,7 @@ export const deleteManifest = (extendedParams = {}) => (dispatch) => {
80
71
  response: data,
81
72
  });
82
73
  })
83
- .catch((result) => {
84
- dispatch({
85
- type: DELETE_MANIFEST_FAILURE,
86
- result,
87
- });
88
- });
74
+ .catch(result => dispatch(apiError(DELETE_MANIFEST_FAILURE, result)));
89
75
  };
90
76
 
91
77
  export const loadManifestHistory = (extendedParams = {}) => (dispatch) => {
@@ -103,12 +89,7 @@ export const loadManifestHistory = (extendedParams = {}) => (dispatch) => {
103
89
  response: data,
104
90
  });
105
91
  })
106
- .catch((result) => {
107
- dispatch({
108
- type: MANIFEST_HISTORY_FAILURE,
109
- result,
110
- });
111
- });
92
+ .catch(result => dispatch(apiError(MANIFEST_HISTORY_FAILURE, result)));
112
93
  };
113
94
 
114
95
  export default loadManifestHistory;
@@ -4,6 +4,8 @@ import {
4
4
  MANIFEST_HISTORY_REQUEST,
5
5
  MANIFEST_HISTORY_SUCCESS,
6
6
  MANIFEST_HISTORY_FAILURE,
7
+ UPLOAD_MANIFEST_SUCCESS,
8
+ DELETE_MANIFEST_SUCCESS,
7
9
  } from './ManifestConstants';
8
10
 
9
11
  const initialState = Immutable({ loading: true, results: [] });
@@ -24,10 +26,16 @@ export default (state = initialState, action) => {
24
26
 
25
27
  case MANIFEST_HISTORY_FAILURE:
26
28
  return state.merge({
27
- error: action.error,
29
+ error: action.payload.message,
28
30
  loading: false,
29
31
  });
30
32
 
33
+ case UPLOAD_MANIFEST_SUCCESS:
34
+ return state.set('taskDetails', action.response);
35
+
36
+ case DELETE_MANIFEST_SUCCESS:
37
+ return state.set('taskDetails', action.response);
38
+
31
39
  default:
32
40
  return state;
33
41
  }
@@ -4,6 +4,8 @@ import toJson from 'enzyme-to-json';
4
4
  import ManageManifestModal from '../ManageManifestModal';
5
5
  import { manifestHistorySuccessState } from './manifest.fixtures';
6
6
 
7
+ jest.mock('../../../../move_to_foreman/foreman_toast_notifications');
8
+
7
9
  describe('manage manifest modal', () => {
8
10
  const noop = () => {};
9
11
  const organization = { id: 1, redhat_repository_url: 'https://redhat.com' };
@@ -17,6 +19,7 @@ describe('manage manifest modal', () => {
17
19
  organization={organization}
18
20
  loadOrganization={noop}
19
21
  saveOrganization={noop}
22
+ bulkSearch={noop}
20
23
  manifestHistory={manifestHistorySuccessState}
21
24
  taskInProgress={false}
22
25
  showModal
@@ -1,5 +1,3 @@
1
- import axios from 'axios';
2
- import MockAdapter from 'axios-mock-adapter';
3
1
  import thunk from 'redux-thunk';
4
2
  import Immutable from 'seamless-immutable';
5
3
  import configureMockStore from 'redux-mock-store';
@@ -15,12 +13,11 @@ import {
15
13
  deleteManifestSuccessActions,
16
14
  deleteManifestFailureActions,
17
15
  } from './manifest.fixtures';
18
-
19
16
  import { loadManifestHistory, uploadManifest, refreshManifest, deleteManifest } from '../ManifestActions';
17
+ import { mock as mockApi, mockErrorRequest } from '../../../../mockRequest';
20
18
 
21
19
  const mockStore = configureMockStore([thunk]);
22
20
  const store = mockStore({ manifest: Immutable({}) });
23
- const mockApi = new MockAdapter(axios);
24
21
 
25
22
  beforeEach(() => {
26
23
  store.clearActions();
@@ -43,7 +40,10 @@ describe('manifest actions', () => {
43
40
  const url = '/katello/api/v2/organizations/1/subscriptions/manifest_history';
44
41
 
45
42
  it('and then fails with 422', () => {
46
- mockApi.onGet(url).reply(422);
43
+ mockErrorRequest({
44
+ url,
45
+ status: 422,
46
+ });
47
47
 
48
48
  return store.dispatch(loadManifestHistory())
49
49
  .then(() => expect(store.getActions()).toEqual(manifestHistoryFailureActions));
@@ -61,7 +61,11 @@ describe('manifest actions', () => {
61
61
  const url = '/katello/api/v2/organizations/1/subscriptions/upload';
62
62
 
63
63
  it('and then fails with 422', () => {
64
- mockApi.onPost(url).reply(422);
64
+ mockErrorRequest({
65
+ url,
66
+ status: 422,
67
+ method: 'POST',
68
+ });
65
69
 
66
70
  return store.dispatch(uploadManifest())
67
71
  .then(() => expect(store.getActions()).toEqual(uploadManifestFailureActions));
@@ -79,7 +83,11 @@ describe('manifest actions', () => {
79
83
  const url = '/katello/api/v2/organizations/1/subscriptions/refresh_manifest';
80
84
 
81
85
  it('and then fails with 422', () => {
82
- mockApi.onPut(url).reply(422);
86
+ mockErrorRequest({
87
+ url,
88
+ status: 422,
89
+ method: 'PUT',
90
+ });
83
91
 
84
92
  return store.dispatch(refreshManifest())
85
93
  .then(() => expect(store.getActions()).toEqual(refreshManifestFailureActions));
@@ -97,7 +105,11 @@ describe('manifest actions', () => {
97
105
  const url = '/katello/api/v2/organizations/1/subscriptions/delete_manifest';
98
106
 
99
107
  it('and then fails with 422', () => {
100
- mockApi.onPost(url).reply(422);
108
+ mockErrorRequest({
109
+ url,
110
+ status: 422,
111
+ method: 'POST',
112
+ });
101
113
 
102
114
  return store.dispatch(deleteManifest())
103
115
  .then(() => expect(store.getActions()).toEqual(deleteManifestFailureActions));
@@ -30,7 +30,9 @@ describe('manifest history reducer', () => {
30
30
  it('should have error on MANIFEST_HISTORY_FAILURE', () => {
31
31
  expect(reducer(manifestHistoryInitialState, {
32
32
  type: types.MANIFEST_HISTORY_FAILURE,
33
- error: 'Unable to process request.',
33
+ payload: {
34
+ message: 'Unable to process request.',
35
+ },
34
36
  })).toEqual(manifestHistoryErrorState);
35
37
  });
36
38
  });