foreman_scc_manager 5.0.4 → 5.2.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/app/assets/javascripts/foreman_scc_manager/locale/de/foreman_scc_manager.js +55 -256
  4. data/app/assets/javascripts/foreman_scc_manager/locale/el/foreman_scc_manager.js +43 -244
  5. data/app/assets/javascripts/foreman_scc_manager/locale/en/foreman_scc_manager.js +381 -2
  6. data/app/assets/javascripts/foreman_scc_manager/locale/fr/foreman_scc_manager.js +58 -259
  7. data/app/assets/javascripts/foreman_scc_manager/locale/ja/foreman_scc_manager.js +58 -259
  8. data/app/assets/javascripts/foreman_scc_manager/locale/ka/foreman_scc_manager.js +58 -259
  9. data/app/assets/javascripts/foreman_scc_manager/locale/ko/foreman_scc_manager.js +55 -256
  10. data/app/assets/javascripts/foreman_scc_manager/locale/zh_CN/foreman_scc_manager.js +58 -259
  11. data/app/controllers/api/v2/scc_accounts_controller.rb +4 -2
  12. data/app/controllers/scc_accounts_controller.rb +0 -3
  13. data/app/models/scc_account.rb +1 -1
  14. data/app/views/scc_accounts/edit.html.erb +24 -2
  15. data/app/views/scc_accounts/index.html.erb +14 -33
  16. data/app/views/scc_accounts/new.html.erb +12 -1
  17. data/lib/foreman_scc_manager/version.rb +1 -1
  18. data/locale/de/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  19. data/locale/de/foreman_scc_manager.po +55 -257
  20. data/locale/el/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  21. data/locale/el/foreman_scc_manager.po +44 -246
  22. data/locale/en/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  23. data/locale/en/foreman_scc_manager.po +392 -0
  24. data/locale/foreman_scc_manager.pot +195 -461
  25. data/locale/fr/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  26. data/locale/fr/foreman_scc_manager.po +58 -260
  27. data/locale/ja/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  28. data/locale/ja/foreman_scc_manager.po +58 -260
  29. data/locale/ka/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  30. data/locale/ka/foreman_scc_manager.po +58 -260
  31. data/locale/ko/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  32. data/locale/ko/foreman_scc_manager.po +55 -257
  33. data/locale/zh_CN/LC_MESSAGES/foreman_scc_manager.mo +0 -0
  34. data/locale/zh_CN/foreman_scc_manager.po +58 -260
  35. data/test/controllers/api/v2/scc_accounts_test.rb +5 -5
  36. data/webpack/components/SCCAccountForm/SCCAccountForm.scss +49 -0
  37. data/webpack/components/SCCAccountForm/SCCAccountFormActions.js +74 -0
  38. data/webpack/components/SCCAccountForm/components/DateTimeField.js +72 -0
  39. data/webpack/components/SCCAccountForm/components/SCCCredentialsCard.js +150 -0
  40. data/webpack/components/SCCAccountForm/components/SCCSyncSettingsCard.js +256 -0
  41. data/webpack/components/SCCAccountForm/components/SCCTokenRefreshCard.js +133 -0
  42. data/webpack/components/SCCAccountForm/index.js +306 -0
  43. data/webpack/components/SCCAccountIndex/SCCAccountIndex.scss +26 -0
  44. data/webpack/components/SCCAccountIndex/SCCAccountIndex.test.js +291 -0
  45. data/webpack/components/SCCAccountIndex/SCCAccountIndexActions.js +205 -0
  46. data/webpack/components/SCCAccountIndex/SCCAccountIndexConstants.js +9 -0
  47. data/webpack/components/SCCAccountIndex/index.js +262 -0
  48. data/webpack/components/SCCProductPage/EmptySccProducts.js +10 -7
  49. data/webpack/components/SCCProductPage/components/SCCProductPicker/components/SCCGenericPicker/index.js +25 -11
  50. data/webpack/components/SCCProductPage/components/SCCProductPicker/styles.scss +8 -3
  51. data/webpack/components/SCCProductPage/sccProductPage.scss +5 -0
  52. data/webpack/index.js +12 -0
  53. metadata +14 -18
  54. data/app/assets/javascripts/foreman_scc_manager/scc_accounts.js.coffee +0 -46
  55. data/app/views/scc_accounts/_form.html.erb +0 -51
