<commit_before>/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {
  var currentPage = 'market';
  var currentCategory = '';

  return angular.module('my-app.marketplace.controllers', [])

  .controller('MarketplaceCommonFunctionsController',
    ['googleCustomSearchService', 'miscSearchService', 'layoutService',
      '$log', 'marketplaceService', 'miscService', 'MISC_URLS',
      '$sessionStorage', '$localStorage', '$rootScope', '$scope',
      '$routeParams', '$timeout', '$location', '$mdColors',
    function(googleCustomSearchService, miscSearchService, layoutService,
      $log, marketplaceService, miscService, MISC_URLS,
        $sessionStorage, $localStorage, $rootScope, $scope,
        $routeParams, $timeout, $location, $mdColors) {
      var vm = this;

      if ($sessionStorage.portal.theme) {
        // theme already in session, use primary color from it
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($sessionStorage.portal.theme.name
          + '-primary');
      } else {
        // theme not yet in session, use primary color from zeroth theme
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($rootScope.THEMES[0].name
            + '-primary');
        }

       $scope.navToDetails = function(marketplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path('apps/details/'+ marketplaceEntry.fname);
       };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 // a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; // static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if ($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage +
              '/web/apps/details/'+ marketplaceEntry.fname;
        } else if (layoutObj.altMaxUrl == false &&
            (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if (layoutObj.altMaxUrl == false &&
            $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function(request, text) {
          angular.element('.fname-'+fname)
            .html(' Added Successfully')
            .prop('disabled', true)
            .removeClass('btn-add')
            .addClass('btn-added');
          $scope.$apply(function() {
            var marketplaceEntries = $.grep(
              $sessionStorage.marketplace,
              function(e) {
                return e.fname === portlet.fname;
              }
            );
            if (marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; // reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            angular.element('.fname-'+fname)
              .parent()
              .append(
                'Issue adding to home, please try again later'
              );
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(
          portlet,
          $scope.searchTerm,
          {
            searchDescription: true,
            searchKeywords: true,
            defaultReturn: true,
          }
        );
      };

      $scope.selectFilter = function(filter, category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating', '-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'name';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'name';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace', 'Tab Select', filter);
      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      vm.setupSearchTerm = function() {
        var tempFilterText = '';
        var filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if ($routeParams.initFilter !== null &&
            ($scope.searchTerm === null || $scope.searchTerm === '')) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter('');
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        // delay on the filter
        $scope.$watch('searchText', function(val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if (initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search', 'Filter', $scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      vm.initializeConstants = function() {
        var errorFn = function(name) {
          return function() {
            $log.warn('Could not ' + name);
          };
        };
        // initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(
          function(webSearchURL) {
            $scope.webSearchUrl = webSearchURL;
            return webSearchURL;
          }
        ).catch(errorFn('getPublicWebSearchURL'));
        googleCustomSearchService.getDomainResultsLabel().then(
          function(domainResultsLabel) {
            $scope.domainResultsLabel = domainResultsLabel;
            return domainResultsLabel;
          }
        ).catch(errorFn('getDomainResultsLabel'));
        miscSearchService.getKBSearchURL().then(
          function(kbSearchURL) {
            $scope.kbSearchUrl = kbSearchURL;
            return kbSearchURL;
          }
        ).catch(errorFn('getKBSearchURL'));
        miscSearchService.getEventSearchURL().then(
          function(eventsSearchURL) {
            $scope.eventsSearchUrl = eventsSearchURL;
            return eventsSearchURL;
          }
        ).catch(errorFn('getEventSearchURL'));
        miscSearchService.getHelpDeskHelpURL().then(
          function(helpdeskURL) {
            $scope.helpdeskUrl = helpdeskURL;
            return helpdeskURL;
          }
        ).catch(errorFn('getHelpDeskHelpURL'));
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      };
    },
  ])

  .controller('MarketplaceController', [
    '$log', '$rootScope', '$scope', '$controller', 'marketplaceService',
    function($log, $rootScope, $scope, $controller, marketplaceService) {
      var base = $controller('MarketplaceCommonFunctionsController',
        {$scope: $scope});

      var init = function() {
        // init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
          return data;
        }).catch(function() {
          $log.warn('Could not getPortlets');
        });

        base.setupSearchTerm();

        // initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if (currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by category for
          // marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use name to filter
          $scope.sortParameter = 'name';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if (currentCategory !== '') {
            $scope.categoryToShow = currentCategory;
          } else {
            $scope.categoryToShow = '';
          }
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating', '-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      // run functions
      init();
    }])

  .controller('MarketplaceDetailsController', [
      '$controller', '$document', '$scope', '$routeParams',
      '$mdDialog', 'marketplaceService', 'SERVICE_LOC',
      function($controller, $document, $scope, $routeParams,
          $mdDialog, marketplaceService, SERVICE_LOC) {
        $controller('MarketplaceCommonFunctionsController',
          {$scope: $scope});

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if (fromInfo.term) {
            // from somewhere
            if ('Search' === fromInfo.searchOrBrowse && fromInfo.term) {
              // if from search and term is populated, return to search
              $scope.backText = 'Search Results for ' + fromInfo.term;
              $scope.backURL = 'apps/search/' + fromInfo.term;
            } else {
              // assuming from browse
              $scope.backText = 'Browse';
              $scope.backURL = 'apps/browse/' + fromInfo.term;
            }

            // reset services
            marketplaceService.setFromInfo(undefined, undefined);
          } else {
            // direct hit, will go back to browse
            $scope.backURL='apps';
            $scope.backText='Browse';
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element($document.body),
            scope: $scope,
            preserveScope: true,
            clickOutsideToClose: true,
            fullscreen: false,
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage =
              'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(
            function(result) {
              $scope.loading = false;
              if (!result) {
                $scope.error = true;
                $scope.portlet = null;
              } else {
                $scope.portlet = result;
                $scope.error = false;
              }
              return result;
            }
          ).catch(function(reason) {
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  )

  .controller('MarketplaceRatingReviewAdminController', [
    '$log', '$scope', 'marketplaceService',
    function($log, $scope, marketplaceService) {
      var init = function() {
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(
          function(ratings) {
            if (ratings) {
              $scope.ratings = ratings;
              $scope.average =0;
              $scope.totalReviews = 0;
              angular.forEach(ratings, function(value, key) {
                $scope.average+= value.rating;
                if (value.review) {
                  $scope.totalReviews += 1;
                }
              });
              $scope.average = Math.round($scope.average / ratings.length);
            }
            return ratings;
          }
        ).catch(function() {
          $log.warn('Could not getAllRatings');
        });
      };

      init();
    }]);
});
<commit_msg>fix: a-z sort app dir browse by portlet.title not portlet.name<commit_after>/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {
  var currentPage = 'market';
  var currentCategory = '';

  return angular.module('my-app.marketplace.controllers', [])

  .controller('MarketplaceCommonFunctionsController',
    ['googleCustomSearchService', 'miscSearchService', 'layoutService',
      '$log', 'marketplaceService', 'miscService', 'MISC_URLS',
      '$sessionStorage', '$localStorage', '$rootScope', '$scope',
      '$routeParams', '$timeout', '$location', '$mdColors',
    function(googleCustomSearchService, miscSearchService, layoutService,
      $log, marketplaceService, miscService, MISC_URLS,
        $sessionStorage, $localStorage, $rootScope, $scope,
        $routeParams, $timeout, $location, $mdColors) {
      var vm = this;

      if ($sessionStorage.portal.theme) {
        // theme already in session, use primary color from it
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($sessionStorage.portal.theme.name
          + '-primary');
      } else {
        // theme not yet in session, use primary color from zeroth theme
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($rootScope.THEMES[0].name
            + '-primary');
        }

       $scope.navToDetails = function(marketplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path('apps/details/'+ marketplaceEntry.fname);
       };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 // a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; // static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if ($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage +
              '/web/apps/details/'+ marketplaceEntry.fname;
        } else if (layoutObj.altMaxUrl == false &&
            (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if (layoutObj.altMaxUrl == false &&
            $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function(request, text) {
          angular.element('.fname-'+fname)
            .html(' Added Successfully')
            .prop('disabled', true)
            .removeClass('btn-add')
            .addClass('btn-added');
          $scope.$apply(function() {
            var marketplaceEntries = $.grep(
              $sessionStorage.marketplace,
              function(e) {
                return e.fname === portlet.fname;
              }
            );
            if (marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; // reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            angular.element('.fname-'+fname)
              .parent()
              .append(
                'Issue adding to home, please try again later'
              );
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(
          portlet,
          $scope.searchTerm,
          {
            searchDescription: true,
            searchKeywords: true,
            defaultReturn: true,
          }
        );
      };

      $scope.selectFilter = function(filter, category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating', '-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'title';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'title';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace', 'Tab Select', filter);
      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      vm.setupSearchTerm = function() {
        var tempFilterText = '';
        var filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if ($routeParams.initFilter !== null &&
            ($scope.searchTerm === null || $scope.searchTerm === '')) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter('');
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        // delay on the filter
        $scope.$watch('searchText', function(val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if (initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search', 'Filter', $scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      vm.initializeConstants = function() {
        var errorFn = function(name) {
          return function() {
            $log.warn('Could not ' + name);
          };
        };
        // initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(
          function(webSearchURL) {
            $scope.webSearchUrl = webSearchURL;
            return webSearchURL;
          }
        ).catch(errorFn('getPublicWebSearchURL'));
        googleCustomSearchService.getDomainResultsLabel().then(
          function(domainResultsLabel) {
            $scope.domainResultsLabel = domainResultsLabel;
            return domainResultsLabel;
          }
        ).catch(errorFn('getDomainResultsLabel'));
        miscSearchService.getKBSearchURL().then(
          function(kbSearchURL) {
            $scope.kbSearchUrl = kbSearchURL;
            return kbSearchURL;
          }
        ).catch(errorFn('getKBSearchURL'));
        miscSearchService.getEventSearchURL().then(
          function(eventsSearchURL) {
            $scope.eventsSearchUrl = eventsSearchURL;
            return eventsSearchURL;
          }
        ).catch(errorFn('getEventSearchURL'));
        miscSearchService.getHelpDeskHelpURL().then(
          function(helpdeskURL) {
            $scope.helpdeskUrl = helpdeskURL;
            return helpdeskURL;
          }
        ).catch(errorFn('getHelpDeskHelpURL'));
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      };
    },
  ])

  .controller('MarketplaceController', [
    '$log', '$rootScope', '$scope', '$controller', 'marketplaceService',
    function($log, $rootScope, $scope, $controller, marketplaceService) {
      var base = $controller('MarketplaceCommonFunctionsController',
        {$scope: $scope});

      var init = function() {
        // init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
          return data;
        }).catch(function() {
          $log.warn('Could not getPortlets');
        });

        base.setupSearchTerm();

        // initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if (currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by category for
          // marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use title to filter
          $scope.sortParameter = 'title';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if (currentCategory !== '') {
            $scope.categoryToShow = currentCategory;
          } else {
            $scope.categoryToShow = '';
          }
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating', '-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      // run functions
      init();
    }])

  .controller('MarketplaceDetailsController', [
      '$controller', '$document', '$scope', '$routeParams',
      '$mdDialog', 'marketplaceService', 'SERVICE_LOC',
      function($controller, $document, $scope, $routeParams,
          $mdDialog, marketplaceService, SERVICE_LOC) {
        $controller('MarketplaceCommonFunctionsController',
          {$scope: $scope});

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if (fromInfo.term) {
            // from somewhere
            if ('Search' === fromInfo.searchOrBrowse && fromInfo.term) {
              // if from search and term is populated, return to search
              $scope.backText = 'Search Results for ' + fromInfo.term;
              $scope.backURL = 'apps/search/' + fromInfo.term;
            } else {
              // assuming from browse
              $scope.backText = 'Browse';
              $scope.backURL = 'apps/browse/' + fromInfo.term;
            }

            // reset services
            marketplaceService.setFromInfo(undefined, undefined);
          } else {
            // direct hit, will go back to browse
            $scope.backURL='apps';
            $scope.backText='Browse';
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element($document.body),
            scope: $scope,
            preserveScope: true,
            clickOutsideToClose: true,
            fullscreen: false,
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage =
              'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(
            function(result) {
              $scope.loading = false;
              if (!result) {
                $scope.error = true;
                $scope.portlet = null;
              } else {
                $scope.portlet = result;
                $scope.error = false;
              }
              return result;
            }
          ).catch(function(reason) {
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  )

  .controller('MarketplaceRatingReviewAdminController', [
    '$log', '$scope', 'marketplaceService',
    function($log, $scope, marketplaceService) {
      var init = function() {
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(
          function(ratings) {
            if (ratings) {
              $scope.ratings = ratings;
              $scope.average =0;
              $scope.totalReviews = 0;
              angular.forEach(ratings, function(value, key) {
                $scope.average+= value.rating;
                if (value.review) {
                  $scope.totalReviews += 1;
                }
              });
              $scope.average = Math.round($scope.average / ratings.length);
            }
            return ratings;
          }
        ).catch(function() {
          $log.warn('Could not getAllRatings');
        });
      };

      init();
    }]);
});
<|endoftext|>


<commit_before>// Karma configuration
// Generated on Sun Dec 08 2013 13:15:24 GMT-0500 (EST)

module.exports = function(config) {
  config.set({

    // base path, that will be used to resolve files and exclude
    basePath: '',

    // frameworks to use
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'app/scripts/angular.js',
      'app/scripts/angular-resource.js',
      'app/scripts/angular-route.js',
      'app/scripts/**/*.js',
      'test/unit/**/*.js'
    ],

    // list of files to exclude
    exclude: [

    ],

    // test results reporter to use
    // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Chrome'],

    // If browser does not capture in given timeout [ms], kill it
    captureTimeout: 60000,

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false
  });
};
<commit_msg>adding tests by phases<commit_after>// Karma configuration
// Generated on Sun Dec 08 2013 13:15:24 GMT-0500 (EST)

module.exports = function(config) {
  config.set({

    // base path, that will be used to resolve files and exclude
    basePath: '',

    // frameworks to use
    frameworks: ['jasmine'],

    // list of files / patterns to load in the browser
    files: [
      'app/scripts/angular.js',
      'app/scripts/angular-resource.js',
      'app/scripts/angular-route.js',
      'app/scripts/underscore.js',
      'test/unit/angular-mocks.js',
      'test/unit/controller-test-helper.js',
      'app/scripts/**/*.js',
//      'test/unit/**/*.js'
      'test/unit/band-edit-phase1-spec.js',
      'test/unit/band-edit-phase2-spec.js',
      'test/unit/band-edit-phase3-spec.js'
    ],

    // list of files to exclude
    exclude: [

    ],

    // test results reporter to use
    // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
    reporters: ['progress'],

    // web server port
    port: 9876,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,

    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,

    // Start these browsers, currently available:
    // - Chrome
    // - ChromeCanary
    // - Firefox
    // - Opera
    // - Safari (only Mac)
    // - PhantomJS
    // - IE (only Windows)
    browsers: ['Chrome'],

    // If browser does not capture in given timeout [ms], kill it
    captureTimeout: 60000,

    // Continuous Integration mode
    // if true, it capture browsers, run tests and exit
    singleRun: false
  });
};
<|endoftext|>


<commit_before>/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {
  var currentPage = 'market';
  var currentCategory = '';

  return angular.module('my-app.marketplace.controllers', [])

  .controller('MarketplaceCommonFunctionsController',
    ['googleCustomSearchService', 'miscSearchService', 'layoutService',
      '$log', 'marketplaceService', 'miscService', 'MISC_URLS',
      '$sessionStorage', '$localStorage', '$rootScope', '$scope',
      '$routeParams', '$timeout', '$location', '$mdColors',
    function(googleCustomSearchService, miscSearchService, layoutService,
      $log, marketplaceService, miscService, MISC_URLS,
        $sessionStorage, $localStorage, $rootScope, $scope,
        $routeParams, $timeout, $location, $mdColors) {
      var vm = this;

      if(!$sessionStorage.portal.theme){
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($rootScope.THEMES[0].name
            + '-primary');
      } else {
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($sessionStorage.portal.theme.name
          + '-primary');
        }

       $scope.navToDetails = function(marketplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path('apps/details/'+ marketplaceEntry.fname);
       };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 // a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; // static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if ($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage +
              '/web/apps/details/'+ marketplaceEntry.fname;
        } else if (layoutObj.altMaxUrl == false &&
            (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if (layoutObj.altMaxUrl == false &&
            $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function(request, text) {
          angular.element('.fname-'+fname)
            .html(' Added Successfully')
            .prop('disabled', true)
            .removeClass('btn-add')
            .addClass('btn-added');
          $scope.$apply(function() {
            var marketplaceEntries = $.grep(
              $sessionStorage.marketplace,
              function(e) {
                return e.fname === portlet.fname;
              }
            );
            if (marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; // reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            angular.element('.fname-'+fname)
              .parent()
              .append(
                'Issue adding to home, please try again later'
              );
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(
          portlet,
          $scope.searchTerm,
          {
            searchDescription: true,
            searchKeywords: true,
            defaultReturn: true,
          }
        );
      };

      $scope.selectFilter = function(filter, category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating', '-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'name';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'name';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace', 'Tab Select', filter);
      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      vm.setupSearchTerm = function() {
        var tempFilterText = '';
        var filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if ($routeParams.initFilter !== null &&
            ($scope.searchTerm === null || $scope.searchTerm === '')) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter('');
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        // delay on the filter
        $scope.$watch('searchText', function(val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if (initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search', 'Filter', $scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      vm.initializeConstants = function() {
        var errorFn = function(name) {
          return function() {
            $log.warn('Could not ' + name);
          };
        };
        // initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(
          function(webSearchURL) {
            $scope.webSearchUrl = webSearchURL;
            return webSearchURL;
          }
        ).catch(errorFn('getPublicWebSearchURL'));
        googleCustomSearchService.getDomainResultsLabel().then(
          function(domainResultsLabel) {
            $scope.domainResultsLabel = domainResultsLabel;
            return domainResultsLabel;
          }
        ).catch(errorFn('getDomainResultsLabel'));
        miscSearchService.getKBSearchURL().then(
          function(kbSearchURL) {
            $scope.kbSearchUrl = kbSearchURL;
            return kbSearchURL;
          }
        ).catch(errorFn('getKBSearchURL'));
        miscSearchService.getEventSearchURL().then(
          function(eventsSearchURL) {
            $scope.eventsSearchUrl = eventsSearchURL;
            return eventsSearchURL;
          }
        ).catch(errorFn('getEventSearchURL'));
        miscSearchService.getHelpDeskHelpURL().then(
          function(helpdeskURL) {
            $scope.helpdeskUrl = helpdeskURL;
            return helpdeskURL;
          }
        ).catch(errorFn('getHelpDeskHelpURL'));
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      };
    },
  ])

  .controller('MarketplaceController', [
    '$log', '$rootScope', '$scope', '$controller', 'marketplaceService',
    function($log, $rootScope, $scope, $controller, marketplaceService) {
      var base = $controller('MarketplaceCommonFunctionsController',
        {$scope: $scope});

      var init = function() {
        // init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
          return data;
        }).catch(function() {
          $log.warn('Could not getPortlets');
        });

        base.setupSearchTerm();

        // initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if (currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by category for
          // marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use name to filter
          $scope.sortParameter = 'name';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if (currentCategory !== '') {
            $scope.categoryToShow = currentCategory;
          } else {
            $scope.categoryToShow = '';
          }
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating', '-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      // run functions
      init();
    }])

  .controller('MarketplaceDetailsController', [
      '$controller', '$document', '$scope', '$routeParams',
      '$mdDialog', 'marketplaceService', 'SERVICE_LOC',
      function($controller, $document, $scope, $routeParams,
          $mdDialog, marketplaceService, SERVICE_LOC) {
        $controller('MarketplaceCommonFunctionsController',
          {$scope: $scope});

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if (fromInfo.term) {
            // from somewhere
            if ('Search' === fromInfo.searchOrBrowse && fromInfo.term) {
              // if from search and term is populated, return to search
              $scope.backText = 'Search Results for ' + fromInfo.term;
              $scope.backURL = 'apps/search/' + fromInfo.term;
            } else {
              // assuming from browse
              $scope.backText = 'Browse';
              $scope.backURL = 'apps/browse/' + fromInfo.term;
            }

            // reset services
            marketplaceService.setFromInfo(undefined, undefined);
          } else {
            // direct hit, will go back to browse
            $scope.backURL='apps';
            $scope.backText='Browse';
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element($document.body),
            scope: $scope,
            preserveScope: true,
            clickOutsideToClose: true,
            fullscreen: false,
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage =
              'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(
            function(result) {
              $scope.loading = false;
              if (!result) {
                $scope.error = true;
                $scope.portlet = null;
              } else {
                $scope.portlet = result;
                $scope.error = false;
              }
              return result;
            }
          ).catch(function(reason) {
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  )

  .controller('MarketplaceRatingReviewAdminController', [
    '$log', '$scope', 'marketplaceService',
    function($log, $scope, marketplaceService) {
      var init = function() {
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(
          function(ratings) {
            if (ratings) {
              $scope.ratings = ratings;
              $scope.average =0;
              $scope.totalReviews = 0;
              angular.forEach(ratings, function(value, key) {
                $scope.average+= value.rating;
                if (value.review) {
                  $scope.totalReviews += 1;
                }
              });
              $scope.average = Math.round($scope.average / ratings.length);
            }
            return ratings;
          }
        ).catch(function() {
          $log.warn('Could not getAllRatings');
        });
      };

      init();
    }]);
});
<commit_msg>style(lint): Style code to follow style guide (#738)<commit_after>/*
 * Licensed to Apereo under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Apereo licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
'use strict';

define(['angular', 'jquery', 'require'], function(angular, $, require) {
  var currentPage = 'market';
  var currentCategory = '';

  return angular.module('my-app.marketplace.controllers', [])

  .controller('MarketplaceCommonFunctionsController',
    ['googleCustomSearchService', 'miscSearchService', 'layoutService',
      '$log', 'marketplaceService', 'miscService', 'MISC_URLS',
      '$sessionStorage', '$localStorage', '$rootScope', '$scope',
      '$routeParams', '$timeout', '$location', '$mdColors',
    function(googleCustomSearchService, miscSearchService, layoutService,
      $log, marketplaceService, miscService, MISC_URLS,
        $sessionStorage, $localStorage, $rootScope, $scope,
        $routeParams, $timeout, $location, $mdColors) {
      var vm = this;

      if (!$sessionStorage.portal.theme) {
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($rootScope.THEMES[0].name
            + '-primary');
      } else {
        $scope.primaryColorRgb =
          $mdColors.getThemeColor($sessionStorage.portal.theme.name
          + '-primary');
        }

       $scope.navToDetails = function(marketplaceEntry, location) {
        marketplaceService.setFromInfo(location, $scope.searchTerm);
        $location.path('apps/details/'+ marketplaceEntry.fname);
       };

      $scope.isStatic = function(portlet) {
        return portlet.maxUrl.indexOf('portal') !== -1 // a portal hit
          && portlet.portletName // there is a portletName
          && portlet.portletName.indexOf('cms') != -1; // static content portlet
      };

      $scope.getLaunchURL = function(marketplaceEntry) {
        var layoutObj = marketplaceEntry.layoutObject;
        if ($rootScope.GuestMode && !marketplaceEntry.hasInLayout) {
          return $scope.loginToAuthPage +
              '/web/apps/details/'+ marketplaceEntry.fname;
        } else if (layoutObj.altMaxUrl == false &&
            (layoutObj.renderOnWeb || $localStorage.webPortletRender)) {
          return 'exclusive/' + layoutObj.fname;
        } else if (layoutObj.altMaxUrl == false &&
            $scope.isStatic(marketplaceEntry)) {
          return 'static/' + layoutObj.fname;
        } else {
          return marketplaceEntry.maxUrl;
        }
      };

      $scope.addToHome = function addToHome(portlet) {
        var fname = portlet.fname;
        var ret = layoutService.addToHome(portlet);
        ret.success(function(request, text) {
          angular.element('.fname-'+fname)
            .html(' Added Successfully')
            .prop('disabled', true)
            .removeClass('btn-add')
            .addClass('btn-added');
          $scope.$apply(function() {
            var marketplaceEntries = $.grep(
              $sessionStorage.marketplace,
              function(e) {
                return e.fname === portlet.fname;
              }
            );
            if (marketplaceEntries.length > 0) {
              marketplaceEntries[0].hasInLayout = true;
            }
            $rootScope.layout = null; // reset layout due to modifications
            $sessionStorage.layout = null;
          });
        })
          .error(function(request, text, error) {
            angular.element('.fname-'+fname)
              .parent()
              .append(
                'Issue adding to home, please try again later'
              );
          });
      };

      $scope.searchTermFilter = function(portlet) {
        return marketplaceService.portletMatchesSearchTerm(
          portlet,
          $scope.searchTerm,
          {
            searchDescription: true,
            searchKeywords: true,
            defaultReturn: true,
          }
        );
      };

      $scope.selectFilter = function(filter, category) {
        $scope.sortParameter = filter;
        $scope.categoryToShow = category;
        $scope.showCategories = false;
        if (filter === 'popular') {
          $scope.selectedFilter = 'popular';
          $scope.sortParameter = ['-rating', '-userRated'];
        }
        if (filter === 'az') {
          $scope.selectedFilter = 'az';
          $scope.sortParameter = 'name';
        }
        if (filter === 'category') {
          $scope.selectedFilter = 'category';
          $scope.sortParameter = 'name';
          $scope.showCategories = true;
        }

        miscService.pushGAEvent('Marketplace', 'Tab Select', filter);
      };

      $scope.slideTabs = function(direction) {
        $scope.tabsPosition = 'start';
        if (direction === 'right') {
          $scope.tabsPosition = 'end';
        }
      };

      $scope.toggleShowAll = function() {
        $scope.showAll = !$scope.showAll;
      };

      vm.setupSearchTerm = function() {
        var tempFilterText = '';
        var filterTextTimeout;
        $scope.searchTerm = marketplaceService.getInitialFilter();
        if ($routeParams.initFilter !== null &&
            ($scope.searchTerm === null || $scope.searchTerm === '')) {
          $scope.searchTerm = $routeParams.initFilter;
        } else {
          marketplaceService.initialFilter('');
        }
        $scope.searchText = $scope.searchTerm;
        var initFilter = false;
        // delay on the filter
        $scope.$watch('searchText', function(val) {
          if (filterTextTimeout) $timeout.cancel(filterTextTimeout);

          tempFilterText = val;
          filterTextTimeout = $timeout(function() {
            $scope.searchTerm = tempFilterText;
            if (initFilter && $scope.searchTerm) {
              miscService.pushGAEvent('Search', 'Filter', $scope.searchTerm);
            } else {
              initFilter = true;
            }
          }, 250); // delay 250 ms
        });
      };

      vm.initializeConstants = function() {
        var errorFn = function(name) {
          return function() {
            $log.warn('Could not ' + name);
          };
        };
        // initialize constants
        googleCustomSearchService.getPublicWebSearchURL().then(
          function(webSearchURL) {
            $scope.webSearchUrl = webSearchURL;
            return webSearchURL;
          }
        ).catch(errorFn('getPublicWebSearchURL'));
        googleCustomSearchService.getDomainResultsLabel().then(
          function(domainResultsLabel) {
            $scope.domainResultsLabel = domainResultsLabel;
            return domainResultsLabel;
          }
        ).catch(errorFn('getDomainResultsLabel'));
        miscSearchService.getKBSearchURL().then(
          function(kbSearchURL) {
            $scope.kbSearchUrl = kbSearchURL;
            return kbSearchURL;
          }
        ).catch(errorFn('getKBSearchURL'));
        miscSearchService.getEventSearchURL().then(
          function(eventsSearchURL) {
            $scope.eventsSearchUrl = eventsSearchURL;
            return eventsSearchURL;
          }
        ).catch(errorFn('getEventSearchURL'));
        miscSearchService.getHelpDeskHelpURL().then(
          function(helpdeskURL) {
            $scope.helpdeskUrl = helpdeskURL;
            return helpdeskURL;
          }
        ).catch(errorFn('getHelpDeskHelpURL'));
        $scope.directorySearchUrl = MISC_URLS.directorySearchURL;
        $scope.feedbackUrl = MISC_URLS.feedbackURL;
        $scope.loginToAuthPage = MISC_URLS.myuwHome;
      };
    },
  ])

  .controller('MarketplaceController', [
    '$log', '$rootScope', '$scope', '$controller', 'marketplaceService',
    function($log, $rootScope, $scope, $controller, marketplaceService) {
      var base = $controller('MarketplaceCommonFunctionsController',
        {$scope: $scope});

      var init = function() {
        // init variables
        $scope.portlets = [];
        marketplaceService.getPortlets().then(function(data) {
          $scope.portlets = data.portlets;
          $scope.categories = data.categories;
          return data;
        }).catch(function() {
          $log.warn('Could not getPortlets');
        });

        base.setupSearchTerm();

        // initialize variables

        $scope.searchResultLimit = 20;
        $scope.showAll = $rootScope.GuestMode || false;
        if (currentPage === 'details') {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by category for
          // marketplaceDetails back to marketplace
          $scope.selectedFilter = 'category';
          // To sort by category, angular will use name to filter
          $scope.sortParameter = 'name';
          // Show category selection div by default
          $scope.showCategories = true;

          currentPage = 'market';
          if (currentCategory !== '') {
            $scope.categoryToShow = currentCategory;
          } else {
            $scope.categoryToShow = '';
          }
        } else {
          // Empty string indicates no categories, show all portlets
          $scope.categoryToShow = '';
          // Default filter is to sort by popularity
          $scope.selectedFilter = 'popular';
          // To sort by popularity, angular will use portlet.rating to filter
          $scope.sortParameter = ['-rating', '-userRated'];
          // Hide category selection div by default
          $scope.showCategories = false;
        }

        base.initializeConstants();
      };

      // run functions
      init();
    }])

  .controller('MarketplaceDetailsController', [
      '$controller', '$document', '$scope', '$routeParams',
      '$mdDialog', 'marketplaceService', 'SERVICE_LOC',
      function($controller, $document, $scope, $routeParams,
          $mdDialog, marketplaceService, SERVICE_LOC) {
        $controller('MarketplaceCommonFunctionsController',
          {$scope: $scope});

        $scope.specifyCategory = function(category) {
          currentCategory=category;
          currentPage='details';
        };

        var figureOutBackStuff = function() {
          var fromInfo = marketplaceService.getFromInfo();
          if (fromInfo.term) {
            // from somewhere
            if ('Search' === fromInfo.searchOrBrowse && fromInfo.term) {
              // if from search and term is populated, return to search
              $scope.backText = 'Search Results for ' + fromInfo.term;
              $scope.backURL = 'apps/search/' + fromInfo.term;
            } else {
              // assuming from browse
              $scope.backText = 'Browse';
              $scope.backURL = 'apps/browse/' + fromInfo.term;
            }

            // reset services
            marketplaceService.setFromInfo(undefined, undefined);
          } else {
            // direct hit, will go back to browse
            $scope.backURL='apps';
            $scope.backText='Browse';
          }
        };

        $scope.clickRatingReviewAdmin = function() {
          $mdDialog.show({
            controller: 'MarketplaceRatingReviewAdminController',
            templateUrl: require.toUrl('./partials/rating-review-admin.html'),
            parent: angular.element($document.body),
            scope: $scope,
            preserveScope: true,
            clickOutsideToClose: true,
            fullscreen: false,
          });
        };

        // init
        var init = function() {
          $scope.loading = true;
          figureOutBackStuff();
          $scope.obj = [];
          $scope.ratingPrefix = SERVICE_LOC.base +
            SERVICE_LOC.marketplace.base;
          $scope.errorMessage =
              'There was an issue loading details, please click back to apps.';
          marketplaceService.getPortlet($routeParams.fname).then(
            function(result) {
              $scope.loading = false;
              if (!result) {
                $scope.error = true;
                $scope.portlet = null;
              } else {
                $scope.portlet = result;
                $scope.error = false;
              }
              return result;
            }
          ).catch(function(reason) {
            $scope.loading = false;
            $scope.error = true;
          });
        };
        init();
      }]
  )

  .controller('MarketplaceRatingReviewAdminController', [
    '$log', '$scope', 'marketplaceService',
    function($log, $scope, marketplaceService) {
      var init = function() {
        $scope.ratings = [];
        marketplaceService.getAllRatings($scope.portlet.fname).then(
          function(ratings) {
            if (ratings) {
              $scope.ratings = ratings;
              $scope.average =0;
              $scope.totalReviews = 0;
              angular.forEach(ratings, function(value, key) {
                $scope.average+= value.rating;
                if (value.review) {
                  $scope.totalReviews += 1;
                }
              });
              $scope.average = Math.round($scope.average / ratings.length);
            }
            return ratings;
          }
        ).catch(function() {
          $log.warn('Could not getAllRatings');
        });
      };

      init();
    }]);
});
<|endoftext|>


<commit_before>var clone= require('clone');
var paths = require('./build/paths');
var webpackConfig = clone(require('./webpack.config.js'));

// Add istanbul-instrumenter to webpack configuration
webpackConfig.module.loaders.push(
    {
        test: /\.js$/,
        exclude: /(node_modules|test)/,
        loader: 'babel-istanbul-loader'
    }
);

webpackConfig.output.filename += '.test';
webpackConfig.plugins = [];
webpackConfig.externals = [];

// The main configuration
module.exports = function(config) {
    if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) {
        console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.')
        process.exit(1)
    }

    var customLaunchers = {
        sl_chrome: {
            base: 'SauceLabs',
            browserName: 'chrome',
            platform: 'Windows 7',
            version: '35'
        },
        sl_firefox: {
            base: 'SauceLabs',
            browserName: 'firefox',
            version: '30'
        },
        sl_ie_11: {
            base: 'SauceLabs',
            browserName: 'internet explorer',
            platform: 'Windows 8.1',
            version: '11'
        }
    }

    config.set({
        frameworks: [
            'jasmine-jquery',
            'jasmine-ajax',
            'jasmine'
        ],

        files: [
            'test/*.spec.js'
        ],

        preprocessors: {
            'test/*.spec.js': [
                'webpack'
            ]
        },

        coverageReporter: {
            reporters: [
                { type: 'lcov', dir: paths.coverageDir },
                { type: 'text' }
            ]
        },

        webpack: webpackConfig,

        webpackMiddleware: {
            noInfo: true
        },
        colors: true,
        recordScreenshots: false,
        reporters: (process.env.TRAVIS) ? ['spec', 'coverage', 'coveralls', 'saucelabs'] : ['spec', 'coverage', 'saucelabs'],

        sauceLabs: {
            testName: 'Dual listbox browser testing',
            public: 'public'
        },
        customLaunchers: customLaunchers,
        captureTimeout: 120000,
        browsers: Object.keys(customLaunchers),
        singleRun: true
    });
}
<commit_msg>Added a check if using CI<commit_after>var clone= require('clone');
var paths = require('./build/paths');
var webpackConfig = clone(require('./webpack.config.js'));

// Add istanbul-instrumenter to webpack configuration
webpackConfig.module.loaders.push(
    {
        test: /\.js$/,
        exclude: /(node_modules|test)/,
        loader: 'babel-istanbul-loader'
    }
);

webpackConfig.output.filename += '.test';
webpackConfig.plugins = [];
webpackConfig.externals = [];

function ConfigException(message) {
   this.message = message;
   this.name = 'ConfigException';
}

// The main configuration
module.exports = function(config) {
    if (process.env.CI && (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY)) {
        throw ConfigException('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.')
    }

    var customLaunchers = {
        sl_chrome: {
            base: 'SauceLabs',
            browserName: 'chrome',
            platform: 'Windows 7',
            version: '35'
        },
        sl_firefox: {
            base: 'SauceLabs',
            browserName: 'firefox',
            version: '30'
        },
        sl_ie_11: {
            base: 'SauceLabs',
            browserName: 'internet explorer',
            platform: 'Windows 8.1',
            version: '11'
        }
    }

    config.set({
        frameworks: [
            'jasmine-jquery',
            'jasmine-ajax',
            'jasmine'
        ],

        files: [
            'test/*.spec.js'
        ],

        preprocessors: {
            'test/*.spec.js': [
                'webpack'
            ]
        },

        coverageReporter: {
            reporters: [
                { type: 'lcov', dir: paths.coverageDir },
                { type: 'text' }
            ]
        },

        webpack: webpackConfig,

        webpackMiddleware: {
            noInfo: true
        },
        colors: true,
        recordScreenshots: false,
        reporters: (process.env.TRAVIS) ? ['spec', 'coverage', 'coveralls', 'saucelabs'] : ['spec', 'coverage', 'saucelabs'],

        sauceLabs: {
            testName: 'Dual listbox browser testing',
            public: 'public'
        },
        customLaunchers: customLaunchers,
        captureTimeout: 120000,
        browsers: Object.keys(customLaunchers),
        singleRun: true
    });
}
<|endoftext|>


<commit_before>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           ______     ______     ______   __  __     __     ______
          /\  == \   /\  __ \   /\__  _\ /\ \/ /    /\ \   /\__  _\
          \ \  __<   \ \ \/\ \  \/_/\ \/ \ \  _"-.  \ \ \  \/_/\ \/
           \ \_____\  \ \_____\    \ \_\  \ \_\ \_\  \ \_\    \ \_\
            \/_____/   \/_____/     \/_/   \/_/\/_/   \/_/     \/_/

This is a sample Facebook bot built with Botkit.

This bot demonstrates many of the core features of Botkit:

* Connect to Facebook's Messenger APIs
* Receive messages based on "spoken" patterns
* Reply to messages
* Use the conversation system to ask questions
* Use the built in storage system to store and retrieve information
  for a user.

# RUN THE BOT:

  Follow the instructions here to set up your Facebook app and page:

    -> https://developers.facebook.com/docs/messenger-platform/implementation

  Run your bot from the command line:

    page_token=<MY PAGE TOKEN> verify_token=<MY_VERIFY_TOKEN> node facebook_bot.js

  Use localtunnel.me to make your bot available on the web:

    lt --port 3000

# USE THE BOT:

  Find your bot inside Facebook to send it a direct message.

  Say: "Hello"

  The bot will reply "Hello!"

  Say: "who are you?"

  The bot will tell you its name, where it running, and for how long.

  Say: "Call me <nickname>"

  Tell the bot your nickname. Now you are friends.

  Say: "who am I?"

  The bot will tell you your nickname, if it knows one for you.

  Say: "shutdown"

  The bot will ask if you are sure, and then shut itself down.

  Make sure to invite your bot into other channels using /invite @<my bot>!

# EXTEND THE BOT:

  Botkit has many features for building cool and useful bots!

  Read all about it here:

    -> http://howdy.ai/botkit

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

if (!process.env.page_token) {
    console.log('Error: Specify page_token in environment');
    process.exit(1);
}

if (!process.env.verify_token) {
    console.log('Error: Specify verify_token in environment');
    process.exit(1);
}

var Botkit = require('botkit');
var os = require('os');

var controller = Botkit.facebookbot({
    debug: true,
    access_token: process.env.page_token,
    verify_token: process.env.verify_token,
});

var bot = controller.spawn({
});

controller.setupWebserver(process.env.port || 3000, function(err, webserver) {
    controller.createWebhookEndpoints(webserver, bot, function() {
        console.log('ONLINE!');
    });
});

controller.hears(['hello', 'hi'], 'message_received', function(bot, message) {

    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Hello ' + user.name + '!!');
        } else {
            bot.reply(message, 'Hello.');
        }
    });
});

controller.hears(['structured'], 'message_received', function(bot, message) {

    bot.reply(message, {
        attachment: {
            'type': 'template',
            'payload': {
                'template_type': 'generic',
                'elements': [
                    {
                        'title': 'Classic White T-Shirt',
                        'image_url': 'http://petersapparel.parseapp.com/img/item100-thumb.png',
                        'subtitle': 'Soft white cotton t-shirt is back in style',
                        'buttons': [
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/view_item?item_id=100',
                                'title': 'View Item'
                            },
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/buy_item?item_id=100',
                                'title': 'Buy Item'
                            },
                            {
                                'type': 'postback',
                                'title': 'Bookmark Item',
                                'payload': 'White T-Shirt'
                            }
                        ]
                    },
                    {
                        'title': 'Classic Grey T-Shirt',
                        'image_url': 'http://petersapparel.parseapp.com/img/item101-thumb.png',
                        'subtitle': 'Soft gray cotton t-shirt is back in style',
                        'buttons': [
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/view_item?item_id=101',
                                'title': 'View Item'
                            },
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/buy_item?item_id=101',
                                'title': 'Buy Item'
                            },
                            {
                                'type': 'postback',
                                'title': 'Bookmark Item',
                                'payload': 'Grey T-Shirt'
                            }
                        ]
                    }
                ]
            }
        }
    });
});

controller.on('facebook_postback', function(bot, message) {

    bot.reply(message, 'Great Choice!!!! (' + message.payload + ')');

});

controller.hears(['call me (.*)', 'my name is (.*)'], 'message_received', function(bot, message) {
    var name = message.match[1];
    controller.storage.users.get(message.user, function(err, user) {
        if (!user) {
            user = {
                id: message.user,
            };
        }
        user.name = name;
        controller.storage.users.save(user, function(err, id) {
            bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
        });
    });
});

controller.hears(['what is my name', 'who am i'], 'message_received', function(bot, message) {
    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Your name is ' + user.name);
        } else {
            bot.startConversation(message, function(err, convo) {
                if (!err) {
                    convo.say('I do not know your name yet!');
                    convo.ask('What should I call you?', function(response, convo) {
                        convo.ask('You want me to call you `' + response.text + '`?', [
                            {
                                pattern: 'yes',
                                callback: function(response, convo) {
                                    // since no further messages are queued after this,
                                    // the conversation will end naturally with status == 'completed'
                                    convo.next();
                                }
                            },
                            {
                                pattern: 'no',
                                callback: function(response, convo) {
                                    // stop the conversation. this will cause it to end with status == 'stopped'
                                    convo.stop();
                                }
                            },
                            {
                                default: true,
                                callback: function(response, convo) {
                                    convo.repeat();
                                    convo.next();
                                }
                            }
                        ]);

                        convo.next();

                    }, {'key': 'nickname'}); // store the results in a field called nickname

                    convo.on('end', function(convo) {
                        if (convo.status == 'completed') {
                            bot.reply(message, 'OK! I will update my dossier...');

                            controller.storage.users.get(message.user, function(err, user) {
                                if (!user) {
                                    user = {
                                        id: message.user,
                                    };
                                }
                                user.name = convo.extractResponse('nickname');
                                controller.storage.users.save(user, function(err, id) {
                                    bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
                                });
                            });

                        } else {
                            // this happens if the conversation ended prematurely for some reason
                            bot.reply(message, 'OK, nevermind!');
                        }
                    });
                }
            });
        }
    });
});

controller.hears(['shutdown'], 'message_received', function(bot, message) {

    bot.startConversation(message, function(err, convo) {

        convo.ask('Are you sure you want me to shutdown?', [
            {
                pattern: bot.utterances.yes,
                callback: function(response, convo) {
                    convo.say('Bye!');
                    convo.next();
                    setTimeout(function() {
                        process.exit();
                    }, 3000);
                }
            },
        {
            pattern: bot.utterances.no,
            default: true,
            callback: function(response, convo) {
                convo.say('*Phew!*');
                convo.next();
            }
        }
        ]);
    });
});

controller.hears(['uptime', 'identify yourself', 'who are you', 'what is your name'], 'message_received',
    function(bot, message) {

        var hostname = os.hostname();
        var uptime = formatUptime(process.uptime());

        bot.reply(message,
            ':robot_face: I am a bot named <@' + bot.identity.name +
             '>. I have been running for ' + uptime + ' on ' + hostname + '.');
    });

controller.on('message_received', function(bot, message) {
    bot.reply(message, 'Try: `what is my name` or `structured` or `call me captain`');
    return false;
});

function formatUptime(uptime) {
    var unit = 'second';
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'minute';
    }
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'hour';
    }
    if (uptime != 1) {
        unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
}
<commit_msg>Move greetings<commit_after>/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           ______     ______     ______   __  __     __     ______
          /\  == \   /\  __ \   /\__  _\ /\ \/ /    /\ \   /\__  _\
          \ \  __<   \ \ \/\ \  \/_/\ \/ \ \  _"-.  \ \ \  \/_/\ \/
           \ \_____\  \ \_____\    \ \_\  \ \_\ \_\  \ \_\    \ \_\
            \/_____/   \/_____/     \/_/   \/_/\/_/   \/_/     \/_/

This is a sample Facebook bot built with Botkit.

This bot demonstrates many of the core features of Botkit:

* Connect to Facebook's Messenger APIs
* Receive messages based on "spoken" patterns
* Reply to messages
* Use the conversation system to ask questions
* Use the built in storage system to store and retrieve information
  for a user.

# RUN THE BOT:

  Follow the instructions here to set up your Facebook app and page:

    -> https://developers.facebook.com/docs/messenger-platform/implementation

  Run your bot from the command line:

    page_token=<MY PAGE TOKEN> verify_token=<MY_VERIFY_TOKEN> node facebook_bot.js

  Use localtunnel.me to make your bot available on the web:

    lt --port 3000

# USE THE BOT:

  Find your bot inside Facebook to send it a direct message.

  Say: "Hello"

  The bot will reply "Hello!"

  Say: "who are you?"

  The bot will tell you its name, where it running, and for how long.

  Say: "Call me <nickname>"

  Tell the bot your nickname. Now you are friends.

  Say: "who am I?"

  The bot will tell you your nickname, if it knows one for you.

  Say: "shutdown"

  The bot will ask if you are sure, and then shut itself down.

  Make sure to invite your bot into other channels using /invite @<my bot>!

# EXTEND THE BOT:

  Botkit has many features for building cool and useful bots!

  Read all about it here:

    -> http://howdy.ai/botkit

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/

var greetings = ['hello', 'hi', 'hey'];

if (!process.env.page_token) {
    console.log('Error: Specify page_token in environment');
    process.exit(1);
}

if (!process.env.verify_token) {
    console.log('Error: Specify verify_token in environment');
    process.exit(1);
}

var Botkit = require('botkit');
var os = require('os');

var controller = Botkit.facebookbot({
    debug: true,
    access_token: process.env.page_token,
    verify_token: process.env.verify_token,
});

var bot = controller.spawn({
});

controller.setupWebserver(process.env.port || 3000, function(err, webserver) {
    controller.createWebhookEndpoints(webserver, bot, function() {
        console.log('ONLINE!');
    });
});

controller.hears(greetings, 'message_received', function(bot, message) {

    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Hello ' + user.name + '!!');
        } else {
            bot.reply(message, 'Hello.');
        }
    });
});

controller.hears(['structured'], 'message_received', function(bot, message) {

    bot.reply(message, {
        attachment: {
            'type': 'template',
            'payload': {
                'template_type': 'generic',
                'elements': [
                    {
                        'title': 'Classic White T-Shirt',
                        'image_url': 'http://petersapparel.parseapp.com/img/item100-thumb.png',
                        'subtitle': 'Soft white cotton t-shirt is back in style',
                        'buttons': [
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/view_item?item_id=100',
                                'title': 'View Item'
                            },
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/buy_item?item_id=100',
                                'title': 'Buy Item'
                            },
                            {
                                'type': 'postback',
                                'title': 'Bookmark Item',
                                'payload': 'White T-Shirt'
                            }
                        ]
                    },
                    {
                        'title': 'Classic Grey T-Shirt',
                        'image_url': 'http://petersapparel.parseapp.com/img/item101-thumb.png',
                        'subtitle': 'Soft gray cotton t-shirt is back in style',
                        'buttons': [
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/view_item?item_id=101',
                                'title': 'View Item'
                            },
                            {
                                'type': 'web_url',
                                'url': 'https://petersapparel.parseapp.com/buy_item?item_id=101',
                                'title': 'Buy Item'
                            },
                            {
                                'type': 'postback',
                                'title': 'Bookmark Item',
                                'payload': 'Grey T-Shirt'
                            }
                        ]
                    }
                ]
            }
        }
    });
});

controller.on('facebook_postback', function(bot, message) {

    bot.reply(message, 'Great Choice!!!! (' + message.payload + ')');

});

controller.hears(['call me (.*)', 'my name is (.*)'], 'message_received', function(bot, message) {
    var name = message.match[1];
    controller.storage.users.get(message.user, function(err, user) {
        if (!user) {
            user = {
                id: message.user,
            };
        }
        user.name = name;
        controller.storage.users.save(user, function(err, id) {
            bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
        });
    });
});

controller.hears(['what is my name', 'who am i'], 'message_received', function(bot, message) {
    controller.storage.users.get(message.user, function(err, user) {
        if (user && user.name) {
            bot.reply(message, 'Your name is ' + user.name);
        } else {
            bot.startConversation(message, function(err, convo) {
                if (!err) {
                    convo.say('I do not know your name yet!');
                    convo.ask('What should I call you?', function(response, convo) {
                        convo.ask('You want me to call you `' + response.text + '`?', [
                            {
                                pattern: 'yes',
                                callback: function(response, convo) {
                                    // since no further messages are queued after this,
                                    // the conversation will end naturally with status == 'completed'
                                    convo.next();
                                }
                            },
                            {
                                pattern: 'no',
                                callback: function(response, convo) {
                                    // stop the conversation. this will cause it to end with status == 'stopped'
                                    convo.stop();
                                }
                            },
                            {
                                default: true,
                                callback: function(response, convo) {
                                    convo.repeat();
                                    convo.next();
                                }
                            }
                        ]);

                        convo.next();

                    }, {'key': 'nickname'}); // store the results in a field called nickname

                    convo.on('end', function(convo) {
                        if (convo.status == 'completed') {
                            bot.reply(message, 'OK! I will update my dossier...');

                            controller.storage.users.get(message.user, function(err, user) {
                                if (!user) {
                                    user = {
                                        id: message.user,
                                    };
                                }
                                user.name = convo.extractResponse('nickname');
                                controller.storage.users.save(user, function(err, id) {
                                    bot.reply(message, 'Got it. I will call you ' + user.name + ' from now on.');
                                });
                            });

                        } else {
                            // this happens if the conversation ended prematurely for some reason
                            bot.reply(message, 'OK, nevermind!');
                        }
                    });
                }
            });
        }
    });
});

controller.hears(['shutdown'], 'message_received', function(bot, message) {

    bot.startConversation(message, function(err, convo) {

        convo.ask('Are you sure you want me to shutdown?', [
            {
                pattern: bot.utterances.yes,
                callback: function(response, convo) {
                    convo.say('Bye!');
                    convo.next();
                    setTimeout(function() {
                        process.exit();
                    }, 3000);
                }
            },
        {
            pattern: bot.utterances.no,
            default: true,
            callback: function(response, convo) {
                convo.say('*Phew!*');
                convo.next();
            }
        }
        ]);
    });
});

controller.hears(['uptime', 'identify yourself', 'who are you', 'what is your name'], 'message_received',
    function(bot, message) {

        var hostname = os.hostname();
        var uptime = formatUptime(process.uptime());

        bot.reply(message,
            ':robot_face: I am a bot named <@' + bot.identity.name +
             '>. I have been running for ' + uptime + ' on ' + hostname + '.');
    });

controller.on('message_received', function(bot, message) {
    bot.reply(message, 'Try: `what is my name` or `structured` or `call me captain`');
    return false;
});

function formatUptime(uptime) {
    var unit = 'second';
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'minute';
    }
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'hour';
    }
    if (uptime != 1) {
        unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
}
<|endoftext|>


<commit_before>const webpackConfig = require('./webpack.conf.js')

module.exports = function(config) {
  config.set({
    browsers: ['PhantomJS'],
    frameworks: ['jasmine'],
    reporters: ['spec'],

    plugins: [
      'karma-webpack',
      'karma-jasmine',
      'karma-sourcemap-loader',
      'karma-phantomjs-launcher',
      'karma-spec-reporter'
    ],

    singleRun: process.env.SINGLE_RUN || false,

    files: [
      'spec/browser/index.js',
      {pattern: 'spec/browser/*-spec.js', watched: false},
      {pattern: 'spec/browser/**/*-spec.js', watched: false}
    ],

    preprocessors: {
      'spec/browser/index.js': ['webpack', 'sourcemap'],
      'spec/browser/*-spec.js': ['webpack', 'sourcemap'],
      'spec/browser/**/*-spec.js': ['webpack', 'sourcemap']
    },

    webpack: webpackConfig,

    webpackMiddleware: {
      stats: 'errors-only'
    }
  })
}
<commit_msg>Remove unused file<commit_after><|endoftext|>