Skip to content

Commit

Permalink
Merge pull request ManageIQ#8867 from jeffibm/fix-notification-duplic…
Browse files Browse the repository at this point in the history
…ates

Fix duplicate notifications and toasters
  • Loading branch information
Fryguy authored Jan 5, 2024
2 parents f29b554 + 5a2b082 commit babdf56
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 15 deletions.
12 changes: 11 additions & 1 deletion app/javascript/components/breadcrumbs/index.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
/* eslint-disable react/destructuring-assignment */
import React from 'react';
import PropTypes from 'prop-types';
import { Breadcrumbs } from './breadcrumbs';
import { NotificationsToggle } from './notifications-toggle';

export const BreadcrumbsBar = (props) => (
<>
<Breadcrumbs {...props} />
<NotificationsToggle />
<NotificationsToggle jsRequest={props.jsRequest} />
</>
);

BreadcrumbsBar.propTypes = {
jsRequest: PropTypes.bool,
};

BreadcrumbsBar.defaultProps = {
jsRequest: false,
};
13 changes: 11 additions & 2 deletions app/javascript/components/breadcrumbs/notifications-toggle.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import cx from 'classnames';
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { Button } from 'carbon-components-react';
import { TOGGLE_DRAWER_VISIBILITY } from '../../miq-redux/actions/notifications-actions';
import MiqIcon from '../../menu/icon';
import NotificationDrawer from '../notification-drawer/notification-drawer';

