<commit_before>
export default {
  methods: {
    openModal() {
      $("#myModal").modal()
    },
    checkPermission(dec){
      return (dec >>> 0).toString(2)
    },
    makeBreadCrumbList(list) {
      var breadcrumblist = []

      _.each(list,(item,i,arr)=>{
        let _breadcrumb = {}
        _breadcrumb.text = item.node_name_en
        _breadcrumb.isActive = i===arr.length-1
        breadcrumblist.push(_breadcrumb)
      })
      return breadcrumblist
    },
    handleError(res){
      if(res.hasOwnProperty("text")){
        swal(res.text.common).then(()=>{
          this.$router.go({path: "/login"});
        })
      }else{
        swal("系統錯誤！")
      }
    },
    handleRemove(api,cb) {
      swal({
        title: '是否確認刪除?',
        type: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#3085d6',
        cancelButtonColor: '#d33',
        confirmButtonText: '確認刪除',
        cancelButtonText: "取消"
      }).then(function() {
        api.then(cb,()=>{
          swal("未刪除成功!");
        })
      })
    },
    obj2arr(obj) {
      var list = []
      _.each(obj,(val,key)=>{
        list.push([key,val])
      })
      return list
    }
  }
}
<commit_msg>table page..<commit_after>
export default {
  methods: {
    openModal() {
      $("#myModal").modal()
    },
    closeModal() {
      $('#myModal').modal("hide")
    },
    makeBreadCrumbList(list) {
      var breadcrumblist = []

      _.each(list,(item,i,arr)=>{
        let _breadcrumb = {}
        _breadcrumb.text = item.node_name_en
        _breadcrumb.isActive = i===arr.length-1
        breadcrumblist.push(_breadcrumb)
      })
      return breadcrumblist
    },
    handleError(res){
      if(res.hasOwnProperty("text")){
        swal(res.text.common).then(()=>{
          this.$router.go({path: "/login"});
        })
      }else{
        swal("系統錯誤！")
      }
    },
    handleRemove(api,cb) {
      swal({
        title: '是否確認刪除?',
        type: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#3085d6',
        cancelButtonColor: '#d33',
        confirmButtonText: '確認刪除',
        cancelButtonText: "取消"
      }).then(function() {
        api.then(cb,()=>{
          swal("未刪除成功!");
        })
      })
    },
    obj2arr(obj) {
      var list = []
      _.each(obj,(val,key)=>{
        list.push([key,val])
      })
      return list
    }
  }
}
<|endoftext|>


