Skip to content

Commit

Permalink
feat(ui): adding progress bar component (#337)
Browse files Browse the repository at this point in the history
  • Loading branch information
BillyFigueroa authored Sep 18, 2024
1 parent 23488f8 commit a36a1ef
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 49 deletions.
43 changes: 43 additions & 0 deletions ui/src/lib/components/ProgressBar/component.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<script lang="ts">
type BarSizeType = 'sm' | 'md' | 'lg' | 'xl'
type UnitType = 'Cores' | 'GB'
export let size: BarSizeType = 'sm'
export let progress: number = 0
export let capacity: number = 0
export let unit: UnitType = 'GB'
let calculatedWidth = 0
let fixedProgress: string
let fixedCapacity: string
$: {
let percentage = (progress / capacity) * 100
fixedProgress = progress.toFixed(2)
fixedCapacity = capacity.toFixed(2)
// Need a minimum width set for rounded corners to look right
calculatedWidth = percentage < 2 ? 2 : percentage
}
$: progressText = `${fixedProgress} ${unit} of ${fixedCapacity} ${unit} used`
const sizeMapping = {
sm: 'h-1.5',
md: 'h-2.5',
lg: 'h-4',
xl: 'h-6',
}
</script>

<div class="flex flex-col">
<div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700 mt-3">
<div
class={`bg-${unit === 'GB' ? 'green' : 'blue'}-600 rounded-full ${sizeMapping[size]}`}
style={`width: ${calculatedWidth}%`}
></div>
</div>

<span class="text-xs mt-1 font-normal text-gray-500 dark:text-gray-400 truncate overflow-ellipsis">
{progressText}
</span>
</div>
7 changes: 5 additions & 2 deletions ui/src/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
// SPDX-FileCopyrightText: 2024-Present The UDS Authors

export { default as AnsiDisplay } from './AnsiDisplay/component.svelte'
export { default as DataTable } from './k8s/DataTable/component.svelte'
export { default as Drawer } from './k8s/Drawer/component.svelte'
export { default as Link } from './Link/component.svelte'
export { default as ProgressBar } from './ProgressBar/component.svelte'
export { default as Tooltip } from './Tooltip/component.svelte'
export { default as LinkCard } from './k8s/Card/LinkCard.svelte'
export { default as Card } from './k8s/Card/component.svelte'
export { default as DataTable } from './k8s/DataTable/component.svelte'
export { default as Drawer } from './k8s/Drawer/component.svelte'
12 changes: 12 additions & 0 deletions ui/src/lib/components/k8s/Card/LinkCard.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
import { goto } from '$app/navigation'
import { Card } from '$components'
export let path: string
</script>

<Card>
<button class="flex flex-col" on:click={() => goto(path)}>
<slot />
</button>
</Card>
5 changes: 5 additions & 0 deletions ui/src/lib/components/k8s/Card/component.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div
class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg hover:dark:bg-gray-700 flex flex-col p-5 sm:p-6"
>
<slot />
</div>
88 changes: 41 additions & 47 deletions ui/src/lib/features/k8s/cluster-overview/component.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
<script lang="ts">
import { onMount } from 'svelte'
import { goto } from '$app/navigation'
import { Card, LinkCard, ProgressBar } from '$components'
import { createEventSource } from '$lib/utils/helpers'
import ApexCharts from 'apexcharts'
import type { ApexOptions } from 'apexcharts'
import { mebibytesToGigabytes, millicoresToCores } from '../helpers'
import './styles.postcss'
type ClusterData = {
Expand Down Expand Up @@ -43,6 +45,10 @@
let cpuPercentage = 0
let memoryPercentage = 0
let gbUsed = 0
let gbCapacity = 0
let cpuUsed = 0
let cpuCapacity = 0
function calculatePercentage(usage: number, capacity: number): number {
if (capacity <= 0) return 0
Expand Down Expand Up @@ -178,14 +184,14 @@
name: 'CPU Usage',
data: (clusterData.historicalUsage ?? []).map((point) => ({
x: new Date(point.Timestamp).getTime(),
y: point.CPU / 1000, // Convert millicores to cores
y: millicoresToCores(point.CPU), // Convert millicores to cores
})),
},
{
name: 'Memory Usage',
data: (clusterData.historicalUsage ?? []).map((point) => ({
x: new Date(point.Timestamp).getTime(),
y: point.Memory / (1024 * 1024 * 1024), // Convert bytes to GB
y: mebibytesToGigabytes(point.Memory), // Convert bytes to GB
})),
},
],
Expand All @@ -201,6 +207,10 @@
cpuPercentage = calculatePercentage(clusterData.currentUsage.CPU, clusterData.cpuCapacity)
memoryPercentage = calculatePercentage(clusterData.currentUsage.Memory, clusterData.memoryCapacity)
gbUsed = mebibytesToGigabytes(clusterData.currentUsage.Memory)
gbCapacity = mebibytesToGigabytes(clusterData.memoryCapacity)
cpuUsed = millicoresToCores(clusterData.currentUsage.CPU)
cpuCapacity = millicoresToCores(clusterData.cpuCapacity)
if (onMessageCount === 0) {
onMessageCount++
Expand All @@ -220,53 +230,37 @@
<div class="p-4 dark:text-white pt-0">
<h1 class="text-2xl font-bold mb-4">Cluster Overview</h1>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<button
class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg hover:dark:bg-gray-700 flex"
on:click={() => goto('/workloads/pods')}
>
<div class="px-4 py-5 sm:p-6 flex flex-col items-start">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">Running Pods</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white">
{clusterData.totalPods}
</dd>
</div>
</button>
<LinkCard path="/workloads/pods">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">Running Pods</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white">
{clusterData.totalPods}
</dd>
</LinkCard>

<button
class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg hover:dark:bg-gray-700 flex"
on:click={() => goto('/nodes')}
>
<div class="px-4 py-5 sm:p-6 flex flex-col items-start">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">Running Nodes</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white" data-testid="node-count">
{clusterData.totalNodes}
</dd>
</div>
</button>
<LinkCard path="/nodes">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">Running Nodes</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white" data-testid="node-count">
{clusterData.totalNodes}
</dd>
</LinkCard>

<div class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">CPU Usage</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white">
{cpuPercentage.toFixed(2)}%
</dd>
<div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700 mt-2">
<div class="bg-blue-600 h-2.5 rounded-full" style="width: {cpuPercentage}%"></div>
</div>
</div>
</div>
<Card>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">CPU Usage</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white">
{cpuPercentage.toFixed(2)}%
</dd>

<div class="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg">
<div class="px-4 py-5 sm:p-6">
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">Memory Usage</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white">
{memoryPercentage.toFixed(2)}%
</dd>
<div class="w-full bg-gray-200 rounded-full h-2.5 dark:bg-gray-700 mt-2">
<div class="bg-green-600 h-2.5 rounded-full" style="width: {memoryPercentage}%"></div>
</div>
</div>
</div>
<ProgressBar size="md" progress={cpuUsed} capacity={cpuCapacity} unit="Cores" />
</Card>

<Card>
<dt class="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">Memory Usage</dt>
<dd class="mt-1 text-3xl font-semibold text-gray-900 dark:text-white">
{memoryPercentage.toFixed(2)}%
</dd>

<ProgressBar size="md" progress={gbUsed} capacity={gbCapacity} unit="GB" />
</Card>
</div>
<div class="mt-8">
<h2 class="text-xl font-bold mb-4">Resource Usage Over Time</h2>
Expand Down
3 changes: 3 additions & 0 deletions ui/src/lib/features/k8s/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ const k8StatusMapping: K8StatusMapping = {
export const getColorAndStatus = <T extends keyof K8StatusMapping>(type: T, status: keyof K8StatusMapping[T]) => {
return (k8StatusMapping[type][status] as { color: string }).color || 'Unknown'
}

export const mebibytesToGigabytes = (value: number) => value / (1024 * 1024 * 1024)
export const millicoresToCores = (value: number) => value / 1000

0 comments on commit a36a1ef

Please sign in to comment.