katello 4.7.0 → 4.7.1

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.

Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/katello/api/v2/alternate_content_sources_controller.rb +4 -1
  3. data/app/controllers/katello/concerns/api/v2/registration_controller_extensions.rb +0 -1
  4. data/app/lib/katello/util/candlepin_repository_checker.rb +2 -0
  5. data/app/models/katello/concerns/host_managed_extensions.rb +4 -2
  6. data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -1
  7. data/app/models/katello/content.rb +1 -1
  8. data/app/models/katello/glue/provider.rb +1 -1
  9. data/app/services/katello/product_content_importer.rb +61 -5
  10. data/lib/katello/engine.rb +1 -0
  11. data/lib/katello/version.rb +1 -1
  12. data/locale/action_names.rb +69 -69
  13. data/locale/bn/katello.po +23 -20
  14. data/locale/cs/katello.po +23 -20
  15. data/locale/de/katello.po +25 -22
  16. data/locale/en/katello.po +23 -20
  17. data/locale/es/katello.po +335 -332
  18. data/locale/fr/katello.po +704 -695
  19. data/locale/gu/katello.po +23 -20
  20. data/locale/hi/katello.po +23 -20
  21. data/locale/it/katello.po +23 -20
  22. data/locale/ja/katello.po +570 -561
  23. data/locale/ka/katello.po +2269 -2260
  24. data/locale/katello.pot +287 -279
  25. data/locale/kn/katello.po +23 -20
  26. data/locale/ko/katello.po +57 -53
  27. data/locale/mr/katello.po +23 -20
  28. data/locale/or/katello.po +23 -20
  29. data/locale/pa/katello.po +23 -20
  30. data/locale/pt/katello.po +23 -20
  31. data/locale/pt_BR/katello.po +441 -438
  32. data/locale/ru/katello.po +23 -20
  33. data/locale/ta/katello.po +23 -20
  34. data/locale/te/katello.po +23 -20
  35. data/locale/zh_CN/katello.po +694 -687
  36. data/locale/zh_TW/katello.po +23 -20
  37. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ChangeHostCVModal.js +5 -11
  38. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/changeHostCVModal.test.js +2 -2
  39. data/webpack/components/extensions/HostDetails/DetailsTabCards/RegistrationCard.js +1 -1
  40. data/webpack/components/extensions/HostDetails/DetailsTabCards/SystemPropertiesCardExtensions.js +58 -1
  41. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +5 -1
  42. data/webpack/global_index.js +2 -0
  43. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignActivationKeysForm.js +10 -10
  44. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignHostsForm.js +10 -10
  45. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +5 -5
  46. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignActivationKeys.js +9 -10
  47. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignHosts.js +13 -10
  48. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignActivationKeysForm.js +18 -18
  49. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignHostsForm.js +10 -6
  50. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +6 -6
  51. data/webpack/scenes/ContentViews/components/ContentViewSelect/ContentViewSelect.js +40 -0
  52. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +0 -1
  53. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +16 -2
  54. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +13 -17
  55. data/webpack/scenes/Hosts/ChangeContentSource/index.js +79 -39
  56. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +6 -2
  57. metadata +3 -2
@@ -10,7 +10,7 @@
10
10
  #
11
11
  msgid ""
12
12
  msgstr ""
13
- "Project-Id-Version: katello 2.4.0-RC1\n"
13
+ "Project-Id-Version: katello 4.7.0\n"
14
14
  "Report-Msgid-Bugs-To: \n"
15
15
  "PO-Revision-Date: 2017-12-19 20:14+0000\n"
16
16
  "Last-Translator: Bryan Kearney <bryan.kearney@gmail.com>, 2022\n"
@@ -1215,7 +1215,7 @@ msgstr ""
1215
1215
  msgid "Cannot set auto publish to a non-composite content view"
1216
1216
  msgstr ""
1217
1217
 
1218
- msgid "Cannot skip metadata check on non-yum repositories."
1218
+ msgid "Cannot skip metadata check on non-yum/deb repositories."
1219
1219
  msgstr ""
1220
1220
 
1221
1221
  msgid "Cannot specify components for non-composite views"
@@ -1530,9 +1530,6 @@ msgstr ""
1530
1530
  msgid "Content source ID"
1531
1531
  msgstr ""
1532
1532
 
1533
- msgid "Content source successfully updated."
1534
- msgstr ""
1535
-
1536
1533
  msgid "Content source was not set for host '%{host}'"
