2018-01-22 13:01:38 -08:00
'use strict' ;
2019-01-22 10:54:03 +01:00
/* global angular:false */
/* global $:false */
2019-05-04 21:57:42 -07:00
angular . module ( 'Application' ) . controller ( 'AppStoreController' , [ '$scope' , '$location' , '$timeout' , '$routeParams' , 'Client' , function ( $scope , $location , $timeout , $routeParams , Client ) {
2019-05-04 18:40:10 -07:00
Client . onReady ( function ( ) { if ( ! Client . getUserInfo ( ) . admin ) $location . path ( '/' ) ; } ) ;
2018-01-22 13:01:38 -08:00
$scope . HOST _PORT _MIN = 1024 ;
$scope . HOST _PORT _MAX = 65535 ;
$scope . ready = false ;
$scope . apps = [ ] ;
$scope . config = Client . getConfig ( ) ;
$scope . user = Client . getUserInfo ( ) ;
$scope . users = [ ] ;
$scope . groups = [ ] ;
$scope . domains = [ ] ;
$scope . category = '' ;
$scope . cachedCategory = '' ; // used to cache the selected category while searching
$scope . searchString = '' ;
2019-05-04 21:57:42 -07:00
$scope . validSubscription = false ;
2019-04-29 14:58:42 +02:00
$scope . unstableApps = false ;
2019-05-04 21:57:42 -07:00
$scope . subscription = { } ;
2018-01-22 13:01:38 -08:00
$scope . showView = function ( view ) {
// wait for dialog to be fully closed to avoid modal behavior breakage when moving to a different view already
$ ( '.modal' ) . on ( 'hidden.bs.modal' , function ( ) {
$scope . $apply ( function ( ) {
$scope . appInstall . reset ( ) ;
$ ( '.modal' ) . off ( 'hidden.bs.modal' ) ;
$location . path ( view ) ;
} ) ;
} ) ;
$ ( '.modal' ) . modal ( 'hide' ) ;
} ;
$scope . appInstall = {
busy : false ,
state : 'appInfo' ,
2019-08-14 16:38:02 +02:00
subscriptionHelperPage : '' ,
2018-01-22 13:01:38 -08:00
error : { } ,
app : { } ,
2019-09-23 23:47:33 +02:00
overwriteDns : false ,
2018-01-22 13:01:38 -08:00
location : '' ,
domain : null ,
portBindings : { } ,
mediaLinks : [ ] ,
certificateFile : null ,
certificateFileName : '' ,
keyFile : null ,
keyFileName : '' ,
accessRestrictionOption : 'any' ,
accessRestriction : { users : [ ] , groups : [ ] } ,
customAuth : false ,
optionalSso : false ,
2018-09-05 17:13:59 +02:00
subscriptionErrorMesssage : '' ,
2018-01-22 13:01:38 -08:00
isAccessRestrictionValid : function ( ) {
var tmp = $scope . appInstall . accessRestriction ;
return ! ! ( tmp . users . length || tmp . groups . length ) ;
} ,
reset : function ( ) {
$scope . appInstall . app = { } ;
$scope . appInstall . error = { } ;
2019-09-23 23:47:33 +02:00
$scope . appInstall . overwriteDns = false ;
2018-01-22 13:01:38 -08:00
$scope . appInstall . location = '' ;
$scope . appInstall . domain = null ;
$scope . appInstall . portBindings = { } ;
$scope . appInstall . state = 'appInfo' ;
2019-08-14 16:38:02 +02:00
$scope . appInstall . subscriptionHelperPage = '' ;
2018-01-22 13:01:38 -08:00
$scope . appInstall . mediaLinks = [ ] ;
$scope . appInstall . certificateFile = null ;
$scope . appInstall . certificateFileName = '' ;
$scope . appInstall . keyFile = null ;
$scope . appInstall . keyFileName = '' ;
$scope . appInstall . accessRestrictionOption = 'any' ;
$scope . appInstall . accessRestriction = { users : [ ] , groups : [ ] } ;
$scope . appInstall . optionalSso = false ;
$scope . appInstall . customAuth = false ;
2018-09-05 17:13:59 +02:00
$scope . appInstall . subscriptionErrorMesssage = '' ;
2018-01-22 13:01:38 -08:00
$ ( '#collapseInstallForm' ) . collapse ( 'hide' ) ;
$ ( '#collapseResourceConstraint' ) . collapse ( 'hide' ) ;
2019-08-14 16:38:02 +02:00
$ ( '#collapseSubscriptionRequired' ) . collapse ( 'hide' ) ;
2018-05-28 20:26:18 +02:00
$ ( '#collapseMediaLinksCarousel' ) . collapse ( 'show' ) ;
2018-01-22 13:01:38 -08:00
if ( $scope . appInstallForm ) {
$scope . appInstallForm . $setPristine ( ) ;
$scope . appInstallForm . $setUntouched ( ) ;
}
} ,
showForm : function ( force ) {
if ( Client . enoughResourcesAvailable ( $scope . appInstall . app ) || force ) {
$scope . appInstall . state = 'installForm' ;
$ ( '#collapseMediaLinksCarousel' ) . collapse ( 'hide' ) ;
$ ( '#collapseResourceConstraint' ) . collapse ( 'hide' ) ;
$ ( '#collapseInstallForm' ) . collapse ( 'show' ) ;
$ ( '#appInstallLocationInput' ) . focus ( ) ;
} else {
$scope . appInstall . state = 'resourceConstraint' ;
$ ( '#collapseMediaLinksCarousel' ) . collapse ( 'hide' ) ;
$ ( '#collapseResourceConstraint' ) . collapse ( 'show' ) ;
}
} ,
2018-08-03 22:04:06 -07:00
show : function ( app ) { // this is an appstore app object!
2018-01-22 13:01:38 -08:00
$scope . appInstall . reset ( ) ;
// make a copy to work with in case the app object gets updated while polling
angular . copy ( app , $scope . appInstall . app ) ;
$scope . appInstall . mediaLinks = $scope . appInstall . app . manifest . mediaLinks || [ ] ;
2019-09-23 23:47:33 +02:00
$scope . appInstall . overwriteDns = false ;
2018-03-13 09:38:55 +01:00
$scope . appInstall . domain = $scope . domains . find ( function ( d ) { return $scope . config . adminDomain === d . domain ; } ) ; // pre-select the adminDomain
2018-08-13 08:38:47 -07:00
$scope . appInstall . portBindingsInfo = angular . extend ( { } , $scope . appInstall . app . manifest . tcpPorts , $scope . appInstall . app . manifest . udpPorts ) ; // Portbinding map only for information
2018-01-22 13:01:38 -08:00
$scope . appInstall . portBindings = { } ; // This is the actual model holding the env:port pair
$scope . appInstall . portBindingsEnabled = { } ; // This is the actual model holding the enabled/disabled flag
var manifest = app . manifest ;
$scope . appInstall . optionalSso = ! ! manifest . optionalSso ;
$scope . appInstall . customAuth = ! ( manifest . addons [ 'ldap' ] || manifest . addons [ 'oauth' ] ) ;
2018-08-03 22:19:07 -07:00
// for spaces users, the User management is hidden. thus the admin flag check
if ( ! $scope . user . admin ) {
2018-08-13 08:38:47 -07:00
// just install it with access restriction as just the user
var me = $scope . users . find ( function ( u ) { return u . id === $scope . user . id ; } ) ;
$scope . appInstall . accessRestrictionOption = 'groups' ;
$scope . appInstall . accessRestriction = { users : [ me ] , groups : [ ] } ;
2018-08-03 22:19:07 -07:00
} else {
$scope . appInstall . accessRestrictionOption = 'any' ;
$scope . appInstall . accessRestriction = { users : [ ] , groups : [ ] } ;
}
2018-01-22 13:01:38 -08:00
// set default ports
2018-08-13 08:38:47 -07:00
var allPorts = angular . extend ( { } , $scope . appInstall . app . manifest . tcpPorts , $scope . appInstall . app . manifest . udpPorts ) ;
for ( var env in allPorts ) {
$scope . appInstall . portBindings [ env ] = allPorts [ env ] . defaultValue || 0 ;
2018-01-22 13:01:38 -08:00
$scope . appInstall . portBindingsEnabled [ env ] = true ;
}
$ ( '#appInstallModal' ) . modal ( 'show' ) ;
} ,
submit : function ( ) {
$scope . appInstall . busy = true ;
$scope . appInstall . error . other = null ;
$scope . appInstall . error . location = null ;
$scope . appInstall . error . port = null ;
// only use enabled ports from portBindings
var finalPortBindings = { } ;
for ( var env in $scope . appInstall . portBindings ) {
if ( $scope . appInstall . portBindingsEnabled [ env ] ) {
finalPortBindings [ env ] = $scope . appInstall . portBindings [ env ] ;
}
}
var finalAccessRestriction = null ;
if ( $scope . appInstall . accessRestrictionOption === 'groups' ) {
finalAccessRestriction = { users : [ ] , groups : [ ] } ;
finalAccessRestriction . users = $scope . appInstall . accessRestriction . users . map ( function ( u ) { return u . id ; } ) ;
finalAccessRestriction . groups = $scope . appInstall . accessRestriction . groups . map ( function ( g ) { return g . id ; } ) ;
}
var data = {
2019-09-23 23:47:33 +02:00
overwriteDns : $scope . appInstall . overwriteDns ,
2018-01-22 13:01:38 -08:00
location : $scope . appInstall . location || '' ,
domain : $scope . appInstall . domain . domain ,
portBindings : finalPortBindings ,
accessRestriction : finalAccessRestriction ,
cert : $scope . appInstall . certificateFile ,
key : $scope . appInstall . keyFile ,
sso : ! $scope . appInstall . optionalSso ? undefined : ( $scope . appInstall . accessRestrictionOption !== 'nosso' )
} ;
2019-09-23 23:47:33 +02:00
Client . getDNSRecords ( data . domain , data . location , function ( error , result ) {
if ( error ) return Client . error ( error ) ;
if ( ! data . overwriteDns ) {
if ( result . error || result . needsOverwrite ) {
$scope . appInstall . error . location = result . error ? result . error . message : 'DNS Record already exists outside of Cloudron' ;
$scope . appInstall . busy = false ;
$scope . appInstallForm . location . $setPristine ( ) ;
$ ( '#appInstallLocationInput' ) . focus ( ) ;
return ;
}
}
Client . installApp ( $scope . appInstall . app . id , $scope . appInstall . app . manifest , $scope . appInstall . app . title , data , function ( error , newAppId ) {
if ( error ) {
if ( error . statusCode === 402 ) {
$scope . appInstall . state = 'subscriptionRequired' ;
$scope . appInstall . subscriptionErrorMesssage = error . message ;
$ ( '#collapseMediaLinksCarousel' ) . collapse ( 'hide' ) ;
$ ( '#collapseResourceConstraint' ) . collapse ( 'hide' ) ;
$ ( '#collapseInstallForm' ) . collapse ( 'hide' ) ;
$ ( '#collapseSubscriptionRequired' ) . collapse ( 'show' ) ;
if ( error . message . indexOf ( 'Upgrade to the premium' ) === 0 ) {
$scope . appInstall . subscriptionHelperPage = 'app_install_premium_subscription_required.html' ;
} else if ( error . message . indexOf ( 'The subscription for this Cloudron has expired.' ) === 0 ) {
$scope . appInstall . subscriptionHelperPage = 'app_install_subscription_expired.html' ;
} else {
$scope . appInstall . subscriptionHelperPage = 'app_install_subscription_required.html' ;
}
} else if ( error . statusCode === 409 ) {
if ( error . portName ) {
$scope . appInstall . error . port = error . message ;
} else if ( error . domain ) {
$scope . appInstall . error . location = error . message ;
$scope . appInstallForm . location . $setPristine ( ) ;
$ ( '#appInstallLocationInput' ) . focus ( ) ;
} else {
$scope . appInstall . error . other = error . message ;
}
} else if ( error . statusCode === 400 ) {
if ( error . field === 'cert' ) {
$scope . appInstall . error . cert = error . message ;
$scope . appInstall . certificateFileName = '' ;
$scope . appInstall . certificateFile = null ;
$scope . appInstall . keyFileName = '' ;
$scope . appInstall . keyFile = null ;
} else {
$scope . appInstall . error . other = error . message ;
}
2019-09-01 21:38:30 -07:00
} else {
$scope . appInstall . error . other = error . message ;
}
2019-09-23 23:47:33 +02:00
$scope . appInstall . busy = false ;
return ;
2018-01-22 13:01:38 -08:00
}
$scope . appInstall . busy = false ;
2019-09-23 23:47:33 +02:00
// stash new app id for later
$scope . appInstall . app . id = newAppId ;
2018-06-14 15:46:55 +02:00
2019-09-23 23:47:33 +02:00
// we track the postinstall confirmation for the current user's browser
// TODO later we might want to have a notification db to track the state across admins and browsers
if ( $scope . appInstall . app . manifest . postInstallMessage ) {
localStorage [ 'confirmPostInstall_' + $scope . appInstall . app . id ] = true ;
}
2018-01-22 13:01:38 -08:00
2019-09-23 23:47:33 +02:00
// wait for dialog to be fully closed to avoid modal behavior breakage when moving to a different view already
$ ( '#appInstallModal' ) . on ( 'hidden.bs.modal' , function ( ) {
$scope . $apply ( function ( ) {
$location . path ( '/apps' ) . search ( { } ) ;
} ) ;
2018-06-14 16:07:27 +02:00
} ) ;
2018-01-22 13:01:38 -08:00
2019-09-23 23:47:33 +02:00
$ ( '#appInstallModal' ) . modal ( 'hide' ) ;
} ) ;
2018-06-14 16:07:27 +02:00
} ) ;
2018-01-22 13:01:38 -08:00
}
} ;
$scope . appNotFound = {
appId : '' ,
version : ''
} ;
$scope . appstoreLogin = {
busy : false ,
error : { } ,
email : '' ,
password : '' ,
2018-04-22 18:52:37 +02:00
totpToken : '' ,
2018-01-22 13:01:38 -08:00
register : true ,
termsAccepted : false ,
submit : function ( ) {
$scope . appstoreLogin . error = { } ;
$scope . appstoreLogin . busy = true ;
2019-05-05 13:02:23 -07:00
Client . registerCloudron ( $scope . appstoreLogin . email , $scope . appstoreLogin . password , $scope . appstoreLogin . totpToken , $scope . appstoreLogin . register , function ( error ) {
2018-01-22 13:01:38 -08:00
if ( error ) {
$scope . appstoreLogin . busy = false ;
if ( error . statusCode === 409 ) {
$scope . appstoreLogin . error . email = 'An account with this email already exists' ;
$scope . appstoreLogin . password = '' ;
$scope . appstoreLoginForm . email . $setPristine ( ) ;
$scope . appstoreLoginForm . password . $setPristine ( ) ;
$ ( '#inputAppstoreLoginEmail' ) . focus ( ) ;
2019-05-04 21:57:42 -07:00
} else if ( error . statusCode === 412 ) {
if ( error . message . indexOf ( 'TOTP token missing' ) !== - 1 ) {
$scope . appstoreLogin . error . totpToken = 'A 2FA token is required' ;
setTimeout ( function ( ) { $ ( '#inputAppstoreLoginTotpToken' ) . focus ( ) ; } , 0 ) ;
} else if ( error . message . indexOf ( 'TOTP token invalid' ) !== - 1 ) {
$scope . appstoreLogin . error . totpToken = 'Wrong 2FA token' ;
$scope . appstoreLogin . totpToken = '' ;
setTimeout ( function ( ) { $ ( '#inputAppstoreLoginTotpToken' ) . focus ( ) ; } , 0 ) ;
} else {
$scope . appstoreLogin . error . password = 'Wrong email or password' ;
$scope . appstoreLogin . password = '' ;
$ ( '#inputAppstoreLoginPassword' ) . focus ( ) ;
$scope . appstoreLoginForm . password . $setPristine ( ) ;
}
} else if ( error . statusCode === 424 ) {
if ( error . message === 'wrong user' ) {
$scope . appstoreLogin . error . generic = 'Wrong cloudron.io account' ;
$scope . appstoreLogin . email = '' ;
$scope . appstoreLogin . password = '' ;
$scope . appstoreLoginForm . email . $setPristine ( ) ;
$scope . appstoreLoginForm . password . $setPristine ( ) ;
$ ( '#inputAppstoreLoginEmail' ) . focus ( ) ;
} else {
console . error ( error ) ;
$scope . appstoreLogin . error . generic = error . message ;
}
2018-01-22 13:01:38 -08:00
} else {
console . error ( error ) ;
2019-05-06 20:05:12 -07:00
$scope . appstoreLogin . error . generic = error . message || 'Please retry later' ;
2018-01-22 13:01:38 -08:00
}
return ;
}
2019-05-05 07:46:06 -07:00
2019-05-05 11:13:29 -07:00
getSubscription ( function ( error ) {
if ( error ) return console . error ( error ) ;
2019-05-05 11:46:33 -07:00
onSubscribed ( function ( error ) { if ( error ) console . error ( error ) ; } ) ;
2019-05-05 11:13:29 -07:00
} ) ;
2018-01-22 13:01:38 -08:00
} ) ;
}
} ;
2019-05-05 11:46:33 -07:00
function onSubscribed ( callback ) {
2019-05-05 07:46:06 -07:00
Client . getAppstoreApps ( function ( error ) {
2019-05-05 11:46:33 -07:00
if ( error ) return callback ( error ) ;
2018-01-22 13:01:38 -08:00
2019-05-05 07:46:06 -07:00
// start with featured apps listing. this also sets $scope.apps accordingly
$scope . showCategory ( null , 'featured' ) ;
2019-05-05 11:46:33 -07:00
// do this in background
fetchUsers ( ) ;
fetchGroups ( ) ;
2019-05-05 07:46:06 -07:00
// domains is required since we populate the dropdown with domains[0]
Client . getDomains ( function ( error , result ) {
2019-05-05 11:46:33 -07:00
if ( error ) return callback ( error ) ;
2019-05-05 07:46:06 -07:00
$scope . domains = result ;
// show install app dialog immediately if an app id was passed in the query
// hashChangeListener calls $apply, so make sure we don't double digest here
setTimeout ( hashChangeListener , 1 ) ;
2019-05-05 07:38:32 -07:00
2019-05-05 07:46:06 -07:00
setTimeout ( function ( ) { $ ( '#appstoreSearch' ) . focus ( ) ; } , 1000 ) ;
2019-05-05 11:46:33 -07:00
callback ( ) ;
2019-05-05 07:46:06 -07:00
} ) ;
2018-01-22 13:01:38 -08:00
} ) ;
}
// TODO does not support testing apps in search
$scope . search = function ( ) {
if ( ! $scope . searchString ) return $scope . showCategory ( null , $scope . cachedCategory ) ;
$scope . category = '' ;
2019-05-04 18:15:33 -07:00
Client . getAppstoreAppsFast ( function ( error , apps ) {
2018-01-22 13:01:38 -08:00
if ( error ) return $timeout ( $scope . search , 1000 ) ;
var token = $scope . searchString . toUpperCase ( ) ;
$scope . apps = apps . filter ( function ( app ) {
if ( app . manifest . id . toUpperCase ( ) . indexOf ( token ) !== - 1 ) return true ;
if ( app . manifest . title . toUpperCase ( ) . indexOf ( token ) !== - 1 ) return true ;
if ( app . manifest . tagline . toUpperCase ( ) . indexOf ( token ) !== - 1 ) return true ;
if ( app . manifest . tags . join ( ) . toUpperCase ( ) . indexOf ( token ) !== - 1 ) return true ;
if ( app . manifest . description . toUpperCase ( ) . indexOf ( token ) !== - 1 ) return true ;
return false ;
} ) ;
} ) ;
} ;
$scope . showCategory = function ( event , category ) {
if ( ! event ) $scope . category = category ;
else $scope . category = event . target . getAttribute ( 'category' ) ;
$scope . cachedCategory = $scope . category ;
2019-05-04 18:15:33 -07:00
Client . getAppstoreAppsFast ( function ( error , apps ) {
2018-01-22 13:01:38 -08:00
if ( error ) return $timeout ( $scope . showCategory . bind ( null , event ) , 1000 ) ;
if ( ! $scope . category ) {
$scope . apps = apps ;
2018-06-08 09:48:34 +02:00
} else if ( $scope . category === 'featured' ) {
$scope . apps = apps . filter ( function ( app ) { return app . featured ; } ) ;
2018-01-22 13:01:38 -08:00
} else {
$scope . apps = apps . filter ( function ( app ) {
return app . manifest . tags . some ( function ( tag ) { return $scope . category === tag ; } ) ;
} ) ;
}
2019-05-06 11:47:57 +02:00
if ( document . getElementById ( 'appstoreGrid' ) ) document . getElementById ( 'appstoreGrid' ) . scrollIntoView ( ) ;
2018-01-22 13:01:38 -08:00
} ) ;
} ;
document . getElementById ( 'appInstallCertificateFileInput' ) . onchange = function ( event ) {
$scope . $apply ( function ( ) {
$scope . appInstall . certificateFile = null ;
$scope . appInstall . certificateFileName = event . target . files [ 0 ] . name ;
var reader = new FileReader ( ) ;
reader . onload = function ( result ) {
if ( ! result . target || ! result . target . result ) return console . error ( 'Unable to read local file' ) ;
$scope . appInstall . certificateFile = result . target . result ;
} ;
reader . readAsText ( event . target . files [ 0 ] ) ;
} ) ;
} ;
document . getElementById ( 'appInstallKeyFileInput' ) . onchange = function ( event ) {
$scope . $apply ( function ( ) {
$scope . appInstall . keyFile = null ;
$scope . appInstall . keyFileName = event . target . files [ 0 ] . name ;
var reader = new FileReader ( ) ;
reader . onload = function ( result ) {
if ( ! result . target || ! result . target . result ) return console . error ( 'Unable to read local file' ) ;
$scope . appInstall . keyFile = result . target . result ;
} ;
reader . readAsText ( event . target . files [ 0 ] ) ;
} ) ;
} ;
$scope . showAppNotFound = function ( appId , version ) {
$scope . appNotFound . appId = appId ;
$scope . appNotFound . version = version ;
$ ( '#appNotFoundModal' ) . modal ( 'show' ) ;
} ;
$scope . gotoApp = function ( app ) {
$location . path ( '/appstore/' + app . manifest . id , false ) . search ( { version : app . manifest . version } ) ;
} ;
function hashChangeListener ( ) {
// event listener is called from DOM not angular, need to use $apply
$scope . $apply ( function ( ) {
var appId = $location . path ( ) . slice ( '/appstore/' . length ) ;
var version = $location . search ( ) . version ;
if ( appId ) {
2019-05-04 18:15:33 -07:00
Client . getAppstoreAppByIdAndVersion ( appId , version || 'latest' , function ( error , result ) {
2019-04-29 14:58:42 +02:00
if ( error ) {
$scope . showAppNotFound ( appId , version ) ;
console . error ( error ) ;
return ;
}
2018-01-22 13:01:38 -08:00
2019-04-29 14:58:42 +02:00
$scope . appInstall . show ( result ) ;
} ) ;
2018-01-22 13:01:38 -08:00
} else {
$scope . appInstall . reset ( ) ;
}
} ) ;
}
function fetchUsers ( ) {
Client . getUsers ( function ( error , users ) {
if ( error ) {
console . error ( error ) ;
return $timeout ( fetchUsers , 5000 ) ;
}
$scope . users = users ;
} ) ;
}
function fetchGroups ( ) {
Client . getGroups ( function ( error , groups ) {
if ( error ) {
console . error ( error ) ;
2019-05-05 07:40:11 -07:00
return $timeout ( fetchGroups , 5000 ) ;
2018-01-22 13:01:38 -08:00
}
$scope . groups = groups ;
} ) ;
}
2019-05-04 21:57:42 -07:00
function getSubscription ( callback ) {
Client . getSubscription ( function ( error , subscription ) {
2019-05-05 07:46:06 -07:00
if ( error ) {
2019-05-06 11:07:19 +02:00
if ( error . statusCode === 412 ) { // not registered yet
2019-05-05 07:46:06 -07:00
$scope . validSubscription = false ;
2019-07-08 09:45:14 -07:00
} else if ( error . statusCode === 402 ) { // invalid token
$scope . validSubscription = false ;
} else { // 424/external error?
2019-05-05 07:46:06 -07:00
return callback ( error ) ;
}
2019-05-04 21:57:42 -07:00
} else {
2019-05-05 11:13:29 -07:00
$scope . validSubscription = true ;
2019-05-04 21:57:42 -07:00
$scope . subscription = subscription ;
}
2018-05-28 20:26:18 +02:00
2019-05-04 21:57:42 -07:00
// clear busy state when a login/signup was performed
$scope . appstoreLogin . busy = false ;
2018-05-28 20:26:18 +02:00
2019-05-04 21:57:42 -07:00
// also update the root controller status
if ( $scope . $parent ) $scope . $parent . updateSubscriptionStatus ( ) ;
2018-04-05 23:27:39 +02:00
2019-05-04 21:57:42 -07:00
callback ( ) ;
2018-01-22 13:01:38 -08:00
} ) ;
}
function init ( ) {
$scope . ready = false ;
2019-05-05 07:46:06 -07:00
getSubscription ( function ( error ) {
2018-01-22 13:01:38 -08:00
if ( error ) {
console . error ( error ) ;
return $timeout ( init , 1000 ) ;
}
2019-05-05 11:46:33 -07:00
if ( ! $scope . validSubscription ) { // show the login form
$scope . ready = true ;
return ;
}
2018-01-22 13:01:38 -08:00
2019-05-05 11:46:33 -07:00
onSubscribed ( function ( error ) {
if ( error ) console . error ( error ) ;
2018-01-22 13:01:38 -08:00
2019-05-05 11:46:33 -07:00
$scope . ready = true ;
} ) ;
2018-01-22 13:01:38 -08:00
} ) ;
}
Client . onReady ( init ) ;
// note: do not use hide.bs.model since it is called immediately from switchToAppsView which is already in angular scope
$ ( '#appInstallModal' ) . on ( 'hidden.bs.modal' , function ( ) {
// clear the appid and version in the search bar when dialog is cancelled
$scope . $apply ( function ( ) {
$location . path ( '/appstore' , false ) . search ( { } ) ; // 'false' means do not reload
} ) ;
} ) ;
window . addEventListener ( 'hashchange' , hashChangeListener ) ;
$scope . $on ( '$destroy' , function handler ( ) {
window . removeEventListener ( 'hashchange' , hashChangeListener ) ;
} ) ;
// setup all the dialog focus handling
2018-03-12 19:08:05 +01:00
[ 'appInstallModal' ] . forEach ( function ( id ) {
2018-01-22 13:01:38 -08:00
$ ( '#' + id ) . on ( 'shown.bs.modal' , function ( ) {
2019-05-05 09:05:06 -07:00
$ ( this ) . find ( '[autofocus]:first' ) . focus ( ) ;
2018-01-22 13:01:38 -08:00
} ) ;
} ) ;
// autofocus if appstore login is shown
2019-05-04 21:57:42 -07:00
$scope . $watch ( 'validSubscription' , function ( newValue /*, oldValue */ ) {
2018-01-22 13:01:38 -08:00
if ( ! newValue ) setTimeout ( function ( ) { $ ( '[name=appstoreLoginForm]' ) . find ( '[autofocus]:first' ) . focus ( ) ; } , 1000 ) ;
} ) ;
$ ( '.modal-backdrop' ) . remove ( ) ;
} ] ) ;