foreman_webhooks 1.0.0 → 1.1.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/api/v2/webhooks_controller.rb +7 -1
  3. data/app/controllers/concerns/foreman_webhooks/controller/parameters/webhook.rb +1 -0
  4. data/app/controllers/webhooks_controller.rb +1 -24
  5. data/app/services/foreman_webhooks/webhook_service.rb +1 -1
  6. data/app/views/foreman_webhooks/webhook_templates/remote_execution_-_host_job.erb +0 -1
  7. data/config/routes.rb +6 -2
  8. data/lib/foreman_webhooks/engine.rb +2 -2
  9. data/lib/foreman_webhooks/version.rb +1 -1
  10. data/package.json +6 -6
  11. data/webpack/ForemanWebhooks/Routes/ForemanWebhooksRoutes.js +2 -2
  12. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/ForemanFormikField.js +117 -0
  13. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.css +7 -0
  14. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/Components/WebhookFormTabs.js +163 -0
  15. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/WebhookForm.js +69 -0
  16. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/WebhookFormSelectors.js +58 -0
  17. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/__tests__/WebhookForm.test.js +51 -0
  18. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/__tests__/__snapshots__/WebhookForm.test.js.snap +510 -0
  19. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/constants.js +9 -0
  20. data/webpack/ForemanWebhooks/Routes/Webhooks/Components/WebhookForm/index.js +73 -0
  21. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/EmptyWebhooksIndexPage/index.js +63 -0
  22. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookCreateModal.js +69 -0
  23. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookDeleteModal.js +1 -0
  24. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookEditModal.js +107 -0
  25. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookEditModalSelectors.js +22 -0
  26. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhookModal.scss +6 -0
  27. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/Formatters/index.js +1 -0
  28. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/Formatters/nameToEditFormatter.js +19 -0
  29. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/Components/NameToEditCell.js +35 -0
  30. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/WebhooksTable.js +31 -14
  31. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/WebhooksTableSchema.js +12 -4
  32. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/__tests__/WebhooksTable.test.js +13 -4
  33. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/__tests__/__snapshots__/WebhooksTable.test.js.snap +62 -19
  34. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/WebhooksTable/index.js +27 -5
  35. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/WebhooksIndexPage.js +61 -32
  36. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/WebhooksIndexPage.fixtures.js +36 -0
  37. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/WebhooksIndexPage.test.js +3 -1
  38. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/__snapshots__/WebhooksIndexPage.test.js.snap +18 -60
  39. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/__snapshots__/integration.test.js.snap +43 -0
  40. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/__tests__/integration.test.js +34 -0
  41. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksPageActions.js +3 -0
  42. data/webpack/ForemanWebhooks/Routes/Webhooks/constants.js +11 -1
  43. data/webpack/__mocks__/foremanReact/Root/Context/ForemanContext.js +1 -0
  44. data/webpack/__mocks__/foremanReact/common/HOC.js +26 -1
  45. data/webpack/__mocks__/foremanReact/common/urlHelpers.js +7 -0
  46. data/webpack/__mocks__/foremanReact/components/ForemanModal/index.js +6 -1
  47. data/webpack/__mocks__/foremanReact/components/Loading/Loading.js +2 -0
  48. data/webpack/__mocks__/foremanReact/components/Loading/index.js +3 -0
  49. data/webpack/__mocks__/foremanReact/components/Pagination/PaginationWrapper.js +3 -1
  50. data/webpack/__mocks__/foremanReact/components/common/forms/ForemanForm.js +9 -0
  51. data/webpack/__mocks__/foremanReact/components/common/forms/FormField.js +3 -0
  52. data/webpack/__mocks__/foremanReact/components/common/table.js +21 -0
  53. data/webpack/__mocks__/foremanReact/history.js +3 -0
  54. data/webpack/__mocks__/foremanReact/redux/actions/common/forms.js +1 -0
  55. data/webpack/test_setup.js +15 -0
  56. metadata +30 -7
  57. data/app/views/webhooks/_form.html.erb +0 -38
  58. data/app/views/webhooks/_templates.html.erb +0 -5
  59. data/app/views/webhooks/edit.html.erb +0 -3
  60. data/app/views/webhooks/new.html.erb +0 -3
  61. data/webpack/ForemanWebhooks/Routes/Webhooks/WebhooksIndexPage/Components/EmptyWebhooksTable/index.js +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b7eefadfce94e1499842423b790e8c387e4f62ce98a1e6b09fe8a9001718b9f1
