2013-12-10 06:38:05 +00:00
var TEAM _PATTERN = '^[a-zA-Z][a-zA-Z0-9]+$' ;
var ROBOT _PATTERN = '^[a-zA-Z][a-zA-Z0-9]+$' ;
2013-12-26 22:45:16 +00:00
function getRestUrl ( args ) {
var url = '' ;
for ( var i = 0 ; i < arguments . length ; ++ i ) {
if ( i > 0 ) {
url += '/' ;
}
url += encodeURI ( arguments [ i ] )
}
return url ;
}
2014-01-10 01:17:28 +00:00
function clickElement ( el ) {
// From: http://stackoverflow.com/questions/16802795/click-not-working-in-mocha-phantomjs-on-certain-elements
var ev = document . createEvent ( "MouseEvent" ) ;
ev . initMouseEvent (
"click" ,
true /* bubble */ , true /* cancelable */ ,
window , null ,
0 , 0 , 0 , 0 , /* coordinates */
false , false , false , false , /* modifier keys */
0 /*left*/ , null ) ;
el . dispatchEvent ( ev ) ;
}
2013-12-26 22:45:16 +00:00
2013-11-05 00:36:56 +00:00
function getFirstTextLine ( commentString ) {
if ( ! commentString ) { return '' ; }
var lines = commentString . split ( '\n' ) ;
var MARKDOWN _CHARS = {
'#' : true ,
'-' : true ,
'>' : true ,
'`' : true
} ;
for ( var i = 0 ; i < lines . length ; ++ i ) {
// Skip code lines.
if ( lines [ i ] . indexOf ( ' ' ) == 0 ) {
continue ;
}
// Skip empty lines.
if ( $ . trim ( lines [ i ] ) . length == 0 ) {
continue ;
}
// Skip control lines.
if ( MARKDOWN _CHARS [ $ . trim ( lines [ i ] ) [ 0 ] ] ) {
continue ;
}
return getMarkedDown ( lines [ i ] ) ;
}
return '' ;
}
2013-12-26 22:45:16 +00:00
function createRobotAccount ( ApiService , is _org , orgname , name , callback ) {
ApiService . createRobot ( is _org ? orgname : null , null , { 'robot_shortname' : name } ) . then ( callback , function ( resp ) {
2013-12-10 06:38:05 +00:00
bootbox . dialog ( {
"message" : resp . data ? resp . data : 'The robot account could not be created' ,
"title" : "Cannot create robot account" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
} ) ;
}
2013-12-26 22:45:16 +00:00
function createOrganizationTeam ( ApiService , orgname , teamname , callback ) {
2013-12-10 06:38:05 +00:00
var data = {
'name' : teamname ,
'role' : 'member'
} ;
2013-12-26 22:45:16 +00:00
var params = {
'orgname' : orgname ,
'teamname' : teamname
} ;
2013-12-10 06:38:05 +00:00
2013-12-26 22:45:16 +00:00
ApiService . updateOrganizationTeam ( data , params ) . then ( callback , function ( ) {
2013-12-10 06:38:05 +00:00
bootbox . dialog ( {
"message" : resp . data ? resp . data : 'The team could not be created' ,
"title" : "Cannot create team" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
} ) ;
}
2013-11-05 00:36:56 +00:00
function getMarkedDown ( string ) {
return Markdown . getSanitizingConverter ( ) . makeHtml ( string || '' ) ;
}
2014-02-25 01:36:54 +00:00
quayApp = angular . module ( 'quay' , [ 'ngRoute' , 'chieffancypants.loadingBar' , 'angular-tour' , 'restangular' , 'angularMoment' , 'angulartics' , /*'angulartics.google.analytics',*/ 'angulartics.mixpanel' , '$strap.directives' , 'ngCookies' , 'ngSanitize' , 'angular-md5' , 'pasvaz.bindonce' , 'ansiToHtml' , 'ngAnimate' ] , function ( $provide , cfpLoadingBarProvider ) {
2013-12-17 18:19:59 +00:00
cfpLoadingBarProvider . includeSpinner = false ;
2013-12-26 22:45:16 +00:00
2014-01-14 21:01:37 +00:00
$provide . factory ( 'UtilService' , [ '$sanitize' , function ( $sanitize ) {
var utilService = { } ;
utilService . textToSafeHtml = function ( text ) {
var adjusted = text . replace ( /&/g , "&" )
. replace ( /</g , "<" )
. replace ( />/g , ">" )
. replace ( /"/g , """ )
. replace ( /'/g , "'" ) ;
return $sanitize ( adjusted ) ;
} ;
return utilService ;
} ] ) ;
$provide . factory ( 'ImageMetadataService' , [ 'UtilService' , function ( UtilService ) {
var metadataService = { } ;
metadataService . getFormattedCommand = function ( image ) {
if ( ! image || ! image . command || ! image . command . length ) {
return '' ;
}
var getCommandStr = function ( command ) {
// Handle /bin/sh commands specially.
if ( command . length > 2 && command [ 0 ] == '/bin/sh' && command [ 1 ] == '-c' ) {
return command [ 2 ] ;
}
return command . join ( ' ' ) ;
} ;
return getCommandStr ( image . command ) ;
} ;
metadataService . getEscapedFormattedCommand = function ( image ) {
return UtilService . textToSafeHtml ( metadataService . getFormattedCommand ( image ) ) ;
} ;
return metadataService ;
} ] ) ;
2013-12-26 22:45:16 +00:00
$provide . factory ( 'ApiService' , [ 'Restangular' , function ( Restangular ) {
var apiService = { } ;
2014-02-11 03:43:48 +00:00
var getResource = function ( path , opt _background ) {
2013-12-26 22:45:16 +00:00
var resource = { } ;
resource . url = path ;
resource . withOptions = function ( options ) {
this . options = options ;
return this ;
} ;
resource . get = function ( processor , opt _errorHandler ) {
var options = this . options ;
var performer = Restangular . one ( this . url ) ;
var result = {
'loading' : true ,
'value' : null ,
'hasError' : false
} ;
2014-02-11 03:43:48 +00:00
if ( opt _background ) {
performer . withHttpConfig ( {
'ignoreLoadingBar' : true
} ) ;
}
2013-12-26 22:45:16 +00:00
performer . get ( options ) . then ( function ( resp ) {
result . value = processor ( resp ) ;
result . loading = false ;
} , function ( resp ) {
result . hasError = true ;
result . loading = false ;
if ( opt _errorHandler ) {
opt _errorHandler ( resp ) ;
}
} ) ;
return result ;
} ;
return resource ;
} ;
var formatMethodName = function ( endpointName ) {
var formatted = '' ;
for ( var i = 0 ; i < endpointName . length ; ++ i ) {
var c = endpointName [ i ] ;
if ( c == '_' ) {
c = endpointName [ i + 1 ] . toUpperCase ( ) ;
i ++ ;
}
formatted += c ;
}
return formatted ;
} ;
var buildUrl = function ( path , parameters ) {
// We already have /api/ on the URLs, so remove them from the paths.
path = path . substr ( '/api/' . length , path . length ) ;
var url = '' ;
for ( var i = 0 ; i < path . length ; ++ i ) {
var c = path [ i ] ;
if ( c == '<' ) {
var end = path . indexOf ( '>' , i ) ;
var varName = path . substr ( i + 1 , end - i - 1 ) ;
var colon = varName . indexOf ( ':' ) ;
var isPathVar = false ;
if ( colon > 0 ) {
isPathVar = true ;
varName = varName . substr ( colon + 1 ) ;
}
if ( ! parameters [ varName ] ) {
throw new Error ( 'Missing parameter: ' + varName ) ;
}
url += isPathVar ? parameters [ varName ] : encodeURI ( parameters [ varName ] ) ;
i = end ;
continue ;
}
url += c ;
}
return url ;
} ;
var getGenericMethodName = function ( userMethodName ) {
return formatMethodName ( userMethodName . replace ( '_user' , '' ) ) ;
} ;
var buildMethodsForEndpoint = function ( endpoint ) {
var method = endpoint . methods [ 0 ] . toLowerCase ( ) ;
var methodName = formatMethodName ( endpoint [ 'name' ] ) ;
2014-02-11 03:43:48 +00:00
apiService [ methodName ] = function ( opt _options , opt _parameters , opt _background ) {
var one = Restangular . one ( buildUrl ( endpoint [ 'path' ] , opt _parameters ) ) ;
if ( opt _background ) {
one . withHttpConfig ( {
'ignoreLoadingBar' : true
} ) ;
}
return one [ 'custom' + method . toUpperCase ( ) ] ( opt _options ) ;
2013-12-26 22:45:16 +00:00
} ;
if ( method == 'get' ) {
2014-02-11 03:43:48 +00:00
apiService [ methodName + 'AsResource' ] = function ( opt _parameters , opt _background ) {
return getResource ( buildUrl ( endpoint [ 'path' ] , opt _parameters ) , opt _background ) ;
2013-12-26 22:45:16 +00:00
} ;
}
if ( endpoint [ 'user_method' ] ) {
2014-02-11 03:43:48 +00:00
apiService [ getGenericMethodName ( endpoint [ 'user_method' ] ) ] = function ( orgname , opt _options , opt _parameters , opt _background ) {
2013-12-26 22:45:16 +00:00
if ( orgname ) {
if ( orgname . name ) {
orgname = orgname . name ;
}
2014-02-11 03:43:48 +00:00
var params = jQuery . extend ( { 'orgname' : orgname } , opt _parameters || { } , opt _background ) ;
2013-12-26 22:45:16 +00:00
return apiService [ methodName ] ( opt _options , params ) ;
} else {
2014-02-11 03:43:48 +00:00
return apiService [ formatMethodName ( endpoint [ 'user_method' ] ) ] ( opt _options , opt _parameters , opt _background ) ;
2013-12-26 22:45:16 +00:00
}
} ;
}
} ;
// Construct the methods for each API endpoint.
if ( ! window . _ _endpoints ) {
return apiService ;
}
for ( var i = 0 ; i < window . _ _endpoints . length ; ++ i ) {
var endpoint = window . _ _endpoints [ i ] ;
buildMethodsForEndpoint ( endpoint ) ;
}
return apiService ;
} ] ) ;
2013-12-18 22:26:56 +00:00
2013-12-17 20:03:34 +00:00
$provide . factory ( 'CookieService' , [ '$cookies' , '$cookieStore' , function ( $cookies , $cookieStore ) {
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 ;
} ;
cookieService . clear = function ( name ) {
$cookies [ name ] = '' ;
} ;
cookieService . get = function ( name ) {
return $cookies [ name ] ;
} ;
return cookieService ;
} ] ) ;
2013-12-26 22:45:16 +00:00
$provide . factory ( 'UserService' , [ 'ApiService' , 'CookieService' , function ( ApiService , CookieService ) {
2013-09-26 23:59:58 +00:00
var userResponse = {
verified : false ,
anonymous : true ,
username : null ,
2013-10-10 17:44:34 +00:00
email : null ,
askForPassword : false ,
2014-01-14 20:23:44 +00:00
organizations : [ ] ,
logins : [ ]
2013-09-26 23:59:58 +00:00
}
var userService = { }
2013-12-11 23:27:35 +00:00
userService . hasEverLoggedIn = function ( ) {
2013-12-17 20:03:34 +00:00
return CookieService . get ( 'quay.loggedin' ) == 'true' ;
2013-12-11 23:27:35 +00:00
} ;
2013-12-17 18:19:59 +00:00
userService . updateUserIn = function ( scope , opt _callback ) {
scope . $watch ( function ( ) { return userService . currentUser ( ) ; } , function ( currentUser ) {
scope . user = currentUser ;
if ( opt _callback ) {
opt _callback ( currentUser ) ;
}
} , true ) ;
2013-12-11 23:27:35 +00:00
} ;
2013-11-12 00:26:56 +00:00
userService . load = function ( opt _callback ) {
2013-12-26 22:45:16 +00:00
ApiService . getLoggedInUser ( ) . then ( function ( loadedUser ) {
2013-09-26 23:59:58 +00:00
userResponse = loadedUser ;
2013-10-03 19:46:22 +00:00
2013-10-03 20:16:10 +00:00
if ( ! userResponse . anonymous ) {
mixpanel . identify ( userResponse . username ) ;
mixpanel . people . set ( {
'$email' : userResponse . email ,
'$username' : userResponse . username ,
'verified' : userResponse . verified
} ) ;
2013-10-10 20:34:59 +00:00
mixpanel . people . set _once ( {
'$created' : new Date ( )
} )
2013-12-11 23:27:35 +00:00
2014-01-10 19:29:18 +00:00
if ( window . olark !== undefined ) {
olark ( 'api.visitor.getDetails' , function ( details ) {
if ( details . fullName === null ) {
olark ( 'api.visitor.updateFullName' , { fullName : userResponse . username } ) ;
}
} ) ;
olark ( 'api.visitor.updateEmailAddress' , { emailAddress : userResponse . email } ) ;
olark ( 'api.chat.updateVisitorStatus' , { snippet : 'username: ' + userResponse . username } ) ;
}
2013-12-17 20:03:34 +00:00
CookieService . putPermanent ( 'quay.loggedin' , 'true' ) ;
2013-10-03 20:16:10 +00:00
}
2013-11-12 00:26:56 +00:00
if ( opt _callback ) {
opt _callback ( ) ;
}
2013-09-26 23:59:58 +00:00
} ) ;
} ;
2013-11-08 22:50:42 +00:00
userService . getOrganization = function ( name ) {
if ( ! userResponse || ! userResponse . organizations ) { return null ; }
for ( var i = 0 ; i < userResponse . organizations . length ; ++ i ) {
var org = userResponse . organizations [ i ] ;
if ( org . name == name ) {
return org ;
}
}
2013-11-01 23:13:58 +00:00
2013-11-08 22:50:42 +00:00
return null ;
2013-11-01 23:13:58 +00:00
} ;
2013-12-10 20:22:22 +00:00
userService . isNamespaceAdmin = function ( namespace ) {
if ( namespace == userResponse . username ) {
return true ;
}
var org = userService . getOrganization ( namespace ) ;
if ( ! org ) {
return false ;
}
return org . is _org _admin ;
} ;
2014-01-31 18:52:35 +00:00
userService . isKnownNamespace = function ( namespace ) {
if ( namespace == userResponse . username ) {
return true ;
}
var org = userService . getOrganization ( namespace ) ;
return ! ! org ;
} ;
2013-12-10 20:22:22 +00:00
2013-09-26 23:59:58 +00:00
userService . currentUser = function ( ) {
return userResponse ;
2013-11-08 22:50:42 +00:00
} ;
2013-09-26 23:59:58 +00:00
// Load the user the first time.
userService . load ( ) ;
return userService ;
2013-10-04 18:35:51 +00:00
} ] ) ;
2013-10-08 17:57:48 +00:00
$provide . factory ( 'KeyService' , [ '$location' , function ( $location ) {
var keyService = { }
if ( $location . host ( ) === 'quay.io' ) {
keyService [ 'stripePublishableKey' ] = 'pk_live_P5wLU0vGdHnZGyKnXlFG4oiu' ;
2013-10-10 18:42:14 +00:00
keyService [ 'githubClientId' ] = '5a8c08b06c48d89d4d1e' ;
2014-01-14 20:23:44 +00:00
keyService [ 'githubRedirectUri' ] = 'https://quay.io/oauth2/github/callback' ;
2013-10-08 17:57:48 +00:00
} else {
keyService [ 'stripePublishableKey' ] = 'pk_test_uEDHANKm9CHCvVa2DLcipGRh' ;
2013-10-10 18:42:14 +00:00
keyService [ 'githubClientId' ] = 'cfbc4aca88e5c1b40679' ;
2014-01-14 20:23:44 +00:00
keyService [ 'githubRedirectUri' ] = 'http://localhost:5000/oauth2/github/callback' ;
2013-10-08 17:57:48 +00:00
}
return keyService ;
} ] ) ;
2013-12-26 22:45:16 +00:00
$provide . factory ( 'PlanService' , [ 'KeyService' , 'UserService' , 'CookieService' , 'ApiService' ,
function ( KeyService , UserService , CookieService , ApiService ) {
2013-11-01 23:13:58 +00:00
var plans = null ;
2013-10-04 18:35:51 +00:00
var planDict = { } ;
2013-11-15 23:17:12 +00:00
var planService = { } ;
var listeners = [ ] ;
2013-10-04 18:35:51 +00:00
2014-02-03 23:18:33 +00:00
var previousSubscribeFailure = false ;
2013-12-20 02:51:46 +00:00
planService . getFreePlan = function ( ) {
return 'free' ;
} ;
2013-11-15 23:17:12 +00:00
planService . registerListener = function ( obj , callback ) {
listeners . push ( { 'obj' : obj , 'callback' : callback } ) ;
} ;
planService . unregisterListener = function ( obj ) {
for ( var i = 0 ; i < listeners . length ; ++ i ) {
if ( listeners [ i ] . obj == obj ) {
listeners . splice ( i , 1 ) ;
break ;
}
}
} ;
2013-12-11 22:50:48 +00:00
planService . notePlan = function ( planId ) {
2013-12-17 20:03:34 +00:00
CookieService . putSession ( 'quay.notedplan' , planId ) ;
2013-12-11 22:50:48 +00:00
} ;
2013-12-20 02:51:46 +00:00
planService . isOrgCompatible = function ( plan ) {
return plan [ 'stripeId' ] == planService . getFreePlan ( ) || plan [ 'bus_features' ] ;
} ;
planService . getMatchingBusinessPlan = function ( callback ) {
planService . getPlans ( function ( ) {
planService . getSubscription ( null , function ( sub ) {
var plan = planDict [ sub . plan ] ;
if ( ! plan ) {
planService . getMinimumPlan ( 0 , true , callback ) ;
return ;
}
var count = Math . max ( sub . usedPrivateRepos , plan . privateRepos ) ;
planService . getMinimumPlan ( count , true , callback ) ;
} , function ( ) {
planService . getMinimumPlan ( 0 , true , callback ) ;
} ) ;
} ) ;
2013-12-11 22:50:48 +00:00
} ;
planService . handleNotedPlan = function ( ) {
var planId = planService . getAndResetNotedPlan ( ) ;
if ( ! planId ) { return ; }
2013-12-11 23:20:24 +00:00
UserService . load ( function ( ) {
if ( UserService . currentUser ( ) . anonymous ) {
return ;
2013-12-11 22:50:48 +00:00
}
2013-12-18 23:16:32 +00:00
planService . getPlan ( planId , function ( plan ) {
2013-12-20 02:51:46 +00:00
if ( planService . isOrgCompatible ( plan ) ) {
2013-12-11 23:20:24 +00:00
document . location = '/organizations/new/?plan=' + planId ;
} else {
document . location = '/user?plan=' + planId ;
}
} ) ;
2013-12-11 22:50:48 +00:00
} ) ;
} ;
planService . getAndResetNotedPlan = function ( ) {
2013-12-17 20:03:34 +00:00
var planId = CookieService . get ( 'quay.notedplan' ) ;
CookieService . clear ( 'quay.notedplan' ) ;
2013-12-11 22:50:48 +00:00
return planId ;
} ;
2013-11-19 22:06:17 +00:00
planService . handleCardError = function ( resp ) {
if ( ! planService . isCardError ( resp ) ) { return ; }
bootbox . dialog ( {
"message" : resp . data . carderror ,
"title" : "Credit card issue" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
} ;
planService . isCardError = function ( resp ) {
return resp && resp . data && resp . data . carderror ;
} ;
2013-11-01 23:13:58 +00:00
planService . verifyLoaded = function ( callback ) {
if ( plans ) {
callback ( plans ) ;
return ;
}
2013-12-26 22:45:16 +00:00
ApiService . listPlans ( ) . then ( function ( data ) {
2013-11-05 19:40:45 +00:00
var i = 0 ;
2013-12-20 02:51:46 +00:00
for ( i = 0 ; i < data . plans . length ; i ++ ) {
planDict [ data . plans [ i ] . stripeId ] = data . plans [ i ] ;
2013-11-05 19:40:45 +00:00
}
2013-12-20 02:51:46 +00:00
plans = data . plans ;
2013-11-01 23:13:58 +00:00
callback ( plans ) ;
} , function ( ) { callback ( [ ] ) ; } ) ;
} ;
2013-12-20 02:51:46 +00:00
planService . getPlans = function ( callback , opt _includePersonal ) {
2013-12-11 22:50:48 +00:00
planService . verifyLoaded ( function ( ) {
2013-12-20 02:51:46 +00:00
var filtered = [ ] ;
for ( var i = 0 ; i < plans . length ; ++ i ) {
var plan = plans [ i ] ;
if ( plan [ 'deprecated' ] ) { continue ; }
if ( ! opt _includePersonal && ! planService . isOrgCompatible ( plan ) ) { continue ; }
filtered . push ( plan ) ;
2013-12-11 22:50:48 +00:00
}
2013-12-20 02:51:46 +00:00
callback ( filtered ) ;
2013-12-11 22:50:48 +00:00
} ) ;
} ;
2013-12-20 02:51:46 +00:00
planService . getPlan = function ( planId , callback ) {
planService . getPlanIncludingDeprecated ( planId , function ( plan ) {
if ( ! plan [ 'deprecated' ] ) {
callback ( plan ) ;
}
} ) ;
2013-10-28 21:08:26 +00:00
} ;
2013-10-04 18:35:51 +00:00
2013-12-20 02:51:46 +00:00
planService . getPlanIncludingDeprecated = function ( planId , callback ) {
2013-11-01 23:13:58 +00:00
planService . verifyLoaded ( function ( ) {
2013-12-20 02:51:46 +00:00
if ( planDict [ planId ] ) {
2013-11-06 23:14:22 +00:00
callback ( planDict [ planId ] ) ;
}
2013-11-01 23:13:58 +00:00
} ) ;
2013-10-28 21:08:26 +00:00
} ;
2013-11-05 19:40:45 +00:00
planService . getMinimumPlan = function ( privateCount , isBusiness , callback ) {
2013-12-21 03:41:00 +00:00
planService . getPlans ( function ( plans ) {
2013-12-20 02:51:46 +00:00
for ( var i = 0 ; i < plans . length ; i ++ ) {
var plan = plans [ i ] ;
if ( isBusiness && ! planService . isOrgCompatible ( plan ) ) {
continue ;
}
2013-11-05 19:40:45 +00:00
2013-11-01 23:13:58 +00:00
if ( plan . privateRepos >= privateCount ) {
callback ( plan ) ;
return ;
}
2013-10-28 21:08:26 +00:00
}
2013-11-01 23:13:58 +00:00
callback ( null ) ;
} ) ;
2013-10-28 21:08:26 +00:00
} ;
2013-11-15 23:17:12 +00:00
planService . getSubscription = function ( orgname , success , failure ) {
2013-12-26 22:45:16 +00:00
ApiService . getSubscription ( orgname ) . then ( success , failure ) ;
2013-11-06 22:30:20 +00:00
} ;
planService . setSubscription = function ( orgname , planId , success , failure , opt _token ) {
var subscriptionDetails = {
plan : planId
} ;
2013-10-28 21:08:26 +00:00
2013-11-06 22:30:20 +00:00
if ( opt _token ) {
subscriptionDetails [ 'token' ] = opt _token . id ;
}
2013-12-26 22:45:16 +00:00
ApiService . updateSubscription ( orgname , subscriptionDetails ) . then ( function ( resp ) {
2013-11-15 23:17:12 +00:00
success ( resp ) ;
planService . getPlan ( planId , function ( plan ) {
for ( var i = 0 ; i < listeners . length ; ++ i ) {
listeners [ i ] [ 'callback' ] ( plan ) ;
}
} ) ;
} , failure ) ;
2013-11-06 22:30:20 +00:00
} ;
2013-11-15 23:58:47 +00:00
planService . getCardInfo = function ( orgname , callback ) {
2013-12-26 22:45:16 +00:00
ApiService . getCard ( orgname ) . then ( function ( resp ) {
2013-11-15 23:58:47 +00:00
callback ( resp . card ) ;
} , function ( ) {
callback ( { 'is_valid' : false } ) ;
} ) ;
} ;
planService . changePlan = function ( $scope , orgname , planId , callbacks ) {
2013-11-09 01:32:56 +00:00
if ( callbacks [ 'started' ] ) {
2013-11-15 23:58:47 +00:00
callbacks [ 'started' ] ( ) ;
2013-11-09 01:32:56 +00:00
}
2013-11-15 23:58:47 +00:00
planService . getPlan ( planId , function ( plan ) {
2013-12-20 02:51:46 +00:00
if ( orgname && ! planService . isOrgCompatible ( plan ) ) { return ; }
2013-11-15 23:58:47 +00:00
planService . getCardInfo ( orgname , function ( cardInfo ) {
2014-02-03 23:18:33 +00:00
if ( plan . price > 0 && ( previousSubscribeFailure || ! cardInfo . last4 ) ) {
2013-11-15 23:58:47 +00:00
planService . showSubscribeDialog ( $scope , orgname , planId , callbacks ) ;
return ;
}
2014-02-03 23:18:33 +00:00
previousSubscribeFailure = false ;
2013-11-19 22:06:17 +00:00
planService . setSubscription ( orgname , planId , callbacks [ 'success' ] , function ( resp ) {
2014-02-03 23:18:33 +00:00
previousSubscribeFailure = true ;
2013-11-19 22:06:17 +00:00
planService . handleCardError ( resp ) ;
callbacks [ 'failure' ] ( resp ) ;
} ) ;
2013-11-15 23:58:47 +00:00
} ) ;
} ) ;
2013-11-06 22:30:20 +00:00
} ;
2013-11-15 23:17:12 +00:00
planService . changeCreditCard = function ( $scope , orgname , callbacks ) {
if ( callbacks [ 'opening' ] ) {
callbacks [ 'opening' ] ( ) ;
}
2013-11-19 22:06:17 +00:00
var submitted = false ;
2013-11-15 23:17:12 +00:00
var submitToken = function ( token ) {
2013-11-19 22:06:17 +00:00
if ( submitted ) { return ; }
submitted = true ;
2013-11-15 23:17:12 +00:00
$scope . $apply ( function ( ) {
if ( callbacks [ 'started' ] ) {
callbacks [ 'started' ] ( ) ;
}
var cardInfo = {
'token' : token . id
} ;
2013-12-26 22:45:16 +00:00
ApiService . setCard ( orgname , cardInfo ) . then ( callbacks [ 'success' ] , function ( resp ) {
planService . handleCardError ( resp ) ;
callbacks [ 'failure' ] ( resp ) ;
} ) ;
2013-11-15 23:17:12 +00:00
} ) ;
} ;
var email = planService . getEmail ( orgname ) ;
StripeCheckout . open ( {
key : KeyService . stripePublishableKey ,
address : false ,
email : email ,
currency : 'usd' ,
name : 'Update credit card' ,
description : 'Enter your credit card number' ,
panelLabel : 'Update' ,
token : submitToken ,
image : 'static/img/quay-icon-stripe.png' ,
opened : function ( ) { $scope . $apply ( function ( ) { callbacks [ 'opened' ] ( ) } ) ; } ,
closed : function ( ) { $scope . $apply ( function ( ) { callbacks [ 'closed' ] ( ) } ) ; }
} ) ;
} ;
planService . getEmail = function ( orgname ) {
var email = null ;
if ( UserService . currentUser ( ) ) {
email = UserService . currentUser ( ) . email ;
if ( orgname ) {
org = UserService . getOrganization ( orgname ) ;
if ( org ) {
emaiil = org . email ;
}
}
}
return email ;
} ;
2013-11-09 01:32:56 +00:00
planService . showSubscribeDialog = function ( $scope , orgname , planId , callbacks ) {
if ( callbacks [ 'opening' ] ) {
callbacks [ 'opening' ] ( ) ;
}
2013-11-19 22:06:17 +00:00
var submitted = false ;
2013-11-06 22:30:20 +00:00
var submitToken = function ( token ) {
2013-11-19 22:06:17 +00:00
if ( submitted ) { return ; }
submitted = true ;
2013-11-06 22:30:20 +00:00
mixpanel . track ( 'plan_subscribe' ) ;
2013-10-28 21:08:26 +00:00
$scope . $apply ( function ( ) {
2013-11-09 01:32:56 +00:00
if ( callbacks [ 'started' ] ) {
callbacks [ 'started' ] ( ) ;
}
2013-11-15 20:31:05 +00:00
planService . setSubscription ( orgname , planId , callbacks [ 'success' ] , callbacks [ 'failure' ] , token ) ;
2013-10-28 21:08:26 +00:00
} ) ;
} ;
2013-11-01 23:13:58 +00:00
planService . getPlan ( planId , function ( planDetails ) {
2013-11-15 23:17:12 +00:00
var email = planService . getEmail ( orgname ) ;
2013-11-01 23:13:58 +00:00
StripeCheckout . open ( {
key : KeyService . stripePublishableKey ,
address : false ,
2013-11-08 22:50:42 +00:00
email : email ,
2013-11-01 23:13:58 +00:00
amount : planDetails . price ,
currency : 'usd' ,
name : 'Quay ' + planDetails . title + ' Subscription' ,
description : 'Up to ' + planDetails . privateRepos + ' private repositories' ,
panelLabel : 'Subscribe' ,
2013-11-06 19:55:40 +00:00
token : submitToken ,
2013-11-09 01:32:56 +00:00
image : 'static/img/quay-icon-stripe.png' ,
opened : function ( ) { $scope . $apply ( function ( ) { callbacks [ 'opened' ] ( ) } ) ; } ,
closed : function ( ) { $scope . $apply ( function ( ) { callbacks [ 'closed' ] ( ) } ) ; }
2013-11-01 23:13:58 +00:00
} ) ;
2013-10-28 21:08:26 +00:00
} ) ;
} ;
2013-10-04 18:35:51 +00:00
return planService ;
} ] ) ;
2013-09-26 23:59:58 +00:00
} ) .
2013-10-01 23:37:33 +00:00
directive ( 'match' , function ( $parse ) {
return {
require : 'ngModel' ,
link : function ( scope , elem , attrs , ctrl ) {
scope . $watch ( function ( ) {
return $parse ( attrs . match ) ( scope ) === ctrl . $modelValue ;
} , function ( currentValue ) {
ctrl . $setValidity ( 'mismatch' , currentValue ) ;
} ) ;
}
} ;
} ) .
2013-10-17 18:29:47 +00:00
directive ( 'onresize' , function ( $window , $parse ) {
return function ( scope , element , attr ) {
var fn = $parse ( attr . onresize ) ;
var notifyResized = function ( ) {
scope . $apply ( function ( ) {
fn ( scope ) ;
} ) ;
} ;
angular . element ( $window ) . on ( 'resize' , null , notifyResized ) ;
scope . $on ( '$destroy' , function ( ) {
angular . element ( $window ) . off ( 'resize' , null , notifyResized ) ;
} ) ;
} ;
} ) .
2013-10-03 19:46:22 +00:00
config ( [ '$routeProvider' , '$locationProvider' , '$analyticsProvider' ,
function ( $routeProvider , $locationProvider , $analyticsProvider ) {
2013-10-03 20:16:10 +00:00
$analyticsProvider . virtualPageviews ( true ) ;
2013-10-10 23:06:04 +00:00
$locationProvider . html5Mode ( true ) ;
2013-10-14 02:06:31 +00:00
// WARNING WARNING WARNING
// If you add a route here, you must add a corresponding route in thr endpoints/web.py
// index rule to make sure that deep links directly deep into the app continue to work.
// WARNING WARNING WARNING
2013-10-03 20:16:10 +00:00
$routeProvider .
2013-11-20 21:17:47 +00:00
when ( '/repository/:namespace/:name' , { templateUrl : '/static/partials/view-repo.html' , controller : RepoCtrl ,
2013-12-18 03:56:28 +00:00
fixFooter : false , reloadOnSearch : false } ) .
2013-11-20 21:17:47 +00:00
when ( '/repository/:namespace/:name/tag/:tag' , { templateUrl : '/static/partials/view-repo.html' , controller : RepoCtrl ,
2013-12-18 03:56:28 +00:00
fixFooter : false } ) .
2013-12-17 18:19:59 +00:00
when ( '/repository/:namespace/:name/image/:image' , { templateUrl : '/static/partials/image-view.html' , controller : ImageViewCtrl , reloadOnSearch : false } ) .
when ( '/repository/:namespace/:name/admin' , { templateUrl : '/static/partials/repo-admin.html' , controller : RepoAdminCtrl , reloadOnSearch : false } ) .
2014-02-10 20:15:23 +00:00
when ( '/repository/:namespace/:name/build' , { templateUrl : '/static/partials/repo-build.html' , controller : RepoBuildCtrl , reloadOnSearch : false } ) .
2014-02-17 22:28:20 +00:00
when ( '/repository/:namespace/:name/build/:buildid/buildpack' , { templateUrl : '/static/partials/build-package.html' , controller : BuildPackageCtrl , reloadOnSearch : false } ) .
2013-11-19 00:03:35 +00:00
when ( '/repository/' , { title : 'Repositories' , description : 'Public and private docker repositories list' ,
templateUrl : '/static/partials/repo-list.html' , controller : RepoListCtrl } ) .
2013-12-10 04:33:28 +00:00
when ( '/user/' , { title : 'Account Settings' , description : 'Account settings for Quay.io' , templateUrl : '/static/partials/user-admin.html' ,
reloadOnSearch : false , controller : UserAdminCtrl } ) .
when ( '/guide/' , { title : 'Guide' , description : 'Guide to using private docker repositories on Quay.io' , templateUrl : '/static/partials/guide.html' ,
controller : GuideCtrl } ) .
2014-02-06 02:00:04 +00:00
when ( '/tutorial/' , { title : 'Tutorial' , description : 'Interactive tutorial for using Quay.io' , templateUrl : '/static/partials/tutorial.html' ,
controller : TutorialCtrl } ) .
2013-12-17 22:02:37 +00:00
when ( '/contact/' , { title : 'Contact Us' , description : 'Different ways for you to get a hold of us when you need us most.' , templateUrl : '/static/partials/contact.html' ,
controller : ContactCtrl } ) .
2014-02-07 00:20:19 +00:00
when ( '/about/' , { title : 'About Us' , description : 'Information about the Quay.io team and the company.' , templateUrl : '/static/partials/about.html' } ) .
2013-11-22 20:54:23 +00:00
when ( '/plans/' , { title : 'Plans and Pricing' , description : 'Plans and pricing for private docker repositories on Quay.io' ,
2013-11-19 00:03:35 +00:00
templateUrl : '/static/partials/plans.html' , controller : PlansCtrl } ) .
2013-11-22 20:54:23 +00:00
when ( '/security/' , { title : 'Security' , description : 'Security features used when transmitting and storing data' ,
2014-02-07 00:20:19 +00:00
templateUrl : '/static/partials/security.html' } ) .
when ( '/signin/' , { title : 'Sign In' , description : 'Sign into Quay.io' , templateUrl : '/static/partials/signin.html' } ) .
2013-11-19 00:03:35 +00:00
when ( '/new/' , { title : 'Create new repository' , description : 'Create a new public or private docker repository, optionally constructing from a dockerfile' ,
templateUrl : '/static/partials/new-repo.html' , controller : NewRepoCtrl } ) .
when ( '/organizations/' , { title : 'Organizations' , description : 'Private docker repository hosting for businesses and organizations' ,
templateUrl : '/static/partials/organizations.html' , controller : OrgsCtrl } ) .
2013-11-22 20:54:23 +00:00
when ( '/organizations/new/' , { title : 'New Organization' , description : 'Create a new organization on Quay.io' ,
2013-11-19 00:03:35 +00:00
templateUrl : '/static/partials/new-organization.html' , controller : NewOrgCtrl } ) .
2013-10-31 22:17:26 +00:00
when ( '/organization/:orgname' , { templateUrl : '/static/partials/org-view.html' , controller : OrgViewCtrl } ) .
2013-12-10 04:33:28 +00:00
when ( '/organization/:orgname/admin' , { templateUrl : '/static/partials/org-admin.html' , controller : OrgAdminCtrl , reloadOnSearch : false } ) .
2013-10-31 22:17:26 +00:00
when ( '/organization/:orgname/teams/:teamname' , { templateUrl : '/static/partials/team-view.html' , controller : TeamViewCtrl } ) .
2013-12-07 00:25:27 +00:00
when ( '/organization/:orgname/logs/:membername' , { templateUrl : '/static/partials/org-member-logs.html' , controller : OrgMemberLogsCtrl } ) .
2013-10-17 21:45:08 +00:00
when ( '/v1/' , { title : 'Activation information' , templateUrl : '/static/partials/v1-page.html' , controller : V1Ctrl } ) .
2013-10-09 22:33:25 +00:00
when ( '/' , { title : 'Hosted Private Docker Registry' , templateUrl : '/static/partials/landing.html' , controller : LandingCtrl } ) .
2013-10-03 20:16:10 +00:00
otherwise ( { redirectTo : '/' } ) ;
} ] ) .
2013-09-24 22:21:14 +00:00
config ( function ( RestangularProvider ) {
RestangularProvider . setBaseUrl ( '/api/' ) ;
2013-09-26 21:59:20 +00:00
} ) ;
2013-11-05 00:36:56 +00:00
2013-11-26 19:37:55 +00:00
quayApp . directive ( 'entityReference' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/entity-reference.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
2014-01-21 21:23:00 +00:00
'entity' : '=entity' ,
'namespace' : '=namespace'
2013-11-26 19:37:55 +00:00
} ,
2013-12-10 20:22:22 +00:00
controller : function ( $scope , $element , UserService ) {
2014-01-21 21:23:00 +00:00
$scope . getIsAdmin = function ( namespace ) {
return UserService . isNamespaceAdmin ( namespace ) ;
2013-12-10 20:22:22 +00:00
} ;
2013-11-26 19:37:55 +00:00
$scope . getPrefix = function ( name ) {
if ( ! name ) { return '' ; }
var plus = name . indexOf ( '+' ) ;
return name . substr ( 0 , plus + 1 ) ;
} ;
$scope . getShortenedName = function ( name ) {
if ( ! name ) { return '' ; }
var plus = name . indexOf ( '+' ) ;
return name . substr ( plus + 1 ) ;
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-05 00:36:56 +00:00
quayApp . directive ( 'markdownView' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/markdown-view.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'content' : '=content' ,
'firstLineOnly' : '=firstLineOnly'
} ,
2013-11-19 00:03:35 +00:00
controller : function ( $scope , $element , $sce ) {
2013-11-05 00:36:56 +00:00
$scope . getMarkedDown = function ( content , firstLineOnly ) {
if ( firstLineOnly ) {
content = getFirstTextLine ( content ) ;
}
2013-11-19 00:03:35 +00:00
return $sce . trustAsHtml ( getMarkedDown ( content ) ) ;
2013-11-05 00:36:56 +00:00
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-01-31 18:52:35 +00:00
quayApp . directive ( 'repoBreadcrumb' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/repo-breadcrumb.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'repo' : '=repo' ,
2014-02-13 23:58:28 +00:00
'image' : '=image' ,
'subsection' : '=subsection' ,
'subsectionIcon' : '=subsectionIcon'
2014-01-31 18:52:35 +00:00
} ,
2014-01-31 19:00:42 +00:00
controller : function ( $scope , $element ) {
2014-01-31 18:52:35 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-10-22 05:26:14 +00:00
quayApp . directive ( 'repoCircle' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/repo-circle.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'repo' : '=repo'
} ,
controller : function ( $scope , $element ) {
2013-10-26 20:03:11 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-12-11 23:20:24 +00:00
quayApp . directive ( 'userSetup' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/user-setup.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'redirectUrl' : '=redirectUrl' ,
'signInStarted' : '&signInStarted' ,
'signedIn' : '&signedIn'
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $location , $timeout , ApiService , KeyService , UserService ) {
2013-12-11 23:20:24 +00:00
$scope . sendRecovery = function ( ) {
2013-12-26 22:45:16 +00:00
ApiService . requestRecoveryEmail ( $scope . recovery ) . then ( function ( ) {
2014-01-10 18:30:17 +00:00
$scope . invalidRecovery = false ;
$scope . errorMessage = '' ;
2013-12-11 23:20:24 +00:00
$scope . sent = true ;
} , function ( result ) {
2014-01-10 18:30:17 +00:00
$scope . invalidRecovery = true ;
$scope . errorMessage = result . data ;
2013-12-11 23:20:24 +00:00
$scope . sent = false ;
} ) ;
} ;
2013-12-11 23:27:35 +00:00
$scope . hasSignedIn = function ( ) {
return UserService . hasEverLoggedIn ( ) ;
} ;
2013-12-11 23:20:24 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-07 20:19:52 +00:00
quayApp . directive ( 'signinForm' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/signin-form.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
2013-12-11 22:50:48 +00:00
'redirectUrl' : '=redirectUrl' ,
'signInStarted' : '&signInStarted' ,
'signedIn' : '&signedIn'
2013-11-07 20:19:52 +00:00
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $location , $timeout , ApiService , KeyService , UserService ) {
2013-12-11 22:50:48 +00:00
$scope . showGithub = function ( ) {
$scope . markStarted ( ) ;
2013-11-07 20:19:52 +00:00
2013-12-11 22:50:48 +00:00
var mixpanelDistinctIdClause = '' ;
2013-11-07 20:19:52 +00:00
if ( mixpanel . get _distinct _id !== undefined ) {
2013-12-11 22:50:48 +00:00
$scope . mixpanelDistinctIdClause = "&state=" + encodeURIComponent ( mixpanel . get _distinct _id ( ) ) ;
2013-11-07 20:19:52 +00:00
}
2013-12-11 22:50:48 +00:00
// Needed to ensure that UI work done by the started callback is finished before the location
// changes.
$timeout ( function ( ) {
var url = 'https://github.com/login/oauth/authorize?client_id=' + encodeURIComponent ( KeyService . githubClientId ) +
'&scope=user:email' + mixpanelDistinctIdClause ;
document . location = url ;
} , 250 ) ;
2013-11-07 20:19:52 +00:00
} ;
2013-12-11 22:50:48 +00:00
$scope . markStarted = function ( ) {
if ( $scope . signInStarted != null ) {
$scope . signInStarted ( ) ;
}
} ;
2013-11-07 20:19:52 +00:00
$scope . signin = function ( ) {
2013-12-11 22:50:48 +00:00
$scope . markStarted ( ) ;
2013-12-26 22:45:16 +00:00
ApiService . signinUser ( $scope . user ) . then ( function ( ) {
2013-11-07 20:19:52 +00:00
$scope . needsEmailVerification = false ;
$scope . invalidCredentials = false ;
2013-12-11 22:50:48 +00:00
if ( $scope . signedIn != null ) {
$scope . signedIn ( ) ;
}
2013-11-07 20:19:52 +00:00
UserService . load ( ) ;
2013-12-11 22:50:48 +00:00
// Redirect to the specified page or the landing page
// Note: The timeout of 500ms is needed to ensure dialogs containing sign in
// forms get removed before the location changes.
$timeout ( function ( ) {
if ( $scope . redirectUrl == $location . path ( ) ) {
return ;
}
$location . path ( $scope . redirectUrl ? $scope . redirectUrl : '/' ) ;
} , 500 ) ;
2013-11-07 20:19:52 +00:00
} , function ( result ) {
$scope . needsEmailVerification = result . data . needsEmailVerification ;
$scope . invalidCredentials = result . data . invalidCredentials ;
} ) ;
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-12-11 21:50:10 +00:00
quayApp . directive ( 'signupForm' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/signup-form.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $location , $timeout , ApiService , KeyService , UserService ) {
2013-12-11 21:50:10 +00:00
$ ( '.form-signup' ) . popover ( ) ;
angulartics . waitForVendorApi ( mixpanel , 500 , function ( loadedMixpanel ) {
var mixpanelId = loadedMixpanel . get _distinct _id ( ) ;
$scope . github _state _clause = '&state=' + mixpanelId ;
} ) ;
$scope . githubClientId = KeyService . githubClientId ;
$scope . awaitingConfirmation = false ;
$scope . registering = false ;
$scope . register = function ( ) {
$ ( '.form-signup' ) . popover ( 'hide' ) ;
$scope . registering = true ;
2013-12-26 22:45:16 +00:00
ApiService . createNewUser ( $scope . newUser ) . then ( function ( ) {
2013-12-11 21:50:10 +00:00
$scope . awaitingConfirmation = true ;
$scope . registering = false ;
mixpanel . alias ( $scope . newUser . username ) ;
} , function ( result ) {
$scope . registering = false ;
$scope . registerError = result . data . message ;
$timeout ( function ( ) {
$ ( '.form-signup' ) . popover ( 'show' ) ;
} ) ;
} ) ;
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-08 03:08:23 +00:00
quayApp . directive ( 'plansTable' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/plans-table.html' ,
replace : false ,
2013-11-23 01:14:44 +00:00
transclude : false ,
2013-11-08 03:08:23 +00:00
restrict : 'C' ,
scope : {
'plans' : '=plans' ,
'currentPlan' : '=currentPlan'
} ,
controller : function ( $scope , $element ) {
$scope . setPlan = function ( plan ) {
$scope . currentPlan = plan ;
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-23 01:14:44 +00:00
quayApp . directive ( 'dockerAuthDialog' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/docker-auth-dialog.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'username' : '=username' ,
'token' : '=token' ,
'shown' : '=shown' ,
'counter' : '=counter'
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element ) {
2013-11-23 01:14:44 +00:00
$scope . isDownloadSupported = function ( ) {
try { return ! ! new Blob ( ) ; } catch ( e ) { }
return false ;
} ;
$scope . downloadCfg = function ( ) {
var auth = $ . base64 . encode ( $scope . username + ":" + $scope . token ) ;
config = {
"https://quay.io/v1/" : {
"auth" : auth ,
"email" : ""
}
} ;
var file = JSON . stringify ( config , null , ' ' ) ;
var blob = new Blob ( [ file ] ) ;
saveAs ( blob , '.dockercfg' ) ;
} ;
var show = function ( r ) {
if ( ! $scope . shown || ! $scope . username || ! $scope . token ) {
$ ( '#dockerauthmodal' ) . modal ( 'hide' ) ;
return ;
}
$ ( '#copyClipboard' ) . clipboardCopy ( ) ;
$ ( '#dockerauthmodal' ) . modal ( { } ) ;
} ;
$scope . $watch ( 'counter' , show ) ;
$scope . $watch ( 'shown' , show ) ;
$scope . $watch ( 'username' , show ) ;
$scope . $watch ( 'token' , show ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-22 23:20:51 +00:00
2014-02-14 23:46:20 +00:00
quayApp . filter ( 'reverse' , function ( ) {
return function ( items ) {
return items . slice ( ) . reverse ( ) ;
} ;
} ) ;
2014-01-03 21:32:00 +00:00
quayApp . filter ( 'bytes' , function ( ) {
return function ( bytes , precision ) {
2014-01-03 21:42:38 +00:00
if ( ! bytes || isNaN ( parseFloat ( bytes ) ) || ! isFinite ( bytes ) ) return 'Unknown' ;
2014-01-03 21:32:00 +00:00
if ( typeof precision === 'undefined' ) precision = 1 ;
var units = [ 'bytes' , 'kB' , 'MB' , 'GB' , 'TB' , 'PB' ] ,
number = Math . floor ( Math . log ( bytes ) / Math . log ( 1024 ) ) ;
return ( bytes / Math . pow ( 1024 , Math . floor ( number ) ) ) . toFixed ( precision ) + ' ' + units [ number ] ;
}
} ) ;
2013-11-27 07:29:31 +00:00
quayApp . filter ( 'visibleLogFilter' , function ( ) {
return function ( logs , allowed ) {
if ( ! allowed ) {
return logs ;
}
var filtered = [ ] ;
angular . forEach ( logs , function ( log ) {
if ( allowed [ log . kind ] ) {
filtered . push ( log ) ;
}
} ) ;
return filtered ;
} ;
} ) ;
2013-12-21 03:38:53 +00:00
quayApp . directive ( 'billingInvoices' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/billing-invoices.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'organization' : '=organization' ,
'user' : '=user' ,
'visible' : '=visible'
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element , $sce , ApiService ) {
2013-12-21 03:38:53 +00:00
$scope . loading = false ;
$scope . invoiceExpanded = { } ;
$scope . toggleInvoice = function ( id ) {
$scope . invoiceExpanded [ id ] = ! $scope . invoiceExpanded [ id ] ;
} ;
var update = function ( ) {
var hasValidUser = ! ! $scope . user ;
var hasValidOrg = ! ! $scope . organization ;
var isValid = hasValidUser || hasValidOrg ;
if ( ! $scope . visible || ! isValid ) {
return ;
}
$scope . loading = true ;
2013-12-26 22:45:16 +00:00
ApiService . listInvoices ( $scope . organization ) . then ( function ( resp ) {
2013-12-21 03:38:53 +00:00
$scope . invoices = resp . invoices ;
$scope . loading = false ;
} ) ;
} ;
$scope . $watch ( 'organization' , update ) ;
$scope . $watch ( 'user' , update ) ;
$scope . $watch ( 'visible' , update ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-27 07:29:31 +00:00
quayApp . directive ( 'logsView' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/logs-view.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'organization' : '=organization' ,
'user' : '=user' ,
2013-12-02 19:55:04 +00:00
'visible' : '=visible' ,
2013-12-07 00:25:27 +00:00
'repository' : '=repository' ,
'performer' : '=performer'
2013-11-27 07:29:31 +00:00
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element , $sce , Restangular , ApiService ) {
2013-11-27 07:29:31 +00:00
$scope . loading = true ;
$scope . logs = null ;
$scope . kindsAllowed = null ;
$scope . chartVisible = true ;
2013-12-06 20:59:59 +00:00
$scope . logsPath = '' ;
2013-11-27 07:29:31 +00:00
2013-12-09 22:28:23 +00:00
var datetime = new Date ( ) ;
$scope . logStartDate = new Date ( datetime . getUTCFullYear ( ) , datetime . getUTCMonth ( ) , datetime . getUTCDate ( ) - 7 ) ;
$scope . logEndDate = new Date ( datetime . getUTCFullYear ( ) , datetime . getUTCMonth ( ) , datetime . getUTCDate ( ) ) ;
2014-01-21 23:39:42 +00:00
var defaultPermSuffix = function ( metadata ) {
if ( metadata . activating _username ) {
return ', when creating user is {activating_username}' ;
}
return '' ;
} ;
2013-11-29 05:04:50 +00:00
var logDescriptions = {
'account_change_plan' : 'Change plan' ,
'account_change_cc' : 'Update credit card' ,
'account_change_password' : 'Change password' ,
'account_convert' : 'Convert account to organization' ,
'create_robot' : 'Create Robot Account: {robot}' ,
'delete_robot' : 'Delete Robot Account: {robot}' ,
'create_repo' : 'Create Repository: {repo}' ,
'push_repo' : 'Push to repository: {repo}' ,
'pull_repo' : function ( metadata ) {
2013-12-02 19:55:04 +00:00
if ( metadata . token ) {
return 'Pull repository {repo} via token {token}' ;
} else if ( metadata . username ) {
return 'Pull repository {repo} by {username}' ;
} else {
return 'Public pull of repository {repo} by {_ip}' ;
}
2013-11-29 05:04:50 +00:00
} ,
'delete_repo' : 'Delete repository: {repo}' ,
2013-12-02 19:55:04 +00:00
'change_repo_permission' : function ( metadata ) {
if ( metadata . username ) {
return 'Change permission for user {username} in repository {repo} to {role}' ;
} else if ( metadata . team ) {
return 'Change permission for team {team} in repository {repo} to {role}' ;
} else if ( metadata . token ) {
return 'Change permission for token {token} in repository {repo} to {role}' ;
}
} ,
'delete_repo_permission' : function ( metadata ) {
if ( metadata . username ) {
return 'Remove permission for user {username} from repository {repo}' ;
} else if ( metadata . team ) {
return 'Remove permission for team {team} from repository {repo}' ;
} else if ( metadata . token ) {
return 'Remove permission for token {token} from repository {repo}' ;
}
} ,
2014-01-21 22:04:00 +00:00
'delete_tag' : 'Tag {tag} deleted in repository {repo} by user {username}' ,
2013-11-29 05:04:50 +00:00
'change_repo_visibility' : 'Change visibility for repository {repo} to {visibility}' ,
'add_repo_accesstoken' : 'Create access token {token} in repository {repo}' ,
'delete_repo_accesstoken' : 'Delete access token {token} in repository {repo}' ,
'add_repo_webhook' : 'Add webhook in repository {repo}' ,
'delete_repo_webhook' : 'Delete webhook in repository {repo}' ,
'set_repo_description' : 'Change description for repository {repo}: {description}' ,
'build_dockerfile' : 'Build image from Dockerfile for repository {repo}' ,
'org_create_team' : 'Create team: {team}' ,
'org_delete_team' : 'Delete team: {team}' ,
'org_add_team_member' : 'Add member {member} to team {team}' ,
'org_remove_team_member' : 'Remove member {member} from team {team}' ,
'org_set_team_description' : 'Change description of team {team}: {description}' ,
2014-01-21 22:04:00 +00:00
'org_set_team_role' : 'Change permission of team {team} to {role}' ,
'create_prototype_permission' : function ( metadata ) {
if ( metadata . delegate _user ) {
2014-01-21 23:39:42 +00:00
return 'Create default permission: {role} for {delegate_user}' + defaultPermSuffix ( metadata ) ;
2014-01-21 22:04:00 +00:00
} else if ( metadata . delegate _team ) {
2014-01-21 23:39:42 +00:00
return 'Create default permission: {role} for {delegate_team}' + defaultPermSuffix ( metadata ) ;
2014-01-21 22:04:00 +00:00
}
} ,
'modify_prototype_permission' : function ( metadata ) {
if ( metadata . delegate _user ) {
2014-01-21 23:39:42 +00:00
return 'Modify default permission: {role} (from {original_role}) for {delegate_user}' + defaultPermSuffix ( metadata ) ;
2014-01-21 22:04:00 +00:00
} else if ( metadata . delegate _team ) {
2014-01-21 23:39:42 +00:00
return 'Modify default permission: {role} (from {original_role}) for {delegate_team}' + defaultPermSuffix ( metadata ) ;
2014-01-21 22:04:00 +00:00
}
} ,
'delete_prototype_permission' : function ( metadata ) {
if ( metadata . delegate _user ) {
2014-01-21 23:39:42 +00:00
return 'Delete default permission: {role} for {delegate_user}' + defaultPermSuffix ( metadata ) ;
2014-01-21 22:04:00 +00:00
} else if ( metadata . delegate _team ) {
2014-01-21 23:39:42 +00:00
return 'Delete default permission: {role} for {delegate_team}' + defaultPermSuffix ( metadata ) ;
2014-01-21 22:04:00 +00:00
}
}
2013-11-29 05:04:50 +00:00
} ;
2013-11-27 07:29:31 +00:00
var logKinds = {
'account_change_plan' : 'Change plan' ,
'account_change_cc' : 'Update credit card' ,
'account_change_password' : 'Change password' ,
'account_convert' : 'Convert account to organization' ,
'create_robot' : 'Create Robot Account' ,
'delete_robot' : 'Delete Robot Account' ,
'create_repo' : 'Create Repository' ,
'push_repo' : 'Push to repository' ,
'pull_repo' : 'Pull repository' ,
'delete_repo' : 'Delete repository' ,
'change_repo_permission' : 'Change repository permission' ,
'delete_repo_permission' : 'Remove user permission from repository' ,
'change_repo_visibility' : 'Change repository visibility' ,
'add_repo_accesstoken' : 'Create access token' ,
'delete_repo_accesstoken' : 'Delete access token' ,
'add_repo_webhook' : 'Add webhook' ,
'delete_repo_webhook' : 'Delete webhook' ,
'set_repo_description' : 'Change repository description' ,
'build_dockerfile' : 'Build image from Dockerfile' ,
2014-01-21 22:04:00 +00:00
'delete_tag' : 'Delete Tag' ,
2013-11-27 07:29:31 +00:00
'org_create_team' : 'Create team' ,
'org_delete_team' : 'Delete team' ,
'org_add_team_member' : 'Add team member' ,
'org_remove_team_member' : 'Remove team member' ,
'org_set_team_description' : 'Change team description' ,
2014-01-21 22:04:00 +00:00
'org_set_team_role' : 'Change team permission' ,
'create_prototype_permission' : 'Create default permission' ,
'modify_prototype_permission' : 'Modify default permission' ,
'delete_prototype_permission' : 'Delete default permission'
2013-11-27 07:29:31 +00:00
} ;
2013-12-09 22:28:23 +00:00
var getDateString = function ( date ) {
return ( date . getMonth ( ) + 1 ) + '/' + date . getDate ( ) + '/' + date . getFullYear ( ) ;
} ;
var getOffsetDate = function ( date , days ) {
return new Date ( date . getFullYear ( ) , date . getMonth ( ) , date . getDate ( ) + days ) ;
} ;
2013-11-27 07:29:31 +00:00
var update = function ( ) {
2013-12-10 04:33:28 +00:00
var hasValidUser = ! ! $scope . user ;
var hasValidOrg = ! ! $scope . organization ;
var hasValidRepo = $scope . repository && $scope . repository . namespace ;
var isValid = hasValidUser || hasValidOrg || hasValidRepo ;
if ( ! $scope . visible || ! isValid ) {
2013-11-27 07:29:31 +00:00
return ;
}
2013-12-09 22:28:23 +00:00
var twoWeeksAgo = getOffsetDate ( $scope . logEndDate , - 14 ) ;
2013-12-10 02:13:21 +00:00
if ( $scope . logStartDate > $scope . logEndDate || $scope . logStartDate < twoWeeksAgo ) {
2013-12-09 22:28:23 +00:00
$scope . logStartDate = twoWeeksAgo ;
}
2013-11-27 21:56:07 +00:00
$scope . loading = true ;
2013-11-27 07:29:31 +00:00
2013-12-26 22:45:16 +00:00
// Note: We construct the URLs here manually because we also use it for the download
// path.
2013-12-02 19:55:04 +00:00
var url = getRestUrl ( 'user/logs' ) ;
if ( $scope . organization ) {
url = getRestUrl ( 'organization' , $scope . organization . name , 'logs' ) ;
}
if ( $scope . repository ) {
url = getRestUrl ( 'repository' , $scope . repository . namespace , $scope . repository . name , 'logs' ) ;
}
2013-12-07 00:25:27 +00:00
2013-12-09 22:28:23 +00:00
url += '?starttime=' + encodeURIComponent ( getDateString ( $scope . logStartDate ) ) ;
url += '&endtime=' + encodeURIComponent ( getDateString ( $scope . logEndDate ) ) ;
2013-12-07 00:25:27 +00:00
if ( $scope . performer ) {
2013-12-09 22:28:23 +00:00
url += '&performer=' + encodeURIComponent ( $scope . performer . username ) ;
2013-12-07 00:25:27 +00:00
}
2013-12-09 22:28:23 +00:00
2013-11-27 07:29:31 +00:00
var loadLogs = Restangular . one ( url ) ;
loadLogs . customGET ( ) . then ( function ( resp ) {
2013-12-06 20:59:59 +00:00
$scope . logsPath = '/api/' + url ;
2013-11-27 07:29:31 +00:00
if ( ! $scope . chart ) {
2013-11-27 21:56:07 +00:00
$scope . chart = new LogUsageChart ( logKinds ) ;
2013-11-27 07:29:31 +00:00
$ ( $scope . chart ) . bind ( 'filteringChanged' , function ( e ) {
$scope . $apply ( function ( ) { $scope . kindsAllowed = e . allowed ; } ) ;
} ) ;
}
2013-12-09 22:28:23 +00:00
$scope . chart . draw ( 'bar-chart' , resp . logs , $scope . logStartDate , $scope . logEndDate ) ;
2013-11-29 05:04:50 +00:00
$scope . kindsAllowed = null ;
2013-11-27 07:29:31 +00:00
$scope . logs = resp . logs ;
$scope . loading = false ;
} ) ;
} ;
$scope . toggleChart = function ( ) {
$scope . chartVisible = ! $scope . chartVisible ;
} ;
$scope . isVisible = function ( allowed , kind ) {
return allowed == null || allowed . hasOwnProperty ( kind ) ;
} ;
$scope . getColor = function ( kind ) {
return $scope . chart . getColor ( kind ) ;
} ;
$scope . getDescription = function ( log ) {
2013-12-02 19:55:04 +00:00
var fieldIcons = {
'username' : 'user' ,
2014-01-21 22:04:00 +00:00
'activating_username' : 'user' ,
'delegate_user' : 'user' ,
'delegate_team' : 'group' ,
2013-12-02 19:55:04 +00:00
'team' : 'group' ,
'token' : 'key' ,
2014-01-21 21:23:00 +00:00
'repo' : 'hdd-o' ,
2014-01-21 22:04:00 +00:00
'robot' : 'wrench' ,
'tag' : 'tag' ,
'role' : 'th-large' ,
'original_role' : 'th-large'
2013-12-02 19:55:04 +00:00
} ;
2014-01-08 23:44:50 +00:00
log . metadata [ '_ip' ] = log . ip ? log . ip : null ;
2013-12-02 19:05:19 +00:00
2014-01-10 01:09:56 +00:00
var description = logDescriptions [ log . kind ] || log . kind ;
2013-12-02 19:05:19 +00:00
if ( typeof description != 'string' ) {
description = description ( log . metadata ) ;
}
2013-11-27 07:29:31 +00:00
for ( var key in log . metadata ) {
if ( log . metadata . hasOwnProperty ( key ) ) {
2014-01-08 23:44:50 +00:00
var value = log . metadata [ key ] != null ? log . metadata [ key ] . toString ( ) : '(Unknown)' ;
var markedDown = getMarkedDown ( value ) ;
2013-11-27 07:29:31 +00:00
markedDown = markedDown . substr ( '<p>' . length , markedDown . length - '<p></p>' . length ) ;
2013-12-02 19:55:04 +00:00
var icon = fieldIcons [ key ] ;
if ( icon ) {
markedDown = '<i class="fa fa-' + icon + '"></i>' + markedDown ;
}
2013-11-27 07:29:31 +00:00
description = description . replace ( '{' + key + '}' , '<code>' + markedDown + '</code>' ) ;
}
}
2014-01-21 22:04:00 +00:00
return $sce . trustAsHtml ( description . replace ( '\n' , '<br>' ) ) ;
2013-11-27 07:29:31 +00:00
} ;
$scope . $watch ( 'organization' , update ) ;
$scope . $watch ( 'user' , update ) ;
2013-12-02 19:55:04 +00:00
$scope . $watch ( 'repository' , update ) ;
2013-11-27 07:29:31 +00:00
$scope . $watch ( 'visible' , update ) ;
2013-12-07 00:25:27 +00:00
$scope . $watch ( 'performer' , update ) ;
2013-12-09 22:28:23 +00:00
$scope . $watch ( 'logStartDate' , update ) ;
$scope . $watch ( 'logEndDate' , update ) ;
2013-11-27 07:29:31 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-22 23:20:51 +00:00
quayApp . directive ( 'robotsManager' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/robots-manager.html' ,
replace : false ,
2013-11-23 01:14:44 +00:00
transclude : false ,
2013-11-22 23:20:51 +00:00
restrict : 'C' ,
scope : {
'organization' : '=organization' ,
'user' : '=user'
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element , ApiService ) {
2013-12-10 06:38:05 +00:00
$scope . ROBOT _PATTERN = ROBOT _PATTERN ;
2013-11-22 23:20:51 +00:00
$scope . robots = null ;
$scope . loading = false ;
2013-11-23 01:14:44 +00:00
$scope . shownRobot = null ;
$scope . showRobotCounter = 0 ;
$scope . showRobot = function ( info ) {
$scope . shownRobot = info ;
$scope . showRobotCounter ++ ;
} ;
2013-11-22 23:20:51 +00:00
$scope . getShortenedName = function ( name ) {
var plus = name . indexOf ( '+' ) ;
return name . substr ( plus + 1 ) ;
} ;
$scope . getPrefix = function ( name ) {
var plus = name . indexOf ( '+' ) ;
return name . substr ( 0 , plus ) ;
} ;
2013-11-23 01:14:44 +00:00
$scope . createRobot = function ( name ) {
if ( ! name ) { return ; }
2013-12-26 22:45:16 +00:00
createRobotAccount ( ApiService , ! ! $scope . organization , $scope . organization ? $scope . organization . name : '' , name ,
2013-12-10 06:38:05 +00:00
function ( created ) {
$scope . robots . push ( created ) ;
} ) ;
2013-11-23 01:14:44 +00:00
} ;
2013-11-22 23:20:51 +00:00
$scope . deleteRobot = function ( info ) {
var shortName = $scope . getShortenedName ( info . name ) ;
2013-12-26 22:45:16 +00:00
ApiService . deleteRobot ( $scope . organization , null , { 'robot_shortname' : shortName } ) . then ( function ( resp ) {
2013-11-22 23:20:51 +00:00
for ( var i = 0 ; i < $scope . robots . length ; ++ i ) {
if ( $scope . robots [ i ] . name == info . name ) {
2013-11-23 01:14:44 +00:00
$scope . robots . splice ( i , 1 ) ;
2013-11-22 23:20:51 +00:00
return ;
}
}
} , function ( ) {
2013-11-23 01:14:44 +00:00
bootbox . dialog ( {
"message" : 'The selected robot account could not be deleted' ,
"title" : "Cannot delete robot account" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
2013-11-22 23:20:51 +00:00
} ) ;
} ;
var update = function ( ) {
if ( ! $scope . user && ! $scope . organization ) { return ; }
if ( $scope . loading ) { return ; }
$scope . loading = true ;
2013-12-26 22:45:16 +00:00
ApiService . getRobots ( $scope . organization ) . then ( function ( resp ) {
2013-11-22 23:20:51 +00:00
$scope . robots = resp . robots ;
$scope . loading = false ;
} ) ;
} ;
$scope . $watch ( 'organization' , update ) ;
$scope . $watch ( 'user' , update ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-01-21 19:18:20 +00:00
quayApp . directive ( 'prototypeManager' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/prototype-manager.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'organization' : '=organization'
} ,
controller : function ( $scope , $element , ApiService ) {
$scope . loading = false ;
2014-01-21 20:09:47 +00:00
$scope . activatingForNew = null ;
$scope . delegateForNew = null ;
$scope . clearCounter = 0 ;
2014-01-21 23:34:54 +00:00
$scope . newForWholeOrg = true ;
2014-01-21 19:18:20 +00:00
$scope . roles = [
{ 'id' : 'read' , 'title' : 'Read' , 'kind' : 'success' } ,
{ 'id' : 'write' , 'title' : 'Write' , 'kind' : 'success' } ,
{ 'id' : 'admin' , 'title' : 'Admin' , 'kind' : 'primary' }
] ;
$scope . setRole = function ( role , prototype ) {
var params = {
'orgname' : $scope . organization . name ,
'prototypeid' : prototype . id
} ;
var data = {
'id' : prototype . id ,
'role' : role
} ;
ApiService . updateOrganizationPrototypePermission ( data , params ) . then ( function ( resp ) {
prototype . role = role ;
} , function ( resp ) {
bootbox . dialog ( {
"message" : resp . data ? resp . data : 'The permission could not be modified' ,
"title" : "Cannot modify permission" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
} ) ;
} ;
2014-01-21 23:34:54 +00:00
$scope . comparePrototypes = function ( p ) {
return p . activating _user ? p . activating _user . name : ' ' ;
} ;
2014-01-21 20:09:47 +00:00
$scope . setRoleForNew = function ( role ) {
$scope . newRole = role ;
} ;
2014-01-21 23:34:54 +00:00
$scope . setNewForWholeOrg = function ( value ) {
$scope . newForWholeOrg = value ;
} ;
2014-01-21 20:09:47 +00:00
$scope . showAddDialog = function ( ) {
$scope . activatingForNew = null ;
$scope . delegateForNew = null ;
$scope . newRole = 'read' ;
$scope . clearCounter ++ ;
2014-01-21 23:34:54 +00:00
$scope . newForWholeOrg = true ;
2014-01-21 20:09:47 +00:00
$ ( '#addPermissionDialogModal' ) . modal ( { } ) ;
} ;
$scope . createPrototype = function ( ) {
$scope . loading = true ;
var params = {
'orgname' : $scope . organization . name
} ;
var data = {
2014-01-21 23:34:54 +00:00
'activating_user' : $scope . newForWholeOrg ? null : $scope . activatingForNew ,
2014-01-21 20:09:47 +00:00
'delegate' : $scope . delegateForNew ,
'role' : $scope . newRole
} ;
ApiService . createOrganizationPrototypePermission ( data , params ) . then ( function ( resp ) {
$scope . prototypes . push ( resp ) ;
$scope . loading = false ;
$ ( '#addPermissionDialogModal' ) . modal ( 'hide' ) ;
} , function ( resp ) {
$ ( '#addPermissionDialogModal' ) . modal ( 'hide' ) ;
bootbox . dialog ( {
"message" : resp . data ? resp . data : 'The permission could not be created' ,
"title" : "Cannot create permission" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
} ) ;
} ;
2014-01-21 19:18:20 +00:00
$scope . deletePrototype = function ( prototype ) {
$scope . loading = true ;
var params = {
'orgname' : $scope . organization . name ,
'prototypeid' : prototype . id
} ;
ApiService . deleteOrganizationPrototypePermission ( null , params ) . then ( function ( resp ) {
$scope . prototypes . splice ( $scope . prototypes . indexOf ( prototype ) , 1 ) ;
$scope . loading = false ;
} , function ( resp ) {
bootbox . dialog ( {
"message" : resp . data ? resp . data : 'The permission could not be deleted' ,
"title" : "Cannot delete permission" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
2014-01-21 20:09:47 +00:00
} ) ;
2014-01-21 19:18:20 +00:00
} ) ;
} ;
var update = function ( ) {
if ( ! $scope . organization ) { return ; }
if ( $scope . loading ) { return ; }
var params = { 'orgname' : $scope . organization . name } ;
$scope . loading = true ;
ApiService . getOrganizationPrototypePermissions ( null , params ) . then ( function ( resp ) {
$scope . prototypes = resp . prototypes ;
$scope . loading = false ;
} ) ;
} ;
$scope . $watch ( 'organization' , update ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-23 01:14:44 +00:00
quayApp . directive ( 'popupInputButton' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/popup-input-button.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'placeholder' : '=placeholder' ,
'pattern' : '=pattern' ,
'submitted' : '&submitted'
} ,
controller : function ( $scope , $element ) {
$scope . popupShown = function ( ) {
setTimeout ( function ( ) {
var box = $ ( '#input-box' ) ;
box [ 0 ] . value = '' ;
box . focus ( ) ;
} , 10 ) ;
} ;
$scope . getRegexp = function ( pattern ) {
if ( ! pattern ) {
pattern = '.*' ;
}
return new RegExp ( pattern ) ;
} ;
$scope . inputSubmit = function ( ) {
var box = $ ( '#input-box' ) ;
if ( box . hasClass ( 'ng-invalid' ) ) { return ; }
var entered = box [ 0 ] . value ;
if ( ! entered ) {
return ;
}
if ( $scope . submitted ) {
$scope . submitted ( { 'value' : entered } ) ;
}
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-22 23:20:51 +00:00
2013-12-17 18:19:59 +00:00
quayApp . directive ( 'resourceView' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/resource-view.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'resource' : '=resource' ,
'errorMessage' : '=errorMessage'
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-12-18 03:56:28 +00:00
quayApp . directive ( 'quaySpinner' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/spinner.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : { } ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-04 19:56:54 +00:00
quayApp . directive ( 'organizationHeader' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/organization-header.html' ,
replace : false ,
2013-11-05 21:15:04 +00:00
transclude : true ,
2013-11-04 19:56:54 +00:00
restrict : 'C' ,
scope : {
'organization' : '=organization' ,
2013-12-02 22:19:19 +00:00
'teamName' : '=teamName' ,
'clickable' : '=clickable'
2013-11-04 19:56:54 +00:00
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-05 00:59:28 +00:00
quayApp . directive ( 'markdownInput' , function ( ) {
var counter = 0 ;
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/markdown-input.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'content' : '=content' ,
'canWrite' : '=canWrite' ,
'contentChanged' : '=contentChanged' ,
'fieldTitle' : '=fieldTitle'
} ,
controller : function ( $scope , $element ) {
var elm = $element [ 0 ] ;
$scope . id = ( counter ++ ) ;
$scope . editContent = function ( ) {
if ( ! $scope . canWrite ) { return ; }
if ( ! $scope . markdownDescriptionEditor ) {
var converter = Markdown . getSanitizingConverter ( ) ;
var editor = new Markdown . Editor ( converter , '-description-' + $scope . id ) ;
editor . run ( ) ;
$scope . markdownDescriptionEditor = editor ;
}
$ ( '#wmd-input-description-' + $scope . id ) [ 0 ] . value = $scope . content ;
$ ( elm ) . find ( '.modal' ) . modal ( { } ) ;
} ;
$scope . saveContent = function ( ) {
$scope . content = $ ( '#wmd-input-description-' + $scope . id ) [ 0 ] . value ;
$ ( elm ) . find ( '.modal' ) . modal ( 'hide' ) ;
if ( $scope . contentChanged ) {
$scope . contentChanged ( $scope . content ) ;
}
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-19 00:03:35 +00:00
quayApp . directive ( 'repoSearch' , function ( ) {
var number = 0 ;
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/repo-search.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
} ,
controller : function ( $scope , $element , $location , UserService , Restangular ) {
var searchToken = 0 ;
$scope . $watch ( function ( ) { return UserService . currentUser ( ) ; } , function ( currentUser ) {
++ searchToken ;
} , true ) ;
var element = $ ( $element [ 0 ] . childNodes [ 0 ] ) ;
element . typeahead ( {
name : 'repositories' ,
remote : {
url : '/api/find/repository?query=%QUERY' ,
replace : function ( url , uriEncodedQuery ) {
url = url . replace ( '%QUERY' , uriEncodedQuery ) ;
url += '&cb=' + searchToken ;
return url ;
} ,
filter : function ( data ) {
var datums = [ ] ;
for ( var i = 0 ; i < data . repositories . length ; ++ i ) {
var repo = data . repositories [ i ] ;
datums . push ( {
'value' : repo . name ,
'tokens' : [ repo . name , repo . namespace ] ,
'repo' : repo
} ) ;
}
return datums ;
}
} ,
template : function ( datum ) {
template = '<div class="repo-mini-listing">' ;
2014-01-15 20:40:37 +00:00
template += '<i class="fa fa-hdd-o fa-lg"></i>'
2013-11-19 00:03:35 +00:00
template += '<span class="name">' + datum . repo . namespace + '/' + datum . repo . name + '</span>'
if ( datum . repo . description ) {
template += '<span class="description">' + getFirstTextLine ( datum . repo . description ) + '</span>'
}
template += '</div>'
return template ;
}
} ) ;
element . on ( 'typeahead:selected' , function ( e , datum ) {
element . typeahead ( 'setQuery' , '' ) ;
document . location = '/repository/' + datum . repo . namespace + '/' + datum . repo . name ;
} ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
quayApp . directive ( 'headerBar' , function ( ) {
var number = 0 ;
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/header-bar.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element , $location , UserService , PlanService , ApiService ) {
2013-12-19 04:03:19 +00:00
$scope . overPlan = false ;
var checkOverPlan = function ( ) {
if ( $scope . user . anonymous ) {
$scope . overPlan = false ;
return ;
}
2013-12-26 22:45:16 +00:00
ApiService . getUserPrivateCount ( ) . then ( function ( resp ) {
2013-12-19 20:29:39 +00:00
$scope . overPlan = resp . privateCount > resp . reposAllowed ;
2013-12-19 04:03:19 +00:00
} ) ;
} ;
// Monitor any user changes and place the current user into the scope.
UserService . updateUserIn ( $scope , checkOverPlan ) ;
// Monitor any plan changes.
PlanService . registerListener ( this , checkOverPlan ) ;
2013-11-19 00:03:35 +00:00
$scope . signout = function ( ) {
2013-12-26 22:45:16 +00:00
ApiService . logout ( ) . then ( function ( ) {
UserService . load ( ) ;
$location . path ( '/' ) ;
2013-11-19 00:03:35 +00:00
} ) ;
} ;
$scope . appLinkTarget = function ( ) {
if ( $ ( "div[ng-view]" ) . length === 0 ) {
return "_self" ;
}
return "" ;
2013-12-19 04:03:19 +00:00
} ;
2013-11-19 00:03:35 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-02 01:48:10 +00:00
quayApp . directive ( 'entitySearch' , function ( ) {
var number = 0 ;
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/entity-search.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
2013-11-20 23:23:59 +00:00
'namespace' : '=namespace' ,
2013-11-02 01:48:10 +00:00
'inputTitle' : '=inputTitle' ,
2013-11-20 23:23:59 +00:00
'entitySelected' : '=entitySelected' ,
2013-12-10 06:38:05 +00:00
'includeTeams' : '=includeTeams' ,
2014-01-21 20:09:47 +00:00
'isOrganization' : '=isOrganization' ,
'isPersistent' : '=isPersistent' ,
'currentEntity' : '=currentEntity' ,
'clearNow' : '=clearNow'
2013-11-02 01:48:10 +00:00
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element , Restangular , UserService , ApiService ) {
2013-12-10 06:38:05 +00:00
$scope . lazyLoading = true ;
$scope . isAdmin = false ;
$scope . lazyLoad = function ( ) {
if ( ! $scope . namespace || ! $scope . lazyLoading ) { return ; }
2013-12-10 20:49:34 +00:00
$scope . isAdmin = UserService . isNamespaceAdmin ( $scope . namespace ) ;
2013-12-10 06:38:05 +00:00
if ( $scope . isOrganization && $scope . includeTeams ) {
2013-12-26 22:45:16 +00:00
ApiService . getOrganization ( null , { 'orgname' : $scope . namespace } ) . then ( function ( resp ) {
2013-12-10 06:38:05 +00:00
$scope . teams = resp . teams ;
} ) ;
}
2013-12-26 22:45:16 +00:00
ApiService . getRobots ( $scope . isOrganization ? $scope . namespace : null ) . then ( function ( resp ) {
2013-12-10 20:49:34 +00:00
$scope . robots = resp . robots ;
2013-12-10 06:38:05 +00:00
$scope . lazyLoading = false ;
2013-12-10 20:49:34 +00:00
} , function ( ) {
$scope . lazyLoading = false ;
} ) ;
2013-12-10 06:38:05 +00:00
} ;
$scope . createTeam = function ( ) {
2013-12-10 20:49:34 +00:00
if ( ! $scope . isAdmin ) { return ; }
2013-12-10 06:38:05 +00:00
bootbox . prompt ( 'Enter the name of the new team' , function ( teamname ) {
if ( ! teamname ) { return ; }
var regex = new RegExp ( TEAM _PATTERN ) ;
if ( ! regex . test ( teamname ) ) {
bootbox . alert ( 'Invalid team name' ) ;
return ;
}
2013-12-26 22:45:16 +00:00
createOrganizationTeam ( ApiService , $scope . namespace , teamname , function ( created ) {
2013-12-10 06:38:05 +00:00
$scope . setEntity ( created . name , 'team' , false ) ;
$scope . teams [ teamname ] = created ;
} ) ;
} ) ;
} ;
$scope . createRobot = function ( ) {
2013-12-10 20:49:34 +00:00
if ( ! $scope . isAdmin ) { return ; }
2013-12-10 06:38:05 +00:00
bootbox . prompt ( 'Enter the name of the new robot account' , function ( robotname ) {
if ( ! robotname ) { return ; }
var regex = new RegExp ( ROBOT _PATTERN ) ;
if ( ! regex . test ( robotname ) ) {
bootbox . alert ( 'Invalid robot account name' ) ;
return ;
}
2013-12-26 22:45:16 +00:00
createRobotAccount ( ApiService , $scope . isOrganization , $scope . namespace , robotname , function ( created ) {
2013-12-10 06:38:05 +00:00
$scope . setEntity ( created . name , 'user' , true ) ;
$scope . robots . push ( created ) ;
} ) ;
} ) ;
} ;
$scope . setEntity = function ( name , kind , is _robot ) {
var entity = {
'name' : name ,
'kind' : kind ,
'is_robot' : is _robot
} ;
if ( $scope . is _organization ) {
entity [ 'is_org_member' ] = true ;
}
2014-01-21 20:09:47 +00:00
$scope . setEntityInternal ( entity ) ;
2013-12-10 06:38:05 +00:00
} ;
2014-01-21 20:09:47 +00:00
$scope . clearEntityInternal = function ( ) {
$scope . currentEntity = null ;
if ( $scope . entitySelected ) {
$scope . entitySelected ( null ) ;
}
} ;
$scope . setEntityInternal = function ( entity ) {
$ ( input ) . typeahead ( 'setQuery' , $scope . isPersistent ? entity . name : '' ) ;
if ( $scope . isPersistent ) {
$scope . currentEntity = entity ;
}
if ( $scope . entitySelected ) {
$scope . entitySelected ( entity ) ;
}
} ;
2013-11-02 01:48:10 +00:00
number ++ ;
2013-12-10 06:38:05 +00:00
var input = $element [ 0 ] . firstChild . firstChild ;
2013-11-02 01:48:10 +00:00
$ ( input ) . typeahead ( {
name : 'entities' + number ,
remote : {
url : '/api/entities/%QUERY' ,
replace : function ( url , uriEncodedQuery ) {
2013-12-18 03:56:28 +00:00
var namespace = $scope . namespace || '' ;
url = url . replace ( '%QUERY' , uriEncodedQuery ) ;
url += '?namespace=' + encodeURIComponent ( namespace ) ;
if ( $scope . includeTeams ) {
url += '&includeTeams=true'
}
return url ;
2013-11-02 01:48:10 +00:00
} ,
filter : function ( data ) {
var datums = [ ] ;
for ( var i = 0 ; i < data . results . length ; ++ i ) {
var entity = data . results [ i ] ;
datums . push ( {
'value' : entity . name ,
'tokens' : [ entity . name ] ,
'entity' : entity
} ) ;
}
return datums ;
}
} ,
template : function ( datum ) {
template = '<div class="entity-mini-listing">' ;
2013-11-21 00:43:19 +00:00
if ( datum . entity . kind == 'user' && ! datum . entity . is _robot ) {
2013-11-02 01:48:10 +00:00
template += '<i class="fa fa-user fa-lg"></i>' ;
2013-11-21 00:43:19 +00:00
} else if ( datum . entity . kind == 'user' && datum . entity . is _robot ) {
template += '<i class="fa fa-wrench fa-lg"></i>' ;
2013-11-02 01:48:10 +00:00
} else if ( datum . entity . kind == 'team' ) {
template += '<i class="fa fa-group fa-lg"></i>' ;
}
template += '<span class="name">' + datum . value + '</span>' ;
2013-12-18 03:56:28 +00:00
if ( datum . entity . is _org _member === false && datum . entity . kind == 'user' ) {
template += '<i class="fa fa-exclamation-triangle" title="User is outside the organization"></i>' ;
2013-11-02 01:48:10 +00:00
}
template += '</div>' ;
return template ;
} ,
} ) ;
2014-01-21 20:09:47 +00:00
$ ( input ) . on ( 'input' , function ( e ) {
$scope . $apply ( function ( ) {
if ( $scope . isPersistent ) {
$scope . clearEntityInternal ( ) ;
}
} ) ;
} ) ;
2013-11-02 01:48:10 +00:00
$ ( input ) . on ( 'typeahead:selected' , function ( e , datum ) {
2013-12-10 06:38:05 +00:00
$scope . $apply ( function ( ) {
2014-01-21 20:09:47 +00:00
$scope . setEntityInternal ( datum . entity ) ;
2013-12-10 06:38:05 +00:00
} ) ;
2013-11-02 01:48:10 +00:00
} ) ;
2014-01-21 20:09:47 +00:00
$scope . $watch ( 'clearNow' , function ( ) {
$ ( input ) . typeahead ( 'setQuery' , '' ) ;
$scope . clearEntityInternal ( ) ;
} ) ;
2013-11-02 01:48:10 +00:00
$scope . $watch ( 'inputTitle' , function ( title ) {
input . setAttribute ( 'placeholder' , title ) ;
} ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-05 19:47:46 +00:00
quayApp . directive ( 'roleGroup' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/role-group.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'roles' : '=roles' ,
'currentRole' : '=currentRole' ,
'roleChanged' : '&roleChanged'
} ,
controller : function ( $scope , $element ) {
$scope . setRole = function ( role ) {
2013-11-08 04:35:27 +00:00
if ( $scope . currentRole == role ) { return ; }
if ( $scope . roleChanged ) {
2013-11-05 19:47:46 +00:00
$scope . roleChanged ( { 'role' : role } ) ;
2013-11-08 04:35:27 +00:00
} else {
$scope . currentRole = role ;
2013-11-05 19:47:46 +00:00
}
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-15 19:42:31 +00:00
quayApp . directive ( 'billingOptions' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/billing-options.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'user' : '=user' ,
'organization' : '=organization'
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element , PlanService , ApiService ) {
2013-11-15 19:42:31 +00:00
$scope . invoice _email = false ;
2013-11-15 23:17:12 +00:00
$scope . currentCard = null ;
// Listen to plan changes.
PlanService . registerListener ( this , function ( plan ) {
if ( plan && plan . price > 0 ) {
update ( ) ;
}
} ) ;
$scope . $on ( '$destroy' , function ( ) {
PlanService . unregisterListener ( this ) ;
} ) ;
$scope . changeCard = function ( ) {
2013-11-19 22:06:17 +00:00
var previousCard = $scope . currentCard ;
2013-11-15 23:17:12 +00:00
$scope . changingCard = true ;
var callbacks = {
'opened' : function ( ) { $scope . changingCard = true ; } ,
'closed' : function ( ) { $scope . changingCard = false ; } ,
'started' : function ( ) { $scope . currentCard = null ; } ,
'success' : function ( resp ) {
$scope . currentCard = resp . card ;
$scope . changingCard = false ;
} ,
2013-11-19 22:06:17 +00:00
'failure' : function ( resp ) {
2013-11-15 23:17:12 +00:00
$scope . changingCard = false ;
2013-11-19 22:06:17 +00:00
$scope . currentCard = previousCard ;
if ( ! PlanService . isCardError ( resp ) ) {
$ ( '#cannotchangecardModal' ) . modal ( { } ) ;
}
2013-11-15 23:17:12 +00:00
}
} ;
PlanService . changeCreditCard ( $scope , $scope . organization ? $scope . organization . name : null , callbacks ) ;
} ;
$scope . getCreditImage = function ( creditInfo ) {
2013-11-15 23:34:54 +00:00
if ( ! creditInfo || ! creditInfo . type ) { return 'credit.png' ; }
2013-11-15 23:17:12 +00:00
var kind = creditInfo . type . toLowerCase ( ) || 'credit' ;
var supported = {
'american express' : 'amex' ,
'credit' : 'credit' ,
'diners club' : 'diners' ,
'discover' : 'discover' ,
'jcb' : 'jcb' ,
'mastercard' : 'mastercard' ,
'visa' : 'visa'
} ;
kind = supported [ kind ] || 'credit' ;
return kind + '.png' ;
} ;
2013-11-15 19:42:31 +00:00
var update = function ( ) {
if ( ! $scope . user && ! $scope . organization ) { return ; }
$scope . obj = $scope . user ? $scope . user : $scope . organization ;
$scope . invoice _email = $scope . obj . invoice _email ;
2013-11-15 23:17:12 +00:00
// Load the credit card information.
2013-11-15 23:58:47 +00:00
PlanService . getCardInfo ( $scope . organization ? $scope . organization . name : null , function ( card ) {
$scope . currentCard = card ;
2013-11-15 23:17:12 +00:00
} ) ;
2013-11-15 19:42:31 +00:00
} ;
var save = function ( ) {
$scope . working = true ;
2013-12-26 22:45:16 +00:00
ApiService . changeDetails ( $scope . organization , $scope . obj ) . then ( function ( resp ) {
2013-11-15 19:42:31 +00:00
$scope . working = false ;
} ) ;
} ;
var checkSave = function ( ) {
if ( ! $scope . obj ) { return ; }
if ( $scope . obj . invoice _email != $scope . invoice _email ) {
$scope . obj . invoice _email = $scope . invoice _email ;
save ( ) ;
}
} ;
$scope . $watch ( 'invoice_email' , checkSave ) ;
$scope . $watch ( 'organization' , update ) ;
$scope . $watch ( 'user' , update ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-06 22:30:20 +00:00
quayApp . directive ( 'planManager' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/plan-manager.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'user' : '=user' ,
2013-11-06 23:14:22 +00:00
'organization' : '=organization' ,
2013-11-15 23:17:12 +00:00
'readyForPlan' : '&readyForPlan' ,
'planChanged' : '&planChanged'
2013-11-06 22:30:20 +00:00
} ,
2013-12-26 22:45:16 +00:00
controller : function ( $scope , $element , PlanService , ApiService ) {
2013-11-06 22:30:20 +00:00
var hasSubscription = false ;
2013-12-20 02:51:46 +00:00
$scope . isPlanVisible = function ( plan , subscribedPlan ) {
if ( plan [ 'deprecated' ] ) {
return plan == subscribedPlan ;
}
if ( $scope . organization && ! PlanService . isOrgCompatible ( plan ) ) {
return false ;
}
return true ;
2013-11-06 22:30:20 +00:00
} ;
$scope . changeSubscription = function ( planId ) {
if ( $scope . planChanging ) { return ; }
2013-11-09 01:32:56 +00:00
var callbacks = {
'opening' : function ( ) { $scope . planChanging = true ; } ,
'started' : function ( ) { $scope . planChanging = true ; } ,
'opened' : function ( ) { $scope . planChanging = true ; } ,
'closed' : function ( ) { $scope . planChanging = false ; } ,
'success' : subscribedToPlan ,
2013-11-19 22:06:17 +00:00
'failure' : function ( resp ) {
$scope . planChanging = false ;
}
2013-11-09 01:32:56 +00:00
} ;
2013-11-15 23:58:47 +00:00
PlanService . changePlan ( $scope , $scope . organization , planId , callbacks ) ;
2013-11-06 22:30:20 +00:00
} ;
$scope . cancelSubscription = function ( ) {
2013-12-20 02:51:46 +00:00
$scope . changeSubscription ( PlanService . getFreePlan ( ) ) ;
2013-11-06 22:30:20 +00:00
} ;
var subscribedToPlan = function ( sub ) {
$scope . subscription = sub ;
2013-12-20 02:51:46 +00:00
if ( sub . plan != PlanService . getFreePlan ( ) ) {
2013-11-06 22:30:20 +00:00
hasSubscription = true ;
}
2013-12-20 02:51:46 +00:00
PlanService . getPlanIncludingDeprecated ( sub . plan , function ( subscribedPlan ) {
2013-11-06 22:30:20 +00:00
$scope . subscribedPlan = subscribedPlan ;
$scope . planUsagePercent = sub . usedPrivateRepos * 100 / $scope . subscribedPlan . privateRepos ;
2013-11-15 23:17:12 +00:00
if ( $scope . planChanged ) {
$scope . planChanged ( { 'plan' : subscribedPlan } ) ;
}
2013-11-06 22:30:20 +00:00
if ( sub . usedPrivateRepos > $scope . subscribedPlan . privateRepos ) {
2013-11-06 22:59:16 +00:00
$scope . limit = 'over' ;
} else if ( sub . usedPrivateRepos == $scope . subscribedPlan . privateRepos ) {
$scope . limit = 'at' ;
2013-11-06 22:30:20 +00:00
} else if ( sub . usedPrivateRepos >= $scope . subscribedPlan . privateRepos * 0.7 ) {
2013-11-06 22:59:16 +00:00
$scope . limit = 'near' ;
2013-11-06 22:30:20 +00:00
} else {
2013-11-06 22:59:16 +00:00
$scope . limit = 'none' ;
2013-11-06 22:30:20 +00:00
}
if ( ! $scope . chart ) {
$scope . chart = new RepositoryUsageChart ( ) ;
$scope . chart . draw ( 'repository-usage-chart' ) ;
}
$scope . chart . update ( sub . usedPrivateRepos || 0 , $scope . subscribedPlan . privateRepos || 0 ) ;
$scope . planChanging = false ;
$scope . planLoading = false ;
} ) ;
} ;
var update = function ( ) {
$scope . planLoading = true ;
if ( ! $scope . plans ) { return ; }
PlanService . getSubscription ( $scope . organization , subscribedToPlan , function ( ) {
// User/Organization has no subscription.
2013-12-20 02:51:46 +00:00
subscribedToPlan ( { 'plan' : PlanService . getFreePlan ( ) } ) ;
2013-11-06 22:30:20 +00:00
} ) ;
} ;
var loadPlans = function ( ) {
2013-11-07 20:33:56 +00:00
if ( $scope . plans || $scope . loadingPlans ) { return ; }
2013-11-06 22:59:16 +00:00
if ( ! $scope . user && ! $scope . organization ) { return ; }
2013-11-06 23:14:22 +00:00
2013-11-07 20:33:56 +00:00
$scope . loadingPlans = true ;
2013-12-20 02:51:46 +00:00
PlanService . verifyLoaded ( function ( plans ) {
$scope . plans = plans ;
2013-11-06 22:30:20 +00:00
update ( ) ;
2013-11-06 23:14:22 +00:00
if ( $scope . readyForPlan ) {
var planRequested = $scope . readyForPlan ( ) ;
2013-12-20 02:51:46 +00:00
if ( planRequested && planRequested != PlanService . getFreePlan ( ) ) {
2013-11-06 23:14:22 +00:00
$scope . changeSubscription ( planRequested ) ;
}
}
2013-11-06 22:30:20 +00:00
} ) ;
} ;
// Start the initial download.
2013-11-06 22:59:16 +00:00
$scope . planLoading = true ;
loadPlans ( ) ;
2013-11-06 22:30:20 +00:00
2013-11-07 00:19:21 +00:00
$scope . $watch ( 'organization' , loadPlans ) ;
$scope . $watch ( 'user' , loadPlans ) ;
2013-11-06 22:30:20 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-01 21:35:26 +00:00
quayApp . directive ( 'namespaceSelector' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/namespace-selector.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'user' : '=user' ,
2013-11-07 05:49:13 +00:00
'namespace' : '=namespace' ,
'requireCreate' : '=requireCreate'
2013-11-01 21:35:26 +00:00
} ,
2013-12-17 20:03:34 +00:00
controller : function ( $scope , $element , $routeParams , CookieService ) {
2013-11-07 05:49:13 +00:00
$scope . namespaces = { } ;
$scope . initialize = function ( user ) {
2014-01-16 00:15:38 +00:00
var preferredNamespace = user . username ;
2013-11-07 05:49:13 +00:00
var namespaces = { } ;
namespaces [ user . username ] = user ;
2013-11-07 06:48:58 +00:00
if ( user . organizations ) {
for ( var i = 0 ; i < user . organizations . length ; ++ i ) {
namespaces [ user . organizations [ i ] . name ] = user . organizations [ i ] ;
2014-01-16 00:15:38 +00:00
if ( user . organizations [ i ] . preferred _namespace ) {
preferredNamespace = user . organizations [ i ] . name ;
}
2013-11-07 06:48:58 +00:00
}
2013-11-07 05:49:13 +00:00
}
2014-01-16 00:15:38 +00:00
var initialNamespace = $routeParams [ 'namespace' ] || CookieService . get ( 'quay.namespace' ) ||
preferredNamespace || $scope . user . username ;
2013-11-07 05:49:13 +00:00
$scope . namespaces = namespaces ;
$scope . setNamespace ( $scope . namespaces [ initialNamespace ] ) ;
} ;
2013-11-01 21:35:26 +00:00
$scope . setNamespace = function ( namespaceObj ) {
if ( ! namespaceObj ) {
2013-11-07 05:49:13 +00:00
namespaceObj = $scope . namespaces [ $scope . user . username ] ;
}
if ( $scope . requireCreate && ! namespaceObj . can _create _repo ) {
namespaceObj = $scope . namespaces [ $scope . user . username ] ;
2013-11-01 21:35:26 +00:00
}
2013-11-07 05:49:13 +00:00
var newNamespace = namespaceObj . name || namespaceObj . username ;
2013-11-01 21:35:26 +00:00
$scope . namespaceObj = namespaceObj ;
2013-11-07 05:49:13 +00:00
$scope . namespace = newNamespace ;
2013-12-17 20:03:34 +00:00
if ( newNamespace ) {
CookieService . putPermanent ( 'quay.namespace' , newNamespace ) ;
}
2013-11-01 21:35:26 +00:00
} ;
2014-01-16 00:15:38 +00:00
$scope . $watch ( 'namespace' , function ( namespace ) {
if ( $scope . namespaceObj && namespace && namespace != $scope . namespaceObj . username ) {
$scope . setNamespace ( $scope . namespaces [ namespace ] ) ;
}
} ) ;
2013-11-01 21:35:26 +00:00
$scope . $watch ( 'user' , function ( user ) {
2013-11-07 05:49:13 +00:00
$scope . user = user ;
$scope . initialize ( user ) ;
2013-11-01 21:35:26 +00:00
} ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-13 02:16:11 +00:00
quayApp . directive ( 'buildLogPhase' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/build-log-phase.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'phase' : '=phase'
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
quayApp . directive ( 'buildLogError' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/build-log-error.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'error' : '=error'
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-20 18:27:59 +00:00
quayApp . directive ( 'triggerDescription' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/trigger-description.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'trigger' : '=trigger'
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-25 01:36:54 +00:00
quayApp . directive ( 'dropdownSelect' , function ( $compile ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/dropdown-select.html' ,
replace : true ,
transclude : true ,
restrict : 'C' ,
scope : {
'selectedItem' : '=selectedItem' ,
'placeholder' : '=placeholder' ,
'lookaheadItems' : '=lookaheadItems' ,
'handleItemSelected' : '&handleItemSelected' ,
'handleInput' : '&handleInput'
} ,
controller : function ( $scope , $element , $rootScope ) {
if ( ! $rootScope . _ _dropdownSelectCounter ) {
$rootScope . _ _dropdownSelectCounter = 1 ;
}
$scope . placeholder = $scope . placeholder || '' ;
$scope . internalItem = null ;
// Setup lookahead.
var input = $ ( $element ) . find ( '.lookahead-input' ) ;
$scope . $watch ( 'selectedItem' , function ( item ) {
if ( $scope . selectedItem == $scope . internalItem ) {
// The item has already been set due to an internal action.
return ;
}
if ( $scope . selectedItem != null ) {
$ ( input ) . val ( item . toString ( ) ) ;
} else {
$ ( input ) . val ( '' ) ;
}
} ) ;
$scope . $watch ( 'lookaheadItems' , function ( items ) {
$ ( input ) . off ( ) ;
if ( ! items ) {
return ;
}
$ ( input ) . typeahead ( {
name : 'dropdown-items-' + $rootScope . _ _dropdownSelectCounter ,
local : items ,
template : function ( datum ) {
template = datum [ 'template' ] ? datum [ 'template' ] ( datum ) : datum [ 'value' ] ;
return template ;
}
} ) ;
$ ( input ) . on ( 'input' , function ( e ) {
$scope . $apply ( function ( ) {
$scope . internalItem = null ;
$scope . selectedItem = null ;
if ( $scope . handleInput ) {
$scope . handleInput ( { 'input' : $ ( input ) . val ( ) } ) ;
}
} ) ;
} ) ;
$ ( input ) . on ( 'typeahead:selected' , function ( e , datum ) {
$scope . $apply ( function ( ) {
$scope . internalItem = datum [ 'item' ] || datum [ 'value' ] ;
$scope . selectedItem = datum [ 'item' ] || datum [ 'value' ] ;
if ( $scope . handleItemSelected ) {
$scope . handleItemSelected ( { 'datum' : datum } ) ;
}
} ) ;
} ) ;
$rootScope . _ _dropdownSelectCounter ++ ;
} ) ;
} ,
link : function ( scope , element , attrs ) {
var transcludedBlock = element . find ( 'div.transcluded' ) ;
var transcludedElements = transcludedBlock . children ( ) ;
var iconContainer = element . find ( 'div.dropdown-select-icon-transclude' ) ;
var menuContainer = element . find ( 'div.dropdown-select-menu-transclude' ) ;
angular . forEach ( transcludedElements , function ( elem ) {
if ( angular . element ( elem ) . hasClass ( 'dropdown-select-icon' ) ) {
iconContainer . append ( elem ) ;
} else if ( angular . element ( elem ) . hasClass ( 'dropdown-select-menu' ) ) {
menuContainer . replaceWith ( elem ) ;
}
} ) ;
transcludedBlock . remove ( ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
quayApp . directive ( 'dropdownSelectIcon' , function ( ) {
var directiveDefinitionObject = {
priority : 1 ,
require : '^dropdownSelect' ,
templateUrl : '/static/directives/dropdown-select-icon.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
quayApp . directive ( 'dropdownSelectMenu' , function ( ) {
var directiveDefinitionObject = {
priority : 1 ,
require : '^dropdownSelect' ,
templateUrl : '/static/directives/dropdown-select-menu.html' ,
replace : true ,
transclude : true ,
restrict : 'C' ,
scope : {
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-20 23:57:49 +00:00
quayApp . directive ( 'triggerSetupGithub' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/trigger-setup-github.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'repository' : '=repository' ,
'trigger' : '=trigger'
} ,
controller : function ( $scope , $element , ApiService ) {
$scope . setupReady = false ;
$scope . loading = true ;
2014-02-25 01:36:54 +00:00
2014-02-25 05:19:38 +00:00
$scope . handleLocationInput = function ( location ) {
$scope . trigger [ 'config' ] [ 'subdir' ] = location || '' ;
2014-02-25 05:42:33 +00:00
$scope . isInvalidLocation = $scope . locations . indexOf ( location ) < 0 ;
2014-02-25 05:19:38 +00:00
} ;
2014-02-25 01:36:54 +00:00
$scope . setLocation = function ( location ) {
$scope . currentLocation = location ;
$scope . trigger [ 'config' ] [ 'subdir' ] = location || '' ;
2014-02-25 05:42:33 +00:00
$scope . isInvalidLocation = false ;
2014-02-20 23:57:49 +00:00
} ;
2014-02-25 01:36:54 +00:00
2014-02-20 23:57:49 +00:00
$scope . selectRepo = function ( repo , org ) {
2014-02-25 01:36:54 +00:00
$scope . currentRepo = {
'repo' : repo ,
'avatar_url' : org [ 'info' ] [ 'avatar_url' ] ,
'toString' : function ( ) {
return this . repo ;
}
} ;
2014-02-20 23:57:49 +00:00
} ;
2014-02-25 01:36:54 +00:00
$scope . selectRepoInternal = function ( currentRepo ) {
if ( ! currentRepo ) {
$scope . trigger . $ready = false ;
return ;
}
var params = {
'repository' : $scope . repository . namespace + '/' + $scope . repository . name ,
'trigger_uuid' : $scope . trigger [ 'id' ]
2014-02-20 23:57:49 +00:00
} ;
2014-02-25 01:36:54 +00:00
var repo = currentRepo [ 'repo' ] ;
2014-02-20 23:57:49 +00:00
$scope . trigger [ 'config' ] = {
2014-02-25 01:36:54 +00:00
'build_source' : repo ,
'subdir' : ''
2014-02-20 23:57:49 +00:00
} ;
2014-02-25 01:36:54 +00:00
// Lookup the possible Dockerfile locations.
$scope . locations = null ;
if ( repo ) {
ApiService . listBuildTriggerSubdirs ( $scope . trigger [ 'config' ] , params ) . then ( function ( resp ) {
if ( resp [ 'status' ] == 'error' ) {
$scope . locationError = resp [ 'message' ] || 'Could not load Dockerfile locations' ;
$scope . locations = null ;
$scope . trigger . $ready = false ;
2014-02-25 05:42:33 +00:00
$scope . isInvalidLocation = false ;
2014-02-25 01:36:54 +00:00
return ;
}
$scope . locationError = null ;
$scope . locations = resp [ 'subdir' ] || [ ] ;
$scope . trigger . $ready = true ;
2014-02-25 20:25:24 +00:00
if ( $scope . locations . length > 0 ) {
$scope . setLocation ( $scope . locations [ 0 ] ) ;
} else {
$scope . currentLocation = null ;
$scope . isInvalidLocation = resp [ 'subdir' ] . indexOf ( '' ) < 0 ;
}
2014-02-25 01:36:54 +00:00
} , function ( resp ) {
$scope . locationError = resp [ 'message' ] || 'Could not load Dockerfile locations' ;
$scope . locations = null ;
$scope . trigger . $ready = false ;
2014-02-25 05:42:33 +00:00
$scope . isInvalidLocation = false ;
2014-02-25 01:36:54 +00:00
} ) ;
}
2014-02-20 23:57:49 +00:00
} ;
2014-02-25 01:36:54 +00:00
var setupTypeahead = function ( ) {
2014-02-20 23:57:49 +00:00
var repos = [ ] ;
for ( var i = 0 ; i < $scope . orgs . length ; ++ i ) {
var org = $scope . orgs [ i ] ;
var orepos = org [ 'repos' ] ;
for ( var j = 0 ; j < orepos . length ; ++ j ) {
2014-02-25 01:36:54 +00:00
var repoValue = {
'repo' : orepos [ j ] ,
'avatar_url' : org [ 'info' ] [ 'avatar_url' ] ,
'toString' : function ( ) {
return this . repo ;
}
} ;
var datum = {
'name' : orepos [ j ] ,
'org' : org ,
'value' : orepos [ j ] ,
'title' : orepos [ j ] ,
'item' : repoValue
} ;
repos . push ( datum ) ;
2014-02-20 23:57:49 +00:00
}
}
2014-02-25 01:36:54 +00:00
$scope . repoLookahead = repos ;
2014-02-20 23:57:49 +00:00
} ;
var loadSources = function ( ) {
var params = {
'repository' : $scope . repository . namespace + '/' + $scope . repository . name ,
'trigger_uuid' : $scope . trigger . id
} ;
ApiService . listTriggerBuildSources ( null , params ) . then ( function ( resp ) {
$scope . orgs = resp [ 'sources' ] ;
setupTypeahead ( ) ;
$scope . loading = false ;
} ) ;
} ;
loadSources ( ) ;
2014-02-25 01:36:54 +00:00
$scope . $watch ( 'currentRepo' , function ( repo ) {
$scope . selectRepoInternal ( repo ) ;
2014-02-20 23:57:49 +00:00
} ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-13 02:16:11 +00:00
quayApp . directive ( 'buildLogCommand' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/build-log-command.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'command' : '=command'
} ,
2014-02-17 23:31:45 +00:00
controller : function ( $scope , $element ) {
$scope . getWithoutStep = function ( fullTitle ) {
var colon = fullTitle . indexOf ( ':' ) ;
if ( colon <= 0 ) {
return '' ;
}
return $ . trim ( fullTitle . substring ( colon + 1 ) ) ;
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
quayApp . directive ( 'dockerfileCommand' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/dockerfile-command.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'command' : '=command'
} ,
2014-02-13 02:16:11 +00:00
controller : function ( $scope , $element , $sanitize ) {
var registryHandlers = {
'quay.io' : function ( pieces ) {
var rnamespace = pieces [ pieces . length - 2 ] ;
2014-02-17 23:31:45 +00:00
var rname = pieces [ pieces . length - 1 ] . split ( ':' ) [ 0 ] ;
2014-02-13 02:16:11 +00:00
return '/repository/' + rnamespace + '/' + rname + '/' ;
} ,
'' : function ( pieces ) {
var rnamespace = pieces . length == 1 ? '_' : pieces [ 0 ] ;
2014-02-17 23:31:45 +00:00
var rname = pieces [ pieces . length - 1 ] . split ( ':' ) [ 0 ] ;
2014-02-13 02:32:46 +00:00
return 'https://index.docker.io/u/' + rnamespace + '/' + rname + '/' ;
2014-02-13 02:16:11 +00:00
}
} ;
var kindHandlers = {
'FROM' : function ( title ) {
var pieces = title . split ( '/' ) ;
2014-02-13 02:32:46 +00:00
var registry = pieces . length < 3 ? '' : pieces [ 0 ] ;
2014-02-13 02:16:11 +00:00
if ( ! registryHandlers [ registry ] ) {
return title ;
}
2014-02-13 20:08:10 +00:00
return '<i class="fa fa-hdd-o"></i> <a href="' + registryHandlers [ registry ] ( pieces ) + '" target="_blank">' + title + '</a>' ;
2014-02-13 02:16:11 +00:00
}
} ;
2014-02-17 23:31:45 +00:00
$scope . getCommandKind = function ( title ) {
2014-02-13 02:16:11 +00:00
var space = title . indexOf ( ' ' ) ;
return title . substring ( 0 , space ) ;
} ;
2014-02-17 23:31:45 +00:00
$scope . getCommandTitleHtml = function ( title ) {
2014-02-13 02:16:11 +00:00
var space = title . indexOf ( ' ' ) ;
if ( space <= 0 ) {
return $sanitize ( title ) ;
}
2014-02-17 23:31:45 +00:00
var kind = $scope . getCommandKind ( title ) ;
2014-02-13 02:16:11 +00:00
var sanitized = $sanitize ( title . substring ( space + 1 ) ) ;
var handler = kindHandlers [ kind || '' ] ;
if ( handler ) {
return handler ( sanitized ) ;
} else {
return sanitized ;
}
2014-02-17 23:31:45 +00:00
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-13 02:16:11 +00:00
2014-02-17 23:31:45 +00:00
quayApp . directive ( 'dockerfileView' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/dockerfile-view.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'contents' : '=contents'
} ,
controller : function ( $scope , $element , $sanitize ) {
$scope . $watch ( 'contents' , function ( contents ) {
$scope . lines = [ ] ;
var lines = contents ? contents . split ( '\n' ) : [ ] ;
for ( var i = 0 ; i < lines . length ; ++ i ) {
var line = $ . trim ( lines [ i ] ) ;
var kind = 'text' ;
if ( line && line [ 0 ] == '#' ) {
kind = 'comment' ;
} else if ( line . match ( /^([A-Z]+\s)/ ) ) {
kind = 'command' ;
}
var lineInfo = {
'text' : $sanitize ( line ) ,
'kind' : kind
} ;
$scope . lines . push ( lineInfo ) ;
2014-02-13 02:16:11 +00:00
}
2014-02-17 23:31:45 +00:00
} ) ;
2014-02-13 02:16:11 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-17 23:31:45 +00:00
2013-10-26 20:03:11 +00:00
quayApp . directive ( 'buildStatus' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/build-status.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'build' : '=build'
} ,
controller : function ( $scope , $element ) {
2014-02-10 20:15:23 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
quayApp . directive ( 'buildMessage' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/build-message.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
2014-02-13 02:16:11 +00:00
'phase' : '=phase'
2014-02-10 20:15:23 +00:00
} ,
controller : function ( $scope , $element ) {
2014-02-13 02:16:11 +00:00
$scope . getBuildMessage = function ( phase ) {
switch ( phase ) {
2014-02-10 20:15:23 +00:00
case 'starting' :
case 'initializing' :
return 'Starting Dockerfile build' ;
case 'waiting' :
2014-02-13 02:16:11 +00:00
return 'Waiting for available build worker' ;
2014-02-10 20:15:23 +00:00
case 'building' :
return 'Building image from Dockerfile' ;
case 'pushing' :
return 'Pushing image built from Dockerfile' ;
2013-10-26 20:03:11 +00:00
2014-02-10 20:15:23 +00:00
case 'complete' :
return 'Dockerfile build completed and pushed' ;
case 'error' :
2014-02-13 02:16:11 +00:00
return 'Dockerfile build failed' ;
2014-02-10 20:15:23 +00:00
}
} ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-10-26 20:03:11 +00:00
2014-02-10 20:15:23 +00:00
quayApp . directive ( 'buildProgress' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/build-progress.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'build' : '=build'
} ,
controller : function ( $scope , $element ) {
$scope . getPercentage = function ( buildInfo ) {
2014-02-06 00:59:57 +00:00
switch ( buildInfo . phase ) {
case 'building' :
return ( buildInfo . status . current _command / buildInfo . status . total _commands ) * 100 ;
break ;
2013-10-26 20:03:11 +00:00
2014-02-06 00:59:57 +00:00
case 'pushing' :
return buildInfo . status . push _completion * 100 ;
break ;
2013-10-26 20:03:11 +00:00
2014-02-06 00:59:57 +00:00
case 'complete' :
return 100 ;
break ;
case 'initializing' :
case 'starting' :
case 'waiting' :
return 0 ;
break ;
}
return - 1 ;
} ;
2013-10-22 05:26:14 +00:00
}
} ;
return directiveDefinitionObject ;
} ) ;
2014-02-15 03:59:44 +00:00
quayApp . directive ( 'dockerfileBuildDialog' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/dockerfile-build-dialog.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'repository' : '=repository' ,
'showNow' : '=showNow' ,
'buildStarted' : '&buildStarted'
} ,
controller : function ( $scope , $element ) {
$scope . building = false ;
$scope . uploading = false ;
$scope . startCounter = 0 ;
$scope . handleBuildStarted = function ( build ) {
$ ( '#dockerfilebuildModal' ) . modal ( 'hide' ) ;
if ( $scope . buildStarted ) {
$scope . buildStarted ( { 'build' : build } ) ;
}
} ;
$scope . handleBuildFailed = function ( message ) {
$scope . errorMessage = message ;
} ;
$scope . startBuild = function ( ) {
$scope . errorMessage = null ;
$scope . startCounter ++ ;
} ;
$scope . $watch ( 'showNow' , function ( sn ) {
if ( sn && $scope . repository ) {
$ ( '#dockerfilebuildModal' ) . modal ( { } ) ;
}
} ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
quayApp . directive ( 'dockerfileBuildForm' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/dockerfile-build-form.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'repository' : '=repository' ,
'startNow' : '=startNow' ,
'hasDockerfile' : '=hasDockerfile' ,
'uploadFailed' : '&uploadFailed' ,
'uploadStarted' : '&uploadStarted' ,
'buildStarted' : '&buildStarted' ,
'buildFailed' : '&buildFailed' ,
'missingFile' : '&missingFile' ,
'uploading' : '=uploading' ,
'building' : '=building'
} ,
controller : function ( $scope , $element , ApiService ) {
$scope . internal = { 'hasDockerfile' : false } ;
var handleBuildFailed = function ( message ) {
message = message || 'Dockerfile build failed to start' ;
var result = false ;
if ( $scope . buildFailed ) {
result = $scope . buildFailed ( { 'message' : message } ) ;
}
if ( ! result ) {
bootbox . dialog ( {
"message" : message ,
"title" : "Cannot start Dockerfile build" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
}
} ;
var handleUploadFailed = function ( message ) {
message = message || 'Error with file upload' ;
var result = false ;
if ( $scope . uploadFailed ) {
result = $scope . uploadFailed ( { 'message' : message } ) ;
}
if ( ! result ) {
bootbox . dialog ( {
"message" : message ,
"title" : "Cannot upload file for Dockerfile build" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
}
} ;
var handleMissingFile = function ( ) {
var result = false ;
if ( $scope . missingFile ) {
result = $scope . missingFile ( { } ) ;
}
if ( ! result ) {
bootbox . dialog ( {
"message" : 'A Dockerfile or an archive containing a Dockerfile is required' ,
"title" : "Missing Dockerfile" ,
"buttons" : {
"close" : {
"label" : "Close" ,
"className" : "btn-primary"
}
}
} ) ;
}
} ;
var startBuild = function ( fileId ) {
$scope . building = true ;
var repo = $scope . repository ;
var data = {
'file_id' : fileId
} ;
var params = {
'repository' : repo . namespace + '/' + repo . name
} ;
ApiService . requestRepoBuild ( data , params ) . then ( function ( resp ) {
$scope . building = false ;
$scope . uploading = false ;
if ( $scope . buildStarted ) {
$scope . buildStarted ( { 'build' : resp } ) ;
}
} , function ( resp ) {
$scope . building = false ;
$scope . uploading = false ;
handleBuildFailed ( resp . message ) ;
} ) ;
} ;
var conductUpload = function ( file , url , fileId , mimeType ) {
if ( $scope . uploadStarted ) {
$scope . uploadStarted ( { } ) ;
}
var request = new XMLHttpRequest ( ) ;
request . open ( 'PUT' , url , true ) ;
request . setRequestHeader ( 'Content-Type' , mimeType ) ;
request . onprogress = function ( e ) {
$scope . $apply ( function ( ) {
var percentLoaded ;
if ( e . lengthComputable ) {
$scope . upload _progress = ( e . loaded / e . total ) * 100 ;
}
} ) ;
} ;
request . onerror = function ( ) {
$scope . $apply ( function ( ) {
handleUploadFailed ( ) ;
} ) ;
} ;
request . onreadystatechange = function ( ) {
var state = request . readyState ;
if ( state == 4 ) {
$scope . $apply ( function ( ) {
startBuild ( fileId ) ;
$scope . uploading = false ;
} ) ;
return ;
}
} ;
request . send ( file ) ;
} ;
var startFileUpload = function ( repo ) {
$scope . uploading = true ;
$scope . uploading _progress = 0 ;
var uploader = $ ( '#file-drop' ) [ 0 ] ;
if ( uploader . files . length == 0 ) {
handleMissingFile ( ) ;
$scope . uploading = false ;
return ;
}
var file = uploader . files [ 0 ] ;
$scope . upload _file = file . name ;
var mimeType = file . type || 'application/octet-stream' ;
var data = {
'mimeType' : mimeType
} ;
var getUploadUrl = ApiService . getFiledropUrl ( data ) . then ( function ( resp ) {
conductUpload ( file , resp . url , resp . file _id , mimeType ) ;
} , function ( ) {
handleUploadFailed ( 'Could not retrieve upload URL' ) ;
} ) ;
} ;
$scope . $watch ( 'internal.hasDockerfile' , function ( d ) {
$scope . hasDockerfile = d ;
} ) ;
$scope . $watch ( 'startNow' , function ( ) {
if ( $scope . startNow && $scope . repository && ! $scope . uploading && ! $scope . building ) {
startFileUpload ( ) ;
}
} ) ;
}
} ;
return directiveDefinitionObject ;
} ) ;
2013-11-05 22:20:43 +00:00
// Note: ngBlur is not yet in Angular stable, so we add it manaully here.
quayApp . directive ( 'ngBlur' , function ( ) {
return function ( scope , elem , attrs ) {
elem . bind ( 'blur' , function ( ) {
scope . $apply ( attrs . ngBlur ) ;
} ) ;
} ;
} ) ;
2014-02-15 03:59:44 +00:00
quayApp . directive ( "filePresent" , [ function ( ) {
return {
restrict : 'A' ,
scope : {
'filePresent' : "="
} ,
link : function ( scope , element , attributes ) {
element . bind ( "change" , function ( changeEvent ) {
scope . $apply ( function ( ) {
scope . filePresent = changeEvent . target . files . length > 0 ;
} ) ;
} ) ;
}
}
} ] ) ;
2014-02-10 06:18:14 +00:00
quayApp . directive ( 'ngVisible' , function ( ) {
return function ( scope , element , attr ) {
scope . $watch ( attr . ngVisible , function ( visible ) {
element . css ( 'visibility' , visible ? 'visible' : 'hidden' ) ;
} ) ;
} ;
} ) ;
2014-02-05 01:50:13 +00:00
2013-12-17 20:03:34 +00:00
quayApp . run ( [ '$location' , '$rootScope' , 'Restangular' , 'UserService' , 'PlanService' , '$http' , '$timeout' ,
function ( $location , $rootScope , Restangular , UserService , PlanService , $http , $timeout ) {
2013-12-28 19:07:44 +00:00
// Handle session security.
2014-01-27 18:58:12 +00:00
Restangular . setDefaultRequestParams ( [ 'post' , 'put' , 'remove' , 'delete' ] , { '_csrf_token' : window . _ _token || '' } ) ;
2013-12-28 19:07:44 +00:00
2013-12-11 22:50:48 +00:00
// Handle session expiration.
2013-11-12 00:26:56 +00:00
Restangular . setErrorInterceptor ( function ( response ) {
if ( response . status == 401 ) {
$ ( '#sessionexpiredModal' ) . modal ( { } ) ;
return false ;
2013-11-12 00:03:18 +00:00
}
2013-11-12 00:26:56 +00:00
return true ;
2013-11-12 00:03:18 +00:00
} ) ;
2013-12-11 22:50:48 +00:00
// Check if we need to redirect based on a previously chosen plan.
PlanService . handleNotedPlan ( ) ;
2013-12-21 03:38:53 +00:00
var changeTab = function ( activeTab , opt _timeout ) {
var checkCount = 0 ;
2013-12-10 04:33:28 +00:00
$timeout ( function ( ) {
2013-12-21 03:38:53 +00:00
if ( checkCount > 5 ) { return ; }
checkCount ++ ;
2013-12-10 04:33:28 +00:00
$ ( 'a[data-toggle="tab"]' ) . each ( function ( index ) {
var tabName = this . getAttribute ( 'data-target' ) . substr ( 1 ) ;
2013-12-21 03:38:53 +00:00
if ( tabName != activeTab ) {
return ;
}
if ( this . clientWidth == 0 ) {
changeTab ( activeTab , 500 ) ;
return ;
2013-12-10 04:33:28 +00:00
}
2013-12-21 03:38:53 +00:00
2014-01-10 01:17:28 +00:00
clickElement ( this ) ;
2013-12-10 04:33:28 +00:00
} ) ;
2013-12-21 03:38:53 +00:00
} , opt _timeout ) ;
2013-12-10 04:33:28 +00:00
} ;
var resetDefaultTab = function ( ) {
$timeout ( function ( ) {
$ ( 'a[data-toggle="tab"]' ) . each ( function ( index ) {
if ( index == 0 ) {
2014-01-10 01:17:28 +00:00
clickElement ( this ) ;
2013-12-10 04:33:28 +00:00
}
} ) ;
} ) ;
} ;
$rootScope . $on ( '$routeUpdate' , function ( ) {
if ( $location . search ( ) [ 'tab' ] ) {
changeTab ( $location . search ( ) [ 'tab' ] ) ;
} else {
resetDefaultTab ( ) ;
}
} ) ;
2013-09-26 23:07:25 +00:00
$rootScope . $on ( '$routeChangeSuccess' , function ( event , current , previous ) {
if ( current . $$route . title ) {
$rootScope . title = current . $$route . title ;
}
2013-11-19 00:03:35 +00:00
if ( current . $$route . description ) {
$rootScope . description = current . $$route . description ;
} else {
$rootScope . description = 'Hosted private docker repositories. Includes full user management and history. Free for public repositories.' ;
}
2013-11-20 21:17:47 +00:00
2013-11-24 01:03:08 +00:00
$rootScope . fixFooter = ! ! current . $$route . fixFooter ;
2013-12-10 04:33:28 +00:00
$rootScope . current = current . $$route ;
} ) ;
$rootScope . $on ( '$viewContentLoaded' , function ( event , current ) {
var activeTab = $location . search ( ) [ 'tab' ] ;
// Setup deep linking of tabs. This will change the search field of the URL whenever a tab
// is changed in the UI.
$ ( 'a[data-toggle="tab"]' ) . on ( 'shown.bs.tab' , function ( e ) {
var tabName = e . target . getAttribute ( 'data-target' ) . substr ( 1 ) ;
$rootScope . $apply ( function ( ) {
var isDefaultTab = $ ( 'a[data-toggle="tab"]' ) [ 0 ] == e . target ;
2014-02-20 23:57:49 +00:00
var newSearch = $ . extend ( $location . search ( ) , { } ) ;
if ( isDefaultTab ) {
delete newSearch [ 'tab' ] ;
} else {
newSearch [ 'tab' ] = tabName ;
}
$location . search ( newSearch ) ;
2013-12-10 04:33:28 +00:00
} ) ;
e . preventDefault ( ) ;
} ) ;
if ( activeTab ) {
changeTab ( activeTab ) ;
}
2013-09-26 23:07:25 +00:00
} ) ;
2013-11-18 22:11:06 +00:00
var initallyChecked = false ;
window . _ _isLoading = function ( ) {
if ( ! initallyChecked ) {
initallyChecked = true ;
return true ;
}
return $http . pendingRequests . length > 0 ;
} ;
2013-09-27 20:12:51 +00:00
} ] ) ;