Skip to content

Commit

Permalink
Fixing dropdowns, refactoring code, switching to dynamic imports
Browse files Browse the repository at this point in the history
  • Loading branch information
arivepr committed Sep 1, 2023
1 parent db564af commit 770ea3d
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 66 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@
"@data-driven-forms/react-form-renderer": "^3.20.2",
"@formatjs/cli": "4.8.4",
"@openshift/dynamic-plugin-sdk": "^3.0.0",
"@patternfly/patternfly": "^5.0.2",
"@patternfly/patternfly": "^5.0.0",
"@patternfly/quickstarts": "^5.0.0",
"@patternfly/react-charts": "^7.0.0",
"@patternfly/react-core": "^5.0.0",
Expand Down
128 changes: 79 additions & 49 deletions src/components/NotificationsDrawer/DrawerPanelContent.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
import React, { useEffect, useState } from 'react';
import { PopoverPosition } from '@patternfly/react-core/dist/dynamic/components/Popover';
import { Icon } from '@patternfly/react-core/dist/dynamic/components/Icon';
import { Badge } from '@patternfly/react-core/dist/dynamic/components/Badge';
import { Checkbox } from '@patternfly/react-core/dist/dynamic/components/Checkbox';
import { Flex, FlexItem } from '@patternfly/react-core/dist/dynamic/layouts/Flex';
import { Dropdown, DropdownGroup, DropdownItem } from '@patternfly/react-core/dist/dynamic/components/Dropdown';
import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle';
import { Divider } from '@patternfly/react-core/dist/dynamic/components/Divider';
import { Button } from '@patternfly/react-core/dist/dynamic/components/Button';
import { EmptyState, EmptyStateBody, EmptyStateIcon } from '@patternfly/react-core/dist/dynamic/components/EmptyState';
import {
Badge,
Button,
Checkbox,
Divider,
Dropdown,
DropdownGroup,
DropdownItem,
EmptyState,
EmptyStateBody,
EmptyStateIcon,
Icon,
MenuToggle,
MenuToggleElement,
NotificationDrawer,
NotificationDrawerBody,
NotificationDrawerHeader,
NotificationDrawerList,
Text,
Title,
} from '@patternfly/react-core';
} from '@patternfly/react-core/dist/dynamic/components/NotificationDrawer';
import { Text } from '@patternfly/react-core/dist/dynamic/components/Text';
import { Title } from '@patternfly/react-core/dist/dynamic/components/Title';
import { useDispatch, useSelector } from 'react-redux';
import FilterIcon from '@patternfly/react-icons/dist/esm/icons/filter-icon';
import BellSlashIcon from '@patternfly/react-icons/dist/esm/icons/bell-slash-icon';
import ExternalLinkSquareAltIcon from '@patternfly/react-icons/dist/esm/icons/external-link-square-alt-icon';
import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
import FilterIcon from '@patternfly/react-icons/dist/dynamic/icons/filter-icon';
import BellSlashIcon from '@patternfly/react-icons/dist/dynamic/icons/bell-slash-icon';
import ExternalLinkSquareAltIcon from '@patternfly/react-icons/dist/dynamic/icons/external-link-square-alt-icon';
import ExternalLinkAltIcon from '@patternfly/react-icons/dist/dynamic/icons/external-link-alt-icon';
import EllipsisVIcon from '@patternfly/react-icons/dist/dynamic/icons/ellipsis-v-icon';
import { orderBy } from 'lodash';
import { NotificationData, ReduxState } from '../../redux/store';
import NotificationItem from './NotificationItem';
import { markAllNotificationsAsRead, markAllNotificationsAsUnread, toggleNotificationsDrawer } from '../../redux/actions';
import { filterConfig } from './notificationDrawerUtils';

