katello 3.7.0 → 3.7.1

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 (113) 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/v2/host_packages_controller.rb +1 -5
  5. data/app/controllers/katello/remote_execution_controller.rb +6 -6
  6. data/app/helpers/katello/hosts_and_hostgroups_helper.rb +37 -9
  7. data/app/lib/actions/katello/host/hypervisors_update.rb +82 -22
  8. data/app/lib/actions/pulp/consumer/abstract_content_action.rb +12 -0
  9. data/app/lib/actions/pulp/consumer/content_install.rb +1 -1
  10. data/app/lib/actions/pulp/consumer/content_uninstall.rb +1 -1
  11. data/app/lib/actions/pulp/consumer/content_update.rb +1 -1
  12. data/app/models/katello/concerns/subscription_facet_host_extensions.rb +1 -1
  13. data/app/models/katello/content_view.rb +12 -4
  14. data/app/models/katello/glue/candlepin/pool.rb +11 -11
  15. data/app/models/katello/host/content_facet.rb +2 -1
  16. data/app/models/katello/rpm.rb +14 -6
  17. data/app/models/katello/subscription_status.rb +1 -1
  18. data/app/services/katello/candlepin/consumer.rb +8 -0
  19. data/app/views/overrides/activation_keys/_host_environment_select.html.erb +2 -3
  20. data/config/routes.rb +1 -0
  21. data/db/migrate/20180612163403_add_foreign_key_to_hypervisor_id.rb +3 -0
  22. data/db/seeds.d/75-job_templates.rb +5 -2
  23. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-repository-sets-modal.controller.js +4 -3
  24. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/content-hosts-bulk-subscriptions-modal.controller.js +4 -1
  25. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content/content-host-packages-installed.controller.js +1 -1
  26. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/discovery/views/discovery-create.html +1 -1
  27. data/engines/bastion_katello/app/assets/stylesheets/bastion_katello/bastion_katello.scss +5 -0
  28. data/lib/katello/tasks/clean_backend_objects.rake +12 -3
  29. data/lib/katello/version.rb +1 -1
  30. data/package.json +10 -7
  31. data/webpack/__mocks__/foremanReact/redux.js +3 -0
  32. data/webpack/__mocks__/foremanReact/redux/actions/toasts.js +2 -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/move_to_foreman/components/common/{emptyState → EmptyState}/index.js +16 -3
  44. data/webpack/move_to_foreman/components/common/table/components/Table.js +1 -1
  45. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/CollapseSubscriptionGroupButton.test.js.snap +2 -2
  46. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionCell.test.js.snap +1 -1
  47. data/webpack/move_to_foreman/components/common/table/components/__snapshots__/TableSelectionHeaderCell.test.js.snap +1 -1
  48. data/webpack/move_to_pf/LoadingState/LoadingState.js +27 -14
  49. data/webpack/move_to_pf/LoadingState/LoadingState.test.js +8 -4
  50. data/webpack/move_to_pf/Select/Select.js +40 -0
  51. data/webpack/move_to_pf/react-bootstrap-select/index.js +12 -1
  52. data/webpack/redux/actions/RedHatRepositories/enabled.js +0 -1
  53. data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -5
  54. data/webpack/redux/consts.js +6 -0
  55. data/webpack/redux/reducers/index.js +2 -0
  56. data/webpack/scenes/Products/ProductActions.js +24 -0
  57. data/webpack/scenes/Products/ProductConstants.js +3 -0
  58. data/webpack/scenes/Products/__tests__/ProductActions.test.js +40 -0
  59. data/webpack/scenes/Products/__tests__/products.fixtures.js +90 -0
  60. data/webpack/scenes/RedHatRepositories/components/EnabledRepository.js +14 -23
  61. data/webpack/scenes/RedHatRepositories/components/EnabledRepositoryContent.js +34 -0
  62. data/webpack/scenes/RedHatRepositories/components/RepositorySetRepository.js +1 -1
  63. data/webpack/scenes/RedHatRepositories/components/SearchBar.js +1 -0
  64. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepository.test.js +36 -0
  65. data/webpack/scenes/RedHatRepositories/components/__tests__/EnabledRepositoryContent.test.js +27 -0
  66. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepository.test.js.snap +25 -0
  67. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/EnabledRepositoryContent.test.js.snap +47 -0
  68. data/webpack/scenes/RedHatRepositories/components/__tests__/__snapshots__/RecommendedRepositorySetsToggler.test.js.snap +3 -1
  69. data/webpack/scenes/RedHatRepositories/index.js +7 -3
  70. data/webpack/scenes/RedHatRepositories/index.scss +1 -0
  71. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailActions.js +1 -1
  72. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailEnabledProducts.js +54 -0
  73. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailProduct.js +29 -0
  74. data/webpack/scenes/Subscriptions/Details/SubscriptionDetailReducer.js +29 -0
  75. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.js +67 -22
  76. data/webpack/scenes/Subscriptions/Details/SubscriptionDetails.scss +9 -0
  77. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailEnabledProducts.test.js +18 -0
  78. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetailProduct.test.js +13 -0
  79. data/webpack/scenes/Subscriptions/Details/__tests__/SubscriptionDetails.test.js +6 -0
  80. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailEnabledProducts.test.js.snap +45 -0
  81. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetailProduct.test.js.snap +67 -0
  82. data/webpack/scenes/Subscriptions/Details/__tests__/__snapshots__/SubscriptionDetails.test.js.snap +497 -410
  83. data/webpack/scenes/Subscriptions/Details/__tests__/subscriptionDetails.fixtures.js +4 -0
  84. data/webpack/scenes/Subscriptions/Details/index.js +3 -1
  85. data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +78 -34
  86. data/webpack/scenes/Subscriptions/Manifest/ManifestHistoryReducer.js +8 -0
  87. data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +3 -0
  88. data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +34 -7
  89. data/webpack/scenes/Subscriptions/Manifest/index.js +1 -0
  90. data/webpack/scenes/Subscriptions/SubscriptionConstants.js +1 -0
  91. data/webpack/scenes/Subscriptions/SubscriptionHelpers.js +3 -0
  92. data/webpack/scenes/Subscriptions/SubscriptionReducer.js +6 -2
  93. data/webpack/scenes/Subscriptions/SubscriptionsPage.js +31 -36
  94. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +2 -7
  95. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/UpstreamSubscriptionsPage.test.js +1 -1
  96. data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +3 -6
  97. data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +2 -0
  98. data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +14 -2
  99. data/webpack/scenes/Subscriptions/__tests__/subscriptions.fixtures.js +4 -3
  100. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/EntitlementsInlineEditFormatter.js +8 -5
  101. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js +29 -19
  102. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableHelpers.js +9 -2
  103. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableSchema.js +2 -2
  104. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/EntitlementsInlineEditFormatter.test.js +110 -0
  105. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/SubscriptionsTable.test.js +15 -3
  106. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/EntitlementsInlineEditFormatter.test.js.snap +228 -0
  107. data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +54 -21
  108. data/webpack/scenes/Subscriptions/index.js +1 -0
  109. data/webpack/scenes/Tasks/helpers.js +52 -0
  110. data/webpack/services/api/index.js +17 -1
  111. data/webpack/test_setup.js +2 -0
  112. metadata +31 -4
  113. data/config/katello.yaml +0 -89
