Skip to content

Commit

Permalink
Merge pull request #3899 from jcaianirh/drawer
Browse files Browse the repository at this point in the history
Notification drawer component for console.
  • Loading branch information
openshift-merge-robot committed Jan 24, 2020
2 parents a7a1b57 + 2fdd4db commit 56fc64c
Show file tree
Hide file tree
Showing 20 changed files with 686 additions and 20 deletions.
4 changes: 2 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^5.9.0",
"@patternfly/patternfly": "2.43.1",
"@patternfly/react-catalog-view-extension": "1.1.42",
"@patternfly/patternfly": "2.47.2",
"@patternfly/react-charts": "5.2.2",
"@patternfly/react-core": "3.124.1",
"@patternfly/react-table": "2.24.41",
"@patternfly/react-tokens": "2.7.10",
"@patternfly/react-topology": "2.11.27",
"@patternfly/react-virtualized-extension": "1.3.40",
"@patternfly/react-catalog-view-extension": "1.1.42",
"abort-controller": "3.0.0",
"classnames": "2.x",
"core-js": "2.x",
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/console-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@console/network-attachment-definition-plugin": "0.0.0-fixed",
"@console/noobaa-storage-plugin": "0.0.0-fixed",
"@console/operator-lifecycle-manager": "0.0.0-fixed",
"@console/patternfly": "0.0.0-fixed",
"@console/plugin-sdk": "0.0.0-fixed",
"@console/shared": "0.0.0-fixed"
},
Expand Down
80 changes: 80 additions & 0 deletions frontend/packages/patternfly/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"root": true,
"env": {
"browser": true,
"es6": true,
"jasmine": true
},
"extends": [
"eslint:recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:react/recommended",
"plugin:console/json",
"plugin:console/prettier"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"comment": true,
"ecmaFeatures": {
"jsx": true
},
"extraFileExtensions": [".json"],
"ecmaVersion": 2017,
"sourceType": "module"
},
"plugins": ["react", "react-hooks", "@typescript-eslint"],
"rules": {
"camelcase": 2,
"consistent-return": 0,
"consistent-this": [1, "that"],
"curly": [2, "all"],
"default-case": [2],
"dot-notation": [2],
"no-multiple-empty-lines": [2, { "max": 2, "maxEOF": 0 }],
"eqeqeq": [2, "allow-null"],
"guard-for-in": 2,
"import/no-unresolved": ["error"],
"import/no-duplicates": ["error"],
"max-nested-callbacks": [1, 4],
"no-alert": 2,
"no-caller": 2,
"no-console": 2,
"no-constant-condition": 2,
"no-debugger": 2,
"no-else-return": ["error"],
"no-global-strict": 0,
"no-irregular-whitespace": ["error"],
"no-shadow": ["error"],
"no-underscore-dangle": 0,
"@typescript-eslint/no-unused-vars": [
"error",
{ "varsIgnorePattern": "React", "args": "after-used" }
],
"@typescript-eslint/no-use-before-define": 2,
"no-var": 2,
"object-shorthand": ["error", "properties"],
"prefer-const": ["error", { "destructuring": "all" }],
"prefer-template": 2,
"radix": 2,
"react/jsx-fragments": "error",
"react/jsx-no-duplicate-props": 2,
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/no-string-refs": 1,
"react/no-unknown-property": "error",
"react/prop-types": 0,
"react/self-closing-comp": ["error", { "component": true, "html": false }],
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/display-name": 0,
"react/no-unescaped-entities": 0
},
"settings": {
"import/extensions": [".js", ".jsx"],
"import/resolver": { "node": { "extensions": [".js", ".jsx", ".ts", ".tsx"] } },
"react": {
"version": "detect"
}
}
}
7 changes: 7 additions & 0 deletions frontend/packages/patternfly/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "@console/patternfly",
"version": "0.0.0-fixed",
"description": "Components ready for possible export to patternfly react-core repo.",
"private": true,
"main": "src/index.ts"
}
1 change: 1 addition & 0 deletions frontend/packages/patternfly/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './notification-drawer';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { default as NotificationDrawer } from './notification-drawer';
export { default as NotificationDrawerHeading } from './notification-drawer-heading';
export { default as NotificationEntry, NotificationTypes } from './notification-entry';
export { default as NotificationCategory } from './notification-category';
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from 'react';
import * as classNames from 'classnames';
import { Badge } from '@patternfly/react-core';

