Skip to content

Commit dd91b45

Browse files
author
Jicheng Lu
committed
add embedding rich content
1 parent 075d008 commit dd91b45

6 files changed

Lines changed: 174 additions & 6 deletions

File tree

src/lib/helpers/enums.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const richType = {
2929
Generic: 'generic_template',
3030
Upload: 'upload_template',
3131
ProgramCode: 'program_code',
32+
Embedding: 'embedding_template'
3233
}
3334
export const RichType = Object.freeze(richType);
3435

src/lib/helpers/types/conversationTypes.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,33 @@ IRichContent.prototype.code_script;
127127
*/
128128
IRichContent.prototype.language;
129129

130+
/**
131+
* The URL of the embedding rich content.
132+
*
133+
* @name url
134+
* @type {string}
135+
* @instance
136+
*/
137+
IRichContent.prototype.url;
138+
139+
/**
140+
* The title of the embedding rich content.
141+
*
142+
* @name title
143+
* @type {string}
144+
* @instance
145+
*/
146+
IRichContent.prototype.title;
147+
148+
/**
149+
* The html tag of the embedding rich content.
150+
*
151+
* @name html_tag
152+
* @type {string}
153+
* @instance
154+
*/
155+
IRichContent.prototype.html_tag;
156+
130157

131158
/**
132159
* @typedef {Object} TextMessage

src/lib/scss/app.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ File: Main Css File
4747
@import "custom/components/markdown";
4848
@import "custom/components/state";
4949
@import "custom/components/codeScript";
50+
@import "custom/components/rich_content";
5051

5152
/* Plugins */
5253
@import "custom/plugins/custom-scrollbar";
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
.rc-embedding-wrapper {
2+
width: 100%;
3+
margin-top: 8px;
4+
display: flex;
5+
flex-direction: column;
6+
align-items: center;
7+
8+
.rc-embedding-toggle-group {
9+
display: inline-flex;
10+
align-items: center;
11+
gap: 6px;
12+
}
13+
14+
.rc-embedding-link {
15+
display: inline-flex;
16+
align-items: center;
17+
justify-content: center;
18+
color: var(--bs-info, #50a5f1);
19+
font-size: 16px;
20+
transition: color 0.2s ease;
21+
text-decoration: none;
22+
23+
&:hover {
24+
color: darken(#50a5f1, 15%);
25+
}
26+
}
27+
28+
.rc-embedding-toggle {
29+
display: inline-flex;
30+
align-items: center;
31+
justify-content: center;
32+
gap: 8px;
33+
margin: 0 auto;
34+
width: auto;
35+
background: linear-gradient(135deg, rgba(244, 106, 106, 0.08), rgba(244, 106, 106, 0.15));
36+
border: 1px solid rgba(244, 106, 106, 0.2);
37+
border-radius: 20px;
38+
cursor: pointer;
39+
padding: 6px 16px;
40+
font-size: 13px;
41+
font-weight: 500;
42+
color: var(--bs-danger, #f46a6a);
43+
user-select: none;
44+
transition: all 0.25s ease;
45+
backdrop-filter: blur(4px);
46+
47+
&:hover {
48+
background: linear-gradient(135deg, rgba(244, 106, 106, 0.15), rgba(244, 106, 106, 0.25));
49+
border-color: rgba(244, 106, 106, 0.4);
50+
box-shadow: 0 2px 8px rgba(244, 106, 106, 0.2);
51+
transform: translateY(-1px);
52+
}
53+
54+
&:active {
55+
transform: translateY(0);
56+
box-shadow: none;
57+
}
58+
59+
&.closed {
60+
background: linear-gradient(135deg, rgba(52, 195, 143, 0.08), rgba(52, 195, 143, 0.15));
61+
border-color: rgba(52, 195, 143, 0.2);
62+
color: var(--bs-success, #34c38f);
63+
64+
&:hover {
65+
background: linear-gradient(135deg, rgba(52, 195, 143, 0.15), rgba(52, 195, 143, 0.25));
66+
border-color: rgba(52, 195, 143, 0.4);
67+
box-shadow: 0 2px 8px rgba(52, 195, 143, 0.2);
68+
}
69+
}
70+
}
71+
72+
.rc-embedding-container {
73+
width: 100%;
74+
border-radius: 8px;
75+
display: flex;
76+
justify-content: center;
77+
overflow: auto;
78+
scrollbar-width: thin;
79+
80+
.rc-embedding-iframe {
81+
width: fit-content;
82+
min-width: 100%;
83+
max-height: 800px;
84+
min-height: 500px;
85+
border: 1px solid var(--bs-border-color, #dee2e6);
86+
border-radius: 8px;
87+
}
88+
}
89+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<script>
2+
import collapse from 'svelte-collapse';
3+
4+
/**
5+
* @type {{
6+
* url?: string,
7+
* title?: string,
8+
* htmlTag?: string
9+
* }}
10+
*/
11+
let {
12+
url = '',
13+
title = '',
14+
htmlTag = ''
15+
} = $props();
16+
17+
let open = $state(false);
18+
19+
function toggleCollapse() {
20+
open = !open;
21+
}
22+
</script>
23+
24+
{#if htmlTag && url}
25+
<div class="rc-embedding-wrapper">
26+
<div class="rc-embedding-toggle-group">
27+
<button type="button" class="rc-embedding-toggle" class:closed={!open} onclick={toggleCollapse}>
28+
<span>{open ? 'Close' : 'Open'}{title ? ` ${title}` : ''}</span>
29+
</button>
30+
<a href={url} target="_blank" rel="noopener noreferrer" class="rc-embedding-link" title="Open in new tab">
31+
<i class="bx bx-link-external"></i>
32+
</a>
33+
</div>
34+
<div use:collapse={{ open, duration: 0.3, easing: 'ease' }} style="width: 100%; margin-top: 8px;">
35+
<div class="rc-embedding-container">
36+
{#if htmlTag === 'iframe'}
37+
<iframe
38+
src={url}
39+
title={title || ''}
40+
frameborder="0"
41+
allowfullscreen
42+
sandbox="allow-scripts allow-same-origin allow-popups allow-forms"
43+
class="rc-embedding-iframe"
44+
></iframe>
45+
{/if}
46+
</div>
47+
</div>
48+
</div>
49+
{/if}
50+

src/routes/chat/[agentId]/[conversationId]/rich-content/rich-content.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { EditorType, RichType } from "$lib/helpers/enums";
33
import RcPlainOptions from "./rc-plain-options.svelte";
44
import RcComplexOptions from "./rc-complex-options.svelte";
5+
import RcEmbedding from "./rc-embedding.svelte";
56
import ChatAttachmentOptions from "../chat-util/chat-attachment-options.svelte";
67
78
/**
@@ -47,13 +48,12 @@
4748
</script>
4849
4950
50-
5151
{#if message?.rich_content?.editor === EditorType.File}
5252
<ChatAttachmentOptions options={resolvedOptions.options} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
53+
{:else if message?.rich_content?.message?.rich_type === RichType.Embedding}
54+
<RcEmbedding url={message?.rich_content?.message?.url} title={message?.rich_content?.message?.title} htmlTag={message?.rich_content?.message?.html_tag} />
55+
{:else if !resolvedOptions.isComplexElement}
56+
<RcPlainOptions options={resolvedOptions.options} isMultiSelect={resolvedOptions.isMultiSelect} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
5357
{:else}
54-
{#if !resolvedOptions.isComplexElement}
55-
<RcPlainOptions options={resolvedOptions.options} isMultiSelect={resolvedOptions.isMultiSelect} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
56-
{:else}
57-
<RcComplexOptions options={resolvedOptions.options} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
58-
{/if}
58+
<RcComplexOptions options={resolvedOptions.options} disabled={disabled} onConfirm={(title, payload) => handleConfirm(title, payload)} />
5959
{/if}

0 commit comments

Comments
 (0)