<commit_before>
(function (window, angular, undefined) {
  'use strict';

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

  var $el = angular.element;
  var isDef = angular.isDefined;
  var style = (document.body || document.documentElement).style;
  var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
  var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
  var forceBodyReload = false;

  module.provider('ngGallery', function () {
    var defaults = this.defaults = {
      className: 'nggallery-theme-default',
      showClose: true,
      prefix: '',
      closeByDocument: true,
      closeByEscape: true,
      closeByNavigation: false,
      appendTo: false,
      preCloseCallback: false,
      url: false
    };

    this.setForceBodyReload = function (_useIt) {
      forceBodyReload = _useIt || false;
    };

    this.setDefaults = function (newDefaults) {
      angular.extend(defaults, newDefaults);
    };

    var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};

    this.$get = ['$document', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller',
      function ($document, $compile, $q, $http, $rootScope, $timeout, $window, $controller) {
        var $body = $document.find('body');
        if (forceBodyReload) {
          $rootScope.$on('$locationChangeSuccess', function () {
            $body = $document.find('body');
          });
        }

        var privateMethods = {
          onDocumentKeydown: function (event) {
            if (event.keyCode === 27) {
              publicMethods.close('$escape');
            }
          },

          onGalleryKeydown: function (scope) {
            return function () {
              var dialogScope = scope;
              if (event.keyCode === 37) {
                dialogScope.prevImage();
              }
              else if (event.keyCode === 39) {
                dialogScope.nextImage();
              }
            };
          },

          setBodyPadding: function (width) {
            var originalBodyPadding = parseInt(($body.css('padding-right') || 0), 10);
            $body.css('padding-right', (originalBodyPadding + width) + 'px');
            $body.data('ng-dialog-original-padding', originalBodyPadding);
          },

          resetBodyPadding: function () {
            var originalBodyPadding = $body.data('ng-dialog-original-padding');
            if (originalBodyPadding) {
              $body.css('padding-right', originalBodyPadding + 'px');
            } else {
              $body.css('padding-right', '');
            }
          },

          performCloseDialog: function ($dialog, value) {
            var id = $dialog.attr('id');

            if (typeof window.Hammer !== 'undefined') {
              window.Hammer($dialog[0]).off('tap', closeByDocumentHandler);
            } else {
              $dialog.unbind('click');
            }

            if (dialogsCount === 1) {
              $body.unbind('keydown');
            }

            if (!$dialog.hasClass('nggallery-closing')) {
              dialogsCount -= 1;
            }

            if (animationEndSupport) {
              $dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
                $dialog.scope().$destroy();
                $dialog.remove();
                if (dialogsCount === 0) {
                  $body.removeClass('nggallery-open');
                  privateMethods.resetBodyPadding();
                }
                $rootScope.$broadcast('ngGallery.closed', $dialog);
              }).addClass('nggallery-closing');
            } else {
              $dialog.scope().$destroy();
              $dialog.remove();
              if (dialogsCount === 0) {
                $body.removeClass('nggallery-open');
                privateMethods.resetBodyPadding();
              }
              $rootScope.$broadcast('ngGallery.closed', $dialog);
            }
            if (defers[id]) {
              defers[id].resolve({
                id: id,
                value: value,
                $dialog: $dialog,
                remainingGallerys: dialogsCount
              });
              delete defers[id];
            }
          },

          closeDialog: function ($dialog, value) {
            var preCloseCallback = $dialog.data('$ngGalleryPreCloseCallback');

            if (preCloseCallback && angular.isFunction(preCloseCallback)) {

              var preCloseCallbackResult = preCloseCallback.call($dialog, value);

              if (angular.isObject(preCloseCallbackResult)) {
                if (preCloseCallbackResult.closePromise) {
                  preCloseCallbackResult.closePromise.then(function () {
                    privateMethods.performCloseDialog($dialog, value);
                  });
                } else {
                  preCloseCallbackResult.then(function () {
                    privateMethods.performCloseDialog($dialog, value);
                  }, function () {
                    return;
                  });
                }
              } else if (preCloseCallbackResult !== false) {
                privateMethods.performCloseDialog($dialog, value);
              }
            } else {
              privateMethods.performCloseDialog($dialog, value);
            }
          }
        };

        var publicMethods = {

          /*
           * @param {Object} options:
           * - template {String} - id of ng-template, url for partial, plain string (if enabled)
           * - scope {Object}
           * - controller {String}
           * - className {String} - dialog theme class
           * - showClose {Boolean} - show close button, default true
           * - closeByEscape {Boolean} - default true
           * - closeByDocument {Boolean} - default true
           * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set)
           *
           * @return {Object} dialog
           */
          open: function (opts) {
            var self = this;
            var options = angular.copy(defaults);

            opts = opts || {};
            angular.extend(options, opts);

            globalID += 1;

            self.latestID = 'nggallery' + globalID;

            var defer;
            defers[self.latestID] = defer = $q.defer();

            var scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
            var $dialog, $dialogParent;

            $q.when(loadImages(options.url, options.images)).then(function (template) {
              if (options.showClose) {
                template += '

';
              }

              self.$result = $dialog = $el('

');
              $dialog.html('

' + template + '
');

              if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {
                var controllerInstance = $controller(options.controller, {
                  $scope: scope,
                  $element: $dialog
                });
                $dialog.data('$ngGalleryControllerController', controllerInstance);
              }

              if (options.appendTo && angular.isString(options.appendTo)) {
                $dialogParent = angular.element(document.querySelector(options.appendTo));
              } else {
                $dialogParent = $body;
              }

              scope.visibleID = 0;

              scope.nextImage = function () {
                 $timeout(function() {
                    if (scope.visibleID === scope.images.length - 1) {
                      scope.closeThisDialog();
                    } else {
                      scope.visibleID += 1;
                    }
                  }, 0);
              };

              scope.prevImage = function () {
                 $timeout(function() {
                  if (scope.visibleID !== 0) {
                    scope.visibleID -= 1;
                  }
                 }, 0);
              };

              scope.closeGallery = function (event) {
                if ($el(event.target).hasClass('gallery-item') === true) {
                  scope.closeThisDialog();
                }
              };

              scope.closeThisDialog = function (value) {
                privateMethods.closeDialog($dialog, value);
              };

              $timeout(function () {
                $compile($dialog)(scope);

                var widthDiffs = $window.innerWidth - $body.prop('clientWidth');
                $body.addClass('nggallery-open');
                var scrollBarWidth = widthDiffs - ($window.innerWidth - $body.prop('clientWidth'));
                if (scrollBarWidth > 0) {
                  privateMethods.setBodyPadding(scrollBarWidth);
                }
                $dialogParent.append($dialog);

                if (options.name) {
                  $rootScope.$broadcast('ngGallery.opened', {dialog: $dialog, name: options.name});
                } else {
                  $rootScope.$broadcast('ngGallery.opened', $dialog);
                }
              });

              if (options.closeByEscape) {
                $body.bind('keydown', privateMethods.onDocumentKeydown);
              }
              $body.bind('keydown', privateMethods.onGalleryKeydown(scope));

              if (options.closeByNavigation) {
                $rootScope.$on('$locationChangeSuccess', function () {
                  privateMethods.closeDialog($dialog);
                });
              }

              closeByDocumentHandler = function (event) {
                var isOverlay = options.closeByDocument ? $el(event.target).hasClass('nggallery-overlay') : false;
                var isCloseBtn = $el(event.target).hasClass('nggallery-close');

                if (isOverlay || isCloseBtn) {
                  publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
                }
              };

              if (typeof window.Hammer !== 'undefined') {
                window.Hammer($dialog[0]).on('tap', closeByDocumentHandler);
              } else {
                $dialog.bind('click', closeByDocumentHandler);
              }

              dialogsCount += 1;

              return publicMethods;
            });

            return {
              id: 'nggallery' + globalID,
              closePromise: defer.promise,
              close: function (value) {
                privateMethods.closeDialog($dialog, value);
              }
            };

            function loadImages (url, images) {
              var _generateTemplate = function (images) {
                scope.images = images;
                var template = '
';
                for (var i = 0; i < images.length; ++i) {
                  template += '

';
                }
                template += '
';
                return template;
              }
              if(url !== false) {
                return $http.get(url).then(function(result) {
                  return _generateTemplate(result.data);
                }, function(data, status) {
                  // emit error;
                });
              } else {
                return _generateTemplate(images);
              }
            }
          },

          /*
           * @param {Object} options:
           * - template {String} - id of ng-template, url for partial, plain string (if enabled)
           * - plain {Boolean} - enable plain string templates, default false
           * - scope {Object}
           * - controller {String}
           * - className {String} - dialog theme class
           * - showClose {Boolean} - show close button, default true
           * - closeByEscape {Boolean} - default false
           * - closeByDocument {Boolean} - default false
           * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set); not called on confirm
           *
           * @return {Object} dialog
           */
          openConfirm: function (opts) {
            var defer = $q.defer();

            var options = {
              closeByEscape: false,
              closeByDocument: false
            };
            angular.extend(options, opts);

            options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
            options.scope.confirm = function (value) {
              defer.resolve(value);
              var $dialog = $el(document.getElementById(openResult.id));
              privateMethods.performCloseDialog($dialog, value);
            };

            var openResult = publicMethods.open(options);
            openResult.closePromise.then(function (data) {
              if (data) {
                return defer.reject(data.value);
              }
              return defer.reject();
            });

            return defer.promise;
          },

          /*
           * @param {String} id
           * @return {Object} dialog
           */
          close: function (id, value) {
            var $dialog = $el(document.getElementById(id));

            if ($dialog.length) {
              privateMethods.closeDialog($dialog, value);
            } else {
              publicMethods.closeAll(value);
            }

            return publicMethods;
          },

          closeAll: function (value) {
            var $all = document.querySelectorAll('.nggallery');

            angular.forEach($all, function (dialog) {
              privateMethods.closeDialog($el(dialog), value);
            });
          },

          getDefaults: function () {
            return defaults;
          }
        };

        return publicMethods;
      }];
  });

  module.directive('ngGallery', ['ngGallery', function (ngGallery) {
    return {
      restrict: 'A',
      scope : {
        ngGalleryScope : '='
      },
      link: function (scope, elem, attrs) {
        elem.on('click', function (e) {
          e.preventDefault();

          var ngGalleryScope = angular.isDefined(scope.ngGalleryScope) ? scope.ngGalleryScope : 'noScope';
          angular.isDefined(attrs.ngGalleryClosePrevious) && ngGallery.close(attrs.ngGalleryClosePrevious);

          var defaults = ngGallery.getDefaults();

          ngGallery.open({
            className: attrs.ngGalleryClass || defaults.className,
            controller: attrs.ngGalleryController,
            scope: ngGalleryScope,
            data: attrs.ngGalleryData,
            prefix: attrs.ngGalleryPrefix,
            showClose: attrs.ngGalleryShowClose === 'false' ? false : (attrs.ngGalleryShowClose === 'true' ? true : defaults.showClose),
            closeByDocument: attrs.ngGalleryCloseByDocument === 'false' ? false : (attrs.ngGalleryCloseByDocument === 'true' ? true : defaults.closeByDocument),
            closeByEscape: attrs.ngGalleryCloseByEscape === 'false' ? false : (attrs.ngGalleryCloseByEscape === 'true' ? true : defaults.closeByEscape),
            preCloseCallback: attrs.ngGalleryPreCloseCallback || defaults.preCloseCallback
          });
        });
      }
    };
  }]);

})(window, window.angular);
<commit_msg>fix promise get images resolver<commit_after>
(function (window, angular, undefined) {
  'use strict';

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

  var $el = angular.element;
  var isDef = angular.isDefined;
  var style = (document.body || document.documentElement).style;
  var animationEndSupport = isDef(style.animation) || isDef(style.WebkitAnimation) || isDef(style.MozAnimation) || isDef(style.MsAnimation) || isDef(style.OAnimation);
  var animationEndEvent = 'animationend webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend';
  var forceBodyReload = false;

  module.provider('ngGallery', function () {
    var defaults = this.defaults = {
      className: 'nggallery-theme-default',
      showClose: true,
      prefix: '',
      closeByDocument: true,
      closeByEscape: true,
      closeByNavigation: false,
      appendTo: false,
      preCloseCallback: false,
      url: false
    };

    this.setForceBodyReload = function (_useIt) {
      forceBodyReload = _useIt || false;
    };

    this.setDefaults = function (newDefaults) {
      angular.extend(defaults, newDefaults);
    };

    var globalID = 0, dialogsCount = 0, closeByDocumentHandler, defers = {};

    this.$get = ['$document', '$compile', '$q', '$http', '$rootScope', '$timeout', '$window', '$controller',
      function ($document, $compile, $q, $http, $rootScope, $timeout, $window, $controller) {
        var $body = $document.find('body');
        if (forceBodyReload) {
          $rootScope.$on('$locationChangeSuccess', function () {
            $body = $document.find('body');
          });
        }

        var privateMethods = {
          onDocumentKeydown: function (event) {
            if (event.keyCode === 27) {
              publicMethods.close('$escape');
            }
          },

          onGalleryKeydown: function (scope) {
            return function () {
              var dialogScope = scope;
              if (event.keyCode === 37) {
                dialogScope.prevImage();
              }
              else if (event.keyCode === 39) {
                dialogScope.nextImage();
              }
            };
          },

          setBodyPadding: function (width) {
            var originalBodyPadding = parseInt(($body.css('padding-right') || 0), 10);
            $body.css('padding-right', (originalBodyPadding + width) + 'px');
            $body.data('ng-dialog-original-padding', originalBodyPadding);
          },

          resetBodyPadding: function () {
            var originalBodyPadding = $body.data('ng-dialog-original-padding');
            if (originalBodyPadding) {
              $body.css('padding-right', originalBodyPadding + 'px');
            } else {
              $body.css('padding-right', '');
            }
          },

          performCloseDialog: function ($dialog, value) {
            var id = $dialog.attr('id');

            if (typeof window.Hammer !== 'undefined') {
              window.Hammer($dialog[0]).off('tap', closeByDocumentHandler);
            } else {
              $dialog.unbind('click');
            }

            if (dialogsCount === 1) {
              $body.unbind('keydown');
            }

            if (!$dialog.hasClass('nggallery-closing')) {
              dialogsCount -= 1;
            }

            if (animationEndSupport) {
              $dialog.unbind(animationEndEvent).bind(animationEndEvent, function () {
                $dialog.scope().$destroy();
                $dialog.remove();
                if (dialogsCount === 0) {
                  $body.removeClass('nggallery-open');
                  privateMethods.resetBodyPadding();
                }
                $rootScope.$broadcast('ngGallery.closed', $dialog);
              }).addClass('nggallery-closing');
            } else {
              $dialog.scope().$destroy();
              $dialog.remove();
              if (dialogsCount === 0) {
                $body.removeClass('nggallery-open');
                privateMethods.resetBodyPadding();
              }
              $rootScope.$broadcast('ngGallery.closed', $dialog);
            }
            if (defers[id]) {
              defers[id].resolve({
                id: id,
                value: value,
                $dialog: $dialog,
                remainingGallerys: dialogsCount
              });
              delete defers[id];
            }
          },

          closeDialog: function ($dialog, value) {
            var preCloseCallback = $dialog.data('$ngGalleryPreCloseCallback');

            if (preCloseCallback && angular.isFunction(preCloseCallback)) {

              var preCloseCallbackResult = preCloseCallback.call($dialog, value);

              if (angular.isObject(preCloseCallbackResult)) {
                if (preCloseCallbackResult.closePromise) {
                  preCloseCallbackResult.closePromise.then(function () {
                    privateMethods.performCloseDialog($dialog, value);
                  });
                } else {
                  preCloseCallbackResult.then(function () {
                    privateMethods.performCloseDialog($dialog, value);
                  }, function () {
                    return;
                  });
                }
              } else if (preCloseCallbackResult !== false) {
                privateMethods.performCloseDialog($dialog, value);
              }
            } else {
              privateMethods.performCloseDialog($dialog, value);
            }
          }
        };

        var publicMethods = {

          /*
           * @param {Object} options:
           * - template {String} - id of ng-template, url for partial, plain string (if enabled)
           * - scope {Object}
           * - controller {String}
           * - className {String} - dialog theme class
           * - showClose {Boolean} - show close button, default true
           * - closeByEscape {Boolean} - default true
           * - closeByDocument {Boolean} - default true
           * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set)
           *
           * @return {Object} dialog
           */
          open: function (opts) {
            var self = this;
            var options = angular.copy(defaults);

            opts = opts || {};
            angular.extend(options, opts);

            globalID += 1;

            self.latestID = 'nggallery' + globalID;

            var defer;
            defers[self.latestID] = defer = $q.defer();

            var scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
            var $dialog, $dialogParent;

            $q.when(loadImages(options.url, options.images)).then(function (template) {
              if (options.showClose) {
                template += '

';
              }

              self.$result = $dialog = $el('

');
              $dialog.html('

' + template + '
');

              if (options.controller && (angular.isString(options.controller) || angular.isArray(options.controller) || angular.isFunction(options.controller))) {
                var controllerInstance = $controller(options.controller, {
                  $scope: scope,
                  $element: $dialog
                });
                $dialog.data('$ngGalleryControllerController', controllerInstance);
              }

              if (options.appendTo && angular.isString(options.appendTo)) {
                $dialogParent = angular.element(document.querySelector(options.appendTo));
              } else {
                $dialogParent = $body;
              }

              scope.visibleID = 0;

              scope.nextImage = function () {
                 $timeout(function() {
                    if (scope.visibleID === scope.images.length - 1) {
                      scope.closeThisDialog();
                    } else {
                      scope.visibleID += 1;
                    }
                  }, 0);
              };

              scope.prevImage = function () {
                 $timeout(function() {
                  if (scope.visibleID !== 0) {
                    scope.visibleID -= 1;
                  }
                 }, 0);
              };

              scope.closeGallery = function (event) {
                if ($el(event.target).hasClass('gallery-item') === true) {
                  scope.closeThisDialog();
                }
              };

              scope.closeThisDialog = function (value) {
                privateMethods.closeDialog($dialog, value);
              };

              $timeout(function () {
                $compile($dialog)(scope);

                var widthDiffs = $window.innerWidth - $body.prop('clientWidth');
                $body.addClass('nggallery-open');
                var scrollBarWidth = widthDiffs - ($window.innerWidth - $body.prop('clientWidth'));
                if (scrollBarWidth > 0) {
                  privateMethods.setBodyPadding(scrollBarWidth);
                }
                $dialogParent.append($dialog);

                if (options.name) {
                  $rootScope.$broadcast('ngGallery.opened', {dialog: $dialog, name: options.name});
                } else {
                  $rootScope.$broadcast('ngGallery.opened', $dialog);
                }
              });

              if (options.closeByEscape) {
                $body.bind('keydown', privateMethods.onDocumentKeydown);
              }
              $body.bind('keydown', privateMethods.onGalleryKeydown(scope));

              if (options.closeByNavigation) {
                $rootScope.$on('$locationChangeSuccess', function () {
                  privateMethods.closeDialog($dialog);
                });
              }

              closeByDocumentHandler = function (event) {
                var isOverlay = options.closeByDocument ? $el(event.target).hasClass('nggallery-overlay') : false;
                var isCloseBtn = $el(event.target).hasClass('nggallery-close');

                if (isOverlay || isCloseBtn) {
                  publicMethods.close($dialog.attr('id'), isCloseBtn ? '$closeButton' : '$document');
                }
              };

              if (typeof window.Hammer !== 'undefined') {
                window.Hammer($dialog[0]).on('tap', closeByDocumentHandler);
              } else {
                $dialog.bind('click', closeByDocumentHandler);
              }

              dialogsCount += 1;

              return publicMethods;
            });

            return {
              id: 'nggallery' + globalID,
              closePromise: defer.promise,
              close: function (value) {
                privateMethods.closeDialog($dialog, value);
              }
            };

            function loadImages (url, images) {
              var _generateTemplate = function (images) {
                scope.images = images;
                var template = '
';
                for (var i = 0; i < images.length; ++i) {
                  template += '

';
                }
                template += '
';
                return template;
              };
              if(url !== false) {
                return $http.get(url).then(function(result) {
                  return _generateTemplate(result.data);
                }, function(error) {
                  // emit error;
                });
              } else {
                return _generateTemplate(images);
              }
            }
          },

          /*
           * @param {Object} options:
           * - template {String} - id of ng-template, url for partial, plain string (if enabled)
           * - plain {Boolean} - enable plain string templates, default false
           * - scope {Object}
           * - controller {String}
           * - className {String} - dialog theme class
           * - showClose {Boolean} - show close button, default true
           * - closeByEscape {Boolean} - default false
           * - closeByDocument {Boolean} - default false
           * - preCloseCallback {String|Function} - user supplied function name/function called before closing dialog (if set); not called on confirm
           *
           * @return {Object} dialog
           */
          openConfirm: function (opts) {
            var defer = $q.defer();

            var options = {
              closeByEscape: false,
              closeByDocument: false
            };
            angular.extend(options, opts);

            options.scope = angular.isObject(options.scope) ? options.scope.$new() : $rootScope.$new();
            options.scope.confirm = function (value) {
              defer.resolve(value);
              var $dialog = $el(document.getElementById(openResult.id));
              privateMethods.performCloseDialog($dialog, value);
            };

            var openResult = publicMethods.open(options);
            openResult.closePromise.then(function (data) {
              if (data) {
                return defer.reject(data.value);
              }
              return defer.reject();
            });

            return defer.promise;
          },

          /*
           * @param {String} id
           * @return {Object} dialog
           */
          close: function (id, value) {
            var $dialog = $el(document.getElementById(id));

            if ($dialog.length) {
              privateMethods.closeDialog($dialog, value);
            } else {
              publicMethods.closeAll(value);
            }

            return publicMethods;
          },

          closeAll: function (value) {
            var $all = document.querySelectorAll('.nggallery');

            angular.forEach($all, function (dialog) {
              privateMethods.closeDialog($el(dialog), value);
            });
          },

          getDefaults: function () {
            return defaults;
          }
        };

        return publicMethods;
      }];
  });

  module.directive('ngGallery', ['ngGallery', function (ngGallery) {
    return {
      restrict: 'A',
      scope : {
        ngGalleryScope : '='
      },
      link: function (scope, elem, attrs) {
        elem.on('click', function (e) {
          e.preventDefault();

          var ngGalleryScope = angular.isDefined(scope.ngGalleryScope) ? scope.ngGalleryScope : 'noScope';
          angular.isDefined(attrs.ngGalleryClosePrevious) && ngGallery.close(attrs.ngGalleryClosePrevious);

          var defaults = ngGallery.getDefaults();

          ngGallery.open({
            className: attrs.ngGalleryClass || defaults.className,
            controller: attrs.ngGalleryController,
            scope: ngGalleryScope,
            data: attrs.ngGalleryData,
            prefix: attrs.ngGalleryPrefix,
            showClose: attrs.ngGalleryShowClose === 'false' ? false : (attrs.ngGalleryShowClose === 'true' ? true : defaults.showClose),
            closeByDocument: attrs.ngGalleryCloseByDocument === 'false' ? false : (attrs.ngGalleryCloseByDocument === 'true' ? true : defaults.closeByDocument),
            closeByEscape: attrs.ngGalleryCloseByEscape === 'false' ? false : (attrs.ngGalleryCloseByEscape === 'true' ? true : defaults.closeByEscape),
            preCloseCallback: attrs.ngGalleryPreCloseCallback || defaults.preCloseCallback
          });
        });
      }
    };
  }]);

})(window, window.angular);
<|endoftext|>


<commit_before>var crypto = require('crypto');

var _ = require('lodash');
var uuid = require('node-uuid');

var leaderboard = require('./leaderboard');
var utils = require('./utils');

const MAX_LEADERBOARD_INCR = 10;
const TIME_UPDATE_PLAYTIME = 1000 * 60 * 5;  // 5 minutes

function newUser(client, email) {
    var userData = {
        username: email.split('@')[0],
        email: email,
        dateLastLogin: utils.now(),
        id: uuid.v4()
    };
    client.hset('users', userData.id, JSON.stringify(userData));
    client.hset('usersByEmail', email, userData.id);
    // TODO: Figure out a way to store users by username.
    return userData;
}
exports.newUser = newUser;

function updateUser(client, userData, opts) {
    var newUserData = _.extend(_.clone(userData), opts);
    // Only update the modified timestamp if anything but the lastLogin
    // timestamp has changed.
    if (!_.isEqual(_.omit(userData, 'dateLastLogin'),
                   _.omit(newUserData, 'dateLastLogin'))) {
        newUserData.datelastModified = utils.now();
    }
    client.hset('users', newUserData.id, JSON.stringify(newUserData));
    if (userData.email !== newUserData.email) {
        client.hset('usersByEmail', newUserData.email, newUserData.id);
    }
    return newUserData;
}
exports.updateUser = updateUser;

// This manages user state for a single connection.
function user(dataChannel) {
    this.authenticated = false;
    this.dataChannel = dataChannel;
    this.data = {};
    this.friends = null;  // A cache.
}

user.prototype.eachFriend = function(cb) {
    if (this.friends) {
        this.friends.forEach(cb);
    } else {
        var self = this;
        this.dataChannel.smembers('friends:' + this.get('id'), function(err, resp) {
            if (err || !resp) return;
            // NOTE: This cheats. If a user adds a friend, the friend won't get
            // notifications until this user re-connects. Womp womp.
            (self.friends = resp).forEach(cb);
        });
    }
};

user.prototype.notifyFriends = function(type, data) {
    data.notification_type = type;
    data.type = 'notification';
    data.from = publicUserObj(this.get('full'));
    var json = JSON.stringify(data);
    var self = this;
    this.eachFriend(function(friendID) {
        self.dataChannel.publish('user:' + friendID, json);
    });
};

user.prototype.set = function(key, value) {
    this.data[key] = value;
};

user.prototype.get = function(key) {
    return this.data[key] || null;
};

user.prototype.authenticate = function(email, callback) {
    var self = this;
    getUserFromEmail(this.dataChannel, email, function(err, userData) {
        if (err) {
            callback('error_fetching_user');
            return;
        }
        if (!userData) {
            finishAuth(newUser(self.dataChannel, email));
        } else {
            if (userData.id === self.get('id')) {
                callback(null);
                return;
            }
            self.dataChannel.sismember('authenticated', userData.id, function(err, resp) {
                if (resp) {
                    callback('already_authenticated');
                    return;
                }
                finishAuth(userData);
            });
        }
    });

    function finishAuth(userData) {
        self.dataChannel.sadd('authenticated', userData.id);
        self.set('username', userData.username);
        self.set('id', userData.id);
        self.set('email', userData.email);
        self.set('full', userData);
        self.authenticated = true;
        callback(null);
        // After we've responded, send out notifications.
        self.notifyFriends('friend_online', {});
    }
    // TODO: There can be a race condition here. If the client doesn't
    // wait for the server to process an auth request before sending a
    // second request, their second request will be processed before
    // this callback executes. Someday, there should be a queue of
    // requests which can get processed in order when this callback
    // fires.
};

user.prototype.startPlaying = function(game, callback) {
    var self = this;
    this.dataChannel.sismember('gamesPurchased:' + this.get('id'), game, function(err, resp) {
        if (err || !resp) {
            callback('does_not_own');
            return;
        }
        self._startPlaying(game);
        callback(null);
    });
};

user.prototype._startPlaying = function(game) {
    var timeNow = utils.now();
    var currentlyPlaying = this.get('currentlyPlaying');
    if (currentlyPlaying) {
        clearInterval(this.get('playTimer'));

        var startedPlaying = this.get('startedPlaying');
        this.incrPlaytime(currentlyPlaying, timeNow - startedPlaying);
    }
    // TODO: Validate that game is valid.
    // And validate that user can play/paid for game.
    this.set('startedPlaying', timeNow);
    this.set('currentlyPlaying', game);
    this.dataChannel.hset('currentlyPlaying', this.get('id'), game);
    this.dataChannel.sadd('gamePlaying:' + game, this.get('id'));
    this.dataChannel.sadd('userPlayed:' + this.get('id'), game);
    this.dataChannel.sadd('gamePlayed:' + game, this.get('id'));
    this.notifyFriends('friend_playing', {
        game: game  // TODO: Make this use the real game name.
    });

    // Set up a timer to update this every few minutes so the data doesn't
    // get stale.
    var self = this;
    this.set('playTimer', setInterval(function() {
        self.incrPlaytime(game, TIME_UPDATE_PLAYTIME);
        self.set('startedPlaying', utils.now());
    }, TIME_UPDATE_PLAYTIME));
};

user.prototype.incrPlaytime = function(game, amount) {
    if (!amount) {
        return;
    }
    this.dataChannel.hincrby(
        'playtime:' + this.get('currentlyPlaying'),
        this.get('id'),
        amount || 0
    );
};

user.prototype.donePlaying = function() {
    var currentlyPlaying = this.get('currentlyPlaying');
    if (!currentlyPlaying) {
        return;
    }
    this.incrPlaytime(currentlyPlaying, utils.now() - this.get('startedPlaying'));
    this.dataChannel.hdel('currentlyPlaying', this.get('id'));
    this.dataChannel.srem('gamePlaying:' + currentlyPlaying, this.get('id'));

    // Clean up the playtime updater.
    clearInterval(this.get('playTimer'));

    this.set('currentlyPlaying', false);
};

user.prototype.updateLeaderboard = function(board, value, callback) {
    // TODO: Throttle this function.

    var currentlyPlaying = this.get('currentlyPlaying');
    // Check that the user is playing a game.
    if (!currentlyPlaying) {
        callback('not_playing_a_game');
        return;
    }

    // Check that the board is being updated with a valid value.
    if (typeof value !== 'number' ||
        value === 0 ||
        value < -1 * MAX_LEADERBOARD_INCR ||
        value > MAX_LEADERBOARD_INCR) {
        callback('invalid_increment');
        return;
    }

    // Check that the board the user is trying to update exists.
    var self = this;
    leaderboard.isLeaderboard(
        this.dataChannel,
        currentlyPlaying,
        board,
        function(exists) {
            if (!exists) {
                callback('invalid_board');
                return;
            }

            leaderboard.updateLeaderboard(
                self.dataChannel,
                currentlyPlaying,
                board,
                self.get('id'),
                value
            );
        }
    );
};

user.prototype.isFriendsWith = function(friend, cb) {
    // Cheaty optimization.
    if (this.friends && this.friends.indexOf(friend) !== -1) {
        cb(true);
        return;
    }
    this.dataChannel.sismember('friends:' + this.get('id'), friend, function(err, resp) {
        cb(!err && resp);
    });
};

user.prototype.finish = function() {
    if (this.authenticated) {
        this.dataChannel.srem('authenticated', this.get('id'));
        this.authenticated = false;
    }
    this.donePlaying();
};

exports.User = user;

function getUserFromID(client, id, callback) {
    /*
    `callback` is called with an error parameter and a parameter
    containing a JSON blob of user data.
    */
    client.hget('users', id, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_user');
        } else {
            callback(null, JSON.parse(resp));
        }
    });
}
exports.getUserFromID = getUserFromID;