const NotificationCategory: React.FC<NotificationCategoryProps> = ({
label,
count,
isExpanded,
children,
onExpandContents,
}) => (
<section
className={classNames('query-pf-c-notification-drawer__group', {
'pf-m-expanded': isExpanded,
})}
>
<button
className="pf-c-notification-drawer__group-toggle"
aria-expanded={isExpanded}
onClick={() => onExpandContents(!isExpanded)}
>
<div className="pf-c-notification-drawer__group-toggle-title">{label}</div>
<div className="pf-c-notification-drawer__group-toggle-count">
<Badge isRead>{count}</Badge>
</div>
<span className="pf-c-notification-drawer__group-toggle-icon">
<i
className={classNames({
'fas fa-angle-down': isExpanded,
'fas fa-angle-right': !isExpanded,
})}
aria-hidden={!isExpanded}
/>
</span>
</button>
<ul className="pf-c-notification-drawer__list" hidden={!isExpanded}>
{children}
</ul>
</section>
);

type NotificationCategoryProps = {
children: React.ReactNode;
count: number;
isExpanded: boolean;
label: string;
onExpandContents: React.Dispatch<React.SetStateAction<boolean>>;
};

export default NotificationCategory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as React from 'react';

const NotificationDrawerHeading: React.FC<NotificationDrawerHeadingProps> = ({
count,
children,
}) => (
<div className="pf-c-notification-drawer">
<div className="pf-c-notification-drawer__header">
<h1 className="pf-c-notification-drawer__header-title">Notifications</h1>
{count && (
<span className="pf-c-notification-drawer__header-status">{`${count} unread`}</span>
)}
</div>
<div className="pf-c-notification-drawer__body">
<div className="pf-c-notification-drawer__group-list">{children}</div>
</div>
</div>
);

type NotificationDrawerHeadingProps = {
children: React.ReactNode;
count?: number;
};

export default NotificationDrawerHeading;
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import {
Drawer,
DrawerContent,
DrawerPanelContent,
} from '@patternfly/react-core/dist/js/experimental/components/Drawer';

import NotificationDrawerHeading from './notification-drawer-heading';

const NotificationDrawer: React.FC<NotificationDrawerProps> = ({
isExpanded,
isInline,
children,
notificationEntries,
}) => {
return (
<Drawer isExpanded={isExpanded} isInline={isInline}>
<DrawerContent>{children}</DrawerContent>
<DrawerPanelContent noPadding>
<NotificationDrawerHeading>{notificationEntries}</NotificationDrawerHeading>
</DrawerPanelContent>
</Drawer>
);
};

NotificationDrawer.displayName = 'NotificationDrawer';

export type NotificationDrawerProps = {
isInline: boolean;
isExpanded: boolean;
notificationEntries?: JSX.Element[];
count?: number;
children: React.ReactNode;
};

export default NotificationDrawer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import * as classNames from 'classnames';
import * as _ from 'lodash';
import * as React from 'react';
import { Link } from 'react-router-dom';
import {
YellowExclamationTriangleIcon,
GreenCheckCircleIcon,
BlueInfoCircleIcon,
RedExclamationCircleIcon,
} from '@console/shared';
import { ArrowCircleUpIcon } from '@patternfly/react-icons';
import { global_info_color_100 as blueInfoColor } from '@patternfly/react-tokens';
import { history, Timestamp } from '@console/internal/components/utils';

export enum NotificationTypes {
info = 'info',
warning = 'warning',
critical = 'danger',
success = 'success',
update = 'update',
}

const NotificationIcon: React.FC<NotificationIconTypes> = ({ type }) => {
switch (type) {
case NotificationTypes.update:
return <ArrowCircleUpIcon color={blueInfoColor.value} />;
case NotificationTypes.success:
return <GreenCheckCircleIcon />;
case NotificationTypes.critical:
return <RedExclamationCircleIcon />;
case NotificationTypes.warning:
return <YellowExclamationTriangleIcon />;
case NotificationTypes.info:
default:
return <BlueInfoCircleIcon />;
}
};

