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