feat(engine): ⚡️ Accept variables as webhook data path
This commit is contained in:
@ -25,6 +25,7 @@ export const DataVariableInputs = ({
|
|||||||
onValueChange={handleBodyPathChange}
|
onValueChange={handleBodyPathChange}
|
||||||
placeholder="Select the data"
|
placeholder="Select the data"
|
||||||
debounceTimeout={debounceTimeout}
|
debounceTimeout={debounceTimeout}
|
||||||
|
withVariableButton
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
|
@ -8,25 +8,31 @@ import {
|
|||||||
PopoverContent,
|
PopoverContent,
|
||||||
Button,
|
Button,
|
||||||
InputProps,
|
InputProps,
|
||||||
|
HStack,
|
||||||
} from '@chakra-ui/react'
|
} from '@chakra-ui/react'
|
||||||
|
import { Variable } from 'models'
|
||||||
import { useState, useRef, useEffect, ChangeEvent } from 'react'
|
import { useState, useRef, useEffect, ChangeEvent } from 'react'
|
||||||
import { useDebouncedCallback } from 'use-debounce'
|
import { useDebouncedCallback } from 'use-debounce'
|
||||||
import { isEmpty } from 'utils'
|
import { isEmpty } from 'utils'
|
||||||
|
import { VariablesButton } from './buttons/VariablesButton'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
selectedItem?: string
|
selectedItem?: string
|
||||||
items: string[]
|
items: string[]
|
||||||
debounceTimeout?: number
|
debounceTimeout?: number
|
||||||
|
withVariableButton?: boolean
|
||||||
onValueChange?: (value: string) => void
|
onValueChange?: (value: string) => void
|
||||||
} & InputProps
|
} & InputProps
|
||||||
|
|
||||||
export const SearchableDropdown = ({
|
export const SearchableDropdown = ({
|
||||||
selectedItem,
|
selectedItem,
|
||||||
items,
|
items,
|
||||||
|
withVariableButton = false,
|
||||||
debounceTimeout = 1000,
|
debounceTimeout = 1000,
|
||||||
onValueChange,
|
onValueChange,
|
||||||
...inputProps
|
...inputProps
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const [carretPosition, setCarretPosition] = useState<number>(0)
|
||||||
const { onOpen, onClose, isOpen } = useDisclosure()
|
const { onOpen, onClose, isOpen } = useDisclosure()
|
||||||
const [inputValue, setInputValue] = useState(selectedItem ?? '')
|
const [inputValue, setInputValue] = useState(selectedItem ?? '')
|
||||||
const debounced = useDebouncedCallback(
|
const debounced = useDebouncedCallback(
|
||||||
@ -42,7 +48,7 @@ export const SearchableDropdown = ({
|
|||||||
.slice(0, 50),
|
.slice(0, 50),
|
||||||
])
|
])
|
||||||
const dropdownRef = useRef(null)
|
const dropdownRef = useRef(null)
|
||||||
const inputRef = useRef(null)
|
const inputRef = useRef<HTMLInputElement>(null)
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
() => () => {
|
() => () => {
|
||||||
@ -93,6 +99,37 @@ export const SearchableDropdown = ({
|
|||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleVariableSelected = (variable?: Variable) => {
|
||||||
|
if (!inputRef.current || !variable) return
|
||||||
|
const cursorPosition = carretPosition
|
||||||
|
const textBeforeCursorPosition = inputRef.current.value.substring(
|
||||||
|
0,
|
||||||
|
cursorPosition
|
||||||
|
)
|
||||||
|
const textAfterCursorPosition = inputRef.current.value.substring(
|
||||||
|
cursorPosition,
|
||||||
|
inputRef.current.value.length
|
||||||
|
)
|
||||||
|
const newValue =
|
||||||
|
textBeforeCursorPosition +
|
||||||
|
`{{${variable.name}}}` +
|
||||||
|
textAfterCursorPosition
|
||||||
|
setInputValue(newValue)
|
||||||
|
debounced(newValue)
|
||||||
|
inputRef.current.focus()
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!inputRef.current) return
|
||||||
|
inputRef.current.selectionStart = inputRef.current.selectionEnd =
|
||||||
|
carretPosition + `{{${variable.name}}}`.length
|
||||||
|
setCarretPosition(inputRef.current.selectionStart)
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleKeyUp = () => {
|
||||||
|
if (!inputRef.current?.selectionStart) return
|
||||||
|
setCarretPosition(inputRef.current.selectionStart)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex ref={dropdownRef} w="full">
|
<Flex ref={dropdownRef} w="full">
|
||||||
<Popover
|
<Popover
|
||||||
@ -103,14 +140,23 @@ export const SearchableDropdown = ({
|
|||||||
isLazy
|
isLazy
|
||||||
>
|
>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
|
<HStack spacing={0} align={'flex-end'}>
|
||||||
<Input
|
<Input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
onChange={onInputChange}
|
onChange={onInputChange}
|
||||||
onClick={onOpen}
|
onClick={onOpen}
|
||||||
type="text"
|
type="text"
|
||||||
|
onKeyUp={handleKeyUp}
|
||||||
{...inputProps}
|
{...inputProps}
|
||||||
/>
|
/>
|
||||||
|
{withVariableButton && (
|
||||||
|
<VariablesButton
|
||||||
|
onSelectVariable={handleVariableSelected}
|
||||||
|
onClick={onClose}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</HStack>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent
|
<PopoverContent
|
||||||
maxH="35vh"
|
maxH="35vh"
|
||||||
|
@ -20,7 +20,7 @@ type Props = {
|
|||||||
|
|
||||||
export const VariablesButton = ({ onSelectVariable, ...props }: Props) => {
|
export const VariablesButton = ({ onSelectVariable, ...props }: Props) => {
|
||||||
return (
|
return (
|
||||||
<Popover isLazy placement="bottom-end">
|
<Popover isLazy placement="bottom-end" gutter={0}>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Tooltip label="Insert a variable">
|
<Tooltip label="Insert a variable">
|
||||||
|
@ -258,7 +258,10 @@ const executeWebhook = async (
|
|||||||
if (!varMapping?.bodyPath || !varMapping.variableId) return newVariables
|
if (!varMapping?.bodyPath || !varMapping.variableId) return newVariables
|
||||||
const existingVariable = variables.find(byId(varMapping.variableId))
|
const existingVariable = variables.find(byId(varMapping.variableId))
|
||||||
if (!existingVariable) return newVariables
|
if (!existingVariable) return newVariables
|
||||||
const func = Function('data', `return data.${varMapping?.bodyPath}`)
|
const func = Function(
|
||||||
|
'data',
|
||||||
|
`return data.${parseVariables(variables)(varMapping?.bodyPath)}`
|
||||||
|
)
|
||||||
try {
|
try {
|
||||||
const value = func(data)
|
const value = func(data)
|
||||||
updateVariableValue(existingVariable?.id, value)
|
updateVariableValue(existingVariable?.id, value)
|
||||||
|
Reference in New Issue
Block a user