Files
cloudron-box/src/views/apps.js
T

421 lines
13 KiB
JavaScript
Raw Normal View History

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