Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

Previous changes not listed in this document can be traced using Git history.

## [1.0.24] - 2026-05-11

### Changed
- `Notifications` component has been replaced by `Notifications` widget

## [1.0.23] - 2026-04-28

### Fixed
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ The file should have this content:
"SNOWPLOW_API_BASE_URL": "http://localhost:30081",
"EVENTS_API_BASE_URL": "http://localhost:30083",
"ROUTES_LOADER": "/call?resource=routesloaders&apiVersion=widgets.templates.krateo.io/v1beta1&name=routes-loader&namespace=krateo-system",
"NOTIFICATIONS_WIDGET": "/call?resource=notifications&apiVersion=widgets.templates.krateo.io/v1beta1&name=notifications&namespace=krateo-system",
"EVENTS_PUSH_API_BASE_URL": "http://localhost:30083",
"INIT": "/call?resource=navmenus&apiVersion=widgets.templates.krateo.io/v1beta1&name=sidebar-nav-menu&namespace=krateo-system"
},
Expand Down
1 change: 1 addition & 0 deletions docs/theme.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ config:
SNOWPLOW_API_BASE_URL: "" # should be mapped to snowplow service
EVENTS_PUSH_API_BASE_URL: "" # should be mapped to eventsse service
EVENTS_API_BASE_URL: "" # should be mapped to eventsse service
NOTIFICATIONS_WIDGET: ""
ROUTES_LOADER: ""
INIT: ""
THEME: "/call?resource=themes&apiVersion=widgets.templates.krateo.io/v1beta1&name=dark-theme&namespace=krateo-system"
Expand Down
1 change: 1 addition & 0 deletions public/config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"AUTHN_API_BASE_URL": "http://localhost:30082",
"SNOWPLOW_API_BASE_URL": "http://localhost:30081",
"EVENTS_API_BASE_URL": "http://34.154.63.171:8083",
"NOTIFICATIONS_WIDGET": "/call?resource=notifications&apiVersion=widgets.templates.krateo.io/v1beta1&name=example-notifications-basic&namespace=krateo-system",
"ROUTES_LOADER": "/call?resource=routesloaders&apiVersion=widgets.templates.krateo.io/v1beta1&name=routes-loader&namespace=krateo-system",
"EVENTS_PUSH_API_BASE_URL": "http://34.154.63.171:8083",
"INIT": "/call?resource=navmenus&apiVersion=widgets.templates.krateo.io/v1beta1&name=sidebar-nav-menu&namespace=krateo-system"
Expand Down
7 changes: 5 additions & 2 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Header as AntdHeader } from 'antd/es/layout/layout'

import { useConfigContext } from '../../context/ConfigContext'
import Breadcrumb from '../Breadcrumb'
import Notifications from '../Notifications'
import UserMenu from '../UserMenu'
import WidgetRenderer from '../WidgetRenderer'

import styles from './Header.module.css'

Expand All @@ -11,14 +12,16 @@ type HeaderProps = {
}

