🩹 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 {
--primary-color: rgb(87, 75, 255);
--primary-color-dark: rgb(69, 57, 241);
--tile-color: #ebf1ff;
background-color: rgb(255, 255, 255);
--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 (
public node: Node,
public runningPods: number
) { }
relativeCpuUsage?: number;

View File

@ -1,5 +1,5 @@
<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">
<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>
@ -25,20 +25,25 @@ const props = defineProps<{
pod: Pod
}>();
const emits = defineEmits<{
(e: 'close'): void
}>()
const scrollComponent = ref();
function open()
{
logs.value = undefined;
base.value.open();
getLogs(props.pod.metadata?.uid, (_logs: Log[]) => {
onMounted(() => {
getLogs(props.pod.metadata.uid, (_logs: Log[]) => {
logs.value = _logs;
scrollComponent.value.scrollToBottom();
});
}
});
defineExpose({
open
onMounted(() => {
document.addEventListener('keydown', (event) => {
if(event.key === 'Escape')
{
emits('close');
}
});
})
</script>

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
<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="content-l">
<h2>General</h2>
@ -36,6 +36,10 @@ defineProps<{
ingress: Ingress
}>();
const emits = defineEmits<{
(e: 'close'): void
}>()
function open()
{
base.value.open();

View File

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

View File

@ -3,14 +3,14 @@
<div class="header">
<div class="left-center">
<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>
<p>Namespace</p>
<p>Alter</p>
<p>Aktionen</p>
</div>
<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>
</template>

View File

@ -1,6 +1,6 @@
<template>
<div @click="() => podViewPopup.open()">
<p class="grid-element" v-if="pod.metadata">{{ pod.metadata.name }}</p>
<div>
<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">{{ calcAge(pod.metadata.creationTimestamp) }}</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>
</div>
<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 @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>
<LogPopup :pod="pod" ref="logPopup"></LogPopup>
<PodViewPopup :pod="pod" ref="podViewPopup"></PodViewPopup>
<PodDeletePopup v-if="showDeletePopup" :pod="pod" @close="showDeletePopup = false"></PodDeletePopup>
<LogPopup v-if="showLogPopup" :pod="pod" @close="showLogPopup = false"></LogPopup>
<PodViewPopup v-if="showViewPopup" :pod="pod" @close="showViewPopup = false"></PodViewPopup>
</div>
</template>
@ -21,13 +22,13 @@
import type { Pod } from '~/classes/Pod';
import { calcAge } from '~/classes/Pod';
import { hasAnyRole } from '~/classes/User';
import { deletePod } from '~/requests/pod';
import PodDeletePopup from './view/PodDeletePopup.vue';
defineProps<{
pod: Pod
}>();
const logPopup = ref();
const podViewPopup = ref();
const showDeletePopup = ref(false);
const showLogPopup = ref(false);
const showViewPopup = ref(false);
</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>
<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="content-l">
<h2>General</h2>
@ -25,7 +25,9 @@
</UiInput>
<ScrollComponent>
<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>
</ScrollComponent>
</div>
@ -38,6 +40,7 @@ import { calcAge, type Pod } from '~/classes/Pod';
import PhaseComponent from '~/components/PhaseComponent.vue';
import { EnvVar } from '../env/EnvVar';
import ScrollComponent from '~/components/ScrollComponent.vue';
import UiMask from '~/components/ui/UiMask.vue';
const base = ref();
@ -45,6 +48,10 @@ const props = defineProps<{
pod: Pod
}>();
const emits = defineEmits<{
(e: 'close'): void
}>()
const envs: Ref<EnvVar[] | undefined> = ref(undefined);
onMounted(() => {
EnvVar.get(props.pod.metadata.namespace, props.pod.metadata.name, (_envs: EnvVar[]) => {
@ -74,6 +81,19 @@ onMounted(() => {
})
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>
<style scoped>
@ -87,4 +107,8 @@ defineExpose({ open });
.env:hover {
background-color: #cecece;
}
.env {
display: grid;
grid-template-columns: auto 1fr;
}
</style>

View File

@ -1,5 +1,5 @@
<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__header">
<h2>{{ heading }}</h2>
@ -15,8 +15,13 @@
<script lang="ts" setup>
const visible = ref(false);
const emits = defineEmits<{
(e: 'close'): void
}>()
function close() {
enableScrolling();
emits('close');
visible.value = false;
}
@ -92,4 +97,8 @@ function enableScrolling()
height: auto;
width: 740px;
}
.SMALL {
height: auto;
width: 540px;
}
</style>

View File

@ -44,6 +44,7 @@ const props = defineProps<{
}
.button:hover {
cursor: pointer;
background-color: var(--primary-color-dark);
}
.button * {
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/monitorings/nodes">Monitorings</NuxtLink>
<NuxtLink to="/account/settings">Settings</NuxtLink>
<p class="pointer" @click="logout()">Logout</p>
</div>
</div>
</template>
<script setup lang="ts">
function logout()
{
useCookie('session').value = null;
useRouter().push('/');
}
</script>
<style scoped>
.account-page {
height: 100%;

View File

@ -2,7 +2,7 @@
<div class="login-wrapper">
<div class="tile-l login-window">
<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()">
<div class="center">
<h1>Login</h1>
@ -20,7 +20,6 @@
</div>
</form>
</div>
</div>
</template>