katello 3.7.0.rc1 → 3.7.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 (189) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/content_views_controller.rb +5 -2
  3. data/app/controllers/katello/api/v2/environments_controller.rb +8 -3
  4. data/app/controllers/katello/api/v2/host_tracer_controller.rb +1 -1
  5. data/app/controllers/katello/api/v2/upstream_subscriptions_controller.rb +4 -4
  6. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +5 -22
  7. data/app/lib/actions/katello/host/update_content_overrides.rb +1 -0
  8. data/app/lib/actions/katello/product/content_create.rb +1 -0
  9. data/app/lib/actions/katello/product/repositories_certs_reset.rb +25 -0
  10. data/app/lib/actions/katello/product/update.rb +6 -0
  11. data/app/lib/katello/resources/candlepin/activation_key.rb +8 -4
  12. data/app/lib/katello/resources/candlepin/product.rb +2 -1
  13. data/app/lib/katello/util/cdn_var_substitutor.rb +5 -3
  14. data/app/lib/katello/util/package.rb +21 -13
  15. data/app/lib/katello/util/package_filter.rb +33 -31
  16. data/app/lib/katello/validators/prior_validator.rb +6 -10
  17. data/app/models/katello/concerns/host_managed_extensions.rb +2 -0
  18. data/app/models/katello/concerns/organization_extensions.rb +1 -0
  19. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +10 -6
  20. data/app/models/katello/content.rb +23 -2
  21. data/app/models/katello/content_view_docker_filter.rb +1 -1
  22. data/app/models/katello/content_view_puppet_module.rb +3 -3
  23. data/app/models/katello/content_view_version.rb +4 -0
  24. data/app/models/katello/environment_prior.rb +7 -0
  25. data/app/models/katello/glue/candlepin/candlepin_object.rb +2 -2
  26. data/app/models/katello/glue/candlepin/pool.rb +10 -13
  27. data/app/models/katello/glue/candlepin/product.rb +19 -9
  28. data/app/models/katello/glue/candlepin/repository.rb +16 -0
  29. data/app/models/katello/glue/candlepin/subscription.rb +1 -1
  30. data/app/models/katello/glue/provider.rb +15 -81
  31. data/app/models/katello/host/subscription_facet.rb +1 -1
  32. data/app/models/katello/kt_environment.rb +39 -8
  33. data/app/models/katello/pool.rb +2 -1
  34. data/app/models/katello/rpm.rb +144 -2
  35. data/app/models/katello/upstream_pool.rb +7 -10
  36. data/app/services/katello/candlepin/pool_service.rb +18 -3
  37. data/app/services/katello/ui_notifications/pulp/proxy_disk_space.rb +13 -16
  38. data/app/views/dashboard/_content_views_widget.html.erb +3 -3
  39. data/app/views/dashboard/_errata_widget.html.erb +2 -2
  40. data/app/views/dashboard/_host_collection_widget.html.erb +3 -3
  41. data/app/views/dashboard/_subscription_status_widget.html.erb +2 -2
  42. data/app/views/dashboard/_subscription_widget.html.erb +1 -1
  43. data/app/views/dashboard/_sync_widget.html.erb +3 -3
  44. data/app/views/katello/api/v2/subscriptions/base.json.rabl +1 -1
  45. data/app/views/katello/api/v2/upstream_subscriptions/base.json.rabl +2 -6
  46. data/app/views/katello/layouts/react.html.erb +3 -3
  47. data/config/katello.yaml +89 -0
  48. data/config/routes.rb +3 -0
  49. data/db/migrate/20160302091113_change_environment_prior.rb +9 -0
  50. data/db/migrate/20180410140909_add_organization_id_to_pool.rb +2 -1
  51. data/db/migrate/20180612163403_add_foreign_key_to_hypervisor_id.rb +10 -0
  52. data/db/migrate/20180612164926_add_content_org_id.rb +39 -0
  53. data/db/migrate/20180612165011_remove_content_fields_from_host.rb +7 -0
  54. data/db/migrate/20180626160422_add_upstream_pool_id_to_katello_pool.rb +9 -0
  55. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-packages-modal.html +1 -1
  56. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/register.html +1 -1
  57. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/environment-content.controller.js +2 -3
  58. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment.html +4 -2
  59. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/environments.controller.js +19 -14
  60. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/new-environment.controller.js +18 -5
  61. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/paths.service.js +51 -0
  62. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/views/new-environment.html +16 -3
  63. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/products-bulk-advanced-sync-modal.controller.js +1 -1
  64. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.controller.js +2 -2
  65. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/subscriptions/subscriptions.routes.js +3 -3
  66. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/tasks/tasks.module.js +1 -6
  67. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +4 -0
  68. data/engines/bastion_katello/lib/bastion_katello/engine.rb +1 -1
  69. data/lib/katello/plugin.rb +2 -11
  70. data/lib/katello/scheduled_jobs.rb +2 -14
  71. data/lib/katello/tasks/clean_backend_objects.rake +2 -0
  72. data/lib/katello/tasks/repository.rake +11 -2
  73. data/lib/katello/tasks/upgrades/3.7/import_pools.rake +12 -0
  74. data/lib/katello/version.rb +1 -1
  75. data/package.json +4 -3
  76. data/webpack/components/PaginationRow/index.js +6 -2
  77. data/webpack/containers/Application/config.js +7 -2
  78. data/webpack/index.js +3 -5
  79. data/webpack/move_to_foreman/common/helpers.js +5 -24
  80. data/webpack/move_to_foreman/components/common/emptyState/index.js +12 -7
  81. data/webpack/move_to_foreman/components/common/table/components/CollapseSubscriptionGroupButton.js +31 -0
  82. data/webpack/move_to_foreman/components/common/table/components/CollapseSubscriptionGroupButton.test.js +16 -0
  83. data/webpack/move_to_foreman/components/common/table/components/Table.js +76 -0
  84. data/webpack/move_to_foreman/components/common/table/components/Table.test.js +31 -0
  85. data/webpack/move_to_foreman/components/common/table/components/TableBody.js +27 -0
  86. data/webpack/move_to_foreman/components/common/table/components/TableBody.test.js +18 -0
  87. data/webpack/move_to_foreman/components/common/table/components/TableBodyMessage.js +18 -0
  88. data/webpack/move_to_foreman/components/common/table/components/TableBodyMessage.test.js +12 -0
  89. data/webpack/move_to_foreman/components/common/table/components/TableFixtures.js +14 -0
  90. data/webpack/move_to_foreman/components/common/table/components/TableSelectionCell.js +39 -0
  91. data/webpack/move_to_foreman/components/common/table/components/TableSelectionCell.test.js +16 -0
  92. data/webpack/move_to_foreman/components/common/table/components/TableSelectionHeaderCell.js +34 -0
  93. data/webpack/move_to_foreman/components/common/table/components/TableSelectionHeaderCell.test.js +14 -0
  94. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/CollapseSubscriptionGroupButton.test.js.snap +19 -0
  95. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/Table.test.js.snap +167 -0
  96. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableBody.test.js.snap +28 -0
  97. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableBodyMessage.test.js.snap +13 -0
  98. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionCell.test.js.snap +16 -0
  99. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionHeaderCell.test.js.snap +15 -0
  100. data/webpack/move_to_foreman/components/common/table/components/index.js +6 -0
  101. data/webpack/move_to_foreman/components/common/table/formatters/cellFormatter.js +4 -0
  102. data/webpack/move_to_foreman/components/common/table/formatters/collapseableAndSelectionCellFormatter.js +18 -0
  103. data/webpack/move_to_foreman/components/common/table/formatters/ellipsisCellFormatter.js +5 -0
  104. data/webpack/move_to_foreman/components/common/table/formatters/headerFormatter.js +4 -0
  105. data/webpack/move_to_foreman/components/common/table/formatters/index.js +6 -0
  106. data/webpack/move_to_foreman/components/common/table/formatters/selectionCellFormatter.js +17 -0
  107. data/webpack/move_to_foreman/components/common/table/formatters/selectionHeaderCellFormatter.js +10 -0
  108. data/webpack/move_to_foreman/components/common/table/index.js +2 -88
  109. data/webpack/move_to_pf/LoadingState/LoadingState.js +35 -0
  110. data/webpack/move_to_pf/LoadingState/LoadingState.scss +12 -0
  111. data/webpack/move_to_pf/LoadingState/LoadingState.test.js +28 -0
  112. data/webpack/move_to_pf/LoadingState/__snapshots__/LoadingState.test.js.snap +20 -0
  113. data/webpack/move_to_pf/LoadingState/index.js +3 -0
  114. data/webpack/move_to_pf/test-utils/testHelpers.js +71 -0
  115. data/webpack/redux/actions/RedHatRepositories/enabled.js +1 -1
  116. data/webpack/redux/actions/RedHatRepositories/helpers.js +34 -9
  117. data/webpack/redux/actions/RedHatRepositories/sets.js +28 -6
  118. data/webpack/redux/consts.js +1 -0
  119. data/webpack/redux/reducers/RedHatRepositories/sets.fixtures.js +12 -2
  120. data/webpack/redux/reducers/RedHatRepositories/sets.js +34 -27
  121. data/webpack/redux/reducers/RedHatRepositories/sets.test.js +10 -2
  122. data/webpack/redux/reducers/index.js +2 -0
  123. data/webpack/scenes/Organizations/OrganizationActions.js +3 -3
  124. data/webpack/scenes/RedHatRepositories/components/RecommendedRepositorySetsToggler.js +44 -0
  125. data/webpack/scenes/RedHatRepositories/components/RecommendedRepositorySetsToggler.scss +16 -0
  126. data/webpack/scenes/RedHatRepositories/components/RepositorySet.js +8 -2
  127. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepositories.js +5 -3
  128. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository.js +4 -2
  129. data/webpack/scenes/RedHatRepositories/components/Search.js +1 -1
  130. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +1 -1
  131. data/webpack/scenes/RedHatRepositories/components/__tests__/RecommendedRepositorySetsToggler.test.js +17 -0
  132. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/RecommendedRepositorySetsToggler.test.js.snap +37 -0
  133. data/webpack/scenes/RedHatRepositories/helpers.js +1 -1
  134. data/webpack/scenes/RedHatRepositories/index.js +17 -7
  135. data/webpack/scenes/RedHatRepositories/index.scss +16 -4
  136. data/webpack/scenes/Subscriptions/Details/SubscriptionAttributes.js +17 -0
  137. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailActions.js +28 -0
  138. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailAssociations.js +47 -0
  139. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailConstants.js +3 -0
  140. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailInfo.js +65 -0
  141. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProducts.js +20 -0
  142. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +37 -0
  143. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +58 -0
  144. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailActions.test.js +47 -0
  145. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailAssociations.test.js +16 -0
  146. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailInfo.test.js +15 -0
  147. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailProducts.test.js +16 -0
  148. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailReducer.test.js +39 -0
  149. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetails.test.js +28 -0
  150. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailAssociations.test.js.snap +53 -0
  151. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailInfo.test.js.snap +185 -0
  152. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailProducts.test.js.snap +77 -0
  153. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +432 -0
  154. data/webpack/scenes/Subscriptions/Details/__tests__/subscriptionDetails.fixtures.js +167 -0
  155. data/webpack/scenes/Subscriptions/Details/index.js +19 -0
  156. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +58 -12
  157. data/webpack/scenes/Subscriptions/Manifest/Manifest.scss +6 -1
  158. data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +4 -4
  159. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryTableSchema.js +7 -7
  160. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +6 -9
  161. data/webpack/scenes/Subscriptions/Manifest/index.js +2 -2
  162. data/webpack/scenes/Subscriptions/SubscriptionActions.js +5 -6
  163. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +2 -3
  164. data/webpack/scenes/Subscriptions/SubscriptionValidations.js +1 -1
  165. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +46 -30
  166. data/webpack/scenes/Subscriptions/SubscriptionsPage.scss +38 -0
  167. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsActions.js +3 -3
  168. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +7 -6
  169. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsTableSchema.js +17 -14
  170. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +12 -15
  171. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/upstreamSubscriptions.fixtures.js +4 -4
  172. data/webpack/scenes/Subscriptions/__tests__/SubscriptionValidations.test.js +5 -0
  173. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +2 -2
  174. data/webpack/scenes/Subscriptions/{EntitlementsInlineEditFormatter.js → components/SubscriptionsTable/EntitlementsInlineEditFormatter.js} +7 -7
  175. data/webpack/scenes/Subscriptions/{SubscriptionsTable.js → components/SubscriptionsTable/SubscriptionsTable.js} +75 -47
  176. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +60 -0
  177. data/webpack/scenes/Subscriptions/{SubscriptionsTableSchema.js → components/SubscriptionsTable/SubscriptionsTableSchema.js} +37 -26
  178. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +56 -0
  179. data/webpack/scenes/Subscriptions/{__tests__ → components/SubscriptionsTable/__tests__}/__snapshots__/SubscriptionsTable.test.js.snap +16 -5
  180. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/index.js +2 -0
  181. data/webpack/scenes/Subscriptions/index.js +2 -2
  182. data/webpack/scenes/Tasks/TaskActions.js +18 -11
  183. data/webpack/scenes/Tasks/__tests__/TaskActions.test.js +92 -9
  184. data/webpack/scenes/Tasks/__tests__/task.fixtures.js +19 -9
  185. data/webpack/services/api/index.js +2 -2
  186. data/webpack/test_setup.js +1 -0
  187. metadata +79 -10
  188. data/webpack/scenes/Subscriptions/Subscriptions.scss +0 -14
  189. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsTable.test.js +0 -47
