#1308 - Expanded question can't be moved easily to new position

--- jsapp/xlform_model_view/view.surveyApp.coffee
+++ jsapp/xlform_model_view/view.surveyApp.coffee
@@ -382,6 +382,7 @@
         ui.item.find('.survey__row__item').removeClass 'card--expandedsettings'
         ui.item.find('.survey__row__item').removeClass 'group--expanded-settings'

+        ui.helper.height '73'
         $el.toggleClass 'insort', isActivateEvt

       sortable_stop = (evt, ui)=>


Revert test topic

Revert test topic

--- spec/Component.coffee
+++ spec/Component.coffee
@@ -209,7 +209,7 @@
       chai.expect(c.started).to.equal(false)
       chai.expect(c.isStarted()).to.equal(false)

-  describe '-based IPs', ->
+  describe 'with object-based IPs', ->

     it 'should speak IP objects', (done) ->
       c = new component.Component


close #80

close #80

--- src/client/app_admin.coffee
+++ src/client/app_admin.coffee
@@ -164,3 +164,11 @@

 @LogCtrl = ($scope, $log)->
   $scope.$log = $log
+
+#  document on load:
+$(->
+  $(document).keydown((e)->
+    if e.keyCode == 8 and e.target.tagName.toUpperCase() != 'INPUT'
+      e.preventDefault()
+  )
+)


Removes yet another log message

Removes yet another log message

--- src/client/component.coffee
+++ src/client/component.coffee
@@ -88,7 +88,7 @@
           @render()
           @sandbox.on(refreshOn, (=> @refresh()), @) for refreshOn in (@refreshEvents || [])
         , @), (err)->
-          throw new Error 'unable to load template:' + err
+          # Already displays a log in Aura and is caught above

       renderTemplate: (tpl, data)=>
         _tpl = @_templates?[tpl]


Resolve relative urls in window.open, fix #2166

--- atom/renderer/lib/override.coffee
+++ atom/renderer/lib/override.coffee
@@ -1,6 +1,12 @@
 process = global.process
 ipc = require 'ipc'
 remote = require 'remote'
+
+# Helper function to resolve relative url.
+a = document.createElement 'a'
+resolveUrl = (url) ->
+  a.href = url
+  a.href

 # Window object returned by "window.open".
 class BrowserWindowProxy
@@ -48,6 +54,9 @@
   options.title ?= frameName
   options.width ?= 800
   options.height ?= 600
+
+  # Resolve relative urls.
+  url = resolveUrl url

   (options[name] = parseInt(options[name], 10) if options[name]?) for name in ints


tweak

tweak

--- spec/juno-spec.coffee
+++ spec/juno-spec.coffee
@@ -1,3 +1,4 @@
+path = require 'path'
 juno = require '../lib/julia-client'

 # Testing-specific settings
@@ -25,7 +26,6 @@
   client.onDisconnected (disconnectSpy = jasmine.createSpy 'disconnect')

   describe "before booting", ->
-    path = require 'path'
     checkPath = (p) -> juno.misc.paths.getVersion p

     it "can validate an existing julia binary", ->


Adjust formatting

Adjust formatting

--- src/coffee/xmlimport.coffee
+++ src/coffee/xmlimport.coffee
@@ -107,23 +107,23 @@
 exports.XmlImport.prototype.mapAttributes = (row, j)->
   j.attributes = []
   attribs =
-    uid: '',
-    size: '',
-    codeMaterial: '',
-    descriptionMaterial: '',
-    codecolorname: 'codeColorname',
-    descriptionColorname: '',
-    codeFilterColor: '',
-    descriptionFilterColor: '',
-    codeStyle: '',
-    descriptionFilterStyle: '',
-    codeFabrication: '',
-    descriptionFabrication: '',
-    CodeSerie: 'codeSerie',
-    descriptionSerie: '',
-# TODO    codeCareinstruction: '',
-# TODO    descriptionCareinstruction: '',
-    Theme: 'theme',
+    uid: ''
+    size: ''
+    codeMaterial: ''
+    descriptionMaterial: ''
+    codecolorname: 'codeColorname'
+    descriptionColorname: ''
+    codeFilterColor: ''
+    descriptionFilterColor: ''
+    codeStyle: ''
+    descriptionFilterStyle: ''
+    codeFabrication: ''
+    descriptionFabrication: ''
+    CodeSerie: 'codeSerie'
+    descriptionSerie: ''
+# TODO    codeCareinstruction: ''
+# TODO    descriptionCareinstruction: ''
+    Theme: 'theme'
     ean: ''

   for orig, trans of attribs
@@ -131,7 +131,7 @@
     v = @val(row, orig, '')
     continue unless v.length > 0
     d =
-      name: trans,
+      name: trans
       value: v
     j.attributes.push d

@@ -145,9 +145,9 @@
     j.attributes.push d

   enums =
-    bulkygoods: '',
-    specialpriceflag: 'salesprice',
-# TODO    discountable: 'discountable',
+    bulkygoods: ''
+    specialpriceflag: 'salesprice'
+# TODO    discountable: 'discountable'
     Highlight: 'highlighted'

   for orig,trans of enums
@@ -155,7 +155,7 @@
     v = 'NO'
     v = 'YES' if @val(row, orig, '') == '1'
     d =
-      name: trans,
+      name: trans
       value: v
     j.attributes.push d

@@ -183,7 +183,7 @@
   p =
     value:
       centAmount: parseInt @val(row, 'specialprice', ''), 10
-      currencyCode: currency,
+      currencyCode: currency
     country: country
   j.prices.push p

@@ -194,7 +194,7 @@
     return false
   true

-exports.XmlImport.prototype.productType =->
+exports.XmlImport.prototype.productType = ->
   deferred = Q.defer()
   @rest.GET "/product-types", (error, response, body)->
     #console.log("PT: %j", body)
@@ -202,7 +202,7 @@
     deferred.resolve id
   deferred.promise

-exports.XmlImport.prototype.taxCategory =->
+exports.XmlImport.prototype.taxCategory = ->
   deferred = Q.defer()
   @rest.GET "/tax-categories", (error, response, body)->
     #console.log("TC: %j", body)
@@ -210,7 +210,7 @@
     deferred.resolve id
   deferred.promise

-exports.XmlImport.prototype.customerGroup =->
+exports.XmlImport.prototype.customerGroup = ->
   deferred = Q.defer()
   @rest.GET "/customer-groups", (error, response, body)->
     id = JSON.parse(body).results[0].id


Use TextEditor.isDestroyed() instead of .destroyed in specs

--- spec/tabs-spec.coffee
+++ spec/tabs-spec.coffee
@@ -281,7 +281,7 @@

       expect(pane.getItems().length).toBe 2
       expect(pane.getItems().indexOf(editor1)).toBe -1
-      expect(editor1.destroyed).toBeTruthy()
+      expect(editor1.isDestroyed()).toBeTruthy()
       expect(tabBar.getTabs().length).toBe 2
       expect(tabBar.element.textContent).not.toMatch('sample.js')

@@ -309,7 +309,7 @@
       tabBar.tabForItem(editor1).element.querySelector('.close-icon').click()
       expect(pane.getItems().length).toBe 2
       expect(pane.getItems().indexOf(editor1)).toBe -1
-      expect(editor1.destroyed).toBeTruthy()
+      expect(editor1.isDestroyed()).toBeTruthy()
       expect(tabBar.getTabs().length).toBe 2
       expect(tabBar.element.textContent).not.toMatch('sample.js')


Make tests run with promise and non-promise package deactivate

--- spec/tabs-spec.coffee
+++ spec/tabs-spec.coffee
@@ -51,13 +51,16 @@
       expect(centerElement.querySelectorAll('.pane').length).toBe 2
       expect(centerElement.querySelectorAll('.pane > .tab-bar').length).toBe 2

-      atom.packages.deactivatePackage('tabs')
-      expect(centerElement.querySelectorAll('.pane').length).toBe 2
-      expect(centerElement.querySelectorAll('.pane > .tab-bar').length).toBe 0
-
-      pane.splitRight()
-      expect(centerElement.querySelectorAll('.pane').length).toBe 3
-      expect(centerElement.querySelectorAll('.pane > .tab-bar').length).toBe 0
+      waitsForPromise ->
+        Promise.resolve(atom.packages.deactivatePackage('tabs')) # Wrapped so works with Promise & non-Promise deactivate
+
+      runs ->
+        expect(centerElement.querySelectorAll('.pane').length).toBe 2
+        expect(centerElement.querySelectorAll('.pane > .tab-bar').length).toBe 0
+
+        pane.splitRight()
+        expect(centerElement.querySelectorAll('.pane').length).toBe 3
+        expect(centerElement.querySelectorAll('.pane > .tab-bar').length).toBe 0

 describe "TabBarView", ->
   [deserializerDisposable, item1, item2, editor1, pane, tabBar] = []


fix failing test

fix failing test

--- spec/tabs-spec.coffee
+++ spec/tabs-spec.coffee
@@ -4,7 +4,8 @@
 TabBarView = require '../lib/tab-bar-view'
 layout = require '../lib/layout'
 main = require '../lib/main'
-{triggerMouseEvent, triggerClickEvent, buildDragEvents, buildDragEnterLeaveEvents, buildWheelEvent, buildWheelPlusShiftEvent} = require "./event-helpers"
+{triggerMouseEvent, triggerClickEvent, buildDragEvents, buildDragEnterLeaveEvents, buildWheelEvent, buildWheelPlusShiftEvent} = require "./event-helpers.coffee"
+{buildDragEnterLeaveEvents} = require "./event-helpers"

 describe "Tabs package main", ->
   centerElement = null


transport: Test for connecting different queues together

Currently failing

--- spec/transport.coffee
+++ spec/transport.coffee
@@ -91,3 +91,29 @@
                   chai.expect(err).to.be.a 'null'
                 sender.sendToQueue sharedQueue, payload, (err) ->
                   chai.expect(err).to.be.a 'null'
+
+
+      describe 'outqueue bound to inqueue', ->
+        it 'sending to inqueue, show up on outqueue', (done) ->
+          sender = transport.getClient address
+          receiver = transport.getClient address
+          payload = { foo: 'bar99' }
+          inQueue = 'inqueue23'
+          outQueue = 'outqueue32'
+          onReceive = (msg) ->
+            chai.expect(msg).to.include.keys 'data'
+            chai.expect(msg.data).to.eql payload
+            done()
+          connectAll [sender, receiver], (err) ->
+            receiver.createQueue 'inqueue', inQueue, (err) ->
+              chai.expect(err).to.be.a 'null'
+              sender.createQueue 'outqueue', outQueue, (err) ->
+                chai.expect(err).to.be.a 'null'
+
+              broker.bindQueue outQueue, inQueue, (err) ->
+                chai.expect(err).to.be.a 'null'
+
+                receiver.subscribeToQueue inQueue, onReceive, (err) ->
+                  chai.expect(err).to.be.a 'null'
+                sender.sendToQueue outQueue, payload, (err) ->
+                  chai.expect(err).to.be.a 'null'


Fixed selector.

Fixed selector.

--- src/common/FileUtils.coffee
+++ src/common/FileUtils.coffee
@@ -125,7 +125,7 @@
         selector = {'original.name': name, 'original.size': size}
       else if url?
         selector = {'original.url': url}
-      if selector then collection.findOne()
+      if selector then collection.findOne(selector)

     getFileStats: (file) ->
       if Paths.isUrl(file)


Reducing number of sends / replies (append to single string instead)

--- src/mail.coffee
+++ src/mail.coffee
@@ -28,8 +28,10 @@
     DeliverMail = (ctx) ->
         recipient = ctx.message.user.name.toLowerCase()
         if mails = GetMail()[recipient]
+            response = ""
             for mail in mails
-                ctx.reply "[From #{mail[0]}, #{moment.unix(mail[1]).fromNow()}] #{mail[2]}"
+                response += "[From #{mail[0]}, #{moment.unix(mail[1]).fromNow()}] #{mail[2]} \n"
+            ctx.reply response
             delete GetMail()[recipient]
             robot.brain.save()


Expose SetStore and IndexedSetStore

Expose SetStore and IndexedSetStore

--- src/main.coffee
+++ src/main.coffee
@@ -2,6 +2,8 @@
 ActionCreator    = require './action-creator'
 Store            = require './store'
 EntityStore      = require './entity-store'
+SetStore         = require './set-store'
+IndexedSetStore  = require './indexed-set-store'
 ListStore        = require './list-store'
 IndexedListStore = require './indexed-list-store'
 invariant        = require './invariant'
@@ -11,6 +13,8 @@
 	ActionCreator
 	Store
 	EntityStore
+	SetStore
+	IndexedSetStore
 	ListStore
 	IndexedListStore
 	invariant


Set default to 0 points

Set default to 0 points

--- src/components/Enemy.coffee
+++ src/components/Enemy.coffee
@@ -4,8 +4,8 @@
   init: ->
     @requires '2D, WebGL, Collision, Tween, Choreography, Hideable, Flipable, Scalable, SunBlock, Hostile'
     @attr
