project-level avatar -- don't use vertical height

--- src/smc-webapp/project_files.cjsx
+++ src/smc-webapp/project_files.cjsx
@@ -1941,7 +1941,9 @@
                     <ProjectFilesPath current_path={@props.current_path} actions={@props.actions} />
                 </Col>
                 <Col sm=3>
-                    <UsersViewing redux={@props.redux} viewing_what='project' project_id={@props.project_id} />
+                    <div style={height:0}>  {#height 0 so takes up no vertical space}
+                        <UsersViewing redux={@props.redux} viewing_what='project' project_id={@props.project_id} />
+                    </div>
                     <ProjectFilesButtons
                         show_hidden  = {@props.show_hidden ? false}
                         sort_by_time = {@props.sort_by_time ? true}


Let API consumer choose if they want a redirect

--- app/controllers/session-controller.coffee
+++ app/controllers/session-controller.coffee
@@ -26,6 +26,8 @@
       debug 'about to generateAndStoreToken', uuid: foundDevice.uuid
       @meshblu.generateAndStoreToken uuid: foundDevice.uuid, (device) =>
         debug 'got called back'
+        return response.send(device) unless callbackUrl?
+
         uriParams = url.parse callbackUrl
         uriParams.query ?= {}
         uriParams.query.uuid = device.uuid


TaggedNodeCollection: better exception feedback.

--- src/tagged_node_collection.coffee
+++ src/tagged_node_collection.coffee
@@ -1,5 +1,4 @@
 class TaggedNodeCollection
-    # TODO: take idPrefix and propName as defaulted params
     constructor : ->
         @ids = {}
         @count = 0
@@ -16,10 +15,12 @@

     # If ID is not supplied, it will be generated (the common case)
     add : (node, id) ->
+        if !node?
+            throw new Error("Trying to add null node")
         if node.__nodeID?
             if (node != @ids[node.__nodeID])
                 throw new Error("Added a node with existing __nodeID, but it
-                                 doesn't match")
+                                 doesn't match: #{node.__nodeID}")
             # We need to allow assigning a new ID to an existing node so that
             # we can re-tag an iframe's contentDocument.
             # It starts as a blank iframe with a blank document, then src gets
@@ -34,8 +35,9 @@
                 if @ids[id] == undefined
                     found = true
         else if typeof id == 'string'
-            if @ids[id] != undefined
-                throw new Error("User supplied existing ID: #{id}")
+            current = @ids[id]
+            if current && (current != node)
+                throw new Error("User supplied existing but mismatched ID: #{id}")
         else
             throw new Error("Invalid ID: #{id}")
         @count++


rename away references to votes

rename away references to votes

--- core/app/backbone/collections/interested_users.coffee
+++ core/app/backbone/collections/interested_users.coffee
@@ -9,13 +9,13 @@

   opinion_for_current_user:  ->
     return 'no_vote' unless currentSession.signedIn()
-    vote = @vote_for(window.currentSession.user().get('username'))
-    if vote
-      vote.get('type')
+    current_state = user_interest_state(currentSession.user().get('username'))
+    if current_state
+      current_state.get('type')
     else
       'no_vote'

-  vote_for: (username) ->
+  user_interest_state: (username) ->
     @find (vote) -> vote.get('username') == username

   setInterested: (is_interested) ->
@@ -23,11 +23,11 @@
     #TODO: why this guard - this shouldn't be possible, right?

     @fact.saveUnlessNew =>
-      current_vote = @vote_for(currentSession.user().get('username'))
+      current_state = user_interest_state(currentSession.user().get('username'))

-      if !is_interested && current_vote
-        current_vote.destroy()
-      else if is_interested && !current_vote
+      if !is_interested && current_state
+        current_state.destroy()
+      else if is_interested && !current_state
         @create
           username: currentSession.user().get('username')
           user: currentSession.user().attributes


GithubProvider: update provided data as objects

--- workers/social/lib/social/models/gitprovider/githubprovider.coffee
+++ workers/social/lib/social/models/gitprovider/githubprovider.coffee
@@ -62,19 +62,19 @@
         options = { user, repo, path: TEMPLATE_PATH, ref: branch }
         repos.getContent options, (err, data) ->
           return next err  if err
-          next null, helpers.decodeContent data
+          next null, { commitId: data.sha, content: helpers.decodeContent data }

       (next) ->
         options = { user, repo, path: README_PATH, ref: branch }
         repos.getContent options, (err, data) ->
           return next()  if err
-          next null, helpers.decodeContent data
+          next null, { commitId: data.sha, content: helpers.decodeContent data }
     ]

     return async.series queue, (err, results) ->
       return callback err  if err
-      [ rawContent, description ] = results
-      callback null, _.extend { rawContent, description }, urlData
+      [ template, readme ] = results
+      callback null, _.extend { template, readme }, urlData

   importStackTemplateWithRawUrl: (urlData, callback) ->
@@ -88,7 +88,8 @@
           host   : RAW_GITHUB_HOST
           path   : "/#{user}/#{repo}/#{branch}/#{TEMPLATE_PATH}"
           method : 'GET'
-        helpers.loadRawContent options, next
+        helpers.loadRawContent options, (err, template) ->
+          next null, { content: template }

       (next) ->
         options =
@@ -96,10 +97,10 @@
           path   : "/#{user}/#{repo}/#{branch}/#{README_PATH}"
           method : 'GET'
         helpers.loadRawContent options, (err, readme) ->
-          next null, readme
+          next null, { content: readme }
       ]

     return async.series queue, (err, results) ->
       return callback err  if err
