701 workflow improve webhook triggers (#11455)
as title Nota bene: I did not filter execution by http method. A POST webhook trigger can be triggered by a GET request for more flexibility. Tell me if you think it is a mistake https://github.com/user-attachments/assets/1833cbea-51a8-4772-bcd8-088d6a087e79
This commit is contained in:
@ -14,6 +14,13 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { REACT_APP_SERVER_BASE_URL } from '~/config';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useIcons, IconCopy } from 'twenty-ui/display';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { WEBHOOK_TRIGGER_HTTP_METHOD_OPTIONS } from '@/workflow/workflow-trigger/constants/WebhookTriggerHttpMethodOptions';
|
||||
import { getWebhookTriggerDefaultSettings } from '@/workflow/workflow-trigger/utils/getWebhookTriggerDefaultSettings';
|
||||
import { WEBHOOK_TRIGGER_AUTHENTICATION_OPTIONS } from '@/workflow/workflow-trigger/constants/WebhookTriggerAuthenticationOptions';
|
||||
import { FormRawJsonFieldInput } from '@/object-record/record-field/form-types/components/FormRawJsonFieldInput';
|
||||
import { useState } from 'react';
|
||||
import { getFunctionOutputSchema } from '@/serverless-functions/utils/getFunctionOutputSchema';
|
||||
|
||||
type WorkflowEditTriggerWebhookFormProps = {
|
||||
trigger: WorkflowWebhookTrigger;
|
||||
@ -24,9 +31,17 @@ type WorkflowEditTriggerWebhookFormProps = {
|
||||
}
|
||||
| {
|
||||
readonly?: false;
|
||||
onTriggerUpdate: (trigger: WorkflowWebhookTrigger) => void;
|
||||
onTriggerUpdate: (
|
||||
trigger: WorkflowWebhookTrigger,
|
||||
options?: { computeOutputSchema: boolean },
|
||||
) => void;
|
||||
};
|
||||
};
|
||||
|
||||
type FormErrorMessages = {
|
||||
expectedBody?: string | undefined;
|
||||
};
|
||||
|
||||
export const WorkflowEditTriggerWebhookForm = ({
|
||||
trigger,
|
||||
triggerOptions,
|
||||
@ -34,10 +49,16 @@ export const WorkflowEditTriggerWebhookForm = ({
|
||||
const { enqueueSnackBar } = useSnackBar();
|
||||
const theme = useTheme();
|
||||
const { t } = useLingui();
|
||||
const [errorMessages, setErrorMessages] = useState<FormErrorMessages>({});
|
||||
const [errorMessagesVisible, setErrorMessagesVisible] = useState(false);
|
||||
const { getIcon } = useIcons();
|
||||
const workflowId = useRecoilValue(workflowIdState);
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
|
||||
const onBlur = () => {
|
||||
setErrorMessagesVisible(true);
|
||||
};
|
||||
|
||||
const headerTitle = isDefined(trigger.name) ? trigger.name : 'Webhook';
|
||||
|
||||
const headerIcon = getTriggerIcon({
|
||||
@ -93,6 +114,97 @@ export const WorkflowEditTriggerWebhookForm = ({
|
||||
onRightIconClick={copyToClipboardDebounced}
|
||||
readOnly
|
||||
/>
|
||||
<Select
|
||||
dropdownId="workflow-edit-webhook-trigger-http-method"
|
||||
label="HTTP method"
|
||||
fullWidth
|
||||
disabled={triggerOptions.readonly}
|
||||
value={trigger.settings.httpMethod}
|
||||
options={WEBHOOK_TRIGGER_HTTP_METHOD_OPTIONS}
|
||||
onChange={(newTriggerType) => {
|
||||
if (triggerOptions.readonly === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerOptions.onTriggerUpdate(
|
||||
{
|
||||
...trigger,
|
||||
settings: getWebhookTriggerDefaultSettings(newTriggerType),
|
||||
},
|
||||
{ computeOutputSchema: false },
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{trigger.settings.httpMethod === 'POST' && (
|
||||
<FormRawJsonFieldInput
|
||||
label="Expected Body"
|
||||
placeholder="Enter a JSON object"
|
||||
error={
|
||||
errorMessagesVisible ? errorMessages.expectedBody : undefined
|
||||
}
|
||||
onBlur={onBlur}
|
||||
readonly={triggerOptions.readonly}
|
||||
defaultValue={JSON.stringify(trigger.settings.expectedBody)}
|
||||
onChange={(newExpectedBody) => {
|
||||
if (triggerOptions.readonly === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
let formattedExpectedBody = {};
|
||||
try {
|
||||
formattedExpectedBody = JSON.parse(newExpectedBody || '{}');
|
||||
} catch (e) {
|
||||
setErrorMessages((prev) => ({
|
||||
...prev,
|
||||
expectedBody: String(e),
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
setErrorMessages((prev) => ({
|
||||
...prev,
|
||||
expectedBody: undefined,
|
||||
}));
|
||||
|
||||
const outputSchema = getFunctionOutputSchema(
|
||||
formattedExpectedBody,
|
||||
);
|
||||
|
||||
triggerOptions.onTriggerUpdate(
|
||||
{
|
||||
...trigger,
|
||||
settings: {
|
||||
...trigger.settings,
|
||||
expectedBody: formattedExpectedBody,
|
||||
outputSchema,
|
||||
} as WorkflowWebhookTrigger['settings'],
|
||||
},
|
||||
{ computeOutputSchema: false },
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<Select
|
||||
dropdownId="workflow-edit-webhook-trigger-auth"
|
||||
label="Auth"
|
||||
fullWidth
|
||||
disabled
|
||||
value={trigger.settings.authentication}
|
||||
options={WEBHOOK_TRIGGER_AUTHENTICATION_OPTIONS}
|
||||
onChange={(newAuthenticationType) => {
|
||||
if (triggerOptions.readonly === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerOptions.onTriggerUpdate({
|
||||
...trigger,
|
||||
settings: {
|
||||
...trigger.settings,
|
||||
authentication: newAuthenticationType,
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</WorkflowStepBody>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user