Remove unused command-mode-input-confirm event from tests

--- spec/motions-spec.coffee
+++ spec/motions-spec.coffee
@@ -398,8 +398,7 @@

         # How to simulate typing?
         editor.commandModeInputView.editor.setText 'def'
-        # How do I tell the view to simulate'enter'?
-        editor.commandModeInputView.trigger 'vim-mode:command-mode-input-confirm'
+        editor.commandModeInputView.editor.trigger 'core:confirm'

         expect(editor.getCursorBufferPosition()).toEqual [1, 0]

@@ -407,7 +406,7 @@
         editor.setCursorBufferPosition([3, 0])
         keydown '/'
         editor.commandModeInputView.editor.setText 'def'
-        editor.commandModeInputView.trigger 'vim-mode:command-mode-input-confirm'
+        editor.commandModeInputView.editor.trigger 'core:confirm'

         expect(editor.getCursorBufferPosition()).toEqual [1, 0]

@@ -415,7 +414,7 @@
         beforeEach ->
           keydown '/'
           editor.commandModeInputView.editor.setText 'def'
-          editor.commandModeInputView.trigger 'vim-mode:command-mode-input-confirm'
+          editor.commandModeInputView.editor.trigger 'core:confirm'

         describe "the n keybinding", ->
           it "repeats the last search", ->
@@ -433,14 +432,14 @@
           keydown 'd'
           keydown '/'
           editor.commandModeInputView.editor.setText 'def'
-          editor.commandModeInputView.trigger 'vim-mode:command-mode-input-confirm'
+          editor.commandModeInputView.editor.trigger 'core:confirm'
           expect(editor.getText()).toEqual "def\nabc\ndef\n"

         it "repeats correctly with operators", ->
           keydown 'd'
           keydown '/'
           editor.commandModeInputView.editor.setText 'def'
-          editor.commandModeInputView.trigger 'vim-mode:command-mode-input-confirm'
+          editor.commandModeInputView.editor.trigger 'core:confirm'

           keydown '.'
           expect(editor.getText()).toEqual "def\n"
@@ -449,14 +448,14 @@
       it "moves the cursor backwards to the specified search pattern", ->
         keydown '?'
         editor.commandModeInputView.editor.setText 'def'
-        editor.commandModeInputView.trigger 'vim-mode:command-mode-input-confirm'
+        editor.commandModeInputView.editor.trigger 'core:confirm'
         expect(editor.getCursorBufferPosition()).toEqual [3, 0]

       describe "repeating", ->
         beforeEach ->
           keydown '?'
           editor.commandModeInputView.editor.setText 'def'
-          editor.commandModeInputView.trigger 'vim-mode:command-mode-input-confirm'
+          editor.commandModeInputView.editor.trigger 'core:confirm'

         describe 'the n keybinding', ->
           it "repeats the last search backwards", ->


Fix scoping issues where stubs were defined in wrong describe blocks

--- services/web/test/unit/coffee/Subscription/LimitationsManagerTests.coffee
+++ services/web/test/unit/coffee/Subscription/LimitationsManagerTests.coffee
@@ -78,19 +78,16 @@
 				@callback.calledWith(null, @user.features.collaborators).should.equal true

 	describe "canAddXCollaborators", ->
-		beforeEach ->
-			@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
-			@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
-			sinon.stub @LimitationsManager,
-					   "allowedNumberOfCollaboratorsInProject",
-					   (project_id, callback) => callback(null, @allowed_number)
-			@callback = sinon.stub()
-
 		describe "when the project has fewer collaborators than allowed", ->
 			beforeEach ->
 				@current_number = 1
 				@allowed_number = 2
 				@invite_count = 0
+				@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
+				@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
+				sinon.stub @LimitationsManager, "allowedNumberOfCollaboratorsInProject", (project_id, callback) =>
+					callback(null, @allowed_number)
+				@callback = sinon.stub()
 				@LimitationsManager.canAddXCollaborators(@project_id, 1, @callback)

 			it "should return true", ->
@@ -101,6 +98,11 @@
 				@current_number = 1
 				@allowed_number = 4
 				@invite_count = 1
+				@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
+				@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
+				sinon.stub @LimitationsManager, "allowedNumberOfCollaboratorsInProject", (project_id, callback) =>
+					callback(null, @allowed_number)
+				@callback = sinon.stub()
 				@LimitationsManager.canAddXCollaborators(@project_id, 1, @callback)

 			it "should return true", ->
@@ -111,6 +113,11 @@
 				@current_number = 1
 				@allowed_number = 2
 				@invite_count = 0
+				@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
+				@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
+				sinon.stub @LimitationsManager, "allowedNumberOfCollaboratorsInProject", (project_id, callback) =>
+					callback(null, @allowed_number)
+				@callback = sinon.stub()
 				@LimitationsManager.canAddXCollaborators(@project_id, 2, @callback)

 			it "should return false", ->
@@ -121,6 +128,11 @@
 				@current_number = 3
 				@allowed_number = 2
 				@invite_count = 0
+				@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
+				@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
+				sinon.stub @LimitationsManager, "allowedNumberOfCollaboratorsInProject", (project_id, callback) =>
+					callback(null, @allowed_number)
+				@callback = sinon.stub()
 				@LimitationsManager.canAddXCollaborators(@project_id, 1, @callback)

 			it "should return false", ->
@@ -131,6 +143,11 @@
 				@current_number = 100
 				@allowed_number = -1
 				@invite_count = 0
+				@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
+				@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
+				sinon.stub @LimitationsManager, "allowedNumberOfCollaboratorsInProject", (project_id, callback) =>
+					callback(null, @allowed_number)
+				@callback = sinon.stub()
 				@LimitationsManager.canAddXCollaborators(@project_id, 1, @callback)

 			it "should return true", ->
@@ -141,6 +158,11 @@
 				@current_number = 0
 				@allowed_number = 2
 				@invite_count = 2
+				@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
+				@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
+				sinon.stub @LimitationsManager, "allowedNumberOfCollaboratorsInProject", (project_id, callback) =>
+					callback(null, @allowed_number)
+				@callback = sinon.stub()
 				@LimitationsManager.canAddXCollaborators(@project_id, 1, @callback)

 			it "should return false", ->
@@ -151,6 +173,11 @@
 				@current_number = 1
 				@allowed_number = 2
 				@invite_count = 1
+				@CollaboratorsHandler.getInvitedCollaboratorCount = (project_id, callback) => callback(null, @current_number)
+				@CollaboratorsInviteHandler.getInviteCount = (project_id, callback) => callback(null, @invite_count)
+				sinon.stub @LimitationsManager, "allowedNumberOfCollaboratorsInProject", (project_id, callback) =>
+					callback(null, @allowed_number)
+				@callback = sinon.stub()
 				@LimitationsManager.canAddXCollaborators(@project_id, 1, @callback)

 			it "should return false", ->


Removes logs

Removes logs

--- lib/minimap-find-and-replace-binding.coffee
+++ lib/minimap-find-and-replace-binding.coffee
@@ -33,7 +33,6 @@
     @subscribe @findModel, 'updated', @markersUpdated

     setImmediate =>
-    console.log 'activated'
       @findModel.emit('updated', _.clone(@findModel.markers))

   deactivate: =>
@@ -42,7 +41,6 @@

     @findResultsView.detach()
     @unsubscribe @findModel, 'updated'
-    console.log 'deactivated'

   destroy: ->
     @deactivate()


more than I ever wanted to know about SVG... ever...

--- app/scripts/alchemy/core/startGraph.coffee
+++ app/scripts/alchemy/core/startGraph.coffee
@@ -101,7 +101,7 @@
         defs.append("svg:marker")
             .attr("id", "arrow")
             .attr("viewBox", "0 -#{arrowSize * 0.4} #{arrowSize} #{arrowSize}")
-            .attr("refX", 1)
+            .attr('markerUnits', 'userSpaceOnUse')
             .attr("markerWidth", arrowSize)
             .attr("markerHeight", arrowSize)
             .attr("orient", "auto")


Make zooming possible without tooltip display. Fixes #55

--- src/d3-flame-graph.coffee
+++ src/d3-flame-graph.coffee
@@ -161,7 +161,7 @@

     zoom: (node) ->
       throw new Error("Zoom is disabled!") if not @zoomEnabled()
-      @tip.hide()
+      @tip.hide() if @tip
       if node in @_ancestors
         @_ancestors = @_ancestors.slice(0, @_ancestors.indexOf(node))
       else
@@ -330,11 +330,13 @@
         .selectAll('.node')
         .classed('clickable', (d) => clickable(d))
         .on 'click', (d) =>
-          @tip.hide()
+          @tip.hide() if @tip
           @zoom(d) if clickable(d)
       @container
         .selectAll('.ancestor')
-        .on 'click', (d, idx) => @tip.hide(); @zoom(@_ancestors[idx])
+        .on 'click', (d, idx) =>
+          @tip.hide() if @tip
+          @zoom(@_ancestors[idx])
       @

     _generateAccessors: (accessors) ->


Fix FUP 407 error

Fix FUP 407 error

--- app/src/fup/firmware_update_request.coffee
+++ app/src/fup/firmware_update_request.coffee
@@ -302,7 +302,9 @@
         @_waitForPowerCycle(null, yes)
       .fail (e) =>
         switch @_getCard().SW
-          when 0x6985 then @_failure(Errors.ErrorDongleMayHaveASeed)
+          when 0x6985
+            @_processInitOs()
+            return
           when 0x6faa then @_failure(Errors.ErrorDueToCardPersonalization)
           else @_failure(Errors.CommunicationError)
         @_waitForDisconnectDongle()


selection: rename linesContainer to svg and add the mouseUp event to window, fix issue when releasing outside of browser window

--- src/scripts/graph/Selection.coffee
+++ src/scripts/graph/Selection.coffee
@@ -1,13 +1,20 @@
 define (require) ->
   class Selection
-    constructor: (@timeline, @linesContainer, @margin) ->
+    constructor: (@timeline, @svg, @margin) ->
       @init()
+
+    onMouseUp: (e) =>
+      @svg.selectAll('.selection').remove()
+      # Enable again the default browser text selection.
+      $('body').css({
+        'user-select': 'all'
+      })

     init: () ->
       self = this
-      @linesContainer.on("mousedown", () ->
+      @svg.on("mousedown", () ->
         p = d3.mouse(this)
-        self.linesContainer.append('rect')
+        self.svg.append('rect')
           .attr({
             rx: 6,
             ry: 6,
@@ -24,7 +31,7 @@
           'user-select': 'none'
         })
       ).on("mousemove", () ->
-        s = self.linesContainer.select('.selection')
+        s = self.svg.select('.selection')
         if s.empty() then return
         p = d3.mouse(this)
         margin: self.margin
@@ -61,7 +68,7 @@

         d.timeStart = self.timeline.x.invert(d.x - key_width).getTime() / 1000
         d.timeEnd = self.timeline.x.invert(d.x + d.width + key_width).getTime() / 1000
-        containerBounding = self.linesContainer[0][0].getBoundingClientRect()
+        containerBounding = self.svg[0][0].getBoundingClientRect()

         # deselect all previously selected items
         d3.selectAll('.key--selected').classed('key--selected', false)
@@ -74,15 +81,11 @@
             # use or condition for top and bottom
             if (y >= d.y && y <= d.y + d.height) || (y + 10 >= d.y && y + 10 <= d.y + d.height)
               d3.select(this).classed('key--selected', true)
-              #self.timeline.selectionManager.select(this, true)
               selection.push(this)

         self.timeline.selectionManager.select(selection)

-      ).on("mouseup", () ->
-        self.linesContainer.selectAll('.selection').remove()
-        # Enable again the default browser text selection.
-        $('body').css({
-          'user-select': 'all'
-        })
-      )+      )
+      # Attach the mouseup event to window so that it catch it event if
+      # mouseup happen outside of the browser window.
+      $(window).on("mouseup", @onMouseUp)


Implement DisplayMarker.prototype.isDestroyed

--- src/display-marker.coffee
+++ src/display-marker.coffee
@@ -7,13 +7,17 @@
     @hasChangeObservers = false
     @emitter = new Emitter
     @disposables = null
+    @destroyed = false

   destroy: ->
     @bufferMarker.destroy()
+    @destroyed = true
     @emitter.emit('did-destroy')

   onDidDestroy: (callback) ->
     @emitter.on('did-destroy', callback)
+
+  isDestroyed: -> @destroyed

   getBufferRange: ->
     @bufferMarker.getRange()


webapp/latex: fixing "_smc_inline_errors" undefined

--- src/smc-webapp/editor_latex.coffee
+++ src/smc-webapp/editor_latex.coffee
@@ -745,7 +745,7 @@

     _render_inline_error: (line, message, content, error_type) =>
         line -= 1 # to get 0-based numbering for the remaining code