4
- data.tar.gz: ad0b5f62406983e72601d9a28aa7c8a84d364fb99b9984445b61b459f17446f0
3
+ metadata.gz: 24ca3b029befe6d1a5d05f89f7418861dfaf246e56ec07108d3e5cddbb87196d
4
+ data.tar.gz: 9801e362e3a140aeaec85b02e534069e5c1b3802a2ed970ef341de5ce3ffe1cf
5
5
  SHA512:
6
- metadata.gz: 662cfadd46b2f4cf687623a2383b2d27304464606a19df2dd53825accb75668381edada4d3c614705940773cf390a5e31d53c10f2aa4171f94cf690e5023992b
7
- data.tar.gz: 10a37322e66de2ca65a93313b9bfc60b53e35ee1cad0ff599c88ca68f5b888829c3f235747458b13f3735ce315164e117bda4dc5b018f7e050f276c0c84070a2
6
+ metadata.gz: 726f0cdf6c8f7a1c4f3e691020e0fc1e64c0ae76dc9f4bec8864d972025075b2c3f00d9b74360543de4a237ccbe1b8e5f8484cbae4b059c4f633afc32dec63da
7
+ data.tar.gz: 5617358f79addd62638f92dc6669a2088e44bf808997f8ce91853ea307d2d29fd6af5948841579340f17adf06b3266a8703ab4d47181ebdddb6be6c59acf17ee
@@ -6,7 +6,7 @@ module Api
6
6
  include Api::Version2
7
7
  include ForemanWebhooks::Controller::Parameters::Webhook
8
8
 
9
- before_action :find_resource, only: %i[show update destroy]
9
+ before_action :find_resource, only: %i[show destroy]
10
10
 
11
11
  api :GET, '/webhooks/', N_('List Webhooks')
12
12
  param_group :search_and_pagination, ::Api::V2::BaseController
@@ -50,6 +50,7 @@ module Api
50
50
  param :id, :identifier, required: true
51
51
  param_group :webhook, as: :update
52
52
  def update
53
+ @webhook = Webhook.find(params[:id])
53
54
  process_response @webhook.update(webhook_params)
54
55
  end
55
56
 
@@ -58,6 +59,11 @@ module Api
58
59
  def destroy
59
60
  process_response @webhook.destroy
60
61
  end
62
+
63
+ api :GET, '/webhooks/events', N_('List available events for subscription')
64
+ def events
65
+ render json: Webhook.available_events.sort.map { |e| e.delete_suffix(Webhook::EVENT_POSTFIX) }.to_json
66
+ end
61
67
  end
62
68
  end
63
69
  end
@@ -27,6 +27,7 @@ module ForemanWebhooks
27
27
  end
28
28
 
29
29
  def webhook_params
30
+ params['webhook']['event'] = params['event'] unless params['event'].blank?
30
31
  self.class.webhook_params_filter.filter_params(params, parameter_filter_context)
31
32
  end
32
33
  end
@@ -4,30 +4,7 @@ class WebhooksController < ::ApplicationController
4
4
  include ForemanWebhooks::Controller::Parameters::Webhook
5
5
  include Foreman::Controller::AutoCompleteSearch
6
6
 
7
- before_action :find_resource, only: %i[edit update destroy]
8
-
9
- def new
10
- @webhook = Webhook.new
11
- end
12
-
13
- def create
14
- @webhook = Webhook.new(webhook_params)
15
- if @webhook.save
16
- process_success success_redirect: '/webhooks'
17
- else
18
- process_error
19
- end
20
- end
21
-
22
- def edit; end
23
-
24
- def update
25
- if @webhook.update(webhook_params)
26
- process_success success_redirect: '/webhooks'
27
- else
28
- process_error
29
- end
30
- end
7
+ before_action :find_resource, only: %i[destroy]
31
8
 
32
9
  def destroy
33
10
  if @webhook.destroy
@@ -95,7 +95,7 @@ module ForemanWebhooks
95
95
  uri = URI.parse(url)
96
96
 
97
97
  request = Object.const_get("Net::HTTP::#{http_method.to_s.capitalize}").new(uri.request_uri)
98
- request.basic_auth(user, password) if user && password
98
+ request.basic_auth(user, password) if !user.blank? && !password.blank?
99
99
  request['Content-Type'] = content_type
100
100
  request['X-Request-Id'] = ::Logging.mdc['request'] || SecureRandom.uuid
101
101
  request['X-Session-Id'] = ::Logging.mdc['session'] || SecureRandom.uuid
@@ -18,4 +18,3 @@ model: WebhookTemplate
18
18
  # Task ended at <%= @object.task.ended_at %>
19
19
  # Task resulted with <%= @object.task.result %>
20
20
  # Task state <%= @object.task.state %>
21
- # Task action output <%= @object.task.action_output %>
data/config/routes.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Rails.application.routes.draw do
4
- resources :webhooks, except: %i[index show] do
4
+ resources :webhooks, except: %i[index show new edit update] do
5
5
  collection do
6
6
  get 'auto_complete_search'
7
7
  end
@@ -14,7 +14,11 @@ Rails.application.routes.draw do
14
14
  defaults: { apiv: 'v2' },
15
15
  apiv: /v1|v2/,
16
16
  constraints: ApiConstraints.new(version: 2, default: true) do
17
- resources :webhooks, only: %i[index show create update destroy]
17
+ resources :webhooks, only: %i[index show create update destroy] do
18
+ collection do
19
+ get :events
20
+ end
21
+ end
18
22
  resources :webhook_templates, except: %i[new edit] do
19
23
  member do
20
24
  post :clone
@@ -15,7 +15,7 @@ module ForemanWebhooks
15
15
 
16
16
  initializer 'foreman_webhooks.register_plugin', before: :finisher_hook do |_app|
17
17
  Foreman::Plugin.register :foreman_webhooks do
18
- requires_foreman '>= 2.3'
18
+ requires_foreman '>= 2.5'
19
19
 
20
20
  apipie_documented_controllers ["#{ForemanWebhooks::Engine.root}/app/controllers/api/v2/*.rb"]
21
21
  ApipieDSL.configuration.sections += ['webhooks']
@@ -28,7 +28,7 @@ module ForemanWebhooks
28
28
  # Add permissions
29
29
  security_block :foreman_webhooks do
30
30
  permission :view_webhooks, { webhooks: %i[index show auto_complete_search],
31
- 'api/v2/webhooks': %i[index show] }, resource_type: 'Webhook'
31
+ 'api/v2/webhooks': %i[index show events] }, resource_type: 'Webhook'
32
32
  permission :create_webhooks, { webhooks: %i[new create],
33
33
  'api/v2/webhooks': [:create] }, resource_type: 'Webhook'
34
34
  permission :edit_webhooks, { webhooks: %i[edit update],
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ForemanWebhooks
4
- VERSION = '1.0.0'
4
+ VERSION = '1.1.0'
5
5
  end
data/package.json CHANGED
@@ -21,15 +21,15 @@
21
21
  "url": "https://projects.theforeman.org/projects/webhooks/issues"
22
22
  },
