diff --git a/config.py b/config.py
index ba11fc48c..082751508 100644
--- a/config.py
+++ b/config.py
@@ -18,7 +18,7 @@ CLIENT_WHITELIST = ['SERVER_HOSTNAME', 'PREFERRED_URL_SCHEME', 'MIXPANEL_KEY',
'STRIPE_PUBLISHABLE_KEY', 'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN',
'AUTHENTICATION_TYPE', 'REGISTRY_TITLE', 'REGISTRY_TITLE_SHORT',
'CONTACT_INFO', 'AVATAR_KIND', 'LOCAL_OAUTH_HANDLER', 'DOCUMENTATION_LOCATION',
- 'DOCUMENTATION_METADATA', 'SETUP_COMPLETE']
+ 'DOCUMENTATION_METADATA', 'SETUP_COMPLETE', 'DEBUG']
def frontend_visible_config(config_dict):
diff --git a/external_libraries.py b/external_libraries.py
index 45d7f7059..984d2ce80 100644
--- a/external_libraries.py
+++ b/external_libraries.py
@@ -7,10 +7,11 @@ LOCAL_DIRECTORY = '/static/ldn/'
EXTERNAL_JS = [
'code.jquery.com/jquery.js',
'netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js',
- 'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js',
- 'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.min.js',
- 'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-sanitize.min.js',
- 'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-animate.min.js',
+ 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js',
+ 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-route.min.js',
+ 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-sanitize.min.js',
+ 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-animate.min.js',
+ 'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-cookies.min.js',
'cdn.jsdelivr.net/g/momentjs',
'cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.2.0/js/bootstrap-datepicker.min.js',
'cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js',
diff --git a/static/css/directives/ui/avatar.css b/static/css/directives/ui/avatar.css
index 3bcdd9f6b..1e260142d 100644
--- a/static/css/directives/ui/avatar.css
+++ b/static/css/directives/ui/avatar.css
@@ -4,7 +4,6 @@
color: white !important;
text-align: center;
position: relative;
- background: white;
overflow: hidden;
}
@@ -16,7 +15,6 @@
position: absolute;
top: 0px;
left: 0px;
- background: white;
}
.avatar-element .letter {
diff --git a/static/directives/avatar.html b/static/directives/avatar.html
index 5e8c90e7f..9b3fb794d 100644
--- a/static/directives/avatar.html
+++ b/static/directives/avatar.html
@@ -1,11 +1,13 @@
-
-
+ ng-visible="showGravatar"
+ ng-image-watch="imageCallback(result)"
+ ng-style="{'width': imageSize + 'px', 'height': imageSize + 'px'}"
+ crossorigin="anonymous">
+
{{ data.name.charAt(0).toUpperCase() }}
Ω
diff --git a/static/directives/config/config-setup-tool.html b/static/directives/config/config-setup-tool.html
index ca9aef263..2017bbced 100644
--- a/static/directives/config/config-setup-tool.html
+++ b/static/directives/config/config-setup-tool.html
@@ -105,7 +105,7 @@
diff --git a/static/directives/user-setup.html b/static/directives/user-setup.html
index d0e57f187..5dd6276ae 100644
--- a/static/directives/user-setup.html
+++ b/static/directives/user-setup.html
@@ -1,7 +1,7 @@
-
diff --git a/static/js/app.js b/static/js/app.js
index dd1f4727f..1f55d5b2f 100644
--- a/static/js/app.js
+++ b/static/js/app.js
@@ -36,7 +36,7 @@ quayPages.constant('pages', {
});
quayDependencies = ['ngRoute', 'chieffancypants.loadingBar', 'cfp.hotkeys', 'angular-tour', 'restangular', 'angularMoment',
- 'mgcrea.ngStrap', 'ngCookies', 'ngSanitize', 'angular-md5', 'pasvaz.bindonce', 'ansiToHtml', 'debounce',
+ 'mgcrea.ngStrap', 'ngCookies', 'ngSanitize', 'angular-md5', 'pasvaz.bindonce', 'ansiToHtml',
'core-ui', 'core-config-setup', 'quayPages', 'infinite-scroll'];
if (window.__config && window.__config.MIXPANEL_KEY) {
@@ -72,6 +72,12 @@ quayApp.config(['$tooltipProvider', function ($tooltipProvider) {
};
}]);
+quayApp.config(['$compileProvider', function ($compileProvider) {
+ if (!window.__config['DEBUG']) {
+ $compileProvider.debugInfoEnabled(false);
+ }
+}]);
+
// Configure the routes.
quayApp.config(['$routeProvider', '$locationProvider', 'pages', function($routeProvider, $locationProvider, pages) {
$locationProvider.html5Mode(true);
diff --git a/static/js/core-config-setup.js b/static/js/core-config-setup.js
index fc28de4e3..cf7f9941c 100644
--- a/static/js/core-config-setup.js
+++ b/static/js/core-config-setup.js
@@ -1133,12 +1133,19 @@ angular.module("core-config-setup", ['angularFileUpload'])
controller: function($scope, $element) {
var firstSet = true;
+ $scope.patternMap = {};
+
$scope.getRegexp = function(pattern) {
- if (!pattern) {
- pattern = '.*';
- }
- return new RegExp(pattern);
- };
+ if (!pattern) {
+ pattern = '.*';
+ }
+
+ if ($scope.patternMap[pattern]) {
+ return $scope.patternMap[pattern];
+ }
+
+ return $scope.patternMap[pattern] = new RegExp(pattern);
+ };
$scope.$watch('binding', function(binding) {
if (firstSet && !binding && $scope.defaultValue) {
diff --git a/static/js/directives/ui/avatar.js b/static/js/directives/ui/avatar.js
index 80a74f8d5..3e65388e9 100644
--- a/static/js/directives/ui/avatar.js
+++ b/static/js/directives/ui/avatar.js
@@ -16,20 +16,38 @@ angular.module('quay').directive('avatar', function () {
$scope.AvatarService = AvatarService;
$scope.Config = Config;
$scope.isLoading = true;
- $scope.hasGravatar = false;
+ $scope.showGravatar = false;
$scope.loadGravatar = false;
- $scope.imageCallback = function(r) {
- $timeout(function() {
- $scope.isLoading = false;
- $scope.hasGravatar = r;
- }, 1);
+ $scope.imageCallback = function(result) {
+ $scope.isLoading = false;
+
+ if (!result) {
+ $scope.showGravatar = false;
+ return;
+ }
+
+ // Determine whether the gravatar is blank.
+ var canvas = document.createElement("canvas");
+ canvas.width = 512;
+ canvas.height = 512;
+
+ var ctx = canvas.getContext("2d");
+ ctx.drawImage($element.find('img')[0], 0, 0);
+
+ var blank = document.createElement("canvas");
+ blank.width = 512;
+ blank.height = 512;
+
+ var isBlank = canvas.toDataURL('text/png') == blank.toDataURL('text/png');
+ $scope.showGravatar = !isBlank;
};
$scope.$watch('size', function(size) {
size = size * 1 || 16;
$scope.fontSize = (size - 4) + 'px';
$scope.lineHeight = size + 'px';
+ $scope.imageSize = size;
});
$scope.$watch('data', function(data) {
diff --git a/static/js/directives/ui/header-bar.js b/static/js/directives/ui/header-bar.js
index 8b88d886f..f4d1ee5c0 100644
--- a/static/js/directives/ui/header-bar.js
+++ b/static/js/directives/ui/header-bar.js
@@ -147,18 +147,6 @@ angular.module('quay').directive('headerBar', function () {
});
};
- $scope.appLinkTarget = function() {
- if ($scope._appLinkTarget) {
- return $scope._appLinkTarget;
- }
-
- if ($("div[ng-view]").length === 0) {
- return $scope._appLinkTarget = "_self";
- }
-
- return $scope._appLinkTarget = "";
- };
-
$scope.getEnterpriseLogo = function() {
return Config.getEnterpriseLogo(false);
};
diff --git a/static/js/directives/ui/popup-input-button.js b/static/js/directives/ui/popup-input-button.js
index 688fd2203..fce011cc2 100644
--- a/static/js/directives/ui/popup-input-button.js
+++ b/static/js/directives/ui/popup-input-button.js
@@ -14,6 +14,8 @@ angular.module('quay').directive('popupInputButton', function () {
'submitted': '&submitted'
},
controller: function($scope, $element) {
+ $scope.patternMap = {};
+
$scope.popupShown = function() {
setTimeout(function() {
var box = $('#input-box');
@@ -26,7 +28,12 @@ angular.module('quay').directive('popupInputButton', function () {
if (!pattern) {
pattern = '.*';
}
- return new RegExp(pattern);
+
+ if ($scope.patternMap[pattern]) {
+ return $scope.patternMap[pattern];
+ }
+
+ return $scope.patternMap[pattern] = new RegExp(pattern);
};
$scope.inputSubmit = function() {
diff --git a/static/js/directives/ui/signin-form.js b/static/js/directives/ui/signin-form.js
index 1d0bc4d4e..6f8c0695d 100644
--- a/static/js/directives/ui/signin-form.js
+++ b/static/js/directives/ui/signin-form.js
@@ -77,7 +77,12 @@ angular.module('quay').directive('signinForm', function () {
if (redirectUrl == $location.path() || redirectUrl == null) {
return;
}
- window.location = (redirectUrl ? redirectUrl : '/');
+
+ if (redirectUrl) {
+ window.location = redirectUrl
+ } else {
+ $location.path('/');
+ }
}, 500);
}, function(result) {
$scope.signingIn = false;
diff --git a/static/js/pages/landing.js b/static/js/pages/landing.js
index 9595b38d7..08b37ee9f 100644
--- a/static/js/pages/landing.js
+++ b/static/js/pages/landing.js
@@ -21,7 +21,7 @@
UserService.updateUserIn($scope, function(user) {
if (!user.anonymous) {
- $location.path('/repository');
+ $location.path('/repository/');
}
});
diff --git a/static/js/services/cookie-service.js b/static/js/services/cookie-service.js
index 186f933a9..208888b5d 100644
--- a/static/js/services/cookie-service.js
+++ b/static/js/services/cookie-service.js
@@ -1,22 +1,22 @@
/**
* Helper service for working with cookies.
*/
-angular.module('quay').factory('CookieService', ['$cookies', '$cookieStore', function($cookies, $cookieStore) {
+angular.module('quay').factory('CookieService', ['$cookies', function($cookies) {
var cookieService = {};
cookieService.putPermanent = function(name, value) {
document.cookie = escape(name) + "=" + escape(value) + "; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";
};
cookieService.putSession = function(name, value) {
- $cookies[name] = value;
+ $cookies.put(name, value);
};
cookieService.clear = function(name) {
- $cookies[name] = '';
+ $cookies.remove(name);
};
cookieService.get = function(name) {
- return $cookies[name];
+ return $cookies.get(name);
};
return cookieService;
diff --git a/static/lib/angular-cookies.min.js b/static/lib/angular-cookies.min.js
deleted file mode 100644
index 6807b369a..000000000
--- a/static/lib/angular-cookies.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- AngularJS v1.2.0-ed8640b
- (c) 2010-2012 Google, Inc. http://angularjs.org
- License: MIT
-*/
-(function(p,f,n){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,b){var c={},g={},h,k=!1,l=f.copy,m=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,l(a,g),l(a,c),k&&d.$apply())})();k=!0;d.$watch(function(){var a,e,d;for(a in g)m(c[a])&&b.cookies(a,n);for(a in c)(e=c[a],f.isString(e))?e!==g[a]&&(b.cookies(a,e),d=!0):f.isDefined(g[a])?c[a]=g[a]:delete c[a];if(d)for(a in e=b.cookies(),c)c[a]!==e[a]&&(m(e[a])?delete c[a]:c[a]=e[a])});
-return c}]).factory("$cookieStore",["$cookies",function(d){return{get:function(b){return(b=d[b])?f.fromJson(b):b},put:function(b,c){d[b]=f.toJson(c)},remove:function(b){delete d[b]}}}])})(window,window.angular);
\ No newline at end of file
diff --git a/static/lib/angular-debounce.js b/static/lib/angular-debounce.js
deleted file mode 100644
index 9a0dfe99e..000000000
--- a/static/lib/angular-debounce.js
+++ /dev/null
@@ -1,66 +0,0 @@
-'use strict';
-
-angular.module('debounce', [])
- .service('debounce', ['$timeout', function ($timeout) {
- return function (func, wait, immediate) {
- var timeout, args, context, result;
- function debounce() {
- /* jshint validthis:true */
- context = this;
- args = arguments;
- var later = function () {
- timeout = null;
- if (!immediate) {
- result = func.apply(context, args);
- }
- };
- var callNow = immediate && !timeout;
- if (timeout) {
- $timeout.cancel(timeout);
- }
- timeout = $timeout(later, wait);
- if (callNow) {
- result = func.apply(context, args);
- }
- return result;
- }
- debounce.cancel = function () {
- $timeout.cancel(timeout);
- timeout = null;
- };
- return debounce;
- };
- }])
- .directive('debounce', ['debounce', '$parse', function (debounce, $parse) {
- return {
- require: 'ngModel',
- priority: 999,
- link: function ($scope, $element, $attrs, ngModelController) {
- var debounceDuration = $parse($attrs.debounce)($scope);
- var immediate = !!$parse($attrs.immediate)($scope);
- var debouncedValue, pass;
- var prevRender = ngModelController.$render.bind(ngModelController);
- var commitSoon = debounce(function (viewValue) {
- pass = true;
- ngModelController.$setViewValue(viewValue);
- pass = false;
- }, parseInt(debounceDuration, 10), immediate);
- ngModelController.$render = function () {
- prevRender();
- commitSoon.cancel();
- //we must be first parser for this to work properly,
- //so we have priority 999 so that we unshift into parsers last
- debouncedValue = this.$viewValue;
- };
- ngModelController.$parsers.unshift(function (value) {
- if (pass) {
- debouncedValue = value;
- return value;
- } else {
- commitSoon(ngModelController.$viewValue);
- return debouncedValue;
- }
- });
- }
- };
- }]);
|