function getUserFromEmail(client, email, callback) {
    getUserIDFromEmail(client, email, function(err, id) {
        if (err && err !== 'no_such_user') {
            callback(err);
        } else if (!id) {
            callback(null, null);
        } else {
            getUserFromID(client, id, callback);
        }
    });
}
exports.getUserFromEmail = getUserFromEmail;

function getUserIDFromEmail(client, email, callback) {
    client.hget('usersByEmail', email, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_user');
        } else {
            // `resp` is the user ID.
            callback(null, resp);
        }
    });
}
exports.getUserIDFromEmail = getUserIDFromEmail;

function getGravatarURL(email) {
    return 'http://www.gravatar.com/avatar/' + crypto.createHash('md5').update(email.toLowerCase()).digest('hex');
}
exports.getGravatarURL = getGravatarURL;

function publicUserObj(full) {
    return {
        avatar: getGravatarURL(full.email),
        username: full.username,
        id: full.id
    };
}
exports.publicUserObj = publicUserObj;

function getPublicUserObj(client, id, callback) {
    // `callback` is called with a single parameter, which is either
    // the public user object or `null`.
    client.hget('users', id, function(err, resp) {
        if (err || !resp) {
            callback(null);
            return;
        }
        try {
            callback(publicUserObj(JSON.parse(resp)));
        } catch(e) {
            callback(null);
        }
    });
}
exports.getPublicUserObj = getPublicUserObj;