-        if error_type != 'error'
+        if error_type != 'error' or not @latex_editor.codemirror?
             # only show errors, warnings and typesettings are too verbose
             return
         # at most one error widget per line ...


webapp/latex: load/save of conf_doc sometimes happens when codemirror is no longer there. exception: Cannot read property 'getValue' of undefined at f.exports.LatexEditor.f.load_conf_doc.

--- src/smc-webapp/editor_latex.coffee
+++ src/smc-webapp/editor_latex.coffee
@@ -144,7 +144,7 @@
             ev.preventDefault()
             flavor = ev.target.hash ? '#default'
             c = @preview.pdflatex.default_tex_command(flavor[1..])
-            console.log(c)
+            # console.log(c)
             @log_input.val(c)
             @set_conf_doc(latex_command: c)
             @save()
@@ -243,6 +243,8 @@
         @save_conf_doc(conf)

     load_conf_doc: () =>
+        if not @latex_editor.codemirror?
+            return {}
         doc = @latex_editor.codemirror.getValue()
         i = doc.indexOf("%sagemathcloud=")
         if i == -1
@@ -261,6 +263,8 @@

     save_conf_doc: (conf) =>
         cm  = @latex_editor.codemirror
+        if not cm?
+            return
         doc = cm.getValue()
         i = doc.indexOf('%sagemathcloud=')
         line = '%sagemathcloud=' + misc.to_json(conf)


Implemented into schedule tasks table

Implemented into schedule tasks table

--- SingularityUI/app/views/tasks.coffee
+++ SingularityUI/app/views/tasks.coffee
@@ -1,4 +1,6 @@
 View = require './view'
+
+Request = require '../models/Request'

 class TasksView extends View

@@ -117,14 +119,11 @@
         taskModel = @collection.get($(e.target).data('task-id'))
         $row = $(e.target).parents('tr')

-        vex.dialog.confirm
-            message: "
Are you sure you want to run this task immediately?

#{ taskModel.get('id') }
"
-            callback: (confirmed) =>
-                return unless confirmed
-                taskModel.run()
-                @collection.remove(taskModel)
-                app.collections.tasksActive.fetch()
-                $row.remove()
+        requestModel = new Request id: taskModel.get "requestId"
+        requestModel.promptRun =>
+            @collection.remove(taskModel)
+            app.collections.tasksActive.fetch()
+            $row.remove()

     searchChange: ->
         onChange = =>


Reorder and fix items having no parent collection

--- public/coffeescripts/portfolio.coffee
+++ public/coffeescripts/portfolio.coffee
@@ -34,25 +34,6 @@
     $('.itemInfoOverlay .buttonContainer .parent').attr 'target', ''

   generateInfo = (data) ->
-    if !$.isArray data.image then data.image = [data.image]
-    $('.itemInfoOverlay .info .proj,
-       .itemInfoOverlay .info .team,
-       .itemInfoOverlay .info .child
-    ').append $('.itemInfoOverlay .loading').clone().removeClass 'main'
-    $('.itemInfoOverlay .temp').remove()
-    $('.itemInfoOverlay .info .title, .itemInfoOverlay .info .value').show()
-    if data.itemType == 'item' && data.parentCollection
-      getData('collection', data.parentCollection).then (res) ->
-        if res.parentTeam then data.parentTeam = res.parentTeam
-        teamInfo ->
-          $('.itemInfoOverlay .info .team .loading').fadeOut 500, ->
-            $(this).remove()
-        $('.itemInfoOverlay .buttonContainer .parent').removeClass('disabled').attr('target', 'collection:' + res._id)
-        $('.itemInfoOverlay .col-lg-9 .main').prepend $('
Part of Collection - ' + res.name + '
')
-        $('.itemInfoOverlay .loading.main').fadeOut()
-
-    else
-      $('.itemInfoOverlay .loading.main').fadeOut()
     projInfo = (callback) ->
       $('.itemInfoOverlay .main .title').text data.name
       $('.itemInfoOverlay .main .date').text data.date
@@ -102,6 +83,27 @@
       else
         $('.info .child').append $('
Unavaliable
')
         callback()
+    if !$.isArray data.image then data.image = [data.image]
+    $('.itemInfoOverlay .info .proj,
+       .itemInfoOverlay .info .team,
+       .itemInfoOverlay .info .child
+    ').append $('.itemInfoOverlay .loading').clone().removeClass 'main'
+    $('.itemInfoOverlay .temp').remove()
+    $('.itemInfoOverlay .info .title, .itemInfoOverlay .info .value').show()
+    if data.itemType == 'item' && data.parentCollection
+      getData('collection', data.parentCollection).then (res) ->
+        if res.parentTeam then data.parentTeam = res.parentTeam
+        teamInfo ->
+          $('.itemInfoOverlay .info .team .loading').fadeOut 500, ->
+            $(this).remove()
+        $('.itemInfoOverlay .buttonContainer .parent').removeClass('disabled').attr('target', 'collection:' + res._id)
+        $('.itemInfoOverlay .col-lg-9 .main').prepend $('
Part of Collection - ' + res.name + '
')
+        $('.itemInfoOverlay .loading.main').fadeOut()
+    else
+      $('.itemInfoOverlay .loading.main').fadeOut()
+      teamInfo ->
+        $('.itemInfoOverlay .info .team .loading').fadeOut 500, ->
+          $(this).remove()
     if data.itemType != 'item'
       teamInfo ->
         $('.itemInfoOverlay .info .team .loading').fadeOut 500, ->


allow snockets require statements. fixes https://github.com/lessthan3/packages/issues/4573

--- lib/dobi-lint.coffee
+++ lib/dobi-lint.coffee
@@ -133,7 +133,7 @@

     msg = 'a single space is required after the # of a comment'
     for line, index in lines
-      if /^(\s)*#[^\s#{]/.test line
+      if /^(\s)*#[^\s=#{]/.test line
         fail index + 1, msg, line

     msg = 'an empty line is required prior to a single line comment'


Change GitWrite success message to show 'all files' or filepath

--- lib/git-write.coffee
+++ lib/git-write.coffee
@@ -14,7 +14,8 @@
     stderr: (data) ->
       new StatusView(type: 'alert', message: data.toString())
     exit: (data) ->
-      new StatusView(type: 'success', message: "Added #{toStage}")
+      file = if toStage is '.' then 'all files' else toStage
+      new StatusView(type: 'success', message: "Added #{file}")
   })

 module.exports = gitWrite


rabbit v 3.3.0 didn't support the capabilities for per_consumer_qos so allow for that edge case

--- src/lib/Consumer.coffee
+++ src/lib/Consumer.coffee
@@ -37,8 +37,8 @@
       # Rabbitmq 3.3.0 changes the behavior of qos.  we default to gloabl true in this case.
       if !options.global? and\
           @connection.serverProperties?.product == 'RabbitMQ' and\
-          @connection.serverProperties?.version? and \
-          @connection.serverProperties?.capabilities?.per_consumer_qos == true
+          ( @connection.serverProperties?.capabilities?.per_consumer_qos == true or \
+          @connection.serverProperties?.version == "3.3.0" )

         options.global = true


Code review

Code review

--- node_modules/konsserto/lib/src/Konsserto/Bundle/FrameworkBundle/Controller/Controller.coffee
+++ node_modules/konsserto/lib/src/Konsserto/Bundle/FrameworkBundle/Controller/Controller.coffee
@@ -13,7 +13,6 @@
 # @author Jessym Reziga <jessym@konsserto.com>
 #
 class Controller
-

   constructor: () ->
     return this
@@ -58,7 +57,7 @@
     @container.get('Router').generate(route, parameters, referenceType)

   redirect: (url, status = 302)->
-    @response.redirect(status, url);
+    @response.redirect(status, url)

   createForm: (name, data = null, options = {}) ->
     @container.get('Form_Factory').createBuilder(name, data, options)


config: use staging for now.

config: use staging for now.

--- coffee/src/config.coffee
+++ coffee/src/config.coffee
@@ -4,7 +4,7 @@
 goog.provide 'acorn.config'

 _.extend acorn.config,
-  domain: 'acorn.athena.ai'
+  domain: 'staging.acorn.athena.ai'
   version: '0.0.0'
   api:
     version: '0.0.1'


make profile simpler

make profile simpler

--- collections/users.coffee
+++ collections/users.coffee
@@ -9,246 +9,11 @@
         type: 'fileUpload'
         collection: 'ProfilePictures'

-  firstName:
+  name:
     type: String
     optional: true
-
-  lastName:
-    type: String
-    optional: true
-
-  birthday:
-    type: Date
-    optional: true
-
-  bio:
-    type: String
-    optional: true
-    autoform:
-      rows: 4
-
-  location:
-    type: String
-    optional: true
-    autoform:
-      type: 'map'
-      geolocation: true
-      searchBox: true
-      autolocate: true
-
-  country:
-    type: String
-    label: 'Nationality'
-    allowedValues: [
-      "Select Country"
-      "Afghanistan"
-      "Albania"
-      "Algeria"
-      "Andorra"
-      "Angola"
-      "Anguilla"
-      "Antigua & Barbuda"
-      "Argentina"
-      "Armenia"
-      "Aruba"
-      "Australia"
-      "Austria"
-      "Azerbaijan"
-      "Bahamas"
-      "Bahrain"
-      "Bangladesh"
-      "Barbados"
-      "Belarus"
-      "Belgium"
-      "Belize"
-      "Benin"
-      "Bermuda"
-      "Bhutan"
-      "Bolivia"
-      "Bosnia & Herzegovina"
-      "Botswana"
-      "Brazil"
-      "British Virgin Islands"
-      "Brunei"
-      "Bulgaria"
-      "Burkina Faso"
-      "Burundi"
-      "Cambodia"
-      "Cameroon"
-      "Cape Verde"
-      "Cayman Islands"
-      "Chad"
-      "Chile"
-      "China"
-      "Colombia"
-      "Congo"
-      "Cook Islands"
-      "Costa Rica"
-      "Cote D Ivoire"
-      "Croatia"
-      "Cruise Ship"
-      "Cuba"
-      "Cyprus"
-      "Czech Republic"
-      "Denmark"
-      "Djibouti"
-      "Dominica"
-      "Dominican Republic"
-      "Ecuador"
-      "Egypt"
-      "El Salvador"
-      "Equatorial Guinea"
-      "Estonia"
-      "Ethiopia"
-      "Falkland Islands"
-      "Faroe Islands"
-      "Fiji"
-      "Finland"
-      "France"
-      "French Polynesia"
-      "French West Indies"
-      "Gabon"
-      "Gambia"
-      "Georgia"
-      "Germany"
-      "Ghana"
-      "Gibraltar"
-      "Greece"
-      "Greenland"
-      "Grenada"
-      "Guam"
-      "Guatemala"
-      "Guernsey"
-      "Guinea"
-      "Guinea Bissau"
-      "Guyana"
-      "Haiti"
-      "Honduras"
-      "Hong Kong"
-      "Hungary"
-      "Iceland"
-      "India"
-      "Indonesia"
-      "Iran"
-      "Iraq"
-      "Ireland"
-      "Isle of Man"
-      "Israel"
-      "Italy"
-      "Jamaica"
-      "Japan"
-      "Jersey"
-      "Jordan"
-      "Kazakhstan"
-      "Kenya"
-      "Kuwait"
-      "Kyrgyz Republic"
-      "Laos"
-      "Latvia"
-      "Lebanon"
-      "Lesotho"
-      "Liberia"
-      "Libya"
-      "Liechtenstein"
-      "Lithuania"
-      "Luxembourg"
-      "Macau"
-      "Macedonia"
-      "Madagascar"
-      "Malawi"
-      "Malaysia"
-      "Maldives"
-      "Mali"
-      "Malta"
-      "Mauritania"
-      "Mauritius"
-      "Mexico"
-      "Moldova"
-      "Monaco"
-      "Mongolia"
-      "Montenegro"
-      "Montserrat"
-      "Morocco"
-      "Mozambique"
-      "Namibia"
-      "Nepal"
-      "Netherlands"
-      "Netherlands Antilles"
-      "New Caledonia"
-      "New Zealand"
-      "Nicaragua"
-      "Niger"
-      "Nigeria"
-      "Norway"
-      "Oman"
-      "Pakistan"
-      "Palestine"
-      "Panama"
-      "Papua New Guinea"
-      "Paraguay"
-      "Peru"
-      "Philippines"
-      "Poland"
-      "Portugal"
-      "Puerto Rico"
-      "Qatar"
-      "Reunion"
-      "Romania"
-      "Russia"
-      "Rwanda"
-      "Saint Pierre & Miquelon"
-      "Samoa"
-      "San Marino"
-      "Satellite"
-      "Saudi Arabia"
-      "Senegal"
-      "Serbia"
-      "Seychelles"
-      "Sierra Leone"
-      "Singapore"
-      "Slovakia"
-      "Slovenia"
-      "South Africa"
-      "South Korea"
-      "Spain"
-      "Sri Lanka"
-      "St Kitts & Nevis"
-      "St Lucia"
-      "St Vincent"
-      "St. Lucia"
-      "Sudan"
-      "Suriname"
-      "Swaziland"
-      "Sweden"
-      "Switzerland"
-      "Syria"
-      "Taiwan"
-      "Tajikistan"
-      "Tanzania"
-      "Thailand"
-      "Timor L'Este"
-      "Togo"
-      "Tonga"
-      "Trinidad & Tobago"
-      "Tunisia"
-      "Turkey"
-      "Turkmenistan"
-      "Turks & Caicos"
-      "Uganda"
-      "Ukraine"
-      "United Arab Emirates"
-      "United Kingdom"
-      "United States"
-      "Uruguay"
-      "Uzbekistan"
-      "Venezuela"
-      "Vietnam"
-      "Virgin Islands (US)"
-      "Yemen"
-      "Zambia"
-      "Zimbabwe"
-    ]
-    optional: true
+	label:  ->
+		TAPi18n.__ 'name'
 )

 Schemas.User = new SimpleSchema(


Move spelling marker to back marker layer where it is updated properly by Ace

--- services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/HighlightedWordManager.coffee
+++ services/web/public/coffee/ide/editor/directives/aceEditor/spell-check/HighlightedWordManager.coffee
@@ -21,7 +21,7 @@
 				highlight.row, highlight.column,
 				highlight.row, highlight.column + highlight.word.length
 			)
-			highlight.markerId = @editor.getSession().addMarker range, "spelling-highlight", null, true
+			highlight.markerId = @editor.getSession().addMarker range, "spelling-highlight", 'text', false
 			@highlights.rows[highlight.row] ||= []
 			@highlights.rows[highlight.row].push highlight


quick-add for multi-reference form works auto injected

--- client/coffee/references.coffee
+++ client/coffee/references.coffee
@@ -192,6 +192,17 @@
         $(evt.currentTarget).parent().remove()

 Template.referenceMultiSelect.rendered = ->
+
+    # if a new reference is created, inject it into the input scope
+    $ul = $(@find('ul'))
+    Tracker.autorun () ->
+        ref_id = Session.get("referenceNewObj")
+        if ref_id isnt null
+            ids = ($(li).data('id') for li in $ul.find('li'))
+            if ref_id not in ids
+                Blaze.renderWithData(Template.referenceMultiSelectListLI, ref_id, $ul[0])
+            Session.set("referenceNewObj", null)
+
     Meteor.typeahead.inject()


rename to unfinished

rename to unfinished

--- cf/spell.coffee
+++ cf/spell.coffee
@@ -16,7 +16,7 @@
     @current = ""
     @fail = 0
     @reveal = ""
-    @finished = []
+    @unfinished = []
     update_question(data)
     @data = data


fix arrow with no param

fix arrow with no param

--- test/test_page.coffee
+++ test/test_page.coffee
@@ -16,7 +16,7 @@
 module.exports =
   'Page':
     '#hasTimestamps()':
-      'return true': ()->
+      'return true': ->
         page = new Page()
         expect(page.hasTimestamps).to.be.true


Adjust the ajax transition to smooth

Adjust the ajax transition to smooth

--- app/assets/javascripts/application-ux.js.coffee
+++ app/assets/javascripts/application-ux.js.coffee
@@ -19,15 +19,15 @@
       return

     $(document).on 'page:loading', ->
-      $("#main").hide()
+      $("#main").fadeOut('fast')
       NProgress.start()
       return

     $(document).on 'ready page:done', ->
       setTimeout(->
-        $("#main").show()
+        $("#main").fadeIn('fast')
         NProgress.done()
-      , 350)
+      , 150)
       return
   )()


