Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ Build:
yarn build
```

## Features

### File-only uploads

- **Purpose:** Allow users to send uploaded files immediately without having to type a companion message.
- **Usage example:** Upload a document via the **File Upload** button and click **Send** right away; the embed will deliver the files to your Agentflow conversation and, if a text prompt is required, automatically include a hidden `file uploaded` message for you.
- **Dependencies / breaking changes:** No additional configuration is required; the behavior is backward compatible with existing upload settings.

## Embed in your HTML

### PopUp
Expand Down
30 changes: 21 additions & 9 deletions src/components/Bot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1029,17 +1029,27 @@ export const Bot = (botProps: BotProps & { class?: string }) => {

// Handle form submission
const handleSubmit = async (value: string | object, action?: IAction | undefined | null, humanInput?: any) => {
if (typeof value === 'string' && value.trim() === '') {
const fileUploadFallbackMessage = 'file uploaded';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The constant fileUploadFallbackMessage is defined inside handleSubmit, which means it's redeclared on every function call. It's better to define it once at a higher scope, for example, at the module level before the Bot component, or right inside the Bot component but outside handleSubmit. This improves performance slightly and follows best practices for constants.

let submissionValue: string | object = value;
let formData = {};

if (typeof submissionValue === 'string') {
const trimmedValue = submissionValue.trim();
const hasUploads = previews().length > 0;
const containsFile = previews().filter((item) => !item.mime.startsWith('image') && item.type !== 'audio').length > 0;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using .filter(...).length > 0 iterates over the entire previews array even after a match is found. For checking existence, .some() is more efficient as it stops as soon as it finds a matching element.

Suggested change
const containsFile = previews().filter((item) => !item.mime.startsWith('image') && item.type !== 'audio').length > 0;
const containsFile = previews().some((item) => !item.mime.startsWith('image') && item.type !== 'audio');

if (!previews().length || (previews().length && containsFile)) {

if (!hasUploads && trimmedValue === '') {
return;
}

if (trimmedValue === '' && hasUploads && containsFile) {
submissionValue = fileUploadFallbackMessage;
}
}

let formData = {};
if (typeof value === 'object') {
formData = value;
value = Object.entries(value)
if (typeof submissionValue === 'object') {
formData = submissionValue;
submissionValue = Object.entries(submissionValue)
.map(([key, value]) => `${key}: ${value}`)
.join('\n');
}
Expand All @@ -1065,14 +1075,16 @@ export const Bot = (botProps: BotProps & { class?: string }) => {

clearPreviews();

const messageToDisplay = typeof value === 'string' ? value : (submissionValue as string);

setMessages((prevMessages) => {
const messages: MessageType[] = [...prevMessages, { message: value as string, type: 'userMessage', fileUploads: uploads }];
const messages: MessageType[] = [...prevMessages, { message: messageToDisplay as string, type: 'userMessage', fileUploads: uploads }];
addChatMessage(messages);
return messages;
});

const body: IncomingInput = {
question: value,
question: submissionValue,
chatId: chatId(),
};

Expand Down Expand Up @@ -1134,7 +1146,7 @@ export const Bot = (botProps: BotProps & { class?: string }) => {
return allMessages;
});

updateMetadata(data, value);
updateMetadata(data, submissionValue);

setLoading(false);
setUserInput('');
Expand Down