@@ -38,7 +38,7 @@ module Katello
38
38
 
39
39
  def to_status(options = {})
40
40
  return UNKNOWN unless host.subscription_facet.try(:uuid)
41
- status_override = 'unsubscribed_hypervisor' if host.subscription_facet.hypervisor && host.subscription_facet.candlepin_consumer.entitlements.empty?
41
+ status_override = 'unsubscribed_hypervisor' if host.subscription_facet.hypervisor && !host.subscription_facet.candlepin_consumer.entitlements?
42
42
  status_override ||= options.fetch(:status_override, nil)
43
43
  status = status_override || Katello::Candlepin::Consumer.new(host.subscription_facet.uuid, host.organization.label).entitlement_status
44
44
 
@@ -120,6 +120,14 @@ module Katello
120
120
  self.class.friendly_compliance_reasons(Resources::Candlepin::Consumer.compliance(uuid)['reasons'])
121
121
  end
122
122
 
123
+ def entitlements?
124
+ # use cahced consumer_attributes if possible
125
+ count = @consumer_attributes.try(:[], 'entitlementCount')
126
+ return count > 0 if count
127
+
128
+ !entitlements.empty?
129
+ end
130
+
123
131
  def self.friendly_compliance_reasons(candlepin_reasons)
124
132
  candlepin_reasons.map do |reason|
