mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-31 06:37:14 +00:00
feat(wizard): label page bot test preview
This commit is contained in:
@@ -7,6 +7,9 @@
|
|||||||
// Read config from script tag data attributes
|
// Read config from script tag data attributes
|
||||||
var scriptEl = document.currentScript;
|
var scriptEl = document.currentScript;
|
||||||
var scriptTitle = scriptEl ? scriptEl.getAttribute("data-title") : null;
|
var scriptTitle = scriptEl ? scriptEl.getAttribute("data-title") : null;
|
||||||
|
var scriptTestNotice = scriptEl
|
||||||
|
? scriptEl.getAttribute("data-test-notice")
|
||||||
|
: null;
|
||||||
|
|
||||||
// ========== i18n ==========
|
// ========== i18n ==========
|
||||||
var I18N = {
|
var I18N = {
|
||||||
@@ -192,6 +195,7 @@
|
|||||||
.lb-header-btn { background: none; border: none; color: #fff; cursor: pointer; padding: 4px; border-radius: 6px; display: flex; align-items: center; justify-content: center; opacity: 0.8; transition: opacity 0.15s; }\
|
.lb-header-btn { background: none; border: none; color: #fff; cursor: pointer; padding: 4px; border-radius: 6px; display: flex; align-items: center; justify-content: center; opacity: 0.8; transition: opacity 0.15s; }\
|
||||||
.lb-header-btn:hover { opacity: 1; }\
|
.lb-header-btn:hover { opacity: 1; }\
|
||||||
.lb-header-btn svg { width: 18px; height: 18px; fill: currentColor; }\
|
.lb-header-btn svg { width: 18px; height: 18px; fill: currentColor; }\
|
||||||
|
.lb-test-notice { padding: 8px 16px; border-bottom: 1px solid #fde68a; background: #fffbeb; color: #92400e; font-size: 12px; line-height: 1.5; text-align: center; flex-shrink: 0; }\
|
||||||
.lb-messages { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 16px; scroll-behavior: smooth; }\
|
.lb-messages { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 16px; scroll-behavior: smooth; }\
|
||||||
.lb-messages::-webkit-scrollbar { width: 6px; }\
|
.lb-messages::-webkit-scrollbar { width: 6px; }\
|
||||||
.lb-messages::-webkit-scrollbar-track { background: transparent; }\
|
.lb-messages::-webkit-scrollbar-track { background: transparent; }\
|
||||||
@@ -1336,6 +1340,14 @@
|
|||||||
header.appendChild(headerActions);
|
header.appendChild(headerActions);
|
||||||
panel.appendChild(header);
|
panel.appendChild(header);
|
||||||
|
|
||||||
|
if (scriptTestNotice) {
|
||||||
|
var testNotice = document.createElement("div");
|
||||||
|
testNotice.className = "lb-test-notice";
|
||||||
|
testNotice.setAttribute("role", "note");
|
||||||
|
testNotice.textContent = scriptTestNotice;
|
||||||
|
panel.appendChild(testNotice);
|
||||||
|
}
|
||||||
|
|
||||||
// Messages area
|
// Messages area
|
||||||
var messages = document.createElement("div");
|
var messages = document.createElement("div");
|
||||||
messages.className = "lb-messages";
|
messages.className = "lb-messages";
|
||||||
|
|||||||
@@ -1128,14 +1128,17 @@ function StepPlatform({
|
|||||||
function PageBotFloatingWidget({
|
function PageBotFloatingWidget({
|
||||||
botUuid,
|
botUuid,
|
||||||
title,
|
title,
|
||||||
|
testNotice,
|
||||||
}: {
|
}: {
|
||||||
botUuid: string;
|
botUuid: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
testNotice: string;
|
||||||
}) {
|
}) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
script.src = `${window.location.origin}/api/v1/embed/${botUuid}/widget.js`;
|
script.src = `${window.location.origin}/api/v1/embed/${botUuid}/widget.js?preview=wizard&v=${Date.now()}`;
|
||||||
script.dataset.title = title || 'LangBot';
|
script.dataset.title = title || 'LangBot';
|
||||||
|
script.dataset.testNotice = testNotice;
|
||||||
document.body.appendChild(script);
|
document.body.appendChild(script);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -1149,7 +1152,7 @@ function PageBotFloatingWidget({
|
|||||||
root?.remove();
|
root?.remove();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [botUuid, title]);
|
}, [botUuid, testNotice, title]);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1242,6 +1245,7 @@ function StepBotConfig({
|
|||||||
? adapterConfigValues.title
|
? adapterConfigValues.title
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
|
testNotice={t('wizard.botConfig.pageBotTestNotice')}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1833,6 +1833,8 @@ const enUS = {
|
|||||||
'The bot received an IM message. You can continue to the next step.',
|
'The bot received an IM message. You can continue to the next step.',
|
||||||
pageBotTestPrompt:
|
pageBotTestPrompt:
|
||||||
'Page Bot is enabled. Click the chat bubble in the lower-right corner and send a message to verify the full conversation flow.',
|
'Page Bot is enabled. Click the chat bubble in the lower-right corner and send a message to verify the full conversation flow.',
|
||||||
|
pageBotTestNotice:
|
||||||
|
'For testing only. Embed the code on a real external webpage.',
|
||||||
webhookTestPrompt:
|
webhookTestPrompt:
|
||||||
'The callback URL is ready. Configure it on the external platform, then send the bot a real message.',
|
'The callback URL is ready. Configure it on the external platform, then send the bot a real message.',
|
||||||
httpTestPrompt:
|
httpTestPrompt:
|
||||||
|
|||||||
@@ -1750,6 +1750,8 @@ const jaJP = {
|
|||||||
'ボットが IM メッセージを受信しました。次のステップに進めます。',
|
'ボットが IM メッセージを受信しました。次のステップに進めます。',
|
||||||
pageBotTestPrompt:
|
pageBotTestPrompt:
|
||||||
'ページボットが有効になりました。右下のチャットバブルをクリックしてメッセージを送信し、会話フロー全体を確認してください。',
|
'ページボットが有効になりました。右下のチャットバブルをクリックしてメッセージを送信し、会話フロー全体を確認してください。',
|
||||||
|
pageBotTestNotice:
|
||||||
|
'テスト専用です。実際の外部 Web ページにコードを埋め込んでください。',
|
||||||
webhookTestPrompt:
|
webhookTestPrompt:
|
||||||
'コールバック URL の準備ができました。外部プラットフォームに設定し、ボットへ実際のメッセージを送信してください。',
|
'コールバック URL の準備ができました。外部プラットフォームに設定し、ボットへ実際のメッセージを送信してください。',
|
||||||
httpTestPrompt:
|
httpTestPrompt:
|
||||||
|
|||||||
@@ -1753,6 +1753,7 @@ const zhHans = {
|
|||||||
messageReceived: '机器人已成功收到 IM 消息,可以进入下一步。',
|
messageReceived: '机器人已成功收到 IM 消息,可以进入下一步。',
|
||||||
pageBotTestPrompt:
|
pageBotTestPrompt:
|
||||||
'页面机器人已启用。点击右下角聊天气泡并发送一条消息,验证完整对话链路。',
|
'页面机器人已启用。点击右下角聊天气泡并发送一条消息,验证完整对话链路。',
|
||||||
|
pageBotTestNotice: '仅供测试使用,请嵌入代码到真实外部网页。',
|
||||||
webhookTestPrompt:
|
webhookTestPrompt:
|
||||||
'回调地址已就绪。将它配置到外部平台,然后向机器人发送一条真实消息。',
|
'回调地址已就绪。将它配置到外部平台,然后向机器人发送一条真实消息。',
|
||||||
httpTestPrompt: 'HTTP Bot 已启用。可直接发送一条真实入站消息验证连接。',
|
httpTestPrompt: 'HTTP Bot 已启用。可直接发送一条真实入站消息验证连接。',
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import test from 'node:test';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
const currentDirectory = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const wizardSource = fs.readFileSync(
|
||||||
|
path.resolve(currentDirectory, '../../src/app/wizard/page.tsx'),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
const widgetSource = fs.readFileSync(
|
||||||
|
path.resolve(
|
||||||
|
currentDirectory,
|
||||||
|
'../../../src/langbot/templates/embed/widget.js',
|
||||||
|
),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
|
||||||
|
test('shows the test-only notice only when the wizard opts in', () => {
|
||||||
|
assert.match(
|
||||||
|
wizardSource,
|
||||||
|
/widget\.js\?preview=wizard&v=\$\{Date\.now\(\)\}/,
|
||||||
|
);
|
||||||
|
assert.match(wizardSource, /script\.dataset\.testNotice = testNotice/);
|
||||||
|
assert.match(
|
||||||
|
wizardSource,
|
||||||
|
/testNotice=\{t\('wizard\.botConfig\.pageBotTestNotice'\)\}/,
|
||||||
|
);
|
||||||
|
assert.match(widgetSource, /getAttribute\("data-test-notice"\)/);
|
||||||
|
assert.match(widgetSource, /if \(scriptTestNotice\)/);
|
||||||
|
assert.match(widgetSource, /testNotice\.textContent = scriptTestNotice/);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user