1537
1534
  msgstr ""
1538
1535
 
@@ -2726,7 +2723,7 @@ msgstr ""
2726
2723
  msgid "Force sync even if no upstream changes are detected. Non-yum repositories are skipped."
2727
2724
  msgstr ""
2728
2725
 
2729
- msgid "Force sync even if no upstream changes are detected. Only used with yum repositories."
2726
+ msgid "Force sync even if no upstream changes are detected. Only used with yum or deb repositories."
2730
2727
  msgstr ""
2731
2728
 
2732
2729
  msgid "Forces a republish of the specified repository, regenerating metadata and symlinks on the filesystem."
@@ -2906,6 +2903,9 @@ msgstr ""
2906
2903
  msgid "Host collections updated"
2907
2904
  msgstr ""
2908
2905
 
2906
+ msgid "Host configurations are not updated yet"
2907
+ msgstr ""
2908
+
2909
2909
  msgid "Host content and subscription details"
2910
2910
  msgstr "主機內容和訂閱詳細資料"
2911
2911
 
@@ -3170,6 +3170,9 @@ msgstr ""
3170
3170
  msgid "Ignorable content can be only set for Yum repositories."
3171
3171
  msgstr ""
3172
3172
 
3173
+ msgid "Ignore SRPMs can not be set in combination with 'Complete Mirroring' mirroring policy."
3174
+ msgstr ""
3175
+
3173
3176
  msgid "Ignore errors"
3174
3177
  msgstr ""
3175
3178
 
@@ -4370,13 +4373,16 @@ msgstr "找不到主機集項目。"
4370
4373
  msgid "No host collections yet"
4371
4374
  msgstr ""
4372
4375
 
4376
+ msgid "No hosts found"
4377
+ msgstr ""
4378
+
4373
4379
  msgid "No hosts have been specified."
4374
4380
  msgstr "未指定主機。"
4375
4381
 
4376
4382
  msgid "No hosts registered with subscription-manager found in selection."
4377
4383
  msgstr ""
4378
4384
 
4379
- msgid "No hosts with content source found!"
4385
+ msgid "No hosts were specified"
4380
4386
  msgstr ""
4381
4387
 
4382
4388
  msgid "No installed packages and/or enabled repositories have been reported by %s."
@@ -5872,9 +5878,6 @@ msgstr ""
5872
5878
  msgid "Run Sync Plan:"
5873
5879
  msgstr ""
5874
5880
 
5875
- msgid "Run job invocation"
5876
- msgstr ""
5877
-
5878
5881
  msgid "Running"
5879
5882
  msgstr "執行中"
5880
5883
 
@@ -7106,7 +7109,7 @@ msgstr ""
7106
7109
  msgid "This organization has Simple Content Access enabled. Hosts are not required to have subscriptions attached to access repositories. {br} Learn more about your overall subscription usage with the {subscriptionsService}."
7107
7110
  msgstr ""
7108
7111
 
7109
- msgid "This organization is not using {scaLink}. Entitlement-based subscription management is deprecated and will be removed in a future version."
7112
+ msgid "This organization is not using {scaLink}. Legacy subscription management is deprecated and will be removed in a future version."
7110
7113
  msgstr ""
7111
7114
 
7112
7115
  msgid "This repository is not suggested. Please see additional %(anchorBegin)sdocumentation%(anchorEnd)s prior to use."
@@ -7160,6 +7163,12 @@ msgstr "提示"
7160
7163
  msgid "To get started, add this host to a host collection."
7161
7164
  msgstr ""
7162
7165
 
7166
+ msgid "To update the selected host configuration, update hosts manually in the next section."
7167
+ msgstr ""
7168
+
7169
+ msgid "To update the selected host configuration, {link}, or update hosts manually in the next section."
7170
+ msgstr ""
7171
+
7163
7172
  msgid "Toggling Simple Content Access will refresh your manifest."
7164
7173
  msgstr ""
7165
7174
 
@@ -7808,9 +7817,6 @@ msgstr ""
7808
7817
  msgid "Warning"
7809
7818
  msgstr "警告"
7810
7819
 
7811
- msgid "What's next?"
7812
- msgstr ""
7813
-
7814
7820
  msgid "When \"Releases/Distributions\" is set, \"Upstream URL\" must also be set!"
7815
7821
  msgstr ""
7816
7822
 
@@ -8651,6 +8657,9 @@ msgstr "單一資源回應的根節點(選用)"
8651
8657
  msgid "rule identifier"