function getPublicUserObjList(client, ids, callback) {
    // `callback` is called with a single parameter, which is an
    // array of public user objects. If any result is invalid, it
    // is not included.
    if (!ids.length) {
        callback([]);
        return;
    }
    client.hmget(['users'].concat(ids), function(err, resp) {
        if (err || !resp) {
            callback(null);
            return;
        }
        callback(resp.map(function(full) {
            if (!full) return;
            try {
                return publicUserObj(JSON.parse(full));
            } catch(e) {
                return;
            }
        }).filter(function(x) {return x;}));
    });
}
exports.getPublicUserObjList = getPublicUserObjList;
<commit_msg>Add way to get company info from Dev Slug<commit_after>var crypto = require('crypto');

var _ = require('lodash');
var uuid = require('node-uuid');

var leaderboard = require('./leaderboard');
var utils = require('./utils');

const MAX_LEADERBOARD_INCR = 10;
const TIME_UPDATE_PLAYTIME = 1000 * 60 * 5;  // 5 minutes

function newUser(client, email) {
    var userData = {
        username: email.split('@')[0],
        email: email,
        dateLastLogin: utils.now(),
        id: uuid.v4()
    };
    client.hset('users', userData.id, JSON.stringify(userData));
    client.hset('usersByEmail', email, userData.id);
    client.rpush(companySlug, userData.id);
    // TODO: Figure out a way to store users by username.
    return userData;
}
exports.newUser = newUser;