@@ -1,20 +1,43 @@
1
- export function normalizeRepositorySets(data) {
2
- data.results.forEach((repositorySet) => {
3
- /* eslint no-param-reassign: ["error", { "ignorePropertyModificationsFor": ["id"] }] */
4
- repositorySet.id = parseInt(repositorySet.id, 10);
5
- });
6
- return data;
7
- }
8
-
9
1
  const repoTypeSearchQueryMap = {
10
2
  rpm: '(name ~ rpms) and (name !~ source rpm) and (name !~ debug rpm)',
11
3
  sourceRpm: 'name ~ source rpm',
12
4
  debugRpm: 'name ~ debug rpm',
13
- kickstarter: 'name ~ kickstart',
5
+ kickstart: 'name ~ kickstart',
14
6
  ostree: 'name ~ ostree',
15
7
  beta: 'name ~ beta',
16
8
  };
17
9
 
10
+ const recommendedRepositorySetLables = [
11
+ 'rhel-7-server-rpms',
12
+ 'rhel-6-server-rpms',
13
+ 'rhel-6-server-satellite-tools-6.3-rpms',
14
+ 'rhel-server-rhscl-7-rpms',
15
+ 'rhel-7-server-satellite-capsule-6.3-rpms',
16
+ 'rhel-7-server-satellite-capsule-6.4-rpms',
17
+ 'rhel-7-server-satellite-tools-6.3-rpms',
18
+ 'rhel-6-server-satellite-tools-6.3-rpms',
19
+ 'rhel-7-server-ansible-2.5-rpms',
20
+ 'rhel-7-server-optional-rpms',
21
+ 'rhel-7-server-extras-rpms',
22
+ 'rhel-5-server-els-rpms',
23
+ 'rhel-7-server-eus-rpms',
24
+ ];
25
+
26
+ const createLablesQuery = lables =>
27
+ lables.map(label => `label = ${label}`).join(' or ');
28
+
29
+ const isRecommendedRepositorySet = ({ label }) => recommendedRepositorySetLables.includes(label);
30
+
31
+ export const normalizeRepositorySets = (data) => {
32
+ data.results.forEach((repositorySet) => {
33
+ /* eslint no-param-reassign: ["error", { "ignorePropertyModificationsFor": ["id"] }] */
34
+ repositorySet.id = parseInt(repositorySet.id, 10);
35
+ repositorySet.recommended = isRecommendedRepositorySet(repositorySet);
36
+ });
37
+
38
+ return data;
39
+ };
40
+
18
41
  const maptToSearchQuery = (filter) => {
19
42
  if (filter === 'other') {
20
43
  const joined = Object.keys(repoTypeSearchQueryMap)
@@ -35,4 +58,6 @@ export const joinSearchQueries = parts => parts
35
58
  .map(v => `(${v})`)
36
59
  .join(' and ');
37
60
 
61
+ export const recommendedRepositorySetsQuery = createLablesQuery(recommendedRepositorySetLables);
62
+
38
63
  export default normalizeRepositorySets;
@@ -1,25 +1,34 @@
1
1
  import api, { orgId } from '../../../services/api';
2
- import { normalizeRepositorySets, repoTypeFilterToSearchQuery, joinSearchQueries } from './helpers';
2
+ import {
3
+ normalizeRepositorySets,
4
+ repoTypeFilterToSearchQuery,
5
+ joinSearchQueries,
6
+ recommendedRepositorySetsQuery,
7
+ } from './helpers';
3
8
 
4
9
  import {
5
10
  REPOSITORY_SETS_REQUEST,
6
11
  REPOSITORY_SETS_SUCCESS,
7
12
  REPOSITORY_SETS_FAILURE,
13
+ REPOSITORY_SETS_UPDATE_RECOMMENDED,
8
14
  } from '../../consts';
9
15
  import { propsToSnakeCase } from '../../../services/index';
10
16
 
11
17
  // eslint-disable-next-line import/prefer-default-export
12
- export const loadRepositorySets = (extendedParams = {}) => (dispatch) => {
18
+ export const loadRepositorySets = (extendedParams = {}) => (dispatch, getState) => {
19
+ const { recommended } = getState().katello.redHatRepositories.sets;
20
+
13
21
  dispatch({ type: REPOSITORY_SETS_REQUEST, params: extendedParams });
14
22
 
15
23
  const searchParams = extendedParams.search || {};
16
24
  const search = joinSearchQueries([
17
25
  repoTypeFilterToSearchQuery(searchParams.filters || []),
18
26
  searchParams.query,
27
+ recommended ? recommendedRepositorySetsQuery : '',
19
28
  ]);
20
29
 
21
30
  const params = {
22
- ...{ organization_id: orgId },
31
+ ...{ organization_id: orgId() },
23
32
  ...propsToSnakeCase(extendedParams),
24
33
  search,
25
34
  };
@@ -29,14 +38,27 @@ export const loadRepositorySets = (extendedParams = {}) => (dispatch) => {
29
38
  .then(({ data }) => {
30
39
  dispatch({
31
40
  type: REPOSITORY_SETS_SUCCESS,
32
- response: normalizeRepositorySets(data),
33
- search: searchParams,
41
+ payload: {
42
+ response: normalizeRepositorySets(data),
43
+ search: searchParams,
44
+ },
34
45
  });
35
46
  })
36
47
  .catch((result) => {
37
48
  dispatch({
38
49
  type: REPOSITORY_SETS_FAILURE,
39
- result,
50
+ payload: result,
40
51
  });
41
52
  });
42
53
  };
54
+
55
+ export const updateRecommendedRepositorySets = value => (dispatch, getState) => {
56
+ const { search } = getState().katello.redHatRepositories.sets;
57
+
58
+ dispatch({
59
+ type: REPOSITORY_SETS_UPDATE_RECOMMENDED,
60
+ payload: value,
61
+ });
62
+
63
+ dispatch(loadRepositorySets({ search }));
64
+ };
@@ -13,6 +13,7 @@ export const ENABLED_REPOSITORIES_FAILURE = 'ENABLED_REPOSITORIES_FAILURE';
13
13
  export const REPOSITORY_SET_REPOSITORIES_REQUEST = 'REPOSITORY_SET_REPOSITORIES_REQUEST';
14
14
  export const REPOSITORY_SET_REPOSITORIES_SUCCESS = 'REPOSITORY_SET_REPOSITORIES_SUCCESS';
15
15
  export const REPOSITORY_SET_REPOSITORIES_FAILURE = 'REPOSITORY_SET_REPOSITORIES_FAILURE';
16
+ export const REPOSITORY_SETS_UPDATE_RECOMMENDED = 'REPOSITORY_SETS_UPDATE_RECOMMENDED';
16
17
 
17
18
  export const REPOSITORY_ENABLED = 'REPOSITORY_ENABLED';
18
19
  export const REPOSITORY_DISABLED = 'REPOSITORY_DISABLED';
@@ -2,12 +2,21 @@ import Immutable from 'seamless-immutable';
2
2
 
3
3
  export const initialState = Immutable({
4
4
  loading: true,
5
+ recommended: false,
6
+ results: [],
7
+ pagination: {},
8
+ });
9
+
10
+ export const recommendedState = Immutable({
11
+ loading: true,
12
+ recommended: true,
5
13
  results: [],
6
14
  pagination: {},
7
15
  });
8
16
 
9
17
  export const loadingState = Immutable({
10
18
  loading: true,
19
+ recommended: false,
11
20
  results: [],
12
21
  pagination: {},
13
22
  });
@@ -107,9 +116,10 @@ export const requestSuccessResponse = Immutable({
107
116
 
108
117
  export const successState = Immutable({
109
118
  loading: false,
119
+ recommended: false,
110
120
  results: requestSuccessResponse.results,
111
- searchIsActive: false,
112
- search: undefined,
121
+ searchIsActive: true,
122
+ search: requestSuccessResponse.search,
113
123
  pagination: {
114
124
  page: 1,
115
125
  perPage: 5,
@@ -5,37 +5,44 @@ import {
5
5
  REPOSITORY_SETS_REQUEST,
6
6
  REPOSITORY_SETS_SUCCESS,
7
7
  REPOSITORY_SETS_FAILURE,
8
+ REPOSITORY_SETS_UPDATE_RECOMMENDED,
8
9
  } from '../../consts';
9
10
 
10
11
  import { initialState } from './sets.fixtures.js';
11
12
 
12
13
  export default (state = initialState, action) => {
13
- if (action.type === REPOSITORY_SETS_REQUEST) {
14
- return state.set('loading', true);
15
- } else if (action.type === REPOSITORY_SETS_SUCCESS) {
16
- const {
17
- page, per_page, subtotal, results, // eslint-disable-line camelcase
18
- } = action.response;
19
-
20
- return Immutable({
21
- results,
22
- pagination: {
23
- page: Number(page),
24
- // server can return per_page: null when there's error in the search query,
25
- // don't store it in such case
26
- // eslint-disable-next-line camelcase
27
- perPage: Number(per_page || state.pagination.perPage),
28
- },
29
- itemCount: Number(subtotal),
30
- loading: false,
31
- searchIsActive: !isEmpty(action.search),
32
- search: action.search,
33
- });
34
- } else if (action.type === REPOSITORY_SETS_FAILURE) {
35
- return Immutable({
36
- error: action.error,
37
- loading: false,
38
- });
14
+ const { payload } = action;
15
+
16
+ switch (action.type) {
17
+ case REPOSITORY_SETS_REQUEST:
18
+ return state.set('loading', true);
19
+
20
+ case REPOSITORY_SETS_UPDATE_RECOMMENDED:
21
+ return state
22
+ .set('recommended', payload);
23
+
24
+ case REPOSITORY_SETS_SUCCESS:
25
+ return state
26
+ .set('results', payload.response.results)
27
+ .set('pagination', {
28
+ page: Number(payload.response.page),
29
+ // server can return per_page: null when there's error in the search query,
30
+ // don't store it in such case
31
+ // eslint-disable-next-line camelcase
32
+ perPage: Number(payload.response.per_page || state.pagination.perPage),
33
+ })
34
+ .set('itemCount', Number(payload.response.subtotal))
35
+ .set('loading', false)
36
+ .set('searchIsActive', !isEmpty(payload.search))
37
+ .set('search', payload.search);
38
+
39
+ case REPOSITORY_SETS_FAILURE:
40
+ return Immutable({
41
+ error: payload,
42
+ loading: false,
43
+ });
44
+
45
+ default:
46
+ return state;
39
47
  }
40
- return state;
41
48
  };
@@ -2,6 +2,7 @@ import * as types from '../../consts';
2
2
 
3
3
  import {
4
4
  initialState,
5
+ recommendedState,
5
6
  loadingState,
6
7
  requestSuccessResponse,
7
8
  successState,
@@ -14,6 +15,13 @@ describe('sets reducer', () => {
14
15
  expect(reducer(undefined, {})).toEqual(initialState);
15
16
  });
16
17
 
18
+ it('should update the recommended value on REPOSITORY_SETS_UPDATE_RECOMMENDED', () => {
19
+ expect(reducer(initialState, {
20
+ type: types.REPOSITORY_SETS_UPDATE_RECOMMENDED,
21
+ payload: true,
22
+ })).toEqual(recommendedState);
23
+ });
24
+
17
25
  it('should keep loading state on REPOSITORY_SETS_REQUEST', () => {
18
26
  expect(reducer(initialState, {
19
27
  type: types.REPOSITORY_SETS_REQUEST,
@@ -23,14 +31,14 @@ describe('sets reducer', () => {
23
31
  it('should flatten repositories response REPOSITORY_SETS_SUCCESS', () => {
24
32
  expect(reducer(initialState, {
25
33
  type: types.REPOSITORY_SETS_SUCCESS,
26
- response: requestSuccessResponse,
34
+ payload: { response: requestSuccessResponse, search: requestSuccessResponse.search },
27
35
  })).toEqual(successState);
28
36
  });
29
37
 
30
38
  it('should have error on REPOSITORY_SETS_FAILURE', () => {
31
39
  expect(reducer(initialState, {
32
40
  type: types.REPOSITORY_SETS_FAILURE,
33
- error: 'Unable to process request.',
41
+ payload: 'Unable to process request.',
34
42
  })).toEqual(errorState);
35
43
  });
36
44
  });
@@ -4,6 +4,7 @@ import redHatRepositories from './RedHatRepositories';
4
4
  import { subscriptions } from '../../scenes/Subscriptions';
5
5
  import { upstreamSubscriptions } from '../../scenes/Subscriptions/UpstreamSubscriptions';
6
6
  import { manifestHistory } from '../../scenes/Subscriptions/Manifest';
7
+ import { subscriptionDetails } from '../../scenes/Subscriptions/Details';
7
8
 
8
9
  export default combineReducers({
9
10
  organization,
@@ -11,4 +12,5 @@ export default combineReducers({
11
12
  subscriptions,
12
13
  upstreamSubscriptions,
13
14
  manifestHistory,
15
+ subscriptionDetails,
14
16
  });
@@ -18,7 +18,7 @@ export const loadOrganization = (extendedParams = {}) => (dispatch) => {
18
18
  };
19
19
 
20
20
  return api
21
- .get(`/organizations/${orgId}`, {}, params)
21
+ .get(`/organizations/${orgId()}`, {}, params)
22
22
  .then(({ data }) => {
23
23
  dispatch({
24
24
  type: GET_ORGANIZATION_SUCCESS,
@@ -37,12 +37,12 @@ export const saveOrganization = (extendedParams = {}) => (dispatch) => {
37
37
  dispatch({ type: SAVE_ORGANIZATION_REQUEST });
38
38
 
39
39
  const params = {
40
- ...{ id: orgId },
40
+ ...{ id: orgId() },
41
41
  ...propsToSnakeCase(extendedParams),
42
42
  };
43
43
 
44
44
  return api
45
- .put(`/organizations/${orgId}`, params)
45
+ .put(`/organizations/${orgId()}`, params)
46
46
  .then(({ data }) => {
47
47
  dispatch({
48
48
  type: SAVE_ORGANIZATION_SUCCESS,
@@ -0,0 +1,44 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import classNames from 'classnames';
4
+ import { Switch, Icon, FieldLevelHelp } from 'patternfly-react';
5
+
6
+ import './RecommendedRepositorySetsToggler.scss';
7
+
8
+ const RecommendedRepositorySetsToggler = ({
9
+ enabled,
10
+ className,
11
+ children,
12
+ help,
13
+ onChange,
14
+ ...props
15
+ }) => {
16
+ const classes = classNames('recommended-repositories-toggler-container', className);
17
+
18
+ return (
19
+ <div className={classes} {...props}>
20
+ <Switch bsSize="mini" value={enabled} onChange={() => onChange(!enabled)} />
21
+ <Icon type="fa" name="star" />
22
+ {children}
23
+ <FieldLevelHelp content={help} />
24
+ </div>
25
+ );
26
+ };
27
+
28
+ RecommendedRepositorySetsToggler.propTypes = {
29
+ enabled: PropTypes.bool,
30
+ className: PropTypes.string,
31
+ children: PropTypes.node,
32
+ help: PropTypes.node,
33
+ onChange: PropTypes.func,
34
+ };
35
+
36
+ RecommendedRepositorySetsToggler.defaultProps = {
37
+ enabled: false,
38
+ className: '',
39
+ children: __('Recommended Repositories'),
40
+ help: __('This shows repositories that are used in a typical setup.'),
41
+ onChange: () => null,
42
+ };
43
+
44
+ export default RecommendedRepositorySetsToggler;
@@ -0,0 +1,16 @@
1
+ @import '~patternfly/dist/sass/patternfly/_color-variables';
2
+
3
+ .recommended-repositories-toggler-container {
4
+
5
+ > * {
6
+ margin: 0 3px;
7
+
8
+ &.fa.fa-star {
9
+ color: $color-pf-gold-300;
10
+ }
11
+
12
+ &:last-child {
13
+ margin: 0;
14
+ }
15
+ }
16
+ }
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { ListView } from 'patternfly-react';
3
+ import { ListView, Icon } from 'patternfly-react';
4
4
 
5
5
  import RepositoryTypeIcon from './RepositoryTypeIcon';
6
6
  import RepositorySetRepositories from './RepositorySetRepositories';
7
7
 
8
8
  const RepositorySet = ({
9
- type, id, name, label, product,
9
+ type, id, name, label, product, recommended,
10
10
  }) => (
11
11
  <ListView.Item
12
12
  id={id}
@@ -15,6 +15,7 @@ const RepositorySet = ({
15
15
  heading={name}
16
16
  leftContent={<RepositoryTypeIcon id={id} type={type} />}
17
17
  stacked
18
+ actions={recommended ? <Icon type="fa" name="star" className="recommended-repository-set-icon" /> : ''}
18
19
  hideCloseIcon
19
20
  >
20
21
  <RepositorySetRepositories contentId={id} productId={product.id} />
@@ -30,6 +31,11 @@ RepositorySet.propTypes = {
30
31
  name: PropTypes.string.isRequired,
31
32
  id: PropTypes.number.isRequired,
32
33
  }).isRequired,
34
+ recommended: PropTypes.bool,
35
+ };
36
+
37
+ RepositorySet.defaultProps = {
38
+ recommended: false,
33
39
  };
34
40
 
35
41
  export default RepositorySet;
@@ -25,14 +25,16 @@ class RepositorySetRepositories extends Component {
25
25
  </Alert>
26
26
  );
27
27
  }
28
-
29
- const repos = data.repositories
28
+ const availableRepos = data.repositories
30
29
  .filter(({ enabled }) => !enabled)
31
30
  .map(repo => <RepositorySetRepository key={repo.arch + repo.releasever} {...repo} />);
32
31
 
32
+ const repoMessage = (data.repositories.length > 0 && availableRepos.length === 0 ?
33
+ __('All available architectures for this repo are enabled.') : __('No repositories available.'));
34
+
33
35
  return (
34
36
  <Spinner loading={data.loading}>
35
- {repos.length ? repos : <div>{__('No repositories available.')}</div>}
37
+ {availableRepos.length ? availableRepos : <div>{repoMessage}</div>}
36
38
  </Spinner>
37
39
  );
38
40
  }
@@ -8,6 +8,8 @@ import { setRepositoryEnabled } from '../../../redux/actions/RedHatRepositories/
8
8
  import '../index.scss';
9
9
  import api from '../../../services/api';
10
10
 
11
+ const UNSPECIFIED_ARCH = 'Unspecified';
12
+
11
13
  class RepositorySetRepository extends Component {
12
14
  constructor(props) {
13
15
  super(props);
@@ -48,7 +50,7 @@ class RepositorySetRepository extends Component {
48
50
  const data = {
49
51
  id: contentId,
50
52
  product_id: productId,
51
- basearch: arch,
53
+ basearch: arch == UNSPECIFIED_ARCH ? undefined : arch,
52
54
  releasever: releasever || undefined,
53
55
  };
54
56
 
@@ -121,7 +123,7 @@ RepositorySetRepository.propTypes = {
121
123
 
122
124
  RepositorySetRepository.defaultProps = {
123
125
  releasever: '',
124
- arch: __('Unspecified'),
126
+ arch: __(UNSPECIFIED_ARCH),
125
127
  };
126
128
 
127
129
  export default connect(null, { setRepositoryEnabled })(RepositorySetRepository);