421 lines
13 KiB
JavaScript
421 lines
13 KiB
JavaScript
'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();
|
|
}]);
|