Feat: enhance sending files UI
This commit is contained in:
parent
830d5a6ca8
commit
e56ce2f2b4
5 changed files with 130 additions and 104 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
export const getClassNamesFilePreview = (inputFocus) => {
|
export const getClassNamesFilePreview = (inputFocus) => {
|
||||||
return `flex w-full items-center gap-4 rounded-t-lg bg-background px-14 py-5 overflow-auto custom-scroll ${
|
return `transition-all duration-300 flex w-full items-center gap-4 rounded-t-lg bg-background px-14 py-5 overflow-auto custom-scroll ${
|
||||||
inputFocus
|
inputFocus
|
||||||
? "border-2 border-b-0 border-ring"
|
? "border-2 border-b-0 border-ring"
|
||||||
: "border border-b-0 border-border"
|
: "border border-b-0 border-border"
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,9 @@ import remarkMath from "remark-math";
|
||||||
import MaleTechnology from "../../../../../assets/male-technologist.png";
|
import MaleTechnology from "../../../../../assets/male-technologist.png";
|
||||||
import Robot from "../../../../../assets/robot.png";
|
import Robot from "../../../../../assets/robot.png";
|
||||||
import CodeTabsComponent from "../../../../../components/codeTabsComponent";
|
import CodeTabsComponent from "../../../../../components/codeTabsComponent";
|
||||||
import IconComponent from "../../../../../components/genericIconComponent";
|
import IconComponent, {
|
||||||
|
ForwardedIconComponent,
|
||||||
|
} from "../../../../../components/genericIconComponent";
|
||||||
import SanitizedHTMLWrapper from "../../../../../components/sanitizedHTMLWrapper";
|
import SanitizedHTMLWrapper from "../../../../../components/sanitizedHTMLWrapper";
|
||||||
import useAlertStore from "../../../../../stores/alertStore";
|
import useAlertStore from "../../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../../stores/flowStore";
|
import useFlowStore from "../../../../../stores/flowStore";
|
||||||
|
|
@ -22,6 +24,7 @@ export default function ChatMessage({
|
||||||
updateChat,
|
updateChat,
|
||||||
setLockChat,
|
setLockChat,
|
||||||
}: chatMessagePropsType): JSX.Element {
|
}: chatMessagePropsType): JSX.Element {
|
||||||
|
const [showFile, setShowFile] = useState<boolean>(true);
|
||||||
const convert = new Convert({ newline: true });
|
const convert = new Convert({ newline: true });
|
||||||
const [hidden, setHidden] = useState(true);
|
const [hidden, setHidden] = useState(true);
|
||||||
const template = chat.template;
|
const template = chat.template;
|
||||||
|
|
@ -291,7 +294,7 @@ dark:prose-invert"
|
||||||
parts.push(
|
parts.push(
|
||||||
<span className="chat-message-highlight">
|
<span className="chat-message-highlight">
|
||||||
{chat.message[match[1]]}
|
{chat.message[match[1]]}
|
||||||
</span>
|
</span>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -308,6 +311,7 @@ dark:prose-invert"
|
||||||
</span>
|
</span>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
<div className="flex flex-col">
|
||||||
<span
|
<span
|
||||||
className="prose text-primary word-break-break-word dark:prose-invert"
|
className="prose text-primary word-break-break-word dark:prose-invert"
|
||||||
data-testid={
|
data-testid={
|
||||||
|
|
@ -316,17 +320,22 @@ dark:prose-invert"
|
||||||
>
|
>
|
||||||
{chatMessage}
|
{chatMessage}
|
||||||
</span>
|
</span>
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div id={lastMessage ? "last-chat-message" : ""}></div>
|
|
||||||
{chat.files && (
|
{chat.files && (
|
||||||
<div className="my-2 w-full">
|
<div className="my-2">
|
||||||
{chat.files.map((file, index) => {
|
{chat.files.map((file, index) => {
|
||||||
return (
|
return (
|
||||||
<div key={index} className="my-2 w-full">
|
<div key={index} className="flex flex-col gap-2">
|
||||||
|
<span
|
||||||
|
onClick={() => setShowFile(!showFile)}
|
||||||
|
className="flex cursor-pointer gap-2 text-sm text-muted-foreground"
|
||||||
|
>
|
||||||
|
{file.name}
|
||||||
|
<ForwardedIconComponent
|
||||||
|
name={showFile ? "ChevronDown" : "ChevronRight"}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
<FileCard
|
<FileCard
|
||||||
|
showFile={showFile}
|
||||||
fileName={file.name}
|
fileName={file.name}
|
||||||
fileType={file.type}
|
fileType={file.type}
|
||||||
content={file.path}
|
content={file.path}
|
||||||
|
|
@ -336,6 +345,12 @@ dark:prose-invert"
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div id={lastMessage ? "last-chat-message" : ""}></div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
import * as base64js from "base64-js";
|
import * as base64js from "base64-js";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import IconComponent from "../../../../../components/genericIconComponent";
|
import IconComponent, {
|
||||||
|
ForwardedIconComponent,
|
||||||
|
} from "../../../../../components/genericIconComponent";
|
||||||
import { fileCardPropsType } from "../../../../../types/components";
|
import { fileCardPropsType } from "../../../../../types/components";
|
||||||
import useFlowsManagerStore from "../../../../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../../../../stores/flowsManagerStore";
|
||||||
import { BACKEND_URL, BASE_URL_API } from "../../../../../constants/constants";
|
import { BACKEND_URL, BASE_URL_API } from "../../../../../constants/constants";
|
||||||
|
import formatFileName from "../filePreviewChat/utils/format-file-name";
|
||||||
|
|
||||||
const imgTypes = new Set(["png", "jpg"]);
|
const imgTypes = new Set(["png", "jpg"]);
|
||||||
|
|
||||||
|
|
@ -11,10 +14,9 @@ export default function FileCard({
|
||||||
fileName,
|
fileName,
|
||||||
content,
|
content,
|
||||||
fileType,
|
fileType,
|
||||||
}: fileCardPropsType): JSX.Element {
|
showFile = true,
|
||||||
const handleDownload = (): void => {
|
}: fileCardPropsType): JSX.Element | undefined {
|
||||||
//TODO: update download function
|
const handleDownload = (): void => {};
|
||||||
};
|
|
||||||
const [isHovered, setIsHovered] = useState(false);
|
const [isHovered, setIsHovered] = useState(false);
|
||||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||||
function handleMouseEnter(): void {
|
function handleMouseEnter(): void {
|
||||||
|
|
@ -24,22 +26,29 @@ export default function FileCard({
|
||||||
setIsHovered(false);
|
setIsHovered(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const imgSrc = `${BACKEND_URL.slice(0, BACKEND_URL.length - 1)}${BASE_URL_API}files/images/${content}`;
|
||||||
|
|
||||||
|
if (showFile) {
|
||||||
if (imgTypes.has(fileType)) {
|
if (imgTypes.has(fileType)) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative ml-20 h-auto w-auto border border-border"
|
className="inline-block w-full rounded-lg transition-all"
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
|
style={{ display: "inline-block" }}
|
||||||
>
|
>
|
||||||
|
<div className="relative w-[80%] rounded-lg border border-border">
|
||||||
<img
|
<img
|
||||||
src={`${BACKEND_URL.slice(0, BACKEND_URL.length - 1)}${BASE_URL_API}files/images/${content}`}
|
src={imgSrc}
|
||||||
alt="generated image"
|
alt="generated image"
|
||||||
className="h-auto w-auto rounded-lg border border-border"
|
className="m-0 h-auto w-auto rounded-lg border border-border p-0 transition-all"
|
||||||
/>
|
/>
|
||||||
{isHovered && (
|
{isHovered && (
|
||||||
<div className={`file-card-modal-image-div `}>
|
<div
|
||||||
|
className={`absolute right-0 top-0 rounded-bl-lg bg-muted px-1 text-sm font-bold text-foreground `}
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
className="file-card-modal-image-button "
|
className="px-2 py-1 text-ring "
|
||||||
onClick={handleDownload}
|
onClick={handleDownload}
|
||||||
>
|
>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
|
|
@ -50,32 +59,30 @@ export default function FileCard({
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button onClick={handleDownload} className="file-card-modal-button">
|
<div
|
||||||
<div className="file-card-modal-div">
|
className={`relative ${false ? "h-20 w-20" : "h-20 w-80"} cursor-pointer rounded-lg border border-ring bg-muted shadow transition duration-300 hover:drop-shadow-lg ${
|
||||||
{" "}
|
isHovered ? "shadow-md" : ""
|
||||||
{imgTypes.has(fileType) ? (
|
}`}
|
||||||
<img
|
onClick={handleDownload}
|
||||||
src={`${BACKEND_URL.slice(0, BACKEND_URL.length - 1)}${BASE_URL_API}files/images/${content}`}
|
>
|
||||||
alt=""
|
<div className="ml-3 flex h-full w-full items-center gap-2 text-sm">
|
||||||
className="h-8 w-8"
|
<ForwardedIconComponent name="File" className="h-8 w-8" />
|
||||||
/>
|
<div className="flex flex-col">
|
||||||
) : (
|
<span className="font-bold">{formatFileName(fileName, 20)}</span>
|
||||||
<IconComponent name="File" className="h-8 w-8" />
|
<span>File</span>
|
||||||
)}
|
</div>
|
||||||
<div className="file-card-modal-footer">
|
|
||||||
{" "}
|
|
||||||
<div className="file-card-modal-name">{fileName}</div>
|
|
||||||
<div className="file-card-modal-type">{fileType}</div>
|
|
||||||
</div>
|
</div>
|
||||||
<IconComponent
|
<IconComponent
|
||||||
name="DownloadCloud"
|
name="DownloadCloud"
|
||||||
className="ml-auto h-6 w-6 text-current"
|
className="absolute right-2 top-2 ml-auto h-6 w-6 text-current"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
export default function formatFileName(name: string): string {
|
export default function formatFileName(
|
||||||
|
name: string,
|
||||||
|
numberToTruncate: number = 29,
|
||||||
|
): string {
|
||||||
const fileExtension = name.split(".").pop(); // Get the file extension
|
const fileExtension = name.split(".").pop(); // Get the file extension
|
||||||
const baseName = name.slice(0, name.lastIndexOf(".")); // Get the base name without the extension
|
const baseName = name.slice(0, name.lastIndexOf(".")); // Get the base name without the extension
|
||||||
if (baseName.length > 6) {
|
if (baseName.length > 6) {
|
||||||
return `${baseName.slice(0, 29)}...${fileExtension}`;
|
return `${baseName.slice(0, numberToTruncate)}...${fileExtension}`;
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -523,6 +523,7 @@ export type fileCardPropsType = {
|
||||||
fileName: string;
|
fileName: string;
|
||||||
content: string;
|
content: string;
|
||||||
fileType: string;
|
fileType: string;
|
||||||
|
showFile?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type nodeToolbarPropsType = {
|
export type nodeToolbarPropsType = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue