foreman_resource_quota 0.3.1 → 0.5.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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -6
  3. data/app/assets/javascripts/foreman_resource_quota/locale/bn/foreman_resource_quota.js +213 -0
  4. data/app/assets/javascripts/foreman_resource_quota/locale/bn_IN/foreman_resource_quota.js +214 -0
  5. data/app/assets/javascripts/foreman_resource_quota/locale/bqi/foreman_resource_quota.js +213 -0
  6. data/app/assets/javascripts/foreman_resource_quota/locale/ca/foreman_resource_quota.js +214 -0
  7. data/app/assets/javascripts/foreman_resource_quota/locale/cs_CZ/foreman_resource_quota.js +214 -0
  8. data/app/assets/javascripts/foreman_resource_quota/locale/de/foreman_resource_quota.js +214 -0
  9. data/app/assets/javascripts/foreman_resource_quota/locale/de_AT/foreman_resource_quota.js +213 -0
  10. data/app/assets/javascripts/foreman_resource_quota/locale/de_DE/foreman_resource_quota.js +214 -0
  11. data/app/assets/javascripts/foreman_resource_quota/locale/el/foreman_resource_quota.js +214 -0
  12. data/app/assets/javascripts/foreman_resource_quota/locale/en/foreman_resource_quota.js +214 -0
  13. data/app/assets/javascripts/foreman_resource_quota/locale/en_GB/foreman_resource_quota.js +214 -0
  14. data/app/assets/javascripts/foreman_resource_quota/locale/en_US/foreman_resource_quota.js +213 -0
  15. data/app/assets/javascripts/foreman_resource_quota/locale/es/foreman_resource_quota.js +214 -0
  16. data/app/assets/javascripts/foreman_resource_quota/locale/et_EE/foreman_resource_quota.js +213 -0
  17. data/app/assets/javascripts/foreman_resource_quota/locale/fr/foreman_resource_quota.js +214 -0
  18. data/app/assets/javascripts/foreman_resource_quota/locale/gl/foreman_resource_quota.js +214 -0
  19. data/app/assets/javascripts/foreman_resource_quota/locale/gu/foreman_resource_quota.js +214 -0
  20. data/app/assets/javascripts/foreman_resource_quota/locale/he_IL/foreman_resource_quota.js +213 -0
  21. data/app/assets/javascripts/foreman_resource_quota/locale/hi/foreman_resource_quota.js +214 -0
  22. data/app/assets/javascripts/foreman_resource_quota/locale/id/foreman_resource_quota.js +214 -0
  23. data/app/assets/javascripts/foreman_resource_quota/locale/it/foreman_resource_quota.js +214 -0
  24. data/app/assets/javascripts/foreman_resource_quota/locale/ja/foreman_resource_quota.js +214 -0
  25. data/app/assets/javascripts/foreman_resource_quota/locale/ka/foreman_resource_quota.js +214 -0
  26. data/app/assets/javascripts/foreman_resource_quota/locale/kn/foreman_resource_quota.js +214 -0
  27. data/app/assets/javascripts/foreman_resource_quota/locale/ko/foreman_resource_quota.js +214 -0
  28. data/app/assets/javascripts/foreman_resource_quota/locale/ml_IN/foreman_resource_quota.js +213 -0
  29. data/app/assets/javascripts/foreman_resource_quota/locale/mr/foreman_resource_quota.js +214 -0
  30. data/app/assets/javascripts/foreman_resource_quota/locale/nl_NL/foreman_resource_quota.js +214 -0
  31. data/app/assets/javascripts/foreman_resource_quota/locale/or/foreman_resource_quota.js +214 -0
  32. data/app/assets/javascripts/foreman_resource_quota/locale/pa/foreman_resource_quota.js +214 -0
  33. data/app/assets/javascripts/foreman_resource_quota/locale/pl/foreman_resource_quota.js +214 -0
  34. data/app/assets/javascripts/foreman_resource_quota/locale/pl_PL/foreman_resource_quota.js +213 -0
  35. data/app/assets/javascripts/foreman_resource_quota/locale/pt/foreman_resource_quota.js +213 -0
  36. data/app/assets/javascripts/foreman_resource_quota/locale/pt_BR/foreman_resource_quota.js +214 -0
  37. data/app/assets/javascripts/foreman_resource_quota/locale/ro/foreman_resource_quota.js +213 -0
  38. data/app/assets/javascripts/foreman_resource_quota/locale/ro_RO/foreman_resource_quota.js +213 -0
  39. data/app/assets/javascripts/foreman_resource_quota/locale/ru/foreman_resource_quota.js +214 -0
  40. data/app/assets/javascripts/foreman_resource_quota/locale/sl/foreman_resource_quota.js +214 -0
  41. data/app/assets/javascripts/foreman_resource_quota/locale/sv_SE/foreman_resource_quota.js +214 -0
  42. data/app/assets/javascripts/foreman_resource_quota/locale/ta/foreman_resource_quota.js +213 -0
  43. data/app/assets/javascripts/foreman_resource_quota/locale/ta_IN/foreman_resource_quota.js +214 -0
  44. data/app/assets/javascripts/foreman_resource_quota/locale/te/foreman_resource_quota.js +214 -0
  45. data/app/assets/javascripts/foreman_resource_quota/locale/tr/foreman_resource_quota.js +213 -0
  46. data/app/assets/javascripts/foreman_resource_quota/locale/vi/foreman_resource_quota.js +213 -0
  47. data/app/assets/javascripts/foreman_resource_quota/locale/vi_VN/foreman_resource_quota.js +213 -0
  48. data/app/assets/javascripts/foreman_resource_quota/locale/zh/foreman_resource_quota.js +213 -0
  49. data/app/assets/javascripts/foreman_resource_quota/locale/zh_CN/foreman_resource_quota.js +214 -0
  50. data/app/assets/javascripts/foreman_resource_quota/locale/zh_TW/foreman_resource_quota.js +214 -0
  51. data/app/controllers/foreman_resource_quota/api/v2/resource_quotas_controller.rb +17 -10
  52. data/app/controllers/foreman_resource_quota/concerns/api/v2/hosts_controller_extensions.rb +20 -0
  53. data/app/controllers/foreman_resource_quota/concerns/api/v2/usergroups_controller_extensions.rb +19 -0
  54. data/app/controllers/foreman_resource_quota/concerns/api/v2/users_controller_extensions.rb +22 -0
  55. data/app/models/concerns/foreman_resource_quota/host_managed_extensions.rb +9 -7
  56. data/app/views/foreman_resource_quota/api/v2/users/resource_quota.json.rabl +1 -1
  57. data/app/views/foreman_resource_quota/resource_quotas/index.html.erb +1 -1
  58. data/config/initializers/inflections.rb +1 -0
  59. data/lib/foreman_resource_quota/engine.rb +8 -1
  60. data/lib/foreman_resource_quota/register.rb +4 -2
  61. data/lib/foreman_resource_quota/version.rb +1 -1
  62. data/lib/tasks/foreman_resource_quota_tasks.rake +3 -3
  63. data/locale/Makefile +19 -6
  64. data/locale/bn/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  65. data/locale/bn/foreman_resource_quota.po +214 -0
  66. data/locale/bn_IN/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  67. data/locale/bn_IN/foreman_resource_quota.po +219 -0
  68. data/locale/bqi/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  69. data/locale/bqi/foreman_resource_quota.po +215 -0
  70. data/locale/ca/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  71. data/locale/ca/foreman_resource_quota.po +218 -0
  72. data/locale/cs_CZ/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  73. data/locale/cs_CZ/foreman_resource_quota.po +221 -0
  74. data/locale/de/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  75. data/locale/de/foreman_resource_quota.po +223 -0
  76. data/locale/de_AT/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  77. data/locale/de_AT/foreman_resource_quota.po +215 -0
  78. data/locale/de_DE/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  79. data/locale/de_DE/foreman_resource_quota.po +219 -0
  80. data/locale/el/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  81. data/locale/el/foreman_resource_quota.po +218 -0
  82. data/locale/en/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  83. data/locale/en/foreman_resource_quota.po +207 -9
  84. data/locale/en_GB/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  85. data/locale/en_GB/foreman_resource_quota.po +220 -0
  86. data/locale/en_US/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  87. data/locale/en_US/foreman_resource_quota.po +215 -0
  88. data/locale/es/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  89. data/locale/es/foreman_resource_quota.po +223 -0
  90. data/locale/et_EE/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  91. data/locale/et_EE/foreman_resource_quota.po +215 -0
  92. data/locale/foreman_resource_quota.pot +322 -8
  93. data/locale/fr/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  94. data/locale/fr/foreman_resource_quota.po +222 -0
  95. data/locale/gl/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  96. data/locale/gl/foreman_resource_quota.po +218 -0
  97. data/locale/gu/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  98. data/locale/gu/foreman_resource_quota.po +218 -0
  99. data/locale/he_IL/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  100. data/locale/he_IL/foreman_resource_quota.po +216 -0
  101. data/locale/hi/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  102. data/locale/hi/foreman_resource_quota.po +218 -0
  103. data/locale/id/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  104. data/locale/id/foreman_resource_quota.po +218 -0
  105. data/locale/it/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  106. data/locale/it/foreman_resource_quota.po +221 -0
  107. data/locale/ja/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  108. data/locale/ja/foreman_resource_quota.po +219 -0
  109. data/locale/ka/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  110. data/locale/ka/foreman_resource_quota.po +218 -0
  111. data/locale/kn/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  112. data/locale/kn/foreman_resource_quota.po +218 -0
  113. data/locale/ko/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  114. data/locale/ko/foreman_resource_quota.po +220 -0
  115. data/locale/ml_IN/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  116. data/locale/ml_IN/foreman_resource_quota.po +215 -0
  117. data/locale/mr/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  118. data/locale/mr/foreman_resource_quota.po +218 -0
  119. data/locale/nl_NL/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  120. data/locale/nl_NL/foreman_resource_quota.po +223 -0
  121. data/locale/or/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  122. data/locale/or/foreman_resource_quota.po +218 -0
  123. data/locale/pa/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  124. data/locale/pa/foreman_resource_quota.po +219 -0
  125. data/locale/pl/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  126. data/locale/pl/foreman_resource_quota.po +221 -0
  127. data/locale/pl_PL/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  128. data/locale/pl_PL/foreman_resource_quota.po +217 -0
  129. data/locale/pt/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  130. data/locale/pt/foreman_resource_quota.po +215 -0
  131. data/locale/pt_BR/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  132. data/locale/pt_BR/foreman_resource_quota.po +222 -0
  133. data/locale/ro/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  134. data/locale/ro/foreman_resource_quota.po +215 -0
  135. data/locale/ro_RO/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  136. data/locale/ro_RO/foreman_resource_quota.po +216 -0
  137. data/locale/ru/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  138. data/locale/ru/foreman_resource_quota.po +222 -0
  139. data/locale/sl/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  140. data/locale/sl/foreman_resource_quota.po +219 -0
  141. data/locale/sv_SE/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  142. data/locale/sv_SE/foreman_resource_quota.po +221 -0
  143. data/locale/ta/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  144. data/locale/ta/foreman_resource_quota.po +214 -0
  145. data/locale/ta_IN/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  146. data/locale/ta_IN/foreman_resource_quota.po +219 -0
  147. data/locale/te/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  148. data/locale/te/foreman_resource_quota.po +218 -0
  149. data/locale/tr/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  150. data/locale/tr/foreman_resource_quota.po +214 -0
  151. data/locale/vi/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  152. data/locale/vi/foreman_resource_quota.po +214 -0
  153. data/locale/vi_VN/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  154. data/locale/vi_VN/foreman_resource_quota.po +215 -0
  155. data/locale/zh/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  156. data/locale/zh/foreman_resource_quota.po +214 -0
  157. data/locale/zh_CN/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  158. data/locale/zh_CN/foreman_resource_quota.po +221 -0
  159. data/locale/zh_TW/LC_MESSAGES/foreman_resource_quota.mo +0 -0
  160. data/locale/zh_TW/foreman_resource_quota.po +220 -0
  161. data/package.json +10 -10
  162. data/webpack/components/ResourceQuotaEmptyState/__test__/ResourceQuotaEmptyState.test.js +35 -0
  163. data/webpack/components/ResourceQuotaEmptyState/__test__/__snapshots__/ResourceQuotaEmptyState.test.js.snap +81 -0
  164. data/webpack/components/ResourceQuotaEmptyState/index.js +20 -3
  165. data/webpack/components/ResourceQuotaForm/ResourceQuotaForm.scss +1 -1
  166. data/webpack/components/ResourceQuotaForm/ResourceQuotaFormConstants.js +6 -6
  167. data/webpack/components/ResourceQuotaForm/components/Properties/Properties.scss +4 -3
  168. data/webpack/components/ResourceQuotaForm/components/Properties/StaticDetail.js +2 -2
  169. data/webpack/components/ResourceQuotaForm/components/Properties/TextInputField.js +1 -1
  170. data/webpack/components/ResourceQuotaForm/components/Properties/index.js +77 -63
  171. data/webpack/components/ResourceQuotaForm/components/Resource/Resource.scss +5 -5
  172. data/webpack/components/ResourceQuotaForm/components/Resource/UnitInputField.js +97 -52
  173. data/webpack/components/ResourceQuotaForm/components/Resource/UnitInputField.scss +7 -0
  174. data/webpack/components/ResourceQuotaForm/components/Resource/UtilizationProgress.js +1 -1
  175. data/webpack/components/ResourceQuotaForm/components/Resource/UtilizationProgress.scss +4 -4
  176. data/webpack/components/ResourceQuotaForm/components/Resource/__test__/UnitInputField.test.js +108 -0
  177. data/webpack/components/ResourceQuotaForm/components/Resource/__test__/__snapshots__/UnitInputField.test.js.snap +153 -0
  178. data/webpack/components/ResourceQuotaForm/components/Resource/index.js +25 -18
  179. data/webpack/components/ResourceQuotaForm/components/Submit.js +1 -1
  180. data/webpack/lib/ActionableDetail.scss +1 -1
  181. data/webpack/lib/EditableSwitch.js +1 -1
  182. data/webpack/lib/EditableTextInput/EditableTextInput.js +81 -77
  183. data/webpack/lib/EditableTextInput/editableTextInput.scss +30 -28
  184. data/webpack/test_helper.js +49 -0
  185. metadata +161 -9