-      [ rawContent, description ] = results
-      callback null, _.extend { rawContent, description }, urlData
+      [ template, readme ] = results
+      callback null, _.extend { template, readme }, urlData


Slider Component: Codefixes

Slider Component: Codefixes

--- client/Framework/components/sliderbar/KDSliderBarView.coffee
+++ client/Framework/components/sliderbar/KDSliderBarView.coffee
@@ -1,5 +1,6 @@
 class KDSliderBarView extends KDCustomHTMLView
   constructor:(options = {}, data = {})->
+
     options.cssClass    = KD.utils.curryCssClass "sliderbar-container", options.cssClass
     options.minValue   ?= 0
     options.maxValue   ?= 100
@@ -15,10 +16,8 @@
     @labels             = []

   createHandles:->
-    for k, v of @getData().handles
-      @handles.push @addSubView handle = new KDSliderBarHandleView
-          name : k
-        , value: v.value
+    for name, {value} of @getData().handles
+      @handles.push @addSubView handle = new KDSliderBarHandleView {name}, {value}

     sortRef = (a,b) ->
       return -1 if a.getData().value < b.getData().value
@@ -28,31 +27,29 @@

   drawBar:->
     positions = []
-    for i in @handles
-      positions.push i.getPosition()
+    for handle in @handles
+      positions.push handle.getPosition()

     len    = positions.length
-    left   = (positions[0] if len>1) || 0
-    right  = positions[len-1]
+    left   = (positions.first if len>1) or 0
+    right  = positions.last
     diff   = right - left

-    if !@bar
+    unless @bar
       @addSubView @bar = new KDCustomHTMLView
         cssClass : "bar"
     @bar.setWidth diff, "%"
     @bar.setX "#{left}%"

   addLabels:->
-    maxValue = @getOption('maxValue')
-    minValue = @getOption('minValue')
-    interval = @getOption('interval')
+    {maxValue, minValue, interval} = @getOptions()

-    for v in [minValue..maxValue] by interval
-      pos = ((v-minValue)*100)/(maxValue-minValue)
+    for value in [minValue..maxValue] by interval
+      pos = ((value-minValue)*100)/(maxValue-minValue)

       @labels.push @addSubView label = new KDCustomHTMLView
         cssClass    : "sliderbar-label"
-        partial     : "#{v}"
+        partial     : "#{value}"

       label.setX "#{pos}%"

@@ -60,40 +57,41 @@
     if handleName?
       return @getHandle(handleName)?.getData().value

-    else if @handles.length == 1
-      return @handles[0].getData().value
+    else if @handles.length is 1
+      return @handles.first.getData().value

     else
       values = []
-      for i in @handles
-        values.push i.getData().value
+      for handle in @handles
+        values.push handle.getData().value
       return values

   getHandle:(name)->
     if name?
-      for i in @handles
-        return i if i.getOption('name') == name
+      for handle in @handles
+        return handle if handle.getOption('name') is name
       return console.error "Can't find a handle named #{name}"

   setLimits:->
-    maxValue = @getOption('maxValue')
-    minValue = @getOption('minValue')
-    interval = @getOption("interval")
+    {maxValue, minValue, interval} = @getOptions()

     if @handles.length is 1
-      @handles[0].leftLimit   = @getOption('minValue')
-      @handles[0].rightLimit  = @getOption('maxValue')
+      @handles.first.leftLimit     = minValue
+      @handles.first.rightLimit    = maxValue
     else
