Canvas: Get ready for trial

Change-Id: I16088fa041dd0fb35ac801ddbbedf3c1c6e8563d
diff --git a/apps/canvas/front/src/Messages.tsx b/apps/canvas/front/src/Messages.tsx
index 8cd6652..0701afb 100644
--- a/apps/canvas/front/src/Messages.tsx
+++ b/apps/canvas/front/src/Messages.tsx
@@ -1,5 +1,5 @@
 import { Button } from "./components/ui/button";
-import { AppNode, AppState, Message, nodeLabel, useMessages } from "./lib/state";
+import { AppNode, AppState, Message, nodeLabel, useMessages, useProjectId } from "./lib/state";
 import { useCallback, useEffect, useState } from "react";
 import { useNodes } from "@xyflow/react";
 import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./components/ui/accordion";
@@ -8,6 +8,7 @@
 
 export function Messages() {
 	const nodes = useNodes<AppNode>();
+	const projectId = useProjectId();
 	const [nodeMap, setNodeMap] = useState<Map<string, AppNode>>(new Map());
 	useEffect(() => {
 		setNodeMap(new Map(nodes.map((n) => [n.id, n])));
@@ -24,14 +25,25 @@
 	const [grouped, setGrouped] = useState<Map<string, Message[]>>(new Map());
 	useEffect(() => {
 		const g = new Map<string, Message[]>();
-		messages.forEach((m) => {
-			const id = m.nodeId || "global";
-			const existing: Message[] = g.get(id) || [];
-			existing.push(m);
-			g.set(id, existing);
-		});
+		if (projectId == null) {
+			g.set("global", [
+				{
+					id: "global",
+					nodeId: undefined,
+					message: "Create a new project or select existing one to get started",
+					type: "FATAL",
+				},
+			]);
+		} else {
+			messages.forEach((m) => {
+				const id = m.nodeId || "global";
+				const existing: Message[] = g.get(id) || [];
+				existing.push(m);
+				g.set(id, existing);
+			});
+		}
 		setGrouped(g);
-	}, [messages, setGrouped]);
+	}, [projectId, messages, setGrouped]);
 	const [open, setOpen] = useState<string[]>([...grouped.keys()]);
 	useEffect(() => {
 		// TODO(gio): do not reopen closed ones