UNPKG

@kinvolk/headlamp-plugin

Version:

The needed infrastructure for building Headlamp plugins.

119 lines (118 loc) 7.26 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; /* * Copyright 2025 The Kubernetes Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { Icon } from '@iconify/react'; import Box from '@mui/material/Box'; import IconButton from '@mui/material/IconButton'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import { useTheme } from '@mui/material/styles'; import Tooltip from '@mui/material/Tooltip'; import Typography from '@mui/material/Typography'; import { useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; import { useTypedSelector } from '../../../../redux/reducers/reducers'; import Empty from '../../../common/EmptyContent'; import { DateLabel } from '../../../common/Label'; import Link from '../../../common/Link'; import SectionBox from '../../../common/SectionBox'; import SectionFilterHeader from '../../../common/SectionFilterHeader'; import Table from '../../../common/Table'; import { Notification, setNotifications, updateNotifications, } from '../notificationsSlice'; export default function NotificationList() { const notifications = useTypedSelector(state => state.notifications.notifications); const clusters = useTypedSelector(state => state.config.clusters); const { t } = useTranslation(['glossary', 'translation']); const dispatch = useDispatch(); const theme = useTheme(); const history = useHistory(); const allNotificationsAreDeleted = useMemo(() => { return !notifications.find(notification => !notification.deleted); }, [notifications]); const hasUnseenNotifications = useMemo(() => { return !!notifications.find(notification => !notification.deleted && !notification.seen); }, [notifications]); function notificationSeenUnseenHandler(event, notification) { if (!notification) { return; } dispatch(updateNotifications(notification)); } function clearAllNotifications() { const massagedNotifications = notifications.map(notification => { const updatedNotification = Object.assign(new Notification(), notification); updatedNotification.deleted = true; return updatedNotification; }); dispatch(setNotifications(massagedNotifications)); } function markAllAsRead() { const massagedNotifications = notifications.map(notification => { const updatedNotification = Object.assign(new Notification(), notification); updatedNotification.seen = true; return updatedNotification; }); dispatch(setNotifications(massagedNotifications)); } function notificationItemClickHandler(notification) { notification.url && history.push(notification.url); notification.seen = true; dispatch(updateNotifications(notification)); } function NotificationActionMenu() { const [anchorEl, setAnchorEl] = useState(null); function handleClick(event) { setAnchorEl(event.currentTarget); } function handleClose() { setAnchorEl(null); } return (_jsxs(_Fragment, { children: [_jsx(IconButton, { size: "medium", children: _jsx(Icon, { icon: "mdi:dots-vertical", onClick: handleClick }) }), _jsxs(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, children: [_jsx(MenuItem, { onClick: markAllAsRead, disabled: !hasUnseenNotifications, children: _jsx(Typography, { color: 'primary', children: t('translation|Mark all as read') }) }), _jsx(MenuItem, { onClick: clearAllNotifications, disabled: allNotificationsAreDeleted, children: _jsx(Typography, { color: "primary", children: t('translation|Clear all') }) })] })] })); } return (_jsx(SectionBox, { title: _jsx(SectionFilterHeader, { title: t('translation|Notifications'), noNamespaceFilter: true, actions: [_jsx(NotificationActionMenu, {})] }), backLink: true, children: allNotificationsAreDeleted ? (_jsxs(Empty, { children: [" ", t("translation|You don't have any notifications right now")] })) : (_jsx(Box, { style: { maxWidth: '100%', }, children: _jsx(Table, { columns: [ { header: t('translation|Message'), gridTemplate: 'auto', accessorKey: 'message', Cell: ({ row: { original: notification } }) => (_jsx(Box, { children: _jsx(Tooltip, { title: notification.message || t('translation|No message'), disableHoverListener: !notification.message, children: _jsx(Typography, { style: { fontWeight: notification.seen ? 'normal' : 'bold', cursor: 'pointer', }, noWrap: true, onClick: () => notificationItemClickHandler(notification), children: `${notification.message || t(`translation|No message`)}` }) }) })), }, { header: t('glossary|Cluster'), gridTemplate: 'min-content', accessorKey: 'cluster', Cell: ({ row: { original: notification } }) => (_jsxs(Box, { display: 'flex', alignItems: "center", children: [Object.entries(clusters || {}).length > 1 && notification.cluster && (_jsx(Box, { border: 0, p: 0.5, mr: 1, textOverflow: "ellipsis", overflow: 'hidden', whiteSpace: "nowrap", children: _jsx(Link, { routeName: "cluster", params: { cluster: `${notification.cluster}` }, children: notification.cluster }) })), ' '] })), }, { header: t('translation|Date'), gridTemplate: 'min-content', accessorKey: 'date', Cell: ({ row: { original: notification } }) => (_jsx(DateLabel, { date: notification.date })), }, { header: t('translation|Visible'), gridTemplate: 'min-content', accessorKey: 'seen', Cell: ({ row: { original: notification } }) => !notification.seen && (_jsx(Tooltip, { title: t(`translation|Mark as read`), children: _jsx(IconButton, { onClick: e => notificationSeenUnseenHandler(e, notification), "aria-label": t(`translation|Mark as read`), size: "medium", children: _jsx(Icon, { icon: "mdi:circle", color: theme.palette.error.main, height: 12, width: 12 }) }) })), }, ], data: notifications }) })) })); }