Canvas: Rework monitoring page

Display worker statuses with list of commands
Commit hash

Change-Id: I7054ecc5ce81f35cad3fe26fc20677b6f50d3147
diff --git a/apps/canvas/front/src/lib/state.ts b/apps/canvas/front/src/lib/state.ts
index b0c2560..9f0aeb3 100644
--- a/apps/canvas/front/src/lib/state.ts
+++ b/apps/canvas/front/src/lib/state.ts
@@ -223,6 +223,7 @@
 	} finally {
 		console.log("done");
 	}
+	return "Unknown Node";
 }
 
 export function nodeIsConnectable(n: AppNode, handle: string): boolean {
@@ -391,6 +392,25 @@
 	}),
 ]);
 
+export const serviceInfoSchema = z.object({
+	name: z.string(),
+	workers: z.array(
+		z.object({
+			id: z.string(),
+			repoOK: z.boolean(),
+			commit: z.string(),
+			commands: z.optional(
+				z.array(
+					z.object({
+						command: z.string(),
+						state: z.string(),
+					}),
+				),
+			),
+		}),
+	),
+});
+
 export const envSchema = z.object({
 	managerAddr: z.optional(z.string().min(1)),
 	deployKey: z.optional(z.nullable(z.string().min(1))),
@@ -406,7 +426,7 @@
 	integrations: z.object({
 		github: z.boolean(),
 	}),
-	services: z.array(z.string()),
+	services: z.array(serviceInfoSchema),
 	user: z.object({
 		id: z.string(),
 		username: z.string(),
@@ -414,6 +434,7 @@
 	access: z.array(accessSchema),
 });
 
+export type ServiceInfo = z.infer<typeof serviceInfoSchema>;
 export type Env = z.infer<typeof envSchema>;
 
 const defaultEnv: Env = {
@@ -831,7 +852,7 @@
 				nodes.concat({
 					...node,
 					position: getRandomPosition(viewport),
-				}),
+				} as AppNode),
 			);
 		},
 		setNodes: (nodes) => {