@@ -0,0 +1,108 @@
1
+ import React from 'react';
2
+ import '@testing-library/jest-dom';
3
+ import { render, screen, fireEvent } from '@testing-library/react';
4
+
5
+ import { testComponentSnapshotsWithFixtures } from '@theforeman/test';
6
+ import LabelIcon from 'foremanReact/components/common/LabelIcon';
7
+
8
+ import UnitInputField from '../UnitInputField';
9
+
10
+ const getDefaultProps = () => ({
11
+ initialValue: 0,
12
+ onChange: jest.fn(),
13
+ isDisabled: false,
14
+ handleInputValidation: jest.fn(),
15
+ units: [
16
+ { symbol: 'MiB', factor: 1 },
17
+ { symbol: 'GiB', factor: 1024 },
18
+ ],
19
+ labelIcon: <LabelIcon text="Descriptive title." />,
20
+ minValue: 0,
21
+ maxValue: 5,
22
+ });
23
+
24
+ const fixtureDefault = {
25
+ 'should render default': {
26
+ ...getDefaultProps(),
27
+ },
28
+ };
29
+
30
+ const fixtureSingleUnit = {
31
+ 'should render without dropdown (single unit)': {
32
+ ...getDefaultProps(),
33
+ units: [{ symbol: 'cores', factor: 1 }],
34
+ },
35
+ };
36
+
37
+ const fixtureDisabled = {
38
+ 'should render as disabled field': {
39
+ ...getDefaultProps(),
40
+ isDisabled: true,
41
+ },
42
+ };
43
+
44
+ describe('UnitInputField', () => {
45
+ testComponentSnapshotsWithFixtures(UnitInputField, fixtureDefault);
46
+ testComponentSnapshotsWithFixtures(UnitInputField, fixtureSingleUnit);
47
+ testComponentSnapshotsWithFixtures(UnitInputField, fixtureDisabled);
48
+
49
+ it('triggers handleInputValidation on unit change', async () => {
50
+ const props = getDefaultProps();
51
+
52
+ render(<UnitInputField {...props} />);
53
+ const input = screen.getByRole('textbox');
54
+ fireEvent.change(input, { target: { value: 3 } });
55
+
56
+ // gets called (1.) with initialValue and (2.) the simulated change
57
+ expect(props.onChange).toHaveBeenCalledTimes(2);
58
+ expect(props.onChange).toHaveBeenCalledWith(props.initialValue);
59
+ expect(props.onChange).toHaveBeenLastCalledWith(3);
60
+ expect(props.handleInputValidation).toHaveBeenCalledTimes(2);
61
+ expect(props.handleInputValidation).toHaveBeenCalledWith(true);
62
+ });
63
+
64
+ test('triggers onChange with rounded value', () => {
65
+ const props = getDefaultProps();
66
+
67
+ render(<UnitInputField {...props} />);
68
+ const input = screen.getByRole('textbox');
69
+ fireEvent.change(input, { target: { value: 3.5 } });
70
+
71
+ // gets called (1.) with initialValue and (2.) the simulated change
72
+ expect(props.onChange).toHaveBeenCalledTimes(2);
73
+ expect(props.onChange).toHaveBeenCalledWith(props.initialValue);
74
+ expect(props.onChange).toHaveBeenLastCalledWith(3);
75
+ expect(props.handleInputValidation).toHaveBeenCalledTimes(2);
76
+ expect(props.handleInputValidation).toHaveBeenCalledWith(true);
77
+ });
78
+
79
+ test('does not trigger onChange when value out of bounds', () => {
80
+ const props = getDefaultProps();
81
+
82
+ render(<UnitInputField {...props} />);
83
+ const input = screen.getByRole('textbox');
84
+ fireEvent.change(input, { target: { value: props.maxValue + 1 } });
85
+
86
+ // onChange only called for initialValue
87
+ expect(props.onChange).toHaveBeenCalledTimes(1);
88
+ expect(props.onChange).toHaveBeenCalledWith(props.initialValue);
89
+ // handleInputValidation called with false => invalid
90
+ expect(props.handleInputValidation).toHaveBeenCalledTimes(2);
91
+ expect(props.handleInputValidation).toHaveBeenLastCalledWith(false);
92
+ });
93
+
94
+ test('does not trigger onChange when value is not a number', () => {
95
+ const props = getDefaultProps();
96
+
97
+ render(<UnitInputField {...props} />);
98
+ const input = screen.getByRole('textbox');
99
+ fireEvent.change(input, { target: { value: 'no number' } });
100
+
101
+ // onChange only called for initialValue
102
+ expect(props.onChange).toHaveBeenCalledTimes(1);
103
+ expect(props.onChange).toHaveBeenCalledWith(props.initialValue);
104
+ // handleInputValidation called with false => invalid
105
+ expect(props.handleInputValidation).toHaveBeenCalledTimes(2);
106
+ expect(props.handleInputValidation).toHaveBeenLastCalledWith(false);
107
+ });
108
+ });
@@ -0,0 +1,153 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`UnitInputField should render as disabled field 1`] = `
4
+ <div
5
+ className="container-unit-input-field"
6
+ >
7
+ <FormGroup
8
+ fieldId="quota-limit-resource-quota-form-group"
9
+ label="Quota Limit"
10
+ labelIcon={
11
+ <LabelIcon
12
+ text="Descriptive title."
13
+ />
14
+ }
15
+ validated="default"
16
+ >
17
+ <InputGroup>
18
+ <InputGroupItem>
19
+ <TextInput
20
+ id="reg_token_life_time_input"
21
+ isDisabled={true}
22
+ max={5}
23
+ min={0}
24
+ onChange={[Function]}
25
+ validated="default"
26
+ value={0}
27
+ />
28
+ </InputGroupItem>
29
+ <InputGroupItem>
30
+ <Dropdown
31
+ dropdownItems={
32
+ Array [
33
+ <DropdownItem
34
+ id="unit-dropdownitem-mib"
35
+ >
36
+ MiB
37
+ </DropdownItem>,
38
+ <DropdownItem
39
+ id="unit-dropdownitem-gib"
40
+ >
41
+ GiB
42
+ </DropdownItem>,
43
+ ]
44
+ }
45
+ isOpen={false}
46
+ onSelect={[Function]}
47
+ toggle={
48
+ <DropdownToggle
49
+ isDisabled={true}
50
+ onToggle={[Function]}
51
+ >
52
+ MiB
53
+ </DropdownToggle>
54
+ }
55
+ />
56
+ </InputGroupItem>
57
+ </InputGroup>
58
+ </FormGroup>
59
+ </div>
60
+ `;
61
+
62
+ exports[`UnitInputField should render default 1`] = `
63
+ <div
64
+ className="container-unit-input-field"
65
+ >
66
+ <FormGroup
67
+ fieldId="quota-limit-resource-quota-form-group"
68
+ label="Quota Limit"
69
+ labelIcon={
70
+ <LabelIcon
71
+ text="Descriptive title."
72
+ />
73
+ }
74
+ validated="default"
75
+ >
76
+ <InputGroup>
77
+ <InputGroupItem>
78
+ <TextInput
79
+ id="reg_token_life_time_input"
80
+ isDisabled={false}
81
+ max={5}
82
+ min={0}
83
+ onChange={[Function]}
84
+ validated="default"
85
+ value={0}
86
+ />
87
+ </InputGroupItem>
88
+ <InputGroupItem>
89
+ <Dropdown
90
+ dropdownItems={
91
+ Array [
92
+ <DropdownItem
93
+ id="unit-dropdownitem-mib"
94
+ >
95
+ MiB
96
+ </DropdownItem>,
97
+ <DropdownItem
98
+ id="unit-dropdownitem-gib"
99
+ >
100
+ GiB
101
+ </DropdownItem>,
102
+ ]
103
+ }
104
+ isOpen={false}
105
+ onSelect={[Function]}
106
+ toggle={
107
+ <DropdownToggle
108
+ isDisabled={false}
109
+ onToggle={[Function]}
110
+ >
111
+ MiB
112
+ </DropdownToggle>
113
+ }
114
+ />
115
+ </InputGroupItem>
116
+ </InputGroup>
117
+ </FormGroup>
118
+ </div>
119
+ `;
120
+
121
+ exports[`UnitInputField should render without dropdown (single unit) 1`] = `
122
+ <div
123
+ className="container-unit-input-field"
124
+ >
125
+ <FormGroup
126
+ fieldId="quota-limit-resource-quota-form-group"
127
+ label="Quota Limit"
128
+ labelIcon={
129
+ <LabelIcon
130
+ text="Descriptive title."
131
+ />
132
+ }
133
+ validated="default"
134
+ >
135
+ <InputGroup>
136
+ <InputGroupItem>
137
+ <TextInput
138
+ id="reg_token_life_time_input"
139
+ isDisabled={false}
140
+ max={5}
141
+ min={0}
142
+ onChange={[Function]}
143
+ validated="default"
144
+ value={0}
145
+ />
146
+ </InputGroupItem>
147
+ <InputGroupText>
148
+ cores
149
+ </InputGroupText>
150
+ </InputGroup>
151
+ </FormGroup>
152
+ </div>
153
+ `;
@@ -4,7 +4,6 @@ import { useDispatch } from 'react-redux';
4
4
  import {
5
5
  Button,
6
6
  Card,
7
- CardActions,
8
7
  CardExpandableContent,
9
8
  CardHeader,
10
9
  CardTitle,
@@ -74,7 +73,7 @@ const Resource = ({
74
73
  dispatchAPICallbackToast(
75
74
  success,
76
75
  response,
77
- `Sucessfully applied ${resourceTitle}.`,
76
+ `Successfully applied ${resourceTitle}.`,
78
77
  `An error occurred appyling ${resourceTitle}.`
79
78
  )
80
79
  );
@@ -132,19 +131,41 @@ const Resource = ({
132
131
  onChange,
133
132
  ]);
134
133
 
134
+ const renderApplyButton = () => {
135
+ if (isNewQuota) {
136
+ return <></>;
137
+ }
138
+ return (
139
+ <Button
140
+ isDisabled={!isUpdateApplicable}
141
+ size="sm"
142
+ isActive={isApplyLoading}
143
+ variant="primary"
144
+ onClick={onClickApply}
145
+ isLoading={isApplyLoading}
146
+ >
147
+ {__('Apply')}
148
+ </Button>
149
+ );
150
+ };
151
+
135
152
  return (
136
153
  <Card
137
154
  isExpanded={isExpanded}
138
155
  isDisabledRaised={!isEnabled}
139
156
  id={`resource-card-${cardId}`}
140
157
  >
141
- <CardHeader onExpand={onExpand} isToggleRightAligned={false}>
158
+ <CardHeader
159
+ actions={{ actions: renderApplyButton() }}
160
+ onExpand={onExpand}
161
+ isToggleRightAligned={false}
162
+ >
142
163
  <Flex>
143
164
  <FlexItem>
144
165
  <Switch
145
166
  id={`switch-${cardId}`}
146
167
  aria-label={`switch-${cardId}`}
147
- onChange={onChangeEnabled}
168
+ onChange={(_event, val) => onChangeEnabled(val)}
148
169
  isChecked={isEnabled}
149
170
  />
150
171
  </FlexItem>
@@ -152,20 +173,6 @@ const Resource = ({
152
173
  <CardTitle>{resourceTitle}</CardTitle>
153
174
  </FlexItem>
154
175
  </Flex>
155
- {!isNewQuota && (
156
- <CardActions>
157
- <Button
158
- isDisabled={!isUpdateApplicable}
159
- isSmall
160
- isActive={isApplyLoading}
161
- variant="primary"
162
- onClick={onClickApply}
163
- isLoading={isApplyLoading}
164
- >
165
- {__('Apply')}
166
- </Button>
167
- </CardActions>
168
- )}
169
176
  </CardHeader>
170
177
  <CardExpandableContent>
171
178
  <CardBody>
@@ -31,7 +31,7 @@ const Submit = ({ isValid, onCreate, onSubmit }) => {
31
31
  dispatchAPICallbackToast(
32
32
  success,
33
33
  response,
34
- `Sucessfully created new Resource Quota`,
34
+ `Successfully created new Resource Quota`,
35
35
  `An error occurred while creating new Resource Quota.`
36
36
  )
37
37
  );
@@ -1,4 +1,4 @@
1
1
 
2
2
  dt {
3
- font-size: var(--pf-global--FontSize--sm);
3
+ font-size: var(--pf-v5-global--FontSize--sm);
4
4
  }
@@ -23,7 +23,7 @@ const EditableSwitch = ({
23
23
  aria-label={identifier}
24
24
  ouiaId={`switch-${identifier}`}
25
25
  isChecked={value}
26
- onChange={onSwitch}
26
+ onChange={(_event, val) => onSwitch(val)}
27
27
  disabled={disabled}
28
28
  />
29
29
  );
@@ -89,87 +89,91 @@ const EditableTextInput = ({
89
89
  onKeyUp,
90
90
  component,
91
91
  value: inputValue || '',
92
- onChange: setInputValue,
92
+ onChange: (_event, val) => setInputValue(val),
93
93
  validated: valid,
94
94
  };
95
95
 
96
- return editing ? (
97
- <Split>
98
- <SplitItem>
99
- {textArea ? (
100
- <TextArea {...inputProps} aria-label={`${attribute} text area`} />
101
- ) : (
102
- <TextInput
103
- {...inputProps}
104
- type={isPassword && !showPassword ? 'password' : 'text'}
105
- aria-label={`${attribute} text input`}
106
- ouiaId={ouiaId}
107
- />
108
- )}
109
- </SplitItem>
110
- <SplitItem>
111
- <Button
112
- ouiaId={`submit-button-${attribute}`}
113
- aria-label={`submit ${attribute}`}
114
- variant="plain"
115
- onClick={onSubmit}
116
- >
117
- <CheckIcon />
118
- </Button>
119
- </SplitItem>
120
- <SplitItem>
121
- <Button
122
- ouiaId={`clear-button-${attribute}`}
123
- aria-label={`clear ${attribute}`}
124
- variant="plain"
125
- onClick={onClear}
126
- >
127
- <TimesIcon />
128
- </Button>
129
- </SplitItem>
130
- {isPassword ? (
131
- <SplitItem>
132
- <Button
133
- ouiaId={`show-button-${attribute}`}
134
- aria-label={`show-password ${attribute}`}
135
- variant="plain"
136
- isDisabled={!inputValue?.length}
137
- onClick={toggleShowPassword}
138
- >
139
- {showPassword ? <EyeSlashIcon /> : <EyeIcon />}
140
- </Button>
141
- </SplitItem>
142
- ) : null}
143
- </Split>
144
- ) : (
145
- <Split>
146
- <SplitItem>
147
- {inputValue ? (
148
- <Text
149
- className={`text${textArea ? 'Area' : 'Input'}-value`}
150
- ouiaId={`${attribute}-text-value`}
151
- aria-label={`${attribute} text value`}
152
- component={component}
153
- >
154
- {editing ? inputValue : passwordPlaceholder || inputValue}
155
- </Text>
156
- ) : (
157
- <Text
158
- className={`text${textArea ? 'Area' : 'Input'}-placeholder`}
159
- ouiaId={`${attribute}-text-value`}
160
- aria-label={`${attribute} text value`}
161
- component={component}
162
- >
163
- {passwordPlaceholder || placeholder}
164
- </Text>
165
- )}
166
- </SplitItem>
167
- {!disabled && (
168
- <SplitItem>
169
- <PencilEditButton {...{ attribute, onEditClick }} />
170
- </SplitItem>
96
+ return (
97
+ <div className="container-editable-text-input">
98
+ {editing ? (
99
+ <Split>
100
+ <SplitItem>
101
+ {textArea ? (
102
+ <TextArea {...inputProps} aria-label={`${attribute} text area`} />
103
+ ) : (
104
+ <TextInput
105
+ {...inputProps}
106
+ type={isPassword && !showPassword ? 'password' : 'text'}
107
+ aria-label={`${attribute} text input`}
108
+ ouiaId={ouiaId}
109
+ />
110
+ )}
111
+ </SplitItem>
112
+ <SplitItem>
113
+ <Button
114
+ ouiaId={`submit-button-${attribute}`}
115
+ aria-label={`submit ${attribute}`}
116
+ variant="plain"
117
+ onClick={onSubmit}
118
+ >
119
+ <CheckIcon />
120
+ </Button>
121
+ </SplitItem>
122
+ <SplitItem>
123
+ <Button
124
+ ouiaId={`clear-button-${attribute}`}
125
+ aria-label={`clear ${attribute}`}
126
+ variant="plain"
127
+ onClick={onClear}
128
+ >
129
+ <TimesIcon />
130
+ </Button>
131
+ </SplitItem>
132
+ {isPassword ? (
133
+ <SplitItem>
134
+ <Button
135
+ ouiaId={`show-button-${attribute}`}
136
+ aria-label={`show-password ${attribute}`}
137
+ variant="plain"
138
+ isDisabled={!inputValue?.length}
139
+ onClick={toggleShowPassword}
140
+ >
141
+ {showPassword ? <EyeSlashIcon /> : <EyeIcon />}
142
+ </Button>
143
+ </SplitItem>
144
+ ) : null}
145
+ </Split>
146
+ ) : (
147
+ <Split>
148
+ <SplitItem>
149
+ {inputValue ? (
150
+ <Text
151
+ className={`text${textArea ? 'Area' : 'Input'}-value`}
152
+ ouiaId={`${attribute}-text-value`}
153
+ aria-label={`${attribute} text value`}
154
+ component={component}
155
+ >
156
+ {editing ? inputValue : passwordPlaceholder || inputValue}
157
+ </Text>
158
+ ) : (
159
+ <Text
160
+ className={`text${textArea ? 'Area' : 'Input'}-placeholder`}
161
+ ouiaId={`${attribute}-text-value`}
162
+ aria-label={`${attribute} text value`}
163
+ component={component}
164
+ >
165
+ {passwordPlaceholder || placeholder}
166
+ </Text>
167
+ )}
168
+ </SplitItem>
169
+ {!disabled && (
170
+ <SplitItem>
171
+ <PencilEditButton {...{ attribute, onEditClick }} />
172
+ </SplitItem>
173
+ )}
174
+ </Split>
171
175
  )}
172
- </Split>
176
+ </div>
173
177
  );
174
178
  };
175
179
 
@@ -1,38 +1,40 @@
1
1
  /* Credits: https://github.com/Katello/katello/blob/631d5bb83dc5d87320ee9002a6de33809a281b3e/webpack/components/EditableTextInput/editableTextInput.scss */
2
- @import '~@theforeman/vendor/scss/variables';
2
+ @import 'foremanReact/common/variables';
3
3
 
4
- .foreman-limited-text {
5
- max-width: 200px;
6
- margin: auto 0px;
7
- }
4
+ .container-editable-text-input {
5
+ .foreman-limited-text {
6
+ max-width: 200px;
7
+ margin: auto 0px;
8
+ }
8
9
 
9
- .foreman-limited-editable-text {
10
- max-width: 300px;
11
- margin: auto 0px;
12
- }
10
+ .foreman-limited-editable-text {
11
+ max-width: 300px;
12
+ margin: auto 0px;
13
+ }
13
14
 
14
- // Edit icon isn't in line with text
15
- .foreman-edit-icon {
16
- padding-top: 2px;
17
- }
15
+ // Edit icon isn't in line with text
16
+ .foreman-edit-icon {
17
+ padding-top: 2px;
18
+ }
18
19
 
19
- .textInput-placeholder, .textArea-placeholder {
20
- color: var(--pf-global--disabled-color--100);
21
- }
20
+ .textInput-placeholder, .textArea-placeholder {
21
+ color: var(--pf-v5-global--disabled-color--100);
22
+ }
22
23
 
23
- textarea.pf-c-form-control {
24
- width: 215px;
25
- }
24
+ textarea.pf-v5-c-form-control {
25
+ width: 215px;
26
+ }
26
27
 
27
- .pf-c-form-control:not(textarea) {
28
- width: 215px;
29
- }
28
+ .pf-v5-c-form-control:not(textarea) {
29
+ width: 215px;
30
+ }
30
31
 
31
- p {
32
- width: 215px;
33
- }
32
+ p {
33
+ width: 215px;
34
+ }
34
35
 
35
- p.textArea-placeholder, p.textArea-value {
36
- width: 215px;
37
- height: 50px;
36
+ p.textArea-placeholder, p.textArea-value {
37
+ width: 215px;
38
+ height: 50px;
39
+ }
38
40
  }
@@ -0,0 +1,49 @@
1
+ /* Credits: https://github.com/theforeman/foreman_ansible/blob/master/webpack/testHelper.js */
2
+ import React, { useState } from 'react';
3
+ import { applyMiddleware, createStore, compose, combineReducers } from 'redux';
4
+ import { reducers as apiReducer, APIMiddleware } from 'foremanReact/redux/API';
5
+ import { Provider } from 'react-redux';
6
+ import { MockedProvider } from '@apollo/react-testing';
7
+ import thunk from 'redux-thunk';
8
+
9
+ import ConfirmModal, {
10
+ reducers as confirmModalReducers,
11
+ } from 'foremanReact/components/ConfirmModal';
12
+ import { getForemanContext } from 'foremanReact/Root/Context/ForemanContext';
13
+
14
+ const reducers = combineReducers({ ...apiReducer, ...confirmModalReducers });
15
+ export const generateStore = () =>
16
+ createStore(reducers, compose(applyMiddleware(thunk, APIMiddleware)));
17
+
18
+ // use to resolve async mock requests for apollo MockedProvider
19
+ export const tick = () => new Promise(resolve => setTimeout(resolve, 0));
20
+
21
+ export const withRedux = Component => props => (
22
+ <Provider store={generateStore()}>
23
+ <Component {...props} />
24
+ <ConfirmModal />
25
+ </Provider>
26
+ );
27
+
28
+ export const withMockedProvider = Component => props => {
29
+ const [context, setContext] = useState({
30
+ metadata: {
31
+ UISettings: {
32
+ perPage: 20,
33
+ },
34
+ },
35
+ });
36
+ const contextData = { context, setContext };
37
+ const ForemanContext = getForemanContext(contextData);
38
+
39
+ // eslint-disable-next-line react/prop-types
40
+ const { mocks, ...rest } = props;
41
+
42
+ return (
43
+ <ForemanContext.Provider value={contextData}>
44
+ <MockedProvider mocks={mocks}>
45
+ <Component {...rest} />
46
+ </MockedProvider>
47
+ </ForemanContext.Provider>
48
+ );
49
+ };