Skip to content

Commit a54603c

Browse files
committed
ui: make notifications more generic
partially addresses reanahub#123
1 parent cbb8ce0 commit a54603c

File tree

5 files changed

+61
-26
lines changed

5 files changed

+61
-26
lines changed

reana-ui/src/actions.js

+14-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import {
2020
} from "./selectors";
2121

2222
export const ERROR = "Error";
23-
export const CLEAR_ERROR = "Clear error";
23+
export const NOTIFICATION = "Notification";
24+
export const CLEAR_NOTIFICATION = "Clear notification";
2425

2526
export const CONFIG_FETCH = "Fetch app config info";
2627
export const CONFIG_RECEIVED = "App config info received";
@@ -78,10 +79,20 @@ const WORKFLOW_FILES_URL = (id, { page = 1, size }) => {
7879
function errorActionCreator(error, name) {
7980
const { status, data } = error?.response;
8081
const { message } = data;
81-
return { type: ERROR, name, status, message };
82+
return {
83+
type: ERROR,
84+
name,
85+
status,
86+
message,
87+
header: "An error has occurred",
88+
};
89+
}
90+
91+
export function triggerNotification(header, message) {
92+
return { type: NOTIFICATION, header, message };
8293
}
8394

84-
export const clearError = { type: CLEAR_ERROR };
95+
export const clearNotification = { type: CLEAR_NOTIFICATION };
8596

8697
export function loadConfig() {
8798
return async (dispatch) => {

reana-ui/src/components/Notification.js

+25-13
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,44 @@ import { useDispatch, useSelector } from "react-redux";
1313
import { Container, Message, Transition } from "semantic-ui-react";
1414
import PropTypes from "prop-types";
1515

16-
import { clearError } from "../actions";
17-
import { getError } from "../selectors";
16+
import { clearNotification } from "../actions";
17+
import { getNotification } from "../selectors";
1818

1919
import styles from "./Notification.module.scss";
2020

2121
const AUTO_CLOSE_TIMEOUT = 16000;
2222

23-
export default function Notification({ icon, header, message, closable }) {
23+
export default function Notification({
24+
icon,
25+
header,
26+
message,
27+
closable,
28+
error,
29+
success,
30+
}) {
2431
const dispatch = useDispatch();
25-
const error = useSelector(getError);
32+
const notification = useSelector(getNotification);
2633
const timer = useRef(null);
2734

28-
const hide = () => dispatch(clearError);
29-
const visible = message || error ? true : false;
35+
const hide = () => dispatch(clearNotification);
36+
const visible = message || notification ? true : false;
37+
const actionIcon = notification?.isError ? "warning sign" : "info circle";
3038

3139
if (closable && visible) {
3240
clearTimeout(timer.current);
3341
timer.current = setTimeout(() => hide(), AUTO_CLOSE_TIMEOUT);
3442
}
35-
3643
return (
3744
<Transition visible={visible} duration={300}>
3845
<Container text className={styles.container}>
3946
<Message
40-
icon={icon}
41-
header={header}
42-
content={message || error?.message}
47+
icon={icon || actionIcon}
48+
header={header || notification?.header}
49+
content={message || notification?.message}
4350
onDismiss={closable ? hide : null}
4451
size="small"
45-
error
52+
error={error || (notification && notification.isError)}
53+
success={success || (notification && !notification.isError)}
4654
/>
4755
</Container>
4856
</Transition>
@@ -54,11 +62,15 @@ Notification.propTypes = {
5462
header: PropTypes.string,
5563
message: PropTypes.string,
5664
closable: PropTypes.bool,
65+
error: PropTypes.bool,
66+
success: PropTypes.bool,
5767
};
5868

5969
Notification.defaultProps = {
60-
icon: "warning sign",
61-
header: "An error has occurred",
70+
icon: null,
71+
header: null,
6272
message: null,
6373
closable: true,
74+
error: false,
75+
success: false,
6476
};

reana-ui/src/pages/workflowDetails/WorkflowDetails.js

+3
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,11 @@ function WorkflowDetails() {
5959
if (!workflow) {
6060
return (
6161
<Notification
62+
icon="warning sign"
63+
header="An error has occurred"
6264
message="Sorry, this workflow either does not exist or you are not authorised to see it."
6365
closable={false}
66+
error
6467
/>
6568
);
6669
}

reana-ui/src/reducers.js

+17-8
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
import { combineReducers } from "redux";
1212
import {
1313
ERROR,
14-
CLEAR_ERROR,
14+
NOTIFICATION,
15+
CLEAR_NOTIFICATION,
1516
CONFIG_FETCH,
1617
CONFIG_RECEIVED,
1718
CONFIG_ERROR,
@@ -35,7 +36,7 @@ import {
3536
} from "./actions";
3637
import { USER_ERROR } from "./errors";
3738

38-
const errorInitialState = null;
39+
const notificationInitialState = null;
3940

4041
export const configInitialState = {
4142
announcement: null,
@@ -74,13 +75,21 @@ const detailsInitialState = {
7475
loadingDetails: false,
7576
};
7677

77-
const error = (state = errorInitialState, action) => {
78-
const { name, status, message } = action;
78+
const notification = (state = notificationInitialState, action) => {
79+
const { name, status, message, header } = action;
7980
switch (action.type) {
8081
case ERROR:
81-
return { ...state, name, status, message };
82-
case CLEAR_ERROR:
83-
return errorInitialState;
82+
case NOTIFICATION:
83+
return {
84+
...state,
85+
name,
86+
status,
87+
message,
88+
header,
89+
isError: action.type === ERROR,
90+
};
91+
case CLEAR_NOTIFICATION:
92+
return notificationInitialState;
8493
default:
8594
return state;
8695
}
@@ -239,7 +248,7 @@ const details = (state = detailsInitialState, action) => {
239248
};
240249

241250
const reanaApp = combineReducers({
242-
error,
251+
notification,
243252
config,
244253
auth,
245254
workflows,

reana-ui/src/selectors.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
import { USER_ERROR } from "./errors";
1212

13-
// Error
14-
export const getError = (state) => state.error;
13+
// Notification
14+
export const getNotification = (state) => state.notification;
1515

1616
// Config
1717
export const getConfig = (state) => state.config;

0 commit comments

Comments
 (0)