foreman_webhooks 4.0.2 → 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 (24) hide show
  1. checksums.yaml +4 -4
  2. data/lib/foreman_webhooks/engine.rb +1 -1
  3. data/lib/foreman_webhooks/version.rb +1 -1
  4. data/test/integration/webhooks_test.rb +234 -0
  5. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/FieldConstructor.js +321 -0
  6. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.css +23 -4
  7. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.js +191 -157
  8. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/__tests__/FieldConstructor.test.js +216 -0
  9. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/WebhookForm.js +55 -26
  10. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/__tests__/WebhookForm.test.js +253 -37
  11. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/index.js +3 -4
  12. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookCreateModal.js +30 -19
  13. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookDeleteModal.js +52 -18
  14. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookEditModal.js +37 -26
  15. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookTestModal.js +57 -32
  16. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/WebhooksTable.js +24 -11
  17. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/__tests__/__snapshots__/WebhooksTable.test.js.snap +64 -0
  18. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/index.js +21 -22
  19. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/WebhooksIndexPage.js +9 -15
  20. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/integration.test.js +0 -3
  21. metadata +7 -5
  22. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/ForemanFormikField.js +0 -152
  23. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/__tests__/__snapshots__/WebhookForm.test.js.snap +0 -512
  24. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/__snapshots__/integration.test.js.snap +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51b84ad832dc00ee4ef55877801f6d9b5dd8761e8555464a0342b007a534a11a
4
- data.tar.gz: e60a3dd891be4547d6d11436ea27d6189e693344785e7c53a54ffad05cf28849
3
+ metadata.gz: eb9a972c704d74ff30075493b920ff61d79582800a99ddb918b4217dd465288c
4
+ data.tar.gz: 9342868fdd9895fb61fcfe034021efcada6eb56cb71aebad003cb2d8a7fd6e9f
5
5
  SHA512:
6
- metadata.gz: 9a4c9300644b35b21f465079fc723c30f249a30111a685e1fb7c58fe7967331d57f8b43a503e5de8db82133e2b65e2a076f3fdf8ac13b421fd5c6ae5fd92a79d
7
- data.tar.gz: c3aa90eab09a3fdc3044a38409a03dc8a0596bc477d06838f6ccc739a421a0c9ad23413e2172c7ae0b112b8217c70ceb8c758ddad020c16d07de4c95374153e4
6
+ metadata.gz: 6e448c9f8a2816e9378eb5ba17217c173e12db0472b15b3198e078dd07f416765d4f05e6695a7aa2f7b9cb5fc10850a1e6ce12f8a97880f95a6abdd4dfb3375a
7
+ data.tar.gz: 96738b273f3ed94440359682714747a504fdfa92f36f3c49bfe82f1931a583bd68c1bf9edb413ff8079864a084c200b90d8e400aa7ad697858cd597f80a609dc
@@ -14,7 +14,7 @@ module ForemanWebhooks
14
14
  initializer 'foreman_webhooks.register_plugin', before: :finisher_hook do |app|
15
15
  app.reloader.to_prepare do
16
16
  Foreman::Plugin.register :foreman_webhooks do
17
- requires_foreman '>= 3.13'
17
+ requires_foreman '>= 3.18'
18
18
  register_gettext
19
19
 
20
20
  apipie_documented_controllers ["#{ForemanWebhooks::Engine.root}/app/controllers/api/v2/*.rb"]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ForemanWebhooks
4
- VERSION = "4.0.2"
4
+ VERSION = "5.0.0"
5
5
  end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_plugin_helper'
