Fix modal opening bug when not supposed to (#1795)

* fix opening modal error

* Fix cleanOnClose behavior in IOModal component

* Refactor useEffect dependency in CollectionCardComponent

* remove console

* add console.log for debugging

---------

Co-authored-by: anovazzi1 <otavio2204@gmail.com>
This commit is contained in:
Cristhian Zanforlin Lousa 2024-04-30 09:39:50 -03:00 • committed by GitHub
commit 9c0ae350bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 257 additions and 246 deletions

View file

@ -1,7 +1,9 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { getComponent, postLikeComponent } from "../../controllers/API"; import { getComponent, postLikeComponent } from "../../controllers/API";
import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal"; import DeleteConfirmationModal from "../../modals/DeleteConfirmationModal";
import IOModal from "../../modals/IOModal";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import useFlowStore from "../../stores/flowStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { useStoreStore } from "../../stores/storeStore"; import { useStoreStore } from "../../stores/storeStore";
import { storeComponent } from "../../types/store"; import { storeComponent } from "../../types/store";
@ -18,11 +20,6 @@ import {
CardHeader, CardHeader,
CardTitle, CardTitle,
} from "../ui/card"; } from "../ui/card";
import IOModal from "../../modals/IOModal";
import useFlowStore from "../../stores/flowStore";
import { set } from "lodash";
import LoadingComponent from "../loadingComponent";
import { f } from "million/dist/shared/million.9d4df3c1";
import Loading from "../ui/loading"; import Loading from "../ui/loading";
export default function CollectionCardComponent({ export default function CollectionCardComponent({
@ -31,7 +28,7 @@ export default function CollectionCardComponent({
disabled = false, disabled = false,
button, button,
onDelete, onDelete,
playground playground,
}: { }: {
data: storeComponent; data: storeComponent;
authorized?: boolean; authorized?: boolean;
@ -62,25 +59,32 @@ export default function CollectionCardComponent({
const setNodes = useFlowStore((state) => state.setNodes); const setNodes = useFlowStore((state) => state.setNodes);
const setEdges = useFlowStore((state) => state.setEdges); const setEdges = useFlowStore((state) => state.setEdges);
const [openPlayground, setOpenPlayground] = useState(false); const [openPlayground, setOpenPlayground] = useState(false);
const setCurrentFlowId = useFlowsManagerStore((state) => state.setCurrentFlowId); const setCurrentFlowId = useFlowsManagerStore(
(state) => state.setCurrentFlowId
);
const [loadingPlayground, setLoadingPlayground] = useState(false); const [loadingPlayground, setLoadingPlayground] = useState(false);
const name = data.is_component ? "Component" : "Flow"; const name = data.is_component ? "Component" : "Flow";
async function getFlowData() { async function getFlowData() {
const res = await getComponent(data.id) const res = await getComponent(data.id);
const newFlow = cloneFLowWithParent(res, res.id, data.is_component, true); const newFlow = cloneFLowWithParent(res, res.id, data.is_component, true);
return newFlow; return newFlow;
} }
useEffect(() => { useEffect(() => {
if (currentFlowId && playground) { if (currentFlowId && playground) {
setNodes(currentFlow?.data?.nodes ?? [], true); if(openPlayground){
setEdges(currentFlow?.data?.edges ?? [], true); setNodes(currentFlow?.data?.nodes ?? [], true);
cleanFlowPool(); setEdges(currentFlow?.data?.edges ?? [], true);
}
else{
setNodes([], true);
setEdges([], true);
cleanFlowPool();
}
} }
}, [currentFlowId]); }, [openPlayground]);
useEffect(() => { useEffect(() => {
if (data) { if (data) {
@ -100,16 +104,18 @@ export default function CollectionCardComponent({
addFlow(true, newFlow) addFlow(true, newFlow)
.then((id) => { .then((id) => {
setSuccessData({ setSuccessData({
title: `${name} ${isStore ? "Downloaded" : "Installed" title: `${name} ${
} Successfully.`, isStore ? "Downloaded" : "Installed"
} Successfully.`,
}); });
setLoading(false); setLoading(false);
}) })
.catch((error) => { .catch((error) => {
setLoading(false); setLoading(false);
setErrorData({ setErrorData({
title: `Error ${isStore ? "downloading" : "installing" title: `Error ${
} the ${name}`, isStore ? "downloading" : "installing"
} the ${name}`,
list: [error["response"]["data"]["detail"]], list: [error["response"]["data"]["detail"]],
}); });
}); });
@ -159,269 +165,283 @@ export default function CollectionCardComponent({
} }
return ( return (
<Card <>
className={cn( <Card
"group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:shadow-md", className={cn(
disabled ? "pointer-events-none opacity-50" : "" "group relative flex min-h-[11rem] flex-col justify-between overflow-hidden transition-all hover:shadow-md",
)} disabled ? "pointer-events-none opacity-50" : ""
> )}
<div> >
<CardHeader> <div>
<div> <CardHeader>
<CardTitle className="flex w-full items-center justify-between gap-3 text-xl"> <div>
<IconComponent <CardTitle className="flex w-full items-center justify-between gap-3 text-xl">
className={cn( <IconComponent
"flex-shrink-0", className={cn(
data.is_component "flex-shrink-0",
? "mx-0.5 h-6 w-6 text-component-icon" data.is_component
: "h-7 w-7 flex-shrink-0 text-flow-icon" ? "mx-0.5 h-6 w-6 text-component-icon"
)} : "h-7 w-7 flex-shrink-0 text-flow-icon"
name={data.is_component ? "ToyBrick" : "Group"}
/>
<ShadTooltip content={data.name}>
<div className="w-full truncate">{data.name}</div>
</ShadTooltip>
{data?.metadata !== undefined && (
<div className="flex gap-3">
{data.private && (
<ShadTooltip content="Private">
<span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<IconComponent name="Lock" className="h-4 w-4" />
</span>
</ShadTooltip>
)} )}
{!data.is_component && ( name={data.is_component ? "ToyBrick" : "Group"}
<ShadTooltip content="Components"> />
<ShadTooltip content={data.name}>
<div className="w-full truncate">{data.name}</div>
</ShadTooltip>
{data?.metadata !== undefined && (
<div className="flex gap-3">
{data.private && (
<ShadTooltip content="Private">
<span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<IconComponent name="Lock" className="h-4 w-4" />
</span>
</ShadTooltip>
)}
{!data.is_component && (
<ShadTooltip content="Components">
<span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<IconComponent name="ToyBrick" className="h-4 w-4" />
<span data-testid={`total-${data.name}`}>
{data?.metadata?.total ?? 0}
</span>
</span>
</ShadTooltip>
)}
<ShadTooltip content="Likes">
<span className="flex items-center gap-1.5 text-xs text-muted-foreground"> <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<IconComponent name="ToyBrick" className="h-4 w-4" /> <IconComponent
<span data-testid={`total-${data.name}`}> name="Heart"
{data?.metadata?.total ?? 0} className={cn("h-4 w-4 ")}
/>
<span data-testid={`likes-${data.name}`}>
{likes_count ?? 0}
</span> </span>
</span> </span>
</ShadTooltip> </ShadTooltip>
)} <ShadTooltip content="Downloads">
<ShadTooltip content="Likes"> <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<span className="flex items-center gap-1.5 text-xs text-muted-foreground"> <IconComponent
<IconComponent name="Heart" className={cn("h-4 w-4 ")} /> name="DownloadCloud"
<span data-testid={`likes-${data.name}`}> className="h-4 w-4"
{likes_count ?? 0} />
<span data-testid={`downloads-${data.name}`}>
{downloads_count ?? 0}
</span>
</span> </span>
</span> </ShadTooltip>
</ShadTooltip> </div>
<ShadTooltip content="Downloads"> )}
<span className="flex items-center gap-1.5 text-xs text-muted-foreground">
<IconComponent name="DownloadCloud" className="h-4 w-4" />
<span data-testid={`downloads-${data.name}`}>
{downloads_count ?? 0}
</span>
</span>
</ShadTooltip>
</div>
)}
{onDelete && data?.metadata === undefined && ( {onDelete && data?.metadata === undefined && (
<DeleteConfirmationModal <DeleteConfirmationModal
onConfirm={() => { onConfirm={() => {
onDelete(); onDelete();
}} }}
>
<IconComponent
name="Trash2"
className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
/>
</DeleteConfirmationModal>
)}
</CardTitle>
</div>
{data.user_created && data.user_created.username && (
<span className="text-sm text-primary">
by <b>{data.user_created.username}</b>
{data.last_tested_version && (
<>
{" "}
|{" "}
<span className="text-xs">
{" "}
⛓︎ v{data.last_tested_version}
</span>
</>
)}
</span>
)}
<CardDescription className="pb-2 pt-2">
<div className="truncate-doubleline">{data.description}</div>
</CardDescription>
</CardHeader>
</div>
<CardFooter>
<div className="flex w-full items-center justify-between gap-2">
<div className="flex w-full flex-wrap items-end justify-between gap-2">
<div className="flex w-full flex-1 flex-wrap gap-2">
{data.tags &&
data.tags.length > 0 &&
data.tags.map((tag, index) => (
<Badge
key={index}
variant="outline"
size="xq"
className="text-muted-foreground"
> >
{tag.name} <IconComponent
</Badge> name="Trash2"
))} className="h-5 w-5 text-primary opacity-0 transition-all hover:text-destructive group-hover:opacity-100"
/>
</DeleteConfirmationModal>
)}
</CardTitle>
</div> </div>
{data.liked_by_count != undefined && ( {data.user_created && data.user_created.username && (
<div className="flex gap-0.5"> <span className="text-sm text-primary">
{onDelete && data?.metadata !== undefined ? ( by <b>{data.user_created.username}</b>
<ShadTooltip {data.last_tested_version && (
content={ <>
authorized ? "Delete" : "Please review your API key." {" "}
} |{" "}
> <span className="text-xs">
<DeleteConfirmationModal {" "}
onConfirm={() => { ⛓︎ v{data.last_tested_version}
onDelete(); </span>
}} </>
)}
</span>
)}
<CardDescription className="pb-2 pt-2">
<div className="truncate-doubleline">{data.description}</div>
</CardDescription>
</CardHeader>
</div>
<CardFooter>
<div className="flex w-full items-center justify-between gap-2">
<div className="flex w-full flex-wrap items-end justify-between gap-2">
<div className="flex w-full flex-1 flex-wrap gap-2">
{data.tags &&
data.tags.length > 0 &&
data.tags.map((tag, index) => (
<Badge
key={index}
variant="outline"
size="xq"
className="text-muted-foreground"
>
{tag.name}
</Badge>
))}
</div>
{data.liked_by_count != undefined && (
<div className="flex gap-0.5">
{onDelete && data?.metadata !== undefined ? (
<ShadTooltip
content={
authorized ? "Delete" : "Please review your API key."
}
>
<DeleteConfirmationModal
onConfirm={() => {
onDelete();
}}
>
<Button
variant="ghost"
size="icon"
className={
"whitespace-nowrap" +
(!authorized ? " cursor-not-allowed" : "")
}
>
<IconComponent
name="Trash2"
className={cn(
"h-5 w-5",
!authorized ? " text-ring" : ""
)}
/>
</Button>
</DeleteConfirmationModal>
</ShadTooltip>
) : (
<ShadTooltip
content={
authorized ? "Like" : "Please review your API key."
}
> >
<Button <Button
disabled={loadingLike}
variant="ghost" variant="ghost"
size="icon" size="icon"
className={ className={
"whitespace-nowrap" + "whitespace-nowrap" +
(!authorized ? " cursor-not-allowed" : "") (!authorized ? " cursor-not-allowed" : "")
} }
onClick={() => {
if (!authorized) {
return;
}
handleLike();
}}
data-testid={`like-${data.name}`}
> >
<IconComponent <IconComponent
name="Trash2" name="Heart"
className={cn( className={cn(
"h-5 w-5", "h-5 w-5",
liked_by_user
? "fill-destructive stroke-destructive"
: "",
!authorized ? " text-ring" : "" !authorized ? " text-ring" : ""
)} )}
/> />
</Button> </Button>
</DeleteConfirmationModal> </ShadTooltip>
</ShadTooltip> )}
) : (
<ShadTooltip <ShadTooltip
content={ content={
authorized ? "Like" : "Please review your API key." authorized
? isStore
? "Download"
: "Install Locally"
: "Please review your API key."
} }
> >
<Button <Button
disabled={loadingLike} disabled={loading}
variant="ghost" variant="ghost"
size="icon" size="icon"
className={ className={
"whitespace-nowrap" + "whitespace-nowrap" +
(!authorized ? " cursor-not-allowed" : "") (!authorized ? " cursor-not-allowed" : "") +
(!loading ? " p-0.5" : "")
} }
onClick={() => { onClick={() => {
if (!authorized) { if (loading || !authorized) {
return; return;
} }
handleLike(); handleInstall();
}} }}
data-testid={`like-${data.name}`} data-testid={`install-${data.name}`}
> >
<IconComponent <IconComponent
name="Heart" name={
loading ? "Loader2" : isStore ? "Download" : "Plus"
}
className={cn( className={cn(
"h-5 w-5", loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
liked_by_user
? "fill-destructive stroke-destructive"
: "",
!authorized ? " text-ring" : "" !authorized ? " text-ring" : ""
)} )}
/> />
</Button> </Button>
</ShadTooltip> </ShadTooltip>
)} </div>
<ShadTooltip )}
content={ {button && button}
authorized {playground && (
? isStore <Button
? "Download" disabled={loadingPlayground}
: "Install Locally" key={data.id}
: "Please review your API key." tabIndex={-1}
} variant="outline"
> size="sm"
<Button className="whitespace-nowrap "
disabled={loading} data-testid={"playground-flow-button-" + data.id}
variant="ghost" onClick={() => {
size="icon" setLoadingPlayground(true);
className={ if (getFlowById(data.id)) {
"whitespace-nowrap" + setCurrentFlowId(data.id);
(!authorized ? " cursor-not-allowed" : "") +
(!loading ? " p-0.5" : "")
}
onClick={() => {
if (loading || !authorized) {
return;
}
handleInstall();
}}
data-testid={`install-${data.name}`}
>
<IconComponent
name={loading ? "Loader2" : isStore ? "Download" : "Plus"}
className={cn(
loading ? "h-5 w-5 animate-spin" : "h-5 w-5",
!authorized ? " text-ring" : ""
)}
/>
</Button>
</ShadTooltip>
</div>
)}
{button && button}
{playground &&
<Button
disabled={loadingPlayground}
key={data.id}
tabIndex={-1}
variant="outline"
size="sm"
className="whitespace-nowrap "
data-testid={
"playground-flow-button-" + data.id
}
onClick={() => {
setLoadingPlayground(true);
if (getFlowById(data.id)) {
setCurrentFlowId(data.id);
setOpenPlayground(true);
setLoadingPlayground(false);
}
else {
getFlowData().then((res) => {
setCurrentFlow(res);
setOpenPlayground(true); setOpenPlayground(true);
setLoadingPlayground(false); setLoadingPlayground(false);
}); } else {
getFlowData().then((res) => {
} setCurrentFlow(res);
}} setOpenPlayground(true);
> setLoadingPlayground(false);
{!loadingPlayground ? });
<> }
<IconComponent }}
name="ExternalLink" >
className="main-page-nav-button select-none" {!loadingPlayground ? (
/> <>
Playground <IconComponent
</>: name="ExternalLink"
<Loading /> className="main-page-nav-button select-none"
} />
{openPlayground && < IOModal cleanOnClose={true} open={openPlayground} setOpen={setOpenPlayground}> Playground
<></> </>
</IOModal>} ) : (
</Button> <Loading />
} )}
</Button>
)}
</div>
</div> </div>
</div> </CardFooter>
</CardFooter> </Card>
</Card >
{openPlayground && (
<IOModal
cleanOnClose={true}
open={openPlayground}
setOpen={setOpenPlayground}
>
<></>
</IOModal>
)}
</>
); );
} }

View file

@ -31,10 +31,8 @@ export default function IOModal({
open, open,
setOpen, setOpen,
disable, disable,
cleanOnClose=false,
}: IOModalPropsType): JSX.Element { }: IOModalPropsType): JSX.Element {
const allNodes = useFlowStore((state) => state.nodes); const allNodes = useFlowStore((state) => state.nodes);
const cleanFlowPool = useFlowStore((state) => state.CleanFlowPool);
const inputs = useFlowStore((state) => state.inputs).filter( const inputs = useFlowStore((state) => state.inputs).filter(
(input) => input.type !== "ChatInput" (input) => input.type !== "ChatInput"
); );
@ -85,12 +83,6 @@ export default function IOModal({
return updateVerticesOrder(currentFlow!.id, null); return updateVerticesOrder(currentFlow!.id, null);
} }
// useEffect(() => {
// if (open) {
// updateVertices();
// }
// }, [open, currentFlow]);
async function sendMessage(count = 1): Promise<void> { async function sendMessage(count = 1): Promise<void> {
if (isBuilding) return; if (isBuilding) return;
setIsBuilding(true); setIsBuilding(true);
@ -129,13 +121,6 @@ export default function IOModal({
open={open} open={open}
setOpen={setOpen} setOpen={setOpen}
disable={disable} disable={disable}
onChangeOpenModal={(open)=>{
if(!open && cleanOnClose){
console.log("cleaning flow pool")
cleanFlowPool();
}
}}
> >
<BaseModal.Trigger>{children}</BaseModal.Trigger> <BaseModal.Trigger>{children}</BaseModal.Trigger>
{/* TODO ADAPT TO ALL TYPES OF INPUTS AND OUTPUTS */} {/* TODO ADAPT TO ALL TYPES OF INPUTS AND OUTPUTS */}

View file

@ -27,6 +27,7 @@ export default function PlaygroundPage() {
// Set flow tab id // Set flow tab id
useEffect(() => { useEffect(() => {
console.log("id", id);
if (getFlowById(id!)) { if (getFlowById(id!)) {
setCurrentFlowId(id!); setCurrentFlowId(id!);
} }
@ -44,6 +45,11 @@ export default function PlaygroundPage() {
cleanFlowPool(); cleanFlowPool();
setLoading(false); setLoading(false);
} }
return () => {
setNodes([], true);
setEdges([], true);
cleanFlowPool();
};
}, [currentFlow]); }, [currentFlow]);