-      pointsOnHit: 10
-      pointsOnDestroy: 50
+      pointsOnHit: 0
+      pointsOnDestroy: 0
       damage: 2
     @invincible = no
     @bind 'HitFlash', @applyHitFlash


fixed coffeelint errors on workers/social/lib/social/models/payment/token.coffee

--- workers/social/lib/social/models/payment/token.coffee
+++ workers/social/lib/social/models/payment/token.coffee
@@ -1,8 +1,8 @@
-{Module} = require 'jraphical'
+{ Module } = require 'jraphical'

 module.exports = class JPaymentToken extends Module

-  {secure, signature}    = require 'bongo'
+  { secure, signature }    = require 'bongo'
   crypto      = require 'crypto'

   Emailer     = require '../../emailer'
@@ -29,14 +29,14 @@
         type      : Date
         default   : -> new Date

-  @checkToken = secure ({connection:{delegate}}, data, callback)->
+  @checkToken = secure ({ connection:{ delegate } }, data, callback) ->
     # CAUTION: we do not ask for nor validate token for now
     return callback yes

     @one
       userCode: delegate.profile.nickname
       planCode: data.planCode
-    , (err, token)->
+    , (err, token) ->
       return callback err  if err
       return callback new KodingError 'Token not found!'  unless token
       token.tries ?= 0
@@ -46,17 +46,17 @@
         callback null
       else
         token.tries++
-        token.save (err)->
+        token.save (err) ->
           return callback err  if err
           return callback new KodingError 'Incorrect PIN'

-  @createToken = secure (client, data, callback)->
-    {delegate} = client.connection
+  @createToken = secure (client, data, callback) ->
+    { delegate } = client.connection

     @one
       userCode: delegate.profile.nickname
       planCode: data.planCode
-    , (err, token)=>
+    , (err, token) ->
       pin = Math.floor Math.random() * 10001

       # Create entry if necessary
@@ -71,9 +71,9 @@

       # Send email
       # TODO: use emailSender (with Koding template)
-      token.save (err)->
+      token.save (err) ->
         return callback err  if err
-        JUser.fetchUser client, (e, r)->
+        JUser.fetchUser client, (e, r) ->
           email     = r.email
           firstName = delegate.profile.firstName

@@ -100,8 +100,10 @@

 class PINExistsError extends Error

-  constructor:(message)->
+  constructor:(message) ->
     return new PINExistsError(message)  unless this instanceof PINExistsError
     Error.call this
     @message = message
     @name    = 'PINExistsError'
+
+


Save mandatory Recurly account information

--- workers/social/lib/social/models/recurly/index.coffee
+++ workers/social/lib/social/models/recurly/index.coffee
@@ -198,12 +198,16 @@
   subscribeGroup: (group, data, callback)->
     data.quantity   ?= 1
     data.accountCode = "group_#{group.slug}"
+    data.email       = "group@example.com"
     data.plan        = @code
+    data.firstName   = "Group"
+    data.lastName    = group.title

     payment.addSubscriptionAndAccount data, (err, result)->
+      console.log result
       return callback err  if err
       sub = new JRecurlySubscription
-        planCode : result.code
+        planCode : result.plan
         userCode : data.accountCode
         uuid     : result.uuid
         quantity : result.quantity


reduced complexity in rewards model

reduced complexity in rewards model

--- workers/social/lib/social/models/rewards/index.coffee
+++ workers/social/lib/social/models/rewards/index.coffee
@@ -112,6 +112,73 @@
       callback null, res[0]?.total ? 0

+  fetchReferrer = (account, callback) ->
+
+    unless referrerUsername = account.referrerUsername
+      return callback null # User doesn't have any referrer
+
+    # get referrer
+    JAccount.one { 'profile.nickname': referrerUsername }, (err, referrer) ->
+
+      return callback err  if err
+
+      unless referrer
+        # if referrer not fonud then do nothing and return
+        return callback null # Referrer couldn't found
+
+      callback null, referrer
+
+
+  confirmRewards = (source, target, callback) ->
+
+    JReward.update
+      providedBy : source.getId()
+      originId   : target.getId()
+    ,
+      $set       : { confirmed : yes }
+    , (err) ->
+      return callback err  if err?
+
+      options = { originId: target.getId() }
+      JReward.calculateAndUpdateEarnedAmount options, callback
+
+
+  createRewards = (campaign, source, target, callback) ->
+
+    reward   = null
+    type     = campaign.type
+    unit     = campaign.unit
+    originId = target.getId()
+
+    queue = [
+
+      ->
+
+        reward = new JReward {
+          amount         : campaign.perEventAmount
+          sourceCampaign : campaign.name
+          providedBy     : source.getId()
+          originId, type, unit
+        }
+
+        reward.save (err) ->
+          return callback err  if err
+          queue.next()
+
+      ->
+
+        campaign.increaseGivenAmount (err) ->
+          logError "Couldn't increase given amount:", err  if err?
+
+          callback null
+
+    ]
+
+    daisy queue
+
+
+  logError = (rest...) -> console.error '[Rewards]', rest...
+

   # Private Methods
   # ---------------
@@ -274,74 +341,7 @@
   # Background Processes
   # --------------------

-  do ->
-
-    logError = (rest...) -> console.error '[Rewards]', rest...
-
-    fetchReferrer = (account, callback) ->
-
-      unless referrerUsername = account.referrerUsername
-        return callback null # User doesn't have any referrer
-
-      # get referrer
-      JAccount.one { 'profile.nickname': referrerUsername }, (err, referrer) ->
-
-        return callback err  if err
-
-        unless referrer
-          # if referrer not fonud then do nothing and return
-          return callback null # Referrer couldn't found
-
-        callback null, referrer
-
-
-    confirmRewards = (source, target, callback) ->
-
-      JReward.update
-        providedBy : source.getId()
-        originId   : target.getId()
-      ,
-        $set       : { confirmed : yes }
-      , (err) ->
-        return callback err  if err?
-
-        options = { originId: target.getId() }
-        JReward.calculateAndUpdateEarnedAmount options, callback
-
-
-    createRewards = (campaign, source, target, callback) ->
-
-      reward   = null
-      type     = campaign.type
-      unit     = campaign.unit
-      originId = target.getId()
-
-      queue = [
-
-        ->
-
-          reward = new JReward {
-            amount         : campaign.perEventAmount
-            sourceCampaign : campaign.name
-            providedBy     : source.getId()
-            originId, type, unit
-          }
-
-          reward.save (err) ->
-            return callback err  if err
-            queue.next()
-
-        ->
-
-          campaign.increaseGivenAmount (err) ->
-            logError "Couldn't increase given amount:", err  if err?
-
-            callback null
-
-      ]
-
-      daisy queue
-
+  addUserRegisteredListener = ->

     JRewardCampaign = require './rewardcampaign'

@@ -391,6 +391,8 @@

       daisy queue

+
+  addEmailConfimedListener = ->

     # When users confirm their emails we need to confirm
     # existing rewards for them.
@@ -450,3 +452,9 @@
       daisy queue

+  do ->
+
+    addUserRegisteredListener()
+    addEmailConfimedListener()
+
+


Conform to new finer grained accessibility rules.

--- src/p13n.coffee
+++ src/p13n.coffee
@@ -163,14 +163,24 @@
         get_accessibility_profile_ids: () ->
             ids = {}
             acc_vars = @get 'accessibility'
+            transport = @get 'transport'
             mobility = acc_vars['mobility']
             key = PROFILE_IDS[mobility]
             if key
+                if key in [1, 2, 3, 5]
+                    key += if transport.car then 'B' else 'A'
+                else
+                    key += 'A'
                 ids[key] = mobility
-            for key in ['visually_impaired', 'hearing_aid']
-                val = @get_accessibility_mode key
+            for disability in ['visually_impaired', 'hearing_aid']
+                val = @get_accessibility_mode disability
                 if val
-                    ids[PROFILE_IDS[key]] = key
+                    key = PROFILE_IDS[disability]
+                    if disability == 'visually_impaired'
+                        key += if transport.car then 'B' else 'A'
+                    else
+                        key += 'A'
+                    ids[key] = disability
             ids

         set_transport: (mode_name, val) ->


Pay transfer fees in the asset being transfered #101

--- dl/src/chain/transaction_operations.coffee
+++ dl/src/chain/transaction_operations.coffee
@@ -44,6 +44,8 @@
         operation_id = chain_types.operations[_type.operation_name]
         if operation_id is undefined
             throw new Error "unknown operation: #{_type.operation_name}"
+        unless operation.fee
+            operation.fee = {amount: 0, asset_id: 0}
         operation_instance = _type.fromObject operation
         @operations.push [operation_id, operation_instance]
         return
@@ -52,15 +54,23 @@
         throw new Error "already finalized" if @tr_buffer
         @expiration = Math.round(Date.now()/1000) + (min*60)

-    set_required_fees:(asset_id = "1.3.0")->
+    set_required_fees:(asset_id)->
         throw new Error "already finalized" if @tr_buffer
+        throw new Error "add operations first" unless @operations.length
         operations = for op in @operations
             type.operation.toObject op
+
+        if not asset_id
+            op1_fee = operations[0][1].fee
+            if op1_fee and op1_fee.asset_id isnt null
+                asset_id = op1_fee.asset_id
+            else
+                asset_id = "1.3.0"
+
         api.db_api().exec( "get_required_fees",
             [operations, asset_id]
         ).then (assets)=>
-            #DEBUG
-            console.log('... get_required_fees',assets)
+            #DEBUG console.log('... get_required_fees',assets)
             for i in [0...@operations.length] by 1
                 @operations[i][1].fee = assets[i]
             return
@@ -125,55 +135,55 @@
                 )
                 return

-class _my.transfer
-    _template = ->
-        fee :
-            amount : 0
-            asset_id : 0 # 1.3.0
-        from: null       # 1.2.0
-        to: null         # 1.2.0
-        amount:
-            amount: "0"
-            asset_id: 0 # 1.3.0
-        memo:
-            from: null  # GPHXyz...public_key
-            to: null    # GPHXyz...public_key
-            nonce: "0" # "0"
-            message: null
-
-    constructor:( @memo_from_privkey )->
-        for key in Object.keys _tmp = _template()
-            @[key] = _tmp[key]
-
-    get_operations:->
-        @fee.asset_id = lookup.asset_id(@fee.asset_id)
-        @from = lookup.account_id(@from)
-        @to = lookup.account_id(@to)
-        @amount.asset_id = lookup.asset_id(@amount.asset_id)
-        if validation.is_empty_user_input @memo.message
-            @memo = undefined
-        else
-            to = @memo.to
-            @memo.from = lookup.memo_public_key(@memo.from)
-            @memo.to = lookup.memo_public_key(@memo.to)
-            if @memo_from_privkey
-                @memo.nonce = helper.unique_nonce_uint64()
-                @memo_to_public = lookup.memo_public_key(to)
-            else
-                empty_checksum = "\x00\x00\x00\x00"
-                # assert (new Buffer("\x00\x00\x00\x00")).toString() == "\x00\x00\x00\x00"
-                @memo.message = new Buffer(empty_checksum + @memo.message)
-
-        [[ chain_types.operations.transfer, @]]
+#class _my.transfer
+#    _template = ->
+#        fee :
+#            amount : 0
+#            asset_id : 0 # 1.3.0
+#        from: null       # 1.2.0
+#        to: null         # 1.2.0
+#        amount:
+#            amount: "0"
+#            asset_id: 0 # 1.3.0
+#        memo:
+#            from: null  # GPHXyz...public_key
+#            to: null    # GPHXyz...public_key
+#            nonce: "0" # "0"
+#            message: null
+#
+#    constructor:( @memo_from_privkey )->
+#        for key in Object.keys _tmp = _template()
+#            @[key] = _tmp[key]
+#
+#    get_operations:->
+#        @fee.asset_id = lookup.asset_id(@fee.asset_id)
+#        @from = lookup.account_id(@from)
+#        @to = lookup.account_id(@to)
+#        @amount.asset_id = lookup.asset_id(@amount.asset_id)
+#        if not @memo.message
+#            @memo = undefined
+#        else
+#            to = @memo.to
+#            @memo.from = lookup.memo_public_key(@memo.from)
+#            @memo.to = lookup.memo_public_key(@memo.to)
+#            if @memo_from_privkey
+#                @memo.nonce = helper.unique_nonce_uint64()
+#                @memo_to_public = lookup.memo_public_key(to)
+#            else
+#                empty_checksum = "\x00\x00\x00\x00"
+#                # assert (new Buffer("\x00\x00\x00\x00")).toString() == "\x00\x00\x00\x00"
+#                @memo.message = new Buffer(empty_checksum + @memo.message)
+#
+#        [[ chain_types.operations.transfer, @]]
+#
+#    finalize:->
+#        if @memo_from_privkey
+#            ciphertext = Aes.encrypt_with_checksum(
+#                @memo_from_privkey
+#                @memo_to_public.resolve
+#                @memo.nonce
+#                @memo.message
+#            )
+#            @memo.message = new Buffer(ciphertext)
+#        return

-    finalize:->
-        if @memo_from_privkey
-            ciphertext = Aes.encrypt_with_checksum(
-                @memo_from_privkey
-                @memo_to_public.resolve
-                @memo.nonce
-                @memo.message
-            )
-            @memo.message = new Buffer(ciphertext)
-        return
-


