katello 4.7.0.rc2 → 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 (82) 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/api/v2/products_bulk_actions_controller.rb +1 -1
  4. data/app/controllers/katello/api/v2/repositories_controller.rb +1 -1
  5. data/app/controllers/katello/api/v2/repository_sets_controller.rb +25 -14
  6. data/app/controllers/katello/concerns/api/v2/registration_controller_extensions.rb +0 -1
  7. data/app/lib/actions/katello/repository/sync.rb +3 -3
  8. data/app/lib/actions/pulp3/orchestration/repository/copy_all_units.rb +1 -0
  9. data/app/lib/katello/resources/candlepin.rb +1 -1
  10. data/app/lib/katello/resources/cdn.rb +1 -1
  11. data/app/lib/katello/util/candlepin_repository_checker.rb +2 -0
  12. data/app/models/katello/concerns/host_managed_extensions.rb +4 -2
  13. data/app/models/katello/concerns/smart_proxy_extensions.rb +1 -1
  14. data/app/models/katello/content.rb +1 -1
  15. data/app/models/katello/glue/provider.rb +1 -1
  16. data/app/models/katello/root_repository.rb +4 -0
  17. data/app/services/katello/product_content_importer.rb +61 -5
  18. data/app/services/katello/pulp3/repository/apt.rb +6 -0
  19. data/app/services/katello/pulp3/repository/yum.rb +2 -1
  20. data/app/services/katello/pulp3/repository.rb +2 -2
  21. data/app/services/katello/pulp3/repository_mirror.rb +1 -0
  22. data/config/initializers/monkeys.rb +2 -1
  23. data/db/migrate/20221206170122_update_ignore_srpm_to_false_for_mirror_complete.rb +5 -0
  24. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/bulk/views/products-bulk-advanced-sync-modal.html +1 -1
  25. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/details/views/repository-advanced-sync-options.html +4 -4
  26. data/engines/bastion_katello/app/assets/javascripts/bastion_katello/products/details/repositories/repositories.routes.js +2 -2
  27. data/lib/katello/engine.rb +1 -0
  28. data/lib/katello/version.rb +1 -1
  29. data/lib/monkeys/fix_deb_optimized_sync.rb +35 -0
  30. data/lib/monkeys/{try_pulp_container_path.rb → fix_pulp_container_path.rb} +0 -0
  31. data/locale/action_names.rb +69 -69
  32. data/locale/bn/katello.po +23 -20
  33. data/locale/cs/katello.po +23 -20
  34. data/locale/de/katello.po +25 -22
  35. data/locale/en/katello.po +23 -20
  36. data/locale/es/katello.po +335 -332
  37. data/locale/fr/katello.po +704 -695
  38. data/locale/gu/katello.po +23 -20
  39. data/locale/hi/katello.po +23 -20
  40. data/locale/it/katello.po +23 -20
  41. data/locale/ja/katello.po +570 -561
  42. data/locale/ka/katello.po +2269 -2260
  43. data/locale/katello.pot +287 -279
  44. data/locale/kn/katello.po +23 -20
  45. data/locale/ko/katello.po +57 -53
  46. data/locale/mr/katello.po +23 -20
  47. data/locale/or/katello.po +23 -20
  48. data/locale/pa/katello.po +23 -20
  49. data/locale/pt/katello.po +23 -20
  50. data/locale/pt_BR/katello.po +441 -438
  51. data/locale/ru/katello.po +23 -20
  52. data/locale/ta/katello.po +23 -20
  53. data/locale/te/katello.po +23 -20
  54. data/locale/zh_CN/katello.po +694 -687
  55. data/locale/zh_TW/katello.po +23 -20
  56. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/ChangeHostCVModal.js +5 -11
  57. data/webpack/components/extensions/HostDetails/Cards/ContentViewDetailsCard/__tests__/changeHostCVModal.test.js +2 -2
  58. data/webpack/components/extensions/HostDetails/DetailsTabCards/RegistrationCard.js +1 -1
  59. data/webpack/components/extensions/HostDetails/DetailsTabCards/SystemPropertiesCardExtensions.js +58 -1
  60. data/webpack/components/extensions/HostDetails/Tabs/ModuleStreamsTab/ModuleStreamsTab.js +5 -1
  61. data/webpack/components/extensions/HostDetails/Tabs/__tests__/errataTab.test.js +2 -2
  62. data/webpack/components/extensions/HostDetails/Tabs/__tests__/moduleStreamsTab.test.js +2 -2
  63. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packageInstallModal.test.js +2 -2
  64. data/webpack/components/extensions/HostDetails/Tabs/__tests__/packagesTab.test.js +2 -2
  65. data/webpack/components/extensions/HostDetails/Tabs/__tests__/tracesTab.test.js +3 -3
  66. data/webpack/components/extensions/HostDetails/Tabs/customizedRexUrlHelpers.js +1 -1
  67. data/webpack/global_index.js +2 -0
  68. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignActivationKeysForm.js +10 -10
  69. data/webpack/scenes/ContentViews/Delete/Steps/CVDeletionReassignHostsForm.js +10 -10
  70. data/webpack/scenes/ContentViews/Delete/__tests__/contentViewDelete.test.js +5 -5
  71. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignActivationKeys.js +9 -10
  72. data/webpack/scenes/ContentViews/Details/Versions/BulkDelete/Steps/ReassignHosts.js +13 -10
  73. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignActivationKeysForm.js +18 -18
  74. data/webpack/scenes/ContentViews/Details/Versions/Delete/RemoveSteps/CVReassignHostsForm.js +10 -6
  75. data/webpack/scenes/ContentViews/Details/Versions/Delete/__tests__/cvVersionRemove.test.js +6 -6
  76. data/webpack/scenes/ContentViews/components/ContentViewSelect/ContentViewSelect.js +40 -0
  77. data/webpack/scenes/Hosts/ChangeContentSource/actions.js +0 -1
  78. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceForm.js +16 -2
  79. data/webpack/scenes/Hosts/ChangeContentSource/components/ContentSourceTemplate.js +13 -17
  80. data/webpack/scenes/Hosts/ChangeContentSource/index.js +79 -39
  81. data/webpack/scenes/Hosts/ChangeContentSource/styles.scss +6 -2
  82. metadata +9 -6