@@ -0,0 +1,205 @@
1
+ import { APIActions } from 'foremanReact/redux/API';
2
+ import { translate as __ } from 'foremanReact/common/I18n';
3
+
4
+ import { INITIAL_DELAY, MAX_DELAY, BACKOFF } from './SCCAccountIndexConstants';
5
+
6
+ const isDone = (state, result) =>
7
+ state === 'stopped' || result === 'success' || result === 'error';
8
+
9
+ const nextDelay = (prevDelay, changed) => {
10
+ const base = changed ? INITIAL_DELAY : prevDelay;
11
+ const next = Math.min(Math.ceil(base * BACKOFF), MAX_DELAY);
12
+ return next;
13
+ };
14
+
15
+ const schedule = (taskTimeoutRef, taskId, ms, fn) => {
16
+ if (taskTimeoutRef.current[taskId])
17
+ clearTimeout(taskTimeoutRef.current[taskId]);
18
+ taskTimeoutRef.current[taskId] = setTimeout(fn, ms);
19
+ };
20
+
21
+ const deriveSyncStatus = (done, result, endedAt, state, fallback) => {
22
+ if (!done) return state || fallback;
23
+ return result === 'success' ? endedAt || __('finished') : __('error');
24
+ };
25
+
26
+ const checkUntilChanged = (
27
+ dispatch,
28
+ taskId,
29
+ accountId,
30
+ setAccounts,
31
+ taskTimeoutRef,
32
+ lastStateRef,
33
+ delay = INITIAL_DELAY
34
+ ) => {
35
+ if (!taskId) return;
36
+
37
+ dispatch(
38
+ APIActions.get({
39
+ key: `task_${taskId}`,
40
+ url: `/foreman_tasks/api/tasks/${taskId}`,
41
+ handleSuccess: (payload) => {
42
+ const task = payload?.data ?? payload;
43
+ const { state, result, ended_at: endedAt } = task || {};
44
+ const prev = lastStateRef.current[accountId];
45
+ const done = isDone(state, result);
46
+
47
+ setAccounts((prevState) =>
48
+ prevState.map((acc) => {
49
+ if (acc.id !== accountId) {
50
+ return acc;
51
+ }
52
+
53
+ const syncStatus = deriveSyncStatus(
54
+ done,
55
+ result,
56
+ endedAt,
57
+ state,
58
+ acc.sync_status
59
+ );
60
+ return {
61
+ ...acc,
62
+ sync_status: syncStatus,
63
+ sync_task: {
64
+ ...(acc.sync_task || {}),
65
+ id: taskId,
66
+ ended_at: endedAt,
67
+ },
68
+ };
69
+ })
70
+ );
71
+
72
+ lastStateRef.current[accountId] = state;
73
+
74
+ if (done) {
75
+ if (taskTimeoutRef.current[taskId])
76
+ clearTimeout(taskTimeoutRef.current[taskId]);
77
+ delete taskTimeoutRef.current[taskId];
78
+ delete lastStateRef.current[accountId];
79
+ return;
80
+ }
81
+
82
+ const changed = state !== prev;
83
+ const newDelay = nextDelay(delay, changed);
84
+
85
+ schedule(taskTimeoutRef, taskId, newDelay, () =>
86
+ checkUntilChanged(
87
+ dispatch,
88
+ taskId,
89
+ accountId,
90
+ setAccounts,
91
+ taskTimeoutRef,
92
+ lastStateRef,
93
+ newDelay
94
+ )
95
+ );
96
+ },
97
+ handleError: () => {
98
+ const newDelay = nextDelay(delay, false);
99
+ schedule(taskTimeoutRef, taskId, newDelay, () =>
100
+ checkUntilChanged(
101
+ dispatch,
102
+ taskId,
103
+ accountId,
104
+ setAccounts,
105
+ taskTimeoutRef,
106
+ lastStateRef,
107
+ newDelay
108
+ )
109
+ );
110
+ },
111
+ errorToast: () => null,
112
+ })
113
+ );
114
+ };
115
+
116
+ export const syncSccAccountAction = (
117
+ dispatch,
118
+ accountId,
119
+ setAccounts,
120
+ taskTimeoutRef,
121
+ lastStateRef
122
+ ) => {
123
+ if (!accountId) return;
124
+
125
+ dispatch(
126
+ APIActions.put({
127
+ key: `syncSccAccount_${accountId}`,
128
+ url: `/api/v2/scc_accounts/${accountId}/sync`,
129
+ successToast: () => __('Sync task started.'),
130
+ errorToast: () => __('Failed to start sync task.'),
131
+ handleSuccess: (resp) => {
132
+ const taskId = resp?.data?.id;
133
+ const initialState = resp?.data?.state || 'planned';
134
+
135
+ lastStateRef.current[accountId] = initialState;
136
+
137
+ setAccounts((prev) =>
138
+ prev.map((acc) =>
139
+ acc.id === accountId
140
+ ? {
141
+ ...acc,
142
+ sync_status: initialState || __('running'),
143
+ }
144
+ : acc
145
+ )
146
+ );
147
+
148
+ if (taskTimeoutRef.current[taskId]) {
149
+ clearTimeout(taskTimeoutRef.current[taskId]);
150
+ }
151
+ taskTimeoutRef.current[taskId] = setTimeout(() => {
152
+ checkUntilChanged(
153
+ dispatch,
154
+ taskId,
155
+ accountId,
156
+ setAccounts,
157
+ taskTimeoutRef,
158
+ lastStateRef
159
+ );
160
+ }, 15000);
161
+ },
162
+ handleError: () => {
163
+ setAccounts((prev) =>
164
+ prev.map((acc) =>
165
+ acc.id === accountId
166
+ ? {
167
+ ...acc,
168
+ sync_status: __('error'),
169
+ taskId: null,
170
+ }
171
+ : acc
172
+ )
173
+ );
174
+ },
175
+ })
176
+ );
177
+ };
178
+
179
+ export const deleteSccAccountAction = (
180
+ dispatch,
181
+ id,
182
+ setAccounts,
183
+ setDeleteOpen,
184
+ deletingIdRef
185
+ ) => {
186
+ if (!id) return;
187
+
188
+ dispatch(
189
+ APIActions.delete({
190
+ key: `deleteSccAccount_${id}`,
191
+ url: `/api/v2/scc_accounts/${id}`,
192
+ successToast: () => __('SCC account deleted successfully.'),
193
+ errorToast: () => __('Failed to delete SCC account.'),
194
+ handleSuccess: () => {
195
+ setAccounts((prev) => prev.filter((acc) => acc.id !== id));
196
+ setDeleteOpen(false);
197
+ deletingIdRef.current = null;
198
+ },
199
+ handleError: () => {
200
+ setDeleteOpen(false);
201
+ deletingIdRef.current = null;
202
+ },
203
+ })
204
+ );
205
+ };
@@ -0,0 +1,9 @@
1
+ import { translate as __ } from 'foremanReact/common/I18n';
2
+
3
+ export const WARN_DELETE = __(
4
+ 'WARNING: If you want to switch SCC accounts and retain the synchronized content, DO NOT delete your old SCC account, even if it is expired. Please change the login and password of your SCC account, instead.\n\nIf you delete your old SCC account, you CANNOT reuse existing repositories, products, content views, and composite content views.\n\n Do you Really want to delete this SCC account %acc_name?'
5
+ );
6
+
7
+ export const INITIAL_DELAY = 5000;
8
+ export const MAX_DELAY = 30000;
9
+ export const BACKOFF = 1.5;
@@ -0,0 +1,262 @@
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ PageSection,
5
+ Modal,
6
+ Button,
7
+ Dropdown,
8
+ DropdownList,
9
+ DropdownItem,
10
+ MenuToggle,
11
+ } from '@patternfly/react-core';
12
+ import { Table, Thead, Tr, Th, Td, Tbody } from '@patternfly/react-table';
13
+ import { EllipsisVIcon } from '@patternfly/react-icons';
14
+ import { useDispatch } from 'react-redux';
15
+ import { translate as __ } from 'foremanReact/common/I18n';
16
+ import { foremanUrl } from 'foremanReact/common/helpers';
17
+ import { WARN_DELETE } from './SCCAccountIndexConstants';
18
+ import {
19
+ syncSccAccountAction,
20
+ deleteSccAccountAction,
21
+ } from './SCCAccountIndexActions';
22
+ import './SCCAccountIndex.scss';
23
+
24
+ function SccAccountsIndex({ initialAccounts }) {
25
+ const dispatch = useDispatch();
26
+ const [deleteOpen, setDeleteOpen] = useState(false);
27
+ const [openMenuRow, setOpenMenuRow] = useState(null);
28
+ const [accounts, setAccounts] = useState(initialAccounts);
29
+ const [selectedAccountName, setSelectedAccountName] = useState(null);
30
+ const deletingIdRef = useRef(null);
31
+ const taskTimeoutRef = useRef({});
32
+ const lastStateRef = useRef({});
33
+
34
+ const handleSync = (accountId) => {
35
+ syncSccAccountAction(
36
+ dispatch,
37
+ accountId,
38
+ setAccounts,
39
+ taskTimeoutRef,
40
+ lastStateRef
41
+ );
42
+ };
43
+
44
+ const handleDelete = (id) => {
45
+ deleteSccAccountAction(
46
+ dispatch,
47
+ id,
48
+ setAccounts,
49
+ setDeleteOpen,
50
+ deletingIdRef
51
+ );
52
+ };
53
+
54
+ useEffect(
55
+ () => () => {
56
+ Object.values(taskTimeoutRef.current).forEach(clearTimeout);
57
+ taskTimeoutRef.current = {};
58
+ },
59
+ []
60
+ );
61
+
62
+ return (
63
+ <PageSection ouiaId="scc-accounts-index-page-section">
64
+ <div className="scc-account-add-container">
65
+ <Button
66
+ component="a"
67
+ href={foremanUrl('/scc_accounts/new')}
68
+ variant="primary"
69
+ ouiaId="scc-account-add-button"
70
+ >
71
+ {__('Add SCC account')}
72
+ </Button>
73
+ </div>
74
+
75
+ <Table
76
+ aria-label={__('SUSE subscriptions')}
77
+ ouiaId="scc-accounts-table"
78
+ variant="compact"
79
+ >
80
+ <Thead ouiaId="scc-accounts-table-head">
81
+ <Tr ouiaId="scc-accounts-table-header-row">
82
+ <Th ouiaId="scc-accounts-name-header">{__('Name')}</Th>
83
+ <Th ouiaId="scc-accounts-products-header">{__('Products')}</Th>
84
+ <Th ouiaId="scc-accounts-last-synced-header">
85
+ {__('Last synced')}
86
+ </Th>
87
+ <Th width={10} ouiaId="scc-accounts-actions-header">
88
+ {__('Actions')}
89
+ </Th>
90
+ </Tr>
91
+ </Thead>
92
+ <Tbody ouiaId="scc-accounts-table-body">
93
+ {accounts &&
94
+ accounts.map((acc) => {
95
+ const lastSynced = acc.sync_task ? (
96
+ <a
97
+ target="_blank"
98
+ href={foremanUrl(`/foreman_tasks/tasks/${acc.sync_task.id}`)}
99
+ rel="noreferrer"
100
+ >
101
+ {acc.sync_status}
102
+ </a>
103
+ ) : (
104
+ acc.sync_status || __('never synced')
105
+ );
106
+
107
+ return (
108
+ <Tr key={acc.id} ouiaId={`scc-account-row-${acc.id}`}>
109
+ <Td
110
+ dataLabel={__('Name')}
111
+ ouiaId={`scc-account-name-${acc.id}`}
112
+ >
113
+ <a href={`/scc_accounts/${acc.id}/edit`}>{acc.name}</a>
114
+ </Td>
115
+ <Td
116
+ dataLabel={__('Products')}
117
+ ouiaId={`scc-account-products-${acc.id}`}
118
+ >
119
+ {acc.scc_products_with_repos_count}
120
+ </Td>
121
+
122
+ <Td
123
+ dataLabel={__('Last synced')}
124
+ ouiaId={`scc-account-last-synced-${acc.id}`}
125
+ >
126
+ {lastSynced}
127
+ </Td>
128
+ <Td
129
+ dataLabel={__('Actions')}
130
+ ouiaId={`scc-account-actions-${acc.id}`}
131
+ >
132
+ <div className="scc-account-actions">
133
+ <Button
134
+ variant="primary"
135
+ size="sm"
136
+ onClick={() => {
137
+ window.location.href = `/scc_accounts/${acc.id}`;
138
+ }}
139
+ ouiaId={`scc-account-select-products-button-${acc.id}`}
140
+ >
141
+ {__('Select Products')}
142
+ </Button>
143
+
144
+ <Dropdown
145
+ isOpen={openMenuRow === acc.id}
146
+ onSelect={() => setOpenMenuRow(null)}
147
+ onOpenChange={(isOpen) =>
148
+ setOpenMenuRow(isOpen ? acc.id : null)
149
+ }
150
+ ouiaId={`scc-account-actions-dropdown-${acc.id}`}
151
+ toggle={(toggleRef) => (
152
+ <MenuToggle
153
+ ref={toggleRef}
154
+ aria-label={__('Actions menu')}
155
+ variant="plain"
156
+ isExpanded={openMenuRow === acc.id}
157
+ onClick={() =>
158
+ setOpenMenuRow(
159
+ openMenuRow === acc.id ? null : acc.id
160
+ )
161
+ }
162
+ ouiaId={`scc-account-actions-menu-toggle-${acc.id}`}
163
+ >
164
+ <EllipsisVIcon />
165
+ </MenuToggle>
166
+ )}
167
+ >
168
+ <DropdownList
169
+ ouiaId={`scc-account-actions-dropdown-list-${acc.id}`}
170
+ >
171
+ <DropdownItem
172
+ key="sync"
173
+ isDisabled={
174
+ acc.sync_status === 'running' ||
175
+ acc.sync_status === 'planned'
176
+ }
177
+ onClick={() => {
178
+ setOpenMenuRow(null);
179
+ handleSync(acc.id);
180
+ }}
181
+ ouiaId={`scc-account-sync-item-${acc.id}`}
182
+ >
183
+ {acc.sync_status === 'running' ||
184
+ acc.sync_status === 'planned'
185
+ ? __('Syncing...')
186
+ : __('Sync')}
187
+ </DropdownItem>
188
+
189
+ <DropdownItem
190
+ key="delete"
191
+ onClick={() => {
192
+ setOpenMenuRow(null);
193
+ deletingIdRef.current = acc.id;
194
+ setDeleteOpen(true);
195
+ setSelectedAccountName(acc.name);
196
+ }}
197
+ ouiaId={`scc-account-delete-item-${acc.id}`}
198
+ >
199
+ {__('Delete')}
200
+ </DropdownItem>
201
+ </DropdownList>
202
+ </Dropdown>
203
+ </div>
204
+ </Td>
205
+ </Tr>
206
+ );
207
+ })}
208
+ </Tbody>
209
+ </Table>
210
+
211
+ <Modal
212
+ title={__('Delete SCC Account')}
213
+ isOpen={deleteOpen}
214
+ onClose={() => setDeleteOpen(false)}
215
+ variant="small"
216
+ ouiaId="scc-account-delete-modal"
217
+ actions={[
218
+ <Button
219
+ key="confirm"
220
+ variant="danger"
221
+ onClick={() => handleDelete(deletingIdRef.current)}
222
+ ouiaId="scc-account-delete-confirm-button"
223
+ >
224
+ {__('Delete')}
225
+ </Button>,
226
+ <Button
227
+ key="cancel"
228
+ variant="link"
229
+ onClick={() => setDeleteOpen(false)}
230
+ ouiaId="scc-account-delete-cancel-button"
231
+ >
232
+ {__('Cancel')}
233
+ </Button>,
234
+ ]}
235
+ >
236
+ <div className="scc-account-delete-warning">
237
+ {WARN_DELETE.replace('%acc_name', selectedAccountName || '')}
238
+ </div>
239
+ </Modal>
240
+ </PageSection>
241
+ );
242
+ }
243
+
244
+ SccAccountsIndex.propTypes = {
245
+ initialAccounts: PropTypes.arrayOf(
246
+ PropTypes.shape({
247
+ id: PropTypes.number.isRequired,
248
+ name: PropTypes.string.isRequired,
249
+ sync_status: PropTypes.string,
250
+ sync_task: PropTypes.shape({
251
+ id: PropTypes.string,
252
+ }),
253
+ scc_products_with_repos_count: PropTypes.number,
254
+ })
255
+ ),
256
+ };
257
+
258
+ SccAccountsIndex.defaultProps = {
259
+ initialAccounts: [],
260
+ };
261
+
262
+ export default SccAccountsIndex;
@@ -5,6 +5,7 @@ import { Button } from '@patternfly/react-core';
5
5
  import { translate as __ } from 'foremanReact/common/I18n';
