foreman_scc_manager 4.0.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/app/assets/javascripts/foreman_scc_manager/locale/de/foreman_scc_manager.js +341 -341
  4. data/app/assets/javascripts/foreman_scc_manager/locale/el/foreman_scc_manager.js +288 -288
  5. data/app/assets/javascripts/foreman_scc_manager/locale/en/foreman_scc_manager.js +2 -582
  6. data/app/assets/javascripts/foreman_scc_manager/locale/fr/foreman_scc_manager.js +1 -1
  7. data/app/assets/javascripts/foreman_scc_manager/locale/ja/foreman_scc_manager.js +348 -348
  8. data/app/assets/javascripts/foreman_scc_manager/locale/ka/foreman_scc_manager.js +381 -381
  9. data/app/assets/javascripts/foreman_scc_manager/locale/ko/foreman_scc_manager.js +592 -0
  10. data/app/assets/javascripts/foreman_scc_manager/locale/zh_CN/foreman_scc_manager.js +346 -346
  11. data/app/views/scc_accounts/_form.html.erb +2 -2
  12. data/lib/foreman_scc_manager/version.rb +1 -1
  13. data/locale/Makefile +12 -2
  14. data/locale/de/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  15. data/locale/de/foreman_scc_manager.po +101 -98
  16. data/locale/el/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  17. data/locale/el/foreman_scc_manager.po +25 -24
  18. data/locale/en/foreman_scc_manager.po +0 -593
  19. data/locale/fr/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  20. data/locale/fr/foreman_scc_manager.po +1 -1
  21. data/locale/ja/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  22. data/locale/ja/foreman_scc_manager.po +94 -92
  23. data/locale/ka/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  24. data/locale/ka/foreman_scc_manager.po +139 -133
  25. data/locale/ko/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  26. data/locale/ko/foreman_scc_manager.po +600 -0
  27. data/locale/zh_CN/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  28. data/locale/zh_CN/foreman_scc_manager.po +92 -91
  29. data/package.json +6 -6
  30. data/test/controllers/api/v2/scc_accounts_test.rb +4 -4
  31. data/test/features/sync_test.rb +3 -3
  32. data/test/lib/scc_manager_test.rb +64 -0
  33. data/test/test_plugin_helper.rb +4 -1
  34. data/webpack/components/SCCProductPage/EmptySccProducts.js +7 -2
  35. data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCGenericPicker/index.js +238 -50
  36. data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/components/SCCRepoPicker/index.js +26 -12
  37. data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/components/SCCRepoPicker/styles.scss +2 -2
  38. data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/index.js +5 -3
  39. data/webpack/components/SCCProductPage/components/SCCProductPicker/index.js +48 -33
  40. data/webpack/components/SCCProductPage/components/SCCProductPicker/styles.scss +5 -5
  41. data/webpack/components/SCCProductPage/components/SCCProductPickerModal/index.js +13 -6
  42. data/webpack/components/SCCProductPage/components/SCCProductView/components/SCCRepoView/index.js +36 -23
  43. data/webpack/components/SCCProductPage/components/SCCProductView/components/SCCRepoView/styles.scss +10 -10
  44. data/webpack/components/SCCProductPage/components/SCCProductView/index.js +26 -8
  45. data/webpack/components/SCCProductPage/components/common/SCCGenericExpander/SCCGenericExpander.test.js +2 -2
  46. data/webpack/components/SCCProductPage/components/common/SCCGenericExpander/index.js +28 -10
  47. data/webpack/components/SCCProductPage/sccProductPage.scss +5 -5
  48. metadata +9 -7
@@ -1,79 +1,267 @@
1
+ // Reference: https://v5-archive.patternfly.org/components/menus/select#typeahead
2
+
1
3
  import React, { useState, useEffect } from 'react';
2
4
  import PropTypes from 'prop-types';
3
- import { ContextSelector, ContextSelectorItem } from '@patternfly/react-core';
5
+ import {
6
+ Select,
7
+ SelectOption,
8
+ SelectList,
9
+ MenuToggle,
10
+ TextInputGroup,
11
+ TextInputGroupMain,
12
+ TextInputGroupUtilities,
13
+ Button,
14
+ } from '@patternfly/react-core';
15
+ import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
16
+ import { translate as __ } from 'foremanReact/common/I18n';
4
17
 
