katello 4.12.1 → 4.13.0
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/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/controllers/katello/api/registry/registry_proxies_controller.rb +370 -132
- 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/repositories_controller.rb +19 -13
- 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/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/sync_capsule.rb +7 -2
- 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_delete.rb +6 -1
- 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/create.rb +17 -11
- data/app/lib/actions/katello/repository/create_root.rb +4 -2
- 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/katello/upstream_subscriptions/bind_entitlement.rb +1 -1
- 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/actions/pulp3/orchestration/orphan_cleanup/remove_orphans.rb +1 -0
- data/app/lib/actions/pulp3/orphan_cleanup/purge_completed_tasks.rb +15 -0
- data/app/lib/katello/concerns/base_template_scope_extensions.rb +7 -2
- 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/concerns/organization_extensions.rb +42 -3
- data/app/models/katello/content_view.rb +30 -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 +11 -3
- data/app/models/katello/host/content_facet.rb +1 -1
- data/app/models/katello/host/subscription_facet.rb +1 -1
- data/app/models/katello/ping.rb +1 -1
- data/app/models/katello/repository.rb +32 -1
- data/app/models/katello/root_repository.rb +4 -6
- data/app/models/katello/trace_status.rb +1 -1
- 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 +21 -0
- data/app/services/katello/pulp3/api/docker.rb +4 -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/yum.rb +1 -6
- 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/foreman/smart_proxies/_content_tab.html.erb +3 -1
- 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/organizations/show.json.rabl +9 -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/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/migrate/20240520142245_add_container_push_props_to_repo.rb +7 -0
- data/db/migrate/20240531193030_remove_sha1_repository_checksum_type.rb +10 -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/checksum.service.js +6 -1
- 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 -13
- data/lib/katello/permission_creator.rb +3 -3
- data/lib/katello/permissions/registry_permissions.rb +4 -7
- data/lib/katello/plugin.rb +21 -8
- 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/package.json +0 -1
- data/webpack/ForemanColumnExtensions/index.js +129 -0
- data/webpack/components/Content/ContentTable.js +0 -1
- data/webpack/components/Content/__tests__/__snapshots__/ContentTable.test.js.snap +0 -1
- data/webpack/components/Table/TableWrapper.js +14 -0
- data/webpack/components/extensions/HostDetails/ActionsBar/index.js +1 -1
- 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 +9 -0
- data/webpack/scenes/Hosts/ChangeContentSource/actions.js +3 -1
- data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +62 -24
- data/webpack/scenes/Hosts/ChangeContentSource/index.js +24 -16
- data/webpack/scenes/ModuleStreams/ModuleStreamsPage.js +33 -39
- data/webpack/scenes/ModuleStreams/__tests__/ModuleStreamPage.test.js +4 -2
- data/webpack/scenes/ModuleStreams/__tests__/__snapshots__/ModuleStreamsTable.test.js.snap +0 -1
- data/webpack/scenes/RedHatRepositories/__tests__/__snapshots__/RedHatRepositoriesPage.test.js.snap +1 -0
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +66 -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 +60 -42
- data/app/lib/actions/katello/host/upload_package_profile.rb +0 -45
- data/app/lib/actions/katello/host/upload_profiles.rb +0 -47
- data/webpack/utils/__tests__/useParamsWithHash.test.js +0 -22
- data/webpack/utils/paramsFromHash.js +0 -16
- data/webpack/utils/useUrlParams.js +0 -14
data/package.json
CHANGED
@@ -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;
|
@@ -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
|
};
|
data/webpack/components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/BulkChangeHostCVModal.js
ADDED
@@ -0,0 +1,220 @@
|
|
1
|
+
import React, { useState } from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { useDispatch, useSelector } from 'react-redux';
|
4
|
+
import { FormattedMessage } from 'react-intl';
|
5
|
+
import { Modal, Button, Alert, TextContent, Text, TextVariants } from '@patternfly/react-core';
|
6
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
7
|
+
import { STATUS } from 'foremanReact/constants';
|
8
|
+
import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
|
9
|
+
import { selectAPIStatus } from 'foremanReact/redux/API/APISelectors';
|
10
|
+
import { ENVIRONMENT_PATHS_KEY } from '../../../../../scenes/ContentViews/components/EnvironmentPaths/EnvironmentPathConstants';
|
11
|
+
import EnvironmentPaths from '../../../../../scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths';
|
12
|
+
import ContentViewSelect from '../../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelect';
|
13
|
+
import ContentViewSelectOption from '../../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelectOption';
|
14
|
+
import api from '../../../../../services/api';
|
15
|
+
import getContentViews from '../../../../../scenes/ContentViews/ContentViewsActions';
|
16
|
+
import { selectContentViews, selectContentViewStatus } from '../../../../../scenes/ContentViews/ContentViewSelectors';
|
17
|
+
import { bulkUpdateHostContentViewAndEnvironment } from './actions';
|
18
|
+
import { getCVPlaceholderText } from '../../../../../scenes/ContentViews/components/ContentViewSelect/helpers';
|
19
|
+
import HOST_CV_AND_ENV_KEY from '../../../HostDetails/Cards/ContentViewDetailsCard/HostContentViewConstants';
|
20
|
+
|
21
|
+
const ENV_PATH_OPTIONS = { key: ENVIRONMENT_PATHS_KEY };
|
22
|
+
|
23
|
+
const BulkChangeHostCVModal = ({
|
24
|
+
isOpen,
|
25
|
+
closeModal,
|
26
|
+
selectedCount,
|
27
|
+
orgId,
|
28
|
+
fetchBulkParams,
|
29
|
+
}) => {
|
30
|
+
const [selectedLifecycleEnv, setSelectedLifecycleEnv]
|
31
|
+
= useState([]);
|
32
|
+
|
33
|
+
const [selectedContentView, setSelectedContentView] = useState(null);
|
34
|
+
const [cvSelectOpen, setCVSelectOpen] = useState(false);
|
35
|
+
const dispatch = useDispatch();
|
36
|
+
const contentViewsInEnvResponse = useSelector(state => selectContentViews(state, '_FOR_DEFAULT_ENV'));
|
37
|
+
const { results } = contentViewsInEnvResponse;
|
38
|
+
const contentViewsInEnvStatus = useSelector(state => selectContentViewStatus(state, '_FOR_DEFAULT_ENV'));
|
39
|
+
const hostUpdateStatus = useSelector(state => selectAPIStatus(state, HOST_CV_AND_ENV_KEY));
|
40
|
+
const pathsUrl = `/organizations/${orgId}/environments/paths?permission_type=promotable`;
|
41
|
+
useAPI( // No TableWrapper here, so we can useAPI from Foreman
|
42
|
+
'get',
|
43
|
+
api.getApiUrl(pathsUrl),
|
44
|
+
ENV_PATH_OPTIONS,
|
45
|
+
);
|
46
|
+
const selectedContentViewId = results?.find(cv => cv.name === selectedContentView)?.id;
|
47
|
+
|
48
|
+
const handleModalClose = () => {
|
49
|
+
setCVSelectOpen(false);
|
50
|
+
setSelectedContentView(null);
|
51
|
+
setSelectedLifecycleEnv([]);
|
52
|
+
closeModal();
|
53
|
+
};
|
54
|
+
|
55
|
+
const selectedEnv = selectedLifecycleEnv?.[0];
|
56
|
+
const selectedEnvId = selectedEnv?.id;
|
57
|
+
|
58
|
+
const handleCVSelect = (event, selection) => {
|
59
|
+
setSelectedContentView(selection);
|
60
|
+
setCVSelectOpen(false);
|
61
|
+
};
|
62
|
+
|
63
|
+
const handleEnvSelect = (selection) => {
|
64
|
+
dispatch(getContentViews({
|
65
|
+
environment_id: selection[0].id,
|
66
|
+
include_default: true,
|
67
|
+
full_result: true,
|
68
|
+
order: 'default DESC', // show Default Organization View first
|
69
|
+
}, '_FOR_DEFAULT_ENV'));
|
70
|
+
setSelectedContentView(null);
|
71
|
+
setSelectedLifecycleEnv(selection);
|
72
|
+
};
|
73
|
+
const { results: contentViewsInEnv = [] } = contentViewsInEnvResponse;
|
74
|
+
const canSave = !!(selectedContentView && selectedLifecycleEnv.length);
|
75
|
+
|
76
|
+
const handleSave = () => {
|
77
|
+
const requestBody = {
|
78
|
+
content_view_id: selectedContentViewId,
|
79
|
+
environment_id: selectedEnvId,
|
80
|
+
organization_id: orgId,
|
81
|
+
included: {
|
82
|
+
search: fetchBulkParams(),
|
83
|
+
},
|
84
|
+
};
|
85
|
+
dispatch(bulkUpdateHostContentViewAndEnvironment(
|
86
|
+
requestBody, fetchBulkParams(),
|
87
|
+
handleModalClose, handleModalClose,
|
88
|
+
));
|
89
|
+
};
|
90
|
+
|
91
|
+
const cvPlaceholderText = getCVPlaceholderText({
|
92
|
+
environments: selectedLifecycleEnv,
|
93
|
+
cvSelectOptions: contentViewsInEnv,
|
94
|
+
contentViewsStatus: contentViewsInEnvStatus,
|
95
|
+
});
|
96
|
+
|
97
|
+
const stillLoading =
|
98
|
+
(contentViewsInEnvStatus === STATUS.PENDING || hostUpdateStatus === STATUS.PENDING);
|
99
|
+
const noContentViewsAvailable =
|
100
|
+
(contentViewsInEnv.length === 0 || selectedLifecycleEnv.length === 0);
|
101
|
+
|
102
|
+
const modalActions = ([
|
103
|
+
<Button
|
104
|
+
key="add"
|
105
|
+
ouiaId="bulk-change-host-cv-modal-add-button"
|
106
|
+
variant="primary"
|
107
|
+
onClick={handleSave}
|
108
|
+
isDisabled={!canSave || hostUpdateStatus === STATUS.PENDING}
|
109
|
+
isLoading={hostUpdateStatus === STATUS.PENDING}
|
110
|
+
>
|
111
|
+
{__('Save')}
|
112
|
+
</Button>,
|
113
|
+
<Button key="cancel" ouiaId="change-host-cv-modal-cancel-button" variant="link" onClick={handleModalClose}>
|
114
|
+
Cancel
|
115
|
+
</Button>,
|
116
|
+
]);
|
117
|
+
return (
|
118
|
+
<Modal
|
119
|
+
isOpen={isOpen}
|
120
|
+
onClose={handleModalClose}
|
121
|
+
onEscapePress={handleModalClose}
|
122
|
+
title={__('Edit content view environments')}
|
123
|
+
width="50%"
|
124
|
+
position="top"
|
125
|
+
actions={modalActions}
|
126
|
+
id="bulk-change-host-cv-modal"
|
127
|
+
key="bulk-change-host-cv-modal"
|
128
|
+
ouiaId="bulk-change-host-cv-modal"
|
129
|
+
>
|
130
|
+
<TextContent>
|
131
|
+
<Text
|
132
|
+
ouiaId="bulk-change-cv-options-description"
|
133
|
+
>
|
134
|
+
<FormattedMessage
|
135
|
+
defaultMessage={__('This will update the content view environments for {hosts}.')}
|
136
|
+
values={{
|
137
|
+
hosts: (
|
138
|
+
<strong>
|
139
|
+
<FormattedMessage
|
140
|
+
defaultMessage="{count, plural, one {# {singular}} other {# {plural}}}"
|
141
|
+
values={{
|
142
|
+
count: selectedCount,
|
143
|
+
singular: __('selected host'),
|
144
|
+
plural: __('selected hosts'),
|
145
|
+
}}
|
146
|
+
id="ccs-options-i18n"
|
147
|
+
/>
|
148
|
+
</strong>
|
149
|
+
),
|
150
|
+
}}
|
151
|
+
id="bulk-change-cv-options-description-i18n"
|
152
|
+
/>
|
153
|
+
</Text>
|
154
|
+
</TextContent>
|
155
|
+
{contentViewsInEnvStatus === STATUS.RESOLVED &&
|
156
|
+
!!selectedLifecycleEnv.length && contentViewsInEnv.length === 0 &&
|
157
|
+
<Alert
|
158
|
+
ouiaId="no-cv-alert"
|
159
|
+
variant="warning"
|
160
|
+
isInline
|
161
|
+
title={__('No content views available for the selected environment')}
|
162
|
+
style={{ marginBottom: '1rem' }}
|
163
|
+
>
|
164
|
+
<a href="/content_views">{__('View the Content Views page')}</a>
|
165
|
+
{__(' to manage and promote content views, or select a different environment.')}
|
166
|
+
</Alert>
|
167
|
+
}
|
168
|
+
<EnvironmentPaths
|
169
|
+
userCheckedItems={selectedLifecycleEnv}
|
170
|
+
setUserCheckedItems={handleEnvSelect}
|
171
|
+
publishing={false}
|
172
|
+
multiSelect={false}
|
173
|
+
headerText={__('Select environment')}
|
174
|
+
isDisabled={hostUpdateStatus === STATUS.PENDING}
|
175
|
+
/>
|
176
|
+
<ContentViewSelect
|
177
|
+
selections={selectedContentView}
|
178
|
+
onClear={() => setSelectedContentView(null)}
|
179
|
+
onSelect={handleCVSelect}
|
180
|
+
isOpen={cvSelectOpen}
|
181
|
+
isDisabled={stillLoading || noContentViewsAvailable}
|
182
|
+
onToggle={isExpanded => setCVSelectOpen(isExpanded)}
|
183
|
+
placeholderText={cvPlaceholderText}
|
184
|
+
>
|
185
|
+
{(contentViewsInEnv.length !== 0 && selectedLifecycleEnv.length !== 0) &&
|
186
|
+
contentViewsInEnv?.map(cv => (
|
187
|
+
<ContentViewSelectOption
|
188
|
+
key={cv.id}
|
189
|
+
value={cv.name}
|
190
|
+
cv={cv}
|
191
|
+
env={selectedLifecycleEnv[0]}
|
192
|
+
/>
|
193
|
+
))}
|
194
|
+
</ContentViewSelect>
|
195
|
+
<hr />
|
196
|
+
<TextContent>
|
197
|
+
<Text component={TextVariants.small} ouiaId="profile-upload-reminder-text">
|
198
|
+
{__('Errata and package information will be updated at the next host check-in or package action.')}
|
199
|
+
</Text>
|
200
|
+
</TextContent>
|
201
|
+
<hr />
|
202
|
+
</Modal>
|
203
|
+
);
|
204
|
+
};
|
205
|
+
|
206
|
+
BulkChangeHostCVModal.propTypes = {
|
207
|
+
isOpen: PropTypes.bool,
|
208
|
+
closeModal: PropTypes.func,
|
209
|
+
selectedCount: PropTypes.number.isRequired,
|
210
|
+
orgId: PropTypes.number.isRequired,
|
211
|
+
fetchBulkParams: PropTypes.func.isRequired,
|
212
|
+
};
|
213
|
+
|
214
|
+
BulkChangeHostCVModal.defaultProps = {
|
215
|
+
isOpen: false,
|
216
|
+
closeModal: () => {},
|
217
|
+
};
|
218
|
+
|
219
|
+
|
220
|
+
export default BulkChangeHostCVModal;
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
2
|
+
import { API_OPERATIONS, put } from 'foremanReact/redux/API';
|
3
|
+
import { errorToast, renderTaskStartedToast } from '../../../../../scenes/Tasks/helpers';
|
4
|
+
import { foremanApi } from '../../../../../services/api';
|
5
|
+
import HOST_CV_AND_ENV_KEY from '../../../HostDetails/Cards/ContentViewDetailsCard/HostContentViewConstants';
|
6
|
+
|
7
|
+
export const bulkUpdateHostContentViewAndEnvironment =
|
8
|
+
(params, bulkParams, handleSuccess, handleError) => put({
|
9
|
+
type: API_OPERATIONS.PUT,
|
10
|
+
key: HOST_CV_AND_ENV_KEY,
|
11
|
+
url: foremanApi.getApiUrl('/hosts/bulk/environment_content_view'),
|
12
|
+
...bulkParams,
|
13
|
+
successToast: () => __('Host content view environments updating.'),
|
14
|
+
handleSuccess: (response) => {
|
15
|
+
if (handleSuccess) handleSuccess(response);
|
16
|
+
return renderTaskStartedToast(response.data);
|
17
|
+
},
|
18
|
+
handleError,
|
19
|
+
errorToast,
|
20
|
+
params,
|
21
|
+
});
|
22
|
+
|
23
|
+
export default bulkUpdateHostContentViewAndEnvironment;
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import React, { useContext } from 'react';
|
2
|
+
import { useForemanOrganization } from 'foremanReact/Root/Context/ForemanContext';
|
3
|
+
import { ForemanActionsBarContext } from 'foremanReact/components/HostDetails/ActionsBar';
|
4
|
+
import { useForemanModal } from 'foremanReact/components/ForemanModal/ForemanModalHooks';
|
5
|
+
import BulkChangeHostCVModal from './BulkChangeHostCVModal';
|
6
|
+
|
7
|
+
const BulkChangeHostCVModalScene = () => {
|
8
|
+
const org = useForemanOrganization();
|
9
|
+
const { selectedCount, fetchBulkParams } = useContext(ForemanActionsBarContext);
|
10
|
+
const { modalOpen, setModalClosed } = useForemanModal({ id: 'bulk-change-cv-modal' });
|
11
|
+
|
12
|
+
return (
|
13
|
+
<BulkChangeHostCVModal
|
14
|
+
key="bulk-change-cv-modal"
|
15
|
+
selectedCount={selectedCount}
|
16
|
+
fetchBulkParams={fetchBulkParams}
|
17
|
+
isOpen={modalOpen}
|
18
|
+
closeModal={setModalClosed}
|
19
|
+
orgId={org?.id}
|
20
|
+
/>
|
21
|
+
|
22
|
+
);
|
23
|
+
};
|
24
|
+
|
25
|
+
export default BulkChangeHostCVModalScene;
|
@@ -0,0 +1,133 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { renderWithRedux, patientlyWaitFor, act } from 'react-testing-lib-wrapper';
|
3
|
+
import userEvent from '@testing-library/user-event';
|
4
|
+
import BulkChangeHostCVModal from '../BulkChangeHostCVModal/BulkChangeHostCVModal.js';
|
5
|
+
import mockEnvPaths from '../../../HostDetails/Cards/ContentViewDetailsCard/__tests__/envPaths.fixtures.json';
|
6
|
+
import mockContentViews from '../../../HostDetails/Cards/ContentViewDetailsCard/__tests__/contentViews.fixtures.json';
|
7
|
+
import HOST_CV_AND_ENV_KEY from '../../../HostDetails/Cards/ContentViewDetailsCard/HostContentViewConstants';
|
8
|
+
import { assertNockRequest, nockInstance } from '../../../../../test-utils/nockWrapper';
|
9
|
+
import katelloApi from '../../../../../services/api';
|
10
|
+
|
11
|
+
const contentViews = katelloApi.getApiUrl('/content_views');
|
12
|
+
const renderOptions = () => ({
|
13
|
+
apiNamespace: HOST_CV_AND_ENV_KEY,
|
14
|
+
initialState: {
|
15
|
+
API: {
|
16
|
+
HOST_DETAILS: {
|
17
|
+
response: {
|
18
|
+
id: 1,
|
19
|
+
name: 'test-host',
|
20
|
+
content_facet_attributes: {
|
21
|
+
content_view_id: 1,
|
22
|
+
lifecycle_environment_id: 1,
|
23
|
+
},
|
24
|
+
organization_id: 1,
|
25
|
+
},
|
26
|
+
status: 'RESOLVED',
|
27
|
+
},
|
28
|
+
ENVIRONMENT_PATHS: {
|
29
|
+
response: mockEnvPaths,
|
30
|
+
status: 'RESOLVED',
|
31
|
+
},
|
32
|
+
},
|
33
|
+
},
|
34
|
+
});
|
35
|
+
|
36
|
+
let firstEnvPath;
|
37
|
+
let firstCV;
|
38
|
+
let secondCV;
|
39
|
+
let firstEnv;
|
40
|
+
|
41
|
+
const cvQuery = {
|
42
|
+
organization_id: 1,
|
43
|
+
include_permissions: true,
|
44
|
+
include_default: true,
|
45
|
+
environment_id: 1,
|
46
|
+
full_result: true,
|
47
|
+
order: 'default DESC',
|
48
|
+
};
|
49
|
+
|
50
|
+
beforeEach(() => {
|
51
|
+
const { results } = mockEnvPaths;
|
52
|
+
[firstEnvPath] = results;
|
53
|
+
const { environments: envResults } = firstEnvPath;
|
54
|
+
[firstEnv] = envResults;
|
55
|
+
const { results: cvResults } = mockContentViews;
|
56
|
+
[firstCV, secondCV] = cvResults;
|
57
|
+
});
|
58
|
+
|
59
|
+
jest.mock('foremanReact/common/hooks/API/APIHooks', () => ({
|
60
|
+
useAPI: jest.fn(),
|
61
|
+
}));
|
62
|
+
|
63
|
+
test('Displays environment paths', async (done) => {
|
64
|
+
const jsx = (
|
65
|
+
<BulkChangeHostCVModal
|
66
|
+
isOpen
|
67
|
+
closeModal={jest.fn()}
|
68
|
+
selectedCount={1}
|
69
|
+
fetchBulkParams={() => 'id ^ 1'}
|
70
|
+
orgId={1}
|
71
|
+
/>
|
72
|
+
);
|
73
|
+
const { getAllByText }
|
74
|
+
= renderWithRedux(jsx, renderOptions());
|
75
|
+
|
76
|
+
await patientlyWaitFor(() =>
|
77
|
+
expect(getAllByText(firstEnv.name)[0]).toBeInTheDocument());
|
78
|
+
done();
|
79
|
+
});
|
80
|
+
|
81
|
+
test('Select an env > call CV API > select a CV > Save button is enabled', async (done) => {
|
82
|
+
const contentViewsScope = nockInstance
|
83
|
+
.get(contentViews)
|
84
|
+
.query(cvQuery)
|
85
|
+
.reply(200, mockContentViews);
|
86
|
+
|
87
|
+
const jsx = (
|
88
|
+
<BulkChangeHostCVModal
|
89
|
+
isOpen
|
90
|
+
closeModal={jest.fn()}
|
91
|
+
selectedCount={1}
|
92
|
+
fetchBulkParams={() => 'id ^ 1'}
|
93
|
+
orgId={1}
|
94
|
+
/>
|
95
|
+
);
|
96
|
+
const {
|
97
|
+
getAllByText, getByText,
|
98
|
+
findByPlaceholderText, getAllByRole,
|
99
|
+
} = renderWithRedux(jsx, renderOptions());
|
100
|
+
|
101
|
+
await patientlyWaitFor(() => {
|
102
|
+
const envLabel = getAllByText(firstEnv.name)[0];
|
103
|
+
expect(envLabel).toBeInTheDocument();
|
104
|
+
});
|
105
|
+
|
106
|
+
const envRadio = getAllByRole('radio', { name: firstEnv.name })[0];
|
107
|
+
expect(envRadio).toBeInTheDocument();
|
108
|
+
|
109
|
+
await act(async () => {
|
110
|
+
userEvent.click(envRadio); // Select the Library environment
|
111
|
+
|
112
|
+
const cvDropdown = await findByPlaceholderText('Select a content view');
|
113
|
+
expect(cvDropdown).toBeInTheDocument();
|
114
|
+
|
115
|
+
userEvent.click(cvDropdown); // Open the CV dropdown
|
116
|
+
|
117
|
+
|
118
|
+
[firstCV, secondCV].forEach((cv) => {
|
119
|
+
expect(getByText(cv.name)).toBeInTheDocument(); // the content view names should be showing
|
120
|
+
});
|
121
|
+
|
122
|
+
|
123
|
+
userEvent.click(getByText(secondCV.name)); // Select the second content view
|
124
|
+
});
|
125
|
+
|
126
|
+
// find the Save button and assert that it is enabled
|
127
|
+
const saveButton = getAllByRole('button', { name: 'Save' })[0];
|
128
|
+
expect(saveButton).toBeInTheDocument();
|
129
|
+
expect(saveButton).toHaveAttribute('aria-disabled', 'false');
|
130
|
+
|
131
|
+
assertNockRequest(contentViewsScope, done);
|
132
|
+
act(done);
|
133
|
+
});
|