From 03aadab4094c0460c85c3c2c29f192e7faf5b04e Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Tue, 22 Mar 2022 15:32:48 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20=E2=99=BF=EF=B8=8F=20Improve=20inputs=20?= =?UTF-8?q?responsivity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/builder/components/shared/TableList.tsx | 39 ++++++++----------- .../components/shared/VariableSearchInput.tsx | 27 ++++++++----- .../layouts/dashboard/TemplatesContent.tsx | 9 ++++- apps/builder/pages/api/typebots.ts | 1 + apps/builder/services/typebots/typebots.ts | 10 ++++- 5 files changed, 52 insertions(+), 34 deletions(-) diff --git a/apps/builder/components/shared/TableList.tsx b/apps/builder/components/shared/TableList.tsx index 22bbfcc13e0..75ecf4b9e13 100644 --- a/apps/builder/components/shared/TableList.tsx +++ b/apps/builder/components/shared/TableList.tsx @@ -1,10 +1,7 @@ import { Box, Button, Fade, Flex, IconButton, Stack } from '@chakra-ui/react' import { TrashIcon, PlusIcon } from 'assets/icons' import cuid from 'cuid' -import { dequal } from 'dequal' -import { Draft } from 'immer' -import React, { useEffect, useState } from 'react' -import { useImmer } from 'use-immer' +import React, { useState } from 'react' type ItemWithId = T & { id: string } @@ -31,32 +28,28 @@ export const TableList = ({ Item, ComponentBetweenItems = () => <>, }: Props) => { - const [items, setItems] = useImmer(initialItems) + const [items, setItems] = useState(initialItems) const [showDeleteIndex, setShowDeleteIndex] = useState(null) - useEffect(() => { - if (dequal(items, initialItems)) return - onItemsChange(items) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [items]) - const createItem = () => { - setItems((items) => { - const id = cuid() - const newItem = { id } as Draft> - items.push(newItem) - }) + const id = cuid() + const newItem = { id } as ItemWithId + setItems([...items, newItem]) + onItemsChange([...items, newItem]) } - const updateItem = (itemIndex: number, updates: Partial) => - setItems((items) => { - items[itemIndex] = { ...items[itemIndex], ...updates } - }) + const updateItem = (itemIndex: number, updates: Partial) => { + const newItems = items.map((item, idx) => + idx === itemIndex ? { ...item, ...updates } : item + ) + setItems(newItems) + onItemsChange(newItems) + } const deleteItem = (itemIndex: number) => () => { - setItems((items) => { - items.splice(itemIndex, 1) - }) + items.splice(itemIndex, 1) + setItems([...items]) + onItemsChange([...items]) } const handleMouseEnter = (itemIndex: number) => () => diff --git a/apps/builder/components/shared/VariableSearchInput.tsx b/apps/builder/components/shared/VariableSearchInput.tsx index 9f0465aaa6c..10c69b5142d 100644 --- a/apps/builder/components/shared/VariableSearchInput.tsx +++ b/apps/builder/components/shared/VariableSearchInput.tsx @@ -15,7 +15,7 @@ import { useTypebot } from 'contexts/TypebotContext' import cuid from 'cuid' import { Variable } from 'models' import React, { useState, useRef, ChangeEvent, useEffect } from 'react' -import { useDebounce } from 'use-debounce' +import { useDebouncedCallback } from 'use-debounce' import { byId, isNotDefined } from 'utils' type Props = { @@ -40,8 +40,11 @@ export const VariableSearchInput = ({ const [inputValue, setInputValue] = useState( variables.find(byId(initialVariableId))?.name ?? '' ) - const [debouncedInputValue] = useDebounce( - inputValue, + const debounced = useDebouncedCallback( + (value) => { + const variable = variables.find((v) => v.name === value) + if (variable) onSelectVariable(variable) + }, process.env.NEXT_PUBLIC_E2E_TEST ? 0 : debounceTimeout ) const [filteredItems, setFilteredItems] = useState( @@ -60,14 +63,16 @@ export const VariableSearchInput = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, []) - useEffect(() => { - const variable = variables.find((v) => v.name === debouncedInputValue) - if (variable) onSelectVariable(variable) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [debouncedInputValue]) + useEffect( + () => () => { + debounced.flush() + }, + [debounced] + ) const onInputChange = (e: ChangeEvent) => { setInputValue(e.target.value) + debounced(e.target.value) onOpen() if (e.target.value === '') { setFilteredItems([...variables.slice(0, 50)]) @@ -84,6 +89,7 @@ export const VariableSearchInput = ({ const handleVariableNameClick = (variable: Variable) => () => { setInputValue(variable.name) + onSelectVariable(variable) onClose() } @@ -100,7 +106,10 @@ export const VariableSearchInput = ({ e.stopPropagation() deleteVariable(variable.id) setFilteredItems(filteredItems.filter((item) => item.id !== variable.id)) - if (variable.name === inputValue) setInputValue('') + if (variable.name === inputValue) { + setInputValue('') + debounced('') + } } return ( diff --git a/apps/builder/layouts/dashboard/TemplatesContent.tsx b/apps/builder/layouts/dashboard/TemplatesContent.tsx index a63446cd40e..720baeec2d9 100644 --- a/apps/builder/layouts/dashboard/TemplatesContent.tsx +++ b/apps/builder/layouts/dashboard/TemplatesContent.tsx @@ -10,7 +10,7 @@ import { import { CreateTypebotMoreButton } from 'components/templates/ImportFileMenuItem' import { TemplateButton } from 'components/templates/TemplateButton' import { useUser } from 'contexts/UserContext' -import { Typebot } from 'models' +import { defaultTheme, Typebot } from 'models' import { useRouter } from 'next/router' import React, { useState } from 'react' import { createTypebot, importTypebot } from 'services/typebots/typebots' @@ -40,6 +40,13 @@ export const TemplatesContent = () => { ...typebot, ownerId: user.id, folderId, + theme: { + ...defaultTheme, + chat: { + ...defaultTheme.chat, + hostAvatar: { isEnabled: true, url: user.image ?? undefined }, + }, + }, }) : await createTypebot({ folderId, diff --git a/apps/builder/pages/api/typebots.ts b/apps/builder/pages/api/typebots.ts index 1b0f4dd5ed4..c8cf2431831 100644 --- a/apps/builder/pages/api/typebots.ts +++ b/apps/builder/pages/api/typebots.ts @@ -59,6 +59,7 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => { ? data : (parseNewTypebot({ ownerId: user.id, + ownerAvatarUrl: user.image, ...data, }) as Prisma.TypebotUncheckedCreateInput), }) diff --git a/apps/builder/services/typebots/typebots.ts b/apps/builder/services/typebots/typebots.ts index 49b6c9f00d8..e2c8af85537 100644 --- a/apps/builder/services/typebots/typebots.ts +++ b/apps/builder/services/typebots/typebots.ts @@ -324,10 +324,12 @@ export const parseNewTypebot = ({ ownerId, folderId, name, + ownerAvatarUrl, }: { ownerId: string folderId: string | null name: string + ownerAvatarUrl?: string }): Omit< Typebot, | 'createdAt' @@ -358,7 +360,13 @@ export const parseNewTypebot = ({ blocks: [startBlock], edges: [], variables: [], - theme: defaultTheme, + theme: { + ...defaultTheme, + chat: { + ...defaultTheme.chat, + hostAvatar: { isEnabled: true, url: ownerAvatarUrl }, + }, + }, settings: defaultSettings, } }