2
0

🐛 (wordpress) Fix admin critical bug and better lib import

This commit is contained in:
Baptiste Arnaud
2023-02-25 17:13:26 +01:00
parent 2b2b1c3d6d
commit c889f302f6
18 changed files with 177 additions and 127 deletions

View File

@ -1,4 +1,11 @@
import { Button, useDisclosure, VStack, WrapItem, Text } from '@chakra-ui/react' import {
Button,
useDisclosure,
VStack,
WrapItem,
Text,
useColorModeValue,
} from '@chakra-ui/react'
import { import {
WordpressLogo, WordpressLogo,
ShopifyLogo, ShopifyLogo,
@ -116,7 +123,13 @@ export const integrationsList = [
), ),
(props: Pick<ModalProps, 'publicId' | 'isPublished'>) => ( (props: Pick<ModalProps, 'publicId' | 'isPublished'>) => (
<EmbedButton <EmbedButton
logo={<ScriptIcon height={100} width="70px" color="gray.300" />} logo={
<ScriptIcon
height={100}
width="70px"
color={useColorModeValue('gray.800', 'gray.300')}
/>
}
label="Script" label="Script"
Modal={ScriptModal} Modal={ScriptModal}
{...props} {...props}

View File

@ -1,6 +1,6 @@
import prettier from 'prettier/standalone' import prettier from 'prettier/standalone'
import parserHtml from 'prettier/parser-html' import parserHtml from 'prettier/parser-html'
import { parseInitBubbleCode } from '../../snippetParsers' import { parseInitBubbleCode, typebotImportCode } from '../../snippetParsers'
import { useTypebot } from '@/features/editor' import { useTypebot } from '@/features/editor'
import { CodeEditor } from '@/components/CodeEditor' import { CodeEditor } from '@/components/CodeEditor'
import { BubbleProps } from '@typebot.io/js' import { BubbleProps } from '@typebot.io/js'
@ -13,19 +13,21 @@ export const JavascriptBubbleSnippet = ({ theme, previewMessage }: Props) => {
const { typebot } = useTypebot() const { typebot } = useTypebot()
const snippet = prettier.format( const snippet = prettier.format(
`<script type="module">${parseInitBubbleCode({ `<script type="module">${typebotImportCode}
typebot: typebot?.publicId ?? '',
apiHost: isCloudProdInstance ${parseInitBubbleCode({
? undefined typebot: typebot?.publicId ?? '',
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(), apiHost: isCloudProdInstance
theme: { ? undefined
...theme, : env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
chatWindow: { theme: {
backgroundColor: typebot?.theme.general.background.content ?? '#fff', ...theme,
}, chatWindow: {
}, backgroundColor: typebot?.theme.general.background.content ?? '#fff',
previewMessage, },
})}</script>`, },
previewMessage,
})}</script>`,
{ {
parser: 'html', parser: 'html',
plugins: [parserHtml], plugins: [parserHtml],

View File

@ -1,7 +1,7 @@
import { useTypebot } from '@/features/editor' import { useTypebot } from '@/features/editor'
import parserHtml from 'prettier/parser-html' import parserHtml from 'prettier/parser-html'
import prettier from 'prettier/standalone' import prettier from 'prettier/standalone'
import { parseInitPopupCode } from '../../snippetParsers' import { parseInitPopupCode, typebotImportCode } from '../../snippetParsers'
import { CodeEditor } from '@/components/CodeEditor' import { CodeEditor } from '@/components/CodeEditor'
import { PopupProps } from '@typebot.io/js' import { PopupProps } from '@typebot.io/js'
import { isCloudProdInstance } from '@/utils/helpers' import { isCloudProdInstance } from '@/utils/helpers'
@ -29,5 +29,7 @@ export const JavascriptPopupSnippet = ({ autoShowDelay }: Props) => {
const createSnippet = (params: PopupProps): string => { const createSnippet = (params: PopupProps): string => {
const jsCode = parseInitPopupCode(params) const jsCode = parseInitPopupCode(params)
return `<script type="module">${jsCode}</script>` return `<script type="module">${typebotImportCode}
${jsCode}</script>`
} }

View File

@ -1,6 +1,6 @@
import parserHtml from 'prettier/parser-html' import parserHtml from 'prettier/parser-html'
import prettier from 'prettier/standalone' import prettier from 'prettier/standalone'
import { parseInitStandardCode } from '../../snippetParsers' import { parseInitStandardCode, typebotImportCode } from '../../snippetParsers'
import { useTypebot } from '@/features/editor' import { useTypebot } from '@/features/editor'
import { CodeEditor } from '@/components/CodeEditor' import { CodeEditor } from '@/components/CodeEditor'
import { isCloudProdInstance } from '@/utils/helpers' import { isCloudProdInstance } from '@/utils/helpers'
@ -31,12 +31,14 @@ export const JavascriptStandardSnippet = ({
export const parseStandardHeadCode = (publicId?: string | null) => export const parseStandardHeadCode = (publicId?: string | null) =>
prettier.format( prettier.format(
`<script type="module">${parseInitStandardCode({ `<script type="module">${typebotImportCode};
typebot: publicId ?? '',
apiHost: isCloudProdInstance ${parseInitStandardCode({
? undefined typebot: publicId ?? '',
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(), apiHost: isCloudProdInstance
})}</script>`, ? undefined
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
})}</script>`,
{ parser: 'html', plugins: [parserHtml] } { parser: 'html', plugins: [parserHtml] }
) )

View File

@ -7,7 +7,11 @@ import { Typebot } from 'models'
import { useState } from 'react' import { useState } from 'react'
import { env, getViewerUrl } from 'utils' import { env, getViewerUrl } from 'utils'
import { BubbleSettings } from '../../../settings/BubbleSettings/BubbleSettings' import { BubbleSettings } from '../../../settings/BubbleSettings/BubbleSettings'
import { parseInlineScript, parseInitBubbleCode } from '../../../snippetParsers' import {
parseInlineScript,
parseInitBubbleCode,
typebotImportCode,
} from '../../../snippetParsers'
export const parseDefaultBubbleTheme = (typebot?: Typebot) => ({ export const parseDefaultBubbleTheme = (typebot?: Typebot) => ({
button: { button: {
@ -29,14 +33,16 @@ export const ScriptBubbleInstructions = () => {
useState<BubbleProps['previewMessage']>() useState<BubbleProps['previewMessage']>()
const scriptSnippet = parseInlineScript( const scriptSnippet = parseInlineScript(
parseInitBubbleCode({ `${typebotImportCode}
typebot: typebot?.publicId ?? '',
apiHost: isCloudProdInstance ${parseInitBubbleCode({
? undefined typebot: typebot?.publicId ?? '',
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(), apiHost: isCloudProdInstance
theme, ? undefined
previewMessage, : env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
}) theme,
previewMessage,
})}`
) )
return ( return (

View File

@ -6,20 +6,25 @@ import { useState } from 'react'
import { env, getViewerUrl } from 'utils' import { env, getViewerUrl } from 'utils'
import { PopupSettings } from '../../../settings/PopupSettings' import { PopupSettings } from '../../../settings/PopupSettings'
import { parseInitPopupCode } from '../../../snippetParsers' import { parseInitPopupCode } from '../../../snippetParsers'
import { parseInlineScript } from '../../../snippetParsers/shared' import {
parseInlineScript,
typebotImportCode,
} from '../../../snippetParsers/shared'
export const ScriptPopupInstructions = () => { export const ScriptPopupInstructions = () => {
const { typebot } = useTypebot() const { typebot } = useTypebot()
const [inputValue, setInputValue] = useState<number>() const [inputValue, setInputValue] = useState<number>()
const scriptSnippet = parseInlineScript( const scriptSnippet = parseInlineScript(
parseInitPopupCode({ `${typebotImportCode}
typebot: typebot?.publicId ?? '',
apiHost: isCloudProdInstance ${parseInitPopupCode({
? undefined typebot: typebot?.publicId ?? '',
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(), apiHost: isCloudProdInstance
autoShowDelay: inputValue, ? undefined
}) : env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
autoShowDelay: inputValue,
})}`
) )
return ( return (

View File

@ -7,7 +7,10 @@ import { env, getViewerUrl } from 'utils'
import { StandardSettings } from '../../../settings/StandardSettings' import { StandardSettings } from '../../../settings/StandardSettings'
import { parseInitStandardCode } from '../../../snippetParsers/standard' import { parseInitStandardCode } from '../../../snippetParsers/standard'
import { parseStandardElementCode } from '../../Javascript/JavascriptStandardSnippet' import { parseStandardElementCode } from '../../Javascript/JavascriptStandardSnippet'
import { parseInlineScript } from '../../../snippetParsers/shared' import {
parseInlineScript,
typebotImportCode,
} from '../../../snippetParsers/shared'
export const ScriptStandardInstructions = () => { export const ScriptStandardInstructions = () => {
const { typebot } = useTypebot() const { typebot } = useTypebot()
@ -24,14 +27,14 @@ export const ScriptStandardInstructions = () => {
inputValues.heightLabel inputValues.heightLabel
) )
const scriptSnippet = parseInlineScript( const scriptSnippet = parseInlineScript(`${typebotImportCode}
parseInitStandardCode({
typebot: typebot?.publicId ?? '', ${parseInitStandardCode({
apiHost: isCloudProdInstance typebot: typebot?.publicId ?? '',
? undefined apiHost: isCloudProdInstance
: env('VIEWER_INTERNAL_URL') ?? getViewerUrl(), ? undefined
}) : env('VIEWER_INTERNAL_URL') ?? getViewerUrl(),
) })}`)
return ( return (
<Stack spacing={4}> <Stack spacing={4}>

View File

@ -6,7 +6,6 @@ import {
parseBotProps, parseBotProps,
parseNumberOrBoolParam, parseNumberOrBoolParam,
parseReactBotProps, parseReactBotProps,
typebotImportUrl,
} from './shared' } from './shared'
const parseButtonTheme = ( const parseButtonTheme = (
@ -111,15 +110,10 @@ export const parseInitBubbleCode = ({
const botProps = parseBotProps({ typebot, apiHost }) const botProps = parseBotProps({ typebot, apiHost })
const bubbleProps = parseBubbleProps({ previewMessage, theme }) const bubbleProps = parseBubbleProps({ previewMessage, theme })
return prettier.format( return prettier.format(`Typebot.initBubble({${botProps}${bubbleProps}});`, {
`import Typebot from '${typebotImportUrl}' parser: 'babel',
plugins: [parserBabel],
Typebot.initBubble({${botProps}${bubbleProps}});`, })
{
parser: 'babel',
plugins: [parserBabel],
}
)
} }
const parseReactBubbleTheme = (theme: BubbleProps['theme']): string => { const parseReactBubbleTheme = (theme: BubbleProps['theme']): string => {

View File

@ -8,7 +8,6 @@ import {
parseReactNumberOrBoolParam, parseReactNumberOrBoolParam,
parseReactStringParam, parseReactStringParam,
parseStringParam, parseStringParam,
typebotImportUrl,
} from './shared' } from './shared'
const parsePopupTheme = (theme: PopupProps['theme']): string => { const parsePopupTheme = (theme: PopupProps['theme']): string => {
@ -41,15 +40,10 @@ export const parseInitPopupCode = ({
const botProps = parseBotProps({ typebot, apiHost }) const botProps = parseBotProps({ typebot, apiHost })
const bubbleProps = parsePopupProps({ theme, autoShowDelay }) const bubbleProps = parsePopupProps({ theme, autoShowDelay })
return prettier.format( return prettier.format(`Typebot.initPopup({${botProps}${bubbleProps}});`, {
`import Typebot from '${typebotImportUrl}' parser: 'babel',
plugins: [parserBabel],
Typebot.initPopup({${botProps}${bubbleProps}});`, })
{
parser: 'babel',
plugins: [parserBabel],
}
)
} }
const parseReactThemeProp = (theme: PopupProps['theme']): string => { const parseReactThemeProp = (theme: PopupProps['theme']): string => {

View File

@ -31,7 +31,7 @@ export const parseReactBotProps = ({ typebot, apiHost }: BotProps) => {
return `${typebotLine} ${apiHostLine}` return `${typebotLine} ${apiHostLine}`
} }
export const typebotImportUrl = `https://cdn.jsdelivr.net/npm/@typebot.io/js@0.0.14/dist/web.js` export const typebotImportCode = `import Typebot from 'https://cdn.jsdelivr.net/npm/@typebot.io/js@0.0/dist/web.js'`
export const parseInlineScript = (script: string) => export const parseInlineScript = (script: string) =>
prettier.format( prettier.format(

View File

@ -1,7 +1,7 @@
import { BotProps } from '@typebot.io/js' import { BotProps } from '@typebot.io/js'
import parserBabel from 'prettier/parser-babel' import parserBabel from 'prettier/parser-babel'
import prettier from 'prettier/standalone' import prettier from 'prettier/standalone'
import { parseBotProps, typebotImportUrl } from './shared' import { parseBotProps } from './shared'
export const parseInitStandardCode = ({ export const parseInitStandardCode = ({
typebot, typebot,
@ -9,13 +9,8 @@ export const parseInitStandardCode = ({
}: Pick<BotProps, 'typebot' | 'apiHost'>) => { }: Pick<BotProps, 'typebot' | 'apiHost'>) => {
const botProps = parseBotProps({ typebot, apiHost }) const botProps = parseBotProps({ typebot, apiHost })
return prettier.format( return prettier.format(`Typebot.initStandard({${botProps}});`, {
`import Typebot from '${typebotImportUrl}' parser: 'babel',
plugins: [parserBabel],
Typebot.initStandard({${botProps}});`, })
{
parser: 'babel',
plugins: [parserBabel],
}
)
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "wordpress", "name": "wordpress",
"version": "2.1.11", "version": "3.1.0",
"main": "index.js", "main": "index.js",
"repository": "https://github.com/baptisteArno/typebot.io", "repository": "https://github.com/baptisteArno/typebot.io",
"author": "baptisteArno", "author": "baptisteArno",
@ -11,7 +11,7 @@
}, },
"scripts": { "scripts": {
"deploy": "pnpm copy && pnpm commit", "deploy": "pnpm copy && pnpm commit",
"copy": "svn copy ./trunk ./tags/3.0.1", "copy": "svn copy ./trunk ./tags/3.1.0",
"commit": "svn ci -m 'Fix standard flow not proceeding'" "commit": "svn ci -m 'Fix admin critical bug and introduce excluded pages'"
} }
} }

View File

@ -5,7 +5,7 @@ Requires at least: 5.0
Tested up to: 6.0 Tested up to: 6.0
License: GPL 2.0 License: GPL 2.0
License URI: http://www.gnu.org/licenses/gpl-2.0.txt License URI: http://www.gnu.org/licenses/gpl-2.0.txt
Stable Tag: 3.0.1 Stable Tag: 3.1.0
Build beautiful conversational forms Build beautiful conversational forms
@ -26,6 +26,11 @@ This plugin relies on Typebot which is a tool that allows you to create conversa
3. Activate your Typebot with the "Typebot" admin button located in the sidebar 3. Activate your Typebot with the "Typebot" admin button located in the sidebar
== Changelog == == Changelog ==
= 3.1.0 =
* Breaking change! You will need to import the new code snippet again.
* Fix wp admin crash
* Introduce excluded pages input
= 3.0.1 = = 3.0.1 =
* Fix flow not proceeding on unknown domains * Fix flow not proceeding on unknown domains

View File

@ -26,5 +26,6 @@ class Typebot_Admin
public function register_typebot_settings() public function register_typebot_settings()
{ {
register_setting('typebot', 'init_snippet'); register_setting('typebot', 'init_snippet');
register_setting('typebot', 'excluded_pages');
} }
} }

View File

@ -11,7 +11,13 @@
?> ?>
<div style="display: flex; flex-direction: column"> <div style="display: flex; flex-direction: column">
<label>If embedding as <strong>Popup</strong> or <strong>Bubble</strong>, paste the initialization snippet here:</label> <label>If embedding as <strong>Popup</strong> or <strong>Bubble</strong>, paste the initialization snippet here:</label>
<textarea name="init_snippet" placeholder='Typebot.initPopup({ typebot: "https://typebot.io/my-typebot" });' style="min-height: 150px; padding: 0.5rem; margin-top: 1rem"><?php echo esc_attr(get_option('init_snippet')); ?></textarea> <textarea name="init_snippet" style="min-height: 150px; padding: 0.5rem; margin-top: 1rem"><?php echo esc_attr(get_option('init_snippet')); ?></textarea>
</div>
<div style="display: flex; flex-direction: column; margin-top: 1rem">
<label>Excluded pages (optionnal):</label>
<p style="color: gray">Example: /app/*, /user/*, /admin/settings</p>
<input name="excluded_pages" value="<?php echo esc_attr(get_option('excluded_pages')); ?>" style="padding: .5rem" />
</div> </div>
<div style="margin-top: 1rem"> <div style="margin-top: 1rem">

View File

@ -42,7 +42,6 @@ class Typebot
private function define_admin_hooks() private function define_admin_hooks()
{ {
$plugin_admin = new Typebot_Admin($this->get_version()); $plugin_admin = new Typebot_Admin($this->get_version());
$this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
$this->loader->add_action('admin_menu', $plugin_admin, 'my_admin_menu'); $this->loader->add_action('admin_menu', $plugin_admin, 'my_admin_menu');
$this->loader->add_action('admin_init', $plugin_admin, 'register_typebot_settings'); $this->loader->add_action('admin_init', $plugin_admin, 'register_typebot_settings');
} }

View File

@ -4,55 +4,78 @@ class Typebot_Public
{ {
public function add_head_code() public function add_head_code()
{ {
function add_module_type($tag, $handle) function parse_wp_user()
{ {
if ('typebot' !== $handle) { $wp_user = wp_get_current_user();
return $tag; echo '<script>
} if(typeof window.typebotWpUser === "undefined"){
$tag = str_replace(
'<script',
'<script type ="module"',
$tag
);
return $tag;
}
wp_enqueue_script('typebot', 'whatever.js');
add_filter('script_loader_tag', 'add_module_type', 10, 2);
wp_add_inline_script('typebot', $this->parse_wp_user());
if (get_option('init_snippet') && get_option('init_snippet') !== '') {
wp_add_inline_script('typebot', get_option('init_snippet'));
wp_add_inline_script('typebot', 'Typebot.setPrefilledVariables({ typebotWpUser });');
}
}
private function parse_wp_user()
{
$wp_user = wp_get_current_user();
return 'if(typeof window.typebotWpUser === "undefined"){
window.typebotWpUser = { window.typebotWpUser = {
wp_id:"' . wp_id:"' .
$wp_user->ID . $wp_user->ID .
'", '",
wp_username:"' . wp_username:"' .
$wp_user->user_login . $wp_user->user_login .
'", '",
wp_email:"' . wp_email:"' .
$wp_user->user_email . $wp_user->user_email .
'", '",
wp_first_name:"' . wp_first_name:"' .
$wp_user->user_firstname . $wp_user->user_firstname .
'", '",
wp_last_name:"' . wp_last_name:"' .
$wp_user->user_lastname . $wp_user->user_lastname .
'", '",
} }
}'; }
</script>';
}
function typebot_script()
{
echo '<script type="module">
import Typebot from "https://cdn.jsdelivr.net/npm/@typebot.io/js@0.0/dist/web.js";';
if (
get_option('excluded_pages') !== null &&
get_option('excluded_pages') !== ''
) {
$paths = explode(',', get_option('excluded_pages'));
$arr_js = 'const typebotExcludePaths = [';
foreach ($paths as $path) {
$arr_js = $arr_js . '"' . $path . '",';
}
$arr_js = substr($arr_js, 0, -1) . '];';
echo $arr_js;
}
if (get_option('init_snippet') && get_option('init_snippet') !== '') {
echo 'if(!typebotExcludePaths || typebotExcludePaths.every((path) => {
let excludePath = path.trim();
let windowPath = window.location.pathname;
if (excludePath.endsWith("*")) {
return !windowPath.startsWith(excludePath.slice(0, -1));
}
if (excludePath.endsWith("/")) {
excludePath = path.slice(0, -1);
}
if (windowPath.endsWith("/")) {
windowPath = windowPath.slice(0, -1);
}
return windowPath !== excludePath;
})) {
' . get_option('init_snippet') . '
Typebot.setPrefilledVariables({ typebotWpUser });
}';
}
echo '</script>';
}
add_action('wp_head', 'parse_wp_user');
add_action('wp_footer', 'typebot_script');
} }
public function add_typebot_container($attributes = []) public function add_typebot_container($attributes = [])
{ {
$lib_url = "https://cdn.jsdelivr.net/npm/@typebot.io/js@0.0.14/dist/web.js"; $lib_url = "https://cdn.jsdelivr.net/npm/@typebot.io/js@0.0/dist/web.js";
$width = '100%'; $width = '100%';
$height = '500px'; $height = '500px';
if (array_key_exists('width', $attributes)) { if (array_key_exists('width', $attributes)) {

View File

@ -3,7 +3,7 @@
/** /**
* Plugin Name: Typebot * Plugin Name: Typebot
* Description: Convert more with conversational forms * Description: Convert more with conversational forms
* Version: 3.0.1 * Version: 3.1.0
* Author: Typebot * Author: Typebot
* Author URI: http://typebot.io/ * Author URI: http://typebot.io/
* License: GPL-2.0+ * License: GPL-2.0+
@ -16,7 +16,7 @@ if (!defined('WPINC')) {
die(); die();
} }
define('TYPEBOT_VERSION', '3.0.1'); define('TYPEBOT_VERSION', '3.1.0');
function activate_typebot() function activate_typebot()
{ {