use checkBongoConnectiviy in machine.test.coffee

--- workers/social/lib/social/models/computeproviders/machine.test.coffee
+++ workers/social/lib/social/models/computeproviders/machine.test.coffee
@@ -1,34 +1,22 @@
-{ argv }                      = require 'optimist'
-{ expect }                    = require 'chai'
-{ env : { MONGO_URL } }       = process
-
-KONFIG                        = require('koding-config-manager').load("main.#{argv.c}")
-
-Bongo                         = require 'bongo'
 JUser                         = require '../user/index'
-mongo                         = MONGO_URL or "mongodb://#{ KONFIG.mongo }"
 JMachine                      = require './machine'

-{ daisy }                     = Bongo
 { createUserAndMachine
   generateMachineParams }     = require '../../../../testhelper/models/machinehelper'

-{ generateUserInfo
+{ daisy
+  expect
+  generateUserInfo
   generateDummyClient
   generateRandomString
+  checkBongoConnectivity
   generateDummyUserFormData } = require '../../../../testhelper'

 # this function will be called once before running any test
 beforeTests = -> before (done) ->

-  bongo = new Bongo
-    root   : __dirname
-    mongo  : mongo
-    models : ''
-
-  bongo.once 'dbClientReady', ->
-    done()
+  checkBongoConnectivity done

 # here we have actual tests


Naming!

Naming!

--- source/changers/AlgAnimation.js.coffee
+++ source/changers/AlgAnimation.js.coffee
@@ -5,10 +5,10 @@
   update: (now) ->
     return if @_finished

-    if @changer.finished()
+    if @move_changer.finished()
       this._next_alg_move()

-    @changer.update(now)
+    @move_changer.update(now)

   finish: ->
     # API creep
@@ -20,4 +20,4 @@
     if @alg.at_end() || not @alg.playing
       @_finished = true
     else
-      @changer = @alg.next_move().show_do()
+      @move_changer = @alg.next_move().show_do()


Add concurrent updates spec

Add concurrent updates spec

--- spec/updates-panel-spec.coffee
+++ spec/updates-panel-spec.coffee
@@ -107,6 +107,13 @@
         expect(panel.updateAllButton.prop('disabled')).toBe false
         expect(panel.updateAllButton).toBeVisible()

+    it 'does not attempt to update packages that are already updating', ->
+      cardA.update()
+      packageManager.emitPackageEvent 'updating', packA
+      panel.updateAll()
+
+      expect(cardA.update.calls.length).toBe 1
+
   describe 'the Check for Updates button', ->
     pack =
       name: 'test-package'


Update opcode definition highlighting

Update opcode definition highlighting

--- grammars/csound.cson
+++ grammars/csound.cson
@@ -47,8 +47,8 @@
             patterns: [
               {
                 name:  "meta.opcode-type-signature.csound"
-                # https://github.com/csound/csound/search?q=XIDENT+path%3AEngine+filename%3Acsound_orc.lex
-                begin: "\\b(?:0|[afijkKoOpPStV\\[\\]]+)"
+                # https://csound.com/docs/manual/opcode.html
+                begin: "\\b(?:0|[aijkOPVKopS\\[\\]]+)"
                 end:   ",|$"
                 beginCaptures: 0: name: "storage.type.csound"
                 patterns: [include: "#commentsAndMacroUses"]


Fix boundary-matching of device control lines

--- grammars/output.cson
+++ grammars/output.cson
@@ -89,7 +89,7 @@
 		patterns: [{
 			# Arbitrary device control function generated by \X
 			name: "meta.custom.device-control.ditroff"
-			begin: "^\\s*(x)\\s*(X\\S*)"
+			begin: "(x)\\s*(X\\S*)"
 			end:   "^(?!\\+)"
 			beginCaptures:
 				1: name: "keyword.operator.other.ditroff"
@@ -102,7 +102,7 @@
 		},{
 			# Everything else
 			name: "meta.device-control.ditroff"
-			begin: "^\\s*(x)\\s*"
+			begin: "(x)\\s*"
 			end:   "(?=$|#)"
 			beginCaptures:
 				1: name: "keyword.operator.other.ditroff"
@@ -305,5 +305,5 @@

 	# Paddable word-space: information only, no action
 	wordSpace:
-		name: "entity.name.function.ditroff"
+		name: "entity.name.function.word-space.ditroff"
 		match: "(?<=^|[\\s\\d])w"


Start new instance of flight before the backbone router.

--- js/application.coffee
+++ js/application.coffee
@@ -11,9 +11,10 @@
     console.log message

   init: ->
+    window.flight = new Flight();
+
     new @Routers.AppRouter

-    window.flight = new Flight();
     Backbone.history.start()

 window.app = new App


Refactored supplier test

Refactored supplier test

--- test/supplier.coffee
+++ test/supplier.coffee
@@ -10,7 +10,16 @@
     beforeEach ->
         supply = supplier()

-    it "should be configurable", ->
+    it "should extend event emitter", ->
+        catched = false
+
+        supply.on "event", ->
+            catched = true
+
+        supply.emit "event"
+        assert.equal true, catched
+
+    it "should contain configuration", ->
         supply.set "foo", "bar"
         assert.equal "bar", supply.get "foo"

@@ -23,76 +32,67 @@
             supply.use plugin
             assert.equal 1, supply.plugins.length()

-    it "should extend event emitter", ->
-        catched = false
+        it "should emit 'configured' after all plugins configured", (callback) ->
+            configured = false

-        supply.on "event", ->
-            catched = true
+            supply.on "configured", ->
+                configured = true

-        supply.emit "event"
-        assert.equal true, catched
+            plugin0 = fakePlugin()
+            plugin1 = fakePlugin()

-    it "should emit 'configured' after all plugins configured", (callback) ->
-        configured = false
+            supply.use plugin0.factory()
+            supply.use plugin1.factory()

-        supply.on "configured", ->
-            configured = true
-
-        plugin0 = fakePlugin()
-        plugin1 = fakePlugin()
-
-        supply.use plugin0.factory()
-        supply.use plugin1.factory()
-
-        assert.equal false, configured
-
-        process.nextTick ->
-            plugin0.configured()
             assert.equal false, configured
-            plugin1.configured()
-
-            assert.equal true, configured
-            callback()
-
-    it "should emit 'loaded' after all plugins loaded", (callback) ->
-        loaded = false
-
-        supply.on "loaded", ->
-            loaded = true
-
-        plugin0 = fakePlugin()
-        plugin1 = fakePlugin()
-
-        supply.use plugin0.factory()
-        supply.use plugin1.factory()
-
-        assert.equal false, loaded
-
-        process.nextTick ->
-            plugin0.loaded()
-            assert.equal false, loaded
-            plugin1.loaded()
-
-            assert.equal true, loaded
-            callback()
-
-    it "should allow include one plugin in another", (callback) ->
-        loaded = false
-
-        supply.on "loaded", ->
-            loaded = true
-
-        plugin0 = fakePlugin()
-
-        supply.use (supply, pluginCallback) ->
-            supply.use plugin0.factory()
-            pluginCallback()

             process.nextTick ->
+                plugin0.configured()
+                assert.equal false, configured
+                plugin1.configured()
+
+                assert.equal true, configured
+                callback()
+
+        it "should emit 'loaded' after all plugins loaded", (callback) ->
+            loaded = false
+
+            supply.on "loaded", ->
+                loaded = true
+
+            plugin0 = fakePlugin()
+            plugin1 = fakePlugin()
+
+            supply.use plugin0.factory()
+            supply.use plugin1.factory()
+
+            assert.equal false, loaded
+
+            process.nextTick ->
+                plugin0.loaded()
                 assert.equal false, loaded
-                plugin0.loaded()
+                plugin1.loaded()
+
                 assert.equal true, loaded
                 callback()
+
+        it "should allow include one plugin in another", (callback) ->
+            loaded = false
+
+            supply.on "loaded", ->
+                loaded = true
+
+            plugin0 = fakePlugin()
+
+            supply.use (supply, pluginCallback) ->
+                supply.use plugin0.factory()
+                pluginCallback()
+
+                process.nextTick ->
+                    assert.equal false, loaded
+                    plugin0.loaded()
+                    assert.equal true, loaded
+                    callback()

     describe "wait", ->
         it "should run all listeners after value setted", (callback) ->


Fetch objects: No render option means it shouldn't be modified.

--- engine/fetch_assets.coffee
+++ engine/fetch_assets.coffee
@@ -113,13 +113,14 @@
 # This returns a promise of all things necessary to display the object
 # (meshes, textures, materials)
 fetch_objects = (object_list, options={}) ->
-    render = options.render or true
+    {render} = options
     if not object_list.length
         return Promise.resolve()

     promises = []
     for ob in object_list
-        ob.render = render
+        if render?
+            ob.render = render
         if ob.type == 'MESH'
             {scene} = ob
             promises.push fetch_mesh(ob, options)


Remove trailing whitespaces

Remove trailing whitespaces

--- client/landing/app/Applications/Ace.kdapplication/AppController.coffee
+++ client/landing/app/Applications/Ace.kdapplication/AppController.coffee
@@ -38,7 +38,6 @@
     else
       @bringToFront new AceView {}, file

-
   removeOpenDocument:(doc)->

     if doc
@@ -70,7 +69,7 @@

     file.on "fs.delete.finished", => @removeOpenDocument @aceViews[file.path]

-
   clearFileRecords:(view)->
     file = view.getData()
-    delete @aceViews[file.path]+    delete @aceViews[file.path]
+


Renamed 'publish' to 'broadcast'

Renamed 'publish' to 'broadcast'

--- game.coffee
+++ game.coffee
@@ -22,8 +22,8 @@
     @state = null
     @pointsPerFrame = 100

-  publish: (type, data) =>
-    console.log "Publish: #{type}: #{JSON.stringify(data)}"
+  broadcast: (type, data) =>
+    console.log "Broadcast: #{type}: #{JSON.stringify(data)}"
     @sockets.in(@id).emit(type, data)

   startGame: =>
@@ -34,7 +34,7 @@
     @inProgress = true
     @frameTimer = setInterval(@tick, @frameInterval)

-    @publish('startGame')
+    @broadcast('startGame')

   fetchFrameState: =>
     state =
@@ -84,7 +84,7 @@

   publishFrameState: =>
     @state = @fetchFrameState()
-    @publish('updateGameState', @state)
+    @broadcast('updateGameState', @state)

   tick: =>
     @updateFrameState()


fix for ssh_enabled_now when nodes becomes nil

--- js/inner/build.coffee
+++ js/inner/build.coffee
@@ -183,7 +183,7 @@
             "unknown"

     @ssh_enabled_now = @komp =>
-        (n for n in @node() when n.ssh_enabled).length > 0
+      @node() and _.some(@node(), (n) -> n.ssh_enabled)

     @can_cancel = @komp =>
       if @status() == "canceled"


add command to toggle treeview in the result corresponding to the current cursor position

fixes JunoLab/atom-julia-client#61

--- lib/editor/results.coffee
+++ lib/editor/results.coffee
@@ -12,6 +12,7 @@
     @subs.add atom.commands.add 'atom-text-editor:not([mini])',
       'inline-results:clear-current': (e) => @removeCurrent e
       'inline-results:clear-all': => @removeAll()
+      'inline-results:toggle': => @toggleCurrent()

     @subs.add atom.commands.add '.ink.inline',
       'inline-results:clear': (e) ->
@@ -139,3 +140,10 @@
       if @removeLines(ed, sel.getHeadBufferPosition().row, sel.getTailBufferPosition().row)
         done = true
     e.abortKeyBinding() unless done
+
+  toggleCurrent: ->
+    ed = atom.workspace.getActiveTextEditor()
+    pos = ed.getCursorBufferPosition()
+    ms = ed.findMarkers {containsBufferPosition: pos}
+    m = ms.filter((m)->m.result?).map((m)->m.result)
+    m[0]?.view.firstElementChild?.firstElementChild?.click()


Map the rest of the lower case registers

--- keymaps/vim-mode.cson
+++ keymaps/vim-mode.cson
@@ -44,6 +44,22 @@
   '" h': 'vim-mode:register-prefix'
   '" i': 'vim-mode:register-prefix'
   '" j': 'vim-mode:register-prefix'
+  '" k': 'vim-mode:register-prefix'
+  '" l': 'vim-mode:register-prefix'
+  '" m': 'vim-mode:register-prefix'
+  '" n': 'vim-mode:register-prefix'
+  '" o': 'vim-mode:register-prefix'
+  '" p': 'vim-mode:register-prefix'
+  '" q': 'vim-mode:register-prefix'
+  '" r': 'vim-mode:register-prefix'
+  '" s': 'vim-mode:register-prefix'
+  '" t': 'vim-mode:register-prefix'
+  '" u': 'vim-mode:register-prefix'
+  '" v': 'vim-mode:register-prefix'
+  '" w': 'vim-mode:register-prefix'
+  '" x': 'vim-mode:register-prefix'
+  '" y': 'vim-mode:register-prefix'
+  '" z': 'vim-mode:register-prefix'
   '" *': 'vim-mode:register-prefix'
   '" +': 'vim-mode:register-prefix'
   '" %': 'vim-mode:register-prefix'


KernelManager: Don't save kernel specs to settings

--- lib/kernel-manager.coffee
+++ lib/kernel-manager.coffee
@@ -11,6 +11,7 @@
 class KernelManager
     constructor: ->
         @_runningKernels = {}
+        @_kernelSpecs = []

     destroy: ->
@@ -91,8 +92,7 @@

     getAllKernelSpecs: ->
-        kernelSpecs = _.map @parseKernelSpecSettings(), 'spec'
-        return kernelSpecs
+        return _.clone @_kernelSpecs

     getAllKernelSpecsFor: (language) ->
@@ -162,10 +162,10 @@
         kernelSpecs = @parseKernelSpecSettings()
         _.assign kernelSpecs, newKernelSpecs

-        Config.setJson 'kernelspec', kernelspecs: kernelSpecs
+        @_kernelSpecs = _.map kernelSpecs, 'spec'

         message = 'Hydrogen Kernels updated:'
-        options = detail: (_.map kernelSpecs, 'spec.display_name').join('\n')
+        options = detail: (_.map @_kernelSpecs, 'display_name').join('\n')
         atom.notifications.addInfo message, options


getConfigJson + setConfigJson

getConfigJson + setConfigJson

--- lib/kernel-manager.coffee
+++ lib/kernel-manager.coffee
@@ -63,16 +63,18 @@
         else
             return language

-    getLanguageMappings: ->
-        languageMappings = atom.config.get 'Hydrogen.languageMappings'
+    getConfigJson: (key) ->
+        return {} unless value = atom.config.get "Hydrogen.#{key}"
+        try
+            return JSON.parse value
+        catch error
+            atom.notifications.addError "Your Hydrogen config is broken: #{key}", detail: error

-        if languageMappings
-            try
-                return JSON.parse languageMappings
-            catch error
-                console.error error
+    setConfigJson: (key, value, merge=false) ->
+        value = _.merge @getConfigJson key, value if merge
+        atom.config.set "Hydrogen.#{key}", JSON.stringify value

-        return {}
+    getLanguageMappings: -> @getConfigJson('languageMappings')

     getKernelInfoForLanguage: (grammarLanguage) ->
         kernels = @getAvailableKernels()


add test for accessing views

add test for accessing views

--- test/request_tests.coffee
+++ test/request_tests.coffee
@@ -34,8 +34,17 @@
             console.log 'DB destroyed'
             db.create ->
                 console.log 'DB recreated'
-                db.save '321', {"value":"val"}, ->
-                    done()
+                docs = ({'type':'dumb_doc', 'num':num} for num in [0..100])
+                db.save docs, ->
+                    map_no_doc = (doc) ->
+                    map_every_docs = (doc) ->
+                        emit doc._id, null
+
+                    views = {no_doc:{map:map_no_doc}, \
+                            every_docs:{map:map_every_docs}}
+
+                    db.save "_design/cozy-request", views, ->
+                        done()

     # Start application before starting tests.
     before (done) ->
@@ -49,7 +58,7 @@

-    describe "Access to a view", ->
+    describe "Access to a view without option", ->
         describe "Access to a non existing view", ->
             before cleanRequest

@@ -60,3 +69,27 @@

             it "Then error 404 should be returned", ->
                 @response.statusCode.should.equal 404
+
+        describe "Access to an existing view : no_doc", ->
+            before cleanRequest
+
+            it "When I send a request to access view no_doc", (done) ->
+                client.get "request/no_doc/", (error, response, body) =>
+                    response.statusCode.should.equal 200
+                    @body = parseBody response, body
+                    done()
+
+            it "Then I should have no document returned", ->
+                @body.should.have.length 0
+
+        describe "Access to an existing view : every_docs", (done) ->
+            before cleanRequest
+
+            it "When I send a request to access view every-docs", (done) ->
+                client.get "request/every_docs/", (error, response, body) =>
+                    response.statusCode.should.equal 200
+                    @body = parseBody response, body
+                    done()
+
+            it "Then I should have 101 documents returned", ->
+                @body.should.have.length 101


fixing test breakage (forgot to rename to coffin in the tests)

--- test/templateTests.coffee
+++ test/templateTests.coffee
@@ -2,7 +2,7 @@
 assert      = require 'assert'
 fs          = require 'fs'
 path        = require 'path'
-coffeecloud = require '../lib/coffeecloud'
+coffin = require '../lib/coffin'

 @assertListsEqual = (actualList, expectedList) ->
   assert.equal actualList.length, expectedList.length
@@ -47,7 +47,7 @@
       @assertListsEqual generatedTemplate.Outputs, originalTemplate.Outputs
   'when using resource types':
     topic: ->
-      coffeecloud ->
+      coffin ->
         @AWS.AutoScaling.ScalingPolicy 'scalePolicy'
         @Param.String 'shortParam'
     'it does not break': (topic) ->
@@ -61,7 +61,7 @@
       assert.ok topic.Parameters.shortParam?
   'when using a blank template':
     topic: ->
-      coffeecloud ->
+      coffin ->
     'it is not null': (topic) ->
       assert.ok topic?
     'there is no description': (topic) ->
@@ -76,7 +76,7 @@
       assert.ok topic.Outputs?
   'when using mappings':
     topic: ->
-      coffeecloud ->
+      coffin ->
         @Mapping 'AWSRegionArch2AMI'
           'us-east-1':
             32: "ami-f417e49d"
@@ -88,7 +88,7 @@
       assert.equal 'ami-f617e49f', topic.Mappings.AWSRegionArch2AMI['us-east-1']['64']
   'when using tags':
     topic: ->
-      coffeecloud ->
+      coffin ->
         @AWS.EC2.Instance 'instance',
           Tags: [ @Tag('Name', 'someInstance'), @Tag('Environment', 'someEnvironment') ]
     'tags are correct': (topic) ->
@@ -99,7 +99,7 @@
   'when using the join function':
     topic: ->
       myArray = ['x', 'y', 'z']
-      coffeecloud ->
+      coffin ->
         @AWS.EC2.Instance 'a',
           UserData: @Join '', 'x', 'y', 'z'
         @AWS.EC2.Instance 'b',
@@ -112,7 +112,7 @@
       assert.deepEqual topic.Resources.b.Properties.UserData['Fn::Join'][1], ['x', 'y', 'z']
   'when using metadata and top level properties':
     topic: ->
-      coffeecloud ->
+      coffin ->
         @AWS.EC2.Instance 'a',
           Metadata:
             meta: 'data'


fixed test for node v4

fixed test for node v4

--- test/test-longjohn.coffee
+++ test/test-longjohn.coffee
@@ -11,7 +11,8 @@
     fs.readFile 'not_there.txt', 'utf8', (err, text) ->
       return done() if err? and err instanceof Error and
       (err.stack is "Error: ENOENT, open 'not_there.txt'" or
-       err.stack is "Error: ENOENT, open 'not_there.txt'\n    at Error (native)")
+       err.stack is "Error: ENOENT, open 'not_there.txt'\n    at Error (native)" or
+       err.stack is "Error: ENOENT: no such file or directory, open 'not_there.txt'\n    at Error (native)")
       assert.fail()

   it 'should track frames across setTimeout', (done) ->


Put the comments in english

Put the comments in english

--- ZONE-watcher/app/assets/javascripts/sources.js.coffee
+++ ZONE-watcher/app/assets/javascripts/sources.js.coffee
@@ -24,23 +24,23 @@
   ev.preventDefault()
   data = ev.dataTransfer.getData("Text")

-  #Id de la ligne originale
+  #Original line id
   originalId = "#" + data

-  #Id temporaire pour le nouvel tr
+  #Temp ID for the new

   tempId = $(originalId).attr("id") + "c"

-  #Contenu du tr ( ensemble de ses td )
+  #Content of the
 ( all his  )
   trContent = $(originalId).html()

-  #Url de la source
+  #Source URL
   sourceUrl = $(originalId).find("a.linkSource").html()

-  #Url a appellé en ajax pour enregistrer la modification de theme
+  #URL to call via ajax to save the update
   urlUpdate = "/sources/changeCategory?id=" + encodeURI(sourceUrl) + "&theme=" + encodeURI(idTheme)
   alert(urlUpdate)

-  #Ajout de la ligne dans le nouveau tableau
+  #Add the
 with his  to the new table
   $(idTheme).append "
" + trContent + "
"
   $.ajax
     url: urlUpdate,


Create draft release when one does not exist

--- build/tasks/publish-build-task.coffee
+++ build/tasks/publish-build-task.coffee
@@ -142,7 +142,31 @@
             firstDraft.assets = assets
             callback(null, firstDraft)
       else
-        callback(new Error('No draft release in atom/atom repo'))
+        createAtomDraftRelease(callback)
+
+createAtomDraftRelease = (callback) ->
+  {version} = require('../../package.json')
+  options =
+    uri: 'https://api.github.com/repos/atom/atom/releases'
+    method: 'POST'
+    headers: defaultHeaders
+    json: true
+    qs:
+      tag_name: "v#{version}"
+      name: version
+      draft: true
+      body: """
+        ### Notable Changes
+
+        *
+      """
+
+  request options, (error, response, body='') ->
+    if error? or response.statusCode isnt 201
+      logError("Creating atom/atom draft release failed", error, body)
+      callback(error ? new Error(response.statusCode))
+    else
+      callback(null, body)

 deleteRelease = (release) ->
   options =


Just showing the error thrown by OptionParser rather than parsing it

--- cake.coffee
+++ cake.coffee
@@ -53,7 +53,7 @@
   try
     options = oparse.parse(args)
   catch e
-    return badArgument "#{e}".match(/option: (.+)/)[1], "option"
+    return fatalError "#{e}"
   invoke arg for arg in options.arguments

 # Display the list of Cake tasks in a format similar to `rake -T`
@@ -68,12 +68,12 @@
   console.log oparse.help() if switches.length

 # Print an error and exit when attempting to use an invalid task/option.
-badArgument = (arg, type) ->
-  console.error """No such #{type}: "#{arg}"\n"""
+fatalError = (message) ->
+  console.error message + '\n'
   console.log 'To see a list of all tasks/options, run "cake"'
   process.exit 1

-missingTask = (task) -> badArgument task, "task"
+missingTask = (task) -> fatalError "No such task: #{task}"

 # When `cake` is invoked, search in the current and all parent directories
 # to find the relevant Cakefile.


more new lines

more new lines

--- resources/assets/lib/store-xsolla.coffee
+++ resources/assets/lib/store-xsolla.coffee
@@ -26,10 +26,12 @@
       StoreXsolla.onXsollaReady(orderNumber)
       XPayStationWidget.init(options)

+
   @fetchScript: ->
     new Promise (resolve, reject) ->
       loading = window.turbolinksReload.load 'https://static.xsolla.com/embed/paystation/1.0.7/widget.min.js', resolve
       resolve() unless loading
+

   @fetchToken: ->
     new Promise (resolve, reject) ->
@@ -41,9 +43,11 @@
       .fail (xhr) ->
         reject(xhr: xhr)

+
   @optionsWithToken: (token) ->
     access_token: token,
     sandbox: process.env.PAYMENT_SANDBOX # injected by webpack.DefinePlugin
+

   @onXsollaReady: (orderNumber) ->
     done = false


refactor of classification serializer

refactor of classification serializer

--- app/assets/javascripts/components/subject-viewer.cjsx
+++ app/assets/javascripts/components/subject-viewer.cjsx
@@ -264,7 +264,7 @@
       })
       .done (response) =>
         console.log "Success", response #, #response #, response._id.$oid
-        console.log 'RECEIVED SECONDARY SUBJECT ID: ', response.child_subject_id.$oid
+        console.log 'RECEIVED SECONDARY SUBJECT ID: ', response.child_subject_id
         console.log 'SELECTED MARK: ', @state.selectedMark
         # @setTranscribeSubject(key, response._id.$oid)
         # @enableMarkButton(key)


only apply curent geoloc to hiddenfield if user didn't overwrite

--- app/assets/javascripts/modules/search_location.coffee
+++ app/assets/javascripts/modules/search_location.coffee
@@ -3,6 +3,6 @@
     $(document).on 'newGeolocation', updateLocationInput

 updateLocationInput = ->
-  $('.JS-Search-location').attr 'value', document.Clarat.currentGeolocation
   unless readCookie('last_search_location')
+    $('.JS-Search-location').attr 'value', document.Clarat.currentGeolocation
     $('.JS-Search-location-display').attr 'value', I18n.t('conf.current_location')


formatting

formatting

--- client/lanes/models/AssociationMap.coffee
+++ client/lanes/models/AssociationMap.coffee
@@ -105,7 +105,7 @@
     fk: (name) ->
         def = @definitions[name]
         return null unless name and def
-        _.result(def,'fk', ( if def.model then "id" else "#{name}_id" ) )
+        _.result(def, 'fk', ( if def.model then "id" else "#{name}_id" ) )

     # returns the data from all assocations for saving
     dataForSave: (model, options) ->


Healthcheck connection refused message made more clear

--- SingularityUI/app/views/taskHealthcheckNotificationSubview.coffee
+++ SingularityUI/app/views/taskHealthcheckNotificationSubview.coffee
@@ -61,11 +61,13 @@
         secondsElapsed: healthTimeoutSeconds
         doNotDisplayHealthcheckNotification: @deployFailureKilledTask()

-    healthcheckFailureReasonMessage: () ->
+    healthcheckFailureReasonMessage: () -> # For now this only looks for connection refused, but feel free to improve the logic to detect more reasons.
         healthcheckResults = @model.get('healthcheckResults')
         if healthcheckResults.length > 0
             if healthcheckResults[0].errorMessage.toLowerCase().indexOf('connection refused') isnt -1
-                return 'a connection was refused. This is probably the connection to the host your app is running on.'
+                portIndex = @model.attributes.task.taskRequest.deploy.healthcheckPortIndex or 0
+                port = if @model.attributes.ports.length > portIndex then @model.attributes.ports[portIndex] else false
+                return "a refused connection. It is possible your app did not start properly or was not listening on the anticipated port (#{port}). Please check the logs for more details."

     triggerToggleHealthchecks: ->
         @trigger 'toggleHealthchecks'


Don't parse [up-action] for form actions

--- lib/assets/javascripts/unpoly/form.coffee
+++ lib/assets/javascripts/unpoly/form.coffee
@@ -193,7 +193,7 @@
     params.addAll(options.params)
     options.params = params

-    parser.string('url', attr: ['up-action', 'action'], default: up.fragment.source(form))
+    parser.string('url', attr: 'action', default: up.fragment.source(form))
     parser.string('method', attr: ['up-method', 'data-method', 'method'], default: 'POST', normalize: u.normalizeMethod)
     if options.method == 'GET'
       # Only for GET forms, browsers discard all query params from the form's [action] URL.


fix stream stall

fix stream stall

--- client/mtrPlayer.coffee
+++ client/mtrPlayer.coffee
@@ -57,8 +57,6 @@
   checkStatus: =>
     newNetworkState = @audioTag().networkState
     newReadyState = @audioTag().readyState
-
-    # @audioTag().volume = 1
     @play()

     if @readyState? and
@@ -68,6 +66,8 @@
       console.log 'Restart channel'
       @readyState = @networkState = null
       @setChannel Session.get 'channel'
+      @audioTag()?.load()
+      @play()

     else
       if newReadyState


Fix and refactor audio streaming and panel resizing autoruns for room view.

--- client/room/room.coffee
+++ client/room/room.coffee
@@ -39,19 +39,19 @@
   Session.setTemp 'audioLocked', true
   Session.setTemp 'controlsLocked', true
   Session.setTemp 'audioStreaming', false
-  self = @
   @autorun =>
     offline = Template.currentData().room.offline
     resizePanelTitle()
+  @autorun =>
     audioStreaming = Session.get 'audioStreaming'
     url = ''
     if audioStreaming
-      room = self.data.room
+      room = @data.room
       url = "http://#{room.ip}:#{room.stream.port}/#{room.stream.key}"
-      $('#peakaboo-audio-stream span').show 'slow'
+      @$('#peakaboo-audio-stream span').show 'slow'
     else
-      $('#peakaboo-audio-stream span').hide 'slow'
-    self.$('#audioStreaming').prop 'src', url
+      @$('#peakaboo-audio-stream span').hide 'slow'
+    @$('#audioStreaming').prop 'src', url

 Template.confirmModal.rendered = ->
   Ladda.bind 'button.ladda-button'


Create JSON of creator in Comment templateHelper

--- core/app/backbone/models/comment.coffee
+++ core/app/backbone/models/comment.coffee
@@ -3,6 +3,6 @@
   templateHelpers: =>
     creator: @creator

-  creator: -> new User(@get('created_by'))
+  creator: -> new User(@get('created_by')).toJSON()

   can_destroy: -> @creator().get('id') == currentUser.get('id')


Removing envelope for now

Removing envelope for now

--- scripts/crashlytics-notifications.coffee
+++ scripts/crashlytics-notifications.coffee
@@ -29,8 +29,6 @@

     res.end('')

-    envelope.room = query.room if query.room
-
     try
       data = req.body


Only pull in large image version for carousels

--- src/mobile/apps/artwork/routes.coffee
+++ src/mobile/apps/artwork/routes.coffee
@@ -62,7 +62,7 @@
         width
       }
       images {
-        url
+        url(version: "large")
         height
         width
         is_default


Tweak section heading

Tweak section heading

--- lib/packages-panel.coffee
+++ lib/packages-panel.coffee
@@ -15,7 +15,7 @@
   @content: ->
     @div =>
       @div class: 'section packages', =>
-        @div class: 'section-heading icon icon-squirrel', 'Package Updates'
+        @div class: 'section-heading icon icon-squirrel', 'Available Updates'

         @div outlet: 'updateErrors'
         @div outlet: 'checkingMessage', class: 'alert alert-info featured-message icon icon-hourglass', 'Checking for updates\u2026'


remove event listeners when removing AddEventView.

--- assets/javascripts/app/timeline/add_event_view.coffee
+++ assets/javascripts/app/timeline/add_event_view.coffee
@@ -43,6 +43,8 @@
       userGenerated: true

     remove: ->
+      $('#addEventSave').off 'click'
+      $('#addEventCancel').off 'click'
       $('.addEventWrapper').remove()

     onSave: (e) =>


Fix message URL for Github Enterprise.

Fix message URL for Github Enterprise.

--- src/scripts/github-commit-link.coffee
+++ src/scripts/github-commit-link.coffee
@@ -36,7 +36,10 @@
         issue_title = ""
         base_url = process.env.HUBOT_GITHUB_API || 'https://api.github.com'
         github.get "#{base_url}/repos/#{bot_github_repo}/commits/" + commit_sha, (commit_obj) ->
-          url = commit_obj.url.replace(/api\./,'')
+          if process.env.HUBOT_GITHUB_API
+            url = commit_obj.url.replace(/api\/v3\//,'')
+          else
+            url = commit_obj.url.replace(/api\./,'')
           url = url.replace(/repos\//,'')
           url = url.replace(/commits/,'commit')
           msg.send "Commit: " + commit_obj.commit.message + " " + url


Converted ArticleEditor to use Immutable.

--- src/scripts/views/article-editor.cjsx
+++ src/scripts/views/article-editor.cjsx
@@ -1,4 +1,5 @@
 React = require 'react'
+Immutable = require 'immutable'

 utils = require '../utils.coffee'
 articleActions = require '../actions/article-actions.coffee'
@@ -6,33 +7,27 @@
 module.exports = React.createClass
 	displayName: 'ArticleEditor'
 	setLanguage: (lang) ->
-		@setState lang: lang
+		@replaceState lang: lang
 	getInitialState: ->
-		state = {
-			lang: 'nb'
-		}
-		for key, val of @props.data
-			state[key] = val
+		state = Immutable.Map lang: 'nb'
+		state = state.merge @props.data
 		state
 	handleChange: (e) ->
-		lang = @state.lang
-		key = e.target.name
-		val = e.target.value
-		state = {}
-		if @state[key].hasOwnProperty(lang)
-			state[key] = JSON.parse JSON.stringify @state[key]
-			state[key][lang] = val
+		lang = @state.get 'lang'
+		k = e.target.name
+		v = e.target.value
+		if @state.hasIn [k, lang]
+			state = @state.setIn [k, lang], v
 		else
-			state[key] = val
-		@setState state
+			state = @state.set k, v
+		@replaceState state
 	handleSubmit: (e) ->
 		e.preventDefault()
-		article = {}
-		for key, val of @state
-			article[key] = val unless key == 'lang'
-		articleActions.save article
+		article = @state.filterNot utils.keyIn 'lang'
+		articleActions.save article.toJS()
 	render: ->
-		data = utils.localize @state.lang, @state
+		state = @state.toJS()
+		data = utils.localize state.lang, state
 		<form onSubmit={ @handleSubmit }>
 			<input type="radio" name="lang" value="nb" checked={ data.lang == 'nb' } onChange={ @handleChange }/> Norwegian
 			<input type="radio" name="lang" value="en" checked={ data.lang == 'en' } onChange={ @handleChange }/> English


Handled canceling enqueued imports

Handled canceling enqueued imports

--- client/import.coffee
+++ client/import.coffee
@@ -11,6 +11,7 @@
   # imported: true if file was successfully imported
   # publicationId: publication ID for the imported file
   # sha256: SHA256 hash for the file
+  # enqueued: true when file is enqueued

   @Meta
     name: 'ImportingFile'
@@ -26,6 +27,19 @@
 processedFiles.observeChanges
   removed: (id) ->
     delete importingFiles[id]
+
+# Observes enqueued files that get canceled
+canceledFiles = ImportingFile.documents.find
+  canceled: true
+  enqueued: true
+  finished: false
+  errored: false
+canceledFiles.observe
+  added: (id) ->
+    ImportingFile.documents.update id,
+      $set:
+        finished: true
+        status: "Import canceled"

 verifyFile = (file, publicationId, samples) ->
   ImportingFile.documents.update file._id,
@@ -90,6 +104,7 @@
   document = ImportingFile.documents.findOne
     finished: false
     errored: false
+    canceled: false
     sha256:
       $exists: true
   ,
@@ -99,6 +114,10 @@
       sha256: 1
   return unless document

+  ImportingFile.documents.update document._id,
+    $set:
+      enqueued: false
+
   Meteor.call 'create-publication', document.name, document.sha256, (error, result) ->
     if error
       ImportingFile.documents.update document._id,
@@ -152,6 +171,7 @@
     sha256:
       $exists: false
     errored: false
+    finished: false
   ,
     fields:
       _id: 1
@@ -160,6 +180,7 @@
   ImportingFile.documents.update document._id,
     $set:
       status: "Preprocessing"
+      enqueued: false

   reader = new FileReader()
   reader.onload = ->
@@ -177,6 +198,8 @@
           $set:
             sha256: sha256
             status: "In import queue"
+            enqueued: true
+
   reader.onerror = (error) ->
     console.log "Error " + error
     ImportingFile.documents.update document._id,
@@ -204,6 +227,7 @@
     errored: false
     canceled: false
     imported: false
+    enqueued: true

 hideOverlay = ->
   allCount = ImportingFile.documents.find().count()


Added observers for preprocessing files (#429)

--- client/import.coffee
+++ client/import.coffee
@@ -15,6 +15,88 @@

 UPLOAD_CHUNK_SIZE = 128 * 1024 # bytes
 DRAGGING_OVER_DOM = false
+fileBuffer = []
+
+# observing files with computed checksums
+checksummed = ImportingFile.documents.find
+  sha256:
+    $exists: true
+checksummed.observe
+  added: (document) ->
+    id = document._id
+    file = fileBuffer[id].file
+    fileContent = fileBuffer[id].fileContent
+
+    console.log "Creating publication for file " + document.name
+    Meteor.call 'create-publication', document.name, document.sha256, (error, result) ->
+      if error
+        ImportingFile.documents.update id,
+          $set:
+            errored: true
+            status: error.toString()
+        return
+
+      if result.already
+        ImportingFile.documents.update id,
+          $set:
+            finished: true
+            status: "File already imported"
+            publicationId: result.publicationId
+        return
+
+      if result.verify
+        console.log "Verifying file " + document.name
+        verifyFile file, fileContent, result.publicationId, result.samples
+      else
+        console.log "Uploading file " + document.name
+        uploadFile file, result.publicationId
+
+      # remove file from buffer
+      delete fileBuffer[id]
+
+# observing files that are ready for checksum computation
+preprocessed = ImportingFile.documents.find
+  preprocessed:
+    $exists: true
+preprocessed.observe
+  added: (document) ->
+    id = document._id
+    fileContent = fileBuffer[id].fileContent
+
+    console.log "Computing checksum for " + document.name
+    ImportingFile.documents.update id,
+      $set:
+        status: "Computing checksum"
+
+    hash = new Crypto.SHA256
+      onProgress: (progress) ->
+        #TODO: update progressbar
+    hash.update fileContent, (error, result) ->
+      #TODO: handle errors
+      if error
+        console.log "Import error: " + error.message
+    hash.finalize (error, result) ->
+      #TODO: handle errors
+      if error
+        console.log "Import error: " + error.message
+
+      alreadyImporting = ImportingFile.documents.findOne
+        sha256: result
+
+      if alreadyImporting
+        ImportingFile.documents.update id,
+          $set:
+            finished: true
+            status: "File is already importing"
+            # publicationId might not yet be available, but let's try
+            publicationId: alreadyImporting.publicationId
+        return
+
+      console.log "Setting sha256 value"
+      # so that observer can do it's work
+      ImportingFile.documents.update id,
+        $set:
+          sha256: result

 verifyFile = (file, fileContent, publicationId, samples) ->
   ImportingFile.documents.update file._id,
@@ -36,22 +118,12 @@
         finished: true
         publicationId: publicationId

-
-uploadQueue = async.queue (params, callback) ->
-  meteorFile = new MeteorFile params.file,
+uploadFile = (file, publicationId) ->
+  meteorFile = new MeteorFile file,
     collection: ImportingFile.Meta.collection

-  meteorFile.upload params.file, 'upload-publication',
+  meteorFile.upload file, 'upload-publication',
     size: UPLOAD_CHUNK_SIZE,
-    publicationId: params.publicationId
-  ,
-    callback
-,
-  1 # simultaneous upload(s)
-
-uploadFile = (file, publicationId) ->
-  uploadQueue.push
-    file: file
     publicationId: publicationId
   ,
     (error) ->
@@ -67,11 +139,6 @@
           finished: true
           publicationId: publicationId

-  ImportingFile.documents.update file._id,
-    $set:
-      status: "In queue"
-
-
 testPDF = (file, fileContent, callback) ->
   PDFJS.getDocument(data: fileContent, password: '').then callback, (message, exception) ->
     ImportingFile.documents.update file._id,
@@ -80,59 +147,21 @@
         status: "Invalid PDF file"

 importFile = (file) ->
+  console.log "Import file called"
   reader = new FileReader()
   reader.onload = ->
     fileContent = @result
-
     testPDF file, fileContent, ->
-      hash = new Crypto.SHA256
-        onProgress: (progress) ->
-          #TODO: update progressbar
-      hash.update fileContent, (error, result) ->
-        #TODO: handle errors
-        if error
-          console.log "Import error: " + error.message
-      hash.finalize (error, result) ->
-        #TODO: handle errors
-        if error
-          console.log "Import error: " + error.message
-        sha256 = result
-
-        alreadyImporting = ImportingFile.documents.findOne(sha256: sha256)
-        if alreadyImporting
-          ImportingFile.documents.update file._id,
-            $set:
-              finished: true
-              status: "File is already importing"
-              # publicationId might not yet be available, but let's try
-              publicationId: alreadyImporting.publicationId
-          return
-
-        ImportingFile.documents.update file._id,
-          $set:
-            sha256: sha256
-
-        Meteor.call 'create-publication', file.name, sha256, (error, result) ->
-          if error
-            ImportingFile.documents.update file._id,
-              $set:
-                errored: true
-                status: error.toString()
-            return
-
-          if result.already
-            ImportingFile.documents.update file._id,
-              $set:
-                finished: true
-                status: "File already imported"
-                publicationId: result.publicationId
-            return
-
-          if result.verify
-            verifyFile file, fileContent, result.publicationId, result.samples
-          else
-            uploadFile file, result.publicationId
-
+      fileBuffer[file._id] =
+        file: file
+        fileContent: fileContent
+
+      ImportingFile.documents.update file._id,
+        $set:
+          status: "In queue for checksum computation"
+          preprocessed: true
+
+  console.log "Inserting file into collection " + file.name
   ImportingFile.documents.insert
     name: file.name
     status: "Preprocessing file"
@@ -140,6 +169,7 @@
     uploadProgress: 0
     finished: false
     errored: false
+    file: file
   ,
     # We are using callback to make sure ImportingFiles really has the file now
     (error, id) ->


use ActivityLogger in tags

use ActivityLogger in tags

--- lib/views/tag-view.coffee
+++ lib/views/tag-view.coffee
@@ -1,8 +1,8 @@
 {$$, SelectListView} = require 'atom-space-pen-views'

-git = require '../git'
+git = require('../git-es').default
 GitShow = require '../models/git-show'
-notifier = require '../notifier'
+ActivityLogger = require('../activity-logger').default
 RemoteListView = require '../views/remote-list-view'

 module.exports =
@@ -46,8 +46,8 @@
       when 'Show'
         GitShow(@repo, tag)
       when 'Push'
-        git.cmd(['remote'], cwd: @repo.getWorkingDirectory())
-        .then (data) => new RemoteListView(@repo, data, mode: 'push', tag: @tag)
+        git(['remote'], cwd: @repo.getWorkingDirectory())
+        .then (result) => new RemoteListView(@repo, result.output, mode: 'push', tag: @tag)
       when 'Checkout'
         args = ['checkout', tag]
       when 'Verify'
@@ -56,6 +56,5 @@
         args = ['tag', '--delete', tag]

     if args?
-      git.cmd(args, cwd: @repo.getWorkingDirectory())
-      .then (data) -> notifier.addSuccess data
-      .catch (msg) -> notifier.addWarning msg
+      git(args, cwd: @repo.getWorkingDirectory())
+      .then (result) -> ActivityLogger.record(Object.assign({message: "#{cmd} tag '#{tag}'"}, result))


Fix #17: Render TextBlock content linebreaks as <br>

--- entry/NOAT.coffee
+++ entry/NOAT.coffee
@@ -185,7 +185,7 @@

         # Add the escaped segment text content, but track the length of the
         # original text to preserve annotation positions.
-        output += _escapeHTML(seg_text)
+        output += _escapeHTML(seg_text).replace(/\n/g, '<br />')
         i += seg_text.length

     # Close any tags that are still open (should only be any that are set to


kontrol: don't override a user-provided value for version

--- client/Main/kite/kodingkontrol.coffee
+++ client/Main/kite/kodingkontrol.coffee
@@ -32,7 +32,7 @@
     }[name] ? ''

   injectQueryParams: (args) ->
-    args.query.version = @getVersion args.query.name
+    args.query.version ?= @getVersion args.query.name
     args.query.username = KD.config.kites.kontrol.username
     args.query.environment = KD.config.environment
     args


Fixed: removed useless statements that cause the app to crash if it had no data

--- client/app/stores/AccountStore.coffee
+++ client/app/stores/AccountStore.coffee
@@ -31,9 +31,6 @@
     _selectedAccount = null
     _newAccountWaiting = false
     _newAccountError = null
-
-    account = _accounts.get('gmail-ID')
-    AccountTranslator.toRawObject account

     ###


removed debugging console logging that was left in

--- src/coffeecodegenerator.coffee
+++ src/coffeecodegenerator.coffee
@@ -76,12 +76,8 @@
     jsStr.replace(/"/g, '\\"')

   generateJsFunction: (functionBody) ->
-    console.log('------------------------------')
-    console.log(functionBody)
-    console.log('------------------------------')
     try
       fn = CoffeeScript.compile functionBody, bare: true
-      console.log("[#{fn}]")
       new Function(fn)
     catch e
       throw "Incorrect embedded code has resulted in an invalid Haml function - #{e}\nGenerated Function:\n#{fn}"


Add fonts directory to production build

Add fonts directory to production build

Vs the individual files.

--- Gulpfile.coffee
+++ Gulpfile.coffee
@@ -128,7 +128,6 @@
       'node_modules/**/*.{eot,svg,png,jpg,ttf,woff,woff2}',
       'resources/fonts/**/*'
     ])
-    .pipe(flatten())
     .pipe(gulp.dest(destDirFonts))

 gulp.task '_cleanFonts', (done) ->


fixing version number to 1.1.0-pre ... to make it installable with npm.

--- coffee-script.coffee
+++ coffee-script.coffee
@@ -20,7 +20,7 @@
   require.registerExtension '.coffee', (content) -> compile content

 # The current CoffeeScript version number.
-exports.VERSION = '1.1-pre'
+exports.VERSION = '1.1.0-pre'

 # Words that cannot be used as identifiers in CoffeeScript code
 exports.RESERVED = RESERVED


Use coffee binary of coffee that overrode fork

This solves two potential problems when it comes to forking:

    1) Forking will now work correctly even when `coffee` is not installed
       globally.
    2) Forking when using a locally installed version of `coffee` will fork
       using that version, and not fallback to a globally installed version.

Fixes #2957

--- coffee-script.coffee
+++ coffee-script.coffee
@@ -15,6 +15,7 @@
 # The current CoffeeScript version number.
 exports.VERSION = '1.6.3'

+binary = require.resolve '../../bin/coffee'
 fileExtensions = ['.coffee', '.litcoffee', '.coffee.md']

 # Expose helpers for testing.
@@ -202,7 +203,7 @@
 if child_process
   {fork} = child_process
   child_process.fork = (path, args = [], options = {}) ->
-    execPath = if helpers.isCoffee(path) then 'coffee' else null
+    execPath = if helpers.isCoffee(path) then binary else null
     if not Array.isArray args
       args = []
       options = args or {}


duplicate fix

duplicate fix

--- coffee/editor.coffee
+++ coffee/editor.coffee
@@ -42,7 +42,6 @@
     @elems.previewSidebar.innerHTML = ''
     parser = new Parser text: text

-    parser.parse()
     try
      parser.parse()
     catch e


prevNode

prevNode

--- coffee/parser.coffee
+++ coffee/parser.coffee
@@ -57,7 +57,7 @@
      @node = @root
      @main = true
      @sidenotes = []
-     @prevBlock = null
+     @prevNode = null
      @blocks = []

     parse: ->
@@ -226,7 +226,7 @@

      if line.empty
       if @node.type is TYPES.block
-       @prevBlock = @node
+       @prevNode = @node
        @node = @node.parent()

       if @node.type is TYPES.codeBlock or @node.type is TYPES.html
@@ -236,7 +236,7 @@

      while line.indentation < @node.indentation
-      @prevBlock = @node
+      @prevNode = @node
       @node = @node.parent()
       if not @node?
        if @main
@@ -245,7 +245,7 @@
        @main = true
        @node = @mainNode

-     @prevBlock ?= @node
+     @prevNode ?= @node

      switch @node.type
       when TYPES.list
@@ -305,7 +305,7 @@

        @main = false
        id = @node.id
-       id = @prevBlock.id if @prevBlock?
+       id = @prevNode.id if @prevNode?
        n = new Sidenote indentation: line.indentation + 1, link: id
        @mainNode = @node
        @node = n
@@ -318,7 +318,7 @@

       when TYPES.media
        @addNode new Media indentation: line.indentation + 1, media: @parseMedia line.text
-       @prevBlock = @node
+       @prevNode = @node
        return

       else


Removed empty line

Removed empty line

--- main/static/src/script/common/util.coffee
+++ main/static/src/script/common/util.coffee
@@ -41,4 +41,3 @@
         #{message}
       </div>
     """
-


Correct overdrag

Correct overdrag

--- framer/LayerDraggable.coffee
+++ framer/LayerDraggable.coffee
@@ -163,7 +163,7 @@
 			x: touchEvent.clientX - @_correctedLayerStartPoint.x
 			y: touchEvent.clientY - @_correctedLayerStartPoint.y

-		@_point = @layer.point
+		@_point = @_correctedLayerStartPoint
 		@_ignoreUpdateLayerPosition = false

 		@emit(Events.DragStart, event)


actually added the coffee script version, sorry

--- core/app/backbone/views/facts_view.coffee
+++ core/app/backbone/views/facts_view.coffee
@@ -10,9 +10,8 @@
     "click #create_fact_for_channel": "focusCreateFactlink"
     "click #create_fact_for_channel .input-box": "focusField"

-  template: "channels/facts"
+  template: "channels/_facts"
   initialize: (options) ->
-    @views = {}
     @addShowHideToggle "loadingIndicator", "div.loading"
     @collection.on "startLoading", @loadingIndicatorOn, this
     @collection.on "stopLoading", @loadingIndicatorOff, this


Sidebar: Refactored NavigationWorkspaceItem to work with new list controller.

--- client/Main/navigation/navigationworkspaceitem.coffee
+++ client/Main/navigation/navigationworkspaceitem.coffee
@@ -1,57 +1,42 @@
-class NavigationWorkspaceItem extends JView
+class NavigationWorkspaceItem extends KDListItemView
+
+  JView.mixin @prototype

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

-    super options, data
+    options.cssClass = 'kdlistitemview-main-nav workspace'

-    @init()
+    super options, data # machine data is `options.machine`, workspace data is `data`

-
-  init: ->
-
-    @unsetClass 'kdview'
-
-    { href, title } = @getData()
-    href = KD.utils.groupifyLink href
+    {machine} = options
+    workspace = data # to make it more sense in the following lines.
+    path      = "/IDE/#{machine.slug or machine.label}/#{workspace.slug}"
+    href      = KD.utils.groupifyLink path
+    title     = workspace.name

     @title = new CustomLinkView { href, title }

     @unreadCount = new KDCustomHTMLView
-      tagName  : 'cite'
-      cssClass : 'count hidden'
+      tagName    : 'cite'
+      cssClass   : 'count hidden'

+    @settingsIcon = new KDCustomHTMLView

-  click: (event) ->
-
-    # TODO: at least a KDView - DOM element check would
-    # be more appropriate, fix later. ~Umut
-    isSettingsIconView = event.target.classList.contains 'ws-settings-icon'
-    navItem            = @getDelegate()
-
-    # if the event's target settings icon
-    # do not pass the event to the delegate
-    # which is navigation item itself. if it's not
-    # don't do anything special and pass the event to
-    # delegate, so that it can do its job. ~Umut
-    if isSettingsIconView
-      KD.utils.stopDOMEvent event
-      @showSettingsPopup()
-      return
-
-    navItem.emit 'click', event
+    unless workspace.isDefault
+      @settingsIcon = new KDCustomHTMLView
+        tagName     : 'span'
+        cssClass    : 'ws-settings-icon'
+        click       : @bound 'showSettingsPopup'

   showSettingsPopup: ->

-    navItem     = @getDelegate()
-    { x, y, w } = navItem.getBounds()
+    { x, y, w } = @getBounds()
+    top         = Math.max y - 38, 0
+    left        = x + w + 16
+    position    = { top, left }

-    top  = Math.max(y - 38, 0)
-    left = x + w + 16
-
-    position = { top, left }
-
-    new WorkspaceSettingsPopup { position, delegate: navItem }
+    new WorkspaceSettingsPopup { position, delegate: this }

   setUnreadCount: (unreadCount = 0) ->
@@ -69,8 +54,9 @@

   pistachio: ->
     """
-

-    {{> @title}}
-    {{> @unreadCount}}
+

+      {{> @title}}
+      {{> @settingsIcon}}
+      {{> @unreadCount}}
     """


Fix rebase issues

Fix rebase issues

--- common/lib/xmodule/xmodule/js/src/capa/display.coffee
+++ common/lib/xmodule/xmodule/js/src/capa/display.coffee
@@ -211,7 +211,7 @@
     fd.append('grader_id', grader_id)
     if(!score)
       @gentle_alert "You need to pick a rating before you can submit."
-      return
+      return
     else
       fd.append('score', score)


HTML modules can also run script_placeholder

--- common/lib/xmodule/xmodule/js/src/html/display.coffee
+++ common/lib/xmodule/xmodule/js/src/html/display.coffee
@@ -2,6 +2,7 @@

   constructor: (@element) ->
     @el = $(@element)
+    JavascriptLoader.executeModuleScripts(@el)
     JavascriptLoader.setCollapsibles(@el)

   $: (selector) ->


Fix setting of content

Fix setting of content

--- core/app/backbone/views/evidence/react_comment.coffee
+++ core/app/backbone/views/evidence/react_comment.coffee
@@ -36,8 +36,8 @@

   _content: ->

-    _div ["comment-content spec-comment-content"],
-      dangerouslySetInnerHTML: {__html: @model().get('formatted_content')}
+    _div ["comment-content spec-comment-content",
+      dangerouslySetInnerHTML: {__html: @model().get('formatted_content')}]

   _bottom: ->
     sub_comment_count = @model().get('sub_comments_count')


Return doubt state when it's not believes or disbelieves

--- core/app/backbone/views/evidence/react_comment.coffee
+++ core/app/backbone/views/evidence/react_comment.coffee
@@ -7,7 +7,7 @@
     switch @model().get('type')
       when 'believes' then 'comment-believes'
       when 'disbelieves' then 'comment-disbelieves'
-      when 'doubts' then 'comment-unsure'
+      else 'comment-unsure'

   render: ->
     R.div className: 'comment-post-heading',


StacksCustomViews: simplfy repo listing flow

--- client/admin/lib/views/stacks/stackscustomviews.coffee
+++ client/admin/lib/views/stacks/stackscustomviews.coffee
@@ -437,7 +437,6 @@
         stepsHeaderView   :
           steps           : STEPS.REPO_FLOW
           selected        : 2
-        text              : "Github: Select a repository from your account"
         repoListView      :
           users           : ['gokmen', 'koding']
         navCancelButton   :
@@ -523,19 +522,20 @@
       { users } = options

       container    = @views.container 'repo-listview'
-      views        = @addTo container,
+      loader       = @addTo container,
         mainLoader : 'Fetching repositories list...'
-        repoList   : options
-
-      {controller, __view: repoList} = views.repoList
-
-      repoList.hide()
-      GitHub.fetchUsersRepos users, (err, response) ->
-        views.mainLoader.hide()
+
+      GitHub.fetchUsersRepos users, (err, response) =>
+        loader.hide()
+
+        views        = @addTo container,
+          text       : "Github: Select a repository from your account"
+          repoList   : options
+
+        {controller, __view: repoList} = views.repoList
+
         controller.replaceAllItems response
-        repoList.show()
-
-      container.forwardEvent repoList, 'RepoSelected'
+        container.forwardEvent repoList, 'RepoSelected'

       return container


profile: fixed appendActivities controller mishmash as well, also stopped multiple subview adds if someone clicks about page fast

--- client/app/MainApp/lazy/staticprofilecontroller.coffee
+++ client/app/MainApp/lazy/staticprofilecontroller.coffee
@@ -368,12 +368,11 @@
     @profileLogoView.$().css
       top: @landingView.getHeight()-42

-  appendActivities:(err,activities)->
-    @activityController.listActivities activities
-    @activityController.hideLazyLoader()
+  appendActivities:(err,activities, controller)->
+    controller.listActivities activities
+    controller.hideLazyLoader()

   refreshActivities:(err,activities,wrapperInstance,controllerInstance)->
-    log ',,,,',arguments
     @profileShowMoreView.hide()

     # listWrapper = if isStatic then @staticListWrapper else @activityListWrapper
@@ -417,7 +416,8 @@
         facets    : @currentFacets
         to        : @activityController.itemsOrdered.last.getData().meta.createdAt
         bypass    : yes
-      , @bound "appendActivities"
+      , (err,activities)=>
+        @appendActivities err,activities,@activityController

     callback()

@@ -426,6 +426,8 @@

     @profileLoadingBar.setClass 'active'
     @profileLoaderView.show()
+
+    @aboutWrapper = yes

     @profileUser.fetchAbout (err,about)=>
       log arguments
@@ -467,7 +469,8 @@
         facets    : ['CBlogPostActivity']
         to        : @staticController.itemsOrdered.last.getData().meta.createdAt
         bypass    : yes
-      , @bound "appendActivities"
+      , (err, activities)=>
+       @appendActivities err, activities, @staticController

     callback()


profile: removed unneeded instance variables

--- client/app/MainApp/lazy/staticprofilecontroller.coffee
+++ client/app/MainApp/lazy/staticprofilecontroller.coffee
@@ -408,7 +408,7 @@
     @landingView.listenWindowResize()
     @landingView._windowDidResize = =>
       @landingView.setHeight window.innerHeight
-      @profileContentView.setHeight window.innerHeight-@profileTitleView.getHeight()
+      @profileContentView.setHeight window.innerHeight-profileTitleView.getHeight()

     groupKodingLogo = new KDView
@@ -421,17 +421,7 @@
         else
           @mainController.loginScreen.animateToForm 'login'

-    # groupAvatarDrop = new KDView
-    #   lazyDomId : 'landing-page-avatar-drop'
-    #   tooltip   :
-    #     title   : "Click here to go to Koding"
-    #   click     : =>
-    #     if KD.isLoggedIn()
-    #       @lazyDomController.hideLandingPage()
-    #     else
-    #       @mainController.loginScreen.animateToForm 'login'
-
-    @profileTitleView = new KDView
+    profileTitleView = new KDView
       lazyDomId : 'profile-title'

     @profileShowMoreView = new KDView


teams: sidebar: show selective warning for admins and users

--- client/app/lib/activity/sidebar/activitysidebar.coffee
+++ client/app/lib/activity/sidebar/activitysidebar.coffee
@@ -520,14 +520,25 @@
     return  if isKoding()
     return  @showStacksNotConfiguredWarning()  if @stacksNotConfiguredWarning?

-    @stacksNotConfiguredWarning = @machinesWrapper.addSubView (new KDCustomHTMLView
-      cssClass : 'stack-warning hidden'
-      partial  : "Your team page has not been

-                  fully configured yet please

-                  click here to setup now."
-      ), null, shouldPrepend = yes
-
-    @showStacksNotConfiguredWarning()
+    currentGroup = kd.singletons.groupsController.getCurrentGroup()
+    currentGroup.fetchMyRoles (err, roles) =>
+      return kd.warn err  if err
+
+      if 'admin' in (roles ? [])
+        partial = "Your team page has not been

+                      fully configured yet please

+                      click here to setup now."
+      else
+        partial = "Your team page has not been

+                      fully configured yet please

+                      contact your team admin."
+
+      cssClass = 'stack-warning hidden'
+      view     = new KDCustomHTMLView { cssClass, partial }
+
+      @stacksNotConfiguredWarning = @machinesWrapper.addSubView view, null, shouldPrepend = yes
+
+      @showStacksNotConfiguredWarning()

   showStacksNotConfiguredWarning: ->


Existence check

Existence check

--- client/app/lib/activity/sidebar/activitysidebar.coffee
+++ client/app/lib/activity/sidebar/activitysidebar.coffee
@@ -113,7 +113,7 @@

     { channel, channelMessage, unreadCount } = update

-    if isChannelCollaborative channel
+    if isChannelCollaborative channel and channelMessage.payload
       if channelMessage.payload['system-message'] in ['start', 'stop']
         @fetchEnvironmentData =>
           @setWorkspaceUnreadCount channel, unreadCount


add abstract methods for nested tables

add abstract methods for nested tables

--- client/coffee/abstractEvidence.coffee
+++ client/coffee/abstractEvidence.coffee
@@ -1,5 +1,6 @@
 Session.setDefault('evidenceShowNew', false)
 Session.setDefault('evidenceEditingId', null)
+Session.setDefault('nestedEvidenceEditingId', null)
 Session.setDefault('evidenceShowAll', false)
 Session.setDefault('evidenceType', null)

@@ -53,6 +54,13 @@
         fn = share.evidenceType[key].excel_fn
         Meteor.call method, tbl_id, (err, response) ->
             share.returnExcelFile(response, fn)
+
+share.abstractRowHelpers =
+
+    getChildren: ->
+        key = Session.get('evidenceType')
+        NestedCollection = share.evidenceType[key].nested_collection
+        return NestedCollection.find({parent_id: @_id}, {sort: {sortIdx: 1}})

 share.abstractRowEvents =

@@ -72,6 +80,14 @@
         Collection = share.evidenceType[key].collection
         Collection.update(@_id, {$set: {isHidden: !@isHidden}})

+    'click .add-nested': (evt, tmpl) ->
+        # remove exiting modal, add new one, and inject scope
+        div = tmpl.find('#nestedModalHolder')
+        $(div).empty()
+        key = Session.get('evidenceType')
+        NestedTemplate = share.evidenceType[key].nested_template
+        Blaze.renderWithData(NestedTemplate, {parent: @}, div)
+
 share.abstractFormEvents =

     'click #create-cancel': (evt, tmpl) ->
@@ -119,3 +135,111 @@
         collection_name = share.evidenceType[key].collection_name
         Meteor.call 'adminToggleQAd', this._id, collection_name, (err, response) ->
             if response then share.toggleQA(tmpl, response.QAd)
+
+share.abstractNestedTableHelpers =
+
+    showRow: (isHidden) ->
+        Session.get('evidenceShowAll') or !isHidden
+
+share.abstractNestedTableEvents =
+
+    'click #inner-show-edit': (evt, tmpl) ->
+        div = tmpl.find('#nestedModalHolder')
+        key = Session.get('evidenceType')
+        NestedTemplate = share.evidenceType[key].nested_template
+        Session.set('nestedEvidenceEditingId', tmpl.data._id)
+        Blaze.renderWithData(NestedTemplate, {}, div)
+
+    'click #inner-toggle-hidden': (evt, tmpl) ->
+        key = Session.get('evidenceType')
+        NestedCollection = share.evidenceType[key].nested_collection
+        data = tmpl.view.parentView.dataVar.curValue
+        NestedCollection.update(data._id, {$set: {isHidden: !data.isHidden}})
+
+    'click #inner-copy-as-new': (evt, tmpl) ->
+        key = Session.get('evidenceType')
+        NestedTemplate = share.evidenceType[key].nested_template
+        data = tmpl.view.parentView.dataVar.curValue
+        data.parent = {_id: data.parent_id}
+        div = tmpl.find('#nestedModalHolder')
+        Blaze.renderWithData(NestedTemplate, data, div)
+
+share.abstractNestedFormHelpers =
+
+    isNew: ->
+        return Session.get('nestedEvidenceEditingId') is null
+
+    getObject: () ->
+        # get data to render into form, either using a reactive data-source if
+        # editing an existing result, or by using initial-data specified from
+        # a creation view
+        key = Session.get('evidenceType')
+        NestedCollection = share.evidenceType[key].nested_collection
+        initial = @
+        existing = NestedCollection.findOne({_id: Session.get('nestedEvidenceEditingId')})
+        return existing || initial
+
+removeModal = (tmpl, options) ->
+
+    onHidden = () ->
+        # remove template from DOM completely
+        key = Session.get('evidenceType')
+        NestedCollection = share.evidenceType[key].nested_collection
+        $(tmpl.view._domrange.members).remove()
+        Blaze.remove(tmpl.view)
+        if options? and options.remove?
+            NestedCollection.remove(options.remove)
+
+    $(tmpl.find('#nestedModalDiv'))
+        .on('hidden.bs.modal', onHidden)
+        .modal('hide')
+
+share.abstractNestedFormEvents =
+
+    'click #inner-create': (evt, tmpl) ->
+        key = Session.get('evidenceType')
+        NestedCollection = share.evidenceType[key].nested_collection
+        obj = share.newValues(tmpl.find('#nestedModalForm'))
+        obj['tbl_id'] = Session.get('Tbl')._id
+        obj['parent_id'] = tmpl.data.parent._id
+        obj['sortIdx'] = 1e10  # temporary, make sure to place at bottom
+        obj['isHidden'] = false
+        isValid = NestedCollection.simpleSchema().namedContext().validate(obj)
+        if isValid
+            NestedCollection.insert(obj)
+            removeModal(tmpl)
+        else
+            errorDiv = share.createErrorDiv(NestedCollection.simpleSchema().namedContext())
+            $(tmpl.find("#errors")).html(errorDiv)
+
+    'click #inner-create-cancel': (evt, tmpl) ->
+        removeModal(tmpl)
+
+    'click #inner-update': (evt, tmpl) ->
+        key = Session.get('evidenceType')
+        NestedCollection = share.evidenceType[key].nested_collection
+        vals = share.updateValues(tmpl.find('#nestedModalForm'), @)
+        modifier = {$set: vals}
+        isValid = NestedCollection.simpleSchema().namedContext().validate(modifier, {modifier: true})
+        if isValid
+            NestedCollection.update(@_id, modifier)
+            Session.set("nestedEvidenceEditingId", null)
+            removeModal(tmpl)
+        else
+            errorDiv = share.createErrorDiv(NestedCollection.simpleSchema().namedContext())
+            $(tmpl.find("#errors")).html(errorDiv)
+
+    'click #inner-update-cancel': (evt, tmpl) ->
+        Session.set("nestedEvidenceEditingId", null)
+        removeModal(tmpl)
+
+    'click #inner-delete': (evt, tmpl) ->
+        Session.set("nestedEvidenceEditingId", null)
+        removeModal(tmpl, {"remove": @_id})
+
+    'click #setQA,#unsetQA': (evt, tmpl) ->
+        key = Session.get('evidenceType')
+        nested_collection_name = share.evidenceType[key].nested_collection_name
+        Meteor.call 'adminToggleQAd', this._id, nested_collection_name, (err, response) ->
+            if response then share.toggleQA(tmpl, response.QAd)
+


filetree: give a default size

filetree: give a default size

--- client/ide/views/basesplitview.coffee
+++ client/ide/views/basesplitview.coffee
@@ -4,7 +4,7 @@

     super

-    @lastKnownFileTreeSize = @getOption('sizes').first
+    @lastKnownFileTreeSize = @getOption('sizes').first or 250

     @on 'PanelDidResize', KD.utils.debounce 10, =>


Use ArrayPort to allow keying for 'in' and 'ready'

--- components/Cache.coffee
+++ components/Cache.coffee
@@ -14,7 +14,7 @@
     @inPorts =
       in: new noflo.Port
       ready: new noflo.Port
-      key: new noflo.Port
+      key: new noflo.ArrayPort
       size: new noflo.Port
     @outPorts =
       out: new noflo.Port


ContentSearch: Hide previous warningView when new search performed.

--- client/ide/views/contentsearch/idecontentsearch.coffee
+++ client/ide/views/contentsearch/idecontentsearch.coffee
@@ -52,8 +52,12 @@
     super options, data

   search: ->
+    @warningView.hide()
+
     vmController = KD.getSingleton 'vmController'
-    @searchText  = Encoder.XSSEncode @input.getValue()
+    @searchText  = Encoder.XSSEncode @findInput.getValue()
+    @rootPath    = Encoder.XSSEncode @whereInput.getValue()
+
     vmController.run "ag '#{@searchText}' '#{@rootPath}' -C 3 --ackmate --stats", (err, res) =>
       return @showWarning 'Something went wrong, please try again.', yes  if err or res.stderr


Set message.ts if empty

Set message.ts if empty

--- packages/rocketchat-lib/server/methods/sendMessage.coffee
+++ packages/rocketchat-lib/server/methods/sendMessage.coffee
@@ -7,6 +7,8 @@
 				throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', { method: 'sendMessage', message_ts: message.ts, server_ts: new Date().getTime() })
 			else if tsDiff > 10000
 				message.ts = new Date()
+		else
+			message.ts = new Date()

 		if message.msg?.length > RocketChat.settings.get('Message_MaxAllowedSize')
 			throw new Meteor.Error('error-message-size-exceeded', 'Message size exceeds Message_MaxAllowedSize', { method: 'sendMessage' })


fix indent

fix indent

--- config/constants.coffee
+++ config/constants.coffee
@@ -1,9 +1,8 @@
 module.exports =
-  score:
-    checkPoint:
-      team: 10
-      user: 5
-  energy:
-    frequencyMs: 15000
-    value: 1
-    maxValue: 15
+    score: checkPoint:
+        team: 10
+        user: 5
+    energy:
+        frequencyMs: 15000
+        value: 1
+        maxValue: 15


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/function_extensions.coffee
+++ src/function_extensions.coffee
@@ -6,7 +6,7 @@
     return memo if ran
     ran = true

-    return mom
+    return memo =

   _.once = function(func) {
     var ran = false, memo;


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/function_extensions.coffee
+++ src/function_extensions.coffee
@@ -8,7 +8,7 @@
     return memo if ran
     ran = true

-    return memo = @apply(arguments)
+    return memo = func.apply(arguments)

 Function::withBefore = (interception) ->
   method = this


Enable capacity labels for Heat sortable

--- app/assets/javascripts/lib/app.coffee
+++ app/assets/javascripts/lib/app.coffee
@@ -57,7 +57,7 @@
       new UserSortable(flex_order, 'flexibility_order', true).render()

     if (heat_order = wrapper.find('#heat-network-options')).length
-      new UserSortable(heat_order, 'heat_network_order').render()
+      new UserSortable(heat_order, 'heat_network_order', true).render()

     if (curve_upload = wrapper.find('.curve-upload')).length
       CustomCurveChooserView.setupWithWrapper(curve_upload).render();


Remove line that now doesn't do anything anyway

--- app/assets/javascripts/main.js.coffee
+++ app/assets/javascripts/main.js.coffee
@@ -36,7 +36,6 @@

 window.onhashchange = ->
   if location.hash.substring(0, 3) == '#!/'
-    $('#dialog_wrapper').remove()
     window.active_navigation.abort() if window.active_navigation
     window.active_navigation = $.getScript location.hash.replace('#!', '')


Added initial work on the basic text dropdown

--- coffee/bootstrap-text-dropdown.coffee
+++ coffee/bootstrap-text-dropdown.coffee
@@ -1,137 +1,220 @@
-(($) ->
-
-  backdrop = '.text-dropdown-backdrop'
-  toggle   = '[data-toggle="text-dropdown"]'
-  Dropdown = (element) ->
-    $(element).on('click.bs.text-dropdown', @toggle)
-
-  Dropdown.VERSION = '3.3.1'
-
-  Dropdown.prototype.toggle = (e) ->
-    $this = $(@)
-
-    return if $this.is('.disabled, :disabled')
-
-    $parent  = getParent($this)
-    isActive = $parent.hasClass('open')
-
-    clearMenus()
-
-    if !isActive
-      if 'ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length
-        $('
').insertAfter($(this)).on('click', clearMenus)
-
-      relatedTarget = { relatedTarget: this }
-      $parent.trigger(e = $.Event('show.bs.text-dropdown', relatedTarget))
-
-      return if e.isDefaultPrevented()
-
-      $this
-        .trigger('focus')
-        .attr('aria-expanded', 'true')
-
-      $parent
-        .toggleClass('open')
-        .trigger('shown.bs.text-dropdown', relatedTarget)
-
-    return false
-
-  Dropdown.prototype.keydown = (e) ->
-    return if !/(38|40|27|32)/.test(e.which) or /input|textarea/i.test(e.target.tagName)
-
-    $this = $(this)
-
-    e.preventDefault()
-    e.stopPropagation()
-
-    return if $this.is('.disabled, :disabled')
-
-    $parent  = getParent($this)
-    isActive = $parent.hasClass('open')
-
-    if (!isActive and e.which != 27) or (isActive and e.which == 27)
-      if e.which == 27 then $parent.find(toggle).trigger('focus')
-      return $this.trigger('click')
-
-    desc = ' li:not(.divider):visible a'
-    $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
-
-    return if !$items.length
-
-    index = $items.index(e.target)
-
-    if e.which == 38 and index > 0                    then index--                        ## up
-    if e.which == 40 and index < $items.length - 1    then index++                        ## down
-    if !~index                                        then index = 0
-
-    $items.eq(index).trigger('focus')
-
-
-  clearMenus = (e) ->
-    return if e && e.which == 3
-    $(backdrop).remove()
-    $(toggle).each () ->
-      $this         = $(this)
-      $parent       = getParent($this)
-      relatedTarget = { relatedTarget: this }
-
-      return if (!$parent.hasClass('open'))
-
-      $parent.trigger(e = $.Event('hide.bs.text-dropdown', relatedTarget))
-
-      return if (e.isDefaultPrevented())
-
-      $this.attr('aria-expanded', 'false')
-      $parent.removeClass('open').trigger('hidden.bs.text-dropdown', relatedTarget)
-
-
-  getParent = ($this) ->
-    selector = $this.attr('data-target')
-
-    if !selector
-      selector = $this.attr('href')
-      selector = selector and /#[A-Za-z]/.test(selector) and selector.replace(/.*(?=#[^\s]*$)/, '') ## strip for ie7
-
-    $parent = selector and $(selector)
-
-    return $parent and $parent.length ? $parent : $this.parent()
-
-
-  ## DROPDOWN PLUGIN DEFINITION
-  ## ==========================
-
-  Plugin = (option) ->
-    return @each () ->
+(($, window, document) ->
+
+  'use strict'
+
+  Textdropdown = (element, options) ->
+    this.widget = ''
+    this.$element = $(element)
+    this.isOpen = options.isOpen
+    this.orientation = options.orientation
+    this.container = options.container
+    @_init()
+
+  Textdropdown.prototype =
+
+    constructor: Textdropdown
+
+    _init: () ->
+      self = @
+      @.$element.on {
+        'click.textdropdown': $.proxy(this.showWidget, this)
+        'blur.textdropdown': $.proxy(this.blurElement, this)
+      }
+
+      @.$widget = $(@getTemplate()).on('click', $.proxy(@widgetClick, @))
+      @.$widget.find('textarea').each () ->
+        $(@).on {
+          'click.textdropdown': () -> $(@).select()
+          'keydown.textdropdown': $.proxy(self.widgetKeydown, self)
+          'keyup.textdropdown': $.proxy(self.widgetKeyup, self)
+        }
+
+    blurElement: () ->
+      @highlightedUnit = null
+      @updateFromElementVal()
+
+    clear: () ->
+      @.$element.val('')
+
+
+    elementKeydown: (e) ->
+      @update()
+
+    getTemplate: () ->
+      "
<textarea class='bootstrap-text-dropdown-body'></textarea>
"
+
+    getText: () ->
+      @text
+
+    hideWidget: () ->
+      return if @isOpen == false
+
+      @.$element.trigger {
+        'type': 'hide.textdropdown'
+        'text': {
+          'value': this.getText()
+        }
+      }
+
+      @.$widget.removeClass('open')
+
+      $(document).off('mousedown.textdropdown, touchend.textdropdown')
+
+      @isOpen = false
+      @.$widget.detach()
+
+    place : () ->
+      return if @isInline
+
+      widgetWidth = @.$widget.outerWidth()
+      widgetHeight = @.$widget.outerHeight()
+      visualPadding = 10
+      windowWidth = $(window).width()
+      windowHeight = $(window).height()
+      scrollTop = $(window).scrollTop()
+
+      zIndex = parseInt(@.$element.parents().first().css('z-index'), 10) + 10
+      offset = if @component then @.omponent.parent().offset() else @.$element.offset()
+      height = if @component then @component.outerHeight(true) else @.$element.outerHeight(false)
+      width = if @component then @component.outerWidth(true) else @.$element.outerWidth(false)
+      left = offset.left
+      top = offset.top
+
+      @.$widget.removeClass('textdropdown-orient-top textdropdown-orient-bottom textdropdown-orient-right textdropdown-orient-left')
+
+      if @orientation.x != 'auto'
+        @picker.addClass('textdropdown-orient-' + this.orientation.x)
+        if @orientation.x == 'right'
+          left -= widgetWidth - width
+      else
+        @.$widget.addClass('textdropdown-orient-left')
+        if offset.left < 0
+          left -= offset.left - visualPadding
+        else if offset.left + widgetWidth > windowWidth
+          left = windowWidth - widgetWidth - visualPadding
+
+      yorient = @.orientation.y
+      topOverflow = undefined
+      bottomOverflow = undefined
+
+      if yorient == 'auto'
+        topOverflow = -scrollTop + offset.top - widgetHeight
+        bottomOverflow = scrollTop + windowHeight - (offset.top + height + widgetHeight)
+        if Math.max(topOverflow, bottomOverflow) == bottomOverflow
+          yorient = 'top'
+        else
+          yorient = 'bottom'
+
+      @.$widget.addClass('textdropdown-orient-' + yorient)
+      if yorient == 'top'
+        top += height
+      else
+        top -= widgetHeight + parseInt(this.$widget.css('padding-top'), 10)
+
+      @.$widget.css {
+        top : top
+        left : left
+        zIndex : zIndex
+      }
+
+    remove: () ->
+      $('document').off('.textdropdown')
+      if @.$widget
+        @.$widget.remove()
+      delete @.$element.data().textdropdown
+
+    setText: (text, ignoreWidget) ->
+      if !text
+        @clear()
+        return
+
+      @text = text
+      @update(ignoreWidget)
+
+    showWidget: (e) ->
+      e.preventDefault()
+      return if @isOpen
+      return if @.$element.is(':disabled')
+
+
+      @.$widget.appendTo(this.container)
+      self = @;
+      $(document).on 'mousedown.textdropdown, touchend.textdropdown', (e) ->
+        self.hideWidget() if !(self.$element.parent().find(e.target).length || self.$widget.is(e.target) || self.$widget.find(e.target).length)
+
+      @.$element.trigger {
+        'type': 'show.textdropdown',
+        'text': {
+          'value': this.getText()
+        }
+      }
+
+      @place()
+      @.$element.blur()
+
+      @.$widget.addClass('open') if @isOpen == false
+      @.$widget.find("textarea").focus()
+      @isOpen = true
+
+    update: (ignoreWidget) ->
+      @updateElement()
+      this.updateWidget() if !ignoreWidget
+
+    updateElement: () ->
+      @.$element.val(@getText()).change()
+
+    updateFromElementVal: () ->
+      @setText(@.$element.val())
+
+    updateWidget: () ->
+      return if (@.$widget == false)
+
+      text = @text;
+      @.$widget.find('.bootstrap-text-dropdown-body').val(text)
+
+    updateFromWidgetInputs: () ->
+      return if @.$widget == false
+
+      t = @.$widget.find('.bootstrap-text-dropdown-body').val()
+      @setText(t, true)
+
+    widgetClick: (e) ->
+      e.stopPropagation()
+      e.preventDefault()
+
+      $input = $(e.target)
+      action = $input.closest('a').data('action')
+
+      if action
+        @[action]()
+      @update()
+
+    widgetKeyup: (e) ->
+      @updateFromWidgetInputs()
+
+
+  $.fn.textdropdown = (option) ->
+    args = Array.apply(null, arguments)
+    args.shift()
+    @each () ->
       $this = $(@)
-      data  = $this.data('bs.text-dropdown')
-
-      if !data then $this.data('bs.text-dropdown', (data = new Dropdown(@)))
-      if typeof option == 'string' then data[option].call($this)
-
-  old = $.fn.textDropdown
-
-  $.fn.textDropdown             = Plugin
-  $.fn.textDropdown.Constructor = Dropdown
-
-
-  ## DROPDOWN NO CONFLICT
-  ## ====================
-
-  $.fn.textDropdown.noConflict = () ->
-    $.fn.dropdown = old
-    return @
-
-
-  ## APPLY TO STANDARD DROPDOWN ELEMENTS
-  ## ===================================
-
-  $(document)
-    .on 'click.bs.text-dropdown.data-api', clearMenus
-    .on 'click.bs.text-dropdown.data-api', '.dropdown form', (e) -> e.stopPropagation()
-    .on 'click.bs.text-dropdown.data-api', toggle, Dropdown.prototype.toggle
-    .on 'keydown.bs.text-dropdown.data-api', toggle, Dropdown.prototype.keydown
-    .on 'keydown.bs.text-dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown
-    .on 'keydown.bs.text-dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown
-
-
-) jQuery
+      data = $this.data('textdropdown')
+      options = typeof option == 'object' && option
+
+      if !data
+        $this.data('textdropdown', (data = new Textdropdown(this, $.extend({}, $.fn.textdropdown.defaults, options, $(this).data()))))
+
+      if typeof option == 'string'
+        data[option].apply(data, args)
+
+
+  $.fn.textdropdown.defaults =
+    isOpen: false
+    orientation: { x: 'auto', y: 'auto'}
+    container: 'body'
+
+  $.fn.textdropdown.Constructor = Textdropdown
+
+
+) jQuery, window, document
+


fix xss in the kanban with the fullname

fix xss in the kanban with the fullname

--- app/coffee/modules/kanban/main.coffee
+++ app/coffee/modules/kanban/main.coffee
@@ -517,7 +517,7 @@
             html = template(ctx)
             $el.html(html)
             username_label = $el.parent().find("a.task-assigned")
-            username_label.html(ctx.name)
+            username_label.text(ctx.name)
             username_label.on "click", (event) ->
                 if $el.find("a").hasClass("noclick")
                     return


add text re: sign-in to tutorial

add text re: sign-in to tutorial

--- app/lib/slide-tutorial-content.coffee
+++ app/lib/slide-tutorial-content.coffee
@@ -21,6 +21,6 @@

   {image: 'assets/tutorial-content/slide5.jpg'
   title: '''Join the community and learn more!''',
-  content: '''That’s it! You’re ready to start exploring Gorongosa! If you’d like to learn more about the project, you can visit the About page or the WildCam Gorongosa blog. And if you have any more questions, or just want to chat about the project or share a cool image you found, please join us on WildCam Gorongosa Talk. Thank you for your help!''',
+  content: '''That’s it! You’re ready to start exploring Gorongosa! Make sure to sign in with your Zooniverse account (in the top right corner) so you can track your contributions, collect images, and discuss the project on the Talk pages. If you’d like to learn more about the project, you can visit the About page or the WildCam Gorongosa blog. And if you have any more questions, or just want to chat about the project or share a cool image you found, please join us on WildCam Gorongosa Talk. Thank you for your help!''',
   button: 'Finish'}
 ]


fix test failed

fix test failed

--- test/server/doc-coverage-test.coffee
+++ test/server/doc-coverage-test.coffee
@@ -13,7 +13,7 @@

     it 'should return object which has tree layered hash', ->
       correct = {
-        "all": 5,
+        "all": 7,
         "covered": 5,
         "children": [
           {
@@ -37,7 +37,7 @@
                 "covered": 3
               }
             ],
-            "all": 3,
+            "all": 4,
             "covered": 3
           },
           {
@@ -56,7 +56,7 @@
                 "covered": 2
               }
             ],
-            "all": 2,
+            "all": 3,
             "covered": 2
           }
         ]


Implement RubyMotion file detection

Implement RubyMotion file detection

--- lib/rubymotion.coffee
+++ lib/rubymotion.coffee
@@ -1,4 +1,6 @@
 _ = require 'underscore-plus'
+fs = require 'fs'
+pathmod = require 'path'
 RubyMotionAutocompleteView = require './rubymotion-autocomplete-view'
 # FIXME: dirty hack for wrong module path detection on `apm test`
 snippetsModPath = _.find atom.packages.getAvailablePackagePaths(), (path) ->
@@ -17,6 +19,7 @@
   activate: (state) ->
     @editorSubscription = atom.workspaceView.eachEditorView (editor) =>
       if editor.attached
+        @detectRubyMotion(editor)
         @enableAutocomplete(editor)

     @collectSnippets (prefixes) =>
@@ -47,6 +50,19 @@
         word1.toLowerCase().localeCompare(word2.toLowerCase())
       callback keys

+  detectRubyMotion: (editor) ->
+    editorPath = editor.getEditor().getPath()
+    ext = pathmod.extname(editorPath)
+    return if ext isnt '.rb'
+    rakefile_path = atom.project.rootDirectory.path + '/Rakefile'
+    fs.readFile rakefile_path, (err, data) ->
+      if !err && data.toString().match /Motion/
+        rbpath = atom.packages.resolvePackagePath('RubyMotion') + '/grammars/rubymotion.cson'
+        grammar = atom.syntax.loadGrammarSync(rbpath)
+        editor.getEditor().setGrammar grammar
+        editor.getEditor().on 'grammar-changed', =>
+          editor.getEditor().setGrammar grammar
+
   lookUpInDash: (editor) ->
     word = editor.getWordUnderCursor(includeNonWordCharacters: false)
     return if word is ''


Scroll comment into view if needed

Scroll comment into view if needed

--- src/js/content/~init.js.coffee
+++ src/js/content/~init.js.coffee
@@ -19,3 +19,7 @@

   History.load()
   Controls.load()
+
+  if /^#comment_/.test(window.location.hash)
+    node = document.getElementById(window.location.hash.slice(1))
+    node.scrollIntoViewIfNeeded() if node?


fix for when store.get returns nothing

fix for when store.get returns nothing

--- src/js/peteshow-storage.coffee
+++ src/js/peteshow-storage.coffee
@@ -5,6 +5,7 @@
   get: (key) ->
     console.log('PeteshowStorage::get')
     data = store.get('peteshow')
+    return unless data
     return data[key] if key?
     data


fix(injected-component): Correctly call methods to the injected instance

- Adds check to `_runInnerDOMMethod` to check if inner is an UnsafeComponent and
relay the call appropriately
- Removes duplicated logic from `_setRequiredMethods`

--- src/components/injected-component.cjsx
+++ src/components/injected-component.cjsx
@@ -127,27 +127,26 @@
   # 2. Any native implementation provided by the DOM
   # 3. Ourselves, so that the method always has /some/ effect.
   #
-  _runInnerDOMMethod: (method) =>
+  _runInnerDOMMethod: (method, args...) =>
     target = null
-    if @refs.inner and @refs.inner[method]
+    if @refs.inner instanceof UnsafeComponent and @refs.inner.injected[method]?
+      target = @refs.inner.injected
+    else if @refs.inner and @refs.inner[method]?
       target = @refs.inner
     else if @refs.inner
       target = React.findDOMNode(@refs.inner)
     else
       target = React.findDOMNode(@)

-    target[method]?()
+    target[method].bind(target)(args...)

   _setRequiredMethods: (methods) =>
     methods.forEach (method) =>
       Object.defineProperty(@, method,
         configurable: true
         enumerable: true
-        get: =>
-          if @refs.inner instanceof UnsafeComponent
-            @refs.inner.injected[method]?.bind(@refs.inner.injected)
-          else
-            @refs.inner[method]?.bind(@refs.inner)
+        value: (args...)=>
+          @_runInnerDOMMethod(method, args...)
       )

   _verifyRequiredMethods: =>


Prevent mouse events from bubbling

Prevent mouse events from bubbling

--- lib/table-view.coffee
+++ lib/table-view.coffee
@@ -59,6 +59,7 @@
       'table-edit:select-to-end-of-table': => @expandSelectionToEndOfTable()
       'table-edit:select-to-beginning-of-table': => @expandSelectionToBeginningOfTable()
       'mousedown': (e) =>
+        e.stopPropagation()
         e.preventDefault()
         @focus()

@@ -66,6 +67,7 @@
       'scroll': => @requestUpdate()
       'dblclick': (e) => @startEdit()
       'mousedown': (e) =>
+        e.stopPropagation()
         e.preventDefault()

         @stopEdit() if @isEditing()
@@ -76,9 +78,11 @@
         @startDrag(e)
         @focus()
       'mousemove': (e) =>
+        e.stopPropagation()
         e.preventDefault()
         @drag(e)
       'mouseup': (e) =>
+        e.stopPropagation()
         e.preventDefault()
         @endDrag(e)


After a lot of deliberation, I like this default

Whiny conflicts for static picks make some sense, but b/c of the vendor+
app relationship (where app is seen as overriding vendor), I think I'd
prefer to default to allowing merge conflicts with the assumption that
callers will prioritize app over vendor.

--- lib/util/merge.coffee
+++ lib/util/merge.coffee
@@ -2,4 +2,4 @@
 mergeTrees = require('broccoli-merge-trees')

 module.exports = (trees...) ->
-  mergeTrees(_(trees).chain().flatten().compact().value())
+  mergeTrees(_(trees).chain().flatten().compact().value(), overwrite: true)


RTE sever value for newly controls, fixes #868 - issue: on switch, previousServerValue is empty string   - serverValue is from ORBEON.xforms.ServerValueStore.get(controlId) - what happens: when adding an RTE, ServerValueStore.set is called twice   - in AjaxServer, when handling the control element   - in AjaxServer, after the update, in case the HTML changes when set     - at that point the value is empty as the control doesn't exist - solution: in RTE.coffee set server value after setting it in RTE

--- src/resources-packaged/ops/javascript/orbeon/xforms/control/RTE.coffee
+++ src/resources-packaged/ops/javascript/orbeon/xforms/control/RTE.coffee
@@ -84,6 +84,9 @@
         @onRendered () =>
             if (not YD.hasClass(@container, "xforms-incremental") || ORBEON.xforms.Globals.currentFocusControlId != @container.id)
                 @yuiRTE.setEditorHTML(newValue)
+                # Set new server value; if we don't value server value for new controls will be empty as it wasn't
+                # available at the time the control was created
+                ServerValueStore.set(@container.id, @yuiRTE.getEditorHTML())

     getValue: () ->
         value = @yuiRTE.getEditorHTML()


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- test/array_extensions.coffee
+++ test/array_extensions.coffee
@@ -1,6 +1,6 @@
 module "Array"

-test ""
+test "#aver"

 test "#compact", ->
   a = [0, 1, undefined, 2, null, 3, '', 4]


removed remaining.coffee test case

removed remaining.coffee test case

--- tests/cases/remaining.coffee
+++ tests/cases/remaining.coffee
@@ -1,26 +0,0 @@
-
-# See also errors in function_invocation.coffee, ranges.coffee
-
-i = 10
-results = while i > 0
-  i--
-  switch i % 2
-    when 1 then i
-    when 0 then break
-
-###
-(success and= typeof n is 'number') for n in flatten [0, [[[1]], 2], 3, [4]]
-
-eq 4, 0b100
-
-result = ident
-  one: 1
-  two: 2 for i in [1..3]
-
-eq 1, [5 in []].length
-
-arr = [1..4]
-
-arrayEq [1, 2, 3, 4], shared[a..b]
-###
-


config.cson specific to environment, don't sync

--- config.cson
+++ config.cson
@@ -1,26 +0,0 @@
-"*":
-  minimap:
-    plugins:
-      "git-diff": true
-      linter: true
-  welcome:
-    showOnStartup: false
-  "exception-reporting":
-    userId: "883a98c2-d4d6-21fa-2ffa-02c51bd94e01"
-  core:
-    themes: [
-      "atom-material-ui"
-      "one-light-syntax"
-    ]
-  editor:
-    invisibles: {}
-    backUpBeforeSaving: true
-    preferredLineLength: 100
-  linter:
-    showErrorPanel: false
-  react: {}
-  "tool-bar": {}
-  "tut-ascii-art":
-    font: "Ghoulish"
-    config:
-      font: {}


Fix variable name

Fix variable name

--- src/trix/utilities/html_parser.coffee
+++ src/trix/utilities/html_parser.coffee
@@ -57,7 +57,7 @@
         if element.classList.contains("attachment")
           attributes = getAttachmentAttributes(element)
           if Object.keys(attributes).length
-            textAttributes = getTextAttributes(node)
+            textAttributes = getTextAttributes(element)
             if image = element.querySelector("img")
               textAttributes.width = image.width if image.width?
               textAttributes.height = image.height if image.height?


Remove debugger

Remove debugger

--- app/src/database/model_context.coffee
+++ app/src/database/model_context.coffee
@@ -194,7 +194,6 @@
         unless _(collectionData).isEmpty()
           collection.updateSynchronizedProperties(collectionData)
         else
-          debugger
           # delete all
           collection.getModelClass().chain(this).remove()
       @emit 'synchronized'


Repair support URL in DropdownUserDirective

--- app/modules/navigation-bar/dropdown-user/dropdown-user.directive.coffee
+++ app/modules/navigation-bar/dropdown-user/dropdown-user.directive.coffee
@@ -23,6 +23,7 @@
     link = (scope, el, attrs, ctrl) ->
         scope.vm = {}
         scope.vm.isFeedbackEnabled = configService.get("feedbackEnabled")
+        scope.vm.supportUrl = configService.get("supportUrl")
         taiga.defineImmutableProperty(scope.vm, "user", () -> authService.userData)

         scope.vm.logout = ->


changed modifier to hyper key

changed modifier to hyper key

--- tilde/zephyros/config.coffee
+++ tilde/zephyros/config.coffee
@@ -4,41 +4,41 @@
 # - send window space [dir]

 # Make Window Full Screen
-bind "M", ["cmd", "ctrl"], -> moveWindow null
+bind "M", ["cmd", "ctrl", "alt", "shift"], -> moveWindow null

 # Center Window
-bind "C", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "C", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   frame.x += frame.w / 6
   frame.y += frame.h / 8
   frame.w /= 1.5
   frame.h /= 1.3

 # Center Window with borders
-bind "B", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "B", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   frame.x += frame.w / 15
   frame.w /= 1.15

 # Top Left Corner
-bind "1", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "1", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   frame.w /= 1.5
   frame.h /= 1.3

 # Top Right Corner
-bind "2", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "2", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   width = win.screen().frameIncludingDockAndMenu().w
   frame.x = width - (frame.w / 1.5)
   frame.w /= 1.5
   frame.h /= 1.3

 # Bottom Left Corner
-bind "3", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "3", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   height = win.screen().frameIncludingDockAndMenu().h
   frame.y = height - (frame.h / 1.3)
   frame.w /= 1.5
   frame.h /= 1.3

 # Bottom Right Corner
-bind "4", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "4", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   height = win.screen().frameIncludingDockAndMenu().h
   width = win.screen().frameIncludingDockAndMenu().w
   frame.x = width - (frame.w / 1.5)
@@ -47,58 +47,34 @@
   frame.h /= 1.3

 # show clipboard contents
-bind "I", ["cmd", "ctrl"], ->
+bind "I", ["cmd", "ctrl", "alt", "shift"], ->
   alert api.clipboardContents()

 # Send Window Left
-bind "LEFT", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "LEFT", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   frame.w /= 2

 # Send Window Right
-bind "RIGHT", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "RIGHT", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   frame.x += frame.w / 2
   frame.w /= 2

 # Send Window Up
-bind "UP", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "UP", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   frame.h /= 2

 # Send Window Down
-bind "DOWN", ["cmd", "ctrl"], -> moveWindow (win, frame) ->
+bind "DOWN", ["cmd", "ctrl", "alt", "shift"], -> moveWindow (win, frame) ->
   frame.y += frame.h / 2
   frame.h /= 2

-# Send Window Upper Left
-bind "LEFT", ["shift", "alt", "ctrl"], -> moveWindow (win, frame) ->
-  frame.w /= 2
-  frame.h /= 2
-
-# Send Window Upper Right
-bind "UP", ["shift", "alt", "ctrl"], -> moveWindow (win, frame) ->
-  frame.y += frame.h / 2
-  frame.w /= 2
-  frame.h /= 2
-
-# Send Window Lower Left
-bind "DOWN", ["shift", "alt", "ctrl"], -> moveWindow (win, frame) ->
-  frame.x += frame.w / 2
-  frame.w /= 2
-  frame.h /= 2
-
-# Send Window Lower Right
-bind "RIGHT", ["shift", "alt", "ctrl"], -> moveWindow (win, frame) ->
-  frame.x += frame.w / 2
-  frame.y += frame.h / 2
-  frame.w /= 2
-  frame.h /= 2
-
 # Send Window to Next Display
-bind "RIGHT", ['ctrl', 'alt'], ->
+bind "H", ["cmd", "ctrl", "alt", "shift"], ->
   win = api.focusedWindow()
   moveToScreen win, win.screen().nextScreen()

 # Send Window to Previous Display
-bind "LEFT", ['ctrl', 'alt'], ->
+bind "L", ["cmd", "ctrl", "alt", "shift"], ->
   win = api.focusedWindow()
   moveToScreen win, win.screen().previousScreen()


Fix hrefs

Fix hrefs

--- models/auction.coffee
+++ models/auction.coffee
@@ -15,7 +15,10 @@
     response

   href: ->
-    "/auction/#{@id}"
+    if @isAuctionPromo()
+      "/sale/#{@id}"
+    else
+      "/auction/#{@id}"

   registrationSuccessUrl: ->
     "#{@href()}/confirm-registration"


send gravatar_id to the user

send gravatar_id to the user

--- js/inner/user.coffee
+++ js/inner/user.coffee
@@ -20,6 +20,7 @@
     basic_email_prefs: "smart"
     plan: null
     parallelism: 1
+    gravatar_id: null

   constructor: (json) ->
     super json,


Fixed comment count & remove all animations

--- public/dreamcatcher/controllers/comment_controller.coffee
+++ public/dreamcatcher/controllers/comment_controller.coffee
@@ -45,6 +45,7 @@
     totalCount = @getTotalCommentCount(entry)
     $(".showAll span",entry).text(totalCount)
     $(".commentsHeader .count span",entry).text(totalCount)
+    $(".comment .count span",entry).text(totalCount)

   loadComments: (entryId) ->
     #show loading wheel
@@ -116,9 +117,8 @@
     entryId = el.data 'entryid'
     commentId = el.data 'id'
     Dreamcatcher.Models.Comment.delete entryId,commentId
-    el.closest('.prevCommentWrap').fadeOut 200, (element) =>
-      $(element).remove()
-      @updateCommentCount entry
+    el.closest('.prevCommentWrap').remove()
+    @updateCommentCount entry

   '.save click': (el) ->
     $(".comment_body,.save",el.parent()).attr("disabled",true).addClass("disabled")


Stop docs images being loaded eagerly on any page load

--- js/outer/docs.coffee
+++ js/outer/docs.coffee
@@ -1,7 +1,6 @@
 CI.outer.Docs = class Docs extends CI.outer.Page
   constructor: ->
     @name = "docs"
-    @initialize()

   rewrite_old_name: (name) =>
     switch name
@@ -108,6 +107,7 @@
       null

   render: (cx) =>
+    @initialize()
     try
       rewrite = @rewrite_old_name cx.params.splat[0]
       if rewrite != false


Fix stupid error - make docs links automatically again

--- js/outer/docs.coffee
+++ js/outer/docs.coffee
@@ -123,7 +123,7 @@

   addLinkTargets: =>
     # Add a link target to every heading. If there's an existing id, it won't override it
-    h = "article doc" # hierarchy
+    h = "article .doc" # hierarchy
     for heading in $("#{h} h2, #{h} h3, #{h} h4, #{h} h5, #{h} h6")
       @addLinkTarget heading


rename `updateDisplay` to `updatePriceDisplay`

--- resources/assets/coffee/_classes/store-support-osu.coffee
+++ resources/assets/coffee/_classes/store-support-osu.coffee
@@ -57,9 +57,9 @@
       max: @MAX_VALUE * @RESOLUTION,
       slide: (event, ui) =>
         values = @calculate(ui.value)
-        @updateDisplay(values)
+        @updatePriceDisplay(values)
     }
-    @updateDisplay(@calculate(@MIN_VALUE * @RESOLUTION))
+    @updatePriceDisplay(@calculate(@MIN_VALUE * @RESOLUTION))
     slider

   initializeUsernameInput: =>
@@ -94,7 +94,7 @@

     Object.assign(Object.create(StoreSupportOsu.Price), values)

-  updateDisplay: (obj) =>
+  updatePriceDisplay: (obj) =>
     @priceElement.textContent = "USD #{obj.price}"
     monthText = if (obj.duration == 1) then 'month' else 'months'
     @durationElement.textContent = "#{obj.duration} #{monthText}"