@kinvolk/headlamp-plugin
Version:
The needed infrastructure for building Headlamp plugins.
127 lines (126 loc) • 7.67 kB
JavaScript
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/hooks';
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, { "aria-label": t('translation|Menu'), size: "medium", onClick: handleClick, children: _jsx(Icon, { icon: "mdi:dots-vertical" }) }), _jsxs(Menu, { anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, children: [_jsx(MenuItem, { sx: {
'&.Mui-disabled': {
opacity: 0.7,
},
}, onClick: markAllAsRead, disabled: !hasUnseenNotifications, children: _jsx(Typography, { color: theme.palette.text.primary, children: t('translation|Mark all as read') }) }), _jsx(MenuItem, { sx: {
'&.Mui-disabled': {
opacity: 0.7,
},
}, onClick: clearAllNotifications, disabled: allNotificationsAreDeleted, children: _jsx(Typography, { color: theme.palette.text.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 }) })) }));
}