'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(); }]);