4
+ require 'integration_test_helper'
5
+
6
+ class WebhooksIntegrationTest < IntegrationTestWithJavascript
7
+ let(:webhook_template) { FactoryBot.create(:webhook_template, name: 'Test Template') }
8
+ let(:second_template) { FactoryBot.create(:webhook_template, name: 'Second Template') }
9
+
10
+ setup do
11
+ webhook_template
12
+ second_template
13
+ end
14
+
15
+ test 'create webhook and verify via UI' do
16
+ hook_name = "TestWebhook"
17
+ subscribe_to = 'Host Created'
18
+ target_url = 'http://example.com/webhook'
19
+ http_method = 'GET'
20
+ username = 'testuser'
21
+ password = 'testpass123'
22
+
23
+ visit '/webhooks'
24
+ assert_selector 'h1', text: 'Webhooks'
25
+
26
+ click_button 'Create new'
27
+ assert_selector '.pf-v5-c-modal-box'
28
+
29
+ fill_in_typeahead('id-event', subscribe_to)
30
+ fill_in 'id-name', with: hook_name
31
+ fill_in 'id-target_url', with: target_url
32
+ fill_in_typeahead('id-webhook_template_id', webhook_template.name)
33
+ fill_in_typeahead('id-http_method', http_method)
34
+ uncheck_checkbox('id-enabled')
35
+
36
+ click_tab('Credentials')
37
+ fill_in 'id-user', with: username
38
+ fill_in 'id-password', with: password
39
+ check_checkbox('id-proxy_authorization')
40
+ uncheck_checkbox('id-verify_ssl')
41
+
42
+ click_submit_button
43
+ wait_for_success_toast
44
+
45
+ visit '/webhooks'
46
+ wait_for_ajax
47
+ click_webhook_name(hook_name)
48
+ assert_selector '.pf-v5-c-modal-box'
49
+
50
+ assert_field_value('id-name', hook_name)
51
+ assert_typeahead_value('id-event', subscribe_to)
52
+ assert_field_value('id-target_url', target_url)
53
+ assert_typeahead_value('id-webhook_template_id', webhook_template.name)
54
+ assert_typeahead_value('id-http_method', http_method)
55
+ assert_checkbox_unchecked('id-enabled')
56
+
57
+ click_tab('Credentials')
58
+ assert_field_value('id-user', username)
59
+ assert_checkbox_checked('id-proxy_authorization')
60
+ assert_checkbox_unchecked('id-verify_ssl')
61
+
62
+ click_cancel_button
63
+ assert_no_selector '.pf-v5-c-modal-box'
64
+
65
+ webhook = Webhook.find_by(name: hook_name)
66
+ assert webhook, "Webhook '#{hook_name}' was not created"
67
+ assert webhook.password.present?, 'Password was not saved to database'
68
+ end
69
+
70
+ test 'update webhook and verify via UI' do
71
+ webhook = FactoryBot.create(:webhook,
72
+ name: 'ExistingWebhook',
73
+ target_url: 'http://old.example.com/webhook',
74
+ http_method: 'POST',
75
+ webhook_template: webhook_template,
76
+ user: 'olduser',
77
+ password: 'oldpass123',
78
+ enabled: false)
79
+
80
+ new_hook_name = "UpdatedWebhook"
81
+ new_subscribe_to = 'Host Destroyed'
82
+ new_target_url = 'http://newexample.com/webhook'
83
+ new_http_method = 'PUT'
84
+
85
+ visit '/webhooks'
86
+ wait_for_ajax
87
+ click_webhook_name(webhook.name)
88
+ assert_selector '.pf-v5-c-modal-box'
89
+
90
+ fill_in_typeahead('id-event', new_subscribe_to)
91
+ fill_in 'id-name', with: '', fill_options: { clear: :backspace }
92
+ fill_in 'id-name', with: new_hook_name
93
+ fill_in 'id-target_url', with: '', fill_options: { clear: :backspace }
94
+ fill_in 'id-target_url', with: new_target_url
95
+ fill_in_typeahead('id-webhook_template_id', second_template.name)
96
+ fill_in_typeahead('id-http_method', new_http_method)
97
+ check_checkbox('id-enabled')
98
+
99
+ click_submit_button
100
+ wait_for_success_toast
101
+
102
+ visit '/webhooks'
103
+ wait_for_ajax
104
+ click_webhook_name(new_hook_name)
105
+ assert_selector '.pf-v5-c-modal-box'
106
+
107
+ assert_field_value('id-name', new_hook_name)
108
+ assert_typeahead_value('id-event', new_subscribe_to)
109
+ assert_field_value('id-target_url', new_target_url)
110
+ assert_typeahead_value('id-webhook_template_id', second_template.name)
111
+ assert_typeahead_value('id-http_method', new_http_method)
112
+ assert_checkbox_checked('id-enabled')
113
+
114
+ click_cancel_button
115
+ assert_no_selector '.pf-v5-c-modal-box'
116
+
117
+ webhook.reload
118
+ assert webhook.password.present?, 'Password was cleared after update'
119
+ end
120
+
121
+ test 'delete webhook via UI' do
122
+ webhook = FactoryBot.create(:webhook,
123
+ name: 'WebhookToDelete',
124
+ target_url: 'http://example.com/webhook',
125
+ http_method: 'POST',
126
+ webhook_template: webhook_template)
127
+
128
+ visit '/webhooks'
129
+ wait_for_ajax
130
+ click_webhook_delete_button(webhook.name)
131
+ assert_selector '#webhookDeleteModal'
132
+ click_delete_confirm_button
133
+ wait_for_success_toast
134
+ assert_no_selector '#webhookDeleteModal'
135
+
136
+ assert_no_selector :xpath, "//tr[contains(., '#{webhook.name}')]"
137
+ assert_nil Webhook.find_by(name: webhook.name), "Webhook should be deleted"
138
+ end
139
+
140
+ private
141
+
142
+ def click_tab(tab_name)
143
+ tab_id = case tab_name
144
+ when 'General' then 'webhook-form-tab-general'
145
+ when 'Credentials' then 'webhook-form-tab-creds'
146
+ when 'Additional' then 'webhook-form-tab-add'
147
+ else raise "Unknown tab: #{tab_name}"
148
+ end
149
+ tab_button = find(:ouia_component_id, tab_id)
150
+ page.execute_script('arguments[0].click()', tab_button.native)
151
+ end
152
+
153
+ def fill_in_typeahead(field_id, value)
154
+ input = find("##{field_id}")
155
+ input.click
156
+ input.send_keys([:control, 'a'])
157
+ input.send_keys(:backspace)
158
+ input.send_keys(value)
159
+ # Wait for dropdown to appear with matching option
160
+ assert_selector '[role="option"]', text: value
161
+ find('[role="option"]', text: value, match: :prefer_exact).click
162
+ # Wait for dropdown to close
163
+ assert_no_selector '[role="listbox"]'
164
+ end
165
+
166
+ def check_checkbox(field_id)
167
+ checkbox = find("##{field_id}", visible: :all)
168
+ return if checkbox.checked?
169
+ page.execute_script("document.getElementById('#{field_id}').click()")
170
+ end
171
+
172
+ def uncheck_checkbox(field_id)
173
+ checkbox = find("##{field_id}", visible: :all)
174
+ return unless checkbox.checked?
175
+ page.execute_script("document.getElementById('#{field_id}').click()")
176
+ end
177
+
178
+ def click_submit_button
179
+ modal = find('.pf-v5-c-modal-box', wait: 10)
180
+ button = modal.find(:ouia_component_id, 'submit-webhook-form', wait: 10, visible: :all)
181
+ wait_for { !button.disabled? }
182
+ page.execute_script('arguments[0].scrollIntoView({block: "center"})', button.native)
183
+ page.execute_script('arguments[0].click()', button.native)
184
+ end
185
+
186
+ def click_cancel_button
187
+ modal = find('.pf-v5-c-modal-box', wait: 10)
188
+ button = modal.find('button', text: 'Cancel', match: :first, wait: 10, visible: :all)
189
+ page.execute_script('arguments[0].scrollIntoView({block: "center"})', button.native)
190
+ page.execute_script('arguments[0].click()', button.native)
191
+ end
192
+
193
+ def click_webhook_name(name)
194
+ row = find(:xpath, "//tbody//tr[contains(., '#{name}')]", wait: 15, match: :first)
195
+ within(row) do
196
+ button = find(:ouia_component_id, 'name-edit-active-button', wait: 10)
197
+ page.execute_script('arguments[0].click()', button.native)
198
+ end
199
+ end
200
+
201
+ def click_webhook_delete_button(name)
202
+ row = find(:xpath, "//tbody//tr[contains(., '#{name}')]", wait: 15, match: :first)
203
+ within(row) do
204
+ find('button', text: 'Delete', match: :first).click
205
+ end
206
+ end
207
+
208
+ def click_delete_confirm_button
209
+ within('#webhookDeleteModal') do
210
+ find('button', text: 'Delete', match: :first).click
211
+ end
212
+ end
213
+
214
+ def assert_field_value(field_id, expected_value)
215
+ assert page.has_field?(field_id, with: expected_value),
216
+ "Field #{field_id} expected '#{expected_value}'"
217
+ end
218
+
219
+ def assert_typeahead_value(field_id, expected_value)
220
+ field = find("##{field_id}")
221
+ assert_includes field.value, expected_value,
222
+ "Typeahead #{field_id} expected to contain '#{expected_value}' but was '#{field.value}'"
223
+ end
224
+
225
+ def assert_checkbox_checked(field_id)
226
+ assert page.has_checked_field?(field_id, visible: :all),
227
+ "Checkbox #{field_id} expected to be checked"
228
+ end
229
+
230
+ def assert_checkbox_unchecked(field_id)
231
+ assert page.has_unchecked_field?(field_id, visible: :all),
232
+ "Checkbox #{field_id} expected to be unchecked"
233
+ end
234
+ end
@@ -0,0 +1,321 @@
1
+ /* eslint-disable max-lines */
2
+ import React, { useEffect, useState } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import AutocompleteInput from 'foremanReact/components/common/AutocompleteInput/AutocompleteInput';
5
+ import { translate as __ } from 'foremanReact/common/I18n';
6
+ import {
7
+ ExclamationCircleIcon,
8
+ HelpIcon,
9
+ PencilAltIcon,
10
+ } from '@patternfly/react-icons';
11
+ import {
12
+ TextInput,
13
+ Checkbox,
14
+ Button,
15
+ FormHelperText,
16
+ HelperText,
17
+ HelperTextItem,
18
+ Icon,
19
+ TextArea,
20
+ FormGroup,
21
+ Popover,
22
+ Grid,
23
+ GridItem,
24
+ } from '@patternfly/react-core';
25
+
26
+ const FormField = ({
27
+ name,
28
+ type,
29
+ required,
30
+ options,
31
+ isLoading,
32
+ validated,
33
+ value,
34
+ disabled,
35
+ setValue,
36
+ placeholder,
37
+ errMsg,
38
+ fieldId,
39
+ ...props
40
+ }) => {
41
+ const [fieldValidated, setFieldValidated] = useState('default');
42
+ const [firstLoad, setFirstLoad] = useState(true);
43
+ const [isDisabled, setIsDisabled] = useState(disabled);
44
+
45
+ const requiredValidate = () => {
46
+ if (firstLoad || !required) return;
47
+ if (!value || value === '' || validated === 'error')
48
+ setFieldValidated('error');
49
+ else setFieldValidated('success');
50
+ };
51
+
52
+ const localHandler = (_event, newValue) => {
53
+ setValue(name, newValue);
54
+ };
55
+
56
+ useEffect(() => {
57
+ setFirstLoad(false);
58
+ }, []);
59
+
60
+ useEffect(() => {
61
+ setIsDisabled(disabled);
62
+ }, [disabled]);
63
+
64
+ useEffect(() => {
65
+ requiredValidate();
66
+ // eslint-disable-next-line react-hooks/exhaustive-deps
67
+ }, [value]);
68
+
69
+ if (type === 'checkbox') {
70
+ return (
71
+ <>
72
+ <Checkbox
73
+ ouiaId={name}
74
+ id={fieldId ?? `id-${name}`}
75
+ isChecked={value || false}
76
+ onChange={(_, newValue) => {
77
+ setValue(name, newValue);
78
+ }}
79
+ isDisabled={isLoading || isDisabled}
80
+ isRequired={required}
81
+ type={type}
82
+ validated={fieldValidated}
83
+ />
84
+ <ValidationComponent localValidated={fieldValidated} errMsg={errMsg} />
85
+ </>
86
+ );
87
+ } else if (type === 'textarea') {
88
+ return (
89
+ <>
90
+ <TextArea
91
+ rows={6}
92
+ name={name}
93
+ id={fieldId ?? `id-${name}`}
94
+ value={value ?? ''}
95
+ onChange={(_, newValue) => setValue(name, newValue)}
96
+ isRequired={required}
97
+ isDisabled={isLoading || isDisabled}
98
+ type={type}
99
+ validated={fieldValidated}
100
+ placeholder={placeholder}
101
+ />
102
+ <ValidationComponent localValidated={fieldValidated} errMsg={errMsg} />
103
+ </>
104
+ );
105
+ } else if (options.length !== 0) {
106
+ return (
107
+ <>
108
+ <AutocompleteInput
109
+ options={options}
110
+ selected={value ?? ''}
111
+ onSelect={newValue => setValue(name, newValue)}
112
+ onChange={() => requiredValidate()}
113
+ name={name}
114
+ placeholder={placeholder}
115
+ validationStatus={fieldValidated}
116
+ validationMsg={errMsg}
117
+ fieldId={fieldId}
118
+ />
119
+ </>
120
+ );
121
+ }
122
+ return (
123
+ <>
124
+ {name === 'password' && (isDisabled || disabled) ? (
125
+ <Grid hasGutter={false}>
126
+ <GridItem span={11}>
127
+ <TextInput
128
+ name={name}
129
+ value={value ?? ''}
130
+ id={fieldId ?? `id-${name}`}
131
+ onChange={localHandler}
132
+ isDisabled={isLoading || isDisabled}
133
+ isRequired={required}
134
+ type={type}
135
+ validated={fieldValidated}
136
+ placeholder={placeholder}
137
+ onBlur={requiredValidate}
138
+ autoComplete="off"
139
+ />
140
+ </GridItem>
141
+ <GridItem span={1}>
142
+ <Button
143
+ ouiaId={`reset-${name}`}
144
+ onClick={() => setIsDisabled(false)}
145
+ variant="control"
146
+ icon={<PencilAltIcon />}
147
+ />
148
+ </GridItem>
149
+ </Grid>
150
+ ) : (
151
+ <TextInput
152
+ name={name}
153
+ value={value ?? ''}
154
+ id={fieldId ?? `id-${name}`}
155
+ onChange={localHandler}
156
+ isDisabled={isLoading || isDisabled}
157
+ isRequired={required}
158
+ type={type}
159
+ validated={fieldValidated}
160
+ placeholder={placeholder}
161
+ onBlur={requiredValidate}
162
+ autoComplete={type === 'password' ? 'new-password' : null}
163
+ />
164
+ )}
165
+
166
+ <ValidationComponent localValidated={fieldValidated} errMsg={errMsg} />
167
+ </>
168
+ );
169
+ };
170
+
171
+ const ValidationComponent = ({ localValidated, errMsg }) => (
172
+ <>
173
+ {localValidated === 'error' && (
174
+ <FormHelperText>
175
+ <HelperText>
176
+ <HelperTextItem
177
+ icon={
178
+ <Icon>
179
+ <ExclamationCircleIcon />
180
+ </Icon>
181
+ }
182
+ variant={localValidated}
183
+ >
184
+ {errMsg ?? __('Field is required')}
185
+ </HelperTextItem>
186
+ </HelperText>
187
+ </FormHelperText>
188
+ )}
189
+ </>
190
+ );
191
+
192
+ const FieldConstructor = ({
193
+ label,
194
+ value,
195
+ required,
196
+ labelHelp,
197
+ fieldId,
198
+ name,
199
+ ...props
200
+ }) => (
201
+ <FormGroup
202
+ isInline
203
+ fieldId={fieldId ?? `id-${name}`}
204
+ label={label}
205
+ isRequired={required}
206
+ labelIcon={
207
+ labelHelp ? (
208
+ <Popover
209
+ bodyContent={
210
+ typeof labelHelp === 'string' ? (
211
+ <div dangerouslySetInnerHTML={{ __html: labelHelp }} />
212
+ ) : (
213
+ labelHelp
214
+ )
215
+ }
216
+ >
217
+ <Button
218
+ ouiaId={`label-${label}`}
219
+ type="button"
220
+ variant="plain"
221
+ onClick={e => e.preventDefault()}
222
+ >
223
+ <Icon>
224
+ <HelpIcon />
225
+ </Icon>
226
+ </Button>
227
+ </Popover>
228
+ ) : (
229
+ ''
230
+ )
231
+ }
232
+ >
233
+ <FormField
234
+ value={value}
235
+ required={required}
236
+ name={name}
237
+ {...props}
238
+ fieldId={fieldId}
239
+ />
240
+ </FormGroup>
241
+ );
242
+
243
+ FieldConstructor.propTypes = {
244
+ label: PropTypes.string.isRequired,
245
+ required: PropTypes.bool,
246
+ labelHelp: PropTypes.oneOfType([
247
+ PropTypes.string,
248
+ PropTypes.object,
249
+ PropTypes.node,
250
+ ]),
251
+ setValue: PropTypes.func.isRequired,
252
+ name: PropTypes.string.isRequired,
253
+ disabled: PropTypes.bool,
254
+ value: PropTypes.oneOfType([
255
+ PropTypes.string,
256
+ PropTypes.object,
257
+ PropTypes.bool,
258
+ PropTypes.number,
259
+ ]),
260
+ fieldId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
261
+ };
262
+
263
+ FieldConstructor.defaultProps = {
264
+ labelHelp: undefined,
265
+ required: false,
266
+ disabled: false,
267
+ value: '',
268
+ fieldId: undefined,
269
+ };
270
+
271
+ FormField.propTypes = {
272
+ disabled: PropTypes.bool,
273
+ setValue: PropTypes.func.isRequired,
274
+ name: PropTypes.string.isRequired,
275
+ type: PropTypes.string.isRequired,
276
+ label: PropTypes.string,
277
+ required: PropTypes.bool,
278
+ allowClear: PropTypes.bool,
279
+ options: PropTypes.arrayOf(
280
+ PropTypes.shape({
281
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
282
+ .isRequired,
283
+ label: PropTypes.string.isRequired,
284
+ })
285
+ ),
286
+ isLoading: PropTypes.bool,
287
+ validated: PropTypes.string,
288
+ placeholder: PropTypes.string,
289
+ errMsg: PropTypes.string,
290
+ value: PropTypes.oneOfType([
291
+ PropTypes.bool,
292
+ PropTypes.string,
293
+ PropTypes.number,
294
+ ]),
295
+ fieldId: PropTypes.string,
296
+ };
297
+
298
+ FormField.defaultProps = {
299
+ label: '',
300
+ errMsg: null,
301
+ placeholder: '',
302
+ validated: 'default',
303
+ required: false,
304
+ allowClear: false,
305
+ options: [],
306
+ isLoading: false,
307
+ disabled: false,
308
+ value: '',
309
+ fieldId: undefined,
310
+ };
311
+
312
+ ValidationComponent.propTypes = {
313
+ localValidated: PropTypes.string.isRequired,
314
+ errMsg: PropTypes.string,
315
+ };
316
+
317
+ ValidationComponent.defaultProps = {
318
+ errMsg: null,
319
+ };
320
+
321
+ export default FieldConstructor;
@@ -1,7 +1,26 @@
1
- .webhook-form-tab-content {
2
- padding-top: 3em;
3
- }
4
-
5
1
  .webhook-form-tab:focus {
6
2
  outline: none;
7
3
  }
4
+
5
+ .pf-v5-c-form.pf-m-horizontal .webhook-form-tab {
6
+ .webhook-form-tab-content .pf-v5-c-form__group{
7
+ margin-top: var(--pf-v5-c-form--GridGap);
8
+ grid-template-columns: calc(var(--pf-v5-c-form--m-horizontal__group-label--md--GridColumnWidth) + 3rem) var(--pf-v5-c-form--m-horizontal__group-control--md--GridColumnWidth);
9
+ }
10
+
11
+ .autocomplete-input-wrapper {
12
+ width: 100%;
13
+ }
14
+
15
+ .pf-v5-c-form__group-control {
16
+ align-content: space-evenly;
17
+ }
18
+
19
+ .pf-v5-c-form__group-label {
20
+ text-wrap: nowrap;
21
+ }
22
+ }
23
+ #select-typeahead-listbox {
24
+ max-height: 400px;
25
+ overflow: auto;
26
+ }