-      for h in @handles
-        i = @handles.indexOf(h)
-        h.data.leftLimit  = @handles[i-1]?.getData().value + interval || minValue
-        h.data.rightLimit = @handles[i+1]?.getData().value - interval || maxValue
+      for handle in @handles
+        i    = @handles.indexOf(handle)
+        data = handle.data
+
+        data.leftLimit  = @handles[i-1]?.getData().value + interval or minValue
+        data.rightLimit = @handles[i+1]?.getData().value - interval or maxValue

   viewAppended:->
     @createHandles()
     @setLimits()
     @drawBar()   if @getOption('drawBar')
     @addLabels() if @getOption('showLabels')
+    window.asd = @

 class KDSliderBarHandleView extends KDCustomHTMLView
   constructor:(options = {}, data = {})->
@@ -104,9 +102,8 @@
     super options, data

   attachEvents:->
-    maxValue         = @parent.getOption('maxValue')
-    minValue         = @parent.getOption('minValue')
-    windowController = KD.getSingleton "windowController"
+    {maxValue, minValue} = @parent.getOptions()
+    windowController     = KD.getSingleton "windowController"

     @on "mousedown", ->
       @parent.bindEvent "mousemove"
@@ -125,15 +122,13 @@
       @snap() if @parent.getOption "snap"

   getPosition:->
-    maxValue = @parent.getOption('maxValue')
-    minValue = @parent.getOption('minValue')
-    value    = @getData().value
+    {maxValue, minValue} = @parent.getOptions()
+    {value}              = @getData()

     return ((value-minValue)*100)/(maxValue-minValue)

   setValue:(value)->
-    leftLimit     = @getData().leftLimit
-    rightLimit    = @getData().rightLimit
+    {leftLimit, rightLimit} = @getData()

     if !(value<leftLimit) and !(value>rightLimit)
       @data.value = value
@@ -149,8 +144,8 @@
     @setX "#{@getPosition()}%"

   getSnappedValue:->
-    interval = @parent.getOption('interval')
-    value    = @getData().value
+    {interval}  = @parent.getOptions()
+    {value}     = @getData()

     if interval isnt no
       mod = value%interval
@@ -162,8 +157,8 @@
         else value

   snap:->
-    interval = @parent.getOption "interval"
-    value    = @getSnappedValue()
+    {interval}  = @parent.getOptions()
+    value       = @getSnappedValue()

     if interval isnt no and @parent.getOption "snap"
       @setValue value


広告の背景色を指定

広告の背景色を指定

--- app/assets/javascripts/components/adsense/google_adsense_ins.js.cjsx
+++ app/assets/javascripts/components/adsense/google_adsense_ins.js.cjsx
@@ -3,9 +3,11 @@
     super

   render: ->
+    style = $.extend true, {}, @props.style
+    style['backgroundColor'] = 'white'
     <ins
       className={'adsbygoogle ' + @props.className}
-      style={@props.style}
+      style={style}
       data-ad-client={@props.client}
       data-ad-slot={@props.slot}
       data-ad-format={@props.format}
@@ -17,4 +19,3 @@
   className: React.PropTypes.string.isRequired
   style: React.PropTypes.object.isRequired
   format: React.PropTypes.string
-      # style={display: 'block', backgroundColor: 'white'}


Fixed selection for new API

Fixed selection for new API

--- app/assets/javascripts/components/kid_mentor_schedules.js.jsx.coffee
+++ app/assets/javascripts/components/kid_mentor_schedules.js.jsx.coffee
@@ -168,12 +168,8 @@

 MentorsForDisplayingFilter = createReactClass
   DELEMITER: ";"
-  onChange: (valuesAsString) ->
-    if valuesAsString? and valuesAsString.length > 0
-      values = valuesAsString.split(@DELEMITER).map (id) -> parseInt id, 10
-      selectedMentorIds = limitAndRemoveFromBeginning values
-    else
-      selectedMentorIds = []
+  onChange: (values) ->
+    selectedMentorIds = limitAndRemoveFromBeginning(values.map((m) -> Number(m.value)))
     @triggerChange selectedMentorIds

   triggerChange: (selectedMentorIds) ->


adding in class name for multiple choice prompt for fred

--- src/components/task-step/exercise-multiple-choice.cjsx
+++ src/components/task-step/exercise-multiple-choice.cjsx
@@ -53,7 +53,7 @@

     <Question model={question} answer_id={answer_id} correct_answer_id={correct_answer_id} feedback_html={feedback_html} onChange={@onAnswerChanged}>

