2018-01-22 13:01:38 -08:00
'use strict' ;
2019-01-22 10:54:03 +01:00
/* global angular:false */
/* global $:false */
2018-01-22 13:01:38 -08:00
2019-01-22 10:54:03 +01:00
angular . module ( 'Application' ) . controller ( 'AppsController' , [ '$scope' , '$location' , '$timeout' , '$interval' , 'Client' , function ( $scope , $location , $timeout , $interval , Client ) {
2019-05-20 23:40:02 +02:00
var ALL _DOMAINS _DOMAIN = { _alldomains : true , domain : 'All Domains' } ; // dummy record for the single select filter
2018-01-22 13:01:38 -08:00
$scope . HOST _PORT _MIN = 1024 ;
$scope . HOST _PORT _MAX = 65535 ;
$scope . installedApps = Client . getInstalledApps ( ) ;
2019-04-12 11:06:56 +02:00
$scope . tags = Client . getAppTags ( ) ;
$scope . selectedTags = [ ] ;
2019-05-20 23:40:02 +02:00
$scope . selectedDomain = ALL _DOMAINS _DOMAIN ;
$scope . filterDomains = [ ALL _DOMAINS _DOMAIN ] ;
2018-01-22 13:01:38 -08:00
$scope . config = Client . getConfig ( ) ;
$scope . user = Client . getUserInfo ( ) ;
$scope . domains = [ ] ;
$scope . groups = [ ] ;
$scope . users = [ ] ;
2019-05-07 10:11:54 -07:00
$scope . backupsEnabled = true ;
2019-03-20 09:53:10 -07:00
$scope . disableIndexingTemplate = '# Disable search engine indexing\n\nUser-agent: *\nDisallow: /' ;
2018-01-22 13:01:38 -08:00
2019-07-12 17:18:21 +02:00
$scope . appClone = {
2018-01-22 13:01:38 -08:00
busy : false ,
error : { } ,
app : { } ,
2019-07-12 17:18:21 +02:00
backup : { } ,
2018-01-22 13:01:38 -08:00
2019-07-12 17:18:21 +02:00
// form
2018-05-28 00:47:53 -07:00
location : '' ,
domain : null ,
portBindings : { } ,
portBindingsInfo : { } ,
portBindingsEnabled : { } ,
2019-07-12 17:18:21 +02:00
show : function ( app , backup ) {
// hide restore modal if open
$ ( '#appRestoreModal' ) . modal ( 'hide' ) ;
$scope . appClone . busy = false ;
$scope . appClone . error = { } ;
$scope . appClone . app = app ;
$scope . appClone . backup = backup ;
$scope . appClone . location = '' ;
$scope . appClone . domain = $scope . domains . find ( function ( d ) { return app . domain === d . domain ; } ) ; // pre-select the app's domain
$scope . appClone . portBindingsInfo = angular . extend ( { } , $scope . appClone . app . manifest . tcpPorts , $scope . appClone . app . manifest . udpPorts ) ; // Portbinding map only for information
// set default ports
for ( var env in $scope . appClone . portBindingsInfo ) {
$scope . appClone . portBindings [ env ] = $scope . appClone . portBindingsInfo [ env ] . defaultValue || 0 ;
$scope . appClone . portBindingsEnabled [ env ] = true ;
}
$ ( '#appCloneModal' ) . modal ( 'show' ) ;
} ,
submit : function ( ) {
$scope . appClone . busy = true ;
// only use enabled ports from portBindings
var finalPortBindings = { } ;
for ( var env in $scope . appClone . portBindings ) {
if ( $scope . appClone . portBindingsEnabled [ env ] ) {
finalPortBindings [ env ] = $scope . appClone . portBindings [ env ] ;
}
}
var data = {
location : $scope . appClone . location ,
domain : $scope . appClone . domain . domain ,
portBindings : finalPortBindings ,
backupId : $scope . appClone . backup . id
} ;
Client . cloneApp ( $scope . appClone . app . id , data , function ( error , clonedApp ) {
$scope . appClone . busy = false ;
2018-05-28 10:00:12 -07:00
2019-07-12 17:18:21 +02:00
if ( error ) {
2019-09-03 15:18:05 -07:00
if ( error . statusCode === 409 ) {
if ( error . portName ) {
$scope . appClone . error . port = error . message ;
} else if ( error . domain ) {
$scope . appClone . error . location = 'This location is already taken.' ;
$ ( '#appCloneLocationInput' ) . focus ( ) ;
} else {
Client . error ( error ) ;
}
2019-07-12 17:18:21 +02:00
} else {
Client . error ( error ) ;
}
return ;
}
$ ( '#appCloneModal' ) . modal ( 'hide' ) ;
Client . refreshAppCache ( clonedApp . id ) ; // reflect the new app state immediately
} ) ;
}
2019-08-29 11:17:48 -07:00
} ;
2019-07-12 17:18:21 +02:00
$scope . appRestore = {
busy : false ,
busyFetching : false ,
error : { } ,
app : { } ,
backups : [ ] ,
2019-02-24 19:17:38 +01:00
copyBackupIdDone : false ,
2019-09-06 15:10:57 -07:00
creatingBackup : false ,
2019-02-24 19:17:38 +01:00
2019-07-12 17:18:21 +02:00
copyBackupId : function ( backup ) {
var copyText = document . getElementById ( 'appRestoreBackupIdHelper' ) ;
copyText . value = backup . id ;
2019-02-23 18:28:15 -08:00
copyText . select ( ) ;
document . execCommand ( 'copy' ) ;
2019-02-24 19:17:38 +01:00
$scope . appRestore . copyBackupIdDone = true ;
2019-03-04 21:47:14 -08:00
// reset after 2.5sec
$timeout ( function ( ) { $scope . appRestore . copyBackupIdDone = false ; } , 2500 ) ;
2019-02-23 18:28:15 -08:00
} ,
2018-05-23 20:36:54 -07:00
createBackup : function ( ) {
2019-09-06 15:10:57 -07:00
$scope . appRestore . creatingBackup = true ;
2018-05-23 20:36:54 -07:00
Client . backupApp ( $scope . appRestore . app . id , function ( error ) {
2018-05-29 22:05:18 +02:00
if ( error ) Client . error ( error ) ;
function waitForBackupFinish ( ) {
if ( $scope . appRestore . app . installationState === 'pending_backup' ) return $timeout ( waitForBackupFinish , 1000 ) ;
// we are done, refresh the backup list
Client . getAppBackups ( $scope . appRestore . app . id , function ( error , backups ) {
if ( error ) return Client . error ( error ) ;
$scope . appRestore . backups = backups ;
2019-09-06 15:10:57 -07:00
$scope . appRestore . creatingBackup = false ;
2018-05-29 22:05:18 +02:00
} ) ;
2018-05-23 20:36:54 -07:00
}
2018-08-28 10:38:53 -07:00
// reflect the new app state immediately
2018-06-26 08:49:43 -07:00
Client . refreshAppCache ( $scope . appRestore . app . id , waitForBackupFinish ) ;
2018-05-23 20:36:54 -07:00
} ) ;
} ,
2018-01-22 13:01:38 -08:00
show : function ( app ) {
$scope . reset ( ) ;
$scope . appRestore . app = app ;
$scope . appRestore . busyFetching = true ;
2019-09-06 15:29:59 -07:00
$scope . appRestore . creatingBackup = $scope . appRestore . app . installationState === 'pending_backup' ;
2018-01-22 13:01:38 -08:00
$ ( '#appRestoreModal' ) . modal ( 'show' ) ;
Client . getAppBackups ( app . id , function ( error , backups ) {
if ( error ) {
Client . error ( error ) ;
} else {
$scope . appRestore . backups = backups ;
$scope . appRestore . busyFetching = false ;
}
} ) ;
return false ; // prevent propagation and default
} ,
2019-07-12 17:18:21 +02:00
restore : function ( backup ) {
2018-01-22 13:01:38 -08:00
$scope . appRestore . busy = true ;
2019-05-13 23:31:45 +02:00
2019-07-12 17:18:21 +02:00
Client . restoreApp ( $scope . appRestore . app . id , backup . id , function ( error ) {
2019-05-13 23:31:45 +02:00
if ( error ) {
2018-01-22 13:01:38 -08:00
Client . error ( error ) ;
} else {
$ ( '#appRestoreModal' ) . modal ( 'hide' ) ;
}
$scope . appRestore . busy = false ;
2018-06-26 08:49:43 -07:00
Client . refreshAppCache ( $scope . appRestore . app . id ) ; // reflect the new app state immediately
2018-01-22 13:01:38 -08:00
} ) ;
}
} ;
2019-08-29 14:28:45 -07:00
$scope . appCancel = {
app : { } ,
busy : false ,
show : function ( app ) {
$scope . appCancel . app = app ;
$scope . appCancel . busy = false ;
$ ( '#appCancelModal' ) . modal ( 'show' ) ;
} ,
submit : function ( ) {
2019-08-29 14:51:21 -07:00
$scope . appCancel . busy = true ;
2019-08-29 14:28:45 -07:00
Client . stopTask ( $scope . appCancel . app . taskId , function ( error ) {
if ( error ) Client . error ( error ) ;
2019-08-29 14:51:21 -07:00
setTimeout ( function ( ) { // small delay for UI
$scope . appCancel . busy = false ;
Client . refreshAppCache ( $scope . appCancel . app . id ) ; // reflect the new app state immediately
2019-08-29 14:35:39 -07:00
2019-08-29 14:51:21 -07:00
$ ( '#appCancelModal' ) . modal ( 'hide' ) ;
} , 1000 ) ;
2019-08-29 14:28:45 -07:00
} ) ;
return false ; // prevent propagation and default
}
} ;
2018-01-22 13:01:38 -08:00
$scope . appInfo = {
app : { } ,
message : ''
} ;
2018-06-14 15:46:55 +02:00
$scope . appPostInstallConfirm = {
app : { } ,
message : '' ,
confirmed : false ,
show : function ( app ) {
$scope . reset ( ) ;
$scope . appPostInstallConfirm . app = app ;
$scope . appPostInstallConfirm . message = app . manifest . postInstallMessage ;
$ ( '#appPostInstallConfirmModal' ) . modal ( 'show' ) ;
return false ; // prevent propagation and default
} ,
submit : function ( ) {
2018-06-15 13:39:30 +02:00
if ( ! $scope . appPostInstallConfirm . confirmed ) return ;
2018-06-14 15:46:55 +02:00
$scope . appPostInstallConfirm . app . pendingPostInstallConfirmation = false ;
delete localStorage [ 'confirmPostInstall_' + $scope . appPostInstallConfirm . app . id ] ;
$ ( '#appPostInstallConfirmModal' ) . modal ( 'hide' ) ;
}
} ;
2018-01-22 13:01:38 -08:00
$scope . appError = {
2019-09-07 09:24:39 +02:00
app : null ,
2019-09-05 17:50:10 -07:00
show : function ( app ) {
$scope . reset ( ) ;
$scope . appError . app = app ;
$ ( '#appErrorModal' ) . modal ( 'show' ) ;
return false ; // prevent propagation and default
}
2018-01-22 13:01:38 -08:00
} ;
$scope . appUpdate = {
busy : false ,
error : { } ,
app : { } ,
manifest : { } ,
2019-08-29 11:33:22 -07:00
portBindings : { } ,
show : function ( app , updateManifest ) {
$scope . reset ( ) ;
$scope . appUpdate . app = app ;
$scope . appUpdate . manifest = angular . copy ( updateManifest ) ;
$ ( '#appUpdateModal' ) . modal ( 'show' ) ;
} ,
submit : function ( ) {
$scope . appUpdate . busy = true ;
Client . updateApp ( $scope . appUpdate . app . id , $scope . appUpdate . manifest , function ( error ) {
if ( error ) {
Client . error ( error ) ;
} else {
$scope . appUpdate . app = { } ;
$ ( '#appUpdateModal' ) . modal ( 'hide' ) ;
}
$scope . appUpdate . busy = false ;
Client . refreshAppCache ( $scope . appUpdate . app . id ) ; // reflect the new app state immediately
} ) ;
}
2018-01-22 13:01:38 -08:00
} ;
$scope . reset = function ( ) {
// close all dialogs
$ ( '#appErrorModal' ) . modal ( 'hide' ) ;
$ ( '#appRestoreModal' ) . modal ( 'hide' ) ;
$ ( '#appUpdateModal' ) . modal ( 'hide' ) ;
$ ( '#appInfoModal' ) . modal ( 'hide' ) ;
2018-06-14 15:46:55 +02:00
$ ( '#appPostInstallConfirmModal' ) . modal ( 'hide' ) ;
2018-01-22 13:01:38 -08:00
// reset update dialog
$scope . appUpdate . error = { } ;
$scope . appUpdate . app = { } ;
$scope . appUpdate . manifest = { } ;
// reset restore dialog
$scope . appRestore . error = { } ;
$scope . appRestore . app = { } ;
$scope . appRestore . backups = [ ] ;
2018-05-28 00:47:53 -07:00
$scope . appRestore . location = '' ;
$scope . appRestore . domain = null ;
$scope . appRestore . portBindings = { } ;
$scope . appRestore . portBindingsInfo = { } ;
$scope . appRestore . portBindingsEnabled = { } ;
2018-05-28 10:00:12 -07:00
$scope . appRestore . action = 'restore' ;
2018-06-14 15:46:55 +02:00
// post install confirmation dialog
$scope . appPostInstallConfirm . app = { } ;
$scope . appPostInstallConfirm . message = '' ;
$scope . appPostInstallConfirm . confirmed = false ;
2018-01-22 13:01:38 -08:00
} ;
$scope . showInformation = function ( app ) {
$scope . reset ( ) ;
$scope . appInfo . app = app ;
$scope . appInfo . message = app . manifest . postInstallMessage ;
$ ( '#appInfoModal' ) . modal ( 'show' ) ;
return false ; // prevent propagation and default
} ;
$scope . renderAccessRestrictionUser = function ( userId ) {
var user = $scope . users . filter ( function ( u ) { return u . id === userId ; } ) [ 0 ] ;
// user not found
if ( ! user ) return userId ;
return user . username ? user . username : user . email ;
} ;
$scope . cancel = function ( ) {
window . history . back ( ) ;
} ;
function fetchUsers ( ) {
Client . getUsers ( function ( error , users ) {
if ( error ) {
console . error ( error ) ;
return $timeout ( fetchUsers , 5000 ) ;
}
2018-03-05 12:14:20 +01:00
// ensure we have something to work with in the access restriction dropdowns
users . forEach ( function ( user ) { user . display = user . username || user . email ; } ) ;
2018-01-22 13:01:38 -08:00
$scope . users = users ;
} ) ;
}
function fetchGroups ( ) {
Client . getGroups ( function ( error , groups ) {
if ( error ) {
console . error ( error ) ;
return $timeout ( fetchUsers , 5000 ) ;
}
$scope . groups = groups ;
} ) ;
}
function getDomains ( ) {
Client . getDomains ( function ( error , result ) {
if ( error ) {
console . error ( error ) ;
return $timeout ( getDomains , 5000 ) ;
}
$scope . domains = result ;
2019-05-20 23:40:02 +02:00
$scope . filterDomains = [ ALL _DOMAINS _DOMAIN ] . concat ( result ) ;
2018-01-22 13:01:38 -08:00
} ) ;
}
function getBackupConfig ( ) {
Client . getBackupConfig ( function ( error , backupConfig ) {
if ( error ) return console . error ( error ) ;
2019-05-07 10:11:54 -07:00
$scope . backupEnabled = backupConfig . provider !== 'noop' ;
2018-01-22 13:01:38 -08:00
} ) ;
}
2019-03-25 10:42:31 +01:00
function refreshInstalledApps ( ) {
Client . refreshInstalledApps ( ) ;
}
2018-01-22 13:01:38 -08:00
Client . onReady ( function ( ) {
2019-03-25 10:42:31 +01:00
refreshInstalledApps ( ) ; // refresh the new list immediately when switching from another view (appstore)
2018-06-26 10:19:50 -07:00
2019-05-04 18:40:10 -07:00
if ( $scope . user . admin ) {
2018-06-25 18:06:17 -07:00
fetchUsers ( ) ;
fetchGroups ( ) ;
getDomains ( ) ;
2019-05-07 10:11:54 -07:00
getBackupConfig ( ) ;
2018-06-25 18:06:17 -07:00
}
2018-01-22 13:01:38 -08:00
2019-03-25 10:42:31 +01:00
var refreshAppsTimer = $interval ( refreshInstalledApps , 5000 ) ;
2018-01-22 13:01:38 -08:00
2018-06-25 18:06:17 -07:00
$scope . $on ( '$destroy' , function ( ) {
$interval . cancel ( refreshAppsTimer ) ;
2018-01-22 13:01:38 -08:00
} ) ;
} ) ;
// setup all the dialog focus handling
2019-09-13 11:29:19 +02:00
[ 'appUpdateModal' , 'appRestoreModal' , 'appInfoModal' , 'appErrorModal' ] . forEach ( function ( id ) {
2018-01-22 13:01:38 -08:00
$ ( '#' + id ) . on ( 'shown.bs.modal' , function ( ) {
$ ( this ) . find ( "[autofocus]:first" ) . focus ( ) ;
} ) ;
} ) ;
$ ( '.modal-backdrop' ) . remove ( ) ;
} ] ) ;