Adding progress bar on build

This commit is contained in:
Cristhian Zanforlin Lousa 2023-06-19 22:45:55 -03:00
commit 625f22c024
10 changed files with 4733 additions and 7420 deletions

File diff suppressed because it is too large Load diff

View file

@ -8,15 +8,16 @@
"@headlessui/react": "^1.7.10", "@headlessui/react": "^1.7.10",
"@heroicons/react": "^2.0.15", "@heroicons/react": "^2.0.15",
"@mui/material": "^5.11.9", "@mui/material": "^5.11.9",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-menubar": "^1.0.3",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-label": "^2.0.2", "@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-menubar": "^1.0.3",
"@radix-ui/react-progress": "^1.0.3",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-tooltip": "^1.0.6", "@radix-ui/react-tooltip": "^1.0.6",
"@tabler/icons-react": "^2.18.0", "@tabler/icons-react": "^2.18.0",
"@tailwindcss/forms": "^0.5.3", "@tailwindcss/forms": "^0.5.3",

View file

@ -0,0 +1,21 @@
import { ReactElement, useContext, useEffect, useRef, useState } from "react";
import { ProgressBarType } from "../../types/components";
import { Progress } from "../../components/ui/progress";
import { progressContext } from "../../contexts/ProgressContext";
import { setInterval } from "timers/promises";
export default function ProgressBarComponent({
value,
children,
}: ProgressBarType) {
const ref = useRef(0);
const reff = useRef();
const { progress } = useContext(progressContext);
useEffect(() => {
ref.current = progress * 100;
console.log(progress);
}, [progress]);
return <Progress className="h-2.5" value={ref.current} />;
}

View file