6
6
  import EmptyState from 'foremanReact/components/common/EmptyState';
7
7
  import { syncSccAccountAction } from './SCCProductPageActions';
8
+ import './sccProductPage.scss';
8
9
 
9
10
  export const EmptySccProducts = ({ canCreate, sccAccountId }) => {
10
11
  const dispatch = useDispatch();
@@ -27,13 +28,15 @@ export const EmptySccProducts = ({ canCreate, sccAccountId }) => {
27
28
  'https://docs.orcharhino.com/or/docs/sources/usage_guides/managing_sles_systems_guide.html#mssg_adding_scc_accounts',
28
29
  }}
29
30
  />
30
- <Button
31
- onClick={onSyncStart}
32
- ouiaId="scc-manager-welcome-sync-products"
33
- className="btn btn-primary"
34
- >
35
- {__('Synchronize SUSE Account')}
36
- </Button>
31
+ <div className="scc-sync-button-container">
32
+ <Button
33
+ onClick={onSyncStart}
34
+ ouiaId="scc-manager-welcome-sync-products"
35
+ className="btn btn-primary"
36
+ >
37
+ {__('Synchronize SUSE Account')}
38
+ </Button>
39
+ </div>
37
40
  </>
38
41
  );
39
42
  };
@@ -14,6 +14,7 @@ import {
14
14
  } from '@patternfly/react-core';