@@ -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 ?
@@ -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 AffectedHosts from '../affectedHosts';
11
11
  import DeleteContext from '../DeleteContext';
12
+ import ContentViewSelect from '../../../../components/ContentViewSelect/ContentViewSelect';
12
13
 
13
14
  const CVReassignHostsForm = () => {
14
15
  const dispatch = useDispatch();
@@ -74,6 +75,11 @@ const CVReassignHostsForm = () => {
74
75
  return results.filter(cv => cv.id === id)[0]?.name;
75
76
  };
76
77
 
78
+ const onClear = () => {
79
+ setSelectedCVForHosts(null);
80
+ setSelectedCVNameForHosts(null);
81
+ };
82
+
77
83
  const onSelect = (event, selection) => {
78
84
  setSelectedCVForHosts(selection);
79
85
  setSelectedCVNameForHosts(fetchSelectedCVName(selection));
@@ -90,9 +96,8 @@ const CVReassignHostsForm = () => {
90
96
  multiSelect={false}
91
97
  />
92
98
  {selectedEnvForHost.length > 0 &&
93
- <div style={{ marginTop: '1em' }}>
94
- <h3>{__('Select content view')}</h3>
95
- <Select
99
+ <ContentViewSelect
100
+ onClear={onClear}
96
101
  selections={selectedCVForHosts}
97
102
  onSelect={onSelect}
98
103
  isOpen={cvSelectOpen}
@@ -105,8 +110,7 @@ const CVReassignHostsForm = () => {
105
110
  placeholderText={(cvSelectOptions.length === 0) ? __('No content views available') : __('Select a content view')}
106
111
  >
107
112
  {cvSelectOptions}
108
- </Select>
109
- </div>
113
+ </ContentViewSelect>
110
114
  }
111
115
  <ExpandableSection
112
116
  toggleText={showHosts ? 'Hide hosts' : 'Show hosts'}
@@ -160,7 +160,7 @@ test('Can open Remove wizard and remove version from environment with hosts', as
160
160
 
161
161
 
162
162
  const {
163
- getByText, getAllByText, getByLabelText, getAllByLabelText, queryByText,
163
+ getByText, getAllByText, getByLabelText, getAllByLabelText, queryByText, getByPlaceholderText,
164
164
  } = renderWithRedux(
165
165
  <ContentViewVersions cvId={2} details={cvDetailData} />,
166
166
  renderOptions,
@@ -190,9 +190,9 @@ test('Can open Remove wizard and remove version from environment with hosts', as
190
190
  fireEvent.click(getByLabelText('test1'));
191
191
  await patientlyWaitFor(() => {
192
192
  expect(getByText('Select content view')).toBeInTheDocument();
193
- expect(getByText('Select a content view')).toBeInTheDocument();
193
+ expect(getByPlaceholderText('Select a content view')).toBeInTheDocument();
194
194
  });
195
- fireEvent.click(getByText('Select a content view'));
195
+ fireEvent.click(getByPlaceholderText('Select a content view'));
196
196
  await patientlyWaitFor(() => {
197
197
  expect(getByText('cv2')).toBeInTheDocument();
198
198
  });
@@ -250,7 +250,7 @@ test('Can open Remove wizard and remove version from environment with activation
250
250
 
251
251
 
252
252
  const {
253
- getByText, getAllByText, getByLabelText, getAllByLabelText, queryByText,
253
+ getByText, getAllByText, getByLabelText, getAllByLabelText, queryByText, getByPlaceholderText,
254
254
  } = renderWithRedux(
255
255
  <ContentViewVersions cvId={2} details={cvDetailData} />,
256
256
  renderOptions,
@@ -280,9 +280,9 @@ test('Can open Remove wizard and remove version from environment with activation
280
280
  fireEvent.click(getByLabelText('test1'));
281
281
  await patientlyWaitFor(() => {
282
282
  expect(getByText('Select content view')).toBeInTheDocument();
283
- expect(getByText('Select a content view')).toBeInTheDocument();
283
+ expect(getByPlaceholderText('Select a content view')).toBeInTheDocument();
284
284
  });
285
- fireEvent.click(getByText('Select a content view'));
285
+ fireEvent.click(getByPlaceholderText('Select a content view'));
286
286
  await patientlyWaitFor(() => {
287
287
  expect(getByText('cv2')).toBeInTheDocument();
288
288
  });
@@ -0,0 +1,40 @@
1
+ import React from 'react';
2
+ import { translate as __ } from 'foremanReact/common/I18n';
3
+ import { Select, SelectVariant } from '@patternfly/react-core';
4
+ import PropTypes from 'prop-types';
5
+
6
+ const ContentViewSelect = ({
7
+ headerText,
8
+ children,
9
+ onClear,
10
+ ...pfSelectProps
11
+ }) => (
12
+ <div style={{ marginTop: '1em' }}>
13
+ <h3>{headerText}</h3>
14
+ <Select
15
+ variant={SelectVariant.typeahead}
16
+ onClear={onClear}
17
+ maxHeight="20rem"
18
+ menuAppendTo="parent"
19
+ ouiaId="select-content-view"
20
+ id="selectCV"
21
+ name="selectCV"
22
+ aria-label="selectCV"
23
+ {...pfSelectProps}
24
+ >
25
+ {children}
26
+ </Select>
27
+ </div>
28
+ );
29
+
30
+ ContentViewSelect.propTypes = {
31
+ headerText: PropTypes.string,
32
+ onClear: PropTypes.func.isRequired,
33
+ children: PropTypes.node.isRequired,
34
+ };
35
+
36
+ ContentViewSelect.defaultProps = {
37
+ headerText: __('Select content view'),
38
+ };
39
+
40
+ export default ContentViewSelect;
@@ -27,7 +27,6 @@ export const changeContentSource = (environmentId, contentViewId, contentSourceI
27
27
  content_source_id: contentSourceId,
28
28
  host_ids: hostIds,
29
29
  },
30
- successToast: () => __('Content source successfully updated.'),
31
30
  errorToast: () => __('Something went wrong while updating the content source. See the logs for more information'),
32
31
  });
33
32
 
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import {
3
3
  ActionGroup,
4
+ Alert,
4
5
  Button,
5
6
  Form,
6
7
  Grid,
@@ -24,6 +25,7 @@ const ContentSourceForm = ({
24
25
  contentSourceId,
25
26
  contentHosts,
26
27
  isLoading,
28
+ hostsUpdated,
27
29
  }) => {
28
30
  const formIsValid = () => (!!environmentId &&
29
31
  !!contentViewId &&
@@ -44,6 +46,16 @@ const ContentSourceForm = ({
44
46
  isHorizontal
45
47
  >
46
48
  <Grid hasGutter className="margin-top-16">
49
+ {(contentHosts.length === 0 && !isLoading) && (
50
+
51
+ <GridItem span={7}>
52
+ <Alert
53
+ variant="danger"
54
+ className="margin-top-20"
55
+ title={__('No hosts found')}
56
+ />
57
+ </GridItem>
58
+ )}
47
59
  <FormField label={__('Content source')} id="change_cs_content_source" value={contentSourceId} items={contentSources} onChange={handleContentSource} isDisabled={contentSourcesIsDisabled} />
48
60
  <FormField label={__('Environment')} id="change_cs_environment" value={environmentId} items={environments} onChange={handleEnvironment} isDisabled={environmentIsDisabled} />
49
61
  <FormField label={__('Content view')} id="change_cs_content_view" value={contentViewId} items={contentViews} onChange={handleContentView} isDisabled={viewIsDisabled} />
@@ -54,10 +66,10 @@ const ContentSourceForm = ({
54
66
  variant="primary"
55
67
  id="generate_btn"
56
68
  onClick={e => handleSubmit(e)}
57
- isDisabled={isLoading || !formIsValid()}
69
+ isDisabled={isLoading || !formIsValid() || hostsUpdated}
58
70
  isLoading={isLoading}
59
71
  >
60
- {__('Change content source')}
72
+ {__('Update')}
61
73
  </Button>
62
74
  </ActionGroup>
63
75
  </GridItem>
@@ -78,6 +90,7 @@ ContentSourceForm.propTypes = {
78
90
  contentSourceId: PropTypes.string,
79
91
  contentHosts: PropTypes.arrayOf(PropTypes.shape({})),
80
92
  isLoading: PropTypes.bool,
93
+ hostsUpdated: PropTypes.bool,
81
94
  };
82
95
 
83
96
  ContentSourceForm.defaultProps = {
@@ -89,6 +102,7 @@ ContentSourceForm.defaultProps = {
89
102
  contentSourceId: '',
90
103
  contentHosts: [],
91
104
  isLoading: false,
105
+ hostsUpdated: false,
92
106
  };
93
107
 
94
108
  export default ContentSourceForm;
@@ -1,5 +1,7 @@
1
1
  import React, { useState } from 'react';
2
+ import { FormattedMessage } from 'react-intl';
2
3
  import {
4
+ Alert,
3
5
  Grid,
4
6
  GridItem,
5
7
  CodeBlock,
@@ -39,25 +41,19 @@ const ContentSourceTemplate = ({ template, jobInvocationPath }) => {
39
41
  return (
40
42
  <Grid>
41
43
  <GridItem span={7}>
42
- <h1>
43
- {__("What's next?")}
44
- </h1>
45
- <p>
46
- {jobInvocationPath && (
47
- <>
48
- <a href={jobInvocationPath}>
49
- {__('Run job invocation')}
50
- </a>
51
- &nbsp;
52
- {__('to update configuration on all hosts, or')}
53
- </>
54
- )}
55
- &nbsp;
56
- {__('update configuration on the hosts manually:')}
57
- </p>
44
+ <Alert variant="warning" title={__('Host configurations are not updated yet')} className="margin-top-20" isInline>
45
+ <FormattedMessage
46
+ id="ccs_alert"
47
+ values={{
48
+ link: <a href={jobInvocationPath}>{__('run job invocation')}</a>,
49
+ }}
50
+ defaultMessage={jobInvocationPath ? __('To update the selected host configuration, {link}, or update hosts manually in the next section.') : __('To update the selected host configuration, update hosts manually in the next section.')}
51
+ />
52
+ </Alert>
53
+
58
54
  </GridItem>
59
55
  <GridItem span={7}>
60
- <CodeBlock actions={actions} className="cs_template_code">
56
+ <CodeBlock actions={actions} className="cs_template_code margin-top-20">
61
57
  <CodeBlockCode>
62
58
  {__('Change content source')}
63
59
  <ExpandableSection isExpanded={isExpanded} isDetached>
@@ -1,10 +1,13 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { useSelector, useDispatch } from 'react-redux';
3
3
 
4
- import { Alert, Grid, GridItem } from '@patternfly/react-core';
4
+ import { Alert, Grid, GridItem, PageSection, Title } from '@patternfly/react-core';
5
5
 
6
6
  import { translate as __ } from 'foremanReact/common/I18n';
7
+ import { foremanUrl } from 'foremanReact/common/helpers';
7
8
  import { STATUS } from 'foremanReact/constants';
9
+ import BreadcrumbBar from 'foremanReact/components/BreadcrumbBar';
10
+ import Head from 'foremanReact/components/Head';
8
11
 
9
12
  import { selectApiDataStatus,
10
13
  selectApiContentViewStatus,
@@ -53,6 +56,8 @@ const ChangeContentSourcePage = () => {
53
56
  const [environmentId, setEnvironmentId] = useState('');
54
57
  const [contentViewId, setContentViewId] = useState('');
55
58
 
59
+ const noHostSpecified = getHostIds(urlParams.host_id).length === 0 && urlParams.searchParam === '';
60
+
56
61
  const handleSubmit = (e) => {
57
62
  e.preventDefault();
58
63
 
@@ -61,6 +66,7 @@ const ChangeContentSourcePage = () => {
61
66
  contentViewId,
62
67
  contentSourceId,
63
68
  contentHosts.map(h => h.id),
69
+ jobInvocationPath,
64
70
  ));
65
71
  };
66
72
 
@@ -74,6 +80,19 @@ const ChangeContentSourcePage = () => {
74
80
  }
75
81
  };
76
82
 
83
+ const breadcrumbItems = () => {
84
+ const linkHosts = { caption: __('Hosts'), url: foremanUrl('/hosts') };
85
+ const linkContent = { caption: __('Change host content source') };
86
+
87
+ if (urlParams.host_id) {
88
+ const hostName = contentHosts.concat(hostsWithoutContent)
89
+ .find(h => `${h.id}` === urlParams.host_id)?.name;
90
+
91
+ return ([linkHosts, { caption: hostName, url: foremanUrl(`/new/hosts/${hostName}`) }, linkContent]);
92
+ }
93
+ return ([linkHosts, linkContent]);
94
+ };
95
+
77
96
  const handleEnvironment = (envId) => {
78
97
  setEnvironmentId(envId);
79
98
  setContentViewId('');
@@ -86,45 +105,66 @@ const ChangeContentSourcePage = () => {
86
105
  dispatch(getFormData(getHostIds(urlParams.host_id), urlParams.searchParam));
87
106
  }, [dispatch, urlParams.host_id, urlParams.searchParam]);
88
107
 
89
- if (getHostIds(urlParams.host_id).length === 0 && urlParams.searchParam === '') {
90
- return (
91
- <Grid className="margin-40">
92
- <GridItem span={7}>
93
- <Alert
94
- variant="danger"
95
- title={__('No hosts with content source found!')}
96
- />
97
- </GridItem>
98
- </Grid>);
99
- }
100
-
101
108
  return (
102
- <Grid className="margin-40">
103
- <GridItem span={7}>
104
- <h1>{__('Change host content source')}</h1>
105
- </GridItem>
106
- <Hosts
107
- contentHosts={contentHosts}
108
- hostsWithoutContent={hostsWithoutContent}
109
- />
110
-
111
- <ContentSourceForm
112
- handleSubmit={handleSubmit}
113
- environments={environments}
114
- handleEnvironment={handleEnvironment}
115
- environmentId={environmentId}
116
- contentViews={contentViews}
117
- handleContentView={setContentViewId}
118
- contentViewId={contentViewId}
119
- contentSources={contentSources}
120
- contentSourceId={contentSourceId}
121
- handleContentSource={handleContentSource}
122
- contentHosts={contentHosts}
123
- isLoading={isLoading}
124
- />
125
- { apiChangeStatus === STATUS.RESOLVED &&
126
- <ContentSourceTemplate template={template} jobInvocationPath={jobInvocationPath} /> }
127
- </Grid>
109
+ <>
110
+ <Head>
111
+ <title>{__('Change host content source')}</title>
112
+ </Head>
113
+ <PageSection
114
+ isFilled
115
+ variant="light"
116
+ >
117
+ <div className="margin-left-20">
118
+ <BreadcrumbBar
119
+ breadcrumbItems={breadcrumbItems()}
120
+ />
121
+ </div>
122
+ <Grid className="margin-left-20">
123
+ <GridItem span={7}>
124
+ <Title
125
+ headingLevel="h5"
126
+ size="2xl"
127
+ >
128
+ {__('Change host content source')}
129
+ </Title>
130
+ </GridItem>
131
+ {noHostSpecified &&
132
+ <GridItem span={7}>
133
+ <Alert
134
+ variant="danger"
135
+ className="margin-top-20"
136
+ title={__('No hosts were specified')}
137
+ />
138
+ </GridItem>
139
+ }
140
+ { !noHostSpecified &&
141
+ <>
142
+ <Hosts
143
+ contentHosts={contentHosts}
144
+ hostsWithoutContent={hostsWithoutContent}
145
+ />
146
+
147
+ <ContentSourceForm
148
+ handleSubmit={handleSubmit}
149
+ environments={environments}
150
+ handleEnvironment={handleEnvironment}
151
+ environmentId={environmentId}
152
+ contentViews={contentViews}
153
+ handleContentView={setContentViewId}
154
+ contentViewId={contentViewId}
155
+ contentSources={contentSources}
156
+ contentSourceId={contentSourceId}
157
+ handleContentSource={handleContentSource}
158
+ contentHosts={contentHosts}
159
+ isLoading={isLoading}
160
+ hostsUpdated={apiChangeStatus === STATUS.RESOLVED}
161
+ />
162
+ </> }
163
+ { apiChangeStatus === STATUS.RESOLVED &&
164
+ <ContentSourceTemplate template={template} jobInvocationPath={jobInvocationPath} /> }
165
+ </Grid>
166
+ </PageSection>
167
+ </>
128
168
  );
129
169
  };
130
170
 
@@ -6,6 +6,10 @@
6
6
  margin-bottom: 40px;
7
7
  }
8
8
 
9
- .margin-40 {
10
- margin: 40px;
9
+ .margin-left-20 {
10
+ margin-left: 20px;
11
+ }
12
+
13
+ .margin-top-20 {
14
+ margin-top: 20px;
11
15
  }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katello
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.0.rc2
4
+ version: 4.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - N/A
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-11-28 00:00:00.000000000 Z
11
+ date: 2023-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -2234,6 +2234,7 @@ files:
2234
2234
  - db/migrate/20220730033504_update_custom_cdn.rb
2235
2235
  - db/migrate/20220920173656_add_http_proxy_to_smart_proxy.rb
2236
2236
  - db/migrate/20220920180858_remove_http_proxy_from_katello_alternate_content_sources.rb
2237
+ - db/migrate/20221206170122_update_ignore_srpm_to_false_for_mirror_complete.rb
2237
2238
  - db/seeds.d/101-locations.rb
2238
2239
  - db/seeds.d/102-organizations.rb
2239
2240
  - db/seeds.d/104-proxy.rb
@@ -4479,8 +4480,9 @@ files:
4479
4480
  - lib/katello/version.rb
4480
4481
  - lib/monkeys/anemone.rb
4481
4482
  - lib/monkeys/ar_postgres_evr_t.rb
4483
+ - lib/monkeys/fix_deb_optimized_sync.rb
4484
+ - lib/monkeys/fix_pulp_container_path.rb
4482
4485
  - lib/monkeys/fx_sqlite_skip.rb
4483
- - lib/monkeys/try_pulp_container_path.rb
4484
4486
  - lib/proxy_api/container_gateway.rb
4485
4487
  - lib/proxy_api/pulp.rb
4486
4488
  - lib/proxy_api/pulp_node.rb
@@ -5158,6 +5160,7 @@ files:
5158
5160
  - webpack/scenes/ContentViews/__tests__/mockDetails.fixtures.json
5159
5161
  - webpack/scenes/ContentViews/components/CVBreadCrumb.js
5160
5162
  - webpack/scenes/ContentViews/components/ContentViewIcon.js
5163
+ - webpack/scenes/ContentViews/components/ContentViewSelect/ContentViewSelect.js
5161
5164
  - webpack/scenes/ContentViews/components/ContentViewsCounter.js
5162
5165
  - webpack/scenes/ContentViews/components/EnvironmentLabels.js
5163
5166
  - webpack/scenes/ContentViews/components/EnvironmentPaths/EnvironmentPathActions.js
@@ -5435,11 +5438,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
5435
5438
  version: '2.5'
5436
5439
  required_rubygems_version: !ruby/object:Gem::Requirement
5437
5440
  requirements:
5438
- - - ">"
5441
+ - - ">="
5439
5442
  - !ruby/object:Gem::Version
5440
- version: 1.3.1
5443
+ version: '0'
5441
5444
  requirements: []
5442
- rubygems_version: 3.3.7
5445
+ rubygems_version: 3.3.26
5443
5446
  signing_key:
5444
5447
  specification_version: 4
5445
5448
  summary: Content and Subscription Management plugin for Foreman