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.
- checksums.yaml +4 -4
- data/README.md +1 -2
- data/app/assets/javascripts/foreman_scc_manager/locale/de/foreman_scc_manager.js +341 -341
- data/app/assets/javascripts/foreman_scc_manager/locale/el/foreman_scc_manager.js +288 -288
- data/app/assets/javascripts/foreman_scc_manager/locale/en/foreman_scc_manager.js +2 -582
- data/app/assets/javascripts/foreman_scc_manager/locale/fr/foreman_scc_manager.js +1 -1
- data/app/assets/javascripts/foreman_scc_manager/locale/ja/foreman_scc_manager.js +348 -348
- data/app/assets/javascripts/foreman_scc_manager/locale/ka/foreman_scc_manager.js +381 -381
- data/app/assets/javascripts/foreman_scc_manager/locale/ko/foreman_scc_manager.js +592 -0
- data/app/assets/javascripts/foreman_scc_manager/locale/zh_CN/foreman_scc_manager.js +346 -346
- data/app/views/scc_accounts/_form.html.erb +2 -2
- data/lib/foreman_scc_manager/version.rb +1 -1
- data/locale/Makefile +12 -2
- data/locale/de/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/de/foreman_scc_manager.po +101 -98
- data/locale/el/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/el/foreman_scc_manager.po +25 -24
- data/locale/en/foreman_scc_manager.po +0 -593
- data/locale/fr/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/fr/foreman_scc_manager.po +1 -1
- data/locale/ja/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/ja/foreman_scc_manager.po +94 -92
- data/locale/ka/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/ka/foreman_scc_manager.po +139 -133
- data/locale/ko/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/ko/foreman_scc_manager.po +600 -0
- data/locale/zh_CN/LC_MESSAGES/foreman_scc_manager.mo +0 -0
- data/locale/zh_CN/foreman_scc_manager.po +92 -91
- data/package.json +6 -6
- data/test/controllers/api/v2/scc_accounts_test.rb +4 -4
- data/test/features/sync_test.rb +3 -3
- data/test/lib/scc_manager_test.rb +64 -0
- data/test/test_plugin_helper.rb +4 -1
- data/webpack/components/SCCProductPage/EmptySccProducts.js +7 -2
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCGenericPicker/index.js +238 -50
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/components/SCCRepoPicker/index.js +26 -12
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/components/SCCRepoPicker/styles.scss +2 -2
- data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/index.js +5 -3
- data/webpack/components/SCCProductPage/components/SCCProductPicker/index.js +48 -33
- data/webpack/components/SCCProductPage/components/SCCProductPicker/styles.scss +5 -5
- data/webpack/components/SCCProductPage/components/SCCProductPickerModal/index.js +13 -6
- data/webpack/components/SCCProductPage/components/SCCProductView/components/SCCRepoView/index.js +36 -23
- data/webpack/components/SCCProductPage/components/SCCProductView/components/SCCRepoView/styles.scss +10 -10
- data/webpack/components/SCCProductPage/components/SCCProductView/index.js +26 -8
- data/webpack/components/SCCProductPage/components/common/SCCGenericExpander/SCCGenericExpander.test.js +2 -2
- data/webpack/components/SCCProductPage/components/common/SCCGenericExpander/index.js +28 -10
- data/webpack/components/SCCProductPage/sccProductPage.scss +5 -5
- 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 {
|
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
|
-
|
7
|
-
|
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 [
|
13
|
-
const [
|
14
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
26
|
-
|
27
|
-
setIsOpen(!isOpen);
|
28
|
-
setGlobalSelected(value);
|
71
|
+
const resetActiveAndFocusedItem = () => {
|
72
|
+
setFocusedItemIndex(null);
|
73
|
+
setActiveItemId(null);
|
29
74
|
};
|
30
|
-
|
31
|
-
|
32
|
-
|
75
|
+
const closeMenu = () => {
|
76
|
+
setIsOpen(false);
|
77
|
+
resetActiveAndFocusedItem();
|
33
78
|
};
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
<
|
49
|
-
|
50
|
-
|
226
|
+
<Select
|
227
|
+
id={initialLabel}
|
228
|
+
ouiaId={initialLabel.concat('scc-product-picker-select')}
|
51
229
|
isOpen={isOpen}
|
52
|
-
|
53
|
-
onToggle={onToggle}
|
230
|
+
selected={selected}
|
54
231
|
onSelect={onSelect}
|
55
|
-
|
56
|
-
|
232
|
+
onOpenChange={(isOpenSelect) => {
|
233
|
+
!isOpenSelect && closeMenu();
|
234
|
+
}}
|
235
|
+
toggle={toggle}
|
236
|
+
shouldFocusFirstItemOnOpen={false}
|
57
237
|
>
|
58
|
-
{
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
-
|
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
|
-
|
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 {
|
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
|
-
|
67
|
-
|
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
|
-
|
144
|
-
|
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
|
-
|
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
|
}
|
data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCTreePicker/index.js
CHANGED
@@ -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
|
-
|
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
|
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 ===
|
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
|
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
|
-
|
144
|
-
|
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
|
-
|
161
|
-
|
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
|
-
|
178
|
-
|
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
|
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
|
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
|
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)}
|