diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b55a77..558119e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/README.md b/README.md index b7b11e9..235b387 100644 --- a/README.md +++ b/README.md @@ -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" }, diff --git a/docs/theme.md b/docs/theme.md index b457321..8d19a99 100644 --- a/docs/theme.md +++ b/docs/theme.md @@ -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" diff --git a/public/config/config.json b/public/config/config.json index 63fa852..c9e0ac7 100644 --- a/public/config/config.json +++ b/public/config/config.json @@ -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" diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 1f04b50..8a7d3b3 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -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' @@ -11,6 +12,8 @@ type HeaderProps = { } const Header = ({ breadcrumbVisible = true }: HeaderProps) => { + const { config } = useConfigContext() + return (
@@ -18,7 +21,7 @@ const Header = ({ breadcrumbVisible = true }: HeaderProps) => { {breadcrumbVisible && }
- +
diff --git a/src/components/WidgetRenderer/WidgetRenderer.tsx b/src/components/WidgetRenderer/WidgetRenderer.tsx index 18ee51a..e1cbe44 100644 --- a/src/components/WidgetRenderer/WidgetRenderer.tsx +++ b/src/components/WidgetRenderer/WidgetRenderer.tsx @@ -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' @@ -131,6 +133,8 @@ const parseWidget = ( return case 'NavMenu': return + case 'Notifications': + return case 'Page': return case 'Panel': diff --git a/src/context/ConfigContext.tsx b/src/context/ConfigContext.tsx index 744b1a9..04b99a5 100644 --- a/src/context/ConfigContext.tsx +++ b/src/context/ConfigContext.tsx @@ -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 diff --git a/src/env.d.ts b/src/env.d.ts index 9de6f76..7c840ae 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -6,3 +6,9 @@ interface ImportMetaEnv { interface ImportMeta { readonly env: ImportMetaEnv } +declare module '*.module.css' { + const classes: Record + export default classes +} + +declare module '*.css' diff --git a/src/examples/widgets/Notifications/Notifications.example.yaml b/src/examples/widgets/Notifications/Notifications.example.yaml new file mode 100644 index 0000000..3e4dd8b --- /dev/null +++ b/src/examples/widgets/Notifications/Notifications.example.yaml @@ -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: {} \ No newline at end of file diff --git a/src/examples/widgets/Notifications/Notifications.menu.yaml b/src/examples/widgets/Notifications/Notifications.menu.yaml new file mode 100644 index 0000000..c026ba4 --- /dev/null +++ b/src/examples/widgets/Notifications/Notifications.menu.yaml @@ -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 \ No newline at end of file diff --git a/src/components/Notifications/Notifications.module.css b/src/widgets/Notifications/Notifications.module.css similarity index 100% rename from src/components/Notifications/Notifications.module.css rename to src/widgets/Notifications/Notifications.module.css diff --git a/src/widgets/Notifications/Notifications.schema.json b/src/widgets/Notifications/Notifications.schema.json new file mode 100644 index 0000000..3f6320c --- /dev/null +++ b/src/widgets/Notifications/Notifications.schema.json @@ -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"] +} diff --git a/src/components/Notifications/Notifications.tsx b/src/widgets/Notifications/Notifications.tsx similarity index 94% rename from src/components/Notifications/Notifications.tsx rename to src/widgets/Notifications/Notifications.tsx index a6ef08f..9d90f93 100644 --- a/src/components/Notifications/Notifications.tsx +++ b/src/widgets/Notifications/Notifications.tsx @@ -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 @@ -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) => { const [drawerVisible, setDrawerVisible] = useState(false) const queryClient = useQueryClient() const containerRef = useRef(null) @@ -100,7 +104,7 @@ const Notifications: React.FC = () => { const { created_at: creationTimestamp, event_type: type, - global_uid: uid, + global_uid: globalUid, message, namespace, reason, @@ -114,7 +118,7 @@ const Notifications: React.FC = () => { return (