🩹 Fixing minor bugs

This commit is contained in:
andreas.dinauer 2025-11-01 20:34:46 +01:00
parent ee5ed78d35
commit 08fbf78a76
18 changed files with 156 additions and 34 deletions

View File

@ -11,6 +11,7 @@
html { html {
--primary-color: rgb(87, 75, 255); --primary-color: rgb(87, 75, 255);
--primary-color-dark: rgb(69, 57, 241);
--tile-color: #ebf1ff; --tile-color: #ebf1ff;
background-color: rgb(255, 255, 255); background-color: rgb(255, 255, 255);
--shade-light: #f3f3f3; --shade-light: #f3f3f3;

BIN
assets/transparent_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

View File

@ -4,6 +4,7 @@ export class NodeStats
{ {
constructor ( constructor (
public node: Node, public node: Node,
public runningPods: number
) { } ) { }
relativeCpuUsage?: number; relativeCpuUsage?: number;

View File

@ -1,5 +1,5 @@
<template> <template>
<PopupTemplate :heading="'Logs: ' + pod.metadata?.namespace + '/' + pod.metadata?.name" ref="base"> <PopupTemplate :heading="'Logs: ' + pod.metadata?.namespace + '/' + pod.metadata?.name" ref="base" @close="emits('close')">
<ScrollComponent ref="scrollComponent" v-show="logs"> <ScrollComponent ref="scrollComponent" v-show="logs">
<div class="console" v-if="logs"> <div class="console" v-if="logs">
<p class="log" v-for="log, index in logs" :class="{ even: index % 2 }"><span>[{{ dayjs(log.timestamp).format('YYYY-MM-DD HH:mm') }}]</span><span>{{ log.message }}</span></p> <p class="log" v-for="log, index in logs" :class="{ even: index % 2 }"><span>[{{ dayjs(log.timestamp).format('YYYY-MM-DD HH:mm') }}]</span><span>{{ log.message }}</span></p>
@ -25,20 +25,25 @@ const props = defineProps<{
pod: Pod pod: Pod
}>(); }>();
const emits = defineEmits<{
(e: 'close'): void
}>()
const scrollComponent = ref(); const scrollComponent = ref();
function open() onMounted(() => {
{ getLogs(props.pod.metadata.uid, (_logs: Log[]) => {
logs.value = undefined;
base.value.open();
getLogs(props.pod.metadata?.uid, (_logs: Log[]) => {
logs.value = _logs; logs.value = _logs;
scrollComponent.value.scrollToBottom();
}); });
} });
defineExpose({ onMounted(() => {
open document.addEventListener('keydown', (event) => {
if(event.key === 'Escape')
{
emits('close');
}
});
}) })
</script> </script>

View File

@ -4,6 +4,7 @@
<div class="grid-element"> <div class="grid-element">
<p>{{ calcAge(nodeStats.node?.metadata?.creationTimestamp) }}</p> <p>{{ calcAge(nodeStats.node?.metadata?.creationTimestamp) }}</p>
</div> </div>
<p class="grid-element">{{ nodeStats.runningPods }}</p>
<div class="grid-element"> <div class="grid-element">
<NodeReadyComponent :ready="isReady(nodeStats)"></NodeReadyComponent> <NodeReadyComponent :ready="isReady(nodeStats)"></NodeReadyComponent>
</div> </div>

View File

@ -2,7 +2,6 @@
<nav class="sidebar"> <nav class="sidebar">
<slot></slot> <slot></slot>
</nav> </nav>
<AccountPopup ref="accountPopup"></AccountPopup>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">

View File

@ -1,5 +1,5 @@
<template> <template>
<div @click="() => viewIngressPopup.open()"> <div @click="() => showViewPopup = true">
<p class="grid-element">{{ ingress.metadata.name }}</p> <p class="grid-element">{{ ingress.metadata.name }}</p>
<p class="grid-element">{{ ingress.metadata.namespace }}</p> <p class="grid-element">{{ ingress.metadata.namespace }}</p>
<p class="grid-element">{{ ingress.spec.ingressClassName }}</p> <p class="grid-element">{{ ingress.spec.ingressClassName }}</p>
@ -7,7 +7,7 @@
<div class="grid-element action-buttons"> <div class="grid-element action-buttons">
<ActionButton>delete</ActionButton> <ActionButton>delete</ActionButton>
</div> </div>
<IngressViewPopup :ingress="ingress" ref="viewIngressPopup"></IngressViewPopup> <IngressViewPopup v-if="showViewPopup" :ingress="ingress" ref="viewIngressPopup" @close="showViewPopup = false"></IngressViewPopup>
</div> </div>
</template> </template>
@ -19,5 +19,5 @@ defineProps<{
ingress: Ingress ingress: Ingress
}>(); }>();
const viewIngressPopup = ref(); const showViewPopup = ref(false);
</script> </script>

View File

@ -1,5 +1,5 @@
<template> <template>
<PopupTemplate ref="base" :heading="ingress.metadata?.name + '/' + ingress.metadata?.namespace"> <PopupTemplate ref="base" @close="emits('close')" :heading="StringUtils.format('%s/%s', ingress.metadata.namespace, ingress.metadata.name)">
<div class="col-2"> <div class="col-2">
<div class="content-l"> <div class="content-l">
<h2>General</h2> <h2>General</h2>
@ -36,6 +36,10 @@ defineProps<{
ingress: Ingress ingress: Ingress
}>(); }>();
const emits = defineEmits<{
(e: 'close'): void
}>()
function open() function open()
{ {
base.value.open(); base.value.open();

View File

@ -4,6 +4,7 @@
<div class="header"> <div class="header">
<p>Name</p> <p>Name</p>
<p>Alter</p> <p>Alter</p>
<p>Pods</p>
<p>Status</p> <p>Status</p>
<p>CPU</p> <p>CPU</p>
<p>RAM</p> <p>RAM</p>
@ -23,6 +24,6 @@ const node = ResourceRepo.init<NodeStats>().load('nodes').get();
<style> <style>
.node-container { .node-container {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
} }
</style> </style>

View File

@ -3,14 +3,14 @@
<div class="header"> <div class="header">
<div class="left-center"> <div class="left-center">
<p>Name</p> <p>Name</p>
<UiButton icon="add" class="extra-small" reverse @click="() => secretAddComponent.open()">Add</UiButton> <UiButton v-if="false" icon="add" class="extra-small" reverse @click="() => secretAddComponent.open()">Add</UiButton>
</div> </div>
<p>Namespace</p> <p>Namespace</p>
<p>Alter</p> <p>Alter</p>
<p>Aktionen</p> <p>Aktionen</p>
</div> </div>
<SecretComponent v-for="secret, index in secrets" :secret="secret" class="resource" :class="{ even: index % 2 }"></SecretComponent> <SecretComponent v-for="secret, index in secrets" :secret="secret" class="resource" :class="{ even: index % 2 }"></SecretComponent>
<SecretAddComponent ref="secretAddComponent"></SecretAddComponent> <SecretAddComponent v-if="false" ref="secretAddComponent"></SecretAddComponent>
</div> </div>
</template> </template>

View File

@ -1,6 +1,6 @@
<template> <template>
<div @click="() => podViewPopup.open()"> <div>
<p class="grid-element" v-if="pod.metadata">{{ pod.metadata.name }}</p> <p class="grid-element pointer" v-if="pod.metadata" @click="() => showViewPopup = true">{{ pod.metadata.name }}</p>
<p class="grid-element" v-if="pod.metadata">{{ pod.metadata.namespace }}</p> <p class="grid-element" v-if="pod.metadata">{{ pod.metadata.namespace }}</p>
<p class="grid-element" v-if="pod.metadata">{{ calcAge(pod.metadata.creationTimestamp) }}</p> <p class="grid-element" v-if="pod.metadata">{{ calcAge(pod.metadata.creationTimestamp) }}</p>
<p class="grid-element" v-if="pod.spec">{{ pod.spec.nodeName }}</p> <p class="grid-element" v-if="pod.spec">{{ pod.spec.nodeName }}</p>
@ -8,12 +8,13 @@
<PhaseComponent v-if="pod.status" :phase="pod.status.phase"></PhaseComponent> <PhaseComponent v-if="pod.status" :phase="pod.status.phase"></PhaseComponent>
</div> </div>
<div class="grid-element action-buttons"> <div class="grid-element action-buttons">
<ActionButton @click="() => logPopup.open()">text_snippet</ActionButton> <ActionButton @click="showLogPopup = true">text_snippet</ActionButton>
<ActionButton>open_in_full</ActionButton> <ActionButton>open_in_full</ActionButton>
<ActionButton @click="() => deletePod(pod.metadata?.uid, () => {})" v-if="hasAnyRole(getUser(), ['admin', 'maintainer'])">delete</ActionButton> <ActionButton @click="showDeletePopup = true" v-if="hasAnyRole(getUser(), ['admin', 'maintainer'])">delete</ActionButton>
</div> </div>
<LogPopup :pod="pod" ref="logPopup"></LogPopup> <PodDeletePopup v-if="showDeletePopup" :pod="pod" @close="showDeletePopup = false"></PodDeletePopup>
<PodViewPopup :pod="pod" ref="podViewPopup"></PodViewPopup> <LogPopup v-if="showLogPopup" :pod="pod" @close="showLogPopup = false"></LogPopup>
<PodViewPopup v-if="showViewPopup" :pod="pod" @close="showViewPopup = false"></PodViewPopup>
</div> </div>
</template> </template>
@ -21,13 +22,13 @@
import type { Pod } from '~/classes/Pod'; import type { Pod } from '~/classes/Pod';
import { calcAge } from '~/classes/Pod'; import { calcAge } from '~/classes/Pod';
import { hasAnyRole } from '~/classes/User'; import { hasAnyRole } from '~/classes/User';
import { deletePod } from '~/requests/pod'; import PodDeletePopup from './view/PodDeletePopup.vue';
defineProps<{ defineProps<{
pod: Pod pod: Pod
}>(); }>();
const logPopup = ref(); const showDeletePopup = ref(false);
const showLogPopup = ref(false);
const podViewPopup = ref(); const showViewPopup = ref(false);
</script> </script>

View File

@ -0,0 +1,36 @@
<template>
<PopupTemplate size="SMALL" heading="Delete Pod" @close="emits('close')">
<div class="content-l">
<div class="content-m">
<div class="tile-m">
<h3>Namespace</h3>
<p>{{ pod.metadata.namespace }}</p>
</div>
<div class="tile-m">
<h3>Name</h3>
<p>{{ pod.metadata.name }}</p>
</div>
</div>
<div class="center">
<UiButton class="width-6rem hollow">Cancel</UiButton>
<UiButton class="width-6rem" icon="delete" reverse>Delete</UiButton>
</div>
</div>
</PopupTemplate>
</template>
<script setup lang="ts">
import { type Pod } from '~/classes/Pod';
defineProps<{
pod: Pod
}>();
const emits = defineEmits<{
(e: 'close'): void
}>()
</script>
<style scoped>
</style>

View File

@ -1,5 +1,5 @@
<template> <template>
<PopupTemplate ref="base" :heading="StringUtils.format('%s/%s', pod.metadata.namespace, pod.metadata.name)"> <PopupTemplate ref="base" :heading="StringUtils.format('%s/%s', pod.metadata.namespace, pod.metadata.name)" @close="emits('close')">
<div class="col-2 expand"> <div class="col-2 expand">
<div class="content-l"> <div class="content-l">
<h2>General</h2> <h2>General</h2>
@ -25,7 +25,9 @@
</UiInput> </UiInput>
<ScrollComponent> <ScrollComponent>
<div> <div>
<p class="env" v-for="env, index in filteredEnv">{{ env.key }} = {{ env.value }}</p> <div class="env" v-for="env in filteredEnv">
<UiMask class="spaced-center" :prefix="env.key" :enabled="isSensitive(env.key)" :value="env.value"></UiMask>
</div>
</div> </div>
</ScrollComponent> </ScrollComponent>
</div> </div>
@ -38,12 +40,17 @@ import { calcAge, type Pod } from '~/classes/Pod';
import PhaseComponent from '~/components/PhaseComponent.vue'; import PhaseComponent from '~/components/PhaseComponent.vue';
import { EnvVar } from '../env/EnvVar'; import { EnvVar } from '../env/EnvVar';
import ScrollComponent from '~/components/ScrollComponent.vue'; import ScrollComponent from '~/components/ScrollComponent.vue';
import UiMask from '~/components/ui/UiMask.vue';
const base = ref(); const base = ref();
const props = defineProps<{ const props = defineProps<{
pod: Pod pod: Pod
}>(); }>();
const emits = defineEmits<{
(e: 'close'): void
}>()
const envs: Ref<EnvVar[] | undefined> = ref(undefined); const envs: Ref<EnvVar[] | undefined> = ref(undefined);
onMounted(() => { onMounted(() => {
@ -74,6 +81,19 @@ onMounted(() => {
}) })
defineExpose({ open }); defineExpose({ open });
function isSensitive(key: string)
{
const markers = ["token", "key", "password", "secret", "private", "credential", "auth", "jwt"];
for (const marker of markers)
{
if (key.toLowerCase().includes(marker) && !key.toLowerCase().includes("public"))
{
return true;
}
}
return false;
}
</script> </script>
<style scoped> <style scoped>
@ -87,4 +107,8 @@ defineExpose({ open });
.env:hover { .env:hover {
background-color: #cecece; background-color: #cecece;
} }
.env {
display: grid;
grid-template-columns: auto 1fr;
}
</style> </style>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="overlay center" @click="close" v-show="visible"> <div class="overlay center" @click="close" v-show="visible || true">
<div class="popup" :class="size" @click.stop> <div class="popup" :class="size" @click.stop>
<div class="popup__header"> <div class="popup__header">
<h2>{{ heading }}</h2> <h2>{{ heading }}</h2>
@ -15,8 +15,13 @@
<script lang="ts" setup> <script lang="ts" setup>
const visible = ref(false); const visible = ref(false);
const emits = defineEmits<{
(e: 'close'): void
}>()
function close() { function close() {
enableScrolling(); enableScrolling();
emits('close');
visible.value = false; visible.value = false;
} }
@ -92,4 +97,8 @@ function enableScrolling()
height: auto; height: auto;
width: 740px; width: 740px;
} }
.SMALL {
height: auto;
width: 540px;
}
</style> </style>

View File

@ -44,6 +44,7 @@ const props = defineProps<{
} }
.button:hover { .button:hover {
cursor: pointer; cursor: pointer;
background-color: var(--primary-color-dark);
} }
.button * { .button * {
color: white; color: white;

31
components/ui/UiMask.vue Normal file
View File

@ -0,0 +1,31 @@
<template>
<div class="ui-mask">
<p><span>{{ prefix }}</span>: <span>{{ display }}</span></p>
<UiIcon @click="show = !show" class="pointer" v-if="enabled">visibility</UiIcon>
</div>
</template>
<script setup lang="ts">
const props = defineProps<{
prefix: string,
enabled: boolean,
value: string
}>();
const show = ref(false);
const display = computed(() => {
if (props.enabled && show.value === false)
{
const length = props.value.length;
return "*".repeat(length);
}
return props.value;
})
</script>
<style scoped>
.ui-mask {
gap: 1rem;
}
</style>

View File

@ -5,10 +5,19 @@
<NuxtLink to="/account/inspect/nodes/_all">Inspect</NuxtLink> <NuxtLink to="/account/inspect/nodes/_all">Inspect</NuxtLink>
<NuxtLink to="/account/monitorings/nodes">Monitorings</NuxtLink> <NuxtLink to="/account/monitorings/nodes">Monitorings</NuxtLink>
<NuxtLink to="/account/settings">Settings</NuxtLink> <NuxtLink to="/account/settings">Settings</NuxtLink>
<p class="pointer" @click="logout()">Logout</p>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts">
function logout()
{
useCookie('session').value = null;
useRouter().push('/');
}
</script>
<style scoped> <style scoped>
.account-page { .account-page {
height: 100%; height: 100%;

View File

@ -2,7 +2,7 @@
<div class="login-wrapper"> <div class="login-wrapper">
<div class="tile-l login-window"> <div class="tile-l login-window">
<h2>Kubooboo</h2> <h2>Kubooboo</h2>
<img class="logo" src="@/assets/logo.png" alt=""> <img class="logo" src="@/assets/transparent_logo.png" alt="">
<form class="login content-xl" @submit.prevent="doLogin()"> <form class="login content-xl" @submit.prevent="doLogin()">
<div class="center"> <div class="center">
<h1>Login</h1> <h1>Login</h1>
@ -20,7 +20,6 @@
</div> </div>
</form> </form>
</div> </div>
</div> </div>
</template> </template>