function updateUser(client, userData, opts) {
    var newUserData = _.extend(_.clone(userData), opts);
    // Only update the modified timestamp if anything but the lastLogin
    // timestamp has changed.
    if (!_.isEqual(_.omit(userData, 'dateLastLogin'),
                   _.omit(newUserData, 'dateLastLogin'))) {
        newUserData.datelastModified = utils.now();
    }
    client.hset('users', newUserData.id, JSON.stringify(newUserData));
    if (userData.email !== newUserData.email) {
        client.hset('usersByEmail', newUserData.email, newUserData.id);
    }
    return newUserData;
}
exports.updateUser = updateUser;

// This manages user state for a single connection.
function user(dataChannel) {
    this.authenticated = false;
    this.dataChannel = dataChannel;
    this.data = {};
    this.friends = null;  // A cache.
}

user.prototype.eachFriend = function(cb) {
    if (this.friends) {
        this.friends.forEach(cb);
    } else {
        var self = this;
        this.dataChannel.smembers('friends:' + this.get('id'), function(err, resp) {
            if (err || !resp) return;
            // NOTE: This cheats. If a user adds a friend, the friend won't get
            // notifications until this user re-connects. Womp womp.
            (self.friends = resp).forEach(cb);
        });
    }
};

user.prototype.notifyFriends = function(type, data) {
    data.notification_type = type;
    data.type = 'notification';
    data.from = publicUserObj(this.get('full'));
    var json = JSON.stringify(data);
    var self = this;
    this.eachFriend(function(friendID) {
        self.dataChannel.publish('user:' + friendID, json);
    });
};

user.prototype.set = function(key, value) {
    this.data[key] = value;
};

user.prototype.get = function(key) {
    return this.data[key] || null;
};

user.prototype.authenticate = function(email, callback) {
    var self = this;
    getUserFromEmail(this.dataChannel, email, function(err, userData) {
        if (err) {
            callback('error_fetching_user');
            return;
        }
        if (!userData) {
            finishAuth(newUser(self.dataChannel, email));
        } else {
            if (userData.id === self.get('id')) {
                callback(null);
                return;
            }
            self.dataChannel.sismember('authenticated', userData.id, function(err, resp) {
                if (resp) {
                    callback('already_authenticated');
                    return;
                }
                finishAuth(userData);
            });
        }
    });

    function finishAuth(userData) {
        self.dataChannel.sadd('authenticated', userData.id);
        self.set('username', userData.username);
        self.set('id', userData.id);
        self.set('email', userData.email);
        self.set('full', userData);
        self.authenticated = true;
        callback(null);
        // After we've responded, send out notifications.
        self.notifyFriends('friend_online', {});
    }
    // TODO: There can be a race condition here. If the client doesn't
    // wait for the server to process an auth request before sending a
    // second request, their second request will be processed before
    // this callback executes. Someday, there should be a queue of
    // requests which can get processed in order when this callback
    // fires.
};

user.prototype.startPlaying = function(game, callback) {
    var self = this;
    this.dataChannel.sismember('gamesPurchased:' + this.get('id'), game, function(err, resp) {
        if (err || !resp) {
            callback('does_not_own');
            return;
        }
        self._startPlaying(game);
        callback(null);
    });
};

user.prototype._startPlaying = function(game) {
    var timeNow = utils.now();
    var currentlyPlaying = this.get('currentlyPlaying');
    if (currentlyPlaying) {
        clearInterval(this.get('playTimer'));

        var startedPlaying = this.get('startedPlaying');
        this.incrPlaytime(currentlyPlaying, timeNow - startedPlaying);
    }
    // TODO: Validate that game is valid.
    // And validate that user can play/paid for game.
    this.set('startedPlaying', timeNow);
    this.set('currentlyPlaying', game);
    this.dataChannel.hset('currentlyPlaying', this.get('id'), game);
    this.dataChannel.sadd('gamePlaying:' + game, this.get('id'));
    this.dataChannel.sadd('userPlayed:' + this.get('id'), game);
    this.dataChannel.sadd('gamePlayed:' + game, this.get('id'));
    this.notifyFriends('friend_playing', {
        game: game  // TODO: Make this use the real game name.
    });

    // Set up a timer to update this every few minutes so the data doesn't
    // get stale.
    var self = this;
    this.set('playTimer', setInterval(function() {
        self.incrPlaytime(game, TIME_UPDATE_PLAYTIME);
        self.set('startedPlaying', utils.now());
    }, TIME_UPDATE_PLAYTIME));
};

user.prototype.incrPlaytime = function(game, amount) {
    if (!amount) {
        return;
    }
    this.dataChannel.hincrby(
        'playtime:' + this.get('currentlyPlaying'),
        this.get('id'),
        amount || 0
    );
};

user.prototype.donePlaying = function() {
    var currentlyPlaying = this.get('currentlyPlaying');
    if (!currentlyPlaying) {
        return;
    }
    this.incrPlaytime(currentlyPlaying, utils.now() - this.get('startedPlaying'));
    this.dataChannel.hdel('currentlyPlaying', this.get('id'));
    this.dataChannel.srem('gamePlaying:' + currentlyPlaying, this.get('id'));

    // Clean up the playtime updater.
    clearInterval(this.get('playTimer'));

    this.set('currentlyPlaying', false);
};

user.prototype.updateLeaderboard = function(board, value, callback) {
    // TODO: Throttle this function.

    var currentlyPlaying = this.get('currentlyPlaying');
    // Check that the user is playing a game.
    if (!currentlyPlaying) {
        callback('not_playing_a_game');
        return;
    }

    // Check that the board is being updated with a valid value.
    if (typeof value !== 'number' ||
        value === 0 ||
        value < -1 * MAX_LEADERBOARD_INCR ||
        value > MAX_LEADERBOARD_INCR) {
        callback('invalid_increment');
        return;
    }

    // Check that the board the user is trying to update exists.
    var self = this;
    leaderboard.isLeaderboard(
        this.dataChannel,
        currentlyPlaying,
        board,
        function(exists) {
            if (!exists) {
                callback('invalid_board');
                return;
            }

            leaderboard.updateLeaderboard(
                self.dataChannel,
                currentlyPlaying,
                board,
                self.get('id'),
                value
            );
        }
    );
};

user.prototype.isFriendsWith = function(friend, cb) {
    // Cheaty optimization.
    if (this.friends && this.friends.indexOf(friend) !== -1) {
        cb(true);
        return;
    }
    this.dataChannel.sismember('friends:' + this.get('id'), friend, function(err, resp) {
        cb(!err && resp);
    });
};

user.prototype.finish = function() {
    if (this.authenticated) {
        this.dataChannel.srem('authenticated', this.get('id'));
        this.authenticated = false;
    }
    this.donePlaying();
};

exports.User = user;

function getUserFromID(client, id, callback) {
    /*
    `callback` is called with an error parameter and a parameter
    containing a JSON blob of user data.
    */
    client.hget('users', id, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_user');
        } else {
            callback(null, JSON.parse(resp));
        }
    });
}
exports.getUserFromID = getUserFromID;

function getUserFromEmail(client, email, callback) {
    getUserIDFromEmail(client, email, function(err, id) {
        if (err && err !== 'no_such_user') {
            callback(err);
        } else if (!id) {
            callback(null, null);
        } else {
            getUserFromID(client, id, callback);
        }
    });
}
exports.getUserFromEmail = getUserFromEmail;

function getUserIDFromEmail(client, email, callback) {
    client.hget('usersByEmail', email, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_such_user');
        } else {
            // `resp` is the user ID.
            callback(null, resp);
        }
    });
}
exports.getUserIDFromEmail = getUserIDFromEmail;

