🚀 feat(chatComponent): add build trigger component to allow users to build a flow
✨ feat(chatComponent): add loading animation to build trigger component
The BuildTrigger component is added to the chatComponent to allow users to build a flow. The component is triggered by clicking on a button and sends a POST request to the server to build the flow. A loading animation is added to the component to indicate that the flow is being built. The postBuild function is added to the API controller to handle the POST request.
This commit is contained in:
parent
2c0a9aee95
commit
f88b14f33d
3 changed files with 128 additions and 0 deletions
|
|
@ -0,0 +1,85 @@
|
|||
import { useState, useContext } from "react";
|
||||
import { Transition } from "@headlessui/react";
|
||||
import { Bars3CenterLeftIcon } from "@heroicons/react/24/outline";
|
||||
import { Zap } from "lucide-react";
|
||||
import { nodeColors } from "../../../utils";
|
||||
import { PopUpContext } from "../../../contexts/popUpContext";
|
||||
import ChatModal from "../../../modals/chatModal";
|
||||
import { FlowType } from "../../../types/flow";
|
||||
import { postBuild } from "../../../controllers/API";
|
||||
import Loading from "../../../components/ui/loading";
|
||||
|
||||
export default function BuildTrigger({
|
||||
open,
|
||||
flow,
|
||||
setIsBuilt,
|
||||
isBuilt,
|
||||
}: {
|
||||
open: boolean;
|
||||
flow: FlowType;
|
||||
setIsBuilt: any;
|
||||
isBuilt: boolean;
|
||||
}) {
|
||||
const [isBuilding, setIsBuilding] = useState(false);
|
||||
|
||||
function handleBuild(flow: FlowType) {
|
||||
const minimumLoadingTime = 500; // in milliseconds
|
||||
const startTime = Date.now();
|
||||
|
||||
setIsBuilding(true);
|
||||
|
||||
postBuild(flow)
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
setIsBuilt(true);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
setIsBuilt(false);
|
||||
})
|
||||
.finally(() => {
|
||||
const endTime = Date.now();
|
||||
const elapsedTime = endTime - startTime;
|
||||
|
||||
if (elapsedTime < minimumLoadingTime) {
|
||||
const remainingTime = minimumLoadingTime - elapsedTime;
|
||||
setTimeout(() => {
|
||||
setIsBuilding(false);
|
||||
}, remainingTime);
|
||||
} else {
|
||||
setIsBuilding(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Transition
|
||||
show={!open}
|
||||
appear={true}
|
||||
enter="transition ease-out duration-300"
|
||||
enterFrom="translate-y-96"
|
||||
enterTo="translate-y-0"
|
||||
leave="transition ease-in duration-300"
|
||||
leaveFrom="translate-y-0"
|
||||
leaveTo="translate-y-96"
|
||||
>
|
||||
<div className={`fixed right-4` + (isBuilt ? " bottom-20" : " bottom-4")}>
|
||||
<div
|
||||
className="border flex justify-center align-center py-1 px-3 w-12 h-12 rounded-full bg-gradient-to-r from-blue-700 via-blue-600 to-blue-500 dark:border-gray-600 cursor-pointer"
|
||||
onClick={() => handleBuild(flow)}
|
||||
>
|
||||
<button>
|
||||
<div className="flex gap-3 items-center">
|
||||
{isBuilding ? (
|
||||
// Render your loading animation here when isBuilding is true
|
||||
<Loading style={{ color: "white" }} />
|
||||
) : (
|
||||
<Zap className="h-6 w-6" style={{ color: "white" }} />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
);
|
||||
}
|
||||
39
src/frontend/src/components/ui/loading.tsx
Normal file
39
src/frontend/src/components/ui/loading.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import * as React from "react";
|
||||
import { SVGProps } from "react";
|
||||
|
||||
export const Loading = (props: SVGProps<SVGSVGElement>) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
className="feather feather-circle"
|
||||
{...props}
|
||||
>
|
||||
<circle cx={12} cy={12} r={10} strokeDasharray={63} strokeDashoffset={21}>
|
||||
<animateTransform
|
||||
attributeName="transform"
|
||||
type="rotate"
|
||||
from="0 12 12"
|
||||
to="360 12 12"
|
||||
dur="2s"
|
||||
repeatCount="indefinite"
|
||||
/>
|
||||
<animate
|
||||
attributeName="stroke-dashoffset"
|
||||
dur="8s"
|
||||
repeatCount="indefinite"
|
||||
keyTimes="0; 0.5; 1"
|
||||
values="-16; -47; -16"
|
||||
calcMode="spline"
|
||||
keySplines="0.4 0 0.2 1; 0.4 0 0.2 1"
|
||||
/>
|
||||
</circle>
|
||||
</svg>
|
||||
);
|
||||
export default Loading;
|
||||
|
|
@ -39,3 +39,7 @@ export async function getExamples(): Promise<FlowType[]> {
|
|||
|
||||
return await Promise.all(contentsPromises);
|
||||
}
|
||||
|
||||
export async function postBuild(flow: FlowType) {
|
||||
return await axios.post(`/build/${flow.id}`, flow);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue