fix(dashboard): 🩹 typebot buttons menu
This commit is contained in:
@ -10,7 +10,7 @@ import { Block } from 'models'
|
||||
import { useGraph } from 'contexts/GraphContext'
|
||||
import { useStepDnd } from 'contexts/StepDndContext'
|
||||
import { StepsList } from './StepsList'
|
||||
import { filterTable, isDefined } from 'utils'
|
||||
import { isDefined } from 'utils'
|
||||
import { useTypebot } from 'contexts/TypebotContext/TypebotContext'
|
||||
import { ContextMenu } from 'components/shared/ContextMenu'
|
||||
import { BlockNodeContextMenu } from './BlockNodeContextMenu'
|
||||
@ -114,12 +114,7 @@ export const BlockNode = ({ block }: Props) => {
|
||||
/>
|
||||
<EditableInput minW="0" px="1" />
|
||||
</Editable>
|
||||
{typebot && (
|
||||
<StepsList
|
||||
blockId={block.id}
|
||||
steps={filterTable(block.stepIds, typebot?.steps)}
|
||||
/>
|
||||
)}
|
||||
{typebot && <StepsList blockId={block.id} stepIds={block.stepIds} />}
|
||||
</Stack>
|
||||
)}
|
||||
</ContextMenu>
|
||||
|
@ -44,7 +44,7 @@ export const StepNode = ({
|
||||
const { query } = useRouter()
|
||||
const { setConnectingIds, connectingIds, openedStepId, setOpenedStepId } =
|
||||
useGraph()
|
||||
const { moveStep } = useTypebot()
|
||||
const { detachStepFromBlock } = useTypebot()
|
||||
const [isConnecting, setIsConnecting] = useState(false)
|
||||
const [mouseDownEvent, setMouseDownEvent] =
|
||||
useState<{ absolute: Coordinates; relative: Coordinates }>()
|
||||
@ -116,8 +116,9 @@ export const StepNode = ({
|
||||
onMouseDown &&
|
||||
(event.movementX > 0 || event.movementY > 0)
|
||||
if (isMovingAndIsMouseDown && step.type !== 'start') {
|
||||
console.log(step)
|
||||
onMouseDown(mouseDownEvent, step)
|
||||
moveStep(step.id)
|
||||
detachStepFromBlock(step.id)
|
||||
setMouseDownEvent(undefined)
|
||||
}
|
||||
const element = event.currentTarget as HTMLDivElement
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Box, Flex, Image, Text } from '@chakra-ui/react'
|
||||
import { Box, Image, Text } from '@chakra-ui/react'
|
||||
import {
|
||||
Step,
|
||||
StartStep,
|
||||
@ -7,9 +7,12 @@ import {
|
||||
LogicStepType,
|
||||
IntegrationStepType,
|
||||
} from 'models'
|
||||
import { isInputStep } from 'utils'
|
||||
import { ChoiceItemsList } from '../ChoiceInputStepNode/ChoiceItemsList'
|
||||
import { ConditionNodeContent } from './ConditionNodeContent'
|
||||
import { SetVariableNodeContent } from './SetVariableNodeContent'
|
||||
import { StepNodeContentWithVariable } from './StepNodeContentWithVariable'
|
||||
import { TextBubbleNodeContent } from './TextBubbleNodeContent'
|
||||
import { VideoStepNodeContent } from './VideoStepNodeContent'
|
||||
import { WebhookContent } from './WebhookContent'
|
||||
|
||||
@ -18,21 +21,12 @@ type Props = {
|
||||
isConnectable?: boolean
|
||||
}
|
||||
export const StepNodeContent = ({ step }: Props) => {
|
||||
if (isInputStep(step) && step.options.variableId) {
|
||||
return <StepNodeContentWithVariable step={step} />
|
||||
}
|
||||
switch (step.type) {
|
||||
case BubbleStepType.TEXT: {
|
||||
return (
|
||||
<Flex
|
||||
flexDir={'column'}
|
||||
opacity={step.content.html === '' ? '0.5' : '1'}
|
||||
className="slate-html-container"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
step.content.html === ''
|
||||
? `<p>Click to edit...</p>`
|
||||
: step.content.html,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
return <TextBubbleNodeContent step={step} />
|
||||
}
|
||||
case BubbleStepType.IMAGE: {
|
||||
return !step.content?.url ? (
|
||||
|
@ -0,0 +1,28 @@
|
||||
import { InputStep } from 'models'
|
||||
import { chakra, Text } from '@chakra-ui/react'
|
||||
import React from 'react'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
|
||||
type Props = {
|
||||
step: InputStep
|
||||
}
|
||||
|
||||
export const StepNodeContentWithVariable = ({ step }: Props) => {
|
||||
const { typebot } = useTypebot()
|
||||
const variableName =
|
||||
typebot?.variables.byId[step.options.variableId as string].name
|
||||
return (
|
||||
<Text>
|
||||
Collect{' '}
|
||||
<chakra.span
|
||||
bgColor="orange.400"
|
||||
color="white"
|
||||
rounded="md"
|
||||
py="0.5"
|
||||
px="1"
|
||||
>
|
||||
{variableName}
|
||||
</chakra.span>
|
||||
</Text>
|
||||
)
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { Flex } from '@chakra-ui/react'
|
||||
import { useTypebot } from 'contexts/TypebotContext'
|
||||
import { TextBubbleStep } from 'models'
|
||||
import React from 'react'
|
||||
import { parseVariableHighlight } from 'services/utils'
|
||||
|
||||
type Props = {
|
||||
step: TextBubbleStep
|
||||
}
|
||||
|
||||
export const TextBubbleNodeContent = ({ step }: Props) => {
|
||||
const { typebot } = useTypebot()
|
||||
return (
|
||||
<Flex
|
||||
flexDir={'column'}
|
||||
opacity={step.content.html === '' ? '0.5' : '1'}
|
||||
className="slate-html-container"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html:
|
||||
step.content.html === ''
|
||||
? `<p>Click to edit...</p>`
|
||||
: parseVariableHighlight(step.content.html, typebot),
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { useEventListener, Stack, Flex, Portal } from '@chakra-ui/react'
|
||||
import { DraggableStep, Step, Table } from 'models'
|
||||
import { DraggableStep } from 'models'
|
||||
import { useStepDnd } from 'contexts/StepDndContext'
|
||||
import { Coordinates } from 'contexts/GraphContext'
|
||||
import { useMemo, useState } from 'react'
|
||||
@ -8,10 +8,10 @@ import { useTypebot } from 'contexts/TypebotContext'
|
||||
|
||||
export const StepsList = ({
|
||||
blockId,
|
||||
steps,
|
||||
stepIds,
|
||||
}: {
|
||||
blockId: string
|
||||
steps: Table<Step>
|
||||
stepIds: string[]
|
||||
}) => {
|
||||
const {
|
||||
draggedStep,
|
||||
@ -21,7 +21,7 @@ export const StepsList = ({
|
||||
setDraggedStepType,
|
||||
setMouseOverBlockId,
|
||||
} = useStepDnd()
|
||||
const { createStep } = useTypebot()
|
||||
const { typebot, createStep } = useTypebot()
|
||||
const [expandedPlaceholderIndex, setExpandedPlaceholderIndex] = useState<
|
||||
number | undefined
|
||||
>()
|
||||
@ -59,14 +59,14 @@ export const StepsList = ({
|
||||
e.stopPropagation()
|
||||
setMouseOverBlockId(undefined)
|
||||
setExpandedPlaceholderIndex(undefined)
|
||||
if (draggedStepType) {
|
||||
createStep(blockId, draggedStepType, expandedPlaceholderIndex)
|
||||
setDraggedStepType(undefined)
|
||||
}
|
||||
if (draggedStep) {
|
||||
createStep(blockId, draggedStep, expandedPlaceholderIndex)
|
||||
setDraggedStep(undefined)
|
||||
}
|
||||
if (!draggedStep && !draggedStepType) return
|
||||
createStep(
|
||||
blockId,
|
||||
draggedStep || draggedStepType,
|
||||
expandedPlaceholderIndex
|
||||
)
|
||||
setDraggedStep(undefined)
|
||||
setDraggedStepType(undefined)
|
||||
}
|
||||
|
||||
const handleStepMouseDown = (
|
||||
@ -107,31 +107,32 @@ export const StepsList = ({
|
||||
rounded="lg"
|
||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||
/>
|
||||
{steps.allIds.map((stepId, idx) => (
|
||||
<Stack key={stepId} spacing={1}>
|
||||
<StepNode
|
||||
key={stepId}
|
||||
step={steps.byId[stepId]}
|
||||
isConnectable={steps.allIds.length - 1 === idx}
|
||||
onMouseMoveTopOfElement={() => handleMouseOnTopOfStep(idx)}
|
||||
onMouseMoveBottomOfElement={() => {
|
||||
handleMouseOnBottomOfStep(idx)
|
||||
}}
|
||||
onMouseDown={handleStepMouseDown}
|
||||
/>
|
||||
<Flex
|
||||
h={
|
||||
showSortPlaceholders && expandedPlaceholderIndex === idx + 1
|
||||
? '50px'
|
||||
: '2px'
|
||||
}
|
||||
bgColor={'gray.300'}
|
||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||
rounded="lg"
|
||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
{typebot &&
|
||||
stepIds.map((stepId, idx) => (
|
||||
<Stack key={stepId} spacing={1}>
|
||||
<StepNode
|
||||
key={stepId}
|
||||
step={typebot?.steps.byId[stepId]}
|
||||
isConnectable={stepIds.length - 1 === idx}
|
||||
onMouseMoveTopOfElement={() => handleMouseOnTopOfStep(idx)}
|
||||
onMouseMoveBottomOfElement={() => {
|
||||
handleMouseOnBottomOfStep(idx)
|
||||
}}
|
||||
onMouseDown={handleStepMouseDown}
|
||||
/>
|
||||
<Flex
|
||||
h={
|
||||
showSortPlaceholders && expandedPlaceholderIndex === idx + 1
|
||||
? '50px'
|
||||
: '2px'
|
||||
}
|
||||
bgColor={'gray.300'}
|
||||
visibility={showSortPlaceholders ? 'visible' : 'hidden'}
|
||||
rounded="lg"
|
||||
transition={showSortPlaceholders ? 'height 200ms' : 'none'}
|
||||
/>
|
||||
</Stack>
|
||||
))}
|
||||
{draggedStep && draggedStep.blockId === blockId && (
|
||||
<Portal>
|
||||
<StepNodeOverlay
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
import { FolderPlusIcon } from 'assets/icons'
|
||||
import { useTypebotDnd } from 'contexts/TypebotDndContext'
|
||||
import { Typebot } from 'models'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { createFolder, useFolders } from 'services/folders'
|
||||
import { patchTypebot, useTypebots } from 'services/typebots'
|
||||
import { BackButton } from './FolderContent/BackButton'
|
||||
|
@ -16,8 +16,7 @@ export const MoreButton = ({ children, ...props }: Props) => {
|
||||
<MenuButton
|
||||
as={IconButton}
|
||||
icon={<MoreVerticalIcon />}
|
||||
onMouseUp={(e) => e.stopPropagation()}
|
||||
onMouseDown={(e) => e.stopPropagation()}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
colorScheme="gray"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
|
@ -18,6 +18,7 @@ import { GlobeIcon, GripIcon, ToolIcon } from 'assets/icons'
|
||||
import { deleteTypebot, duplicateTypebot } from 'services/typebots'
|
||||
import { Typebot } from 'models'
|
||||
import { useTypebotDnd } from 'contexts/TypebotDndContext'
|
||||
import { useDebounce } from 'use-debounce'
|
||||
|
||||
type ChatbotCardProps = {
|
||||
typebot: Typebot
|
||||
@ -32,6 +33,7 @@ export const TypebotButton = ({
|
||||
}: ChatbotCardProps) => {
|
||||
const router = useRouter()
|
||||
const { draggedTypebot } = useTypebotDnd()
|
||||
const [draggedTypebotDebounced] = useDebounce(draggedTypebot, 200)
|
||||
const {
|
||||
isOpen: isDeleteOpen,
|
||||
onOpen: onDeleteOpen,
|
||||
@ -44,7 +46,7 @@ export const TypebotButton = ({
|
||||
})
|
||||
|
||||
const handleTypebotClick = () => {
|
||||
if (draggedTypebot) return
|
||||
if (draggedTypebotDebounced) return
|
||||
router.push(
|
||||
isMobile
|
||||
? `/typebots/${typebot.id}/results/responses`
|
||||
@ -72,10 +74,15 @@ export const TypebotButton = ({
|
||||
if (createdTypebot) router.push(`/typebots/${createdTypebot?.id}`)
|
||||
}
|
||||
|
||||
const handleDeleteClick = (e: React.MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
onDeleteOpen()
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
as={WrapItem}
|
||||
onMouseUp={handleTypebotClick}
|
||||
onClick={handleTypebotClick}
|
||||
display="flex"
|
||||
flexDir="column"
|
||||
variant="outline"
|
||||
@ -108,13 +115,7 @@ export const TypebotButton = ({
|
||||
aria-label={`Show ${typebot.name} menu`}
|
||||
>
|
||||
<MenuItem onClick={handleDuplicateClick}>Duplicate</MenuItem>
|
||||
<MenuItem
|
||||
color="red"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onDeleteOpen()
|
||||
}}
|
||||
>
|
||||
<MenuItem color="red" onClick={handleDeleteClick}>
|
||||
Delete
|
||||
</MenuItem>
|
||||
</MoreButton>
|
||||
|
Reference in New Issue
Block a user