const NotificationEntry: React.FC<NotificationEntryProps> = ({
title,
description,
isRead = false,
timestamp,
targetURL,
toggleNotificationDrawer,
type,
}) => {
const notificationAction = type === NotificationTypes.update && targetURL && (
<div className="pf-c-notification-drawer__header-action">
<Link to="">Install Update</Link>
</div>
);
return (
<li
className={classNames(`pf-c-notification-drawer__list-item pf-m-hoverable pf-m-${type}`, {
'pf-m-read': isRead,
})}
tabIndex={0}
onClick={
targetURL
? () => {
history.push(targetURL);
toggleNotificationDrawer();
}
: null
}
>
<div className="pf-c-notification-drawer__list-item-header">
<span className="pf-c-notification-drawer__list-item-header-icon">
<NotificationIcon type={type} />
</span>
<h4 className="pf-c-notification-drawer__list-item-header-title">
<span className="pf-screen-reader">{`${_.capitalize(type)} notification:`}</span>
{title}
</h4>
{notificationAction}
</div>
<div className="pf-c-notification-drawer__list-item-description">{description}</div>
<div className="pf-c-notification-drawer__list-item-timestamp">
{timestamp && <Timestamp simple timestamp={timestamp} />}
</div>
</li>
);
};

export type NotificationEntryProps = {
title: string;
description: string;
isRead?: boolean;
targetURL?: string;
timestamp?: string;
toggleNotificationDrawer?: () => any;
type: NotificationTypes;
};

type NotificationIconTypes = {
type: NotificationTypes;
};

export default NotificationEntry;
1 change: 1 addition & 0 deletions frontend/packages/patternfly/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './components';
17 changes: 13 additions & 4 deletions frontend/public/actions/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export enum ActionType {
MonitoringDashboardsPatchVariable = 'monitoringDashboardsPatchVariable',
SetMonitoringData = 'setMonitoringData',
ToggleMonitoringGraphs = 'monitoringToggleGraphs',
NotificationDrawerToggleExpanded = 'notificationDrawerExpanded',
NotificationDrawerToggleRead = 'notificationDrawerRead',
QueryBrowserAddQuery = 'queryBrowserAddQuery',
QueryBrowserDeleteAllQueries = 'queryBrowserDeleteAllQueries',
QueryBrowserDeleteQuery = 'queryBrowserDeleteQuery',
Expand Down Expand Up @@ -264,16 +266,21 @@ export const monitoringDashboardsClearVariables = () =>
action(ActionType.MonitoringDashboardsClearVariables);
export const monitoringDashboardsPatchVariable = (key: string, patch: any) =>
action(ActionType.MonitoringDashboardsPatchVariable, { key, patch });
export const monitoringLoading = (key: 'alerts' | 'silences') =>
export const monitoringLoading = (key: 'alerts' | 'silences' | 'notificationAlerts') =>
action(ActionType.SetMonitoringData, {
key,
data: { loaded: false, loadError: null, data: null },
});
export const monitoringLoaded = (key: 'alerts' | 'silences', data: any) =>
export const monitoringLoaded = (key: 'alerts' | 'silences' | 'notificationAlerts', data: any) =>
action(ActionType.SetMonitoringData, { key, data: { loaded: true, loadError: null, data } });
export const monitoringErrored = (key: 'alerts' | 'silences', loadError: any) =>
action(ActionType.SetMonitoringData, { key, data: { loaded: true, loadError, data: null } });
export const monitoringErrored = (
key: 'alerts' | 'silences' | 'notificationAlerts',
loadError: any,
) => action(ActionType.SetMonitoringData, { key, data: { loaded: true, loadError, data: null } });
export const monitoringToggleGraphs = () => action(ActionType.ToggleMonitoringGraphs);
export const notificationDrawerToggleExpanded = () =>
action(ActionType.NotificationDrawerToggleExpanded);
export const notificationDrawerToggleRead = () => action(ActionType.NotificationDrawerToggleRead);
export const queryBrowserAddQuery = () => action(ActionType.QueryBrowserAddQuery);
export const queryBrowserDeleteAllQueries = () => action(ActionType.QueryBrowserDeleteAllQueries);
export const queryBrowserDismissNamespaceAlert = () =>
Expand Down Expand Up @@ -348,6 +355,8 @@ const uiActions = {
setConsoleLinks,
setPodMetrics,
setNamespaceMetrics,
notificationDrawerToggleExpanded,
notificationDrawerToggleRead,
};

export type UIAction = Action<typeof uiActions>;

0 comments on commit 56fc64c

Please sign in to comment.