2016-02-25 15:38:46 +01:00
< div class = "row animateMeOpacity ng-hide" ng-show = "installedApps.length === 0 && user.admin" >
2015-07-20 00:09:47 -07:00
< div class = "col-lg-6 col-lg-offset-3" style = "text-align: center;" >
< br / > < br / > < br / > < br / >
< h1 > < i class = "fa fa-cloud-download fa-fw" > < / i > Your Cloudron does not have any apps installed yet!< / h1 >
< br / > < / br >
< h3 > How about installing some? Checkout the < a href = "#/appstore" > App Store< / a > < / h3 >
< / div >
< / div >
2016-02-25 15:38:46 +01:00
< div class = "row animateMeOpacity ng-hide" ng-show = "installedApps.length === 0 && !user.admin" >
< div class = "col-lg-6 col-lg-offset-3" style = "text-align: center;" >
< br / > < br / > < br / > < br / >
< h1 > You don't have access to any apps on this Cloudron yet!< / h1 >
< br / > < / br >
< h3 > Once you do, they will show up here.< / h3 >
< / div >
< / div >
2015-07-20 00:09:47 -07:00
<!-- Modal configure app -->
< div class = "modal fade" id = "appConfigureModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Configure {{ appConfigure.app.manifest.title }}< / h4 >
< / div >
< div class = "modal-body" >
< fieldset >
2016-02-11 12:53:35 +01:00
< form role = "form" name = "appConfigureForm" ng-submit = "doConfigure()" autocomplete = "off" >
2015-07-20 00:09:47 -07:00
< div class = "has-error text-center" ng-show = "appConfigure.error.other" > {{ appConfigure.error.other }}< / div >
< div class = "form-group" ng-class = "{ 'has-error': (appConfigureForm.location.$dirty && appConfigureForm.location.$invalid) || (!appConfigureForm.location.$dirty && appConfigure.error.location) }" >
< label class = "control-label" for = "appConfigureLocationInput" > Location {{ appConfigure.error.location }} < / label >
< div class = "input-group form-inline" >
< input type = "text" class = "form-control" ng-model = "appConfigure.location" id = "appConfigureLocationInput" name = "location" placeholder = "Leave empty to use bare domain" autofocus >
< div class = "input-group-addon" >
{{ !appConfigure.location ? '' : (config.isCustomDomain ? '.' : '-') }}{{ config.fqdn }}
< / div >
< / div >
< / div >
< div class = "has-error text-center" ng-show = "appConfigure.error.port" > {{ appConfigure.error.port }}< / div >
< div ng-repeat = "(env, info) in appConfigure.portBindingsInfo" >
< ng-form name = "portInfo_form" >
< div class = "form-group" ng-class = "{ 'has-error': (!appConfigureForm.itemName{{$index}}.$dirty && appConfigure.error.port) || (portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid) }" >
< label class = "control-label" for = "appConfigurePortInput{{env}}" > < input type = "checkbox" ng-model = "appConfigure.portBindingsEnabled[env]" > {{ info.description }} ({{ HOST_PORT_MIN }} - {{ HOST_PORT_MAX }})< / label >
< input type = "number" class = "form-control" ng-model = "appConfigure.portBindings[env]" ng-disabled = "!appConfigure.portBindingsEnabled[env]" id = "appConfigurePortInput{{env}}" later-name = "itemName{{$index}}" min = "{{HOST_PORT_MIN}}" max = "{{HOST_PORT_MAX}}" required >
< / div >
< / ng-form >
< / div >
2015-10-19 10:29:51 +02:00
< div class = "form-group" ng-show = "appConfigure.app.manifest.singleUser" >
2015-10-19 10:31:19 +02:00
< label class = "control-label" > User< / label >
2016-01-20 16:27:41 +01:00
< p >
This is a single user application.< br / > < br / >
2016-04-02 12:55:14 +02:00
Access is granted to < b > {{ renderAccessRestrictionUser(appConfigure.app.accessRestriction.users[0]) }}< / b > .
2016-01-20 16:27:41 +01:00
< / p >
2016-02-11 14:14:51 +01:00
< / div >
2016-02-18 16:14:45 +01:00
< div class = "form-group" ng-hide = "appConfigure.app.manifest.singleUser" >
2016-02-11 14:14:51 +01:00
< label class = "control-label" > Access control< / label >
< div class = "radio" >
< label >
< input type = "radio" ng-model = "appConfigure.accessRestrictionOption" value = "" >
Every Cloudron user
< / label >
< / div >
< div class = "radio" >
< label >
< input type = "radio" ng-model = "appConfigure.accessRestrictionOption" value = "restricted" >
Restrict to groups
< / label >
< / div >
2016-02-19 18:02:51 +01:00
< div class = "has-error" ng-show = "appConfigure.accessRestrictionOption !== '' && !appConfigure.isAccessRestrictionValid()" > Select at least one group< / div >
2016-02-11 14:14:51 +01:00
< div >
2016-02-18 18:26:24 +01:00
< div >
2016-02-26 00:13:07 +01:00
< span ng-repeat = "group in groups | ignoreAdminGroup" >
2016-02-18 18:26:24 +01:00
< button class = "btn btn-default" type = "button" ng-disabled = "appConfigure.accessRestrictionOption === ''" ng-click = "appConfigureToggleGroup(group);" ng-class = "{ 'btn-primary': (appConfigure.accessRestriction.groups && appConfigure.accessRestriction.groups.indexOf(group.id) !== -1) }" > {{ group.name }}< / button >
< / span >
< / div >
2016-02-11 14:14:51 +01:00
< / div >
2015-10-19 10:29:51 +02:00
< / div >
2016-02-14 13:14:03 +01:00
< div class = "form-group" ng-hide = "true" >
2016-02-11 17:29:00 +01:00
< label class = "control-label" for = "memoryUsage" > Maximum Memory Usage: < b > {{ appConfigure.memoryUsage / 1024 / 1024 }} MB< / b > < / label >
2016-02-11 16:31:11 +01:00
< br / >
2016-02-04 16:45:00 +01:00
< div style = "padding: 0 10px;" >
2016-02-11 17:29:00 +01:00
< slider id = "memoryUsage" ng-model = "appConfigure.memoryUsage" step = "33554432" tooltip = "hide" ticks = "memoryTicks" ticks-snap-bounds = "67108864" > < / slider >
2016-02-04 16:45:00 +01:00
< / div >
< / div >
2016-04-19 00:36:09 -07:00
< div class = "form-group" >
2016-04-21 12:27:40 -07:00
< label class = "control-label" for = "appConfigureAltDomainInput" > Alternate external domain< / label >
< br / >
< input type = "text" class = "form-control" ng-model = "appConfigure.altDomain" id = "appConfigureAltDomainInput" name = "altDomain" placeholder = "chat.example.com" autofocus >
2016-04-19 00:36:09 -07:00
< / div >
2016-02-04 16:45:00 +01:00
2016-01-13 15:53:14 +01:00
< div class = "hide" >
2015-10-29 21:01:16 +01:00
< label class = "control-label" for = "appConfigureCertificateInput" ng-show = "config.isCustomDomain" > Certificate (optional)< / label >
< div class = "has-error text-center" ng-show = "appConfigure.error.cert && config.isCustomDomain" > {{ appConfigure.error.cert }}< / div >
2015-10-28 20:30:15 +01:00
< div class = "form-group" ng-class = "{ 'has-error': !appConfigureForm.certificate.$dirty && appConfigure.error.cert }" ng-show = "config.isCustomDomain" >
2015-10-27 12:26:55 +01:00
< div class = "input-group" >
< input type = "file" id = "appConfigureCertificateFileInput" style = "display:none" / >
2015-10-28 21:20:59 +01:00
< input type = "text" class = "form-control" placeholder = "Certificate" ng-model = "appConfigure.certificateFileName" id = "appConfigureCertificateInput" name = "certificate" onclick = "getElementById('appConfigureCertificateFileInput').click();" style = "cursor: pointer;" ng-required = "appConfigure.keyFileName" >
2015-10-27 12:26:55 +01:00
< span class = "input-group-addon" >
< i class = "fa fa-upload" onclick = "getElementById('appConfigureCertificateFileInput').click();" > < / i >
< / span >
< / div >
< / div >
2015-10-28 20:30:15 +01:00
< div class = "form-group" ng-class = "{ 'has-error': !appConfigureForm.key.$dirty && appConfigure.error.cert }" ng-show = "config.isCustomDomain" >
2015-10-27 12:26:55 +01:00
< div class = "input-group" >
< input type = "file" id = "appConfigureKeyFileInput" style = "display:none" / >
2015-10-28 21:20:59 +01:00
< input type = "text" class = "form-control" placeholder = "Key" ng-model = "appConfigure.keyFileName" id = "appConfigureKeyInput" name = "key" onclick = "getElementById('appConfigureKeyFileInput').click();" style = "cursor: pointer;" ng-required = "appConfigure.certificateFileName" >
2015-10-27 12:26:55 +01:00
< span class = "input-group-addon" >
< i class = "fa fa-upload" onclick = "getElementById('appConfigureKeyFileInput').click();" > < / i >
< / span >
< / div >
< / div >
2016-01-13 15:53:14 +01:00
< / div >
2015-10-27 12:26:55 +01:00
2015-08-06 12:28:35 -07:00
< a ng-show = "!!appConfigure.app.manifest.configurePath" ng-href = "https://{{ appConfigure.app.location }}{{ !appConfigure.app.location ? '' : (config.isCustomDomain ? '.' : '-') }}{{ config.fqdn }}/{{ appConfigure.app.manifest.configurePath }}" target = "_blank" > Application Specific Settings< / a >
2015-07-20 00:09:47 -07:00
< br / >
< br / >
< div class = "form-group" ng-class = "{ 'has-error': (appConfigureForm.password.$dirty && appConfigureForm.password.$invalid) || (!appConfigureForm.password.$dirty && appConfigure.error.password) }" >
< label class = "control-label" for = "appConfigurePasswordInput" > Provide your password to confirm this action< / label >
2016-01-21 15:03:51 +01:00
< div class = "control-label" ng-show = "(appConfigureForm.password.$dirty && appConfigureForm.password.$invalid) || (!appConfigureForm.password.$dirty && appConfigure.error.password)" >
< small ng-show = " appConfigureForm.password.$dirty && appConfigureForm.password.$invalid" > Password required< / small >
< small ng-show = "!appConfigureForm.password.$dirty && appConfigure.error.password" > Wrong password< / small >
< / div >
< input type = "password" class = "form-control" ng-model = "appConfigure.password" id = "appConfigurePasswordInput" name = "password" required >
2015-07-20 00:09:47 -07:00
< / div >
2016-02-19 18:02:51 +01:00
< input class = "ng-hide" type = "submit" ng-disabled = "appConfigureForm.$invalid || busy || (appConfigure.accessRestrictionOption !== '' && !appConfigure.isAccessRestrictionValid())" / >
2015-07-20 00:09:47 -07:00
< / form >
< / fieldset >
< / div >
2015-08-11 12:26:19 +02:00
< div class = "modal-footer " >
2015-07-20 00:09:47 -07:00
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
2016-02-19 18:02:51 +01:00
< button type = "button" class = "btn btn-success" ng-click = "doConfigure()" ng-disabled = "appConfigureForm.$invalid || appConfigure.busy || (appConfigure.accessRestrictionOption !== '' && !appConfigure.isAccessRestrictionValid())" > < i class = "fa fa-spinner fa-pulse" ng-show = "appConfigure.busy" > < / i > Save< / button >
2015-07-20 00:09:47 -07:00
< / div >
< / div >
< / div >
< / div >
<!-- Modal restore app -->
< div class = "modal fade" id = "appRestoreModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Really Restore {{ appRestore.app.location }}< / h4 >
< / div >
< div class = "modal-body" >
2015-07-20 10:36:13 -07:00
< p ng-show = "appRestore.app.lastBackupId !== null" > Restoring the app will lose all content generated since last backup of this app!< / p >
< p ng-show = "appRestore.app.lastBackupId === null" > This app was never backed up. Restoring the app will lose all content!< / p >
2015-07-20 00:09:47 -07:00
< fieldset >
2016-02-11 12:53:35 +01:00
< form role = "form" name = "appRestoreForm" ng-submit = "doRestore()" autocomplete = "off" >
2016-01-21 15:06:22 +01:00
< div class = "form-group" ng-class = "{ 'has-error': (appRestoreForm.password.$dirty && appRestoreForm.password.$invalid) || (!appRestoreForm.password.$dirty && appRestore.error.password) }" >
2015-07-20 00:09:47 -07:00
< label class = "control-label" for = "appRestorePasswordInput" > Provide your password to confirm this action< / label >
2016-01-21 15:06:22 +01:00
< div class = "control-label" ng-show = "(appRestoreForm.password.$dirty && appRestoreForm.password.$invalid) || (!appRestoreForm.password.$dirty && appRestore.error.password)" >
< small ng-show = " appRestoreForm.password.$dirty && appRestoreForm.password.$invalid" > Password required< / small >
< small ng-show = "!appRestoreForm.password.$dirty && appRestore.error.password" > Wrong password< / small >
< / div >
< input type = "password" class = "form-control" ng-model = "appRestore.password" id = "appRestorePasswordInput" name = "password" required autofocus >
2015-07-20 00:09:47 -07:00
< / div >
< input class = "ng-hide" type = "submit" ng-disabled = "appRestoreForm.$invalid || busy" / >
< / form >
< / fieldset >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
< button type = "button" class = "btn btn-success" ng-click = "doRestore()" ng-disabled = "appRestoreForm.$invalid || appRestore.busy" > < i class = "fa fa-spinner fa-pulse" ng-show = "appRestore.busy" > < / i > Restore< / button >
< / div >
< / div >
< / div >
< / div >
2015-12-14 17:52:56 -08:00
<!-- Modal error app -->
< div class = "modal fade" id = "appErrorModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > {{ appError.app.location }}< / h4 >
< / div >
< div class = "modal-body" >
2016-02-24 18:36:40 +01:00
< p > < b > There was an error:< / b > < / p >
2015-12-14 17:52:56 -08:00
< p > {{appError.app.installationProgress}}< / p >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > OK< / button >
< / div >
< / div >
< / div >
< / div >
2015-07-20 00:09:47 -07:00
<!-- Modal uninstall app -->
< div class = "modal fade" id = "appUninstallModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Really uninstall {{ appUninstall.app.location }}< / h4 >
< / div >
< div class = "modal-body" >
< p > Deleting the app will also remove all content generated within this app!< / p >
< fieldset >
2016-02-11 12:53:35 +01:00
< form role = "form" name = "appUninstallForm" ng-submit = "doUninstall()" autocomplete = "off" >
2016-01-21 15:09:22 +01:00
< div class = "form-group" ng-class = "{ 'has-error': (appUninstallForm.password.$dirty && appUninstallForm.password.$invalid) || (!appUninstallForm.password.$dirty && appUninstall.error.password) }" >
2015-07-20 00:09:47 -07:00
< label class = "control-label" for = "appUninstallPasswordInput" > Provide your password to confirm this action< / label >
2016-01-21 15:09:22 +01:00
< div class = "control-label" ng-show = "(appUninstallForm.password.$dirty && appUninstallForm.password.$invalid) || (!appUninstallForm.password.$dirty && appUninstall.error.password)" >
< small ng-show = " appUninstallForm.password.$dirty && appUninstallForm.password.$invalid" > Password required< / small >
< small ng-show = "!appUninstallForm.password.$dirty && appUninstall.error.password" > Wrong password< / small >
< / div >
< input type = "password" class = "form-control" ng-model = "appUninstall.password" id = "appUninstallPasswordInput" name = "password" required autofocus >
2015-07-20 00:09:47 -07:00
< / div >
< input class = "ng-hide" type = "submit" ng-disabled = "appUninstallForm.$invalid || busy" / >
< / form >
< / fieldset >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
< button type = "button" class = "btn btn-danger" ng-click = "doUninstall()" ng-disabled = "appUninstallForm.$invalid || appUninstall.busy" > < i class = "fa fa-spinner fa-pulse" ng-show = "appUninstall.busy" > < / i > Uninstall< / button >
< / div >
< / div >
< / div >
< / div >
<!-- Modal update app -->
< div class = "modal fade" id = "appUpdateModal" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" >
< div class = "modal-content" >
< div class = "modal-header" >
< h4 class = "modal-title" > Update {{ appUpdate.app.location }}< / h4 >
< / div >
< div class = "modal-body" >
2016-02-04 14:43:03 +01:00
< p > Recent Changes for new version < b > {{ appUpdate.manifest.version}}< / b > :< / p >
< pre > {{ appUpdate.manifest.changelog }}< / pre >
2016-02-04 14:09:44 +01:00
< br / >
2015-07-20 00:09:47 -07:00
< fieldset >
2016-02-11 12:53:35 +01:00
< form role = "form" name = "appUpdateForm" ng-submit = "doUpdate(appUpdateForm)" autocomplete = "off" >
2015-07-20 00:09:47 -07:00
< div ng-repeat = "(env, info) in appUpdate.portBindingsInfo" ng-class = "{ 'newPort': info.isNew }" >
< ng-form name = "portInfo_form" >
< div class = "form-group" ng-class = "{ 'has-error': portInfo_form.itemName{{$index}}.$dirty && portInfo_form.itemName{{$index}}.$invalid }" >
< label class = "control-label" for = "inputPortInfo{{env}}" > < input type = "checkbox" ng-model = "appUpdate.portBindingsEnabled[env]" > < span ng-show = "info.isNew" > New - < / span > {{ info.description }} ({{ HOST_PORT_MIN }} - {{ HOST_PORT_MAX }})< / label >
< input type = "number" class = "form-control" ng-model = "appUpdate.portBindings[env]" ng-disabled = "!appUpdate.portBindingsEnabled[env]" id = "inputPortInfo{{env}}" later-name = "itemName{{$index}}" min = "{{HOST_PORT_MIN}}" max = "{{HOST_PORT_MAX}}" required >
< / div >
< / ng-form >
< / div >
< div ng-repeat = "(env, port) in appUpdate.obsoletePortBindings" class = "obsoletePort" >
< ng-form name = "obsoletePortInfo_form" >
< div class = "form-group" >
Obsolete -
< label class = "control-label" > {{ env }}< / label >
< input type = "number" class = "form-control" ng-model = "port" disabled >
< / div >
< / ng-form >
< / div >
< div class = "form-group" ng-class = "{ 'has-error': (!appUpdateForm.password.$dirty && appUpdate.error.password) || (appUpdateForm.password.$dirty && appUpdateForm.password.$invalid) }" >
< label class = "control-label" for = "inputUpdatePassword" > Provide your password to confirm this action< / label >
2016-01-21 14:26:24 +01:00
< input type = "password" class = "form-control" ng-model = "appUpdate.password" id = "inputUpdatePassword" name = "password" ng-maxlength = "30" ng-minlength = "8" required autofocus >
2015-07-20 00:09:47 -07:00
< / div >
< input class = "ng-hide" type = "submit" ng-disabled = "appUpdateForm.$invalid || busy" / >
< / form >
< / fieldset >
< / div >
< div class = "modal-footer" >
< button type = "button" class = "btn btn-default" data-dismiss = "modal" > Cancel< / button >
< button type = "button" class = "btn btn-danger" ng-click = "doUpdate(appUpdateForm)" ng-disabled = "appUpdateForm.$invalid || appUpdate.busy" > < i class = "fa fa-spinner fa-pulse" ng-show = "appUpdate.busy" > < / i > Update< / button >
< / div >
< / div >
< / div >
< / div >
< script >
function imageErrorHandler(elem) {
'use strict';
var appstoreIconUrl = elem.getAttribute('appstore-icon');
var fallbackIconUrl = elem.getAttribute('fallback-icon');
if (elem.src === appstoreIconUrl) {
elem.src = fallbackIconUrl;
elem.onerror = null; // avoid retry after default icon cannot be loaded
} else {
elem.src = appstoreIconUrl;
}
}
< / script >
< div class = "content" >
2015-08-12 13:48:55 +02:00
< br / >
2015-07-20 00:09:47 -07:00
< div class = "row animateMeOpacity ng-hide" ng-show = "installedApps.length > 0" >
< div class = "col-lg-12" >
2016-02-25 15:34:33 +01:00
< h1 > Your Applications< / h1 >
2015-07-20 00:09:47 -07:00
< / div >
< / div >
< div class = "row animateMeOpacity ng-hide" ng-show = "installedApps.length > 0" >
2016-02-19 13:36:39 +01:00
< div class = "col-sm-1 grid-item" ng-repeat = "app in installedApps | orderBy:'location'" >
2015-07-20 00:09:47 -07:00
< div style = "background-color: white;" class = "highlight grid-item-content" >
2015-12-14 18:56:15 -08:00
< a ng-href = "{{app | applicationLink}}" ng-click = "(app | installError) === true && showError(app)" target = "_blank" >
2015-07-20 00:09:47 -07:00
< div class = "grid-item-top" >
< div class = "row" >
< div class = "col-xs-12 text-center" style = "padding-left: 5px; padding-right: 5px;" >
2016-01-20 16:01:39 +01:00
< img ng-src = "{{app.iconUrl || 'img/appicon_fallback.png'}}" fallback-icon = "img/appicon_fallback.png" appstore-icon = "{{ app.iconUrlStore }}" onerror = "imageErrorHandler(this)" class = "app-icon" / >
2015-07-20 00:09:47 -07:00
< / div >
< / div >
< br / >
< div class = "row" >
2015-08-11 15:22:30 +02:00
< div class = "col-xs-12 text-center" >
< div class = "grid-item-top-title" > {{ app.location || app.fqdn }}< / div >
2015-07-20 00:09:47 -07:00
< div class = "text-muted" style = "text-overflow: ellipsis; white-space: nowrap; overflow: hidden" >
{{ app | installationStateLabel }}
< / div >
2015-10-12 20:32:43 +02:00
< div ng-style = "{ 'visibility': (app | installationActive) ? 'visible' : 'hidden' }" >
2015-07-20 00:09:47 -07:00
< div class = "progress progress-striped active" >
< div class = "progress-bar progress-bar-success" role = "progressbar" style = "width: {{ app.progress }}%" > < / div >
< / div >
< / div >
< / div >
< / div >
< / div >
2015-08-11 12:26:19 +02:00
< div class = "grid-item-bottom-mobile" ng-show = "user.admin" >
< div class = "row" >
< div class = "col-xs-4 text-left" >
2015-10-14 11:36:10 -07:00
< a href = "" ng-click = "showRestore(app)" ng-show = "app.lastBackupId != null || (app | installError) === true" >
2015-08-11 12:26:19 +02:00
< i class = "fa fa-undo scale" > < / i >
< / a >
< a href = "" ng-click = "showConfigure(app)" ng-show = "(app | installSuccess) == true" >
< i class = "fa fa-wrench scale" > < / i >
< / a >
< / div >
2016-01-20 12:00:19 +01:00
< div class = "col-xs-4 text-center" > < / div >
2015-08-11 12:26:19 +02:00
< div class = "col-xs-4 text-right" >
< a href = "" ng-click = "showUninstall(app)" >
< i class = "fa fa-remove scale" > < / i >
< / a >
< / div >
< / div >
< / div >
< div class = "grid-item-bottom" ng-show = "user.admin" >
< div >
2015-09-16 09:36:22 +02:00
< a href = "" ng-click = "showUninstall(app)" title = "Uninstall App" > < i class = "fa fa-remove scale" > < / i > < / a >
2015-08-11 12:26:19 +02:00
< / div >
2015-10-14 11:36:10 -07:00
< div ng-show = "app.lastBackupId !== null || (app | installError) === true" >
2015-09-16 09:36:22 +02:00
< a href = "" ng-click = "showRestore(app)" title = "Restore App" > < i class = "fa fa-undo scale" > < / i > < / a >
2015-08-11 12:26:19 +02:00
< / div >
< div ng-show = "(app | installSuccess) == true" >
2015-09-16 09:36:22 +02:00
< a href = "" ng-click = "showConfigure(app)" title = "Configure App" > < i class = "fa fa-wrench scale" > < / i > < / a >
2015-07-20 00:09:47 -07:00
< / div >
< / div >
2015-09-16 09:36:46 +02:00
<!-- we check the version here because the box updater does not know when an app gets updated -->
2016-01-20 11:56:42 +01:00
< div class = "app-update-badge" ng-show = "config.update.apps[app.id].manifest.version && config.update.apps[app.id].manifest.version !== app.manifest.version && (app | installSuccess)" >
2015-09-16 09:36:22 +02:00
< a href = "" ng-click = "showUpdate(app)" title = "Update Available" > < i class = "fa fa-asterisk fa-2x text-success scale" > < / i > < / a >
2015-09-16 09:28:41 +02:00
< / div >
2015-08-11 12:26:19 +02:00
< / a >
2015-07-20 00:09:47 -07:00
< / div >
< / div >
< / div >
< / div >
2015-08-20 23:50:45 -07:00
<!-- Offset the footer -->
< br / > < br / >