|
|
import { |
|
|
CircleNotch, |
|
|
FileCode, |
|
|
FileCsv, |
|
|
FileDoc, |
|
|
FileHtml, |
|
|
FileText, |
|
|
FileImage, |
|
|
FilePdf, |
|
|
WarningOctagon, |
|
|
X, |
|
|
} from "@phosphor-icons/react"; |
|
|
import { REMOVE_ATTACHMENT_EVENT } from "../../DnDWrapper"; |
|
|
import { Tooltip } from "react-tooltip"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export default function AttachmentManager({ attachments }) { |
|
|
if (attachments.length === 0) return null; |
|
|
return ( |
|
|
<div className="flex flex-wrap gap-2 mt-2 mb-4"> |
|
|
{attachments.map((attachment) => ( |
|
|
<AttachmentItem key={attachment.uid} attachment={attachment} /> |
|
|
))} |
|
|
</div> |
|
|
); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function AttachmentItem({ attachment }) { |
|
|
const { uid, file, status, error, document, type, contentString } = |
|
|
attachment; |
|
|
const { iconBgColor, Icon } = displayFromFile(file); |
|
|
|
|
|
function removeFileFromQueue() { |
|
|
window.dispatchEvent( |
|
|
new CustomEvent(REMOVE_ATTACHMENT_EVENT, { detail: { uid, document } }) |
|
|
); |
|
|
} |
|
|
|
|
|
if (status === "in_progress") { |
|
|
return ( |
|
|
<div className="relative flex items-center gap-x-1 rounded-lg bg-theme-attachment-bg border-none w-[180px] group"> |
|
|
<div |
|
|
className={`bg-theme-attachment-icon-spinner-bg rounded-md flex items-center justify-center flex-shrink-0 h-[32px] w-[32px] m-1`} |
|
|
> |
|
|
<CircleNotch |
|
|
size={18} |
|
|
weight="bold" |
|
|
className="text-theme-attachment-icon-spinner animate-spin" |
|
|
/> |
|
|
</div> |
|
|
<div className="flex flex-col w-[125px]"> |
|
|
<p className="text-theme-attachment-text text-xs font-semibold truncate"> |
|
|
{file.name} |
|
|
</p> |
|
|
<p className="text-theme-attachment-text-secondary text-[10px] leading-[14px] font-medium"> |
|
|
Uploading... |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
); |
|
|
} |
|
|
|
|
|
if (status === "failed") { |
|
|
return ( |
|
|
<> |
|
|
<div |
|
|
data-tooltip-id={`attachment-uid-${uid}-error`} |
|
|
data-tooltip-content={error} |
|
|
className={`relative flex items-center gap-x-1 rounded-lg bg-theme-attachment-error-bg border-none w-[180px] group`} |
|
|
> |
|
|
<div className="invisible group-hover:visible absolute -top-[5px] -right-[5px] w-fit h-fit z-[10]"> |
|
|
<button |
|
|
onClick={removeFileFromQueue} |
|
|
type="button" |
|
|
className="bg-white hover:bg-error hover:text-theme-attachment-text rounded-full p-1 flex items-center justify-center hover:border-transparent border border-theme-attachment-bg" |
|
|
> |
|
|
<X size={10} className="flex-shrink-0" /> |
|
|
</button> |
|
|
</div> |
|
|
<div |
|
|
className={`bg-error rounded-md flex items-center justify-center flex-shrink-0 h-[32px] w-[32px] m-1`} |
|
|
> |
|
|
<WarningOctagon size={24} className="text-theme-attachment-icon" /> |
|
|
</div> |
|
|
<div className="flex flex-col w-[125px]"> |
|
|
<p className="text-theme-attachment-text text-xs font-semibold truncate"> |
|
|
{file.name} |
|
|
</p> |
|
|
<p className="text-theme-attachment-text-secondary text-[10px] leading-[14px] font-medium truncate"> |
|
|
{error ?? "File not embedded!"} |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
<Tooltip |
|
|
id={`attachment-uid-${uid}-error`} |
|
|
place="top" |
|
|
delayShow={300} |
|
|
className="allm-tooltip !allm-text-xs" |
|
|
/> |
|
|
</> |
|
|
); |
|
|
} |
|
|
|
|
|
if (type === "attachment") { |
|
|
return ( |
|
|
<> |
|
|
<div |
|
|
data-tooltip-id={`attachment-uid-${uid}-success`} |
|
|
data-tooltip-content={`${file.name} will be attached to this prompt. It will not be embedded into the workspace permanently.`} |
|
|
className={`relative flex items-center gap-x-1 rounded-lg bg-theme-attachment-success-bg border-none w-[180px] group`} |
|
|
> |
|
|
<div className="invisible group-hover:visible absolute -top-[5px] -right-[5px] w-fit h-fit z-[10]"> |
|
|
<button |
|
|
onClick={removeFileFromQueue} |
|
|
type="button" |
|
|
className="bg-white hover:bg-error hover:text-theme-attachment-text rounded-full p-1 flex items-center justify-center hover:border-transparent border border-theme-attachment-bg" |
|
|
> |
|
|
<X size={10} className="flex-shrink-0" /> |
|
|
</button> |
|
|
</div> |
|
|
{contentString ? ( |
|
|
<img |
|
|
alt={`Preview of ${file.name}`} |
|
|
src={contentString} |
|
|
className={`${iconBgColor} w-[30px] h-[30px] rounded-lg flex items-center justify-center m-1`} |
|
|
/> |
|
|
) : ( |
|
|
<div |
|
|
className={`${iconBgColor} rounded-md flex items-center justify-center flex-shrink-0 h-[32px] w-[32px] m-1`} |
|
|
> |
|
|
<Icon size={24} className="text-theme-attachment-icon" /> |
|
|
</div> |
|
|
)} |
|
|
<div className="flex flex-col w-[125px]"> |
|
|
<p className="text-theme-attachment-text text-xs font-semibold truncate"> |
|
|
{file.name} |
|
|
</p> |
|
|
<p className="text-theme-attachment-text-secondary text-[10px] leading-[14px] font-medium"> |
|
|
Image attached! |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
<Tooltip |
|
|
id={`attachment-uid-${uid}-success`} |
|
|
place="top" |
|
|
delayShow={300} |
|
|
className="allm-tooltip !allm-text-xs" |
|
|
/> |
|
|
</> |
|
|
); |
|
|
} |
|
|
|
|
|
return ( |
|
|
<> |
|
|
<div |
|
|
data-tooltip-id={`attachment-uid-${uid}-success`} |
|
|
data-tooltip-content={ |
|
|
status === "embedded" |
|
|
? `${file.name} was uploaded and embedded into this workspace. It will be available for RAG chat now.` |
|
|
: `${file.name} will be used as context for this chat only.` |
|
|
} |
|
|
className={`relative flex items-center gap-x-1 rounded-lg bg-theme-attachment-bg border-none w-[180px] group`} |
|
|
> |
|
|
<div className="invisible group-hover:visible absolute -top-[5px] -right-[5px] w-fit h-fit z-[10]"> |
|
|
<button |
|
|
onClick={removeFileFromQueue} |
|
|
type="button" |
|
|
className="bg-white hover:bg-error hover:text-theme-attachment-text rounded-full p-1 flex items-center justify-center hover:border-transparent border border-theme-attachment-bg" |
|
|
> |
|
|
<X size={10} className="flex-shrink-0" /> |
|
|
</button> |
|
|
</div> |
|
|
<div |
|
|
className={`${iconBgColor} rounded-md flex items-center justify-center flex-shrink-0 h-[32px] w-[32px] m-1`} |
|
|
> |
|
|
<Icon |
|
|
size={24} |
|
|
weight="light" |
|
|
className="text-theme-attachment-icon" |
|
|
/> |
|
|
</div> |
|
|
<div className="flex flex-col w-[125px]"> |
|
|
<p className="text-white text-xs font-semibold truncate"> |
|
|
{file.name} |
|
|
</p> |
|
|
<p className="text-theme-attachment-text-secondary text-[10px] leading-[14px] font-medium"> |
|
|
{status === "embedded" ? "File embedded!" : "Added as context!"} |
|
|
</p> |
|
|
</div> |
|
|
</div> |
|
|
<Tooltip |
|
|
id={`attachment-uid-${uid}-success`} |
|
|
place="top" |
|
|
delayShow={300} |
|
|
className="allm-tooltip !allm-text-xs" |
|
|
/> |
|
|
</> |
|
|
); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function displayFromFile(file) { |
|
|
const extension = file?.name?.split(".")?.pop()?.toLowerCase() ?? "txt"; |
|
|
switch (extension) { |
|
|
case "pdf": |
|
|
return { iconBgColor: "bg-magenta", Icon: FilePdf }; |
|
|
case "doc": |
|
|
case "docx": |
|
|
return { iconBgColor: "bg-royalblue", Icon: FileDoc }; |
|
|
case "html": |
|
|
return { iconBgColor: "bg-purple", Icon: FileHtml }; |
|
|
case "csv": |
|
|
case "xlsx": |
|
|
return { iconBgColor: "bg-success", Icon: FileCsv }; |
|
|
case "json": |
|
|
case "sql": |
|
|
case "js": |
|
|
case "jsx": |
|
|
case "cpp": |
|
|
case "c": |
|
|
return { iconBgColor: "bg-warn", Icon: FileCode }; |
|
|
case "png": |
|
|
case "jpg": |
|
|
case "jpeg": |
|
|
return { iconBgColor: "bg-royalblue", Icon: FileImage }; |
|
|
default: |
|
|
return { iconBgColor: "bg-royalblue", Icon: FileText }; |
|
|
} |
|
|
} |
|
|
|