8652
8658
  msgstr "規則識別子"
8653
8659
 
8660
+ msgid "run job invocation"
8661
+ msgstr ""
8662
+
8654
8663
  msgid "service level"
8655
8664
  msgstr "服務等級"
8656
8665
 
@@ -8705,9 +8714,6 @@ msgstr "Red Hat 供應者的以下屬性可以更新:[ %s ]"
8705
8714
  msgid "to"
8706
8715
  msgstr ""
8707
8716
 
8708
- msgid "to update configuration on all hosts, or"
8709
- msgstr ""
8710
-
8711
8717
  msgid "true if the latest version of the component's content view is desired"
8712
8718
  msgstr ""
8713
8719
 
@@ -8735,9 +8741,6 @@ msgstr ""
8735
8741
  msgid "update a filter"
8736
8742
  msgstr "更新篩選器"
8737
8743
 
8738
- msgid "update configuration on the hosts manually:"
8739
- msgstr ""
8740
-
8741
8744
  msgid "updating package group..."
8742
8745
  msgstr "正在更新套件群組..."
8743
8746
 
@@ -2,7 +2,7 @@ import React, { useState, useCallback } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { FormattedMessage } from 'react-intl';
4
4
  import { useDispatch, useSelector } from 'react-redux';
5
- import { Modal, Button, Select, SelectOption, Alert, Flex } from '@patternfly/react-core';
5
+ import { Modal, Button, SelectOption, Alert, Flex } from '@patternfly/react-core';
6
6
  import {
7
7
  global_palette_black_600 as pfDescriptionColor,
8
8
  } from '@patternfly/react-tokens';
@@ -20,6 +20,7 @@ import ContentViewIcon from '../../../../../scenes/ContentViews/components/Conte
20
20
  import updateHostContentViewAndEnvironment from './HostContentViewActions';
21
21
  import HOST_CV_AND_ENV_KEY from './HostContentViewConstants';
22
22
  import { getHostDetails } from '../../HostDetailsActions';
23
+ import ContentViewSelect from '../../../../../scenes/ContentViews/components/ContentViewSelect/ContentViewSelect';
23
24
 
24
25
  const ENV_PATH_OPTIONS = { key: ENVIRONMENT_PATHS_KEY };
25
26
 