@ -1,4 +1,4 @@
import { useContext } from "react"; import { useContext, useEffect, useRef, useState } from "react";
import { Transition } from "@headlessui/react"; import { Transition } from "@headlessui/react";
import { Zap } from "lucide-react"; import { Zap } from "lucide-react";
import { validateNodes } from "../../../utils"; import { validateNodes } from "../../../utils";
@ -8,6 +8,11 @@ import { useSSE } from "../../../contexts/SSEContext";
import { typesContext } from "../../../contexts/typesContext"; import { typesContext } from "../../../contexts/typesContext";
import { alertContext } from "../../../contexts/alertContext"; import { alertContext } from "../../../contexts/alertContext";
import { postBuildInit } from "../../../controllers/API"; import { postBuildInit } from "../../../controllers/API";
import ProgressBarComponent from "../../ProgressBarComponent";
import {
progressContext,
useProgress,
} from "../../../contexts/ProgressContext";
export default function BuildTrigger({ export default function BuildTrigger({
open, open,
@ -20,9 +25,11 @@ export default function BuildTrigger({
setIsBuilt: any; setIsBuilt: any;
isBuilt: boolean; isBuilt: boolean;
}) { }) {
const { updateSSEData, isBuilding, setIsBuilding } = useSSE(); const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE();
const { setProgress } = useContext(progressContext);
const { reactFlowInstance } = useContext(typesContext); const { reactFlowInstance } = useContext(typesContext);
const { setErrorData, setSuccessData } = useContext(alertContext); const { setErrorData, setSuccessData } = useContext(alertContext);
const [isIconTouched, setIsIconTouched] = useState(false);
async function handleBuild(flow: FlowType) { async function handleBuild(flow: FlowType) {
try { try {
@ -63,7 +70,7 @@ export default function BuildTrigger({
// Step 1: Make a POST request to send the flow data and receive a unique session ID // Step 1: Make a POST request to send the flow data and receive a unique session ID
const response = await postBuildInit(flow); const response = await postBuildInit(flow);
const { flowId } = response.data; const { flowId } = response.data;
let loadProgress = [];
// Step 2: Use the session ID to establish an SSE connection using EventSource // Step 2: Use the session ID to establish an SSE connection using EventSource
let validationResults = []; let validationResults = [];
let finished = false; let finished = false;
@ -79,13 +86,15 @@ export default function BuildTrigger({
// if the event is the end of the stream, close the connection // if the event is the end of the stream, close the connection
if (parsedData.end_of_stream) { if (parsedData.end_of_stream) {
eventSource.close(); eventSource.close();
return; return;
} else if (parsedData.log) { } else if (parsedData.log) {
// If the event is a log, log it // If the event is a log, log it
// TODO: implement the progress // TODO: implement the progress
setSuccessData({ title: parsedData.log }); setSuccessData({ title: parsedData.log });
setSuccessData({ title: parsedData.progress }); setSuccessData({ title: parsedData.progress });
setProgress(parsedData.progress);
loadProgress.push(parsedData.progress);
} else { } else {
// Otherwise, process the data // Otherwise, process the data
const isValid = processStreamResult(parsedData); const isValid = processStreamResult(parsedData);
@ -129,6 +138,14 @@ export default function BuildTrigger({
} }
} }
const handleMouseEnter = () => {
setIsIconTouched(true);
};
const handleMouseLeave = () => {
setIsIconTouched(false);
};
return ( return (
<Transition <Transition
show={!open} show={!open}
@ -141,12 +158,20 @@ export default function BuildTrigger({
leaveTo="translate-y-96" leaveTo="translate-y-96"
> >
<div className={`fixed right-4` + (isBuilt ? " bottom-20" : " bottom-4")}> <div className={`fixed right-4` + (isBuilt ? " bottom-20" : " bottom-4")}>
<div className="mb-2">
{isIconTouched && isBuilding && (
<ProgressBarComponent></ProgressBarComponent>
)}
</div>
<div <div
className="flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full shadow-md shadow-[#0000002a] hover:shadow-[#00000032] className="flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full shadow-md shadow-[#0000002a] hover:shadow-[#00000032]
bg-[#E2E7EE] dark:border-gray-600 cursor-pointer" bg-[#E2E7EE] dark:border-gray-600 cursor-pointer"
onClick={() => { onClick={() => {
handleBuild(flow); handleBuild(flow);
}} }}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
> >
<button> <button>
<div className="flex gap-3 items-center"> <div className="flex gap-3 items-center">

View file

@ -69,34 +69,34 @@ export default function Header() {
</div> </div>
<div className="flex justify-end px-2 w-96"> <div className="flex justify-end px-2 w-96">
<div className="ml-auto mr-2 flex gap-5 items-center"> <div className="ml-auto mr-2 flex gap-5 items-center">
<a <a
href="https://github.com/logspace-ai/langflow" href="https://github.com/logspace-ai/langflow"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-gray-600 dark:text-gray-300 border border-input hover:bg-accent hover:text-accent-foreground h-9 px-3 pr-0 rounded-md" className="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background text-gray-600 dark:text-gray-300 border border-input hover:bg-accent hover:text-accent-foreground h-9 px-3 pr-0 rounded-md"
> >
<FaGithub className="h-5 w-5 mr-2" /> <FaGithub className="h-5 w-5 mr-2" />
Star Star
<div className="ml-2 flex text-sm bg-background rounded-md rounded-l-none border px-2 h-9 -mr-px items-center justify-center"> <div className="ml-2 flex text-sm bg-background rounded-md rounded-l-none border px-2 h-9 -mr-px items-center justify-center">
{stars} {stars}
</div> </div>
</a> </a>
<a <a
href="https://twitter.com/logspace_ai" href="https://twitter.com/logspace_ai"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="text-muted-foreground" className="text-muted-foreground"
> >
<FaTwitter className="h-5 w-5" /> <FaTwitter className="h-5 w-5" />
</a> </a>
<a <a
href="https://discord.gg/EqksyE2EX9" href="https://discord.gg/EqksyE2EX9"
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
className="text-muted-foreground" className="text-muted-foreground"
> >
<FaDiscord className="h-5 w-5" /> <FaDiscord className="h-5 w-5" />
</a> </a>
{/* <button {/* <button
className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200" className="text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
onClick={() => { onClick={() => {

View file

@ -0,0 +1,27 @@
"use client";
import * as React from "react";
import * as ProgressPrimitive from "@radix-ui/react-progress";
import { cn } from "../../utils";
const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
>(({ className, value, ...props }, ref) => (
<ProgressPrimitive.Root
ref={ref}
className={cn(
"relative h-4 w-full overflow-hidden rounded-full bg-secondary",
className
)}
{...props}
>
<ProgressPrimitive.Indicator
className="h-full w-full flex-1 bg-primary transition-all"
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
/>
</ProgressPrimitive.Root>
));
Progress.displayName = ProgressPrimitive.Root.displayName;
export { Progress };

View file

@ -0,0 +1,30 @@
import { createContext, useContext, useState } from "react";
import _ from "lodash";
//types for progressContext
type progressContextType = {
setProgress: (newState: number) => void;
progress: number;
};
const initialValue = {
setProgress: () => {},
progress: 0,
};
export const progressContext = createContext<progressContextType>(initialValue);
export function useProgress() {
return useContext(progressContext);
}
export function ProgressProvider({ children }) {
const [progress, setProgress] = useState(0);
return (
<progressContext.Provider
value={{
setProgress,
progress,
}}
>
{children}
</progressContext.Provider>
);
}

View file

@ -8,6 +8,7 @@ import { TypesProvider } from "./typesContext";
import { ReactFlowProvider } from "reactflow"; import { ReactFlowProvider } from "reactflow";
import { UndoRedoProvider } from "./undoRedoContext"; import { UndoRedoProvider } from "./undoRedoContext";
import { SSEProvider } from "./SSEContext"; import { SSEProvider } from "./SSEContext";
import { ProgressProvider } from "./ProgressContext";
export default function ContextWrapper({ children }: { children: ReactNode }) { export default function ContextWrapper({ children }: { children: ReactNode }) {
//element to wrap all context //element to wrap all context
@ -21,7 +22,9 @@ export default function ContextWrapper({ children }: { children: ReactNode }) {
<SSEProvider> <SSEProvider>
<TabsProvider> <TabsProvider>
<UndoRedoProvider> <UndoRedoProvider>
<PopUpProvider>{children}</PopUpProvider> <ProgressProvider>
<PopUpProvider>{children}</PopUpProvider>
</ProgressProvider>
</UndoRedoProvider> </UndoRedoProvider>
</TabsProvider> </TabsProvider>
</SSEProvider> </SSEProvider>

View file

@ -22,7 +22,9 @@ const GITHUB_API_URL = "https://api.github.com";
export async function getRepoStars(owner, repo) { export async function getRepoStars(owner, repo) {
try { try {
const response = await axios.get(`${GITHUB_API_URL}/repos/${owner}/${repo}`); const response = await axios.get(
`${GITHUB_API_URL}/repos/${owner}/${repo}`
);
return response.data.stargazers_count; return response.data.stargazers_count;
} catch (error) { } catch (error) {
console.error("Error fetching repository data:", error); console.error("Error fetching repository data:", error);

View file

@ -98,3 +98,9 @@ export type TooltipComponentType = {
| "top-start" | "top-start"
| "top"; | "top";
}; };
export type ProgressBarType = {
children?: ReactElement;
value?: number;
max?: number;
};