Skip to content

Commit

Permalink
Merge pull request #145 from janlauber/100-overview-map
Browse files Browse the repository at this point in the history
Overview Map
  • Loading branch information
janlauber authored Mar 26, 2024
2 parents 882bab8 + f97c6f0 commit c19aa2a
Show file tree
Hide file tree
Showing 42 changed files with 2,424 additions and 88 deletions.
389 changes: 369 additions & 20 deletions frontend/package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"@sveltejs/adapter-node": "^5.0.1",
"@sveltejs/adapter-static": "^3.0.0",
"@webcontainer/api": "^1.1.4",
"@xyflow/svelte": "^0.0.39",
"chart.js": "^4.3.0",
"diff": "^5.2.0",
"diff2html": "^3.4.47",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@
let blueprintModalOpen = false;
function jsonToYaml(json: any): string {
return yaml.dump(json);
}
let name: string = "";
let description: string = "";
let isPrivate: boolean = false;
Expand Down Expand Up @@ -224,7 +221,7 @@
<div class=" h-96 overflow-y-auto rounded-lg p-2" style="background-color: #1E1E1E;">
<MonacoEditor
bind:value={manifest}
options={{ language: "yaml", automaticLayout: false, minimap: { enabled: false } }}
options={{ language: "yaml", automaticLayout: true, minimap: { enabled: false } }}
theme="vs-dark"
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/lib/components/blueprints/ProjectCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@
<div class=" h-96 overflow-y-auto rounded-lg p-2" style="background-color: #1E1E1E;">
<MonacoEditor
bind:value={manifest}
options={{ language: "yaml", automaticLayout: false, minimap: { enabled: false } }}
options={{ language: "yaml", automaticLayout: true, minimap: { enabled: false } }}
theme="vs-dark"
/>
</div>
Expand Down
10 changes: 3 additions & 7 deletions frontend/src/lib/components/image/ImageSettings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,10 @@
}
};
// check if the manifest has changed, it could be that the values are in different order
// order first by key
let sorted_manifest = Object.keys(current_rollout.manifest ?? {}).sort();
let new_sorted_manifest = Object.keys(new_manifest).sort();
// check if the manifest has changed, it could be that the key values are in different order
if (JSON.stringify(new_manifest) === JSON.stringify(current_rollout.manifest))
return;
if (JSON.stringify(sorted_manifest) === JSON.stringify(new_sorted_manifest)) {
return;
}
const data: RolloutsRecord = {
manifest: new_manifest,
Expand Down
144 changes: 144 additions & 0 deletions frontend/src/lib/components/map/EventStream.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<script lang="ts">
import { selectedProject } from "$lib/stores/data";
import { Timeline, TimelineItem } from "flowbite-svelte";
import { onDestroy, onMount } from "svelte";
export let kind: string;
export let name: string;
let initialLoadComplete = false;
// events is json:
// example: {"message":"Successfully assigned ztn22x0b7bdrt0v/ztn22x0b7bdrt0v-677b57fffd-jxg9n to natr-shared-wrk-001.natr-4.natron.cloud","reason":"Scheduled","typus":"Normal"}{"message":"Pulling image \"docker.io/chentex/random-logger:latest\"","reason":"Pulling","typus":"Normal"}{"message":"Successfully pulled image \"docker.io/chentex/random-logger:latest\" in 926ms (926ms including waiting)","reason":"Pulled","typus":"Normal"}{"message":"Created container ztn22x0b7bdrt0v","reason":"Created","typus":"Normal"}{"message":"Started container ztn22x0b7bdrt0v","reason":"Started","typus":"Normal"}
let events: string = "";
let event_array: any[] = [];
let ws: WebSocket;
// parse the events string into an array of objects
$: event_array = events.split("}{").map((event) => {
// remove the first and last curly braces
event = event.replace("{", "").replace("}", "");
// split the event string into an array of key-value pairs
let event_array = event.split(",");
// create an object from the key-value pairs
let event_object = {};
event_array.forEach((pair) => {
let [key, value] = pair.split(":");
// they key are strings with double quotes around them -> e.g. "message"
// remove the double quotes
key = key.replace(/"/g, "");
// only if value is not null or undefined
if (!value) return;
// remove " and \" from the value
value = value.replace(/\\"/g, '"').replace(/"/g, "");
// @ts-ignore
event_object[key] = value;
});
return event_object;
});
function parseKind(kind: string) {
if (kind === "pod") {
return "Pod";
} else if (kind === "deployment") {
return "Deployment";
} else if (kind === "service") {
return "Service";
} else if (kind === "ingress") {
return "Ingress";
} else if (kind === "secret") {
return "Secret";
} else if (kind === "pvc") {
return "PersistentVolumeClaim";
} else {
return "Unknown";
}
}
onMount(() => {
// host
let host = window.location.host;
if (host.includes("localhost")) {
host = "localhost:8090";
}
// check for tls
let protocol = window.location.protocol === "https:" ? "wss" : "ws";
ws = new WebSocket(`${protocol}://${host}/ws/k8s/events`);
ws.onopen = () => {
type LogMessage = {
rolloutId: string;
name: string;
kind: string;
};
let message: LogMessage = {
rolloutId: $selectedProject?.id ?? "",
name: name,
kind: parseKind(kind)
};
ws.send(JSON.stringify(message));
};
ws.onmessage = (event) => {
// event.data is a string
events += event.data;
};
// set initialLoadComplete to true after 0.3s
setTimeout(() => {
initialLoadComplete = true;
}, 300);
});
onDestroy(() => {
// Close the WebSocket connection
ws.close();
// Reset the logs
events = "";
});
</script>

<div class="px-2 rounded-lg">
<div
class="absolute top-36 bottom-0 right-0 left-0 overflow-y-auto rounded-lg p-2 bg-white dark:bg-slate-800"
>
{#if event_array.length > 0 && event_array[0].message}
<!-- <Timeline>
<TimelineItem title="Application UI code in Tailwind CSS" date="February 2022">
<p class="mb-4 text-base font-normal text-gray-500 dark:text-gray-400">
Get access to over 20+ pages including a dashboard layout, charts, kanban board,
calendar, and pre-order E-commerce & Marketing pages.
</p>
</TimelineItem>
<TimelineItem title="Application UI code in Tailwind CSS" date="March 2022">
<p class="text-base font-normal text-gray-500 dark:text-gray-400">
All of the pages and components are first designed in Figma and we keep a parity between
the two versions even as we update the project.
</p>
</TimelineItem>
<TimelineItem title="Application UI code in Tailwind CSS" date="April 2022">
<p class="text-base font-normal text-gray-500 dark:text-gray-400">
Get started with dozens of web components and interactive elements built on top of
Tailwind CSS.
</p>
</TimelineItem>
</Timeline> -->
<Timeline>
{#each event_array as event}
<TimelineItem title={event.message} date={event.reason}>
<p class={event.typus === "Normal" ? "text-green-500" : "text-red-500"}>
{event.typus}
</p>
</TimelineItem>
{/each}
</Timeline>
{/if}
</div>
</div>
31 changes: 31 additions & 0 deletions frontend/src/lib/components/map/KubernetesObject.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script lang="ts">
import MonacoEditor from "svelte-monaco";
// @ts-ignore
import yaml from "js-yaml";
export let manifest: JSON;
function jsonToYaml(json: any): string {
return yaml.dump(json);
}
let yamlManifest = jsonToYaml(manifest);
</script>

<div class="log-container px-2 rounded-lg bg-gray-800">
<div class="absolute top-36 bottom-0 right-0 left-0 overflow-y-auto rounded-lg p-2" style="background-color: #1E1E1E;">
<MonacoEditor
bind:value={yamlManifest}
options={{
language: "yaml",
automaticLayout: true,
minimap: { enabled: false },
readOnly: true,
scrollBeyondLastLine: false,
scrollbar: { vertical: "auto", horizontal: "auto" },
}}
theme="vs-dark"
/>
</div>
</div>
109 changes: 109 additions & 0 deletions frontend/src/lib/components/map/LogStream.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<script lang="ts">
import { selectedProject } from "$lib/stores/data";
import { onDestroy, onMount } from "svelte";
import MonacoEditor from "svelte-monaco";
export let podName: string;
// function downloadLogs(podName: string) {
// const logsStream = logs[podName].join("\n");
// const blob = new Blob([logsStream], { type: "text/plain;charset=utf-8" });
// const url = URL.createObjectURL(blob);
// const a = document.createElement("a");
// a.href = url;
// a.download = `${podName}.log`;
// document.body.appendChild(a);
// a.click();
// document.body.removeChild(a);
// }
// // get rollout logs from specific pod as EventSource from /rollouts/{projectId}/{podName}/logs
// // Object to hold log streams for each pod
let initialLoadComplete = false;
let logs: string = "";
let ws: WebSocket;
onMount(() => {
// host
let host = window.location.host;
if (host.includes("localhost")) {
host = "localhost:8090";
}
// check for tls
let protocol = window.location.protocol === "https:" ? "wss" : "ws";
ws = new WebSocket(`${protocol}://${host}/ws/k8s/logs`);
ws.onopen = () => {
type LogMessage = {
rolloutId: string;
podName: string;
};
let message: LogMessage = {
rolloutId: $selectedProject?.id ?? "",
podName: podName
};
ws.send(JSON.stringify(message));
};
ws.onmessage = (event) => {
// event.data is a string
logs += event.data;
};
// set initialLoadComplete to true after 0.3s
setTimeout(() => {
initialLoadComplete = true;
}, 300);
});
onDestroy(() => {
// Close the WebSocket connection
ws.close();
// Reset the logs
logs = "";
});
function handleEditorReady(event: CustomEvent) {
const editor = event.detail;
setTimeout(() => {
scrollToBottom(editor);
}, 100); // Adjust delay as necessary
}
function scrollToBottom(editor: any) {
if (editor) {
const model = editor.getModel();
if (model) {
const lastLine = model.getLineCount();
editor.revealLine(lastLine);
}
}
}
</script>

<div class="log-container px-2 rounded-lg bg-gray-800">
<div
class="absolute top-36 bottom-0 right-0 left-0 overflow-y-auto rounded-lg p-2"
style="background-color: #1E1E1E;"
>
<MonacoEditor
bind:value={logs}
options={{
language: "shell",
automaticLayout: true,
minimap: { enabled: false },
readOnly: true,
scrollBeyondLastLine: false,
scrollbar: { vertical: "auto", horizontal: "auto" },
wordWrap: "on"
}}
theme="vs-dark"
on:ready={handleEditorReady}
/>
</div>
</div>
Loading

0 comments on commit c19aa2a

Please sign in to comment.