Feat: Adjust the EmbedDialog style #3221 (#8911)

### What problem does this PR solve?

Feat: Adjust the EmbedDialog style #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-07-18 17:06:28 +08:00
committed by GitHub
parent daa1113513
commit 3722fec921
4 changed files with 90 additions and 49 deletions

View File

@ -1,6 +1,7 @@
import classNames from 'classnames'; import classNames from 'classnames';
import Markdown from 'react-markdown'; import Markdown from 'react-markdown';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import rehypeKatex from 'rehype-katex'; import rehypeKatex from 'rehype-katex';
import rehypeRaw from 'rehype-raw'; import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
@ -13,8 +14,10 @@ import styles from './index.less';
const HightLightMarkdown = ({ const HightLightMarkdown = ({
children, children,
dark = false,
}: { }: {
children: string | null | undefined; children: string | null | undefined;
dark?: boolean;
}) => { }) => {
return ( return (
<Markdown <Markdown
@ -31,7 +34,7 @@ const HightLightMarkdown = ({
{...rest} {...rest}
PreTag="div" PreTag="div"
language={match[1]} language={match[1]}
// style={dark} style={dark && oneDark}
> >
{String(children).replace(/\n$/, '')} {String(children).replace(/\n$/, '')}
</SyntaxHighlighter> </SyntaxHighlighter>

View File

@ -38,7 +38,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content <DialogPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-2xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-colors-background-neutral-standard p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg', 'fixed left-[50%] top-[50%] z-50 grid w-full max-w-xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-colors-background-neutral-standard p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
className, className,
)} )}
{...props} {...props}

View File

@ -1,17 +1,21 @@
import CopyToClipboard from '@/components/copy-to-clipboard'; import CopyToClipboard from '@/components/copy-to-clipboard';
import HightLightMarkdown from '@/components/highlight-markdown'; import HightLightMarkdown from '@/components/highlight-markdown';
import { import { SelectWithSearch } from '@/components/originui/select-with-search';
UnderlineTabs,
UnderlineTabsContent,
UnderlineTabsList,
UnderlineTabsTrigger,
} from '@/components/originui/underline-tabs';
import { import {
Dialog, Dialog,
DialogContent, DialogContent,
DialogHeader, DialogHeader,
DialogTitle, DialogTitle,
} from '@/components/ui/dialog'; } from '@/components/ui/dialog';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form';
import { Switch } from '@/components/ui/switch';
import { SharedFrom } from '@/constants/chat'; import { SharedFrom } from '@/constants/chat';
import { import {
LanguageAbbreviation, LanguageAbbreviation,
@ -19,11 +23,19 @@ import {
} from '@/constants/common'; } from '@/constants/common';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { IModalProps } from '@/interfaces/common'; import { IModalProps } from '@/interfaces/common';
import { memo, useMemo, useState } from 'react'; import { zodResolver } from '@hookform/resolvers/zod';
import { memo, useCallback, useMemo } from 'react';
import { useForm, useWatch } from 'react-hook-form';
import { z } from 'zod';
const FormSchema = z.object({
visibleAvatar: z.boolean(),
locale: z.string(),
});
type IProps = IModalProps<any> & { type IProps = IModalProps<any> & {
token: string; token: string;
form: SharedFrom; from: SharedFrom;
beta: string; beta: string;
isAgent: boolean; isAgent: boolean;
}; };
@ -31,14 +43,21 @@ type IProps = IModalProps<any> & {
function EmbedDialog({ function EmbedDialog({
hideModal, hideModal,
token = '', token = '',
form, from,
beta = '', beta = '',
isAgent, isAgent,
}: IProps) { }: IProps) {
const { t } = useTranslate('chat'); const { t } = useTranslate('chat');
const [visibleAvatar, setVisibleAvatar] = useState(false); const form = useForm<z.infer<typeof FormSchema>>({
const [locale, setLocale] = useState(''); resolver: zodResolver(FormSchema),
defaultValues: {
visibleAvatar: false,
locale: '',
},
});
const values = useWatch({ control: form.control });
const languageOptions = useMemo(() => { const languageOptions = useMemo(() => {
return Object.values(LanguageAbbreviation).map((x) => ({ return Object.values(LanguageAbbreviation).map((x) => ({
@ -47,8 +66,9 @@ function EmbedDialog({
})); }));
}, []); }, []);
const generateIframeSrc = () => { const generateIframeSrc = useCallback(() => {
let src = `${location.origin}/chat/share?shared_id=${token}&from=${form}&auth=${beta}`; const { visibleAvatar, locale } = values;
let src = `${location.origin}/chat/share?shared_id=${token}&from=${from}&auth=${beta}`;
if (visibleAvatar) { if (visibleAvatar) {
src += '&visible_avatar=1'; src += '&visible_avatar=1';
} }
@ -56,11 +76,11 @@ function EmbedDialog({
src += `&locale=${locale}`; src += `&locale=${locale}`;
} }
return src; return src;
}; }, [beta, from, token, values]);
const iframeSrc = generateIframeSrc(); const text = useMemo(() => {
const iframeSrc = generateIframeSrc();
const text = ` return `
~~~ html ~~~ html
<iframe <iframe
src="${iframeSrc}" src="${iframeSrc}"
@ -70,6 +90,7 @@ function EmbedDialog({
</iframe> </iframe>
~~~ ~~~
`; `;
}, [generateIframeSrc]);
return ( return (
<Dialog open onOpenChange={hideModal}> <Dialog open onOpenChange={hideModal}>
@ -79,40 +100,57 @@ function EmbedDialog({
{t('embedIntoSite', { keyPrefix: 'common' })} {t('embedIntoSite', { keyPrefix: 'common' })}
</DialogTitle> </DialogTitle>
</DialogHeader> </DialogHeader>
<section className="w-full overflow-auto"> <section className="w-full overflow-auto space-y-5 text-sm text-text-sub-title">
<UnderlineTabs defaultValue="1" className="w-full"> <Form {...form}>
<UnderlineTabsList> <form className="space-y-5">
<UnderlineTabsTrigger value="1"> <FormField
{t('fullScreenTitle')} control={form.control}
</UnderlineTabsTrigger> name="visibleAvatar"
<UnderlineTabsTrigger value="2"> render={({ field }) => (
{t('partialTitle')} <FormItem>
</UnderlineTabsTrigger> <FormLabel>{t('avatarHidden')}</FormLabel>
<UnderlineTabsTrigger value="3"> <FormControl>
{t('extensionTitle')} <Switch
</UnderlineTabsTrigger> checked={field.value}
</UnderlineTabsList> onCheckedChange={field.onChange}
<UnderlineTabsContent value="1"> ></Switch>
<section> </FormControl>
<HightLightMarkdown>{text}</HightLightMarkdown> <FormMessage />
</section> </FormItem>
</UnderlineTabsContent> )}
<UnderlineTabsContent value="2"> />
{t('comingSoon')} <FormField
</UnderlineTabsContent> control={form.control}
<UnderlineTabsContent value="3"> name="locale"
{t('comingSoon')} render={({ field }) => (
</UnderlineTabsContent> <FormItem>
</UnderlineTabs> <FormLabel>{t('locale')}</FormLabel>
<div className="text-base font-medium mt-4 mb-1"> <FormControl>
<SelectWithSearch
{...field}
options={languageOptions}
></SelectWithSearch>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
<div>
<span>Embed code</span>
<HightLightMarkdown dark>{text}</HightLightMarkdown>
</div>
<div className=" font-medium mt-4 mb-1">
{t(isAgent ? 'flow' : 'chat', { keyPrefix: 'header' })} {t(isAgent ? 'flow' : 'chat', { keyPrefix: 'header' })}
<span className="ml-1 inline-block">ID</span> <span className="ml-1 inline-block">ID</span>
</div> </div>
<div className="bg-background-card rounded-md p-2 "> <div className="bg-background-card rounded-lg flex justify-between p-2">
{token} <CopyToClipboard text={token}></CopyToClipboard> <span>{token} </span>
<CopyToClipboard text={token}></CopyToClipboard>
</div> </div>
<a <a
className="pt-3 cursor-pointer text-background-checked inline-block" className="cursor-pointer text-background-checked inline-block"
href={ href={
isAgent isAgent
? 'https://ragflow.io/docs/dev/http_api_reference#create-session-with-agent' ? 'https://ragflow.io/docs/dev/http_api_reference#create-session-with-agent'

View File

@ -153,7 +153,7 @@ export default function Agent() {
visible={embedVisible} visible={embedVisible}
hideModal={hideEmbedModal} hideModal={hideEmbedModal}
token={id!} token={id!}
form={SharedFrom.Agent} from={SharedFrom.Agent}
beta={beta} beta={beta}
isAgent isAgent
></EmbedDialog> ></EmbedDialog>