Top Banner
Controlling Route Traversal With Flows nathanhammond
50

Controlling Route Traversal

Dec 12, 2015

Download

Documents

sunilkaspo

Controlling Route Traversal
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Controlling Route Traversal

Controlling Route Traversal With Flows

nathanhammond

Page 2: Controlling Route Traversal
Page 3: Controlling Route Traversal

URLs/accounts

/accounts/12

/transfers

/transfers/78

/statements

/statements/august

/tour

/contact

/login

/login/one-time-password/setup

/login/one-time-password/select-delivery-method

/login/one-time-password/authenticate

/login/one-time-password/register-device

/login/electronic-consent

/login/terms-of-service-consent

/login/reset-password /login/complete

/logout

/recover-username

/recover-password

Page 4: Controlling Route Traversal

Resources/accounts

/accounts/12

/transfers

/transfers/78

/statements

/statements/august

/tour

/contact

/login

/login/one-time-password/setup

/login/one-time-password/select-delivery-method

/login/one-time-password/authenticate

/login/one-time-password/register-device

/login/electronic-consent

/login/terms-of-service-consent

/login/reset-password /login/complete

/logout

/recover-username

/recover-password

Page 5: Controlling Route Traversal

Actions/accounts

/accounts/12

/transfers

/transfers/78

/statements

/statements/august

/tour

/contact

/login

/login/one-time-password/setup

/login/one-time-password/select-delivery-method

/login/one-time-password/authenticate

/login/one-time-password/register-device

/login/electronic-consent

/login/terms-of-service-consent

/login/reset-password /login/complete

/logout

/recover-username

/recover-password

Page 6: Controlling Route Traversal

Flows?login otp.

authenticate accounts

Page 7: Controlling Route Traversal

ComparisonResource Action Flow

Route name is a noun. Route name is a verb. Route name is a verb.

Appears in the history stack. Appears in the history stack. Depends. One or more entries in the history stack.

Doesn't appreciably change application state. Changes application state. Flow state incrementally or

transactionally committed.

Newly rendered page. Flash messaging and/or the newly created resource.

Next step, results page, or the finalized resource.

Reload the model state. Reload a model (if any) and possibly the controller state.

Possibly drop the user back into the state machine.

No reset necessary after view. Reset typical after completion. Reset typical after completion.

Page 8: Controlling Route Traversal
Page 9: Controlling Route Traversal

Designing a Flow

Page 10: Controlling Route Traversal

Flow Spaghetti

Page 11: Controlling Route Traversal

Step 1: Inventory Your Routes

Page 12: Controlling Route Traversal

Router.map(function() { this.resource('authenticated', { path: '/' }, function() { this.resource('accounts', { path: '/' }, function() { this.route('details', { path : 'account/:account_id' }); }); this.resource('transfers'); this.resource('statements', function() {}); this.route('tour'); }); ! this.resource('login', function() { this.resource('one-time-password', function() { this.route('setup'); this.route('select-delivery-method'); this.route('authenticate'); this.route('register-device'); }); this.route('electronic-consent'); this.route('terms-of-service-consent'); this.route('reset-password'); this.route('complete'); }); ! this.route('logout'); this.route('recover-username'); this.route('recover-password'); this.route('contact'); });

https://github.com/alexdiliberto/emberconf-2014-demo/blob/master/app/router.js

Page 13: Controlling Route Traversal

Step 2: List Linear Paths

Page 14: Controlling Route Traversal

https://docs.google.com/spreadsheet/ccc?key=0ApnSRONV3LTVdGJuLUlnOGxzY1FadGZHN050ZVJXcWc

Description Steps

Already logged in. login.index accounts.index

Login is clean. login.index login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Invalid credentials. login.index login.index!flash message

Dismiss message on keypress.

Login, secondary challenge, no OTP method.

login.index contact

Login, secondary challenge, single OTP method.

login.index one-time-password.authenticate

one-time-password.register-device

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Login, secondary challenge, multiple OTP methods.

login.index one-time-password.select-delivery-method

one-time-password.authenticate

one-time-password.register-device

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Login, needs to set up OTP. login.index one-time-password.setup

one-time-password.register-device

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Login using a temporary password. login.index login.reset-password login.reset-password-complete

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Login using a temporary password, needs to set up OTP

login.index login.reset-password login.reset-password-complete

one-time-password.setup

one-time-password.register-device

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Login using a temporary password, secondary challenge, no OTP method.

login.index contact

Login using a temporary password, secondary challenge, single OTP method.

login.index one-time-password.authenticate

one-time-password.register-device

login.reset-password login.reset-password-complete

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Login using a temporary password, secondary challenge, multiple OTP methods.

login.index one-time-password.select-delivery-method

one-time-password.authenticate

one-time-password.register-device

login.reset-password login.reset-password-complete

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Recover Username recover-username login.index!flash message

Recover Password, no OTP method. recover-password contact

Recover Password, single OTP method.

recover-password one-time-password.authenticate

login.reset-password login.reset-password-complete

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Recover Password, multiple OTP methods.

recover-password one-time-password.select-delivery-method

one-time-password.authenticate

login.reset-password login.reset-password-complete

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Login, forced OTP review, login.index one-time-password.setup?edit=true

one-time-password.register-device

login.electronic-consent?

login.terms-of-service-consent?

tour? accounts.index

Page 15: Controlling Route Traversal

Step 3: Convert Paths Into Node Graph

Page 16: Controlling Route Traversal

login

otp.select-delivery-method

otp.setup otp. authenticate

otp. register-device

accounts - or -

deep linkelectronic-

consentterms-of-service-consent

tourcomplete

Page 17: Controlling Route Traversal

Step 4: Describe Edge Traversal

Page 18: Controlling Route Traversal

