Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I was in need of a thing that is able to inform my users about recent activities as well as intercept any action with a modal (e.g for undo purposes)

I decided that I will go for an independent module that could be included in any project. The module contains the following:

  • A directive which will show the messages to the user and handle interactions with the modals
  • A controller for said directive
  • A configurable provider that shall provide the logic

Further, there are 2 external files, the template and the stylesheet.


Desired procedure

Notifications

Notifications are simple. They shall pop up and disappear after n seconds. It would be nice if we had different types (e.g error, success etc.)

Interceptions

Interceptions shall show a message and provide either 1 or 2 buttons. They have to return a promise in order to decide further action.

If there is only one button specified, hitting it should resolve the promise. When there are 2, the first one should resolve while the second one should reject.

if neither one is hit, the promise should be rejected after n seconds.

Solution

"use strict";

var purr = angular.module('purr', []);

purr.controller('purrController',function($scope,purr){

    $scope.notificationQueue = purr.getNotificationQueue();
    $scope.interceptionQueue = purr.getInterceptionQueue();

});

purr.directive('purr',function(purr){
    return{
        restrict: 'EA',
        scope: {},
        templateUrl: "partials/assets/purr.html",
        controller: 'purrController'
    }
});

purr.provider('purr',function(){

    var module = this;

    this.options = {};

    this.$get = function($timeout,$q){

        var self = this;

        var defer = $q.defer();

        var notificationQueue = [];

        var interceptionQueue = [];

        var timer;

        var types = {

            'info': {
                'icon': 'fa-info',
                'class': 'purr-info',
                'type': 'Information'
            },

            'warning': {
                'icon': 'fa-warning',
                'class': 'purr-warning',
                'type': 'Warning'
            },

            'error': {
                'icon': 'fa-exclamation',
                'class': 'purr-error',
                'type': 'Failure'
            },

            'success': {
                'icon': 'fa-check',
                'class': 'purr-success',
                'type': 'Success'
            }

        };

        var createNotification = function(msg,type){

            var defaults = {
                'message': "No message given. Please report this issue.",
                'icon': 'fa-info'
            };

            var settings = {
                'timeout': 5000
            };

            settings = angular.extend(settings, module.options);

            var notification = angular.extend(types[type],{message: msg || this.defaults.message});

            notificationQueue.push(notification);

            $timeout(function(){
                notificationQueue.length = 0;
            },settings.timeout);

        };

        function Interception(msg,appr,decl){

            this.message = msg;

            this.approval = {
                caption: appr,
                fire: function(){
                    defer.resolve('yup');
                    interceptionQueue.length = 0;
                    resetPromise();
                    $timeout.cancel(timer);
                }
            };

            this.decline = {
                caption: decl,
                fire: function(){
                    defer.reject('nope');
                    interceptionQueue.length = 0;
                    resetPromise();
                    $timeout.cancel(timer);
                }
            };
        }

        function resetPromise(){
            defer = $q.defer();
        }

        return{

            getNotificationQueue: function(){
                return notificationQueue;
            },
            getInterceptionQueue: function(){
                return interceptionQueue;
            },
            info: function(msg){
                createNotification(msg,'info');
            },
            warning: function(msg){
                createNotification(msg,'warning');
            },
            success: function(msg){
                createNotification(msg,'success');
            },
            error: function(msg){
                createNotification(msg,'error');
            },
            intercept: function(msg,appr,decl){

                var interception = new Interception(msg,appr,decl);

                interceptionQueue.push(interception);

                timer = $timeout(function(){},5000);

                timer
                    .then(function(){
                        if(interceptionQueue.length){
                            defer.reject('timeout');
                            interceptionQueue.length = 0;
                            resetPromise();
                        }
                    });

                return defer.promise;

            }
        }

    }

});

This is my solution. It is used like this:

//Interception
purr.intercept('Do you want to undo that action?','Yes','No')
            .then(function(res){
               //undo
            })
            .catch(function(res){
                //do nothing
            });

 //notification
 purr.error('fail');

I am happy with the result since it works. Yet, I feel like the code base could be improved. An issue that bothers me is the fact that I have to call both resetPromise() and $timeout.cancel() in redundant ways.

Further, as you may have noticed, I decided to use a class-like implementation for the interceptions while the notifications are created in a more procedural way. Are there any reasons to prefer one over the other? (Personally, I prefer the OO style)

Purr on GitHub

share|improve this question

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.