export type DrawerPanelProps = {
innerRef: React.Ref<unknown>;
Expand Down Expand Up @@ -63,6 +62,7 @@ const DrawerPanelBase = ({ innerRef }: DrawerPanelProps) => {
const [filteredNotifications, setFilteredNotifications] = useState<NotificationData[]>([]);
const dispatch = useDispatch();
const notifications = useSelector(({ chrome: { notifications } }: ReduxState) => notifications?.data || []);
const isOrgAdmin = useSelector(({ chrome }: ReduxState) => chrome.user?.identity.user?.is_org_admin);

useEffect(() => {
const modifiedNotifications = (activeFilters || []).reduce(
Expand Down Expand Up @@ -95,47 +95,59 @@ const DrawerPanelBase = ({ innerRef }: DrawerPanelProps) => {
};

const dropdownItems = [
<DropdownItem key="read all" onClick={() => onMarkAllAsRead()}>
<DropdownItem key="read all" onClick={() => onMarkAllAsRead()} isDisabled={notifications.length === 0}>
Mark visible as read
</DropdownItem>,
<DropdownItem key="unread all" onClick={() => onMarkAllAsUnread()}>
<DropdownItem key="unread all" onClick={() => onMarkAllAsUnread()} isDisabled={notifications.length === 0}>
Mark visible as unread
</DropdownItem>,
<Divider key="divider" />,
<DropdownItem key="event log">
<Icon>
<ExternalLinkSquareAltIcon />
</Icon>
View event log
</DropdownItem>,
<DropdownItem key="notification settings">
<Icon>
<ExternalLinkSquareAltIcon />
</Icon>
Configure notification settings
<Flex>
<FlexItem>View event log</FlexItem>
<FlexItem align={{ default: 'alignRight' }}>
<Icon className="pf-v5-u-ml-auto">
<ExternalLinkAltIcon />
</Icon>
</FlexItem>
</Flex>
</DropdownItem>,
isOrgAdmin && (
<DropdownItem key="notification settings">
<Flex>
<FlexItem>Configure notification settings</FlexItem>
<FlexItem align={{ default: 'alignRight' }}>
<Icon className="pf-v5-u-ml-auto">
<ExternalLinkAltIcon />
</Icon>
</FlexItem>
</Flex>
</DropdownItem>
),
<DropdownItem key="notification preferences">
<Icon>
<ExternalLinkSquareAltIcon />
</Icon>
Manage my notification preferences
<Flex>
<FlexItem>Manage my notification preferences</FlexItem>
<FlexItem align={{ default: 'alignRight' }}>
<Icon className="pf-v5-u-ml-auto">
<ExternalLinkAltIcon />
</Icon>
</FlexItem>
</Flex>
</DropdownItem>,
];

const filterDropdownItems = () => {
const sources = notifications.reduce((acc: string[], { source }) => (acc.includes(source) ? acc : [...acc, source]), []);

return [
<DropdownGroup key="filter-label" label="Show notifications for...">
{sources.map((source, index) => (
<DropdownItem key={index} onClick={() => onFilterSelect(source)}>
<Checkbox isChecked={activeFilters.includes(source)} id={index.toString()} className="pf-u-mr-xs" />
{source}
{filterConfig.map((source, index) => (
<DropdownItem key={index} onClick={() => onFilterSelect(source.value)}>
<Checkbox isChecked={activeFilters.includes(source.value)} id={index.toString()} className="pf-v5-u-mr-sm" />
{source.title}
</DropdownItem>
))}
<Divider />
<DropdownItem key="reset-filters" onClick={() => setActiveFilters([])}>
<Button variant="link" isInline>
<Button variant="link" isDisabled={activeFilters.length === 0} isInline>
Reset filters
</Button>
</DropdownItem>
Expand Down Expand Up @@ -163,26 +175,44 @@ const DrawerPanelBase = ({ innerRef }: DrawerPanelProps) => {
{activeFilters.length > 0 && <Badge isRead>{activeFilters.length}</Badge>}
<Dropdown
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={() => setIsFilterDropdownOpen(!isFilterDropdownOpen)} id="filter-toggle" isFullWidth variant="plain">
<MenuToggle
ref={toggleRef}
onClick={() => setIsFilterDropdownOpen(!isFilterDropdownOpen)}
id="notifications-filter-toggle"
isFullWidth
variant="plain"
>
<FilterIcon />
</MenuToggle>
)}
isOpen={isFilterDropdownOpen}
id="filter-dropdown"
onOpenChange={setIsFilterDropdownOpen}
popperProps={{
position: PopoverPosition.right,
}}
id="notifications-filter-dropdown"
aria-label="Notifications filter"
isPlain
>
{filterDropdownItems()}
</Dropdown>
<Dropdown
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
<MenuToggle ref={toggleRef} onClick={() => setIsDropdownOpen(!isDropdownOpen)} variant="plain" id="kebab-toggle" isFullWidth>
<MenuToggle
ref={toggleRef}
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
variant="plain"
id="notifications-actions-toggle"
isFullWidth
>
<EllipsisVIcon />
</MenuToggle>
)}
isOpen={isDropdownOpen}
isPlain
id="notification-dropdown"
onOpenChange={setIsDropdownOpen}
popperProps={{
position: PopoverPosition.right,
}}
id="notifications-actions-dropdown"
>
{dropdownItems.map((dropdownItem) => dropdownItem)}
</Dropdown>
Expand Down
24 changes: 13 additions & 11 deletions src/components/NotificationsDrawer/NotificationItem.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import React, { useState } from 'react';
import {
Checkbox,
Dropdown,
DropdownItem,
Label,
MenuToggle,
MenuToggleElement,
NotificationDrawerList,
NotificationDrawerListItem,
NotificationDrawerListItemBody,
NotificationDrawerListItemHeader,
} from '@patternfly/react-core';
} from '@patternfly/react-core/dist/dynamic/components/NotificationDrawer';
import { PopoverPosition } from '@patternfly/react-core/dist/dynamic/components/Popover';
import { Checkbox } from '@patternfly/react-core/dist/dynamic/components/Checkbox';
import { Label } from '@patternfly/react-core/dist/dynamic/components/Label';
import { MenuToggle, MenuToggleElement } from '@patternfly/react-core/dist/dynamic/components/MenuToggle';
import { Dropdown, DropdownItem } from '@patternfly/react-core/dist/dynamic/components/Dropdown';
import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon';
import DateFormat from '@redhat-cloud-services/frontend-components/DateFormat';
import { useDispatch } from 'react-redux';
Expand Down Expand Up @@ -40,18 +39,21 @@ const NotificationItem = ({ notification }: { notification: NotificationData })
ref={toggleRef}
aria-label="Notification actions dropdown"
onClick={() => setIsDropdownOpen(!isDropdownOpen)}
id="kebab-toggle"
id="notification-item-toggle"
isExpanded={isDropdownOpen}
variant="plain"
>
<EllipsisVIcon />
</MenuToggle>
)}
isOpen={isDropdownOpen}
isPlain
id="notification-dropdown"
onOpenChange={setIsDropdownOpen}
popperProps={{
position: PopoverPosition.right,
}}
id="notification-item-dropdown"
>
{dropdownItems.map((dropDownItem) => dropDownItem)}
{dropdownItems}
</Dropdown>
</NotificationDrawerListItemHeader>
<NotificationDrawerListItemBody timestamp={<DateFormat date={notification.created} />}>
Expand Down
12 changes: 9 additions & 3 deletions testData.js → ...icationsDrawer/notificationDrawerUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,30 @@ export const testData = [
title: 'Test Notification 1',
description: 'Testing of notification',
read: false,
source: 'RHEL', // the origin of the message
source: 'rhel', // the origin of the message
created: '2023-08-18T12:00:00Z',
},
{
id: 2,
title: 'Test Notification 2',
description: 'Testing of notification',
read: false,
source: 'RBAC', // the origin of the message
source: 'ansible', // the origin of the message
created: '2023-08-18T12:05:00Z',
},
{
id: 3,
title: 'Test Notification 3',
description: 'Testin of notification',
read: false,
source: 'SATURN', // the origin of the message
source: 'openshift', // the origin of the message
created: '2023-08-18T12:10:00Z',
},
];

export const filterConfig = [
{ title: 'Console', value: 'console' },
{ title: 'OpenShift', value: 'openshift' },
{ title: 'Red Hat Enterprise Linux', value: 'rhel' },
{ title: 'Ansible Automation Platform', value: 'ansible' },
];
3 changes: 1 addition & 2 deletions src/redux/chromeReducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { ChromeModule, NavItem, Navigation } from '../@types/types';
import { ITLess, generateRoutesList, highlightItems, isBeta, levelArray } from '../utils/common';
import { ThreeScaleError } from '../utils/responseInterceptors';
import { AccessRequest, ChromeState, NotificationData } from './store';
import { testData } from '../../testData';

export function contextSwitcherBannerReducer(state: ChromeState): ChromeState {
return {
Expand Down Expand Up @@ -339,7 +338,7 @@ export function toggleNotificationsReducer(state: ChromeState) {
...state,
notifications: {
...state.notifications,
data: testData,
data: [],
isExpanded: !state.notifications?.isExpanded,
},
};
Expand Down

0 comments on commit 770ea3d

Please sign in to comment.