5
18
  const GenericSelector = ({
6
- selectionItems,
7
- setGlobalSelected,
8
- screenReaderLabel,
19
+ initialSelectOptions,
20
+ setSelected,
9
21
  initialLabel,
22
+ selected,
23
+ inputValue,
24
+ setInputValue,
10
25
  }) => {
11
26
  const [isOpen, setIsOpen] = useState(false);
12
- const [selected, setSelected] = useState(initialLabel);
13
- const [searchValue, setSearchValue] = useState('');
14
- const [filteredItems, setFilteredItems] = useState(selectionItems);
27
+ const [filterValue, setFilterValue] = useState('');
28
+ const [selectOptions, setSelectOptions] = useState(
29
+ initialSelectOptions.map((option) => ({
30
+ children: option,
31
+ value: option,
32
+ }))
33
+ );
34
+ const [focusedItemIndex, setFocusedItemIndex] = useState(null);
35
+ const [activeItemId, setActiveItemId] = useState(null);
36
+ const NO_RESULTS = __('no results');
15
37
 
16
38
  useEffect(() => {
17
- setFilteredItems(selectionItems);
18
- setSelected(initialLabel);
19
- }, [selectionItems, initialLabel]);
20
-
21
- const onToggle = (selectorOpen) => {
22
- setIsOpen(selectorOpen);
39
+ let newSelectOptions = initialSelectOptions.map((option) => ({
40
+ children: option,
41
+ value: option,
42
+ }));
43
+ if (filterValue) {
44
+ newSelectOptions = newSelectOptions.filter((menuItem) =>
45
+ String(menuItem.children)
46
+ .toLowerCase()
47
+ .includes(filterValue.toLowerCase())
48
+ );
49
+ if (!newSelectOptions.length) {
50
+ newSelectOptions = [
51
+ {
52
+ isAriaDisabled: true,
53
+ children: `No results found for "${filterValue}"`,
54
+ value: NO_RESULTS,
55
+ },
56
+ ];
57
+ }
58
+ if (!isOpen) {
59
+ setIsOpen(true);
60
+ }
61
+ }
62
+ setSelectOptions(newSelectOptions);
63
+ }, [filterValue, initialSelectOptions]);
64
+ const createItemId = (value) =>
65
+ `select-typeahead-${value?.replace(' ', '-')}`;
66
+ const setActiveAndFocusedItem = (itemIndex) => {
67
+ setFocusedItemIndex(itemIndex);
68
+ const focusedItem = selectOptions[itemIndex];
69
+ setActiveItemId(createItemId(focusedItem.value));
23
70
  };
