451 lines
16 KiB
JavaScript
451 lines
16 KiB
JavaScript
'use strict';
|
|
|
|
/* global angular:false */
|
|
/* global $:false, TASK_TYPES */
|
|
|
|
angular.module('Application').controller('SettingsController', ['$scope', '$location', '$translate', '$rootScope', '$timeout', 'Client', function ($scope, $location, $translate, $rootScope, $timeout, Client) {
|
|
Client.onReady(function () { if (!Client.getUserInfo().isAtLeastAdmin) $location.path('/'); });
|
|
|
|
$scope.client = Client;
|
|
$scope.user = Client.getUserInfo();
|
|
$scope.config = Client.getConfig();
|
|
$scope.installedApps = Client.getInstalledApps();
|
|
|
|
$scope.subscription = null;
|
|
$scope.subscriptionBusy = true;
|
|
|
|
// values correspond to cron days
|
|
$scope.cronDays = [
|
|
{ name: 'Sunday', value: 0 },
|
|
{ name: 'Monday', value: 1 },
|
|
{ name: 'Tuesday', value: 2 },
|
|
{ name: 'Wednesday', value: 3 },
|
|
{ name: 'Thursday', value: 4 },
|
|
{ name: 'Friday', value: 5 },
|
|
{ name: 'Saturday', value: 6 },
|
|
];
|
|
|
|
// generates 24h time sets (instead of american 12h) to avoid having to translate everything to locales eg. 12:00
|
|
$scope.cronHours = Array.from({ length: 24 }).map(function (v, i) { return { name: (i < 10 ? '0' : '') + i + ':00', value: i }; });
|
|
|
|
$scope.registryConfigProviders = [
|
|
{ name: 'AWS', value: 'aws' },
|
|
{ name: 'Cloudron', value: 'cloudron' },
|
|
{ name: 'Digital Ocean', value: 'digitalocean' },
|
|
{ name: 'DockerHub', value: 'dockerhub' },
|
|
{ name: 'Google Cloud', value: 'google-cloud' },
|
|
{ name: 'Linode', value: 'linode' },
|
|
{ name: 'Quay', value: 'quay' },
|
|
{ name: 'Treescale', value: 'treescale' },
|
|
{ name: 'Other', value: 'other' },
|
|
{ name: 'Disabled', value: 'noop' }
|
|
];
|
|
|
|
$translate(['settings.registryConfig.providerOther', 'settings.registryConfig.providerDisabled']).then(function (tr) {
|
|
if (tr['settings.registryConfig.providerOther']) $scope.registryConfigProviders.find(function (p) { return p.value === 'other'; }).name = tr['settings.registryConfig.providerOther'];
|
|
if (tr['settings.registryConfig.providerDisabled']) $scope.registryConfigProviders.find(function (p) { return p.value === 'noop'; }).name = tr['settings.registryConfig.providerDisabled'];
|
|
});
|
|
|
|
$scope.openSubscriptionSetup = function () {
|
|
Client.openSubscriptionSetup($scope.subscription || {});
|
|
};
|
|
|
|
$scope.prettyProviderName = function (provider) {
|
|
switch (provider) {
|
|
case 'caas': return 'Managed Cloudron';
|
|
default: return provider;
|
|
}
|
|
};
|
|
|
|
$scope.prettyAutoUpdateSchedule = function (pattern) {
|
|
if (!pattern) return '';
|
|
var tmp = pattern.split(' ');
|
|
|
|
if (tmp.length === 1) return tmp[0];
|
|
|
|
var hours = tmp[2].split(',');
|
|
var days = tmp[5].split(',');
|
|
var prettyDay;
|
|
if (days.length === 7 || days[0] === '*') {
|
|
prettyDay = 'Everyday';
|
|
} else {
|
|
prettyDay = days.map(function (day) { return $scope.cronDays[parseInt(day, 10)].name.substr(0, 3); }).join(',');
|
|
}
|
|
|
|
try {
|
|
var prettyHour = hours.map(function (hour) { return $scope.cronHours[parseInt(hour, 10)].name; }).join(',');
|
|
|
|
return prettyDay + ' at ' + prettyHour;
|
|
} catch (error) {
|
|
return 'Custom pattern';
|
|
}
|
|
};
|
|
|
|
$scope.update = {
|
|
error: {}, // this is for the dialog
|
|
busy: false,
|
|
checking: false,
|
|
percent: 0,
|
|
message: 'Downloading',
|
|
errorMessage: '', // this shows inline
|
|
skipBackup: false,
|
|
tasks: [],
|
|
|
|
refreshTasks: function () {
|
|
Client.getTasksByType(TASK_TYPES.TASK_UPDATE, function (error, tasks) {
|
|
if (error) return console.error(error);
|
|
$scope.update.tasks = tasks.slice(0, 10);
|
|
if ($scope.update.tasks.length && $scope.update.tasks[0].active) $scope.update.updateStatus();
|
|
});
|
|
},
|
|
|
|
checkNow: function () {
|
|
$scope.update.checking = true;
|
|
|
|
Client.checkForUpdates(function (error) {
|
|
if (error) Client.error(error);
|
|
|
|
$scope.update.checking = false;
|
|
});
|
|
},
|
|
|
|
show: function () {
|
|
$scope.update.error.generic = null;
|
|
$scope.update.busy = false;
|
|
|
|
$('#updateModal').modal('show');
|
|
},
|
|
|
|
stopUpdate: function () {
|
|
var taskId = $scope.update.tasks[0].id;
|
|
|
|
Client.stopTask(taskId, function (error) {
|
|
if (error) {
|
|
if (error.statusCode === 409) {
|
|
$scope.update.errorMessage = 'No update is currently in progress';
|
|
} else {
|
|
console.error(error);
|
|
$scope.update.errorMessage = error.message;
|
|
}
|
|
|
|
$scope.update.busy = false;
|
|
|
|
return;
|
|
}
|
|
});
|
|
},
|
|
|
|
reloadIfNeeded: function () {
|
|
Client.getProvisionStatus(function (error, status) {
|
|
if (error) return $scope.error(error);
|
|
|
|
if (window.localStorage.version !== status.version) window.location.reload(true);
|
|
});
|
|
},
|
|
|
|
updateStatus: function () {
|
|
var taskId = $scope.update.tasks[0].id;
|
|
|
|
Client.getTask(taskId, function (error, data) {
|
|
if (error) return window.setTimeout($scope.update.updateStatus, 5000);
|
|
|
|
if (!data.active) {
|
|
$scope.update.busy = false;
|
|
$scope.update.message = '';
|
|
$scope.update.percent = 100; // indicates that 'result' is valid
|
|
$scope.update.errorMessage = data.success ? '' : data.error.message;
|
|
|
|
if (!data.errorMessage) $scope.update.reloadIfNeeded(); // assume success
|
|
|
|
$scope.update.refreshTasks(); // redundant... update the tasks list dropdown
|
|
|
|
return;
|
|
}
|
|
|
|
$scope.update.busy = true;
|
|
$scope.update.percent = data.percent;
|
|
$scope.update.message = data.message;
|
|
|
|
window.setTimeout($scope.update.updateStatus, 500);
|
|
});
|
|
},
|
|
|
|
startUpdate: function () {
|
|
$scope.update.error.generic = null;
|
|
$scope.update.busy = true;
|
|
$scope.update.percent = 0;
|
|
$scope.update.message = '';
|
|
$scope.update.errorMessage = '';
|
|
|
|
Client.update({ skipBackup: $scope.update.skipBackup }, function (error /*, taskId */) {
|
|
if (error) {
|
|
$scope.update.error.generic = error.message;
|
|
$scope.update.busy = false;
|
|
return;
|
|
}
|
|
|
|
$('#updateModal').modal('hide');
|
|
|
|
$scope.update.refreshTasks();
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.timeZone = {
|
|
busy: false,
|
|
success: false,
|
|
error: '',
|
|
timeZone: '',
|
|
currentTimeZone: '',
|
|
availableTimeZones: window.timezones,
|
|
|
|
submit: function () {
|
|
if ($scope.timeZone.timeZone === $scope.timeZone.currentTimeZone) return;
|
|
|
|
$scope.timeZone.error = '';
|
|
$scope.timeZone.busy = true;
|
|
$scope.timeZone.success = false;
|
|
|
|
Client.setTimeZone($scope.timeZone.timeZone.id, function (error) {
|
|
if (error) $scope.timeZone.error = error.message;
|
|
else $scope.timeZone.currentTimeZone = $scope.timeZone.timeZone;
|
|
|
|
$timeout(function () {
|
|
$scope.timeZone.busy = false;
|
|
$scope.timeZone.success = true;
|
|
}, 2000); // otherwise, it's too fast
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.language = {
|
|
busy: false,
|
|
success: false,
|
|
error: '',
|
|
language: '',
|
|
currentLanguage: '',
|
|
availableLanguages: Client.getAvailableLanguages(),
|
|
|
|
submit: function () {
|
|
if ($scope.language.language === $scope.language.currentLanguage) return;
|
|
|
|
$scope.language.error = '';
|
|
$scope.language.busy = true;
|
|
$scope.language.success = false;
|
|
|
|
Client.setLanguage($scope.language.language.id, function (error) {
|
|
if (error) $scope.language.error = error.message;
|
|
else $scope.language.currentLanguage = $scope.language.language;
|
|
|
|
$timeout(function () {
|
|
$scope.language.busy = false;
|
|
$scope.language.success = true;
|
|
}, 2000); // otherwise, it's too fast
|
|
});
|
|
}
|
|
};
|
|
|
|
$scope.updateSchedule = {
|
|
busy: false,
|
|
currentPattern: '',
|
|
days: [],
|
|
hours: [],
|
|
type: 'pattern',
|
|
|
|
isScheduleValid: function () {
|
|
return $scope.updateSchedule.hours.length !== 0 && $scope.updateSchedule.days !== 0;
|
|
},
|
|
|
|
show: function () {
|
|
$scope.updateSchedule.busy = false;
|
|
|
|
if ($scope.updateSchedule.currentPattern === 'never') {
|
|
$scope.updateSchedule.type = 'never';
|
|
$scope.updateSchedule.days = [];
|
|
$scope.updateSchedule.hours = [];
|
|
} else {
|
|
$scope.updateSchedule.type = 'pattern';
|
|
|
|
var tmp = $scope.updateSchedule.currentPattern.split(' ');
|
|
var hours = tmp[2].split(','), days = tmp[5].split(',');
|
|
if (days[0] === '*') {
|
|
$scope.updateSchedule.days = angular.copy($scope.cronDays, []);
|
|
} else {
|
|
$scope.updateSchedule.days = days.map(function (day) { return $scope.cronDays[parseInt(day, 10)]; });
|
|
}
|
|
try {
|
|
$scope.updateSchedule.hours = hours.map(function (hour) { return $scope.cronHours[parseInt(hour, 10)]; });
|
|
} catch (e) {
|
|
console.error('Error parsing hour');
|
|
}
|
|
}
|
|
|
|
$('#updateScheduleModal').modal('show');
|
|
},
|
|
|
|
submit: function () {
|
|
var pattern = 'never';
|
|
if ($scope.updateSchedule.type === 'pattern') {
|
|
var daysPattern;
|
|
if ($scope.updateSchedule.days.length === 7) daysPattern = '*';
|
|
else daysPattern = $scope.updateSchedule.days.map(function (d) { return d.value; });
|
|
|
|
var hoursPattern;
|
|
if ($scope.updateSchedule.hours.length === 24) hoursPattern = '*';
|
|
else hoursPattern = $scope.updateSchedule.hours.map(function (d) { return d.value; });
|
|
|
|
pattern ='00 00 ' + hoursPattern + ' * * ' + daysPattern;
|
|
}
|
|
|
|
$scope.updateSchedule.busy = true;
|
|
|
|
Client.setAutoupdatePattern(pattern, function (error) {
|
|
if (error) Client.error(error);
|
|
|
|
$timeout(function () {
|
|
$scope.updateSchedule.busy = false;
|
|
if (!error) $scope.updateSchedule.currentPattern = pattern;
|
|
$('#updateScheduleModal').modal('hide');
|
|
}, 3000);
|
|
});
|
|
}
|
|
};
|
|
|
|
function getTimeZone() {
|
|
Client.getTimeZone(function (error, timeZone) {
|
|
if (error) return console.error(error);
|
|
|
|
$scope.timeZone.currentTimeZone = window.timezones.find(function (t) { return t.id === timeZone; });
|
|
$scope.timeZone.timeZone = $scope.timeZone.currentTimeZone;
|
|
});
|
|
}
|
|
|
|
function getAutoupdatePattern() {
|
|
Client.getAutoupdatePattern(function (error, result) {
|
|
if (error) return console.error(error);
|
|
|
|
// just keep the UI sane by supporting previous default pattern
|
|
if (result.pattern === '00 30 1,3,5,23 * * *') result.pattern = '00 15 1,3,5,23 * * *';
|
|
|
|
$scope.updateSchedule.currentPattern = result.pattern;
|
|
$scope.updateSchedule.pattern = result.pattern;
|
|
});
|
|
}
|
|
|
|
function getRegistryConfig() {
|
|
Client.getRegistryConfig(function (error, result) {
|
|
if (error) return console.error(error);
|
|
|
|
$scope.registryConfig.currentConfig = result;
|
|
});
|
|
}
|
|
|
|
function getSubscription() {
|
|
$scope.subscriptionBusy = true;
|
|
|
|
Client.getSubscription(function (error, result) {
|
|
if (error && error.statusCode === 402) return $scope.subscriptionBusy = false; // not yet registered
|
|
if (error && error.statusCode === 412) return $scope.subscriptionBusy = false; // invalid appstore token
|
|
if (error) return console.error(error);
|
|
|
|
$scope.subscription = result;
|
|
|
|
// avoid UI flicker
|
|
$timeout(function () {$scope.subscriptionBusy = false; }, 1);
|
|
});
|
|
}
|
|
|
|
$scope.registryConfig = {
|
|
busy: false,
|
|
error: null,
|
|
serverAddress: '',
|
|
provider: 'noop',
|
|
username: '',
|
|
password: '',
|
|
email: '',
|
|
currentConfig: {},
|
|
|
|
reset: function () {
|
|
$scope.registryConfig.busy = false;
|
|
$scope.registryConfig.error = null;
|
|
|
|
$scope.registryConfig.provider = $scope.registryConfig.currentConfig.provider;
|
|
$scope.registryConfig.serverAddress = $scope.registryConfig.currentConfig.serverAddress || '';
|
|
$scope.registryConfig.username = $scope.registryConfig.currentConfig.username || '';
|
|
$scope.registryConfig.email = $scope.registryConfig.currentConfig.email || '';
|
|
$scope.registryConfig.password = $scope.registryConfig.currentConfig.password || '';
|
|
|
|
$scope.registryConfigForm.$setUntouched();
|
|
$scope.registryConfigForm.$setPristine();
|
|
},
|
|
|
|
show: function () {
|
|
$scope.registryConfig.reset();
|
|
$('#registryConfigModal').modal('show');
|
|
},
|
|
|
|
submit: function () {
|
|
$scope.registryConfig.busy = true;
|
|
|
|
var data = {
|
|
provider: $scope.registryConfig.provider
|
|
};
|
|
|
|
if ($scope.registryConfig.provider !== 'noop') {
|
|
data.serverAddress = $scope.registryConfig.serverAddress;
|
|
data.username = $scope.registryConfig.username || '';
|
|
data.password = $scope.registryConfig.password;
|
|
data.email = $scope.registryConfig.email || '';
|
|
}
|
|
|
|
Client.setRegistryConfig(data, function (error) {
|
|
$scope.registryConfig.busy = false;
|
|
|
|
if (error) {
|
|
$scope.registryConfig.error = error.message;
|
|
return;
|
|
}
|
|
|
|
$('#registryConfigModal').modal('hide');
|
|
|
|
getRegistryConfig();
|
|
});
|
|
}
|
|
};
|
|
|
|
Client.onReady(function () {
|
|
getAutoupdatePattern();
|
|
getRegistryConfig();
|
|
getTimeZone();
|
|
|
|
$translate.onReady(function () {
|
|
Client.getLanguage(function (error, usedLang) {
|
|
if (error) return console.error('Unable to fetch language:', error);
|
|
|
|
$scope.language.availableLanguages = Client.getAvailableLanguages().map(function (l) {
|
|
return {
|
|
// we only show those in english for easier restore
|
|
display: $translate.instant('lang.'+l, {}, undefined, 'en'),
|
|
id: l
|
|
};
|
|
}).sort(function (a, b) { return a.display.localeCompare(b.display); });
|
|
$scope.language.currentLanguage = $scope.language.availableLanguages.find(function (l) { return l.id === usedLang; });
|
|
$scope.language.language = $scope.language.currentLanguage;
|
|
});
|
|
});
|
|
|
|
$scope.update.refreshTasks();
|
|
|
|
if ($scope.user.isAtLeastOwner) getSubscription();
|
|
});
|
|
|
|
// setup all the dialog focus handling
|
|
['planChangeModal', 'appstoreLoginModal'].forEach(function (id) {
|
|
$('#' + id).on('shown.bs.modal', function () {
|
|
$(this).find("[autofocus]:first").focus();
|
|
});
|
|
});
|
|
|
|
$('.modal-backdrop').remove();
|
|
}]);
|