Better catcode behaviour + fixed control symbol typo

--- grammars/latex.cson
+++ grammars/latex.cson
@@ -26,6 +26,7 @@
   metaControl: {
     comment: 'All these commands begin with a backslash.'
     patterns: [
+      { include: '#doubleCaret' } # Temporary, to see if it works better this way.
       { include: '#metaCommonControlSequences' }
       { include: '#metaEnvironment' }
       { include: '#metaDollar' } # Because of \( and \[. Must appear below escaped characters, to prevent \$ from being a false positive.
@@ -139,6 +140,7 @@
       { include: '#metaFootnote' }
       { include: '#metaReferences' } # maybe include \ref \label as well?
       { include: '#constants' } # words that represent constants
+      { include: '#catcode' } # and all the other <something>code commands

       # Potential additions:
       # { include: '#commandDefinitions' }
@@ -171,6 +173,13 @@
   metaPrimitives: {
     comment: 'Allows organisation of various primitive sources'
     patterns: [
+      # {
+      #   match: '((\\\\)catcode)\\s*\\`(.*?)='
+      #   captures:
+      #     1: name: 'entity.name.function.primitive.latex'
+      #     2: name: 'punctuation.definition.function.latex'
+      #     3: patterns: [{ include: '$self' }]
+      # }
       { include: '#texPrimitives' }
       { include: '#pdfTexPrimitives' }
       { include: '#unsortedPrimitives' }
@@ -416,6 +425,14 @@
   }

 # Other
+  catcode: {
+    comment: 'Prevent catcoding from triggering mathmode; could be made more general into whenever a backtick is followed by math mode brackets'
+    match: '((\\\\)(?>cat|math|sf|del)code)`(\\\\\\(|\\\\\\[)'
+    captures:
+      1: name: 'entity.name.function.primitive.latex'
+      2: name: 'punctuation.definition.function.latex'
+      3: name: 'keyword.control.symbol.latex'
+  }
   escapedCharacter: {
     comment: 'Finds escaped characters like \$ and \%. Uses this regex so unique capture groups can be used.'
     name: 'constant.character.latex'
@@ -424,7 +441,7 @@
   controlSymbol: {
     comment: 'Mostly covered by escapedCharacter, but this is a catch all for any control symbols'
     name: 'keyword.control.symbol.latex'
-    match: '\\\\([^a-zA-Z@]|@[^a-zA-A@])'
+    match: '\\\\([^a-zA-Z@]|@[^a-zA-Z@])'
   }
   controlWord: {
     comment: 'A catch all for latex control words that have not already been identified.'
@@ -1133,7 +1150,7 @@
   doubleCaret: {
     comment: 'Im not sure what these are called, but they seem to work (eg. ^^M is a linebreak)'
     name: 'constant.character.latex'
-    match: '\\^\\^(\\d+|.|$)'
+    match: '(\\\\)?\\^\\^(\\d+|.|$)'
   }
   text: {
     begin: '((\\\\)text)\\s*(\\{)'


Syntax highlighting for the <app> tag

Syntax highlighting for the <app> tag

--- grammars/marko.cson
+++ grammars/marko.cson
@@ -254,7 +254,7 @@
     ]
   }
   {
-    'begin': '(</?)((?i:for|if|else-if|else|var|require|def|invoke|include|with)\\b)'
+    'begin': '(</?)((?i:for|if|else-if|else|var|require|def|invoke|include|with|app)\\b)'
     'captures':
       '1':
         'name': 'punctuation.definition.tag.html'


fix bug with comments that stopped regexes from coloring

--- grammars/stata.cson
+++ grammars/stata.cson
@@ -38,7 +38,7 @@
             'name': 'variable.parameter.function.stata'
           }
           {
-            'include': '#comments'
+            'include': '#comments-triple-slash'
           }
         ]
       '4':
@@ -48,6 +48,10 @@
       '6':
         'patterns': [
           {'include': 'source.regexp.stata'}
+          # {
+          #   'include': '#comments-triple-slash'
+          # }
+          # Unknown if this helps. Regex not colored when regexm split over multiple lines as of 9/11/2017, 1:32:26 AM
         ]
       '7':
         'name': 'punctuation.definition.string.end.stata'
@@ -121,7 +125,7 @@
             'name': 'variable.parameter.function.stata'
           }
           {
-            'include': '#comments'
+            'include': '#comments-triple-slash'
           }
         ]
       '10':
@@ -685,6 +689,21 @@
   'comments':
     'patterns': [
       {
+        'include': '#comments-block'
+      }
+      {
+        'include': '#comments-star'
+      }
+      {
+        'include': '#comments-triple-slash'
+      }
+      {
+        'include': '#comments-double-slash'
+      }
+    ]
+  'comments-block':
+    'patterns': [
+      {
         'comment': 'There could be a * as a glob in a path'
         'begin': '^/\\*|(?<=\\s)/\\*'
         'beginCaptures':
@@ -701,6 +720,9 @@
           }
         ]
       }
+    ]
+  'comments-star':
+    'patterns': [
       {
         'captures':
           '0':
@@ -715,6 +737,9 @@
           }
         ]
       }
+    ]
+  'comments-triple-slash':
+    'patterns': [
       {
         'captures':
           '0':
@@ -728,6 +753,9 @@
           }
         ]
       }