const Header = ({ breadcrumbVisible = true }: HeaderProps) => {
const { config } = useConfigContext()

return (
<AntdHeader className={styles.header}>
<div className={styles.content}>
<div className={styles.left}>
{breadcrumbVisible && <Breadcrumb />}
</div>
<div className={styles.right}>
<Notifications />
<WidgetRenderer widgetEndpoint={config!.api.NOTIFICATIONS_WIDGET} />
<UserMenu />
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/components/WidgetRenderer/WidgetRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import Markdown from '../../widgets/Markdown'
import type { MarkdownWidgetData } from '../../widgets/Markdown/Markdown'
import type { NavMenuWidgetData } from '../../widgets/NavMenu/NavMenu'
import { NavMenu } from '../../widgets/NavMenu/NavMenu'
import type { NotificationsWidgetData } from '../../widgets/Notifications/Notifications'
import Notifications from '../../widgets/Notifications/Notifications'
import { Page, type PageWidgetData } from '../../widgets/Page/Page'
import type { PanelWidgetData } from '../../widgets/Panel/Panel'
import Panel from '../../widgets/Panel/Panel'
Expand Down Expand Up @@ -131,6 +133,8 @@ const parseWidget = (
return <Markdown {...props} widgetData={widgetData as MarkdownWidgetData} />
case 'NavMenu':
return <NavMenu {...props} widgetData={widgetData as NavMenuWidgetData} />
case 'Notifications':
return <Notifications {...props} widgetData={widgetData as NotificationsWidgetData} />
case 'Page':
return <Page {...props} widgetData={widgetData as PageWidgetData} />
case 'Panel':
Expand Down
1 change: 1 addition & 0 deletions src/context/ConfigContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export interface Config {
SNOWPLOW_API_BASE_URL: string
EVENTS_API_BASE_URL: string
EVENTS_PUSH_API_BASE_URL: string
NOTIFICATIONS_WIDGET: string
ROUTES_LOADER: string
INIT: string
THEME?: string
Expand Down
6 changes: 6 additions & 0 deletions src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ interface ImportMetaEnv {
interface ImportMeta {
readonly env: ImportMetaEnv
}
declare module '*.module.css' {
const classes: Record<string, string>
export default classes
}

declare module '*.css'
9 changes: 9 additions & 0 deletions src/examples/widgets/Notifications/Notifications.example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Basic Notifications
# Expected behavior: Displays a Notifications component
kind: Notifications
apiVersion: widgets.templates.krateo.io/v1beta1
metadata:
name: example-notifications-basic
namespace: krateo-system
spec:
widgetData: {}
77 changes: 77 additions & 0 deletions src/examples/widgets/Notifications/Notifications.menu.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
kind: NavMenuItem
apiVersion: widgets.templates.krateo.io/v1beta1
metadata:
name: example-notifications-navmenuitem
namespace: krateo-system
spec:
widgetData:
allowedResources:
- pages
resourceRefId: example-notifications-page
label: Notifications
icon: fa-bell
path: /notifications
resourcesRefs:
items:
- id: example-notifications-page
apiVersion: widgets.templates.krateo.io/v1beta1
name: example-notifications-page
namespace: krateo-system
resource: pages
verb: GET
---
kind: Page
apiVersion: widgets.templates.krateo.io/v1beta1
metadata:
name: example-notifications-page
namespace: krateo-system
spec:
widgetData:
allowedResources:
- eventlists
- buttons
- columns
- datagrids
- eventlists
- filters
- flowcharts
- forms
- linecharts
- markdowns
- panels
- paragraphs
- piecharts
- rows
- tables
- tablists
- yamlviewers
items:
- resourceRefId: example-notifications-basic-panel
resourcesRefs:
items:
- id: example-notifications-basic-panel
apiVersion: widgets.templates.krateo.io/v1beta1
name: example-notifications-basic-panel
namespace: krateo-system
resource: panels
verb: GET
---
kind: Panel
apiVersion: widgets.templates.krateo.io/v1beta1
metadata:
name: example-notifications-basic-panel
namespace: krateo-system
spec:
widgetData:
actions: {}
title: 'Basic Notifications'
items:
- resourceRefId: example-notifications-basic
resourcesRefs:
items:
- id: example-notifications-basic
apiVersion: widgets.templates.krateo.io/v1beta1
name: example-notifications-basic
namespace: krateo-system
resource: notifications
verb: GET
136 changes: 136 additions & 0 deletions src/widgets/Notifications/Notifications.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
{
"type": "object",
"additionalProperties": false,
"properties": {
"version": {
"description": "widget version",
"type": "string",
"default": "v1beta1"
},
"kind": {
"default": "Notifications",
"description": "Notifications renders messages coming from a Kubernetes cluster",
"type": "string"
},
"spec": {
"type": "object",
"properties": {
"widgetData": {
"type": "object",
"properties": {
"queryParams": {
"description": "list of query parameters to add to the notifications call",
"type": "array",
"items": {
"description": "key-value definition of a specific query parameter",
"type": "object",
"properties": {
"name": {
"description": "the name of the query parameter",
"type": "string"
},
"value": {
"description": "the value of the query parameter",
"type": "string"
}
},
"required": ["name", "value"],
"additionalProperties": false
}
}
},
"additionalProperties": false
},
"resourcesRefs": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"allowed": {
"type": "boolean"
},
"apiVersion": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"namespace": {
"type": "string"
},
"payload": {
"type": "object"
},
"resource": {
"type": "string"
},
"verb": {
"type": "string",
"enum": ["POST", "PUT", "PATCH", "DELETE", "GET"]
},
"slice": {
"type": "object",
"properties": {
"offset": {
"type": "integer"
},
"page": {
"type": "integer"
},
"perPage": {
"type": "integer"
},
"continue": {
"type": "boolean"
}
},
"required": ["perPage"]
}
},
"required": ["id"]
}
}
},
"required": ["allowed", "id"]
},
"apiRef": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"namespace": {
"type": "string"
}
},
"required": ["name", "namespace"],
"additionalProperties": false
},
"widgetDataTemplate": {
"type": "array",
"items": {
"type": "object",
"properties": {
"forPath": {
"type": "string"
},
"expression": {
"type": "string"
}
},
"additionalProperties": false
}
}
},
"required": ["widgetData"],
"additionalProperties": false
}
},
"required": ["kind", "spec", "version"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import VirtualList from 'rc-virtual-list'
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'

import { useGetEvents } from '../../hooks/useGetEvents'
import type { WidgetProps } from '../../types/Widget'
import type { EventsApiResource } from '../../utils/types'
import { formatISODate } from '../../utils/utils'

import styles from './Notifications.module.css'
import type { Notifications as WidgetType } from './Notifications.type'

export type NotificationsWidgetData = WidgetType['spec']['widgetData']

type LoaderItem = {
__isLoader: true
Expand All @@ -20,7 +24,7 @@ type NotificationItem = EventsApiResource | LoaderItem
const isLoaderItem = (item: unknown): item is LoaderItem =>
(!!item && typeof item === 'object' && '__isLoader' in item && (item as LoaderItem).__isLoader === true)

const Notifications: React.FC = () => {
const Notifications = ({ uid }: WidgetProps<NotificationsWidgetData>) => {
const [drawerVisible, setDrawerVisible] = useState(false)
const queryClient = useQueryClient()
const containerRef = useRef<HTMLDivElement | null>(null)
Expand Down Expand Up @@ -100,7 +104,7 @@ const Notifications: React.FC = () => {
const {
created_at: creationTimestamp,
event_type: type,
global_uid: uid,
global_uid: globalUid,
message,
namespace,
reason,
Expand All @@ -114,7 +118,7 @@ const Notifications: React.FC = () => {
return (
<List.Item
className={`${styles.listItem} ${isFirst ? styles.firstElement : ''} ${notifications?.length && isLast ? styles.lastElement : ''}`}
key={uid}
key={globalUid}
>
<Button className={styles.notificationElement} type='link'>
<div className={styles.space}>
Expand Down Expand Up @@ -176,6 +180,7 @@ const Notifications: React.FC = () => {
<Button
className={styles.icon}
icon={<BellFilled />}
id={uid}
onClick={() => setDrawerVisible(true)}
shape='circle'
type='link'
Expand Down
Loading
Loading