@@ -183,19 +184,13 @@ const ChangeHostCVModal = ({
183
184
  isDisabled={hostUpdateStatus === STATUS.PENDING}
184
185
  />
185
186
  {selectedEnvForHost.length > 0 &&
186
- <div style={{ marginTop: '1em' }}>
187
- <h3>{__('Select content view')}</h3>
188
- <Select
187
+ <ContentViewSelect
189
188
  selections={selectedCVForHost}
189
+ onClear={() => setSelectedCVForHost(null)}
190
190
  onSelect={handleCVSelect}
191
191
  isOpen={cvSelectOpen}
192
- menuAppendTo="parent"
193
192
  isDisabled={contentViewsInEnv.length === 0 || hostUpdateStatus === STATUS.PENDING}
194
193
  onToggle={isExpanded => setCVSelectOpen(isExpanded)}
195
- ouiaId="select-content-view"
196
- id="selectCV"
197
- name="selectCV"
198
- aria-label="selectCV"
199
194
  placeholderText={cvPlaceholderText()}
200
195
  >
201
196
  {contentViewsInEnv?.map(cv => (
@@ -227,8 +222,7 @@ const ChangeHostCVModal = ({
227
222
  </SelectOption>
228
223
  ))
229
224
  }
230
- </Select>
231
- </div>
225
+ </ContentViewSelect>
232
226
  }
233
227
  </Modal>
234
228
  );
@@ -86,7 +86,7 @@ test('Select an env > call CV API > select a CV > Save button is enabled', async
86
86
 
87
87
  const {
88
88
  getAllByText, getByText,
89
- findByText, getAllByRole,
89
+ findByPlaceholderText, getAllByRole,
90
90
  } = renderWithRedux(<ChangeHostCVModal
91
91
  isOpen
92
92
  closeModal={jest.fn()}
@@ -107,7 +107,7 @@ test('Select an env > call CV API > select a CV > Save button is enabled', async
107
107
  await act(async () => {
108
108
  userEvent.click(envRadio); // Select the Library environment
109
109
 
110
- const cvDropdown = await findByText('Select a content view');
110
+ const cvDropdown = await findByPlaceholderText('Select a content view');
111
111
  expect(cvDropdown).toBeInTheDocument();
112
112
 
113
113
  userEvent.click(cvDropdown); // Open the CV dropdown
@@ -77,7 +77,7 @@ const RegistrationCard = ({ isExpandedGlobal, hostDetails }) => {
77
77
  <RegisteredBy user={login} activationKeys={activationKeys} />
78
78
  </DescriptionListGroup>
79
79
  <DescriptionListGroup>
80
- <DescriptionListTerm>{__('Registered through')}</DescriptionListTerm>
80
+ <DescriptionListTerm>{__('Content source')}</DescriptionListTerm>
81
81
  <DescriptionListDescription>{registeredThrough}</DescriptionListDescription>
82
82
  </DescriptionListGroup>
83
83
  </DescriptionList>
@@ -5,8 +5,10 @@ import {
5
5
  DescriptionListTerm,
6
6
  DescriptionListDescription,
7
7
  ClipboardCopy,
8
+ Label,
8
9
  } from '@patternfly/react-core';
9
- import { translate as __ } from 'foremanReact/common/I18n';
10
+ import { sprintf, translate as __ } from 'foremanReact/common/I18n';
11
+ import { propsToCamelCase } from 'foremanReact/common/helpers';
10
12
 
11
13
  export const SystemPropertiesCardSubscription = ({ hostDetails }) => {
12
14
  const subscriptionUuid = hostDetails?.subscription_facet_attributes?.uuid;
@@ -35,6 +37,61 @@ SystemPropertiesCardSubscription.defaultProps = {
35
37
  hostDetails: {},
36
38
  };
37
39
 
40
+ export const SystemPropertiesCardVirtualization = ({ hostDetails }) => {
41
+ if (!hostDetails?.subscription_facet_attributes) return null;
42
+
43
+ const {
44
+ virtualGuests,
45
+ hypervisor,
46
+ virtualHost,
47
+ } = propsToCamelCase(hostDetails.subscription_facet_attributes);
48
+ const virtualGuestIds = `name ^ (${virtualGuests.map(guest => guest.name).join(', ')})`;
49
+
50
+ return (
51
+ <>
52
+ {hypervisor &&
53
+ <DescriptionListGroup>
54
+ <DescriptionListTerm>{__('Virtual guests')}</DescriptionListTerm>
55
+ <DescriptionListDescription>
56
+ <a href={`/hosts?search=${encodeURI(virtualGuestIds)}`}>
57
+ <Label color="blue" className="virtual-guests-label">
58
+ {sprintf(__('%s guests'), virtualGuests.length)}
59
+ </Label>
60
+ </a>
61
+ </DescriptionListDescription>
62
+ </DescriptionListGroup>
63
+ }
64
+ {virtualHost &&
65
+ <DescriptionListGroup>
66
+ <DescriptionListTerm>{__('Virtual host')}</DescriptionListTerm>
67
+ <DescriptionListDescription>
68
+ <a href={`/new/hosts/${virtualHost.name}`}>
69
+ {virtualHost.name}
70
+ </a>
71
+ </DescriptionListDescription>
72
+ </DescriptionListGroup>
73
+ }
74
+ </>
75
+ );
76
+ };
77
+
78
+ SystemPropertiesCardVirtualization.propTypes = {
79
+ hostDetails: PropTypes.shape({
80
+ subscription_facet_attributes: PropTypes.shape({
81
+ virtual_guests: PropTypes.arrayOf(PropTypes.shape({})),
82
+ hypervisor: PropTypes.bool,
83
+ virtual_host: PropTypes.shape({
84
+ id: PropTypes.number,
85
+ name: PropTypes.string,
86
+ }),
87
+ }),
88
+ }),
89
+ };
90
+
91
+ SystemPropertiesCardVirtualization.defaultProps = {
92
+ hostDetails: {},
93
+ };
94
+
38
95
  export const SystemPropertiesCardTracer = ({ hostDetails }) => {
39
96
  const tracerStatus = hostDetails?.content_facet_attributes?.katello_tracer_installed;
40
97
  return (
@@ -46,9 +46,13 @@ import {
46
46
  userPermissionsFromHostDetails,
47
47
  } from '../../hostDetailsHelpers';
48
48
 
49
+ const moduleStreamSupported = ({ os, version }) =>
50
+ os.match(/RedHat|RHEL|CentOS|Rocky|AlmaLinux|OracleLinux/i) && Number(version) > 7;
49
51
  export const hideModuleStreamsTab = ({ hostDetails }) => {
50
52
  const osMatch = hostDetails?.operatingsystem_name?.match(/(\w+) (\d+)/);
51
- return !(osMatch && osMatch[1].match(/RedHat|CentOS/i) && Number(osMatch[2]) > 7);
53
+ if (!osMatch) return true;
54
+ const [, os, version] = osMatch;
55
+ return !(osMatch && moduleStreamSupported({ os, version }));
52
56
  };
53
57
 
54
58
  const EnabledIcon = ({ streamText, streamInstallStatus, upgradable }) => {
@@ -22,6 +22,7 @@ import HostCollectionsCard from './components/extensions/HostDetails/Cards/HostC
22
22
  import { hostIsNotRegistered } from './components/extensions/HostDetails/hostDetailsHelpers';
23
23
  import {
24
24
  SystemPropertiesCardSubscription,
25
+ SystemPropertiesCardVirtualization,
25
26
  SystemPropertiesCardTracer,
26
27
  } from './components/extensions/HostDetails/DetailsTabCards/SystemPropertiesCardExtensions';
27
28
  import HostActionsBar from './components/extensions/HostDetails/ActionsBar';
@@ -61,6 +62,7 @@ addGlobalFill('host-tab-details-cards', 'Installed products', <InstalledProducts
61
62
  addGlobalFill('host-tab-details-cards', 'Registration details', <RegistrationCard key="registration-details" />, 200);
62
63
  addGlobalFill('host-details-tab-properties-1', 'Subscription UUID', <SystemPropertiesCardSubscription key="subscription-uuid" />);
63
64
  addGlobalFill('host-details-tab-properties-2', 'Tracer', <SystemPropertiesCardTracer key="tracer-status" />);
65
+ addGlobalFill('host-details-tab-properties-3', 'Virtualization', <SystemPropertiesCardVirtualization key="virtualization" />);
64
66
 
65
67
  addGlobalFill(
66
68
  'host-details-kebab',
@@ -1,7 +1,7 @@
1
1
  import React, { useContext, useState } from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
  import useDeepCompareEffect from 'use-deep-compare-effect';
4
- import { ExpandableSection, Select, SelectOption } from '@patternfly/react-core';
4
+ import { ExpandableSection, SelectOption } from '@patternfly/react-core';
5
5
  import { translate as __ } from 'foremanReact/common/I18n';
6
6
  import { STATUS } from 'foremanReact/constants';
7
7
  import getContentViews from '../../ContentViewsActions';
@@ -9,6 +9,7 @@ import { selectContentViewError, selectContentViews, selectContentViewStatus } f
9
9
  import CVDeleteContext from '../CVDeleteContext';
10
10
  import EnvironmentPaths from '../../components/EnvironmentPaths/EnvironmentPaths';
11
11
  import AffectedActivationKeys from '../../Details/Versions/Delete/affectedActivationKeys';
12
+ import ContentViewSelect from '../../components/ContentViewSelect/ContentViewSelect';
12
13
 
13
14
  const CVDeletionReassignActivationKeysForm = () => {
14
15
  const dispatch = useDispatch();
@@ -66,6 +67,11 @@ const CVDeletionReassignActivationKeysForm = () => {
66
67
  return results?.filter(cv => cv.id === id)[0]?.name;
67
68
  };
68
69
 
70
+ const onClear = () => {
71
+ setSelectedCVForAK(null);
72
+ setSelectedCVNameForAK(null);
73
+ };
74
+
69
75
  const onSelect = (_event, selection) => {
70
76
  setSelectedCVForAK(selection);
71
77
  setSelectedCVNameForAK(fetchSelectedCVName(selection));
@@ -82,23 +88,17 @@ const CVDeletionReassignActivationKeysForm = () => {
82
88
  multiSelect={false}
83
89
  />
84
90
  {!cvInEnvLoading && selectedEnvForAK.length > 0 &&
85
- <div style={{ marginTop: '1em' }}>
86
- <h3>{__('Select content view')}</h3>
87
- <Select
91
+ <ContentViewSelect
88
92
  selections={selectedCVForAK}
89
93
  onSelect={onSelect}
94
+ onClear={onClear}
90
95
  isOpen={cvSelectOpen}
91
96
  isDisabled={cvSelectOptions.length === 0}
92
97
  onToggle={isExpanded => setCVSelectOpen(isExpanded)}
93
- id="selectCV"
94
- name="selectCV"
95
- aria-label="selectCV"
96
- ouiaId="selectCV"
97
98
  placeholderText={(cvSelectOptions.length === 0) ? __('No content views available') : __('Select a content view')}
98
99
  >
99
100
  {cvSelectOptions}
100
- </Select>
101
- </div>
101
+ </ContentViewSelect>
102
102
  }
103
103
  <ExpandableSection
104
104
  toggleText={showActivationKeys ?
@@ -1,7 +1,7 @@
1
1
  import React, { useState, useContext } from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
  import useDeepCompareEffect from 'use-deep-compare-effect';
4
- import { ExpandableSection, Select, SelectOption } from '@patternfly/react-core';
4
+ import { ExpandableSection, SelectOption } from '@patternfly/react-core';
5
5
  import { translate as __ } from 'foremanReact/common/I18n';
6
6
  import { STATUS } from 'foremanReact/constants';
7
7
  import getContentViews from '../../ContentViewsActions';
@@ -9,6 +9,7 @@ import { selectContentViewError, selectContentViews, selectContentViewStatus } f
9
9
  import CVDeleteContext from '../CVDeleteContext';
10
10
  import EnvironmentPaths from '../../components/EnvironmentPaths/EnvironmentPaths';
11
11
  import AffectedHosts from '../../Details/Versions/Delete/affectedHosts';
12
+ import ContentViewSelect from '../../components/ContentViewSelect/ContentViewSelect';
12
13
 
13
14
 
14
15
  const CVDeletionReassignHostsForm = () => {
@@ -67,6 +68,11 @@ const CVDeletionReassignHostsForm = () => {
67
68
  return results?.filter(cv => cv.id === id)[0]?.name;
68
69
  };
69
70
 
71
+ const onClear = () => {
72
+ setSelectedCVForHosts(null);
73
+ setSelectedCVNameForHosts(null);
74
+ };
75
+
70
76
  const onSelect = (_event, selection) => {
71
77
  setSelectedCVForHosts(selection);
72
78
  setSelectedCVNameForHosts(fetchSelectedCVName(selection));
@@ -83,23 +89,17 @@ const CVDeletionReassignHostsForm = () => {
83
89
  multiSelect={false}
84
90
  />
85
91
  {selectedEnvForHost.length > 0 &&
86
- <div style={{ marginTop: '1em' }}>
87
- <h3>{__('Select content view')}</h3>
88
- <Select
92
+ <ContentViewSelect
89
93
  selections={selectedCVForHosts}
90
94
  onSelect={onSelect}
95
+ onClear={onClear}
91
96
  isOpen={cvSelectOpen}
92
97
  isDisabled={cvSelectOptions.length === 0}
93
98
  onToggle={isExpanded => setCVSelectOpen(isExpanded)}
94
- id="selectCV"
95
- name="selectCV"
96
- aria-label="selectCV"
97
- ouiaId="selectCV"
98
99
  placeholderText={(cvSelectOptions.length === 0) ? __('No content views available') : __('Select a content view')}
99
100
  >
100
101
  {cvSelectOptions}
101
- </Select>
102
- </div>
102
+ </ContentViewSelect>
103
103
  }
104
104
  <ExpandableSection
105
105
  toggleText={showHosts ? 'Hide hosts' : 'Show hosts'}
@@ -165,7 +165,7 @@ test('Can open Delete wizard and delete CV with all steps', async (done) => {
165
165
  .reply(200, cVDropDownOptionsData);
166
166
 
167
167
  const {
168
- getByText, getByLabelText, getAllByLabelText, getAllByText, queryByText,
168
+ getByText, getByLabelText, getAllByLabelText, getAllByText, queryByText, getByPlaceholderText,
169
169
  } =
170
170
  renderWithRedux(<ContentViewsPage />, renderOptions);
171
171
  expect(queryByText(firstCV.name)).toBeNull();
@@ -191,9 +191,9 @@ test('Can open Delete wizard and delete CV with all steps', async (done) => {
191
191
  fireEvent.click(getByLabelText('test1'));
192
192
  await patientlyWaitFor(() => {
193
193
  expect(getByText('Select content view')).toBeInTheDocument();
194
- expect(getByText('Select a content view')).toBeInTheDocument();
194
+ expect(getByPlaceholderText('Select a content view')).toBeInTheDocument();
195
195
  });
196
- fireEvent.click(getByText('Select a content view'));
196
+ fireEvent.click(getByPlaceholderText('Select a content view'));
197
197
  await patientlyWaitFor(() => {
198
198
  expect(getByText('cv2')).toBeInTheDocument();
199
199
  });
@@ -210,9 +210,9 @@ test('Can open Delete wizard and delete CV with all steps', async (done) => {
210
210
  fireEvent.click(getByLabelText('test1'));
211
211
  await patientlyWaitFor(() => {
212
212
  expect(getByText('Select content view')).toBeInTheDocument();
213
- expect(getByText('Select a content view')).toBeInTheDocument();
213
+ expect(getByPlaceholderText('Select a content view')).toBeInTheDocument();
214
214
  });
215
- fireEvent.click(getByText('Select a content view'));
215
+ fireEvent.click(getByPlaceholderText('Select a content view'));
216
216
  await patientlyWaitFor(() => {
217
217
  expect(getByText('cv2')).toBeInTheDocument();
218
218
  });
@@ -18,10 +18,8 @@ import {
18
18
  ExpandableSection,
19
19
  Popover,
20
20
  PopoverPosition,
21
- Select,
22
21
  SelectDirection,
23
22
  SelectOption,
24
- TextContent,
25
23
  } from '@patternfly/react-core';
26
24
  import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
27
25
 
@@ -39,6 +37,7 @@ import {
39
37
  getEnvironmentList,
40
38
  getNumberOfActivationKeys,
41
39
  } from '../BulkDeleteHelpers';
40
+ import ContentViewSelect from '../../../../components/ContentViewSelect/ContentViewSelect';
42
41
 
43
42
  export default () => {
44
43
  const dispatch = useDispatch();
@@ -107,6 +106,11 @@ export default () => {
107
106
  setSelectedEnvForAK(value);
108
107
  };
109
108
 
109
+ const onClear = () => {
110
+ setSelectedCVForAK(null);
111
+ setSelectedEnvForAK([]);
112
+ };
113
+
110
114
  const onSelect = (_event, selection) => {
111
115
  setSelectedCVForAK(selection);
112
116
  setToggleCVSelect(false);
@@ -170,16 +174,11 @@ export default () => {
170
174
  headerText={__('Select an environment')}
171
175
  multiSelect={false}
172
176
  />
173
- <TextContent>
174
- {__('Select a content view')}
175
- </TextContent>
176
- <Select
177
+ <ContentViewSelect
177
178
  selections={selectedCVForAK}
178
179
  onSelect={onSelect}
180
+ onClear={onClear}
179
181
  isDisabled={cvInEnvLoading || !selectOptions?.length || !selectedEnvForAK?.length}
180
- id="selectCV"
181
- name="selectCV"
182
- aria-label="selectCV"
183
182
  placeholderText={placeHolder}
184
183
  isOpen={toggleCVSelect}
185
184
  onToggle={setToggleCVSelect}
@@ -189,7 +188,7 @@ export default () => {
189
188
  width={350}
190
189
  >
191
190
  {selectOptions}
192
- </Select>
191
+ </ContentViewSelect>
193
192
  </>
194
193
  );
195
194
  };
@@ -18,10 +18,8 @@ import {
18
18
  ExpandableSection,
19
19
  Popover,
20
20
  PopoverPosition,
21
- Select,
22
21
  SelectDirection,
23
22
  SelectOption,
24
- TextContent,
25
23
  } from '@patternfly/react-core';
26
24
  import { OutlinedQuestionCircleIcon } from '@patternfly/react-icons';
27
25
 
@@ -40,6 +38,7 @@ import {
40
38
  getNumberOfActivationKeys,
41
39
  getNumberOfHosts,
42
40
  } from '../BulkDeleteHelpers';
41
+ import ContentViewSelect from '../../../../components/ContentViewSelect/ContentViewSelect';
43
42
 
44
43
  export default () => {
45
44
  const dispatch = useDispatch();
@@ -115,6 +114,15 @@ export default () => {
115
114
  }
116
115
  };
117
116
 
117
+ const onClear = () => {
118
+ setSelectedCVForHosts(null);
119
+ setSelectedEnvForHosts([]);
120
+ if (numberOfAKs) {
121
+ setSelectedCVForAK(null);
122
+ setSelectedEnvForAK([]);
123
+ }
124
+ };
125
+
118
126
  const onSelect = (_event, selection) => {
119
127
  setSelectedCVForHosts(selection);
120
128
  if (numberOfAKs) {
@@ -194,16 +202,11 @@ export default () => {
194
202
  headerText={__('Select an environment')}
195
203
  multiSelect={false}
196
204
  />
197
- <TextContent>
198
- {__('Select a content view')}
199
- </TextContent>
200
- <Select
205
+ <ContentViewSelect
201
206
  selections={selectedCVForHosts}
202
207
  onSelect={onSelect}
208
+ onClear={onClear}
203
209
  isDisabled={cvInEnvLoading || !selectOptions?.length || !selectedEnvForHosts?.length}
204
- id="selectCV"
205
- name="selectCV"
206
- aria-label="selectCV"
207
210
  placeholderText={placeHolder}
208
211
  isOpen={toggleCVSelect}
209
212
  onToggle={setToggleCVSelect}
@@ -213,7 +216,7 @@ export default () => {
213
216
  width={350}
214
217
  >
215
218
  {selectOptions}
216
- </Select>
219
+ </ContentViewSelect>
217
220
  </>
218
221
  );
219
222
  };
@@ -1,7 +1,7 @@
1
1
  import React, { useState, useContext } from 'react';
2
2
  import { useDispatch, useSelector } from 'react-redux';
3
3
  import useDeepCompareEffect from 'use-deep-compare-effect';
4
- import { ExpandableSection, Select, SelectOption } from '@patternfly/react-core';
4
+ import { ExpandableSection, SelectOption } from '@patternfly/react-core';
5
5
  import { STATUS } from 'foremanReact/constants';
6
6
  import { translate as __ } from 'foremanReact/common/I18n';
7
7
  import EnvironmentPaths from '../../../../components/EnvironmentPaths/EnvironmentPaths';
@@ -9,6 +9,7 @@ import getContentViews from '../../../../ContentViewsActions';
9
9
  import { selectContentViewError, selectContentViews, selectContentViewStatus } from '../../../../ContentViewSelectors';
10
10
  import AffectedActivationKeys from '../affectedActivationKeys';
11
11
  import DeleteContext from '../DeleteContext';
12
+ import ContentViewSelect from '../../../../components/ContentViewSelect/ContentViewSelect';
12
13
 
13
14
  const CVReassignActivationKeysForm = () => {
14
15
  const dispatch = useDispatch();
@@ -75,6 +76,11 @@ const CVReassignActivationKeysForm = () => {
75
76
  return results.filter(cv => cv.id === id)[0]?.name;
76
77
  };
77
78
 
79
+ const onClear = () => {
80
+ setSelectedCVForAK(null);
81
+ setSelectedCVNameForAK(null);
82
+ };
83
+
78
84
  const onSelect = (event, selection) => {
79
85
  setSelectedCVForAK(selection);
80
86
  setSelectedCVNameForAK(fetchSelectedCVName(selection));
@@ -91,23 +97,17 @@ const CVReassignActivationKeysForm = () => {
91
97
  multiSelect={false}
92
98
  />
93
99
  {!cvInEnvLoading && selectedEnvForAK.length > 0 &&
94
- <div style={{ marginTop: '1em' }}>
95
- <h3>{__('Select content view')}</h3>
96
- <Select
97
- selections={selectedCVForAK}
98
- onSelect={onSelect}
99
- isOpen={cvSelectOpen}
100
- isDisabled={cvSelectOptions.length === 0}
101
- onToggle={isExpanded => setCVSelectOpen(isExpanded)}
102
- id="selectCV"
103
- name="selectCV"
104
- aria-label="selectCV"
105
- ouiaId="selectCV"
106
- placeholderText={(cvSelectOptions.length === 0) ? __('No content views available') : __('Select a content view')}
107
- >
108
- {cvSelectOptions}
109
- </Select>
110
- </div>
100
+ <ContentViewSelect
101
+ selections={selectedCVForAK}
102
+ onSelect={onSelect}
103
+ onClear={onClear}
104
+ isOpen={cvSelectOpen}
105
+ isDisabled={cvSelectOptions.length === 0}
106
+ onToggle={isExpanded => setCVSelectOpen(isExpanded)}
107
+ placeholderText={(cvSelectOptions.length === 0) ? __('No content views available') : __('Select a content view')}
108
+ >
109
+ {cvSelectOptions}
110
+ </ContentViewSelect>
111
111
  }
112
112
  <ExpandableSection
113
113
  toggleText={showActivationKeys ?