125
133
  product_name = reason['productName'] || reason['attributes']['name']
@@ -35,12 +35,11 @@ end %>
35
35
  <% cs_select_name = using_hostgroups_page? ? 'hostgroup[content_source_id]' : 'host[content_facet_attributes][content_source_id]' %>
36
36
  <% cs_select_attr = using_hostgroups_page? ? 'content_source' : 'content_facet.content_source' %>
37
37
 
38
- <% proxies = accessible_content_proxies(@host || @hostgroup) %>
39
38
  <%= field(f, cs_select_attr, {:label => _("Content Source")}) do
40
39
  if using_hostgroups_page?
41
- select_tag cs_select_id, options_from_collection_for_select(proxies, :id, :name, @hostgroup.content_source_id), :data => {"spinner_path" => spinner_path},
40
+ select_tag cs_select_id, content_source_options(@hostgroup, :selected_host_group => @hostgroup.hostgroup, :include_blank => blank_or_inherit_with_id(f, :content_source)), :data => {"spinner_path" => spinner_path},
42
41
  :class => 'form-control', :name => cs_select_name, include_blank: true
43
42
  else
44
- select_tag cs_select_id, options_from_collection_for_select(proxies, :id, :name, @host.content_source_id), :data => {"spinner_path" => spinner_path}, :class => 'form-control', :name => cs_select_name, include_blank: true
43
+ select_tag cs_select_id, content_source_options(@host, :selected_host_group => @host.hostgroup, :include_blank => blank_or_inherit_with_id(f, :content_source)), :data => {"spinner_path" => spinner_path}, :class => 'form-control', :name => cs_select_name, include_blank: true
45
44
  end
46
45
  end %>
data/config/routes.rb CHANGED
@@ -23,4 +23,5 @@ Katello::Engine.routes.draw do
23
23
 
24
24
  match '/xui' => 'react#index', :via => [:get]
25
25
  match '/xui/*page' => 'react#index', :via => [:get]
26
+ match '/organization_select' => 'react#index', :via => [:get]
26
27
  end
@@ -1,5 +1,8 @@
1
1
  class AddForeignKeyToHypervisorId < ActiveRecord::Migration[5.1]
2
2
  def up
3
+ # Update all pools that have a hypervisor reference that's not a host before we add the FK
4
+ ::Katello::Pool.where.not(hypervisor_id: nil).where.not(hypervisor_id: Host::Managed.all).update_all(hypervisor_id: nil)
5
+
3
6
  add_foreign_key(:katello_pools, :hosts,
4
7
  :name => 'katello_pools_hypervisor_fk', :column => 'hypervisor_id')
5
8
  end
@@ -7,10 +7,13 @@ if Katello.with_remote_execution?
7
7
  sync = !Rails.env.test? && Setting[:remote_execution_sync_templates]
8
8
  # import! was renamed to import_raw! around 1.3.1
9
9
  if JobTemplate.respond_to?('import_raw!')
10
- JobTemplate.import_raw!(File.read(template), :default => true, :locked => true, :update => sync)
10
+ template = JobTemplate.import_raw!(File.read(template), :default => true, :locked => true, :update => sync)
11
11
  else
12
- JobTemplate.import!(File.read(template), :default => true, :locked => true, :update => sync)
12
+ template = JobTemplate.import!(File.read(template), :default => true, :locked => true, :update => sync)
13
13
  end
14
+
15
+ template.organizations << Organization.unscoped.all if template && template.organizations.empty?
16
+ template.locations << Location.unscoped.all if template && template.locations.empty?
14
17
  end
15
18
  end
16
19
  end