login

otp.select-delivery-method

otp.setup otp. authenticate

otp. register-device

accounts - or -

deep linkelectronic-

consentterms-of-service-consent

tourcomplete

{ isIdentified: true, isAuthenticated: false, hasOneDeliveryMethod: deliveryMethods.length, }

Page 19: Controlling Route Traversal

Step 5: Identify Backwards Traversals

Page 20: Controlling Route Traversal

login

otp.select-delivery-method

otp.setup otp. authenticate

otp. register-device

accounts - or -

deep linkelectronic-

consentterms-of-service-consent

tourcomplete

Page 21: Controlling Route Traversal

Step 6: Done!

Page 22: Controlling Route Traversal

login

otp.select-delivery-method

otp.setup otp. authenticate

otp. register-device

accounts - or -

deep linkelectronic-

consentterms-of-service-consent

tourcomplete

reset-password

recover-password

reset-password-complete

Page 23: Controlling Route Traversal
Page 24: Controlling Route Traversal

A Few Important Things

Page 25: Controlling Route Traversal

http://www.flickr.com/photos/joi/8224269021

#1:

Page 26: Controlling Route Traversal

#2: Don't break the web.

Page 27: Controlling Route Traversal

#3: Ember.Router is awesome.

Page 28: Controlling Route Traversal
Page 29: Controlling Route Traversal

A Quick Demo

Page 30: Controlling Route Traversal

Playing Alonghttp://alexdiliberto.com/emberconf-2014-demo

https://github.com/alexdiliberto/emberconf-2014-demo

Page 31: Controlling Route Traversal

http://alexdiliberto.com/emberconf-2014-demo/

Page 32: Controlling Route Traversal

// Direct Login ic.ajax.defineFixture('/session', { response: { /* Successfully identified username and password. */ isIdentified: true, !

/* Related to one-time-passcode. */ willSetupOTP: false, isAuthenticated: true, !

hasElectronicConsent: true, hasTermsOfServiceConsent: true, showTour: false }, textStatus: 'success' });

Page 33: Controlling Route Traversal

// One Time Password with selection. ic.ajax.defineFixture('/session', { response: { /* Successfully identified username and password. */ isIdentified: true, !

/* Related to one-time-passcode. */ willSetupOTP: false, isAuthenticated: false, !

hasElectronicConsent: true, hasTermsOfServiceConsent: true, showTour: false }, textStatus: 'success' });

Page 34: Controlling Route Traversal
Page 35: Controlling Route Traversal

Coding a Flow

Page 36: Controlling Route Traversal

A Naive Approachgit clone https://github.com/alexdiliberto/emberconf-2014-demo git checkout tags/naive

Page 37: Controlling Route Traversal

General Strategy• Load the session state from a route-global injection.

• Reset the controller on setupController.

• Delegate identification of where to go next to the current route.

• Traverse the longest possible path through the application so that every route can identify whether or not they should be stopped at.

Page 38: Controlling Route Traversal

Inject The Session Statevar session = Ember.Object.extend(); Ember.Application.initializer({ name: 'session', initialize: function(container, app) { app.register('session:main', session); app.inject('route', 'session', 'session:main'); } });

Page 39: Controlling Route Traversal

beforeModel

beforeModel: function() { if (this.get('session.isAuthenticated')) { this.replaceWith('one-time-password.register-device'); } }

Page 40: Controlling Route Traversal

Tangent: replaceWithIt's awesome. Use it.

Page 41: Controlling Route Traversal

{{action}}

actions: { authenticate: function() { ic.ajax.raw('/authenticate').then(function(result) { if (result.response.isAuthenticated) { this.set('session.isAuthenticated', true); this.replaceWith('one-time-password.register-device'); } }); } }

Page 42: Controlling Route Traversal

An Improved ApproachThe "Using Flows" part of the presentation.

Page 43: Controlling Route Traversal

General Strategy• Define all progression in a separate location.

• Load the Flow and its state from a route-global injection.

• Rely on Alex Matchneer's new primitive for repopulating controller state?

• Delegate identification of where to go next to the Flow itself.

• Call back into the Flow to progress.

• Your flow tracks which edges you've traversed in case you need that information in your application.

Page 44: Controlling Route Traversal

Definitions

LoginFlow.addEdge({ from: 'login.index', to: 'accounts.index', weight: 1, conditions: ['isIdentified', 'isAuthenticated'] });

Page 45: Controlling Route Traversal

Inject The Login Flowvar login = Ember.Object.extend(); Ember.Application.initializer({ name: 'login', initialize: function(container, app) { app.register('flow:login', login); app.inject('route', 'login', 'flow:login'); } });

Page 46: Controlling Route Traversal

beforeModel

beforeModel: function() { // Looks up the current flow. // Identifies where the user should be. this.get('flow').check(); }

Page 47: Controlling Route Traversal

{{action}}actions: { authenticate: function() { var Flow = this.get('flow'); !

ic.ajax.raw('/authenticate').then(function(result) { if (result.response.isAuthenticated) { Flow.set('isAuthenticated', true); Flow.progress(); } }); } }

Page 48: Controlling Route Traversal

ember-flowshttps://github.com/nathanhammond/ember-flows

Page 49: Controlling Route Traversal
Page 50: Controlling Route Traversal

Resources• https://signalvnoise.com/posts/1926-a-shorthand-for-designing-ui-flows

• https://docs.google.com/spreadsheet/ccc?key=0ApnSRONV3LTVdGJuLUlnOGxzY1FadGZHN050ZVJXcWc

• http://alexdiliberto.com/emberconf-2014-demo

• https://github.com/alexdiliberto/emberconf-2014-demo

• https://github.com/nathanhammond/ember-flows

• https://code.google.com/p/libphonenumber/