Skip to content

Commit

Permalink
ui: make notifications more generic
Browse files Browse the repository at this point in the history
partially addresses reanahub#123
  • Loading branch information
mvidalgarcia committed Dec 18, 2020
1 parent cbb8ce0 commit a54603c
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 26 deletions.
17 changes: 14 additions & 3 deletions reana-ui/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
} from "./selectors";

export const ERROR = "Error";
export const CLEAR_ERROR = "Clear error";
export const NOTIFICATION = "Notification";
export const CLEAR_NOTIFICATION = "Clear notification";

export const CONFIG_FETCH = "Fetch app config info";
export const CONFIG_RECEIVED = "App config info received";
Expand Down Expand Up @@ -78,10 +79,20 @@ const WORKFLOW_FILES_URL = (id, { page = 1, size }) => {
function errorActionCreator(error, name) {
const { status, data } = error?.response;
const { message } = data;
return { type: ERROR, name, status, message };
return {
type: ERROR,
name,
status,
message,
header: "An error has occurred",
};
}

export function triggerNotification(header, message) {
return { type: NOTIFICATION, header, message };
}

export const clearError = { type: CLEAR_ERROR };
export const clearNotification = { type: CLEAR_NOTIFICATION };

export function loadConfig() {
return async (dispatch) => {
Expand Down
38 changes: 25 additions & 13 deletions reana-ui/src/components/Notification.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,44 @@ import { useDispatch, useSelector } from "react-redux";
import { Container, Message, Transition } from "semantic-ui-react";
import PropTypes from "prop-types";

import { clearError } from "../actions";
import { getError } from "../selectors";
import { clearNotification } from "../actions";
import { getNotification } from "../selectors";

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

const AUTO_CLOSE_TIMEOUT = 16000;

export default function Notification({ icon, header, message, closable }) {
export default function Notification({
icon,
header,
message,
closable,
error,
success,
}) {
const dispatch = useDispatch();
const error = useSelector(getError);
const notification = useSelector(getNotification);
const timer = useRef(null);

const hide = () => dispatch(clearError);
const visible = message || error ? true : false;
const hide = () => dispatch(clearNotification);
const visible = message || notification ? true : false;
const actionIcon = notification?.isError ? "warning sign" : "info circle";

if (closable && visible) {
clearTimeout(timer.current);
timer.current = setTimeout(() => hide(), AUTO_CLOSE_TIMEOUT);
}

return (
<Transition visible={visible} duration={300}>
<Container text className={styles.container}>
<Message
icon={icon}
header={header}
content={message || error?.message}
icon={icon || actionIcon}
header={header || notification?.header}
content={message || notification?.message}
onDismiss={closable ? hide : null}
size="small"
error
error={error || (notification && notification.isError)}
success={success || (notification && !notification.isError)}
/>
</Container>
</Transition>
Expand All @@ -54,11 +62,15 @@ Notification.propTypes = {
header: PropTypes.string,
message: PropTypes.string,
closable: PropTypes.bool,
error: PropTypes.bool,
success: PropTypes.bool,
};

Notification.defaultProps = {
icon: "warning sign",
header: "An error has occurred",
icon: null,
header: null,
message: null,
closable: true,
error: false,
success: false,
};
3 changes: 3 additions & 0 deletions reana-ui/src/pages/workflowDetails/WorkflowDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ function WorkflowDetails() {
if (!workflow) {
return (
<Notification
icon="warning sign"
header="An error has occurred"
message="Sorry, this workflow either does not exist or you are not authorised to see it."
closable={false}
error
/>
);
}
Expand Down
25 changes: 17 additions & 8 deletions reana-ui/src/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import { combineReducers } from "redux";
import {
ERROR,
CLEAR_ERROR,
NOTIFICATION,
CLEAR_NOTIFICATION,
CONFIG_FETCH,
CONFIG_RECEIVED,
CONFIG_ERROR,
Expand All @@ -35,7 +36,7 @@ import {
} from "./actions";
import { USER_ERROR } from "./errors";

const errorInitialState = null;
const notificationInitialState = null;

export const configInitialState = {
announcement: null,
Expand Down Expand Up @@ -74,13 +75,21 @@ const detailsInitialState = {
loadingDetails: false,
};

const error = (state = errorInitialState, action) => {
const { name, status, message } = action;
const notification = (state = notificationInitialState, action) => {
const { name, status, message, header } = action;
switch (action.type) {
case ERROR:
return { ...state, name, status, message };
case CLEAR_ERROR:
return errorInitialState;
case NOTIFICATION:
return {
...state,
name,
status,
message,
header,
isError: action.type === ERROR,
};
case CLEAR_NOTIFICATION:
return notificationInitialState;
default:
return state;
}
Expand Down Expand Up @@ -239,7 +248,7 @@ const details = (state = detailsInitialState, action) => {
};

const reanaApp = combineReducers({
error,
notification,
config,
auth,
workflows,
Expand Down
4 changes: 2 additions & 2 deletions reana-ui/src/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

import { USER_ERROR } from "./errors";

// Error
export const getError = (state) => state.error;
// Notification
export const getNotification = (state) => state.notification;

// Config
export const getConfig = (state) => state.config;
Expand Down

0 comments on commit a54603c

Please sign in to comment.