diff --git a/assets/css/src/components/_notice.scss b/assets/css/src/components/_notice.scss
index dacba47373..4486b10822 100644
--- a/assets/css/src/components/_notice.scss
+++ b/assets/css/src/components/_notice.scss
@@ -10,6 +10,7 @@
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, .1);
margin: 5px 0 15px;
padding: 1px 12px;
+ position: relative;
}
.mailpoet_success_notice {
diff --git a/assets/js/src/notices/api_errors_notice.jsx b/assets/js/src/notices/api_errors_notice.jsx
index 1c92bb40ff..9d3a6ccc6b 100644
--- a/assets/js/src/notices/api_errors_notice.jsx
+++ b/assets/js/src/notices/api_errors_notice.jsx
@@ -4,7 +4,7 @@ import Notice from 'notices/notice.jsx';
const APIErrorsNotice = ({ errors }) => {
if (errors.length < 1) return null;
- return {errors.map((err) => {err.message}
)};
+ return {errors.map((err) => {err.message}
)};
};
APIErrorsNotice.propTypes = {
errors: PropTypes.arrayOf(PropTypes.shape({
diff --git a/assets/js/src/notices/mailer_status_notice.jsx b/assets/js/src/notices/mailer_status_notice.jsx
index 38b11aa767..7bf7e0eeae 100644
--- a/assets/js/src/notices/mailer_status_notice.jsx
+++ b/assets/js/src/notices/mailer_status_notice.jsx
@@ -4,7 +4,7 @@ import Notice from 'notices/notice.jsx';
const MailerStatusNotice = ({ error }) => {
if (!error || error.operation !== 'authorization') return null;
- return {error.error_message}
;
+ return {error.error_message}
;
};
MailerStatusNotice.propTypes = {
error: PropTypes.shape({
diff --git a/assets/js/src/notices/notice.jsx b/assets/js/src/notices/notice.jsx
index 096496c8b2..eb7739b7e2 100644
--- a/assets/js/src/notices/notice.jsx
+++ b/assets/js/src/notices/notice.jsx
@@ -7,12 +7,19 @@ const Notice = (props) => {
const elementRef = React.useRef(null);
const timeoutRef = React.useRef(null);
+ const { onClose, onDisplay } = props;
+
+ const close = React.useCallback(() => {
+ if (onClose) onClose();
+ setHidden(true);
+ }, [onClose]);
+
React.useEffect(() => {
if (props.timeout) {
- timeoutRef.current = setTimeout(() => setHidden(true), props.timeout);
+ timeoutRef.current = setTimeout(close, props.timeout);
}
return () => (timeoutRef.current ? clearTimeout(timeoutRef.current) : null);
- }, [props.timeout]);
+ }, [close, props.timeout]);
React.useLayoutEffect(() => {
if (props.scroll && elementRef.current) {
@@ -20,15 +27,29 @@ const Notice = (props) => {
}
}, [props.scroll]);
+ React.useLayoutEffect(() => {
+ if (onDisplay) onDisplay();
+ }, [onDisplay]);
+
if (hidden) return null;
return ReactDOM.createPortal(
-
{props.children}
,
+
+ {props.children}
+ {props.closable && (
+
+ )}
+
,
document.getElementById('mailpoet_notices')
);
};
Notice.propTypes = {
type: PropTypes.oneOf(['success', 'info', 'warning', 'error']).isRequired,
scroll: PropTypes.bool,
+ closable: PropTypes.bool,
+ onDisplay: PropTypes.func,
+ onClose: PropTypes.func,
timeout: PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf([false])]),
children: PropTypes.oneOfType([
PropTypes.string,
@@ -39,6 +60,9 @@ Notice.propTypes = {
Notice.defaultProps = {
timeout: 10000,
scroll: false,
+ closable: true,
+ onDisplay: undefined,
+ onClose: undefined,
};
export default Notice;
diff --git a/assets/js/src/notices/subscribers_limit_notice.jsx b/assets/js/src/notices/subscribers_limit_notice.jsx
index 7a8bf38036..41af035e03 100644
--- a/assets/js/src/notices/subscribers_limit_notice.jsx
+++ b/assets/js/src/notices/subscribers_limit_notice.jsx
@@ -5,7 +5,7 @@ import Notice from 'notices/notice.jsx';
const SubscribersLimitNotice = () => {
if (!window.mailpoet_subscribers_limit_reached) return null;
return (
-
+
{
MailPoet.I18n.t('subscribersLimitNoticeTitle')