@@ -28,14 +28,15 @@ angular.module('Bastion.content-hosts').controller('ContentHostsBulkRepositorySe
28
28
  nutupaneParams = {
29
29
  'organization_id': CurrentOrganization,
30
30
  'offset': 0,
31
- 'sort_by': 'name',
32
- 'sort_order': 'ASC',
33
31
  'paged': true
34
32
  };
35
33
 
36
- nutupane = new Nutupane(RepositorySet, nutupaneParams, 'queryPaged');
34
+ nutupane = new Nutupane(RepositorySet, nutupaneParams,
35
+ 'queryPaged', {disableAutoLoad: true});
37
36
  $scope.controllerName = 'katello_repository_sets';
38
37
  nutupane.masterOnly = true;
38
+ nutupane.setSearchKey('repoSetsSearch');
39
+ nutupane.load();
39
40
 
40
41
  $scope.table = nutupane.table;
41
42
 
@@ -44,11 +44,14 @@ angular.module('Bastion.content-hosts').controller('ContentHostsBulkSubscription
44
44
  });
45
45
  };
46
46
 
47
- $scope.contentNutupane = new Nutupane(Subscription, params);
47
+
48
+ $scope.contentNutupane = new Nutupane(Subscription, params,
49
+ 'queryPaged', {disableAutoLoad: true});
48
50
  $scope.controllerName = 'katello_subscriptions';
49
51
  $scope.table = $scope.contentNutupane.table;
50
52
  $scope.contentNutupane.setSearchKey('subscriptionSearch');
51
53
  $scope.contentNutupane.masterOnly = true;
54
+ $scope.contentNutupane.load();
52
55
  $scope.groupedSubscriptions = {};
53
56
 