function getUserIDsFromDevSlug(client, slug, callback) {
    client.lrange(slug, 0, -1, function(err, resp) {
        if (err) {
            callback('db_error');
        } else if (!resp) {
            callback('no_users');
        } else {
            // `resp` is the list of user IDs.
            callback(null, resp);
        }
    });
}
exports.getUserIDsFromDevSlug = getUserIDsFromDevSlug;

function getCompanyInfoFromDevSlug (client, slug, callback) {
    getUserIDsFromDevSlug(client, slug, function(err, devs) {
        if (err && err !== 'no_users') {
            callback(err);
        } else if (!devs) {
            callback(null, null);
        } else {
            getUserFromID(client, devs[0], function(err, user) {
                if (err) {
                    callback(err);
                } else {
                    callback(null, publicDevObj(user));
                }
            })
        }
    });
}
exports.getCompanyInfoFromDevSlug = getCompanyInfoFromDevSlug;

function getGravatarURL(email) {
    return 'http://www.gravatar.com/avatar/' + crypto.createHash('md5').update(email.toLowerCase()).digest('hex');
}
exports.getGravatarURL = getGravatarURL;

function publicUserObj(full) {
    return {
        avatar: getGravatarURL(full.email),
        username: full.username,
        id: full.id
    };
}
exports.publicUserObj = publicUserObj;

function publicDevObj(full) {
    return {
        //TODO: Company images
        avatar: getGravatarURL(full.email),
        companyName: full.companyName,
        homepage: full.homepage,
        support: support
    }
}
exports.publicDevObj = publicDevObj;

function getPublicUserObj(client, id, callback) {
    // `callback` is called with a single parameter, which is either
    // the public user object or `null`.
    client.hget('users', id, function(err, resp) {
        if (err || !resp) {
            callback(null);
            return;
        }
        try {
            callback(publicUserObj(JSON.parse(resp)));
        } catch(e) {
            callback(null);
        }
    });
}
exports.getPublicUserObj = getPublicUserObj;

function getPublicUserObjList(client, ids, callback) {
    // `callback` is called with a single parameter, which is an
    // array of public user objects. If any result is invalid, it
    // is not included.
    if (!ids.length) {
        callback([]);
        return;
    }
    client.hmget(['users'].concat(ids), function(err, resp) {
        if (err || !resp) {
            callback(null);
            return;
        }
        callback(resp.map(function(full) {
            if (!full) return;
            try {
                return publicUserObj(JSON.parse(full));
            } catch(e) {
                return;
            }
        }).filter(function(x) {return x;}));
    });
}
exports.getPublicUserObjList = getPublicUserObjList;
<|endoftext|>


<commit_before>(function ( document ) {
  'use strict';

  var app = document.querySelector( '#app' );

  app.appName = "Analiz";

  /**
   * Require modules
   */
  app.remote = require( 'remote' );
  app.npm = require( 'npm' );
  app.async = require( 'async' );
  app.categories = require( './categories.js' );
  app.getFilters = require( './moduleLister.js' );
  app.directory = require( 'directory-tree' );
  app.directory.fs = require( 'fs' );
  app.directory.path = require( 'path' );
  app.dateFormat = require( 'dateformat' );

  /**
   * Get the categories list with the correct structure
   */
  app.categoriesList = [];
  Object.getOwnPropertyNames(app.categories).forEach( function ( element, index, array ) {
    app.categoriesList.push( app.categories[element] );
  } );

  /**
   * Show a toast
   * @param  {String} message Toast message
   */
  app.toast = function ( message ) {
    var toast = document.getElementById('toast');

    toast.text = message;
    toast.show();
  };

  /**
   * Get the filters from the external plugins
   */
  app.npmPrefix = 'resources/app';
  app.filters = [];
  app.getFilters();

  /**
   * Analyze config object
   */
  app.analyzeConfig = {
    path: '',
    plugins: [],

    set: function ( property, value ) {
      this[property] = value;
      // If the path and the config are set show the 'Analiz !' button
      document.getElementById( 'analyzeButton' ).disabled = ( this.path && this.plugins.length === 0 );
    }
  };

  app.analyzeResults = [];
  app.currentPlugin = {};

  /**
   * The analyse function
   * @param  {Object} data Data configuration object
   */
  app.analiz = function ( data ) {
    var files;

    app.loadingModal.set( 'data.pluginTotal', data.plugins.length);
    app.toast( 'Lancement de l\'analyse...');
    // Open the loader modal
    app.loadingModal.open();

    // Get all the files in the directory
    walk( data.path, function ( err, files ) {
      // Run the plugins one by one
      data.plugins.forEach( function ( plugin, index ) {
        // Prepare the parameters
        var parameters = {
          files: [],
          options: {}
        };

        // Get the files the plugin need
        files.forEach( function( file ) {
          if ( plugin.config.fileTypes.indexOf( app.directory.path.extname( file ) ) >= 0 ) {
            parameters.files.push( file );
          }
        } );

        // Get the options the plugin need
        plugin.config.options.forEach( function( option ) {
          parameters.options[option.name] = option;
        } );

        // Set the loading data for the current plugin
        app.loadingModal.push( 'data.name', plugin.config.name );
        app.loadingModal.set( 'data.fileTotal', parameters.files.length );

        app.currentPlugin = plugin.config;
        app.currentPlugin.id = index;

        // Run the plugin
        plugin.run( parameters.files, parameters.options, app.loadingResults );
      } );
    } );
  };

  app.loadingResults = function ( error, results ) {
    // Store the analyze results
    if ( !app.analyzeResults[app.currentPlugin.id] ) {
      app.analyzeResults[app.currentPlugin.id] = {
        name: app.currentPlugin.name,
        category: app.currentPlugin.category,
        options: app.currentPlugin.options,
        data: []
      };
    }
    app.analyzeResults[app.currentPlugin.id].data.push( results );

    // Set the file progress
    app.loadingModal.set( 'data.fileCount', app.loadingModal.data.fileCount + 1 );
    app.loadingModal.set( 'data.fileValue', Math.round( ( 100 * app.loadingModal.data.fileCount ) / app.loadingModal.data.fileTotal ));
    // Verify if all the files for the current plugin has been analyzed
    if ( app.loadingModal.data.fileCount == app.loadingModal.data.fileTotal ) {
      // Set the plugin progress
      app.loadingModal.set( 'data.pluginCount', app.loadingModal.data.pluginCount + 1 );
      app.loadingModal.set( 'data.pluginValue', Math.round( ( 100 * app.loadingModal.data.pluginCount ) / app.loadingModal.data.pluginTotal ));
      // Verify if the analyze is over
      if ( app.loadingModal.data.pluginCount == app.loadingModal.data.pluginTotal ) {
        app.isLoaded( app.analyzeResults );
      } else {
        app.loadingModal.set( 'data.fileCount', 0);
      }
    }
  };

  app.isLoaded = function ( results ) {
    // Close the modal, reset the loader and show the audit page
    document.querySelector('loading-modal').close();
    setTimeout(function () {
      document.querySelector('loading-modal').reset();
    }, 500);

    app.analyzeResults = [];

    document.querySelector('page-audit').set('data', results);

    app.isAudit = true;
    app.selected = 2;
  };

  app.isAudit = false;

  app.changeTab = function ( e ) {
    document.querySelector( 'page-audit #pages' ).selected = 0;
  };

  // Default page
  app.selected = 0;

  var i = 0;

  window.addEventListener( 'WebComponentsReady', function() {
    document.querySelector( 'body' ).removeAttribute( 'unresolved' );
    app.isNarrow = document.getElementById('paperDrawerPanel').narrow;

    app.loadingModal = document.querySelector('loading-modal');
  });

  // About dialog
  app.aboutOpen = function ( e ) {
    document.querySelector( '.settings-dropdown' ).close();
    document.querySelector( 'about-dialog paper-dialog' ).open();
  };

  app.filterResults = function ( e ) {
    app.changeTab();
    document.querySelector( '.result-card-' + e.detail.name ).classList.toggle( 'hide-result-card' );
  };

  var walk = function(dir, done) {
    var results = [];
    app.directory.fs.readdir(dir, function(err, list) {
      if (err) return done(err);
      var pending = list.length;
      if (!pending) return done(null, results);
      list.forEach(function(file) {
        file = app.directory.path.resolve(dir, file);
        app.directory.fs.stat(file, function(err, stat) {
          if (stat && stat.isDirectory()) {
            walk(file, function(err, res) {
              results = results.concat(res);
              if (!--pending) done(null, results);
            });
          } else {
            results.push(file);
            if (!--pending) done(null, results);
          }
        });
      });
    });
  };

})(document);
<commit_msg>Add toast after analyze<commit_after>(function ( document ) {
  'use strict';

  var app = document.querySelector( '#app' );

  app.appName = "Analiz";

  /**
   * Require modules
   */
  app.remote = require( 'remote' );
  app.npm = require( 'npm' );
  app.async = require( 'async' );
  app.categories = require( './categories.js' );
  app.getFilters = require( './moduleLister.js' );
  app.directory = require( 'directory-tree' );
  app.directory.fs = require( 'fs' );
  app.directory.path = require( 'path' );
  app.dateFormat = require( 'dateformat' );

  /**
   * Get the categories list with the correct structure
   */
  app.categoriesList = [];
  Object.getOwnPropertyNames(app.categories).forEach( function ( element, index, array ) {
    app.categoriesList.push( app.categories[element] );
  } );

  /**
   * Show a toast
   * @param  {String} message Toast message
   */
  app.toast = function ( message ) {
    var toast = document.getElementById('toast');

    toast.text = message;
    toast.show();
  };

  /**
   * Get the filters from the external plugins
   */
  app.npmPrefix = 'resources/app';
  app.filters = [];
  app.getFilters();

  /**
   * Analyze config object
   */
  app.analyzeConfig = {
    path: '',
    plugins: [],

    set: function ( property, value ) {
      this[property] = value;
      // If the path and the config are set show the 'Analiz !' button
      document.getElementById( 'analyzeButton' ).disabled = ( this.path && this.plugins.length === 0 );
    }
  };

  app.analyzeResults = [];
  app.currentPlugin = {};

  /**
   * The analyse function
   * @param  {Object} data Data configuration object
   */
  app.analiz = function ( data ) {
    var files;

    app.loadingModal.set( 'data.pluginTotal', data.plugins.length);
    // Open the loader modal
    app.loadingModal.open();

    // Get all the files in the directory
    walk( data.path, function ( err, files ) {
      // Run the plugins one by one
      data.plugins.forEach( function ( plugin, index ) {
        // Prepare the parameters
        var parameters = {
          files: [],
          options: {}
        };

        // Get the files the plugin need
        files.forEach( function( file ) {
          if ( plugin.config.fileTypes.indexOf( app.directory.path.extname( file ) ) >= 0 ) {
            parameters.files.push( file );
          }
        } );

        // Get the options the plugin need
        plugin.config.options.forEach( function( option ) {
          parameters.options[option.name] = option;
        } );

        // Set the loading data for the current plugin
        app.loadingModal.push( 'data.name', plugin.config.name );
        app.loadingModal.set( 'data.fileTotal', parameters.files.length );

        app.currentPlugin = plugin.config;
        app.currentPlugin.id = index;

        // Run the plugin
        plugin.run( parameters.files, parameters.options, app.loadingResults );
      } );
    } );
  };

  app.loadingResults = function ( error, results ) {
    // Store the analyze results
    if ( !app.analyzeResults[app.currentPlugin.id] ) {
      app.analyzeResults[app.currentPlugin.id] = {
        name: app.currentPlugin.name,
        category: app.currentPlugin.category,
        options: app.currentPlugin.options,
        data: []
      };
    }
    app.analyzeResults[app.currentPlugin.id].data.push( results );

    // Set the file progress
    app.loadingModal.set( 'data.fileCount', app.loadingModal.data.fileCount + 1 );
    app.loadingModal.set( 'data.fileValue', Math.round( ( 100 * app.loadingModal.data.fileCount ) / app.loadingModal.data.fileTotal ));
    // Verify if all the files for the current plugin has been analyzed
    if ( app.loadingModal.data.fileCount == app.loadingModal.data.fileTotal ) {
      // Set the plugin progress
      app.loadingModal.set( 'data.pluginCount', app.loadingModal.data.pluginCount + 1 );
      app.loadingModal.set( 'data.pluginValue', Math.round( ( 100 * app.loadingModal.data.pluginCount ) / app.loadingModal.data.pluginTotal ));
      // Verify if the analyze is over
      if ( app.loadingModal.data.pluginCount == app.loadingModal.data.pluginTotal ) {
        app.isLoaded( app.analyzeResults );
      } else {
        app.loadingModal.set( 'data.fileCount', 0);
      }
    }
  };

  app.isLoaded = function ( results ) {
    // Close the modal, reset the loader and show the audit page
    document.querySelector('loading-modal').close();
    setTimeout(function () {
      document.querySelector('loading-modal').reset();
    }, 500);
    app.toast( 'Analyse terminée !');

    app.analyzeResults = [];

    document.querySelector('page-audit').set('data', results);

    app.isAudit = true;
    app.selected = 2;
  };

  app.isAudit = false;

  app.changeTab = function ( e ) {
    document.querySelector( 'page-audit #pages' ).selected = 0;
  };

  // Default page
  app.selected = 0;

  var i = 0;

  window.addEventListener( 'WebComponentsReady', function() {
    document.querySelector( 'body' ).removeAttribute( 'unresolved' );
    app.isNarrow = document.getElementById('paperDrawerPanel').narrow;

    app.loadingModal = document.querySelector('loading-modal');
  });

  // About dialog
  app.aboutOpen = function ( e ) {
    document.querySelector( '.settings-dropdown' ).close();
    document.querySelector( 'about-dialog paper-dialog' ).open();
  };

  app.filterResults = function ( e ) {
    app.changeTab();
    document.querySelector( '.result-card-' + e.detail.name ).classList.toggle( 'hide-result-card' );
  };

  var walk = function(dir, done) {
    var results = [];
    app.directory.fs.readdir(dir, function(err, list) {
      if (err) return done(err);
      var pending = list.length;
      if (!pending) return done(null, results);
      list.forEach(function(file) {
        file = app.directory.path.resolve(dir, file);
        app.directory.fs.stat(file, function(err, stat) {
          if (stat && stat.isDirectory()) {
            walk(file, function(err, res) {
              results = results.concat(res);
              if (!--pending) done(null, results);
            });
          } else {
            results.push(file);
            if (!--pending) done(null, results);
          }
        });
      });
    });
  };

})(document);
<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