export const NotificationsToggle = () => {
export const NotificationsToggle = ({ jsRequest }) => {
const dispatch = useDispatch();
const { isDrawerVisible, unreadCount } = useSelector(({ notificationReducer }) => notificationReducer);

Expand Down Expand Up @@ -39,7 +40,15 @@ export const NotificationsToggle = () => {
{' '}
<MiqIcon icon={unreadCount ? 'carbon--NotificationNew' : 'carbon--Notification'} />
</Button>
<NotificationDrawer />
<NotificationDrawer jsRequest={jsRequest} />
</div>
);
};

NotificationsToggle.propTypes = {
jsRequest: PropTypes.bool,
};

NotificationsToggle.defaultProps = {
jsRequest: false,
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import moment from 'moment';
import { useDispatch, useSelector } from 'react-redux';
import { ChevronLeft16, Close16 } from '@carbon/icons-react';
Expand All @@ -13,15 +14,17 @@ import {

import initNotifications from '../../notifications/init';

const NotificationDrawer = () => {
const NotificationDrawer = ({ jsRequest }) => {
const dispatch = useDispatch();
const drawerTitle = __('Notifications');
const [isDrawerExpanded, setDrawerExpanded] = useState(false);
const {
isDrawerVisible, unreadCount, notifications, totalNotificationsCount, maxNotifications,
} = useSelector(({ notificationReducer }) => notificationReducer);
useEffect(() => {
initNotifications();
if (!jsRequest) {
initNotifications();
}
}, []);
return (
isDrawerVisible ? (
Expand Down Expand Up @@ -192,3 +195,11 @@ const NotificationDrawer = () => {
};

export default NotificationDrawer;

NotificationDrawer.propTypes = {
jsRequest: PropTypes.bool,
};

NotificationDrawer.defaultProps = {
jsRequest: false,
};
1 change: 1 addition & 0 deletions app/javascript/components/toast-list/toast-item.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const ToastItem = ({ toastNotification }) => {
caption={EMPTY}
subtitle={toastNotification.message}
onClick={() => dispatch(markNotificationRead(toastNotification))}
timeout={6000}
>
{toastNotification.data.link && (
<div className="pull-right toast-pf-action">
Expand Down
22 changes: 18 additions & 4 deletions app/javascript/miq-redux/notification-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,39 @@ const notificationInitialState = {
maxNotifications,
};

/** Function to filter out the toastNotification that are already displayed. */
const filterToastNotification = ({ payload }, toastNotifications) => {
const exists = toastNotifications.find((item) => item.id === payload.id);
return exists ? toastNotifications : [payload, ...toastNotifications];
};

/** Function to filter out the notification that are already displayed. */
const filterNotifications = ({ payload }, notifications) => {
const exists = notifications.find((item) => item.id === payload.id);
return exists ? notifications : [payload, ...notifications].slice(0, 100);
};

export const notificationReducer = (state = notificationInitialState, action) => {
switch (action.type) {
case INIT_NOTIFICATIONS:
return {
...state,
notifications: action.payload.notifications,
unreadCount: action.payload.notifications.filter(notification => notification.unread).length,
unreadCount: action.payload.notifications.filter((notification) => notification.unread).length,
totalNotificationsCount: action.payload.count,
};

case ADD_NOTIFICATION:
const notifications = [action.payload, ...state.notifications].slice(0, 100);
{
const notifications = filterNotifications(action, state.notifications);
return {
...state,
notifications,
unreadCount: notifications.filter(notification => notification.unread).length,
unreadCount: notifications.filter((notification) => notification.unread).length,
totalNotificationsCount: state.totalNotificationsCount + 1,
toastNotifications: [action.payload, ...state.toastNotifications],
toastNotifications: filterToastNotification(action, state.toastNotifications),
};
}

case TOGGLE_DRAWER_VISIBILITY:
return { ...state, isDrawerVisible: !state.isDrawerVisible };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ exports[`Breadcrumbs component is correctly rendered 1`] = `
},
]
}
jsRequest={false}
title="Title"
>
<Breadcrumbs
Expand All @@ -58,6 +59,7 @@ exports[`Breadcrumbs component is correctly rendered 1`] = `
},
]
}
jsRequest={false}
title="Title"
>
<Breadcrumb
Expand Down Expand Up @@ -136,7 +138,9 @@ exports[`Breadcrumbs component is correctly rendered 1`] = `
</nav>
</Breadcrumb>
</Breadcrumbs>
<NotificationsToggle>
<NotificationsToggle
jsRequest={false}
>
<div
className="notification-module"
>
Expand Down Expand Up @@ -212,7 +216,9 @@ exports[`Breadcrumbs component is correctly rendered 1`] = `
</MiqIcon>
</button>
</Button>
<NotificationDrawer />
<NotificationDrawer
jsRequest={false}
/>
</div>
</NotificationsToggle>
</BreadcrumbsBar>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ exports[`Notification drawer tests should render correctly 1`] = `
}
}
>
<NotificationDrawer>
<NotificationDrawer
jsRequest={false}
>
<div
id="miq-notifications-drawer-container"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ exports[`Toast list tests should render correctly with notifications 1`] = `
lowContrast={true}
onClick={[Function]}
subtitle="Plan has completed with errors"
timeout={6000}
title=""
>
<ToastNotification
Expand All @@ -55,7 +56,7 @@ exports[`Toast list tests should render correctly with notifications 1`] = `
onCloseButtonClick={[Function]}
role="alert"
subtitle="Plan has completed with errors"
timeout={0}
timeout={6000}
title=""
>
<div
Expand Down Expand Up @@ -224,6 +225,7 @@ exports[`Toast list tests should render correctly with notifications 1`] = `
lowContrast={true}
onClick={[Function]}
subtitle="Plan has completed successfully"
timeout={6000}
title=""
>
<ToastNotification
Expand All @@ -237,7 +239,7 @@ exports[`Toast list tests should render correctly with notifications 1`] = `
onCloseButtonClick={[Function]}
role="alert"
subtitle="Plan has completed successfully"
timeout={0}
timeout={6000}
title=""
>
<div
Expand Down
3 changes: 2 additions & 1 deletion app/views/layouts/_breadcrumbs.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
= react('BreadcrumbsBar',
:items => (data_for_breadcrumbs({:right_cell_text => right_cell_text}) if respond_to?(:data_for_breadcrumbs)),
:controllerName => controller_name,
:title => @title)
:title => @title,
:jsRequest => request.format.js?)

0 comments on commit babdf56

Please sign in to comment.