application embedded add chrome && ChatBot Chrome plugin update v1.5 (#1480)

Co-authored-by: luowei <glpat-EjySCyNjWiLqAED-YmwM>
Co-authored-by: crazywoola <427733928@qq.com>
This commit is contained in:
Charlie.Wei 2023-11-08 17:59:53 +08:00 committed by GitHub
parent ab2e20ee0a
commit 306216dbe5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 176268 additions and 58 deletions

View File

@ -20,16 +20,14 @@
- options.js 插件配置JS脚本
### 插件导入完成后,后续配置无差异
- 初始化设置Dify 应用配置分别输入Dify根域名和应用TokenToken可以在Dify应用嵌入中获取,如图:
- 创建Dify应用配置在应用概览中点击嵌入切换到安装Chrome浏览器扩展视图点击copy按钮获取ChatBot Url,如图:
![img-2.png](images/img-2.png)
![img-3.png](images/img-3.png)
- 点击保存,确认提示配置成功即可
![img-4.png](images/img-4.png)
![img-3.png](images/img-3.png)
- 保险起见重启浏览器确保所有分页刷新成功
- Chrome打开任意页面均可正常加载DIfy机器人浮动栏后续如需更换机器人只需要变更Token即可
- Chrome打开任意页面均可正常加载DIfy机器人浮动栏后续如需更换机器人只需要变更ChatBot Url即可
![img-5.png](images/img-5.png)
![img-4.png](images/img-4.png)

View File

@ -0,0 +1,6 @@
## Chrome Dify ChatBot插件
1、初始化设置Dify 应用配置分别输入Dify根域名和应用TokenToken可以在Dify应用嵌入中获取
2、点击保存确认提示配置成功即可
3、保险起见重启浏览器确保所有分页刷新成功
4、Chrome打开任意页面均可正常加载DIfy机器人浮动栏后续如需更换机器人只需要变更Token即可

View File

@ -1,8 +1,7 @@
var storage = chrome.storage.sync;
chrome.storage.sync.get(['baseUrl', 'token'], function(result) {
const storage = chrome.storage.sync;
chrome.storage.sync.get(['chatbotUrl'], function(result) {
window.difyChatbotConfig = {
baseUrl: result.baseUrl,
token: result.token
chatbotUrl: result.chatbotUrl,
};
});
@ -10,11 +9,10 @@ document.body.onload = embedChatbot;
async function embedChatbot() {
const difyChatbotConfig = window.difyChatbotConfig;
if (!difyChatbotConfig || !difyChatbotConfig.token) {
console.warn('difyChatbotConfig is empty or token is not provided');
if (!difyChatbotConfig) {
console.warn('Dify Chatbot Url is empty or is not provided');
return;
}
const baseUrl = difyChatbotConfig.baseUrl
const openIcon = `<svg
id="openIcon"
width="24"
@ -53,7 +51,7 @@ async function embedChatbot() {
iframe.allow = "fullscreen;microphone"
iframe.title = "dify chatbot bubble window"
iframe.id = 'dify-chatbot-bubble-window'
iframe.src = `${baseUrl}/chat/${difyChatbotConfig.token}`
iframe.src = difyChatbotConfig.chatbotUrl
iframe.style.cssText = 'border: none; position: fixed; flex-direction: column; justify-content: space-between; box-shadow: rgba(150, 150, 150, 0.2) 0px 10px 30px 0px, rgba(150, 150, 150, 0.2) 0px 0px 0px 1px; bottom: 6.7rem; right: 1rem; width: 30rem; height: 48rem; border-radius: 0.75rem; display: flex; z-index: 2147483647; overflow: hidden; left: unset; background-color: #F3F4F6;'
document.body.appendChild(iframe);
}

BIN
third-party/chrome plug-in/favicon.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

View File

@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "Dify Chatbot",
"version": "1.3",
"version": "1.5",
"description": "This is a chrome extension to inject a dify chatbot on any pages",
"content_scripts": [
{
@ -17,7 +17,7 @@
"32": "images/32.png",
"48": "images/48.png",
"128": "images/128.png"
}
},
"icons": {

19
third-party/chrome plug-in/options.css vendored Normal file
View File

@ -0,0 +1,19 @@
body {
background-color: #f2f2f2;
font-family: Arial, sans-serif;
}
h2 {
color: #333;
}
label {
display: block;
margin-top: 10px;
margin-bottom: 10px;
}
input[type="text"] {
width: 280px;
padding: 6px;
}

View File

@ -4,32 +4,21 @@
<head>
<title>Dify Chatbot Extension</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link href="./tailwind.css" rel="stylesheet">
</head>
<body class="bg-gray-100 py-8 px-4 w-96">
<body class="bg-gray-100 py-4 px-4 w-128">
<div class="max-w-md mx-auto bg-white shadow-md rounded-lg p-4">
<h2 class="text-2xl font-semibold mb-4">Dify Chatbot Extension</h2>
<form>
<div class="mb-4 flex items-center">
<div class="w-1/4">
<label for="base-url" class="block font-semibold text-gray-700">Base URL</label>
<label for="chatbot-url" class="block font-semibold text-gray-700">ChatBot URL</label>
</div>
<div class="w-3/4">
<input type="text" id="base-url" name="base-url" value=""
<input type="text" id="chatbot-url" name="base-url" value=""
class="w-full border border-gray-300 rounded px-3 py-2 focus:outline-none focus:border-blue-400"
placeholder="https://udify.app">
</div>
</div>
<div class="mb-4 flex items-center">
<div class="w-1/4">
<label for="token" class="block font-semibold text-gray-700">Token</label>
</div>
<div class="w-3/4">
<input type="text" id="token" name="token" value=""
class="w-full border border-gray-300 rounded px-3 py-2 focus:outline-none focus:border-blue-400"
placeholder="Application Embedded Token">
placeholder="https://udify.app/chatbot/7CQBa5yyvYLSkZtx">
</div>
</div>

View File

@ -1,39 +1,28 @@
document.getElementById('save-button').addEventListener('click', function (e) {
e.preventDefault();
var baseUrl = document.getElementById('base-url').value;
var token = document.getElementById('token').value;
var errorTip = document.getElementById('error-tip');
const chatbotUrl = document.getElementById('chatbot-url').value;
const errorTip = document.getElementById('error-tip');
if (baseUrl.trim() === "" || token.trim() === "") {
if (baseUrl.trim() === "") {
errorTip.textContent = "Base URL cannot be empty.";
} else {
errorTip.textContent = "Token cannot be empty.";
}
if (chatbotUrl.trim() === "") {
errorTip.textContent = "Dify ChatBot URL cannot be empty.";
} else {
errorTip.textContent = "";
chrome.storage.sync.set({
'baseUrl': baseUrl,
'token': token
'chatbotUrl': chatbotUrl,
}, function () {
alert('Save Success!');
});
}
});
// Load parameters from chrome.storage when the page loads
chrome.storage.sync.get(['baseUrl', 'token'], function (result) {
const baseUrlInput = document.getElementById('base-url');
const tokenInput = document.getElementById('token');
chrome.storage.sync.get(['chatbotUrl'], function (result) {
const chatbotUrlInput = document.getElementById('chatbot-url');
if (result.baseUrl) {
baseUrlInput.value = result.baseUrl;
if (result.chatbotUrl) {
chatbotUrlInput.value = result.chatbotUrl;
}
if (result.token) {
tokenInput.value = result.token;
}
});

176015
third-party/chrome plug-in/tailwind.css vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.91722 6.7298L3.08403 3.65525C2.93723 3.40905 2.86384 3.28596 2.84729 3.14436C2.83386 3.02937 2.85797 2.8842 2.90785 2.77973C2.96928 2.65108 3.06488 2.5699 3.2561 2.40754C4.53491 1.32168 6.19097 0.666626 8.00002 0.666626C10.5383 0.666626 12.7753 1.95619 14.0918 3.91589C14.2371 4.13226 14.3098 4.24045 14.3034 4.35234C14.2981 4.44429 14.2454 4.54327 14.172 4.59892C14.0827 4.66663 13.9425 4.66663 13.6621 4.66663H8.00002C6.60882 4.66663 5.41668 5.51889 4.91722 6.7298Z" fill="white"/>
<path d="M0.666687 7.99996C0.666687 6.87421 0.92035 5.80771 1.37364 4.85449C1.48535 4.61957 1.5412 4.50211 1.64056 4.45053C1.72221 4.40813 1.83412 4.40288 1.91938 4.43744C2.02313 4.4795 2.0948 4.5997 2.23814 4.8401L5.06356 9.57876C5.62637 10.6234 6.73029 11.3333 8.00002 11.3333C8.13686 11.3333 8.27178 11.325 8.4043 11.309L6.62101 14.4166C6.4785 14.665 6.40724 14.7891 6.29186 14.873C6.19827 14.941 6.05961 14.9912 5.94418 14.9988C5.80188 15.0083 5.68457 14.9648 5.44995 14.8778C2.65701 13.8418 0.666687 11.1533 0.666687 7.99996Z" fill="white"/>
<path d="M7.81791 15.0098C7.73532 15.1537 7.83408 15.3333 8.00002 15.3333C12.0501 15.3333 15.3334 12.05 15.3334 7.99996C15.3334 7.58673 15.2992 7.18148 15.2335 6.78688C15.1924 6.53989 15.1718 6.41639 15.0928 6.29755C15.0287 6.20113 14.9162 6.10577 14.8105 6.05838C14.6803 5.99996 14.5371 5.99996 14.2505 5.99996H10.6669C11.0854 6.55707 11.3334 7.24956 11.3334 7.99996C11.3334 8.65299 11.1456 9.26216 10.821 9.77642L7.81791 15.0098Z" fill="white"/>
<path d="M10 7.99996C10 9.10453 9.10459 9.99996 8.00002 9.99996C6.89545 9.99996 6.00002 9.10453 6.00002 7.99996C6.00002 6.89539 6.89545 5.99996 8.00002 5.99996C9.10459 5.99996 10 6.89539 10 7.99996Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -9,8 +9,6 @@ import Tooltip from '@/app/components/base/tooltip'
import { useAppContext } from '@/context/app-context'
import { IS_CE_EDITION } from '@/config'
// const isDevelopment = process.env.NODE_ENV === 'development'
type Props = {
isShow: boolean
onClose: () => void
@ -47,6 +45,9 @@ const OPTION_MAP = {
defer>
</script>`,
},
chromePlugin: {
getContent: (url: string, token: string) => `ChatBot URL: ${url}/chatbot/${token}`,
},
}
const prefixEmbedded = 'appOverview.overview.appInfo.embedded'
@ -55,17 +56,25 @@ type Option = keyof typeof OPTION_MAP
type OptionStatus = {
iframe: boolean
scripts: boolean
chromePlugin: boolean
}
const Embedded = ({ isShow, onClose, appBaseUrl, accessToken }: Props) => {
const { t } = useTranslation()
const [option, setOption] = useState<Option>('iframe')
const [isCopied, setIsCopied] = useState<OptionStatus>({ iframe: false, scripts: false })
const [isCopied, setIsCopied] = useState<OptionStatus>({ iframe: false, scripts: false, chromePlugin: false })
const { langeniusVersionInfo } = useAppContext()
const isTestEnv = langeniusVersionInfo.current_env === 'TESTING' || langeniusVersionInfo.current_env === 'DEVELOPMENT'
const onClickCopy = () => {
copy(OPTION_MAP[option].getContent(appBaseUrl, accessToken, isTestEnv))
if (option === 'chromePlugin') {
const splitUrl = OPTION_MAP[option].getContent(appBaseUrl, accessToken).split(': ')
if (splitUrl.length > 1)
copy(splitUrl[1])
}
else {
copy(OPTION_MAP[option].getContent(appBaseUrl, accessToken, isTestEnv))
}
setIsCopied({ ...isCopied, [option]: true })
}
@ -78,6 +87,10 @@ const Embedded = ({ isShow, onClose, appBaseUrl, accessToken }: Props) => {
setIsCopied(cache)
}
const navigateToChromeUrl = () => {
window.open('https://chrome.google.com/webstore/detail/dify-chatbot/ceehdapohffmjmkdcifjofadiaoeggaf/related', '_blank')
}
useEffect(() => {
resetCopyStatus()
}, [isShow])
@ -93,7 +106,7 @@ const Embedded = ({ isShow, onClose, appBaseUrl, accessToken }: Props) => {
<div className="mb-4 mt-8 text-gray-900 text-[14px] font-medium leading-tight">
{t(`${prefixEmbedded}.explanation`)}
</div>
<div className="flex gap-4 items-center">
<div className="flex items-center justify-between">
{Object.keys(OPTION_MAP).map((v, index) => {
return (
<div
@ -111,7 +124,17 @@ const Embedded = ({ isShow, onClose, appBaseUrl, accessToken }: Props) => {
)
})}
</div>
<div className="mt-6 w-full bg-gray-100 rounded-lg flex-col justify-start items-start inline-flex">
{option === 'chromePlugin' && (
<div className="mt-6 w-full">
<div className={cn('gap-2 py-3 justify-center items-center inline-flex w-full rounded-lg',
'bg-primary-600 hover:bg-primary-600/75 hover:shadow-md cursor-pointer text-white hover:shadow-sm flex-shrink-0')}>
<div className={`w-4 h-4 relative ${style.pluginInstallIcon}`}></div>
<div className="text-white text-sm font-medium font-['Inter'] leading-tight" onClick={navigateToChromeUrl}>{t(`${prefixEmbedded}.chromePlugin`)}</div>
</div>
</div>
)}
<div className={cn('w-full bg-gray-100 rounded-lg flex-col justify-start items-start inline-flex',
'mt-6')}>
<div className="self-stretch pl-3 pr-1 py-1 bg-gray-50 rounded-tl-lg rounded-tr-lg border border-black border-opacity-5 justify-start items-center gap-2 inline-flex">
<div className="grow shrink basis-0 text-slate-700 text-[13px] font-medium leading-none">
{t(`${prefixEmbedded}.${option}`)}

View File

@ -12,3 +12,9 @@
.scriptsIcon {
background-image: url(../assets/scripts-option.svg);
}
.chromePluginIcon {
background-image: url(../assets/chromeplugin-option.svg);
}
.pluginInstallIcon {
background-image: url(../assets/chromeplugin-install.svg);
}

View File

@ -58,6 +58,7 @@ const translation = {
explanation: 'Choose the way to embed chat app to your website',
iframe: 'To add the chat app any where on your website, add this iframe to your html code.',
scripts: 'To add a chat app to the bottom right of your website add this code to your html.',
chromePlugin: 'Install Dify Chatbot Chrome Extension',
copied: 'Copied',
copy: 'Copy',
},

View File

@ -58,6 +58,7 @@ const translation = {
explanation: '选择一种方式将聊天应用嵌入到你的网站中',
iframe: '将以下 iframe 嵌入到你的网站中的目标位置',
scripts: '将以下代码嵌入到你的网站中',
chromePlugin: '安装 Dify Chrome 浏览器扩展',
copied: '已复制',
copy: '复制',
},