Add formatting for values in megatons.

Add formatting for values in megatons.

--- app/assets/javascripts/lib/models/metric.coffee
+++ app/assets/javascripts/lib/models/metric.coffee
@@ -69,6 +69,8 @@
         return "#{value}#{@scaling_in_words(pow + 3, 'joules')}"
       when 'MW'
         return "#{value}#{@scaling_in_words(pow, 'watt')}"
+      when 'MT'
+        return "#{value}#{@scaling_in_words(pow + 2, 'ton')}"
       when 'euro'
         return @euros_to_string x, true
       when 'bln_euro'


Fix: make _UIGuidersCollection class global as well

--- app/assets/javascripts/lib/ui_guiders.js.coffee
+++ app/assets/javascripts/lib/ui_guiders.js.coffee
@@ -151,5 +151,5 @@
       for guider in @ui_guiders
         guider.hide()

-
-  window.UIGuidersCollection = new _UIGuidersCollection()
+  window._UIGuidersCollection = _UIGuidersCollection
+  window.UIGuidersCollection  = new _UIGuidersCollection()


wiring up desktop version of product gallery

--- app/assets/javascripts/mobile/_mobile.js.coffee
+++ app/assets/javascripts/mobile/_mobile.js.coffee
@@ -74,7 +74,7 @@
         for product_image, i in product_images
             product_gallery_data =
                 index: i
-                classes: "product-thumbnail #{(if i is 0 then 'on' else 'hide')}"
+                class: "product-thumbnail #{(if i is 0 then 'on' else null)}"
                 product_name: gon.product_name
                 product_image: product_image

@@ -85,8 +85,10 @@
                 classes: "product-gallery-control #{(if i is 0 then 'on' else '')}"
                 index: i

-             $product_gallery_controls_wrapper.append Mustache.render(
-                templates.product_thumbnail_gallery_control_template, product_gallery_control_data)
+
+            if product_images.length > 1
+                $product_gallery_controls_wrapper.append Mustache.render(
+                    templates.product_thumbnail_gallery_control_template, product_gallery_control_data)

         $self.find('.product-thumbnail-gallery')
             .html($product_gallery_wrapper)
@@ -135,23 +137,39 @@

             fetch_product_images($('.product'), render_multiple_product_images)

-            ($ '.product-thumbnail-gallery')
-                .on('swipeLeft', (e) ->
-                    $this = ($ e.target)
-                    next_index = $this.next().data('index')
-                    if next_index?
-                        $this.addClass('hide')
-                        $this.next().removeClass('hide')
-                        ($ '.product-gallery-control.on')
-                            .removeClass('on').next().addClass('on'))
-                .on('swipeRight', (e) ->
-                    $this = ($ e.target)
-                    previous_index = $this.prev().data('index')
-                    if previous_index?
-                        $this.addClass('hide')
-                        $this.prev().removeClass('hide')
-                        ($ '.product-gallery-control.on')
-                            .removeClass('on').prev().addClass('on'))
+            swipe_left = (e) ->
+                $this = ($ e.target)
+                next_index = $this.next().data('index')
+                if next_index?
+                    $this.removeClass('on')
+                    $this.next().addClass('on')
+                    ($ '.product-gallery-control.on')
+                        .removeClass('on').next().addClass('on')
+
+            swipe_right = (e) ->
+                $this = ($ e.target)
+                previous_index = $this.prev().data('index')
+                if previous_index?
+                    $this.removeClass('on')
+                    $this.prev().addClass('on')
+                    ($ '.product-gallery-control.on')
+                        .removeClass('on').prev().addClass('on')
+
+            if has_touch_events
+                ($ '.product-thumbnail-gallery')
+                    .on('swipeLeft', (e) -> swipe_left(e))
+                    .on('swipeRight', (e) -> swipe_right(e))
+            else
+                ($ '.product-thumbnail-gallery')
+                    .on('click', '.product-gallery-control', ->
+                        index = ($ @).data('index')
+
+                        ($ '.product-gallery-control.on').removeClass('on')
+                        ($ @).addClass('on')
+                        ($ '.product-thumbnail.on').removeClass('on')
+                        ($ "#product_gallery_image_#{index}").addClass('on')
+                    )
+

             # setTimeout is required because
             # tap was clicking the purchase


Made sure to listen to private channel when session is initiated.

--- app/assets/javascripts/models/session.js.coffee
+++ app/assets/javascripts/models/session.js.coffee
@@ -3,8 +3,9 @@
   initialize: (attr) ->

     @set 'user', new Cloudsdale.Models.User(@get('user'))
+    @listenToPrivateChannel()
+
     @set 'users', new Cloudsdale.Collections.Users()
-
     @get('users').add(@get('user'))

     @bindEvents()
@@ -20,9 +21,9 @@

   bindEvents: ->

-    @get('user').on 'change', () =>
-      window.location.replace("/logout") if @get('user').get('is_banned')
-      @listenToPrivateChannel()
+    @get('user').on 'change', (user) =>
+      window.location.replace("/logout") if user.get('is_banned')
+      @listenToPrivateChannel()

   # Returns true if the user is not a new user.
   isRegistered: -> @get('user').get('is_registered')


Added dedicated /404 route

Added dedicated /404 route

--- app/assets/javascripts/sprangular/routes.coffee
+++ app/assets/javascripts/sprangular/routes.coffee
@@ -86,5 +86,8 @@
         order: (Orders, $route) ->
           Orders.find($route.current.params.number)

+    .when '/404',
+      templateUrl: '404.html'
+
     .otherwise
       templateUrl: '404.html'


Show map on no search in direction widget

--- app/assets/javascripts/widgets/direction.coffee
+++ app/assets/javascripts/widgets/direction.coffee
@@ -225,7 +225,16 @@
     else
       alert('Nie znaleziono trasy! Spróbuj ponownie.')

-searchRelics = (callback) ->
+performSearch = (search_params, callback) ->
+  $.ajax
+    url: Routes.api_v1_relics_path(search_params)
+    dataType: 'json'
+    success: (result) ->
+      callback(result)
+    error: ->
+      alert('Nastąpił błąd podczas wyszukiwania zabytków.')
+
+searchRelics = ->
   search_params = $('#new_search').serializeObject().search
   search_params.api_key = "oz"
   search_params.per_page = 1000
@@ -233,17 +242,15 @@
   window.parent.postMessage(JSON.stringify(
     event: "on_params_changed", params: search_params
   ), "*")
-
-  searchRoute search_params, (route) ->
-    search_params.bounding_box = gmap.getLatLngBounds().toString()
-    $.ajax
-      url: Routes.api_v1_relics_path(search_params)
-      dataType: 'json'
-      success: (result) ->
+
+  if search_params.start.length && search_params.end.length
+    searchRoute search_params, (route) ->
+      search_params.bounding_box = gmap.getLatLngBounds().toString()
+      performSearch search_params, (result) ->
         process(search_params, result.clusters, result.relics, route.path)
-        do callback if typeof callback == 'function'
-      error: ->
-        alert('Nastąpił błąd podczas wyszukiwania zabytków.')
+  else
+    performSearch search_params, (result) ->
+      renderResults(result.clusters, result.relics)

   false

@@ -259,3 +266,8 @@
       if bounds = gmap.getLatLngBounds()
         $('#search_bounding_box').val(bounds.toString())
         searchRelics()
+
+    gmap.onNextMovement ->
+    gmap.setCenter(new google.maps.LatLng(52, 20))
+    gmap.setZoom(6)
+    searchRelics()


Remote prefixed pull_db working

Remote prefixed pull_db working

--- tasks/lib/util.coffee
+++ tasks/lib/util.coffee
@@ -8,6 +8,8 @@

   exports.db_dump = (config, output_paths) ->
     grunt.file.mkdir output_paths.dir
+
+    console.log config, 'config'

     if config.table_prefix
       console.log "Using table prefix " + config.table_prefix
@@ -16,7 +18,8 @@
       console.log "NOT using table prefix " + config.table_prefix
       cmd = exports.mysqldump_cmd(config)

-    grunt.log.oklns "dump command: " + cmd
+    grunt.log.oklns "dump command:"
+    console.log cmd

     output = shell.exec(cmd,
       silent: true
@@ -31,7 +34,7 @@
   #==========  Caliper mods  ==========

-  exports.prefixed_mysqldump_cmd = (config) ->
+  exports.prefixed_mysqldump_cmd = (config, output_paths) ->

     prefix_matches = exports.all_table_prefix_matches(config)
     grunt.log.oklns "Prefix matches from '" + config.table_prefix + "'"
@@ -41,10 +44,9 @@
     grunt.log.oklns "Tables to dump"

     console.log tables_to_dump
-    prefixed_sqldump = exports.prefixed_sqldump(config, tables_to_dump)
-    grunt.file.write output_paths.file, prefixed_sqldump
-    grunt.log.oklns "Database DUMP for '" + config.table_prefix + "' succesfully exported to: " + output_paths.file
-    return
+
+    # Return the cmd
+    exports.build_prefixed_sqldump(config, tables_to_dump)

   # Find all table prefix that match the config.table_prefix
@@ -160,35 +162,28 @@

     cmd = exports.add_ssh_connect config, cmd if config.ssh_host?

-    console.log "tables to dump cmd \n" + cmd
+    # console.log "tables to dump cmd \n" + cmd

     # Make sure you strip the new line chars
     tables_to_dump = shell.exec(cmd,
       silent: true
-    ).output
-
-    console.log "tables_to_dump\n" + tables_to_dump
-
-    tables_to_dump.replace(/(\r\n|\n|\r)/g, "")
+    ).output.replace(/(\r\n|\n|\r)/g, "")
+
+    # console.log "tables_to_dump\n" + tables_to_dump
+
     tables_to_dump.split " "

   # Run the mysqldump cmd and append the table names from exports.tables_to_dump() fn
