Minor improvements

This commit is contained in:
Andreas Dinauer 2025-12-20 14:00:56 +01:00
parent 48780e5164
commit b593189a9a
22 changed files with 170 additions and 34 deletions

View File

@ -5,11 +5,19 @@ export class Deployment implements HasMetadata
{
constructor (
public metadata: Metadata,
public spec: DeploymentSpec
public spec: DeploymentSpec,
public status: DeploymentStatus
) {}
}
export class DeploymentSpec
{
replicas?: number;
}
export class DeploymentStatus
{
replicas?: number;
availableReplicas?: number;
readyReplicas?: number;
}

View File

@ -4,6 +4,8 @@ import type { HasMetadata } from "./repo/ResourceRepo";
export class Secret implements HasMetadata
{
constructor (
public metadata: Metadata
public metadata: Metadata,
public type: string,
public data?: Record<string, string>,
) { }
}

View File

@ -1,6 +1,6 @@
<template>
<div>
<p class="grid-element">{{ deployment.metadata.name }}</p>
<p class="grid-element" @click="() => showViewPopup = true">{{ deployment.metadata.name }}</p>
<p class="grid-element">{{ deployment.metadata.namespace }}</p>
<p class="grid-element">{{ calcAge(deployment.metadata.creationTimestamp) }}</p>
<p class="grid-element">{{ deployment.spec.replicas }}</p>
@ -10,17 +10,20 @@
<ActionButton @click="() => rescaleDeploymentPopup.open()">height</ActionButton>
</div>
<RescaleDeploymentPopup ref="rescaleDeploymentPopup" :deployment="deployment"></RescaleDeploymentPopup>
<DeploymentViewPopup v-if="showViewPopup" :deployment="deployment" @close="() => showViewPopup = false"></DeploymentViewPopup>
</div>
</template>
<script setup lang="ts">
import { Deployment } from '~/classes/Deployment';
import RescaleDeploymentPopup from '../RescaleDeploymentPopup.vue';
import { calcAge } from '~/classes/Pod';
import RescaleDeploymentPopup from '../RescaleDeploymentPopup.vue';
import DeploymentViewPopup from "~/components/deployment/view/DeploymentViewPopup.vue";
defineProps<{
deployment: Deployment
}>();
const rescaleDeploymentPopup = ref();
const showViewPopup = ref(false);
</script>

View File

@ -1,11 +1,67 @@
<template>
<PopupTemplate>
<PopupTemplate :heading="StringUtils.format('%s/%s', deployment.metadata.namespace, deployment.metadata.name)" @close="emits('close')">
<div class="content-l">
<h2>General</h2>
<div class="content-m">
<h3>Deployment</h3>
<p class="tile-m">{{ deployment.metadata.namespace }}/{{ deployment.metadata.name }}</p>
</div>
<div class="col-4">
<div class="content-m">
<h3>Desired Replicas</h3>
<p class="tile-m">{{ deployment.spec.replicas }}</p>
</div>
<div class="content-m">
<h3>Current Replicas</h3>
<p class="tile-m">{{ deployment.status.replicas }}</p>
</div>
<div class="content-m">
<h3>Available Replicas</h3>
<p class="tile-m">{{ deployment.status.availableReplicas }}</p>
</div>
<div class="content-m">
<h3>Ready Replicas</h3>
<p class="tile-m">{{ deployment.status.readyReplicas }}</p>
</div>
</div>
<div class="content-m">
<h3>Annotations (<span v-if="deployment.metadata.annotations">{{ Object.keys(deployment.metadata.annotations).length }}</span><span v-else>0</span>)</h3>
<div class="left-center" v-if="deployment.metadata.annotations">
<div class="content-m">
<p class="tile-m" v-for="[key, value] in Object.entries(deployment.metadata.annotations)"><span>{{ key }}:</span>&nbsp;<span style="overflow-wrap:anywhere; white-space: normal; width: 100%;">{{ value }}</span></p>
</div>
</div>
</div>
<div class="content-m">
<h3>Labels (<span v-if="deployment.metadata.labels">{{ Object.keys(deployment.metadata.labels).length }}</span><span v-else>0</span>)</h3>
<div class="content-m" v-if="deployment.metadata.labels">
<p class="tile-m" v-for="[key, value] in Object.entries(deployment.metadata.labels)"><span>{{ key }}:</span>&nbsp;<span>{{ value }}</span></p>
</div>
</div>
</div>
</PopupTemplate>
</template>
<script setup lang="ts">
import PopupTemplate from "~/components/popup/PopupTemplate.vue";
import type { Deployment } from "~/classes/Deployment";
defineProps<{
deployment: Deployment
}>()
const emits = defineEmits<{
(e: 'close'): void
}>()
onMounted(() => {
document.addEventListener('keydown', (event) => {
if(event.key === 'Escape')
{
emits('close');
}
});
})
</script>
<style scoped>

