All files / src/Notify Notify.js

0% Statements 0/40
0% Branches 0/16
0% Functions 0/10
0% Lines 0/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182                                                                                                                                                                                                                                                                                                                                                                           
import React, { Component } from 'preact';
import PropTypes from 'prop-types';
import NotifyPortal from './NotifyPortal';
import lodash from 'lodash';
import Icon from './../Icon';
import colors from './../theme';
import NotifyPanel from './NotifyPanel';
import { StyledNotify } from './styles';
 
/**
 * Notification system for application with customizable features
 *
 * @example ./../../docs/components/Notify.md
 */
class Notify extends Component {
    static propTypes = {
        /**
         * Unique id for the notification wrapper
         */
        id: PropTypes.string.required,
 
        /**
         * Custom styles
         */
        style: PropTypes.object,
 
        /**
         * Title
         */
        title: PropTypes.string,
 
        /**
         * Delay in seconds for the notification go away. Set this to 0 to not auto-dismiss the notification.
         */
        autoDismiss: PropTypes.number,
 
        /**
         * Message
         */
        message: PropTypes.string,
 
        /**
         * Level of the notification
         */
        type: PropTypes.oneOf(['success', 'warning', 'error', 'info']),
 
        /**
         * Callback function on click of notification
         */
        onClick: PropTypes.func,
 
        /**
         * Icon name from font awesome - default is bell-o
         */
        iconName: PropTypes.string,
 
        /**
         * Size of the icon
         */
        iconSize: PropTypes.oneOf([
            'xsmall',
            'small',
            'medium',
            'large',
            'xlarge',
        ]),
 
        /**
         * Icon color
         */
        iconColor: PropTypes.string,
 
        /**
         * A callback function that will be called when the notification is successfully added. The first argument is the original notification e.g. `function (notification) { console.log(notification.title + 'was added'); }`
         */
        onAdd: PropTypes.func,
 
        /**
         * A callback function that will be called when the notification is about to be removed. The first argument is the original notification e.g. `function (notification) { console.log(notification.title + 'was removed'); }`
         */
        onDismiss: PropTypes.func,
    };
 
    static defaultProps = {
        type: 'info',
        style: {},
        title: null,
        message: null,
        autoDismiss: 5,
        iconName: 'bell-o',
        iconColor: 'dark gray',
        iconSize: 'xsmall',
    };
 
    constructor(props) {
        super(props);
        this.state = {
            notifications: [],
        };
    }
 
    get guid() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
            const r = (Math.random() * 16) | 0,
                v = c == 'x' ? r : (r & 0x3) | 0x8;
            return v.toString(16);
        });
    }
 
    add = notification => {
        const notifications = this.state.notifications;
        notifications.push(
            Object.assign(notification, {
                guid: this.guid,
                close: () => {
                    this.dismiss(notification);
                },
            })
        );
 
        // onAdd callback
        if (typeof notification.onAdd === 'function') {
            notification.onAdd(notification);
        }
 
        // set the state to display the notification
        this.setState(
            {
                notifications,
            },
            () => {
                const { autoDismiss = 5 } = notification;
                if (autoDismiss !== 0 && typeof autoDismiss === 'number') {
                    setTimeout(() => {
                        this.dismiss(notification);
                    }, autoDismiss * 1000);
                }
                // clear notification state
                this.setState({
                    notifications: [],
                });
            }
        );
    };
 
    dismiss = notification => {
        const { id } = this.props;
        const notifyWrapper = document.getElementById(id);
        const notificationElement = document.getElementById(notification.guid);
 
        // onDismiss callback
        if (typeof notification.onDismiss === 'function') {
            notification.onDismiss(notification);
        }
 
        // close the notitication
        notificationElement.classList.add('close');
 
        // destroy the notification after 500ms
        setTimeout(() => {
            notifyWrapper.removeChild(notificationElement.parentNode);
        }, 500);
    };
 
    renderNotification = () => {
        return this.state.notifications.map((notification, i) => (
            <NotifyPanel key={i} {...notification} />
        ));
    };
 
    render() {
        const { id, position = 'bottom' } = this.props;
        return (
            <NotifyPortal portalId={id} position={position}>
                {this.renderNotification()}
            </NotifyPortal>
        );
    }
}
 
export default Notify;