{free_response}

-
Choose the best answer from the following:

+
Choose the best answer from the following:

     </Question>

   onAnswerChanged: (answer) ->


clean up old debug variable

clean up old debug variable

--- lib/mixins/view-management.coffee
+++ lib/mixins/view-management.coffee
@@ -54,7 +54,7 @@
     # the callback.
     @eachPaneViewSubscription = atom.workspaceView.eachPaneView (paneView) =>
       paneId = paneView.model.id
-      view = new MinimapView(paneView, @allowDebug)
+      view = new MinimapView(paneView)
       view.onActiveItemChanged(paneView.getActiveItem())
       @updateAllViews()


fix p cursor position

fix p cursor position

--- lib/operators/put-operator.coffee
+++ lib/operators/put-operator.coffee
@@ -58,9 +58,9 @@
       @editor.setCursorScreenPosition(originalPosition)
       @editor.moveToFirstCharacterOfLine()

-    @vimState.activateNormalMode()
     if type isnt 'linewise'
       @editor.moveLeft()
+    @vimState.activateNormalMode()

   # Private: Helper to determine if the editor is currently on the last row.
   #


Updated comment text per design

Updated comment text per design

--- core/app/backbone/views/evidence/evidence_bottom_view.coffee
+++ core/app/backbone/views/evidence/evidence_bottom_view.coffee
@@ -18,10 +18,13 @@
   updateSubCommentsLink: ->
     count = @model.get('sub_comments_count')

-    if count > 0
-      @ui.subCommentsLink.text "Comments (#{count})"
-    else
-      @ui.subCommentsLink.text "Comments"
+    switch count
+      when 0
+        @ui.subCommentsLink.text "Comment"
+      when 1
+        @ui.subCommentsLink.text "1 comment"
+      else
+        @ui.subCommentsLink.text "#{count} comments"

     if Factlink.Global.signed_in or count > 0
       @showSubCommentsLink()


reset widget problem fixed

reset widget problem fixed

--- client/app/Applications/Activity.kdapplication/views/embedbox.coffee
+++ client/app/Applications/Activity.kdapplication/views/embedbox.coffee
@@ -109,10 +109,10 @@
             $(element).removeAttr "data-src"
           element

-  refreshEmbed:=>
+  refreshEmbed:->
     @populateEmbed @getEmbedData(), @embedURL, {}, @getEmbedCache()

-  resetEmbedAndHide:=>
+  resetEmbedAndHide:->
     @resetEmbed()

     # these resets concern the whole box, not just the embed currently
@@ -120,9 +120,10 @@
     @embedLinks.clearLinks()
     @setEmbedCache []

+    @hasValidContent = no
     @hide()

-  resetEmbed:=>
+  resetEmbed:->
     @clearEmbed()

     # these resets only concern the currently displayed embed
@@ -131,11 +132,11 @@
     @setEmbedHiddenItems []
     @setEmbedImageIndex 0

-  clearEmbed:=>
+  clearEmbed:->
     # here them embed can be prepared for population
     # @$("div.embed").html ""

-  clearEmbedAndHide:=>
+  clearEmbedAndHide:->
     @clearEmbed()
     @hide()

@@ -169,19 +170,19 @@
     else
       @embedData

-  getEmbedURL:=>
+  getEmbedURL:->
     @embedURL

-  getEmbedCache:=>
+  getEmbedCache:->
     @embedCache

-  getEmbedImageIndex:=>
+  getEmbedImageIndex:->
     @embedImageIndex

-  getEmbedHiddenItems:=>
+  getEmbedHiddenItems:->
     @embedHiddenItems

-  setEmbedCache:(cache)=>
+  setEmbedCache:(cache)->
     unless @embedCache? then @embedCache = []
     for item in cache
       unless item in @embedCache
@@ -189,7 +190,7 @@
           @embedCache.push item
     @embedCache = _.uniq @embedCache

-  setEmbedData:(data)=>
+  setEmbedData:(data)->
     isChached = no
     for embed in @embedCache
       if data.url is embed.url then isCached = yes
@@ -197,27 +198,27 @@
       @embedCache.push data
     @embedData = data

-  setEmbedURL:(url)=>
+  setEmbedURL:(url)->
     @embedURL = url

-  setEmbedHiddenItems:(ehi)=>
+  setEmbedHiddenItems:(ehi)->
     @embedHiddenItems = ehi