View File

@ -6,9 +6,9 @@
<p>Namespace</p>
<p>Age</p>
<p>Entries</p>
<p>Aktionen</p>
<p>Actions</p>
</div>
<ConfigMapComponent v-for="configMap, index in configMaps" :config-map="configMap" class="resource" :class="{ even: index % 2 }"></ConfigMapComponent>
<ConfigMapComponent v-for="(configMap, index) in configMaps" :config-map="configMap" class="resource" :class="{ even: index % 2 }"></ConfigMapComponent>
</div>
</TableComponent>
</template>

View File

@ -3,9 +3,9 @@
<div class="resource-container crd-container">
<div class="header">
<p>Name</p>
<p>Gruppe</p>
<p>Group</p>
</div>
<div v-for="customResourceDefinition, index in customResourceDefinitions" class="resource" :class="{ even: index % 2 }">
<div v-for="(customResourceDefinition, index) in customResourceDefinitions" class="resource" :class="{ even: index % 2 }">
<p class="grid-element">{{ customResourceDefinition.metadata.name }}</p>
<p class="grid-element">{{ customResourceDefinition.spec.group }}</p>
</div>

View File

@ -8,7 +8,7 @@
<p>Replicas</p>
<p>Aktionen</p>
</div>
<DeploymentComponent :deployment="deployment" v-for="deployment, index in deployments" class="resource" :class="{ even: index % 2 }"></DeploymentComponent>
<DeploymentComponent :deployment="deployment" v-for="(deployment, index) in deployments" class="resource" :class="{ even: index % 2 }"></DeploymentComponent>
</div>
</TableComponent>
</template>
@ -16,11 +16,11 @@
<script setup lang="ts">
import type { Deployment } from '~/classes/Deployment';
import { ResourceRepo } from '~/classes/repo/ResourceRepo';
import DeploymentComponent from '~/components/deployment/DeploymentComponent.vue';
import DeploymentComponent from "~/components/deployment/DeploymentComponent.vue";
const repo = ResourceRepo.init<Deployment>();
onMounted(() => {
repo.listen("deployment");
repo.listen("deployments");
});
onUnmounted(() => {
repo.clear();

View File

@ -9,7 +9,7 @@
<p>Rules</p>
<p>Actions</p>
</div>
<IngressComponent :ingress="ingress" v-for="ingress, index in ingresses" class="resource" :class="{ even: index % 2 }"></IngressComponent>
<IngressComponent :ingress="ingress" v-for="(ingress, index) in ingresses" class="resource" :class="{ even: index % 2 }"></IngressComponent>
</div>
</TableComponent>
</template>

View File

@ -6,7 +6,7 @@
<p>Age</p>
<p>Actions</p>
</div>
<NamespaceComponent :namespace="namespace" v-for="namespace, index in namespaces" class="resource" :class="{ even: index % 2 }"></NamespaceComponent>
<NamespaceComponent :namespace="namespace" v-for="(namespace, index) in namespaces" class="resource" :class="{ even: index % 2 }"></NamespaceComponent>
</div>
</TableComponent>
</template>

View File

@ -3,14 +3,14 @@
<div class="resource-container node-container">
<div class="header">
<p>Name</p>
<p>Alter</p>
<p>Age</p>
<p>Pods</p>
<p>Status</p>
<p>CPU</p>
<p>Memory</p>
<p>Disk Usage</p>
</div>
<NodeComponent :node-stats="ns" v-for="ns, index in node" class="resource" :class="{ even: index % 2 }"></NodeComponent>
<NodeComponent :node-stats="ns" v-for="(ns, index) in node" class="resource" :class="{ even: index % 2 }"></NodeComponent>
</div>
</TableComponent>
</template>

View File

@ -7,9 +7,9 @@
<p>Age</p>
<p>Storage Class</p>
<p>Access Modes</p>
<p>Aktionen</p>
<p>Actions</p>
</div>
<PersistentVolumeClaimComponent v-for="persistentVolumeClaim, index in persistentVolumeClaims" :persistent-volume-claim="persistentVolumeClaim" class="resource" :class="{ even: index % 2 }"></PersistentVolumeClaimComponent>
<PersistentVolumeClaimComponent v-for="(persistentVolumeClaim, index) in persistentVolumeClaims" :persistent-volume-claim="persistentVolumeClaim" class="resource" :class="{ even: index % 2 }"></PersistentVolumeClaimComponent>
</div>
</TableComponent>
</template>

View File

@ -4,9 +4,9 @@
<div class="header">
<p>Name</p>
<p>Age</p>
<p>Aktionen</p>
<p>Actions</p>
</div>
<PersistentVolumeComponent v-for="persistentVolume, index in persistentVolumes" :persistent-volume="persistentVolume" class="resource" :class="{ even: index % 2 }"></PersistentVolumeComponent>
<PersistentVolumeComponent v-for="(persistentVolume, index) in persistentVolumes" :persistent-volume="persistentVolume" class="resource" :class="{ even: index % 2 }"></PersistentVolumeComponent>
</div>
</TableComponent>
</template>

View File

@ -8,9 +8,9 @@
<p>Node</p>
<p>Containers</p>
<p>Status</p>
<p>Aktionen</p>
<p>Actions</p>
</div>
<PodComponent v-for="pod, index in pods" :pod="pod" class="resource" :class="{ even: index % 2 }"></PodComponent>
<PodComponent v-for="(pod, index) in pods" :pod="pod" class="resource" :class="{ even: index % 2 }"></PodComponent>
</div>
</TableComponent>
</template>

View File

@ -8,9 +8,11 @@
</div>
<p>Namespace</p>
<p>Age</p>
<p>Aktionen</p>
<p>Type</p>
<p>Entries</p>
<p>Actions</p>
</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>
</div>
</TableComponent>
</template>
@ -35,6 +37,6 @@ const secretAddComponent = ref();
<style scoped>
.secret-container {
display: grid;
grid-template-columns: auto auto 1fr auto;
grid-template-columns: auto auto auto auto 1fr auto;
}
</style>

View File

@ -6,9 +6,9 @@
<p>Namespace</p>
<p>Age</p>
<p>Type</p>
<p>Aktionen</p>
<p>Actions</p>
</div>
<ServiceComponent :service="service" v-for="service, index in services" class="resource" :class="{ even: index % 2 }"></ServiceComponent>
<ServiceComponent :service="service" v-for="(service, index) in services" class="resource" :class="{ even: index % 2 }"></ServiceComponent>
</div>
</TableComponent>
</template>

View File

@ -5,9 +5,9 @@
<p>Name</p>
<p>Namespace</p>
<p>Replicas</p>
<p>Aktionen</p>
<p>Actions</p>
</div>
<StatefulSetComponent :stateful-set="statefulSet" v-for="statefulSet, index in statefulSets" class="resource" :class="{ even: index % 2 }"></StatefulSetComponent>
<StatefulSetComponent :stateful-set="statefulSet" v-for="(statefulSet, index) in statefulSets" class="resource" :class="{ even: index % 2 }"></StatefulSetComponent>
</div>
</TableComponent>
</template>

View File

@ -1,22 +1,28 @@
<template>
<div class="resource">
<p class="grid-element">{{ secret.metadata.name }}</p>
<p class="grid-element" @click="() => showViewPopup = true">{{ secret.metadata.name }}</p>
<p class="grid-element">{{ secret.metadata.namespace }}</p>
<p class="grid-element">{{ calcAge(secret.metadata.creationTimestamp) }}</p>
<p class="grid-element">{{ secret.type }}</p>
<p class="grid-element"><span v-if="secret.data">{{ Object.keys(secret.data).length }}</span><span v-else>-</span></p>
<div class="grid-element action-buttons">
<ActionButton>edit</ActionButton>
<ActionButton>delete</ActionButton>
</div>
<SecretViewPopup :secret="secret" v-if="showViewPopup" @close="() => showViewPopup = false"></SecretViewPopup>
</div>
</template>
<script setup lang="ts">
import { calcAge } from '~/classes/Pod';
import type { Secret } from '~/classes/Secret';
import SecretViewPopup from "~/components/secrets/view/SecretViewPopup.vue";
defineProps<{
secret: Secret
}>();
const showViewPopup = ref(false);
</script>
<style scoped>

View File

@ -0,0 +1,40 @@
<template>
<PopupTemplate :heading="StringUtils.format('%s/%s', secret.metadata.namespace, secret.metadata.name)" @close="emits('close')">
<div class="content-l">
<h3>General</h3>
<div class="content-m">
<h3>Secret</h3>
<p class="tile-m">{{ secret.metadata.namespace }}/{{ secret.metadata.name }}</p>
</div>
<h3>Data</h3>
<div class="content-m">
<UiMask class="tile-m" v-if="secret.data" v-for="[key, value] in Object.entries(secret.data)" :enabled="true" :prefix="key" :value="base64.decode(value)"></UiMask>
</div>
</div>
</PopupTemplate>
</template>
<script setup lang="ts">
import type {Secret} from "~/classes/Secret";
import UiMask from "~/components/ui/UiMask.vue";
import base64 from 'base-64';
defineProps<{
secret: Secret
}>();
const emits = defineEmits<{
(e: 'close'): void
}>()
onMounted(() => {
document.addEventListener('keydown', (event) => {
if(event.key === 'Escape')
{
emits('close');
}
});
})
defineExpose({ open });
</script>

View File

@ -1,5 +1,5 @@
<template>
<div class="ui-mask">
<div class="ui-mask left-center">
<p><span>{{ prefix }}</span>: <span>{{ display }}</span></p>
<UiIcon @click="show = !show" class="pointer" v-if="enabled">visibility</UiIcon>
</div>

15
package-lock.json generated
View File

@ -9,6 +9,7 @@
"dependencies": {
"@pinia/nuxt": "^0.11.0",
"axios": "^1.9.0",
"base-64": "^1.0.0",
"chart.js": "^4.5.0",
"chartjs-adapter-luxon": "^1.3.1",
"chartjs-adapter-moment": "^1.0.1",
@ -20,6 +21,9 @@
"pinia": "^3.0.2",
"vue": "^3.5.15",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@types/base-64": "^1.0.2"
}
},
"node_modules/@ampproject/remapping": {
@ -2958,6 +2962,12 @@
"tslib": "^2.4.0"
}
},
"node_modules/@types/base-64": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/base-64/-/base-64-1.0.2.tgz",
"integrity": "sha512-uPgKMmM9fmn7I+Zi6YBqctOye4SlJsHKcisjHIMWpb2YKZRc36GpKyNuQ03JcT+oNXg1m7Uv4wU94EVltn8/cw==",
"dev": true
},
"node_modules/@types/estree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
@ -3758,6 +3768,11 @@
"integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==",
"optional": true
},
"node_modules/base-64": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
"integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",