15
15
  import { TimesIcon } from '@patternfly/react-icons';
16
16
  import { translate as __ } from 'foremanReact/common/I18n';
17
+ import '../../../SCCProductPicker/styles.scss';
17
18
 
18
19
  const GenericSelector = ({
19
20
  initialSelectOptions,
@@ -234,18 +235,31 @@ const GenericSelector = ({
234
235
  }}
235
236
  toggle={toggle}
236
237
  shouldFocusFirstItemOnOpen={false}
238
+ popperProps={{
239
+ direction: 'down',
240
+ appendTo: () => document.body,
241
+ }}
237
242
  >
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
- ))}
243
+ <SelectList
244
+ id={initialLabel.concat('select-typeahead-listbox')}
245
+ isAriaMultiselectable={false}
246
+ className="product-picker__select-list"
247
+ >
248
+ {selectOptions.length > 0 ? (
249
+ selectOptions.map((option, index) => (
250
+ <SelectOption
251
+ key={option.value || option.children}
252
+ isFocused={focusedItemIndex === index}
253
+ id={createItemId(option.value)}
254
+ className={option.className}
255
+ {...option}
256
+ />
257
+ ))
258
+ ) : (
259
+ <SelectOption isDisabled key="no-options">
260
+ {__('No options available')}
261
+ </SelectOption>
262
+ )}
249
263
  </SelectList>
