katello 4.1.4 → 4.2.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/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +2 -2
- data/app/controllers/katello/api/v2/content_credentials_controller.rb +3 -3
- data/app/controllers/katello/api/v2/content_uploads_controller.rb +3 -1
- data/app/controllers/katello/api/v2/content_view_components_controller.rb +33 -1
- data/app/controllers/katello/api/v2/content_views_controller.rb +12 -0
- data/app/controllers/katello/api/v2/host_errata_controller.rb +1 -1
- data/app/controllers/katello/api/v2/products_bulk_actions_controller.rb +1 -2
- data/app/controllers/katello/api/v2/products_controller.rb +4 -4
- data/app/controllers/katello/api/v2/repositories_bulk_actions_controller.rb +3 -11
- data/app/controllers/katello/api/v2/repositories_controller.rb +68 -47
- data/app/controllers/katello/api/v2/upstream_subscriptions_controller.rb +0 -28
- data/app/controllers/katello/concerns/api/v2/registration_commands_controller_extensions.rb +26 -5
- data/app/controllers/katello/concerns/api/v2/registration_controller_extensions.rb +26 -1
- data/app/lib/actions/candlepin/environment/destroy.rb +2 -0
- data/app/lib/actions/katello/agent_action.rb +2 -2
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +3 -2
- data/app/lib/actions/katello/{gpg_key → content_credential}/update.rb +1 -1
- data/app/lib/actions/katello/content_view/publish.rb +6 -1
- data/app/lib/actions/katello/content_view_version/create_repos.rb +1 -1
- data/app/lib/actions/katello/content_view_version/incremental_update.rb +0 -47
- data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +1 -1
- data/app/lib/actions/katello/repository/clone_contents.rb +1 -7
- data/app/lib/actions/katello/repository/clone_to_environment.rb +1 -7
- data/app/lib/actions/katello/repository/create.rb +4 -8
- data/app/lib/actions/katello/repository/create_root.rb +1 -1
- data/app/lib/actions/katello/repository/destroy.rb +1 -3
- data/app/lib/actions/katello/repository/import_upload.rb +3 -2
- data/app/lib/actions/katello/repository/instance_update.rb +1 -1
- data/app/lib/actions/katello/repository/metadata_generate.rb +2 -8
- data/app/lib/actions/katello/repository/multi_clone_contents.rb +0 -1
- data/app/lib/actions/katello/repository/refresh_repository.rb +1 -4
- data/app/lib/actions/katello/repository/remove_content.rb +6 -4
- data/app/lib/actions/katello/repository/sync.rb +5 -25
- data/app/lib/actions/katello/repository/update.rb +1 -2
- data/app/lib/actions/katello/repository/update_http_proxy_details.rb +2 -5
- data/app/lib/actions/katello/repository/update_redhat_repository.rb +1 -1
- data/app/lib/actions/katello/repository/upload_files.rb +8 -3
- data/app/lib/actions/katello/repository/upload_package_group.rb +2 -11
- data/app/lib/actions/katello/repository/verify_checksum.rb +0 -1
- data/app/lib/actions/katello/repository_set/enable_repository.rb +1 -1
- data/app/lib/actions/pulp3/orchestration/repository/create.rb +2 -2
- data/app/lib/actions/pulp3/repository/create.rb +3 -4
- data/app/lib/actions/pulp3/repository/create_remote.rb +1 -6
- data/app/lib/actions/pulp3/repository/repair.rb +4 -0
- data/app/lib/katello/errors.rb +1 -0
- data/app/lib/katello/http_resource.rb +26 -73
- data/app/lib/katello/qpid/connection.rb +1 -3
- data/app/lib/katello/resources/candlepin/consumer.rb +1 -1
- data/app/lib/katello/resources/candlepin/environment.rb +2 -0
- data/app/lib/katello/resources/registry.rb +7 -20
- data/app/lib/katello/util/http_proxy.rb +0 -3
- data/app/lib/katello/validators/gpg_key_content_validator.rb +1 -1
- data/app/models/katello/authorization/{gpg_key.rb → content_credential.rb} +1 -1
- data/app/models/katello/authorization/product.rb +0 -4
- data/app/models/katello/concerns/host_managed_extensions.rb +2 -16
- data/app/models/katello/concerns/organization_extensions.rb +1 -1
- data/app/models/katello/concerns/pulp_database_unit.rb +13 -5
- data/app/models/katello/concerns/smart_proxy_extensions.rb +45 -41
- data/app/models/katello/{gpg_key.rb → content_credential.rb} +4 -4
- data/app/models/katello/content_view.rb +6 -1
- data/app/models/katello/generic_content_unit.rb +16 -0
- data/app/models/katello/glue/pulp/repos.rb +9 -25
- data/app/models/katello/kt_environment.rb +1 -1
- data/app/models/katello/product.rb +4 -4
- data/app/models/katello/repository.rb +13 -7
- data/app/models/katello/repository_generic_content_unit.rb +7 -0
- data/app/models/katello/root_repository.rb +38 -7
- data/app/models/setting/content.rb +5 -0
- data/app/services/cert/certs.rb +16 -8
- data/app/services/katello/applicability/applicable_content_helper.rb +1 -2
- data/app/services/katello/candlepin/consumer.rb +6 -0
- data/app/services/katello/component_view_presenter.rb +27 -0
- data/app/services/katello/pulp/repository.rb +1 -1
- data/app/services/katello/pulp/server.rb +2 -2
- data/app/services/katello/pulp3/api/core.rb +4 -0
- data/app/services/katello/pulp3/api/generic.rb +68 -0
- data/app/services/katello/pulp3/generic_content_unit.rb +29 -0
- data/app/services/katello/pulp3/pulp_content_unit.rb +5 -1
- data/app/services/katello/pulp3/repository/generic.rb +94 -0
- data/app/services/katello/pulp3/repository/yum.rb +4 -5
- data/app/services/katello/pulp3/repository.rb +27 -12
- data/app/services/katello/pulp3/repository_mirror.rb +2 -2
- data/app/services/katello/pulp3/smart_proxy_repository.rb +4 -4
- data/app/services/katello/registration_manager.rb +18 -7
- data/app/services/katello/repository_type.rb +59 -1
- data/app/services/katello/repository_type_manager.rb +116 -24
- data/app/views/katello/api/v2/content_views/base.json.rabl +4 -4
- data/app/views/katello/api/v2/repositories/show.json.rabl +1 -0
- data/app/views/smart_proxies/plugins/_pulpcore.html.erb +2 -5
- data/app/views/smart_proxies/pulp_status.html.erb +0 -7
- data/config/katello.yaml.example +0 -21
- data/config/routes/api/v2.rb +2 -1
- data/db/functions/deb_version_cmp_v01.sql +200 -0
- data/db/migrate/20171110082124_add_ssl_certs_to_products_and_repos.rb +5 -1
- data/db/migrate/20200402130013_add_repsoitory_docker_meta_tag_f_key.rb +3 -1
- data/db/migrate/20210624221630_katello_generic_content.rb +22 -0
- data/db/migrate/20210625095042_add_retain_package_versions_count.rb +9 -0
- data/db/migrate/20210628182553_add_generic_remote_options_to_root_repository.rb +5 -0
- data/db/migrate/20210714140440_remove_repo_export_permission.rb +5 -0
- data/db/migrate/20210721163730_change_gpg_keys_to_content_credentials.rb +8 -0
- data/db/migrate/20210728130748_create_function_deb_version_cmp.rb +12 -0
- data/db/seeds.d/111-upgrade_tasks.rb +1 -2
- data/engines/bastion/app/views/bastion/layouts/assets.html.erb +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/capsule-content.controller.js +7 -5
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/bulk/views/content-hosts-bulk-errata-modal.html +4 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-details.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/apply-errata.controller.js +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/errata/views/apply-errata-confirm.html +2 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/i18n/bastion_katello.pot +25 -33
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/views/products-bulk-advanced-sync-modal.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/product-repositories.controller.js +1 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +10 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.filter.js +9 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details.controller.js +0 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-advanced-sync-options.html +1 -25
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-details.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +31 -13
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +11 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/views/product-repositories.html +0 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/tasks/aggregate-task.factory.js +3 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/tasks/task.factory.js +1 -1
- data/lib/katello/engine.rb +2 -4
- data/lib/katello/permission_creator.rb +6 -12
- data/lib/katello/plugin.rb +76 -80
- data/lib/katello/repository_types/python.rb +37 -0
- data/lib/katello/tasks/reimport.rake +0 -9
- data/lib/katello/tasks/repository.rake +3 -4
- data/lib/katello/version.rb +1 -1
- data/locale/action_names.rb +28 -29
- data/locale/bn/katello.po +699 -221
- data/locale/cs/katello.po +167 -59
- data/locale/de/katello.po +585 -352
- data/locale/en/katello.po +167 -59
- data/locale/es/katello.po +1388 -1189
- data/locale/fr/katello.po +1740 -1494
- data/locale/gu/katello.po +896 -416
- data/locale/hi/katello.po +892 -415
- data/locale/it/katello.po +371 -170
- data/locale/ja/katello.po +1657 -1439
- data/locale/katello.pot +933 -736
- data/locale/kn/katello.po +894 -416
- data/locale/ko/katello.po +515 -317
- data/locale/mr/katello.po +857 -415
- data/locale/or/katello.po +894 -416
- data/locale/pa/katello.po +874 -411
- data/locale/pt/katello.po +347 -154
- data/locale/pt_BR/katello.po +1398 -1215
- data/locale/ru/katello.po +671 -463
- data/locale/ta/katello.po +697 -221
- data/locale/te/katello.po +891 -415
- data/locale/zh_CN/katello.po +2029 -1845
- data/locale/zh_TW/katello.po +735 -407
- data/package.json +3 -1
- data/webpack/components/EditableTextInput/EditableTextInput.js +3 -3
- data/webpack/components/RoutedTabs/RoutedTabs.js +7 -8
- data/webpack/components/Table/TableWrapper.js +19 -11
- data/webpack/components/Table/helpers.js +1 -1
- data/webpack/components/extensions/HostDetails/Tabs/ContentTab.js +42 -0
- data/webpack/components/extensions/HostDetails/Tabs/SubscriptionTab.js +12 -0
- data/webpack/components/extensions/RegistrationCommands/__tests__/__snapshots__/ActivationKeys.test.js.snap +4 -0
- data/webpack/components/extensions/RegistrationCommands/fields/ActivationKeys.js +1 -1
- data/webpack/components/extensions/RegistrationCommands/index.js +1 -2
- data/webpack/components/pf3Table/formatters/selectionHeaderCellFormatter.js +2 -1
- data/webpack/fills_index.js +4 -1
- data/webpack/redux/actions/RedHatRepositories/helpers.js +2 -4
- data/webpack/redux/reducers/RedHatRepositories/enabled.js +4 -1
- data/webpack/scenes/ContentViews/ContentViewsActions.js +16 -1
- data/webpack/scenes/ContentViews/ContentViewsConstants.js +15 -0
- data/webpack/scenes/ContentViews/ContentViewsPage.js +12 -22
- data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +4 -3
- data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +25 -14
- data/webpack/scenes/ContentViews/Create/CreateContentViewModal.js +4 -2
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentContentViewAddModal.js +153 -0
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentVersion.js +21 -10
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ContentViewComponents.js +157 -19
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.fixtures.json +100 -108
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/contentViewComponents.test.js +140 -16
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/__tests__/publishedContentViewDetails.fixtures.json +367 -0
- data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +59 -6
- data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +43 -0
- data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +44 -13
- data/webpack/scenes/ContentViews/Details/Filters/Add/CVFilterAddModal.js +161 -0
- data/webpack/scenes/ContentViews/Details/Filters/Add/__tests__/cvFilterAdd.test.js +54 -0
- data/webpack/scenes/ContentViews/Details/Filters/Add/__tests__/cvFilterCreateResult.fixtures.json +124 -0
- data/webpack/scenes/ContentViews/Details/Filters/CVPackageGroupFilterContent.js +8 -6
- data/webpack/scenes/ContentViews/Details/Filters/CVRpmFilterContent.js +7 -6
- data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilterDetails.js +4 -3
- data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +71 -12
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.test.js +77 -0
- data/webpack/scenes/ContentViews/Details/Histories/ContentViewHistories.js +13 -12
- data/webpack/scenes/ContentViews/Details/Histories/__tests__/contentViewHistory.test.js +2 -2
- data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +17 -14
- data/webpack/scenes/ContentViews/Details/Repositories/LastSync.js +3 -3
- data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewAddRemove.test.js +2 -2
- data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.test.js +6 -2
- data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +61 -20
- data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewTaskInProgressResponse.fixtures.json +71 -0
- data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewTaskResponse.fixtures.json +75 -0
- data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +86 -1
- data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersionsWithTask.fixtures.json +713 -0
- data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +3 -0
- data/webpack/scenes/ContentViews/Publish/CVPublishFinish.js +184 -0
- data/webpack/scenes/ContentViews/Publish/CVPublishForm.js +104 -0
- data/webpack/scenes/ContentViews/Publish/CVPublishReview.js +71 -0
- data/webpack/scenes/ContentViews/Publish/ContentViewPublishSelectors.js +17 -0
- data/webpack/scenes/ContentViews/Publish/PublishContentViewWizard.js +145 -0
- data/webpack/scenes/ContentViews/Publish/__tests__/environmentPaths.fixtures.json +352 -0
- data/webpack/scenes/ContentViews/Publish/__tests__/publishContentView.test.js +184 -0
- data/webpack/scenes/ContentViews/Publish/__tests__/publishResponse.fixture.json +69 -0
- data/webpack/scenes/ContentViews/Publish/cvPublishForm.scss +3 -0
- data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +75 -48
- data/webpack/scenes/ContentViews/Table/tableDataGenerator.js +15 -2
- data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +6 -10
- data/webpack/scenes/ContentViews/components/EnvironmentLabels.js +22 -10
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPathActions.js +12 -0
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPathConstants.js +2 -0
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPathSelectors.js +16 -0
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +72 -0
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.scss +8 -0
- data/webpack/scenes/ContentViews/components/TaskPresenter/TaskPresenter.js +85 -0
- data/webpack/scenes/SmartProxy/SmartProxyContentTable.js +9 -8
- data/webpack/scenes/Subscriptions/SubscriptionsPage.js +4 -25
- data/webpack/scenes/Subscriptions/__tests__/SubscriptionsPage.test.js +0 -3
- data/webpack/scenes/Subscriptions/__tests__/__snapshots__/SubscriptionsPage.test.js.snap +3 -3
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTableSchema.js +4 -2
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/__tests__/__snapshots__/SubscriptionsTable.test.js.snap +24 -0
- data/webpack/scenes/Subscriptions/components/SubscriptionsTable/components/Table.js +4 -1
- data/webpack/scenes/Subscriptions/index.js +1 -4
- metadata +74 -39
- data/app/lib/actions/candlepin/environment/create.rb +0 -21
- data/app/lib/actions/foreman/environment/destroy.rb +0 -23
- data/app/lib/actions/katello/content_view/environment_create.rb +0 -21
- data/app/lib/actions/katello/repository/export.rb +0 -85
- data/app/lib/actions/katello/repository/purge_empty_content.rb +0 -16
- data/app/lib/actions/katello/repository/upload_errata.rb +0 -38
- data/app/lib/katello/util/proxy_uri.rb +0 -64
- data/app/models/katello/rhsm_fact_importer.rb +0 -20
- data/app/models/katello/rhsm_fact_name.rb +0 -17
- data/app/models/katello/rhsm_fact_parser.rb +0 -120
@@ -16,6 +16,7 @@ jest.mock('../Repositories/ContentViewRepositories.js', () => () => 'mocked!');
|
|
16
16
|
jest.mock('../Filters/ContentViewFilters.js', () => () => 'mocked!');
|
17
17
|
jest.mock('../Histories/ContentViewHistories.js', () => () => 'mocked!');
|
18
18
|
jest.mock('../Versions/ContentViewVersions.js', () => () => 'mocked!');
|
19
|
+
jest.mock('../../Publish/PublishContentViewWizard.js', () => () => 'mocked!');
|
19
20
|
|
20
21
|
test('Can call API and show details on page load', async (done) => {
|
21
22
|
const { label, name, description } = cvDetailData;
|
@@ -33,6 +34,8 @@ test('Can call API and show details on page load', async (done) => {
|
|
33
34
|
expect(getByLabelText('name text value')).toHaveTextContent(name);
|
34
35
|
expect(getByLabelText('label text value')).toHaveTextContent(label);
|
35
36
|
expect(getByLabelText('description text value')).toHaveTextContent(description);
|
37
|
+
expect(getByLabelText('cv_breadcrumb')).toBeInTheDocument();
|
38
|
+
expect(getByLabelText('cv_breadcrumb_cv')).toHaveTextContent(name);
|
36
39
|
});
|
37
40
|
|
38
41
|
assertNockRequest(scope, done);
|
@@ -0,0 +1,184 @@
|
|
1
|
+
import { STATUS } from 'foremanReact/constants';
|
2
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
3
|
+
import useDeepCompareEffect from 'use-deep-compare-effect';
|
4
|
+
import PropTypes from 'prop-types';
|
5
|
+
import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
6
|
+
import { Bullseye, Button, Grid, GridItem,
|
7
|
+
Progress, ProgressSize, ProgressMeasureLocation,
|
8
|
+
ProgressVariant, EmptyState, EmptyStateIcon, EmptyStateVariant,
|
9
|
+
Title } from '@patternfly/react-core';
|
10
|
+
import { ExternalLinkAltIcon, InProgressIcon } from '@patternfly/react-icons';
|
11
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
12
|
+
import {
|
13
|
+
selectPublishContentViewsError, selectPublishContentViews,
|
14
|
+
selectPublishContentViewStatus,
|
15
|
+
} from './ContentViewPublishSelectors';
|
16
|
+
import { selectPublishTaskPoll, selectPublishTaskPollStatus } from '../Details/ContentViewDetailSelectors';
|
17
|
+
import getContentViews, { publishContentView } from '../ContentViewsActions';
|
18
|
+
import Loading from '../../../components/Loading';
|
19
|
+
import EmptyStateMessage from '../../../components/Table/EmptyStateMessage';
|
20
|
+
import { cvVersionPublishKey } from '../ContentViewsConstants';
|
21
|
+
import { startPollingTask, stopPollingTask, toastTaskFinished } from '../../Tasks/TaskActions';
|
22
|
+
import getContentViewDetails from '../Details/ContentViewDetailActions';
|
23
|
+
|
24
|
+
const CVPublishFinish = ({
|
25
|
+
cvId,
|
26
|
+
userCheckedItems, setUserCheckedItems,
|
27
|
+
forcePromote, description, setDescription,
|
28
|
+
setIsOpen, versionCount, currentStep, setCurrentStep,
|
29
|
+
}) => {
|
30
|
+
const dispatch = useDispatch();
|
31
|
+
const [publishDispatched, setPublishDispatched] = useState(false);
|
32
|
+
const [saving, setSaving] = useState(true);
|
33
|
+
const [polling, setPolling] = useState(false);
|
34
|
+
const [taskErrored, setTaskErrored] = useState(false);
|
35
|
+
const response = useSelector(state => selectPublishContentViews(state, cvId, versionCount));
|
36
|
+
const status = useSelector(state => selectPublishContentViewStatus(state, cvId, versionCount));
|
37
|
+
const error = useSelector(state => selectPublishContentViewsError(state, cvId, versionCount));
|
38
|
+
const pollResponse = useSelector(state =>
|
39
|
+
selectPublishTaskPoll(state, cvVersionPublishKey(cvId, versionCount)), shallowEqual);
|
40
|
+
const pollResponseStatus = useSelector(state =>
|
41
|
+
selectPublishTaskPollStatus(state, cvVersionPublishKey(cvId, versionCount)), shallowEqual);
|
42
|
+
|
43
|
+
const progressCompleted = () => (pollResponse.progress ? pollResponse.progress * 100 : 0);
|
44
|
+
|
45
|
+
const handleEndTask = useCallback(({ taskComplete }) => {
|
46
|
+
if (currentStep !== 1) {
|
47
|
+
dispatch(stopPollingTask(cvVersionPublishKey(cvId, versionCount)));
|
48
|
+
setCurrentStep(1);
|
49
|
+
setIsOpen(false);
|
50
|
+
dispatch(getContentViewDetails(cvId));
|
51
|
+
dispatch(getContentViews);
|
52
|
+
if (taskComplete) {
|
53
|
+
dispatch(toastTaskFinished(pollResponse));
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}, [currentStep, cvId, dispatch, pollResponse, setCurrentStep, setIsOpen, versionCount]);
|
57
|
+
|
58
|
+
|
59
|
+
useEffect(() => {
|
60
|
+
if (currentStep !== 3 && !publishDispatched) {
|
61
|
+
setCurrentStep(3);
|
62
|
+
setSaving(true);
|
63
|
+
setPublishDispatched(true);
|
64
|
+
dispatch(publishContentView({
|
65
|
+
id: cvId,
|
66
|
+
versionCount,
|
67
|
+
description,
|
68
|
+
environment_ids: userCheckedItems.map(item => item.id),
|
69
|
+
is_force_promote: (forcePromote.length > 0),
|
70
|
+
}));
|
71
|
+
setDescription('');
|
72
|
+
setUserCheckedItems([]);
|
73
|
+
}
|
74
|
+
}, [dispatch, setSaving, publishDispatched, setPublishDispatched,
|
75
|
+
setDescription, setUserCheckedItems, currentStep, setCurrentStep,
|
76
|
+
cvId, versionCount, description, forcePromote, userCheckedItems]);
|
77
|
+
|
78
|
+
useDeepCompareEffect(() => {
|
79
|
+
if (!response) return;
|
80
|
+
const pollPublishTask = (cvPublishVersionKey, task) => {
|
81
|
+
if (!polling) dispatch(startPollingTask(cvPublishVersionKey, task));
|
82
|
+
};
|
83
|
+
|
84
|
+
setSaving(true);
|
85
|
+
const { id } = response;
|
86
|
+
if (id && status === STATUS.RESOLVED) {
|
87
|
+
setSaving(false);
|
88
|
+
pollPublishTask(cvVersionPublishKey(cvId, versionCount), response);
|
89
|
+
setPolling(true);
|
90
|
+
} else if (status === STATUS.ERROR) {
|
91
|
+
setSaving(false);
|
92
|
+
}
|
93
|
+
}, [response, status, error, cvId, versionCount,
|
94
|
+
dispatch, polling, setPolling, setSaving]);
|
95
|
+
|
96
|
+
|
97
|
+
useDeepCompareEffect(() => {
|
98
|
+
const { state, result } = pollResponse;
|
99
|
+
if (state === 'paused' || result === 'error') {
|
100
|
+
setTaskErrored(true);
|
101
|
+
setTimeout(() => {
|
102
|
+
handleEndTask({ taskComplete: true });
|
103
|
+
}, 500);
|
104
|
+
}
|
105
|
+
if (state === 'stopped' && result === 'success') {
|
106
|
+
setTimeout(() => {
|
107
|
+
handleEndTask({ taskComplete: true });
|
108
|
+
}, 500);
|
109
|
+
}
|
110
|
+
}, [pollResponse, dispatch, setTaskErrored,
|
111
|
+
setPolling, setIsOpen, pollResponseStatus, handleEndTask]);
|
112
|
+
|
113
|
+
if (saving) {
|
114
|
+
return <Loading />;
|
115
|
+
}
|
116
|
+
if (polling && pollResponse) {
|
117
|
+
return (
|
118
|
+
<>
|
119
|
+
<EmptyState style={{ marginTop: '10px' }} variant={EmptyStateVariant.large}>
|
120
|
+
<EmptyStateIcon icon={InProgressIcon} />
|
121
|
+
<Title headingLevel="h2" size="lg">
|
122
|
+
{__('Publishing content view')}
|
123
|
+
</Title>
|
124
|
+
</EmptyState>
|
125
|
+
<Grid hasGutter>
|
126
|
+
<GridItem span={12} rowSpan={19}>
|
127
|
+
<Progress
|
128
|
+
value={progressCompleted()}
|
129
|
+
title={__('In progress')}
|
130
|
+
measureLocation={ProgressMeasureLocation.outside}
|
131
|
+
variant={taskErrored ? ProgressVariant.danger : ProgressVariant.default}
|
132
|
+
size={ProgressSize.lg}
|
133
|
+
/>
|
134
|
+
</GridItem>
|
135
|
+
<GridItem style={{ marginTop: '10px' }} span={12} rowSpan={1}>
|
136
|
+
<Bullseye>
|
137
|
+
<Button
|
138
|
+
onClick={() => {
|
139
|
+
handleEndTask({ taskComplete: false });
|
140
|
+
}}
|
141
|
+
variant="primary"
|
142
|
+
aria-label="publish_content_view"
|
143
|
+
>
|
144
|
+
{__('Close')}
|
145
|
+
</Button>
|
146
|
+
<Button
|
147
|
+
component="a"
|
148
|
+
aria-label="view tasks button"
|
149
|
+
href={`/foreman_tasks/tasks/${pollResponse.id}`}
|
150
|
+
target="_blank"
|
151
|
+
variant="link"
|
152
|
+
>
|
153
|
+
{__(' View task details ')}
|
154
|
+
<ExternalLinkAltIcon />
|
155
|
+
</Button>
|
156
|
+
</Bullseye>
|
157
|
+
</GridItem>
|
158
|
+
</Grid>
|
159
|
+
</>
|
160
|
+
);
|
161
|
+
}
|
162
|
+
if (status === STATUS.PENDING) return (<Loading />);
|
163
|
+
if (status === STATUS.ERROR) return (<EmptyStateMessage error={error} />);
|
164
|
+
return <Loading />;
|
165
|
+
};
|
166
|
+
|
167
|
+
CVPublishFinish.propTypes = {
|
168
|
+
cvId: PropTypes.oneOfType([
|
169
|
+
PropTypes.number,
|
170
|
+
PropTypes.string,
|
171
|
+
]).isRequired,
|
172
|
+
forcePromote: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
173
|
+
description: PropTypes.string.isRequired,
|
174
|
+
setDescription: PropTypes.func.isRequired,
|
175
|
+
userCheckedItems: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
176
|
+
setUserCheckedItems: PropTypes.func.isRequired,
|
177
|
+
setIsOpen: PropTypes.func.isRequired,
|
178
|
+
versionCount: PropTypes.number.isRequired,
|
179
|
+
currentStep: PropTypes.number.isRequired,
|
180
|
+
setCurrentStep: PropTypes.func.isRequired,
|
181
|
+
};
|
182
|
+
|
183
|
+
|
184
|
+
export default CVPublishFinish;
|
@@ -0,0 +1,104 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
4
|
+
import { Alert, Switch, Flex, FlexItem, TextContent, Text, TextVariants, Form, FormGroup, TextArea } from '@patternfly/react-core';
|
5
|
+
import { EnterpriseIcon, RegistryIcon } from '@patternfly/react-icons';
|
6
|
+
import EnvironmentPaths from '../components/EnvironmentPaths/EnvironmentPaths';
|
7
|
+
import ComponentEnvironments from '../Details/ComponentContentViews/ComponentEnvironments';
|
8
|
+
import './cvPublishForm.scss';
|
9
|
+
|
10
|
+
const CVPublishForm = ({
|
11
|
+
description,
|
12
|
+
setDescription,
|
13
|
+
details,
|
14
|
+
userCheckedItems,
|
15
|
+
setUserCheckedItems,
|
16
|
+
promote,
|
17
|
+
setPromote,
|
18
|
+
forcePromote,
|
19
|
+
}) => {
|
20
|
+
const {
|
21
|
+
name, composite, next_version: nextVersion,
|
22
|
+
} = details;
|
23
|
+
|
24
|
+
return (
|
25
|
+
<>
|
26
|
+
<>
|
27
|
+
<TextContent>
|
28
|
+
<Text style={{ marginBottom: '1em' }} component={TextVariants.h1}>{__('Publish')}</Text>
|
29
|
+
</TextContent>
|
30
|
+
<Flex flex={{ default: 'inlineFlex' }}>
|
31
|
+
<FlexItem>{__('A new version of ')}<b>{composite ? <RegistryIcon /> : <EnterpriseIcon />} {name}</b>
|
32
|
+
{__(' will be created and automatically promoted to the ' +
|
33
|
+
'Library environment. You can promote to other environments as well. ')}
|
34
|
+
</FlexItem>
|
35
|
+
</Flex>
|
36
|
+
<TextContent>
|
37
|
+
<Text style={{ marginTop: '1em', marginBottom: '1em' }} component={TextVariants.h3}>{__('Publish new version - ')}{nextVersion || '1.0'}</Text>
|
38
|
+
</TextContent>
|
39
|
+
<Form>
|
40
|
+
<FormGroup label="Description" fieldId="description">
|
41
|
+
<TextArea
|
42
|
+
isRequired
|
43
|
+
type="text"
|
44
|
+
id="description"
|
45
|
+
aria-label="input_description"
|
46
|
+
name="description"
|
47
|
+
value={description}
|
48
|
+
onChange={value => setDescription(value)}
|
49
|
+
/>
|
50
|
+
</FormGroup>
|
51
|
+
<FormGroup label="Promote" fieldId="promote" style={{ marginBottom: '2em', outlineStyle: 'none' }}>
|
52
|
+
<Switch
|
53
|
+
id="promote-switch"
|
54
|
+
aria-label="promote-switch"
|
55
|
+
isChecked={promote}
|
56
|
+
onChange={checked => setPromote(checked)}
|
57
|
+
/>
|
58
|
+
</FormGroup>
|
59
|
+
</Form>
|
60
|
+
</>
|
61
|
+
<>
|
62
|
+
{forcePromote.length > 0 && (
|
63
|
+
<Alert variant="info" isInline title="Force Promotion">
|
64
|
+
<p>{__('Selected environments are out of the environment order. ' +
|
65
|
+
'The recommended practice is to promote to the next environment in the path.')}
|
66
|
+
</p>
|
67
|
+
<ComponentEnvironments environments={forcePromote} />
|
68
|
+
</Alert>
|
69
|
+
)
|
70
|
+
}
|
71
|
+
{promote &&
|
72
|
+
<EnvironmentPaths
|
73
|
+
userCheckedItems={userCheckedItems}
|
74
|
+
setUserCheckedItems={setUserCheckedItems}
|
75
|
+
/>
|
76
|
+
}
|
77
|
+
</>
|
78
|
+
</>
|
79
|
+
);
|
80
|
+
};
|
81
|
+
|
82
|
+
CVPublishForm.propTypes = {
|
83
|
+
description: PropTypes.string.isRequired,
|
84
|
+
setDescription: PropTypes.func.isRequired,
|
85
|
+
userCheckedItems: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
86
|
+
setUserCheckedItems: PropTypes.func.isRequired,
|
87
|
+
promote: PropTypes.bool.isRequired,
|
88
|
+
setPromote: PropTypes.func.isRequired,
|
89
|
+
forcePromote: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
90
|
+
details: PropTypes.shape({
|
91
|
+
id: PropTypes.oneOfType([
|
92
|
+
PropTypes.number,
|
93
|
+
PropTypes.string,
|
94
|
+
]),
|
95
|
+
name: PropTypes.string.isRequired,
|
96
|
+
composite: PropTypes.bool.isRequired,
|
97
|
+
next_version: PropTypes.oneOfType([
|
98
|
+
PropTypes.number,
|
99
|
+
PropTypes.string,
|
100
|
+
]).isRequired,
|
101
|
+
}).isRequired,
|
102
|
+
};
|
103
|
+
|
104
|
+
export default CVPublishForm;
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import React, { useMemo } from 'react';
|
2
|
+
import { useSelector } from 'react-redux';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
import { TableComposable, Thead, Tbody, Tr, Th, Td } from '@patternfly/react-table';
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
import { STATUS } from 'foremanReact/constants';
|
7
|
+
import ContentViewIcon from '../components/ContentViewIcon';
|
8
|
+
import InactiveText from '../components/InactiveText';
|
9
|
+
import ComponentEnvironments from '../Details/ComponentContentViews/ComponentEnvironments';
|
10
|
+
import { selectEnvironmentPaths, selectEnvironmentPathsStatus } from '../components/EnvironmentPaths/EnvironmentPathSelectors';
|
11
|
+
|
12
|
+
const CVPublishReview = ({
|
13
|
+
details,
|
14
|
+
userCheckedItems,
|
15
|
+
}) => {
|
16
|
+
const environmentPathResponse = useSelector(selectEnvironmentPaths);
|
17
|
+
const environmentPathStatus = useSelector(selectEnvironmentPathsStatus);
|
18
|
+
const environmentPathLoading = environmentPathStatus === STATUS.PENDING;
|
19
|
+
|
20
|
+
const promotedToEnvironments = useMemo(() => {
|
21
|
+
if (!environmentPathLoading) {
|
22
|
+
const { results } = environmentPathResponse || {};
|
23
|
+
const library = results[0].environments[0];
|
24
|
+
return [library].concat(userCheckedItems);
|
25
|
+
}
|
26
|
+
return [];
|
27
|
+
}, [environmentPathResponse, environmentPathLoading, userCheckedItems]);
|
28
|
+
|
29
|
+
const {
|
30
|
+
name, composite, next_version: nextVersion,
|
31
|
+
} = details;
|
32
|
+
|
33
|
+
return (
|
34
|
+
<TableComposable aria-label="Review Table">
|
35
|
+
<Thead>
|
36
|
+
<Tr>
|
37
|
+
<Th>{__('Content view')}</Th>
|
38
|
+
<Th>{__('Version')}</Th>
|
39
|
+
<Th>{__('Environments')}</Th>
|
40
|
+
</Tr>
|
41
|
+
</Thead>
|
42
|
+
<Tbody>
|
43
|
+
<Tr>
|
44
|
+
<Td>
|
45
|
+
<><ContentViewIcon composite={composite} description={name} /><InactiveText text={__('Newly published')} /></>
|
46
|
+
</Td>
|
47
|
+
<Td>
|
48
|
+
{__('Version')} {nextVersion}
|
49
|
+
</Td>
|
50
|
+
<Td>
|
51
|
+
<ComponentEnvironments environments={promotedToEnvironments} />
|
52
|
+
</Td>
|
53
|
+
</Tr>
|
54
|
+
</Tbody>
|
55
|
+
</TableComposable>
|
56
|
+
);
|
57
|
+
};
|
58
|
+
|
59
|
+
CVPublishReview.propTypes = {
|
60
|
+
userCheckedItems: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
61
|
+
details: PropTypes.shape({
|
62
|
+
name: PropTypes.string.isRequired,
|
63
|
+
composite: PropTypes.bool.isRequired,
|
64
|
+
next_version: PropTypes.oneOfType([
|
65
|
+
PropTypes.number,
|
66
|
+
PropTypes.string,
|
67
|
+
]).isRequired,
|
68
|
+
}).isRequired,
|
69
|
+
};
|
70
|
+
|
71
|
+
export default CVPublishReview;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import {
|
2
|
+
selectAPIStatus,
|
3
|
+
selectAPIError,
|
4
|
+
selectAPIResponse,
|
5
|
+
} from 'foremanReact/redux/API/APISelectors';
|
6
|
+
import { STATUS } from 'foremanReact/constants';
|
7
|
+
import { cvVersionPublishKey } from '../ContentViewsConstants';
|
8
|
+
|
9
|
+
export const selectPublishContentViews = (state, cvId, versionCount) =>
|
10
|
+
selectAPIResponse(state, cvVersionPublishKey(cvId, versionCount)) || {};
|
11
|
+
|
12
|
+
export const selectPublishContentViewStatus = (state, cvId, versionCount) =>
|
13
|
+
selectAPIStatus(state, cvVersionPublishKey(cvId, versionCount)) || STATUS.PENDING;
|
14
|
+
|
15
|
+
export const selectPublishContentViewsError = (state, cvId, versionCount) =>
|
16
|
+
selectAPIError(state, cvVersionPublishKey(cvId, versionCount));
|
17
|
+
|
@@ -0,0 +1,145 @@
|
|
1
|
+
import React, { useEffect, useState, useMemo, useCallback } from 'react';
|
2
|
+
import { useDispatch, useSelector } from 'react-redux';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
import { STATUS } from 'foremanReact/constants';
|
5
|
+
import { Wizard } from '@patternfly/react-core';
|
6
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
7
|
+
import CVPublishForm from './CVPublishForm';
|
8
|
+
import CVPublishFinish from './CVPublishFinish';
|
9
|
+
import getEnvironmentPaths from '../components/EnvironmentPaths/EnvironmentPathActions';
|
10
|
+
import CVPublishReview from './CVPublishReview';
|
11
|
+
import {
|
12
|
+
selectEnvironmentPaths,
|
13
|
+
selectEnvironmentPathsStatus,
|
14
|
+
} from '../components/EnvironmentPaths/EnvironmentPathSelectors';
|
15
|
+
import getContentViews from '../ContentViewsActions';
|
16
|
+
import getContentViewDetails from '../Details/ContentViewDetailActions';
|
17
|
+
import { stopPollingTask } from '../../Tasks/TaskActions';
|
18
|
+
import { cvVersionPublishKey } from '../ContentViewsConstants';
|
19
|
+
|
20
|
+
const PublishContentViewWizard = ({
|
21
|
+
details, show, setIsOpen, currentStep, setCurrentStep,
|
22
|
+
}) => {
|
23
|
+
const { name, id: cvId, version_count: versionCount } = details;
|
24
|
+
const [description, setDescription] = useState('');
|
25
|
+
const [userCheckedItems, setUserCheckedItems] = useState([]);
|
26
|
+
const [promote, setPromote] = useState(false);
|
27
|
+
const [forcePromote, setForcePromote] = useState([]);
|
28
|
+
const dispatch = useDispatch();
|
29
|
+
const environmentPathResponse = useSelector(selectEnvironmentPaths);
|
30
|
+
const environmentPathStatus = useSelector(selectEnvironmentPathsStatus);
|
31
|
+
const environmentPathLoading = environmentPathStatus === STATUS.PENDING;
|
32
|
+
|
33
|
+
const steps = [
|
34
|
+
{
|
35
|
+
id: 1,
|
36
|
+
name: 'Publish',
|
37
|
+
component: <CVPublishForm
|
38
|
+
description={description}
|
39
|
+
setDescription={setDescription}
|
40
|
+
details={details}
|
41
|
+
show={show}
|
42
|
+
userCheckedItems={userCheckedItems}
|
43
|
+
setUserCheckedItems={setUserCheckedItems}
|
44
|
+
promote={promote}
|
45
|
+
setPromote={setPromote}
|
46
|
+
forcePromote={forcePromote}
|
47
|
+
/>,
|
48
|
+
},
|
49
|
+
{
|
50
|
+
id: 2, name: 'Review', component: <CVPublishReview details={details} userCheckedItems={userCheckedItems} show={show} />, nextButtonText: 'Finish',
|
51
|
+
},
|
52
|
+
{
|
53
|
+
id: 3,
|
54
|
+
name: 'Finish',
|
55
|
+
component: <CVPublishFinish
|
56
|
+
description={description}
|
57
|
+
setDescription={setDescription}
|
58
|
+
userCheckedItems={userCheckedItems}
|
59
|
+
setUserCheckedItems={setUserCheckedItems}
|
60
|
+
forcePromote={forcePromote}
|
61
|
+
cvId={cvId}
|
62
|
+
versionCount={versionCount}
|
63
|
+
show={show}
|
64
|
+
setIsOpen={setIsOpen}
|
65
|
+
currentStep={currentStep}
|
66
|
+
setCurrentStep={setCurrentStep}
|
67
|
+
/>,
|
68
|
+
isFinishedStep: true,
|
69
|
+
},
|
70
|
+
];
|
71
|
+
|
72
|
+
useEffect(
|
73
|
+
() => {
|
74
|
+
dispatch(getEnvironmentPaths());
|
75
|
+
},
|
76
|
+
[dispatch],
|
77
|
+
);
|
78
|
+
|
79
|
+
const envPathFlat = useMemo(() => {
|
80
|
+
if (!environmentPathLoading) {
|
81
|
+
const { results } = environmentPathResponse || {};
|
82
|
+
return results.map(result => result.environments).flatten();
|
83
|
+
}
|
84
|
+
return [];
|
85
|
+
}, [environmentPathResponse, environmentPathLoading]);
|
86
|
+
|
87
|
+
const prior = useCallback(
|
88
|
+
env => envPathFlat.find(item => item.id === env.prior.id),
|
89
|
+
[envPathFlat],
|
90
|
+
);
|
91
|
+
const isChecked = useCallback(
|
92
|
+
env => userCheckedItems.includes(env) || env.library,
|
93
|
+
[userCheckedItems],
|
94
|
+
);
|
95
|
+
|
96
|
+
const isValid = useCallback((env) => {
|
97
|
+
if (!env.prior) return true;
|
98
|
+
if (!isChecked(prior(env))) return false;
|
99
|
+
return isValid(prior(env));
|
100
|
+
}, [prior, isChecked]);
|
101
|
+
|
102
|
+
useEffect(() => {
|
103
|
+
setForcePromote(userCheckedItems.filter(item => !isValid(item)));
|
104
|
+
}, [userCheckedItems, setForcePromote, isValid]);
|
105
|
+
|
106
|
+
return (
|
107
|
+
<Wizard
|
108
|
+
title={__('Publish')}
|
109
|
+
description={currentStep === 3 ? __(`Publishing ${name}`) : __(`Determining settings for ${name}`)}
|
110
|
+
steps={steps}
|
111
|
+
startAtStep={currentStep}
|
112
|
+
onClose={() => {
|
113
|
+
setDescription('');
|
114
|
+
setUserCheckedItems([]);
|
115
|
+
setPromote(false);
|
116
|
+
setForcePromote([]);
|
117
|
+
if (currentStep === 3) {
|
118
|
+
setCurrentStep(1);
|
119
|
+
dispatch(getContentViewDetails(cvId));
|
120
|
+
dispatch(getContentViews);
|
121
|
+
dispatch(stopPollingTask(cvVersionPublishKey(cvId, versionCount)));
|
122
|
+
}
|
123
|
+
setIsOpen(false);
|
124
|
+
}}
|
125
|
+
isOpen={show}
|
126
|
+
/>
|
127
|
+
);
|
128
|
+
};
|
129
|
+
|
130
|
+
PublishContentViewWizard.propTypes = {
|
131
|
+
show: PropTypes.bool.isRequired,
|
132
|
+
setIsOpen: PropTypes.func.isRequired,
|
133
|
+
currentStep: PropTypes.number.isRequired,
|
134
|
+
setCurrentStep: PropTypes.func.isRequired,
|
135
|
+
details: PropTypes.shape({
|
136
|
+
id: PropTypes.oneOfType([
|
137
|
+
PropTypes.number,
|
138
|
+
PropTypes.string,
|
139
|
+
]),
|
140
|
+
name: PropTypes.string,
|
141
|
+
version_count: PropTypes.number,
|
142
|
+
}).isRequired,
|
143
|
+
};
|
144
|
+
|
145
|
+
export default PublishContentViewWizard;
|