Canvas: Service dev UI

Change-Id: I11968dbf5ec51c5fd234ad927d40b0b3983e71dd
diff --git a/apps/canvas/front/src/lib/config.ts b/apps/canvas/front/src/lib/config.ts
index a3784c1..60d9966 100644
--- a/apps/canvas/front/src/lib/config.ts
+++ b/apps/canvas/front/src/lib/config.ts
@@ -1,4 +1,4 @@
-import { AppNode, Env, GatewayHttpsNode, Message, MessageType, NodeType, ServiceType, VolumeType } from "./state";
+import { AppNode, Env, Message, MessageType, NodeType, ServiceType, VolumeType } from "./state";
 
 export type AuthDisabled = {
 	enabled: false;
@@ -57,6 +57,11 @@
 	expose?: PortDomain[];
 	volume?: string[];
 	preBuildCommands?: { bin: string }[];
+	dev?: {
+		enabled: boolean;
+		ssh?: Domain;
+		codeServer?: Domain;
+	};
 };
 
 export type Volume = {
@@ -143,7 +148,7 @@
 						ingress: ingressNodes
 							.filter((i) => i.data.https!.serviceId === n.id)
 							.map(
-								(i: GatewayHttpsNode): Ingress => ({
+								(i): Ingress => ({
 									network: networkMap.get(i.data.network!)!,
 									subdomain: i.data.subdomain!,
 									port: {
@@ -165,6 +170,23 @@
 						preBuildCommands: n.data.preBuildCommands
 							? n.data.preBuildCommands.split("\n").map((cmd) => ({ bin: cmd }))
 							: [],
+						dev: {
+							enabled: n.data.dev ? n.data.dev.enabled : false,
+							codeServer:
+								n.data.dev?.enabled && n.data.dev.expose != null
+									? {
+											network: n.data.dev.expose.network,
+											subdomain: n.data.dev.expose.subdomain,
+										}
+									: undefined,
+							ssh:
+								n.data.dev?.enabled && n.data.dev.expose != null
+									? {
+											network: n.data.dev.expose.network,
+											subdomain: n.data.dev.expose.subdomain,
+										}
+									: undefined,
+						},
 					};
 				}),
 			volume: nodes