katello 4.3.0.rc1 → 4.3.0.rc2
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/v2/api_controller.rb +4 -0
- data/app/controllers/katello/api/v2/host_errata_controller.rb +5 -0
- data/app/controllers/katello/api/v2/host_packages_controller.rb +2 -0
- data/app/controllers/katello/api/v2/host_tracer_controller.rb +4 -0
- data/app/controllers/katello/api/v2/repository_sets_controller.rb +2 -2
- data/app/controllers/katello/api/v2/root_controller.rb +10 -19
- data/app/controllers/katello/concerns/api/v2/bulk_extensions.rb +3 -13
- data/app/controllers/katello/remote_execution_controller.rb +1 -1
- data/app/lib/actions/katello/capsule_content/sync_capsule.rb +7 -5
- data/app/lib/actions/katello/repository/destroy.rb +3 -3
- data/app/lib/actions/pulp/repository/sync.rb +0 -2
- data/app/lib/actions/pulp3/abstract_async_task.rb +16 -4
- data/app/lib/katello/resources/cdn.rb +10 -1
- data/app/models/katello/concerns/host_managed_extensions.rb +7 -4
- data/app/models/katello/concerns/smart_proxy_extensions.rb +6 -2
- data/app/models/katello/content_view_version.rb +1 -6
- data/app/models/katello/glue/pulp/repo.rb +1 -2
- data/app/models/katello/host_tracer.rb +2 -0
- data/app/models/katello/repository.rb +2 -30
- data/app/models/katello/root_repository.rb +3 -43
- data/app/presenters/katello/host_package_presenter.rb +21 -0
- data/app/services/katello/bulk_items_helper.rb +35 -0
- data/app/services/katello/smart_proxy_helper.rb +10 -1
- data/app/views/foreman/job_templates/install_errata.erb +8 -6
- data/app/views/foreman/job_templates/resolve_traces.erb +4 -5
- data/app/views/foreman/job_templates/resolve_traces_-_katello_ansible_default.erb +3 -5
- data/app/views/foreman/smart_proxies/_content_sync.html.erb +7 -0
- data/app/views/katello/api/v2/capsule_content/sync_status.json.rabl +4 -0
- data/app/views/katello/api/v2/{organizations/cdn_configuration.rabl → cdn_configurations/show.json.rabl} +4 -0
- data/app/views/katello/api/v2/content_facet/show.json.rabl +8 -0
- data/app/views/katello/api/v2/content_view_filters/show.json.rabl +0 -1
- data/app/views/katello/api/v2/content_views/base.json.rabl +1 -1
- data/app/views/katello/api/v2/host_packages/base.json.rabl +2 -0
- data/app/views/katello/api/v2/organizations/show.json.rabl +1 -1
- data/app/views/katello/api/v2/repositories/show.json.rabl +0 -3
- data/config/routes/api/v2.rb +0 -10
- data/db/migrate/20211115215210_drop_ostree_branches.rb +13 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/bastion-katello-bootstrap.js +0 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/bastion_katello.js +0 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/content-views.routes.js +0 -10
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/details/views/content-view-versions.html +0 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/versions/content-view-version-content.controller.js +0 -10
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/versions/content-view-versions.module.js +0 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/versions/views/content-view-version.html +0 -7
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/content.service.js +0 -5
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/environments.module.js +0 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/environments.routes.js +0 -11
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/organizations/fenced-pages.service.js +1 -2
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.controller.js +2 -4
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/repository-details-info.filter.js +0 -10
- 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/new/new-repository.controller.js +3 -6
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/new/views/new-repository.html +4 -1
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/os-versions.service.js +1 -0
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repositories.routes.js +0 -9
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/views/product-repositories.html +0 -8
- data/engines/bastion_katello/lib/bastion_katello/engine.rb +0 -1
- data/lib/katello/permission_creator.rb +0 -1
- data/lib/katello/plugin.rb +0 -10
- data/lib/katello/tasks/reset.rake +2 -2
- data/lib/katello/version.rb +1 -1
- data/webpack/components/Packages/index.js +63 -0
- data/webpack/components/Search/Search.js +7 -1
- data/webpack/components/SelectAllCheckbox/index.js +2 -2
- data/webpack/components/Table/MainTable.scss +7 -1
- data/webpack/components/Table/TableHooks.js +10 -19
- data/webpack/components/Table/TableWrapper.js +0 -2
- data/webpack/components/WithOrganization/__snapshots__/withOrganization.test.js.snap +3 -3
- data/webpack/components/extensions/HostDetails/HostDetailsConstants.js +1 -0
- data/webpack/components/extensions/HostDetails/HostDetailsSelectors.js +16 -0
- data/webpack/components/extensions/HostDetails/HostErrata/HostErrataConstants.js +2 -0
- data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesActions.js +11 -0
- data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesConstants.js +2 -0
- data/webpack/components/extensions/HostDetails/HostPackages/HostPackagesSelectors.js +16 -0
- data/webpack/components/extensions/HostDetails/Tabs/ContentTab/SecondaryTabsRoutes.js +4 -0
- data/webpack/components/extensions/HostDetails/Tabs/ContentTab/constants.js +1 -0
- data/webpack/components/extensions/HostDetails/Tabs/ErrataTab.js +119 -25
- data/webpack/components/extensions/HostDetails/Tabs/HostTracesConstants.js +1 -0
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.js +127 -0
- data/webpack/components/extensions/HostDetails/Tabs/PackagesTab.scss +11 -0
- data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionActions.js +30 -4
- data/webpack/components/extensions/HostDetails/Tabs/RemoteExecutionConstants.js +1 -0
- data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsActions.js +73 -0
- data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsConstants.js +2 -0
- data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsSelectors.js +16 -0
- data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.js +347 -0
- data/webpack/components/extensions/HostDetails/Tabs/RepositorySetsTab/RepositorySetsTab.scss +7 -0
- data/webpack/components/extensions/HostDetails/Tabs/TracesTab.js +38 -31
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/bookmarks.fixtures.json +12 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/contentOverrides.fixtures.json +227 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +423 -2
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packages.fixtures.json +28 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +91 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySets.fixtures.json +120 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/repositorySetsTab.test.js +307 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/resolveErrata.fixtures.json +35 -0
- data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +55 -9
- data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +28 -14
- data/webpack/containers/Application/overrides.scss +31 -9
- data/webpack/global_index.js +4 -2
- data/webpack/redux/reducers/RedHatRepositories/enabled.fixtures.js +0 -2
- data/webpack/scenes/Content/ContentConfig.js +23 -7
- data/webpack/scenes/ContentCredentials/ContentCredentialActions.js +18 -0
- data/webpack/scenes/ContentCredentials/ContentCredentialConstants.js +2 -0
- data/webpack/scenes/ContentCredentials/ContentCredentialSelectors.js +12 -0
- data/webpack/scenes/ContentCredentials/__tests__/contentCredentials.fixtures.js +73 -0
- data/webpack/scenes/ContentViews/Copy/CopyContentViewForm.js +1 -1
- data/webpack/scenes/ContentViews/Create/ContentViewFormComponents.js +3 -3
- data/webpack/scenes/ContentViews/Create/CreateContentViewForm.js +7 -2
- data/webpack/scenes/ContentViews/Create/CreateContentViewForm.scss +7 -0
- data/webpack/scenes/ContentViews/Create/__tests__/createContentView.test.js +9 -9
- data/webpack/scenes/ContentViews/Delete/ContentViewDeleteWizard.js +6 -6
- data/webpack/scenes/ContentViews/Delete/Steps/CVDeleteEnvironmentsSelection.js +39 -37
- data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReview.js +35 -33
- data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +7 -5
- data/webpack/scenes/ContentViews/Delete/__tests__/cvVersionsData.fixtures.json +2 -6
- data/webpack/scenes/ContentViews/Details/ComponentContentViews/ComponentEnvironments.js +13 -14
- data/webpack/scenes/ContentViews/Details/ContentViewDetails.js +18 -9
- data/webpack/scenes/ContentViews/Details/ContentViewInfo.js +3 -2
- data/webpack/scenes/ContentViews/Details/Filters/Add/__tests__/cvFilterCreateResult.fixtures.json +1 -2
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/CVRpmFilterContent.test.js +1 -1
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewErrataByDateDetails.fixtures.json +1 -8
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetail.fixtures.json +1 -2
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/contentViewFilterDetails.test.js +3 -8
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvAllRepos.fixtures.json +0 -2
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvErratumFilterDetails.fixtures.json +1 -2
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvFilterDetailModuleAffectedRepos.fixtures.json +1 -8
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvFilterDetailWithAffectedRepos.fixtures.json +1 -8
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvModuleStreamFilterDetails.fixtures.json +1 -2
- data/webpack/scenes/ContentViews/Details/Filters/__tests__/cvPackageFilterDetail.fixtures.json +1 -3
- data/webpack/scenes/ContentViews/Details/Promote/ContentViewVersionPromote.js +44 -28
- data/webpack/scenes/ContentViews/Details/Repositories/ContentCounts.js +2 -1
- data/webpack/scenes/ContentViews/Details/Repositories/ContentViewRepositories.js +1 -1
- data/webpack/scenes/ContentViews/Details/Repositories/LastSync.js +46 -8
- data/webpack/scenes/ContentViews/Details/Repositories/__tests__/contentViewDetailRepos.fixtures.json +0 -2
- data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionContent.js +19 -3
- data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionEnvironments.js +2 -2
- data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionErrata.js +5 -3
- data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersionErrata.scss +5 -2
- data/webpack/scenes/ContentViews/Details/Versions/ContentViewVersions.js +7 -4
- data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVEnvironmentSelectionForm.js +59 -53
- data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVVersionRemoveReview.js +24 -17
- data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/versionsResponseData.fixtures.json +1 -4
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/ContentViewVersionRepositoryCell.js +8 -3
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionComponent.fixtures.json +1 -4
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetails.fixtures.json +1 -2
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionDetailsCounts.fixtures.json +1 -2
- data/webpack/scenes/ContentViews/Details/Versions/VersionDetails/__tests__/ContentViewVersionRepositories.fixtures.json +1 -18
- data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.fixtures.json +5 -5
- data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersions.test.js +1 -0
- data/webpack/scenes/ContentViews/Details/Versions/__tests__/contentViewVersionsWithTask.fixtures.json +1 -3
- data/webpack/scenes/ContentViews/Details/contentViewInfo.scss +0 -4
- data/webpack/scenes/ContentViews/Publish/CVPublishForm.js +66 -53
- data/webpack/scenes/ContentViews/Publish/CVPublishReview.js +40 -28
- data/webpack/scenes/ContentViews/Publish/PublishContentViewWizard.js +3 -3
- data/webpack/scenes/ContentViews/Publish/__tests__/publishContentView.test.js +14 -14
- data/webpack/scenes/ContentViews/Publish/cvPublishForm.scss +6 -0
- data/webpack/scenes/ContentViews/Table/ContentViewsTable.js +53 -12
- data/webpack/scenes/ContentViews/Table/tableDataGenerator.js +12 -6
- data/webpack/scenes/ContentViews/__tests__/contentViewPage.test.js +6 -6
- data/webpack/scenes/ContentViews/components/ContentViewIcon.js +6 -5
- data/webpack/scenes/ContentViews/components/ContentViewsCounter.js +2 -2
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.js +26 -27
- data/webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPaths.scss +18 -6
- data/webpack/scenes/ContentViews/components/WizardHeader.js +44 -0
- data/webpack/scenes/ContentViews/components/contentViewIcon.scss +13 -2
- data/webpack/scenes/Organizations/OrganizationActions.js +22 -24
- data/webpack/scenes/Organizations/OrganizationConstants.js +1 -3
- data/webpack/scenes/Organizations/OrganizationReducer.js +0 -7
- data/webpack/scenes/Organizations/OrganizationSelectors.js +16 -0
- data/webpack/scenes/Organizations/__tests__/OrganizationActions.test.js +1 -21
- data/webpack/scenes/Organizations/__tests__/OrganizationReducer.test.js +0 -20
- data/webpack/scenes/Organizations/__tests__/organizations.fixtures.js +34 -23
- data/webpack/scenes/Subscriptions/Manifest/ManageManifestModal.js +151 -14
- data/webpack/scenes/Subscriptions/Manifest/__tests__/ManageManifestModal.test.js +150 -31
- data/webpack/scenes/Subscriptions/Manifest/index.js +14 -3
- data/webpack/utils/dateTimeHelpers.js +7 -0
- data/webpack/utils/helpers.js +1 -1
- metadata +45 -43
- data/app/controllers/katello/api/v2/ostree_branches_controller.rb +0 -16
- data/app/lib/actions/pulp/repository/presenters/ostree_presenter.rb +0 -91
- data/app/models/katello/ostree_branch.rb +0 -12
- data/app/models/katello/repository_ostree_branch.rb +0 -7
- data/app/services/katello/pulp/ostree_branch.rb +0 -14
- data/app/services/katello/pulp/repository/ostree.rb +0 -48
- data/app/views/katello/api/v2/ostree_branches/compare.json.rabl +0 -10
- data/app/views/katello/api/v2/ostree_branches/index.json.rabl +0 -7
- data/app/views/katello/api/v2/ostree_branches/show.json.rabl +0 -5
- data/app/views/katello/api/v2/root/resource_list.json.rabl +0 -3
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/content-views/versions/views/content-view-version-ostree-branches.html +0 -26
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/environments/details/views/environment-ostree.html +0 -27
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/details/ostree-branch-repositories.controller.js +0 -77
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/details/ostree-branch.controller.js +0 -31
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/details/views/ostree-branch-info.html +0 -15
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/details/views/ostree-branch-repositories.html +0 -72
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/details/views/ostree-branch.html +0 -30
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/ostree-branch.factory.js +0 -27
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/ostree-branches.controller.js +0 -67
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/ostree-branches.module.js +0 -15
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/ostree-branches.routes.js +0 -50
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/ostree-branches/views/ostree-branches.html +0 -40
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-manage-ostree-branches.html +0 -40
- data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/ostree-upstream-sync-policy.service.js +0 -26
- data/webpack/components/extensions/HostDetails/Tabs/SubscriptionTab.js +0 -12
- data/webpack/scenes/Content/Details/ContentCounts.js +0 -42
- data/webpack/scenes/Subscriptions/Manifest/__tests__/SimpleContentAccess.test.js +0 -108
- data/webpack/scenes/Subscriptions/Manifest/__tests__/__snapshots__/ManageManifestModal.test.js.snap +0 -158
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
2
2
|
import { useDispatch } from 'react-redux';
|
3
3
|
import { ControlLabel } from 'react-bootstrap';
|
4
4
|
import { loadSetting } from 'foremanReact/components/Settings/SettingsActions';
|
@@ -26,11 +26,14 @@ const Search = ({
|
|
26
26
|
}) => {
|
27
27
|
const [items, setItems] = useState([]);
|
28
28
|
const dispatch = useDispatch();
|
29
|
+
const mountedRef = useRef(true);
|
29
30
|
|
30
31
|
const onInputUpdate = async (searchTerm = '') => {
|
31
32
|
const newItems = items.filter(({ text }) => stringIncludes(text, searchTerm));
|
32
33
|
|
33
34
|
if (newItems.length !== items.length) {
|
35
|
+
// Checking whether the current component is mounted before state change events
|
36
|
+
if (!mountedRef.current) return;
|
34
37
|
setItems(newItems);
|
35
38
|
}
|
36
39
|
|
@@ -43,6 +46,8 @@ const Search = ({
|
|
43
46
|
} else {
|
44
47
|
data = await api.get(endpoint, undefined, params);
|
45
48
|
}
|
49
|
+
// Checking whether the current component is mounted before state change events
|
50
|
+
if (!mountedRef.current) return;
|
46
51
|
setItems(data?.data?.filter(({ error }) => !error).map(({ label }) => ({
|
47
52
|
text: label.trim(),
|
48
53
|
})));
|
@@ -56,6 +61,7 @@ const Search = ({
|
|
56
61
|
useEffect(() => {
|
57
62
|
dispatch(loadSetting(AUTOSEARCH_DELAY));
|
58
63
|
dispatch(loadSetting(AUTOSEARCH_WHILE_TYPING));
|
64
|
+
return () => { mountedRef.current = false; };
|
59
65
|
}, [dispatch]);
|
60
66
|
|
61
67
|
const onNewSearch = (search) => {
|
@@ -71,13 +71,13 @@ const SelectAllCheckbox = ({
|
|
71
71
|
<DropdownItem key="select-none" component="button" isDisabled={selectedCount === 0} onClick={handleSelectNone} >
|
72
72
|
{`${__('Select none')} (0)`}
|
73
73
|
</DropdownItem>,
|
74
|
-
<DropdownItem key="select-page" component="button" isDisabled={areAllRowsOnPageSelected} onClick={handleSelectPage}>
|
74
|
+
<DropdownItem key="select-page" component="button" isDisabled={pageRowCount === 0 || areAllRowsOnPageSelected} onClick={handleSelectPage}>
|
75
75
|
{`${__('Select page')} (${pageRowCount})`}
|
76
76
|
</DropdownItem>,
|
77
77
|
];
|
78
78
|
if (canSelectAll) {
|
79
79
|
selectAllDropdownItems.push((
|
80
|
-
<DropdownItem key="select-all" id="all" component="button" isDisabled={areAllRowsSelected} onClick={handleSelectAll}>
|
80
|
+
<DropdownItem key="select-all" id="all" component="button" isDisabled={totalCount === 0 || areAllRowsSelected} onClick={handleSelectAll}>
|
81
81
|
{`${__('Select all')} (${totalCount})`}
|
82
82
|
</DropdownItem>));
|
83
83
|
}
|
@@ -1,11 +1,17 @@
|
|
1
|
-
.pf-c-dropdown.pf-m-align-right{
|
1
|
+
.pf-c-dropdown.pf-m-align-right {
|
2
2
|
width: 100%;
|
3
3
|
justify-content: flex-end;
|
4
4
|
display: flex;
|
5
5
|
}
|
6
|
+
|
6
7
|
.pf-c-dropdown__menu {
|
7
8
|
min-width: 0;
|
8
9
|
}
|
10
|
+
|
9
11
|
.pf-c-wizard__footer {
|
10
12
|
z-index: 1;
|
13
|
+
}
|
14
|
+
|
15
|
+
.pf-c-table tbody tr td {
|
16
|
+
vertical-align: inherit;
|
11
17
|
}
|
@@ -179,27 +179,18 @@ export const useBulkSelect = ({
|
|
179
179
|
};
|
180
180
|
|
181
181
|
const fetchBulkParams = () => {
|
182
|
-
const
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
},
|
187
|
-
excluded: {
|
188
|
-
ids: [],
|
189
|
-
},
|
190
|
-
all: false,
|
182
|
+
const searchQueryWithExclusionSet = () => {
|
183
|
+
const query = [searchQuery,
|
184
|
+
!isEmpty(exclusionSet) && `${idColumn} !^ (${[...exclusionSet].join(',')})`];
|
185
|
+
return query.filter(item => item).join(' and ');
|
191
186
|
};
|
192
187
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
} else {
|
200
|
-
return {};
|
201
|
-
}
|
202
|
-
return selected;
|
188
|
+
const searchQueryWithInclusionSet = () => {
|
189
|
+
if (isEmpty(inclusionSet)) throw new Error('Cannot build a search query with no items selected');
|
190
|
+
return `${idColumn} ^ (${[...inclusionSet].join(',')})`;
|
191
|
+
};
|
192
|
+
|
193
|
+
return selectAllMode ? searchQueryWithExclusionSet() : searchQueryWithInclusionSet();
|
203
194
|
};
|
204
195
|
|
205
196
|
const prevSearchRef = usePrevious({ searchQuery });
|
@@ -63,8 +63,6 @@ const TableWrapper = ({
|
|
63
63
|
const hasChanged = (oldValue, newValue) => !isEqual(oldValue, newValue);
|
64
64
|
|
65
65
|
const spawnFetch = useCallback((paginationData) => {
|
66
|
-
// The search component will update the search query when a search is performed, listen for that
|
67
|
-
// and perform the search so we can be sure the searchQuery is updated when search is performed.
|
68
66
|
const fetchWithParams = (allParams = {}) => {
|
69
67
|
const newRequest = {
|
70
68
|
...(paginationData ?? paginationParams()),
|
@@ -17,7 +17,6 @@ exports[`subscriptions page should render select org page 1`] = `
|
|
17
17
|
default={[Function]}
|
18
18
|
loadOrganization={[Function]}
|
19
19
|
organization={Object {}}
|
20
|
-
saveOrganization={[Function]}
|
21
20
|
store={
|
22
21
|
Object {
|
23
22
|
"clearActions": [Function],
|
@@ -28,6 +27,7 @@ exports[`subscriptions page should render select org page 1`] = `
|
|
28
27
|
"subscribe": [Function],
|
29
28
|
}
|
30
29
|
}
|
30
|
+
updateCdnConfiguration={[Function]}
|
31
31
|
>
|
32
32
|
<Header
|
33
33
|
title="Select Organization"
|
@@ -73,7 +73,6 @@ exports[`subscriptions page should render the wrapped component 1`] = `
|
|
73
73
|
default={[Function]}
|
74
74
|
loadOrganization={[Function]}
|
75
75
|
organization={Object {}}
|
76
|
-
saveOrganization={[Function]}
|
77
76
|
store={
|
78
77
|
Object {
|
79
78
|
"clearActions": [Function],
|
@@ -84,12 +83,12 @@ exports[`subscriptions page should render the wrapped component 1`] = `
|
|
84
83
|
"subscribe": [Function],
|
85
84
|
}
|
86
85
|
}
|
86
|
+
updateCdnConfiguration={[Function]}
|
87
87
|
>
|
88
88
|
<WrappedComponent
|
89
89
|
default={[Function]}
|
90
90
|
loadOrganization={[Function]}
|
91
91
|
organization={Object {}}
|
92
|
-
saveOrganization={[Function]}
|
93
92
|
store={
|
94
93
|
Object {
|
95
94
|
"clearActions": [Function],
|
@@ -100,6 +99,7 @@ exports[`subscriptions page should render the wrapped component 1`] = `
|
|
100
99
|
"subscribe": [Function],
|
101
100
|
}
|
102
101
|
}
|
102
|
+
updateCdnConfiguration={[Function]}
|
103
103
|
>
|
104
104
|
<div>
|
105
105
|
Wrapped!
|
@@ -0,0 +1 @@
|
|
1
|
+
export default 'HOST_DETAILS';
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import {
|
2
|
+
selectAPIStatus,
|
3
|
+
selectAPIError,
|
4
|
+
selectAPIResponse,
|
5
|
+
} from 'foremanReact/redux/API/APISelectors';
|
6
|
+
import { STATUS } from 'foremanReact/constants';
|
7
|
+
import HOST_DETAILS_KEY from './HostDetailsConstants';
|
8
|
+
|
9
|
+
export const selectHostDetails = state =>
|
10
|
+
selectAPIResponse(state, HOST_DETAILS_KEY) || {};
|
11
|
+
|
12
|
+
export const selectHostDetailsStatus = state =>
|
13
|
+
selectAPIStatus(state, HOST_DETAILS_KEY) || STATUS.PENDING;
|
14
|
+
|
15
|
+
export const selectHostDetailsError = state =>
|
16
|
+
selectAPIError(state, HOST_DETAILS_KEY);
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { API_OPERATIONS, get } from 'foremanReact/redux/API';
|
2
|
+
import { foremanApi } from '../../../../services/api';
|
3
|
+
import { HOST_PACKAGES_KEY } from './HostPackagesConstants';
|
4
|
+
|
5
|
+
export const getInstalledPackagesWithLatest = (hostId, params) => get({
|
6
|
+
type: API_OPERATIONS.GET,
|
7
|
+
key: HOST_PACKAGES_KEY,
|
8
|
+
url: foremanApi.getApiUrl(`/hosts/${hostId}/packages?include_latest_upgradable=true`),
|
9
|
+
params,
|
10
|
+
});
|
11
|
+
export default getInstalledPackagesWithLatest;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import {
|
2
|
+
selectAPIStatus,
|
3
|
+
selectAPIError,
|
4
|
+
selectAPIResponse,
|
5
|
+
} from 'foremanReact/redux/API/APISelectors';
|
6
|
+
import { STATUS } from 'foremanReact/constants';
|
7
|
+
import { HOST_PACKAGES_KEY } from './HostPackagesConstants';
|
8
|
+
|
9
|
+
export const selectHostPackages = state =>
|
10
|
+
selectAPIResponse(state, HOST_PACKAGES_KEY) || {};
|
11
|
+
|
12
|
+
export const selectHostPackagesStatus = state =>
|
13
|
+
selectAPIStatus(state, HOST_PACKAGES_KEY) || STATUS.PENDING;
|
14
|
+
|
15
|
+
export const selectHostPackagesError = state =>
|
16
|
+
selectAPIError(state, HOST_PACKAGES_KEY);
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { Route, Switch, Redirect } from 'react-router-dom';
|
3
|
+
import { PackagesTab } from '../PackagesTab';
|
3
4
|
import { ErrataTab } from '../ErrataTab';
|
4
5
|
import { route } from './helpers';
|
5
6
|
|
@@ -8,6 +9,9 @@ const SecondaryTabRoutes = () => (
|
|
8
9
|
<Route exact path="/Content">
|
9
10
|
<Redirect to={route('errata')} />
|
10
11
|
</Route>
|
12
|
+
<Route path={route('packages')}>
|
13
|
+
<PackagesTab />
|
14
|
+
</Route>
|
11
15
|
<Route path={route('errata')}>
|
12
16
|
<ErrataTab />
|
13
17
|
</Route>
|
@@ -18,7 +18,6 @@ import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors';
|
|
18
18
|
import IsoDate from 'foremanReact/components/common/dates/IsoDate';
|
19
19
|
import { urlBuilder } from 'foremanReact/common/urlHelpers';
|
20
20
|
import { propsToCamelCase } from 'foremanReact/common/helpers';
|
21
|
-
import { isEmpty } from 'lodash';
|
22
21
|
import SelectableDropdown from '../../../SelectableDropdown';
|
23
22
|
import { useSet, useBulkSelect } from '../../../../components/Table/TableHooks';
|
24
23
|
import TableWrapper from '../../../../components/Table/TableWrapper';
|
@@ -28,12 +27,15 @@ import ErratumExpansionDetail from './ErratumExpansionDetail';
|
|
28
27
|
import ErratumExpansionContents from './ErratumExpansionContents';
|
29
28
|
import { selectHostErrataStatus } from '../HostErrata/HostErrataSelectors';
|
30
29
|
import { HOST_ERRATA_KEY, ERRATA_TYPES, ERRATA_SEVERITIES, TYPES_TO_PARAM, SEVERITIES_TO_PARAM } from '../HostErrata/HostErrataConstants';
|
30
|
+
import { installErrata } from './RemoteExecutionActions';
|
31
|
+
import { errataInstallUrl } from './customizedRexUrlHelpers';
|
31
32
|
import './ErrataTab.scss';
|
32
33
|
|
33
34
|
export const ErrataTab = () => {
|
34
35
|
const hostDetails = useSelector(state => selectAPIResponse(state, 'HOST_DETAILS'));
|
35
36
|
const {
|
36
37
|
id: hostId,
|
38
|
+
name: hostname,
|
37
39
|
content_facet_attributes: contentFacetAttributes,
|
38
40
|
} = hostDetails;
|
39
41
|
const contentFacet = propsToCamelCase(contentFacetAttributes ?? {});
|
@@ -91,7 +93,7 @@ export const ErrataTab = () => {
|
|
91
93
|
const response = useSelector(state => selectAPIResponse(state, HOST_ERRATA_KEY));
|
92
94
|
const { results, ...metadata } = response;
|
93
95
|
const status = useSelector(state => selectHostErrataStatus(state));
|
94
|
-
|
96
|
+
const errataSearchQuery = id => `errata_id = ${id}`;
|
95
97
|
const {
|
96
98
|
selectOne, isSelected, searchQuery, selectedCount, isSelectable,
|
97
99
|
updateSearchQuery, selectNone, fetchBulkParams, ...selectAll
|
@@ -104,38 +106,99 @@ export const ErrataTab = () => {
|
|
104
106
|
|
105
107
|
if (!hostId) return <Skeleton />;
|
106
108
|
|
107
|
-
const
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
109
|
+
const applyErratumViaRemoteExecution = id => dispatch(installErrata({
|
110
|
+
hostname,
|
111
|
+
search: errataSearchQuery(id),
|
112
|
+
}));
|
113
|
+
|
114
|
+
const applyViaRemoteExecution = () => {
|
115
|
+
dispatch(installErrata({
|
116
|
+
hostname, search: fetchBulkParams(),
|
117
|
+
}));
|
118
|
+
|
119
|
+
const params = { page: metadata.page, per_page: metadata.per_page, search: metadata.search };
|
120
|
+
dispatch(getInstallableErrata(
|
121
|
+
hostId,
|
122
|
+
{ ...params, include_applicable: toggleGroupState === ALL },
|
123
|
+
));
|
124
|
+
};
|
125
|
+
|
126
|
+
const bulkCustomizedRexUrl = () => errataInstallUrl({
|
127
|
+
hostname, search: (selectedCount > 0) ? fetchBulkParams() : '',
|
128
|
+
});
|
118
129
|
|
119
130
|
const recalculateErrata = () => {
|
120
131
|
setIsBulkActionOpen(false);
|
121
132
|
dispatch(regenerateApplicability(hostId));
|
122
133
|
};
|
123
134
|
|
135
|
+
const applyByKatelloAgent = () => {
|
136
|
+
const selected = fetchBulkParams();
|
137
|
+
setIsBulkActionOpen(false);
|
138
|
+
selectNone();
|
139
|
+
dispatch(applyViaKatelloAgent(hostId, { search: selected }));
|
140
|
+
};
|
141
|
+
|
142
|
+
const applyErratumViaKatelloAgent = id => dispatch(applyViaKatelloAgent(
|
143
|
+
hostId,
|
144
|
+
{ errata_ids: [id] },
|
145
|
+
));
|
146
|
+
|
147
|
+
const katelloAgentAvailable = (contentFacet.katelloAgentInstalled &&
|
148
|
+
contentFacet.katelloAgentEnabled);
|
149
|
+
const apply = () => {
|
150
|
+
if (contentFacet.remoteExecutionByDefault || !katelloAgentAvailable) {
|
151
|
+
applyViaRemoteExecution();
|
152
|
+
} else {
|
153
|
+
applyByKatelloAgent();
|
154
|
+
}
|
155
|
+
};
|
156
|
+
|
124
157
|
const dropdownItems = [
|
125
|
-
<DropdownItem
|
158
|
+
<DropdownItem
|
159
|
+
aria-label="bulk_add"
|
160
|
+
key="bulk_add"
|
161
|
+
component="button"
|
162
|
+
onClick={recalculateErrata}
|
163
|
+
>
|
126
164
|
{__('Recalculate')}
|
127
165
|
</DropdownItem>,
|
128
166
|
];
|
129
167
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
168
|
+
if (katelloAgentAvailable) {
|
169
|
+
dropdownItems.push((
|
170
|
+
<DropdownItem
|
171
|
+
aria-label="apply_via_katello_agent"
|
172
|
+
key="apply_via_katello_agent"
|
173
|
+
component="button"
|
174
|
+
onClick={applyByKatelloAgent}
|
175
|
+
isDisabled={selectedCount === 0}
|
176
|
+
>
|
177
|
+
{__('Apply via Katello agent')}
|
178
|
+
</DropdownItem>));
|
179
|
+
}
|
180
|
+
|
181
|
+
dropdownItems.push((
|
182
|
+
<DropdownItem
|
183
|
+
aria-label="apply_via_remote_execution"
|
184
|
+
key="apply_via_remote_execution"
|
185
|
+
component="button"
|
186
|
+
onClick={applyViaRemoteExecution}
|
187
|
+
isDisabled={selectedCount === 0}
|
188
|
+
>
|
189
|
+
{__('Apply via remote execution')}
|
190
|
+
</DropdownItem>));
|
191
|
+
|
192
|
+
dropdownItems.push((
|
193
|
+
<DropdownItem
|
194
|
+
aria-label="apply_via_customized_remote_execution"
|
195
|
+
key="apply_via_customized_remote_execution"
|
196
|
+
component="a"
|
197
|
+
href={bulkCustomizedRexUrl()}
|
198
|
+
isDisabled={selectedCount === 0}
|
199
|
+
>
|
200
|
+
{__('Apply via customized remote execution')}
|
201
|
+
</DropdownItem>));
|
139
202
|
|
140
203
|
const handleErrataTypeSelected = newType => setErrataTypeSelected((prevType) => {
|
141
204
|
if (prevType === newType) {
|
@@ -157,7 +220,7 @@ export const ErrataTab = () => {
|
|
157
220
|
<SplitItem>
|
158
221
|
<ActionList isIconList>
|
159
222
|
<ActionListItem>
|
160
|
-
<Button isDisabled={selectedCount === 0} onClick={
|
223
|
+
<Button isDisabled={selectedCount === 0} onClick={apply}> {__('Apply')} </Button>
|
161
224
|
</ActionListItem>
|
162
225
|
<ActionListItem>
|
163
226
|
<Dropdown
|
@@ -259,7 +322,7 @@ export const ErrataTab = () => {
|
|
259
322
|
<Th key="select-all" />
|
260
323
|
{columnHeaders.map(col =>
|
261
324
|
<Th key={col}>{col}</Th>)}
|
262
|
-
<Th />
|
325
|
+
<Th key="action-menu" />
|
263
326
|
</Tr>
|
264
327
|
</Thead>
|
265
328
|
<>
|
@@ -273,6 +336,36 @@ export const ErrataTab = () => {
|
|
273
336
|
installable: isInstallable,
|
274
337
|
} = erratum;
|
275
338
|
const isExpanded = erratumIsExpanded(id);
|
339
|
+
let rowActions;
|
340
|
+
if (isInstallable) {
|
341
|
+
rowActions = [
|
342
|
+
{
|
343
|
+
title: __('Apply via remote execution'),
|
344
|
+
onClick: () => applyErratumViaRemoteExecution(errataId),
|
345
|
+
},
|
346
|
+
{
|
347
|
+
title: __('Apply via customized remote execution'),
|
348
|
+
component: 'a',
|
349
|
+
href: errataInstallUrl({ hostname, search: errataSearchQuery(errataId) }),
|
350
|
+
},
|
351
|
+
];
|
352
|
+
|
353
|
+
if (contentFacet.katelloAgentInstalled && contentFacet.katelloAgentEnabled) {
|
354
|
+
rowActions.unshift({
|
355
|
+
title: __('Apply via Katello agent'),
|
356
|
+
onClick: () => applyErratumViaKatelloAgent(errataId),
|
357
|
+
});
|
358
|
+
}
|
359
|
+
} else {
|
360
|
+
rowActions = [
|
361
|
+
{
|
362
|
+
title: __('Apply Erratum'),
|
363
|
+
component: 'a',
|
364
|
+
href: urlBuilder(`errata/${id}/content-hosts`, ''),
|
365
|
+
},
|
366
|
+
];
|
367
|
+
}
|
368
|
+
|
276
369
|
return (
|
277
370
|
<Tbody isExpanded={isExpanded} key={`${id}_${createdAt}`}>
|
278
371
|
<Tr>
|
@@ -319,6 +412,7 @@ export const ErrataTab = () => {
|
|
319
412
|
actions={{
|
320
413
|
items: rowActions,
|
321
414
|
}}
|
415
|
+
|
322
416
|
/>
|
323
417
|
</Tr>
|
324
418
|
<Tr key="child_row" isExpanded={isExpanded}>
|
@@ -0,0 +1,127 @@
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
2
|
+
import { useSelector } from 'react-redux';
|
3
|
+
import { Button, Hint, HintBody } from '@patternfly/react-core';
|
4
|
+
import { TableVariant, Thead, Tbody, Tr, Th, Td } from '@patternfly/react-table';
|
5
|
+
import { translate as __ } from 'foremanReact/common/I18n';
|
6
|
+
import { selectAPIResponse } from 'foremanReact/redux/API/APISelectors';
|
7
|
+
|
8
|
+
import { urlBuilder } from 'foremanReact/common/urlHelpers';
|
9
|
+
import TableWrapper from '../../../../components/Table/TableWrapper';
|
10
|
+
import { PackagesStatus, PackagesLatestVersion } from '../../../../components/Packages';
|
11
|
+
import { getInstalledPackagesWithLatest } from '../HostPackages/HostPackagesActions';
|
12
|
+
import { selectHostPackagesStatus } from '../HostPackages/HostPackagesSelectors';
|
13
|
+
import { HOST_PACKAGES_KEY } from '../HostPackages/HostPackagesConstants';
|
14
|
+
import './PackagesTab.scss';
|
15
|
+
|
16
|
+
export const PackagesTab = () => {
|
17
|
+
const hostDetails = useSelector(state => selectAPIResponse(state, 'HOST_DETAILS'));
|
18
|
+
const { id: hostId } = hostDetails;
|
19
|
+
const actionButtons = <Button isDisabled> {__('Upgrade')} </Button>;
|
20
|
+
|
21
|
+
const [searchQuery, updateSearchQuery] = useState('');
|
22
|
+
|
23
|
+
const emptyContentTitle = __('This host does not have any packages.');
|
24
|
+
const emptyContentBody = __('Packages will appear here when available.');
|
25
|
+
const emptySearchTitle = __('No matching packages found');
|
26
|
+
const emptySearchBody = __('Try changing your search settings.');
|
27
|
+
const columnHeaders = [
|
28
|
+
__('Package'),
|
29
|
+
__('Status'),
|
30
|
+
__('Installed Version'),
|
31
|
+
__('Upgradable To'),
|
32
|
+
];
|
33
|
+
|
34
|
+
const fetchItems = useCallback(
|
35
|
+
params => (hostId ? getInstalledPackagesWithLatest(hostId, params) : null),
|
36
|
+
[hostId],
|
37
|
+
);
|
38
|
+
|
39
|
+
const response = useSelector(state => selectAPIResponse(state, HOST_PACKAGES_KEY));
|
40
|
+
const { results, ...metadata } = response;
|
41
|
+
const status = useSelector(state => selectHostPackagesStatus(state));
|
42
|
+
const rowActions = [
|
43
|
+
{
|
44
|
+
title: __('Upgrade via remote execution'), disabled: true,
|
45
|
+
},
|
46
|
+
{
|
47
|
+
title: __('Upgrade via customized remote execution'), disabled: true,
|
48
|
+
},
|
49
|
+
];
|
50
|
+
|
51
|
+
return (
|
52
|
+
<div>
|
53
|
+
<div id="packages-hint">
|
54
|
+
<Hint>
|
55
|
+
<HintBody>
|
56
|
+
{__('Packages management functionality on this page is incomplete')}.
|
57
|
+
<br />
|
58
|
+
<Button component="a" variant="link" isInline href={urlBuilder(`content_hosts/${hostId}/packages/installed`, '')}>
|
59
|
+
{__('Visit the previous Packages page')}.
|
60
|
+
</Button>
|
61
|
+
</HintBody>
|
62
|
+
</Hint>
|
63
|
+
</div>
|
64
|
+
<div id="packages-tab">
|
65
|
+
<TableWrapper
|
66
|
+
{...{
|
67
|
+
metadata,
|
68
|
+
emptyContentTitle,
|
69
|
+
emptyContentBody,
|
70
|
+
emptySearchTitle,
|
71
|
+
emptySearchBody,
|
72
|
+
status,
|
73
|
+
actionButtons,
|
74
|
+
searchQuery,
|
75
|
+
updateSearchQuery,
|
76
|
+
}
|
77
|
+
}
|
78
|
+
additionalListeners={[hostId]}
|
79
|
+
fetchItems={fetchItems}
|
80
|
+
autocompleteEndpoint={`/hosts/${hostId}/packages/auto_complete_search`}
|
81
|
+
foremanApiAutoComplete
|
82
|
+
variant={TableVariant.compact}
|
83
|
+
>
|
84
|
+
<Thead>
|
85
|
+
<Tr>
|
86
|
+
{columnHeaders.map(col =>
|
87
|
+
<Th key={col}>{col}</Th>)}
|
88
|
+
<Th />
|
89
|
+
</Tr>
|
90
|
+
</Thead>
|
91
|
+
<Tbody>
|
92
|
+
{results?.map((packages) => {
|
93
|
+
const {
|
94
|
+
id,
|
95
|
+
name: packageName,
|
96
|
+
nvra: installedVersion,
|
97
|
+
rpm_id: rpmId,
|
98
|
+
} = packages;
|
99
|
+
return (
|
100
|
+
<Tr key={`${id}`}>
|
101
|
+
<Td>
|
102
|
+
{rpmId
|
103
|
+
? <a href={urlBuilder(`packages/${rpmId}`, '')}>{packageName}</a>
|
104
|
+
: packageName
|
105
|
+
}
|
106
|
+
</Td>
|
107
|
+
<Td><PackagesStatus {...packages} /></Td>
|
108
|
+
<Td>{installedVersion.replace(`${packageName}-`, '')}</Td>
|
109
|
+
<Td><PackagesLatestVersion {...packages} /></Td>
|
110
|
+
<Td
|
111
|
+
key={`rowActions-${id}`}
|
112
|
+
actions={{
|
113
|
+
items: rowActions,
|
114
|
+
}}
|
115
|
+
/>
|
116
|
+
</Tr>
|
117
|
+
);
|
118
|
+
})
|
119
|
+
}
|
120
|
+
</Tbody>
|
121
|
+
</TableWrapper>
|
122
|
+
</div>
|
123
|
+
</div>
|
124
|
+
);
|
125
|
+
};
|
126
|
+
|
127
|
+
export default PackagesTab;
|