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
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
|
+
});
|
data/webpack/global_index.js
CHANGED
@@ -2,7 +2,10 @@ import React from 'react';
|
|
2
2
|
import { addGlobalFill } from 'foremanReact/components/common/Fill/GlobalFill';
|
3
3
|
import { registerReducer } from 'foremanReact/common/MountingService';
|
4
4
|
import { translate as __ } from 'foremanReact/common/I18n';
|
5
|
+
import { registerColumns } from 'foremanReact/components/HostsIndex/Columns/core';
|
6
|
+
import componentRegistry from 'foremanReact/components/componentRegistry';
|
5
7
|
|
8
|
+
import hostsIndexColumnExtensions from './ForemanColumnExtensions/index';
|
6
9
|
import SystemStatuses from './components/extensions/about';
|
7
10
|
import {
|
8
11
|
RegistrationCommands,
|
@@ -29,6 +32,10 @@ import HostDetailsActionsBar from './components/extensions/HostDetails/ActionsBa
|
|
29
32
|
import HostsIndexActionsBar from './components/extensions/Hosts/ActionsBar';
|
30
33
|
import RecentCommunicationCardExtensions from './components/extensions/HostDetails/DetailsTabCards/RecentCommunicationCardExtensions';
|
31
34
|
import SystemPurposeCard from './components/extensions/HostDetails/Cards/SystemPurposeCard/SystemPurposeCard';
|
35
|
+
import BulkChangeHostCVModal from './components/extensions/Hosts/BulkActions/BulkChangeHostCVModal/index.js';
|
36
|
+
|
37
|
+
|
38
|
+
import ActivationKeysSearch from './components/ActivationKeysSearch';
|
32
39
|
|
33
40
|
registerReducer('katelloExtends', extendReducer);
|
34
41
|
registerReducer('katello', rootReducer);
|
@@ -80,3 +87,15 @@ addGlobalFill(
|
|
80
87
|
);
|
81
88
|
|
82
89
|
addGlobalFill('host-tab-details-cards', 'HW properties', <HwPropertiesCard key="hw-properties" />, 200);
|
90
|
+
|
91
|
+
// Hosts Index page extensions
|
92
|
+
addGlobalFill('_all-hosts-modals', 'BulkChangeHostCVModal', <BulkChangeHostCVModal key="bulk-change-host-cv-modal" />, 100);
|
93
|
+
|
94
|
+
registerColumns(hostsIndexColumnExtensions);
|
95
|
+
|
96
|
+
|
97
|
+
componentRegistry.register({
|
98
|
+
name: 'ActivationKeysSearch',
|
99
|
+
type: ActivationKeysSearch,
|
100
|
+
});
|
101
|
+
|
@@ -5,7 +5,6 @@ import {
|
|
5
5
|
Bullseye, Split, SplitItem, Button, ActionList,
|
6
6
|
ActionListItem, Dropdown, DropdownItem, KebabToggle,
|
7
7
|
} from '@patternfly/react-core';
|
8
|
-
import { Link } from 'react-router-dom';
|
9
8
|
import { TableVariant, fitContent, TableText } from '@patternfly/react-table';
|
10
9
|
import { PencilAltIcon } from '@patternfly/react-icons';
|
11
10
|
import { STATUS } from 'foremanReact/constants';
|
@@ -136,7 +135,7 @@ const ContentViewComponents = ({ cvId, details }) => {
|
|
136
135
|
id: componentCvId, content_view: cv, content_view_version: cvVersion,
|
137
136
|
latest, component_content_view_versions: componentCvVersions,
|
138
137
|
} = componentCV;
|
139
|
-
const { environments, repositories } = cvVersion || {};
|
138
|
+
const { environments, repositories, id: cvVersionId } = cvVersion || {};
|
140
139
|
const {
|
141
140
|
id,
|
142
141
|
name,
|
@@ -171,7 +170,11 @@ const ContentViewComponents = ({ cvId, details }) => {
|
|
171
170
|
</Split>),
|
172
171
|
},
|
173
172
|
{ title: environments ? <ComponentEnvironments {...{ environments }} /> : <InactiveText text={__('Not yet published')} /> },
|
174
|
-
{
|
173
|
+
{
|
174
|
+
title: cvVersionId ?
|
175
|
+
<a href={urlBuilder(`content_views/${id}#/versions/${cvVersionId}/repositories`, '')}>{repositories ? repositories.length : 0}</a> :
|
176
|
+
0,
|
177
|
+
},
|
175
178
|
{
|
176
179
|
title: <AddedStatusLabel added={!!componentCvId} />,
|
177
180
|
},
|
@@ -18,7 +18,7 @@ export const getFormData = (hostIds, search) => (post({
|
|
18
18
|
}));
|
19
19
|
|
20
20
|
export const changeContentSource =
|
21
|
-
(environmentId, contentViewId, contentSourceId, hostIds, handleSuccess) =>
|
21
|
+
(environmentId, contentViewId, contentSourceId, hostIds, handleSuccess, successToast) =>
|
22
22
|
put({
|
23
23
|
key: CHANGE_CONTENT_SOURCE,
|
24
24
|
url: foremanUrl('/api/v2/hosts/bulk/change_content_source'),
|
@@ -29,6 +29,7 @@ export const changeContentSource =
|
|
29
29
|
host_ids: hostIds,
|
30
30
|
},
|
31
31
|
errorToast: () => __('Something went wrong while updating the content source. See the logs for more information'),
|
32
|
+
successToast,
|
32
33
|
handleSuccess,
|
33
34
|
});
|
34
35
|
|
@@ -46,6 +47,7 @@ export const getContentViews = environmentId =>
|
|
46
47
|
params: {
|
47
48
|
environment_id: environmentId,
|
48
49
|
full_result: true,
|
50
|
+
order: 'default DESC', // shows the default CV before all other options
|
49
51
|
},
|
50
52
|
errorToast: () => __('Something went wrong while loading the content views. See the logs for more information'),
|
51
53
|
});
|
@@ -23,7 +23,7 @@ import { ENVIRONMENT_PATHS_KEY } from '../../../../scenes/ContentViews/component
|
|
23
23
|
import EnvironmentPaths from '../../../../scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths';
|
24
24
|
import ContentViewSelect from '../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelect';
|
25
25
|
import ContentViewSelectOption from '../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelectOption';
|
26
|
-
import { selectContentViewsStatus } from '../selectors';
|
26
|
+
import { selectContentViewsStatus, selectJobInvocationPath } from '../selectors';
|
27
27
|
import { getCVPlaceholderText, shouldDisableCVSelect } from '../../../ContentViews/components/ContentViewSelect/helpers';
|
28
28
|
import { selectEnvironmentPaths } from '../../../ContentViews/components/EnvironmentPaths/EnvironmentPathSelectors';
|
29
29
|
|
@@ -95,6 +95,9 @@ const ContentSourceForm = ({
|
|
95
95
|
contentSources,
|
96
96
|
handleContentSource,
|
97
97
|
contentSourceId,
|
98
|
+
showCVOnlyAlert,
|
99
|
+
hostDetailsPath,
|
100
|
+
hostEditPath,
|
98
101
|
contentHosts,
|
99
102
|
isLoading,
|
100
103
|
hostsUpdated,
|
@@ -108,13 +111,14 @@ const ContentSourceForm = ({
|
|
108
111
|
);
|
109
112
|
const contentViewsStatus = useSelector(selectContentViewsStatus);
|
110
113
|
const environmentPathResponse = useSelector(selectEnvironmentPaths);
|
114
|
+
const jobInvocationPath = useSelector(selectJobInvocationPath);
|
111
115
|
const envList = environmentPathResponse?.results?.map(path => path.environments).flat();
|
112
116
|
const [csSelectOpen, setCSSelectOpen] = useState(false);
|
113
117
|
const [cvSelectOpen, setCVSelectOpen] = useState(false);
|
114
118
|
const hostCount = contentHosts.length;
|
115
119
|
|
116
120
|
const handleCSSelect = (_event, selection) => {
|
117
|
-
handleContentSource(selection);
|
121
|
+
handleContentSource(typeof selection === 'number' ? selection.toString() : selection);
|
118
122
|
setCSSelectOpen(false);
|
119
123
|
};
|
120
124
|
|
@@ -127,13 +131,12 @@ const ContentSourceForm = ({
|
|
127
131
|
!!contentViewName &&
|
128
132
|
!!contentSourceId &&
|
129
133
|
hostCount !== 0);
|
130
|
-
|
131
134
|
const contentSourcesIsDisabled = (isLoading || contentSources.length === 0 ||
|
132
135
|
hostCount === 0);
|
133
|
-
const environmentIsDisabled = (isLoading ||
|
136
|
+
const environmentIsDisabled = (isLoading ||
|
134
137
|
contentSourceId === '');
|
135
138
|
const viewIsDisabled = (isLoading || contentViews.length === 0 ||
|
136
|
-
contentSourceId === ''
|
139
|
+
contentSourceId === '');
|
137
140
|
|
138
141
|
const cvPlaceholderText = getCVPlaceholderText({
|
139
142
|
contentSourceId,
|
@@ -229,6 +232,15 @@ const ContentSourceForm = ({
|
|
229
232
|
env={environments[0]}
|
230
233
|
/>))}
|
231
234
|
</ContentViewSelect>
|
235
|
+
{showCVOnlyAlert &&
|
236
|
+
<Alert
|
237
|
+
ouiaId="cv-only-alert"
|
238
|
+
variant="info"
|
239
|
+
className="margin-top-20"
|
240
|
+
title={__('Host content source will remain the same. Click Save below to update the host\'s content view environment.')}
|
241
|
+
/>
|
242
|
+
}
|
243
|
+
{!showCVOnlyAlert &&
|
232
244
|
<TextContent>
|
233
245
|
<Text
|
234
246
|
ouiaId="ccs-options-description"
|
@@ -252,27 +264,49 @@ const ContentSourceForm = ({
|
|
252
264
|
/>
|
253
265
|
</Text>
|
254
266
|
</TextContent>
|
267
|
+
}
|
255
268
|
<ActionGroup style={{ display: 'block' }}>
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
269
|
+
{!showCVOnlyAlert &&
|
270
|
+
<>
|
271
|
+
<Button
|
272
|
+
variant="primary"
|
273
|
+
id="generate_btn"
|
274
|
+
ouiaId="run-job-invocation-button"
|
275
|
+
onClick={e => handleSubmit(e, { redirectTo: jobInvocationPath })}
|
276
|
+
isDisabled={isLoading || !formIsValid() || hostsUpdated}
|
277
|
+
isLoading={isLoading}
|
278
|
+
>
|
279
|
+
{__('Run job invocation')}
|
280
|
+
</Button>
|
281
|
+
<Button
|
282
|
+
variant="secondary"
|
283
|
+
id="generate_btn"
|
284
|
+
ouiaId="update-source-button"
|
285
|
+
onClick={showTemplate}
|
286
|
+
isDisabled={isLoading || !formIsValid() || hostsUpdated}
|
287
|
+
isLoading={isLoading}
|
288
|
+
>
|
289
|
+
{__('Update hosts manually')}
|
290
|
+
</Button>
|
291
|
+
</>
|
292
|
+
}
|
293
|
+
{showCVOnlyAlert &&
|
294
|
+
<Button
|
295
|
+
variant="primary"
|
296
|
+
id="generate_btn"
|
297
|
+
ouiaId="change-cv-button"
|
298
|
+
onClick={e =>
|
299
|
+
handleSubmit(e, {
|
300
|
+
redirectTo: hostEditPath || hostDetailsPath,
|
301
|
+
showSuccessToast: true,
|
302
|
+
})
|
303
|
+
}
|
304
|
+
isDisabled={isLoading || !formIsValid() || hostsUpdated}
|
305
|
+
isLoading={isLoading}
|
306
|
+
>
|
307
|
+
{__('Save')}
|
308
|
+
</Button>
|
309
|
+
}
|
276
310
|
|
277
311
|
</ActionGroup>
|
278
312
|
</Form>);
|
@@ -288,6 +322,9 @@ ContentSourceForm.propTypes = {
|
|
288
322
|
contentSources: PropTypes.arrayOf(PropTypes.shape({})),
|
289
323
|
handleContentSource: PropTypes.func.isRequired,
|
290
324
|
contentSourceId: PropTypes.string,
|
325
|
+
showCVOnlyAlert: PropTypes.bool,
|
326
|
+
hostDetailsPath: PropTypes.string.isRequired,
|
327
|
+
hostEditPath: PropTypes.string.isRequired,
|
291
328
|
contentHosts: PropTypes.arrayOf(PropTypes.shape({})),
|
292
329
|
isLoading: PropTypes.bool,
|
293
330
|
hostsUpdated: PropTypes.bool,
|
@@ -300,6 +337,7 @@ ContentSourceForm.defaultProps = {
|
|
300
337
|
contentViewName: '',
|
301
338
|
contentSources: [],
|
302
339
|
contentSourceId: '',
|
340
|
+
showCVOnlyAlert: false,
|
303
341
|
contentHosts: [],
|
304
342
|
isLoading: false,
|
305
343
|
hostsUpdated: false,
|