Skip to content

Commit

Permalink
First pass at user onboarding screens
Browse files Browse the repository at this point in the history
refs #5315

- split setup into 3 screens
- add gravatar fetching
- add download counter
- add button handling for invite users
  • Loading branch information
ErisDS committed May 25, 2015
1 parent 3366df9 commit 064a22e
Show file tree
Hide file tree
Showing 24 changed files with 352 additions and 55 deletions.
1 change: 1 addition & 0 deletions core/client/Brocfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ app.import('bower_components/codemirror/mode/css/css.js');
app.import('bower_components/codemirror/mode/javascript/javascript.js');
app.import('bower_components/xregexp/xregexp-all.js');
app.import('bower_components/password-generator/lib/password-generator.js');
app.import('bower_components/blueimp-md5/js/md5.js');

// 'dem Styles
app.import('bower_components/nprogress/nprogress.css');
Expand Down
3 changes: 3 additions & 0 deletions core/client/app/components/gh-activating-list-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ var ActivatingListItem = Ember.Component.extend({
tagName: 'li',
classNameBindings: ['active'],
active: false,
linkClasses: Ember.computed('linkClass', function () {
return this.get('linkClass');
}),

unfocusLink: function () {
this.$('a').blur();
Expand Down
27 changes: 27 additions & 0 deletions core/client/app/controllers/setup/one.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Ember from 'ember';
import ajax from 'ghost/utils/ajax';

var SetupOneController = Ember.Controller.extend({

count: 'many, many',

downloadCounter: function () {
var self = this,
interval = 3000;

Ember.run.later(this, function () {
ajax({
url: self.get('ghostPaths.count'),
type: 'GET'
}).then(function (data) {
self.set('count', data.count.toLocaleString());
}).catch(function () {
self.set('count', 'many, many');
});

this.downloadCounter();
}, interval);
}.on('init')
});

export default SetupOneController;
43 changes: 43 additions & 0 deletions core/client/app/controllers/setup/three.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Ember from 'ember';
import ValidationEngine from 'ghost/mixins/validation-engine';

var SetupThreeController = Ember.Controller.extend(ValidationEngine, {
users: '',
usersArray: Ember.computed('users', function () {
return this.get('users').split('\n').filter(function (user) {
return validator.isEmail(user);
});
}),
numUsers: Ember.computed('usersArray', function () {
return this.get('usersArray').length;
}),
buttonText: Ember.computed('numUsers', function () {
var user = this.get('numUsers') === 1 ? 'user' : 'users';
return this.get('numUsers') > 0 ?
'Invite ' + this.get('numUsers') + ' ' + user : 'I\'ll do this later, take me to my blog!';
}),
buttonClass: Ember.computed('numUsers', function () {
return this.get('numUsers') > 0 ? 'btn-green' : 'btn-minor';
}),
actions: {
invite: function () {
console.log('inviting', this.get('usersArray'));

if (this.get('numUsers') === 0) {
this.sendAction('signin');
}

// TODO: do invites
},
signin: function () {
var self = this;

this.get('session').authenticate('simple-auth-authenticator:oauth2-password-grant', {
identification: self.get('email'),
password: self.get('password')
});
}
}
});

export default SetupThreeController;
70 changes: 70 additions & 0 deletions core/client/app/controllers/setup/two.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* global md5 */
import Ember from 'ember';
import ajax from 'ghost/utils/ajax';
import ValidationEngine from 'ghost/mixins/validation-engine';

var SetupTwoController = Ember.Controller.extend(ValidationEngine, {
size: 90,
blogTitle: null,
name: null,
email: '',
password: null,
image: null,
submitting: false,

gravatarUrl: Ember.computed('email', function () {
var email = this.get('email'),
size = this.get('size');

return 'http://www.gravatar.com/avatar/' + md5(email) + '?s=' + size + '&d=blank';
}),

userImage: Ember.computed('gravatarUrl', function () {
return this.get('image') || this.get('gravatarUrl');
}),

userImageBackground: Ember.computed('userImage', function () {
return 'background-image: url(' + this.get('userImage') + ')';
}),

// ValidationEngine settings
validationType: 'setup',

actions: {
setup: function () {
var self = this,
data = self.getProperties('blogTitle', 'name', 'email', 'password');

self.notifications.closePassive();

this.toggleProperty('submitting');
this.validate({format: false}).then(function () {
ajax({
url: self.get('ghostPaths.url').api('authentication', 'setup'),
type: 'POST',
data: {
setup: [{
name: data.name,
email: data.email,
password: data.password,
blogTitle: data.blogTitle
}]
}
}).then(function () {
self.get('session').authenticate('simple-auth-authenticator:oauth2-password-grant', {
identification: self.get('email'),
password: self.get('password')
});
}).catch(function (resp) {
self.toggleProperty('submitting');
self.notifications.showAPIError(resp);
});
}).catch(function (errors) {
self.toggleProperty('submitting');
self.notifications.showErrors(errors);
});
}
}
});

export default SetupTwoController;
4 changes: 2 additions & 2 deletions core/client/app/html/install3.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
<meta name="MobileOptimized" content="320" />
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1, minimal-ui" />
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Open+Sans:400,300,700" />
<link rel="stylesheet" href="file:///Users/John/Sites/Ghost/core/built/assets/vendor.css" />
<link rel="stylesheet" href="file:///Users/John/Sites/Ghost/core/built/assets/ghost.css" />
<link rel="stylesheet" href="../../../built/assets/vendor.css" />
<link rel="stylesheet" href="../../../built/assets/ghost.css" />
</head>
<body>

Expand Down
7 changes: 6 additions & 1 deletion core/client/app/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ var Router = Ember.Router.extend({
documentTitle();

Router.map(function () {
this.route('setup');
this.resource('setup', function () {
this.route('one');
this.route('two');
this.route('three');
});

this.route('signin');
this.route('signout');
this.route('signup', {path: '/signup/:token'});
Expand Down
9 changes: 9 additions & 0 deletions core/client/app/routes/setup/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Ember from 'ember';

var SetupRoute = Ember.Route.extend({
beforeModel: function () {
this.transitionTo('setup.one');
}
});

export default SetupRoute;
24 changes: 24 additions & 0 deletions core/client/app/routes/setup/one.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Ember from 'ember';
import ajax from 'ghost/utils/ajax';

var SetupOneRoute = Ember.Route.extend({
titleToken: 'Setup',
beforeModel: function () {
var self = this,
ctrl = this.controllerFor('setup.one');

if (!ctrl) {
this.generateController('setup.one');
ctrl = this.controllerFor('setup.one');
}

return ajax({
url: self.get('ghostPaths.count'),
type: 'GET'
}).then(function (data) {
ctrl.set('count', data.count.toLocaleString());
}).catch(function () { /* Do nothing */ });
}
});

export default SetupOneRoute;
7 changes: 7 additions & 0 deletions core/client/app/routes/setup/three.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Ember from 'ember';

var SetupTwoRoute = Ember.Route.extend({
titleToken: 'Setup'
});

export default SetupTwoRoute;
7 changes: 7 additions & 0 deletions core/client/app/routes/setup/two.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import Ember from 'ember';

var SetupTwoRoute = Ember.Route.extend({
titleToken: 'Setup'
});

export default SetupTwoRoute;
34 changes: 26 additions & 8 deletions core/client/app/styles/layouts/flow.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
background-repeat: repeat-x;
}

.gh-flow-nav .current ~ .divider {
.gh-flow-nav .active ~ .divider {
background-image: linear-gradient(to right, #e3e3e3 33%, rgba(255, 255, 255, 0) 0%);
}

Expand Down Expand Up @@ -107,32 +107,32 @@
line-height: 22px;
}

.gh-flow-nav .current ~ li:not(divider) .step {
.gh-flow-nav .active ~ li:not(divider) .step {
border: #e3e3e3 2px solid;
background: transparent;
color: #cdcdcd;
}

.gh-flow-nav .current ~ li:not(divider) .step .num {
.gh-flow-nav .active ~ li:not(divider) .step .num {
display: block;
}

.gh-flow-nav .current ~ li:not(divider) .step i {
.gh-flow-nav .active ~ li:not(divider) .step i {
display: none;
}

.gh-flow-nav .current .step {
.gh-flow-nav .active .step {
border: var(--green) 2px solid;
background: transparent;
color: color(var(--green) lightness(-10%));
cursor: default;
}

.gh-flow-nav .current .step .num {
.gh-flow-nav .active .step .num {
display: block;
}

.gh-flow-nav .current .step i {
.gh-flow-nav .active .step i {
display: none;
}

Expand Down Expand Up @@ -257,7 +257,7 @@
transition: opacity 0.3s ease;
}

.gh-flow-content .img {
.gh-flow-content .placeholder-img {
display: block;
width: 90px;
height: 90px;
Expand All @@ -268,6 +268,24 @@
animation: fade-in 1s;
}

.gh-flow-content .gravatar-img {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: block;
box-sizing: content-box;
width: calc(100% - 8px);
width: 90px;
height: 90px;
border: #fff 4px solid;
background-position: center center;
background-size: cover;
border-radius: 100%;
animation: fade-in 1s;
}

.gh-flow-content .form-group {
margin-bottom: 2.5rem;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{#link-to route alternateActive=active}}{{title}}{{yield}}{{/link-to}}
{{#link-to route alternateActive=active classNameBindings="linkClasses"}}{{title}}{{yield}}{{/link-to}}
59 changes: 24 additions & 35 deletions core/client/app/templates/setup.hbs
Original file line number Diff line number Diff line change
@@ -1,38 +1,27 @@
<section class="setup-box js-setup-box fade-in">
<div class="vertical">
<form id="setup" class="setup-form" method="post" novalidate="novalidate">
<div class="gh-flow">

{{!-- Horrible hack to prevent Chrome from incorrectly auto-filling inputs --}}
<input style="display:none;" type="text" name="fakeusernameremembered"/>
<input style="display:none;" type="password" name="fakepasswordremembered"/>
<header class="gh-flow-head">
<nav class="gh-flow-nav">
{{!-- TODO: this should only appear on screens 2 & 3 --}}
<a class="gh-flow-back" href="#"><i class="icon-arrow-left"></i> Back</a>
<ol>
{{#gh-activating-list-item route="setup.one" linkClass="step"}}
<i class="icon-check"></i><span class="num">1</span>
{{/gh-activating-list-item}}
<li class="divider"></li>
{{#gh-activating-list-item route="setup.two" linkClass="step"}}
<i class="icon-check"></i><span class="num">2</span>
{{/gh-activating-list-item}}
<li class="divider"></li>
{{#gh-activating-list-item route="setup.three" linkClass="step"}}
<i class="icon-check"></i><span class="num">3</span>
{{/gh-activating-list-item}}
</ol>
</nav>
</header>

<header>
<h1>Welcome to your new Ghost blog</h1>
<h2>Let's get a few things set up so you can get started.</h2>
</header>
<div class="form-group">
<label for="blog-title">Blog Title</label>
{{input type="text" name="blog-title" autofocus="autofocus" autocorrect="off" value=blogTitle }}
<p>What would you like to call your blog?</p>
</div>
<div class="form-group">
<label for="name">Full Name</label>
{{input type="text" name="name" autofocus="autofocus" autocorrect="off" value=name }}
<p>The name that you will sign your posts with</p>
</div>
<div class="form-group">
<label for="email">Email Address</label>
{{input type="email" name="email" autofocus="autofocus" autocorrect="off" value=email }}
<p>Used for important notifications</p>
</div>
<div class="form-group">
<label for="password">Password</label>
{{input type="password" name="password" autofocus="autofocus" autocorrect="off" value=password }}
<p>Must be at least 8 characters</p>
</div>
<footer>
<button type="submit" class="btn btn-green btn-lg" {{action "setup"}} disabled={{submitting}}>Ok, Let's Do This</button>
</footer>
</form>
<div class="gh-flow-content-wrap">
{{outlet}}
</div>
</section>

</div>
12 changes: 12 additions & 0 deletions core/client/app/templates/setup/one.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<section class="gh-flow-content">
<header>
<h1>Welcome to <strong>Ghost</strong>!</h1>
<p>So far there have been <em>{{count}}</em> Ghost blogs made by people all over the world. Today we’re making yours.</p>
</header>

<img class="gh-flow-screenshot" src="{{gh-path 'admin' 'img/install-welcome.png'}}" alt="Ghost screenshot" />

{{#link-to "setup.two" classNames="btn btn-green btn-lg"}}
Create your account <i class="icon-chevron"></i>
{{/link-to}}
</section>
Loading

0 comments on commit 064a22e

Please sign in to comment.