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:
martmull
2025-04-08 21:01:22 +02:00
committed by GitHub
parent 2f7f28a574
commit f121c94d4a
14 changed files with 297 additions and 20 deletions

View File

@ -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>
</>
);