2
0

📝 (embed) Add new script embed instructions

This commit is contained in:
Baptiste Arnaud
2023-02-25 10:16:57 +01:00
parent 8034ceeede
commit 2b2b1c3d6d
8 changed files with 211 additions and 0 deletions

View File

@ -24,6 +24,8 @@ import {
WixModal,
} from './modals'
import { OtherModal } from './modals/OtherModal'
import { ScriptIcon } from '@/features/blocks/logic/script'
import { ScriptModal } from './modals/Script/ScriptModal'
export type ModalProps = {
publicId: string
@ -112,6 +114,14 @@ export const integrationsList = [
{...props}
/>
),
(props: Pick<ModalProps, 'publicId' | 'isPublished'>) => (
<EmbedButton
logo={<ScriptIcon height={100} width="70px" color="gray.300" />}
label="Script"
Modal={ScriptModal}
{...props}
/>
),
(props: Pick<ModalProps, 'publicId' | 'isPublished'>) => (
<EmbedButton
logo={<NotionLogo height={100} width="60px" />}

View File

@ -0,0 +1,25 @@
import React, { useState } from 'react'
import { ModalProps } from '../../EmbedButton'
import { EmbedModal } from '../../EmbedModal'
import { isDefined } from '@udecode/plate-common'
import { ScriptInstructions } from './instructions/ScriptInstructions'
export const ScriptModal = ({ isOpen, onClose, isPublished }: ModalProps) => {
const [selectedEmbedType, setSelectedEmbedType] = useState<
'standard' | 'popup' | 'bubble' | undefined
>()
return (
<EmbedModal
titlePrefix="Script"
isOpen={isOpen}
onClose={onClose}
isPublished={isPublished}
onSelectEmbedType={setSelectedEmbedType}
selectedEmbedType={selectedEmbedType}
>
{isDefined(selectedEmbedType) && (
<ScriptInstructions type={selectedEmbedType} />
)}
</EmbedModal>
)
}

View File

@ -0,0 +1,55 @@
import { CodeEditor } from '@/components/CodeEditor'
import { useTypebot } from '@/features/editor'
import { isCloudProdInstance } from '@/utils/helpers'
import { Stack, Text } from '@chakra-ui/react'
import { BubbleProps } from '@typebot.io/js'
import { Typebot } from 'models'
import { useState } from 'react'
import { env, getViewerUrl } from 'utils'
import { BubbleSettings } from '../../../settings/BubbleSettings/BubbleSettings'
import { parseInlineScript, parseInitBubbleCode } from '../../../snippetParsers'
export const parseDefaultBubbleTheme = (typebot?: Typebot) => ({
button: {
backgroundColor: typebot?.theme.chat.buttons.backgroundColor,
iconColor: typebot?.theme.chat.buttons.color,
},
previewMessage: {
backgroundColor: typebot?.theme.general.background.content ?? 'white',
textColor: 'black',
},
})
export const ScriptBubbleInstructions = () => {
const { typebot } = useTypebot()
const [theme, setTheme] = useState<BubbleProps['theme']>(
parseDefaultBubbleTheme(typebot)
)
const [previewMessage, setPreviewMessage] =
useState<BubbleProps['previewMessage']>()
const scriptSnippet = parseInlineScript(
parseInitBubbleCode({
typebot: typebot?.publicId ?? '',
apiHost: isCloudProdInstance
? undefined
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
theme,
previewMessage,
})
)
return (
<Stack spacing={4}>
<BubbleSettings
theme={theme}
previewMessage={previewMessage}
defaultPreviewMessageAvatar={typebot?.theme.chat.hostAvatar?.url ?? ''}
onThemeChange={setTheme}
onPreviewMessageChange={setPreviewMessage}
/>
<Text>Run this script to initialize the typebot:</Text>
<CodeEditor isReadOnly value={scriptSnippet} lang="javascript" />
</Stack>
)
}

View File

@ -0,0 +1,21 @@
import { ScriptBubbleInstructions } from './ScriptBubbleInstructions'
import { ScriptPopupInstructions } from './ScriptPopupInstructions'
import { ScriptStandardInstructions } from './ScriptStandardInstructions'
type Props = {
type: 'standard' | 'popup' | 'bubble'
}
export const ScriptInstructions = ({ type }: Props) => {
switch (type) {
case 'standard': {
return <ScriptStandardInstructions />
}
case 'popup': {
return <ScriptPopupInstructions />
}
case 'bubble': {
return <ScriptBubbleInstructions />
}
}
}

View File

@ -0,0 +1,34 @@
import { CodeEditor } from '@/components/CodeEditor'
import { useTypebot } from '@/features/editor'
import { isCloudProdInstance } from '@/utils/helpers'
import { Stack, Text } from '@chakra-ui/react'
import { useState } from 'react'
import { env, getViewerUrl } from 'utils'
import { PopupSettings } from '../../../settings/PopupSettings'
import { parseInitPopupCode } from '../../../snippetParsers'
import { parseInlineScript } from '../../../snippetParsers/shared'
export const ScriptPopupInstructions = () => {
const { typebot } = useTypebot()
const [inputValue, setInputValue] = useState<number>()
const scriptSnippet = parseInlineScript(
parseInitPopupCode({
typebot: typebot?.publicId ?? '',
apiHost: isCloudProdInstance
? undefined
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
autoShowDelay: inputValue,
})
)
return (
<Stack spacing={4}>
<PopupSettings
onUpdateSettings={(settings) => setInputValue(settings.autoShowDelay)}
/>
<Text>Run this script to initialize the typebot:</Text>
<CodeEditor isReadOnly value={scriptSnippet} lang="javascript" />
</Stack>
)
}

View File

@ -0,0 +1,50 @@
import { CodeEditor } from '@/components/CodeEditor'
import { useTypebot } from '@/features/editor'
import { isCloudProdInstance } from '@/utils/helpers'
import { Stack, Code, Text } from '@chakra-ui/react'
import { useState } from 'react'
import { env, getViewerUrl } from 'utils'
import { StandardSettings } from '../../../settings/StandardSettings'
import { parseInitStandardCode } from '../../../snippetParsers/standard'
import { parseStandardElementCode } from '../../Javascript/JavascriptStandardSnippet'
import { parseInlineScript } from '../../../snippetParsers/shared'
export const ScriptStandardInstructions = () => {
const { typebot } = useTypebot()
const [inputValues, setInputValues] = useState<{
heightLabel: string
widthLabel?: string
}>({
heightLabel: '100%',
widthLabel: '100%',
})
const standardElementSnippet = parseStandardElementCode(
inputValues.widthLabel,
inputValues.heightLabel
)
const scriptSnippet = parseInlineScript(
parseInitStandardCode({
typebot: typebot?.publicId ?? '',
apiHost: isCloudProdInstance
? undefined
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
})
)
return (
<Stack spacing={4}>
<StandardSettings
onUpdateWindowSettings={(settings) => setInputValues({ ...settings })}
/>
<Text>
Make sure you have this <Code>typebot-standard</Code> element in your{' '}
<Code>{'<body>'}</Code>:
</Text>
<CodeEditor isReadOnly value={standardElementSnippet} lang="html" />
<Text>Then, run this script to initialize the typebot:</Text>
<CodeEditor isReadOnly value={scriptSnippet} lang="javascript" />
</Stack>
)
}

View File

@ -1,4 +1,6 @@
import { BotProps } from '@typebot.io/js'
import parserBabel from 'prettier/parser-babel'
import prettier from 'prettier/standalone'
import { isDefined } from 'utils'
export const parseStringParam = (fieldName: string, fieldValue?: string) =>
@ -30,3 +32,12 @@ export const parseReactBotProps = ({ typebot, apiHost }: BotProps) => {
}
export const typebotImportUrl = `https://cdn.jsdelivr.net/npm/@typebot.io/js@0.0.14/dist/web.js`
export const parseInlineScript = (script: string) =>
prettier.format(
`const typebotInitScript = document.createElement("script");
typebotInitScript.type = "module";
typebotInitScript.innerHTML = \`${script}\`;
document.body.append(typebotInitScript);`,
{ parser: 'babel', plugins: [parserBabel] }
)

View File

@ -0,0 +1,5 @@
# Script
The script embed option is useful only if you don't have access to the HTML tree of your application or if your website builder only allows you to inline script snippets.
Otherwise, it's preferable to follow [HTML & Javascript](./html-javascript) embed instructions because the script snippets are just scripts that will inject the code from the HTML & Javascript embed method.