From 2d635f3f8ebd79043e6b8250c5cdbdd4efa4ec6d Mon Sep 17 00:00:00 2001 From: BFlat Date: Wed, 9 Apr 2025 01:45:43 +0700 Subject: [PATCH] added activity with dummy polling and image lightbox modal + other cleanup (#487) --- frontend/editor2d/package-lock.json | 77 +++------ frontend/editor2d/package.json | 12 +- .../RenderingPrimitives/RealTimeDrawEngine.ts | 2 +- .../editor2d/src/components/PromptBox.tsx | 106 ++---------- .../features/ToolbarTopRight/index.tsx | 39 +---- .../components/reusable/Popover/Popover.tsx | 15 +- .../reusable/ToggleButton/ToggleButton.tsx | 2 +- .../src/components/ui/Activity/Activity.tsx | 154 ++++++++++++++++++ .../components/ui/Activity/CompletedCard.tsx | 89 ++++++++++ .../components/ui/Activity/InProgressCard.tsx | 78 +++++++++ .../src/components/ui/Activity/index.ts | 1 + .../editor2d/src/components/ui/BaseDialog.tsx | 2 +- 12 files changed, 381 insertions(+), 196 deletions(-) create mode 100644 frontend/editor2d/src/components/ui/Activity/Activity.tsx create mode 100644 frontend/editor2d/src/components/ui/Activity/CompletedCard.tsx create mode 100644 frontend/editor2d/src/components/ui/Activity/InProgressCard.tsx create mode 100644 frontend/editor2d/src/components/ui/Activity/index.ts diff --git a/frontend/editor2d/package-lock.json b/frontend/editor2d/package-lock.json index 64aacf04c9..04afbd280c 100644 --- a/frontend/editor2d/package-lock.json +++ b/frontend/editor2d/package-lock.json @@ -9,13 +9,17 @@ "version": "0.0.0", "dependencies": { "@devnomic/marquee": "^1.0.3", - "@fortawesome/free-brands-svg-icons": "^6.6.0", + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/pro-regular-svg-icons": "^6.7.2", + "@fortawesome/pro-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", "@headlessui/react": "^2.1.3", "@preact/signals-react": "^2.2.0", "@tauri-apps/api": "^2.2.0", "@techstark/opencv-js": "^4.10.0-release.1", "@zip.js/zip.js": "^2.7.52", + "dayjs": "^1.11.13", "fortawesome": "^0.0.1-security", "konva": "^9.3.14", "onnxruntime-web": "^1.19.2", @@ -28,14 +32,10 @@ "react-router-dom": "^6.26.1", "sonner": "^2.0.1", "tailwind-merge": "^2.5.2", - "uuid": "^10.0.0", - "yarn": "^1.22.22" + "uuid": "^10.0.0" }, "devDependencies": { "@eslint/js": "^9.9.0", - "@fortawesome/fontawesome-svg-core": "^6.6.0", - "@fortawesome/pro-solid-svg-icons": "^6.7.2", - "@fortawesome/react-fontawesome": "^0.2.2", "@preact/signals-react-transform": "^0.4.0", "@tauri-apps/cli": "^2.4.0", "@types/deep-equal": "^1.0.4", @@ -590,33 +590,30 @@ "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.6.0", - "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/6.6.0/fontawesome-common-types-6.6.0.tgz", - "integrity": "sha512-xyX0X9mc0kyz9plIyryrRbl7ngsA9jz77mCZJsUkLl+ZKs0KWObgaEBoSgQiYWAsSmjz/yjl0F++Got0Mdp4Rw==", - "license": "MIT", + "version": "6.7.2", + "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/6.7.2/fontawesome-common-types-6.7.2.tgz", + "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==", "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.6.0", - "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-svg-core/-/6.6.0/fontawesome-svg-core-6.6.0.tgz", - "integrity": "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg==", - "dev": true, - "license": "MIT", + "version": "6.7.2", + "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-svg-core/-/6.7.2/fontawesome-svg-core-6.7.2.tgz", + "integrity": "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA==", "dependencies": { - "@fortawesome/fontawesome-common-types": "6.6.0" + "@fortawesome/fontawesome-common-types": "6.7.2" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "6.6.0", - "resolved": "https://npm.fontawesome.com/@fortawesome/free-brands-svg-icons/-/6.6.0/free-brands-svg-icons-6.6.0.tgz", - "integrity": "sha512-1MPD8lMNW/earme4OQi1IFHtmHUwAKgghXlNwWi9GO7QkTfD+IIaYpIai4m2YJEzqfEji3jFHX1DZI5pbY/biQ==", + "version": "6.7.2", + "resolved": "https://npm.fontawesome.com/@fortawesome/free-brands-svg-icons/-/6.7.2/free-brands-svg-icons-6.7.2.tgz", + "integrity": "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q==", "dependencies": { - "@fortawesome/fontawesome-common-types": "6.6.0" + "@fortawesome/fontawesome-common-types": "6.7.2" }, "engines": { "node": ">=6" @@ -634,20 +631,10 @@ "node": ">=6" } }, - "node_modules/@fortawesome/pro-regular-svg-icons/node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.7.2", - "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/6.7.2/fontawesome-common-types-6.7.2.tgz", - "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/@fortawesome/pro-solid-svg-icons": { "version": "6.7.2", "resolved": "https://npm.fontawesome.com/@fortawesome/pro-solid-svg-icons/-/6.7.2/pro-solid-svg-icons-6.7.2.tgz", "integrity": "sha512-SY2aP8d7uBlg1rNYznA9w9SVnnQhu3x/C7CCKQYcOGOC1YtPPHgIJhxKGbSzm6RkeJs1HVEfAkORX3J0XB5K9Q==", - "dev": true, "license": "UNLICENSED", "dependencies": { "@fortawesome/fontawesome-common-types": "6.7.2" @@ -656,22 +643,10 @@ "node": ">=6" } }, - "node_modules/@fortawesome/pro-solid-svg-icons/node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.7.2", - "resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-common-types/-/6.7.2/fontawesome-common-types-6.7.2.tgz", - "integrity": "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/@fortawesome/react-fontawesome": { "version": "0.2.2", "resolved": "https://npm.fontawesome.com/@fortawesome/react-fontawesome/-/0.2.2/react-fontawesome-0.2.2.tgz", "integrity": "sha512-EnkrprPNqI6SXJl//m29hpaNzOp1bruISWaOiRtkMi/xSvHJlzc2j2JAYS7egxt/EbjSNV/k6Xy0AQI6vB2+1g==", - "dev": true, - "license": "MIT", "dependencies": { "prop-types": "^15.8.1" }, @@ -2470,6 +2445,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" + }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", @@ -9358,19 +9338,6 @@ "node": ">= 14" } }, - "node_modules/yarn": { - "version": "1.22.22", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.22.tgz", - "integrity": "sha512-prL3kGtyG7o9Z9Sv8IPfBNrWTDmXB4Qbes8A9rEzt6wkJV8mUvoirjU0Mp3GGAU06Y0XQyA3/2/RQFVuK7MTfg==", - "hasInstallScript": true, - "bin": { - "yarn": "bin/yarn.js", - "yarnpkg": "bin/yarn.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/frontend/editor2d/package.json b/frontend/editor2d/package.json index 6be778181d..97cc0adbd1 100644 --- a/frontend/editor2d/package.json +++ b/frontend/editor2d/package.json @@ -12,13 +12,17 @@ }, "dependencies": { "@devnomic/marquee": "^1.0.3", - "@fortawesome/free-brands-svg-icons": "^6.6.0", + "@fortawesome/fontawesome-svg-core": "^6.7.2", + "@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/pro-regular-svg-icons": "^6.7.2", + "@fortawesome/pro-solid-svg-icons": "^6.7.2", + "@fortawesome/react-fontawesome": "^0.2.2", "@headlessui/react": "^2.1.3", "@preact/signals-react": "^2.2.0", "@tauri-apps/api": "^2.2.0", "@techstark/opencv-js": "^4.10.0-release.1", "@zip.js/zip.js": "^2.7.52", + "dayjs": "^1.11.13", "fortawesome": "^0.0.1-security", "konva": "^9.3.14", "onnxruntime-web": "^1.19.2", @@ -31,14 +35,10 @@ "react-router-dom": "^6.26.1", "sonner": "^2.0.1", "tailwind-merge": "^2.5.2", - "uuid": "^10.0.0", - "yarn": "^1.22.22" + "uuid": "^10.0.0" }, "devDependencies": { "@eslint/js": "^9.9.0", - "@fortawesome/fontawesome-svg-core": "^6.6.0", - "@fortawesome/pro-solid-svg-icons": "^6.7.2", - "@fortawesome/react-fontawesome": "^0.2.2", "@preact/signals-react-transform": "^0.4.0", "@tauri-apps/cli": "^2.4.0", "@types/deep-equal": "^1.0.4", diff --git a/frontend/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts b/frontend/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts index 501bc3993e..95707cf6b5 100644 --- a/frontend/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts +++ b/frontend/editor2d/src/KonvaApp/RenderingPrimitives/RealTimeDrawEngine.ts @@ -790,7 +790,7 @@ export class RealTimeDrawEngine { const base64Bitmap = await this.imageBitmapToBase64( this.lastRenderedBitmap, ); - + const generateResponse = await invoke("image_generation_command", { image: base64Bitmap, prompt: this.currentPrompt, diff --git a/frontend/editor2d/src/components/PromptBox.tsx b/frontend/editor2d/src/components/PromptBox.tsx index 1826ae1c4e..732292edca 100644 --- a/frontend/editor2d/src/components/PromptBox.tsx +++ b/frontend/editor2d/src/components/PromptBox.tsx @@ -3,7 +3,7 @@ import { invoke } from "@tauri-apps/api/core"; import { useSignals } from "@preact/signals-react/runtime"; import { UploaderStates, - UploaderState, + // UploaderState, uploadImage, } from "~/components/UploadImage"; @@ -13,11 +13,8 @@ import { Button } from "~/components/reusable/Button"; import { ToggleButton } from "~/components/reusable/ToggleButton"; import { - faCamera, faMessageXmark, faMessageCheck, - faDownload, - faSave, faSparkles, faSpinnerThird, faTimes, @@ -31,11 +28,10 @@ import { faSquare, faRectangle, } from "@fortawesome/pro-regular-svg-icons"; - -import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { PopoverItem } from "~/components/reusable/Popover"; import { getCanvasRenderBitmap } from "~/signal/canvasRenderBitmap"; import { EncodeImageBitmapToBase64 } from "~/utilities/EncodeImageBitmapToBase64"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { PopoverItem } from "~/components/reusable/Popover"; interface ReferenceImage { id: string; @@ -44,11 +40,6 @@ interface ReferenceImage { mediaToken: string; } -interface ExtendedPopoverItem extends PopoverItem { - id: string; - focalLength: number; -} - export const PromptBox = () => { useSignals(); //const { lastRenderedBitmap } = useCanvasSignal(); @@ -60,7 +51,6 @@ export const PromptBox = () => { const [uploadingImages, setUploadingImages] = useState< { id: string; file: File }[] >([]); - const [isCameraSettingsOpen, setIsCameraSettingsOpen] = useState(false); const [aspectRatioList, setAspectRatioList] = useState([ { label: "3:2", @@ -83,22 +73,6 @@ export const PromptBox = () => { icon: , }, ]); - const [cameraList, setCameraList] = useState([ - { - id: "main", - label: "Main View", - selected: true, - icon: , - focalLength: 35, - }, - { - id: "cam2", - label: "Camera 2", - selected: false, - icon: , - focalLength: 35, - }, - ]); const fileInputRef = useRef(null); const textareaRef = useRef(null); @@ -110,41 +84,6 @@ export const PromptBox = () => { } }, [prompt]); - // Update aspect ratio list based on the current cameraAspectRatio signal - useEffect(() => { - setAspectRatioList((prev) => prev); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const handleCameraSelect = (selectedItem: PopoverItem) => {}; - - const handleAddCamera = () => { - const newIndex = cameraList.length + 1; - const newId = `cam${newIndex}`; - setCameraList((prev) => [ - ...prev, - { - id: newId, - label: `Camera ${newIndex}`, - selected: false, - icon: , - focalLength: 35, - }, - ]); - }; - - const handleCameraNameChange = (id: string, newName: string) => { - setCameraList((prev) => - prev.map((cam) => (cam.id === id ? { ...cam, label: newName } : cam)), - ); - }; - - const handleCameraFocalLengthChange = (id: string, value: number) => { - setCameraList((prev) => - prev.map((cam) => (cam.id === id ? { ...cam, focalLength: value } : cam)), - ); - }; - const handleAspectRatioSelect = (selectedItem: PopoverItem) => { setAspectRatioList((prev) => prev.map((item) => ({ @@ -152,15 +91,6 @@ export const PromptBox = () => { selected: item.label === selectedItem.label, })), ); - - // Map the selected label to the corresponding CameraAspectRatio enum value - - // Publish the change to the engine - // Queue.publish({ - // queueName: QueueNames.TO_ENGINE, - // action: toEngineActions.CHANGE_CAMERA_ASPECT_RATIO, - // data: newRatio, - // }); }; const handleFileUpload = (event: React.ChangeEvent) => { @@ -251,7 +181,6 @@ export const PromptBox = () => { setisEnqueueing(true); try { - // Here we would pass both the prompt and reference images to the generation console.log( "Enqueuing with prompt:", prompt, @@ -278,12 +207,16 @@ export const PromptBox = () => { } }; - // Get the current aspect ratio icon based on the cameraAspectRatio signal - const getCurrentAspectRatioIcon = () => {}; + const getCurrentAspectRatioIcon = () => { + const selected = aspectRatioList.find((item) => item.selected); + if (!selected || !selected.icon) return faRectangle; + const iconElement = selected.icon as React.ReactElement; + return iconElement.props.icon; + }; - const handleSaveFrame = async () => {}; + // const handleSaveFrame = async () => {}; - const handleDownloadFrame = () => {}; + // const handleDownloadFrame = () => {}; const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { @@ -408,13 +341,6 @@ export const PromptBox = () => { } /> - {
- { icon={faDownload} onClick={handleDownloadFrame} /> - + */} - + */} +
); }; diff --git a/frontend/editor2d/src/components/reusable/Popover/Popover.tsx b/frontend/editor2d/src/components/reusable/Popover/Popover.tsx index 0e8b563d9a..5973d8907d 100644 --- a/frontend/editor2d/src/components/reusable/Popover/Popover.tsx +++ b/frontend/editor2d/src/components/reusable/Popover/Popover.tsx @@ -1,5 +1,10 @@ import { ReactNode } from "react"; -import { Popover, Transition } from "@headlessui/react"; +import { + Popover, + PopoverButton, + PopoverPanel, + Transition, +} from "@headlessui/react"; import { twMerge } from "tailwind-merge"; import { Button } from "../Button"; @@ -83,11 +88,11 @@ export const PopoverMenu = ({ {({ close }) => ( <> - + {triggerIcon} {mode === "toggle" && selectedItem ? selectedItem.label : null} {mode === "default" && triggerLabel ? triggerLabel : null} - +
- )}
- + diff --git a/frontend/editor2d/src/components/reusable/ToggleButton/ToggleButton.tsx b/frontend/editor2d/src/components/reusable/ToggleButton/ToggleButton.tsx index 2902762591..2646f77a5e 100644 --- a/frontend/editor2d/src/components/reusable/ToggleButton/ToggleButton.tsx +++ b/frontend/editor2d/src/components/reusable/ToggleButton/ToggleButton.tsx @@ -22,7 +22,7 @@ export const ToggleButton = ({ className={twMerge( "flex h-9 w-9 items-center border-2 border-transparent text-sm text-white backdrop-blur-lg transition-all", isActive - ? "bg-brand-primary/40 hover:bg-brand-primary/40 border-white/20 hover:border-white/30" + ? "border-white/20 bg-primary/40 hover:border-white/30 hover:bg-primary/40" : "bg-[#5F5F68]/60 hover:bg-[#5F5F68]/90", className, )} diff --git a/frontend/editor2d/src/components/ui/Activity/Activity.tsx b/frontend/editor2d/src/components/ui/Activity/Activity.tsx new file mode 100644 index 0000000000..59d690c819 --- /dev/null +++ b/frontend/editor2d/src/components/ui/Activity/Activity.tsx @@ -0,0 +1,154 @@ +import { useEffect, useState } from "react"; +import { faBell, faSpinnerThird } from "@fortawesome/pro-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { PopoverMenu } from "~/components/reusable/Popover"; +import { CompletedCard } from "./CompletedCard"; +import { InProgressCard } from "./InProgressCard"; + +// Dummy data types +interface CompletedItem { + token: string; + maybe_title: string; + public_bucket_path: string; + updated_at: string; +} + +interface ActiveJob { + job_token: string; + request: { + maybe_model_title: string; + }; + status: { + status: string; + progress_percentage: number; + }; +} + +// Dummy data for testing +const dummyCompletedItems: CompletedItem[] = [ + { + token: "1", + maybe_title: "Completed Item 1", + public_bucket_path: "/test1", + updated_at: new Date().toISOString(), + }, + { + token: "2", + maybe_title: "Completed Item 2", + public_bucket_path: "/test2", + updated_at: new Date().toISOString(), + }, +]; + +const dummyJobs: ActiveJob[] = [ + { + job_token: "job1", + request: { + maybe_model_title: "In Progress Job 1", + }, + status: { + status: "STARTED", + progress_percentage: 45, + }, + }, + { + job_token: "job2", + request: { + maybe_model_title: "In Progress Job 2", + }, + status: { + status: "PENDING", + progress_percentage: 0, + }, + }, +]; + +export function Activity() { + const [completedItems, setCompletedItems] = useState([]); + const [jobs, setJobs] = useState([]); + const [loading, setLoading] = useState(true); + + // Dummy polling function + useEffect(() => { + const pollData = () => { + // Simulate API calls + setCompletedItems(dummyCompletedItems); + setJobs(dummyJobs); + setLoading(false); + }; + + // Initial load + pollData(); + + // Set up polling interval (every 5 seconds) + const interval = setInterval(pollData, 5000); + + return () => clearInterval(interval); + }, []); + + return ( + + + <> + {jobs.length > 0 ? ( + + ) : ( + + )} + Activity + + + {jobs.length > 0 && ( +
+ )} +
+ } + > +
+ {/* In progress */} + {jobs.length > 0 && ( +
+ {jobs.map((job) => ( + + ))} +
+ )} + + {loading ? ( +
+ +

Retrieving Activities

+
+ ) : completedItems.length === 0 && jobs.length === 0 ? ( +
+

No activities yet

+
+ ) : ( +
+ {/* Completed */} +
+ {completedItems.map((item) => ( + + ))} +
+
+ )} +
+
+ ); +} diff --git a/frontend/editor2d/src/components/ui/Activity/CompletedCard.tsx b/frontend/editor2d/src/components/ui/Activity/CompletedCard.tsx new file mode 100644 index 0000000000..c2cdb50eea --- /dev/null +++ b/frontend/editor2d/src/components/ui/Activity/CompletedCard.tsx @@ -0,0 +1,89 @@ +import { useState } from "react"; +import dayjs from "dayjs"; +import { BaseDialog } from "../BaseDialog"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faXmark } from "@fortawesome/pro-solid-svg-icons"; + +interface Props { + job: { + token: string; + maybe_title: string; + public_bucket_path: string; + updated_at: string; + maybe_style_name?: string; + }; +} + +export function CompletedCard({ job }: Props) { + const [loadError, setLoadError] = useState(false); + const [isModalOpen, setIsModalOpen] = useState(false); + const imageUrl = job.public_bucket_path + "-thumb.gif"; + const fullImageUrl = job.public_bucket_path; + + return ( + <> +
setIsModalOpen(true)} + > +
+
+ {job.maybe_title setLoadError(true)} + loading="lazy" + /> +
+
+
{job.maybe_title || "Untitled"}
+
+ {dayjs(job.updated_at).format("MMM D, YYYY HH:mm:ss")} +
+
+
+
+ + setIsModalOpen(false)} + className="h-[80vh] w-[75vw] max-w-[75vw] p-0" + > +
+ +
+ {job.maybe_title setLoadError(true)} + /> +
+
+
+ {job.maybe_title || "Untitled"} +
+
+ Created: {dayjs(job.updated_at).format("MMM D, YYYY HH:mm:ss")} +
+ {job.maybe_style_name && ( +
+ Style: {job.maybe_style_name} +
+ )} +
+
+
+ + ); +} diff --git a/frontend/editor2d/src/components/ui/Activity/InProgressCard.tsx b/frontend/editor2d/src/components/ui/Activity/InProgressCard.tsx new file mode 100644 index 0000000000..9579161fb7 --- /dev/null +++ b/frontend/editor2d/src/components/ui/Activity/InProgressCard.tsx @@ -0,0 +1,78 @@ +import { useCallback } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faClose, + faCircleExclamation, + faSpinnerThird, +} from "@fortawesome/pro-solid-svg-icons"; + +interface Props { + job: { + job_token: string; + request: { + maybe_model_title: string; + }; + status: { + status: string; + progress_percentage: number; + }; + }; +} + +function getPercent(status: string, percentage: number) { + if (["COMPLETE_FAILURE", "ATTEMPT_FAILED", "DEAD"].includes(status)) { + return 0; + } else { + return percentage; + } +} + +export function InProgressCard({ job }: Props) { + const completePercent = getPercent( + job.status.status, + job.status.progress_percentage, + ); + + const deleteJob = useCallback(async (jobToDelete: Props["job"]) => { + // Simulate API call + console.log("Deleting job:", jobToDelete.job_token); + }, []); + + return ( +
+
+
+ {(job.status.status === "STARTED" || + job.status.status === "PENDING") && ( + + )} + {(job.status.status === "COMPLETE_FAILURE" || + job.status.status === "ATTEMPT_FAILED") && ( + + )} +
+
+
+ {job.request.maybe_model_title || "Untitled"} +
+ +
+ {job.status.status.split("_").join(" ")}... {completePercent}% +
+
+
+ + {job.status.status !== "STARTED" && ( +
+ +
+ )} +
+ ); +} diff --git a/frontend/editor2d/src/components/ui/Activity/index.ts b/frontend/editor2d/src/components/ui/Activity/index.ts new file mode 100644 index 0000000000..1077f3502f --- /dev/null +++ b/frontend/editor2d/src/components/ui/Activity/index.ts @@ -0,0 +1 @@ +export { Activity } from "./Activity"; diff --git a/frontend/editor2d/src/components/ui/BaseDialog.tsx b/frontend/editor2d/src/components/ui/BaseDialog.tsx index cd9fcd644f..47a207f412 100644 --- a/frontend/editor2d/src/components/ui/BaseDialog.tsx +++ b/frontend/editor2d/src/components/ui/BaseDialog.tsx @@ -33,7 +33,7 @@ export const BaseDialog = ({ leaveFrom="opacity-100" leaveTo="opacity-0" > -