From 27efc6af6698a414af402f4abb4cd798a5b1ced1 Mon Sep 17 00:00:00 2001 From: Pavel Jankoski Date: Fri, 17 Nov 2023 18:42:29 +0100 Subject: [PATCH] console: Refactor webhook form component --- .../console/components/webhook-form/index.js | 824 +++++++++--------- 1 file changed, 407 insertions(+), 417 deletions(-) diff --git a/pkg/webui/console/components/webhook-form/index.js b/pkg/webui/console/components/webhook-form/index.js index 2bb78718b8..81c3b3b7f5 100644 --- a/pkg/webui/console/components/webhook-form/index.js +++ b/pkg/webui/console/components/webhook-form/index.js @@ -12,9 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import React, { Component } from 'react' +import React, { useCallback, useRef, useState } from 'react' import { defineMessages, FormattedRelativeTime } from 'react-intl' -import bind from 'autobind-decorator' import { uniq } from 'lodash' import tts from '@console/api/tts' @@ -233,120 +232,97 @@ const validationSchema = Yup.object().shape({ .nullable(), }) -export default class WebhookForm extends Component { - static propTypes = { - error: PropTypes.error, - existCheck: PropTypes.func, - hasUnhealthyWebhookConfig: PropTypes.bool, - healthStatusEnabled: PropTypes.bool, - initialWebhookValue: PropTypes.shape({ - ids: PropTypes.shape({ - webhook_id: PropTypes.string, - }), - health_status: PropTypes.shape({ - healthy: PropTypes.shape({}), - unhealthy: PropTypes.shape({}), - }), - headers: PropTypes.shape({ - Authorization: PropTypes.string, - }), - }), - onDelete: PropTypes.func, - onDeleteFailure: PropTypes.func, - onDeleteSuccess: PropTypes.func, - onReactivate: PropTypes.func, - onReactivateSuccess: PropTypes.func, - onSubmit: PropTypes.func.isRequired, - update: PropTypes.bool.isRequired, - webhookRetryInterval: PropTypes.string, - webhookTemplate: PropTypes.webhookTemplate, +const WebhookForm = props => { + const { + update, + initialWebhookValue, + webhookTemplate, + healthStatusEnabled, + webhookRetryInterval, + hasUnhealthyWebhookConfig, + error: propsError, + existCheck, + onSubmit, + onDelete, + onDeleteSuccess, + onDeleteFailure, + onReactivate, + onReactivateSuccess, + } = props + + const form = useRef(null) + const modalResolve = useRef(() => {}) + const modalReject = useRef(() => {}) + const [shouldShowCredentialsInput, setShouldShowCredentialsInput] = useState( + Boolean(initialWebhookValue?.headers?.Authorization?.startsWith('Basic ')) && + Boolean(!decodeValues(initialWebhookValue)._headers.find(i => i.decodeError)?.decodeError), + ) + const [showDecodeError, setShowDecodeError] = useState( + Boolean(decodeValues(initialWebhookValue)._headers.find(i => i.decodeError)?.decodeError), + ) + const [displayOverwriteModal, setDisplayOverwriteModal] = useState(false) + const [existingId, setExistingId] = useState(undefined) + const [error, setError] = useState(undefined) + + const retryIntervalValue = webhookRetryInterval?.match(durationRegExp)[0] + const retryIntervalUnit = webhookRetryInterval?.match(durationRegExp)[1] + const retryIntervalIntlUnit = units[retryIntervalUnit] + + let initialValues = blankValues + if (update && initialWebhookValue) { + initialValues = decodeValues({ ...blankValues, ...initialWebhookValue }) } - static defaultProps = { - initialWebhookValue: undefined, - onReactivate: () => null, - onReactivateSuccess: () => null, - onDeleteFailure: () => null, - onDeleteSuccess: () => null, - onDelete: () => null, - webhookTemplate: undefined, - healthStatusEnabled: false, - error: undefined, - existCheck: () => null, - webhookRetryInterval: null, - hasUnhealthyWebhookConfig: false, - } + const hasTemplate = Boolean(webhookTemplate) - form = React.createRef() - - modalResolve = () => null - modalReject = () => null - - constructor(props) { - super(props) - const { initialWebhookValue } = this.props - - this.state = { - shouldShowCredentialsInput: - Boolean(initialWebhookValue?.headers?.Authorization?.startsWith('Basic ')) && - Boolean(!decodeValues(initialWebhookValue)._headers.find(i => i.decodeError)?.decodeError), - showDecodeError: Boolean( - decodeValues(initialWebhookValue)._headers.find(i => i.decodeError)?.decodeError, - ), - displayOverwriteModal: false, - existingId: undefined, - error: undefined, - } - } + const healthStatus = initialWebhookValue?.health_status + const mayReactivate = update && hasUnhealthyWebhookConfig && healthStatus?.unhealthy + const isPending = update && healthStatusEnabled && !healthStatus - @bind - handleReplaceModalDecision(mayReplace) { + const handleReplaceModalDecision = useCallback(mayReplace => { if (mayReplace) { - this.modalResolve() + modalResolve.current() } else { - this.modalReject() - } - this.setState({ displayOverwriteModal: false }) - } - - @bind - async handleSubmit(values, { setSubmitting, resetForm }) { - const { onSubmit, existCheck } = this.props - const castedWebhookValues = validationSchema.cast(values) - const encodedValues = encodeValues(castedWebhookValues) - const webhookId = encodedValues.ids.webhook_id - const exists = await existCheck(webhookId) - this.setState({ - showDecodeError: Boolean( - decodeValues(encodedValues)._headers.find(i => i.decodeError)?.decodeError, - ), - }) - if (exists) { - this.setState({ displayOverwriteModal: true, existingId: webhookId }) - await new Promise((resolve, reject) => { - this.modalResolve = resolve - this.modalReject = reject - }) + modalReject.current() } - await onSubmit(castedWebhookValues, encodedValues, { setSubmitting, resetForm }) - } + setDisplayOverwriteModal(false) + }, []) + + const handleSubmit = useCallback( + async (values, { setSubmitting, resetForm }) => { + const castedWebhookValues = validationSchema.cast(values) + const encodedValues = encodeValues(castedWebhookValues) + const webhookId = encodedValues.ids.webhook_id + const exists = await existCheck(webhookId) + setShowDecodeError( + Boolean(decodeValues(encodedValues)._headers.find(i => i.decodeError)?.decodeError), + ) - @bind - async handleDelete() { - const { onDelete, onDeleteSuccess, onDeleteFailure } = this.props + if (exists) { + setDisplayOverwriteModal(true) + setExistingId(webhookId) + await new Promise((resolve, reject) => { + modalResolve.current = resolve + modalReject.current = reject + }) + } + await onSubmit(castedWebhookValues, encodedValues, { setSubmitting, resetForm }) + }, + [existCheck, onSubmit], + ) + + const handleDelete = useCallback(async () => { try { await onDelete() - this.form.current.resetForm() + form.current.resetForm() onDeleteSuccess() } catch (error) { - this.setState({ error }) + setError(error) onDeleteFailure() } - } + }, [onDelete, onDeleteFailure, onDeleteSuccess]) - @bind - async handleReactivate() { - const { onReactivate, onReactivateSuccess } = this.props + const handleReactivate = useCallback(async () => { const healthStatus = { health_status: null, } @@ -355,342 +331,356 @@ export default class WebhookForm extends Component { await onReactivate(healthStatus) onReactivateSuccess() } catch (error) { - this.setState({ error }) + setError(error) } - } + }, [onReactivate, onReactivateSuccess]) - @bind - handleRequestAuthenticationChange(event) { - const currentHeaders = this.form.current.values._headers + const handleRequestAuthenticationChange = useCallback(event => { + const currentHeaders = form.current.values._headers if (!event.target.checked) { - this.form.current.setFieldValue( + form.current.setFieldValue( '_headers', currentHeaders.filter(i => !i.readOnly), ) } else { - this.form.current.setFieldValue('_headers', [ + form.current.setFieldValue('_headers', [ { key: 'Authorization', value: 'Basic ...', readOnly: true }, ]) } - this.setState({ shouldShowCredentialsInput: event.target.checked }) - } - - @bind - handleHeadersChange() { - this.setState({ showDecodeError: !hasNoEmptyEntry }) - } - - render() { - const { - update, - initialWebhookValue, - webhookTemplate, - healthStatusEnabled, - webhookRetryInterval, - hasUnhealthyWebhookConfig, - error, - } = this.props - - const retryIntervalValue = webhookRetryInterval?.match(durationRegExp)[0] - const retryIntervalUnit = webhookRetryInterval?.match(durationRegExp)[1] - const retryIntervalIntlUnit = units[retryIntervalUnit] - - let initialValues = blankValues - if (update && initialWebhookValue) { - initialValues = decodeValues({ ...blankValues, ...initialWebhookValue }) - } - - const hasTemplate = Boolean(webhookTemplate) - - const healthStatus = initialWebhookValue?.health_status - const mayReactivate = update && hasUnhealthyWebhookConfig && healthStatus?.unhealthy - const isPending = update && healthStatusEnabled && !healthStatus - - return ( - <> - {!hasTemplate && ( - <> - ( - - {val} - - ), - }} - component="p" + setShouldShowCredentialsInput(event.target.checked) + }, []) + + const handleHeadersChange = useCallback(() => { + setShowDecodeError(!hasNoEmptyEntry) + }, []) + + return ( + <> + {!hasTemplate && ( + <> + ( + + {val} + + ), + }} + component="p" + /> +
+ + )} + {mayReactivate && ( + + ), + }} + children={ +