Skip to content

Commit

Permalink
feat(ui): adding events tab (#342)
Browse files Browse the repository at this point in the history
  • Loading branch information
BillyFigueroa authored Sep 20, 2024
1 parent 2981598 commit cb9b43a
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 6 deletions.
2 changes: 2 additions & 0 deletions ui/src/lib/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ 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'
export { default as EventList } from './k8s/Event/EventList.svelte'
export { default as Event } from './k8s/Event/component.svelte'
22 changes: 19 additions & 3 deletions ui/src/lib/components/k8s/Drawer/component.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
<script lang="ts">
import { onMount } from 'svelte'
import type { KubernetesObject } from '@kubernetes/client-node'
import type { CoreV1Event, KubernetesObject } from '@kubernetes/client-node'
import { goto } from '$app/navigation'
import { EventList } from '$components'
import { Close } from 'carbon-icons-svelte'
import DOMPurify from 'dompurify'
import hljs from 'highlight.js/lib/core'
Expand All @@ -19,12 +20,21 @@
type Tab = 'metadata' | 'yaml' | 'events'
let events: CoreV1Event[] = []
onMount(() => {
// initialize highlight language
hljs.registerLanguage('yaml', yaml)
const path: string = '/api/v1/resources/events?fields=.count,.involvedObject,.message,.source,.type'
const eventSource = new EventSource(path)
eventSource.onmessage = (event) => {
events = JSON.parse(event.data) as CoreV1Event[]
}
const handleKeydown = (e: KeyboardEvent) => {
const tabList: Tab[] = ['metadata', 'yaml', 'events']
const tabList: Tab[] = ['metadata', 'events', 'yaml']
let targetTab: string | undefined
switch (e.key) {
Expand Down Expand Up @@ -56,6 +66,7 @@
// Clean up the event listener when the component is destroyed
return () => {
window.removeEventListener('keydown', handleKeydown)
eventSource.close()
}
})
Expand All @@ -78,7 +89,7 @@
let activeTab: Tab = 'metadata'
function setActiveTab(evt: Event) {
function setActiveTab(evt: MouseEvent) {
const target = evt.target as HTMLButtonElement
activeTab = target.id as Tab
}
Expand Down Expand Up @@ -111,6 +122,9 @@
<li class="flex-1">
<button id="metadata" class:active={activeTab === 'metadata'} on:click={setActiveTab}>Metadata</button>
</li>
<li class="flex-1">
<button id="events" class:active={activeTab === 'events'} on:click={setActiveTab}>Events</button>
</li>
<li class="flex-1">
<button id="yaml" class:active={activeTab === 'yaml'} on:click={setActiveTab}>YAML</button>
</li>
Expand Down Expand Up @@ -159,6 +173,8 @@
{/if}
</dl>
</div>
{:else if activeTab === 'events'}
<EventList {events} {resource} />
{:else if activeTab === 'yaml'}
<!-- YAML tab -->
<div class="text-gray-200 p-4">
Expand Down
24 changes: 24 additions & 0 deletions ui/src/lib/components/k8s/Event/EventList.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
import type { CoreV1Event, KubernetesObject } from '@kubernetes/client-node'
import { Event } from '$components'
export let events: CoreV1Event[]
export let resource: KubernetesObject
let filteredEvents: CoreV1Event[] = []
$: filteredEvents =
events?.filter((event: CoreV1Event) => event.involvedObject.name === resource.metadata?.name) || []
</script>

<div class="m-6">
{#if filteredEvents.length === 0}
<span>No events.</span>
{:else}
{#each filteredEvents as event}
<div class="my-6">
<Event {event} />
</div>
{/each}
{/if}
</div>
46 changes: 46 additions & 0 deletions ui/src/lib/components/k8s/Event/component.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script lang="ts">
import type { CoreV1Event } from '@kubernetes/client-node'
import { ChevronRight } from 'carbon-icons-svelte'
export let event: CoreV1Event
let toggled = false
const renderSource = () => {
if (event.source && Object.keys(event.source).length !== 0) {
return `${event.source.component} ${event.source.host}`
}
return '<unknown>'
}
</script>

<div class="flex flex-col">
<div class="flex">
<button class="mr-2" on:click={() => (toggled = !toggled)}>
<ChevronRight class="expanded-only h-6 w-6 transition {toggled ? 'rotate-90 transform' : ''} duration-300" />
</button>
<div>
<span class={`${event.type === 'Warning' ? 'text-red-600' : ''}`}>{event.message}</span>
</div>
</div>

<div class={`${toggled ? '' : 'hidden'}`}>
<dl class="mt-3 space-y-4 ml-6">
<div class="flex flex-col sm:flex-row gap-9 border-b border-gray-700 pb-2">
<dt class="font-bold text-sm flex-none w-[180px]">Source</dt>
<dd class="text-gray-400">{renderSource()}</dd>
</div>

<div class="flex flex-col sm:flex-row gap-9 border-b border-gray-700 pb-2">
<dt class="font-bold text-sm flex-none w-[180px]">Count</dt>
<dd class="text-gray-400">{event?.count || '-'}</dd>
</div>

<div class="flex flex-col sm:flex-row gap-9 border-b border-gray-700 pb-2">
<dt class="font-bold text-sm flex-none w-[180px]">Sub-object</dt>
<dd class="text-gray-400">{event.involvedObject?.fieldPath || '-'}</dd>
</div>
</dl>
</div>
</div>
3 changes: 0 additions & 3 deletions ui/src/lib/features/k8s/workloads/pods/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ export function createStore(): ResourceStoreInterface<Resource, Row> {
const key = `${d.resource.metadata?.namespace}/${d.resource.metadata?.name}`
const metric = metrics.get(key)

console.log('metric')
console.log(metric)

if (metric?.containers) {
d.table.usage.sort = metric.containers.reduce((sum, container) => sum + parseCPU(container.usage.cpu), 0)
d.table.usage.props.containers = metric.containers
Expand Down
9 changes: 9 additions & 0 deletions ui/tests/drawer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ test.describe('Drawer', async () => {
await expect(drawerEl.getByText('podinfo', { exact: true })).toBeVisible()
})

test('will display Events details', async ({ page }) => {
const drawerEl = page.getByTestId('drawer')

await expect(drawerEl).toBeVisible()
await drawerEl.getByRole('button', { name: 'Events' }).click()

await expect(drawerEl.getByText('Created container podinfo')).toBeVisible()
})

test('will display YAML details', async ({ page }) => {
const drawerEl = page.getByTestId('drawer')
const labelName = await drawerEl.locator(':text("app.kubernetes.io/name:")').textContent()
Expand Down

0 comments on commit cb9b43a

Please sign in to comment.