commit
d596a6d5b2
19 changed files with 91 additions and 133 deletions
|
@ -18,7 +18,7 @@ CLIENT_WHITELIST = ['SERVER_HOSTNAME', 'PREFERRED_URL_SCHEME', 'MIXPANEL_KEY',
|
||||||
'STRIPE_PUBLISHABLE_KEY', 'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN',
|
'STRIPE_PUBLISHABLE_KEY', 'ENTERPRISE_LOGO_URL', 'SENTRY_PUBLIC_DSN',
|
||||||
'AUTHENTICATION_TYPE', 'REGISTRY_TITLE', 'REGISTRY_TITLE_SHORT',
|
'AUTHENTICATION_TYPE', 'REGISTRY_TITLE', 'REGISTRY_TITLE_SHORT',
|
||||||
'CONTACT_INFO', 'AVATAR_KIND', 'LOCAL_OAUTH_HANDLER', 'DOCUMENTATION_LOCATION',
|
'CONTACT_INFO', 'AVATAR_KIND', 'LOCAL_OAUTH_HANDLER', 'DOCUMENTATION_LOCATION',
|
||||||
'DOCUMENTATION_METADATA', 'SETUP_COMPLETE']
|
'DOCUMENTATION_METADATA', 'SETUP_COMPLETE', 'DEBUG']
|
||||||
|
|
||||||
|
|
||||||
def frontend_visible_config(config_dict):
|
def frontend_visible_config(config_dict):
|
||||||
|
|
|
@ -7,10 +7,11 @@ LOCAL_DIRECTORY = '/static/ldn/'
|
||||||
EXTERNAL_JS = [
|
EXTERNAL_JS = [
|
||||||
'code.jquery.com/jquery.js',
|
'code.jquery.com/jquery.js',
|
||||||
'netdna.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.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.5.3/angular.min.js',
|
||||||
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-route.min.js',
|
'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-route.min.js',
|
||||||
'ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular-sanitize.min.js',
|
'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/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-animate.min.js',
|
||||||
|
'ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular-cookies.min.js',
|
||||||
'cdn.jsdelivr.net/g/momentjs',
|
'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-datepicker/1.2.0/js/bootstrap-datepicker.min.js',
|
||||||
'cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js',
|
'cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js',
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
color: white !important;
|
color: white !important;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
background: white;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
background: white;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar-element .letter {
|
.avatar-element .letter {
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
<span class="avatar-element"
|
<span class="avatar-element"
|
||||||
ng-style="{'width': size, 'height': size, 'backgroundColor': data.color, 'fontSize': fontSize, 'lineHeight': lineHeight}"
|
ng-style="{'width': size, 'height': size, 'backgroundColor': (showGravatar || isLoading) ? 'transparent' : data.color, 'fontSize': fontSize, 'lineHeight': lineHeight}"
|
||||||
ng-class="data.kind">
|
ng-class="data.kind">
|
||||||
<img ng-src="//www.gravatar.com/avatar/{{ data.hash }}?d=404&size={{ size }}"
|
<img ng-src="//www.gravatar.com/avatar/{{ data.hash }}?d=blank&size=512"
|
||||||
ng-if="loadGravatar"
|
ng-if="loadGravatar"
|
||||||
ng-show="hasGravatar"
|
ng-visible="showGravatar"
|
||||||
ng-image-watch="imageCallback(result)">
|
ng-image-watch="imageCallback(result)"
|
||||||
<span class="default-avatar" ng-if="!isLoading && !hasGravatar">
|
ng-style="{'width': imageSize + 'px', 'height': imageSize + 'px'}"
|
||||||
|
crossorigin="anonymous">
|
||||||
|
<span class="default-avatar" ng-if="!isLoading && !showGravatar">
|
||||||
<span class="letter" ng-if="data.kind != 'team' || data.name != 'owners'">{{ data.name.charAt(0).toUpperCase() }}</span>
|
<span class="letter" ng-if="data.kind != 'team' || data.name != 'owners'">{{ data.name.charAt(0).toUpperCase() }}</span>
|
||||||
<span class="letter" ng-if="data.kind == 'team' && data.name == 'owners'">Ω</span>
|
<span class="letter" ng-if="data.kind == 'team' && data.name == 'owners'">Ω</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
<td>
|
<td>
|
||||||
<div class="co-checkbox">
|
<div class="co-checkbox">
|
||||||
<input id="enable-ssl" type="checkbox" ng-model="config.PREFERRED_URL_SCHEME"
|
<input id="enable-ssl" type="checkbox" ng-model="config.PREFERRED_URL_SCHEME"
|
||||||
ng-true-value="https" ng-false-value="http">
|
ng-true-value="'https'" ng-false-value="'http'">
|
||||||
<label for="enable-ssl">Enable SSL</label>
|
<label for="enable-ssl">Enable SSL</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="help-text" style="margin-bottom: 10px">
|
<div class="help-text" style="margin-bottom: 10px">
|
||||||
|
@ -322,7 +322,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>Authentication Key:</td>
|
<td>Authentication Key:</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="config-service-key-field" service-name="{{ config.SECURITY_SCANNER_ISSUER_NAME }}"></span>
|
<span class="config-service-key-field" service-name="{{ config.SECURITY_SCANNER_ISSUER_NAME || 'secscan' }}"></span>
|
||||||
<div class="help-text">
|
<div class="help-text">
|
||||||
The security scanning service requires an authorized service key to speak to Quay. Once setup, the key
|
The security scanning service requires an authorized service key to speak to Quay. Once setup, the key
|
||||||
can be managed in the Service Keys panel under the Super User Admin Panel.
|
can be managed in the Service Keys panel under the Super User Admin Panel.
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<ng-transclude>
|
<span></span>
|
|
@ -6,7 +6,7 @@
|
||||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
|
||||||
≡
|
≡
|
||||||
</button>
|
</button>
|
||||||
<a class="navbar-brand" ng-href="{{ user.anonymous ? '/' : '/repository/' }}" target="{{ appLinkTarget() }}">
|
<a class="navbar-brand" ng-href="{{ user.anonymous ? '/' : '/repository/' }}">
|
||||||
<span id="quay-logo" ng-style="{'background-image': 'url(' + getEnterpriseLogo() + ')'}"
|
<span id="quay-logo" ng-style="{'background-image': 'url(' + getEnterpriseLogo() + ')'}"
|
||||||
ng-class="Config.ENTERPRISE_LOGO_URL ? 'enterprise-logo' : 'hosted-logo'"></span>
|
ng-class="Config.ENTERPRISE_LOGO_URL ? 'enterprise-logo' : 'hosted-logo'"></span>
|
||||||
</a>
|
</a>
|
||||||
|
@ -21,17 +21,17 @@
|
||||||
<div class="collapse navbar-collapse navbar-ex1-collapse">
|
<div class="collapse navbar-collapse navbar-ex1-collapse">
|
||||||
<!-- Not signed in -->
|
<!-- Not signed in -->
|
||||||
<ul class="nav navbar-nav navbar-links" ng-if="user.anonymous">
|
<ul class="nav navbar-nav navbar-links" ng-if="user.anonymous">
|
||||||
<li><a ng-href="/tour/" target="{{ appLinkTarget() }}" quay-section="tour">Tour</a></li>
|
<li><a ng-href="/tour/" quay-section="tour">Tour</a></li>
|
||||||
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li>
|
<li><a ng-href="/tutorial/" quay-section="tutorial">Tutorial</a></li>
|
||||||
<li quay-require="['BILLING']"><a ng-href="/plans/" target="{{ appLinkTarget() }}" quay-section="plans">Pricing</a></li>
|
<li quay-require="['BILLING']"><a ng-href="/plans/" quay-section="plans">Pricing</a></li>
|
||||||
<li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li>
|
<li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li>
|
||||||
<li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li>
|
<li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Signed in -->
|
<!-- Signed in -->
|
||||||
<ul class="nav navbar-nav navbar-links" ng-if="!user.anonymous">
|
<ul class="nav navbar-nav navbar-links" ng-if="!user.anonymous">
|
||||||
<li><a ng-href="/repository/" target="{{ appLinkTarget() }}" quay-section="repository">Repositories</a></li>
|
<li><a ng-href="/repository/" quay-section="repository">Repositories</a></li>
|
||||||
<li><a ng-href="/tutorial/" target="{{ appLinkTarget() }}" quay-section="tutorial">Tutorial</a></li>
|
<li><a ng-href="/tutorial/" quay-section="tutorial">Tutorial</a></li>
|
||||||
<li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li>
|
<li><a href="https://docs.quay.io/" ng-safenewtab>Docs</a></li>
|
||||||
<li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li>
|
<li><a href="https://blog.quay.io/" ng-safenewtab>Blog</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -39,13 +39,13 @@
|
||||||
<!-- Phone -->
|
<!-- Phone -->
|
||||||
<ul class="nav navbar-nav navbar-right visible-xs" ng-switch on="user.anonymous">
|
<ul class="nav navbar-nav navbar-right visible-xs" ng-switch on="user.anonymous">
|
||||||
<li ng-switch-when="false">
|
<li ng-switch-when="false">
|
||||||
<a href="/user/{{ user.username }}?tab=settings" class="user-view" target="{{ appLinkTarget() }}">
|
<a href="/user/{{ user.username }}?tab=settings" class="user-view">
|
||||||
<span class="avatar" size="32" data="user.avatar"></span>
|
<span class="avatar" size="32" data="user.avatar"></span>
|
||||||
{{ user.username }}
|
{{ user.username }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li ng-switch-default>
|
<li ng-switch-default>
|
||||||
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}" ng-if="!externalSigninUrl">Sign in</a>
|
<a class="user-view" href="/signin/" ng-if="!externalSigninUrl">Sign in</a>
|
||||||
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
|
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -128,7 +128,7 @@
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li>
|
<li>
|
||||||
<a href="/user/{{ user.username }}?tab=settings" target="{{ appLinkTarget() }}">
|
<a href="/user/{{ user.username }}?tab=settings">
|
||||||
Account Settings
|
Account Settings
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -137,7 +137,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li ng-switch-default>
|
<li ng-switch-default>
|
||||||
<a class="user-view" href="/signin/" target="{{ appLinkTarget() }}" ng-if="!externalSigninUrl">Sign in</a>
|
<a class="user-view" href="/signin/" ng-if="!externalSigninUrl">Sign in</a>
|
||||||
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
|
<a class="user-view" ng-href="{{ externalSigninUrl }}" ng-if="externalSigninUrl">Sign in</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -149,7 +149,6 @@
|
||||||
<div class="search-box-wrapper">
|
<div class="search-box-wrapper">
|
||||||
<input id="search-box-input" type="search" placeholder="(Enter Search Terms)"
|
<input id="search-box-input" type="search" placeholder="(Enter Search Terms)"
|
||||||
ng-model-options="{'debounce': 250}" ng-model="currentSearchQuery"
|
ng-model-options="{'debounce': 250}" ng-model="currentSearchQuery"
|
||||||
debounce="250"
|
|
||||||
ng-keydown="handleSearchKeyDown($event)">
|
ng-keydown="handleSearchKeyDown($event)">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<div class="repo-list-table-element">
|
<div class="repo-list-table-element">
|
||||||
<div class="cor-loader" ng-if="isLoading"></div>
|
<div class="cor-loader" ng-if="isLoading"></div>
|
||||||
<div ng-if="orderedRepositories.length == 0 && !isLoading">
|
<div ng-if="orderedRepositories.entries.length == 0 && !isLoading">
|
||||||
<div class="empty-primary-msg" ng-if="namespaces.length != 1">You do not have any viewable repositories.</div>
|
<div class="empty-primary-msg" ng-if="namespaces.length != 1">You do not have any viewable repositories.</div>
|
||||||
<div class="empty-primary-msg" ng-if="namespaces.length == 1">This namespace doesn't have any viewable repositories.</div>
|
<div class="empty-primary-msg" ng-if="namespaces.length == 1">This namespace doesn't have any viewable repositories.</div>
|
||||||
<div class="empty-secondary-msg">Either no repositories exist yet or you may not have permission to view any. If you have permission, try <a href="/new">creating a new repository</a>.</div>
|
<div class="empty-secondary-msg">Either no repositories exist yet or you may not have permission to view any. If you have permission, try <a href="/new">creating a new repository</a>.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="co-table" ng-if="orderedRepositories.length && !isLoading">
|
<table class="co-table" ng-if="orderedRepositories.entries.length && !isLoading">
|
||||||
<thead>
|
<thead>
|
||||||
<td class="hidden-xs"
|
<td class="hidden-xs"
|
||||||
ng-class="tablePredicateClass('full_name', options.predicate, options.reverse)">
|
ng-class="tablePredicateClass('full_name', options.predicate, options.reverse)">
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="user-setup-element">
|
<div class="user-setup-element">
|
||||||
<div class="user-setup-element-view">
|
<div class="user-setup-element-view">
|
||||||
<div class="setup-logo-container" ng-show="hideLogo != 'true'">
|
<div class="setup-logo-container" ng-show="hideLogo != 'true'">
|
||||||
<img src="{{ Config.getEnterpriseLogo(true) }}">
|
<img ng-src="{{ Config.getEnterpriseLogo(true) }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="user-setup-content">
|
<div class="user-setup-content">
|
||||||
|
|
|
@ -36,7 +36,7 @@ quayPages.constant('pages', {
|
||||||
});
|
});
|
||||||
|
|
||||||
quayDependencies = ['ngRoute', 'chieffancypants.loadingBar', 'cfp.hotkeys', 'angular-tour', 'restangular', 'angularMoment',
|
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'];
|
'core-ui', 'core-config-setup', 'quayPages', 'infinite-scroll'];
|
||||||
|
|
||||||
if (window.__config && window.__config.MIXPANEL_KEY) {
|
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.
|
// Configure the routes.
|
||||||
quayApp.config(['$routeProvider', '$locationProvider', 'pages', function($routeProvider, $locationProvider, pages) {
|
quayApp.config(['$routeProvider', '$locationProvider', 'pages', function($routeProvider, $locationProvider, pages) {
|
||||||
$locationProvider.html5Mode(true);
|
$locationProvider.html5Mode(true);
|
||||||
|
|
|
@ -1133,12 +1133,19 @@ angular.module("core-config-setup", ['angularFileUpload'])
|
||||||
controller: function($scope, $element) {
|
controller: function($scope, $element) {
|
||||||
var firstSet = true;
|
var firstSet = true;
|
||||||
|
|
||||||
|
$scope.patternMap = {};
|
||||||
|
|
||||||
$scope.getRegexp = function(pattern) {
|
$scope.getRegexp = function(pattern) {
|
||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
pattern = '.*';
|
pattern = '.*';
|
||||||
}
|
}
|
||||||
return new RegExp(pattern);
|
|
||||||
};
|
if ($scope.patternMap[pattern]) {
|
||||||
|
return $scope.patternMap[pattern];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $scope.patternMap[pattern] = new RegExp(pattern);
|
||||||
|
};
|
||||||
|
|
||||||
$scope.$watch('binding', function(binding) {
|
$scope.$watch('binding', function(binding) {
|
||||||
if (firstSet && !binding && $scope.defaultValue) {
|
if (firstSet && !binding && $scope.defaultValue) {
|
||||||
|
|
|
@ -16,20 +16,38 @@ angular.module('quay').directive('avatar', function () {
|
||||||
$scope.AvatarService = AvatarService;
|
$scope.AvatarService = AvatarService;
|
||||||
$scope.Config = Config;
|
$scope.Config = Config;
|
||||||
$scope.isLoading = true;
|
$scope.isLoading = true;
|
||||||
$scope.hasGravatar = false;
|
$scope.showGravatar = false;
|
||||||
$scope.loadGravatar = false;
|
$scope.loadGravatar = false;
|
||||||
|
|
||||||
$scope.imageCallback = function(r) {
|
$scope.imageCallback = function(result) {
|
||||||
$timeout(function() {
|
$scope.isLoading = false;
|
||||||
$scope.isLoading = false;
|
|
||||||
$scope.hasGravatar = r;
|
if (!result) {
|
||||||
}, 1);
|
$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) {
|
$scope.$watch('size', function(size) {
|
||||||
size = size * 1 || 16;
|
size = size * 1 || 16;
|
||||||
$scope.fontSize = (size - 4) + 'px';
|
$scope.fontSize = (size - 4) + 'px';
|
||||||
$scope.lineHeight = size + 'px';
|
$scope.lineHeight = size + 'px';
|
||||||
|
$scope.imageSize = size;
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$watch('data', function(data) {
|
$scope.$watch('data', function(data) {
|
||||||
|
|
|
@ -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() {
|
$scope.getEnterpriseLogo = function() {
|
||||||
return Config.getEnterpriseLogo(false);
|
return Config.getEnterpriseLogo(false);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,8 @@ angular.module('quay').directive('popupInputButton', function () {
|
||||||
'submitted': '&submitted'
|
'submitted': '&submitted'
|
||||||
},
|
},
|
||||||
controller: function($scope, $element) {
|
controller: function($scope, $element) {
|
||||||
|
$scope.patternMap = {};
|
||||||
|
|
||||||
$scope.popupShown = function() {
|
$scope.popupShown = function() {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
var box = $('#input-box');
|
var box = $('#input-box');
|
||||||
|
@ -26,7 +28,12 @@ angular.module('quay').directive('popupInputButton', function () {
|
||||||
if (!pattern) {
|
if (!pattern) {
|
||||||
pattern = '.*';
|
pattern = '.*';
|
||||||
}
|
}
|
||||||
return new RegExp(pattern);
|
|
||||||
|
if ($scope.patternMap[pattern]) {
|
||||||
|
return $scope.patternMap[pattern];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $scope.patternMap[pattern] = new RegExp(pattern);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.inputSubmit = function() {
|
$scope.inputSubmit = function() {
|
||||||
|
|
|
@ -77,7 +77,12 @@ angular.module('quay').directive('signinForm', function () {
|
||||||
if (redirectUrl == $location.path() || redirectUrl == null) {
|
if (redirectUrl == $location.path() || redirectUrl == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.location = (redirectUrl ? redirectUrl : '/');
|
|
||||||
|
if (redirectUrl) {
|
||||||
|
window.location = redirectUrl
|
||||||
|
} else {
|
||||||
|
$location.path('/');
|
||||||
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}, function(result) {
|
}, function(result) {
|
||||||
$scope.signingIn = false;
|
$scope.signingIn = false;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
UserService.updateUserIn($scope, function(user) {
|
UserService.updateUserIn($scope, function(user) {
|
||||||
if (!user.anonymous) {
|
if (!user.anonymous) {
|
||||||
$location.path('/repository');
|
$location.path('/repository/');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
/**
|
/**
|
||||||
* Helper service for working with cookies.
|
* 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 = {};
|
var cookieService = {};
|
||||||
cookieService.putPermanent = function(name, value) {
|
cookieService.putPermanent = function(name, value) {
|
||||||
document.cookie = escape(name) + "=" + escape(value) + "; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";
|
document.cookie = escape(name) + "=" + escape(value) + "; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";
|
||||||
};
|
};
|
||||||
|
|
||||||
cookieService.putSession = function(name, value) {
|
cookieService.putSession = function(name, value) {
|
||||||
$cookies[name] = value;
|
$cookies.put(name, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
cookieService.clear = function(name) {
|
cookieService.clear = function(name) {
|
||||||
$cookies[name] = '';
|
$cookies.remove(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
cookieService.get = function(name) {
|
cookieService.get = function(name) {
|
||||||
return $cookies[name];
|
return $cookies.get(name);
|
||||||
};
|
};
|
||||||
|
|
||||||
return cookieService;
|
return cookieService;
|
||||||
|
|
7
static/lib/angular-cookies.min.js
vendored
7
static/lib/angular-cookies.min.js
vendored
|
@ -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);
|
|
66
static/lib/angular-debounce.js
vendored
66
static/lib/angular-debounce.js
vendored
|
@ -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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}]);
|
|
Reference in a new issue