23
23
  "peerDependencies": {
24
- "@theforeman/vendor": ">= 4.15.1"
24
+ "@theforeman/vendor": ">= 8.4.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@babel/core": "^7.7.0",
28
- "@theforeman/builder": "^4.15.1",
29
- "@theforeman/stories": "^4.15.1",
30
- "@theforeman/test": "^4.15.1",
31
- "@theforeman/vendor-dev": "^4.15.1",
32
- "@theforeman/eslint-plugin-foreman": "^4.15.1",
28
+ "@theforeman/builder": "^8.4.1",
29
+ "@theforeman/stories": "^8.4.1",
30
+ "@theforeman/test": "^8.4.1",
31
+ "@theforeman/vendor-dev": "^8.4.1",
32
+ "@theforeman/eslint-plugin-foreman": "^8.4.1",
33
33
  "babel-eslint": "^10.0.0",
34
34
  "eslint": "^6.8.0",
35
35
  "eslint-plugin-spellcheck": "^0.0.17",
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
- import WebhooksIndexPage from './Webhooks/WebhooksIndexPage';
2
+ import ConnectedWebhooksIndexPage from './Webhooks/WebhooksIndexPage';
3
3
 
4
4
  const ForemanWebhooksRoutes = [
5
5
  {
6
6
  path: '/webhooks',
7
7
  exact: true,
8
- render: props => <WebhooksIndexPage {...props} />,
8
+ render: props => <ConnectedWebhooksIndexPage {...props} />,
9
9
  },
10
10
  ];
11
11
 
@@ -0,0 +1,117 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Field as FormikField } from 'formik';
4
+ import { Spinner } from '@patternfly/react-core';
5
+ import { TypeAheadSelect } from 'patternfly-react';
6
+ import { filter } from 'lodash';
7
+
8
+ import { translate as __ } from 'foremanReact/common/I18n';
9
+
10
+ import FormField from 'foremanReact/components/common/forms/FormField';
11
+
12
+ const ForemanFormikField = ({
13
+ name,
14
+ type,
15
+ required,
16
+ label,
17
+ labelHelp,
18
+ inputSizeClass,
19
+ labelSizeClass,
20
+ rows,
21
+ placeholder,
22
+ options,
23
+ isLoading,
24
+ }) => (
25
+ <FormikField name={name}>
26
+ {({
27
+ field, // { name, value, onChange, onBlur }
28
+ form: { touched, errors, setFieldValue, setFieldTouched }, // also values, setXXXX, handleXXXX, dirty, isValid, status, etc.
29
+ }) => {
30
+ const defaultSelection = (fieldValue, initialOptions) => {
31
+ if (!fieldValue) return [];
32
+
33
+ return filter(initialOptions, o => o.value === fieldValue);
34
+ };
35
+ let content = null;
36
+ switch (type) {
37
+ case 'textarea':
38
+ content = (
39
+ <textarea
40
+ {...field}
41
+ className="form-control"
42
+ rows={rows}
43
+ placeholder={placeholder}
44
+ />
45
+ );
46
+ break;
47
+ case 'select':
48
+ content = isLoading ? (
49
+ <Spinner size="md" aria-label="loading icon" />
50
+ ) : (
51
+ <TypeAheadSelect
52
+ id={name}
53
+ options={options}
54
+ placeholder={__('Start typing to search')}
55
+ selected={defaultSelection(field.value, options)}
56
+ onChange={selected =>
57
+ setFieldValue(field.name, selected[0]?.value)
58
+ }
59
+ // onBlur={e => setFieldTouched(field.name, true)}
60
+ />
61
+ );
62
+ break;
63
+ default:
64
+ content = (
65
+ <input
66
+ {...field}
67
+ type={type}
68
+ checked={type === 'checkbox' ? field.value || '' : undefined}
69
+ className={type === 'checkbox' ? '' : 'form-control'}
70
+ />
71
+ );
72
+ }
73
+ return (
74
+ <FormField
75
+ {...field}
76
+ error={touched[name] ? errors[name] : undefined}
77
+ type={type}
78
+ inputSizeClass={inputSizeClass}
79
+ labelSizeClass={labelSizeClass}
80
+ required={required}
81
+ label={label}
82
+ labelHelp={labelHelp}
83
+ options={options}
84
+ >
85
+ {content}
86
+ </FormField>
87
+ );
88
+ }}
89
+ </FormikField>
90
+ );
91
+
92
+ ForemanFormikField.propTypes = {
93
+ name: PropTypes.string.isRequired,
94
+ type: PropTypes.string.isRequired,
95
+ required: PropTypes.bool,
96
+ label: PropTypes.string.isRequired,
97
+ labelHelp: PropTypes.string,
98
+ inputSizeClass: PropTypes.string,
99
+ labelSizeClass: PropTypes.string,
100
+ rows: PropTypes.number,
101
+ placeholder: PropTypes.string,
102
+ options: PropTypes.array,
103
+ isLoading: PropTypes.bool,
104
+ };
105
+
106
+ ForemanFormikField.defaultProps = {
107
+ required: false,
108
+ labelHelp: null,
109
+ inputSizeClass: 'col-md-8',
110
+ labelSizeClass: 'col-md-3',
111
+ rows: 1,
112
+ placeholder: '',
113
+ options: null,
114
+ isLoading: false,
115
+ };
116
+
117
+ export default ForemanFormikField;
@@ -0,0 +1,7 @@
1
+ .webhook-form-tab-content {
2
+ padding-top: 3em;
3
+ }
4
+
5
+ .webhook-form-tab:focus {
6
+ outline: none;
7
+ }
@@ -0,0 +1,163 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Tabs, Tab, TabTitleText } from '@patternfly/react-core';
4
+
5
+ import { translate as __ } from 'foremanReact/common/I18n';
6
+
7
+ import ForemanFormikField from './ForemanFormikField';
8
+
9
+ import './WebhookFormTabs.css';
10
+
11
+ const WebhookFormTabs = ({
12
+ formProps,
13
+ disabled,
14
+ activeTab,
15
+ handleTabClick,
16
+ webhookTemplates,
17
+ httpMethods,
18
+ availableEvents,
19
+ isTemplatesLoading,
20
+ isEventsLoading,
21
+ }) => (
22
+ <Tabs activeKey={activeTab} onSelect={handleTabClick} isFilled>
23
+ <Tab
24
+ className="webhook-form-tab"
25
+ eventKey={0}
26
+ title={<TabTitleText>{__('General')}</TabTitleText>}
27
+ >
28
+ <div className="webhook-form-tab-content">
29
+ <ForemanFormikField
30
+ name="event"
31
+ type="select"
32
+ label={__('Subscribe to')}
33
+ required
34
+ allowClear={false}
35
+ options={availableEvents}
36
+ isLoading={isEventsLoading}
37
+ />
38
+ <ForemanFormikField
39
+ name="name"
40
+ type="text"
41
+ required
42
+ label={__('Name')}
43
+ />
44
+ <ForemanFormikField
45
+ name="target_url"
46
+ type="text"
47
+ required
48
+ label={__('Target URL')}
49
+ labelHelp={__('Target URL that should be called by Foreman')}
50
+ />
51
+ <ForemanFormikField
52
+ name="webhook_template_id"
53
+ type="select"
54
+ label={__('Template')}
55
+ required
56
+ allowClear={false}
57
+ options={webhookTemplates}
58
+ isLoading={isTemplatesLoading}
59
+ />
60
+ <ForemanFormikField
61
+ name="http_method"
62
+ type="select"
63
+ label={__('HTTP Method')}
64
+ required
65
+ allowClear={false}
66
+ options={httpMethods}
67
+ />
68
+ <ForemanFormikField
69
+ name="enabled"
70
+ type="checkbox"
71
+ label={__('Enabled')}
72
+ labelHelp={__('If unchecked, the webhook will be inactive')}
73
+ />
74
+ </div>
75
+ </Tab>
76
+ <Tab
77
+ className="webhook-form-tab"
78
+ eventKey={1}
79
+ title={<TabTitleText>{__('Credentials')}</TabTitleText>}
80
+ >
81
+ <div className="webhook-form-tab-content">
82
+ <ForemanFormikField
83
+ name="user"
84
+ type="text"
85
+ label={__('User')}
86
+ labelHelp={__('Authentication credentials')}
87
+ />
88
+ <ForemanFormikField
89
+ name="password"
90
+ type="password"
91
+ label={__('Password')}
92
+ labelHelp={__('Authentication credentials')}
93
+ />
94
+ <ForemanFormikField
95
+ name="verify_ssl"
96
+ type="checkbox"
97
+ label={__('Verify SSL')}
98
+ labelHelp={__(
99
+ "Uncheck this option to disable validation of the receiver's SSL certificate"
100
+ )}
101
+ />
102
+ <ForemanFormikField
103
+ name="proxy_authorization"
104
+ type="checkbox"
105
+ label={__('Proxy Authorization')}
106
+ labelHelp={__(
107
+ 'Authorize with Foreman client certificate and validate smart-proxy CA from Settings'
108
+ )}
109
+ />
110
+ <ForemanFormikField
111
+ name="ssl_ca_certs"
112
+ type="textarea"
113
+ label={__('X509 Certification Authorities')}
114
+ placeholder={__(
115
+ "Optional CAs in PEM format concatenated to verify the receiver's SSL certificate"
116
+ )}
117
+ inputSizeClass="col-md-8"
118
+ rows={8}
119
+ />
120
+ </div>
121
+ </Tab>
122
+ <Tab
123
+ className="webhook-form-tab"
124
+ eventKey={2}
125
+ title={<TabTitleText>{__('Additional')}</TabTitleText>}
126
+ >
127
+ <div className="webhook-form-tab-content">
128
+ <ForemanFormikField
129
+ name="http_content_type"
130
+ type="text"
131
+ label={__('HTTP Content Type')}
132
+ />
133
+ <ForemanFormikField
134
+ name="http_headers"
135
+ type="textarea"
136
+ label={__('Optional HTTP headers as JSON (ERB allowed)')}
137
+ placeholder='{\n"X-Shellhook-Arg-1": "value"\n}'
138
+ inputSizeClass="col-md-8"
139
+ rows={8}
140
+ />
141
+ </div>
142
+ </Tab>
143
+ </Tabs>
144
+ );
145
+
146
+ WebhookFormTabs.propTypes = {
147
+ formProps: PropTypes.object,
148
+ disabled: PropTypes.bool,
149
+ activeTab: PropTypes.number.isRequired,
150
+ handleTabClick: PropTypes.func.isRequired,
151
+ webhookTemplates: PropTypes.array.isRequired,
152
+ httpMethods: PropTypes.array.isRequired,
153
+ availableEvents: PropTypes.array.isRequired,
154
+ isTemplatesLoading: PropTypes.bool.isRequired,
155
+ isEventsLoading: PropTypes.bool.isRequired,
156
+ };
157
+
158
+ WebhookFormTabs.defaultProps = {
159
+ disabled: false,
160
+ formProps: {},
161
+ };
162
+
163
+ export default WebhookFormTabs;