+    ]
+  'comments-double-slash':
+    'patterns': [
       {
         'captures':
           '0':
@@ -745,9 +773,9 @@
   'docblockr-comment':
     'patterns': [
       {
-        'match': '\\*?\\s*(@[A-za-z0-9]+)'
+        'match': '(^\\s*\\*\\s*|\\s+)(@[A-za-z0-9]+)'
         'captures':
-          '1':
+          '2':
             'name': 'keyword.docblockr.stata'
       }
     ]


fix spec

fix spec

--- src/editor-component.coffee
+++ src/editor-component.coffee
@@ -280,7 +280,7 @@
       headScreenRow = null
       if marker.isValid()
         for decoration in decorations
-          if decoration.isType('gutter') or decoration.isType(decoration, 'line')
+          if decoration.isType('gutter') or decoration.isType('line')
             decorationParams = decoration.getParams()
             screenRange ?= marker.getScreenRange()
             headScreenRow ?= marker.getHeadScreenPosition().row


add doc

add doc

--- log.coffee
+++ log.coffee
@@ -1,9 +1,19 @@
+# A basic logging module.
+
+# Log info messages for debugging. **TODO**: empty later
+
+info = (message) ->
+  console.log message
+
+# Throw an application specific error.
+
+fail = (message) ->
+  throw
+    name: '2cpyError'
+    message: message
+
+# ### Public API
+
 module.exports =
-
-  info: (message) ->
-    console.log message
-
-  fail: (message) ->
-    throw
-      name: '2cpyError'
-      message: message+  info: info
+  fail: fail


adding debug

adding debug

--- src/poll.coffee
+++ src/poll.coffee
@@ -23,8 +23,10 @@
     return (optionsString.split "option: ")[1..]

 createPoll = (robot, topic, options...) ->
+    @robot.logger.info "Creating poll with #{topic}"
     id = generateId
     pollOptions = parseOptions options
+    @robot.logger.info "We have #{pollOptions.length()} options"
     robot.brain.data.poll[id].topic = topic
     optionsString = ""

@@ -33,6 +35,7 @@
         robot.brain.data.poll[id].option[index].text
         optionsString += "\t#{index}: #{pollOption}\n"
     robot.brain.save()
+    @robot.logg.info "Brain saved"

     text =  """
             POLL ID: #{id}
@@ -40,6 +43,7 @@
             Options:
             #{optionsString}
             """
+    return text

 module.exports = (robot) ->


Run tests by default

Run tests by default

diversity-build has been fixed and now runs tests more smoothly.
Also, there is no need to see if the tests are missing - diversity-build does this automatically. It will report a success and print a warning in the console that no tests were found.

--- src/push.coffee
+++ src/push.coffee
@@ -1,5 +1,5 @@
 # Diversity Push <denis@dervisevic.se>
-# A simple node script to update the version of Diversity <https:#diversity.io/> components.
+# A simple node script to update the version of Diversity <https://diversity.io/> components.
 # More info in readme

 fs    = require('fs');
@@ -56,16 +56,10 @@

     # Run karma tests, if they exist
     karmaConfPath = process.cwd() + '/test/karma.conf.js'
-    karmaTestsExist = fs.existsSync karmaConfPath
-    skipKarmaTests = rls.question 'Do you want to proceed without running tests? [Y/n]: '

-    if skipKarmaTests?.toLowerCase() is 'n'
-      if karmaTestsExist
-        runCommand 'gulp karma:single-run'
-      else
-        console.log "Could not find karma conf path."
-        shell.exit 1
-
+    skipKarmaTests = rls.question 'Do you want to run the tests? [Y/n]: '
+    if skipKarmaTests?.toLowerCase() isnt 'n'
+      runCommand 'gulp karma:single-run'

     diversityData = JSON.parse readDiversity(settings.diversityPath)
     versionArray = diversityData.version.split '.'


removed obsolete sputnik

removed obsolete sputnik

--- src/game/states/game.coffee
+++ src/game/states/game.coffee
@@ -117,7 +117,7 @@

      #add sounds
     music = @game.add.audio ('backgroundSound')
-    #@soundSputnik = @game.add.audio 'soundSputnik'
+

     music.play()


Add legacy ‘Syntax’ deserializer for GrammarRegistry

--- src/grammar-registry.coffee
+++ src/grammar-registry.coffee
@@ -20,12 +20,14 @@
 class GrammarRegistry extends FirstMate.GrammarRegistry
   PropertyAccessors.includeInto(this)
   Subscriber.includeInto(this)
-  atom.deserializers.add(this)

   @deserialize: ({grammarOverridesByPath}) ->
     grammarRegistry = new GrammarRegistry()
     grammarRegistry.grammarOverridesByPath = grammarOverridesByPath
     grammarRegistry
+
+  atom.deserializers.add(this)
+  atom.deserializers.add(name: 'Syntax', deserialize: @deserialize) # Support old serialization

   constructor: ->
     super(maxTokensPerLine: 100)


Use ? in the conditional.

Use ? in the conditional.

--- src/gutter-component.coffee
+++ src/gutter-component.coffee
@@ -144,7 +144,7 @@
     innerHTML = @buildLineNumberInnerHTML(bufferRow, softWrapped, maxLineNumberDigits)

     classes = ''
-    if lineDecorations and decorations = lineDecorations[screenRow]
+    if lineDecorations? and decorations = lineDecorations[screenRow]
       for decoration in decorations
         if editor.decorationMatchesType(decoration, 'gutter')
           classes += decoration.class + ' '


Actions can now be removed from the list by defining an available function in the action definition. Returning non-truthy will remove it

--- src/ribs.coffee
+++ src/ribs.coffee
@@ -373,7 +373,10 @@

             $batchActions = $ "<ul/>", class: "actions"

-            @allActions = new Ribs.Actions @actions, ribs: this
+            _availableActions = _.reject @actions, (action) =>
+                action.available? and !action.available.call this
+
+            @allActions = new Ribs.Actions _availableActions, ribs: this

             @inlineActions = @allActions.where inline: true

@@ -704,7 +707,9 @@
             @ribs = options.ribs ? @collection.ribs

             if @has "actions"
-                @actions = new Ribs.Actions @get("actions"), ribs: @ribs
+                availableActions = _.reject @get("actions"), (action) =>
+                    action.available? and not action.available.call @ribs
+                @actions = new Ribs.Actions availableActions, ribs: @ribs
                 @min = 0

             if @has("hotkey") and not @ribs.suppressHotKeys


added configurable delay property to timer


beginnings of sending avatars

beginnings of sending avatars

--- src/Main.coffee
+++ src/Main.coffee
@@ -7,8 +7,15 @@
     mode = if debug then Phaser.CANVAS else Phaser.AUTO
     new Phaser.Game(800, 450, mode, @parent, this, false, false, null)

+  preload:->
+    @game.load.spritesheet('nigel', 'assets/nigel.png', 32, 32)
+    @game.load.spritesheet('bruce', 'assets/bruce.png', 32, 32)
+    @game.load.spritesheet('julie', 'assets/julie.png', 32, 32)
+    @game.load.spritesheet('rachel', 'assets/rachel.png', 32, 32)
+
   init: ->
     @game.physics.startSystem(Phaser.Physics.ARCADE)
+    @generator = new Phaser.RandomDataGenerator([(new Date()).getTime()])

     @game.input.gamepad.start
     @pads = [
@@ -41,16 +48,13 @@
     @myId = '555'

     @dudes = @game.add.group()
-    @player = @addDude(@myId, 0, 0, 'nigel')
-
+    @avatar = @generator.pick(['nigel','bruce', 'julie', 'rachel'])
+    @player = @addDude(@myId, 0, 0, @avatar)
     @game.physics.arcade.enable(@player)
-    console.log(@dudes)
-    @cursors = @game.input.keyboard.createCursorKeys()
-
-    @peer = new Peer({ host: 'router.kranzky.com', port: 80, config: { 'iceServers': [] }, debug: 0 })

     @allPeers = []
     @myPeerId = null
+    @peer = new Peer({ host: 'router.kranzky.com', port: 80, config: { 'iceServers': [] }, debug: 0 })
     @peer.on 'open', (id)=>
       console.log('My peer ID is: ' + id)
       @myPeerId = id
@@ -59,13 +63,10 @@
         @allPeers = _.map data, (peerId) =>
           channel = @peer.connect(peerId)
           channel.on 'open', =>
-            channel.send({message:"arrive"})
+            channel.send({message:"arrive", x: 0, y: 0, @avatar})
             @addDude(channel.peer, data.x, data.y, 'nigel')
           channel
-
         console.log('all peers: ' + _.map @allPeers, (channel)->channel.peer )
-
-
     @peer.on 'connection', (remote)=>
       remote.on 'data', (data)=>
         if data.message == "update"
@@ -75,7 +76,7 @@
           channel = @peer.connect remote.peer
           @allPeers.push(channel)
           console.log('all peers: ' + _.map @allPeers, (channel)->channel.peer)
-          @addDude(remote.peer, data.x, data.y, 'nigel')
+          @addDude(remote.peer, data.x, data.y, data.avatar)
       remote.on 'close', =>
         @allPeers = _.reject @allPeers, (channel)-> channel.peer == remote.peer
         @removeDude(remote.peer)
@@ -126,8 +127,8 @@
         anim = "up"
     @player.animations.play(anim)

-    @player.body.velocity.x *= 0.95
-    @player.body.velocity.y *= 0.95
+    @player.body.velocity.x *= 0.9
+    @player.body.velocity.y *= 0.9

     @sendUpdate(@myId, @player.body.x, @player.body.y, anim)

@@ -193,9 +194,6 @@

   destroy:->

-  preload:->
-    @game.load.spritesheet('nigel', 'assets/nigel.png', 32, 32)
-
   loadRender:->

   render:->


FIX #9: Paused bug fixed.

FIX #9: Paused bug fixed.

--- src/Moon.coffee
+++ src/Moon.coffee
@@ -194,12 +194,7 @@
                         el.style[this._getPrefix(key)] = value

                 # timer to continue animation
-                nextTimeout = setTimeout =>
-
-                    # if it is paused, clear and stop
-                    if this._paused?
-                        clearTimeout(nextTimeout)
-                        return undefined
+                this._nextTimeout = setTimeout =>

                     # after animation function
                     anm.after() if typeof anm.after == "function"
@@ -207,7 +202,7 @@
                     # continue chained animations
                     @._play()

-                    clearTimeout(nextTimeout)
+                    clearTimeout(@._nextTimeout)
                 , anm.delay + anm.duration

                 this._lastTimePlayed = new Date()
@@ -254,6 +249,8 @@
                     el.style[this._getPrefix(key)] = computedStyle.getPropertyValue(this._getCssPrefix(key))

                 el.style[this._getPrefix("transition")] = ""
+
+            clearTimeout(this._nextTimeout)

             return this


FIX #2: Capitalization with Regex

FIX #2: Capitalization with Regex

--- src/Moon.coffee
+++ src/Moon.coffee
@@ -48,31 +48,27 @@
                 return Moon.fn._prefixes[prop]

             # if not, continue the search for it
-            prefixes = ["webkit", "moz", "ms", "O"]
+            prefixes = ["webkit-", "moz-", "ms-", "O-"]

-            indexOfDash = prop.indexOf("-")
-            while indexOfDash > -1
+            # camelCase properties
+            prop = Moon.fn.camelize(prop)

-                # the letter after the dash is capitalized
-                prop = prop.slice(0, indexOfDash) + prop.charAt(indexOfDash + 1).toUpperCase() + prop.slice(indexOfDash + 2)
-                indexOfDash = prop.indexOf("-")
-
-            # is the propertie avaiable without prefix?
+            # is the property avaiable without prefix?
             if document.documentElement.style[prop]?
                 Moon.fn._prefixes[prop] = prop
                 return prop

             # if not, try to find the prefix
-            propCap = Moon.fn.cap(prop)
             for pre in prefixes
-                propertie = pre + propCap
-                if document.documentElement.style[propertie]?
-                    Moon.fn._prefixes[prop] = propertie
+                property = Moon.fn.camelize(pre + propCap)
+                if document.documentElement.style[property]?
+                    Moon.fn._prefixes[prop] = property
                     return propertie

         # capitalizes the first letter
-        cap: (str) ->
-            return str.charAt(0).toUpperCase() + str.slice(1);
+        camelize: (str) ->
+            return str.replace(/-([\da-z])/gi, ($1) ->
+                return $1.toUpperCase().replace('-','')

         # defines an animation step. Moon animations must have at least one step
         animate: (args) ->


adding LilyPond support

adding LilyPond support

--- src/sloc.coffee
+++ src/sloc.coffee
@@ -65,6 +65,8 @@
         r
       when "rkt", "clj", "cljs", "hy", "asm"
         /;/
+      when "ly", "ily"
+        start = /%/
       else null

   ## block comments
@@ -123,6 +125,10 @@
     when "ml", "mli", "fs", "fsi", "fsx"
       start = /\(\*/
       stop  = /\*\)/
+
+    when "ly", "ily"
+      start = /%\{/
+      stop  = /%\}/

     else
       if lang in extensions then start = stop = null
@@ -281,6 +287,7 @@
   "hxx"
   "hy"
   "iced"
+  "ily"
   "ino"
   "jade"
   "java"
@@ -292,6 +299,7 @@
   "kts"
   "latex"
   "less"
+  "ly"
   "lua"
   "ls"
   "ml"


Add hooks for requests of opportunity

Add hooks for requests of opportunity

--- src/teak.coffee
+++ src/teak.coffee
@@ -223,6 +223,29 @@
         @internal_directRequest(carrotResponse, callback, postMethod);
       )

+  hasRequestOfOpportunity: (opts, callback) ->
+    if !opts
+      opts = {}
+
+    params = {
+      'object_properties' : JSON.stringify(opts['object_properties'] || {})
+    }
+
+    @postSignedRequest("/me/request_of_opportunity.json", params, (jqXHR) =>
+      carrotResponse = $.parseJSON(jqXHR.responseText)
+      if(carrotResponse.code == 200) {
+        @requestOfOpportunity = carrotResponse
+        callback(true) if callback
+      } else {
+        callback(false) if callback
+      }
+    )
+
+  sendRequestOfOpporunity: (callback) ->
+    if @requestOfOpportunity
+      internal_directRequest(@requestOfOpportunity, callback)
+    @requestOfOpportunity = undefined
+
   internal_directRequest: (carrotResponse, callback, postMethod) ->
     if !postMethod? && FB?
       postMethod = FB.ui


add missing dependency

add missing dependency


fix style

fix style

--- lib/carte/client/views/card.cjsx
+++ lib/carte/client/views/card.cjsx
@@ -56,9 +56,7 @@

-

-

-

+


psr2 test

psr2 test

--- BackofficeBundle/Resources/public/coffee/addPrototype.coffee
+++ BackofficeBundle/Resources/public/coffee/addPrototype.coffee
@@ -32,7 +32,7 @@
     else
       prototype.addClass "error"
     return
-
+
   @toogleAddButton()

   if @getIndex() == 0 && @settings.required


Use correct formatter for right axes

Use correct formatter for right axes

--- src/time.coffee
+++ src/time.coffee
@@ -233,7 +233,7 @@
     extent = @extent((d) -> d.y)
     ticks = @options.ticks.right
     axis = d3.svg.axis().scale(@ySvg()).orient('right')
-      .tickFormat(@options.tickFormats.left)
+      .tickFormat(@options.tickFormats.right)
     if ticks == 2
       axis.tickValues @extent((d) -> d.y)
     else


i don't see how this EVER worked

i don't see how this EVER worked

--- lib/cli/runs-next-command.coffee
+++ lib/cli/runs-next-command.coffee
@@ -15,24 +15,20 @@
   constructor: (commander, currentCommandName) ->
     @commander = commander
     @currentCommandName = currentCommandName
-    @nextCommand = @findChainedCommand()
-    @overrideLinemanEnv()

   run: =>
-    return unless @nextCommand?
-    process.argv = @exciseCurrentCommandFromArgv(process.argv)
-    @commander.parse(process.argv)
+    currentCommandIndex = process.argv.indexOf(@currentCommandName)
+    if nextCommand = @findChainedCommand(process.argv.slice(currentCommandIndex + 1))
+      nextCommandIndex = process.argv.indexOf(nextCommand._name, currentCommandIndex + 1)
+      process.argv = process.argv.slice(0,2).concat(process.argv.slice(nextCommandIndex))
+      @overrideLinemanEnv()
+      @commander.parse(process.argv)

   #private

-  findChainedCommand: ->
+  findChainedCommand: (args) ->
     _.find @commander.commands, (c) =>
-      _.includes(@commander.args, c._name)
-
-  exciseCurrentCommandFromArgv: (argv) ->
-    currentCommandIndex = process.argv.indexOf(@currentCommandName)
-    nextCommandIndex = process.argv.indexOf(@nextCommand._name, currentCommandIndex + 1)
-    argv.slice(0, currentCommandIndex).concat(argv.slice(nextCommandIndex))
+      _.includes(args, c._name)

   overrideLinemanEnv: ->
     return process.env["LINEMAN_ENV"] = "production" if _.includes(process.argv, "build")


Remove outdated comments, re-order two operations.

--- src/TinyMockJS.coffee
+++ src/TinyMockJS.coffee
@@ -19,8 +19,8 @@
     @_throws = undefined
     @called = false
     @_original_method = undefined
+    _install_mock_method(@, object, method_name)
     Expectation._all_expectations.push(@)
-    _install_mock_method(@, object, method_name)

   #
   # mock (my_mock) ->
@@ -53,39 +53,12 @@
     @

   #
-  # TODO: Expectation() constructor takes an object parameter;
-  # fix the examples below to show this.
-  #
-  # Returns true if this exectation equals (has the same values
-  # as) another.  For example:
-  #
-  #   exp1 = new Expectation("my_method")
-  #   exp1.args( 1, "a" )
-  #
-  #   exp2 = new Expectation("my_method")
-  #   exp2.args( 1, "a" )
-  #
-  #   exp1.equals(exp2)           # returns true
-  #
   # Note: this method is similar to matches() but is used to
   # find duplicate expectations.
   #
   equals: (other) ->
     @matches(other._object, other.method_name, other._args...)

-  #
-  # TODO: Expectation() constructor takes an object parameter;
-  # fix the examples below to show this.
-  #
-  # Returns true if this expectation has the specified method
-  # name and arguments.  For example:
-  #
-  #   exp = new Expectation("my_method")
-  #   exp.args( 1, "a" )
-  #   ...
-  #   exp.matches( "my_method", [ 1, "a" ] )     # returns true
-  #   exp.matches( "your_method", [ 1, "a" ] )   # returns false
-  #   exp.matches( "my_method", [ 2, "b" ] )     # returns false
   #
   # Note: this method is similar to equals() but is used to
   # search for a expectation with a given name and args.


Change s3 path from h2o-dev to h2o

Change s3 path from h2o-dev to h2o

--- h2o-web/help.coffee
+++ h2o-web/help.coffee
@@ -199,13 +199,13 @@
     ul [
       li link 'REST API Endpoints',  '#route-reference'
       li link 'REST API Schemas',    '#schema-reference'
-      li link 'R API',               "http://h2o-release.s3.amazonaws.com/h2o-dev/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-r/h2o_package.pdf"
-      li link 'Python API',          "http://h2o-release.s3.amazonaws.com/h2o-dev/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-py/docs/index.html"
-      li link 'h2o-core Javadoc',    "http://h2o-release.s3.amazonaws.com/h2o-dev/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-core/javadoc/index.html"
-      li link 'h2o-algos Javadoc',   "http://h2o-release.s3.amazonaws.com/h2o-dev/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-algos/javadoc/index.html"
-      li link 'h2o-scala Scaladoc',  "http://h2o-release.s3.amazonaws.com/h2o-dev/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-scala/scaladoc/index.html"
+      li link 'R API',               "http://h2o-release.s3.amazonaws.com/h2o/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-r/h2o_package.pdf"
+      li link 'Python API',          "http://h2o-release.s3.amazonaws.com/h2o/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-py/docs/index.html"
+      li link 'h2o-core Javadoc',    "http://h2o-release.s3.amazonaws.com/h2o/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-core/javadoc/index.html"
+      li link 'h2o-algos Javadoc',   "http://h2o-release.s3.amazonaws.com/h2o/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-algos/javadoc/index.html"
+      li link 'h2o-scala Scaladoc',  "http://h2o-release.s3.amazonaws.com/h2o/#{argv.branch_name}/#{argv.build_number}/docs-website/h2o-scala/scaladoc/index.html"
       li link 'Sparkling Water API', 'https://github.com/h2oai/sparkling-water/blob/master/DEVEL.md'
-      li link 'Build page',          "http://h2o-release.s3.amazonaws.com/h2o-dev/#{argv.branch_name}/#{argv.build_number}/index.html"
+      li link 'Build page',          "http://h2o-release.s3.amazonaws.com/h2o/#{argv.branch_name}/#{argv.build_number}/index.html"
     ]
   ].join EOL


tree: show string literal with quotes

tree: show string literal with quotes

--- src/tree.coffee
+++ src/tree.coffee
@@ -5,6 +5,8 @@
 class TreeBuilder extends FormulaVisitor
   visitLiteral: (node) ->
     { name: node.value }
+  visitStringLiteral: (node) ->
+    { name: "'#{node.value}'" }
   visitReference: (node) ->
     { name: node.name }
   visitParens: (node) ->


Removed redundant code in util.whilst

Removed redundant code in util.whilst

--- src/util.coffee
+++ src/util.coffee
@@ -36,19 +36,12 @@
 	Promise.resolve val

 exports.whilst = (test, fn) ->
-	poisonPill = {}
-
-	iteration = ->
+	do iteration = ->
 		Promise.resolve(test())
 		.then (doLoop) ->
 			if doLoop
 				Promise.resolve(fn())
 				.then iteration
-
-			else throw poisonPill
-
-	iteration()
-	.catch (e) -> if e isnt poisonPill then throw e

 exports.edge = (r, edge) ->
 	switch edge


Rename `config` "update" event to "updated"

--- src/app/config.coffee
+++ src/app/config.coffee
@@ -73,14 +73,14 @@
         previousValue = _.clone(value)
         callback(value)

-    subscription = { cancel: => @off 'update', updateCallback  }
-    @on 'update', updateCallback
+    subscription = { cancel: => @off 'updated', updateCallback  }
+    @on 'updated', updateCallback
     callback(value)
     subscription

   update: ->
     @save()
-    @trigger 'update'
+    @trigger 'updated'

   save: ->
     fs.write(configJsonPath, JSON.stringify(@settings, undefined, 2) + "\n")


add padding to title frame to avoid overlapping borders (j3 suggestion)

--- src/smc-webapp/code-editor/frame-title-bar.cjsx
+++ src/smc-webapp/code-editor/frame-title-bar.cjsx
@@ -21,6 +21,7 @@
     lineHeight    : '20px'
     textOverflow  : 'ellipsis'
     minHeight     : '24px'
+    padding       : '1px'

 path_style =
     whiteSpace   : 'nowrap'


Use request helper in View class

Use request helper in View class

--- src/view.coffee
+++ src/view.coffee
@@ -1,9 +1,9 @@
 _ = require 'underscore-plus'
 optimist = require 'optimist'
-request = require 'request'

 Command = require './command'
 config = require './config'
+request = require './request'
 tree = require './tree'

 module.exports =
@@ -29,7 +29,6 @@
     requestSettings =
       url: "#{config.getAtomPackagesUrl()}/#{packageName}"
       json: true
-      proxy: process.env.http_proxy || process.env.https_proxy
     request.get requestSettings, (error, response, body={}) ->
       if error?
         callback(error)


Task methods should be chainable

Task methods should be chainable

--- src/backburner.coffee
+++ src/backburner.coffee
@@ -28,14 +28,17 @@
     # Make this task runnable
     start: ->
         @_runnable = yes
+        return this

     # Make this task unrunnable
     stop: ->
         @_runnable = no
+        return this

     # Run this task's tick function once
     tick: ->
         @_tickFn.call @_context
+        return this

 backburner.spawn = (fn, config) ->
     task = new Task fn, config


add setter and getter

add setter and getter

--- src/base_model.coffee
+++ src/base_model.coffee
@@ -46,8 +46,17 @@
           self.set(attr, obj[attr])

+  set: (attr, value) ->
+    throw new Error("Attribute '#{attr}' not found for current model") if @attributes.indexOf(attr) == -1
+
+    # TODO validate value
+    @["_#{attr}"] = value
+
+  get: (attr) ->
+    throw new Error("Attribute '#{attr}' not found for current model") if @attributes.indexOf(attr) == -1
+
+    @["_#{attr}"]

-


Add delay & tap method

Add delay & tap method

--- src/bbjscompat.coffee
+++ src/bbjscompat.coffee
@@ -1,3 +1,15 @@
+# http://bluebirdjs.com/docs/api/promise.delay.html
+unless Promise.delay
+  Promise.delay = (ms, value) ->
+    return new Promise((resolve) ->
+      window.setTimeout((-> resolve(value)), ms)
+    )
+
+# http://bluebirdjs.com/docs/api/delay.html
+unless Promise::delay
+  Promise::delay = (ms) ->
+    return Promise.delay(ms, this)
+
 # http://bluebirdjs.com/docs/api/finally.html
 unless Promise::finally
   Promise::finally = (handler) ->
@@ -27,6 +39,17 @@
       return fulfilledHandler(valueArray...)
     )

+# http://bluebirdjs.com/docs/api/tap.html
+unless Promise::tap
+  Promise::tap = (handler) ->
+    return @then(
+      (value) ->
+        pass = -> Promise.resolve(value)
+        return Promise.resolve().then(->
+          return handler()
+        ).then(pass, pass)
+    )
+
 # http://bluebirdjs.com/docs/api/timeout.html
 unless Promise.TimeoutError
   class TimeoutError


Better comments for postversion script

Better comments for postversion script

--- src/argv.coffee
+++ src/argv.coffee
@@ -113,9 +113,9 @@

       * Verifies head is <branch>
       * Verifies working folder is not dirty
+      * Verifies current version is tagged
+      * git push / git push --tags
       * Checkout version tag
-      * git push
-      * git push --tags
       * npm publish
       * Revert to branch


Add atom.getVersion

Add atom.getVersion

--- src/atom.coffee
+++ src/atom.coffee
@@ -241,6 +241,9 @@
   isFullScreen: ->
     @getCurrentWindow().isFullScreen()

+  getVersion: ->
+    app.getVersion()
+
   getHomeDirPath: ->
     process.env[if process.platform is 'win32' then 'USERPROFILE' else 'HOME']


Serialize project

Serialize project

--- src/atom.coffee
+++ src/atom.coffee
@@ -229,7 +229,7 @@

   deserializeProject: ->
     Project = require './project'
-    @project ?= @deserializers.deserialize(@project) ? new Project(path: @getLoadSettings().initialPath)
+    @project ?= @deserializers.deserialize(@state.project) ? new Project(path: @getLoadSettings().initialPath)

   deserializeWorkspaceView: ->
     Workspace = require './workspace'
@@ -280,6 +280,7 @@
     return if not @project and not @workspaceView

     @state.syntax = @syntax.serialize()
+    @state.project = @project.serialize()
     @state.workspace = @workspace.serialize()
     @packages.deactivatePackages()
     @state.packageStates = @packages.packageStates


Add maximized parameter

Add maximized parameter

--- src/atom.coffee
+++ src/atom.coffee
@@ -211,7 +211,7 @@
   #   :width - The new width.
   #   :height - The new height.
   #   :maximized - A {Boolean} for the maximized window state.
-  setWindowDimensions: ({x, y, width, height}) ->
+  setWindowDimensions: ({x, y, width, height, maximized}) ->
     if maximized and process.platform isnt 'darwin'
       @maximize()
     else


Add JCB to list of checked cards

Add JCB to list of checked cards

--- src/card_utils.coffee
+++ src/card_utils.coffee
@@ -1,5 +1,6 @@
 AMEX        = 'amex'
 DISCOVER    = 'discover'
+JCB         = 'jcb'
 MASTERCARD  = 'mastercard'
 VISA        = 'visa'

@@ -15,6 +16,8 @@
     VISA
   else if pan.slice(0, 4) is '6011' or firsttwo is 65 or (halfiin >= 664 && halfiin <= 649) or (iin >= 622126 and iin <= 622925)
     DISCOVER
+  else if pan.slice(0, 4) is '2131' or pan.slice(0, 4) is '1800' or firsttwo is 35
+    JCB
   else if firsttwo >= 51 and firsttwo <= 55
     MASTERCARD
   else if firsttwo in [34, 37]
@@ -35,9 +38,11 @@
       pan.length in [13, 16]
     when DISCOVER, MASTERCARD
       pan.length is 16
+    when JCB
+      pan.length in [15, 16]
     when AMEX
       pan.length is 15
     else
       false

-module.exports = { determineCardType, luhnCheck, validCardLength, AMEX, DISCOVER, MASTERCARD, VISA }
+module.exports = { determineCardType, luhnCheck, validCardLength, AMEX, DISCOVER, JCB, MASTERCARD, VISA }


Remove debug message from save method.

Remove debug message from save method.

--- src/bang.coffee
+++ src/bang.coffee
@@ -9,7 +9,6 @@
   data = JSON.parse(fs.readFileSync bang)

 save = ->
-  console.log "save called"
   fs.writeFileSync bang, JSON.stringify(data)

 get = (key) ->


Update menu to show dashboard instead of old messages page

--- ui/scripts/models/menu.coffee
+++ ui/scripts/models/menu.coffee
@@ -14,7 +14,7 @@
             'contact'
         ]
         loggedIn: [
-            'inbox'
+            'dashboard'
             'settings'
             'contact'
             'terms'
@@ -28,8 +28,7 @@
         login: { title: 'Log In', icon: 'sign-in' }
         terms: { icon: 'pencil-square-o' }
         contact: { icon: 'envelope' }
-        # dashboard: { icon: 'tachometer' }
-        inbox: { icon: 'inbox' }
+        dashboard: { icon: 'tachometer' }
         settings: { icon: 'cog' }
         logout: { icon: 'sign-out' }
     }


