diff --git a/webadmin/src/js/setup.js b/webadmin/src/js/setup.js index 387652e34..c32169ea8 100644 --- a/webadmin/src/js/setup.js +++ b/webadmin/src/js/setup.js @@ -1,7 +1,7 @@ 'use strict'; // create main application module -var app = angular.module('Application', ['ngRoute', 'ngAnimate', 'angular-md5', 'ui-notification']); +var app = angular.module('Application', ['angular-md5', 'ui-notification']); app.directive('ngEnter', function () { return function (scope, element, attrs) { @@ -17,267 +17,123 @@ app.directive('ngEnter', function () { }; }); -// setup all major application routes -app.config(['$routeProvider', function ($routeProvider) { - $routeProvider.when('/', { - redirectTo: '/step1' - }).when('/step1', { - controller: 'StepController', - templateUrl: 'views/setup/step1.html' - }).when('/step2', { - controller: 'StepController', - templateUrl: 'views/setup/step2.html' - }).when('/step3', { - controller: 'StepController', - templateUrl: 'views/setup/step3.html' - }).when('/step4', { - controller: 'FinishController', - templateUrl: 'views/setup/step4.html' - }).otherwise({ redirectTo: '/'}); -}]); +// app.service('Wizard', [ function () { +// var instance = null; -app.service('Wizard', [ function () { - var instance = null; +// function Wizard() { +// this.username = ''; +// this.email = ''; +// this.password = ''; +// this.displayName = ''; +// this.setupToken = null; +// this.provider = null; +// this.apiServerOrigin = null; +// this.createAppstoreAccount = true; +// this.dnsConfig = null; +// } - function Wizard() { - this.username = ''; - this.email = ''; - this.password = ''; - this.displayName = ''; - this.setupToken = null; - this.provider = null; - this.apiServerOrigin = null; - this.createAppstoreAccount = true; - this.availableAvatars = [{ - file: null, - data: null, - url: '/img/avatars/avatar_0.png', - }, { - file: null, - data: null, - url: '/img/avatars/rubber-duck.png' - }, { - file: null, - data: null, - url: '/img/avatars/carrot.png' - }, { - file: null, - data: null, - url: '/img/avatars/cup.png' - }, { - file: null, - data: null, - url: '/img/avatars/football.png' - }, { - file: null, - data: null, - url: '/img/avatars/owl.png' - }, { - file: null, - data: null, - url: '/img/avatars/space-rocket.png' - }, { - file: null, - data: null, - url: '/img/avatars/armchair.png' - }, { - file: null, - data: null, - url: '/img/avatars/cap.png' - }, { - file: null, - data: null, - url: '/img/avatars/pan.png' - }, { - file: null, - data: null, - url: '/img/avatars/meat.png' - }, { - file: null, - data: null, - url: '/img/avatars/umbrella.png' - }, { - file: null, - data: null, - url: '/img/avatars/jar.png' - }]; - this.avatar = {}; - this.avatarBlob = null; - this.dnsConfig = null; - } +// instance = new Wizard(); +// return instance; +// }]); - Wizard.prototype.setPreviewAvatar = function (avatar) { - var that = this; +// app.controller('StepController', ['$scope', '$route', '$location', 'Wizard', function ($scope, $route, $location, Wizard) { +// $scope.wizard = Wizard; - this.avatar = avatar; +// $scope.next = function (bad) { +// if (bad) return; - // scale image and get the blob now. do not use the previewAvatar element here because it is not updated yet - var img = document.createElement('img'); - img.src = avatar.data || avatar.url; - var canvas = document.createElement('canvas'); - canvas.width = 256; - canvas.height = 256; +// var current = $location.path(); +// var next = ''; - var imageDimensionRatio = img.width / img.height; - var canvasDimensionRatio = canvas.width / canvas.height; - var renderableHeight, renderableWidth, xStart, yStart; +// if (current === '/step1') { +// next = '/step2'; +// } else if (current === '/step2') { +// if (Wizard.dnsConfig === null) next = '/step4'; +// else next = '/step3'; +// } else if (current === '/step3') { +// next = '/step4'; +// } else { +// next = '/step1'; +// } - if (imageDimensionRatio > canvasDimensionRatio) { - renderableHeight = canvas.height; - renderableWidth = img.width * (renderableHeight / img.height); - xStart = (canvas.width - renderableWidth) / 2; - yStart = 0; - } else if (imageDimensionRatio < canvasDimensionRatio) { - renderableWidth = canvas.width; - renderableHeight = img.height * (renderableWidth / img.width); - xStart = 0; - yStart = (canvas.height - renderableHeight) / 2; - } else { - renderableHeight = canvas.height; - renderableWidth = canvas.width; - xStart = 0; - yStart = 0; - } +// $location.path(next); +// }; - var ctx = canvas.getContext('2d'); - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.drawImage(img, xStart, yStart, renderableWidth, renderableHeight); +// $scope.focusNext = function (elemId, bad) { +// if (!bad) $('#' + elemId).focus(); +// }; +// }]); - canvas.toBlob(function (blob) { - that.avatarBlob = blob; - }); - }; +// app.controller('FinishController', ['$scope', '$location', '$http', 'Wizard', 'Client', function ($scope, $location, $http, Wizard, Client) { +// $scope.wizard = Wizard; - instance = new Wizard(); - return instance; -}]); +// function setDnsConfigIfNeeded(callback) { +// if ($scope.wizard.dnsConfig === null) return callback(null); -app.controller('StepController', ['$scope', '$route', '$location', 'Wizard', function ($scope, $route, $location, Wizard) { - $scope.wizard = Wizard; +// Client.setDnsConfig($scope.wizard.dnsConfig, callback); +// } - $scope.next = function (bad) { - if (bad) return; - - var current = $location.path(); - var next = ''; - - if (current === '/step1') { - next = '/step2'; - } else if (current === '/step2') { - if (Wizard.dnsConfig === null) next = '/step4'; - else next = '/step3'; - } else if (current === '/step3') { - next = '/step4'; - } else { - next = '/step1'; - } - - $location.path(next); - }; - - $scope.focusNext = function (elemId, bad) { - if (!bad) $('#' + elemId).focus(); - }; - - $scope.$on('$viewContentLoaded', function () { - if ($location.path() === '/step2') { - if (Wizard.requireEmail) $('#inputEmail').focus(); - else $('#inputDisplayName').focus(); - } else { - $('a[autofocus]').focus(); - $('input[autofocus]').focus(); - } - }); - - $scope.showCustomAvatarSelector = function () { - $('#avatarFileInput').click(); - }; - - // cheap way to detect if we are in avatar and name selection step - if ($route.current.templateUrl === 'views/setup/step1.html') { - $('#avatarFileInput').get(0).onchange = function (event) { - var fr = new FileReader(); - fr.onload = function () { - $scope.$apply(function () { - var tmp = { - file: event.target.files[0], - data: fr.result, - url: null - }; - - $scope.wizard.availableAvatars.push(tmp); - $scope.wizard.setPreviewAvatar(tmp); - }); - }; - fr.readAsDataURL(event.target.files[0]); - }; - - // ensure image got loaded before setting the preview avatar - var image = document.createElement('img'); - var randomIndex = Math.floor(Math.random() * $scope.wizard.availableAvatars.length); - image.onload = function() { - $scope.$apply(function () { $scope.wizard.setPreviewAvatar($scope.wizard.availableAvatars[randomIndex]); }); - image = null; - }; - image.src = $scope.wizard.availableAvatars[randomIndex].data || $scope.wizard.availableAvatars[randomIndex].url; - } else if ($route.current.templateUrl === 'views/setup/step3.html' && Wizard.dnsConfig === null) { - $location.path('/step4'); // not using custom domain - } - -}]); - -app.controller('FinishController', ['$scope', '$location', '$http', 'Wizard', 'Client', function ($scope, $location, $http, Wizard, Client) { - $scope.wizard = Wizard; - - function setDnsConfigIfNeeded(callback) { - if ($scope.wizard.dnsConfig === null) return callback(null); - - Client.setDnsConfig($scope.wizard.dnsConfig, callback); - } - - function registerAppstoreAccountIfNeeded(callback) { - if (!Wizard.createAppstoreAccount) return callback(null); - if (Wizard.provider === 'caas') return callback(null); - - $http.post(Wizard.apiServerOrigin + '/api/v1/users', { email: Wizard.email, password: Wizard.password }).success(function (data, status) { - if (status !== 201) return callback({ status: status, data: data }); - - Client.setAppstoreConfig({ userId: data.userId, token: data.accessToken }, callback); - }).error(function (data, status) { - callback({ status: status, data: data }); - }); - } - - Client.createAdmin(Wizard.username, Wizard.password, Wizard.email, Wizard.displayName, Wizard.setupToken, function (error) { - if (error) { - console.error('Internal error', error); - $location.path('/step2').search('error', error.message); - return; - } - - Client.changeCloudronAvatar($scope.wizard.avatarBlob, function (error) { - if (error) return console.error('Unable to set avatar.', error); - - setDnsConfigIfNeeded(function (error) { - if (error) return console.error('Unable to set dns config.', error); - - registerAppstoreAccountIfNeeded(function (error) { - if (error) console.error('Unable to create appstore account.', error); // this is not fatal - - window.location.href = '/'; - }); - }); - }); - }); -}]); - -app.controller('SetupController', ['$scope', '$location', 'Client', 'Wizard', function ($scope, $location, Client, Wizard) { - $scope.initialized = false; - $scope.wizard = Wizard; +// }]); +app.controller('SetupController', ['$scope', '$http', 'Client', function ($scope, $http, Client) { // Stupid angular location provider either wants html5 location mode or not, do the query parsing on my own var search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {}); + $scope.initialized = false; + $scope.busy = false; + $scope.account = { + email: '', + displayName: '', + requireEmail: false, + username: '', + password: '' + }; + $scope.error = null; + $scope.provider = ''; + $scope.apiServerOrigin = ''; + $scope.setupToken = ''; + $scope.createAppstoreAccount = true; + $scope.showDNSSetup = false; + + $scope.activateCloudron = function () { + $scope.busy = true; + + function registerAppstoreAccountIfNeeded(callback) { + if (!$scope.createAppstoreAccount) return callback(null); + + $http.post($scope.apiServerOrigin + '/api/v1/users', { email: $scope.account.email, password: $scope.account.password }).success(function (data, status) { + if (status !== 201) return callback({ status: status, data: data }); + + Client.setAppstoreConfig({ userId: data.userId, token: data.accessToken }, callback); + }).error(function (data, status) { + callback({ status: status, data: data }); + }); + } + + Client.createAdmin($scope.account.username, $scope.account.password, $scope.account.email, $scope.account.displayName, $scope.setupToken, function (error) { + if (error) { + console.error('Internal error', error); + $scope.error = error; + $scope.busy = false; + return; + } + + registerAppstoreAccountIfNeeded(function (error) { + if (error) console.error('Unable to create appstore account.', error); // this is not fatal + + $scope.busy = false; + + // for caas we are done here + if ($scope.provider === 'caas') { + window.location.href = '/'; + return; + } + + $scope.showDNSSetup = true; + }); + }); + }; + Client.getStatus(function (error, status) { if (error) { window.location.href = '/error.html'; @@ -300,16 +156,15 @@ app.controller('SetupController', ['$scope', '$location', 'Client', 'Wizard', fu return; } - Wizard.setupToken = search.setupToken; + $scope.setupToken = search.setupToken; + $scope.createAppstoreAccount = false; } - Wizard.email = search.email; - Wizard.displayName = search.displayName; - Wizard.requireEmail = !search.email; - Wizard.provider = status.provider; - Wizard.apiServerOrigin = status.apiServerOrigin; - - $location.path('/step1'); + $scope.account.email = search.email || $scope.account.email; + $scope.account.displayName = search.displayName || $scope.account.displayName; + $scope.account.requireEmail = !search.email; + $scope.provider = status.provider; + $scope.apiServerOrigin = status.apiServerOrigin; $scope.initialized = true; }); diff --git a/webadmin/src/setup.html b/webadmin/src/setup.html index a5fab57d5..5f3153353 100644 --- a/webadmin/src/setup.html +++ b/webadmin/src/setup.html @@ -15,17 +15,12 @@ - - - - - @@ -37,18 +32,67 @@ -
+

No setup token provided.

Please use the setup link for this cloudron.
-
-
-
+
+
+
-
-
-
+
+ +
+
+
+
+
+

Welcome to your Cloudron

+

Create an Admin Account

+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+ Password must be 8-30 character with at least one uppercase, one numeric and one special character +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + +
+
+
+
+
+ Now do DNS setup +