blob: cc09a592ad8dda63f601b54fdadbcbbfdbcb6904 [file] [log] [blame]
import { AppNode, useEnv, useMessages, useProjectId, useStateStore } from "@/lib/state";
import { Button } from "./ui/button";
import { useCallback, useEffect, useState } from "react";
import { generateDodoConfig } from "@/lib/config";
import { useNodes, useReactFlow } from "@xyflow/react";
import { useToast } from "@/hooks/use-toast";
export function Actions() {
const { toast } = useToast();
const store = useStateStore();
const projectId = useProjectId();
const nodes = useNodes<AppNode>();
const env = useEnv();
const messages = useMessages();
const instance = useReactFlow();
const [ok, setOk] = useState(false);
const [loading, setLoading] = useState(false);
useEffect(() => {
setOk(!messages.some((m) => m.type === "FATAL"));
}, [messages, setOk]);
const deploy = useCallback(async () => {
if (projectId == null) {
return;
}
setLoading(true);
try {
const config = generateDodoConfig(nodes, env);
if (config == null) {
throw new Error("MUST NOT REACH!");
}
const resp = await fetch(`/api/project/${projectId}/deploy`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
state: JSON.stringify(instance.toObject()),
config,
}),
});
if (resp.ok) {
toast({
title: "Deployment succeeded",
});
} else {
toast({
variant: "destructive",
title: "Deployment failed",
description: await resp.text(),
});
}
} catch (e) {
console.log(e);
toast({
variant: "destructive",
title: "Deployment failed",
});
} finally {
setLoading(false);
}
}, [projectId, instance, nodes, env, setLoading]);
const [st, setSt] = useState<string>();
const save = useCallback(async () => {
if (projectId == null) {
return;
}
const resp = await fetch(`/api/project/${projectId}/saved`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(instance.toObject()),
});
if (resp.ok) {
toast({
title: "Save succeeded",
});
} else {
toast({
variant: "destructive",
title: "Save failed",
description: await resp.text(),
});
}
}, [projectId, instance, setSt]);
const restoreSaved = useCallback(async () => {
if (projectId == null) {
return;
}
const resp = await fetch(`/api/project/${projectId}/saved`, {
method: "GET",
});
const inst = await resp.json();
const { x = 0, y = 0, zoom = 1 } = inst.viewport;
store.setNodes(inst.nodes || []);
store.setEdges(inst.edges || []);
instance.setViewport({ x, y, zoom });
}, [projectId, instance, st]);
const [props, setProps] = useState({});
useEffect(() => {
if (loading) {
setProps({ loading: true });
} else if (ok) {
setProps({ disabled: false });
} else {
setProps({ disabled: true });
}
}, [ok, loading, setProps]);
return (
<>
<Button onClick={deploy} {...props}>Deploy</Button>
<Button onClick={save}>Save</Button>
<Button onClick={restoreSaved}>Restore</Button>
</>
)
}