diff --git a/dashboard/gulpfile.js b/dashboard/gulpfile.js index dc1b7ffb5..7e80c2982 100644 --- a/dashboard/gulpfile.js +++ b/dashboard/gulpfile.js @@ -82,7 +82,6 @@ gulp.task('js-index', function () { return gulp.src([ 'src/js/index.js', 'src/js/client.js', - 'src/js/main.js', 'src/js/utils.js', 'src/views/*.js' ]) @@ -210,7 +209,7 @@ gulp.task('watch', function (done) { gulp.watch(['src/js/restore.js', 'src/js/client.js', 'src/js/utils.js'], gulp.series(['js-restore'])); gulp.watch(['src/js/passwordreset.js', 'src/js/utils.js'], gulp.series(['js-passwordreset'])); gulp.watch(['src/js/setupaccount.js', 'src/js/utils.js'], gulp.series(['js-setupaccount'])); - gulp.watch(['src/js/index.js', 'src/js/client.js', 'src/js/main.js', 'src/views/*.js', 'src/js/utils.js'], gulp.series(['js-index'])); + gulp.watch(['src/js/index.js', 'src/js/client.js', 'src/views/*.js', 'src/js/utils.js'], gulp.series(['js-index'])); gulp.watch(['src/3rdparty/**/*'], gulp.series(['3rdparty'])); done(); }); diff --git a/dashboard/src/js/index.js b/dashboard/src/js/index.js index 37caa4ff9..d70c73d9b 100644 --- a/dashboard/src/js/index.js +++ b/dashboard/src/js/index.js @@ -610,3 +610,219 @@ app.config(['fitTextConfigProvider', function (fitTextConfigProvider) { max: 24 }; }]); + +app.controller('MainController', ['$scope', '$route', '$timeout', '$location', '$interval', 'Notification', 'Client', function ($scope, $route, $timeout, $location, $interval, Notification, Client) { + $scope.initialized = false; // used to animate the UI + $scope.user = Client.getUserInfo(); + $scope.installedApps = Client.getInstalledApps(); + $scope.config = {}; + $scope.client = Client; + $scope.subscription = {}; + $scope.notificationCount = 0; + $scope.hideNavBarActions = $location.path() === '/logs'; + $scope.backgroundImageUrl = ''; + + $scope.reboot = { + busy: false, + + show: function () { + $scope.reboot.busy = false; + $('#rebootModal').modal('show'); + }, + + submit: function () { + $scope.reboot.busy = true; + + Client.reboot(function (error) { + if (error) return Client.error(error); + + $('#rebootModal').modal('hide'); + + // trigger refetch to show offline banner + $timeout(function () { Client.getStatus(function () {}); }, 5000); + }); + } + }; + + $scope.isActive = function (url) { + if (!$route.current) return false; + return $route.current.$$route.originalPath.indexOf(url) === 0; + }; + + $scope.logout = function (event) { + event.stopPropagation(); + $scope.initialized = false; + Client.logout(); + }; + + $scope.openSubscriptionSetup = function () { + Client.openSubscriptionSetup($scope.subscription); + }; + + // NOTE: this function is exported and called from the appstore.js + $scope.updateSubscriptionStatus = function () { + Client.getSubscription(function (error, subscription) { + if (error && error.statusCode === 412) return; // not yet registered + if (error && error.statusCode === 402) return; // invalid appstore token + if (error) return console.error(error); + + $scope.subscription = subscription; + }); + }; + + function refreshNotifications() { + if (!Client.getUserInfo().isAtLeastAdmin) return; + + Client.getNotifications({ acknowledged: false }, 1, 100, function (error, results) { // counter maxes out at 100 + if (error) console.error(error); + else $scope.notificationCount = results.length; + }); + } + + // update state of acknowledged notification + $scope.notificationAcknowledged = function () { + refreshNotifications(); + }; + + function redirectOnMandatory2FA() { + if (Client.getConfig().mandatory2FA && !Client.getUserInfo().twoFactorAuthenticationEnabled) { + $location.path('/profile').search({ setup2fa: true }); + } + } + + // Make it redirect if the browser URL is changed directly - https://forum.cloudron.io/topic/7510/bug-in-2fa-force + $scope.$on('$routeChangeStart', function (/* event */) { + if ($scope.initialized) redirectOnMandatory2FA(); + }); + + var gPlatformStatusNotification = null; + function trackPlatformStatus() { + Client.getPlatformStatus(function (error, result) { + if (error) return console.error('Failed to get platform status.', error); + + // see box/src/platform.js + if (result.message === 'Ready') { + if (gPlatformStatusNotification) { + gPlatformStatusNotification.kill(); + gPlatformStatusNotification = null; + } + + return; + } + + if (!gPlatformStatusNotification) { + var options = { title: 'Platform status', message: result.message, delay: 'notimeout', replaceMessage: true, closeOnClick: false }; + + Notification.primary(options).then(function (result) { + gPlatformStatusNotification = result; + $timeout(trackPlatformStatus, 5000); + }); + } else { + gPlatformStatusNotification.message = result.message; + $timeout(trackPlatformStatus, 5000); + } + }); + } + + function redirectIfNeeded(status) { + if (!status.activated) { + console.log('Not activated yet, redirecting', status); + if (status.restore.active || status.restore.errorMessage) { // show the error message in restore page + window.location.href = '/restore.html' + window.location.search; + } else if (status.adminFqdn) { + window.location.href = 'https://' + status.adminFqdn + '/setup.html' + (window.location.search); + } else { + window.location.href = '/setupdns.html' + window.location.search; + } + return true; + } + + // support local development with localhost check + if (window.location.hostname !== status.adminFqdn && window.location.hostname !== 'localhost' && !window.location.hostname.startsWith('192.')) { + // user is accessing by IP or by the old admin location (pre-migration) + window.location.href = '/setupdns.html' + window.location.search; + return true; + } + + return false; + } + + // this loads the very first thing when accessing via IP or domain + function init() { + Client.getProvisionStatus(function (error, status) { + if (error) return Client.initError(error, init); + + if (redirectIfNeeded(status)) return; + + // check version and force reload if needed + if (!localStorage.version) { + localStorage.version = status.version; + } else if (localStorage.version !== status.version) { + localStorage.version = status.version; + window.location.reload(true); + } + + console.log('Running dashboard version ', localStorage.version); + + // get user profile as the first thing. this populates the "scope" and affects subsequent API calls + Client.refreshUserInfo(function (error) { + if (error) return Client.initError(error, init); + + Client.refreshConfig(function (error) { + if (error) return Client.initError(error, init); + + Client.refreshAvailableLanguages(function (error) { + if (error) return Client.initError(error, init); + + Client.refreshInstalledApps(function (error) { + if (error) return Client.initError(error, init); + + // now mark the Client to be ready + Client.setReady(); + + $scope.config = Client.getConfig(); + + if (Client.getUserInfo().hasBackgroundImage) { + document.getElementById('mainContentContainer').style.backgroundImage = 'url("' + Client.getBackgroundImageUrl() + '")'; + document.getElementById('mainContentContainer').classList.add('has-background'); + } + + $scope.initialized = true; + + redirectOnMandatory2FA(); + + $interval(refreshNotifications, 60 * 1000); + refreshNotifications(); + + Client.getSubscription(function (error, subscription) { + if (error && error.statusCode === 412) return; // not yet registered + if (error && error.statusCode === 402) return; // invalid appstore token + if (error) return console.error(error); + + $scope.subscription = subscription; + + // only track platform status if we are registered + trackPlatformStatus(); + }); + }); + }); + }); + }); + }); + } + + Client.onConfig(function (config) { + if (config.cloudronName) { + document.title = config.cloudronName; + } + }); + + init(); + + // setup all the dialog focus handling + ['updateModal'].forEach(function (id) { + $('#' + id).on('shown.bs.modal', function () { + $(this).find('[autofocus]:first').focus(); + }); + }); +}]); diff --git a/dashboard/src/js/main.js b/dashboard/src/js/main.js deleted file mode 100644 index 0bd1106cb..000000000 --- a/dashboard/src/js/main.js +++ /dev/null @@ -1,220 +0,0 @@ -'use strict'; - -/* global angular */ -/* global $ */ - -angular.module('Application').controller('MainController', ['$scope', '$route', '$timeout', '$location', '$interval', 'Notification', 'Client', function ($scope, $route, $timeout, $location, $interval, Notification, Client) { - $scope.initialized = false; // used to animate the UI - $scope.user = Client.getUserInfo(); - $scope.installedApps = Client.getInstalledApps(); - $scope.config = {}; - $scope.client = Client; - $scope.subscription = {}; - $scope.notificationCount = 0; - $scope.hideNavBarActions = $location.path() === '/logs'; - $scope.backgroundImageUrl = ''; - - $scope.reboot = { - busy: false, - - show: function () { - $scope.reboot.busy = false; - $('#rebootModal').modal('show'); - }, - - submit: function () { - $scope.reboot.busy = true; - - Client.reboot(function (error) { - if (error) return Client.error(error); - - $('#rebootModal').modal('hide'); - - // trigger refetch to show offline banner - $timeout(function () { Client.getStatus(function () {}); }, 5000); - }); - } - }; - - $scope.isActive = function (url) { - if (!$route.current) return false; - return $route.current.$$route.originalPath.indexOf(url) === 0; - }; - - $scope.logout = function (event) { - event.stopPropagation(); - $scope.initialized = false; - Client.logout(); - }; - - $scope.openSubscriptionSetup = function () { - Client.openSubscriptionSetup($scope.subscription); - }; - - // NOTE: this function is exported and called from the appstore.js - $scope.updateSubscriptionStatus = function () { - Client.getSubscription(function (error, subscription) { - if (error && error.statusCode === 412) return; // not yet registered - if (error && error.statusCode === 402) return; // invalid appstore token - if (error) return console.error(error); - - $scope.subscription = subscription; - }); - }; - - function refreshNotifications() { - if (!Client.getUserInfo().isAtLeastAdmin) return; - - Client.getNotifications({ acknowledged: false }, 1, 100, function (error, results) { // counter maxes out at 100 - if (error) console.error(error); - else $scope.notificationCount = results.length; - }); - } - - // update state of acknowledged notification - $scope.notificationAcknowledged = function () { - refreshNotifications(); - }; - - function redirectOnMandatory2FA() { - if (Client.getConfig().mandatory2FA && !Client.getUserInfo().twoFactorAuthenticationEnabled) { - $location.path('/profile').search({ setup2fa: true }); - } - } - - // Make it redirect if the browser URL is changed directly - https://forum.cloudron.io/topic/7510/bug-in-2fa-force - $scope.$on('$routeChangeStart', function (/* event */) { - if ($scope.initialized) redirectOnMandatory2FA(); - }); - - var gPlatformStatusNotification = null; - function trackPlatformStatus() { - Client.getPlatformStatus(function (error, result) { - if (error) return console.error('Failed to get platform status.', error); - - // see box/src/platform.js - if (result.message === 'Ready') { - if (gPlatformStatusNotification) { - gPlatformStatusNotification.kill(); - gPlatformStatusNotification = null; - } - - return; - } - - if (!gPlatformStatusNotification) { - var options = { title: 'Platform status', message: result.message, delay: 'notimeout', replaceMessage: true, closeOnClick: false }; - - Notification.primary(options).then(function (result) { - gPlatformStatusNotification = result; - $timeout(trackPlatformStatus, 5000); - }); - } else { - gPlatformStatusNotification.message = result.message; - $timeout(trackPlatformStatus, 5000); - } - }); - } - - function redirectIfNeeded(status) { - if (!status.activated) { - console.log('Not activated yet, redirecting', status); - if (status.restore.active || status.restore.errorMessage) { // show the error message in restore page - window.location.href = '/restore.html' + window.location.search; - } else if (status.adminFqdn) { - window.location.href = 'https://' + status.adminFqdn + '/setup.html' + (window.location.search); - } else { - window.location.href = '/setupdns.html' + window.location.search; - } - return true; - } - - // support local development with localhost check - if (window.location.hostname !== status.adminFqdn && window.location.hostname !== 'localhost' && !window.location.hostname.startsWith('192.')) { - // user is accessing by IP or by the old admin location (pre-migration) - window.location.href = '/setupdns.html' + window.location.search; - return true; - } - - return false; - } - - // this loads the very first thing when accessing via IP or domain - function init() { - Client.getProvisionStatus(function (error, status) { - if (error) return Client.initError(error, init); - - if (redirectIfNeeded(status)) return; - - // check version and force reload if needed - if (!localStorage.version) { - localStorage.version = status.version; - } else if (localStorage.version !== status.version) { - localStorage.version = status.version; - window.location.reload(true); - } - - console.log('Running dashboard version ', localStorage.version); - - // get user profile as the first thing. this populates the "scope" and affects subsequent API calls - Client.refreshUserInfo(function (error) { - if (error) return Client.initError(error, init); - - Client.refreshConfig(function (error) { - if (error) return Client.initError(error, init); - - Client.refreshAvailableLanguages(function (error) { - if (error) return Client.initError(error, init); - - Client.refreshInstalledApps(function (error) { - if (error) return Client.initError(error, init); - - // now mark the Client to be ready - Client.setReady(); - - $scope.config = Client.getConfig(); - - if (Client.getUserInfo().hasBackgroundImage) { - document.getElementById('mainContentContainer').style.backgroundImage = 'url("' + Client.getBackgroundImageUrl() + '")'; - document.getElementById('mainContentContainer').classList.add('has-background'); - } - - $scope.initialized = true; - - redirectOnMandatory2FA(); - - $interval(refreshNotifications, 60 * 1000); - refreshNotifications(); - - Client.getSubscription(function (error, subscription) { - if (error && error.statusCode === 412) return; // not yet registered - if (error && error.statusCode === 402) return; // invalid appstore token - if (error) return console.error(error); - - $scope.subscription = subscription; - - // only track platform status if we are registered - trackPlatformStatus(); - }); - }); - }); - }); - }); - }); - } - - Client.onConfig(function (config) { - if (config.cloudronName) { - document.title = config.cloudronName; - } - }); - - init(); - - // setup all the dialog focus handling - ['updateModal'].forEach(function (id) { - $('#' + id).on('shown.bs.modal', function () { - $(this).find('[autofocus]:first').focus(); - }); - }); -}]);