katello 3.18.5 → 4.0.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/assets/stylesheets/katello/katello.scss +72 -0
- data/app/controllers/katello/api/registry/registry_proxies_controller.rb +6 -4
- data/app/controllers/katello/api/rhsm/candlepin_dynflow_proxy_controller.rb +0 -19
- data/app/controllers/katello/api/rhsm/candlepin_proxies_controller.rb +1 -3
- data/app/controllers/katello/api/v2/content_credentials_controller.rb +24 -24
- data/app/controllers/katello/api/v2/content_export_incrementals_controller.rb +1 -1
- data/app/controllers/katello/api/v2/content_exports_controller.rb +4 -0
- data/app/controllers/katello/api/v2/content_views_controller.rb +2 -2
- data/app/controllers/katello/api/v2/host_subscriptions_controller.rb +2 -3
- data/app/controllers/katello/api/v2/repositories_controller.rb +3 -19
- data/app/controllers/katello/api/v2/simple_content_access_controller.rb +34 -0
- data/app/controllers/katello/api/v2/subscriptions_controller.rb +1 -1
- data/app/controllers/katello/api/v2/upstream_subscriptions_controller.rb +8 -4
- data/app/controllers/katello/concerns/api/v2/authorization.rb +1 -14
- data/app/controllers/katello/concerns/authorization/api/v2/content_views_controller.rb +1 -1
- data/app/helpers/katello/sync_management_helper.rb +0 -2
- data/app/lib/actions/candlepin/environment/create.rb +1 -1
- data/app/lib/actions/candlepin/environment/set_content.rb +1 -1
- data/app/lib/actions/katello/activation_key/create.rb +9 -11
- data/app/lib/actions/katello/capsule_content/sync.rb +8 -8
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +9 -0
- data/app/lib/actions/katello/check_matching_content.rb +17 -0
- data/app/lib/actions/katello/content_view/environment_create.rb +6 -8
- data/app/lib/actions/katello/content_view/publish.rb +1 -1
- data/app/lib/actions/katello/content_view_version/incremental_update.rb +11 -7
- data/app/lib/actions/katello/host/hypervisors_update.rb +4 -4
- data/app/lib/actions/katello/organization/create.rb +3 -5
- data/app/lib/actions/katello/organization/destroy.rb +1 -1
- data/app/lib/actions/katello/organization/manifest_delete.rb +3 -5
- data/app/lib/actions/katello/organization/manifest_import.rb +1 -1
- data/app/lib/actions/katello/organization/manifest_refresh.rb +1 -1
- data/app/lib/actions/katello/orphan_cleanup/remove_orphans.rb +1 -1
- data/app/lib/actions/katello/repository/check_matching_content.rb +3 -1
- data/app/lib/actions/katello/repository/clone_contents.rb +8 -11
- data/app/lib/actions/katello/repository/create.rb +0 -8
- data/app/lib/actions/katello/repository/filtered_index_content.rb +3 -0
- data/app/lib/actions/katello/repository/index_content.rb +1 -0
- data/app/lib/actions/katello/repository/multi_clone_contents.rb +9 -12
- data/app/lib/actions/katello/repository/sync.rb +1 -5
- data/app/lib/actions/katello/repository/update.rb +0 -8
- data/app/lib/actions/middleware/execute_if_contents_changed.rb +4 -1
- data/app/lib/actions/pulp/orchestration/repository/refresh_repos.rb +0 -6
- data/app/lib/actions/pulp3/capsule_content/refresh_distribution.rb +3 -3
- data/app/lib/actions/pulp3/content_guard/refresh_all_distributions.rb +1 -2
- data/app/lib/actions/pulp3/content_migration_presenter.rb +2 -5
- data/app/lib/actions/pulp3/orchestration/repository/refresh_repos.rb +1 -6
- data/app/lib/katello/concerns/base_template_scope_extensions.rb +8 -0
- data/app/lib/katello/errors.rb +1 -1
- data/app/lib/katello/event_daemon/monitor.rb +53 -0
- data/app/lib/katello/event_daemon/runner.rb +99 -0
- data/app/lib/katello/logging.rb +32 -0
- data/app/lib/katello/messaging/connection.rb +1 -7
- data/app/lib/katello/util/pulpcore_content_filters.rb +1 -1
- data/app/lib/katello/validators/content_view_puppet_module_validator.rb +1 -1
- data/app/models/katello/activation_key.rb +2 -2
- data/app/models/katello/candlepin/repository_mapper.rb +1 -1
- data/app/models/katello/concerns/hostgroup_extensions.rb +2 -4
- data/app/models/katello/concerns/organization_extensions.rb +2 -2
- data/app/models/katello/concerns/pulp_database_unit.rb +0 -12
- data/app/models/katello/concerns/redhat_extensions.rb +8 -9
- data/app/models/katello/concerns/smart_proxy_extensions.rb +24 -0
- data/app/models/katello/content_view.rb +5 -1
- data/app/models/katello/content_view_environment.rb +2 -2
- data/app/models/katello/content_view_puppet_environment.rb +2 -2
- data/app/models/katello/content_view_version.rb +2 -1
- data/app/models/katello/content_view_version_export_history.rb +20 -0
- data/app/models/katello/erratum.rb +3 -1
- data/app/models/katello/file_unit.rb +0 -4
- data/app/models/katello/glue/candlepin/pool.rb +2 -0
- data/app/models/katello/glue/pulp/repo.rb +0 -6
- data/app/models/katello/glue/pulp/repos.rb +1 -22
- data/app/models/katello/host/content_facet.rb +31 -9
- data/app/models/katello/ping.rb +19 -39
- data/app/models/katello/pool.rb +5 -0
- data/app/models/katello/product.rb +3 -3
- data/app/models/katello/repository.rb +3 -3
- data/app/presenters/katello/host_subscription_presenter.rb +3 -4
- data/app/presenters/katello/host_subscriptions_presenter.rb +24 -0
- data/app/services/katello/applicability/applicable_content_helper.rb +6 -8
- data/app/services/katello/candlepin_event_listener.rb +11 -19
- data/app/services/katello/event_monitor/poller_thread.rb +2 -11
- data/app/services/katello/pulp/repository.rb +2 -4
- data/app/services/katello/pulp/smart_proxy_repository.rb +0 -15
- data/app/services/katello/pulp3/api/core.rb +0 -14
- data/app/services/katello/pulp3/erratum.rb +1 -2
- data/app/services/katello/pulp3/migration.rb +9 -83
- data/app/services/katello/pulp3/migration_plan.rb +5 -54
- data/app/services/katello/pulp3/migration_switchover.rb +5 -36
- data/app/services/katello/pulp3/repository/apt.rb +2 -1
- data/app/services/katello/pulp3/repository/yum.rb +2 -11
- data/app/services/katello/pulp3/repository.rb +13 -34
- data/app/services/katello/pulp3/rpm.rb +1 -5
- data/app/services/katello/pulp3/task.rb +5 -8
- data/app/services/katello/pulp3/task_group.rb +5 -13
- data/app/services/katello/repository_type.rb +1 -1
- data/app/views/foreman/smart_proxies/_content_tab.html.erb +4 -47
- data/app/views/foreman/smart_proxies/show.html.erb +1 -1
- data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +22 -25
- data/app/views/katello/api/v2/content_view_version_export_histories/show.json.rabl +1 -0
- data/app/views/katello/api/v2/organizations/show.json.rabl +7 -9
- data/app/views/katello/sync_management/_products.html.erb +1 -1
- data/app/views/overrides/organizations/_edit_override.html.erb +1 -4
- data/app/views/overrides/smart_proxies/_environment_tab.html.erb +1 -1
- data/app/views/overrides/smart_proxies/_environment_tab_pane.html.erb +1 -1
- data/config/katello.yaml.example +0 -3
- data/config/routes/api/v2.rb +8 -10
- data/db/migrate/20191204214919_add_content_view_version_counts.rb +0 -1
- data/db/migrate/20200514092553_move_katello_fields_from_hostgroups.katello.rb +1 -1
- data/db/migrate/20210119162528_delete_puppet_and_ostree_repos.rb +56 -0
- data/db/migrate/20210128231228_add_type_and_from_cvv_to_cvv_export_history.rb +14 -0
- data/db/migrate/20210201163238_migrate_background_download_policy_to_migrate.rb +7 -0
- data/db/seeds.d/104-proxy.rb +1 -1
- data/db/seeds.d/111-upgrade_tasks.rb +2 -1
- data/engines/bastion/app/assets/javascripts/bastion/auth/authorization.service.js +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/capsule-content/capsule-content.controller.js +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/content-host-register-os-client.directive.js +17 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/details/views/content-host-info.html +2 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/content-hosts.html +2 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/register-client.html +11 -4
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/register-deb-client.html +38 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/register-oracle-client.html +5 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/register-sles-client.html +28 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-hosts/views/register.html +14 -11
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/filters/views/package-filter-details.html +2 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +2 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-info.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/download-policy.service.js +0 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +1 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/products.controller.js +2 -2
- data/lib/katello/engine.rb +4 -5
- data/lib/katello/middleware/event_daemon.rb +1 -1
- data/lib/katello/permission_creator.rb +3 -2
- data/lib/katello/plugin.rb +2 -2
- data/lib/katello/tasks/jenkins.rake +1 -1
- data/lib/katello/tasks/pulp3_content_switchover.rake +20 -31
- data/lib/katello/tasks/pulp3_migration.rake +25 -45
- data/lib/katello/tasks/pulp3_migration_abort.rake +0 -8
- data/lib/katello/tasks/pulp3_migration_stats.rake +3 -46
- data/lib/katello/tasks/upgrades/4.0/remove_ostree_puppet_content.rake +16 -0
- data/lib/katello/version.rb +1 -1
- data/lib/proxy_api/container_gateway.rb +21 -0
- data/locale/bn/katello.edit.po +0 -0
- data/locale/cs/katello.edit.po +0 -0
- data/locale/de/katello.edit.po +0 -0
- data/locale/en/katello.edit.po +0 -0
- data/locale/es/katello.edit.po +0 -0
- data/locale/fr/katello.edit.po +0 -0
- data/locale/gu/katello.edit.po +0 -0
- data/locale/hi/katello.edit.po +0 -0
- data/locale/it/katello.edit.po +0 -0
- data/locale/ja/katello.edit.po +0 -0
- data/locale/kn/katello.edit.po +0 -0
- data/locale/ko/katello.edit.po +0 -0
- data/locale/mr/katello.edit.po +0 -0
- data/locale/or/katello.edit.po +0 -0
- data/locale/pa/katello.edit.po +0 -0
- data/locale/pt/katello.edit.po +0 -0
- data/locale/pt_BR/katello.edit.po +0 -0
- data/locale/ru/katello.edit.po +0 -0
- data/locale/ta/katello.edit.po +0 -0
- data/locale/te/katello.edit.po +0 -0
- data/locale/zh_CN/katello.edit.po +0 -0
- data/locale/zh_TW/katello.edit.po +0 -0
- data/package.json +1 -1
- data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +0 -1
- data/webpack/__mocks__/foremanReact/components/Pagination/PaginationHooks.js +2 -0
- data/webpack/__mocks__/foremanReact/components/common/dates/LongDateTime.js +5 -0
- data/webpack/{scenes/ContentViews/Details/Repositories → components/SelectableDropdown}/SelectableDropdown.js +20 -3
- data/webpack/components/SelectableDropdown/__tests__/SelectableDropdown.test.js +45 -0
- data/webpack/components/SelectableDropdown/index.js +3 -0
- data/webpack/components/Table/TableWrapper.js +2 -1
- data/webpack/components/Table/helpers.js +14 -0
- data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.js +0 -1
- data/webpack/containers/Application/overrides.scss +6 -0
- data/webpack/index.js +6 -0
- data/webpack/redux/actions/RedHatRepositories/helpers.js +5 -5
- data/webpack/scenes/ContentViews/ContentViewsActions.js +31 -2
- data/webpack/scenes/ContentViews/ContentViewsConstants.js +5 -1
- data/webpack/scenes/ContentViews/Copy/ContentViewCopySelectors.js +16 -0
- data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +77 -0
- data/webpack/scenes/ContentViews/Copy/CopyContentViewModal.js +44 -0
- data/webpack/scenes/ContentViews/Copy/__tests__/contentViewCopyResult.fixtures.json +42 -0
- data/webpack/scenes/ContentViews/Copy/__tests__/copyContentView.test.js +39 -0
- data/webpack/scenes/ContentViews/Copy/index.js +4 -0
- data/webpack/scenes/ContentViews/Create/ContentViewCreateSelectors.js +16 -0
- data/webpack/scenes/ContentViews/Create/ContentViewFormComponents.js +58 -0
- data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +175 -0
- data/webpack/scenes/ContentViews/Create/CreateContentViewModal.js +27 -0
- data/webpack/scenes/ContentViews/Create/__tests__/contentViewCreateResult.fixtures.json +42 -0
- data/webpack/scenes/ContentViews/Create/__tests__/createContentView.test.js +92 -0
- data/webpack/scenes/ContentViews/Create/index.js +4 -0
- data/webpack/scenes/ContentViews/Details/ContentViewDetailActions.js +16 -0
- data/webpack/scenes/ContentViews/Details/ContentViewDetailSelectors.js +20 -1
- data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +17 -7
- data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +19 -13
- data/webpack/scenes/ContentViews/Details/Filters/ContentType.js +40 -0
- data/webpack/scenes/ContentViews/Details/Filters/ContentViewFilters.js +124 -0
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.fixtures.json +134 -0
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilters.test.js +92 -0
- data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +44 -25
- data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.test.js +17 -7
- data/webpack/scenes/ContentViews/Details/__tests__/contentViewDetail.test.js +24 -0
- data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +53 -3
- data/webpack/scenes/ContentViews/Table/tableDataGenerator.js +4 -3
- data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +41 -0
- data/webpack/scenes/ContentViews/helpers.js +13 -0
- data/webpack/scenes/SmartProxy/Content.js +17 -0
- data/webpack/scenes/SmartProxy/SmartProxyContentActions.js +11 -0
- data/webpack/scenes/SmartProxy/SmartProxyContentConstants.js +3 -0
- data/webpack/scenes/SmartProxy/SmartProxyContentSelectors.js +16 -0
- data/webpack/scenes/SmartProxy/SmartProxyContentTable.js +152 -0
- data/webpack/scenes/SmartProxy/__tests__/SmartProxyContentResult.fixtures.json +140 -0
- data/webpack/scenes/SmartProxy/__tests__/SmartProxyContentTest.js +38 -0
- data/webpack/scenes/SmartProxy/index.js +4 -0
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +2 -7
- data/webpack/scenes/Subscriptions/Manifest/ManifestActions.js +3 -3
- data/webpack/scenes/Subscriptions/Manifest/__tests__/ManifestActions.test.js +2 -2
- data/webpack/scenes/Subscriptions/Manifest/__tests__/SimpleContentAccess.test.js +2 -2
- data/webpack/scenes/Subscriptions/Manifest/index.js +0 -1
- data/webpack/test-utils/react-testing-lib-wrapper.js +5 -2
- data/webpack/utils/helpers.js +3 -0
- metadata +103 -63
- data/app/controllers/katello/api/v2/gpg_keys_controller.rb +0 -114
- data/app/lib/actions/pulp3/content_migration_reset.rb +0 -22
- data/app/lib/katello/util/hostgroup_facets_helper.rb +0 -126
- data/app/overrides/disable_turbolinks_on_proxies_index.rb +0 -5
- data/app/services/katello/event_daemon.rb +0 -135
- data/app/services/katello/pulp/content_counts_calculator.rb +0 -60
- data/db/migrate/20210201165835_add_migration_missing_content.rb +0 -12
- data/db/migrate/20210420140050_add_pulp3_hrefs_to_content_types_deb.rb +0 -5
- data/lib/katello/tasks/check_config.rake +0 -11
- data/lib/katello/tasks/fix_hostgroup_facets.rake +0 -8
- data/lib/katello/tasks/pulp3_migration_approve_corrupted.rake +0 -21
- data/lib/katello/tasks/pulp3_migration_reset.rake +0 -26
- data/lib/katello/tasks/reports.rake +0 -7
- data/lib/katello/tasks/upgrades/3.10/update_gpg_key_urls.rake +0 -32
- data/webpack/components/TypeAhead/pf4Search/TypeAheadSearch.scss +0 -5
- data/webpack/scenes/ContentViews/Table/actionResolver.js +0 -28
@@ -0,0 +1,175 @@
|
|
1
|
+
import { STATUS } from 'foremanReact/constants';
|
2
|
+
import React, { useState, useEffect } from 'react';
|
3
|
+
import PropTypes from 'prop-types';
|
4
|
+
import { useDispatch, useSelector } from 'react-redux';
|
5
|
+
import { Redirect } from 'react-router-dom';
|
6
|
+
import { Form, FormGroup, TextInput, TextArea, Checkbox, ActionGroup, Button, Tile, Grid, GridItem } from '@patternfly/react-core';
|
7
|
+
import { createContentView } from '../ContentViewsActions';
|
8
|
+
import { selectCreateContentViews, selectCreateContentViewStatus, selectCreateContentViewError } from './ContentViewCreateSelectors';
|
9
|
+
import { LabelDependencies, LabelAutoPublish, LabelImportOnly } from './ContentViewFormComponents';
|
10
|
+
import ContentViewIcon from '../components/ContentViewIcon';
|
11
|
+
|
12
|
+
const CreateContentViewForm = ({ setModalOpen }) => {
|
13
|
+
const dispatch = useDispatch();
|
14
|
+
const [name, setName] = useState('');
|
15
|
+
const [label, setLabel] = useState('');
|
16
|
+
const [description, setDescription] = useState('');
|
17
|
+
const [composite, setComposite] = useState(false);
|
18
|
+
const [component, setComponent] = useState(true);
|
19
|
+
const [autoPublish, setAutoPublish] = useState(false);
|
20
|
+
const [importOnly, setImportOnly] = useState(false);
|
21
|
+
const [dependencies, setDependencies] = useState(false);
|
22
|
+
const [redirect, setRedirect] = useState(false);
|
23
|
+
const [saving, setSaving] = useState(false);
|
24
|
+
|
25
|
+
const response = useSelector(selectCreateContentViews);
|
26
|
+
const status = useSelector(selectCreateContentViewStatus);
|
27
|
+
const error = useSelector(selectCreateContentViewError);
|
28
|
+
|
29
|
+
useEffect(() => {
|
30
|
+
const { id } = response;
|
31
|
+
if (id && status === STATUS.RESOLVED) {
|
32
|
+
setSaving(false);
|
33
|
+
setRedirect(true);
|
34
|
+
} else if (status === STATUS.ERROR) {
|
35
|
+
setSaving(false);
|
36
|
+
}
|
37
|
+
}, [JSON.stringify(response), status, error]);
|
38
|
+
|
39
|
+
const onSave = () => {
|
40
|
+
setSaving(true);
|
41
|
+
dispatch(createContentView({
|
42
|
+
name,
|
43
|
+
label,
|
44
|
+
description,
|
45
|
+
composite,
|
46
|
+
solve_dependencies: dependencies,
|
47
|
+
auto_publish: (autoPublish && composite),
|
48
|
+
import_only: importOnly,
|
49
|
+
}));
|
50
|
+
};
|
51
|
+
|
52
|
+
useEffect(
|
53
|
+
() => {
|
54
|
+
setLabel(name.replace(/ /g, '_'));
|
55
|
+
},
|
56
|
+
[name],
|
57
|
+
);
|
58
|
+
|
59
|
+
if (redirect) {
|
60
|
+
const { id } = response;
|
61
|
+
return (<Redirect to={`/labs/content_views/${id}`} />);
|
62
|
+
}
|
63
|
+
|
64
|
+
return (
|
65
|
+
<Form>
|
66
|
+
<FormGroup label="Name" isRequired fieldId="name">
|
67
|
+
<TextInput
|
68
|
+
isRequired
|
69
|
+
type="text"
|
70
|
+
id="name"
|
71
|
+
aria-label="input_name"
|
72
|
+
name="name"
|
73
|
+
value={name}
|
74
|
+
onChange={value => setName(value)}
|
75
|
+
/>
|
76
|
+
</FormGroup>
|
77
|
+
<FormGroup label="Label" isRequired fieldId="label">
|
78
|
+
<TextInput
|
79
|
+
isRequired
|
80
|
+
type="text"
|
81
|
+
id="label"
|
82
|
+
aria-label="input_label"
|
83
|
+
name="label"
|
84
|
+
value={label}
|
85
|
+
onChange={value => setLabel(value)}
|
86
|
+
/>
|
87
|
+
</FormGroup>
|
88
|
+
<FormGroup label="Description" fieldId="description">
|
89
|
+
<TextArea
|
90
|
+
isRequired
|
91
|
+
type="text"
|
92
|
+
id="description"
|
93
|
+
name="description"
|
94
|
+
aria-label="input_description"
|
95
|
+
value={description}
|
96
|
+
onChange={value => setDescription(value)}
|
97
|
+
/>
|
98
|
+
</FormGroup>
|
99
|
+
<FormGroup isInline fieldId="type" label="Type">
|
100
|
+
<Grid hasGutter>
|
101
|
+
<GridItem span={6}>
|
102
|
+
<Tile
|
103
|
+
isStacked
|
104
|
+
aria-label="component_tile"
|
105
|
+
icon={<ContentViewIcon composite={false} />}
|
106
|
+
id="component"
|
107
|
+
title="Component content view"
|
108
|
+
onClick={() => { setComponent(true); setComposite(false); }}
|
109
|
+
isSelected={component}
|
110
|
+
>
|
111
|
+
Single content view consisting of repositories
|
112
|
+
</Tile>
|
113
|
+
</GridItem>
|
114
|
+
<GridItem span={6}>
|
115
|
+
<Tile
|
116
|
+
isStacked
|
117
|
+
aria-label="composite_tile"
|
118
|
+
icon={<ContentViewIcon composite />}
|
119
|
+
id="composite"
|
120
|
+
title="Composite content view"
|
121
|
+
onClick={() => { setComposite(true); setComponent(false); }}
|
122
|
+
isSelected={composite}
|
123
|
+
>
|
124
|
+
Consists of component content views
|
125
|
+
</Tile>
|
126
|
+
</GridItem>
|
127
|
+
</Grid>
|
128
|
+
</FormGroup>
|
129
|
+
{!composite &&
|
130
|
+
<FormGroup isInline fieldId="dependencies">
|
131
|
+
<Checkbox
|
132
|
+
id="dependencies"
|
133
|
+
name="dependencies"
|
134
|
+
label={LabelDependencies()}
|
135
|
+
isChecked={dependencies}
|
136
|
+
onChange={checked => setDependencies(checked)}
|
137
|
+
/>
|
138
|
+
</FormGroup>}
|
139
|
+
{!composite &&
|
140
|
+
<FormGroup isInline fieldId="importOnly">
|
141
|
+
<Checkbox
|
142
|
+
id="importOnly"
|
143
|
+
name="importOnly"
|
144
|
+
label={LabelImportOnly()}
|
145
|
+
isChecked={importOnly}
|
146
|
+
onChange={checked => setImportOnly(checked)}
|
147
|
+
/>
|
148
|
+
</FormGroup>}
|
149
|
+
{composite &&
|
150
|
+
<FormGroup isInline fieldId="autoPublish">
|
151
|
+
<Checkbox
|
152
|
+
id="autoPublish"
|
153
|
+
name="autoPublish"
|
154
|
+
label={LabelAutoPublish()}
|
155
|
+
isChecked={autoPublish}
|
156
|
+
onChange={checked => setAutoPublish(checked)}
|
157
|
+
/>
|
158
|
+
</FormGroup>}
|
159
|
+
<ActionGroup>
|
160
|
+
<Button aria-label="create_content_view" variant="primary" isDisabled={saving} onClick={() => onSave()}>Create content view</Button>
|
161
|
+
<Button variant="link" onClick={() => setModalOpen(false)}>Cancel</Button>
|
162
|
+
</ActionGroup>
|
163
|
+
</Form>
|
164
|
+
);
|
165
|
+
};
|
166
|
+
|
167
|
+
CreateContentViewForm.propTypes = {
|
168
|
+
setModalOpen: PropTypes.func,
|
169
|
+
};
|
170
|
+
|
171
|
+
CreateContentViewForm.defaultProps = {
|
172
|
+
setModalOpen: null,
|
173
|
+
};
|
174
|
+
|
175
|
+
export default CreateContentViewForm;
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { Modal, ModalVariant } from '@patternfly/react-core';
|
4
|
+
import CreateContentViewForm from './CreateContentViewForm';
|
5
|
+
|
6
|
+
const CreateContentViewModal = ({ show, setIsOpen }) => (
|
7
|
+
<Modal
|
8
|
+
title="Create content view"
|
9
|
+
variant={ModalVariant.small}
|
10
|
+
isOpen={show}
|
11
|
+
onClose={() => { setIsOpen(false); }}
|
12
|
+
appendTo={document.body}
|
13
|
+
><CreateContentViewForm setModalOpen={setIsOpen} />
|
14
|
+
</Modal>
|
15
|
+
);
|
16
|
+
|
17
|
+
CreateContentViewModal.propTypes = {
|
18
|
+
show: PropTypes.bool,
|
19
|
+
setIsOpen: PropTypes.func,
|
20
|
+
};
|
21
|
+
|
22
|
+
CreateContentViewModal.defaultProps = {
|
23
|
+
show: false,
|
24
|
+
setIsOpen: null,
|
25
|
+
};
|
26
|
+
|
27
|
+
export default CreateContentViewModal;
|
@@ -0,0 +1,42 @@
|
|
1
|
+
{
|
2
|
+
"content_host_count": 0,
|
3
|
+
"composite": false,
|
4
|
+
"component_ids": [],
|
5
|
+
"default": false,
|
6
|
+
"force_puppet_environment": false,
|
7
|
+
"version_count": 0,
|
8
|
+
"latest_version": null,
|
9
|
+
"auto_publish": false,
|
10
|
+
"solve_dependencies": false,
|
11
|
+
"import_only": false,
|
12
|
+
"repository_ids": [],
|
13
|
+
"id": 34,
|
14
|
+
"name": "1232123",
|
15
|
+
"label": "1232123",
|
16
|
+
"description": "",
|
17
|
+
"organization_id": 1,
|
18
|
+
"organization": {
|
19
|
+
"name": "Default Organization",
|
20
|
+
"label": "Default_Organization",
|
21
|
+
"id": 1
|
22
|
+
},
|
23
|
+
"created_at": "2020-12-14 12:45:59 -0500",
|
24
|
+
"updated_at": "2020-12-14 12:45:59 -0500",
|
25
|
+
"environments": [],
|
26
|
+
"repositories": [],
|
27
|
+
"puppet_modules": [],
|
28
|
+
"versions": [],
|
29
|
+
"components": [],
|
30
|
+
"content_view_components": [],
|
31
|
+
"activation_keys": [],
|
32
|
+
"next_version": "1.0",
|
33
|
+
"last_published": null,
|
34
|
+
"permissions": {
|
35
|
+
"view_content_views": true,
|
36
|
+
"edit_content_views": true,
|
37
|
+
"destroy_content_views": true,
|
38
|
+
"publish_content_views": true,
|
39
|
+
"promote_or_remove_content_views": true
|
40
|
+
},
|
41
|
+
"duplicate_repositories_to_publish": []
|
42
|
+
}
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { renderWithRedux, patientlyWaitFor, fireEvent } from 'react-testing-lib-wrapper';
|
3
|
+
|
4
|
+
import { nockInstance, assertNockRequest } from '../../../../test-utils/nockWrapper';
|
5
|
+
import api from '../../../../services/api';
|
6
|
+
import CreateContentViewForm from '../CreateContentViewForm';
|
7
|
+
|
8
|
+
const cvCreateData = require('./contentViewCreateResult.fixtures.json');
|
9
|
+
|
10
|
+
const cvCreatePath = api.getApiUrl('/content_views');
|
11
|
+
|
12
|
+
const setModalOpen = jest.fn();
|
13
|
+
|
14
|
+
const createDetails = {
|
15
|
+
name: '1232123',
|
16
|
+
label: '1232123',
|
17
|
+
description: '',
|
18
|
+
composite: false,
|
19
|
+
solve_dependencies: false,
|
20
|
+
auto_publish: false,
|
21
|
+
import_only: false,
|
22
|
+
};
|
23
|
+
|
24
|
+
const createdCVDetails = { ...cvCreateData };
|
25
|
+
|
26
|
+
const form = <CreateContentViewForm setModalOpen={setModalOpen} />;
|
27
|
+
|
28
|
+
test('Can save content view from form', async (done) => {
|
29
|
+
const createscope = nockInstance
|
30
|
+
.post(cvCreatePath, createDetails)
|
31
|
+
.reply(201, createdCVDetails);
|
32
|
+
const { queryByText, getByLabelText } = renderWithRedux(form);
|
33
|
+
expect(queryByText('Description')).toBeInTheDocument();
|
34
|
+
|
35
|
+
fireEvent.change(getByLabelText('input_name'), { target: { value: '1232123' } });
|
36
|
+
|
37
|
+
await patientlyWaitFor(() => { expect(getByLabelText('input_label')).toHaveAttribute('value', '1232123'); });
|
38
|
+
|
39
|
+
getByLabelText('create_content_view').click();
|
40
|
+
|
41
|
+
assertNockRequest(createscope, done);
|
42
|
+
});
|
43
|
+
|
44
|
+
test('Form closes itself upon save', async (done) => {
|
45
|
+
const createscope = nockInstance
|
46
|
+
.post(cvCreatePath, createDetails)
|
47
|
+
.reply(201, createdCVDetails);
|
48
|
+
const { getByText, queryByText, getByLabelText } = renderWithRedux(form);
|
49
|
+
expect(getByText('Description')).toBeInTheDocument();
|
50
|
+
expect(getByText('Name')).toBeInTheDocument();
|
51
|
+
expect(getByText('Label')).toBeInTheDocument();
|
52
|
+
|
53
|
+
fireEvent.change(getByLabelText('input_name'), { target: { value: '1232123' } });
|
54
|
+
|
55
|
+
await patientlyWaitFor(() => { expect(getByLabelText('input_label')).toHaveAttribute('value', '1232123'); });
|
56
|
+
|
57
|
+
getByLabelText('create_content_view').click();
|
58
|
+
// Form closes it self on success
|
59
|
+
await patientlyWaitFor(() => {
|
60
|
+
expect(queryByText('Description')).not.toBeInTheDocument();
|
61
|
+
});
|
62
|
+
|
63
|
+
assertNockRequest(createscope, done);
|
64
|
+
});
|
65
|
+
|
66
|
+
test('Displays dependent fields correctly', () => {
|
67
|
+
const { getByText, queryByText, getByLabelText } = renderWithRedux(form);
|
68
|
+
expect(getByText('Description')).toBeInTheDocument();
|
69
|
+
expect(getByText('Name')).toBeInTheDocument();
|
70
|
+
expect(getByText('Label')).toBeInTheDocument();
|
71
|
+
expect(getByText('Composite content view')).toBeInTheDocument();
|
72
|
+
expect(getByText('Component content view')).toBeInTheDocument();
|
73
|
+
expect(getByText('Solve Dependencies')).toBeInTheDocument();
|
74
|
+
expect(queryByText('Auto Publish')).not.toBeInTheDocument();
|
75
|
+
expect(getByText('Import Only')).toBeInTheDocument();
|
76
|
+
|
77
|
+
// label auto_set
|
78
|
+
fireEvent.change(getByLabelText('input_name'), { target: { value: '123 2123' } });
|
79
|
+
expect(getByLabelText('input_label')).toHaveAttribute('value', '123_2123');
|
80
|
+
|
81
|
+
// display Auto Publish when Composite CV
|
82
|
+
fireEvent.click(getByLabelText('composite_tile'));
|
83
|
+
expect(queryByText('Solve Dependencies')).not.toBeInTheDocument();
|
84
|
+
expect(getByText('Auto Publish')).toBeInTheDocument();
|
85
|
+
expect(queryByText('Import Only')).not.toBeInTheDocument();
|
86
|
+
|
87
|
+
// display Solve Dependencies when Component CV
|
88
|
+
fireEvent.click(getByLabelText('component_tile'));
|
89
|
+
expect(getByText('Solve Dependencies')).toBeInTheDocument();
|
90
|
+
expect(queryByText('Auto Publish')).not.toBeInTheDocument();
|
91
|
+
expect(getByText('Import Only')).toBeInTheDocument();
|
92
|
+
});
|
@@ -8,8 +8,10 @@ import {
|
|
8
8
|
UPDATE_CONTENT_VIEW_SUCCESS,
|
9
9
|
NOT_ADDED,
|
10
10
|
ALL_STATUSES,
|
11
|
+
REPOSITORY_TYPES,
|
11
12
|
cvDetailsKey,
|
12
13
|
cvDetailsRepoKey,
|
14
|
+
cvDetailsFilterKey,
|
13
15
|
} from '../ContentViewsConstants';
|
14
16
|
import api from '../../../services/api';
|
15
17
|
|
@@ -63,4 +65,18 @@ export const getContentViewRepositories = (cvId, params, status) => {
|
|
63
65
|
});
|
64
66
|
};
|
65
67
|
|
68
|
+
export const getRepositoryTypes = () => get({
|
69
|
+
type: API_OPERATIONS.GET,
|
70
|
+
key: REPOSITORY_TYPES,
|
71
|
+
errorToast: error => __(`Something went wrong while retrieving the repository types! ${error}`),
|
72
|
+
url: api.getApiUrl('/repositories/repository_types'),
|
73
|
+
});
|
74
|
+
|
75
|
+
export const getContentViewFilters = (cvId, params) => get({
|
76
|
+
key: cvDetailsFilterKey(cvId),
|
77
|
+
params: { content_view_id: cvId, ...params },
|
78
|
+
errorToast: error => __(`Something went wrong while retrieving the content view filters! ${error}`),
|
79
|
+
url: api.getApiUrl('/content_view_filters'),
|
80
|
+
});
|
81
|
+
|
66
82
|
export default getContentViewDetails;
|
@@ -4,7 +4,12 @@ import {
|
|
4
4
|
selectAPIResponse,
|
5
5
|
} from 'foremanReact/redux/API/APISelectors';
|
6
6
|
import { STATUS } from 'foremanReact/constants';
|
7
|
-
import {
|
7
|
+
import {
|
8
|
+
cvDetailsKey,
|
9
|
+
cvDetailsRepoKey,
|
10
|
+
cvDetailsFilterKey,
|
11
|
+
REPOSITORY_TYPES,
|
12
|
+
} from '../ContentViewsConstants';
|
8
13
|
|
9
14
|
export const selectCVDetails = (state, cvId) =>
|
10
15
|
selectAPIResponse(state, cvDetailsKey(cvId)) || {};
|
@@ -24,5 +29,19 @@ export const selectCVReposStatus = (state, cvId) =>
|
|
24
29
|
export const selectCVReposError = (state, cvId) =>
|
25
30
|
selectAPIError(state, cvDetailsRepoKey(cvId));
|
26
31
|
|
32
|
+
export const selectRepoTypes = state =>
|
33
|
+
selectAPIResponse(state, REPOSITORY_TYPES) || {};
|
34
|
+
|
35
|
+
export const selectRepoTypesStatus = state =>
|
36
|
+
selectAPIStatus(state, REPOSITORY_TYPES) || STATUS.PENDING;
|
37
|
+
|
38
|
+
export const selectCVFilters = (state, cvId) =>
|
39
|
+
selectAPIResponse(state, cvDetailsFilterKey(cvId)) || {};
|
40
|
+
|
41
|
+
export const selectCVFiltersStatus = (state, cvId) =>
|
42
|
+
selectAPIStatus(state, cvDetailsFilterKey(cvId)) || STATUS.PENDING;
|
43
|
+
|
44
|
+
export const selectCVFiltersError = (state, cvId) =>
|
45
|
+
selectAPIError(state, cvDetailsFilterKey(cvId));
|
27
46
|
|
28
47
|
export const selectIsCVUpdating = state => state.katello?.contentViewDetails?.updating;
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { useSelector, shallowEqual } from 'react-redux';
|
3
|
-
import { Grid, GridItem, TextContent, Text, TextVariants } from '@patternfly/react-core';
|
3
|
+
import { Grid, GridItem, TextContent, Text, TextVariants, Button } from '@patternfly/react-core';
|
4
|
+
import { ExternalLinkAltIcon } from '@patternfly/react-icons';
|
4
5
|
import { translate as __ } from 'foremanReact/common/I18n';
|
5
6
|
import PropTypes from 'prop-types';
|
6
7
|
|
7
8
|
import DetailsContainer from './DetailsContainer';
|
8
9
|
import ContentViewInfo from './ContentViewInfo';
|
9
10
|
import ContentViewRepositories from './Repositories/ContentViewRepositories';
|
11
|
+
import ContentViewFilters from './Filters/ContentViewFilters';
|
10
12
|
import { selectCVDetails } from './ContentViewDetailSelectors';
|
11
13
|
import TabbedView from '../../../components/TabbedView';
|
12
14
|
|
@@ -30,27 +32,35 @@ const ContentViewDetails = ({ match }) => {
|
|
30
32
|
},
|
31
33
|
{
|
32
34
|
title: __('Filters'),
|
33
|
-
content: <
|
35
|
+
content: <ContentViewFilters cvId={cvId} />,
|
34
36
|
},
|
35
37
|
{
|
36
38
|
title: __('History'),
|
37
39
|
content: <React.Fragment>History</React.Fragment>,
|
38
40
|
},
|
39
|
-
{
|
40
|
-
title: __('Tasks'),
|
41
|
-
content: <React.Fragment>Tasks</React.Fragment>,
|
42
|
-
},
|
43
41
|
];
|
44
42
|
|
45
43
|
return (
|
46
44
|
<Grid className="grid-with-margin">
|
47
45
|
<DetailsContainer cvId={cvId}>
|
48
46
|
<React.Fragment>
|
49
|
-
<GridItem span={
|
47
|
+
<GridItem span={8}>
|
50
48
|
<TextContent>
|
51
49
|
<Text component={TextVariants.h1}>{`${name} content view`}</Text>
|
52
50
|
</TextContent>
|
53
51
|
</GridItem>
|
52
|
+
<GridItem span={4} style={{ textAlign: 'right' }}>
|
53
|
+
<Button
|
54
|
+
component="a"
|
55
|
+
aria-label="view tasks button"
|
56
|
+
href={`/foreman_tasks/tasks?search=resource_type%3D+Katello%3A%3AContentView+resource_id%3D${cvId}`}
|
57
|
+
target="_blank"
|
58
|
+
variant="secondary"
|
59
|
+
>
|
60
|
+
{'View tasks '}
|
61
|
+
<ExternalLinkAltIcon />
|
62
|
+
</Button>
|
63
|
+
</GridItem>
|
54
64
|
<GridItem span={12}>
|
55
65
|
<TabbedView tabs={tabs} />
|
56
66
|
</GridItem>
|
@@ -8,6 +8,7 @@ import {
|
|
8
8
|
TextListVariants,
|
9
9
|
TextListItem,
|
10
10
|
TextListItemVariants,
|
11
|
+
Switch,
|
11
12
|
} from '@patternfly/react-core';
|
12
13
|
import PropTypes from 'prop-types';
|
13
14
|
import { translate as __ } from 'foremanReact/common/I18n';
|
@@ -18,6 +19,8 @@ import Loading from '../../../components/Loading';
|
|
18
19
|
import ContentViewIcon from '../components/ContentViewIcon';
|
19
20
|
import ActionableDetail from '../../../components/ActionableDetail';
|
20
21
|
import './contentViewInfo.scss';
|
22
|
+
import { dependenciesHelpText, autoPublishHelpText } from '../helpers';
|
23
|
+
import { LabelImportOnly } from '../Create/ContentViewFormComponents';
|
21
24
|
|
22
25
|
const ContentViewInfo = ({ cvId, details }) => {
|
23
26
|
const dispatch = useDispatch();
|
@@ -29,19 +32,9 @@ const ContentViewInfo = ({ cvId, details }) => {
|
|
29
32
|
composite,
|
30
33
|
solve_dependencies: solveDependencies,
|
31
34
|
auto_publish: autoPublish,
|
35
|
+
import_only: importOnly,
|
32
36
|
} = details;
|
33
37
|
|
34
|
-
const autoPublishTooltip = __('Applicable only for composite views. Auto publish composite ' +
|
35
|
-
'view when a new version of a component content view is created. Also note auto publish will ' +
|
36
|
-
'only happen when the component is marked "latest".');
|
37
|
-
|
38
|
-
const solveDependenciesTooltip = __('This option will solve RPM and Module Stream dependencies ' +
|
39
|
-
'on every publish of this Content View. Dependency solving significantly increases publish ' +
|
40
|
-
'time (publishes can take over three times as long) and filters will be ignored when adding ' +
|
41
|
-
'packages to solve dependencies. Also, certain scenarios involving errata may still cause ' +
|
42
|
-
'dependency errors.');
|
43
|
-
|
44
|
-
|
45
38
|
if (updating) return <Loading size="sm" showText={false} />;
|
46
39
|
const onEdit = (val, attribute) => dispatch(updateContentView(cvId, { [attribute]: val }));
|
47
40
|
return (
|
@@ -85,7 +78,7 @@ const ContentViewInfo = ({ cvId, details }) => {
|
|
85
78
|
attribute="auto_publish"
|
86
79
|
value={autoPublish}
|
87
80
|
onEdit={onEdit}
|
88
|
-
tooltip={
|
81
|
+
tooltip={autoPublishHelpText}
|
89
82
|
boolean
|
90
83
|
/>) :
|
91
84
|
(<ActionableDetail
|
@@ -93,9 +86,21 @@ const ContentViewInfo = ({ cvId, details }) => {
|
|
93
86
|
attribute="solve_dependencies"
|
94
87
|
value={solveDependencies}
|
95
88
|
onEdit={onEdit}
|
96
|
-
tooltip={
|
89
|
+
tooltip={dependenciesHelpText}
|
97
90
|
boolean
|
98
91
|
/>)}
|
92
|
+
<TextListItem component={TextListItemVariants.dt}>
|
93
|
+
{LabelImportOnly()}
|
94
|
+
</TextListItem>
|
95
|
+
<TextListItem component={TextListItemVariants.dd} className="foreman-spaced-list">
|
96
|
+
<Switch
|
97
|
+
id="import_only_switch"
|
98
|
+
aria-label="import_only_switch"
|
99
|
+
isChecked={importOnly}
|
100
|
+
className="foreman-spaced-list"
|
101
|
+
disabled
|
102
|
+
/>
|
103
|
+
</TextListItem>
|
99
104
|
</TextList>
|
100
105
|
</TextContent>
|
101
106
|
);
|
@@ -110,6 +115,7 @@ ContentViewInfo.propTypes = {
|
|
110
115
|
composite: PropTypes.bool,
|
111
116
|
solve_dependencies: PropTypes.bool,
|
112
117
|
auto_publish: PropTypes.bool,
|
118
|
+
import_only: PropTypes.bool,
|
113
119
|
}).isRequired,
|
114
120
|
};
|
115
121
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import React, { Fragment } from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
4
|
+
|
5
|
+
import RepoIcon from '../Repositories/RepoIcon';
|
6
|
+
import { capitalize } from '../../../../utils/helpers';
|
7
|
+
|
8
|
+
const typeName = (type, errataByDate) => {
|
9
|
+
if (errataByDate) return 'Errata - by date range';
|
10
|
+
const nameMap = {
|
11
|
+
rpm: __('RPM'),
|
12
|
+
docker: __('Container image tag'),
|
13
|
+
modulemd: __('Module stream'),
|
14
|
+
erratum: __('Errata'),
|
15
|
+
};
|
16
|
+
|
17
|
+
if (Object.prototype.hasOwnProperty.call(nameMap, type)) return nameMap[type];
|
18
|
+
return capitalize(type.replace('_', ' '));
|
19
|
+
};
|
20
|
+
|
21
|
+
const ContentType = ({ type, errataByDate }) => {
|
22
|
+
const repoType = ['rpm', 'modulemd', 'rpm', 'erratum', 'package_group'].includes(type) ? 'yum' : type;
|
23
|
+
return (
|
24
|
+
<Fragment>
|
25
|
+
<span style={{ marginRight: '5px' }}><RepoIcon type={repoType} /></span>
|
26
|
+
{typeName(type, errataByDate)}
|
27
|
+
</Fragment>
|
28
|
+
);
|
29
|
+
};
|
30
|
+
|
31
|
+
ContentType.propTypes = {
|
32
|
+
type: PropTypes.string.isRequired,
|
33
|
+
errataByDate: PropTypes.bool,
|
34
|
+
};
|
35
|
+
|
36
|
+
ContentType.defaultProps = {
|
37
|
+
errataByDate: false,
|
38
|
+
};
|
39
|
+
|
40
|
+
export default ContentType;
|