250
264
  </Select>
251
265
  );
@@ -3,8 +3,13 @@
3
3
  .pf-v5-c-select__toggle {
4
4
  font-size: var(--pf-v5-global--FontSize--xs);
5
5
  font-weight: var(--pf-v5-global--FontWeight--bold);
6
- };
6
+ }
7
7
 
8
8
  .pf-v5-c-switch__input ~ .pf-v5-c-switch__label {
9
- font-size: var(--pf-v5-global--FontSize--xs);
10
- };
9
+ font-size: var(--pf-v5-global--FontSize--xs);
10
+ }
11
+
12
+ .product-picker__select-list {
13
+ max-height: 200px;
14
+ overflow-y: auto;
15
+ }
@@ -6,3 +6,8 @@
6
6
  --pf-v5-c-tile--PaddingBottom: var(--pf-v5-global--spacer--xs);
7
7
  --pf-v5-c-tile--PaddingLeft: var(--pf-v5-global--spacer--xs);
8
8
  }
9
+
10
+ .scc-sync-button-container {
11
+ display: flex;
12
+ justify-content: center;
13
+ }
data/webpack/index.js CHANGED
@@ -2,6 +2,18 @@ import componentRegistry from 'foremanReact/components/componentRegistry';
2
2
  import injectReducer from 'foremanReact/redux/reducers/registerReducer';