24
-
25
- const onSelect = (event, value) => {
26
- setSelected(value);
27
- setIsOpen(!isOpen);
28
- setGlobalSelected(value);
71
+ const resetActiveAndFocusedItem = () => {
72
+ setFocusedItemIndex(null);
73
+ setActiveItemId(null);
29
74
  };
30
-
31
- const onSearchInputChange = (value) => {
32
- setSearchValue(value);
75
+ const closeMenu = () => {
76
+ setIsOpen(false);
77
+ resetActiveAndFocusedItem();
33
78
  };
34
-
35
- const onSearchButtonClick = (event) => {
36
- const filtered =
37
- searchValue === ''
38
- ? selectionItems
39
- : selectionItems.filter((item) => {
40
- const str = item.text ? item.text : item;
41
- return str.toLowerCase().indexOf(searchValue.toLowerCase()) !== -1;
42
- });
43
-
44
- setFilteredItems(filtered || []);
79
+ const onInputClick = () => {
80
+ if (!isOpen) {
81
+ setIsOpen(true);
82
+ } else if (!inputValue) {
83
+ closeMenu();
84
+ }
85
+ };
86
+ const selectOption = (value, content) => {
87
+ setInputValue(String(content));
88
+ setFilterValue('');
89
+ setSelected(String(value));
90
+ closeMenu();
45
91
  };
92
+ const onSelect = (_event, value) => {
93
+ if (value && value !== NO_RESULTS) {
94
+ const optionText = selectOptions.find((option) => option.value === value)
95
+ ?.children;
96
+ selectOption(value, optionText);
97
+ }
98
+ };
99
+ const onTextInputChange = (_event, value) => {
100
+ setInputValue(value);
101
+ setFilterValue(value);
102
+ resetActiveAndFocusedItem();
103
+ if (value !== selected) {
104
+ setSelected('');
105
+ }
106
+ };
107
+ const handleMenuArrowKeys = (key) => {
108
+ let indexToFocus = 0;
109
+ if (!isOpen) {
110
+ setIsOpen(true);
111
+ }
112
+ if (selectOptions.every((option) => option.isDisabled)) {
113
+ return;
114
+ }
115
+ if (key === 'ArrowUp') {
116
+ if (focusedItemIndex === null || focusedItemIndex === 0) {
117
+ indexToFocus = selectOptions.length - 1;
118
+ } else {
119
+ indexToFocus = focusedItemIndex - 1;
120
+ }
121
+ while (selectOptions[indexToFocus].isDisabled) {
122
+ indexToFocus--;
123
+ if (indexToFocus === -1) {
124
+ indexToFocus = selectOptions.length - 1;
125
+ }
126
+ }
127
+ }
128
+ if (key === 'ArrowDown') {
129
+ if (
130
+ focusedItemIndex === null ||
131
+ focusedItemIndex === selectOptions.length - 1
132
+ ) {
133
+ indexToFocus = 0;
134
+ } else {
135
+ indexToFocus = focusedItemIndex + 1;
136
+ }
137
+ while (selectOptions[indexToFocus].isDisabled) {
138
+ indexToFocus++;
139
+ if (indexToFocus === selectOptions.length) {
140
+ indexToFocus = 0;
141
+ }
142
+ }
143
+ }
144
+ setActiveAndFocusedItem(indexToFocus);
145
+ };
146
+ const onInputKeyDown = (event) => {
147
+ const focusedItem =
148
+ focusedItemIndex !== null ? selectOptions[focusedItemIndex] : null;
149
+ switch (event.key) {
150
+ case 'Enter':
151
+ if (
152
+ isOpen &&
153
+ focusedItem &&
154
+ focusedItem.value !== NO_RESULTS &&
155
+ !focusedItem.isAriaDisabled
156
+ ) {
157
+ selectOption(focusedItem.value, focusedItem.children);
158
+ }
159
+ if (!isOpen) {
160
+ setIsOpen(true);
161
+ }
162
+ break;
163
+ case 'ArrowUp':
164
+ case 'ArrowDown':
165
+ event.preventDefault();
166
+ handleMenuArrowKeys(event.key);
167
+ break;
168
+ default:
169
+ break;
170
+ }
171
+ };
172
+ const onToggleClick = () => {
173
+ setIsOpen(!isOpen);
174
+ };
175
+ const onClearButtonClick = () => {
176
+ setSelected('');
177
+ setInputValue('');
178
+ setFilterValue('');
179
+ resetActiveAndFocusedItem();
180
+ };
181
+ const toggle = (toggleRef) => (
182
+ <MenuToggle
183
+ ref={toggleRef}
184
+ variant="typeahead"
185
+ onClick={onToggleClick}
186
+ isExpanded={isOpen}
187
+ isFullWidth
188
+ >
189
+ <TextInputGroup isPlain>
190
+ <TextInputGroupMain
191
+ value={inputValue}
192
+ onClick={onInputClick}
193
+ onChange={onTextInputChange}
194
+ onKeyDown={onInputKeyDown}
195
+ id={initialLabel.concat('typeahead-select-input')}
196
+ autoComplete="off"
197
+ placeholder={initialLabel}
198
+ {...(activeItemId && {
199
+ 'aria-activedescendant': activeItemId,
200
+ })}
201
+ role="combobox"
202
+ isExpanded={isOpen}
203
+ />
46
204
 
205
+ <TextInputGroupUtilities
206
+ {...(!inputValue
207
+ ? {
208
+ style: {
209
+ display: 'none',
210
+ },
211
+ }
212
+ : {})}
213
+ >
214
+ <Button
215
+ variant="plain"
216
+ ouiaId={initialLabel.concat('scc-product-picker-button')}
217
+ onClick={onClearButtonClick}
218
+ >
219
+ <TimesIcon aria-hidden />
220
+ </Button>
221
+ </TextInputGroupUtilities>
222
+ </TextInputGroup>
223
+ </MenuToggle>
224
+ );
47
225
  return (
48
- <ContextSelector
49
- toggleText={selected}
50
- onSearchInputChange={onSearchInputChange}
226
+ <Select
227
+ id={initialLabel}
228
+ ouiaId={initialLabel.concat('scc-product-picker-select')}
51
229
  isOpen={isOpen}
52
- searchInputValue={searchValue}
53
- onToggle={onToggle}
230
+ selected={selected}
54
231
  onSelect={onSelect}
55
- onSearchButtonClick={onSearchButtonClick}
56
- screenReaderLabel={screenReaderLabel}
232
+ onOpenChange={(isOpenSelect) => {
233
+ !isOpenSelect && closeMenu();
234
+ }}
235
+ toggle={toggle}
236
+ shouldFocusFirstItemOnOpen={false}
57
237
  >
58
- {filteredItems.map((item, index) => (
59
- <ContextSelectorItem key={index}>
60
- {item || 'no arch'}
61
- </ContextSelectorItem>
62
- ))}
63
- </ContextSelector>
238
+ <SelectList id={initialLabel.concat('select-typeahead-listbox')}>
239
+ {selectOptions.map((option, index) => (
240
+ <SelectOption
241
+ key={option.value || option.children}
242
+ isFocused={focusedItemIndex === index}
243
+ id={createItemId(option.value)}
244
+ className={option.className}
245
+ {...option}
246
+ ref={null}
247
+ />
248
+ ))}
249
+ </SelectList>
250
+ </Select>
64
251
  );
65
252
  };
66
253
 
67
254
  GenericSelector.propTypes = {
68
- selectionItems: PropTypes.array,
69
- setGlobalSelected: PropTypes.func.isRequired,
70
- screenReaderLabel: PropTypes.string,
255
+ initialSelectOptions: PropTypes.array,
71
256
  initialLabel: PropTypes.string,
257
+ selected: PropTypes.string.isRequired,
258
+ setSelected: PropTypes.func.isRequired,
259
+ inputValue: PropTypes.string.isRequired,
260
+ setInputValue: PropTypes.func.isRequired,
72
261
  };
73
262
 
74
263
  GenericSelector.defaultProps = {
75
- selectionItems: [],
76
- screenReaderLabel: '',
264
+ initialSelectOptions: [],
77
265
  initialLabel: '',
78
266
  };
79
267
 
@@ -1,16 +1,25 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { sprintf, translate as __ } from 'foremanReact/common/I18n';
4
- import { Select, SelectOption, SelectVariant } from '@patternfly/react-core';
4
+ import {
5
+ Select,
6
+ SelectOption,
7
+ SelectList,
8
+ MenuToggle,
9
+ } from '@patternfly/react-core';
5
10
 
6
11
  import './styles.scss';
7
12
 
8
- const createRepoSelectOption = (repo, disableRepos) => (
13
+ const createRepoSelectOption = (repo, disableRepos, selectedItems) => (
9
14
  <SelectOption
15
+ hasCheckbox
10
16
  key={repo.id}
11
17
  isDisabled={repo.katello_repository_id !== null || disableRepos}
12
18
  value={repo.name}
13
- />
19
+ isSelected={selectedItems.includes(repo.name)}
20
+ >
21
+ {repo.name}
22
+ </SelectOption>
14
23
  );
15
24
 
16
25
  const setRepoSelection = (
@@ -63,8 +72,9 @@ const SCCRepoPicker = ({
63
72
  productAlreadySynced
64
73
  )
65
74
  );
66
- const onToggle = (toggle) => {
67
- setIsOpen(toggle);
75
+
76
+ const onToggleClick = () => {
77
+ setIsOpen(!isOpen);
68
78
  };
69
79
 
70
80
  useEffect(() => {
@@ -135,21 +145,25 @@ const SCCRepoPicker = ({
135
145
  };
136
146
 
137
147
  const selectOptions = sccRepos.map((repo) =>
138
- createRepoSelectOption(repo, disableRepos)
148
+ createRepoSelectOption(repo, disableRepos, selected)
149
+ );
150
+
151
+ const toggle = (toggleRef) => (
152
+ <MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>
153
+ {sprintf(__('%s/%s'), selected.length, sccRepos.length)}
154
+ </MenuToggle>
139
155
  );
140
156
 
141
157
  return (
142
158
  <Select
143
- variant={SelectVariant.checkbox}
144
- isCheckboxSelectionBadgeHidden
145
- onToggle={onToggle}
159
+ ouiaId={sccProductId.toString().concat('scc-manager-repo-picker')}
160
+ toggle={toggle}
146
161
  onSelect={onSelect}
147
162
  selections={selected}
148
163
  isOpen={isOpen}
149
- isDisabled={disableRepos}
150
- placeholderText={sprintf(__('%s/%s'), selected.length, sccRepos.length)}
164
+ onOpenChange={(nextOpen) => setIsOpen(nextOpen)}
151
165
  >
152
- {selectOptions}
166
+ <SelectList>{selectOptions}</SelectList>
153
167
  </Select>
154
168
  );
155
169
  };
@@ -1,3 +1,3 @@
1
- .pf-c-tree-view__node .pf-c-tree-view__node-count .pf-c-badge.pf-m-read {
2
- --pf-c-badge--m-read--BackgroundColor: transparent;
1
+ .pf-v5-c-tree-view__node .pf-v5-c-tree-view__node-count .pf-v5-c-badge.pf-m-read {
2
+ --pf-v5-c-badge--m-read--BackgroundColor: transparent;
3
3
  }
@@ -38,7 +38,7 @@ const addSCCRepoPickerToTree = (
38
38
  ) => {
39
39
  tree.customBadgeContent = [];
40
40
  tree.customBadgeContent.push(
41
- <Tooltip content={__('Filter repositories')}>
41
+ <Tooltip aria="none" aria-live="polite" content={__('Filter repositories')}>
42
42
  <SCCRepoPicker
43
43
  sccRepos={tree.scc_repositories}
44
44
  disableRepos={tree.product_id === null && !tree.checkProps.checked}
@@ -234,7 +234,7 @@ const SCCTreePicker = ({
234
234
  };
235
235
 
236
236
  return (
237
- <Card>
237
+ <Card ouiaId="scc-manager-product-picker-card">
238
238
  <CardBody>
239
239
  <Flex direction={{ default: 'column' }}>
240
240
  <Flex>
@@ -249,6 +249,7 @@ const SCCTreePicker = ({
249
249
  >
250
250
  <Switch
251
251
  id="filter-debug-switch"
252
+ ouiaId="scc-manager-filter-debug-switch"
252
253
  onChange={debugFilterChange}
253
254
  isChecked={activateDebugFilter}
254
255
  label={__('Include Debug and Source Pool repositories')}
@@ -261,13 +262,14 @@ const SCCTreePicker = ({
261
262
  data={sccProductTree}
262
263
  allExpanded={expandAll}
263
264
  onCheck={onCheck}
264
- hasChecks
265
+ hasCheckboxes
265
266
  hasBadges
266
267
  hasGuides
267
268
  />
268
269
  </Flex>
269
270
  <Flex>
270
271
  <Button
272
+ ouiaId="scc-manager-add-products-button"
271
273
  variant="primary"
272
274
  onClick={submitForm}
273
275
  isDisabled={Object.keys(selectedRepos).length === 0}
@@ -24,9 +24,6 @@ const resetSelectionStringArch = __(' -- Select Architecture --');
24
24
  const genericFilter = (object, comparator) =>
25
25
  // we can have architectures that are not set
26
26
  comparator === '' ||
27
- comparator === resetSelectionStringProduct ||
28
- comparator === resetSelectionStringVersion ||
29
- comparator === resetSelectionStringArch ||
30
27
  object === comparator ||
31
28
  (object === null && comparator === 'no arch');
32
29
 
@@ -61,6 +58,9 @@ const SCCProductPicker = ({
61
58
  const [filteredSccProducts, setFilteredSccProducts] = useState([]);
62
59
  const [showSearchTree, setShowSearchTree] = useState(false);
63
60
  const [isExpanded, setIsExpanded] = useState(false);
61
+ const [searchInputProduct, setSearchInputProduct] = useState('');
62
+ const [searchInputVersion, setSearchInputVersion] = useState('');
63
+ const [searchInputArch, setSearchInputArch] = useState('');
64
64
 
65
65
  useEffect(() => {
66
66
  if (editProductId !== 0) {
@@ -78,10 +78,12 @@ const SCCProductPicker = ({
78
78
  }, [editProductId, sccProducts]);
79
79
 
80
80
  const onProductSelectionChange = (value) => {
81
- if (value !== resetSelectionStringProduct) {
82
- setVersionItems(filterVersionByProduct(sccProducts, value));
83
- } else {
81
+ if (value === '') {
84
82
  setVersionItems([]);
83
+ setSearchInputVersion('');
84
+ setSearchInputArch('');
85
+ } else {
86
+ setVersionItems(filterVersionByProduct(sccProducts, value));
85
87
  }
86
88
  setSelectedProduct(value);
87
89
  setArchItems([]);
@@ -90,8 +92,9 @@ const SCCProductPicker = ({
90
92
  };
91
93
 
92
94
  const onVersionSelectionChange = (value) => {
93
- if (value === resetSelectionStringVersion) {
95
+ if (value === '') {
94
96
  setArchItems([]);
97
+ setSearchInputArch('');
95
98
  } else {
96
99
  setArchItems(
97
100
  filterArchByVersionAndProduct(sccProducts, selectedProduct, value)
@@ -102,6 +105,9 @@ const SCCProductPicker = ({
102
105
  };
103
106
 
104
107
  const onArchSelectionChange = (value) => {
108
+ if (value === '') {
109
+ setArchItems([]);
110
+ }
105
111
  setSelectedArch(value);
106
112
  };
107
113
 
@@ -126,10 +132,20 @@ const SCCProductPicker = ({
126
132
  setSelectedProduct('');
127
133
  setSelectedVersion('');
128
134
  setSelectedArch('');
135
+ setVersionItems([]);
136
+ setArchItems([]);
137
+ setSearchInputProduct('');
138
+ setSearchInputVersion('');
139
+ setSearchInputArch('');
129
140
  };
130
141
 
131
142
  return (
132
- <Card border="dark" id="product-selection-card" isExpanded={isExpanded}>
143
+ <Card
144
+ border="dark"
145
+ ouiaId="scc-manager-product-selection-card"
146
+ id="product-selection-card"
147
+ isExpanded={isExpanded}
148
+ >
133
149
  <CardHeader onExpand={onExpand}>
134
150
  <CardTitle>{__('Select SUSE products')}</CardTitle>
135
151
  </CardHeader>
@@ -139,62 +155,61 @@ const SCCProductPicker = ({
139
155
  <Flex>
140
156
  <FlexItem>
141
157
  <SCCGenericPicker
142
- key="prod-select"
143
- selectionItems={
144
- selectedProduct === ''
145
- ? productItems
146
- : [resetSelectionStringProduct].concat(productItems)
147
- }
148
- setGlobalSelected={onProductSelectionChange}
149
- screenReaderLabel={resetSelectionStringProduct}
158
+ key="scc-prod-select"
159
+ initialSelectOptions={productItems}
160
+ setSelected={onProductSelectionChange}
150
161
  initialLabel={
151
162
  selectedProduct === ''
152
163
  ? resetSelectionStringProduct
153
164
  : selectedProduct
154
165
  }
166
+ selected={selectedProduct}
167
+ inputValue={searchInputProduct}
168
+ setInputValue={setSearchInputProduct}
155
169
  />
156
170
  </FlexItem>
157
171
  <FlexItem>
158
172
  <SCCGenericPicker
159
- key="vers-select"
160
- selectionItems={
161
- selectedVersion === ''
162
- ? versionItems
163
- : [resetSelectionStringVersion].concat(versionItems)
164
- }
165
- setGlobalSelected={onVersionSelectionChange}
166
- screenReaderLabel={resetSelectionStringVersion}
173
+ key="scc-vers-select"
174
+ initialSelectOptions={versionItems}
175
+ setSelected={onVersionSelectionChange}
167
176
  initialLabel={
168
177
  selectedVersion === ''
169
178
  ? resetSelectionStringVersion
170
179
  : selectedVersion
171
180
  }
181
+ selected={selectedVersion}
182
+ inputValue={searchInputVersion}
183
+ setInputValue={setSearchInputVersion}
172
184
  />
173
185
  </FlexItem>
174
186
  <FlexItem>
175
187
  <SCCGenericPicker
176
- key="arch-select"
177
- selectionItems={
178
- selectedArch === ''
179
- ? archItems
180
- : [resetSelectionStringArch].concat(archItems)
181
- }
182
- setGlobalSelected={onArchSelectionChange}
183
- screenReaderLabel={resetSelectionStringArch}
188
+ key="scc-arch-select"
189
+ initialSelectOptions={archItems}
190
+ setSelected={onArchSelectionChange}
184
191
  initialLabel={
185
192
  selectedArch === ''
186
193
  ? resetSelectionStringArch
187
194
  : selectedArch
188
195
  }
196
+ selected={selectedArch}
197
+ inputValue={searchInputArch}
198
+ setInputValue={setSearchInputArch}
189
199
  />
190
200
  </FlexItem>
191
201
  <FlexItem>
192
- <Button variant="primary" onClick={filterProducts}>
202
+ <Button
203
+ ouiaId="scc-manager-product-search-button"
204
+ variant="primary"
205
+ onClick={filterProducts}
206
+ >
193
207
  {__('Search')}
194
208
  </Button>
195
209
  </FlexItem>
196
210
  <FlexItem>
197
211
  <Button
212
+ ouiaId="scc-manager-product-search-reset-button"
198
213
  variant="link"
199
214
  icon={<TimesIcon />}
200
215
  onClick={resetTreeForm}
@@ -1,10 +1,10 @@
1
1
  @import '~@theforeman/vendor/scss/variables';
2
2
 
3
- .pf-c-select__toggle {
4
- font-size: var(--pf-global--FontSize--xs);
5
- font-weight: var(--pf-global--FontWeight--bold);
3
+ .pf-v5-c-select__toggle {
4
+ font-size: var(--pf-v5-global--FontSize--xs);
5
+ font-weight: var(--pf-v5-global--FontWeight--bold);
6
6
  };
7
7
 
8
- .pf-c-switch__input ~ .pf-c-switch__label {
9
- font-size: var(--pf-global--FontSize--xs);
8
+ .pf-v5-c-switch__input ~ .pf-v5-c-switch__label {
9
+ font-size: var(--pf-v5-global--FontSize--xs);
10
10
  };
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { Fragment } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import ForemanModal from 'foremanReact/components/ForemanModal';
4
4
 
@@ -15,14 +15,14 @@ import {
15
15
  } from '@patternfly/react-core';
16
16
 
17
17
  const generateRepoList = (repoNames, productName) => (
18
- <>
18
+ <Fragment key={productName}>
19
19
  <TextListItem key={productName}>{productName}</TextListItem>
20
20
  <TextList key={repoNames}>
21
21
  {repoNames.map((repo) => (
22
22
  <TextListItem key={repo}>{repo}</TextListItem>
23
23
  ))}
24
24
  </TextList>
25
- </>
25
+ </Fragment>
26
26
  );
27
27
 
28
28
  const generateProductList = (reposToSubscribe) => (
@@ -41,12 +41,16 @@ const SCCProductPickerModal = ({ id, taskId, reposToSubscribe }) => (
41
41
  title={__('Summary of SCC product subscription')}
42
42
  enforceFocus
43
43
  >
44
- <Card>
44
+ <Card ouiaId="scc-product-picker-modal">
45
45
  <CardBody>
46
46
  <TextContent key={taskId}>
47
- <Text key={'modal1'.concat(taskId)}>
47
+ <Text
48
+ ouiaId={'modal1'.concat(taskId)}
49
+ key={'modal1'.concat(taskId)}
50
+ >
48
51
  {__('The subscription task with id ')}
49
52
  <Text
53
+ ouiaId={'modal2'.concat(taskId)}
50
54
  key={'modal2'.concat(taskId)}
51
55
  component={TextVariants.a}
52
56
  target="_blank"
@@ -56,7 +60,10 @@ const SCCProductPickerModal = ({ id, taskId, reposToSubscribe }) => (
56
60
  </Text>
57
61
  {__(' has started successfully.')}
58
62
  </Text>
59
- <Text key={'modal3'.concat(taskId)}>
63
+ <Text
64
+ ouiaId={'modal3'.concat(taskId)}
65
+ key={'modal3'.concat(taskId)}
66
+ >
60
67
  {__('The following products will be imported:')}
61
68
  </Text>
62
69
  {generateProductList(reposToSubscribe)}