diff --git a/apps/builder/src/features/editor/components/BlockLabel.tsx b/apps/builder/src/features/editor/components/BlockLabel.tsx
index 35baa6f34..b1053584b 100644
--- a/apps/builder/src/features/editor/components/BlockLabel.tsx
+++ b/apps/builder/src/features/editor/components/BlockLabel.tsx
@@ -1,225 +1,97 @@
import { Text, TextProps } from '@chakra-ui/react'
import React from 'react'
-import { useTranslate } from '@tolgee/react'
+import { TFnType, useTranslate } from '@tolgee/react'
import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
import { IntegrationBlockType } from '@typebot.io/schemas/features/blocks/integrations/constants'
import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/constants'
import { Block } from '@typebot.io/schemas'
import { ForgedBlockLabel } from '@/features/forge/ForgedBlockLabel'
+import { isForgedBlockType } from '@typebot.io/schemas/features/blocks/forged/helpers'
+import {
+ isBubbleBlockType,
+ isInputBlockType,
+ isIntegrationBlockType,
+ isLogicBlockType,
+} from '@typebot.io/schemas/helpers'
type Props = { type: Block['type'] } & TextProps
export const BlockLabel = ({ type, ...props }: Props): JSX.Element => {
const { t } = useTranslate()
- switch (type) {
- case 'start':
- return (
-
- {t('editor.sidebarBlock.start.label')}
-
- )
- case BubbleBlockType.TEXT:
- case InputBlockType.TEXT:
- return (
-
- {t('editor.sidebarBlock.text.label')}
-
- )
- case BubbleBlockType.IMAGE:
- return (
-
- {t('editor.sidebarBlock.image.label')}
-
- )
- case BubbleBlockType.VIDEO:
- return (
-
- {t('editor.sidebarBlock.video.label')}
-
- )
- case BubbleBlockType.EMBED:
- return (
-
- {t('editor.sidebarBlock.embed.label')}
-
- )
- case BubbleBlockType.AUDIO:
- return (
-
- {t('editor.sidebarBlock.audio.label')}
-
- )
- case InputBlockType.NUMBER:
- return (
-
- {t('editor.sidebarBlock.number.label')}
-
- )
- case InputBlockType.EMAIL:
- return (
-
- {t('editor.sidebarBlock.email.label')}
-
- )
- case InputBlockType.URL:
- return (
-
- {t('editor.sidebarBlock.website.label')}
-
- )
- case InputBlockType.DATE:
- return (
-
- {t('editor.sidebarBlock.date.label')}
-
- )
- case InputBlockType.PHONE:
- return (
-
- {t('editor.sidebarBlock.phone.label')}
-
- )
- case InputBlockType.CHOICE:
- return (
-
- {t('editor.sidebarBlock.button.label')}
-
- )
- case InputBlockType.PICTURE_CHOICE:
- return (
-
- {t('editor.sidebarBlock.picChoice.label')}
-
- )
- case InputBlockType.PAYMENT:
- return (
-
- {t('editor.sidebarBlock.payment.label')}
-
- )
- case InputBlockType.RATING:
- return (
-
- {t('editor.sidebarBlock.rating.label')}
-
- )
- case InputBlockType.FILE:
- return (
-
- {t('editor.sidebarBlock.file.label')}
-
- )
- case LogicBlockType.SET_VARIABLE:
- return (
-
- {t('editor.sidebarBlock.setVariable.label')}
-
- )
- case LogicBlockType.CONDITION:
- return (
-
- {t('editor.sidebarBlock.condition.label')}
-
- )
- case LogicBlockType.REDIRECT:
- return (
-
- {t('editor.sidebarBlock.redirect.label')}
-
- )
- case LogicBlockType.SCRIPT:
- return (
-
- {t('editor.sidebarBlock.script.label')}
-
- )
- case LogicBlockType.TYPEBOT_LINK:
- return (
-
- {t('editor.sidebarBlock.typebot.label')}
-
- )
- case LogicBlockType.WAIT:
- return (
-
- {t('editor.sidebarBlock.wait.label')}
-
- )
- case LogicBlockType.JUMP:
- return (
-
- {t('editor.sidebarBlock.jump.label')}
-
- )
- case LogicBlockType.AB_TEST:
- return (
-
- {t('editor.sidebarBlock.abTest.label')}
-
- )
- case IntegrationBlockType.GOOGLE_SHEETS:
- return (
-
- {t('editor.sidebarBlock.sheets.label')}
-
- )
- case IntegrationBlockType.GOOGLE_ANALYTICS:
- return (
-
- {t('editor.sidebarBlock.analytics.label')}
-
- )
- case IntegrationBlockType.WEBHOOK:
- return (
-
- HTTP request
-
- )
- case IntegrationBlockType.ZAPIER:
- return (
-
- {t('editor.sidebarBlock.zapier.label')}
-
- )
- case IntegrationBlockType.MAKE_COM:
- return (
-
- {t('editor.sidebarBlock.makecom.label')}
-
- )
- case IntegrationBlockType.PABBLY_CONNECT:
- return (
-
- {t('editor.sidebarBlock.pabbly.label')}
-
- )
- case IntegrationBlockType.EMAIL:
- return (
-
- {t('editor.sidebarBlock.email.label')}
-
- )
- case IntegrationBlockType.CHATWOOT:
- return (
-
- {t('editor.sidebarBlock.chatwoot.label')}
-
- )
- case IntegrationBlockType.OPEN_AI:
- return (
-
- {t('editor.sidebarBlock.openai.label')}
-
- )
- case IntegrationBlockType.PIXEL:
- return (
-
- {t('editor.sidebarBlock.pixel.label')}
-
- )
- default:
- return
- }
+ if (isForgedBlockType(type))
+ return
+
+ const label = isBubbleBlockType(type)
+ ? getBubbleBlockLabel(t)[type]
+ : isInputBlockType(type)
+ ? getInputBlockLabel(t)[type]
+ : isLogicBlockType(type)
+ ? getLogicBlockLabel(t)[type]
+ : isIntegrationBlockType(type)
+ ? getIntegrationBlockLabel(t)[type]
+ : t('editor.sidebarBlock.start.label')
+
+ return (
+
+ {label}
+
+ )
}
+
+export const getBubbleBlockLabel = (
+ t: TFnType
+): Record => ({
+ [BubbleBlockType.TEXT]: t('editor.sidebarBlock.text.label'),
+ [BubbleBlockType.IMAGE]: t('editor.sidebarBlock.image.label'),
+ [BubbleBlockType.VIDEO]: t('editor.sidebarBlock.video.label'),
+ [BubbleBlockType.EMBED]: t('editor.sidebarBlock.embed.label'),
+ [BubbleBlockType.AUDIO]: t('editor.sidebarBlock.audio.label'),
+})
+
+export const getInputBlockLabel = (
+ t: TFnType
+): Record => ({
+ [InputBlockType.NUMBER]: t('editor.sidebarBlock.number.label'),
+ [InputBlockType.EMAIL]: t('editor.sidebarBlock.email.label'),
+ [InputBlockType.TEXT]: t('editor.sidebarBlock.text.label'),
+ [InputBlockType.URL]: t('editor.sidebarBlock.website.label'),
+ [InputBlockType.DATE]: t('editor.sidebarBlock.date.label'),
+ [InputBlockType.PHONE]: t('editor.sidebarBlock.phone.label'),
+ [InputBlockType.CHOICE]: t('editor.sidebarBlock.button.label'),
+ [InputBlockType.PICTURE_CHOICE]: t('editor.sidebarBlock.picChoice.label'),
+ [InputBlockType.PAYMENT]: t('editor.sidebarBlock.payment.label'),
+ [InputBlockType.RATING]: t('editor.sidebarBlock.rating.label'),
+ [InputBlockType.FILE]: t('editor.sidebarBlock.file.label'),
+})
+
+export const getLogicBlockLabel = (
+ t: TFnType
+): Record => ({
+ [LogicBlockType.SET_VARIABLE]: t('editor.sidebarBlock.setVariable.label'),
+ [LogicBlockType.CONDITION]: t('editor.sidebarBlock.condition.label'),
+ [LogicBlockType.REDIRECT]: t('editor.sidebarBlock.redirect.label'),
+ [LogicBlockType.SCRIPT]: t('editor.sidebarBlock.script.label'),
+ [LogicBlockType.TYPEBOT_LINK]: t('editor.sidebarBlock.typebot.label'),
+ [LogicBlockType.WAIT]: t('editor.sidebarBlock.wait.label'),
+ [LogicBlockType.JUMP]: t('editor.sidebarBlock.jump.label'),
+ [LogicBlockType.AB_TEST]: t('editor.sidebarBlock.abTest.label'),
+})
+
+export const getIntegrationBlockLabel = (
+ t: TFnType
+): Record => ({
+ [IntegrationBlockType.GOOGLE_SHEETS]: t('editor.sidebarBlock.sheets.label'),
+ [IntegrationBlockType.GOOGLE_ANALYTICS]: t(
+ 'editor.sidebarBlock.analytics.label'
+ ),
+ [IntegrationBlockType.WEBHOOK]: 'HTTP request',
+ [IntegrationBlockType.ZAPIER]: t('editor.sidebarBlock.zapier.label'),
+ [IntegrationBlockType.MAKE_COM]: t('editor.sidebarBlock.makecom.label'),
+ [IntegrationBlockType.PABBLY_CONNECT]: t('editor.sidebarBlock.pabbly.label'),
+ [IntegrationBlockType.EMAIL]: t('editor.sidebarBlock.email.label'),
+ [IntegrationBlockType.CHATWOOT]: t('editor.sidebarBlock.chatwoot.label'),
+ [IntegrationBlockType.OPEN_AI]: t('editor.sidebarBlock.openai.label'),
+ [IntegrationBlockType.PIXEL]: t('editor.sidebarBlock.pixel.label'),
+})
diff --git a/apps/builder/src/features/editor/components/BlocksSideBar.tsx b/apps/builder/src/features/editor/components/BlocksSideBar.tsx
index d9689e243..263de2962 100644
--- a/apps/builder/src/features/editor/components/BlocksSideBar.tsx
+++ b/apps/builder/src/features/editor/components/BlocksSideBar.tsx
@@ -19,13 +19,19 @@ import { LockedIcon, UnlockedIcon } from '@/components/icons'
import { BlockCardOverlay } from './BlockCardOverlay'
import { headerHeight } from '../constants'
import { useTranslate } from '@tolgee/react'
-import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
import { InputBlockType } from '@typebot.io/schemas/features/blocks/inputs/constants'
import { IntegrationBlockType } from '@typebot.io/schemas/features/blocks/integrations/constants'
import { LogicBlockType } from '@typebot.io/schemas/features/blocks/logic/constants'
import { BlockV6 } from '@typebot.io/schemas'
import { useDebouncedCallback } from 'use-debounce'
import { forgedBlocks } from '@typebot.io/forge-repository/definitions'
+import {
+ getBubbleBlockLabel,
+ getInputBlockLabel,
+ getIntegrationBlockLabel,
+ getLogicBlockLabel,
+} from './BlockLabel'
+import { BubbleBlockType } from '@typebot.io/schemas/features/blocks/bubbles/constants'
// Integration blocks migrated to forged blocks
const legacyIntegrationBlocks = [IntegrationBlockType.OPEN_AI]
@@ -92,9 +98,8 @@ export const BlocksSideBar = () => {
}) => {
setSearchInput(event.target.value)
}
- const blocksArray = Object.values(forgedBlocks)
- const filteredForgedBlockIds = blocksArray
+ const filteredForgedBlockIds = Object.values(forgedBlocks)
.filter((block) => {
return (
block.id.toLowerCase().includes(searchInput.toLowerCase()) ||
@@ -107,6 +112,35 @@ export const BlocksSideBar = () => {
})
.map((block) => block.id)
+ const filteredBubbleBlockTypes = Object.values(BubbleBlockType).filter(
+ (type) =>
+ getBubbleBlockLabel(t)
+ [type].toLowerCase()
+ .includes(searchInput.toLowerCase())
+ )
+
+ const filteredInputBlockTypes = Object.values(InputBlockType).filter((type) =>
+ getInputBlockLabel(t)
+ [type].toLowerCase()
+ .includes(searchInput.toLowerCase())
+ )
+
+ const filteredLogicBlockTypes = Object.values(LogicBlockType).filter((type) =>
+ getLogicBlockLabel(t)
+ [type].toLowerCase()
+ .includes(searchInput.toLowerCase())
+ )
+
+ const filteredIntegrationBlockTypes = Object.values(
+ IntegrationBlockType
+ ).filter(
+ (type) =>
+ getIntegrationBlockLabel(t)
+ [type].toLowerCase()
+ .includes(searchInput.toLowerCase()) &&
+ !legacyIntegrationBlocks.includes(type)
+ )
+
return (
{
{t('editor.sidebarBlocks.blockType.bubbles.heading')}
- {Object.values(BubbleBlockType)
- .filter((type) =>
- type.toLowerCase().includes(searchInput.toLowerCase())
- )
- .map((type) => (
-
- ))}
+ {filteredBubbleBlockTypes.map((type) => (
+
+ ))}
@@ -188,17 +214,9 @@ export const BlocksSideBar = () => {
{t('editor.sidebarBlocks.blockType.inputs.heading')}
- {Object.values(InputBlockType)
- .filter((type) =>
- type.toLowerCase().includes(searchInput.toLowerCase())
- )
- .map((type) => (
-
- ))}
+ {filteredInputBlockTypes.map((type) => (
+
+ ))}
@@ -207,17 +225,9 @@ export const BlocksSideBar = () => {
{t('editor.sidebarBlocks.blockType.logic.heading')}
- {Object.values(LogicBlockType)
- .filter((type) =>
- type.toLowerCase().includes(searchInput.toLowerCase())
- )
- .map((type) => (
-
- ))}
+ {filteredLogicBlockTypes.map((type) => (
+
+ ))}
@@ -226,12 +236,8 @@ export const BlocksSideBar = () => {
{t('editor.sidebarBlocks.blockType.integrations.heading')}
- {Object.values(IntegrationBlockType)
- .filter((type) =>
- type.toLowerCase().includes(searchInput.toLowerCase())
- )
+ {filteredIntegrationBlockTypes
.concat(filteredForgedBlockIds as any)
- .filter((type) => !legacyIntegrationBlocks.includes(type))
.map((type) => (
(Object.values(BubbleBlockType) as string[]).includes(type)
+export const isInputBlockType = (type: Block['type']): type is InputBlockType =>
+ (Object.values(InputBlockType) as string[]).includes(type)
+
+export const isIntegrationBlockType = (
+ type: Block['type']
+): type is IntegrationBlockType =>
+ (Object.values(IntegrationBlockType) as string[]).includes(type)
+
+export const isLogicBlockType = (type: Block['type']): type is LogicBlockType =>
+ (Object.values(LogicBlockType) as string[]).includes(type)
+
export const blockHasOptions = (block: Block): block is BlockWithOptions =>
'options' in block