View File

@ -12,6 +12,7 @@
"dependencies": {
"@pinia/nuxt": "^0.11.0",
"axios": "^1.9.0",
"base-64": "^1.0.0",
"chart.js": "^4.5.0",
"chartjs-adapter-luxon": "^1.3.1",
"chartjs-adapter-moment": "^1.0.1",
@ -23,5 +24,8 @@
"pinia": "^3.0.2",
"vue": "^3.5.15",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@types/base-64": "^1.0.2"
}
}

View File

@ -3,7 +3,7 @@
<CustomResourceDefinitionComponent v-else-if="resource === 'custom-resource-definitions'"></CustomResourceDefinitionComponent>
<IngressComponent v-else-if="resource === 'ingresses'"></IngressComponent>
<ServiceComponent v-else-if="resource === 'services'"></ServiceComponent>
<DeploymentComponent v-else-if="resource === 'deployment'"></DeploymentComponent>
<DeploymentList v-else-if="resource === 'deployments'"></DeploymentList>
<NodeComponent v-else-if="resource === 'nodes'"></NodeComponent>
<SecretComponent v-else-if="resource === 'secrets'"></SecretComponent>
<ConfigMapList v-else-if="resource === 'config-maps'"></ConfigMapList>
@ -19,7 +19,7 @@ import PodComponent from '~/components/inspect/resources/PodList.vue';
import CustomResourceDefinitionComponent from '~/components/inspect/resources/CustomResourceDefinitionList.vue';
import IngressComponent from '~/components/inspect/resources/IngressList.vue';
import ServiceComponent from '~/components/inspect/resources/ServiceList.vue';
import DeploymentComponent from '~/components/inspect/resources/DeploymentList.vue';
import DeploymentList from "~/components/inspect/resources/DeploymentList.vue";
import NodeComponent from '~/components/inspect/resources/NodeList.vue';
import SecretComponent from '~/components/inspect/resources/SecretList.vue';
import ConfigMapList from '~/components/inspect/resources/ConfigMapList.vue';