-  setEmbedImageIndex:(i)=>
+  setEmbedImageIndex:(i)->
     @embedImageIndex = i

-  addEmbedHiddenItem:(item)=>
+  addEmbedHiddenItem:(item)->
     if not (item in @embedHiddenItems) then @embedHiddenItems.push item

-  removeEmbedHiddenItem:(item)=>
+  removeEmbedHiddenItem:(item)->
     if (item in @getEmbedHiddenItems()) then delete @embedHiddenItems[@embedHiddenItems.indexOf item]

-  getRichEmbedWhitelist:=>
+  getRichEmbedWhitelist:->
     [
       "SoundCloud"
     ]

-  fetchEmbed:(url="#",options={},callback=noop)=>
+  fetchEmbed:(url="#",options={},callback=noop)->

     # if there is no protocol, supply one! embedly doesn't support //
     unless /^(ht|f)tp(s?)\:\/\//.test url then url = "http://"+url
@@ -252,7 +253,7 @@
     #     @setEmbedURL url
     #     callback oembed,embedlyOptions

-  populateEmbed:(data={},url="#",options={},cache=[])=>
+  populateEmbed:(data={},url="#",options={},cache=[])->
     @setEmbedData data
     @setEmbedURL url
     @setEmbedCache cache unless cache is []
@@ -410,7 +411,7 @@
             # unless link.favicon is item.favicon_url

-  embedExistingData:(data={},options={},callback=noop,cache=[])=>
+  embedExistingData:(data={},options={},callback=noop,cache=[])->
     unless data.type is "error"

       @clearEmbed()
@@ -426,7 +427,7 @@
       @hide() unless @options.hasConfig
       callback no

-  embedUrl:(url,options={},callback=noop)=>
+  embedUrl:(url,options={},callback=noop)->

     # Checking if we have the URL in cached data before requesting it from embedly


View droppable attribute is optional.

View droppable attribute is optional.

--- client/app/lib/commonviews/applicationview/applicationtabview.coffee
+++ client/app/lib/commonviews/applicationview/applicationtabview.coffee
@@ -8,10 +8,12 @@

     options.resizeTabHandles            ?= yes
     options.lastTabHandleMargin         ?= 80
-    options.sortable                    ?= yes
     options.closeAppWhenAllTabsClosed   ?= yes
     options.enableMoveTabHandle         ?= no
     options.detachPanes                 ?= no
+    options.sortable                    ?= yes
+    options.droppable                   ?= yes
+
     options.cssClass = kd.utils.curry 'application-tabview', options.cssClass

     super options, data


Removing unnecessary webterm options - https://app.asana.com/0/3716548652471/7508318293081

--- client/landing/app/Applications/WebTerm.kdapplication/AppView.coffee
+++ client/landing/app/Applications/WebTerm.kdapplication/AppView.coffee
@@ -15,7 +15,7 @@

     @terminal = new WebTerm.Terminal @container.$()
     KD.track "userOpenedTerminal", KD.getSingleton("groupsController").getCurrentGroup()
-    @options.advancedSettings ?= yes
+    @options.advancedSettings ?= no
     if @options.advancedSettings
       @advancedSettings = new KDButtonViewWithMenu
         style         : 'editor-advanced-settings-menu'


Add alias for where method in collections

--- app/assets/javascripts/action_cable_notifications/collection.coffee
+++ app/assets/javascripts/action_cable_notifications/collection.coffee
@@ -67,6 +67,9 @@
       @callbacks.where.call(this, selector)
     else
       _.filter(@data, selector)
+
+  filter: (selector={}) ->
+    @where(selector)

   # Find a record
   find: (selector={}, options={}) ->


Re-add SSL checkboxes with name ssl_required

Summary:
Now that IMAP auth without SSL is enabled,
those checkboxes that weren't doing anything can come
back.

Test Plan:
This change isn't fully tested and should be thoroughly
inspected (on staging?) before rollout. The N1 end works and sends
parameters correctly, but a 401 prevented local testing of the
interface between N1 auth and sync-engine auth.

Reviewers: bengotow, drew

Reviewed By: drew

Subscribers: kav-ya

Maniphest Tasks: T6666

Differential Revision: https://phab.nylas.com/D2632