3
3
  import SCCProductPage from './components/SCCProductPage';
4
4
  import reducer from './reducer';
5
+ import SCCAccountForm from './components/SCCAccountForm';
6
+ import SCCAccountIndex from './components/SCCAccountIndex';
7
+
8
+ componentRegistry.register({
9
+ name: 'SCCAccountForm',
10
+ type: SCCAccountForm,
11
+ });
12
+
13
+ componentRegistry.register({
14
+ name: 'SCCAccountIndex',
15
+ type: SCCAccountIndex,
16
+ });
5
17
 
6
18
  componentRegistry.register({
7
19
  name: 'SCCProductPage',
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_scc_manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.4
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ATIX AG
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-09-16 00:00:00.000000000 Z
10
+ date: 2025-11-03 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rdoc
@@ -57,20 +57,6 @@ dependencies:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
59
  version: '0'
60
- - !ruby/object:Gem::Dependency
61
- name: coffee-rails
62
- requirement: !ruby/object:Gem::Requirement
63
- requirements:
64
- - - "~>"
65
- - !ruby/object:Gem::Version
66
- version: 5.0.0
67
- type: :runtime
68
- prerelease: false
69
- version_requirements: !ruby/object:Gem::Requirement
70
- requirements:
71
- - - "~>"
72
- - !ruby/object:Gem::Version
73
- version: 5.0.0
74
60
  - !ruby/object:Gem::Dependency
75
61
  name: katello
76
62
  requirement: !ruby/object:Gem::Requirement
@@ -104,7 +90,6 @@ files:
104
90
  - app/assets/javascripts/foreman_scc_manager/locale/ka/foreman_scc_manager.js
105
91
  - app/assets/javascripts/foreman_scc_manager/locale/ko/foreman_scc_manager.js
106
92
  - app/assets/javascripts/foreman_scc_manager/locale/zh_CN/foreman_scc_manager.js
107
- - app/assets/javascripts/foreman_scc_manager/scc_accounts.js.coffee
108
93
  - app/controllers/api/v2/scc_accounts_controller.rb
109
94
  - app/controllers/api/v2/scc_products_controller.rb
110
95
  - app/controllers/scc_accounts_controller.rb
@@ -133,7 +118,6 @@ files:
133
118
  - app/views/api/v2/scc_products/main.json.rabl
134
119
  - app/views/api/v2/scc_products/show.json.rabl
135
120
  - app/views/scc_account_sync_plan_task_groups/_scc_account_sync_plan_task_groups.html.erb
136
- - app/views/scc_accounts/_form.html.erb
137
121
  - app/views/scc_accounts/edit.html.erb
138
122
  - app/views/scc_accounts/index.html.erb
139
123
  - app/views/scc_accounts/new.html.erb
@@ -212,6 +196,18 @@ files:
212
196
  - test/support/fixtures_support.rb
213
197
  - test/test_plugin_helper.rb
214
198
  - test/unit/foreman_scc_manager_test.rb
199
+ - webpack/components/SCCAccountForm/SCCAccountForm.scss
200
+ - webpack/components/SCCAccountForm/SCCAccountFormActions.js
201
+ - webpack/components/SCCAccountForm/components/DateTimeField.js
202
+ - webpack/components/SCCAccountForm/components/SCCCredentialsCard.js
203
+ - webpack/components/SCCAccountForm/components/SCCSyncSettingsCard.js
204
+ - webpack/components/SCCAccountForm/components/SCCTokenRefreshCard.js
205
+ - webpack/components/SCCAccountForm/index.js
206
+ - webpack/components/SCCAccountIndex/SCCAccountIndex.scss
207
+ - webpack/components/SCCAccountIndex/SCCAccountIndex.test.js
208
+ - webpack/components/SCCAccountIndex/SCCAccountIndexActions.js
209
+ - webpack/components/SCCAccountIndex/SCCAccountIndexConstants.js
210
+ - webpack/components/SCCAccountIndex/index.js
215
211
  - webpack/components/SCCProductPage/EmptySccProducts.js
216
212
  - webpack/components/SCCProductPage/SCCProductPage.js
217
213
  - webpack/components/SCCProductPage/SCCProductPageActions.js