54
57
  $scope.$watch('table.rows', function (rows) {
@@ -18,7 +18,7 @@ angular.module('Bastion.content-hosts').controller('ContentHostPackagesInstalled
18
18
  var packagesNutupane;
19
19
 
20
20
  $scope.removeSelectedPackages = function () {
21
- var selected = $scope.table.getSelected();
21
+ var selected = _.map($scope.table.getSelected(), 'name');
22
22
 
23
23
  if (!$scope.working) {
24
24
  $scope.working = true;
@@ -44,7 +44,7 @@
44
44
 
45
45
  <div bst-form-group ng-show="createRepoChoices.newProduct === 'true' && contentCredentials.length !== 0"
46
46
  label="{{ 'GPG Key' | translate }}">
47
- <select class="form-control" ng-model="createRepoChoices.product.content_credential_id"
47
+ <select class="form-control" ng-model="createRepoChoices.product.gpg_key_id"
48
48
  ng-options="content_credential.id as content_credential.name for content_credential in contentCredentials"/>
49
49
  </div>
50
50
 
@@ -38,3 +38,8 @@
38
38
  .bottom-padded-content {
39
39
  padding-bottom: 10%;
40
40
  }
41
+
42
+ .modal-body .uib-time input {
43
+ width: 100%;
44
+ padding-right: 6px;
45
+ }
@@ -42,17 +42,17 @@ namespace :katello do
42
42
  def cleanup_hosts(cleaner)
43
43
  cleaner.hosts_with_nil_facets.each do |host|
44
44
  print "Host #{host.id} #{host.name} is partially missing subscription information. Un-registering\n"
45
- execute("Failed to delete host") { Katello::RegistrationManager.unregister_host(host) }
45
+ execute("Failed to delete host") { Katello::RegistrationManager.unregister_host(host, host_unregister_options(host)) }
46
46
  end
47
47
 
48
48
  cleaner.hosts_with_no_subscriptions.each do |host|
49
49
  print "Host #{host.id} #{host.name} #{host.subscription_facet.try(:uuid)} is partially missing subscription information. Un-registering\n"
50
- execute("Failed to delete host") { Katello::RegistrationManager.unregister_host(host) }
50
+ execute("Failed to delete host") { Katello::RegistrationManager.unregister_host(host, host_unregister_options(host)) }
51
51
  end
52
52
 
53
53
  cleaner.hosts_with_no_content.each do |host|
54
54
  print "Host #{host.id} #{host.name} #{host.content_facet.try(:uuid)} is partially missing content information. Un-registering\n"
55
- execute("Failed to delete host") { Katello::RegistrationManager.unregister_host(host) }
55
+ execute("Failed to delete host") { Katello::RegistrationManager.unregister_host(host, host_unregister_options(host)) }
56
56
  end
57
57
  end
58
58
 
@@ -72,6 +72,15 @@ namespace :katello do
72
72
  end
73
73
  end
74
74
 
75
+ def host_unregister_options(host)
76
+ if host.managed? || host.compute_resource
77
+ print "Leaving provisioning record for #{host.name} in place, it is either managed or assigned to a compute resource."
78
+ {:unregistering => true}
79
+ else
80
+ {}
81
+ end
82
+ end
83
+
75
84
  # rubocop:disable HandleExceptions
76
85
  def execute(error_msg)
77
86
  if ENV['COMMIT'] == 'true'
@@ -1,3 +1,3 @@
1
1
  module Katello
2
- VERSION = "3.7.0".freeze
2
+ VERSION = "3.7.1".freeze
3
3
  end
data/package.json CHANGED
@@ -9,7 +9,9 @@
9
9
  "test:current": "jest webpack --watch",
10
10
  "format": "prettier --single-quote --trailing-comma es5 --write 'webpack/**/*.js'",
11
11
  "build": "npm run format && npm run lint",
12
- "lint": "eslint --fix webpack/ || exit 0"
12
+ "lint": "eslint webpack/ || exit 0",
13
+ "lint:fix": "eslint --fix webpack/ || exit 0",
14
+ "lint:test": "npm run lint && npm test"
13
15
  },
14
16
  "repository": {
15
17
  "type": "git",
@@ -22,11 +24,11 @@
22
24
  "@storybook/react": "^3.2.17",
23
25
  "@storybook/storybook-deployer": "^2.0.0",
24
26
  "babel-core": "^6.26.3",
25
- "babel-jest": "^21.2.0",
27
+ "babel-jest": "^23.4.0",
26
28
  "babel-plugin-transform-class-properties": "^6.24.1",
27
29
  "babel-plugin-transform-object-rest-spread": "^6.26.0",
28
- "babel-preset-env": "^1.6.0",
29
30
  "babel-polyfill": "^6.26.0",
31
+ "babel-preset-env": "^1.6.0",
30
32
  "babel-preset-react": "^6.24.1",
31
33
  "enzyme": "^3.2.0",
32
34
  "enzyme-adapter-react-16": "^1.1.0",
@@ -34,11 +36,11 @@
34
36
  "eslint": "^4.8.0",
35
37
  "eslint-config-airbnb": "^16.0.0",
36
38
  "eslint-plugin-import": "^2.7.0",
37
- "eslint-plugin-jest": "^21.2.0",
39
+ "eslint-plugin-jest": "^21.18.0",
38
40
  "eslint-plugin-jsx-a11y": "^6.0.2",
39
41
  "eslint-plugin-react": "^7.4.0",
40
42
  "identity-obj-proxy": "^3.0.0",
41
- "jest": "^21.2.1",
43
+ "jest": "^23.4.1",
42
44
  "prettier": "^1.7.4",
43
45
  "react-test-renderer": "^16.0.0",
44
46
  "redux-mock-store": "^1.3.0",
@@ -53,10 +55,10 @@
53
55
  "jed": "^1.1.1",
54
56
  "lodash": "^4.17.5",
55
57
  "patternfly": "^3.41.1",
56
- "patternfly-react": "2.5.1",
58
+ "patternfly-react": "^2.5.1",
57
59
  "prop-types": "^15.6.0",
58
60
  "react": "^16.3.1",
59
- "react-bootstrap": "^0.31.5",
61
+ "react-bootstrap": "^0.32.1",
60
62
  "react-bootstrap-tooltip-button": "^1.0.6",
61
63
  "react-dom": "^16.3.1",
62
64
  "react-ellipsis-with-tooltip": "^1.0.7",
@@ -72,6 +74,7 @@
72
74
  "raf/polyfill",
73
75
  "./webpack/test_setup.js"
74
76
  ],
77
+ "setupTestFrameworkScriptFile": "./webpack/global_test_setup.js",
75
78
  "testPathIgnorePatterns": [
76
79
  "/node_modules/",
77
80
  "<rootDir>/foreman/",
@@ -0,0 +1,3 @@
1
+ const state = { katello: { setOrganization: { currentId: 1 } } };
2
+ const store = { getState: () => state };
3
+ export default store;
@@ -4,3 +4,5 @@ export const addToast = toast => ({
4
4
  message: toast,
5
5
  },
6
6
  });
7
+
8
+ export default addToast;
@@ -1,17 +1,19 @@
1
1
  import React from 'react';
2
2
  import { shallow } from 'enzyme';
3
3
  import toJson from 'enzyme-to-json';
4
+ import { mock as mockApi } from '../../mockRequest';
4
5
 
5
6
  import Search from '../Search';
6
7
 
7
8
  describe('Search component', () => {
8
9
  const getBaseProps = () => ({
9
10
  onSearch: () => {},
10
- getAutoCompleteParams: () => ({}),
11
+ getAutoCompleteParams: () => ({ endpoint: '/fake' }),
11
12
  });
12
13
 
13
14
  describe('rendering', () => {
14
15
  it('renders correctly', () => {
16
+ mockApi.onGet('/katello/api/v2/fake').reply(200, []);
15
17
  const component = shallow(<Search {...getBaseProps()} />);
16
18
 
17
19
  expect(toJson(component)).toMatchSnapshot();
@@ -0,0 +1,3 @@
1
+ #select-org.well {
2
+ margin-top: 30px;
3
+ }
@@ -0,0 +1,41 @@
1
+ import { foremanApi, foremanEndpoint } from '../../services/api';
2
+ import {
3
+ GET_ORGANIZATIONS_LIST_SUCCESS,
4
+ GET_ORGANIZATIONS_LIST_FAILURE,
5
+ CHANGE_CURRENT_ORGANIZATION_SUCCESS,
6
+ CHANGE_CURRENT_ORGANIZATION_FAILURE,
7
+ GET_ORGANIZATIONS_LIST_REQUEST,
8
+ } from '../../redux/consts';
9
+
10
+ export const getOrganiztionsList = () => (dispatch) => {
11
+ dispatch({ type: GET_ORGANIZATIONS_LIST_REQUEST });
12
+ foremanApi
13
+ .get('/organizations')
14
+ .then(({ data }) => {
15
+ dispatch({
16
+ type: GET_ORGANIZATIONS_LIST_SUCCESS,
17
+ payload: data,
18
+ });
19
+ })
20
+ .catch((result) => {
21
+ dispatch({
22
+ type: GET_ORGANIZATIONS_LIST_FAILURE,
23
+ payload: result,
24
+ });
25
+ });
26
+ };
27
+
28
+ export const changeCurrentOrgaziation = orgID => dispatch => foremanEndpoint
29
+ .get(`organizations/${orgID}/select`)
30
+ .then(() => {
31
+ dispatch({
32
+ type: CHANGE_CURRENT_ORGANIZATION_SUCCESS,
33
+ payload: orgID,
34
+ });
35
+ })
36
+ .catch(() => {
37
+ dispatch({
38
+ type: CHANGE_CURRENT_ORGANIZATION_FAILURE,
39
+ payload: orgID,
40
+ });
41
+ });
@@ -0,0 +1,33 @@
1
+ import Immutable from 'seamless-immutable';
2
+ import {
3
+ GET_ORGANIZATIONS_LIST_SUCCESS,
4
+ GET_ORGANIZATIONS_LIST_REQUEST,
5
+ GET_ORGANIZATIONS_LIST_FAILURE,
6
+ CHANGE_CURRENT_ORGANIZATION_SUCCESS,
7
+ } from '../../redux/consts';
8
+
9
+ const initialState = Immutable({ loading: false });
10
+ export default (state = initialState, action) => {
11
+ const { payload } = action;
12
+
13
+ switch (action.type) {
14
+ case GET_ORGANIZATIONS_LIST_REQUEST:
15
+ return state.set('loading', true);
16
+
17
+ case GET_ORGANIZATIONS_LIST_SUCCESS:
18
+ return state
19
+ .set('list', payload.results)
20
+ .set('loading', false);
21
+
22
+ case CHANGE_CURRENT_ORGANIZATION_SUCCESS:
23
+ return state
24
+ .set('currentId', payload)
25
+ .set('loading', false);
26
+
27
+ case GET_ORGANIZATIONS_LIST_FAILURE:
28
+ return state
29
+ .set('error', payload);
30
+ default:
31
+ return state;
32
+ }
33
+ };
@@ -0,0 +1,116 @@
1
+ import React, { Component } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Form, Button } from 'patternfly-react';
4
+ import { withRouter } from 'react-router';
5
+ import { bindActionCreators } from 'redux';
6
+ import { connect } from 'react-redux';
7
+ import Select from '../../move_to_pf/Select/Select';
8
+ import * as SelectOrgActions from './SelectOrgAction';
9
+ import reducer from './SelectOrgReducer';
10
+ import { LoadingState } from '../../move_to_pf/LoadingState';
11
+ import './SelectOrg.scss';
12
+
13
+ class SetOrganization extends Component {
14
+ constructor(props) {
15
+ super(props);
16
+ this.onSelectItem = this.onSelectItem.bind(this);
17
+ this.onSend = this.onSend.bind(this);
18
+ this.state = { disabled: true };
19
+ }
20
+
21
+ componentDidMount() {
22
+ this.props.getOrganiztionsList();
23
+ }
24
+
25
+ onSelectItem(e) {
26
+ this.setState({
27
+ item: e.target.options[e.target.selectedIndex].text,
28
+ id: e.target.value,
29
+ disabled: false,
30
+ });
31
+ }
32
+
33
+ onSend() {
34
+ const {
35
+ history,
36
+ changeCurrentOrgaziation,
37
+ redirectPath,
38
+ } = this.props;
39
+ const { id, item } = this.state;
40
+
41
+ changeCurrentOrgaziation(`${id}-${item}`).then(() =>
42
+ history.push({
43
+ pathname: redirectPath,
44
+ state: { orgChanged: this.state.item },
45
+ }));
46
+ }
47
+
48
+ render() {
49
+ const {
50
+ list,
51
+ loading,
52
+ } = this.props;
53
+
54
+ return (
55
+ <div id="select-org" className="well col-sm-6 col-sm-offset-3">
56
+ <LoadingState loading={loading} loadingText={__('Loading')}>
57
+ <Form>
58
+ <h1 className="text-center">{__('Select an Organization')}</h1>
59
+ <p className="text-center">
60
+ {__('The page you are attempting to access requires selecting a specific organization.')}
61
+ </p>
62
+ <p className="text-center">
63
+ {__('Please select one from the list below and you will be redirected.')}
64
+ </p>
65
+
66
+ <div className="form-group">
67
+ <div className="col-sm-6 col-sm-offset-3">
68
+ <Select
69
+ value={this.state.id}
70
+ placeholder={__('Select an organization')}
71
+ id="organization"
72
+ name="organization"
73
+ className="form-control"
74
+ options={list}
75
+ onChange={this.onSelectItem}
76
+ />
77
+
78
+ </div>
79
+
80
+ <div className="col-sm-3">
81
+ <Button disabled={this.state.disabled} className="btn btn-primary" onClick={this.onSend}>
82
+ {__('Select')}
83
+ </Button>
84
+ </div>
85
+ </div>
86
+ </Form>
87
+ </LoadingState>
88
+ </div>
89
+ );
90
+ }
91
+ }
92
+
93
+
94
+ SetOrganization.propTypes = {
95
+ list: PropTypes.arrayOf(PropTypes.object),
96
+ loading: PropTypes.bool.isRequired,
97
+ changeCurrentOrgaziation: PropTypes.func.isRequired,
98
+ history: PropTypes.shape({}).isRequired,
99
+ redirectPath: PropTypes.string.isRequired,
100
+ getOrganiztionsList: PropTypes.func.isRequired,
101
+ };
102
+
103
+ SetOrganization.defaultProps = {
104
+ list: [],
105
+ };
106
+
107
+ const mapStateToProps = state => ({
108
+ orgId: state.katello.setOrganization.currentId,
109
+ list: state.katello.setOrganization.list,
110
+ loading: state.katello.setOrganization.loading,
111
+ });
112
+ export const setOrganization = reducer;
113
+ const mapDispatchToProps = dispatch =>
114
+ bindActionCreators(SelectOrgActions, dispatch);
115
+
116
+ export default connect(mapStateToProps, mapDispatchToProps)(withRouter(SetOrganization));