Core: minor code styling

Core: minor code styling

--- client/Core/customlinkview.coffee
+++ client/Core/customlinkview.coffee
@@ -27,19 +27,22 @@

   pistachio:->

-    options = @getOptions()
-    data    = @getData()
+    options            = @getOptions()
+    data               = @getData()
+    {icon, attributes} = options
+    {href}             = attributes

-    data.title ?= options.attributes.href
+    data.title        ?= href  if href isnt '#'

-    tmpl = "{{> @icon}}"
+    {title} = data
+    tmpl    = "{{> @icon}}"

-    if options.icon and data.title
-      if options.icon.placement is 'left'
-        tmpl += "{span.title{ #(title)}}"
-      else
-        tmpl = "{span.title{ #(title)}}" + tmpl
-    else if not options.icon and data.title
+    if icon and title
+      if icon.placement is 'left'
+      then tmpl += "{span.title{ #(title)}}"
+      else tmpl  = "{span.title{ #(title)}}" + tmpl
+
+    else if not icon and title
       tmpl = "{span.title{ #(title)}}"

     return tmpl


Login: reset route added

Login: reset route added

--- client/Login/AppController.coffee
+++ client/Login/AppController.coffee
@@ -9,11 +9,14 @@
       '/:name?/Redeem'      : handler (app)-> app.getView().animateToForm 'redeem'
       '/:name?/Register'    : handler (app)-> app.getView().animateToForm 'register'
       '/:name?/Recover'     : handler (app)-> app.getView().animateToForm 'recover'
+      '/:name?/Reset'       : handler (app)-> app.getView().animateToForm 'reset'
       '/:name?/ResendToken' : handler (app)-> app.getView().animateToForm 'resendEmail'
     hiddenHandle            : yes
     behavior                : 'application'
     preCondition            :
-      condition             : (options, cb)-> cb not KD.isLoggedIn()
+      condition             : (options, cb)->
+        # return cb yes if KD.singleton('router').getCurrentPath() is '/Reset'
+        cb not KD.isLoggedIn()
       failure               : -> KD.getSingleton('router').handleRoute "/Activity"

   constructor:(options = {}, data)->


payment: show current plan depending on state

--- client/Pricing/views/plans.coffee
+++ client/Pricing/views/plans.coffee
@@ -1,4 +1,7 @@
 class PricingPlansView extends KDView
+
+  initialState:
+    currentPlan: 'professional'

   constructor: (options = {}, data) ->

@@ -7,6 +10,10 @@

     super options, data

+    { state } = options
+
+    @state = @utils.extend @initialState, state
+
     @planViews = {}

@@ -14,6 +21,8 @@

     for plan in @plans
       plan.delegate = this
+      planName = plan.title.toLowerCase()
+      plan.cssClass = @utils.curry 'current'  if @state.currentPlan is planName
       @addSubView view = new SinglePlanView plan
       @forwardEvent view, "PlanSelected"

@@ -51,7 +60,7 @@
     monthPrice   : 1900
     yearPrice    : 20520
     description  : 'Great for sad pandas and SEO engineers'