-  exports.prefixed_sqldump = (config, tables_to_dump) ->
+  exports.build_prefixed_sqldump = (config, tables_to_dump) ->
     return false  unless tables_to_dump
     cmd = exports.mysqldump_cmd(config) + " " + tables_to_dump.join(" ")

-    if typeof config.ssh_host is "undefined"
-      grunt.log.oklns "Creating prefixed DUMP of local database [" + config.database + "/" + config.table_prefix + "]"
-    else
-      grunt.log.oklns "Creating prefixed DUMP of remote database [" + config.database + "/" + config.table_prefix + "]"
-      # tpl_ssh = grunt.template.process(tpls.ssh,
-      #   data:
-      #     host: config.ssh_host
-      # )
-      # cmd = tpl_ssh + " \"" + cmd + "\""
-
-    console.log "prefixed sqldump cmd\n" + cmd
+    dest = if config.ssh_host? then 'remote' else 'local'
+
+    grunt.log.oklns "Creating prefixed DUMP of " + dest + " database [" + config.database + "/" + config.table_prefix + "]"
+
+    # console.log "prefixed sqldump cmd\n" + cmd
     cmd

   exports.add_ssh_connect = ( config, cmd ) ->
@@ -196,8 +191,8 @@
       data:
         host: config.ssh_host
     )
