diff --git a/Makefile b/Makefile index 37018d1f..500418bf 100644 --- a/Makefile +++ b/Makefile @@ -6,10 +6,12 @@ sync: up # set up the database tablea docker-compose exec cartoview python manage.py migrate docker-compose exec cartoview python manage.py loaddata sample_admin.json - docker-compose exec cartoview python manage.py loaddata default_oauth_apps.json + docker-compose exec cartoview python manage.py loaddata default_oauth_apps_docker.json docker-compose exec cartoview python manage.py loaddata app_stores.json docker-compose exec cartoview python manage.py loaddata initial_data.json +backfill_api_keys: + docker-compose exec cartoview python manage.py backfill_api_keys prepare_manager: up #make migration for app_manager @@ -34,7 +36,12 @@ reset: down up wait sync collect_static: up docker-compose exec cartoview python manage.py collectstatic --noinput -run: up wait prepare_manager sync collect_static + +prepare_oauth: + docker-compose exec cartoview paver prepare_docker_oauth_fixture + docker-compose exec cartoview paver install_docker_data_dir + +run: up wait prepare_oauth prepare_manager sync collect_static backfill_api_keys static_db: up sync wait collect_static diff --git a/cartoview/app_manager/installer.py b/cartoview/app_manager/installer.py index 106e4c1e..7f7cfaf8 100644 --- a/cartoview/app_manager/installer.py +++ b/cartoview/app_manager/installer.py @@ -71,13 +71,16 @@ def restart_server(cls): def cherry_restart(cls): try: import cherrypy - cherrypy.engine.restart() + # completely stop the cherrypy server instead of reloading + # to avoid waiting to stop used threads error + cherrypy.engine.stop() + cherrypy.engine.start() except ImportError: exit(0) def remove_unwanted(info): - dictionary = info.__dict__.get('_data', {}) + dictionary = info.__dict__.get('_data', {}) if info else {} app_fields = [ str(field.name) for field in sorted(App._meta.fields + App._meta.many_to_many) @@ -139,7 +142,7 @@ def get_store(self, store_id=None): def get_app_version(self): if not self.version or self.version == 'latest' or \ - self.info.latest_version.version == self.version: + (self.info and self.info.latest_version.version == self.version): self.version = self.info.latest_version else: data = self._request_rest_data("appversion/?app__name=", self.name, diff --git a/cartoview/app_manager/rest.py b/cartoview/app_manager/rest.py index 3b1ce3de..8fbf07de 100644 --- a/cartoview/app_manager/rest.py +++ b/cartoview/app_manager/rest.py @@ -97,6 +97,7 @@ class AppResource(ModelResource): store = fields.ForeignKey(AppStoreResource, 'store', full=False, null=True) order = fields.IntegerField() active = fields.BooleanField() + pending = fields.BooleanField() categories = fields.ListField() default_config = fields.DictField(default={}) @@ -119,6 +120,11 @@ def dehydrate_active(self, bundle): active = bundle.obj.config.active return active + def dehydrate_pending(self, bundle): + app = bundle.obj + cartoview_app = CartoviewApp.objects.get(app.name) + return cartoview_app.pending + def dehydrate_categories(self, bundle): return [category.name for category in bundle.obj.category.all()] diff --git a/cartoview/app_manager/settings.py b/cartoview/app_manager/settings.py index 5f1a21fc..ec34d793 100644 --- a/cartoview/app_manager/settings.py +++ b/cartoview/app_manager/settings.py @@ -48,10 +48,10 @@ def load_apps(APPS_DIR): APPS_SETTINGS += (app_settings_file,) if os.path.exists(libs_dir) and libs_dir not in sys.path: logger.info( - "Install {} libs folder to the system.\n".format( + "Append {} libs folder to the system path.\n".format( app.name)) sys.path.append(libs_dir) - logger.info("add {} to INSTALLED_APPS.\n".format(app.name)) + logger.info("add {} to django INSTALLED_APPS.\n".format(app.name)) if app.name not in CARTOVIEW_APPS: # app_config.name.__str__() because Django don't like # unicode_literals diff --git a/cartoview/app_manager/static/app_manager/css/manager.css b/cartoview/app_manager/static/app_manager/css/manager.css index 4b0a63d2..c206f44c 100644 --- a/cartoview/app_manager/static/app_manager/css/manager.css +++ b/cartoview/app_manager/static/app_manager/css/manager.css @@ -625,6 +625,7 @@ div { .actions-wrapper { margin-top: 10px; padding: 0 10px; + min-height: 30px; } .actions-wrapper button { margin-right: 10px; diff --git a/cartoview/app_manager/static/app_manager/js/manager.js b/cartoview/app_manager/static/app_manager/js/manager.js index 5af87a78..c0919c83 100644 --- a/cartoview/app_manager/static/app_manager/js/manager.js +++ b/cartoview/app_manager/static/app_manager/js/manager.js @@ -1,498 +1,543 @@ (function () { - var app = angular.module('cartoview.appManager.manager', ["cartoview.appManager.resources", 'ui.bootstrap', "dndLists"]); + var app = angular.module("cartoview.appManager.manager", [ + "cartoview.appManager.resources", + "ui.bootstrap", + "dndLists", + ]); - app.config(function ($httpProvider) { - $httpProvider.defaults.xsrfCookieName = 'csrftoken'; - $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; - }); - app.directive('dynamicTemplate', function ($compile) { - return { - restrict: 'A', - scope: { - context: '=', - template: '=' - }, - controller: function ($scope, $element, $compile) { - $scope.$watch(function () { - return $scope.context; - }, function () { - if ($scope.context) { - $element.html($scope.template); - angular.extend($scope, $scope.context); - $compile($element.contents())($scope); - } - }); + app.config(function ($httpProvider) { + $httpProvider.defaults.xsrfCookieName = "csrftoken"; + $httpProvider.defaults.xsrfHeaderName = "X-CSRFToken"; + }); + app.directive("dynamicTemplate", function ($compile) { + return { + restrict: "A", + scope: { + context: "=", + template: "=", + }, + controller: function ($scope, $element, $compile) { + $scope.$watch( + function () { + return $scope.context; + }, + function () { + if ($scope.context) { + $element.html($scope.template); + angular.extend($scope, $scope.context); + $compile($element.contents())($scope); } - } - }); + } + ); + }, + }; + }); - app.directive('appsReorder', function ($compile) { - return { - restrict: 'E', - templateUrl: "apps-reorder.html", - scope: { - installedApps: "=" - } - } - }); - app.service("Dialogs", function ($uibModal, $log, $document) { - this.confirm = function (options) { + app.directive("appsReorder", function ($compile) { + return { + restrict: "E", + templateUrl: "apps-reorder.html", + scope: { + installedApps: "=", + }, + }; + }); + app.service("Dialogs", function ($uibModal, $log, $document) { + this.confirm = function (options) { + var controller = function ($scope, $uibModalInstance) { + options.template = options.template || "{{msg}}"; + $scope.options = options; + options.okText = options.okText || "Ok"; + $scope.ok = function () { + $uibModalInstance.close(true); + }; + $scope.cancel = function () { + $uibModalInstance.dismiss("cancel"); + }; + }; + var modalInstance = $uibModal.open({ + animation: true, + templateUrl: "confirm-dialog.html", + controller: controller, + }); - var controller = function ($scope, $uibModalInstance) { - options.template = options.template || "{{msg}}"; - $scope.options = options; - options.okText = options.okText || "Ok"; - $scope.ok = function () { - $uibModalInstance.close(true); - }; - $scope.cancel = function () { - $uibModalInstance.dismiss('cancel'); - }; - }; - var modalInstance = $uibModal.open({ - animation: true, - templateUrl: 'confirm-dialog.html', - controller: controller + return modalInstance.result; + }; + }); + app.service("Alerts", function () { + var service = this; + this.alerts = []; + this.addAlert = function (alert) { + service.alerts.push(alert); + }; + + this.closeAlert = function (index) { + service.alerts.splice(index, 1); + }; + this.closeAll = function () { + service.alerts = []; + }; + }); + app.service("AppInstaller", function ($http, urls) { + var service = this; + // get the apps required to install this app + var _getDependencies = function (app, appsHash, dependencies) { + angular.forEach(app.latest_version.dependencies, function ( + version, + name + ) { + if (appsHash[name] && appsHash[name].installedApp) { + if (appsHash[name].installedApp.version < version) { + dependencies.push({ + name: name, + version: version, + upgrade: true, }); + _getDependencies(appsHash[name], appsHash, dependencies); + } + } else { + dependencies.push({ + name: name, + version: version, + upgrade: false, + }); + _getDependencies(appsHash[name], appsHash, dependencies); + } + }); + return dependencies; + }; + this.getDependencies = function (app, appsHash) { + return _getDependencies(app, appsHash, []); + }; - return modalInstance.result; + var _getDependents = function (app, appsHash, dependents) { + angular.forEach(app.store.installedApps.objects, function (installedApp) { + var currentApp = appsHash[installedApp.name]; + // NOTE:this line will raise an error while uninstalling app + // It was working fine before this commit in gitlab f976590bd981b05f062f055f1aed3040b190f8e9 + // I this our app market result for apps was changed without handle this change here + if (currentApp) { + if ( + dependents.indexOf(currentApp) == -1 && + currentApp.latest_version.dependencies[app.name] + ) { + dependents.push(currentApp); + _getDependents(currentApp, appsHash, dependents); + } + } + }); + return dependents; + }; + // get the apps that depend on this app. + // must be called before app uninstall + this.getDependents = function (app, appsHash) { + return _getDependents(app, appsHash, [app]); + }; + this.install = function (app) { + var url = urls.BULK_INSTALL; + const data = { + apps: [ + { + app_name: app.name, + version: app.latest_version.version, + store_id: app.store.id, + }, + ], + restart: false, + }; + return $http.post(url, data); + }; + this.uninstall = function (app) { + var url = "../uninstall/" + app.store.id + "/" + app.name + "/"; + return $http.post(url); + }; + this.restart = function () { + var url = urls.RESTART_SERVER; + return $http.get(url); + }; + this.pingServer = function () { + var url = "/"; + return $http.get(url); + }; + }); + app.directive("alertsPanel", function () { + return { + restrict: "E", + transclude: true, + replace: true, + scope: { + messages: "=", + }, + template: [ + "
", + "
", + "{{msg.msg}}", + "
", + "
", + ].join(""), + controller: function ($scope) { + var classes = { + error: "alert-danger", }; - }); - app.service("Alerts", function () { - var service = this; - this.alerts = []; - this.addAlert = function (alert) { - service.alerts.push(alert); + $scope.getCls = function (type) { + return "alert " + (classes[type] || "alert-warning"); }; + }, + }; + }); + app.directive("cartoviewAppInstaller", function () { + return { + restrict: "E", + transclude: true, + replace: true, + templateUrl: "app-installer.html", + controller: function ( + $scope, + InstalledAppResource, + AppStoreResource, + AppStore, + AppInstaller, + Dialogs, + $timeout, + Alerts + ) { + $scope.selectedStoreId = null; + var appsHash = {}; + $scope.loading = true; + $scope.appsErrors = []; + $scope.storeError = false; + $scope.busy = false; + $scope.compatible = function (cartoviewVersions) { + var compatible = false; + for (var i = 0; i < cartoviewVersions.length; i++) { + const version = cartoviewVersions[i].version; + const current_version_check = compareVersions( + version, + versionInfo.current_version + ); + var backward_version_check = -1; + for (var j = 0; j < versionInfo.backward_versions.length; j++) { + const v = versionInfo.backward_versions[j]; - this.closeAlert = function (index) { - service.alerts.splice(index, 1); + if (compareVersions(version, v) == 0) { + backward_version_check = 0; + break; + } + } + if (current_version_check === 0 || backward_version_check === 0) { + compatible = true; + break; + } + } + return compatible; }; - this.closeAll = function () { - service.alerts = []; - } - }); - app.service("AppInstaller", function ($http, urls) { - var service = this; - // get the apps required to install this app - var _getDependencies = function (app, appsHash, dependencies) { - - angular.forEach(app.latest_version.dependencies, function (version, name) { - if (appsHash[name] && appsHash[name].installedApp) { - - if (appsHash[name].installedApp.version < version) { - dependencies.push({ - name: name, - version: version, - upgrade: true - }); - _getDependencies(appsHash[name], appsHash, dependencies); + $scope.upgradable = function (currentVersion, storeVersion) { + var compatible = false; + if (compareVersions(currentVersion, storeVersion) === -1) { + compatible = true; + } + return compatible; + }; + $scope.stores = AppStoreResource.query(function () { + $scope.stores.objects.forEach(function (store) { + if ($scope.stores.objects.length > 0) { + $scope.selectedStoreId = $scope.stores.objects[0].id; + } + store.update = function (callback, persist) { + var params = { + store_id: store.id, + t: new Date().getTime(), //to force server request + }; + store.installedApps = InstalledAppResource.query( + params, + function () { + if (store._apps && store._apps.objects) { + store._apps.objects.forEach(function (app) { + delete app.installedApp; + }); + } + store.installedApps.objects.forEach(function (installedApp) { + if (appsHash[installedApp.name]) { + appsHash[installedApp.name].installedApp = installedApp; } - } else { - dependencies.push({ - name: name, - version: version, - upgrade: false + }); + if (typeof callback == "function") { + callback(); + } + }, + function () { + //keep requesting until server responds + if (persist) { + $timeout(function () { + store.update(callback, persist); + }, 2000); + } + } + ); + $scope.loading = false; + }; + Object.defineProperty(store, "apps", { + configurable: true, + get: function () { + if (!this._apps) { + this._apps = AppStore.AppResource(this).query(function () { + store._apps.objects.forEach(function (app) { + appsHash[app.name] = app; + app.store = store; }); - _getDependencies(appsHash[name], appsHash, dependencies); + store.update(); + }); + this._apps.$promise.catch(function (errorResponse) { + // console.error(errorResponse); + $scope.loading = false; + $scope.storeError = true; + }); } + return this._apps; + }, }); - return dependencies; + }); + }); + $scope.getSelectedStore = function () { + var selected; + if ($scope.selectedStoreId) { + $scope.stores.objects.forEach(function (store) { + if (store.id == $scope.selectedStoreId) { + selected = store; + return false; + } + }); + } + return selected; }; - this.getDependencies = function (app, appsHash) { - return _getDependencies(app, appsHash, []) + // + var updateStore = function (store) { + $scope.restarting = true; + //wait for 5 seconds to insure that the server starts the restarting process + $timeout(function () { + store.update(function () { + $scope.restarting = false; + $scope.installing = null; + }, true); + }, 5000); }; - var _getDependents = function (app, appsHash, dependents) { - angular.forEach(app.store.installedApps.objects, function (installedApp) { - var currentApp = appsHash[installedApp.name]; - // NOTE:this line will raise an error while uninstalling app - // It was working fine before this commit in gitlab f976590bd981b05f062f055f1aed3040b190f8e9 - // I this our app market result for apps was changed without handle this change here - if (dependents.indexOf(currentApp) == -1 && currentApp.latest_version.dependencies[app.name]) { - dependents.push(currentApp) - _getDependents(currentApp, appsHash, dependents) + function install(requiredApp) { + $scope.installing = requiredApp; + $scope.appsErrors = []; + AppInstaller.install(requiredApp) + .success(function (res) { + res.forEach(function (appResult) { + if (appResult.success) { + // updateStore(requiredApp.store); + // Just update the store without waiting for the server to restart + requiredApp.store.update(undefined, true); + $scope.installing = null; + } else { + const msgData = { + type: appResult.success ? "success" : "danger", + msg: appResult.app_name + ": " + appResult.message, + }; + $scope.appsErrors.push(msgData); } + }, this); + }) + .error(function (res, status) { + $scope.installing = null; + if (status == -1) { + var error = "Cannot connect to the server"; + app.messages.push({ + type: "danger", + msg: error, + }); + } else if (status >= 400) { + var error = "Cannot install app " + app.title; + app.messages.push({ + type: "danger", + msg: error, + }); + } + if (Array.isArray(res)) { + res.forEach(function (message) { + const msgData = { + type: message.success ? "success" : "danger", + msg: message.app_name + ": " + message.message, + }; + $scope.appsErrors.push(msgData); + }, this); + } + if (res.error_message) { + const msgData = { + type: "danger", + msg: res.error_message, + }; + $scope.appsErrors.push(msgData); + } + console.log($scope.appsErrors); }); - return dependents; - }; - // get the apps that depend on this app. - // must be called before app uninstall - this.getDependents = function (app, appsHash) { - return _getDependents(app, appsHash, [app]); + } + $scope.install = function (app, upgrade) { + var dependencies = AppInstaller.getDependencies(app, appsHash); + if (dependencies.length > 0) { + Dialogs.confirm({ + title: "App dependencies", + template: [ + "This app requires the following apps to be installed
", + "", + "
Install Them?
", + ].join(""), + dependencies: dependencies, + appsHash: appsHash, + }).then(function (confirm) { + if (confirm) { + install(app); + } + }); + } else { + install(app); + } }; - this.install = function (app) { - var url = urls.BULK_INSTALL; - const data = { - apps: [{ - app_name: app.name, - version: app.latest_version.version, - store_id: app.store.id - }], - restart: false, - } - return $http.post(url, data); + var uninstall = function (app) { + $scope.installing = app; + AppInstaller.uninstall(app) + .success(function (res) { + // updateStore(app.store); + // just update the store without waiting for the server to restart + app.store.update(undefined, true); + $scope.installing = null; + }) + .error(function () { + $scope.installing = null; + app.error = "Unable to uninstall"; + }); }; - this.uninstall = function (app) { - var url = "../uninstall/" + app.store.id + "/" + app.name + "/"; - return $http.post(url); - } - this.restart = function () { - var url = urls.RESTART_SERVER; - return $http.get(url); - } - this.pingServer = function () { - var url = '/'; - return $http.get(url); - } - }); - app.directive("alertsPanel", function () { - return { - restrict: 'E', - transclude: true, - replace: true, - scope: { - messages: '=' + + var setActive = function (app, active) { + var action = active ? "activate" : "suspend"; + InstalledAppResource[action]( + { + appId: app.installedApp.id, }, - template: ["
", - "
", - "{{msg.msg}}", - "
", - "
" - ].join(""), - controller: function ($scope) { - var classes = { - error: "alert-danger" - }; - $scope.getCls = function (type) { - return "alert " + (classes[type] || "alert-warning"); - } + function (res) { + if (res.success) { + app.installedApp.active = active; + } } - } - }); - app.directive("cartoviewAppInstaller", function () { - return { - restrict: 'E', - transclude: true, - replace: true, - templateUrl: "app-installer.html", - controller: function ($scope, InstalledAppResource, AppStoreResource, AppStore, - AppInstaller, Dialogs, $timeout, Alerts) { - $scope.selectedStoreId = null; - var appsHash = {}; - $scope.loading = true; - $scope.appsErrors = []; - $scope.storeError = false; - $scope.busy = false; - $scope.compatible = function (cartoviewVersions) { - var compatible = false; - for (var i = 0; i < cartoviewVersions.length; i++) { - const version = cartoviewVersions[i].version - const current_version_check = compareVersions(version, versionInfo.current_version) - var backward_version_check = -1 - for (var j = 0; j < versionInfo.backward_versions.length; j++) { - const v = versionInfo.backward_versions[j] - - if (compareVersions(version, v) == 0) { - backward_version_check = 0 - break - } - } - if (current_version_check === 0 || backward_version_check === 0) { - compatible = true; - break; - } - } - return compatible - } - $scope.upgradable = function (currentVersion, storeVersion) { - var compatible = false - if (compareVersions(currentVersion, storeVersion) === -1) { - compatible = true - } - return compatible - } - $scope.stores = AppStoreResource.query(function () { - $scope.stores.objects.forEach(function (store) { - if ($scope.stores.objects.length > 0) { - $scope.selectedStoreId = $scope.stores.objects[0].id; - } - store.update = function (callback, persist) { - var params = { - store_id: store.id, - t: new Date().getTime() //to force server request - }; - store.installedApps = InstalledAppResource.query(params, function () { - if (store._apps && store._apps.objects) { - store._apps.objects.forEach(function (app) { - delete app.installedApp; - }); - } - store.installedApps.objects.forEach(function (installedApp) { - if (appsHash[installedApp.name]) { - appsHash[installedApp.name].installedApp = installedApp; - } - - }); - if (typeof callback == 'function') { - callback(); - } - }, function () { - //keep requesting until server responds - if (persist) { - $timeout(function () { - store.update(callback, persist) - }, 2000); - } - }); - $scope.loading = false - }; - Object.defineProperty(store, 'apps', { - configurable: true, - get: function () { - if (!this._apps) { - this._apps = AppStore.AppResource(this).query(function () { - store._apps.objects.forEach(function (app) { - appsHash[app.name] = app; - app.store = store; - - }); - store.update() - }) - this._apps.$promise.catch(function (errorResponse) { - // console.error(errorResponse); - $scope.loading = false; - $scope.storeError = true - }); - - } - return this._apps; - } - }); - }); - }); - $scope.getSelectedStore = function () { - var selected; - if ($scope.selectedStoreId) { - $scope.stores.objects.forEach(function (store) { - if (store.id == $scope.selectedStoreId) { - selected = store; - return false; - } - }); - } - return selected; - }; - // - var updateStore = function (store) { - $scope.restarting = true; - //wait for 5 seconds to insure that the server starts the restarting process - $timeout(function () { - store.update(function () { - $scope.restarting = false; - $scope.installing = null; - }, true); - }, 5000); - }; - - function install(requiredApp) { - $scope.installing = requiredApp; - $scope.appsErrors = []; - AppInstaller.install(requiredApp).success(function (res) { - res.forEach(function (appResult) { - if (appResult.success) { - updateStore(requiredApp.store); - } else { - const msgData = { - type: appResult.success ? "success" : "danger", - msg: appResult.app_name + ": " + appResult.message - } - $scope.appsErrors.push(msgData) - } - }, this) - }).error(function (res, status) { - $scope.installing = null; - if (status == -1) { - var error = "Cannot connect to the server" - app.messages.push({ - type: "danger", - msg: error - }); - } else if (status >= 400) { - var error = "Cannot install app " + app.title; - app.messages.push({ - type: "danger", - msg: error - }); - } - - if (Array.isArray(res)) { - res.forEach(function (message) { - const msgData = { - type: message.success ? "success" : "danger", - msg: message.app_name + ": " + message.message - } - $scope.appsErrors.push(msgData) - }, this) - } - if (res.error_message) { - const msgData = { - type: "danger", - msg: res.error_message - } - $scope.appsErrors.push(msgData) - } - console.log($scope.appsErrors); - - }); - } - $scope.install = function (app, upgrade) { - var dependencies = AppInstaller.getDependencies(app, appsHash); - if (dependencies.length > 0) { - Dialogs.confirm({ - title: "App dependencies", - template: [ - "This app requires the following apps to be installed
", - "", - "
Install Them?
" - ].join(""), - dependencies: dependencies, - appsHash: appsHash - }).then(function (confirm) { - if (confirm) { - install(app); - } - }) - } else { - install(app); - } - }; - - var uninstall = function (app) { - $scope.installing = app; - AppInstaller.uninstall(app).success(function (res) { - updateStore(app.store); - }).error(function () { - $scope.installing = null; - app.error = "Unable to uninstall" - - }); - }; - - var setActive = function (app, active) { - var action = active ? 'activate' : 'suspend'; - InstalledAppResource[action]({ - appId: app.installedApp.id - }, function (res) { - if (res.success) { - app.installedApp.active = active; - } - }); - }; - $scope.toggleActive = function (app) { - setActive(app, !app.installedApp.active); - }; - - $scope.uninstall = function (app) { - - var dependents = AppInstaller.getDependents(app, appsHash); - if (dependents.length > 0) { - Dialogs.confirm({ - title: "Uninstall app", - template: [ - "This will uninstall the following apps", - "", - "
Do you want to proceed?
" - ].join(""), - dependents: dependents, - appsHash: appsHash - }).then(function (confirm) { - if (confirm) { - uninstall(app); - } - }) - } else { - uninstall(app) - } - }; + ); + }; + $scope.toggleActive = function (app) { + setActive(app, !app.installedApp.active); + }; - $scope.reorder = function () { - var installedApps = $scope.getSelectedStore().installedApps.objects; - Dialogs.confirm({ - okText: "Save Order", - title: "Reorder Installed Apps", - template: "", - installedApps: installedApps - }).then(function (confirm) { - if (confirm) { - var apps = []; - installedApps.forEach(function (app) { - apps.push(app.id); - }); - var params = { - apps: apps - }; - InstalledAppResource.reorder(params, function (res) { - console.debug(res) - }) - } - }); + $scope.uninstall = function (app) { + var dependents = AppInstaller.getDependents(app, appsHash); + if (dependents.length > 0) { + Dialogs.confirm({ + title: "Uninstall app", + template: [ + "This will uninstall the following apps", + "", + "
Do you want to proceed?
", + ].join(""), + dependents: dependents, + appsHash: appsHash, + }).then(function (confirm) { + if (confirm) { + uninstall(app); + } + }); + } else { + uninstall(app); + } + }; - function waitForRestart() { - AppInstaller.pingServer().success(function (res) { - restarted = true - $scope.restarting = false; - }).error(function (res, status) { - if (status == 500) { - $scope.restarting = false; - const msgData = { - type: "danger", - msg: "Failed to restart Server" - } - $scope.appsErrors.push(msgData) - restarted = true - } - }); - if (!restarted) { - $timeout(function () { - waitForRestart() - }, 3000); - } - } - $timeout(function () { - waitForRestart() - }, 2000); + $scope.reorder = function () { + var installedApps = $scope.getSelectedStore().installedApps.objects; + Dialogs.confirm({ + okText: "Save Order", + title: "Reorder Installed Apps", + template: + "", + installedApps: installedApps, + }).then(function (confirm) { + if (confirm) { + var apps = []; + installedApps.forEach(function (app) { + apps.push(app.id); + }); + var params = { + apps: apps, + }; + InstalledAppResource.reorder(params, function (res) { + console.debug(res); + }); + } + }); + }; + $scope.restart = function () { + $scope.appsErrors = []; + $scope.restarting = true; + var restarted = false; + AppInstaller.restart().error(function (res, status) { + if (status == 500) { + $scope.restarting = false; + const msgData = { + type: "danger", + msg: "Failed to restart Server", + }; + $scope.appsErrors.push(msgData); + restarted = true; + } + }); + function waitForRestart() { + AppInstaller.pingServer() + .success(function (res) { + restarted = true; + $scope.restarting = false; + location.reload() + }) + .error(function (res, status) { + if (status == 500) { + $scope.restarting = false; + const msgData = { + type: "danger", + msg: "Failed to restart Server", + }; + $scope.appsErrors.push(msgData); + restarted = true; } + }); + if (!restarted) { + $timeout(function () { + waitForRestart(); + }, 10000); } - } - }); -})(); \ No newline at end of file + } + $timeout(function () { + waitForRestart(); + }, 10000); + }; + $scope.showRestartPanel = function () { + var installedApps = $scope.getSelectedStore().installedApps.objects; + if(installedApps) + return installedApps.findIndex(function (app) { + return app.pending + }) !== -1 + return false + }; + }, + }; + }); +})(); diff --git a/cartoview/app_manager/templates/app_manager/apps.html b/cartoview/app_manager/templates/app_manager/apps.html index 8ddc2d37..57bf9799 100644 --- a/cartoview/app_manager/templates/app_manager/apps.html +++ b/cartoview/app_manager/templates/app_manager/apps.html @@ -46,7 +46,7 @@

{% trans "Explore Apps" %}

{% for app in Apps %} - {% if app.config.active and app.name != "cartoview_attachment_manager" %} + {% if not app.config.pending and app.config.active and app.name != "cartoview_attachment_manager" %}
diff --git a/cartoview/app_manager/templates/app_manager/manage.html b/cartoview/app_manager/templates/app_manager/manage.html index 933c7147..02e36f72 100644 --- a/cartoview/app_manager/templates/app_manager/manage.html +++ b/cartoview/app_manager/templates/app_manager/manage.html @@ -34,10 +34,23 @@