--- internal_packages/onboarding/lib/account-types.coffee
+++ internal_packages/onboarding/lib/account-types.coffee
@@ -200,6 +200,13 @@
         format: 'integer'
         page: 1
       }, {
+        name: 'ssl_required'
+        type: 'checkbox'
+        label: 'Require SSL'
+        className: 'half'
+        default: true
+        page: 1
+      }, {
         name: 'imap_username'
         type: 'text'
         placeholder: 'Username'
@@ -229,6 +236,13 @@
         className: 'half'
         format: 'integer'
         default: 587
+        page: 2
+      }, {
+        name: 'ssl_required'
+        type: 'checkbox'
+        label: 'Require SSL'
+        className: 'half'
+        default: true
         page: 2
       }, {
         name: 'smtp_username'


fix(onboarding): Check code format before hitting API

--- internal_packages/onboarding/lib/token-auth-page.cjsx
+++ internal_packages/onboarding/lib/token-auth-page.cjsx
@@ -123,10 +123,10 @@
     if @state.tokenAuthInflight
       return

-    if not @state.token
+    if not @state.token or not /^[\w]{32}$/.test(@state.token)
       @setState({
         tokenAuthInflight: false,
-        tokenValidityError: "Please enter an invitation code."
+        tokenValidityError: "Please enter a valid invitation code."
       })
       @_resize()
       return


disable quick render for from_url due to cdn required

--- app/assets/javascripts/uploadcare/widget/tabs/preview-tab.js.coffee
+++ app/assets/javascripts/uploadcare/widget/tabs/preview-tab.js.coffee
@@ -38,11 +38,6 @@

       @file.fail ifCur (error) =>
         @__setState 'error', {error}
-
-      @file.progress ifCur (progressInfo) ->
-        info = progressInfo.incompleteFileInfo
-        if info.isImage? and info.originalUrl?
-          stateKnown info

     # error
     # unknown


show welcome page in first login

show welcome page in first login

--- client/app/MainApp/login/loginview.coffee
+++ client/app/MainApp/login/loginview.coffee
@@ -174,7 +174,7 @@
       if pages.length is 0
         pages.push "table-of-contents"
         appStorage.setValue "readPages", pages
-        KD.getSingleton('mainController').emit "ShowInstructionsBook"
+        KD.getSingleton('mainController').emit "ShowInstructionsBook", 1


Fix syntax error

Fix syntax error

--- client/app/components/message-list.coffee
+++ client/app/components/message-list.coffee
@@ -85,8 +85,7 @@

     # for SelectionManagerMixin
     getSelectables: ->
-        @state.messages.map (message) ->
-            message.get('id'): message
+        @state.messages.map (message) -> message.get('id')

     getEmptyListMessage: ->
         return @props.emptyListMessage if @props.emptyListMessage


invitations: switch handler order so there's no flicker between transitions

--- client/landing/Login/AppController.coffee
+++ client/landing/Login/AppController.coffee
@@ -16,29 +16,26 @@
         app.getView().animateToForm('reset')

   handleFailureOfRestriction =->
-    new KDNotificationView title: "Login restricted"
+    KD.utils.defer -> new KDNotificationView title: "Login restricted"

-    KD.introView = new IntroView
-    KD.introView.appendToDomBody()
-    KD.introView.setClass 'in'
+  handleRestriction = (handler) ->
+    ({params: {token : token }})->
+      return handleFailureOfRestriction()  unless token

-  handleRestriction = ({token}, callback)->
-    return handleFailureOfRestriction()  unless token
+      KD.remote.api.JInvitation.byCode token, (err, invite)->
+        if err or !invite?
+          return handleFailureOfRestriction()  unless token

-    KD.remote.api.JInvitation.byCode token, (err, invite)->
-      if err or !invite?
-        return handleFailureOfRestriction()  unless token
-
-      callback()
+        do handler()

   KD.registerAppClass this,
     name                         : "Login"
     routes                       :
-      '/:name?/Login/:token?'    : handler (app, params)->
-          handleRestriction params, -> app.getView().animateToForm 'login'
+      '/:name?/Login/:token?'    : handleRestriction (app)->
+          handler (app)-> app.getView().animateToForm 'register'
       '/:name?/Redeem'           : handler (app)-> app.getView().animateToForm 'redeem'
-      '/:name?/Register/:token?' : handler (app, params)->
-          handleRestriction params, -> app.getView().animateToForm 'register'
+      '/:name?/Register/:token?' : handleRestriction (app)->
+          handler (app)-> app.getView().animateToForm 'register'
       '/:name?/Recover'          : handler (app)-> app.getView().animateToForm 'recover'
       '/:name?/Reset'            : handler (app)-> app.getView().animateToForm 'reset'
       '/:name?/Reset/:token'     : handleResetRoute