2
0

🐛 (editor) Fix variable dropdown overflow

Closes #209
This commit is contained in:
Baptiste Arnaud
2023-01-04 15:35:11 +01:00
parent e1af6af9c8
commit c1a32ce26b
10 changed files with 125 additions and 94 deletions

View File

@@ -1,6 +1,5 @@
import {
useDisclosure,
useOutsideClick,
Flex,
Popover,
Input,
@@ -16,6 +15,7 @@ import { useState, useRef, useEffect, ChangeEvent, ReactNode } from 'react'
import { useDebouncedCallback } from 'use-debounce'
import { env, isDefined } from 'utils'
import { VariablesButton } from '@/features/variables'
import { useOutsideClick } from '@/hooks/useOutsideClick'
type Props = {
selectedItem?: string

View File

@@ -10,7 +10,7 @@ import {
HStack,
useColorModeValue,
PopoverAnchor,
useOutsideClick,
Portal,
} from '@chakra-ui/react'
import { EditIcon, PlusIcon, TrashIcon } from '@/components/icons'
import { useTypebot } from '@/features/editor'
@@ -19,6 +19,7 @@ import { Variable } from 'models'
import React, { useState, useRef, ChangeEvent, useEffect } from 'react'
import { useDebouncedCallback } from 'use-debounce'
import { byId, env, isDefined, isNotDefined } from 'utils'
import { useOutsideClick } from '@/hooks/useOutsideClick'
type Props = {
initialVariableId?: string
@@ -188,6 +189,7 @@ export const VariableSearchInput = ({
{...inputProps}
/>
</PopoverAnchor>
<Portal>
<PopoverContent
maxH="35vh"
overflowY="scroll"
@@ -225,6 +227,7 @@ export const VariableSearchInput = ({
role="menuitem"
minH="40px"
key={idx}
onMouseDown={(e) => e.stopPropagation()}
onClick={handleVariableNameClick(item)}
fontSize="16px"
fontWeight="normal"
@@ -257,6 +260,7 @@ export const VariableSearchInput = ({
</>
)}
</PopoverContent>
</Portal>
</Popover>
</Flex>
)

View File

@@ -3,7 +3,6 @@ import {
Stack,
useColorModeValue,
useEventListener,
useOutsideClick,
} from '@chakra-ui/react'
import React, { useEffect, useRef, useState } from 'react'
import {
@@ -22,6 +21,7 @@ import { serializeHtml } from '@udecode/plate-serializer-html'
import { parseHtmlStringToPlainText } from '../../utils'
import { VariableSearchInput } from '@/components/VariableSearchInput'
import { colors } from '@/lib/theme'
import { useOutsideClick } from '@/hooks/useOutsideClick'
type TextBubbleEditorContentProps = {
id: string

View File

@@ -193,7 +193,7 @@ export const WebhookSettings = ({
Query params
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4} as={Stack} spacing="6">
<AccordionPanel py={4} as={Stack} spacing="6">
<TableList<KeyValue>
initialItems={localWebhook.queryParams}
onItemsChange={handleQueryParamsChange}
@@ -208,7 +208,7 @@ export const WebhookSettings = ({
Headers
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4} as={Stack} spacing="6">
<AccordionPanel py={4} as={Stack} spacing="6">
<TableList<KeyValue>
initialItems={localWebhook.headers}
onItemsChange={handleHeadersChange}
@@ -223,7 +223,7 @@ export const WebhookSettings = ({
Body
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4} as={Stack} spacing="6">
<AccordionPanel py={4} as={Stack} spacing="6">
<SwitchWithLabel
label="Custom body"
initialValue={options.isCustomBody ?? true}
@@ -244,7 +244,7 @@ export const WebhookSettings = ({
Variable values for test
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4} as={Stack} spacing="6">
<AccordionPanel py={4} as={Stack} spacing="6">
<TableList<VariableForTest>
initialItems={
options?.variablesForTest ?? { byId: {}, allIds: [] }
@@ -279,7 +279,7 @@ export const WebhookSettings = ({
Save in variables
<AccordionIcon />
</AccordionButton>
<AccordionPanel pb={4} as={Stack} spacing="6">
<AccordionPanel py={4} as={Stack} spacing="6">
<TableList<ResponseVariableMapping>
initialItems={options.responseVariableMapping}
onItemsChange={handleResponseMappingChange}

View File

@@ -120,10 +120,6 @@ const NonMemoizedDraggableGroupNode = ({
const handleTitleSubmit = (title: string) =>
title.length > 0 ? updateGroup(groupIndex, { title }) : undefined
const handleMouseDown = (e: React.MouseEvent) => {
e.stopPropagation()
}
const handleMouseEnter = () => {
if (isReadOnly) return
if (mouseOverGroup?.id !== group.id && !isStartGroup)
@@ -200,7 +196,6 @@ const NonMemoizedDraggableGroupNode = ({
currentCoordinates?.y ?? 0
}px)`,
}}
onMouseDown={handleMouseDown}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
cursor={isMouseDown ? 'grabbing' : 'pointer'}

View File

@@ -342,7 +342,7 @@ export const getEndpointTopOffset = ({
if (!endpointId) return
const endpointRef = endpoints[endpointId]?.ref
if (!endpointRef?.current) return
const endpointHeight = 28 * graphScale
const endpointHeight = 34 * graphScale
return (
(endpointRef.current.getBoundingClientRect().y +
endpointHeight / 2 -

View File

@@ -13,6 +13,7 @@ import {
InputRightElement,
ModalFooter,
Link,
useColorModeValue,
} from '@chakra-ui/react'
import { ExternalLinkIcon } from '@/components/icons'
import { env, getViewerUrl } from 'utils'
@@ -44,7 +45,7 @@ export const WordpressModal = ({
<Link
href="https://wordpress.org/plugins/typebot/"
isExternal
color="blue.500"
color={useColorModeValue('blue.500', 'blue.300')}
>
the official Typebot WordPress plugin
<ExternalLinkIcon mx="2px" />

View File

@@ -68,8 +68,8 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
>
<ModalOverlay />
<ModalContent h="85vh">
<ModalBody as={HStack} p="0">
<Stack w="full" h="full">
<ModalBody as={HStack} p="0" spacing="0">
<Stack w="full" h="full" spacing="4">
<Heading pl="10" pt="4" fontSize="2xl">
{selectedTemplate.emoji}{' '}
<chakra.span ml="2">{selectedTemplate.name}</chakra.span>
@@ -79,6 +79,7 @@ export const TemplatesModal = ({ isOpen, onClose, onTypebotChoose }: Props) => {
apiHost={getViewerUrl({ isBuilder: true })}
typebot={parseTypebotToPublicTypebot(typebot)}
key={typebot.id}
style={{ borderRadius: '0.25rem' }}
/>
)}
</Stack>

View File

@@ -0,0 +1,26 @@
import { useEventListener } from '@chakra-ui/react'
import { RefObject } from 'react'
type Handler = (event: MouseEvent) => void
type Props<T> = {
ref: RefObject<T>
handler: Handler
mouseEvent?: 'mousedown' | 'mouseup'
}
export const useOutsideClick = <T extends HTMLElement = HTMLElement>({
ref,
handler,
mouseEvent = 'mousedown',
}: Props<T>): void => {
const triggerHandlerIfOutside = (event: MouseEvent) => {
const el = ref?.current
if (!el || el.contains(event.target as Node)) {
return
}
handler(event)
}
useEventListener(mouseEvent, triggerHandlerIfOutside)
}

View File

@@ -8,9 +8,9 @@ import {
Group,
InputBlockType,
PublicTypebot,
publicTypebotSchema,
Theme,
Typebot,
typebotSchema,
} from 'models'
import { isDefined, isNotDefined } from 'utils'
import { promptAndSetEnvironment } from './utils'
@@ -125,13 +125,10 @@ const fixTypebots = async () => {
log: [{ emit: 'event', level: 'query' }, 'info', 'warn', 'error'],
})
const twoDaysAgo = new Date()
twoDaysAgo.setDate(twoDaysAgo.getDate() - 2)
const typebots = await prisma.typebot.findMany({
const typebots = await prisma.publicTypebot.findMany({
where: {
updatedAt: {
gte: twoDaysAgo,
gte: new Date('2023-01-01T00:00:00.000Z'),
},
},
})
@@ -150,7 +147,7 @@ const fixTypebots = async () => {
(progress / total) * 100
)}%) (${totalFixed} fixed typebots)`
)
const parser = typebotSchema.safeParse({
const parser = publicTypebotSchema.safeParse({
...typebot,
updatedAt: new Date(typebot.updatedAt),
createdAt: new Date(typebot.createdAt),
@@ -161,7 +158,7 @@ const fixTypebots = async () => {
updatedAt: new Date(),
createdAt: new Date(typebot.createdAt),
}
typebotSchema.parse(fixedTypebot)
publicTypebotSchema.parse(fixedTypebot)
fixedTypebots.push(fixedTypebot)
totalFixed += 1
diffs.push({
@@ -182,6 +179,13 @@ const fixTypebots = async () => {
where: { id: fixedTypebot.id },
data: {
...fixedTypebot,
// theme: fixedTypebot.theme ?? undefined,
// settings: fixedTypebot.settings ?? undefined,
// resultsTablePreferences:
// 'resultsTablePreferences' in fixedTypebot &&
// fixedTypebot.resultsTablePreferences
// ? fixedTypebot.resultsTablePreferences
// : undefined,
} as any,
})
)