-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #145 from janlauber/100-overview-map
Overview Map
- Loading branch information
Showing
42 changed files
with
2,424 additions
and
88 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
Oops, something went wrong.