-    cmd = tpl_ssh + " " + cmd
-    console.log cmd, 'add ssh connect'
+    cmd = tpl_ssh + " \"" + cmd.replace( /\"/g, '\\"' ) + "\""
+    # console.log cmd, 'add ssh connect'
     cmd

   #==========  Caliper mods  ==========


Update gruntfile

Update gruntfile

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -106,5 +106,5 @@
                 files: ['**/*.jade', '**/*.styl', '**/*.coffee']
                 tasks: ['stylus', 'coffee', 'jshint', 'uglify', 'jade', 'clean:post']

+    grunt.registerTask 'build', ['clean:pre', 'bower', 'copy', 'sprite', 'image', 'stylus', 'coffee', 'jshint', 'uglify', 'jade', 'clean:post']
     grunt.registerTask 'serve', ['connect', 'watch']
-    grunt.registerTask 'build', ['clean:pre', 'bower', 'copy', 'sprite', 'image', 'stylus', 'coffee', 'jshint', 'uglify', 'jade', 'clean:post']


:boar: Update default task

:boar: Update default task

--- gruntfile.coffee
+++ gruntfile.coffee
@@ -5,7 +5,7 @@
   require('load-grunt-config') grunt,
     jitGrunt: true

-  grunt.registerTask 'default', ['clean', 'babel:dist', 'amd_tamer', 'uglify']
+  grunt.registerTask 'default', ['clean', 'babel:dist_common', 'babel:dist_amd', 'amd_tamer', 'uglify']

   grunt.registerTask 'test', ['default', 'jshint', 'consolidate', 'babel:test', 'amd_tamer:test', 'mocha']


Debug

Debug

--- Content/MAZE/src/game/game.coffee
+++ Content/MAZE/src/game/game.coffee
@@ -147,9 +147,14 @@
         # Disable players with no brick placed
         @mazeModel.players = (player for player in @mazeModel.players when PlayerState == PlayerState.IDLE)

+        # Adjust player indices
+        for i in 0..@mazeModel.players.length:
+            @mazeModel.players[i].index = i
+
         # Move player
         player.state = PlayerState.TURN
         @currentPlayer = player
+        Console.log("--> " + @currentPlayer)

         @playerMovedBrick(position)


use tabs/tab & rm delta

use tabs/tab & rm delta


Can properly save image sections (old image format)

--- api/apps/articles/model/schema.coffee
+++ api/apps/articles/model/schema.coffee
@@ -15,6 +15,7 @@
     caption: @string().allow('', null)
     width: @number().allow(null)
     height: @number().allow(null)
+    layout: @string().allow('', null)
 ).call Joi

 videoSection = (->


fix(plugin-auth): more fixes to plugin auth

--- src/flux/nylas-api.coffee
+++ src/flux/nylas-api.coffee
@@ -383,7 +383,9 @@
   # 3. The API request to auth this account to the plugin failed. This may mean that
   #    the plugin server couldn't be reached or failed to respond properly when authing
   #    the account, or that the Nylas API couldn't be reached.
-  authPlugin: (pluginId, pluginName, account) ->
+  authPlugin: (pluginId, pluginName, accountId) ->
+    AccountStore = AccountStore || require './stores/account-store'
+    account = AccountStore.accountForId(accountId)
     return @makeRequest({
       returnsModel: false,
       method: "GET",
@@ -393,12 +395,12 @@
       if result.authed
         return Promise.resolve()
       else
-        return @_requestPluginAuth(pluginName, account).then( -> @makeRequest({
+        return @_requestPluginAuth(pluginName, account).then( => @makeRequest({
           returnsModel: false,
           method: "POST",
           accountId: account.id,
           path: "/auth/plugin",
-          body: JSON.stringify({client_id: pluginId}),
+          body: {client_id: pluginId},
           json: true
         }))
     )
@@ -422,11 +424,11 @@
       )
     )

-  unauthPlugin: (pluginId, account) ->
+  unauthPlugin: (pluginId, accountId) ->
     return @makeRequest({
       returnsModel: false,
       method: "DELETE",
-      accountId: account.id,
+      accountId: accountId,
       path: "/auth/plugin?client_id=#{pluginId}"
     });


bongo: remove some junk code

bongo: remove some junk code

--- node_modules_koding/bongo/lib/model/index.coffee
+++ node_modules_koding/bongo/lib/model/index.coffee
@@ -812,15 +812,10 @@
       filter node
     (isHard=no)->
       model = @
-      # model.applyDefaults()
-      allowed = []
-      pruned = []
       {constructor} = model
-      # data = model.get()
       method = if isHard then 'forEach' else 'map'
       prunedData = new Traverse(model.data)[method] (node)->
         pathName = @path.join '.'
-        # console.log pathName
         if node instanceof ObjectId
           @update ObjectId(node+''), yes
         else if pathName is '_id'


Add tests for public resources

Add tests for public resources

Change-type: patch
Signed-off-by: Thodoris Greasidis <5791bdc4541e79bd43d586e3c3eff1e39c16665f@balena.io>

--- tests/pine.spec.coffee
+++ tests/pine.spec.coffee
@@ -60,68 +60,148 @@

 				describe 'given a simple GET endpoint', ->

-					beforeEach ->
-						@pine = buildPineInstance(mockServer.url)
-						mockServer.get('/foo').thenJSON(200, hello: 'world')
-
-					describe 'given there is no api key', ->
-						beforeEach: ->
-							@pine = buildPineInstance(mockServer.url, apiKey: '')
-
-						it 'should be rejected with an authentication error message', ->
+					describe 'given a public resource', ->
+
+						beforeEach ->
+							@pine = buildPineInstance(mockServer.url)
+							mockServer.get('/public_resource').thenJSON(200, hello: 'public world')
+
+						describe 'given there is no api key', ->
+
+							# that's wrong and we need a major to fix it
+							it 'should be rejected with an authentication error message', ->
+								promise = @pine._request
+									baseUrl: @pine.API_URL
+									method: 'GET'
+									url: '/public_resource'
+								m.chai.expect(promise).to.be.rejectedWith('You have to log in')
+
+							it 'should be successful, if sent anonymously', ->
+								promise = @pine._request
+									baseUrl: @pine.API_URL
+									method: 'GET'
+									url: '/public_resource'
+									anonymous: true
+								m.chai.expect(promise).to.become(hello: 'public world')
+
+						describe 'given there is an api key', ->
+
+							# that's wrong and we need a major to fix it
+							it 'should be rejected with an authentication error message', ->
+								promise = @pine._request
+									baseUrl: @pine.API_URL
+									method: 'GET'
+									url: '/public_resource'
+								m.chai.expect(promise).to.be.rejectedWith('You have to log in')
+
+					describe 'given a non-public resource', ->
+
+						beforeEach ->
+							mockServer.get('/foo').thenCallback (req) ->
+								if req.headers?.authorization == "Bearer #{tokens.johndoe.token}" or req.url.endsWith("?apikey=#{tokens.johndoe.token}")
+									return {
+										status: 200,
+										json: hello: 'world'
+									}
+
+								return {
+									status: 401
+									body: 'Unauthorized'
+								}
+
+						describe 'given there is no api key', ->
+
+							beforeEach ->
+								@pine = buildPineInstance(mockServer.url, apiKey: '')
+
+							it 'should be rejected with an authentication error message', ->
+								promise = @pine._request
+									baseUrl: @pine.API_URL
+									method: 'GET'
+									url: '/foo'
+								m.chai.expect(promise).to.be.rejectedWith('You have to log in')
+
+							it 'should be rejected with an unauthorized error, if sent anonymously', ->
+								promise = @pine._request
+									baseUrl: @pine.API_URL
+									method: 'GET'
+									url: '/foo'
+									anonymous: true
+								m.chai.expect(promise).to.be.rejectedWith('Unauthorized')
+								.then (res) ->
+									m.chai.expect(res.statusCode).to.equal(401)
+
+						describe 'given there is an api key', ->
+
+							beforeEach ->
+								@pine = buildPineInstance(mockServer.url, apiKey: tokens.johndoe.token)
+
+							it 'should make the request successfully', ->
+								promise = @pine._request
+									baseUrl: @pine.API_URL
+									method: 'GET'
+									url: '/foo'
+								m.chai.expect(promise).to.become(hello: 'world')
+
+							it 'should make the request successfully, if sent anonymously', ->
+								promise = @pine._request
+									baseUrl: @pine.API_URL
+									method: 'GET'
+									url: '/foo'
+									anonymous: true
+								m.chai.expect(promise).to.become(hello: 'world')
+
+			describe 'given there is an auth', ->
+
+				beforeEach ->
+					auth.setKey(tokens.johndoe.token)
+
+				describe 'given a simple GET endpoint', ->
+
+					describe 'given a public resource', ->
+
+						beforeEach ->
+							@pine = buildPineInstance(mockServer.url)
+							mockServer.get('/public_resource').thenJSON(200, hello: 'public world')
+
+						it 'should be successful', ->
+							promise = @pine._request
+								baseUrl: @pine.API_URL
+								method: 'GET'
+								url: '/public_resource'
+							m.chai.expect(promise).to.become(hello: 'public world')
+
+						it 'should be successful, if sent anonymously', ->
+							promise = @pine._request
+								baseUrl: @pine.API_URL
+								method: 'GET'
+								url: '/public_resource'
+								anonymous: true
+							m.chai.expect(promise).to.become(hello: 'public world')
+
+					describe 'given a non-public resource', ->
+
+						beforeEach ->
+							@pine = buildPineInstance(mockServer.url)
+							mockServer.get('/foo')
+								.withHeaders({ 'Authorization': "Bearer #{tokens.johndoe.token}" })
+								.thenJSON(200, hello: 'world')
+							mockServer.get('/foo').thenReply(401, 'Unauthorized')
+
+						it 'should eventually become the response body', ->
 							promise = @pine._request
 								baseUrl: @pine.API_URL
 								method: 'GET'
 								url: '/foo'
-							m.chai.expect(promise).to.be.rejectedWith('You have to log in')
-
-						it 'should be successful, if sent anonymously', ->
+							m.chai.expect(promise).to.eventually.become(hello: 'world')
+
+						it 'should not send the auth token, if using an anonymous flag', ->
 							promise = @pine._request
 								baseUrl: @pine.API_URL
 								method: 'GET'
 								url: '/foo'
 								anonymous: true
-							m.chai.expect(promise).to.become(hello: 'world')
-
-					describe 'given there is an api key', ->
-						beforeEach ->
-							@pine = buildPineInstance(mockServer.url, apiKey: '123456789')
-
-						it 'should make the request successfully', ->
-							promise = @pine._request
-								baseUrl: @pine.API_URL
-								method: 'GET'
-								url: '/foo'
-							m.chai.expect(promise).to.become(hello: 'world')
-
-			describe 'given there is an auth', ->
-
-				beforeEach ->
-					auth.setKey(tokens.johndoe.token)
-
-				describe 'given a simple GET endpoint', ->
-
-					beforeEach ->
-						@pine = buildPineInstance(mockServer.url)
-						mockServer.get('/foo')
-							.withHeaders({ 'Authorization': "Bearer #{tokens.johndoe.token}" })
-							.thenJSON(200, hello: 'world')
-						mockServer.get('/foo').thenReply(401, 'Unauthorized')
-
-					it 'should eventually become the response body', ->
-						promise = @pine._request
-							baseUrl: @pine.API_URL
-							method: 'GET'
-							url: '/foo'
-						m.chai.expect(promise).to.eventually.become(hello: 'world')
-
-					it 'should not send the auth token, if using an anonymous flag', ->
-						promise = @pine._request
-							baseUrl: @pine.API_URL
-							method: 'GET'
-							url: '/foo'
-							anonymous: true
-						m.chai.expect(promise).to.be.rejectedWith('Request error: Unauthorized')
+							m.chai.expect(promise).to.be.rejectedWith('Request error: Unauthorized')

 				describe 'given a POST endpoint that mirrors the request body', ->


cleanup

cleanup

--- lib/term-view.coffee
+++ lib/term-view.coffee
@@ -40,9 +40,6 @@

   onResize: (callback) ->
     @emitter.on 'resize', callback
-
-  forkPtyProcess: (sh, args=[])->
-

   input: (data) ->
     try
@@ -54,7 +51,7 @@
     catch error
       console.error error
     @resizeToPane()
-    # @focusTerm()
+    @focusTerm()

   attached: () ->
     {cols, rows, cwd, shell, shellArguments, shellOverride, runCommand, colors, cursorBlink, scrollback} = @opts
@@ -81,7 +78,6 @@

       @ptyProcess.on 'term2:data', (data) =>
         utf8 = new Buffer(data, "base64").toString("utf-8")
-        console.log 'pty', utf8
         @term.write utf8
         @emitter.emit('data', data)

@@ -144,7 +140,9 @@

   attachEvents: ->
     @resizeToPane = @resizeToPane.bind this
-    @attachResizeEvents()
+    @on 'focus', @focus
+    $(window).on 'resize', => @resizeToPane()
+    @disposable = atom.workspace.getActivePane().observeFlexScale => setTimeout (=> @resizeToPane()), 300
     atom.commands.add "atom-workspace", "term2:paste", => @paste()
     atom.commands.add "atom-workspace", "term2:copy", => @copy()

@@ -165,11 +163,6 @@
   paste: ->
     @input atom.clipboard.read()

-  attachResizeEvents: ->
-    @on 'focus', @focus
-    $(window).on 'resize', => @resizeToPane()
-    @disposable = atom.workspace.getActivePane().observeFlexScale => setTimeout (=> @resizeToPane()), 300
-
   focus: ->
     @resizeToPane()
     @focusTerm()


Arg-block submit button prompt.[#89196068]

 - Change text after the user has submitted at least once.

--- app/assets/javascripts/c_rater.coffee
+++ app/assets/javascripts/c_rater.coffee
@@ -120,7 +120,7 @@
       @$submitPrompt.html( t('ARG_BLOCK.PLEASE_ANSWER') )
       return
     unless @anyQuestionDirty()
-      @$submitPrompt.html( t('ARG_BLOCK.ANSWERS_NOT_CHANGED'))
+      @$submitPrompt.html( t('ARG_BLOCK.RESUBMIT_OR_MOVE'))

   hideSubmitPrompt: ->
     @$submitPrompt.css('display', 'none')


Refactor: re-order methods in source code

--- app/assets/javascripts/home.js.coffee
+++ app/assets/javascripts/home.js.coffee
@@ -84,12 +84,13 @@
 # helpers
 #

-set_field_visibility = (element, is_visible) ->
-  if is_visible
-    element.removeClass('hidden').addClass('visible')
-  else
-    element.removeClass('visible').addClass('hidden')
+set_dirty = (dirty)->
+  dirty_flag = dirty
+  enable_save_button(dirty)

+enable_save_button = (enabled) ->
+  save_button().prop('disabled', not enabled)
+
 set_fields_to_edit_mode = (is_in_edit_mode) ->
   set_field_to_edit_mode(user_name(), is_in_edit_mode)
   set_field_to_edit_mode(user_title(), is_in_edit_mode)
@@ -122,12 +123,11 @@
   is_visible = is_populated(element) or is_edit_mode()
   set_field_visibility(element, is_visible)

-enable_save_button = (enabled) ->
-  save_button().prop('disabled', not enabled)
-
-set_dirty = (dirty)->
-  dirty_flag = dirty
-  enable_save_button(dirty)
+set_field_visibility = (element, is_visible) ->
+  if is_visible
+    element.removeClass('hidden').addClass('visible')
+  else
+    element.removeClass('visible').addClass('hidden')

 #


Dynamic bind for new comments

Dynamic bind for new comments

--- app/assets/javascripts/main.js.coffee
+++ app/assets/javascripts/main.js.coffee
@@ -68,8 +68,8 @@

 # confirm dialog box for class ".confirm-dialog"
 $ ->
-  $(".confirm-dialog").click((event)->
-    this_link = $(this)
+  $("body").on("click", ".confirm-dialog", (event)->
+    this_link = $(event.currentTarget)
     titleText = this_link.data("title")
     bodyText = this_link.data("body")
     methodText = this_link.data("method-type")


fix Japanese flag

fix Japanese flag

--- lib/translate.coffee
+++ lib/translate.coffee
@@ -33,6 +33,8 @@
     flag = 'gr'
   else if @lang == 'he'
     flag = 'il'
+  else if @lang == 'ja'
+    flag = 'jp'
   else if @lang == 'ko'
     flag = 'kr'
   else if @lang == 'ms'


Display fullpath when mouse moves over a specimen box

--- app/assets/javascripts/xray.js.coffee
+++ app/assets/javascripts/xray.js.coffee
@@ -110,7 +110,7 @@

   makeBox: ->
     @bounds = util.computeBoundingBox(@$contents)
-    @$box = $("
").css(@bounds)
+    @$box = $("
").css(@bounds).attr('title', @path)

     # If the element is fixed, override the computed position with the fixed one.
     if @$contents.css('position') == 'fixed'


:art: Rename ::updateRoot -> ::updateRoots

Signed-off-by: Nathan Sobo <2e8aa918660411855c6d44d5bb2da677aa033255@github.com>

--- lib/tree-view.coffee
+++ lib/tree-view.coffee
@@ -47,8 +47,8 @@
       @disposables.add atom.styles.onDidRemoveStyleElement(onStylesheetsChanged)
       @disposables.add atom.styles.onDidUpdateStyleElement(onStylesheetsChanged)

-    @updateRoot(state.directoryExpansionStates)
-    @selectEntry(root) for root in @roots
+    @updateRoots(state.directoryExpansionStates)
+    @selectEntry(@roots[0])

     @selectEntryForPath(state.selectedPath) if state.selectedPath
     @focusAfterAttach = state.hasFocus
@@ -128,17 +128,17 @@
     @disposables.add atom.workspace.onDidChangeActivePaneItem =>
       @selectActiveFile()
     @disposables.add atom.project.onDidChangePaths =>
-      @updateRoot()
+      @updateRoots()
     @disposables.add atom.config.onDidChange 'tree-view.hideVcsIgnoredFiles', =>
-      @updateRoot()
+      @updateRoots()
     @disposables.add atom.config.onDidChange 'tree-view.hideIgnoredNames', =>
-      @updateRoot()
+      @updateRoots()
     @disposables.add atom.config.onDidChange 'core.ignoredNames', =>
-      @updateRoot() if atom.config.get('tree-view.hideIgnoredNames')
+      @updateRoots() if atom.config.get('tree-view.hideIgnoredNames')
     @disposables.add atom.config.onDidChange 'tree-view.showOnRightSide', ({newValue}) =>
       @onSideToggled(newValue)
     @disposables.add atom.config.onDidChange 'tree-view.sortFoldersBeforeFiles', =>
-      @updateRoot()
+      @updateRoots()

   toggle: ->
     if @isVisible()
@@ -237,7 +237,7 @@
       catch error
         console.warn "Error parsing ignore pattern (#{ignoredName}): #{error.message}"

-  updateRoot: (expandedEntries={}) ->
+  updateRoots: (expandedEntries={}) ->
     for root in @roots
       root.directory.destroy()
       root.remove()


Cache the results of calling getPathStatus so we're consistent across calls.

--- src/git-repository.coffee
+++ src/git-repository.coffee
@@ -318,7 +318,7 @@
   getDirectoryStatus: (directoryPath)  ->
     directoryPath = "#{@relativize(directoryPath)}/"
     directoryStatus = 0
-    for path, status of @async.getCachedPathStatuses()
+    for path, status of _.extend({}, @async.getCachedPathStatuses(), @statusesByPath)
       directoryStatus |= status if path.indexOf(directoryPath) is 0
     directoryStatus

@@ -331,7 +331,16 @@
   getPathStatus: (path) ->
     repo = @getRepo(path)
     relativePath = @relativize(path)
-    currentPathStatus = @statusesByPath[relativePath] ? @async.getCachedPathStatuses()[relativePath] ? 0
+
+    # This is a bit particular. If a package calls `getPathStatus` like this:
+    #  - change the file
+    #  - getPathStatus
+    #  - change the file
+    #  - getPathStatus
+    # We need to preserve the guarantee that each call to `getPathStatus` will
+    # synchronously emit 'did-change-status'. So we need to keep a cache of the
+    # statuses found from this call.
+    currentPathStatus = @getCachedRelativePathStatus(relativePath) ? 0

     # Trigger events emitted on the async repo as well
     @async.refreshStatusForPath(path)
@@ -354,7 +363,11 @@
   #
   # Returns a status {Number} or null if the path is not in the cache.
   getCachedPathStatus: (path) ->
-    @async.getCachedPathStatuses()[@relativize(path)]
+    relativePath = @relativize(path)
+    @getCachedRelativePathStatus(relativePath)
+
+  getCachedRelativePathStatus: (relativePath) ->
+    @statusesByPath[relativePath] ? @async.getCachedPathStatuses()[relativePath]

   # Public: Returns true if the given status indicates modification.
   #


Destroy async repo from sync repo

Destroy async repo from sync repo

--- src/git-repository.coffee
+++ src/git-repository.coffee
@@ -120,6 +120,10 @@
       @subscriptions.dispose()
       @subscriptions = null

+    if @async?
+      @async.destroy()
+      @async = null
+
   # Public: Invoke the given callback when this GitRepository's destroy() method
   # is invoked.
   #


Check for favourited status on subject update

--- app/collections/favorites-button.cjsx
+++ app/collections/favorites-button.cjsx
@@ -56,6 +56,12 @@
       .then (favorited) =>
         @setState {favorited}

+  componentDidUpdate: (prevProps) ->
+    if prevProps.subject isnt @props.subject
+      @findSubjectInCollection(@state.favorites)
+      .then (favorited) =>
+        @setState {favorited}
+
   addSubjectTo: (collection) ->
     @setState favorited: true
     collection.addLink('subjects', [@props.subject.id.toString()])


Nicer method handling

Nicer method handling

--- public/coffee/controllers.coffee
+++ public/coffee/controllers.coffee
@@ -47,9 +47,20 @@
     else
       []

+  uniq = (things) ->
+    index = {}
+    for thing in things
+      index[thing] = 1
+    return Object.keys(index)
+
   $scope.suggest = (vv) ->
+    term = String(vv).toLowerCase()
     if $scope.parameter.Options
-      return Suggestions.getSuggestions $scope.params, $scope.parameter
+      # Not sure why I had to implement filtering logic here...
+      filter = (s) -> 0 <= String(s).toLowerCase().indexOf term
+      return Suggestions.getSuggestions($scope.params, $scope.parameter)
+                        .then( (sgs) -> sgs.filter filter )
+                        .then( uniq )
     else
       d = $q.defer()
       d.resolve getHistory()
@@ -105,8 +116,14 @@

 getCurrentValue = (ps, name) -> return p.currentValue for p in ps when p.Name is name

+initMethod = (m) ->
+  m.results ?= []
+  body = m.body?[0]
+  m.bodyContentType = body?.contentType
+  m.content = body?.example

 Controllers.controller 'MethodCtrl', ($scope, $q, $log, $http, Suggestions, Defaults, ParamUtils, Storage, parameterHistoryKey, Counter, Markdown) ->
+  initMethod $scope.m
   $scope.params = angular.copy($scope.m.parameters)

   do initParams = ->
@@ -232,13 +249,6 @@
   methodMatches = (m) ->
     (m.HTTPMethod is $routeParams.method) and ((m.URI or '/') is $routeParams.servicePath)

-  initMethod = (m) ->
-    m.active = true
-    m.results ?= []
-    body = m.body?[0]
-    m.bodyContentType = body?.contentType
-    m.content = body?.example
-
   methodWatch = (s) ->
     {HTTPMethod, URI} = s.currentMethod
     HTTPMethod + URI
@@ -264,7 +274,7 @@
     return $location.path '/'

   m.active = false for m in $scope.endpoint.methods
-  initMethod $scope.currentMethod
+  $scope.currentMethod.active = true

   $log.debug 'CURRENT METHOD', $scope.currentMethod

@@ -278,6 +288,11 @@
   $scope.$watch methodWatch, updateLocation

 Controllers.controller 'EndpointDetails', EndpointCtrl
+
+APPL_JSON = /^application\/json/
+TEXT_XML = /^text\/xml/
+APPL_XML = /^application\/xml/
+TEXT_HTML = /^text\/html/

 Controllers.controller 'ResponseCtrl', ($q, $timeout, $scope, $log, xmlParser, TreeParsing) ->

@@ -288,34 +303,50 @@
   $scope.hasParams = -> Object.keys($scope.params).length > 0
   $scope.parsedData = []
   $scope.tree = expanded: false
+  $scope.totalPromises = 0
+  $scope.currentParsed = 0
+  $scope.percentDone = 0
+
+  startId = TreeParsing.nextId()

   ct = ($scope.headers['content-type'] ? '')
-  promises = []
-  if $scope.res.response?.length
-    if ct.match(/^application\/json/)
-      parsed = try
-        JSON.parse($scope.res.response)
-      catch e
-        {}
-      for k, v of parsed
-        promises.push TreeParsing.parseObj k, v
-    else if /^text\/xml/.test(ct) or /^application\/xml/.test(ct)
-      try
-        dom = xmlParser.parse $scope.res.response
-        promises.push TreeParsing.parseDOMElem(dom.documentElement)
-      catch e
-        $log.error 'Error parsing xml', e
+  if APPL_JSON.test ct
+    parsed = try
+      JSON.parse($scope.res.response)
+    catch e
+      {}
+    $scope.formattedResponse = JSON.stringify(parsed, null, 2) if parsed?

   setTree = (tree) ->
     $scope.parsedData = tree
     $log.debug "Next id = #{ TreeParsing.nextId() }"
-
-  if promises.length
-    $q.all(promises)
-      .then((parsed) -> TreeParsing.expandTree parsed, not $scope.tree.expanded)
-      .then setTree, $log.error
-
-  $scope.isHTML = -> !!ct?.match /^text\/html/
+
+  $scope.makeBrowseableResponse = ->
+    return if $scope.parsedData.length # Already done.
+    promises = []
+    if $scope.res.response?.length
+      if APPL_JSON.test ct
+        parsed = try
+          JSON.parse($scope.res.response)
+        catch e
+          {}
+        for k, v of parsed
+          promises.push TreeParsing.parseObj k, v
+      else if TEXT_XML.test(ct) or APPL_XML.test(ct)
+        try
+          dom = xmlParser.parse $scope.res.response
+          promises.push TreeParsing.parseDOMElem(dom.documentElement)
+        catch e
+          $log.error 'Error parsing xml', e
+
+    if promises.length
+      $q.all(promises)
+        .then((parsed) -> TreeParsing.expandTree parsed, not $scope.tree.expanded)
+        .then setTree, $log.error
+
+  $scope.browseable = APPL_JSON.test(ct) or APPL_XML.test(ct) or TEXT_XML.test(ct)
+
+  $scope.isHTML = TEXT_HTML.test ct

   processingInstructions = /<\?[^?]*\?>/g
   $scope.cleanHTML = $scope.res.response.replace(processingInstructions, '')


:wip: gv

:wip: gv

--- lib/vim-state.coffee
+++ lib/vim-state.coffee
@@ -279,9 +279,9 @@

   reselectLastVisual: ->
     return unless @lastVisual
+    @activate(mode, submode)
     {mode, submode, range, reversed} = @lastVisual
     @editor.getLastSelection().setBufferRange(range, reversed)
-    @activate(mode, submode)

   syncSelectionsReversedSate: (reversed) ->
     for selection in @editor.getSelections()


fix event notification leak

fix event notification leak

--- lib/web/index.coffee
+++ lib/web/index.coffee
@@ -121,6 +121,7 @@
         @log 'debug', 'Client socket disconnected; unregistering notifications'
         @_server.controls.off 'change', notifyControlChange, socket
         @_server.capabilities.off 'change', notifyCapabilityChange, socket
+        @_server.events.off 'add remove change', notifyOngoingEventsChange, socket

     httpServer.listen @_config.port, =>
       @log 'info', "Listening on port #{httpServer.address().port}"


Only track events in production

Only track events in production

Our production environment has this environment variable set.

--- lib/webserver.coffee
+++ lib/webserver.coffee
@@ -24,8 +24,10 @@
 app.use('/assets', express.static(generatedPath))
 app.use('/vendor', express.static(vendorPath))

+port = process.env.PORT || 3002
+env = process.env.NODE_ENV
+
 # Find an available port
-port = process.env.PORT || 3002
 if port > 3002
   webserver.listen(port)
 else
@@ -53,7 +55,8 @@

 # Tracking
 router.use (req, res, next) ->
-  Tracker.trackPage('API request', req.url, next)
+  if env == 'production'
+    Tracker.trackPage('API request', req.url, next)

 # Root
 router.get '/', (req, res) ->


Add event subscriptions for observing level code editors

--- lib/workspace.coffee
+++ lib/workspace.coffee
@@ -20,11 +20,19 @@
   onDidExitWorkspace: (callback) ->
     @emitter.on('did-exit-workspace',callback)

+  observeLevelCodeEditors: (callback) ->
+    callback(levelCodeEditor) for levelCodeEditor in @getLevelCodeEditors()
+    @onDidAddLevelCodeEditor(callback)
+
   onDidAddLevelCodeEditor: (callback) ->
     @emitter.on('did-add-level-code-editor',callback)

   onDidDestroyLevelCodeEditor: (callback) ->
     @emitter.on('did-destroy-level-code-editor',callback)
+
+  observeActiveLevelCodeEditor: (callback) ->
+    callback(@activeLevelCodeEditor) if @isActive()
+    @onDidChangeActiveLevelCodeEditor(callback)

   onDidChangeActiveLevelCodeEditor: (callback) ->
     @emitter.on('did-change-active-level-code-editor',callback)
@@ -45,11 +53,13 @@
   addLevelCodeEditor: (levelCodeEditor) ->
     @levelCodeEditorsById[levelCodeEditor.getId()] = levelCodeEditor
     @emitter.emit('did-add-level-code-editor',levelCodeEditor)
+    console.log @levelCodeEditorsById

   destroyLevelCodeEditor: (levelCodeEditor) ->
     delete @levelCodeEditorsById[levelCodeEditor.getId()]
     levelCodeEditor.destroy()
     @emitter.emit('did-destroy-level-code-editor')
+    console.log @levelCodeEditorsById

   getLevelCodeEditorForTextEditor: (textEditor) ->
     @levelCodeEditorsById[textEditor.id]


Should redraw highlights in Editor::unmark

--- src/controller.coffee
+++ src/controller.coffee
@@ -3739,6 +3739,8 @@

 Editor::unmark = (key) ->
   delete @markedBlocks[key]
+
+  @redrawHighlights()
   return true

 Editor::unmarkLine = (line) ->


Use cubic-bezier

Use cubic-bezier

--- js/flight.coffee
+++ js/flight.coffee
@@ -165,7 +165,7 @@
   # Returns nothing.
   translate: (page, axis, distance, duration) ->
     duration = @speed unless duration?
-    page.style.webkitTransition = "#{duration} ease-in-out"
+    page.style.webkitTransition = "#{duration} cubic-bezier(.10, .10, .25, .90)"
     page.style.webkitTransform = "translate#{axis}(#{distance})"

   # Private: Display the current page.


clampable

clampable

--- test/clampable.coffee
+++ test/clampable.coffee
@@ -2,7 +2,7 @@

 test "testing for equality", ->
   o = GameObject
-    x:
+    x: 1500

   max = 100


Fix mock url for content

Fix mock url for content

--- test/demo-mock.coffee
+++ test/demo-mock.coffee
@@ -12,8 +12,8 @@
     proxy: 'data/content.json'

   $.mockjax (settings) ->
-    # url: '/content/<id>'
-    id = settings.url.match(/\/content\/(.*)$/);
+    # url: '/api/content/<id>'
+    id = settings.url.match(/\/api\/content\/(.*)$/);
     if id
       return {proxy: 'data/content/' + id[1] + '.json'}


fixed timeline with non-discrete axis

fixed timeline with non-discrete axis

--- src/viz/helpers/ui/timeline.coffee
+++ src/viz/helpers/ui/timeline.coffee
@@ -338,7 +338,7 @@
       .on("brush", brushed)
       .on("brushend", brushend)

-    if vars[vars.axes.discrete].value is vars.time.value
+    if vars.axes.discrete and vars[vars.axes.discrete].value is vars.time.value
       tickColor = vars[vars.axes.discrete].ticks.color
     else
       tickColor = vars.x.ticks.color


test is for factory only

test is for factory only

--- test/evaluator.coffee
+++ test/evaluator.coffee
@@ -71,7 +71,7 @@
         assert.equal f.params.length, 1
         assert.equal f.params[0].value, 5

-      it 'builds additions', ->
+      it 'builds infix expressions', ->
         f = e.build {
           expression: 'add'
           left:
@@ -87,4 +87,3 @@
         }
         assert.equal f.left.value, 5
         assert.equal f.right.value, 3
-        assert.equal f.evaluate({}), 8


Focus the message input on window focus

Focus the message input on window focus

--- packages/rocketchat-ui-master/master/main.coffee
+++ packages/rocketchat-ui-master/master/main.coffee
@@ -235,3 +235,9 @@
 		$('html').removeClass "rtl"

 	$('.page-loading').remove()
+
+	window.addEventListener 'focus', ->
+		Meteor.setTimeout ->
+			if not $(':focus').is('INPUT,TEXTAREA')
+				$('.input-message').focus()
+		, 100


Fixed logToChannel rtm

Fixed logToChannel rtm

--- src/helpers/logger.coffee
+++ src/helpers/logger.coffee
@@ -129,7 +129,7 @@
             Logger.error "Error opening DM: #{err}"
         )
     @getChannelName: (channel) ->
-      channel = @rtm.dataStore.getChannelGroupOrDMById channel
+      channel = @initRTM().dataStore.getChannelGroupOrDMById channel
       return channel.name
     @logToChannel: (msg, channel, attachment, isUser) ->
       if msg


Fix removal of popup message element after fading out

--- resources/assets/coffee/shared.coffee
+++ resources/assets/coffee/shared.coffee
@@ -57,7 +57,7 @@
 $(document).on 'click', '#popup-container, #overlay', (e) ->
   $('#overlay').fadeOut()
   $popup = $(e.target).closest('.popup-active')
-  $popup.fadeOut null, $popup.remove
+  $popup.fadeOut null, -> $popup.remove()

 ###


Revert "temporary fix for dependecies"

Revert "temporary fix for dependecies"

This reverts commit e9858c4385a011e183e2d1e64cd72e7729618866.

--- review_front/app/models/commit.coffee
+++ review_front/app/models/commit.coffee
@@ -12,8 +12,8 @@
   author: DS.belongsTo('author')
   tickets: DS.hasMany('ticket')
   reviewer: DS.belongsTo('user', {async: true})
-  fix: DS.hasMany('commit', {inverse: 'fix', async: true})
-  fixed: DS.hasMany('commit', {inverse: 'fixed', async: true})
+  fix: DS.hasMany('commit', {inverse: 'fix'})
+  fixed: DS.hasMany('commit', {inverse: 'fixed'})

   shortHash: Ember.computed('remoteId', ->
     @get('remoteId').substr(0,6)


remove unused template

remove unused template

--- src/coffee/directives/dynamic.coffee
+++ src/coffee/directives/dynamic.coffee
@@ -21,7 +21,6 @@
       restrict: 'E'
       scope:
         field: '='
-      template: ""
       link: l
     }


Edit Vision (Text)

Edit Vision (Text)

--- src/components/LandingExplain.coffee
+++ src/components/LandingExplain.coffee
@@ -19,7 +19,9 @@
   render: ->
     { onClick } = @props
     div null,
-      h2 null, "Online suchen - Offline handeln"
+      h2 null, "Die Welt steckt voller Entdecker."
+       br null
+      "Und voller Orte, die darauf warten entdeckt zu werden."
       div
       img style: {float: "left"}, src: require "../img/lp_illu1.jpg"
       div style: {marginTop: "200px"},
@@ -56,13 +58,13 @@

       h2 null, "Die Vision von morgen"
       p null,
-        "Die Welt steckt voller Entdecker. Und voller Orte,"
-        br null
-        "die darauf warten entdeckt zu werden."
-      p null,
         "von morgen fördert Kreativität, Umweltfreundlichkeit und"
         br null
         "gemeinsames Handeln im bunten Feld des gesellschaftlichen Wandels."
+      p null,
+        "von morgen hat die Vision einer intakten Welt, in der die Menschen"
+        br null
+        "miteinander ein selbstbestimmtes, glückliches und umweltbewusstes Leben führen."
         br null
         "Das Ziel: eine menschliche Zukunft."


Events are ok.

Events are ok.

--- src/xo.coffee
+++ src/xo.coffee
@@ -156,23 +156,56 @@

     # When objects enter or exists, sends a notification to all
     # connected clients.
-    #
-    # FIXME: too much events, we should summarize them.
-    #
-    # FIXME: exit events really mess XO-Web up when a simple update
-    # would be enough.
-    @_xobjs.on 'any', (event, items) =>
-      event = {
-        type: event
-        items: $_.pluck items, 'val'
-      }
-
-      for id, connection of @connections
-        connection.send JSON.stringify {
-          jsonrpc: '2.0'
-          method: 'all'
-          params: event
-        }
+    do =>
+      entered = {}
+      exited = {}
+
+      dispatcherRegistered = false
+      dispatcher = =>
+        entered = $_.pluck entered, 'val'
+        enterEvent = if entered.length
+          JSON.stringify {
+            jsonrpc: '2.0'
+            method: 'all'
+            params: {
+              type: 'enter'
+              items: entered
+            }
+          }
+        exited = $_.pluck exited, 'val'
+        exitEvent = if exited.length
+          JSON.stringify {
+            jsonrpc: '2.0'
+            method: 'all'
+            params: {
+              type: 'exit'
+              items: exited
+            }
+          }
+
+        if entered.length
+          connection.send enterEvent for id, connection of @connections
+        if exited.length
+          connection.send exitEvent for id, connection of @connections
+        dispatcherRegistered = false
+        entered = {}
+        exited = {}
+
+      @_xobjs.on 'any', (event, items) ->
+        unless dispatcherRegistered
+          dispatcherRegistered = true
+          process.nextTick dispatcher
+
+        if event is 'exit'
+          for item in items
+            {key} = item
+            delete entered[key]
+            exited[key] = item
+        else
+          for item in items
+            {key} = item
+            delete exited[key]
+            entered[key] = item

     # Exports the map from UUIDs to keys.
     {$UUIDsToKeys: @_UUIDsToKeys} = (@_xobjs.get 'xo')


Remove extra condition

Remove extra condition

--- src/notification.coffee
+++ src/notification.coffee
@@ -26,7 +26,7 @@
     delete options.groupingHash
     event.metaData = Utils.cloneObject Configuration.metaData if Configuration.metaData && Object.keys(Configuration.metaData).length > 0

-    if options.req || process?.domain?._bugsnagOptions?.req
+    if options.req
       @processRequest event, requestInfo(options.req)
       delete options.req
     else if process?.domain?._bugsnagOptions?.cleanedRequest


Update git-revision-view.coffee

Update git-revision-view.coffee

--- lib/views/git-revision-view.coffee
+++ lib/views/git-revision-view.coffee
@@ -6,6 +6,7 @@
 {CompositeDisposable, BufferedProcess} = require "atom"
 {$} = require "atom-space-pen-views"

+disposables = new CompositeDisposable
 SplitDiff = null
 SyncScroll = null

@@ -63,7 +64,7 @@
             try
               disposables.add newTextEditor.onDidDestroy -> fs.unlink outputFilePath
             catch error
-              return atom.notifications.addError error
+              return atom.notifications.addError "Could not remove file #{outputFilePath}"

   @_updateNewTextEditor: (newTextEditor, editor, gitRevision, fileContents) ->
     _.delay =>


Store: Added forgotten param annotation for second parameter of get method.

--- src/lib/core/Store.coffee
+++ src/lib/core/Store.coffee
@@ -36,6 +36,7 @@

     @export
     @param {string} key Key to be returned.
+    @param {boolean=} escape Whether you want to espace the value or not.
     @return {*}
   ###
   get: (key, escape = yes) ->


Added @GelatoGypsy

Added @GelatoGypsy


Safety in case given buffer hasn't received data

--- src/lib/InPort.coffee
+++ src/lib/InPort.coffee
@@ -163,6 +163,7 @@
   # Fetches a packet from the port
   get: (scope, idx) ->
     buf = @getBuffer scope, idx
+    return undefined unless buf?.length
     return if @options.control then buf[buf.length - 1] else buf.shift()

   # Returns true if port contains packet(s) matching the validator


Added contextualizeBefore and contextualizeAfter events access for plugins

--- src/lib/docpad.coffee
+++ src/lib/docpad.coffee
@@ -117,6 +117,8 @@
 		'generateAfter'
 		'parseBefore'
 		'parseAfter'
+		'contextualizeBefore'
+		'contextualizeAfter'
 		'renderBefore'
 		'render'
 		'renderDocument'


Collection creation functions scope is now the docpad instance. Fixed serverMiddleware500.

--- src/lib/docpad.coffee
+++ src/lib/docpad.coffee
@@ -1229,14 +1229,14 @@
 		_.each @config.collections, (fn,name) ->
 			tasks.push (complete) ->
 				if fn.length is 2 # callback
-					fn database, (err,collection) ->
+					fn.call docpad, database, (err,collection) ->
 						docpad.error(err)  if err
 						if collection
 							collection.live(true)  # make it a live collection
 							docpad.setCollection(name,collection)  # apply the collection
 						complete()
 				else
-					collection = fn(database)
+					collection = fn.call(docpad,database)
 					if collection
 						collection.live(true)  # make it a live collection
 						docpad.setCollection(name,collection)  # apply the collection
@@ -2797,11 +2797,11 @@
 		return res.send(500)  unless database

 		# Serve the document to the user
-		document = database.findOne(relativeOutPath: '404.html')
+		document = database.findOne({relativeOutPath: '404.html'})
 		docpad.serveDocument({document,req,res,next,statusCode:404})

-	# Server Middleware: 404
- 	serverMiddleware500: (err,req,res,next) =>
+	# Server Middleware: 500
+	serverMiddleware500: (err,req,res,next) =>
 		# Prepare
 		docpad = @
 		database = docpad.getDatabase()
@@ -2810,8 +2810,8 @@
 		return res.send(500)  unless database

 		# Serve the document to the user
-		document = database.findOne(relativeOutPath: '500.html')
-		docpad.serveDocument({document,req,res,next,statusCode:500,err})
+		document = database.findOne({relativeOutPath: '500.html'})
+		docpad.serveDocument({document,err,req,res,next,statusCode:500})

 	# Server
 	server: (opts,next) =>


compare stringified function in Facade.isBaseClass() in Titanium #12

--- src/lib/facade.coffee
+++ src/lib/facade.coffee
@@ -329,7 +329,9 @@
     @return {Boolean}
     ###
     @isBaseClass: (klass) ->
-        (klass is @[klass.name]) or (klass is @DomainError) # DomainError does not have name
+        (klass is @[klass.name]) or
+        (klass is @DomainError) or
+        (@[klass.name]?.toString() is klass.toString())

     ###*
     registers the given class as a base class


Update Atom config.

Update Atom config.

--- configs/atom/config.cson
+++ configs/atom/config.cson
@@ -65,12 +65,8 @@
   "linter-phpcs":
     autoExecutableSearch: false
     codeStandardOrConfigFile: "WordPress"
-    executablePath: "/Users/justin/.control/tools/phpcs/scripts/phpcs"
+    executablePath: "/Users/koop/.control/tools/phpcs/bin/phpcs"
     tabWidth: 4
-  "linter-sass-lint":
-    configFile: "/Users/justin/.control/configs/.sass-lint.yml"
-    globalNodePath: "/usr/local"
-    noConfigDisable: true
   "linter-stylelint":
     disableWhenNoConfig: false
   "linter-ui-default":
@@ -79,8 +75,8 @@
   "php-debug":
     AutoExpandLocals: true
     PathMaps: [
-      "/srv/www/wp/wordpress-develop/src;/Users/justin/.developer/wp/wordpress-develop/src"
-      "/srv/www/wp/vip-go;/Users/justin/.developer/wp/work/vip-go"
+      "/srv/www/wp/wordpress-develop/src;/Users/koop/.developer/wp/wordpress-develop/src"
+      "/srv/www/wp/vip-go;/Users/koop/.developer/wp/work/vip-go"
     ]
     ServerPort: 9000
     currentConsoleHeight: "283px"


Pump pool stdout into stdout

Pump pool stdout into stdout

--- src/pow/server.coffee
+++ src/pow/server.coffee
@@ -1,7 +1,7 @@
 http = require 'http'
+sys  = require 'sys'

 {createPool}         = require 'nack/pool'
-{logStream}          = require 'nack/logger'
 {BufferedReadStream} = require 'nack/buffered'

 idle = 1000 * 60 * 15
@@ -23,8 +23,11 @@

   createApplicationPool: (config) ->
     pool = createPool config, size: 3, idle: idle
-    logStream pool.stdout
-    logStream pool.stderr
+
+    # TODO: Pump this to a file
+    sys.pump pool.stdout, process.stdout
+    sys.pump pool.stderr, process.stdout
+
     pool

   applicationForConfig: (config) ->


Call resize method on window resize

Call resize method on window resize

--- assets/javascripts/application.coffee
+++ assets/javascripts/application.coffee
@@ -29,6 +29,10 @@
   Dashing.widget_margins ||= [5, 5]
   Dashing.numColumns ||= 4
   Dashing.currentCurrency ||= "GBP"
+
+  $(window).bind 'resize', (event) =>
+    Dashing.resize()
+
   Dashing.resize()

 Dashing.resize = () ->


working on integrating in the backend

working on integrating in the backend

--- src/Game.coffee
+++ src/Game.coffee
@@ -26,14 +26,18 @@
     @socket = @setupSocket()

     @socket.emit 'new player', playerName
+
     @socket.on 'game started', (data) ->
-      # TODO
-      console.log 'game started'
+      for player in data.players
+        @players[player] = new Player(@viz.two, player)
+
     @socket.on 'game over', (data) ->
       # TODO
       console.log 'game over'
+
     @socket.on 'snap', (data) ->
       @player.addPoints data.d_score
+      @player.snap(@players[data.player])

   sendWord: (word) ->


impersonate: make chrisblum a dummy-admin

--- workers/social/lib/social/models/account/index.coffee
+++ workers/social/lib/social/models/account/index.coffee
@@ -554,7 +554,8 @@
       @update ($set: 'counts.topics': count), ->

   dummyAdmins = [ "sinan", "devrim", "aleksey-m", "gokmen", "chris",
-                  "arvidkahl", "testdude", "blum", "neelance", "halk", "fatihacet"]
+                  "arvidkahl", "testdude", "blum", "neelance", "halk",
+                  "fatihacet", "chrisblum" ]

   flagAccount: secure (client, flag, callback)->
     {delegate} = client.connection


Define shared machine user setter function

--- workers/social/lib/social/models/sharedmachine.coffee
+++ workers/social/lib/social/models/sharedmachine.coffee
@@ -1,6 +1,13 @@
 bongo = require 'bongo'
+
+JMachine = require './computeproviders/machine'

 module.exports = class SharedMachine extends bongo.Base

   @share()
+
+  setUsers = (client, uid, options, callback) ->
+
+    options.permanent = yes
+    JMachine.shareByUId client, uid, options, callback


add exit handler to unexport pins when killing server

--- led-server.coffee
+++ led-server.coffee
@@ -46,3 +46,25 @@

 app.listen app.get('port'), ->
   console.log "Listening on port #{app.get('port')}"
+
+
+exitHandler = (options, err) ->
+  for k, v of io
+    console.log "unexporting #{k}"
+    gpio.unexport k
+  if options.cleanup
+    console.log('cleaning')
+  if err
+    console.log(err.stack)
+  if options.exit
+    process.exit()
+
+
+# do something when app is closing
+process.on('exit', exitHandler.bind(null,{ cleanup: true }))
+
+# catches ctrl+c event
+process.on('SIGINT', exitHandler.bind(null, { exit: true }))
+
+# catches uncaught exceptions
+process.on('uncaughtException', exitHandler.bind(null, { exit: true }))


fixed a bug where context.stack would pop the scope too early

--- src/liquid/context.coffee
+++ src/liquid/context.coffee
@@ -44,6 +44,7 @@
       args?[0]

   push: (newScope = {}) ->
+    Liquid.log "SCOPE PUSH"
     @scopes.unshift newScope
     throw new Error("Nesting too deep") if @scopes.length > 100

@@ -51,6 +52,7 @@
     _(@scopes[0]).extend(newScope)

   pop: ->
+    Liquid.log "SCOPE POP"
     throw new Error("ContextError") if @scopes.length <= 1
     @scopes.shift()

@@ -76,9 +78,9 @@
       @push(newScope)
       result = f()

-      if f?.isFuture?
-        f.when => @pop()
+      if futures.future.isFuture(result)
         popLater = true
+        result.when => @pop()

       result
     finally
@@ -90,10 +92,13 @@
   # Only allow String, Numeric, Hash, Array, Proc, Boolean
   # or <tt>Liquid::Drop</tt>
   set: (key, value) ->
+    Liquid.log "[SET] %s %j", key, value
     @scopes[0][key] = value

   get: (key) ->
-    @resolve(key)
+    value = @resolve(key)
+    Liquid.log "[GET] %s %j", key, value
+    value

   hasKey: (key) ->
     !!@resolve(key)
@@ -151,7 +156,16 @@

     variable or= @lookupAndEvaluate(scope, key)

-    liquify(variable)
+    f = futures.future()
+    delivered = false
+    result = null
+
+    Liquid.Helpers.unfuture variable, (err, variable) ->
+      result = liquify(variable)
+      f.deliver(err, result)
+      delivered = true
+
+    if delivered then result else f

   variable: (markup) ->
     future = futures.future()


Remove unnecessary code

Remove unnecessary code

--- src/atom/line-map.coffee
+++ src/atom/line-map.coffee
@@ -102,9 +102,8 @@
       if pendingFragment
         pendingFragment = pendingFragment.concat(lineFragment)
       else
-        pendingFragment = _.clone(lineFragment)
+        pendingFragment = lineFragment
       if pendingFragment[deltaType].row > 0
-        pendingFragment.bufferDelta = new Point(1, 0)
         lines.push pendingFragment
         pendingFragment = null
     lines


Directly assign submenu when constructor is Menu

--- atom/browser/api/lib/menu-item.coffee
+++ atom/browser/api/lib/menu-item.coffee
@@ -26,8 +26,11 @@

     {click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked} = options

-    if options.submenu? and options.submenu.constructor isnt Menu
-      @submenu = Menu.buildFromTemplate options.submenu
+    if options.submenu?
+      if options.submenu.constructor is Menu
+        @submenu = options.submenu
+      else
+        @submenu = Menu.buildFromTemplate options.submenu
     @type = 'submenu' if not @type? and @submenu?
     throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu


* update test for inheritsDirectly

* update test for inheritsDirectly

--- test/util-test.coffee
+++ test/util-test.coffee
@@ -132,9 +132,9 @@
     assert.equal baseClass, C1
     inheritsDirectly baseClass, C2
     # C11 > C1 > C2 > C
-    assert.ok isInheritedFrom C11, C2, "C11 > C2"
-    assert.ok isInheritedFrom C11, C1, "C11 > C1"
-    assert.ok isInheritedFrom C11, C, "C11 > C"
+    assert.equal isInheritedFrom(C11, C2), C1, "C11 > C2"
+    assert.equal isInheritedFrom(C11, C1), C11, "C11 > C1"
+    assert.equal isInheritedFrom(C11, C), C2, "C11 > C"

   describe "createObject", ->
     createObject = util.createObject


Update to mac

Update to mac

--- atom/projects.cson
+++ atom/projects.cson
@@ -2,27 +2,27 @@
   {
     title: "data"
     paths: [
-      "/home/rogier/git/rm-etl"
-      "/home/rogier/git/rm-pentaho"
+      "/Users/rogier/git/rm-etl"
+      "/Users/rogier/git/rm-pentaho"
     ]
   }
   {
     title: "ror"
     paths: [
-      "/home/rogier/git/rm-data-admin"
-      "/home/rogier/git/rm-masterdata-engine"
-      "/home/rogier/git/rm-rails"
-      "/home/rogier/git/rm-oidc-engine"
+      "/Users/rogier/git/rm-data-admin"
+      "/Users/rogier/git/rm-masterdata-engine"
+      "/Users/rogier/git/rm-rails"
+      "/Users/rogier/git/rm-oidc-engine"
     ]
   }
   {
     title: "var"
     paths: [
-      "/home/rogier/git/rm-docker"
-      "/home/rogier/git/rm-mesos"
-      "/home/rogier/git/rm-scripts"
-      "/home/rogier/git/rm-secrets"
-      "/home/rogier/git/rm-system"
+      "/Users/rogier/git/rm-docker"
+      "/Users/rogier/git/rm-mesos"
+      "/Users/rogier/git/rm-scripts"
+      "/Users/rogier/git/rm-secrets"
+      "/Users/rogier/git/rm-system"
     ]
   }
 ]


Fix bug where rewrite rules were ignoring query strings

--- atom/snippets.cson
+++ atom/snippets.cson
@@ -873,8 +873,8 @@

   'HTTP to HTTPS':
     'prefix': 'https'
-    'body': 'RewriteCond %{HTTPS} off\nRewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]'
+    'body': 'RewriteCond %{HTTPS} off\nRewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [L,R=301]'

   'www to apex':
     'prefix': 'apex'
-    'body': 'RewriteCond %{HTTP_HOST} ^www\\\\.(.+)$ [NC]\nRewriteRule ^ ${1:http}://%1%{REQUEST_URI} [L,R=301]'
+    'body': 'RewriteCond %{HTTP_HOST} ^www\\\\.(.+)$ [NC]\nRewriteRule ^(.*)$ ${1:http}://%1/$1 [L,R=301]'


Rename jqready snippet to documentready

Rename jqready snippet to documentready

--- atom/snippets.cson
+++ atom/snippets.cson
@@ -193,7 +193,7 @@
     'body': '(function($1) {\n$3\n}($2));'

   'jquery document.ready':
-    'prefix': 'jqready'
+    'prefix': 'documentready'
     'body': '$(document).ready(function() {\n$2\n});'

   # Jasmine


Export graph in http://yuml.me/ format

Export graph in http://yuml.me/ format

--- graph.coffee
+++ graph.coffee
@@ -53,5 +53,15 @@

         return dot

+    toYUML: ->
+        yuml = []
+
+        for initializer in @initializers
+            yuml.push "(start)[#{initializer.to.port}]->(#{initializer.to.node})";
+
+        for edge in @edges
+            yuml.push "(#{edge.from.node})[#{edge.from.port}]->(#{edge.to.node})"
+        yuml.join ","
+
 exports.createGraph = (name) ->
     new Graph name


add areaOffset

add areaOffset

--- graph.coffee
+++ graph.coffee
@@ -37,10 +37,13 @@
         'line'

     stack = d3.layout.stack()
+      .offset(params.areaOffset ? 'zero')
       .values((d) -> d.values)
       .x((d) -> d.time)
       .y((d) -> d.value)
-      .out((d, y0) -> d.y0 = y0)
+      .out((d, y0, y) ->
+        d.y0 = y0
+        d.value = y)

     line_fn = (d, i) ->
       mode = line_mode d, i
@@ -71,6 +74,8 @@

     if params.areaMode is 'stacked'
       stack targets
+      value_min = null
+      value_max = null
       for {values} in targets
         for {value, y0} in values
           value += y0


Add malifi.site_meta (relative to the site actually serving the request)

--- lib/action.coffee
+++ lib/action.coffee
@@ -38,7 +38,8 @@
     unless root
       next_layer()
     else
-      actions= malifi.meta_lookup(join(root,malifi.path.relative))._actions
+      site_meta= malifi.site_meta= malifi.meta_lookup(join(root,malifi.path.relative))
+      actions= site_meta._actions
       extLookup= actions[if req.method is 'HEAD' then 'GET' else req.method]
       extSilo = extLookup[urlExtension] ? extLookup['*']
       traverseActionList = (actionList)=>


Tests: Activity: postwith: Pause for image loading postMessageWithImage test.

--- tests/src/activity/postwith.coffee
+++ tests/src/activity/postwith.coffee
@@ -38,8 +38,9 @@
       .click                  '[testpath="ActivityTabHandle-/Activity/Public/Recent"]'
       .click                  '[testpath=ActivityInputView]'
       .setValue               '[testpath=ActivityInputView]', image
-      .pause                  5000
+      .pause                  5000 # wait for image loading
       .click                  '[testpath=post-activity-button]'
+      .pause                  5000 # wait for image loading
       .waitForElementVisible   selector, 20000 # Assertion
       .end()


Handle detachment / focus restoration compatibly with editor shadow DOM


Replace anything resembling newline in int. proc.

--- lib/ghc-mod/interactive-process.coffee
+++ lib/ghc-mod/interactive-process.coffee
@@ -87,7 +87,7 @@
         else
           [command, args...]
       debug "Running ghc-modi command #{command}", args...
-      @proc.stdin.write "#{args_.join(' ').replace(EOL, ' ')}#{EOL}"
+      @proc.stdin.write "#{args_.join(' ').replace(/(?:\r?\n|\r)/g, ' ')}#{EOL}"
       if data?
         debug "Writing data to stdin..."
         @proc.stdin.write "#{data}#{EOT}"


:racehorse: Memoize version to prevent future IPC calls

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

   # Public: Get the version of the Atom application.
   getVersion: ->
-    app.getVersion()
+    @version ?= app.getVersion()

   # Public: Determine whether the current version is an official release.
   isReleasedVersion: ->


limit zoom out to 0.6 because <=0.5 is busted for why?

--- coffee/core/core.coffee
+++ coffee/core/core.coffee
@@ -97,7 +97,7 @@
   zoom: (factor) ->
     oldScale = @scale
     @scale = @scale + factor
-    @scale = Math.max(@scale, 0.2)
+    @scale = Math.max(@scale, 0.6)
     @scale = Math.min(@scale, 4.0)
     @scale = Math.round(@scale * 100) / 100


bugfix: parseInt

bugfix: parseInt

--- coffee/cryptmail.coffee
+++ coffee/cryptmail.coffee
@@ -6,7 +6,6 @@
  * @copyright          Michael Schulze, 31 December, 2011
  * @license            GNU General Public License, version 3 (GPL-3.0)
  * @package            coffeescript
- * @requirements       jquery-1.7.1.min.js
  *
  * @lastmodified       $Date: 2011-12-31 20:29:35  +0100 (Sat, 31 Dec 2011) $
  *
@@ -35,7 +34,7 @@
     if radioObj.length > 0
       i = 0
       while i < radioObj.length
-        radioValue = parseInt(radioObj[i].value if radioObj[i].checked)
+        radioValue = parseInt(radioObj[i].value if radioObj[i].checked, 0)
         i++
     else
       radioValue = 0


enh: index works

enh: index works

--- coffee/indexeddb.coffee
+++ coffee/indexeddb.coffee
@@ -139,6 +139,8 @@
     console.log "Create files and database store"
     @fileStore = db.createObjectStore "files", {autoIncrement: true}
     @catalogStore = db.createObjectStore "catalog", {autoIncrement: true}
+
+    @catalogIndex = @catalogStore.createIndex "catalogByGrid", ['gridN', 'gridM', 'funcId', 'name', 'time'], {unique: false}

     @populated = false

@@ -168,7 +170,7 @@
     filesEnumerated = 0

     onRecord = (res, record)=>
-      console.log "Found file: #{res.key}" if res?
+      #console.log "Found file: #{res.key}" if res?
       grid = "{#{record.gridN};#{record.gridM}}"
       if grid isnt lastGrid
         #loading next group
@@ -227,10 +229,18 @@
     console.log "Loaddata"
     transaction = @db.transaction ["catalog"], "readonly"
     filesStore = transaction.objectStore "catalog"
-    cursor = filesStore.openCursor()
+    cursor = filesStore.index("catalogByGrid").openCursor()
     @loadFromCursor cursor, (rec)->true

   loadDataFor: (gridN, gridM, funcId) ->
+    transaction = @db.transaction ["catalog"], "readonly"
+    catalog = transaction.objectStore "catalog"
+    catalogIndex = catalog.index "catalogByGrid"
+    cursor = catalogIndex.openCursor()
+    @loadFromCursor cursor, (rec)->
+      (rec.gridN is gridN) and (rec.gridM is gridM) and ((funcId is null) or (rec.funcId is funcId))
+
+  loadDataFor1: (gridN, gridM, funcId) ->
     transaction = @db.transaction ["catalog"], "readonly"
     filesStore = transaction.objectStore "catalog"
     #create range
@@ -267,17 +277,19 @@
       rqStoreData.onerror = (e)=>
         console.log "Error storing data #{e.target.error}"
       rqStoreData.onsuccess = (e)=>
-        console.log "Stored data OK, key is #{e.target.result}"
+        #console.log "Stored data OK, key is #{e.target.result}"
         #console.dir e.target
         key = e.target.result
         #console.log "Store catalog record"
         catalogRecord =
-          gridN: (Math.random()*4)|0+4
-          gridM: (Math.random()*4)|0+4
+          gridN: (Math.random()*5)|0+3
+          gridM: (Math.random()*5)|0+3
           name: "File #{i+1}"
           funcId: "B 3 S 2 3"
           funcType: "binary"
           base: 'e'
+          size: fieldData.length
+          time: Date.now()
           offset: M.eye()
           field: key