2020-11-17 13:58:05 +01:00
<!-- Modal postinstall -->
< div class = "modal fade" id = "postInstallModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
2020-11-17 16:24:43 +01:00
< h4 > {{ 'app.appInfo.firstTimeTitle' | tr }}< / h4 >
2020-11-17 13:58:05 +01:00
< / div >
< div class = "modal-body" >
2020-11-17 16:24:43 +01:00
< p ng-show = "app.manifest.addons.email && postInstallMessage.openApp" > {{ 'app.appInfo.ssoEmail' | tr }}< / p >
< p ng-show = "app.sso && !app.manifest.addons.email && postInstallMessage.openApp" > {{ 'app.appInfo.sso' | tr }}< / p >
2020-11-17 13:58:05 +01:00
< div ng-bind-html = "app.manifest.postInstallMessage | markdown2html" > < / div >
< / div >
< div class = "modal-footer" >
< div class = "form-group pull-left" ng-show = "postInstallMessage.openApp" >
< input type = "checkbox" id = "appPostInstallConfirmCheckbox" ng-model = "postInstallMessage.confirmed" >
< label class = "control-label" for = "appPostInstallConfirmCheckbox" > {{ 'app.appInfo.postInstallConfirmCheckbox' | tr }}< / label >
< / div >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.close' | tr }}< / button >
< a class = "btn btn-success" ng-href = "{{ postInstallMessage.confirmed ? ('https://' + app.fqdn) : '' }}" target = "_blank" ng-disabled = "!postInstallMessage.confirmed" ng-click = "postInstallMessage.submit()" ng-show = "postInstallMessage.openApp" > {{ 'app.appInfo.openAction' | tr:{ app: app.manifest.title } }}< / a >
< / div >
< / div >
< / div >
< / div >
2019-09-13 11:18:43 +02:00
<!-- Modal uninstall app -->
< div class = "modal fade" id = "uninstallModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
2021-04-07 10:41:50 +02:00
< div class = "modal-header" >
< h4 class = "modal-title" > {{ 'app.uninstallDialog.title' | tr:{ app: (app.label || app.fqdn) } }}< / h4 >
< / div >
2019-09-13 11:18:43 +02:00
< div class = "modal-body" >
2021-04-13 12:53:50 +02:00
< p ng-bind-html = "'app.uninstallDialog.description' | tr:{ app: (app.label || app.fqdn) }" > < / p >
2019-09-13 11:18:43 +02:00
< / div >
< div class = "modal-footer" >
2020-11-24 19:52:24 +01:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.cancel' | tr }}< / button >
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-danger" ng-click = "uninstall.submit()" ng-disabled = "uninstall.busy" > < i class = "fa fa-circle-notch fa-spin" ng-show = "uninstall.busy" > < / i > {{ 'app.uninstallDialog.uninstallAction' | tr }}< / button >
2019-09-13 11:18:43 +02:00
< / div >
< / div >
< / div >
< / div >
2019-09-20 01:55:45 +02:00
<!-- Modal domain collision -->
< div class = "modal fade" id = "domainCollisionsModal" tabindex = "-1" role = "dialog" >
2019-09-21 22:45:26 +02:00
< div class = "modal-dialog" >
< div class = "modal-content" >
2021-04-07 10:41:50 +02:00
< div class = "modal-header" >
< h4 class = "modal-title" > {{ 'app.domainCollisionDialog.title' | tr }}< / h4 >
< / div >
2019-09-21 22:45:26 +02:00
< div class = "modal-body" >
2020-11-17 13:58:05 +01:00
< p > {{ 'app.domainCollisionDialog.collisionListTitle' | tr }}< / p >
2019-09-21 22:45:26 +02:00
< ul >
< li ng-repeat = "domain in location.domainCollisions" > {{ domain.subdomain + '.' + domain.domain }}< / li >
< / ul >
2020-11-17 13:58:05 +01:00
< p > {{ 'app.domainCollisionDialog.description' | tr }}< / p >
2019-09-21 22:45:26 +02:00
< / div >
< div class = "modal-footer" >
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.cancel' | tr }}< / button >
< button type = "button" class = "btn btn-danger" ng-click = "location.submit(true)" > {{ 'app.domainCollisionDialog.overwriteAction' | tr }}< / button >
2019-09-21 22:45:26 +02:00
< / div >
< / div >
< / div >
< / div >
<!-- Modal repair -->
< div class = "modal fade" id = "repairModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
2020-11-17 13:58:05 +01:00
< h4 class = "modal-title" > {{ 'app.repairDialog.title' | tr:{ app: app.fqdn } }}< / h4 >
2019-09-21 22:45:26 +02:00
< / div >
< div class = "modal-body" >
2019-10-03 11:25:27 -07:00
< div ng-if = "!app.error" >
2020-11-17 13:58:05 +01:00
< p > {{ 'app.repairDialog.description' | tr }}< / p >
2019-10-03 11:25:27 -07:00
< / div >
< div ng-if = "app.error" >
2020-11-17 13:58:05 +01:00
< p ng-bind-html = "'app.repairDialog.taskError' | tr:{ task: (app.error.installationState | taskName) }" > < / p >
2019-10-03 11:25:27 -07:00
< p class = "text-danger" > {{ app.error.reason + ': ' + app.error.message }}< / p >
< / div >
2019-09-23 22:45:45 +02:00
< div class = "form-group" ng-show = "repair.location && repair.domain" >
2020-11-17 13:58:05 +01:00
< p > {{ 'app.repairDialog.domainDescription' | tr }}< / p >
< label class = "control-label" > {{ 'app.repairDialog.location' | tr }}< / label >
2019-09-26 22:23:08 -07:00
< div class = "input-group form-inline" >
< input type = "text" class = "form-control" ng-model = "repair.location" name = "location" placeholder = "{{ 'Leave empty to use bare domain' }}" autofocus >
2019-09-23 22:45:45 +02:00
2019-09-26 22:23:08 -07:00
< div class = "input-group-btn" >
< button type = "button" class = "btn btn-default dropdown-toggle" data-toggle = "dropdown" >
2020-08-15 18:35:51 -07:00
< span > {{ (!repair.location ? '' : '.') + repair.domain.domain }}< / span >
2019-09-26 22:23:08 -07:00
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu dropdown-menu-right" role = "menu" >
< li ng-repeat = "domain in domains" >
< a href = "" ng-click = "repair.domain = domain" > {{ domain.domain }}< / a >
< / li >
< / ul >
2019-09-23 22:45:45 +02:00
< / div >
< / div >
2019-09-26 22:23:08 -07:00
< / div >
2021-01-18 17:55:48 -08:00
< div ng-show = "repair.aliasDomains.length" >
< p ng-repeat = "aliasDomain in repair.aliasDomains" >
< label class = "control-label" > < input type = "checkbox" ng-model = "aliasDomain.enabled" >
{{ aliasDomain.subdomain + (!aliasDomain.subdomain ? '' : '.') + aliasDomain.domain.domain }}
< / label >
< / p >
< / div >
2019-09-23 22:45:45 +02:00
< div ng-show = "repair.alternateDomains.length" >
< p ng-repeat = "alternateDomain in repair.alternateDomains" >
2019-09-27 15:34:54 -07:00
< label class = "control-label" > < input type = "checkbox" ng-model = "alternateDomain.enabled" >
2020-08-15 18:35:51 -07:00
{{ alternateDomain.subdomain + (!alternateDomain.subdomain ? '' : '.') + alternateDomain.domain.domain }}
2019-09-27 15:34:54 -07:00
< / label >
2019-09-21 22:45:26 +02:00
< / p >
2019-09-20 01:55:45 +02:00
< / div >
2019-09-23 15:01:44 +02:00
< div ng-show = "repair.backups.length" >
2020-11-17 13:58:05 +01:00
< label class = "control-label" > {{ 'app.repairDialog.fromBackup' | tr }}< / label >
2019-09-21 22:45:26 +02:00
< select class = "form-control" ng-model = "repair.backupId" >
2020-05-13 22:37:11 -07:00
< option ng-repeat = "backup in repair.backups" value = "{{ backup.id }}" > {{ backup.creationTime | prettyDate }} - v{{ backup.packageVersion }}< / option >
2019-09-21 22:45:26 +02:00
< / select >
< / div >
< / div >
< div class = "modal-footer" >
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.cancel' | tr }}< / button >
2019-12-20 15:38:40 -08:00
< button type = "button" class = "btn btn-success" ng-click = "repair.submit()" ng-disabled = "repair.retryBusy" >
2020-11-17 13:58:05 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "repair.retryBusy" > < / i > {{ 'app.repairDialog.retryAction' | tr:{ task: (app.error.installationState | taskName) } }}
2019-12-20 15:38:40 -08:00
< / button >
2019-09-20 01:55:45 +02:00
< / div >
< / div >
< / div >
2019-09-21 22:45:26 +02:00
< / div >
2019-09-20 01:55:45 +02:00
2020-02-06 16:08:22 -08:00
<!-- modal import backup -->
< div class = "modal fade" id = "importBackupModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
2020-11-17 13:58:05 +01:00
< h4 class = "modal-title" > {{ 'app.importBackupDialog.title' | tr }}< / h4 >
2020-02-06 16:08:22 -08:00
< / div >
< div class = "modal-body" >
2020-11-17 13:58:05 +01:00
< p class = "text-info" > {{ 'app.importBackupDialog.description' | tr }}< / p >
2020-02-06 16:08:22 -08:00
< form name = "importBackupForm" role = "form" novalidate ng-submit = "importBackup.submit()" autocomplete = "off" >
2020-11-17 13:58:05 +01:00
< p class = "has-error text-center" ng-show = "backups.error" > {{ importBackup.error.generic }}< / p >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" >
< label class = "control-label" for = "storageProvider" > {{ 'backups.configureBackupStorage.provider' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/backups/#storage-providers" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
< select class = "form-control" id = "storageProvider" ng-model = "importBackup.provider" ng-options = "a.value as a.name for a in storageProvider" ng-change = "importBackup.clearForm()" ng-disabled = "importBackup.busy" > < / select >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.key }" >
< label ng-show = "importBackup.provider !== 'filesystem'" class = "control-label" for = "inputImportBackupId" > Backup ID< / label >
< label ng-show = "importBackup.provider === 'filesystem'" class = "control-label" for = "inputImportBackupId" > Backup Path< / label >
< input type = "text" class = "form-control" ng-model = "importBackup.backupId" id = "inputImportBackupId" ng-disabled = "importBackup.busy" required >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
<!-- S3/Minio/SOS/GCS -->
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.endpoint }" ng-show = "importBackup.provider === 'minio' || importBackup.provider === 'backblaze-b2' || importBackup.provider === 's3-v4-compat'" >
< label class = "control-label" for = "inputimportBackupEndpoint" > {{ 'backups.configureBackupStorage.s3Endpoint' | tr }}< / label >
< input type = "text" class = "form-control" ng-model = "importBackup.endpoint" id = "inputimportBackupEndpoint" name = "endpoint" ng-disabled = "importBackup.busy" placeholder = "URL" ng-required = "importBackup.provider === 'minio' || importBackup.provider === 'backblaze-b2' || importBackup.provider === 's3-v4-compat'" >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "checkbox" ng-show = "importBackup.provider === 'minio' || importBackup.provider === 's3-v4-compat'" >
< label >
< input type = "checkbox" ng-model = "importBackup.acceptSelfSignedCerts" id = "inputimportBackupSelfSigned" > Accept Self-signed certificate< / input >
< / label >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.bucket }" ng-show = "s3like(importBackup.provider) || importBackup.provider === 'gcs'" >
< label class = "control-label" for = "inputImportBackupBucket" > {{ 'backups.configureBackupStorage.bucketName' | tr }}< / label >
< input type = "text" class = "form-control" ng-model = "importBackup.bucket" id = "inputImportBackupBucket" name = "bucket" ng-disabled = "importBackup.busy" ng-required = "s3like(importBackup.provider)" >
< / div >
2020-02-06 16:08:22 -08:00
2021-01-07 18:28:30 +01:00
<!-- SSHFS/CIFS/NFS -->
2021-01-07 18:40:51 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.mountPoint }" ng-show = "mountlike(importBackup.provider)" >
2021-01-07 18:28:30 +01:00
< label class = "control-label" for = "inputConfigureMountPoint" > {{ 'backups.configureBackupStorage.mountPoint' | tr }}< / label >
< input type = "text" class = "form-control" ng-model = "importBackup.mountPoint" id = "inputConfigureMountPoint" name = "mountPoint" ng-disabled = "importBackup.busy" placeholder = "Folder where filesystem is mounted" ng-required = "mountlike(importBackup.provider)" >
< / div >
<!-- Filesystem -->
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.prefix }" ng-show = "importBackup.provider !== 'filesystem' && importBackup.provider !== ''" >
< label class = "control-label" for = "inputimportBackupPrefix" > {{ 'backups.configureBackupStorage.prefix' | tr }}< / label >
< input type = "text" class = "form-control" ng-model = "importBackup.prefix" id = "inputimportBackupPrefix" name = "prefix" ng-disabled = "importBackup.busy" placeholder = "Prefix for backup file names" >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 's3'" >
< label class = "control-label" for = "inputImportBackupS3Region" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputImportBackupS3Region" ng-model = "importBackup.region" ng-options = "a.value as a.name for a in s3Regions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 's3'" > < / select >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 's3-v4-compat'" >
< label class = "control-label" for = "inputImportBackupS3V4CompatRegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< input class = "form-control" type = "text" name = "region" id = "inputImportBackupS3V4CompatRegion" ng-model = "importBackup.region" ng-disabled = "importBackup.busy" placeholder = "Leave empty to use us-east-1 as default" > < / input >
2020-07-05 10:58:20 -07:00
< / div >
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 'digitalocean-spaces'" >
< label class = "control-label" for = "inputImportBackupDORegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputImportBackupDORegion" ng-model = "importBackup.endpoint" ng-options = "a.value as a.name for a in doSpacesRegions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'digitalocean-spaces'" > < / select >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 'exoscale-sos'" >
< label class = "control-label" for = "inputimportBackupExoscaleRegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputimportBackupExoscaleRegion" ng-model = "importBackup.endpoint" ng-options = "a.value as a.name for a in exoscaleSosRegions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'exoscale-sos'" > < / select >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 'wasabi'" >
< label class = "control-label" for = "inputimportBackupWasabiRegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputimportBackupWasabiRegion" ng-model = "importBackup.endpoint" ng-options = "a.value as a.name for a in wasabiRegions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'wasabi'" > < / select >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 'scaleway-objectstorage'" >
< label class = "control-label" for = "inputimportBackupScalewayRegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputimportBackupScalewayRegion" ng-model = "importBackup.endpoint" ng-options = "a.value as a.name for a in scalewayRegions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'scaleway-objectstorage'" > < / select >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 'linode-objectstorage'" >
< label class = "control-label" for = "inputimportBackupLinodeRegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputimportBackupLinodeRegion" ng-model = "importBackup.endpoint" ng-options = "a.value as a.name for a in linodeRegions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'linode-objectstorage'" > < / select >
< / div >
2020-03-05 11:24:42 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 'ovh-objectstorage'" >
< label class = "control-label" for = "inputimportBackupOvhRegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputimportBackupOvhRegion" ng-model = "importBackup.endpoint" ng-options = "a.value as a.name for a in ovhRegions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'ovh-objectstorage'" > < / select >
< / div >
2020-04-29 12:54:19 -07:00
2021-02-04 10:14:42 -08:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.region }" ng-show = "importBackup.provider === 'ionos-objectstorage'" >
< label class = "control-label" for = "inputimportBackupIonosRegion" > {{ 'backups.configureBackupStorage.region' | tr }}< / label >
< select class = "form-control" name = "region" id = "inputimportBackupIonosRegion" ng-model = "importBackup.endpoint" ng-options = "a.value as a.name for a in ionosRegions" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'ionos-objectstorage'" > < / select >
< / div >
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.accessKeyId }" ng-show = "s3like(importBackup.provider)" >
< label class = "control-label" for = "inputImportBackupAccessKeyId" > {{ 'backups.configureBackupStorage.s3AccessKeyId' | tr }}< / label >
< input type = "text" class = "form-control" ng-model = "importBackup.accessKeyId" id = "inputImportBackupAccessKeyId" name = "accessKeyId" ng-disabled = "importBackup.busy" ng-required = "s3like(importBackup.provider)" >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.secretAccessKey }" ng-show = "s3like(importBackup.provider)" >
< label class = "control-label" for = "inputImportBackupSecretAccessKey" > {{ 'backups.configureBackupStorage.s3SecretAccessKey' | tr }}< / label >
< input type = "text" class = "form-control" ng-model = "importBackup.secretAccessKey" id = "inputImportBackupSecretAccessKey" name = "secretAccessKey" ng-disabled = "importBackup.busy" ng-required = "s3like(importBackup.provider)" >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.gcsKeyInput }" ng-show = "importBackup.provider === 'gcs'" >
< label class = "control-label" for = "gcsKeyInput" > {{ 'backups.configureBackupStorage.gcsServiceKey' | tr }}< / label >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "input-group" >
< input type = "file" id = "gcsKeyFileInput" style = "display:none" / >
< input type = "text" class = "form-control" placeholder = "Service Account Key" ng-model = "importBackup.gcsKey.keyFileName" id = "gcsKeyInput" name = "cert" onclick = "getElementById('gcsKeyFileInput').click();" style = "cursor: pointer;" ng-disabled = "importBackup.busy" ng-required = "importBackup.provider === 'gcs'" >
< span class = "input-group-addon" >
< i class = "fa fa-upload" onclick = "getElementById('gcsKeyFileInput').click();" > < / i >
< / span >
2020-02-06 16:08:22 -08:00
< / div >
2020-11-17 13:58:05 +01:00
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" >
< label class = "control-label" for = "storageFormat" > {{ 'backups.configureBackupStorage.format' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/backups/#backup-formats" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
< select class = "form-control" id = "storageFormat" ng-change = "importBackup.password = ''" ng-model = "importBackup.format" ng-options = "a.value as a.name for a in formats" ng-disabled = "importBackup.busy" > < / select >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< div class = "form-group" ng-class = "{ 'has-error': importBackup.error.password }" >
< label class = "control-label" for = "inputImportBackupPassword" > {{ 'backups.configureBackupStorage.encryptionPassword' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/backups/#encryption" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
< input type = "text" class = "form-control" ng-model = "importBackup.password" id = "inputImportBackupPassword" ng-disabled = "importBackup.busy" placeholder = "Passphrase used to encrypt the backups" >
< / div >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< input class = "ng-hide" type = "submit" ng-disabled = "importBackupForm.$invalid" / >
2020-02-06 16:08:22 -08:00
< / form >
< / div >
< div class = "modal-footer " >
2020-05-16 11:19:47 -07:00
< input type = "file" id = "backupConfigFileInput" style = "display:none" / >
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-default pull-left" onclick = "getElementById('backupConfigFileInput').click();" > {{ 'app.importBackupDialog.uploadAction' | tr }}< / button >
2020-02-06 16:08:22 -08:00
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.cancel' | tr }}< / button >
< button type = "submit" class = "btn btn-outline btn-success pull-right" ng-click = "importBackup.submit()" ng-disabled = "importBackupForm.$invalid || importBackup.busy" > < i class = "fa fa-circle-notch fa-spin" ng-show = "importBackup.busy" > < / i > {{ 'app.importBackupDialog.importAction' | tr }}< / button >
2019-09-26 20:48:04 +02:00
< / div >
< / div >
< / div >
2019-09-27 19:43:03 +02:00
< / div >
2019-09-26 20:48:04 +02:00
2019-09-17 17:14:40 +02:00
<!-- Modal update app -->
< div class = "modal fade" id = "updateModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
2020-11-17 13:58:05 +01:00
< h4 class = "modal-title" > {{ 'app.updateDialog.title' | tr:{ app: app.fqdn } }}< / h4 >
2019-09-17 17:14:40 +02:00
< / div >
< div class = "modal-body" >
2020-12-21 12:49:21 -08:00
< p class = "text-danger" ng-show = "config.update[app.id].unstable" > {{ 'app.updateDialog.unstableWarning' | tr }}< / p >
< p > {{ 'app.updateDialog.changelogHeader' | tr:{ version: config.update[app.id].manifest.version } }}< / p >
< div ng-bind-html = "config.update[app.id].manifest.changelog | markdown2html" > < / div >
< p class = "text-danger text-bold" ng-show = "!config.update[app.id].manifest.dockerImage" >
2020-05-11 23:14:19 +02:00
< br / >
2020-11-17 13:58:05 +01:00
{{ 'app.updateDialog.subscriptionExpired' | tr }}
2020-05-11 23:14:19 +02:00
< / p >
2019-09-17 17:14:40 +02:00
< / div >
< div class = "modal-footer" >
2020-12-21 12:49:21 -08:00
< label class = "checkbox-inline pull-left" ng-show = "config.update[app.id].manifest.dockerImage" >
2020-11-17 13:58:05 +01:00
< input type = "checkbox" ng-model = "updates.skipBackup" > < b > {{ 'app.updateDialog.skipBackupCheckbox' | tr }}< / b >
2020-05-11 23:14:19 +02:00
< / label >
2019-09-26 20:10:25 -07:00
2020-12-21 12:49:21 -08:00
< button type = "button" class = "btn btn-primary pull-left" ng-show = "!config.update[app.id].manifest.dockerImage && user.isAtLeastOwner" ng-click = "openSubscriptionSetup()" > {{ 'app.updateDialog.setupSubscriptionAction' | tr }}< / button >
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.cancel' | tr }}< / button >
2020-12-21 12:49:21 -08:00
< button type = "button" ng-class = "config.update[app.id].unstable ? 'btn btn-danger' : 'btn btn-success'" ng-click = "updates.confirmUpdate()" ng-disabled = "!config.update[app.id].manifest.dockerImage || updates.busyUpdate" > < i class = "fa fa-circle-notch fa-spin" ng-show = "updates.busyUpdate" > < / i > {{ 'app.updateDialog.updateAction' | tr }}< / button >
2019-09-17 17:14:40 +02:00
< / div >
< / div >
< / div >
< / div >
2019-10-24 10:01:23 -07:00
<!-- Modal restore app -->
< div class = "modal fade" id = "restoreModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
2020-11-17 13:58:05 +01:00
< h4 class = "modal-title" > {{ 'app.restoreDialog.title' | tr:{ app: app.fqdn } }}< / h4 >
2019-10-24 10:01:23 -07:00
< / div >
< div class = "modal-body" style = "padding: 0 15px" >
2020-11-17 13:58:05 +01:00
< p > {{ 'app.restoreDialog.description' | tr:{ creationTime: (restore.backup.creationTime | prettyDate) } }}< / p >
< p class = "text-danger" > {{ 'app.restoreDialog.warning' | tr }}< / p >
2019-10-24 10:07:34 -07:00
< br / >
2019-10-24 10:01:23 -07:00
< / div >
< div class = "modal-footer" >
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.close' | tr }}< / button >
< button type = "button" class = "btn btn-danger" ng-click = "restore.submit()" > < i class = "fas fa-history" ng-hide = "restore.busy" > < / i > < i class = "fa fa-circle-notch fa-spin" ng-show = "clone.busy" > < / i > {{ 'app.restoreDialog.restoreAction' | tr }}< / button >
2019-10-24 10:01:23 -07:00
< / div >
< / div >
< / div >
< / div >
2019-09-13 17:18:37 +02:00
<!-- Modal clone app -->
< div class = "modal fade" id = "cloneModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
2020-11-17 13:58:05 +01:00
< h4 class = "modal-title" > {{ 'app.cloneDialog.title' | tr:{ app: app.fqdn } }}< / h4 >
2019-09-13 17:18:37 +02:00
< / div >
< div class = "modal-body" style = "padding: 0 15px" >
2020-11-17 13:58:05 +01:00
< p ng-bind-html = "'app.cloneDialog.description' | tr:{ creationTime: (clone.backup.creationTime | prettyDate), packageVersion: clone.backup.packageVersion }" > < / p >
2020-03-19 19:26:19 -07:00
< form role = "form" ng-submit = "clone.submit()" autocomplete = "off" >
< fieldset >
2019-09-13 17:18:37 +02:00
< div class = "form-group" ng-class = "{ 'has-error': clone.error.location }" >
2020-11-17 13:58:05 +01:00
< label class = "control-label" for = "cloneLocationInput" > {{ 'app.cloneDialog.location' | tr }}< / label >
2019-09-13 17:18:37 +02:00
< div ng-show = "clone.error.location" > < small > {{ clone.error.location }}< / small > < / div >
< div class = "input-group form-inline" >
2020-11-17 13:58:05 +01:00
< input type = "text" class = "form-control" ng-model = "clone.location" id = "cloneLocationInput" name = "location" placeholder = "{{ 'appstore.installDialog.locationPlaceholder' | tr }}" autofocus >
2019-09-13 17:18:37 +02:00
< div class = "input-group-btn" >
< button type = "button" class = "btn btn-default dropdown-toggle" data-toggle = "dropdown" >
2020-08-15 18:35:51 -07:00
< span > {{ (!clone.location ? '' : '.') + clone.domain.domain }}< / span >
2019-09-13 17:18:37 +02:00
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu dropdown-menu-right" role = "menu" >
< li ng-repeat = "domain in domains" >
< a href = "" ng-click = "clone.domain = domain" > {{ domain.domain }}< / a >
< / li >
< / ul >
< / div >
< / div >
< / div >
2020-11-17 13:58:05 +01:00
< p class = "text-small text-warning" ng-show = "clone.domain.provider === 'linode'" ng-bind-html = "'appstore.installDialog.linodeWarning' | tr:{ linodeDocsLink: 'https://docs.cloudron.io/domains/#linode-dns' }" > < / p >
< p class = "text-small text-warning" ng-show = "clone.location && clone.domain.provider === 'manual'" ng-bind-html = "'appstore.installDialog.manualWarning' | tr:{ location: (appInstall.location + '.' + appInstall.domain.domain) }" > < / p >
2019-09-13 17:18:37 +02:00
2019-09-24 18:50:52 +02:00
< div class = "has-error text-center" ng-show = "clone.error.port" > {{ clone.error.port }}< / div >
< div ng-repeat = "(env, info) in clone.portBindingsInfo" >
2019-09-13 17:18:37 +02:00
< ng-form name = "portInfo_form" >
2019-09-24 18:50:52 +02:00
< div class = "form-group" ng-class = "{ 'has-error': (!clone.itemName{{$index}}.$dirty && clone.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }" >
< label class = "control-label" for = "inputPortInfo{{env}}" > < input type = "checkbox" ng-model = "clone.portBindingsEnabled[env]" >
2019-09-13 17:18:37 +02:00
{{ info.title }}
< sup >
< a popover-placement = "top-right" popover-trigger = "outsideClick" uib-popover = "{{info.description}} ({{ HOST_PORT_MIN }} - {{ HOST_PORT_MAX }})" > < i class = "fa fa-question-circle" > < / i > < / a >
< / sup >
< / label >
2019-09-24 18:50:52 +02:00
< input type = "number" class = "form-control" ng-model = "clone.portBindings[env]" ng-disabled = "!clone.portBindingsEnabled[env]" id = "inputPortInfo{{env}}" later-name = "itemName{{$index}}" min = "{{hostPortMin}}" max = "{{hostPortMax}}" required >
2019-09-13 17:18:37 +02:00
< / div >
< / ng-form >
< / div >
2020-03-19 19:26:19 -07:00
< / fieldset >
< / form >
2019-09-13 17:18:37 +02:00
< / div >
< div class = "modal-footer" >
2020-11-17 13:58:05 +01:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > {{ 'main.dialog.cancel' | tr }}< / button >
< button type = "button" class = "btn btn-success" ng-click = "clone.submit()" > < i class = "far fa-clone" ng-hide = "clone.busy" > < / i > < i class = "fa fa-circle-notch fa-spin" ng-show = "clone.busy" > < / i > {{ 'app.cloneDialog.cloneAction' | tr }}< / button >
2019-09-13 17:18:37 +02:00
< / div >
< / div >
< / div >
< / div >
2019-09-16 14:03:13 +02:00
< div class = "content content-large app-configure" >
2019-09-10 19:21:30 +02:00
2020-11-16 16:52:51 +01:00
< a href = "/#/apps" class = "back-to-view-link" > < i class = "fas fa-arrow-left" > < / i > {{ 'app.backAction' | tr }}< / a >
2019-09-16 14:15:38 +02:00
2019-09-12 16:28:21 +02:00
< br / >
2019-09-13 11:29:19 +02:00
2020-04-12 13:20:01 +02:00
< div class = "row" ng-show = "view" >
2019-09-30 15:18:44 +02:00
< div class = "col-sm-2 text-center" >
2019-09-16 14:03:13 +02:00
< img ng-src = "{{ app.iconUrl || 'img/appicon_fallback.png' }}" fallback-icon = "img/appicon_fallback.png" onerror = "imageErrorHandler(this)" class = "app-icon" / >
< / div >
2019-09-30 15:18:44 +02:00
< div class = "col-sm-8" >
2019-09-21 11:02:00 +02:00
< div class = "app-header-container" >
< h1 >
2019-09-27 19:43:03 +02:00
< a ng-href = "{{ app | applicationLink }}" target = "_blank" ng-class = "{ 'hand': (app | appIsInstalledAndHealthy) }" ng-click = "(app | appIsInstalledAndHealthy) && app.pendingPostInstallConfirmation && postInstallMessage.show(true)" > {{ app.label || app.fqdn }} < sup ng-show = "app | appIsInstalledAndHealthy" > < i class = "fas fa-external-link-alt" style = "font-size: 12px;" > < / i > < / sup > < / a >
2019-09-21 11:02:00 +02:00
< / h1 >
< div >
2021-04-06 16:22:44 +02:00
< button class = "btn btn-sm btn-default" ng-class = "{ 'btn-primary': uninstall.startButton }" ng-click = "uninstall.toggleRunState()" ng-disabled = "app.taskId || app.error || app.installationState === 'pending_start' || app.installationState === 'pending_stop'" uib-tooltip = "{{ uninstall.startButton ? ('app.uninstall.startStop.startAction' | tr) : ('app.uninstall.startStop.stopAction' | tr) }}" tooltip-append-to-body = "true" tooltip-placement = "bottom" >
< i ng-show = "app.installationState === 'pending_start' || app.installationState === 'pending_stop'" class = "fa fa-circle-notch fa-spin" > < / i >
2021-04-13 12:49:36 +02:00
< i ng-hide = "app.installationState === 'pending_start' || app.installationState === 'pending_stop'" class = "fas" ng-class = "{ 'fa-power-off': !uninstall.startButton, 'fa-play': uninstall.startButton }" > < / i >
2021-04-06 16:22:44 +02:00
< / button >
2021-04-07 10:36:01 +02:00
< div class = "btn-group btn-group-sm" role = "group" >
< a class = "btn btn-sm btn-default" ng-href = "{{ '/logs.html?appId=' + app.id }}" target = "_blank" uib-tooltip = "{{ 'app.logsActionTooltip' | tr }}" tooltip-append-to-body = "true" tooltip-placement = "bottom" > < i class = "fas fa-align-left" > < / i > < / a >
< a class = "btn btn-sm btn-default" ng-href = "{{ '/terminal.html?id=' + app.id }}" target = "_blank" uib-tooltip = "{{ 'app.terminalActionTooltip' | tr }}" tooltip-append-to-body = "true" tooltip-placement = "bottom" > < i class = "fa fa-terminal" > < / i > < / a >
< a class = "btn btn-sm btn-default" ng-href = "{{ '/filemanager.html?appId=' + app.id }}" target = "_blank" uib-tooltip = "{{ 'app.filemanagerActionTooltip' | tr }}" tooltip-append-to-body = "true" tooltip-placement = "bottom" > < i class = "fas fa-folder" > < / i > < / a >
< / div >
2020-11-08 09:54:21 +01:00
< div class = "dropdown" style = "display: inline-block" >
2020-11-16 16:52:51 +01:00
< button class = "btn btn-sm btn-default dropdown-toggle" type = "button" data-toggle = "dropdown" uib-tooltip = "{{ 'app.docsActionTooltip' | tr }}" tooltip-append-to-body = "true" tooltip-placement = "bottom" >
2020-11-08 09:54:21 +01:00
< i class = "fas fa-book" > < / i >
2019-09-26 20:48:04 +02:00
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu dropdown-menu-right" >
2020-11-16 16:52:51 +01:00
< li ng-class = "{ 'disabled': !app.manifest.postInstallMessage }" > < a href = "" ng-click = "postInstallMessage.show(false)" > {{ 'app.firstTimeSetupAction' | tr }}< / a > < / li >
< li ng-class = "{ 'disabled': !app.manifest.documentationUrl }" > < a ng-href = "{{ app.manifest.documentationUrl }}" target = "_blank" > {{ 'app.docsAction' | tr }}< / a > < / li >
< li ng-class = "{ 'disabled': (!app.manifest.configurePath || !(app | applicationLink)) }" > < a ng-href = "{{ (app.manifest.configurePath && (app | applicationLink)) ? ((app | applicationLink) + app.manifest.configurePath) : ''}}" target = "_blank" > {{ 'app.adminPageAction' | tr }}< / a > < / li >
2019-09-26 20:48:04 +02:00
< li role = "separator" class = "divider" > < / li >
2020-11-16 16:52:51 +01:00
< li ng-class = "{ 'disabled': !app.manifest.website }" > < a ng-href = "{{ app.manifest.website }}" target = "_blank" > {{ 'app.projectWebsiteAction' | tr }}< / a > < / li >
2019-09-26 20:48:04 +02:00
< / ul >
< / div >
2019-09-21 11:02:00 +02:00
< / div >
< / div >
2020-11-23 12:30:39 +01:00
< div class = "app-status-container" >
< span class = "text-small" > {{ app | installationStateLabel }} {{ app.message ? ' - ' + app.message : '' }}< / span >
< span ng-click = "setView('repair')" class = "text-small hand text-hover" ng-show = "app.error" > : {{ app.error.reason + ' - ' + app.error.message }}< / span >
< / div >
2019-09-10 19:21:30 +02:00
< / div >
< / div >
2020-03-26 00:22:46 +01:00
< div class = "row" ng-show = "app.taskId" >
2020-03-26 00:16:23 +01:00
< div class = "col-sm-8 col-sm-offset-2" style = "height: 10px; display: flex; align-items: center;" >
2020-03-26 00:22:46 +01:00
< div class = "progress progress-striped active animateMeOpacity" style = "height: 10px; flex-grow: 1;" >
2020-06-08 17:53:29 -07:00
< div class = "progress-bar progress-bar-success" role = "progressbar" style = "width: {{ app.progress || 5 }}%" > < / div >
2019-09-24 21:08:42 +02:00
< / div >
2021-02-26 11:47:48 -08:00
< div ng-show = "app.taskMinutesActive >= 2" class = "text-danger hand" style = "margin: 0 4px;" ng-click = "stopAppTask(app.taskId)" uib-tooltip = "Cancel Task" > < i class = "fas fa-times" > < / i > < / div >
2019-09-24 21:08:42 +02:00
< / div >
< / div >
2020-04-08 12:56:57 +02:00
< div class = "row" ng-hide = "view" >
< div class = "col-md-12 text-center" >
< br / > < br / > < h2 > < i class = "fa fa-circle-notch fa-spin" > < / i > < / h2 >
< / div >
< / div >
< div class = "row app-configure-links-container" ng-show = "view" >
2019-09-30 15:18:44 +02:00
< div class = "col-sm-2" >
2019-09-16 14:03:13 +02:00
< div class = "app-configure-links" >
2020-11-16 16:52:51 +01:00
< div ng-click = "setView('display')" ng-class = "{ 'active': view === 'display' }" > {{ 'app.displayTabTitle' | tr }}< / div >
< div ng-click = "setView('location')" ng-class = "{ 'active': view === 'location' }" > {{ 'app.locationTabTitle' | tr }}< / div >
< div ng-click = "setView('access')" ng-class = "{ 'active': view === 'access' }" > {{ 'app.accessControlTabTitle' | tr }}< / div >
< div ng-click = "setView('resources')" ng-class = "{ 'active': view === 'resources' }" > {{ 'app.resourcesTabTitle' | tr }}< / div >
< div ng-click = "setView('storage')" ng-class = "{ 'active': view === 'storage' }" > {{ 'app.storageTabTitle' | tr }}< / div >
< div ng-click = "setView('graphs')" ng-class = "{ 'active': view === 'graphs' }" > {{ 'app.graphsTabTitle' | tr }}< / div >
< div ng-click = "setView('security')" ng-class = "{ 'active': view === 'security' }" > {{ 'app.securityTabTitle' | tr }}< / div >
< div ng-click = "setView('email')" ng-class = "{ 'active': view === 'email' }" ng-show = "app.manifest.addons.sendmail || app.manifest.addons.recvmail" > {{ 'app.emailTabTitle' | tr }}< / div >
< div ng-click = "setView('updates')" ng-class = "{ 'active': view === 'updates' }" > {{ 'app.updatesTabTitle' | tr }}< / div >
< div ng-click = "setView('backups')" ng-class = "{ 'active': view === 'backups' }" > {{ 'app.backupsTabTitle' | tr }}< / div >
< div ng-click = "setView('repair')" ng-class = "{ 'active': view === 'repair' }" > {{ 'app.repairTabTitle' | tr }}< / div >
< div ng-click = "setView('uninstall')" ng-class = "{ 'active': view === 'uninstall' }" > {{ 'app.uninstallTabTitle' | tr }}< / div >
2019-09-10 19:21:30 +02:00
< / div >
< / div >
2019-10-25 12:10:08 +02:00
< div class = "col-sm-8 card-container" >
2019-09-16 14:03:13 +02:00
< div class = "card" ng-show = "view === 'display'" >
< div class = "row" >
< div class = "col-md-12" >
2020-03-19 19:26:19 -07:00
< form role = "form" name = "displayForm" ng-submit = "display.submit()" autocomplete = "off" >
< fieldset >
2019-09-16 14:03:13 +02:00
< div class = "form-group" ng-class = "{ 'has-error': !displayForm.label.$dirty && display.error.label }" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.display.label' | tr }}< / label >
2019-09-16 14:03:13 +02:00
< div class = "control-label" ng-show = "display.error.label" > {{display.error.label}}< / div >
< input type = "text" class = "form-control" id = "displayLabelInput" name = "label" ng-model = "display.label" >
< / div >
< div class = "form-group" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.display.tags' | tr }}< / label >
< tag-input class = "form-control" placeholder = "{{ 'app.display.tagsPlaceholder' | tr }}" taglist = "display.tags" name = "tags" uib-tooltip = "{{ 'app.display.tagsTooltip' | tr }}" > < / tag-input >
2019-09-16 14:03:13 +02:00
< / div >
< div class = "form-group" >
< div >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.display.icon' | tr }}< / label >
2019-09-16 14:03:13 +02:00
< / div >
2019-09-26 21:12:11 +02:00
< div id = "previewIcon" class = "app-custom-icon" ng-click = "display.showCustomIconSelector()" >
< img ng-src = "{{ display.iconUrl() || 'img/appicon_fallback.png' }}" fallback-icon = "img/appicon_fallback.png" onerror = "imageErrorHandler(this)" / >
2019-09-16 14:03:13 +02:00
< div class = "overlay" > < / div >
< / div >
2020-11-16 16:52:51 +01:00
< a href = "" style = "font-weight: normal;" ng-click = "display.resetCustomIcon()" > {{ 'app.display.iconResetAction' | tr }}< / a >
2019-09-16 14:03:13 +02:00
< input type = "file" id = "iconFileInput" style = "display: none" accept = "image/png" / >
2019-09-10 19:21:30 +02:00
< / div >
2019-09-16 14:03:13 +02:00
< input class = "ng-hide" type = "submit" ng-disabled = "(!display.icon.data && !displayForm.$dirty) || displayForm.$invalid || display.busy" / >
2020-03-19 19:26:19 -07:00
< / fieldset >
< / form >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
< div class = "row" >
< div class = "col-md-12 text-right" >
2020-11-16 16:52:51 +01:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "display.submit()" ng-disabled = "(!display.icon.data && !displayForm.$dirty) || display.$invalid || display.busy" > < i class = "fa fa-circle-notch fa-spin" ng-show = "display.busy" > < / i > {{ 'app.display.saveAction' | tr }}< / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
< / div >
2019-09-10 19:21:30 +02:00
2019-09-16 14:03:13 +02:00
< div class = "card" ng-show = "view === 'location'" >
< div class = "row" >
< div class = "col-md-12" >
2020-03-19 19:26:19 -07:00
< form role = "form" name = "locationForm" ng-submit = "location.submit()" autocomplete = "off" >
2020-11-16 16:52:51 +01:00
< div class = "form-group" ng-class = "{ 'has-error': (locationForm.location.$dirty && locationForm.location.$invalid) || (!locationForm.location.$dirty && location.error.location) }" >
< label class = "control-label" > {{ 'app.location.location' | tr }}< / label >
< div class = "has-error" ng-show = "location.error.location" > {{ location.error.location }}< / div >
< div class = "input-group form-inline" >
< input type = "text" class = "form-control" ng-model = "location.location" name = "location" placeholder = "{{ 'app.location.locationPlaceholder' | tr }}" autofocus >
< div class = "input-group-btn" >
< button type = "button" class = "btn btn-default dropdown-toggle" data-toggle = "dropdown" >
< span > {{ (!location.location ? '' : '.') + location.domain.domain }}< / span >
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu dropdown-menu-right" role = "menu" >
< li ng-repeat = "domain in domains" >
< a href = "" ng-click = "location.domain = domain" > {{ domain.domain }}< / a >
< / li >
< / ul >
2019-09-10 19:21:30 +02:00
< / div >
< / div >
2020-11-16 16:52:51 +01:00
< / div >
2019-09-16 14:03:13 +02:00
2020-11-16 16:52:51 +01:00
< p class = "text-small text-bold text-warning" ng-show = "location.location && location.domain.provider === 'manual'" ng-bind-html = "'appstore.installDialog.manualWarning' | tr:{ location: (location.location + '.' + location.domain.domain) }" > < / p >
<!-- hidden submit has to be prior to other button elements, otherwise firefox will treat them as the "enter" key action, in this case the alternate domain delete button! -->
< input class = "ng-hide" type = "submit" ng-disabled = "locationForm.$invalid || location.busy" / >
< div class = "has-error text-center" ng-show = "location.error.port" > {{ location.error.port }}< / div >
< div ng-repeat = "(env, info) in location.portBindingsInfo" >
< ng-form name = "portInfo_form" >
< div class = "form-group" ng-class = "{ 'has-error': (!locationForm.itemName{{$index}}.$dirty && location.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }" >
< label class = "control-label" for = "locationPortInput{{env}}" > < input type = "checkbox" ng-model = "location.portBindingsEnabled[env]" >
{{ info.title }}
< sup >
< a popover-placement = "top-right" popover-trigger = "outsideClick" uib-popover = "{{info.description}} ({{ HOST_PORT_MIN }} - {{ HOST_PORT_MAX }})" > < i class = "fa fa-question-circle" > < / i > < / a >
< / sup >
< / label >
< input type = "number" class = "form-control" ng-model = "location.portBindings[env]" ng-disabled = "!location.portBindingsEnabled[env]" id = "locationPortInput{{env}}" later-name = "itemName{{$index}}" min = "{{HOST_PORT_MIN}}" max = "{{HOST_PORT_MAX}}" required >
< / div >
< / ng-form >
< / div >
2019-09-10 19:21:30 +02:00
2021-01-18 17:55:48 -08:00
< div class = "form-group alias-domains" ng-show = "app.manifest.multiDomain" >
< label class = "control-label" > {{ 'app.location.aliases' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#aliases" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
< div class = "has-error" ng-show = "location.error.aliasDomains" > {{ location.error.aliasDomains }}< / div >
< div class = "row" ng-repeat = "aliasDomain in location.aliasDomains" >
< div class = "col col-lg-11" >
< div class = "input-group" >
< input type = "text" class = "form-control" ng-model = "aliasDomain.subdomain" placeholder = "{{ 'app.location.aliasesPlaceholder' | tr }}" >
< div class = "input-group-btn" >
< button type = "button" class = "btn btn-default dropdown-toggle" data-toggle = "dropdown" >
< span > {{ (!aliasDomain.subdomain ? '' : '.') + aliasDomain.domain.domain }}< / span >
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu dropdown-menu-right" role = "menu" >
< li ng-repeat = "domain in domains" >
< a href = "" ng-click = "aliasDomain.domain = domain" > {{ domain.domain }}< / a >
< / li >
< / ul >
< / div >
< / div >
< / div >
< div class = "col col-lg-1" >
< button class = "btn btn-danger btn-sm" ng-click = "location.delAliasDomain($event, $index)" > < i class = "far fa-trash-alt" > < / i > < / button >
< / div >
< / div >
< div ng-show = "location.aliasDomains.length === 0" > {{ 'app.location.noAliases' | tr }}< / div >
< div style = "margin-top: 5px;" > < a href = "" ng-click = "location.addAliasDomain($event)" > {{ 'app.location.addAliasAction' | tr }}< / a > < / div >
< / div >
2020-11-16 16:52:51 +01:00
< div class = "form-group alternate-domains" >
< label class = "control-label" > {{ 'app.location.redirections' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#redirections" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
< div class = "has-error" ng-show = "location.error.alternateDomains" > {{ location.error.alternateDomains }}< / div >
< div class = "row" ng-repeat = "alternateDomain in location.alternateDomains" >
< div class = "col col-lg-11" >
< div class = "input-group" >
< input type = "text" class = "form-control" ng-model = "alternateDomain.subdomain" placeholder = "{{ 'app.location.redirectionsPlaceholder' | tr }}" >
< div class = "input-group-btn" >
< button type = "button" class = "btn btn-default dropdown-toggle" data-toggle = "dropdown" >
< span > {{ (!alternateDomain.subdomain ? '' : '.') + alternateDomain.domain.domain }}< / span >
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu dropdown-menu-right" role = "menu" >
< li ng-repeat = "domain in domains" >
< a href = "" ng-click = "alternateDomain.domain = domain" > {{ domain.domain }}< / a >
< / li >
< / ul >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
< / div >
2020-11-16 16:52:51 +01:00
< div class = "col col-lg-1" >
< button class = "btn btn-danger btn-sm" ng-click = "location.delAlternateDomain($event, $index)" > < i class = "far fa-trash-alt" > < / i > < / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2020-11-16 16:52:51 +01:00
< div ng-show = "location.alternateDomains.length === 0" > {{ 'app.location.noRedirections' | tr }}< / div >
< div style = "margin-top: 5px;" > < a href = "" ng-click = "location.addAlternateDomain($event)" > {{ 'app.location.addRedirectionAction' | tr }}< / a > < / div >
< / div >
2020-03-19 19:26:19 -07:00
< / form >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
< div class = "row" >
< div class = "col-md-12 text-right" >
2020-02-07 10:42:58 -08:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "location.submit()" ng-disabled = "location.$invalid || location.busy || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "location.busy" > < / i > {{ 'app.location.saveAction' | tr }}
2019-12-20 17:05:45 -08:00
< / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2019-09-10 19:21:30 +02:00
< / div >
2019-09-16 14:03:13 +02:00
< div class = "card" ng-show = "view === 'access'" >
< div class = "row" >
< div class = "col-md-12" >
2020-03-19 19:26:19 -07:00
< form role = "form" name = "accessForm" ng-submit = "access.submit()" autocomplete = "off" >
2020-11-16 16:52:51 +01:00
< div class = "form-group" >
2021-03-17 14:22:33 -07:00
< div class = "form-group" ng-show = "app.manifest.addons.email" >
< label class = "control-label" > {{ 'app.accessControl.userManagement.title' | tr }}< / label >
< p > {{ 'appstore.installDialog.userManagementMailbox' | tr }}
< span ng-bind-html = "'appstore.installDialog.configuredForCloudronEmail' | tr:{ emailDocsLink: 'https://docs.cloudron.io/email/' }" >
< / p >
< / div >
< div ng-show = "access.ssoAuth && !app.manifest.addons.email" >
2021-03-02 20:49:47 -08:00
< label class = "control-label" > {{ 'app.accessControl.userManagement.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#access-restriction" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
2020-11-16 16:52:51 +01:00
< p > {{ 'app.accessControl.userManagement.description' | tr }} < span class = "text-small text-warning" ng-show = "access.ftp" > {{ 'app.accessControl.userManagement.descriptionSftp' | tr }}< / span > < / p >
< / div >
2021-03-17 14:22:33 -07:00
< div ng-show = "!access.ssoAuth || app.manifest.addons.email" >
2021-03-02 20:49:47 -08:00
< label class = "control-label" > {{ 'app.accessControl.userManagement.dashboardVisibility' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#dashboard-visibility" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
2021-03-17 14:22:33 -07:00
< p ng-show = "!app.manifest.addons.email" > {{ 'appstore.installDialog.userManagementNone' | tr }} < span ng-show = "access.ftp" > {{ 'app.accessControl.userManagement.sftpAccessControl' | tr }}< / span > < / p >
2020-11-16 16:52:51 +01:00
< / div >
2019-09-10 19:21:30 +02:00
2020-11-16 16:52:51 +01:00
< div class = "radio" >
< label >
< input type = "radio" ng-model = "access.accessRestrictionOption" value = "any" >
< span ng-show = "access.ssoAuth" > {{ 'appstore.installDialog.userManagementAllUsers' | tr }}< / span >
< span ng-show = "!access.ssoAuth" > {{ 'app.accessControl.userManagement.visibleForAllUsers' | tr }}< / span >
< / label >
< / div >
< div class = "radio" >
< label >
< input type = "radio" ng-model = "access.accessRestrictionOption" value = "groups" >
2019-09-10 19:21:30 +02:00
2020-11-16 16:52:51 +01:00
< span ng-show = "access.ssoAuth" > {{ 'appstore.installDialog.userManagementSelectUsers' | tr }}< / span >
< span ng-show = "!access.ssoAuth" > {{ 'app.accessControl.userManagement.visibleForSelected' | tr }}< / span >
2019-09-10 19:21:30 +02:00
2020-11-16 16:52:51 +01:00
< span class = "label label-danger" ng-show = "access.accessRestrictionOption === 'groups' && !access.isAccessRestrictionValid()" > {{ 'appstore.installDialog.errorUserManagementSelectAtLeastOne' | tr }}< / span >
< / label >
< / div >
< div >
< div style = "margin-left: 20px;" >
< div class = "col-md-5" >
{{ 'appstore.installDialog.users' | tr }}: < multiselect class = "input-sm stretch" ng-model = "access.accessRestriction.users" ng-disabled = "access.accessRestrictionOption !== 'groups'" options = "user.display for user in users" data-multiple = "true" filter-after-rows = "5" scroll-after-rows = "10" > < / multiselect >
< / div >
2019-09-16 14:03:13 +02:00
2020-11-16 16:52:51 +01:00
< div class = "col-md-5" >
{{ 'appstore.installDialog.groups' | tr }}: < multiselect class = "input-sm stretch" ng-model = "access.accessRestriction.groups" ng-disabled = "access.accessRestrictionOption !== 'groups'" options = "group.name for group in groups" data-multiple = "true" filter-after-rows = "5" scroll-after-rows = "10" > < / multiselect >
2019-09-16 14:03:13 +02:00
< / div >
2019-09-10 19:21:30 +02:00
< / div >
2019-09-16 14:03:13 +02:00
< / div >
2020-11-16 16:52:51 +01:00
< input class = "ng-hide" type = "submit" ng-disabled = "(access.accessRestrictionOption === 'groups' && !access.isAccessRestrictionValid()) || accessForm.$invalid || access.busy" / >
< / div >
2020-03-19 19:26:19 -07:00
< / form >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
< div class = "row" >
2019-09-17 14:49:26 +02:00
< div class = "col-md-12 text-right" >
2020-11-23 16:27:51 +01:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "access.submit()" ng-disabled = "(access.accessRestrictionOption === 'groups' && !access.isAccessRestrictionValid()) || access.$invalid || access.busy" > < i class = "fa fa-circle-notch fa-spin" ng-show = "access.busy" > < / i > {{ 'main.dialog.save' | tr }}< / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2019-09-17 15:32:43 +02:00
< div class = "row" ng-show = "app.manifest.addons.localstorage.ftp" >
2019-09-19 09:35:25 -07:00
< hr / >
2019-09-17 15:32:43 +02:00
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label > {{ 'app.accessControl.sftp.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#ftp-access" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
2020-06-25 10:36:25 +02:00
< br / >
< div class = "row" >
< div class = "col-xs-6" >
2020-11-16 16:52:51 +01:00
< span class = "text-muted" > {{ 'app.accessControl.sftp.server' | tr }}< / span >
2020-06-25 10:36:25 +02:00
< / div >
< div class = "col-xs-6 text-right" >
< span > {{ config.adminFqdn }}< / span >
< / div >
< / div >
< div class = "row" >
< div class = "col-xs-6" >
2020-11-16 16:52:51 +01:00
< span class = "text-muted" > {{ 'app.accessControl.sftp.port' | tr }}< / span >
2020-06-25 10:36:25 +02:00
< / div >
< div class = "col-xs-6 text-right" >
< span > 222< / span >
< / div >
< / div >
< div class = "row" >
< div class = "col-xs-6" >
2020-11-16 16:52:51 +01:00
< span class = "text-muted" > {{ 'app.accessControl.sftp.username' | tr }}< / span >
2020-06-25 10:36:25 +02:00
< / div >
< div class = "col-xs-6 text-right" >
2020-08-08 19:15:21 -07:00
< span > {{ user.username }}@{{ app.fqdn }}< / span >
2020-06-25 10:36:25 +02:00
< / div >
< / div >
2019-09-17 15:32:43 +02:00
< / div >
< / div >
2019-09-10 19:21:30 +02:00
< / div >
2019-09-16 14:03:13 +02:00
< div class = "card" ng-show = "view === 'resources'" >
< div class = "row" >
< div class = "col-md-12" >
2020-03-19 19:26:19 -07:00
< form role = "form" name = "resourcesForm" ng-submit = "resources.submitMemoryLimit()" autocomplete = "off" >
2020-11-16 16:52:51 +01:00
< div class = "form-group" >
< label class = "control-label" for = "memoryLimit" > {{ 'app.resources.memory.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#memory-limit" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > : < b > {{ resources.memoryLimit | prettyByteSize:'Default (256 MB)' }}< / b > < / label >
< div style = "padding: 0 10px;" >
< slider id = "memoryLimit" ng-model = "resources.memoryLimit" step = "134217728" tooltip = "hide" ticks = "resources.memoryTicks" ticks-snap-bounds = "67108864" > < / slider >
2019-09-16 14:03:13 +02:00
< / div >
2020-11-16 16:52:51 +01:00
< / div >
2019-09-10 19:21:30 +02:00
2020-11-16 16:52:51 +01:00
< input class = "ng-hide" type = "submit" ng-disabled = "resources.memoryLimit === resources.currentMemoryLimit || resourcesForm.$invalid || resources.busy" / >
2020-03-19 19:26:19 -07:00
< / form >
2019-09-18 17:12:10 +02:00
< / div >
< / div >
< div class = "row" >
2020-10-21 13:27:31 +02:00
< div class = "col-md-8" >
2020-11-16 16:52:51 +01:00
< span ng-show = "resources.error.memoryLimit" class = "text-danger" > {{ 'app.resources.memory.error' | tr }}< / span >
2020-10-21 13:27:31 +02:00
< / div >
< div class = "col-md-4 text-right" >
2020-02-07 10:42:58 -08:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "resources.submitMemoryLimit()" ng-disabled = "resources.memoryLimit === resources.currentMemoryLimit || resourcesForm.$invalid || resources.busy || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "resources.busy" > < / i > {{ 'app.resources.memory.resizeAction' | tr }}
2019-12-20 17:05:45 -08:00
< / button >
2019-09-18 17:12:10 +02:00
< / div >
< / div >
< hr / >
2020-01-28 22:05:06 -08:00
< div class = "row" >
< div class = "col-md-12" >
2020-03-19 19:26:19 -07:00
< form role = "form" name = "resourcesForm" ng-submit = "resources.submitCpuShares()" autocomplete = "off" >
< fieldset >
2020-01-28 22:05:06 -08:00
< div class = "form-group" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" for = "cpuShares" > {{ 'app.resources.cpu.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#cpu-shares" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > : < b > {{ (resources.cpuShares * 100 / 1024 | number:0) + ' %' }}< / b > < / label >
< p > {{ 'app.resources.cpu.description' | tr }}< / p >
2020-01-28 22:05:06 -08:00
< div style = "padding: 0 10px;" >
2020-03-06 10:40:21 -08:00
< slider id = "cpuShares" ng-model = "resources.cpuShares" ticks = "[32, 256, 512, 768, 1024]" step = "32" ticks-snap-bounds = "32" min = "32" max = "1024" tooltip = "hide" > < / slider >
2020-01-28 22:05:06 -08:00
< / div >
< / div >
< input class = "ng-hide" type = "submit" ng-disabled = "resources.cpuShares === resources.currentCpuShares || resourcesForm.$invalid || resources.busyCpuShares" / >
2020-03-19 19:26:19 -07:00
< / fieldset >
< / form >
2020-01-28 22:05:06 -08:00
< / div >
< / div >
< div class = "row" >
< div class = "col-md-12 text-right" >
2020-02-07 10:42:58 -08:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "resources.submitCpuShares()" ng-disabled = "resources.cpuShares === resources.currentCpuShares || resourcesForm.$invalid || resources.busyCpuShares || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "resources.busyCpuShares" > < / i > {{ 'app.resources.cpu.setAction' | tr }}
2020-01-28 22:05:06 -08:00
< / button >
< / div >
< / div >
2020-10-28 22:11:05 -07:00
< / div >
< div class = "card" ng-show = "view === 'storage'" >
2019-09-18 17:12:10 +02:00
< div class = "row" >
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.storage.appdata.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/storage/#app-data-directory" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
< p ng-bind-html = "'app.storage.appdata.description' | tr:{ storagePath: ('/home/yellowtent/appsdata/' + app.id) }" > < / p >
2020-10-28 22:11:05 -07:00
< form role = "form" name = "storageDataDirForm" ng-submit = "storage.submitDataDir()" autocomplete = "off" >
2020-11-16 16:52:51 +01:00
< div class = "form-group" ng-class = "{ 'has-error': storageDataDirForm.$dirty && storage.error.dataDir }" >
< div ng-show = "storage.error.dataDir" > {{ storage.error.dataDir }}< / div >
< input type = "text" class = "form-control" name = "dataDir" placeholder = "{{ 'app.storage.appdata.dataDirPlaceholder' | tr }}" ng-model = "storage.dataDir" >
< / div >
2019-09-10 19:21:30 +02:00
2020-11-16 16:52:51 +01:00
< input class = "ng-hide" type = "submit" ng-disabled = "!storageDataDirForm.$dirty || storageDataDirForm.$invalid || storage.busyDataDir" / >
2020-03-19 19:26:19 -07:00
< / form >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
< div class = "row" >
< div class = "col-md-12 text-right" >
2020-10-28 22:11:05 -07:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "storage.submitDataDir()" ng-disabled = "!storageDataDirForm.$dirty || storageDataDirForm.$invalid || storage.busyDataDir || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "storage.busyDataDir" > < / i > {{ 'app.storage.appdata.moveAction' | tr }}
2019-12-20 17:05:45 -08:00
< / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2020-05-22 12:05:23 -07:00
2020-09-24 14:32:00 -07:00
< hr >
2020-04-29 22:18:44 -07:00
2020-10-28 22:11:05 -07:00
< div class = "form-group mounts" >
2020-11-23 17:10:40 -08:00
< label class = "control-label" > {{ 'app.storage.mounts.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#mounts" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
2020-10-28 22:11:05 -07:00
< div class = "has-error" ng-show = "storage.error.mounts" > {{ storage.error.mounts }}< / div >
2020-11-23 17:25:13 -08:00
< div ng-show = "storage.mounts.length === 0" > {{ 'app.storage.mounts.noMounts' | tr }}< / div >
< p ng-bind-html = "'storage.mounts.volumeLocation' | tr" ng-show = "storage.mounts.length > 0" > < / p >
< table ng-show = "storage.mounts.length > 0" class = "table table-hover" style = "margin-top: 10px;" >
2020-10-28 22:11:05 -07:00
< thead >
< tr >
2020-11-16 16:52:51 +01:00
< th style = "width: 40%" > {{ 'app.storage.mounts.volume' | tr }}< / th >
< th class = "text-left hidden-xs hidden-sm" > {{ 'app.storage.mounts.readOnly' | tr }}< / th >
2020-11-11 22:50:57 +01:00
< th style = "width: 100px" class = "text-right" > {{ 'main.actions' | tr }}< / th >
2020-10-28 22:11:05 -07:00
< / tr >
< / thead >
< tbody >
< tr ng-repeat = "mount in storage.mounts" >
< td >
2020-12-04 11:35:01 +01:00
< multiselect ng-model = "mount.volume" data-compare-by = "hostPath" options = "volume.name for volume in volumes" data-multiple = "false" filter-after-rows = "5" scroll-after-rows = "10" > < / multiselect >
2020-10-28 22:11:05 -07:00
< / td >
2020-10-30 12:37:32 +01:00
< td class = "text-left" style = "vertical-align: middle;" >
< input type = "checkbox" ng-model = "mount.readOnly" style = "margin-top: initial;" / >
< / td >
< td class = "text-right no-wrap" style = "vertical-align: middle" >
2020-10-28 22:11:05 -07:00
< button class = "btn btn-danger btn-xs" ng-click = "storage.delMount($event, $index)" > < i class = "far fa-trash-alt" > < / i > < / button >
< / td >
< / tr >
< / tbody >
< / table >
2020-11-16 16:52:51 +01:00
< div style = "margin-top: 5px;" > < a href = "" ng-click = "storage.addMount($event)" > {{ 'app.storage.mounts.addMountAction' | tr }}< / a > < / div >
2020-04-29 22:18:44 -07:00
< / div >
2020-09-24 14:32:00 -07:00
< div class = "row" >
2020-04-29 22:18:44 -07:00
< div class = "col-md-12 text-right" >
2020-10-28 22:11:05 -07:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "storage.submitMounts()" ng-disabled = "storage.busyMounts || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "storage.busyMounts" > < / i > {{ 'app.storage.mounts.saveAction' | tr }}
2020-04-29 22:18:44 -07:00
< / button >
< / div >
< / div >
2019-09-10 19:21:30 +02:00
< / div >
2020-05-13 00:42:27 +02:00
< div class = "card" ng-show = "view === 'graphs'" >
< div class = "row" >
< div class = "col-md-12" >
< div class = "dropdown pull-right" >
2020-05-13 01:12:13 +02:00
< button class = "btn btn-sm btn-primary dropdown-toggle" type = "button" data-toggle = "dropdown" >
2021-04-01 16:05:13 +02:00
{{ graphs.period | trKeyFromPeriod | tr }}
2020-05-13 00:42:27 +02:00
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu" >
2021-04-01 16:05:13 +02:00
< li > < a href = "" ng-click = "graphs.setPeriod(12)" > {{ 12 | trKeyFromPeriod | tr }}< / a > < / li >
< li > < a href = "" ng-click = "graphs.setPeriod(24)" > {{ 24 | trKeyFromPeriod | tr }}< / a > < / li >
< li > < a href = "" ng-click = "graphs.setPeriod(24*7)" > {{ 24*7 | trKeyFromPeriod | tr }}< / a > < / li >
< li > < a href = "" ng-click = "graphs.setPeriod(24*30)" > {{ 24*30 | trKeyFromPeriod | tr }}< / a > < / li >
2020-05-13 00:42:27 +02:00
< / ul >
< / div >
2020-11-16 16:52:51 +01:00
< label style = "margin-top: 10px;" > {{ 'app.graphs.memoryTitle' | tr }}< / label >
2020-05-13 01:12:13 +02:00
< canvas id = "graphsMemoryChart" style = "width: 100%;" > < / canvas >
2020-05-13 00:42:27 +02:00
< / div >
< / div >
< / div >
2019-09-16 14:03:13 +02:00
< div class = "card" ng-show = "view === 'email'" >
< div class = "row" >
< div class = "col-md-12" >
2021-03-17 15:03:20 -07:00
< label class = "control-label" > {{ 'app.email.from.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#mail-from-address" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
2021-03-17 16:40:17 +01:00
2021-03-17 15:03:20 -07:00
< div class = "radio" ng-show = "app.manifest.addons.sendmail.optional" >
2021-03-17 16:40:17 +01:00
< label >
< input type = "radio" ng-model = "email.enableMailbox" value = "1" > {{ 'app.email.from.enable' | tr }}
< / label >
< / div >
2020-11-16 16:52:51 +01:00
2021-03-18 15:44:35 +01:00
< div style = "padding-left: 20px;" >
< p ng-bind-html = "'app.email.from.enableDescription' | tr:{ domain: app.domain, domainConfigLink: ('/#/email/' + app.domain) }" > < / p >
< form role = "form" name = "emailForm" ng-submit = "email.submit()" autocomplete = "off" >
2021-03-18 15:46:43 +01:00
< fieldset ng-disabled = "email.enableMailbox === '0'" >
2021-03-18 15:44:35 +01:00
< div class = "form-group" ng-class = "{ 'has-error': emailForm.$dirty && email.error.mailboxName }" >
< div ng-show = "email.error.mailboxName" > {{ email.error.mailboxName }}< / div >
< div class = "input-group form-inline" ng-class = "{ 'has-error': !emailForm.mailboxName.$dirty && email.error.mailboxName }" >
< input type = "text" class = "form-control" name = "mailboxName" placeholder = "{{ 'app.email.from.mailboxPlaceholder' | tr }}" ng-model = "email.mailboxName" >
< div class = "input-group-btn" >
< button type = "button" class = "btn btn-default dropdown-toggle" data-toggle = "dropdown" >
< span > {{ '@' + email.mailboxDomain.domain }}< / span >
< span class = "caret" > < / span >
< / button >
< ul class = "dropdown-menu dropdown-menu-right" role = "menu" >
< li ng-repeat = "domain in domains" >
< a href = "" ng-click = "email.mailboxDomain = domain" > {{ domain.domain }}< / a >
< / li >
< / ul >
< / div >
2021-03-16 22:41:25 -07:00
< / div >
2021-03-18 15:44:35 +01:00
< br / >
2019-09-16 14:03:13 +02:00
< / div >
2021-03-18 15:44:35 +01:00
< / fieldset >
< input class = "ng-hide" type = "submit" ng-disabled = "(email.currentMailboxDomainName === email.mailboxDomain.domain && email.currentMailboxName === email.mailboxName) || email.busy || app.error || app.taskId" / >
< / form >
< / div >
2021-03-17 15:03:20 -07:00
< div class = "radio" ng-show = "app.manifest.addons.sendmail.optional" >
< label >
< input type = "radio" ng-model = "email.enableMailbox" value = "0" > {{ 'app.email.from.disable' | tr }}
< / label >
< / div >
2021-03-18 15:44:35 +01:00
< div style = "padding-left: 20px;" >
< p ng-show = "app.manifest.addons.sendmail.optional" > {{ 'app.email.from.disableDescription' | tr }}< / p >
< / div >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
< div class = "row" >
2019-09-17 15:09:39 +02:00
< div class = "col-md-12 text-right" >
2021-03-18 15:45:11 +01:00
< br / >
2021-03-17 15:03:20 -07:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "email.submit()" ng-disabled = "(app.enableMailbox === email.enableMailbox && email.currentMailboxDomainName === email.mailboxDomain.domain && email.currentMailboxName === email.mailboxName) || email.busy || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "email.busy" > < / i > {{ 'app.email.from.saveAction' | tr }}
2019-12-20 17:05:45 -08:00
< / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2019-09-10 19:21:30 +02:00
< / div >
2019-09-16 14:03:13 +02:00
< div class = "card" ng-show = "view === 'security'" >
< div class = "row" >
< div class = "col-md-12" >
2020-03-19 19:26:19 -07:00
< form role = "form" name = "securityForm" ng-submit = "security.submit()" autocomplete = "off" >
2020-11-16 16:52:51 +01:00
< div class = "form-group" >
2020-11-23 16:29:48 +01:00
< label class = "control-label" style = "width: 100%" > {{ 'app.security.robots.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#robotstxt" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < a href = "" class = "pull-right" style = "font-weight: normal;" ng-click = "security.robotsTxt = ROBOTS_DISABLE_INDEXING_TEMPLATE" > {{ 'app.security.robots.disableIndexingAction' | tr }}< / a > < / label >
2020-11-16 16:52:51 +01:00
< textarea ng-trim = "false" style = "white-space: pre-wrap" ng-model = "security.robotsTxt" placeholder = "{{ 'app.security.robots.txtPlaceholder' | tr }}" class = "form-control" rows = "4" > < / textarea >
< / div >
2019-09-10 19:21:30 +02:00
2020-11-16 16:52:51 +01:00
< div class = "form-group" >
< label class = "control-label" style = "width: 100%" > {{ 'app.security.csp.title' | tr }} < sup > < a ng-href = "https://docs.cloudron.io/apps/#custom-csp" class = "help" target = "_blank" > < i class = "fa fa-question-circle" > < / i > < / a > < / sup > < / label >
< p > {{ 'app.security.csp.description' | tr }}< / p >
< textarea ng-model = "security.csp" placeholder = "default-src 'self'; frame-ancestors 'none';" class = "form-control" rows = "2" > < / textarea >
< / div >
2019-10-14 15:20:48 -07:00
2020-11-16 16:52:51 +01:00
< input class = "ng-hide" type = "submit" ng-disabled = "securityForm.$invalid || security.busy" / >
2020-03-19 19:26:19 -07:00
< / form >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2019-10-14 15:20:48 -07:00
< br / >
2019-09-16 14:03:13 +02:00
< div class = "row" >
< div class = "col-md-12 text-right" >
2019-12-20 17:05:45 -08:00
< button class = "btn btn-outline btn-primary pull-right" ng-click = "security.submit()" ng-disabled = "security.$invalid || security.busy || app.error" tooltip-enable = "app.error" uib-tooltip = "App is in error state" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "security.busy" > < / i > {{ 'app.security.csp.saveAction' | tr }}
2019-12-20 17:05:45 -08:00
< / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2019-09-10 19:21:30 +02:00
< / div >
2019-09-16 14:03:13 +02:00
< div class = "card" ng-show = "view === 'updates'" >
2020-11-16 16:52:51 +01:00
< p > < label class = "control-label" > {{ 'app.updates.info.title' | tr }}< / label > < / p >
2020-05-18 14:57:21 -07:00
< div class = "row" >
2020-05-27 22:31:10 -07:00
< div class = "col-xs-4" >
2020-11-16 16:52:51 +01:00
< span class = "text-muted" > {{ 'app.updates.info.description' | tr }}< / span >
2020-05-18 14:57:21 -07:00
< / div >
2020-05-27 22:31:10 -07:00
< div class = "col-xs-8 text-right" >
2020-05-18 14:57:21 -07:00
< span ng-show = "app.appStoreId" > {{ app.manifest.title }} {{ app.upstreamVersion }}< / span >
< span ng-show = "!app.appStoreId" > {{ app.manifest.dockerImage }}< / span >
< / div >
< / div >
< div class = "row" >
< div class = "col-xs-6" >
2020-11-16 16:52:51 +01:00
< span class = "text-muted" > {{ 'app.updates.info.appId' | tr }}< / span >
2020-05-18 14:57:21 -07:00
< / div >
< div class = "col-xs-6 text-right" >
< span > {{ app.id }}< / span >
< / div >
< / div >
< div class = "row" >
< div class = "col-xs-6" >
2020-11-16 16:52:51 +01:00
< span class = "text-muted" > {{ 'app.updates.info.packageVersion' | tr }}< / span >
2020-05-18 14:57:21 -07:00
< / div >
< div class = "col-xs-6 text-right" >
2020-12-09 17:13:52 -08:00
< span ng-show = "app.appStoreId" > < a ng-href = "/#/appstore/{{app.manifest.id}}?version={{app.manifest.version}}" > {{ app.manifest.id }}@{{ app.manifest.version }}< / a > < / span >
< span ng-show = "!app.appStoreId" > {{ app.manifest.version }}< / span >
2020-05-18 14:57:21 -07:00
< / div >
< / div >
< div class = "row" >
< div class = "col-xs-6" >
2020-11-16 16:52:51 +01:00
< span class = "text-muted" > {{ 'app.updates.info.lastUpdated' | tr }}< / span >
2020-05-18 14:57:21 -07:00
< / div >
< div class = "col-xs-6 text-right" >
< span > {{ app.updateTime | prettyDate }}< / span >
< / div >
< / div >
< br / >
2019-09-17 15:32:43 +02:00
< div class = "row" >
2020-12-21 12:49:21 -08:00
< div class = "col-md-12" ng-show = "!config.update[app.id].manifest.version || config.update[app.id].manifest.version === app.manifest.version" >
2020-11-16 16:52:51 +01:00
< button class = "btn btn-primary pull-right" ng-show = "app.appStoreId" ng-click = "updates.check()" ng-disabled = "updates.busyCheck" > < i class = "fa fa-circle-notch fa-spin" ng-show = "updates.busyCheck" > < / i > {{ 'app.updates.info.checkForUpdatesAction' | tr }}< / button >
< span ng-show = "!app.appStoreId" class = "text-danger pull-right" > {{ 'app.updates.info.customAppUpdateInfo' | tr }}< / span >
2020-09-29 17:32:25 +02:00
< / div >
2020-12-21 12:49:21 -08:00
< div class = "col-md-12" ng-show = "config.update[app.id].manifest.version && config.update[app.id].manifest.version !== app.manifest.version && app.installationState !== 'pending_update'" >
2020-11-16 16:52:51 +01:00
< button type = "button" class = "btn btn-success pull-right" ng-click = "updates.askUpdate()" ng-disabled = "app.taskId || app.error || app.runState === 'stopped'" tooltip-enable = "app.error || app.taskId || app.runState === 'stopped'" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is not running' }}" > {{ 'app.updates.info.updateAvailableAction' | tr }}< / button >
2019-09-17 15:32:43 +02:00
< / div >
< / div >
2019-09-19 11:58:06 -07:00
< hr / >
2019-09-16 14:03:13 +02:00
< div class = "row" >
2019-09-17 16:16:48 +02:00
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.updates.auto.title' | tr }}< / label >
< p > {{ 'app.updates.auto.description' | tr }}< / p >
2020-11-17 23:37:58 +01:00
< p class = "text-success" ng-show = "updates.enableAutomaticUpdate" > {{ 'app.updates.auto.enabled' | tr }}< / p >
< p class = "text-danger" ng-hide = "updates.enableAutomaticUpdate" > {{ 'app.updates.auto.disabled' | tr }}< / p >
2020-11-16 16:52:51 +01:00
< button class = "btn btn-primary pull-right" uib-tooltip = "{{ app.appStoreId ? '' : 'Not available for custom apps' }}" ng-class = "{ 'btn-danger': updates.enableAutomaticUpdate }" ng-click = "updates.toggleAutomaticUpdates()" ng-disabled = "updates.busyAutomaticUpdates || !app.appStoreId" > < i class = "fa fa-circle-notch fa-spin" ng-show = "updates.busyAutomaticUpdates" > < / i > {{ updates.enableAutomaticUpdate ? ('app.updates.auto.disableAction' | tr) : ('app.updates.auto.enableAction' | tr) }} < / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2019-09-10 19:21:30 +02:00
< / div >
2019-12-17 10:24:42 -08:00
< div class = "card" ng-show = "view === 'backups'" >
2019-09-19 12:24:22 -07:00
< div class = "row" >
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.backups.backups.title' | tr }}< / label >
< div > {{ 'app.backups.backups.description' | tr }}< / div >
2019-12-17 10:15:38 -08:00
< br / >
2019-09-19 12:24:22 -07:00
2020-02-06 16:11:21 -08:00
< table ng-hide = "!backups.backups.length" class = "table table-hover" style = "margin: 0;" >
2019-09-16 14:03:13 +02:00
< thead >
< tr >
< th width = "25px" > < / th >
2020-11-16 16:52:51 +01:00
< th > {{ 'app.backups.backups.packageVersion' | tr }}< / th >
< th > {{ 'app.backups.backups.time' | tr }}< / th >
2020-11-11 22:50:57 +01:00
< th class = "text-right" width = "180px" > {{ 'main.actions' | tr }}< / th >
2019-09-16 14:03:13 +02:00
< / tr >
< / thead >
< tbody >
< tr ng-repeat = "backup in backups.backups" >
2020-11-16 16:52:51 +01:00
< td > < div class = "hand clipboard" data-clipboard-text = "{{ backup.id }}" uib-tooltip = "{{ copyBackupIdDone ? ('main.clipboard.copied' | tr) : ('main.clipboard.clickToCopyBackupId' | tr) }}" tooltip-placement = "right" > < i class = "fa fa-copy" > < / i > < / div > < / td >
< td > < div > v{{ backup.packageVersion }}< / div > < / td >
< td > < div uib-tooltip = "{{ backup.creationTime | prettyLongDate }}" > {{ backup.creationTime | prettyDate }}< / div > < / td >
2019-09-16 14:03:13 +02:00
< td class = "text-right no-wrap" style = "vertical-align: bottom" >
2020-11-16 16:52:51 +01:00
< button class = "btn btn-xs btn-default" ng-click = "downloadConfig(backup)" uib-tooltip = "{{ 'app.backups.backups.downloadConfigTooltip' | tr }}" > < i class = "fas fa-file-alt" > < / i > < / button >
2020-05-16 11:19:47 -07:00
2020-11-16 16:52:51 +01:00
< button class = "btn btn-xs btn-default" ng-click = "clone.show(backup)" uib-tooltip = "{{ 'app.backups.backups.cloneTooltip' | tr }}" > < i class = "far fa-clone" > < / i > < / button >
< button class = "btn btn-xs btn-danger" ng-click = "restore.show(backup)" ng-disabled = "app.taskId || app.runState === 'stopped'" uib-tooltip = "{{ 'app.backups.backups.restoreTooltip' | tr }}" > < i class = "fas fa-history" > < / i > < / button >
2019-09-16 14:03:13 +02:00
< / td >
< / tr >
< / tbody >
< / table >
2020-02-06 16:11:21 -08:00
< br / >
2020-05-28 12:08:39 -07:00
< button type = "button" class = "btn btn-primary pull-right" ng-click = "backups.createBackup()" ng-disabled = "app.taskId || backups.busyCreate || app.error || app.runState === 'stopped'" tooltip-enable = "app.error || app.taskId || app.runState === 'stopped'" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is not running' }}" >
2020-11-16 16:52:51 +01:00
< i class = "fa fa-circle-notch fa-spin" ng-show = "app.installationState === 'pending_backup' || backups.busyCreate" > < / i > {{ 'app.backups.backups.createBackupAction' | tr }}
2020-02-06 16:11:21 -08:00
< / button >
2019-09-16 14:03:13 +02:00
< / div >
< / div >
2019-09-17 16:16:48 +02:00
< hr / >
2020-02-06 16:08:22 -08:00
< div class = "row" >
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.backups.import.title' | tr }}< / label >
< p > {{ 'app.backups.import.description' | tr }}< / p >
2020-02-07 10:42:58 -08:00
2020-11-16 16:52:51 +01:00
< button class = "btn btn-primary pull-right" class = "btn-primary" ng-click = "importBackup.show()" ng-disabled = "importBackup.busy || app.taskId || app.runState === 'stopped'" tooltip-enable = "app.taskId" uib-tooltip = "App is not running" >
< i class = "fa fa-circle-notch fa-spin" ng-show = "backups.busy" > < / i > {{ 'app.backups.backups.importAction' | tr }}
2020-02-07 10:22:52 -08:00
< / button >
2020-02-06 16:08:22 -08:00
< / div >
< / div >
< hr / >
2019-09-16 14:03:13 +02:00
< div class = "row" >
2019-09-17 16:16:48 +02:00
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.backups.auto.title' | tr }}< / label >
2019-09-19 12:24:22 -07:00
2020-11-16 16:52:51 +01:00
< p ng-bind-html = "'app.backups.auto.description' | tr:{ backupLink: '/#/backups' }" > < / p >
< p class = "text-success" ng-show = "backups.enableBackup" > {{ 'app.backups.auto.enabled' | tr }}< / p >
< p class = "text-danger" ng-hide = "backups.enableBackup" > {{ 'app.backups.auto.disabled' | tr }}< / p >
2019-09-19 12:24:22 -07:00
2020-11-16 16:52:51 +01:00
< button class = "btn btn-primary pull-right" ng-class = "{ 'btn-danger': backups.enableBackup }" ng-click = "backups.toggleAutomaticBackups()" ng-disabled = "backups.busyAutomaticBackups" > < i class = "fa fa-circle-notch fa-spin" ng-show = "backups.busyAutomaticBackups" > < / i > {{ backups.enableBackup ? ('app.backups.auto.disableAction' | tr) : ('app.backups.auto.enableAction' | tr) }}< / button >
2019-09-17 16:16:48 +02:00
< / div >
< / div >
2019-09-13 17:07:45 +02:00
< / div >
2019-09-10 19:21:30 +02:00
2019-12-16 13:30:51 -08:00
< div class = "card" ng-show = "view === 'repair'" >
2019-09-23 17:27:40 -07:00
< div class = "row" >
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.repair.recovery.title' | tr }}< / label >
< p ng-bind-html = "'app.repair.recovery.description' | tr:{ docsLink: 'https://docs.cloudron.io/troubleshooting/#unresponsive-app' }" > < / p >
< button class = "btn btn-primary pull-right" ng-click = "repair.pauseAppBegin()" ng-show = "!app.debugMode" ng-disabled = "repair.pauseBusy || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" > {{ 'app.repair.recovery.enableRecoveryModeAction' | tr }}< / button >
< button class = "btn btn-primary pull-right" ng-click = "repair.pauseAppDone()" ng-show = "app.debugMode" ng-disabled = "repair.pauseBusy || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" > {{ 'app.repair.recovery.disableRecoveryModeAction' | tr }}< / button >
< button class = "btn btn-primary pull-right" ng-click = "repair.restartApp()" ng-disabled = "repair.restartBusy || app.error || app.taskId" tooltip-enable = "app.error || app.taskId" uib-tooltip = "{{ app.error ? 'App is in error state' : 'App is busy' }}" > < i ng-show = "repair.restartBusy" class = "fa fa-circle-notch fa-spin" > < / i > {{ 'app.repair.recovery.restartAction' | tr }}< / button >
2019-12-16 18:18:22 -08:00
< / div >
< / div >
< hr / >
< div class = "row" >
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.repair.taskError.title' | tr }}< / label >
< p > {{ 'app.repair.taskError.description' | tr }}< / p >
2019-11-23 17:49:13 -08:00
< p ng-show = "app.error" > An error occurred during the < b > {{ app.error.installationState | taskName }}< / b > operation: < span class = "text-danger" > < b > {{ app.error.reason + ': ' + app.error.message }}< / b > < / span > < / p >
2020-11-24 19:00:16 +01:00
< button class = "btn btn-primary pull-right" ng-click = "repair.confirm()" ng-disabled = "app.taskId || !app.error" tooltip-enable = "app.taskId" uib-tooltip = "{{ 'app.repair.appIsBusyTooltip' | tr }}" > {{ 'app.repair.taskError.retryAction' | tr:{ task: (app.error.installationState | taskName) } }}< / button >
2019-09-19 12:50:06 -07:00
< / div >
< / div >
2019-09-13 10:34:12 +02:00
< / div >
2019-09-16 14:03:13 +02:00
2019-09-17 15:40:04 +02:00
< div class = "card" ng-show = "view === 'uninstall'" >
2020-11-16 14:42:02 +01:00
< div class = "row" >
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.uninstall.startStop.title' | tr }}< / label >
< p > {{ 'app.uninstall.startStop.description' | tr }}< / p >
2020-11-18 00:40:15 +01:00
< button class = "btn btn-default pull-right" ng-class = "{ 'btn-primary': uninstall.startButton }" ng-click = "uninstall.toggleRunState()" ng-disabled = "app.taskId || app.error || app.installationState === 'pending_start' || app.installationState === 'pending_stop'" >
2020-11-16 14:42:02 +01:00
< i ng-show = "app.installationState === 'pending_start' || app.installationState === 'pending_stop'" class = "fa fa-circle-notch fa-spin" > < / i >
2020-11-16 16:52:51 +01:00
{{ uninstall.startButton ? ('app.uninstall.startStop.startAction' | tr) : ('app.uninstall.startStop.stopAction' | tr) }}
2020-11-16 14:42:02 +01:00
< / button >
< / div >
< / div >
< hr / >
2019-12-16 12:54:24 -08:00
< div class = "row" >
< div class = "col-md-12" >
2020-11-16 16:52:51 +01:00
< label class = "control-label" > {{ 'app.uninstall.uninstall.title' | tr }}< / label >
< p > {{ 'app.uninstall.uninstall.description' | tr }}< / p >
< p ng-bind-html = "'app.uninstall.uninstall.backupWarning' | tr:{ importBackupDocsLink: 'https://docs.cloudron.io/backups/#import-app-backup' }" > < / p >
< button class = "btn btn-danger pull-right" ng-click = "uninstall.ask()" > {{ 'app.uninstall.uninstall.uninstallAction' | tr }}< / button >
2019-09-17 15:40:04 +02:00
< / div >
< / div >
2019-12-16 12:54:24 -08:00
< / div >
2019-09-17 15:40:04 +02:00
2019-09-13 10:34:12 +02:00
< / div >
< / div >
2019-09-10 19:21:30 +02:00
< / div >