Canvas: Edit/Deploy mode

Change-Id: I51e5b6c2a1f06009433b0d0824ffcf3dfe39d34e
diff --git a/apps/canvas/front/src/components/actions.tsx b/apps/canvas/front/src/components/actions.tsx
index 509b51c..f292c30 100644
--- a/apps/canvas/front/src/components/actions.tsx
+++ b/apps/canvas/front/src/components/actions.tsx
@@ -4,6 +4,14 @@
 import { generateDodoConfig } from "@/lib/config";
 import { useNodes, useReactFlow } from "@xyflow/react";
 import { useToast } from "@/hooks/use-toast";
+import {
+	DropdownMenuGroup,
+	DropdownMenuItem,
+	DropdownMenu,
+	DropdownMenuContent,
+	DropdownMenuTrigger,
+} from "./ui/dropdown-menu";
+import { Menu } from "lucide-react";
 
 function toNodeType(t: string): string {
 	if (t === "ingress") {
@@ -64,6 +72,7 @@
 			return;
 		}
 		setLoading(true);
+		store.setMode("deploy");
 		try {
 			const config = generateDodoConfig(projectId, nodes, env);
 			if (config == null) {
@@ -92,6 +101,7 @@
 				});
 			}
 		} catch (e) {
+			store.setMode("edit");
 			console.log(e);
 			toast({
 				variant: "destructive",
@@ -100,7 +110,7 @@
 		} finally {
 			setLoading(false);
 		}
-	}, [projectId, instance, nodes, env, setLoading, toast, monitor]);
+	}, [projectId, instance, nodes, env, setLoading, toast, monitor, store]);
 	const save = useCallback(async () => {
 		if (projectId == null) {
 			return;
@@ -128,7 +138,7 @@
 		if (projectId == null) {
 			return;
 		}
-		const resp = await fetch(`/api/project/${projectId}/saved`, {
+		const resp = await fetch(`/api/project/${projectId}/saved/${store.mode === "deploy" ? "deploy" : "draft"}`, {
 			method: "GET",
 		});
 		const inst = await resp.json();
@@ -142,7 +152,9 @@
 		store.setNodes([]);
 		instance.setViewport({ x: 0, y: 0, zoom: 1 });
 	}, [store, instance]);
-	// TODO(gio): Update store
+	const edit = useCallback(async () => {
+		store.setMode("edit");
+	}, [store]);
 	const deleteProject = useCallback(async () => {
 		if (projectId == null) {
 			return;
@@ -154,12 +166,12 @@
 			clear();
 			store.setProject(undefined);
 			toast({
-				title: "Save succeeded",
+				title: "Project deleted",
 			});
 		} else {
 			toast({
 				variant: "destructive",
-				title: "Save failed",
+				title: "Failed to delete project",
 				description: await resp.text(),
 			});
 		}
@@ -214,22 +226,71 @@
 			setReloadProps({ disabled: projectId === undefined });
 		}
 	}, [ok, loading, reloading, projectId]);
-	return (
-		<>
-			<Button onClick={deploy} {...deployProps}>
-				Deploy
-			</Button>
-			<Button onClick={reload} {...reloadProps}>
-				Reload
-			</Button>
-			<Button onClick={save}>Save</Button>
-			<Button onClick={restoreSaved}>Restore</Button>
-			<Button onClick={clear} variant="destructive">
-				Clear
-			</Button>
-			<Button onClick={deleteProject} variant="destructive" disabled={projectId === undefined}>
-				Delete
-			</Button>
-		</>
-	);
+	if (store.mode === "deploy") {
+		return (
+			<div className="flex flex-row gap-1 items-center">
+				<Button onClick={edit} {...reloadProps}>
+					Edit
+				</Button>
+				<DropdownMenu>
+					<DropdownMenuTrigger>
+						<Menu className="rounded-md bg-gray-200 opacity-50" />
+					</DropdownMenuTrigger>
+					<DropdownMenuContent className="w-56">
+						<DropdownMenuGroup>
+							<DropdownMenuItem
+								onClick={reload}
+								className="cursor-pointer hover:bg-gray-200"
+								{...reloadProps}
+							>
+								Reload Services
+							</DropdownMenuItem>
+							<DropdownMenuItem
+								onClick={deleteProject}
+								disabled={projectId === undefined}
+								className="cursor-pointer hover:bg-gray-200"
+							>
+								Delete Project
+							</DropdownMenuItem>
+						</DropdownMenuGroup>
+					</DropdownMenuContent>
+				</DropdownMenu>
+			</div>
+		);
+	} else {
+		return (
+			<div className="flex flex-row gap-1 items-center">
+				<Button onClick={deploy} {...deployProps}>
+					Deploy
+				</Button>
+				<Button onClick={save}>Save</Button>
+				<DropdownMenu>
+					<DropdownMenuTrigger>
+						<Menu />
+					</DropdownMenuTrigger>
+					<DropdownMenuContent className="w-56">
+						<DropdownMenuGroup>
+							<DropdownMenuItem
+								onClick={restoreSaved}
+								disabled={projectId === undefined}
+								className="cursor-pointer hover:bg-gray-200"
+							>
+								Restore
+							</DropdownMenuItem>
+							<DropdownMenuItem onClick={clear} className="cursor-pointer hover:bg-gray-200">
+								Clear
+							</DropdownMenuItem>
+							<DropdownMenuItem
+								onClick={deleteProject}
+								disabled={projectId === undefined}
+								className="cursor-pointer hover:bg-gray-200"
+							>
+								Delete Project
+							</DropdownMenuItem>
+						</DropdownMenuGroup>
+					</DropdownMenuContent>
+				</DropdownMenu>
+			</div>
+		);
+	}
 }