feat: add 'Open in new tab' button for agents (#13044)

- Add new button in agent management dropdown to open agent in new tab
- Implement token-based authentication for shared agent access
- Add translations for 9 languages (en, zh, zh-tw, de, fr, it, ru,
pt-br, vi)
- Keep existing 'Embed into webpage' functionality intact

### What problem does this PR solve?

This allows users to open agents in a separate tab to work in background
while continuing to use other parts of the application.

<img width="1920" height="1080" alt="image"
src="https://github.com/user-attachments/assets/ca1719c8-2f00-4570-a730-1321fa0bfd57"
/>
<img width="254" height="222" alt="image"
src="https://github.com/user-attachments/assets/b3dd6d9f-b7e7-46b0-83e7-f0ea86e7b156"
/>
<img width="1920" height="1080" alt="image"
src="https://github.com/user-attachments/assets/e94e99f9-9039-43f7-b2d9-862b9448630c"
/>

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
PentaFDevs
2026-02-25 06:39:02 +01:00
committed by GitHub
parent cf6fd6f115
commit 8ad47bf242
12 changed files with 33 additions and 3 deletions

View File

@@ -11,7 +11,14 @@ You can use iframe to embed an agent into a third-party webpage.
1. Before proceeding, you must [acquire an API key](../models/llm_api_key_setup.md); otherwise, an error message would appear.
2. On the **Agent** page, click an intended agent to access its editing page.
3. Click **Management > Embed into webpage** on the top right corner of the canvas to show the **iframe** window:
4. Copy the iframe and embed it into your webpage.
3. Click **Management > Embed into webpage** on the top right corner of the canvas to show the **Embed into webpage** dialog.
4. Configure your embed options:
- **Embed Type**: Choose between Fullscreen Chat (traditional iframe) or Floating Widget (Intercom-style)
- **Theme**: Select Light or Dark theme (for fullscreen mode)
- **Hide avatar**: Toggle avatar visibility
- **Enable Streaming Responses**: Enable streaming for widget mode
- **Locale**: Select the language for the embedded agent
5. Copy the generated iframe code and embed it into your webpage.
6. **Chat in new tab**: Click the "Chat in new tab" button to preview the agent in a separate browser tab with your configured settings. This allows you to test the agent before embedding it.
![Embed_agent](https://raw.githubusercontent.com/infiniflow/ragflow-docs/main/images/embed_agent_into_webpage.jpg)

View File

@@ -1,6 +1,7 @@
import CopyToClipboard from '@/components/copy-to-clipboard';
import HighLightMarkdown from '@/components/highlight-markdown';
import { SelectWithSearch } from '@/components/originui/select-with-search';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
@@ -28,6 +29,7 @@ import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common';
import { Routes } from '@/routes';
import { zodResolver } from '@hookform/resolvers/zod';
import { ExternalLink } from 'lucide-react';
import { memo, useCallback, useMemo } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { z } from 'zod';
@@ -146,6 +148,11 @@ function EmbedDialog({
}
}, [generateIframeSrc, values]);
const handleOpenInNewTab = useCallback(() => {
const iframeSrc = generateIframeSrc();
window.open(iframeSrc, '_blank');
}, [generateIframeSrc]);
return (
<Dialog open onOpenChange={hideModal}>
<DialogContent>
@@ -280,6 +287,14 @@ function EmbedDialog({
<HighLightMarkdown>{text}</HighLightMarkdown>
</div>
</div>
<Button
onClick={handleOpenInNewTab}
className="w-full"
variant="secondary"
>
<ExternalLink className="mr-2 h-4 w-4" />
{t('openInNewTab', { keyPrefix: 'common' })}
</Button>
<div className=" font-medium mt-4 mb-1">
{t(isAgent ? 'flow' : 'chat', { keyPrefix: 'header' })}
<span className="ml-1 inline-block">ID</span>

View File

@@ -48,6 +48,7 @@ export default {
submit: 'Absenden',
clear: 'Leeren',
embedIntoSite: 'In Webseite einbetten',
openInNewTab: 'Chat in neuem Tab',
previousPage: 'Zurück',
nextPage: 'Weiter',
add: 'Hinzufügen',

View File

@@ -46,6 +46,7 @@ export default {
submit: 'Submit',
clear: 'Clear',
embedIntoSite: 'Embed into webpage',
openInNewTab: 'Chat in new tab',
previousPage: 'Previous',
nextPage: 'Next',
add: 'Add',

View File

@@ -37,6 +37,7 @@ export default {
pleaseInput: 'Veuillez saisir',
submit: 'Soumettre',
embedIntoSite: 'Intégrer dans la page web',
openInNewTab: 'Chat dans un nouvel onglet',
previousPage: 'Précédent',
nextPage: 'Suivant',
add: 'Ajouter',

View File

@@ -53,6 +53,7 @@ export default {
submit: 'Invia',
clear: 'Cancella',
embedIntoSite: 'Incorpora nella pagina web',
openInNewTab: 'Chat in una nuova scheda',
previousPage: 'Precedente',
nextPage: 'Successivo',
add: 'Aggiungi',

View File

@@ -36,6 +36,7 @@ export default {
pleaseInput: 'Por favor, insira',
submit: 'Enviar',
embedIntoSite: 'Incorporar no site',
openInNewTab: 'Chat em nova aba',
previousPage: 'Anterior',
nextPage: 'Próxima',
},

View File

@@ -45,6 +45,7 @@ export default {
submit: 'Отправить',
clear: 'Очистить',
embedIntoSite: 'Встроить на веб-страницу',
openInNewTab: 'Чат в новой вкладке',
previousPage: 'Назад',
nextPage: 'Вперед',
add: 'Добавить',

View File

@@ -39,6 +39,7 @@ export default {
spanish: 'Tiếng Tây Ban Nha',
japanese: 'Tiếng Nhật',
embedIntoSite: 'Nhúng vào trang web',
openInNewTab: 'Chat trong tab mới',
nextPage: 'Tới',
previousPage: 'Lùi',
},

View File

@@ -36,6 +36,7 @@ export default {
pleaseInput: '請輸入',
submit: '提交',
embedIntoSite: '嵌入網站',
openInNewTab: '在新標籤頁中聊天',
previousPage: '上一頁',
nextPage: '下一頁',
add: '添加',

View File

@@ -45,6 +45,7 @@ export default {
submit: '提交',
clear: '清空',
embedIntoSite: '嵌入网站',
openInNewTab: '在新标签页中聊天',
previousPage: '上一页',
nextPage: '下一页',
add: '添加',

View File

@@ -17,7 +17,6 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import message from '@/components/ui/message';
import { SharedFrom } from '@/constants/chat';
import { useSetModalState } from '@/hooks/common-hooks';
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';