"use strict";

var config = require('../config.js');

var crypto = require('crypto');
var async = require('async');
var sync = require('sync');

exports.userExists = function(dbConnection, username, callback)
{
	dbConnection.query(
		'SELECT count(*) AS result FROM uniusers WHERE lower(username) = lower($1)',
		[username],
		function (error, result) {
			callback(error, error || (result.rows[0].result > 0));
		}
	);
};

exports.idExists = function(dbConnection, id, callback) {
	dbConnection.query(
		'SELECT count(*) AS result FROM uniusers WHERE id = $1',
		[id],
		function (error, result) {
			callback(error, error || (result.rows[0].result > 0));
		}
	);
};

exports.sessionExists = function(dbConnection, sess, callback) {
	dbConnection.query(
		'SELECT count(*) AS result FROM uniusers WHERE sessid = $1',
		[sess],
		function (error, result) {
			if (!!error)
			{
				callback(error, null);
				return;
			}
			callback(null, (result.rows[0].result > 0));
		}
	);
};

exports.sessionInfoRefreshing = function(dbConnection, sessid, sess_timeexpire, asyncUpdate, callback) {
	if (!sessid)
	{
		return { sessionIsActive: false };
	}

	var userdata = dbConnection.query.sync(dbConnection,
		'SELECT id, username, permissions FROM uniusers '+
		"WHERE sessid = $1 AND sess_time > NOW() - $2 * INTERVAL '1 SECOND'",
		[sessid, sess_timeexpire]
	);

	if (userdata.rows.length === 0)
	{
		return { sessionIsActive: false };
	}

	if (asyncUpdate)
	{
		process.nextTick(function(){
			dbConnection.query(
				'UPDATE uniusers SET sess_time = NOW() WHERE id = $1',
				[userdata.rows[0].id]
			);
		});
	}
	else
	{
		dbConnection.query.sync(dbConnection,
			'UPDATE uniusers SET sess_time = NOW() WHERE id = $1',
			[userdata.rows[0].id]
		);
	}

	return {
		sessionIsActive: true,
		username: userdata.rows[0].username,
		admin: (userdata.rows[0].permissions === config.PERMISSIONS_ADMIN),
		userid: userdata.rows[0].id
	};
}.async();

exports.generateSessId = function(dbConnection, sess_length, callback) {
	//here random sessid must be checked for uniqueness
	//and it'll be!
	(function iteration()
	{
		var sessid = exports.createSalt(sess_length);
		exports.sessionExists(dbConnection, sessid, function(error, exists) {
			if (!!error)
			{
				callback(error, null);
				return;
			}
			if (exists)
			{
				iteration();
				return;
			}
			callback(null, sessid);
		});
	})();
};

exports.idBySession = function(dbConnection, sess, callback) {
	dbConnection.query(
		'SELECT id FROM uniusers WHERE sessid = $1',
		[sess],
		function (error, result) {
			if (!!result && result.rows.length === 0)
			{
				error = new Error("Wrong user's id");
			}
			callback(error, error || result.rows[0].id);
		}
	);
};