-    cssClass     : 'developer current'
+    cssClass     : 'developer'
     planFeatures : [
       { partial: '1 GB RAM'     , cssClass: 'ram' }
       { partial: '1 Core'       , cssClass: 'cpu' }


remove markdowncode.coffee (move parser dir)

--- packages/rocketchat-markdown/markdowncode.coffee
+++ packages/rocketchat-markdown/markdowncode.coffee
@@ -1,88 +0,0 @@
-###
-# MarkdownCode is a named function that will parse `inline code` and ```codeblock``` syntaxes
-# @param {Object} message - The message object
-###
-import hljs from 'highlight.js';
-
-class MarkdownCode
-	constructor: (message) ->
-
-		if s.trim message.html
-			message.tokens ?= []
-
-			MarkdownCode.handle_codeblocks message
-			MarkdownCode.handle_inlinecode message
-
-			console.log 'Markdown', message if window?.rocketDebug
-
-		return message
-
-	@handle_inlinecode: (message) ->
-		# Support `text`
-		message.html = message.html.replace /(^|>|[ >_*~])\`([^`\r\n]+)\`([<_*~]|\B|\b|$)/gm, (match, p1, p2, p3, offset, text) ->
-			token = "=&=#{Random.id()}=&="
-
-			message.tokens.push
-				token: token
-				text: "#{p1}`</span><span><code class=\"code-colors inline\">#{p2}</code></span><span class=\"copyonly\">`#{p3}"
-				noHtml: match
-
-			return token
-
-
-	@handle_codeblocks: (message) ->
-		# Count occurencies of ```
-		count = (message.html.match(/```/g) || []).length
-
-		if count
-
-			# Check if we need to add a final ```
-			if (count % 2 > 0)
-				message.html = message.html + "\n```"
-				message.msg = message.msg + "\n```"
-
-			# Separate text in code blocks and non code blocks
-			msgParts = message.html.split(/(^.*)(```(?:[a-zA-Z]+)?(?:(?:.|\n)*?)```)(.*\n?)$/gm)
-
-			for part, index in msgParts
-				# Verify if this part is code
-				codeMatch = part.match(/^```(\w*[\n\ ]?)([\s\S]*?)```+?$/)
-
-				if codeMatch?
-					# Process highlight if this part is code
-					singleLine = codeMatch[0].indexOf('\n') is -1
-
-					if singleLine
-						lang = ''
-						code = _.unescapeHTML codeMatch[1] + codeMatch[2]
-					else
-						lang = codeMatch[1]
-						code = _.unescapeHTML codeMatch[2]
-
-					if s.trim(lang) is ''
-						lang = ''
-
-					if s.trim(lang) not in hljs.listLanguages()
-						result = hljs.highlightAuto (lang + code)
-					else
-						result = hljs.highlight s.trim(lang), code
-
-					token = "=&=#{Random.id()}=&="
-
-					message.tokens.push
-						highlight: true
-						token: token
-						text: "<pre><code class='code-colors hljs " + result.language + "'><span class='copyonly'>```
" + result.value + "
```</span></code></pre>"
-						noHtml: "```\n#{s.stripTags(result.value)}\n```"
-
-					msgParts[index] = token
-				else
-					msgParts[index] = part
-
-			# Re-mount message
-			message.html = msgParts.join('')
-
-RocketChat.MarkdownCode = MarkdownCode
-
-# MarkdownCode gets higher priority over Markdown so it's possible place a callback in between (katex for exmaple)
-RocketChat.callbacks.add 'renderMessage', MarkdownCode, RocketChat.callbacks.priority.HIGH - 2, 'markdowncode'


Scoreboard should be a PureComponent

Scoreboard should be a PureComponent

--- resources/assets/coffee/react/beatmapset-page/scoreboard.coffee
+++ resources/assets/coffee/react/beatmapset-page/scoreboard.coffee
@@ -19,7 +19,7 @@
 {div, h2, p} = ReactDOMFactories
 el = React.createElement

-class BeatmapsetPage.Scoreboard extends React.Component
+class BeatmapsetPage.Scoreboard extends React.PureComponent
   DEFAULT_MODS = ['NM', 'EZ', 'NF', 'HT', 'HR', 'SD', 'PF', 'DT', 'NC', 'HD', 'FL', 'SO']
   MANIA_KEY_MODS = ['4K', '5K', '6K', '7K', '8K', '9K']
   MANIA_MODS = ['NM', 'EZ', 'NF', 'HT', 'HR', 'SD', 'PF', 'DT', 'NC', 'FI', 'HD', 'FL']


Revert "Sort the selector according to how it's displayed"

This reverts commit 2cdf70c676ec1318046b854a7cf97fdbe2bd3b8d.

--- resources/assets/coffee/react/beatmapset-page/scoreboard.coffee
+++ resources/assets/coffee/react/beatmapset-page/scoreboard.coffee
@@ -20,10 +20,10 @@
 el = React.createElement

 class BeatmapsetPage.Scoreboard extends React.PureComponent
-  DEFAULT_MODS = ['NM', 'NF', 'EZ', 'HD', 'HR', 'NC', 'DT', 'HT', 'FL', 'SO', 'PF', 'SD']
+  DEFAULT_MODS = ['NM', 'EZ', 'NF', 'HT', 'HR', 'SD', 'PF', 'DT', 'NC', 'HD', 'FL', 'SO']
   OSU_MODS = DEFAULT_MODS.concat('TD')
   MANIA_KEY_MODS = ['4K', '5K', '6K', '7K', '8K', '9K']
-  MANIA_MODS = ['NM', 'NF', 'EZ', 'HD', 'FI', 'HR', 'NC', 'DT', 'HT', 'FL', 'PF', 'SD']
+  MANIA_MODS = ['NM', 'EZ', 'NF', 'HT', 'HR', 'SD', 'PF', 'DT', 'NC', 'FI', 'HD', 'FL']

   hitTypeMapping: =>
     # mapping of [displayed text, internal name] for each mode


Use the Accounts object

Use the Accounts object

--- client/views/social/social.coffee
+++ client/views/social/social.coffee
@@ -15,11 +15,9 @@
       else if (err instanceof Accounts.LoginCancelledError)
         # do nothing
       else if (err instanceof ServiceConfiguration.ConfigError)
-        # FIX THIS
-        loginButtonsSession.configureService(serviceName)
+        Accounts._loginButtonsSession.configureService(serviceName)
       else
-        # FIX THIS
-        loginButtonsSession.errorMessage(err.reason || i18n("error.unknown"))
+        Accounts._loginButtonsSession.errorMessage(err.reason || i18n("error.unknown"))
     loginWithService = Meteor["loginWith" + capitalize(serviceName)]
     options = {}


Fetch OL projects using OAuth

Fetch OL projects using OAuth

--- services/web/app/coffee/Features/Project/OlProjectGetter.coffee
+++ services/web/app/coffee/Features/Project/OlProjectGetter.coffee
@@ -1,6 +1,8 @@
 request = require 'request'
 settings = require 'settings-sharelatex'
+logger = require 'logger-sharelatex'
 Errors = require '../Errors/Errors'
+oAuthRequest = require '../../../../modules/overleaf-integration-web-module/app/coffee/oauth/OAuthRequest'

 makeRequest = (opts, callback) ->
 	if settings.apis?.olProjects?.url?
@@ -12,7 +14,11 @@

 module.exports = OlProjectGetter =
 	findAllUsersProjects: (userId, callback = (error, projects) ->) ->
-		opts =
+		oAuthRequest userId, {
+			url: "#{settings.overleaf.host}/api/v1/sharelatex/docs"
 			method: 'GET'
-			url: '/api/v0/current_user'
-			json: true+			json: true
+		}, (error, docs) ->
+			return callback(error) if error?
+			logger.log {userId, docs}, "got projects from OL"
+			callback(null, docs)


Pad date

Pad date


closes #1

closes #1

--- shared/idle/controllers/global/IdleGlobalStatsController.coffee
+++ shared/idle/controllers/global/IdleGlobalStatsController.coffee
@@ -51,10 +51,10 @@
           stat.max = @getMaxOfStat stat.key

       $scope.getOrderedByXpPercent = ->
-        _.sortBy $scope.players, (player) -> -(player.xp.__current / player.xp.maximum)
+        _.sortBy $scope.players, (player) -> -(player.xp?.__current / player.xp?.maximum) or 0

       $scope.getOrderedByJoinTime = ->
-        _.sortBy $scope.players, (player) -> -player.registrationDate.getTime()
+        _.sortBy $scope.players, (player) -> -player.registrationDate?.getTime() or 0

       $scope.remainderToString = (runnerups) ->
         "Notable Mentions

" +


update links to use the app_root()

update links to use the app_root()

--- app/assets/javascripts/osc_jobs.js.coffee
+++ app/assets/javascripts/osc_jobs.js.coffee
@@ -12,7 +12,7 @@
     show_job_panel()
     $.ajax
       type: 'GET'
-      url: window.location + Routes.osc_job_path(id)
+      url: app_root() + Routes.osc_job_path(id)
       contentType: "application/json; charset=utf-8"
       dataType: "json"
       error: (jqXHR, textStatus, errorThrown) ->
@@ -64,7 +64,7 @@

 @update_copy_button = (id) ->
   if id?
-    $("#copy_button").attr("href", window.location + Routes.copy_osc_job_path(id))
+    $("#copy_button").attr("href", app_root() + Routes.copy_osc_job_path(id))
     $("#copy_button").data("method", "PUT")
     $("#copy_button").removeAttr("disabled")
     $("#copy_button").unbind('click', false)
@@ -75,7 +75,7 @@

 @update_submit_button = (id, status_char) ->
   if id? && !status_char?
-      $("#submit_button").attr("href", window.location + Routes.submit_osc_job_path(id))
+      $("#submit_button").attr("href", app_root() + Routes.submit_osc_job_path(id))
       $("#submit_button").data("method", "PUT")
       $("#submit_button").removeAttr("disabled")
       $("#submit_button").unbind('click', false)
@@ -97,7 +97,7 @@

 @update_template_button = (path, host) ->
   if path?
-    $("#template_button").attr("href", window.location + Routes.new_template_path({ path: path, host: host }))
+    $("#template_button").attr("href", app_root() + Routes.new_template_path({ path: path, host: host }))
     $("#template_button").removeAttr("disabled")
     $("#template_button").unbind('click', false)
   else
@@ -107,7 +107,7 @@

 @update_destroy_button = (id) ->
   if id?
-    $("#destroy_button").attr("href", window.location + Routes.osc_job_path(id))
+    $("#destroy_button").attr("href", app_root() + Routes.osc_job_path(id))
     $("#destroy_button").data("method", "DELETE")
     $("#destroy_button").removeAttr("disabled")
     $("#destroy_button").unbind('click', false)


more detailed error handling

more detailed error handling

--- platform.coffee
+++ platform.coffee
@@ -31,6 +31,12 @@
 -> EXPRESS 4.x!
 ###

+codes =
+	EXITING_CLEANLY: 0
+	UNCAUGHT_EXCEPTION: 1
+	INITIALIZATION_FAILED: 2
+	ADDRESS_IN_USE: 3
+
 module.exports = (args...) ->
 	new Platform args...

@@ -290,43 +296,60 @@

 				said_bye = false
-				exiter = ->
-					unless said_bye
-						end_time = new Date
-
-						unless models_ok and routes_ok and mws_ok
-							winston.error 'yikes! exited early due to problems:'
-
-							if not models_ok
-								winston.error 'models initialization failed'
-							else if not mws_ok
-								winston.error 'middlewares initialization failed'
-							else if not routes_ok
-								winston.error 'routes initialization failed'
-
-						else
-							uptime = undefined
-
-							if start_time? and end_time?
-								hang = moment.duration(end_time - start_time)
-
-								if hang.asSeconds() > 0
-									uptime = ''
-									uptime += (hang.years() + 'y ') if hang.years() > 0
-									uptime += (hang.months() + 'M ') if hang.months() > 0
-									uptime += (hang.days() + 'd ') if hang.days() > 0
-									uptime += (hang.hours() + 'h ') if hang.hours() > 0
-									uptime += (hang.minutes() + 'm ') if hang.minutes() > 0
-									uptime += (hang.seconds() + 's ') if hang.seconds() > 0
-									uptime = uptime.trim()
-
-							winston.info 'platform-ng exiting cleanly. thanks for using!'
-
-							if uptime?
-								winston.info "uptime: #{uptime}"
-
-					said_bye = true
-					process.exit()
-
-				process.on 'exit', exiter
-				process.on 'SIGINT', exiter
+				exiter = (type) ->
+					(error) ->
+						unless said_bye
+							end_time = new Date
+
+							code = codes.EXITING_CLEANLY
+
+							if type is 'uncaughtException'
+								if error.code is 'EADDRINUSE'
+									winston.error "port #{port} is already in use, so I can't bind to it. exiting."
+									code = codes.ADDRESS_IN_USE
+								else
+									winston.error 'uncaught exception causing platform-ng to exit:'
+									winston.error if typeof error is 'string' then error else JSON.stringify(error, null, 4)
+									code = codes.UNCAUGHT_EXCEPTION
+
+							else unless models_ok and routes_ok and mws_ok
+								winston.error 'yikes! exiting early due to problems:'
+
+								if not models_ok
+									winston.error 'models initialization failed'
+								else if not mws_ok
+									winston.error 'middlewares initialization failed'
+								else if not routes_ok
+									winston.error 'routes initialization failed'
+
+								code = codes.INITIALIZATION_FAILED
+
+							else
+								uptime = undefined
+
+								if start_time? and end_time?
+									hang = moment.duration(end_time - start_time)
+
+									if hang.asSeconds() > 0
+										uptime = ''
+										uptime += (hang.years() + 'y ') if hang.years() > 0
+										uptime += (hang.months() + 'M ') if hang.months() > 0
+										uptime += (hang.days() + 'd ') if hang.days() > 0
+										uptime += (hang.hours() + 'h ') if hang.hours() > 0
+										uptime += (hang.minutes() + 'm ') if hang.minutes() > 0
+										uptime += (hang.seconds() + 's ') if hang.seconds() > 0
+										uptime = uptime.trim()
+
+								winston.info 'platform-ng exiting cleanly. thanks for using!'
+
+								if uptime?
+									winston.info "uptime: #{uptime}"
+
+							said_bye = true
+
+						unless type is 'exit'
+							process.exit code
+
+				process.on 'exit', exiter('exit')
+				process.on 'SIGINT', exiter('SIGINT')
+				process.on 'uncaughtException', exiter('uncaughtException')


simplified CRUD routes.

simplified CRUD routes.

--- public/js/app/config/router.coffee
+++ public/js/app/config/router.coffee
@@ -7,33 +7,28 @@
     '!/blocks/add': 'blocksAdd'
     '!/blocks/:id/edit': 'blocksEdit'
     '!/blocks/:id': 'blocksShow'
-
-  dashboard: ->
-    Dashboard = require 'views/dashboard'
-    window.dashboardView = new Dashboard
-    $('#main').html window.dashboardView.render().el

-  # Blocks
-  blocksIndex: ->
-    Collection = require 'collections/blocks'
-    View = require 'views/blocks/index'
+  # CRUD methods
+  _index: (collectionPath, ViewPath, container = '#main') ->
+    Collection = require collectionPath
+    View = require ViewPath
     view = new View
       collection: new Collection
-    $('#main').html view.render().el
+    $(container).html view.render().el

-  blocksAdd: ->
-    Collection = require 'collections/blocks'
-    Model = require 'models/block'
-    View = require 'views/blocks/form'
-
+  _add: (collectionPath, modelPath, viewPath, container = '#main') ->
+    Collection = require collectionPath
+    Model = require modelPath
+    View = require viewPath
+
     view = new View
       collection: new Collection
       model: new Model
-    $('#main').html view.render().el
-
-  blocksEdit: (id) ->
-    Collection = require 'collections/blocks'
-    View = require 'views/blocks/form'
+    $(container).html view.render().el
+
+  _edit: (collectionPath, viewPath, id, container = '#main') ->
+    Collection = require collectionPath
+    View = require viewPath

     collection = new Collection
     collection.fetch
@@ -42,11 +37,11 @@
         view = new View
           collection: collection
           model: model
-        $('#main').html view.render().el
-
-  blocksShow: (id) ->
-    Collection = require 'collections/blocks'
-    View = require 'views/blocks/show'
+        $(container).html view.render().el
+
+  _show: (collectionPath, viewPath, id, container = '#main') ->
+    Collection = require collectionPath
+    View = require viewPath

     collection = new Collection
     collection.fetch
@@ -55,7 +50,26 @@
         view = new View
           collection: collection
           model: model
-        $('#main').html view.render().el
+        $(container).html view.render().el
+
+  # Basic methods
+  dashboard: ->
+    Dashboard = require 'views/dashboard'
+    window.dashboardView = new Dashboard
+    $('#main').html window.dashboardView.render().el
+
+  # Blocks
+  blocksIndex: ->
+    @_index 'collections/blocks', 'views/blocks/index'
+
+  blocksAdd: ->
+    @_add 'collections/blocks', 'models/block', 'views/blocks/form'
+
+  blocksEdit: (id) ->
+    @_edit 'collections/blocks', 'views/blocks/form', id
+
+  blocksShow: (id) ->
+    @_show 'collections/blocks', 'views/blocks/show', id

 module.exports = AppRouter


Simplify Pancakes.Adapter.

Simplify Pancakes.Adapter.

The FixtureAdapter isn't really needed anymore.

--- app/assets/javascripts/adapter.coffee
+++ app/assets/javascripts/adapter.coffee
@@ -1,14 +1,8 @@
-adapter = if window.location.search.lastIndexOf('fixture') != -1
-            DS.FixtureAdapter.extend
-              latency: 250
-          else
-            DS.RESTAdapter.configure 'plurals',
-              event_search: 'event_searches'
+Pancakes.Adapter = DS.RESTAdapter.extend
+  namespace: 'api/v1'

-            DS.RESTAdapter.extend
-              namespace: 'api/v1'
-
-Pancakes.Adapter = adapter
+Pancakes.Adapter.configure 'plurals',
+  event_search: 'event_searches'

 Pancakes.Adapter.map 'Pancakes.EventType',
   primaryKey: 'local_code'


スクロールを修正

スクロールを修正

--- app/assets/javascripts/chat.js.coffee
+++ app/assets/javascripts/chat.js.coffee
@@ -16,8 +16,8 @@
       e.preventDefault()
       @sendMessage()
     # サーバーからnew_messageを受け取ったらreceiveMessageを実行
-    @dispatcher.bind 'new_message', @receiveMessage
-    @channel.bind 'new_message', @receiveSystemMessage
+    @dispatcher.bind 'new_message', @receiveSystemMessage
+    @channel.bind 'new_message', @receiveMessage
     @privateChannel.bind 'new_message', @receivePrivateMessage

   setChannelCode: () =>
@@ -51,16 +51,17 @@
       height += $(this).height()
     $('#chat dt').each ->
       height += $(this).height()
-    console.log height
-    $('#chat').animate({scrollTop: $('#chat').prop("scrollHeight") }, 500);
+    $('#chat').scrollTo('+=100px', 500)

   receivePrivateMessage: (message) =>
     # 受け取ったデータをappend
     $('#chat').append "
#{message.user_name} :

#{message.body}
"
+    $('#chat').scrollTo('+=100px', 500)

   receiveSystemMessage: (message) =>
     # 受け取ったデータをappend
     $('#chat').append "
#{message.user_name} :

#{message.body}
"
+    $('#chat').stop().scrollTo('100%', 1500)

 $ ->
   window.chatClass = new ChatClass($('#chat').data('uri'), true)


manyboxplots: Add title to histogram

manyboxplots: Add title to histogram

--- manyboxplots/manyboxplots.coffee
+++ manyboxplots/manyboxplots.coffee
@@ -219,18 +219,30 @@
      .attr("x", (d) -> lowxScale(d))
      .attr("dominant-baseline", "middle")
      .attr("text-anchor", "middle")
-
+
   histline = d3.svg.line()
         .x((d,i) -> lowxScale(data.br[i]))
         .y((d) -> lowyScale(d))

+  randomInd = data.ind[Math.floor(Math.random()*data.ind.length)]
+
   hist = lowsvg.append("path")
-    .datum(data.counts["Mouse3084"])
+    .datum(data.counts[randomInd])
        .attr("d", histline)
        .attr("id", "histline")
        .attr("fill", "none")
        .attr("stroke", "purple")
        .attr("stroke-width", "2")
+
+
+  lowsvg.append("text")
+        .datum(randomInd)
+        .attr("x", w/2)
+        .attr("y", pad/2)
+        .text((d) -> d)
+        .attr("id", "histtitle")
+        .attr("text-anchor", "middle")
+        .attr("dominant-baseline", "middle")

   indRect
     .on("mouseover", (d) ->
@@ -238,6 +250,9 @@
               d3.select("#histline")
                  .datum(data.counts[d])
                  .attr("d", histline)
+              d3.select("#histtitle")
+                 .datum(d)
+                 .text((d) -> d)
             )
     .on("mouseout", (d) ->
               d3.select(this).attr("opacity", "0")


GitLab: events export events

GitLab: events export events

--- servers/lib/server/handlers/api/gitlab/_events.coffee
+++ servers/lib/server/handlers/api/gitlab/_events.coffee
@@ -1,7 +1,7 @@
 # Events from GitLab System Hooks
 # Extracted from http://docs.gitlab.com/ee/system_hooks/system_hooks.html

-KNOWN_EVENTS = [
+module.exports = KNOWN_EVENTS = [
   'project_create'
   'project_destroy'
   'project_rename'


simplify

simplify

--- log.coffee
+++ log.coffee
@@ -12,7 +12,7 @@

 fail = (message) ->
   throw
-    name: '2cpyError'
+    name: "2cpyError"
     message: message

 # ### Public API


Adjust log file name.

Adjust log file name.

--- src/coffee/run.coffee
+++ src/coffee/run.coffee
@@ -20,7 +20,7 @@
 logger = new Logger
   streams: [
     { level: 'error', stream: process.stderr }
-    { level: argv.logLevel, path: "#{argv.logDir}/sphere-order-distribution-#{argv.projectKey}.log" }
+    { level: argv.logLevel, path: "#{argv.logDir}/sphere-order-distribution_#{argv.projectKey}.log" }
   ]

 options =


Allow to specify target directory. Closes #14

--- src/coffee/run.coffee
+++ src/coffee/run.coffee
@@ -1,3 +1,4 @@
+path = require 'path'
 _ = require 'underscore'
 Promise = require 'bluebird'
 fs = Promise.promisifyAll require('fs')
@@ -14,7 +15,8 @@
   .describe('sphereHost', 'SPHERE.IO API host to connecto to')
   .describe('fetchHours', 'Number of hours to fetch modified orders')
   .describe('standardShippingMethod', 'Allows to define the fallback shipping method name of order has none')
-  .describe('useExportTmpDir', 'whether to use a tmp folder to store resulting XML files in or not (if no, files will be created under \'./exports\')')
+  .describe('targetDir', 'the folder where exported files are saved')
+  .describe('useExportTmpDir', 'whether to use a system tmp folder to store exported files')
   .describe('csvTemplate', 'CSV template to define the structure of the export - if present only one CSV file will be generated, otherwise XML files')
   .describe('csvFile', "CSV file to export template to, otherwise see option 'useExportTmpDir'")
   .describe('fileWithTimestamp', 'whether exported file should contain a timestamp')
@@ -31,6 +33,7 @@
   .default('fetchHours', 0) # by default don't restrict on modifications
   .default('standardShippingMethod', 'None')
   .default('useExportTmpDir', false)
+  .default('targetDir', path.join(__dirname,'../exports'))
   .default('fileWithTimestamp', false)
   .default('logLevel', 'info')
   .default('logDir', '.')
@@ -73,7 +76,7 @@
     # unsafeCleanup: recursively removes the created temporary directory, even when it's not empty
     tmp.dirAsync {unsafeCleanup: true}
   else
-    exportsPath = "#{__dirname}/../exports"
+    exportsPath = argv.targetDir
     fsExistsAsync(exportsPath)
     .then (exists) ->
       if exists


bugfix

bugfix

--- src/render/renderPageWithComponent.coffee
+++ src/render/renderPageWithComponent.coffee
@@ -106,11 +106,10 @@
           rejectUnauthorized: false
           json: true
         request clumperUrl, reqOptions, (err, response, deps) ->
-            file.fileId + file.version
           unless deps?.files?.length > 0
             console.log 'uh oh, no deps from clumper?', deps
           return finish() unless deps?.files?.length > 0
-          files = _.filter deps.files, (file) ->
+          files = _.filter _.compact(deps?.files ? []), (file) ->
             -1 == String(req.cookies?.clumper ? '').indexOf file.fileId + file.version
           console.log 'injecting', files.length, _.map files, 'name'
           injectedScripts = """


fixed JSON call timing

fixed JSON call timing

--- app/assets/javascripts/maps.js.coffee
+++ app/assets/javascripts/maps.js.coffee
@@ -78,12 +78,6 @@
     heatmapData = []
     heatmapBounds = new google.maps.LatLngBounds()

-    $.getJSON '/violations/heatmap.json', (data, textStatus, jqXHR) ->
-      for v in data.violations
-        vLatLng = new google.maps.LatLng v.latitude, v.longitude
-        heatmapData.push vLatLng
-        heatmapBounds.extend vLatLng
-
     heatmap = new google.maps.Map document.getElementById("violation_heatmap"),
       center: default_latlng,
       zoom: 12,
@@ -91,9 +85,15 @@
       streetViewControl: false,
       mapTypeControl: false

-    heatmap_layer = new google.maps.visualization.HeatmapLayer
-      data: heatmapData
+    $.getJSON '/violations/heatmap.json', (data, textStatus, jqXHR) ->
+      for v in data.violations
+        vLatLng = new google.maps.LatLng v.latitude, v.longitude
+        heatmapData.push vLatLng
+        heatmapBounds.extend vLatLng

-    heatmap.setCenter heatmapBounds.getCenter()
-    heatmap.fitBounds heatmapBounds
-    heatmap_layer.setMap heatmap+      heatmap_layer = new google.maps.visualization.HeatmapLayer
+        data: heatmapData
+
+      heatmap.setCenter heatmapBounds.getCenter()
+      heatmap.fitBounds heatmapBounds
+      heatmap_layer.setMap heatmap


Fix #82

Fix #82

--- app/assets/javascripts/top4.js.coffee
+++ app/assets/javascripts/top4.js.coffee
@@ -11,7 +11,7 @@
       # Only select the top 3 contributors and put the rest in and 'other' user
       repo.contributors = repo_contributors[0..2]
       if repo_contributors.length > 3
-        repo.contributors +=
+        repo.contributors.push
           github_name: 'other'
           score: d3.sum(repo_contributors[3..], (d) -> d.score)


fix typo

fix typo

--- app/assets/javascripts/wish.js.coffee
+++ app/assets/javascripts/wish.js.coffee
@@ -1,5 +1,5 @@
 $ ->
-  wishPlaceholders = [ "showed more detail", "were less technical", "had more documentation" ]
+  wishPlaceholders = [ "showed more detail", "was less technical", "had more documentation" ]
   currentPlaceholder = wishPlaceholders[Math.floor(Math.random()*wishPlaceholders.length)]
   $("#wish-value").attr("placeholder", currentPlaceholder)


adapt issues list for include/exclude filter modes

--- app/coffee/modules/issues/list.coffee
+++ app/coffee/modules/issues/list.coffee
@@ -61,6 +61,18 @@

     filtersHashSuffix: "issues-filters"
     myFiltersHashSuffix: "issues-my-filters"
+    excludePrefix: "exclude_"
+    filterCategories: [
+        "tags",
+        "status",
+        "type",
+        "severity",
+        "priority",
+        "assigned_to",
+        "owner",
+        "role",
+    ]
+

     constructor: (@scope, @rootscope, @repo, @confirm, @rs, @urls, @params, @q, @location, @appMetaService,
                   @navUrls, @events, @analytics, @translate, @errorHandlingService, @storage, @filterRemoteStorageService, @projectService) ->
@@ -114,13 +126,13 @@

     removeFilter: (filter) ->
         @.unselectFilter("page")
-        @.unselectFilter(filter.dataType, filter.id)
+        @.unselectFilter(filter.dataType, filter.id, false, filter.mode)
         @.loadIssues()
         @.generateFilters()

     addFilter: (newFilter) ->
         @.unselectFilter("page")
-        @.selectFilter(newFilter.category.dataType, newFilter.filter.id)
+        @.selectFilter(newFilter.category.dataType, newFilter.filter.id, false, newFilter.mode)
         @.loadIssues()
         @.generateFilters()

@@ -165,20 +177,16 @@

     generateFilters: ->
         @.storeFilters(@params.pslug, @location.search(), @.filtersHashSuffix)
-
         urlfilters = @location.search()

         loadFilters = {}
         loadFilters.project = @scope.projectId
-        loadFilters.tags = urlfilters.tags
-        loadFilters.status = urlfilters.status
-        loadFilters.type = urlfilters.type
-        loadFilters.severity = urlfilters.severity
-        loadFilters.priority = urlfilters.priority
-        loadFilters.assigned_to = urlfilters.assigned_to
-        loadFilters.owner = urlfilters.owner
-        loadFilters.role = urlfilters.role
         loadFilters.q = urlfilters.q
+
+        for key in @.filterCategories
+            excludeKey = @.excludePrefix.concat(key)
+            loadFilters[key] = urlfilters[key]
+            loadFilters[excludeKey] = urlfilters[excludeKey]

         return @q.all([
             @rs.issues.filtersData(loadFilters),
@@ -186,32 +194,33 @@
         ]).then (result) =>
             data = result[0]
             customFiltersRaw = result[1]
-
-            statuses = _.map data.statuses, (it) ->
+            dataCollection = {}
+
+            dataCollection.statuses = _.map data.statuses, (it) ->
                 it.id = it.id.toString()

                 return it
-            type = _.map data.types, (it) ->
+            dataCollection.type = _.map data.types, (it) ->
                 it.id = it.id.toString()

                 return it
-            severity = _.map data.severities, (it) ->
+            dataCollection.severity = _.map data.severities, (it) ->
                 it.id = it.id.toString()

                 return it
-            priority = _.map data.priorities, (it) ->
+            dataCollection.priority = _.map data.priorities, (it) ->
                 it.id = it.id.toString()

                 return it
-            tags = _.map data.tags, (it) ->
+            dataCollection.tags = _.map data.tags, (it) ->
                 it.id = it.name

                 return it

-            tagsWithAtLeastOneElement = _.filter tags, (tag) ->
+            tagsWithAtLeastOneElement = _.filter dataCollection.tags, (tag) ->
                 return tag.count > 0

-            assignedTo = _.map data.assigned_to, (it) ->
+            dataCollection.assignedTo = _.map data.assigned_to, (it) ->
                 if it.id
                     it.id = it.id.toString()
                 else
@@ -220,12 +229,12 @@
                 it.name = it.full_name || "Unassigned"

                 return it
-            owner = _.map data.owners, (it) ->
+            dataCollection.owner = _.map data.owners, (it) ->
                 it.id = it.id.toString()
                 it.name = it.full_name

                 return it
-            role = _.map data.roles, (it) ->
+            dataCollection.role = _.map data.roles, (it) ->
                 if it.id
                     it.id = it.id.toString()
                 else
@@ -237,37 +246,14 @@

             @.selectedFilters = []

-            if loadFilters.status
-                selected = @.formatSelectedFilters("status", statuses, loadFilters.status)
-                @.selectedFilters = @.selectedFilters.concat(selected)
-
-            if loadFilters.tags
-                selected = @.formatSelectedFilters("tags", tags, loadFilters.tags)
-                @.selectedFilters = @.selectedFilters.concat(selected)
-
-            if loadFilters.assigned_to
-                selected = @.formatSelectedFilters("assigned_to", assignedTo, loadFilters.assigned_to)
-                @.selectedFilters = @.selectedFilters.concat(selected)
-
-            if loadFilters.owner
-                selected = @.formatSelectedFilters("owner", owner, loadFilters.owner)
-                @.selectedFilters = @.selectedFilters.concat(selected)
-
-            if loadFilters.type
-                selected = @.formatSelectedFilters("type", type, loadFilters.type)
-                @.selectedFilters = @.selectedFilters.concat(selected)
-
-            if loadFilters.severity
-                selected = @.formatSelectedFilters("severity", severity, loadFilters.severity)
-                @.selectedFilters = @.selectedFilters.concat(selected)
-
-            if loadFilters.priority
-                selected = @.formatSelectedFilters("priority", priority, loadFilters.priority)
-                @.selectedFilters = @.selectedFilters.concat(selected)
-
-            if loadFilters.role
-                selected = @.formatSelectedFilters("role", role, loadFilters.role)
-                @.selectedFilters = @.selectedFilters.concat(selected)
+            for key in @.filterCategories
+                excludeKey = @.excludePrefix.concat(key)
+                if loadFilters[key]
+                    selected = @.formatSelectedFilters(key, dataCollection[key], loadFilters[key])
+                    @.selectedFilters = @.selectedFilters.concat(selected)
+                if loadFilters[excludeKey]
+                    selected = @.formatSelectedFilters(key, dataCollection[key], loadFilters[excludeKey], "exclude")
+                    @.selectedFilters = @.selectedFilters.concat(selected)

             @.filterQ = loadFilters.q

@@ -275,44 +261,44 @@
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.TYPE"),
                     dataType: "type",
-                    content: type
+                    content: dataCollection.type
                 },
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.SEVERITY"),
                     dataType: "severity",
-                    content: severity
+                    content: dataCollection.severity
                 },
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.PRIORITIES"),
                     dataType: "priority",
-                    content: priority
+                    content: dataCollection.priority
                 },
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.STATUS"),
                     dataType: "status",
-                    content: statuses
+                    content: dataCollection.statuses
                 },
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.TAGS"),
                     dataType: "tags",
-                    content: tags,
+                    content: dataCollection.tags,
                     hideEmpty: true,
                     totalTaggedElements: tagsWithAtLeastOneElement.length
                 },
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.ASSIGNED_TO"),
                     dataType: "assigned_to",
-                    content: assignedTo
+                    content: dataCollection.assignedTo
                 },
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.ROLE"),
                     dataType: "role",
-                    content: role
+                    content: dataCollection.role
                 },
                 {
                     title: @translate.instant("COMMON.FILTERS.CATEGORIES.CREATED_BY"),
                     dataType: "owner",
-                    content: owner
+                    content: dataCollection.owner
                 }
             ]


Use updated endpoint and fix for legacy endpoint

--- collections/user_interests.coffee
+++ collections/user_interests.coffee
@@ -6,24 +6,28 @@
 module.exports = class UserInterests extends Backbone.Collection
   model: UserInterest

+  interestType: 'Artist' # Should/will be configurable
+
   url: ->
-    if (id = @collectorProfile?.id)?
-      "#{API_URL}/api/v1/collector_profile/#{id}/user_interest"
+    if @collectorProfile?
+      "#{API_URL}/api/v1/user_interests"
+    else
+      "#{API_URL}/api/v1/me/user_interest/artists"
+
+  initialize: (models, { @collectorProfile } = {}) ->
+    @model::urlRoot = if @collectorProfile?
+      "#{API_URL}/api/v1/user_interest"
     else
       "#{API_URL}/api/v1/me/user_interest"
-
-  initialize: (models, { @collectorProfile } = {}) -> #

   parse: (response) ->
     _.filter response, (obj) ->
       not _.isEmpty(obj.interest)

   fetch: (options = {}) ->
-    options.url = "#{@url()}/artists" # Temporary hack for this non-RESTful endpoint
-
     if @collectorProfile?
-      options.data = _.extend options.data or {}, @collectorProfile.pick('anonymous_session_id')
-
+      options.data = _.extend options.data or {}, @owner(),
+        interest_type: @interestType
     super options

   comparator: (userInterest) ->
@@ -36,9 +40,15 @@
   alreadyInterested: (interest) ->
     @findByInterestId(interest.id)?

+  owner: ->
+    if @collectorProfile?
+      owner_id: @collectorProfile.id, owner_type: 'CollectorProfile'
+
   addInterest: (interest) ->
     return if @alreadyInterested interest

-    @unshift
+    @unshift _.extend {
+      interest_type: @interestType
       interest_id: interest.id
       interest: interest.attributes
+    }, @owner()


Checked asset name validation (still same as c++ code), updated comments

--- dl/src/common/validation.coffee
+++ dl/src/common/validation.coffee
@@ -5,8 +5,7 @@
     Account names may contain one or more names separated by a dot.
     Each name needs to start with a letter and may contain
     numbers, or well placed dashes.
-
-    @see graphene/libraries/chain/protocol/account.cpp is_valid_name
+    @see is_valid_name graphene/libraries/chain/protocol/account.cpp
     ###
     is_account_name: (value, allow_too_short = false)->
         return no if is_empty value
@@ -54,6 +53,7 @@
             throw new Error "value required for #{field_name}: #{value}"
         value

+    ###* @see is_valid_symbol graphene/libraries/chain/protocol/asset_ops.cpp ###
     is_valid_symbol_error: (value) ->
         suffix = "Asset name should "
         return suffix + "not be empty." if is_empty value
@@ -62,7 +62,6 @@
         return suffix + "be shorter." if value.length > 16
         return suffix + "start with a letter" unless /^[A-Z]/.test value
         return suffix + "end with a letter" unless /[A-Z]$/.test value
-        #return "not start with BIT." if /^BIT/.test value # scam_pattern
         return suffix + "contain only letters numbers and perhaps a dot." if /^[A-Z0-9\.]$/.test value
         return null


Ignore empty results sets

Ignore empty results sets

--- app/assets/javascripts/analysis/views/area_view.coffee
+++ app/assets/javascripts/analysis/views/area_view.coffee
@@ -76,7 +76,7 @@
     return "#{timeInYears} years"

   resultsToObj: ->
-    if @area.get('results')?
+    if @area.get('results')? && @area.get('results').length > 0
       results =
         sum: {}
         habitats: {}


Fix checkbox to slide correctly only when ticked

--- app/assets/javascripts/components/users/base.js.coffee
+++ app/assets/javascripts/components/users/base.js.coffee
@@ -25,7 +25,10 @@

   @respondentsTable: ->
     $('.delegate-box').on('click', ->
-      $('.respondents-list').slideToggle()
+      if $(@).attr('checked')
+        $('.respondents-list').slideDown()
+      else
+        $('.respondents-list').slideUp()
     )

 $(document).ready -> UsersComponent.initialize()


fix displaying of info and errors

fix displaying of info and errors

--- app/assets/javascripts/hctbox/display_errors.js.coffee
+++ app/assets/javascripts/hctbox/display_errors.js.coffee
@@ -9,8 +9,9 @@
     for entry in @json
       tds = ['' + tableIndex + '	']
       for key, val of entry
-        td = '' + val + '	'
-        tds.push td
+        if key == 'type' || key == 'message'
+          td = '' + val + '	'
+          tds.push td

       row = '
' + tds.join('') + '
'
       tableRows.push row
@@ -18,14 +19,13 @@
       ++tableIndex

     table =
-      '
' +
+      '
' +
       '
' +
       '    ' + tableRows.join('') +
       '
' +
       '
'

     modalHtml = @createModal(table)
-    console.info modalHtml
     $('#js-modal .modal').modal('hide')
     $('#js-modal').html(modalHtml)
     $('#js-modal .modal').modal()