katello 4.12.0 → 4.13.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.
- checksums.yaml +4 -4
- data/README.md +0 -1
- data/app/assets/javascripts/katello/locale/bn/katello.js +3365 -3350
- data/app/assets/javascripts/katello/locale/bn_IN/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/ca/katello.js +3588 -3576
- data/app/assets/javascripts/katello/locale/cs/katello.js +3499 -3487
- data/app/assets/javascripts/katello/locale/cs_CZ/katello.js +4186 -4186
- data/app/assets/javascripts/katello/locale/de/katello.js +5553 -5562
- data/app/assets/javascripts/katello/locale/de_AT/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/de_DE/katello.js +3066 -3051
- data/app/assets/javascripts/katello/locale/el/katello.js +3376 -3370
- data/app/assets/javascripts/katello/locale/en/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/en_GB/katello.js +3076 -3073
- data/app/assets/javascripts/katello/locale/en_US/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/es/katello.js +5366 -5372
- data/app/assets/javascripts/katello/locale/et_EE/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/fr/katello.js +5975 -5984
- data/app/assets/javascripts/katello/locale/gl/katello.js +3125 -3113
- data/app/assets/javascripts/katello/locale/gu/katello.js +3119 -3104
- data/app/assets/javascripts/katello/locale/he_IL/katello.js +3020 -3005
- data/app/assets/javascripts/katello/locale/hi/katello.js +3137 -3122
- data/app/assets/javascripts/katello/locale/id/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/it/katello.js +4469 -4466
- data/app/assets/javascripts/katello/locale/ja/katello.js +5969 -5978
- data/app/assets/javascripts/katello/locale/ka/katello.js +5649 -5652
- data/app/assets/javascripts/katello/locale/kn/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/ko/katello.js +4717 -4720
- data/app/assets/javascripts/katello/locale/locale/katello.js +1050 -1084
- data/app/assets/javascripts/katello/locale/ml_IN/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/mr/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/nl_NL/katello.js +3116 -3101
- data/app/assets/javascripts/katello/locale/or/katello.js +3137 -3122
- data/app/assets/javascripts/katello/locale/pa/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/pl/katello.js +3210 -3195
- data/app/assets/javascripts/katello/locale/pl_PL/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/pt/katello.js +3009 -2994
- data/app/assets/javascripts/katello/locale/pt_BR/katello.js +5362 -5368
- data/app/assets/javascripts/katello/locale/ro/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/ro_RO/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/ru/katello.js +4638 -4641
- data/app/assets/javascripts/katello/locale/sl/katello.js +3051 -3036
- data/app/assets/javascripts/katello/locale/sv_SE/katello.js +3156 -3144
- data/app/assets/javascripts/katello/locale/ta/katello.js +3365 -3350
- data/app/assets/javascripts/katello/locale/ta_IN/katello.js +3121 -3106
- data/app/assets/javascripts/katello/locale/te/katello.js +3136 -3121
- data/app/assets/javascripts/katello/locale/tr/katello.js +3025 -3010
- data/app/assets/javascripts/katello/locale/vi/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/vi_VN/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/zh/katello.js +3008 -2993
- data/app/assets/javascripts/katello/locale/zh_CN/katello.js +5968 -5977
- data/app/assets/javascripts/katello/locale/zh_TW/katello.js +4694 -4697
- data/app/assets/javascripts/katello/sync_management/sync_management.js +1 -0
- data/app/controllers/katello/api/registry/registry_proxies_controller.rb +51 -124
- data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +12 -20
- data/app/controllers/katello/api/v2/activation_keys_controller.rb +10 -4
- data/app/controllers/katello/api/v2/capsule_content_controller.rb +24 -0
- data/app/controllers/katello/api/v2/content_view_versions_controller.rb +9 -2
- data/app/controllers/katello/api/v2/debs_controller.rb +1 -1
- data/app/controllers/katello/api/v2/errata_controller.rb +1 -1
- data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +12 -4
- data/app/controllers/katello/api/v2/hosts_bulk_actions_controller.rb +3 -3
- data/app/controllers/katello/api/v2/organizations_controller.rb +0 -11
- data/app/controllers/katello/api/v2/packages_controller.rb +1 -1
- data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -1
- data/app/controllers/katello/api/v2/repositories_controller.rb +18 -12
- data/app/controllers/katello/api/v2/repository_sets_controller.rb +2 -1
- data/app/controllers/katello/api/v2/simple_content_access_controller.rb +9 -22
- data/app/controllers/katello/concerns/api/v2/authorization.rb +1 -1
- data/app/helpers/katello/katello_urls_helper.rb +26 -1
- data/app/helpers/katello/subscription_mailer_helper.rb +1 -1
- data/app/jobs/create_manifest_expire_soon_warning_notifications.rb +11 -0
- data/app/lib/actions/candlepin/owner/regenerate_upstream_identity_cert.rb +21 -0
- data/app/lib/actions/katello/capsule_content/sync.rb +1 -1
- data/app/lib/actions/katello/capsule_content/verify_checksum.rb +75 -0
- data/app/lib/actions/katello/content_view/promote.rb +1 -1
- data/app/lib/actions/katello/content_view/publish.rb +1 -1
- data/app/lib/actions/katello/content_view_version/verify_checksum.rb +29 -0
- data/app/lib/actions/katello/host/hypervisors_update.rb +1 -0
- data/app/lib/actions/katello/host/update_content_view.rb +2 -2
- data/app/lib/actions/katello/organization/manifest_import.rb +5 -0
- data/app/lib/actions/katello/organization/manifest_refresh.rb +3 -0
- data/app/lib/actions/katello/repository/metadata_generate.rb +7 -1
- data/app/lib/actions/katello/repository/remove_content.rb +1 -0
- data/app/lib/actions/katello/repository/sync.rb +2 -1
- data/app/lib/actions/katello/repository/upload_files.rb +1 -0
- data/app/lib/actions/pulp3/capsule_content/verify_checksum.rb +27 -0
- data/app/lib/actions/pulp3/orchestration/content_view_version/export_repository.rb +7 -9
- data/app/lib/actions/pulp3/orchestration/content_view_version/syncable_export.rb +5 -4
- data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -2
- data/app/lib/katello/errors.rb +4 -0
- data/app/lib/katello/http_resource.rb +6 -1
- data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
- data/app/lib/katello/resources/candlepin/upstream_consumer.rb +18 -6
- data/app/lib/katello/resources/candlepin/upstream_job.rb +1 -1
- data/app/lib/katello/resources/registry.rb +25 -0
- data/app/mailers/katello/subscription_mailer.rb +3 -6
- data/app/models/katello/candlepin/repository_mapper.rb +1 -1
- data/app/models/katello/concerns/organization_extensions.rb +42 -3
- data/app/models/katello/content_view.rb +28 -0
- data/app/models/katello/content_view_environment_content_facet.rb +4 -2
- data/app/models/katello/glue/provider.rb +19 -12
- data/app/models/katello/glue/pulp/repos.rb +3 -8
- data/app/models/katello/host/content_facet.rb +1 -1
- data/app/models/katello/host/subscription_facet.rb +1 -1
- data/app/models/katello/host_collection.rb +12 -3
- data/app/models/katello/ping.rb +1 -1
- data/app/models/katello/repository.rb +33 -0
- data/app/models/katello/root_repository.rb +0 -4
- data/app/services/katello/content_unit_indexer.rb +9 -0
- data/app/services/katello/pulp3/alternate_content_source.rb +4 -6
- data/app/services/katello/pulp3/api/core.rb +13 -0
- data/app/services/katello/pulp3/api/yum.rb +11 -0
- data/app/services/katello/pulp3/docker_manifest.rb +5 -1
- data/app/services/katello/pulp3/repository/generic.rb +1 -1
- data/app/services/katello/pulp3/repository.rb +26 -6
- data/app/services/katello/pulp3/repository_mirror.rb +13 -12
- data/app/services/katello/pulp3/service_common.rb +2 -10
- data/app/services/katello/pulp3/smart_proxy_repository.rb +0 -2
- data/app/services/katello/ui_notifications/subscriptions/manifest_expire_soon_warning.rb +75 -0
- data/app/views/foreman/job_templates/update_package_-_katello_ansible_default.erb +5 -1
- data/app/views/foreman/job_templates/update_packages_by_search_query_-_katello_ansible_default.erb +2 -2
- data/app/views/foreman/job_templates/upload_profile.erb +16 -0
- data/app/views/katello/api/v2/content_view_filter_rules/show.json.rabl +9 -0
- data/app/views/katello/api/v2/docker_manifests/show.json.rabl +1 -0
- data/app/views/katello/api/v2/hosts/host_collections.json.rabl +5 -1
- data/app/views/katello/api/v2/organizations/show.json.rabl +9 -1
- data/app/views/katello/hosts/_errata_counts.html.erb +1 -1
- data/app/views/overrides/activation_keys/_host_environment_select.html.erb +1 -1
- data/app/views/overrides/activation_keys/_host_media_type_select.html.erb +15 -5
- data/app/views/overrides/activation_keys/_host_tab_pane.html.erb +1 -29
- data/config/routes/api/registry.rb +4 -8
- data/config/routes/api/v2.rb +2 -0
- data/db/migrate/20240423112842_add_fields_to_katello_docker_manifest.rb +8 -0
- data/db/migrate/20240502192021_change_katello_repository_rpms_id_seq_to_big_int.rb +9 -0
- data/db/seeds.d/109-katello-notification-blueprints.rb +6 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/activation-keys/details/activation-key-repository-sets.controller.js +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-credentials/new/views/new-content-credential.html +2 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/content-host-repository-sets.controller.js +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +0 -15
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +8 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +12 -10
- data/lib/katello/permission_creator.rb +3 -3
- data/lib/katello/permissions/registry_permissions.rb +4 -7
- data/lib/katello/plugin.rb +10 -9
- data/lib/katello/repository_types/ostree.rb +7 -0
- data/lib/katello/scheduled_jobs.rb +7 -1
- data/lib/katello/tasks/clean_backend_objects.rake +1 -1
- data/lib/katello/tasks/repository.rake +22 -0
- data/lib/katello/version.rb +1 -1
- data/locale/action_names.rb +4 -3
- data/locale/bn/katello.po +166 -151
- data/locale/bn_IN/katello.po +166 -151
- data/locale/ca/katello.po +166 -151
- data/locale/cs/katello.po +166 -151
- data/locale/cs_CZ/LC_MESSAGES/katello.mo +0 -0
- data/locale/cs_CZ/katello.po +172 -157
- data/locale/de/LC_MESSAGES/katello.mo +0 -0
- data/locale/de/katello.po +178 -163
- data/locale/de_AT/katello.po +166 -151
- data/locale/de_DE/katello.po +166 -151
- data/locale/el/katello.po +166 -151
- data/locale/en/katello.po +166 -151
- data/locale/en_GB/katello.po +166 -151
- data/locale/en_US/katello.po +166 -151
- data/locale/es/LC_MESSAGES/katello.mo +0 -0
- data/locale/es/katello.po +178 -163
- data/locale/et_EE/katello.po +166 -151
- data/locale/fr/LC_MESSAGES/katello.mo +0 -0
- data/locale/fr/katello.po +179 -164
- data/locale/gl/katello.po +166 -151
- data/locale/gu/katello.po +166 -151
- data/locale/he_IL/katello.po +166 -151
- data/locale/hi/katello.po +166 -151
- data/locale/id/katello.po +166 -151
- data/locale/it/LC_MESSAGES/katello.mo +0 -0
- data/locale/it/katello.po +169 -154
- data/locale/ja/LC_MESSAGES/katello.mo +0 -0
- data/locale/ja/katello.po +179 -164
- data/locale/ka/LC_MESSAGES/katello.mo +0 -0
- data/locale/ka/katello.po +177 -162
- data/locale/katello.pot +1119 -1062
- data/locale/kn/katello.po +166 -151
- data/locale/ko/LC_MESSAGES/katello.mo +0 -0
- data/locale/ko/katello.po +174 -159
- data/locale/ml_IN/katello.po +166 -151
- data/locale/mr/katello.po +166 -151
- data/locale/nl_NL/katello.po +166 -151
- data/locale/or/katello.po +166 -151
- data/locale/pa/katello.po +166 -151
- data/locale/pl/katello.po +166 -151
- data/locale/pl_PL/katello.po +166 -151
- data/locale/pt/katello.po +166 -151
- data/locale/pt_BR/LC_MESSAGES/katello.mo +0 -0
- data/locale/pt_BR/katello.po +178 -163
- data/locale/ro/katello.po +166 -151
- data/locale/ro_RO/katello.po +166 -151
- data/locale/ru/LC_MESSAGES/katello.mo +0 -0
- data/locale/ru/katello.po +171 -156
- data/locale/sl/katello.po +166 -151
- data/locale/sv_SE/katello.po +166 -151
- data/locale/ta/katello.po +166 -151
- data/locale/ta_IN/katello.po +166 -151
- data/locale/te/katello.po +166 -151
- data/locale/tr/katello.po +166 -151
- data/locale/vi/katello.po +166 -151
- data/locale/vi_VN/katello.po +166 -151
- data/locale/zh/katello.po +166 -151
- data/locale/zh_CN/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh_CN/katello.po +179 -164
- data/locale/zh_TW/LC_MESSAGES/katello.mo +0 -0
- data/locale/zh_TW/katello.po +171 -156
- data/webpack/ForemanColumnExtensions/index.js +129 -0
- data/webpack/components/ActivationKeysSearch/ActivationKeysSearch.test.js +28 -0
- data/webpack/components/ActivationKeysSearch/index.js +222 -0
- data/webpack/components/Table/TableWrapper.js +14 -0
- data/webpack/components/extensions/HostDetails/ActionsBar/index.js +1 -1
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab/PackagesTab.js +1 -1
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +1 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +1 -0
- data/webpack/components/extensions/Hosts/ActionsBar/index.js +20 -1
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/BulkChangeHostCVModal.js +220 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/actions.js +23 -0
- data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/index.js +25 -0
- data/webpack/components/extensions/Hosts/BulkActions/__tests__/bulkChangeHostCVModal.test.js +133 -0
- data/webpack/global_index.js +19 -0
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +6 -3
- data/webpack/scenes/Hosts/ChangeContentSource/actions.js +3 -1
- data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +63 -25
- data/webpack/scenes/Hosts/ChangeContentSource/index.js +24 -16
- data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +1 -0
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +64 -5
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/UpstreamSubscriptionsPage.js +16 -13
- data/webpack/scenes/Subscriptions/UpstreamSubscriptions/__tests__/__snapshots__/UpstreamSubscriptionsPage.test.js.snap +14 -8
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +1 -0
- data/webpack/scenes/Subscriptions/components/SubscriptionsToolbar/SubscriptionsToolbar.js +1 -1
- metadata +61 -42
- data/app/assets/javascripts/katello/hosts/activation_key_edit.js +0 -167
- data/app/lib/actions/katello/host/upload_package_profile.rb +0 -45
- data/app/lib/actions/katello/host/upload_profiles.rb +0 -47
@@ -0,0 +1,129 @@
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
2
|
+
import React from 'react';
|
3
|
+
import {
|
4
|
+
BugIcon,
|
5
|
+
SecurityIcon,
|
6
|
+
EnhancementIcon,
|
7
|
+
PackageIcon,
|
8
|
+
} from '@patternfly/react-icons';
|
9
|
+
import { Link } from 'react-router-dom';
|
10
|
+
import { Flex, FlexItem } from '@patternfly/react-core';
|
11
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
12
|
+
import RelativeDateTime from 'foremanReact/components/common/dates/RelativeDateTime';
|
13
|
+
|
14
|
+
const hostsIndexColumnExtensions = [
|
15
|
+
{
|
16
|
+
columnName: 'rhel_lifecycle_status',
|
17
|
+
title: __('RHEL Lifecycle status'),
|
18
|
+
wrapper: (hostDetails) => {
|
19
|
+
const rhelLifecycle = hostDetails?.rhel_lifecycle_status_label;
|
20
|
+
return rhelLifecycle || '—';
|
21
|
+
},
|
22
|
+
weight: 2000,
|
23
|
+
isSorted: true,
|
24
|
+
},
|
25
|
+
{
|
26
|
+
columnName: 'installable_updates',
|
27
|
+
title: __('Installable updates'),
|
28
|
+
wrapper: (hostDetails) => {
|
29
|
+
const errataCounts = hostDetails?.content_facet_attributes?.errata_counts;
|
30
|
+
const registered = !!hostDetails?.subscription_facet_attributes?.uuid;
|
31
|
+
const { security, bugfix, enhancement } = errataCounts ?? {};
|
32
|
+
const upgradableRpmCount = hostDetails?.content_facet_attributes?.upgradable_package_count;
|
33
|
+
if (!registered) return '—';
|
34
|
+
const hostErrataUrl = type => `hosts/${hostDetails?.name}#/Content/errata?type=${type}&show=installable`;
|
35
|
+
return (
|
36
|
+
<Flex alignContent={{ default: 'alignContentSpaceBetween' }}>
|
37
|
+
{security !== undefined &&
|
38
|
+
<FlexItem>
|
39
|
+
<SecurityIcon color="#0066cc" />
|
40
|
+
<Link to={hostErrataUrl('security')}>{security}</Link>
|
41
|
+
</FlexItem>
|
42
|
+
}
|
43
|
+
{bugfix !== undefined &&
|
44
|
+
<FlexItem>
|
45
|
+
<BugIcon color="#8bc1f7" />
|
46
|
+
<Link to={hostErrataUrl('bugfix')}>{bugfix}</Link>
|
47
|
+
</FlexItem>
|
48
|
+
}
|
49
|
+
{enhancement !== undefined &&
|
50
|
+
<FlexItem>
|
51
|
+
<EnhancementIcon color="#002f5d" />
|
52
|
+
<Link to={hostErrataUrl('enhancement')}>{enhancement}</Link>
|
53
|
+
</FlexItem>
|
54
|
+
}
|
55
|
+
{upgradableRpmCount !== undefined &&
|
56
|
+
<FlexItem>
|
57
|
+
<PackageIcon />
|
58
|
+
<Link to={`hosts/${hostDetails?.name}#/Content/Packages?status=Upgradable`}>{upgradableRpmCount}</Link>
|
59
|
+
</FlexItem>
|
60
|
+
}
|
61
|
+
</Flex>
|
62
|
+
);
|
63
|
+
},
|
64
|
+
weight: 2100,
|
65
|
+
isSorted: false,
|
66
|
+
},
|
67
|
+
{
|
68
|
+
columnName: 'last_checkin',
|
69
|
+
title: __('Last seen'),
|
70
|
+
wrapper: (hostDetails) => {
|
71
|
+
const lastCheckin =
|
72
|
+
hostDetails?.subscription_facet_attributes?.last_checkin;
|
73
|
+
return <RelativeDateTime defaultValue="—" date={lastCheckin} />;
|
74
|
+
},
|
75
|
+
weight: 2200,
|
76
|
+
isSorted: true,
|
77
|
+
},
|
78
|
+
{
|
79
|
+
columnName: 'lifecycle_environment',
|
80
|
+
title: __('Lifecycle environment'),
|
81
|
+
wrapper: (hostDetails) => {
|
82
|
+
const lifecycleEnvironment =
|
83
|
+
hostDetails?.content_facet_attributes?.lifecycle_environment?.name;
|
84
|
+
return lifecycleEnvironment || '—';
|
85
|
+
},
|
86
|
+
weight: 2300,
|
87
|
+
isSorted: true,
|
88
|
+
},
|
89
|
+
{
|
90
|
+
columnName: 'content_view',
|
91
|
+
title: __('Content view'),
|
92
|
+
wrapper: (hostDetails) => {
|
93
|
+
const contentView =
|
94
|
+
hostDetails?.content_facet_attributes?.content_view?.name;
|
95
|
+
return contentView || '—';
|
96
|
+
},
|
97
|
+
weight: 2400,
|
98
|
+
isSorted: true,
|
99
|
+
},
|
100
|
+
{
|
101
|
+
columnName: 'content_source',
|
102
|
+
title: __('Content source'),
|
103
|
+
wrapper: (hostDetails) => {
|
104
|
+
const contentSource =
|
105
|
+
hostDetails?.content_facet_attributes?.content_source_name;
|
106
|
+
return contentSource || '—';
|
107
|
+
},
|
108
|
+
weight: 2500,
|
109
|
+
isSorted: false,
|
110
|
+
},
|
111
|
+
{
|
112
|
+
columnName: 'registered_at',
|
113
|
+
title: __('Registered at'),
|
114
|
+
wrapper: (hostDetails) => {
|
115
|
+
const registeredAt = hostDetails?.subscription_facet_attributes?.registered_at;
|
116
|
+
return <RelativeDateTime defaultValue="—" date={registeredAt} />;
|
117
|
+
},
|
118
|
+
weight: 2600,
|
119
|
+
isSorted: true,
|
120
|
+
},
|
121
|
+
];
|
122
|
+
|
123
|
+
hostsIndexColumnExtensions.forEach((column) => {
|
124
|
+
column.tableName = 'hosts';
|
125
|
+
column.categoryName = 'Content';
|
126
|
+
column.categoryKey = 'content';
|
127
|
+
});
|
128
|
+
|
129
|
+
export default hostsIndexColumnExtensions;
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { renderWithRedux } from 'react-testing-lib-wrapper';
|
3
|
+
import ActivationKeysSearch from './index';
|
4
|
+
|
5
|
+
describe('ActivationKeysSearch', () => {
|
6
|
+
const mockQuerySelector = jest.spyOn(document, 'querySelector');
|
7
|
+
mockQuerySelector.mockImplementation((selector) => {
|
8
|
+
if (selector === '#hostgroup_lifecycle_environment_id') {
|
9
|
+
return {
|
10
|
+
options: [{}],
|
11
|
+
selectedIndex: 0,
|
12
|
+
value: '1',
|
13
|
+
};
|
14
|
+
}
|
15
|
+
if (selector === '#hostgroup_content_view_id') {
|
16
|
+
return {
|
17
|
+
options: [{}],
|
18
|
+
selectedIndex: 0,
|
19
|
+
value: '2 ',
|
20
|
+
};
|
21
|
+
}
|
22
|
+
return null;
|
23
|
+
});
|
24
|
+
it('renders without crashing', () => {
|
25
|
+
const { getByText } = renderWithRedux(<ActivationKeysSearch />, {});
|
26
|
+
expect(getByText('Activation Key information')).toBeInTheDocument();
|
27
|
+
});
|
28
|
+
});
|
@@ -0,0 +1,222 @@
|
|
1
|
+
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
2
|
+
import { useDispatch, useSelector } from 'react-redux';
|
3
|
+
import {
|
4
|
+
Form,
|
5
|
+
FormGroup,
|
6
|
+
Spinner,
|
7
|
+
EmptyState,
|
8
|
+
Title,
|
9
|
+
Button,
|
10
|
+
Select,
|
11
|
+
SelectOption,
|
12
|
+
SelectVariant,
|
13
|
+
Alert,
|
14
|
+
} from '@patternfly/react-core';
|
15
|
+
import { FormattedMessage } from 'react-intl';
|
16
|
+
import $ from 'jquery';
|
17
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
18
|
+
import { get } from 'foremanReact/redux/API';
|
19
|
+
import { foremanUrl } from 'foremanReact/common/helpers';
|
20
|
+
import { STATUS } from 'foremanReact/constants';
|
21
|
+
import { selectAPIStatus } from 'foremanReact/redux/API/APISelectors';
|
22
|
+
|
23
|
+
const getSelectedEnvId = () => {
|
24
|
+
const selectElement = document.querySelector('#hostgroup_lifecycle_environment_id');
|
25
|
+
const selectedOption = selectElement.options[selectElement.selectedIndex];
|
26
|
+
let dataId = selectedOption?.getAttribute?.('data-id');
|
27
|
+
if (!dataId) {
|
28
|
+
dataId = selectElement.value;
|
29
|
+
}
|
30
|
+
return dataId;
|
31
|
+
};
|
32
|
+
const getSelectedContentViewId = () => {
|
33
|
+
const selectElement = document.querySelector('#hostgroup_content_view_id');
|
34
|
+
const selectedOption = selectElement.options[selectElement.selectedIndex];
|
35
|
+
let dataId = selectedOption?.getAttribute?.('data-id');
|
36
|
+
if (!dataId) {
|
37
|
+
dataId = selectElement.value;
|
38
|
+
}
|
39
|
+
return dataId;
|
40
|
+
};
|
41
|
+
const ActivationKeysSearch = () => {
|
42
|
+
const ACTIVATION_KEYS = 'ACTIVATION_KEYS';
|
43
|
+
const KT_AK_LABEL = 'kt_activation_keys';
|
44
|
+
const [selectedEnvId, setSelectedEnvId] = useState(getSelectedEnvId());
|
45
|
+
const [selectedContentViewId, setSelectedContentViewId] = useState(getSelectedContentViewId());
|
46
|
+
const isLoading =
|
47
|
+
useSelector(state => selectAPIStatus(state, ACTIVATION_KEYS)) === STATUS.PENDING;
|
48
|
+
const [activationKeys, setActivationKeys] = useState([]);
|
49
|
+
const [selectedKeys, setSelectedKeys] = useState([]);
|
50
|
+
const [isOpen, setIsOpen] = useState(false);
|
51
|
+
const dispatch = useDispatch();
|
52
|
+
|
53
|
+
const ktLoadActivationKeys = useCallback(() => {
|
54
|
+
if (selectedEnvId && selectedContentViewId) {
|
55
|
+
dispatch(get({
|
56
|
+
key: ACTIVATION_KEYS,
|
57
|
+
url: foremanUrl(`/katello/api/v2/environments/${selectedEnvId}/activation_keys`),
|
58
|
+
params: { content_view_id: selectedContentViewId },
|
59
|
+
handleSuccess: ({ data }) => {
|
60
|
+
setActivationKeys(data.results);
|
61
|
+
},
|
62
|
+
errorToast: () =>
|
63
|
+
__('There was a problem retrieving Activation Key data from the server.'),
|
64
|
+
}));
|
65
|
+
}
|
66
|
+
}, [dispatch, selectedEnvId, selectedContentViewId, setActivationKeys]);
|
67
|
+
const paramContainer = useMemo(() => {
|
68
|
+
let ret;
|
69
|
+
const inputs = document.querySelectorAll("div#parameters .fields input[type='text']");
|
70
|
+
inputs.forEach((input) => {
|
71
|
+
if (input.value === KT_AK_LABEL) {
|
72
|
+
ret = input.closest('.fields');
|
73
|
+
}
|
74
|
+
});
|
75
|
+
return ret;
|
76
|
+
}, []);
|
77
|
+
|
78
|
+
useEffect(() => {
|
79
|
+
$('#hostgroup_lifecycle_environment_id').on('change', () => setSelectedEnvId(getSelectedEnvId)); // cant use eventlistener on select2
|
80
|
+
$('#hostgroup_content_view_id').on('change', () =>
|
81
|
+
setSelectedContentViewId(getSelectedContentViewId())); // cant use eventlistener on select2
|
82
|
+
if (selectedEnvId && selectedContentViewId) {
|
83
|
+
ktLoadActivationKeys();
|
84
|
+
}
|
85
|
+
|
86
|
+
const ktHideParams = () => {
|
87
|
+
if (paramContainer) {
|
88
|
+
paramContainer.style.display = 'none';
|
89
|
+
}
|
90
|
+
};
|
91
|
+
|
92
|
+
const ktAkGetKeysFromParam = () => {
|
93
|
+
let keys = [];
|
94
|
+
if (paramContainer) {
|
95
|
+
const textarea = paramContainer.querySelector('textarea');
|
96
|
+
if (textarea) {
|
97
|
+
keys = textarea.value.split(',').map(key => key.trim());
|
98
|
+
}
|
99
|
+
}
|
100
|
+
return keys;
|
101
|
+
};
|
102
|
+
ktHideParams();
|
103
|
+
setSelectedKeys(ktAkGetKeysFromParam());
|
104
|
+
}, [ktLoadActivationKeys, paramContainer, selectedContentViewId, selectedEnvId]);
|
105
|
+
|
106
|
+
useEffect(() => {
|
107
|
+
function ktSetParam() {
|
108
|
+
let paramContainerCopy = paramContainer;
|
109
|
+
if (selectedKeys.length > 0) {
|
110
|
+
const value = selectedKeys.map(key => key.trim()).join(',');
|
111
|
+
if (!paramContainerCopy) {
|
112
|
+
// we create the param for kt_activation_keys
|
113
|
+
const addParameterButton = document.querySelector('#parameters .btn-primary');
|
114
|
+
addParameterButton.click();
|
115
|
+
const directionOfAddedItems = addParameterButton.getAttribute('direction');
|
116
|
+
const paramContainers = document.querySelectorAll('#parameters .fields');
|
117
|
+
if (directionOfAddedItems === 'append') {
|
118
|
+
paramContainerCopy = paramContainers[paramContainers.length - 1];
|
119
|
+
} else {
|
120
|
+
[paramContainerCopy] = paramContainers;
|
121
|
+
}
|
122
|
+
paramContainerCopy.querySelector("input[name*='name']").value = KT_AK_LABEL;
|
123
|
+
}
|
124
|
+
paramContainerCopy.querySelector('textarea').value = value;
|
125
|
+
paramContainerCopy.querySelector("input[type='hidden']").value = 0;
|
126
|
+
} else if (paramContainerCopy) {
|
127
|
+
// we remove the param by setting destroy to 1
|
128
|
+
paramContainerCopy.querySelector("input[type='hidden']").value = 1;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
ktSetParam();
|
132
|
+
}, [paramContainer, selectedKeys]);
|
133
|
+
|
134
|
+
if (!(selectedEnvId && selectedContentViewId)) {
|
135
|
+
return (
|
136
|
+
<EmptyState>
|
137
|
+
<Title headingLevel="h4" size="lg" ouiaId="ak-empty-state-title">
|
138
|
+
{__('Please select a lifecycle environment and content view to view activation keys.')}
|
139
|
+
</Title>
|
140
|
+
</EmptyState>
|
141
|
+
);
|
142
|
+
}
|
143
|
+
|
144
|
+
const onSelect = (event, selection) => {
|
145
|
+
setIsOpen(false);
|
146
|
+
if (selectedKeys.includes(selection)) {
|
147
|
+
setSelectedKeys(prevState => prevState.filter(item => item !== selection));
|
148
|
+
} else {
|
149
|
+
setSelectedKeys(prevState => [...prevState, selection]);
|
150
|
+
}
|
151
|
+
};
|
152
|
+
const isEmptyResults = activationKeys.length === 0;
|
153
|
+
return (
|
154
|
+
<div>
|
155
|
+
<Form isHorizontal>
|
156
|
+
<FormGroup label={__('Activation Keys')}>
|
157
|
+
<Select
|
158
|
+
ouiaId="ak-select"
|
159
|
+
variant={SelectVariant.typeaheadMulti}
|
160
|
+
onToggle={setIsOpen}
|
161
|
+
onSelect={onSelect}
|
162
|
+
selections={selectedKeys}
|
163
|
+
isOpen={isOpen}
|
164
|
+
isCreatable
|
165
|
+
shouldResetOnSelect
|
166
|
+
isDisabled={isLoading || isEmptyResults}
|
167
|
+
placeholderText={
|
168
|
+
isEmptyResults
|
169
|
+
? __('The selected lifecycle environment contains no activation keys')
|
170
|
+
: null
|
171
|
+
}
|
172
|
+
>
|
173
|
+
{activationKeys.map(({ id, name }) => (
|
174
|
+
<SelectOption key={id} value={name} />
|
175
|
+
))}
|
176
|
+
</Select>
|
177
|
+
</FormGroup>
|
178
|
+
<Alert title={__('Activation Key information')} variant="info" ouiaId="ak-info">
|
179
|
+
<p>{__("The value will be available in templates as @host.params['kt_activation_keys']")}</p>
|
180
|
+
<p>
|
181
|
+
<FormattedMessage
|
182
|
+
id="ak-link-manage"
|
183
|
+
defaultMessage={__('Activation keys can be managed {here}.')}
|
184
|
+
values={{
|
185
|
+
here: (
|
186
|
+
<b>
|
187
|
+
<a href="/activation_keys" target="_blank">
|
188
|
+
{__('here')}
|
189
|
+
</a>
|
190
|
+
</b>
|
191
|
+
),
|
192
|
+
}}
|
193
|
+
/>
|
194
|
+
</p>
|
195
|
+
<p>
|
196
|
+
<FormattedMessage
|
197
|
+
id="ak-subscriptions-info"
|
198
|
+
defaultMessage={__('Activation keys may be used during {system_registration}.')}
|
199
|
+
values={{
|
200
|
+
system_registration: <a href="/hosts/register">{__('system registration')}</a>,
|
201
|
+
}}
|
202
|
+
/>
|
203
|
+
</p>
|
204
|
+
<p>
|
205
|
+
<Button
|
206
|
+
id="ak_refresh_subscriptions"
|
207
|
+
variant="link"
|
208
|
+
onClick={ktLoadActivationKeys}
|
209
|
+
ouiaId="ak-refresh-button"
|
210
|
+
isInline
|
211
|
+
>
|
212
|
+
{__('Reload data')}
|
213
|
+
</Button>
|
214
|
+
</p>
|
215
|
+
</Alert>
|
216
|
+
</Form>
|
217
|
+
{isLoading && <Spinner id="ak-subscriptions-spinner" />}
|
218
|
+
</div>
|
219
|
+
);
|
220
|
+
};
|
221
|
+
|
222
|
+
export default ActivationKeysSearch;
|
@@ -36,10 +36,12 @@ const TableWrapper = ({
|
|
36
36
|
selectAll,
|
37
37
|
selectAllMode,
|
38
38
|
selectNone,
|
39
|
+
selectDefault,
|
39
40
|
selectPage,
|
40
41
|
areAllRowsOnPageSelected,
|
41
42
|
areAllRowsSelected,
|
42
43
|
selectedCount,
|
44
|
+
selectedDefaultCount,
|
43
45
|
selectedResults,
|
44
46
|
clearSelectedResults,
|
45
47
|
emptySearchBody,
|
@@ -49,6 +51,8 @@ const TableWrapper = ({
|
|
49
51
|
nodesBelowSearch,
|
50
52
|
bookmarkController,
|
51
53
|
readOnlyBookmarks,
|
54
|
+
inclusionSet,
|
55
|
+
exclusionSet,
|
52
56
|
...allTableProps
|
53
57
|
}) => {
|
54
58
|
const dispatch = useDispatch();
|
@@ -182,7 +186,9 @@ const TableWrapper = ({
|
|
182
186
|
selectAll,
|
183
187
|
selectPage,
|
184
188
|
selectNone,
|
189
|
+
selectDefault,
|
185
190
|
selectedCount,
|
191
|
+
selectedDefaultCount,
|
186
192
|
pageRowCount,
|
187
193
|
}
|
188
194
|
}
|
@@ -298,11 +304,13 @@ TableWrapper.propTypes = {
|
|
298
304
|
])),
|
299
305
|
displaySelectAllCheckbox: PropTypes.bool,
|
300
306
|
selectedCount: PropTypes.number,
|
307
|
+
selectedDefaultCount: PropTypes.number,
|
301
308
|
selectedResults: PropTypes.arrayOf(PropTypes.shape({})),
|
302
309
|
clearSelectedResults: PropTypes.func,
|
303
310
|
selectAll: PropTypes.func,
|
304
311
|
selectAllMode: PropTypes.bool,
|
305
312
|
selectNone: PropTypes.func,
|
313
|
+
selectDefault: PropTypes.func,
|
306
314
|
selectPage: PropTypes.func,
|
307
315
|
areAllRowsOnPageSelected: PropTypes.func,
|
308
316
|
areAllRowsSelected: PropTypes.func,
|
@@ -314,6 +322,8 @@ TableWrapper.propTypes = {
|
|
314
322
|
bookmarkController: PropTypes.string,
|
315
323
|
readOnlyBookmarks: PropTypes.bool,
|
316
324
|
resetFilters: PropTypes.func,
|
325
|
+
inclusionSet: PropTypes.oneOfType([PropTypes.array, PropTypes.element, PropTypes.object]),
|
326
|
+
exclusionSet: PropTypes.oneOfType([PropTypes.array, PropTypes.element, PropTypes.object]),
|
317
327
|
};
|
318
328
|
|
319
329
|
TableWrapper.defaultProps = {
|
@@ -329,11 +339,13 @@ TableWrapper.defaultProps = {
|
|
329
339
|
toggleGroup: null,
|
330
340
|
displaySelectAllCheckbox: false,
|
331
341
|
selectedCount: 0,
|
342
|
+
selectedDefaultCount: 0,
|
332
343
|
selectedResults: [],
|
333
344
|
clearSelectedResults: noop,
|
334
345
|
selectAll: undefined,
|
335
346
|
selectAllMode: false,
|
336
347
|
selectNone: undefined,
|
348
|
+
selectDefault: undefined,
|
337
349
|
selectPage: undefined,
|
338
350
|
areAllRowsOnPageSelected: noop,
|
339
351
|
areAllRowsSelected: noop,
|
@@ -346,6 +358,8 @@ TableWrapper.defaultProps = {
|
|
346
358
|
readOnlyBookmarks: false,
|
347
359
|
resetFilters: undefined,
|
348
360
|
autocompleteQueryParams: undefined,
|
361
|
+
inclusionSet: new Set([]),
|
362
|
+
exclusionSet: new Set([]),
|
349
363
|
};
|
350
364
|
|
351
365
|
export default TableWrapper;
|
@@ -65,7 +65,7 @@ const HostActionsBar = () => {
|
|
65
65
|
<DropdownItem
|
66
66
|
ouiaId="katello-change-host-content-source"
|
67
67
|
key="katello-change-host-content-source"
|
68
|
-
href={foremanUrl(`/change_host_content_source?host_id=${hostDetails?.id}`)}
|
68
|
+
href={foremanUrl(`/change_host_content_source?host_id=${hostDetails?.id}&initialContentSourceId=${hostDetails?.content_facet_attributes?.content_source_id}`)}
|
69
69
|
icon={<CubeIcon />}
|
70
70
|
>
|
71
71
|
{__('Change content source')}
|
@@ -1,8 +1,11 @@
|
|
1
|
-
import React, { useContext } from 'react';
|
1
|
+
import React, { useContext, useEffect } from 'react';
|
2
|
+
import { useDispatch } from 'react-redux';
|
2
3
|
import { DropdownItem } from '@patternfly/react-core';
|
3
4
|
import { translate as __ } from 'foremanReact/common/I18n';
|
4
5
|
import { foremanUrl } from 'foremanReact/common/helpers';
|
5
6
|
import { ForemanHostsIndexActionsBarContext } from 'foremanReact/components/HostsIndex';
|
7
|
+
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
8
|
+
import { addModal } from 'foremanReact/components/ForemanModal/ForemanModalActions';
|
6
9
|
|
7
10
|
const HostActionsBar = () => {
|
8
11
|
const {
|
@@ -11,6 +14,14 @@ const HostActionsBar = () => {
|
|
11
14
|
selectAllMode,
|
12
15
|
} = useContext(ForemanHostsIndexActionsBarContext);
|
13
16
|
|
17
|
+
const dispatch = useDispatch();
|
18
|
+
useEffect(() => {
|
19
|
+
dispatch(addModal({
|
20
|
+
id: 'bulk-change-cv-modal',
|
21
|
+
}));
|
22
|
+
}, [dispatch]);
|
23
|
+
const { setModalOpen } = useForemanModal({ id: 'bulk-change-cv-modal' });
|
24
|
+
|
14
25
|
let href = '';
|
15
26
|
if (selectAllMode) {
|
16
27
|
const query = fetchBulkParams({ selectAllQuery: 'created_at < "1 second ago"' });
|
@@ -29,6 +40,14 @@ const HostActionsBar = () => {
|
|
29
40
|
>
|
30
41
|
{__('Change content source')}
|
31
42
|
</DropdownItem>
|
43
|
+
<DropdownItem
|
44
|
+
ouiaId="bulk-change-cv-dropdown-item"
|
45
|
+
key="bulk-change-cv-dropdown-item"
|
46
|
+
onClick={setModalOpen}
|
47
|
+
isDisabled={selectedCount === 0}
|
48
|
+
>
|
49
|
+
{__('Change content view environments')}
|
50
|
+
</DropdownItem>
|
32
51
|
</>
|
33
52
|
);
|
34
53
|
};
|