exports.closeSession = function(dbConnection, sessid, callback) {
	if (!sessid)
	{
		callback(undefined, 'Not closing: empty sessid');
		return;
	}
	exports.generateSessId(dbConnection, config.sessionLength, function(error, newSessid) {
		if (!!error)
		{
			callback(error);
			return;
		}
		dbConnection.query(
			'UPDATE uniusers SET sessid = $1 WHERE sessid = $2',
			[newSessid, sessid], callback
		);
	});
};

exports.createSalt = function(sess_length) {
	var salt = '';
	var a = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
	for(var i=0; i<sess_length; i++) { salt += a[Math.floor(Math.random() * a.length)]; }
	return salt;
};

exports.registerUser = function (dbConnection, username, password, permissions) {
	if (exports.userExists.sync(null, dbConnection, username) === true)
	{
		throw new Error('user already exists');
	}
	var salt = exports.createSalt(16);
	var hash = crypto.pbkdf2.sync(null, password, salt, 4096, 256);
	var sessid = exports.generateSessId.sync(null, dbConnection, config.sessionLength);
	dbConnection.query.sync(dbConnection,
		'INSERT INTO uniusers ('+
			'username, salt, hash, sessid, reg_time, sess_time, '+
			'location, permissions'+
			') VALUES ('+
			'$1, $2, $3, $4, NOW(), NOW(), '+
			'(SELECT id FROM locations WHERE initial = 1), $5'+
			')',
		[username, salt, hash.toString('hex'), sessid, permissions]
	);
	return { sessid: sessid };
}.async();

exports.accessGranted = function(dbConnection, username, password, callback) {
	async.waterfall(
		[
			function (innerCallback) {
				dbConnection.query(
					'SELECT salt, hash FROM uniusers WHERE lower(username) = lower($1)',
					[username],
					function(error, result) {
						if (!!result && result.rows.length === 0)
						{
							callback(null, false); //Wrong username
							return;
						}
						innerCallback(error, error || result.rows[0]);
					});
			},
			function (result, innerCallback) {
				crypto.pbkdf2(password, result.salt, 4096, 256, function(error, hash) {
					if (result.hash == hash.toString('hex'))
					{
						callback(null, true);
					}
					else
					{
						callback(null, false); //Wrong user's pass
					}
				});
			},
		],
		function (error, result) {
			callback(error, result);
		}
	);
};

exports.createSession = function(dbConnection, username, callback) {
	async.waterfall([
			function (innerCallback) {
				exports.generateSessId(dbConnection, config.sessionLength, innerCallback);
			},
			function (sessid, innerCallback) {
				dbConnection.query(
					'UPDATE uniusers '+
					'SET sess_time = NOW(), sessid = $1 '+
					'WHERE lower(username) = lower($2)',
					[sessid, username],
					function (error, result) {
						innerCallback(error, result, sessid);
					});
			},
		],
		function (error, result, sessid) {
			callback(error, sessid);
		}
	);
};

<commit_msg>Errrrm, it seems to fix a bug.<commit_after>/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

"use strict";

var config = require('../config.js');

var crypto = require('crypto');
var async = require('async');
var sync = require('sync');

exports.userExists = function(dbConnection, username, callback)
{
	dbConnection.query(
		'SELECT count(*) AS result FROM uniusers WHERE lower(username) = lower($1)',
		[username],
		function (error, result) {
			callback(error, error || (result.rows[0].result > 0));
		}
	);
};

exports.idExists = function(dbConnection, id, callback) {
	dbConnection.query(
		'SELECT count(*) AS result FROM uniusers WHERE id = $1',
		[id],
		function (error, result) {
			callback(error, error || (result.rows[0].result > 0));
		}
	);
};

exports.sessionExists = function(dbConnection, sess, callback) {
	dbConnection.query(
		'SELECT count(*) AS result FROM uniusers WHERE sessid = $1',
		[sess],
		function (error, result) {
			if (!!error)
			{
				callback(error, null);
				return;
			}
			callback(null, (result.rows[0].result > 0));
		}
	);
};

exports.sessionInfoRefreshing = function(dbConnection, sessid, sess_timeexpire, asyncUpdate, callback) {
	if (!sessid)
	{
		return { sessionIsActive: false };
	}

	var userdata = dbConnection.query.sync(dbConnection,
		'SELECT id, username, permissions FROM uniusers '+
		"WHERE sessid = $1 AND sess_time > NOW() - $2 * INTERVAL '1 SECOND'",
		[sessid, sess_timeexpire]
	);

	if (userdata.rows.length === 0)
	{
		return { sessionIsActive: false };
	}

	if (asyncUpdate)
	{
		process.nextTick(function(){
			dbConnection.query(
				'UPDATE uniusers SET sess_time = NOW() WHERE id = $1',
				[userdata.rows[0].id],
				function(error, result){
					if (!!error) console.log(error.stack);
				}
			);
		});
	}
	else
	{
		dbConnection.query.sync(dbConnection,
			'UPDATE uniusers SET sess_time = NOW() WHERE id = $1',
			[userdata.rows[0].id]
		);
	}

	return {
		sessionIsActive: true,
		username: userdata.rows[0].username,
		admin: (userdata.rows[0].permissions === config.PERMISSIONS_ADMIN),
		userid: userdata.rows[0].id
	};
}.async();

exports.generateSessId = function(dbConnection, sess_length, callback) {
	//here random sessid must be checked for uniqueness
	//and it'll be!
	(function iteration()
	{
		var sessid = exports.createSalt(sess_length);
		exports.sessionExists(dbConnection, sessid, function(error, exists) {
			if (!!error)
			{
				callback(error, null);
				return;
			}
			if (exists)
			{
				iteration();
				return;
			}
			callback(null, sessid);
		});
	})();
};

exports.idBySession = function(dbConnection, sess, callback) {
	dbConnection.query(
		'SELECT id FROM uniusers WHERE sessid = $1',
		[sess],
		function (error, result) {
			if (!!result && result.rows.length === 0)
			{
				error = new Error("Wrong user's id");
			}
			callback(error, error || result.rows[0].id);
		}
	);
};

exports.closeSession = function(dbConnection, sessid, callback) {
	if (!sessid)
	{
		callback(undefined, 'Not closing: empty sessid');
		return;
	}
	exports.generateSessId(dbConnection, config.sessionLength, function(error, newSessid) {
		if (!!error)
		{
			callback(error);
			return;
		}
		dbConnection.query(
			'UPDATE uniusers SET sessid = $1 WHERE sessid = $2',
			[newSessid, sessid], callback
		);
	});
};

exports.createSalt = function(sess_length) {
	var salt = '';
	var a = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
	for(var i=0; i<sess_length; i++) { salt += a[Math.floor(Math.random() * a.length)]; }
	return salt;
};

exports.registerUser = function (dbConnection, username, password, permissions) {
	if (exports.userExists.sync(null, dbConnection, username) === true)
	{
		throw new Error('user already exists');
	}
	var salt = exports.createSalt(16);
	var hash = crypto.pbkdf2.sync(null, password, salt, 4096, 256);
	var sessid = exports.generateSessId.sync(null, dbConnection, config.sessionLength);
	dbConnection.query.sync(dbConnection,
		'INSERT INTO uniusers ('+
			'username, salt, hash, sessid, reg_time, sess_time, '+
			'location, permissions'+
			') VALUES ('+
			'$1, $2, $3, $4, NOW(), NOW(), '+
			'(SELECT id FROM locations WHERE initial = 1), $5'+
			')',
		[username, salt, hash.toString('hex'), sessid, permissions]
	);
	return { sessid: sessid };
}.async();

exports.accessGranted = function(dbConnection, username, password, callback) {
	async.waterfall(
		[
			function (innerCallback) {
				dbConnection.query(
					'SELECT salt, hash FROM uniusers WHERE lower(username) = lower($1)',
					[username],
					function(error, result) {
						if (!!result && result.rows.length === 0)
						{
							callback(null, false); //Wrong username
							return;
						}
						innerCallback(error, error || result.rows[0]);
					});
			},
			function (result, innerCallback) {
				crypto.pbkdf2(password, result.salt, 4096, 256, function(error, hash) {
					if (result.hash == hash.toString('hex'))
					{
						callback(null, true);
					}
					else
					{
						callback(null, false); //Wrong user's pass
					}
				});
			},
		],
		function (error, result) {
			callback(error, result);
		}
	);
};

exports.createSession = function(dbConnection, username, callback) {
	async.waterfall([
			function (innerCallback) {
				exports.generateSessId(dbConnection, config.sessionLength, innerCallback);
			},
			function (sessid, innerCallback) {
				dbConnection.query(
					'UPDATE uniusers '+
					'SET sess_time = NOW(), sessid = $1 '+
					'WHERE lower(username) = lower($2)',
					[sessid, username],
					function (error, result) {
						innerCallback(error, result, sessid);
					});
			},
		],
		function (error, result, sessid) {
			callback(error, sessid);
		}
	);
};

<|endoftext|>