From 1c5bd06657bdd1453155965cf715af46c6e5e86c Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Sat, 29 Jan 2022 11:22:22 +0100 Subject: [PATCH] =?UTF-8?q?feat(editor):=20=E2=9C=A8=20Add=20unlock/lock?= =?UTF-8?q?=20sidebar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/builder/assets/icons.tsx | 14 ++ apps/builder/components/board/Board.tsx | 4 +- .../board/StepTypesList/StepTypesList.tsx | 137 ------------- .../components/board/StepTypesList/index.tsx | 1 - .../StepCard.tsx | 0 .../StepIcon.tsx | 26 +-- .../board/StepsSideBar/StepSideBar.tsx | 191 ++++++++++++++++++ .../StepTypeLabel.tsx | 0 .../components/board/StepsSideBar/index.tsx | 1 + .../ChoiceInputStepNode/ChoiceItemNode.tsx | 2 +- .../ContentPopover/ContentPopover.tsx | 2 +- .../graph/BlockNode/StepNode/StepNode.tsx | 4 +- .../BlockNode/StepNode/StepNodeOverlay.tsx | 2 +- .../components/shared/DropdownList.tsx | 2 +- .../ImageUploadContent/ImageUploadContent.tsx | 21 +- apps/builder/libs/chakra.ts | 8 + apps/builder/pages/api/auth/[...nextauth].ts | 2 +- apps/builder/services/publicTypebot.tsx | 2 +- 18 files changed, 249 insertions(+), 170 deletions(-) delete mode 100644 apps/builder/components/board/StepTypesList/StepTypesList.tsx delete mode 100644 apps/builder/components/board/StepTypesList/index.tsx rename apps/builder/components/board/{StepTypesList => StepsSideBar}/StepCard.tsx (100%) rename apps/builder/components/board/{StepTypesList => StepsSideBar}/StepIcon.tsx (64%) create mode 100644 apps/builder/components/board/StepsSideBar/StepSideBar.tsx rename apps/builder/components/board/{StepTypesList => StepsSideBar}/StepTypeLabel.tsx (100%) create mode 100644 apps/builder/components/board/StepsSideBar/index.tsx diff --git a/apps/builder/assets/icons.tsx b/apps/builder/assets/icons.tsx index 714e1d7eaf..ae6959dd09 100644 --- a/apps/builder/assets/icons.tsx +++ b/apps/builder/assets/icons.tsx @@ -297,3 +297,17 @@ export const GripIcon = (props: IconProps) => ( ) + +export const LockedIcon = (props: IconProps) => ( + + + + +) + +export const UnlockedIcon = (props: IconProps) => ( + + + + +) diff --git a/apps/builder/components/board/Board.tsx b/apps/builder/components/board/Board.tsx index 8c98018af9..dfcb064a4b 100644 --- a/apps/builder/components/board/Board.tsx +++ b/apps/builder/components/board/Board.tsx @@ -2,7 +2,7 @@ import { Flex } from '@chakra-ui/react' import React from 'react' import Graph from './graph/Graph' import { StepDndContext } from 'contexts/StepDndContext' -import { StepTypesList } from './StepTypesList' +import { StepsSideBar } from './StepsSideBar' import { PreviewDrawer } from './preview/PreviewDrawer' import { RightPanel, useEditor } from 'contexts/EditorContext' import { GraphProvider } from 'contexts/GraphContext' @@ -13,7 +13,7 @@ export const Board = () => { return ( - + diff --git a/apps/builder/components/board/StepTypesList/StepTypesList.tsx b/apps/builder/components/board/StepTypesList/StepTypesList.tsx deleted file mode 100644 index 57388014c9..0000000000 --- a/apps/builder/components/board/StepTypesList/StepTypesList.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { - Stack, - Input, - Text, - SimpleGrid, - useEventListener, - Portal, -} from '@chakra-ui/react' -import { - BubbleStepType, - DraggableStepType, - InputStepType, - IntegrationStepType, - LogicStepType, -} from 'models' -import { useStepDnd } from 'contexts/StepDndContext' -import React, { useState } from 'react' -import { StepCard, StepCardOverlay } from './StepCard' - -export const StepTypesList = () => { - const { setDraggedStepType, draggedStepType } = useStepDnd() - const [position, setPosition] = useState({ - x: 0, - y: 0, - }) - const [relativeCoordinates, setRelativeCoordinates] = useState({ x: 0, y: 0 }) - - const handleMouseMove = (event: MouseEvent) => { - if (!draggedStepType) return - const { clientX, clientY } = event - setPosition({ - ...position, - x: clientX - relativeCoordinates.x, - y: clientY - relativeCoordinates.y, - }) - } - useEventListener('mousemove', handleMouseMove) - - const handleMouseDown = (e: React.MouseEvent, type: DraggableStepType) => { - const element = e.currentTarget as HTMLDivElement - const rect = element.getBoundingClientRect() - setPosition({ x: rect.left, y: rect.top }) - const x = e.clientX - rect.left - const y = e.clientY - rect.top - setRelativeCoordinates({ x, y }) - setDraggedStepType(type) - } - - const handleMouseUp = () => { - if (!draggedStepType) return - setDraggedStepType(undefined) - setPosition({ - x: 0, - y: 0, - }) - } - useEventListener('mouseup', handleMouseUp) - - return ( - - - - - Bubbles - - - {Object.values(BubbleStepType).map((type) => ( - - ))} - - - - - - Inputs - - - {Object.values(InputStepType).map((type) => ( - - ))} - - - - - - Logic - - - {Object.values(LogicStepType).map((type) => ( - - ))} - - - - - - Integrations - - - {Object.values(IntegrationStepType).map((type) => ( - - ))} - - - - {draggedStepType && ( - - - - )} - - ) -} diff --git a/apps/builder/components/board/StepTypesList/index.tsx b/apps/builder/components/board/StepTypesList/index.tsx deleted file mode 100644 index 532a5f8804..0000000000 --- a/apps/builder/components/board/StepTypesList/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export { StepTypesList } from './StepTypesList' diff --git a/apps/builder/components/board/StepTypesList/StepCard.tsx b/apps/builder/components/board/StepsSideBar/StepCard.tsx similarity index 100% rename from apps/builder/components/board/StepTypesList/StepCard.tsx rename to apps/builder/components/board/StepsSideBar/StepCard.tsx diff --git a/apps/builder/components/board/StepTypesList/StepIcon.tsx b/apps/builder/components/board/StepsSideBar/StepIcon.tsx similarity index 64% rename from apps/builder/components/board/StepTypesList/StepIcon.tsx rename to apps/builder/components/board/StepsSideBar/StepIcon.tsx index d496cc1169..3baebc9fe6 100644 --- a/apps/builder/components/board/StepTypesList/StepIcon.tsx +++ b/apps/builder/components/board/StepsSideBar/StepIcon.tsx @@ -31,31 +31,31 @@ type StepIconProps = { type: StepType } & IconProps export const StepIcon = ({ type, ...props }: StepIconProps) => { switch (type) { case BubbleStepType.TEXT: - return + return case BubbleStepType.IMAGE: - return + return case BubbleStepType.VIDEO: - return + return case InputStepType.TEXT: - return + return case InputStepType.NUMBER: - return + return case InputStepType.EMAIL: - return + return case InputStepType.URL: - return + return case InputStepType.DATE: - return + return case InputStepType.PHONE: - return + return case InputStepType.CHOICE: - return + return case LogicStepType.SET_VARIABLE: - return + return case LogicStepType.CONDITION: - return + return case LogicStepType.REDIRECT: - return + return case IntegrationStepType.GOOGLE_SHEETS: return case IntegrationStepType.GOOGLE_ANALYTICS: diff --git a/apps/builder/components/board/StepsSideBar/StepSideBar.tsx b/apps/builder/components/board/StepsSideBar/StepSideBar.tsx new file mode 100644 index 0000000000..f619fd54f7 --- /dev/null +++ b/apps/builder/components/board/StepsSideBar/StepSideBar.tsx @@ -0,0 +1,191 @@ +import { + Stack, + Input, + Text, + SimpleGrid, + useEventListener, + Portal, + Flex, + IconButton, + Tooltip, + Fade, +} from '@chakra-ui/react' +import { + BubbleStepType, + DraggableStepType, + InputStepType, + IntegrationStepType, + LogicStepType, +} from 'models' +import { useStepDnd } from 'contexts/StepDndContext' +import React, { useState } from 'react' +import { StepCard, StepCardOverlay } from './StepCard' +import { LockedIcon, UnlockedIcon } from 'assets/icons' +import { headerHeight } from 'components/shared/TypebotHeader' + +export const StepsSideBar = () => { + const { setDraggedStepType, draggedStepType } = useStepDnd() + const [position, setPosition] = useState({ + x: 0, + y: 0, + }) + const [relativeCoordinates, setRelativeCoordinates] = useState({ x: 0, y: 0 }) + const [isLocked, setIsLocked] = useState(true) + const [isExtended, setIsExtended] = useState(true) + + const handleMouseMove = (event: MouseEvent) => { + if (!draggedStepType) return + const { clientX, clientY } = event + setPosition({ + ...position, + x: clientX - relativeCoordinates.x, + y: clientY - relativeCoordinates.y, + }) + } + useEventListener('mousemove', handleMouseMove) + + const handleMouseDown = (e: React.MouseEvent, type: DraggableStepType) => { + const element = e.currentTarget as HTMLDivElement + const rect = element.getBoundingClientRect() + setPosition({ x: rect.left, y: rect.top }) + const x = e.clientX - rect.left + const y = e.clientY - rect.top + setRelativeCoordinates({ x, y }) + setDraggedStepType(type) + } + + const handleMouseUp = () => { + if (!draggedStepType) return + setDraggedStepType(undefined) + setPosition({ + x: 0, + y: 0, + }) + } + useEventListener('mouseup', handleMouseUp) + + const handleLockClick = () => setIsLocked(!isLocked) + + const handleDockBarEnter = () => setIsExtended(true) + + const handleMouseLeave = () => { + if (isLocked) return + setIsExtended(false) + } + + return ( + + + + + + : } + aria-label={isLocked ? 'Unlock' : 'Lock'} + size="sm" + variant="outline" + onClick={handleLockClick} + /> + + + + + + + + Bubbles + + + {Object.values(BubbleStepType).map((type) => ( + + ))} + + + + + + Inputs + + + {Object.values(InputStepType).map((type) => ( + + ))} + + + + + + Logic + + + {Object.values(LogicStepType).map((type) => ( + + ))} + + + + + + Integrations + + + {Object.values(IntegrationStepType).map((type) => ( + + ))} + + + + {draggedStepType && ( + + + + )} + + + + + + + + ) +} diff --git a/apps/builder/components/board/StepTypesList/StepTypeLabel.tsx b/apps/builder/components/board/StepsSideBar/StepTypeLabel.tsx similarity index 100% rename from apps/builder/components/board/StepTypesList/StepTypeLabel.tsx rename to apps/builder/components/board/StepsSideBar/StepTypeLabel.tsx diff --git a/apps/builder/components/board/StepsSideBar/index.tsx b/apps/builder/components/board/StepsSideBar/index.tsx new file mode 100644 index 0000000000..5d4f2b6bfc --- /dev/null +++ b/apps/builder/components/board/StepsSideBar/index.tsx @@ -0,0 +1 @@ +export { StepsSideBar } from './StepSideBar' diff --git a/apps/builder/components/board/graph/BlockNode/StepNode/ChoiceInputStepNode/ChoiceItemNode.tsx b/apps/builder/components/board/graph/BlockNode/StepNode/ChoiceInputStepNode/ChoiceItemNode.tsx index 16a9af3129..8eea2a5e4d 100644 --- a/apps/builder/components/board/graph/BlockNode/StepNode/ChoiceInputStepNode/ChoiceItemNode.tsx +++ b/apps/builder/components/board/graph/BlockNode/StepNode/ChoiceInputStepNode/ChoiceItemNode.tsx @@ -94,6 +94,7 @@ export const ChoiceItemNode = ({ > {(ref, isOpened) => ( { return ( - + diff --git a/apps/builder/components/board/graph/BlockNode/StepNode/StepNode.tsx b/apps/builder/components/board/graph/BlockNode/StepNode/StepNode.tsx index 797b02f77c..de99b9c5f3 100644 --- a/apps/builder/components/board/graph/BlockNode/StepNode/StepNode.tsx +++ b/apps/builder/components/board/graph/BlockNode/StepNode/StepNode.tsx @@ -9,7 +9,7 @@ import { import React, { useEffect, useState } from 'react' import { BubbleStep, DraggableStep, Step, TextBubbleStep } from 'models' import { Coordinates, useGraph } from 'contexts/GraphContext' -import { StepIcon } from 'components/board/StepTypesList/StepIcon' +import { StepIcon } from 'components/board/StepsSideBar/StepIcon' import { isBubbleStep, isTextBubbleStep } from 'utils' import { TextEditor } from './TextEditor/TextEditor' import { StepNodeContent } from './StepNodeContent/StepNodeContent' @@ -152,7 +152,7 @@ export const StepNode = ({ renderMenu={() => } > {(ref, isOpened) => ( - + ({ {currentItem ?? placeholder} - + {items.map((item) => ( void } const UploadFileContent = ({ onNewUrl }: ContentProps) => { const { typebot } = useTypebot() return ( - + { > Choose an image - + ) } @@ -106,11 +106,14 @@ const EmbedLinkContent = ({ initialUrl, onNewUrl }: ContentProps) => { setImageUrl(e.target.value) return ( - + + + ) } diff --git a/apps/builder/libs/chakra.ts b/apps/builder/libs/chakra.ts index 27be24e640..973f71dd2d 100644 --- a/apps/builder/libs/chakra.ts +++ b/apps/builder/libs/chakra.ts @@ -90,6 +90,14 @@ const components = { _hover: { textDecoration: 'none' }, }, }, + Menu: { + parts: ['list'], + defaultProps: { + list: { + shadow: 'lg', + }, + }, + }, } export const customTheme = extendTheme({ colors, fonts, components }) diff --git a/apps/builder/pages/api/auth/[...nextauth].ts b/apps/builder/pages/api/auth/[...nextauth].ts index 3efa15328d..52b12f5b05 100644 --- a/apps/builder/pages/api/auth/[...nextauth].ts +++ b/apps/builder/pages/api/auth/[...nextauth].ts @@ -12,7 +12,7 @@ const providers: Provider[] = [ EmailProvider({ server: { host: process.env.EMAIL_SERVER_HOST, - port: process.env.EMAIL_SERVER_PORT, + port: Number(process.env.EMAIL_SERVER_PORT), auth: { user: process.env.EMAIL_SERVER_USER, pass: process.env.EMAIL_SERVER_PASSWORD, diff --git a/apps/builder/services/publicTypebot.tsx b/apps/builder/services/publicTypebot.tsx index fbe28bc8fc..36ea0be07e 100644 --- a/apps/builder/services/publicTypebot.tsx +++ b/apps/builder/services/publicTypebot.tsx @@ -2,7 +2,7 @@ import { PublicTypebot, Typebot } from 'models' import shortId from 'short-uuid' import { HStack, Text } from '@chakra-ui/react' import { CalendarIcon } from 'assets/icons' -import { StepIcon } from 'components/board/StepTypesList/StepIcon' +import { StepIcon } from 'components/board/StepsSideBar/StepIcon' import { isInputStep, sendRequest } from 'utils' export const parseTypebotToPublicTypebot = (