Get collection detail subjects.

Get collection detail subjects.

--- app/javascripts/routes.coffee
+++ app/javascripts/routes.coffee
@@ -77,6 +77,17 @@
             url: '/:collection'
             resolve:
               Subject: 'Subject'
+              subjects: (Subject, project) ->
+                # The selection criterion is the project name.
+                cond = REST.where(project: project)
+                # The id is always fetched. In addition, the
+                # project/collection/number secondary key is fetched.
+                # No other fields are fetched.
+                fields = REST.map(['project', 'collection', 'number'])
+                # The HTML query parameter.
+                param = _.extend(_.clone(cond), fields)
+                # Delegate to the resource.
+                Subject.query(param).$promise
               collection: ($stateParams) ->
                 _s.capitalize($stateParams.collection)
               charting: (Subject, project, collection) ->


'yield*' now works as expected

'yield*' now works as expected

--- lexer.coffee
+++ lexer.coffee
@@ -99,8 +99,9 @@
   # referenced as property names here, so you can still do `jQuery.is()` even
   # though `is` means `===` otherwise.
   identifierToken: ->
-    return 0 unless match = IDENTIFIER.exec @chunk
+    return 0 unless match = /^yield\*/.exec(@chunk) or IDENTIFIER.exec @chunk
     [input, id, colon] = match
+    if input is 'yield*' then id = 'yield*'

     # Preserve length of id for location data
     idLength = id.length
@@ -404,10 +405,6 @@
     if value is ';'
       @seenFor = no
       tag = 'TERMINATOR'
-    else if value is '*' and prev[1] is 'yield' and not prev.spaced
-      poppedToken = @tokens.pop()
-      tag = 'UNARY'
-      value = 'yield*'
     else if value in MATH            then tag = 'MATH'
     else if value in COMPARE         then tag = 'COMPARE'
     else if value in COMPOUND_ASSIGN then tag = 'COMPOUND_ASSIGN'


More robust error handling

More robust error handling

--- src/server/models/scope.coffee
+++ src/server/models/scope.coffee
@@ -70,13 +70,13 @@

         model = model.daoInstance

-        unless field
-          throw new Error "Scope::includes - Could not find an association between #{@context} and #{model}"
-
       # the association name was passed. Resolve to the correct association
-      else
+      else if @context.hasAssociation(model)
         field = model
         model = @context.getAssociation(model).daoInstance
+
+      unless field
+        throw new Error "Scope::includes - Could not find an association between #{@context.name} and #{model}"

       option =
         model: model


all functions that take state now log their entry with the state

--- src/giphy.coffee
+++ src/giphy.coffee
@@ -85,7 +85,6 @@
       }

   match: (input) ->
-    @log 'match:', input
     Giphy.regex.exec input or ''

   getEndpoint: (state) ->
@@ -99,6 +98,7 @@
       state.endpoint = state.args = ''

   getNextOption: (state) ->
+    @log 'getNextOption:', state
     regex = /\/(\w+):(\w+)/
     optionFound = false
     state.args = state.args.replace regex, (match, key, val) ->
@@ -175,6 +175,7 @@
       @handleResponse state, err, => @getRandomResult(res.data, @getUriFromResult)

   getHelp: (state) ->
+    @log 'getHelp:', state

   getUri: (state) ->
     @log 'getUri:', state
@@ -188,6 +189,7 @@
       else @error state.msg, "Unrecognized Endpoint: #{state.endpoint}"

   handleResponse: (state, err, uriCreator) ->
+    @log 'handleResponse:', state
     if err
       @error state.msg, err
     else


runit centos

runit centos

--- scripts/factoid-natural.coffee
+++ scripts/factoid-natural.coffee
@@ -22,7 +22,9 @@

 factoidkeys = [
   ['merlinsupport', ['merlin', 'support']],
-  ['chefsupport', ['chef', 'support']]
+  ['chefsupport', ['chef', 'support']],
+  ['runitcentos', ['chef', 'runit', 'cento']],
+  ['runitcentos', ['cookbook', 'runit', 'cento']]
 ]

 compare = (tokens, factoidkey) ->


jview mixin needed

jview mixin needed

--- client/Social/Activity/views/embedbox/embedboxlinkviewdescription.coffee
+++ client/Social/Activity/views/embedbox/embedboxlinkviewdescription.coffee
@@ -1,4 +1,6 @@
 class EmbedBoxLinkViewDescription extends KDView
+
+  JView.mixin @prototype

   { getDescendantsByClassName, setText } = KD.dom


fix resopnsive behavior (wow!)

fix resopnsive behavior (wow!)

--- app/assets/javascripts/chaltron/main.js.coffee
+++ app/assets/javascripts/chaltron/main.js.coffee
@@ -7,11 +7,11 @@
 $(document).on 'page:change', ->
   $('.datatable').DataTable({
     # ajax: ...,
-    # autoWidth: false,
-    # pagingType: 'full_numbers',
+    autoWidth: false,
+    pagingType: 'full_numbers',
     # processing: true,
     # serverSide: true,
-    # responsive: true
+    responsive: true

     # Optional, if you want full pagination controls.
     # Check dataTables documentation to learn more about available options.


revert flash message fade out

revert flash message fade out

--- app/assets/javascripts/chaltron/main.js.coffee
+++ app/assets/javascripts/chaltron/main.js.coffee
@@ -1,7 +1,7 @@
 $(document).on 'turbolinks:load', ->
   $('.dropdown-toggle').dropdown()

-  # # Flash
-  # if (flash = $('.flash-container div.alert')).length > 0
-  #   flash.click -> $(@).fadeOut()
-  #   setTimeout (-> flash.fadeOut()), 5000
+  # Flash
+  if (flash = $('.flash-container div.alert')).length > 0
+    flash.click -> $(@).fadeOut()
+    setTimeout (-> flash.fadeOut()), 5000


typo fix

typo fix

--- ios-drag-drop.coffee
+++ ios-drag-drop.coffee
@@ -109,7 +109,7 @@
           snapBack = false
           @el.style["-webkit-transform"] = "translate(0,0)"
         once doc, "drop", =>
-          snapBack if snapBack
+          doSnapBack() if snapBack

         # dispatch event on drop target
         parent = @el.parentNode


cleaning up html nightmare markup in the .coffee file.

--- assets/coffeescript/pupil_store.coffee
+++ assets/coffeescript/pupil_store.coffee
@@ -197,69 +197,69 @@
         $(".Cart-container").show()
         for k,v of LocalStorage.dict()
           # product, id, specs, price, quantity
-          newRow = "

-

-
-

-                            #{ getOrderSpecTxt(v.order) }
-

-
-
-

-
-
-

-
-

+          specTxtHtml = "

+                          #{ getOrderSpecTxt(v.order) }
+
"
+
+          costFormulaHtml = "

-

-
€ #{ getProductsSum(v.order,1) }

-

+

+
€ #{ getProductsSum(v.order,1) }

+

-

-

-

-
x

-

-

-
#{ v.qty }

-

-

-

-

-

+

+

+

+
x

+

+

+
#{ v.qty }

+

+

+

+

+

+

-

-
-

-

-
-
-
-

-

-
-

-
=

-

+
+

+
"
+
+          costSumHtml = "

+

+
+

+
=

+

-

-
€ #{ getProductsSum(v.order,v.qty) }

-

+

+
€ #{ getProductsSum(v.order,v.qty) }

+

-

-
(remove)

-

-
-

-

-

-
-

-
"
+

+
(remove)

+

+
+

+
"
+
+          newRow = "

+
" +
+
+                        specTxtHtml +
+                        "
" +
+                          "
" +
+                            costFormulaHtml +
+                            costSumHtml +
+                          "
" +
+                        "
" +
+
+                      "
" +
+                    "
"
+
           $("#Cart-table").after(newRow)
         [totalPrice,label] = if LocalStorage.length() > 0 then [getProductsSum(v.order,v.qty) for k,v of LocalStorage.dict(),"Sub Total"] else ["",""]
         totalPrice = if totalPrice.length > 0 then "€ " + _sumAll(totalPrice)


fix race condition in publisher spec

fix race condition in publisher spec

--- test/lib/Publisher-spec.coffee
+++ test/lib/Publisher-spec.coffee
@@ -1,3 +1,4 @@
+async = require 'async'
 Publisher = require '../../lib/Publisher'
 {createClient} = require '../../lib/redis'

@@ -27,8 +28,10 @@
         @redis.subscribe 'testy:sent:yer-id', done

       beforeEach (done) ->
-        @redis.once 'message', (@channel, @message) =>
-        @sut.publish 'sent', 'yer-id', carnivorousPlant: 'Feed me, Seymour!', done
+        async.parallel [
+          (callback) => @redis.once 'message', (@channel, @message) => callback()
+          async.apply @sut.publish, 'sent', 'yer-id', carnivorousPlant: 'Feed me, Seymour!'
+        ], done

       it 'should publish into redis', ->
         expect(@message).to.exist


fix error when setting general subtype filter

--- app/assets/javascripts/species/controllers/elibrary_search_controller.js.coffee
+++ app/assets/javascripts/species/controllers/elibrary_search_controller.js.coffee
@@ -36,12 +36,23 @@

     @set('selectedDocumentType', allDocumentTypes.findBy('id', filtersHash.document_type))
     @set('selectedDocumentType', allDocumentTypes.findBy('id', filtersHash.document_type))
-
-    @set('selectedGeneralSubType',
-      @get('controllers.events.generalSubTypes')
-        .findBy('id', if filtersHash.general_subtype == 'true' then 'general' else 'parts'))
+
+    general_subtype_type = @get_general_subtype_type(filtersHash)
+    @set('selectedGeneralSubType', general_subtype_type)

     @set('selectedReviewPhaseId', filtersHash.review_phase_id)
+
+  get_general_subtype_type: (filtersHash) ->
+    if filtersHash.general_subtype == 'true'
+      general_subtype_id = 'general'
+    else if filtersHash.general_subtype == 'false'
+      general_subtype_id = 'parts'
+
+    if general_subtype_id
+      return @get('controllers.events.generalSubTypes')
+        .findBy('id', general_subtype_id)
+
+    return null

   getFilters: ->
     if @get('taxonConceptQueryForDisplay') && @get('taxonConceptQueryForDisplay').length > 0


Generator spec adjustment

Generator spec adjustment

--- test/lib/generator_spec.coffee
+++ test/lib/generator_spec.coffee
@@ -21,8 +21,6 @@
         bozonVersion: "0.3.8",
         electronVersion: "1.2.1",
         name: 'TestApp',
-        platforms: ['linux-x64', 'darwin-x64', 'win32-ia32'],
-        platformsStr: "[\"linux-x64\", \"darwin-x64\", \"win32-ia32\"]",
         year: date.getFullYear()
       })

@@ -53,9 +51,6 @@
       expect($.fileExists('app/javascripts/renderer/application.js')).to.be.true
       expect($.fileExists('app/javascripts/main/index.js')).to.be.true
       expect($.fileExists('app/stylesheets/application.css')).to.be.true
-      expect($.fileExists('app/images/electron.icns')).to.be.true
-      expect($.fileExists('app/images/electron.ico')).to.be.true
-      expect($.fileExists('app/images/electron.png')).to.be.true
       expect($.fileExists('config/settings.json')).to.be.true
       expect($.fileExists('config/environments/development.json')).to.be.true
       expect($.fileExists('config/environments/test.json')).to.be.true
@@ -63,6 +58,8 @@
       expect($.fileExists('config/platforms/osx.json')).to.be.true
       expect($.fileExists('config/platforms/linux.json')).to.be.true
       expect($.fileExists('config/platforms/windows.json')).to.be.true
+      expect($.fileExists('resources/icon.icns')).to.be.true
+      expect($.fileExists('resources/icon.ico')).to.be.true
       expect($.fileExists('spec/helper.js')).to.be.true
       expect($.fileExists('spec/features/main_spec.js')).to.be.true

@@ -73,7 +70,6 @@
       expect($.fileContains('package.json', '"name": "TestApp"')).to.be.true
       expect($.fileContains('package.json', '"version": "0.1.0"')).to.be.true
       expect($.fileContains('package.json', '"electron-prebuilt": "1.2.1"')).to.be.true
-      expect($.fileContains('package.json', '"version": "1.2.1"')).to.be.true

     it 'app package.json should contain actual information', ->
       expect($.fileContains('app/package.json', '"name": "TestApp"')).to.be.true


issue 13 - thanks for esszopo or some code code reviewing :)

--- app/assets/javascripts/helpers/mcclient.coffee
+++ app/assets/javascripts/helpers/mcclient.coffee
@@ -30,14 +30,14 @@
         validationRules[ddlKey]['maxlength'] = actionDdl.input[ddlKey]['maxlength']

       if actionDdl.input[ddlKey]['minlength']
-        validationRules[ddlKey]['minlength'] = actionDdl.input[ddlKey]['maxlength']
+        validationRules[ddlKey]['minlength'] = actionDdl.input[ddlKey]['minlength']

       switch actionDdl.input[ddlKey].type
         when "string" then actionDdl.input[ddlKey]['isString'] = 1
         when "boolean" then actionDdl.input[ddlKey]['isBool'] = 1
         when "integer", "number"
           actionDdl.input[ddlKey]['isInteger'] = 1
-          validationRules[ddlKey]['dataType'] = "number"
+          validationRules[ddlKey]['remote']['dataType'] = "number"

     # when displaying result rows, this is used to make sure the columns
     # align properly (we don't have to rely on the same fields and order)


better comment

better comment

--- src/hooks.coffee
+++ src/hooks.coffee
@@ -37,5 +37,5 @@
     # # called when a promise is resolved into an instance
     # resolution: (chain, instance) ->

-    # called right before a factory is called
+    # called before a factory is called
     # factory: (chain, factory, args) ->


change url for mathjax CDN #1845

change url for mathjax CDN #1845

--- src/smc-webapp/printing.coffee
+++ src/smc-webapp/printing.coffee
@@ -294,7 +294,7 @@

                     <script type="text/javascript">window.MathJax = #{misc.to_json(MathJaxConfig)};</script>
                     <script type="text/javascript" async
-                        src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML">
+                        src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS_HTML">
                     </script>
                 </head>


Fuzzy-filter scores basename matches higher.

Idea stolen from github/github https://github.com/github/github/blob/master/app/assets/javascripts/github/tree_finder.js

--- src/stdlib/fuzzy-filter.coffee
+++ src/stdlib/fuzzy-filter.coffee
@@ -1,10 +1,16 @@
 stringScore = require 'stringscore'

-module.exports = (candidates, query, options) ->
+module.exports = (candidates, query, options={}) ->
   if query
     scoredCandidates = candidates.map (candidate) ->
       string = if options.key? then candidate[options.key] else candidate
-      { candidate, score: stringScore(string, query) }
+      score = stringScore(string, query)
+
+      # Basename matches count for more.
+      unless /\//.test(query)
+        score += stringScore(candidate.replace(/^.*\//,''), query)
+
+      { candidate, score }

     scoredCandidates.sort (a, b) ->
       if a.score > b.score then -1
@@ -13,4 +19,4 @@
     candidates = (scoredCandidate.candidate for scoredCandidate in scoredCandidates when scoredCandidate.score > 0)

   candidates = candidates[0...options.maxResults] if options.maxResults?
-  candidates
+  candidates


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/engine_clear.coffee
+++ src/engine_clear.coffee
@@ -24,7 +24,7 @@
     if I.clear
       I.canvas.clear()
     else if I.background
-      I.background.fill(canvas, ),
+      I.background.fill(canvas, 0, 0, )
     else if I.backgroundColor
       I.canvas.fill(I.backgroundColor)


Track connections and disconnections

Track connections and disconnections

--- src/index.coffee
+++ src/index.coffee
@@ -55,6 +55,14 @@
             if err or !data then return
             log.info "Sending stats"
             io.emit 'stats', data
+
+        # Send number of connected clients
+        # Do this on connection and disconnect
+        log.info  io.sockets.clients().length + 'clients connected'
+        sock.on 'disconnect' ->
+            log.info "Client disconnected"
+            log.info  io.sockets.clients().length + 'clients connected'
+

 # This is a 1 page shop, so just do a catchall
 app.all '/', (req, res) ->


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/engine_mouse.coffee
+++ src/engine_mouse.coffee
@@ -9,7 +9,7 @@
 ###
 Engine.Mouse = (I, self) ->
   self.bind "beforeUpdate", ->
-    # TODO: Make a Gamepad/Keyboard/ input module that has web and XNA
+    # TODO: Make a Gamepad/Keyboard/Mouse input module that has web and XNA
     # implementations
     updateMouse?()


Ensure token exists before opening Chooser link.

--- src/index.coffee
+++ src/index.coffee
@@ -144,18 +144,23 @@

     openDropboxChooserLink =
         'Open Dropbox Chooser'
+
     expose.launchDropBoxChooser = () ->
         slog 'launchDropBoxChooser'
-        Dropbox.choose options =
-            extensions: ['text', '.taskpaper', '.txt', '.ft']
-            success: (files) ->
-                p1 = dbx.sharingGetSharedLinkFile options =
-                    url: files[0].link
-                p1.then (fileData) ->
-                    window.location.hash = fileData.path_lower
-                p1.catch (error) ->
-                    slog 'Error @sharingGetSharedLinkFile'
-                    slog error
+        # Get access token first so we can convert the link to a path later
+        if not dbx.accessToken
+            window.location = dbx.getAuthenticationUrl(location.href.split("#")[0], 'CHOOSE')
+        else
+            Dropbox.choose options =
+                extensions: ['text', '.taskpaper', '.txt', '.ft']
+                success: (files) ->
+                    p1 = dbx.sharingGetSharedLinkFile options =
+                        url: files[0].link
+                    p1.then (fileData) ->
+                        window.location.hash = fileData.path_lower
+                    p1.catch (error) ->
+                        slog 'Error @sharingGetSharedLinkFile'
+                        slog error

     history.pushState(null, null, "##{path}")

@@ -166,9 +171,6 @@
         when 'BLANK', 'NEW', 'DEMO'
             amplify.publish 'outline-ready'
         when 'CHOOSE'
-            # Get access token first so we can convert the link to a path later
-            if not dbx.accessToken
-                window.location = dbx.getAuthenticationUrl(location.href.split("#")[0], 'CHOOSE')
             try
                 launchDropBoxChooser()
             catch e


* update index.coffee

* update index.coffee

--- src/index.coffee
+++ src/index.coffee
@@ -22,7 +22,7 @@
   constructor: (aTypeName, aOptions)->
     # create a new instance object if aOptions is not the original
     # options of the type.
-    if not (this instanceof Type) and not (aTypeName instanceof Type)
+    if not (this instanceof ClassType) and not (aTypeName instanceof ClassType)
       if aTypeName
         if isObject aTypeName
           aOptions = aTypeName


Stop accidentally including all of React in lc-core

--- src/index.coffee
+++ src/index.coffee
@@ -2,7 +2,6 @@
 require './ie_setLineDash'

 LiterallyCanvasModel = require './core/LiterallyCanvas'
-LiterallyCanvasReactComponent = require './reactGUI/LiterallyCanvas'
 defaultOptions = require './core/defaultOptions'

 canvasRenderer = require './core/canvasRenderer'
@@ -15,6 +14,7 @@
 {localize} = require './core/localization'

 # @ifdef INCLUDE_GUI
+LiterallyCanvasReactComponent = require './reactGUI/LiterallyCanvas'
 initReactDOM = require './reactGUI/initDOM'
 require './optionsStyles/font'
 require './optionsStyles/stroke-width'
@@ -115,6 +115,7 @@
   setDefaultImageURLPrefix, defaultTools,
   # @ifdef INCLUDE_GUI
   defineOptionsStyle,
+  LiterallyCanvas: LiterallyCanvasReactComponent,
   # @endif

   defineShape: shapes.defineShape,
@@ -138,6 +139,4 @@
   renderSnapshotToSVG: renderSnapshotToSVG

   localize: localize
-
-  LiterallyCanvas: LiterallyCanvasReactComponent
 }


* [bug] case-insensitive file system can not work

--- src/index.coffee
+++ src/index.coffee
@@ -19,6 +19,9 @@

 fns.caseSensitive = isCaseSensitive = (aPath)->
     t = tmp.fileSync template: path.join aPath, '_tmp-XXXXXXXXX'
-    result = !fs.existsSync t.name.toUpperCase()
+    vDirName  = path.dirname(t.name)
+    vBaseName = path.basename(t.name)
+    vBaseName = vBaseName.toUpperCase()
+    result = !fs.existsSync(path.join(vDirName, vBaseName));
     t.removeCallback()
     result


이름 수정, 디폴트 out callback 에서 에러시 출력.

이름 수정, 디폴트 out callback 에서 에러시 출력.

--- src/index.coffee
+++ src/index.coffee
@@ -41,6 +41,8 @@

 _defaultCallbackFn = (err)->
   if err
+    console.error err
+    console.error err.stack
     throw err

 toss =
@@ -55,20 +57,20 @@
         # debug 'assign', prop, '=', val
     return

-  mixErr: (callback)->
-    return unless callback
-    callback.toss_props = ()->
-      toss.toss_props callback
-
-    callback.err = (nextFn)->
+  mix_toss: (_toss)->
+    return unless _toss
+    _toss.toss_props = ()->
+      toss.toss_props _toss
+
+    _toss.err = (nextFn)->
       return (errMayBe, args...)->
         # debug 'err-to', 'take', arguments
         if _isError errMayBe # Stupid Proof
-          return callback errMayBe, args...
+          return _toss errMayBe, args...
         try
           nextFn errMayBe, args...
         catch err
-          callback err
+          _toss err
   toss_props: (fn)->
     l = {}
     for own prop, val of fn
@@ -194,7 +196,7 @@

       # debug 'tmpCB ', finx, '<', '_toss'
       toss.assign cb_callcheck, _toss
-      toss.mixErr cb_callcheck
+      toss.mix_toss cb_callcheck
       return cb_callcheck

     _toss = (err, tossArgs...)->
@@ -235,7 +237,7 @@
       catch newErr
         err = err or newErr
         _toss err
-    toss.mixErr _toss
+    toss.mix_toss _toss
     debug '_toss',  '<', 'outCallback'
     toss.assign _toss, outCallback
     _toss startErr, args...
@@ -290,7 +292,7 @@
         finished[inx] = true

         callOut()
-      toss.mixErr _cb
+      toss.mix_toss _cb
       inFns.push _cb
       return _cb
     out: (fn)->
@@ -327,13 +329,13 @@
       unless _isArray args
         args = [args]
       # debug 'mk Closure Fn with ', args
-      return (next)->
+      return (_toss)->
         # debug 'inside par', args
-        taskFn args..., (err, results_values...)->
+        taskFn args..., _toss.err (err, results_values...)->
           if results_values.length is 1
             results_values = results_values[0]
           results_array.push results_values
-          next err
+          _toss err

     f = ficent.flow fns
     f (err)->


Towards tool loading in ubret library

Towards tool loading in ubret library

--- src/index.coffee
+++ src/index.coffee
@@ -1 +1,50 @@
-window.Ubret = new Object unless typeof window.Ubret isnt 'undefined'+window.Ubret = new Object unless typeof window.Ubret isnt 'undefined'
+
+Dependencies =
+  "d3":
+    source: "vendor/d3.js"
+  "Leaflet":
+    source: "vendor/leaflet.js"
+  "Events" :
+    source: "ubret/events.js"
+  "BaseTool":
+    source: "ubret/base_tool.js"
+    deps: ["d3"]
+  "Graph" :
+    source: "ubret/graph.js"
+    deps: ["BaseTool"]
+  "Histogram" :
+    source: "ubret/histogram.js"
+    deps: ["Graph"]
+  "Scatterplot" :
+    source: "ubret/scatterplot.js"
+    deps: ["Graph"]
+  "SubjectViewer" :
+    source: "ubret/subject_viewer.js"
+    deps: ["BaseTool"]
+  "Mapper" :
+    source: "ubret/map.js"
+    deps: ["BaseTool", "L"]
+  "Statistics" :
+    source: "ubret/statistics.js"
+    deps: ["BaseTool"]
+  "Table" :
+    source: "ubret/table.js"
+    deps: ["BaseTool"]
+  "Spectra" :
+    source: "ubret/spectra.js"
+    deps: ["BaseTool"]
+
+Ubret.Loader = (tools, cb) ->
+  isScriptLoaded = (script) ->
+    not (typeof window[script] is 'undefined' or typeof Ubret[script] is 'undefined')
+
+  unique = (array) ->
+    uniqueArray = new Array
+    for item in array
+      unless (item in array) or (typeof item is 'undefined')
+        uniqueArray.push item
+    uniqueArray
+
+  dependencies.push Dependencies[tool].deps for tool in tools
+  dependencies = unique dependencies


Changed overload test spec so that it actually test if user passed a signature

Signature is expected to be an array, so we want to check that, checking that array contents is happening in next tests

--- test/spec/overload.spec.coffee
+++ test/spec/overload.spec.coffee
@@ -10,7 +10,7 @@
         ).toThrow()

         expect( ->
-            overloadableFunc.overload [null]
+            overloadableFunc.overload null
         ).toThrow()

         expect( ->
@@ -47,6 +47,7 @@
         expect( ->
             overloadableFunc.overload [/\./], ->
         ).not.toThrow()
+
     it "should accept object arguments", ->
         expect( ->
             overloadableFunc.overload [{}], ->


Add support for testing if an object is of a certain class

Signed-off-by: Ian Macalinao <08370e385f4778cad8fe504ec5445edd3d45bd9a@gmail.com>

--- src/items.coffee
+++ src/items.coffee
@@ -39,9 +39,8 @@

     matches:
       propTypes: ["string"]
-      valTypes: ["object"]
+      valTypes: [RegExp]
       handler: (property, val) ->
-        throw new Error "Argument must be a regular expression!" unless val instanceof RegExp
         val.test property

   ##
@@ -193,29 +192,34 @@
             return false if item[property] isnt matcher

           # It's a query!
+          checkTypes = (types, value) ->
+            valid = false
+            for type in types
+              typeType = typeof type
+              valType = typeof value
+
+              if typeType is "string"
+                if valType is type
+                  valid = true; break
+
+              else if typeType is "function"
+                if value instanceof type
+                  valid = true; break
+
+              else
+                throw new Error "Unknown type '#{type.toString()}' specified in type array!"
+
+            return valid
+
           for handlerName, handler of lol.items._queryHandlers
             if matcher[handlerName]
               # Check if the property is of the right type
-              if handler.propTypes
-                prop = false
-                for type in handler.propTypes
-                  if typeof item[property] is type
-                    prop = true
-                    break
-
-                unless prop
-                  throw new Error "Invalid type for property '#{item[property]}'! Available types are: #{handler.propTypes.join(", ")}"
-
+              if handler.propTypes and not checkTypes handler.propTypes, item[property]
+                throw new Error "Invalid type for property '#{item[property]}'! Available types are: #{handler.propTypes.join(", ")}"
+
               # Check if the handler argument is of the right type for the handler
-              if handler.valTypes
-                val = false
-                for type in handler.valTypes
-                  if typeof matcher[handlerName] is type
-                    val = true
-                    break
-
-                unless val
-                  throw new Error "Invalid type for handler argument '#{matcher[handlerName]}'! Available types are: #{handler.valTypes.join(", ")}"
+              if handler.valTypes and not checkTypes handler.valTypes, matcher[handlerName]
+                throw new Error "Invalid type for handler argument '#{matcher[handlerName]}'! Available types are: #{handler.valTypes.join(", ")}"

               # Does not match filter unless the handler is triggered correctly
               return false unless handler.handler item[property], matcher[handlerName]


Use enemy constructor

Use enemy constructor

--- app/scripts/lib/enemyformations/FlyOver.coffee
+++ app/scripts/lib/enemyformations/FlyOver.coffee
@@ -4,13 +4,13 @@

 class Game.EnemyFormation.FlyOver extends Game.EventHandler

-  constructor: (@level, @enemyType, @callback) ->
+  constructor: (@level, @enemyConstructor, @callback) ->
     super
     @enemiesSpawned = 0
     @enemiesDestroyed = 0
     Crafty.e('Delay').delay(
       =>
-        e = Crafty.e(@enemyType)
+        e = @enemyConstructor(@enemiesSpawned)

         c = [
           length: 1
@@ -72,5 +72,5 @@
         @level.addComponent(e, x: 750, y: 150)
         @enemiesSpawned += 1

-        e.enemy().choreography(c, 0)
+        e.choreography(c, 0)
     , 500, 3)


Delete unused SettingsRestClient

Delete unused SettingsRestClient

--- app/src/restclients/settings_restclient.coffee
+++ app/src/restclients/settings_restclient.coffee
@@ -1,22 +0,0 @@
-
-class ledger.api.SettingRestClient extends ledger.api.RestClient
-
-  @instance: new @
-
-  getAccountBalance: (account, callback) ->
-    account = ledger.wallet.HDWallet.instance.getAccount(account) unless _.isKindOf(account, ledger.wallet.HDWallet.Account)
-    addressesPaths = account.getAllAddressesPaths()
-    accountBalance = {total: 0, confirmed: 0, unconfirmed: 0}
-    ledger.wallet.pathsToAddresses addressesPaths, (addresses) =>
-      _.async.eachBatch _.values(addresses), 20, (addresses, done, hasNext) =>
-        @http().get(
-          url: "blockchain/addresses/#{addresses.join(',')}"
-        ).done( (addressesBalances) ->
-          for addressBalance in addressesBalances
-            accountBalance.total += parseInt(addressBalance.total.balance)
-            accountBalance.confirmed += parseInt(addressBalance.confirmed.balance) if parseInt(addressBalance.confirmed.balance) <= parseInt(addressBalance.total.balance)
-          unless hasNext
-            accountBalance.unconfirmed = accountBalance.total - accountBalance.confirmed
-            callback?(accountBalance)
-          do done
-        ).fail @networkErrorCallback(callback)


clean common.coffee

clean common.coffee

--- app/templates/app/scripts/coffee/common.coffee
+++ app/templates/app/scripts/coffee/common.coffee
@@ -11,39 +11,16 @@
       memo
     ),{}

-  share=($el,type,server,text,image, ga_attr_name="", options={})->
-    title = description = text = encodeURIComponent(text)
-    app_id_fb  = preprocess.social?.fb?.appID
-    host = "#{window.location.protocol}//#{window.location.host}"
-    server = server.replace /#/g,"%23"
-    href = if type is "vk"
-      "http://vk.com/share.php?url=#{server}&image=#{image}&title=#{title}&noparse=true"
-    else if type is "fb"
-      "https://www.facebook.com/dialog/feed?link=#{server}&redirect_uri=https://www.facebook.com&app_id=#{app_id_fb}&picture=#{image}&name=#{title}"
-    else if type is "ok"
-      image = encodeURIComponent(image)
-      url_redirect = encodeURIComponent(options.ok_url or host)
-      "http://www.odnoklassniki.ru/dk?st.cmd=addShare&st._surl=#{url_redirect}"
-    else if type is "tw"
-      "https://twitter.com/intent/tweet?text=#{text}&url=#{server}&original_referer=#{server}"
-    else
-      ""
-    $el.attr {href}
-    if !!ga_attr_name
-      options.type = type
-      if JSON?
-        $el.attr ga_attr_name, JSON.stringify(options)
-
   window.common = common = {
-    app:null
-    router:null
+    app:null  #Application
+    router:null #Router
     urlparams:urlparams
-    images: null
+    images: null #ImagePreloader
     async:-> $.Deferred()
-    api:null
-    sapi:null
-    user:null
-    share:share
+    api:null #ServerApi
+    sapi:null #SocialApi
+    user:null #UserModel
+    ga:null #Google Analitics
     localization: new Localization
   }
   if window.PRELOADER?


Refactor block

Refactor block

--- static/coffee/simulator.coffee
+++ static/coffee/simulator.coffee
@@ -67,13 +67,10 @@
     if media_type
       ele += " media-msg"
     ele += "\">"
-
-    if media_type
-      ele += msg.text
-      if media_viewer_elt
-        ele += media_viewer_elt
-    else
-      ele += msg.text
+    ele += msg.text
+
+    if media_type and media_viewer_elt
+      ele += media_viewer_elt

     ele += "</div>"


fix errant infinite recursion

fix errant infinite recursion

--- bokehjs/src/coffee/renderer/glyph/glyph.coffee
+++ bokehjs/src/coffee/renderer/glyph/glyph.coffee
@@ -59,9 +59,10 @@

       # any additional customization can happen here
       if @_set_data?
-        @set_data()
-
-      len = @[@_fields[0]].length
+        @_set_data()
+
+      # just use the length of the last added field
+      len = @[field].length

       @mask = new Uint8Array(len)
       @selected_mask = new Uint8Array(len)


Add floor and ceiling to stats dialog graphs

--- app/controllers/stats_dialog.coffee
+++ app/controllers/stats_dialog.coffee
@@ -88,12 +88,15 @@
       el: @el.find '.wind-speed .graph'
       x: 'Date': @storm.times
       y: 'kt': @storm.winds
+      floor: 0
+      ceiling: 185

     @pressureGraph = new BarGraph
       el: @el.find '.pressure .graph'
       x: 'Date': @storm.times
       y: 'mb': @storm.pressures
-      floor: Math.floor 0.95 * Math.min @storm.pressures...
+      floor: 870
+      ceiling: 1020

 window.SD = StatsDialog
 module.exports = StatsDialog


Improve end-of-level fade/pause behavior (#664)

--- app/lib/surface/Surface.ozar.coffee
+++ app/lib/surface/Surface.ozar.coffee
@@ -144,7 +144,7 @@
       @handleEvents
     })
     @countdownScreen = new CountdownScreen camera: @camera, layer: @screenLayer, showsCountdown: @world.showsCountdown
-    unless @options.levelType is 'game-dev'
+    if @options.levelType in ['ladder', 'hero-ladder', 'course-ladder']
       @playbackOverScreen = new PlaybackOverScreen camera: @camera, layer: @screenLayer, playerNames: @options.playerNames
       @normalStage.addChildAt @playbackOverScreen.dimLayer, 0  # Put this below the other layers, actually, so we can more easily read text on the screen.
     @initCoordinates()
@@ -341,11 +341,13 @@
   setPaused: (paused) ->
     # We want to be able to essentially stop rendering the surface if it doesn't need to animate anything.
     # If pausing, though, we want to give it enough time to finish any tweens.
+    clearTimeout @surfacePauseTimeout if @surfacePauseTimeout
+    clearTimeout @surfaceZoomPauseTimeout if @surfaceZoomPauseTimeout
+    return if @options.levelType in ['game-dev']
+    return unless @handleEvents  # Don't do this within the level editor
     performToggle = =>
       createjs.Ticker.framerate = if paused then 1 else @options.frameRate
       @surfacePauseTimeout = null
-    clearTimeout @surfacePauseTimeout if @surfacePauseTimeout
-    clearTimeout @surfaceZoomPauseTimeout if @surfaceZoomPauseTimeout
     @surfacePauseTimeout = @surfaceZoomPauseTimeout = null
     if paused
       @surfacePauseTimeout = _.delay performToggle, 2000
@@ -375,10 +377,10 @@
     )

     if (not @world.indefiniteLength) and @lastFrame < @world.frames.length and @currentFrame >= @world.totalFrames - 1
+      @updatePaths()  # TODO: this is a hack to make sure paths are on the first time the level loads
       @ended = true
       @setPaused true
       Backbone.Mediator.publish 'surface:playback-ended', {}
-      @updatePaths()  # TODO: this is a hack to make sure paths are on the first time the level loads
     else if @currentFrame < @world.totalFrames and @ended
       @ended = false
       @setPaused false


Restricts wizard to level bounds when moving around

--- app/lib/surface/WizardSprite.coffee
+++ app/lib/surface/WizardSprite.coffee
@@ -120,10 +120,19 @@

     @shoveOtherWizards(true) if @targetSprite
     @targetSprite = if isSprite then newTarget else null
-    @targetPos = targetPos
+    @targetPos = @boundWizard targetPos
     @beginMoveTween(duration, isLinear)
     @shoveOtherWizards()
     Backbone.Mediator.publish('self-wizard:target-changed', {sender:@}) if @isSelf
+
+  boundWizard: (target) ->
+    # Passed an {x, y} in world coordinates, returns {x, y} within world bounds
+    return target unless @options.camera.bounds
+    @bounds = @options.camera.bounds
+    surfaceTarget = @options.camera.worldToSurface target
+    x = Math.min(Math.max(surfaceTarget.x, @bounds.x), @bounds.x + @bounds.width)
+    y = Math.min(Math.max(surfaceTarget.y, @bounds.y), @bounds.y + @bounds.height)
+    return @options.camera.surfaceToWorld {x: x, y: y}

   getPosFromTarget: (target) ->
     """


Eliminate EditSession references from tokenized-buffer-spec

--- spec/app/tokenized-buffer-spec.coffee
+++ spec/app/tokenized-buffer-spec.coffee
@@ -4,7 +4,7 @@
 _ = require 'underscore'

 describe "TokenizedBuffer", ->
-  [editSession, tokenizedBuffer, buffer, changeHandler] = []
+  [tokenizedBuffer, buffer, changeHandler] = []

   beforeEach ->
     atom.activatePackage('javascript.tmbundle', sync: true)
@@ -18,15 +18,14 @@

   describe "when the buffer contains soft-tabs", ->
     beforeEach ->
-      editSession = project.buildEditSession('sample.js', autoIndent: false)
-      buffer = editSession.buffer
-      tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
-      editSession.setVisible(true)
-      changeHandler = jasmine.createSpy('changeHandler')
-      tokenizedBuffer.on "changed", changeHandler
+      buffer = project.bufferForPath('sample.js')
+      tokenizedBuffer = new TokenizedBuffer(buffer)
+      tokenizedBuffer.setVisible(true)
+      tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')

     afterEach ->
-      editSession.destroy()
+      tokenizedBuffer.destroy()
+      buffer.release()

     describe "on construction", ->
       it "initially creates un-tokenized screen lines, then tokenizes lines chunk at a time in the background", ->
@@ -299,21 +298,20 @@
   describe "when the buffer contains hard-tabs", ->
     beforeEach ->
       atom.activatePackage('coffee-script-tmbundle', sync: true)
-      tabLength = 2
-      editSession = project.buildEditSession('sample-with-tabs.coffee', { tabLength })
-      buffer = editSession.buffer
-      tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
-      editSession.setVisible(true)
+      buffer = project.bufferForPath('sample-with-tabs.coffee')
+      tokenizedBuffer = new TokenizedBuffer(buffer)
+      tokenizedBuffer.setVisible(true)

     afterEach ->
-      editSession.destroy()
+      tokenizedBuffer.destroy()
+      buffer.release()

     describe "when the buffer is fully tokenized", ->
       beforeEach ->
         fullyTokenize(tokenizedBuffer)

       it "renders each tab as its own atomic token with a value of size tabLength", ->
-        tabAsSpaces = _.multiplyString(' ', editSession.getTabLength())
+        tabAsSpaces = _.multiplyString(' ', tokenizedBuffer.tabLength)
         screenLine0 = tokenizedBuffer.lineForScreenRow(0)
         expect(screenLine0.text).toBe "# Econ 101#{tabAsSpaces}"
         { tokens } = screenLine0
@@ -332,11 +330,10 @@
       atom.activatePackage('ruby.tmbundle', sync: true)
       atom.activatePackage('ruby-on-rails-tmbundle', sync: true)

-      editSession = project.buildEditSession()
-      editSession.setVisible(true)
-      editSession.setGrammar(syntax.selectGrammar('test.erb'))
-      editSession.buffer.setText("
<%= User.find(2).full_name %>
")
-      tokenizedBuffer = editSession.displayBuffer.tokenizedBuffer
+      buffer = project.bufferForPath(null, "
<%= User.find(2).full_name %>
")
+      tokenizedBuffer = new TokenizedBuffer(buffer)
+      tokenizedBuffer.setGrammar(syntax.selectGrammar('test.erb'))
+      tokenizedBuffer.setVisible(true)
       fullyTokenize(tokenizedBuffer)

       {tokens} = tokenizedBuffer.lineForScreenRow(0)


Get correct informations

Get correct informations

--- server/lib/server/index.coffee
+++ server/lib/server/index.coffee
@@ -307,7 +307,7 @@
 console.log '[WEBSERVER] running', "http://localhost:#{webPort} pid:#{process.pid}"

 kontrolRegister = () ->
-  {host, port, protocol, login, password, vhost, heartbeat} = kontrold
+  {host, port, protocol, login, password, vhost, heartbeat} = kontrold.rabbitmq
   port              ?= 5672
   protocol          ?= 'amqp:'
   options           = {host, port, protocol} # but not vhost, because of a bug in node-amqp


Restore theme find!

Restore theme find!

--- server/test/units/theme.coffee
+++ server/test/units/theme.coffee
@@ -96,6 +96,8 @@

     assert.ok themeSpy.calledOnce, "Expected Theme.find to be called once"
     assert.ok themeSpy.calledWith(filter), "Expected Theme.find to be called with the filter"
+
+    themeSpy.restore()
     done()
   )
 )


Remove unnecessary import

Remove unnecessary import

--- app/assets/javascripts/app.js.coffee
+++ app/assets/javascripts/app.js.coffee
@@ -7,7 +7,6 @@
 #= require custom-bootstrap.js.coffee
 #= require function
 #= require map-overlay.js
-#= require language_picker_styling.js
 #= require handlebars
 #= require ember
 #= require ember-data


Add Monday as first day of the week

Add Monday as first day of the week

--- app/assets/javascripts/custom.coffee
+++ app/assets/javascripts/custom.coffee
@@ -1,12 +1,16 @@
 $(document).on "turbolinks:load", ->
-  $('div.calendar').calendar()
+  $('div.calendar').calendar
+    firstDayOfWeek: 1
+
   $('.calendar_range_start').calendar
     endCalendar: $('.calendar_range_end'),
-    type: 'date'
+    type: 'date',
+    firstDayOfWeek: 1

   $('.calendar_range_end').calendar
     startCalendar: $('.calendar_range_start'),
-    type: 'date'
+    type: 'date',
+    firstDayOfWeek: 1

   $('.ui.accordion').accordion()
   $('.ui.dropdown').dropdown


Fixes some error with file name display, icons

--- app/assets/javascripts/upload.coffee
+++ app/assets/javascripts/upload.coffee
@@ -367,8 +367,12 @@
   renderOptimization = (file) ->
     $('#multiple-files-selected').hide()
     $('#files-merge').hide()
-    $("#userManuscriptMetadata").text(file.name+"("+formatBytes(file.size)+")")
+    name= file.name
+    if file.name == undefined
+      name =[f.name for f in filez].join(".")
+    $("#userManuscriptMetadata").text(name+"("+formatBytes(file.size)+")")
     # rerender all
+    $("#removeUserManuscript").hide()
     $('#userManuscript-status').show(400)
     $('#file-size-correct').hide()
     $('#file-size-way-too-big').hide()
@@ -400,8 +404,8 @@
     if $("#file-permission-checkbox").is(":checked")
       #Upload blob
       formData = new FormData()
-      file = document.getElementById('upload-userManuscript').files[0]
-      formData.append("file", result, file.name)
+      name =[f.name for f in filez].join(".")
+      formData.append("file", result, name)
       xhr = new XMLHttpRequest()
       xhr.open('POST', '/submissions/upload', true)
       xhr.onload =  () ->
@@ -524,9 +528,9 @@
             )
           else
             $('#userManuscript-uploadButton-call').prop('disabled',false)
-            file = document.getElementById('upload-userManuscript').files[0]
+            name =[f.name for f in filez].join(".")
             $("#userManuscriptMetadata").text(
-              file.name + "(" + formatBytes(result.size) + ")"
+              name + "(" + formatBytes(result.size) + ")"
             )
             $('#userManuscript-uploadButton-call')
               .removeClass('btn-outline-secondary')
@@ -545,6 +549,9 @@

   $('#upload-userManuscript').change () ->
     $('input[type="submit"]').prop('disabled',true)
+    filez = Array.prototype.slice.call(
+        document.getElementById('upload-userManuscript').files
+      )
     if this.files.length > 1
       $('#userManuscript-status').show(400)
       $('#multiple-files-selected').show()
@@ -553,9 +560,6 @@
       $('#file-size-way-too-big').hide()
       $('#file-size-too-big').hide()
       $('#file-optimize').hide()
-      filez = Array.prototype.slice.call(
-        document.getElementById('upload-userManuscript').files
-      )
       renderMultipleFiles()
     else
       renderOptimization(this.files[0])


Remove some ss add buttons; fix datum updates

Fixes #3593

--- app/assets/volume/spreadsheet.coffee
+++ app/assets/volume/spreadsheet.coffee
@@ -133,6 +133,7 @@
             not: 'No ' + (if Top then 'materials' else 'sessions')
             template: if Top then ['name'] else ['name', 'date', 'release']
             sort: -10000
+            fixed: true
           0:
             id: 0
             name: 'record'
@@ -144,6 +145,7 @@
             not: 'No files'
             template: ['name', 'classification', 'excerpt']
             sort: 10000
+            fixed: true
         constants.deepFreeze(pseudoCategory)
         getCategory = (c) ->
           pseudoCategory[c || 0] || constants.category[c]
@@ -393,12 +395,14 @@
               start: si
             }
           $scope.cols = Cols
-          if Editing
+          if Editing && Key.id == 'slot'
             ### jshint ignore:start #### fixed in jshint 2.5.7
             $scope.categories = (c for ci, c of constants.category when ci not of Data)
             ### jshint ignore:end ###
             $scope.categories.sort(bySortId)
             $scope.categories.push(pseudoCategory[0]) unless 0 of Data
+          else
+            $scope.categories = []
           return

         # Call all populate functions
@@ -775,7 +779,7 @@
         updateDatum = (info, v) ->
           info.v = v
           rcm = Data[info.c][info.metric.id]
-          if info.c == Key.c || info.c == 'asset'
+          if info.c == Key.id || info.c == 'asset'
             rcm[info.n][info.i] = v
             generateText(info)
           else


smarter error reporting

smarter error reporting

--- app/server/methods/generators.coffee
+++ app/server/methods/generators.coffee
@@ -118,11 +118,14 @@
               console.log("wkhtmltopdf:", data)

             toPdf.stderr.setEncoding('utf8');
+            toPdfStderr = ""
             toPdf.stderr.on 'data', (data) ->
-              console.log("wkhtmltopdf error:", data)
+              toPdfStderr += data

             toPdf.on 'close', (code) ->
               console.log("wkhtmltopdf exit:", code)
+              if code isnt 0
+                console.log("wkhtmltopdf error:", toPdfStderr)

       else
         console.log("generatedBid: Could not generate html for bid. id:#{id}")


replaced empty callback with undefined

replaced empty callback with undefined

--- test/async/page.coffee
+++ test/async/page.coffee
@@ -120,8 +120,8 @@
             test = this
             if _.isEqual options.mode,['mixed', 'args']
               # need to pass a callback in this mode
-              page.set 'onConsoleMessage', ((msg) -> test.callback null, msg), ->
-              page.evaluate (-> console.log "Hello, world!"), ->
+              page.set 'onConsoleMessage', ((msg) -> test.callback null, msg), undefined
+              page.evaluate (-> console.log "Hello, world!"), undefined
             else
               page.set 'onConsoleMessage', ((msg) -> test.callback null, msg)
               page.evaluate (-> console.log "Hello, world!")


Optimize a bit

Optimize a bit


deep copy article in case of multiple ref_dates

--- app/scripts/controllers/main.coffee
+++ app/scripts/controllers/main.coffee
@@ -28,13 +28,14 @@
                 a_day = ref_date.date[2]
                 article['reference_date'] = new Date a_year, a_month, a_day
                 article['snippet'] = ref_date.extract if ref_date.extract?
+                article.pub_date = new Date article.pub_date
                 if a_month is monthDigit
                   if a_day is day
-                    $scope.days.push article
+                    $scope.days.push angular.copy article
                   else if not a_day?
-                    $scope.month.push article
+                    $scope.month.push angular.copy article
                 else if not a_month?
-                  $scope.year.push article
+                  $scope.year.push angular.copy article
         $scope.active  = -1
         $scope.article = null
         $scope.previewStyle = ->


Use feed option.

Use feed option.

--- scripts/chat-logger.coffee
+++ scripts/chat-logger.coffee
@@ -233,7 +233,8 @@
       author:
         name: robot.name
         link: base_url
-      link: "#{base_url}/#{req.params.room}/feed"
+      link: "#{base_url}/#{req.params.room}"
+      feed: "#{base_url}/#{req.params.room}/feed"
     if chat_data()[req.params.room]?
       list_feed_item(req.params.room).forEach (v) -> feed.addItem v
     res.type 'application/atom+xml'


TerminalSession: rollbar logging is removed for broker connection error

--- client/Main/troubleshoot/brokerrecovery.coffee
+++ client/Main/troubleshoot/brokerrecovery.coffee
@@ -35,8 +35,6 @@
     @broker.disconnect no
     brokerURL = @broker.sockURL.replace("/subscribe", "")
     @broker.selectAndConnect [brokerURL]
-    # log while changing and send alert
-    KD.logToExternal "broker connection error", broker : brokerURL

   recover: (callback) ->


Flux: Environment: Fix collaboration machines "workspace" problem

--- client/app/lib/flux/environment/actions.coffee
+++ client/app/lib/flux/environment/actions.coffee
@@ -1,8 +1,13 @@
 kd                      = require 'kd'
-environmentDataProvider = require 'app/userenvironmentdataprovider'
 actions                 = require './actiontypes'
 getters                 = require './getters'
 Promise                 = require 'bluebird'
+Machine                 = require 'app/providers/machine'
+environmentDataProvider = require 'app/userenvironmentdataprovider'
+sinkrow                 = require 'sinkrow'
+showError               = require 'app/util/showError'
+remote                  = require('app/remote').getInstance()
+

 _bindMachineEvents = (environmentData) ->

@@ -52,13 +57,20 @@
         _bindMachineEvents data

     if environmentDataProvider.hasData() and not isPayloadUsed
-      isPayloadUsed = yes
+      isPayloadUsed   = yes
+      environmentData = environmentDataProvider.get()
+
+      # If there are any collaboration machines, fetch all machines data from server.
+      # Because `_globals` doesn't give workspace data of collaboration machines.
+      # Ping @senthil for the best solution.
+      if environmentData.collaboration.length
+        return environmentDataProvider.fetch (data) -> kallback null, data
+
       return kd.utils.defer ->
-        environmentData = environmentDataProvider.get()
         environmentDataProvider.revive()
         kallback null, environmentData

-    environmentDataProvider.fetch kallback
+    environmentDataProvider.fetch (data) -> kallback null, data

 loadStacks = ->


sort by success rate for gateblu device installs

--- client/components/gateblu-device-installs.cjsx
+++ client/components/gateblu-device-installs.cjsx
@@ -16,7 +16,7 @@
     @gatebluDeviceInstalls.on 'change', =>
       @setState
         isFetching: false
-        devices: @gatebluDeviceInstalls.toJSON().devices
+        devices: _.sortBy @gatebluDeviceInstalls.toJSON().devices, 'successPercentage'

   componentDidMount: ->


Support multiple localstorages with different versions in LocalStorageController

--- client/landing/app/MainApp/LocalStorage.coffee
+++ client/landing/app/MainApp/LocalStorage.coffee
@@ -38,12 +38,12 @@
     super
     @localStorages = {}

-  storage:(appName, version)->
-
-    if @localStorages[appName]?
-      storage = @localStorages[appName]
+  storage:(appName, version = "1.0")->
+    key = "#{appName}-{version}"
+    if @localStorages[key]?
+      storage = @localStorages[key]
     else
-      storage = @localStorages[appName] = new LocalStorage appName, version
+      storage = @localStorages[key] = new LocalStorage appName, version

     return storage


Assign Google API configuration

Assign Google API configuration

--- client/landing/site.landing/coffee/main.coffee
+++ client/landing/site.landing/coffee/main.coffee
@@ -41,6 +41,7 @@
   KD.config.hasTeamAccess = kookies.get('team-access')?
   KD.config.groupName     = groupName = KD.utils.getGroupNameFromLocation()
   KD.config.recaptcha     = window._runtimeOptions.recaptcha
+  KD.config.google        = window._runtimeOptions.google

   if groupName is 'koding'
   then setGroup()


Reflect error on failure to update

Reflect error on failure to update

--- client/src/controllers/admin_controller.coffee
+++ client/src/controllers/admin_controller.coffee
@@ -11,6 +11,21 @@

   $el.css('background-color', '#7BAB3C')
   $el.css('border-color', '#7BAB3C')
+  $el.css('color', '#FFF')
+
+  setTimeout(->
+    $el.text(oldText)
+    $el.removeAttr('style')
+  , 1000)
+
+reflectError = (el) ->
+  $el = $(el)
+
+  oldText = $el.text()
+  $el.text("Error")
+
+  $el.css('background-color', '#E37100')
+  $el.css('border-color', '#E37100')
   $el.css('color', '#FFF')

   setTimeout(->
@@ -73,8 +88,9 @@
       $(spinnerEl).replaceWith(@)
       reflectSuccess(@)

-    error: (err) ->
-      $("##{id}.action-or-response").text "Failed"
+    error: (err) =>
+      $(spinnerEl).replaceWith(@)
+      reflectError(@)
       console.log "Message from remote server for #{id}: #{err.responseText}"

 reloadIndicatorDefinition = (ev) ->


Queueing for scoring models - checkpoint PP-10

--- client/src/scripts/model-selection-view.coffee
+++ client/src/scripts/model-selection-view.coffee
@@ -31,19 +31,31 @@

     _predicate predicate unless _predicate() is predicate

+  runScoringJobs = (jobs) ->
+    queue = copy jobs
+    runNext = ->
+      job = shift queue
+      if job
+        console.log "Queue size #{queue.length}/#{jobs.length}"
+        job.run -> defer runNext
+    defer runNext
+
   scoreModels = ->
     frameKey = _predicate().frameKey
-    forEach _selections(), (selection) ->
+    runScoringJobs map _selections(), (selection) ->
       modelKey = selection.data.key
-      selection.status 'running'
-      _.requestScoringOnFrame frameKey, modelKey, (error, result) ->
-        data = if error then error.data else result
-        selection.status data.response.status
-        selection.time data.response.time
-        selection.result error or result
+      selection.status 'waiting'
+      run: (go) ->
+        selection.status 'running'
+        _.requestScoringOnFrame frameKey, modelKey, (error, result) ->
+          data = if error then error.data else result
+          selection.status data.response.status
+          selection.time data.response.time
+          selection.result error or result
+          do go

   clearSelected = ->
-    _selections []
+    _selections.removeAll()
     _.deselectAllModels()


further tweaks for batches chart tooltip

--- app/assets/javascripts/batches.coffee
+++ app/assets/javascripts/batches.coffee
@@ -32,23 +32,27 @@
 tooltipTemplate = Handlebars.compile """

-    {{when}}
+    {{batchName}}
+

+

+    Date
+    {{when}}

   {{#if passed}}

       Passed
-      {{passed}}
+      {{passed}}

   {{/if}}
   {{#if failed}}

       Failed
-      {{failed}}
+      {{failed}}

   {{/if}}

     Total
-    {{total}}
+    {{total}}

 """
@@ -62,6 +66,7 @@
     date = passes[item.dataIndex][0]
     tooltipText = tooltipTemplate
       when: formatDateAndTime(date)
+      batchName: batchName
       passed: passCount
       failed: failCount
       total: passCount + failCount


fix ordering of conditions to address a possible null access

Former-commit-id: b0bd60ea3ef8fea72ace928c5dc63f876b72a0ea [formerly ca82cf89aad6fecfdca506942057ce6d25215a1a] [formerly ccf1709c1746dcc0c35870c77714da5445b21c46 [formerly ccf1709c1746dcc0c35870c77714da5445b21c46 [formerly 931233921935fb5b389e04fada2f6b0a59c3b94c]]]
Former-commit-id: 54bdee3ebaa80c768a39a7c4563f50a29d114de6 [formerly af8a06bdbd384445326b98b978f65798e96a2928]
Former-commit-id: a014040ede8c6bd360e8290e29afcae1bca0cf80
Former-commit-id: 042b399d5d6ef866b455403d4ad41147a24a4ec8

--- app/assets/javascripts/main.js.coffee
+++ app/assets/javascripts/main.js.coffee
@@ -139,7 +139,7 @@
   ConsiderIt.app.usermanagerview.handle_third_party_callback(parameters)

 window.pollLoginPopup = ->
-  if window.location.origin == window.openidpopup.location.origin && window.openidpopup? && window.openidpopup.open_id_params?
+  if window.openidpopup? && window.location.origin == window.openidpopup.location.origin && window.openidpopup.open_id_params?
     window.handleOpenIdResponse(window.openidpopup.open_id_params)
     window.openidpopup.close()
     window.openidpopup = null


fix #1511

fix #1511

--- app/coffee/modules/issues/list.coffee
+++ app/coffee/modules/issues/list.coffee
@@ -508,14 +508,14 @@

         showFilters = (title, type) ->
             $el.find(".filters-cats").hide()
-            $el.find(".filter-list").addClass("hidden")
+            $el.find(".filter-list").removeClass("hidden")
             $el.find("h2.breadcrumb").removeClass("hidden")
             $el.find("h2 a.subfilter span.title").html(title)
             $el.find("h2 a.subfilter span.title").prop("data-type", type)

         showCategories = ->
             $el.find(".filters-cats").show()
-            $el.find(".filter-list").removeClass("hidden")
+            $el.find(".filter-list").addClass("hidden")
             $el.find("h2.breadcrumb").addClass("hidden")

         initializeSelectedFilters = (filters) ->
@@ -552,7 +552,9 @@
                 return null

             filters = $scope.filters[type]
-            filter = _.find(filters, {id: taiga.toString(id)})
+            filterId = if type == 'tags' then taiga.toString(id) else id
+            filter = _.find(filters, {id: filterId})
+
             filter.selected = (not filter.selected)

             # Convert id to null as string for properly


:bug: Prevent access to undefined lines in updates

It seems we are not guaranteed that all lines exists when updating the
minimap. This patch protect against access to an undefined line class
list.

Fix #95

--- lib/minimap-editor-view.coffee
+++ lib/minimap-editor-view.coffee
@@ -63,7 +63,7 @@

     if @firstRenderedScreenRow? and line >= @firstRenderedScreenRow and line <= @lastRenderedScreenRow
       index = line - @firstRenderedScreenRow - 1
-      @lines.children()[index].classList.add(cls)
+      @lines.children()[index]?.classList.add(cls)

   removeLineClass: (line, cls) ->
     if @lineClasses[line] and (index = @lineClasses[line].indexOf cls) isnt -1
@@ -71,7 +71,7 @@

     if @firstRenderedScreenRow? and line >= @firstRenderedScreenRow and line <= @lastRenderedScreenRow
       index = line - @firstRenderedScreenRow - 1
-      @lines.children()[index].classList.remove(cls)
+      @lines.children()[index]?.classList.remove(cls)

   removeAllLineClasses: (classesToRemove...) ->
     for k,classes of @lineClasses
@@ -249,7 +249,7 @@

         for lineElement in @editorView.buildLineElementsForScreenRows(row, dirtyRangeEnd)
           classes = @lineClasses[row+1]
-          lineElement.classList.add(classes...) if classes?
+          lineElement?.classList.add(classes...) if classes?
           @lines[0].insertBefore(lineElement, currentLine)
           row++
       else


refactoring includer

refactoring includer

--- src/lib/includer.coffee
+++ src/lib/includer.coffee
@@ -90,8 +90,7 @@
             continue if subModel not instanceof BaseModel
             continue if subModel.included()

-            includer = new Includer(subModel, @options)
-            promises.push includer.include()
+            promises.push subModel.include(@options)

         return Promise.all(promises).then =>
             if @entityPoolCreated


Check if package is loaded before activating config

--- lib/package-detail-view.coffee
+++ lib/package-detail-view.coffee
@@ -62,7 +62,8 @@

   activate: ->
     # Package.activateConfig() is part of the Private package API and should not be used outside of core.
-    @pack.activateConfig() if not atom.packages.isPackageActive(@pack.name)
+    if atom.packages.isPackageLoaded(@pack.name) and not atom.packages.isPackageActive(@pack.name)
+      @pack.activateConfig()

   detached: ->
     @unsubscribe()


Remove unused requires

Remove unused requires

--- lib/package-keymap-view.coffee
+++ lib/package-keymap-view.coffee
@@ -1,4 +1,4 @@
-{$$, $$$, _, View} = require 'atom'
+{$$$, View} = require 'atom'

 # Displays the keybindings for a package namespace
 module.exports =


Fixed Camera Motion Bug

Fixed Camera Motion Bug

--- js/camera.coffee
+++ js/camera.coffee
@@ -21,10 +21,10 @@
       @rotation = ((@rotation%(Math.PI*2))+(Math.PI*2))%(Math.PI*2)
       @scale *= 1 + @ZOOM_SPEED * deltaTime if Keyboard.isDown 88
       @scale *= 1 - @ZOOM_SPEED * deltaTime if Keyboard.isDown 90
-      @offset = @offset.add new Vector(@PAN_SPEED * deltaTime, 0) if Keyboard.isDown 65
-      @offset = @offset.add new Vector(0, @PAN_SPEED * deltaTime) if Keyboard.isDown 87
-      @offset = @offset.add new Vector(-@PAN_SPEED * deltaTime, 0) if Keyboard.isDown 68
-      @offset = @offset.add new Vector(0, -@PAN_SPEED * deltaTime) if Keyboard.isDown 83
+      @offset = @offset.add new Vector(@PAN_SPEED * deltaTime * Math.cos(@rotation), -@PAN_SPEED * deltaTime * Math.sin(@rotation)) if Keyboard.isDown 65
+      @offset = @offset.add new Vector(@PAN_SPEED * deltaTime * Math.sin(@rotation), @PAN_SPEED * deltaTime * Math.cos(@rotation)) if Keyboard.isDown 87
+      @offset = @offset.add new Vector(-@PAN_SPEED * deltaTime * Math.cos(@rotation), @PAN_SPEED * deltaTime * Math.sin(@rotation)) if Keyboard.isDown 68
+      @offset = @offset.add new Vector(-@PAN_SPEED * deltaTime * Math.sin(@rotation), -@PAN_SPEED * deltaTime * Math.cos(@rotation)) if Keyboard.isDown 83
       @offset = Wheel.getOffset().multiply(deltaTime).add(@offset)

     render: (context, width, height) ->
@@ -32,7 +32,6 @@
       context.translate width/2, height/2
       context.rotate @rotation
       context.scale @scale, @scale
-      context.translate -width/2, -height/2
       context.translate @offset.x, @offset.y

     reset: (context) ->


fixed button for Office 365

fixed button for Office 365

--- app/assets/javascripts/mno_enterprise/angular/services/maestrano-apps-list-helper.js.coffee
+++ app/assets/javascripts/mno_enterprise/angular/services/maestrano-apps-list-helper.js.coffee
@@ -265,7 +265,9 @@
         instance.stack == 'connector' && instance.app_nid == 'myob' && !instance.oauth_keys_valid

       isOauthConnectBtnShown: (instance) ->
-        instance.stack == 'connector' && !instance.oauth_keys_valid
+        instance.app_nid != 'office-365' &&
+        instance.stack == 'connector' &&
+        !instance.oauth_keys_valid

       connectToQuickBooks: (instance) ->
         instance.status = 'updating'


show file name

show file name

--- js/chrome.coffee
+++ js/chrome.coffee
@@ -18,7 +18,9 @@
     Weya elem: @elems.toolbar, context: this, ->
      @$.elems.folder = @i ".fa.fa-folder-open", on: {click: @$.on.folder}
      @$.elems.open = @i ".fa.fa-file", on: {click: @$.on.file}
-     @$.elems.save = @i ".fa.fa-save", on: {click: @$.on.save}
+     @$.elems.save = @span ->
+      @i ".fa.fa-save", on: {click: @$.on.save}
+      @$.elems.saveName = @span ""

     @elems.save.style.display = 'none'

@@ -74,6 +76,7 @@
      file: chrome.fileSystem.retainEntry entry

     @elems.save.style.display = 'inline-block'
+    @elems.saveName.textContent = entry.name
     @file = entry
     entry.file (file) =>
      reader = new FileReader()


needed these other filters for location functionality

--- src/model-filter.coffee
+++ src/model-filter.coffee
@@ -60,3 +60,56 @@

   urlEncoded: () ->
     encodeURI @asXml()
+
+models.filters = {}
+class models.filters.BaseFilter extends Backbone.Model
+  filterObj: null
+
+  initialize: (params, options) ->
+    @set "version", options.version or "1.1.0"
+
+  asXml: () ->
+    xml = new OpenLayers.Format.XML()
+    writer = new OpenLayers.Format.Filter
+      version: @get "version"
+    xml.write writer.write @filterObj
+
+  urlEncoded: () ->
+    encodeURI @asXml()
+
+class models.filters.PropertyFilter extends models.filters.BaseFilter
+  initialize: (parameters) ->
+    # Parameters should be array [ propertyName, value ]
+    @filterObj = new OpenLayers.Filter.Comparison
+      type: OpenLayers.Filter.Comparison.EQUAL_TO
+      property: parameters[0]
+      value: parameters[1]
+
+class models.filters.RangeFilter extends models.filters.BaseFilter
+  initialize: (parameters) ->
+    # parameters should be arra [ propertyName, [ lowerBound, upperBound ] ]
+    @filterObj = new OpenLayers.Filter.Comparison
+      type: OpenLayers.Filter.Comparison.BETWEEN
+      property: parameters[0]
+      lowerBoundary: parameters[1][0]
+      upperBoundary: parameters[1][1]
+
+class models.filters.BBoxFilter extends models.filters.BaseFilter
+  initialize: (parameters) ->
+    # parameters should be array [ propertyName, [left, bottom, right, top] ]
+    @filterObj = new OpenLayers.Filter.Spatial
+      type: OpenLayers.Filter.Spatial.BBOX
+      property: parameters[0]
+      value: new OpenLayers.Bounds parameters[1][0], parameters[1][1], parameters[1][2], parameters[1][3]
+
+class models.filters.AndFilter extends models.filters.BaseFilter
+  initialize: (filters) ->
+    @filterObj = new OpenLayers.Filter.Logical
+      type: OpenLayers.Filter.Logical.AND
+      filters: ( f.filterObj for f in filters )
+
+class models.filters.OrFilter extends models.filters.BaseFilter
+  initialize: (filters) ->
+    @filterObj = new OpenLayers.Filter.Logical
+      type: OpenLayers.Filter.Logical.OR
+      filters: ( f.filterObj for f in filters )


FIX: Changed find -> filter

FIX: Changed find -> filter

--- src/scripts/singularity.coffee
+++ src/scripts/singularity.coffee
@@ -109,13 +109,14 @@

                 taskDetails = JSON.parse body
                 host = taskDetails.offer.hostname
-
-                portsResource = taskDetails.mesosTask.resources.find (r) ->
+                portsResource = taskDetails.mesosTask.resources.filter (r) ->
                   r.name == 'ports'

-                if (portsResource and portsResource.ranges.range)
-                  port = portsResource.ranges.range[0].begin;
+                if (portsResource[0] and portsResource[0].ranges.range)
+                  port = portsResource[0].ranges.range[0].begin;
                   msg.send "Task started on '#{host}:#{port}' at #{new Date(task.taskId.startedAt)} with id: '#{task.taskId.id}'"
+                else
+                  msg.send "Task started on '#{host}' at #{new Date(task.taskId.startedAt)} with id: '#{task.taskId.id}'"
         catch error
           msg.send "Ran into an error parsing JSON :"
           msg.send error


status metrics

status metrics

--- src/model/statsd.coffee
+++ src/model/statsd.coffee
@@ -53,6 +53,7 @@
     var i = 0;
     //_.forEach(raw, function *(item) {
       data.push({
+        _id : {"channelID": channelId },
         failed: raw.data[0][0],
         successful: raw.data1[0][0]
       });


Remove no execution mode available info span

--- lib/terminal-panel-view.coffee
+++ lib/terminal-panel-view.coffee
@@ -52,11 +52,6 @@
     stopExecutionLinkSpan.textContent = 'Stop'
     @stopExecutionLink.appendChild stopExecutionLinkSpan
     @executionControls.appendChild @stopExecutionLink
-
-    @noExecutionModeAvailableInfo = document.createElement 'span'
-    @noExecutionModeAvailableInfo.className = 'text-subtle'
-    @noExecutionModeAvailableInfo.textContent = '(no execution mode available)'
-    @executionControls.appendChild @noExecutionModeAvailableInfo

     cg = document.createElement 'div'
     cg.className = 'control-group'
@@ -241,11 +236,9 @@
       if @activeLanguage.isExecutable()
         @startExecutionLink.style.display = ''
         @stopExecutionLink.style.display = 'none'
-        @noExecutionModeAvailableInfo.style.display = 'none'
       else
         @startExecutionLink.style.display = 'none'
         @stopExecutionLink.style.display = 'none'
-        @noExecutionModeAvailableInfo.style.display = ''

   onDidChangeFontSize: =>
     fontSize = parseInt(@fontSizeSelect.value)
@@ -313,15 +306,12 @@
     if isExecuting
       @startExecutionLink.style.display = 'none'
       @stopExecutionLink.style.display = ''
-      @noExecutionModeAvailableInfo.style.display = 'none'
     else
       @stopExecutionLink.style.display = 'none'
       if @activeLanguage.isExecutable()
         @startExecutionLink.style.display = ''
-        @noExecutionModeAvailableInfo.style.display = 'none'
       else
         @startExecutionLink.style.display = 'none'
-        @noExecutionModeAvailableInfo.style.display = ''

   show: ->
     unless @bottomPanel?


Stop loading when modal opened

Stop loading when modal opened

--- app/js/jail_iframe/util/create.coffee
+++ app/js/jail_iframe/util/create.coffee
@@ -1,6 +1,7 @@
 FactlinkJailRoot.createFactFromSelection = (current_user_opinion) ->
   success = ->
     window.document.getSelection().removeAllRanges()
+    FactlinkJailRoot.createButton.stopLoading()
     FactlinkJailRoot.createButton.hide()
     FactlinkJailRoot.off 'modalOpened', success


allow for feed to be filtered by tutorials and discussions

--- client/landing/app/Applications/Activity.kdapplication/views/activityinnernavigation.coffee
+++ client/landing/app/Applications/Activity.kdapplication/views/activityinnernavigation.coffee
@@ -38,8 +38,9 @@
         { title : "Everything" }
         { title : "Status Updates",   type : "CStatusActivity" }
         { title : "Code Snippets",    type : "CCodeSnipActivity" }
+        { title : "Discussions",      type : "CDiscussionActivity" }
+        { title : "Tutorials",        type : "CTutorialActivity" }
         { title : "Q&A",              type : "qa",disabledForBeta : yes }
-        { title : "Discussions",      type : "CDiscussionActivity", disabledForBeta : yes  }
         { title : "Links",            type : "CLinkActivity", disabledForBeta : yes }
         # { title : "Code Shares",      type : "codeshare", disabledForBeta : yes }
         # { title : "Commits",          type : "commit", disabledForBeta : yes }


Revised time parse failure policy in Punch#parseRaw

--- src/models/punch.coffee
+++ src/models/punch.coffee
@@ -101,9 +101,12 @@
                             'MM/DD/YYYY hh:mm:ss a',
                             constants.TIMEZONE)
         if not newDate or
-           not newDate.isValid() or
-           not newDate.isSame(date, 'day')
-          newDate = moment.tz("#{row[headers.today]} #{newDate.format('hh:mm:ss a')}",
+           not newDate.isValid()
+          timePiece = moment.tz(row[headers[MODES[i]]],
+                                'hh:mm:ss a',
+                                constants.TIMEZONE)
+
+          newDate = moment.tz("#{row[headers.today]} #{row[headers[MODES[i]]]}",
                               'MM/DD/YYYY hh:mm:ss a',
                               constants.TIMEZONE)
         datetimes.push newDate.tz(tz)
@@ -113,6 +116,8 @@
       datetimes.block = block
     else if datetimes.length is 2
       elapsed = _calculateElapsed datetimes[0], datetimes[1], mode, user
+      if elapsed < 0
+        Logger.error 'Elapsed time is less than 0', new Error(datetimes)

     foundProjects = []
     for i in [1..6]


making checkboxcolumn working when grid is not editable

--- app/assets/javascripts/netzke-extension/selection_column.js.coffee
+++ app/assets/javascripts/netzke-extension/selection_column.js.coffee
@@ -24,8 +24,11 @@
         if this.selected.items.indexOf(record) == -1
           this.select record, true
         else this.deselect record
+        #this is a stub needed for selecting for read-only grid
+        old_view_ready = view.viewReady
         view.viewReady = true
         view.refreshNode recordIndex
+        view.viewReady = old_view_ready
       false
     else @callParent arguments
   renderer: (value, metaData, record, rowIndex, colIndex, store, view)->


fixed view name

fixed view name

--- app/assets/javascripts/species/views/taxon_concepts_view.js.coffee
+++ app/assets/javascripts/species/views/taxon_concepts_view.js.coffee
@@ -1,2 +1,2 @@
-Species.ResultsView = Ember.View.extend
+Species.TaxonConceptsView = Ember.View.extend
   templateName: 'species/taxon_concepts'


Index of an enumerable starts at 0 for JS.

--- app/assets/javascripts/sprangular/directives/creditCardForm.coffee
+++ app/assets/javascripts/sprangular/directives/creditCardForm.coffee
@@ -5,7 +5,7 @@
     creditCard: '='
   controller: ($scope, $locale) ->
     $scope.months = _.map $locale.DATETIME_FORMATS.MONTH, (month, index) ->
-      {"index": index, "name": month}
+      {"index": index + 1, "name": month}

     currentYear = (new Date).getFullYear()
     $scope.years = [currentYear .. currentYear+15]


Fix #183

Fix #183

 - Use more certain mime-type check
 - File extension now always is lowercase

--- files.coffee
+++ files.coffee
@@ -1089,7 +1089,7 @@
   ###
   _getExt: (fileName) ->
     if !!~fileName.indexOf('.')
-      extension = fileName.split('.').pop().split('?')[0]
+      extension = (fileName.split('.').pop().split('?')[0] or '').toLowerCase()
       return { ext: extension, extension, extensionWithDot: '.' + extension }
     else
       return { ext: '', extension: '', extensionWithDot: '' }
@@ -1116,12 +1116,12 @@
           size: data.size
           type: data.type
           extension: data.extension
-      isVideo: !!~data.type.toLowerCase().indexOf('video')
-      isAudio: !!~data.type.toLowerCase().indexOf('audio')
-      isImage: !!~data.type.toLowerCase().indexOf('image')
-      isText:  !!~data.type.toLowerCase().indexOf('text')
-      isJSON:  !!~data.type.toLowerCase().indexOf('json')
-      isPDF:   !!~data.type.toLowerCase().indexOf('pdf')
+      isVideo: /^video\//i.test data.type
+      isAudio: /^audio\//i.test data.type
+      isImage: /^image\//i.test data.type
+      isText:  /^text\//i.test data.type
+      isJSON:  /application\/json/i.test data.type
+      isPDF:   /application\/pdf|application\/x-pdf/i.test data.type
       _storagePath:    data._storagePath or @storagePath
       _downloadRoute:  data._downloadRoute or @downloadRoute
       _collectionName: data._collectionName or @collectionName


Overall fixes

Overall fixes

 - Don’t force `attachment` on non-download requests
 - Better in-code docs
 - Return original file if `version` is not exists

--- files.coffee
+++ files.coffee
@@ -624,10 +624,9 @@

     if Meteor.isServer
       resp = @response
-
       if self.currentFile
-        if _.has self.currentFile, 'versions'
-          fileRef = if not version or version is 'original' or not _.has self.currentFile.versions, version then {path: self.currentFile.path, size: self.currentFile.size} else self.currentFile.versions[version]
+        if _.has(self.currentFile, 'versions') and _.has self.currentFile.versions, version
+          fileRef = self.currentFile.versions[version]
         else
           fileRef = self.currentFile
       else
@@ -638,14 +637,13 @@
           console.info "======================|404|======================"
           console.info @request.headers

+        text = "File Not Found :("
         resp.writeHead 404,
-          "Content-Type": "text/plain"
-        resp.write "File Not Found :("
-        resp.end()
+          'Content-Length': text.length
+          'Content-Type':   "text/plain"
+        resp.end text

       else if self.currentFile
-
-
         if self.debug
           console.info "======================|Headers for: #{self.currentFile.path}|======================"
           console.info @request.headers
@@ -658,8 +656,7 @@
             'Content-Encoding':     'binary'
             'Content-Disposition':  "attachment; filename=\"#{encodeURI self.currentFile.name}\"; charset=utf-8"
             'Content-Length':       fileRef.size
-          resp.write file
-          resp.end()
+          resp.end file

         else if @params.query.play and @params.query.play == 'true'
           if @request.headers.range
@@ -713,7 +710,7 @@
             'Cache-Control':        self.cacheControl
             'Content-Type':         fileRef.type
             'Content-Encoding':     'binary'
-            'Content-Disposition':  "attachment; filename=\"#{encodeURI(self.currentFile.name)}\"; charset=utf-8"
+            'Content-Disposition':  "filename=\"#{encodeURI(self.currentFile.name)}\"; charset=utf-8"
             'Content-Length':       fileRef.size
           stream.pipe resp

@@ -728,6 +725,7 @@
   @class Meteor.Files
   @name link
   @param {Object} fileRef - File reference object
+  @param {String} version - [Optional] Version of file you would like to request
   @description Returns link
   @returns {String}
   ###
@@ -741,8 +739,14 @@

 if Meteor.isClient
   ###
+  @client
+  @TemplateHelper
+  @name fileURL
+  @param {Object} fileRef - File reference object
+  @param {String} version - [Optional] Version of file you would like to request
   @description Get download URL for file by fileRef, even without subscription
   @example {{fileURL fileRef}}
+  @returns {String}
   ###
   Template.registerHelper 'fileURL', (fileRef, version) ->
     version = if not _.isString version then 'original' else version


more cleanup

more cleanup

--- js/src/KryptnosticObject.coffee
+++ js/src/KryptnosticObject.coffee
@@ -10,7 +10,8 @@

   #
   # Chunked and encrypted representation of a document.
-  # Operations using instance methods do not mutate the object, but rather return a new instance.
+  # Decryption does not mutate the object, but rather returns a new instance.
+  #
   # Author: rbuckheit
   #
   class KryptnosticObject
@@ -26,10 +27,9 @@
     # decrypt object using a cryptoService
     decrypt : (cryptoService) ->
       if @isEncrypted(this)
-        chunkingStrategyUri   = @body.data.chunkingStrategy
-        chunkingStrategyClass = ChunkingStrategyRegistry.get(chunkingStrategyUri)
+        decryptedBlocks       = @body.data.map((chunk) -> cryptoService.decrypt(chunk.block))
+        chunkingStrategyClass = ChunkingStrategyRegistry.get(@body.data.chunkingStrategy)
         chunkingStrategy      = new chunkingStrategyClass()
-        decryptedBlocks       = @body.data.map((chunk) -> cryptoService.decrypt(chunk.block))
         data                  = chunkingStrategy.join(decryptedBlocks)
         raw                   = _.extend({}, _.cloneDeep(this), {body: {data}})
         return new KryptnosticObject(raw)


return undefined for missing pub keys

return undefined for missing pub keys

--- js/src/http/DirectoryApi.coffee
+++ js/src/http/DirectoryApi.coffee
@@ -126,6 +126,8 @@
         envelope = response.data
         log.debug('getPublicKey', { envelope })
         return new PublicKeyEnvelope(envelope)
+      .catch (e) ->
+        return undefined

     # gets the user's encrypted salt.
     # request is not wrapped because the user has not auth'ed yet.


Make sure when going back to root (the startPage) that transition is always back.

--- js/flight.coffee
+++ js/flight.coffee
@@ -3,6 +3,7 @@
   pageHistory: []
   currentPage: ''
   targetPage: ''
+  startPage: ''

   isTransitioning: false
   menuOpen: false
@@ -53,6 +54,10 @@
     @isTransitioning = true
     @menuOpen = false

+    if @pageHistory.length is 1 and window.location.hash is @startPage
+      @back = true
+      @pageHistory.pop()
+
     if @pageHistory.length > 1 and window.location.hash is @pageHistory[@pageHistory.length - 2]
       @back = true


Clean up button test.

Clean up button test.

--- js/flight.coffee
+++ js/flight.coffee
@@ -123,15 +123,13 @@

 window.flight = new Flight();

-backBtn = document.querySelector('.back')
-
 #backBtn.addEventListener 'touchstart', ->
 #  flight.slideTransition('#panel-1','#panel-2','0.4s',true)
-backBtn.addEventListener 'click', ->
+$('.back').click (e) =>
     flight.goToPage('#panel-2')

 $('.forward').click (e) =>
-  flight.slideTransition('#panel-1','#panel-2','0.4s',false)
+  flight.goToPage('#panel-1')

 #if 'ontouchstart' in window


Port change 7010 => 7015

Port change 7010 => 7015

--- SingularityUI/app/env.coffee
+++ SingularityUI/app/env.coffee
@@ -1,3 +1,3 @@
 module.exports =
     env: 'local'
-    SINGULARITY_BASE: 'http://heliograph.iad01.hubspot-networks.net:7010'
+    SINGULARITY_BASE: 'http://heliograph.iad01.hubspot-networks.net:7015'


rounded sunset down by half a minute

rounded sunset down by half a minute

--- js/mincha.coffee
+++ js/mincha.coffee
@@ -25,7 +25,7 @@
   start_eating_at

 mincha_time = (zmanim, hebrew_date) ->
-  sunset = moment(zmanim.sunset)
+  sunset = moment(zmanim.sunset).subtract('second', 30)
   if hebrew_date.isShabbat()
     $('.rabbenu-tam').html(moment(sunset).add('minute', 73).format('h:mm'))
     $('.begin-seudat-shelishit-before').html(sunset.format('h:mm')) unless hebrew_date.isErebYomTob() || hebrew_date.is1stDayOfYomTob()


Explicitly return

Explicitly return

--- scripts/models/content/inherits/base.coffee
+++ scripts/models/content/inherits/base.coffee
@@ -17,7 +17,8 @@
           @_loading = @fetch()
         @_loading.done () =>
           @trigger('loaded')
-      @_loading
+
+      return @_loading

     toJSON: () ->
       json = super()


Known failure mode

Known failure mode

--- test/spec/test_reactive.coffee
+++ test/spec/test_reactive.coffee
@@ -81,7 +81,8 @@
       elt = rxt.svg_tags.rect {
         x: 10
         y: 20
-      }, bind -> [
+      }
+      ###, bind -> [
         rxt.svg_tags.animatetransform {
           attributeName: 'transform'
           begin: '0s'
@@ -91,7 +92,7 @@
           to: '360 60 60'
           repeatCount: 'indefinite'
         }
-      ]
+      ]###

     it 'should have the right tag', ->
       expect(elt).toBeDefined()


Remove console logging

Remove console logging

--- assets/javascripts/application.coffee
+++ assets/javascripts/application.coffee
@@ -46,7 +46,6 @@
   $('.add-symbol-wrapper').toggleClass('visible')

 $('.stock-list li').click ->
-  console.log 'hi'
   $(@).toggleClass('show-drawer')

 window.bindEvents =  ->


Unnecessary fat arrow removed

Unnecessary fat arrow removed

--- frontend/app/assets/javascripts/spree/frontend/checkout/payment.js.coffee
+++ frontend/app/assets/javascripts/spree/frontend/checkout/payment.js.coffee
@@ -67,7 +67,7 @@
             async: false,
             method: "PUT",
             url: url,
-            success: (data) =>
+            success: (data) ->
               coupon_code_field.val('')
               coupon_status.addClass("alert-success").html(Spree.translations.coupon_code_applied)
               coupon_applied = true


Fix file selector filter when clicking entry uploader

--- resources/assets/coffee/react/contest/entry/uploader.coffee
+++ resources/assets/coffee/react/contest/entry/uploader.coffee
@@ -29,12 +29,26 @@
     @setState state: state

   componentDidMount: =>
+    switch @props.contest.type
+      when 'art'
+        allowedExtensions = ['.jpg', '.jpeg', '.png']
+        maxSize = 4000000
+
+      when 'beatmap'
+        allowedExtensions = ['.osu']
+        maxSize = 1000000
+
+      when 'music'
+        allowedExtensions = ['.mp3']
+        maxSize = 15000000
+
+
     $dropzone = $('.js-contest-entry-upload--dropzone')
     $uploadButton = $ '<input>',
       class: 'js-contest-entry-upload fileupload__input'
       type: 'file'
       name: 'entry'
-      accept: '.osu'
+      accept: allowedExtensions.join(',')
       disabled: @props.disabled

     $(@refs.uploadButtonContainer).append($uploadButton)
@@ -56,21 +70,9 @@
         return if @props.disabled

         file = data.files[0];
+        extension = /(\.[^.]+)$/.exec(file.name)[1]

-        switch @props.contest.type
-          when 'beatmap'
-            allowedExtensions = /\.osu$/i
-            maxSize = 1000000
-
-          when 'art'
-            allowedExtensions = /\.(jpg|jpeg|png)$/i
-            maxSize = 4000000
-
-          when 'music'
-            allowedExtensions = /\.mp3$/i
-            maxSize = 15000000
-
-        if !(allowedExtensions).test(file.name)
+        if $.inArray(extension, allowedExtensions) < 0
           osu.popup osu.trans("contest.entry.wrong_type.#{@props.contest.type}"), 'danger'
           return


Fix for missing path include in #560

Fix for missing path include in #560

--- server/lib/importer.coffee
+++ server/lib/importer.coffee
@@ -3,6 +3,7 @@
 log = require('printit')
     prefix: null
     date: true
+path = require 'path'

 Konnector = require '../models/konnector'
 localization = require './localization_manager'


Publication updates

Publication updates

--- server/publications.coffee
+++ server/publications.coffee
@@ -3,15 +3,3 @@

 Meteor.publish "patients", ->
     Patients.find() if authorizedUser @userId
-
-Meteor.publish "observations", (patientId) ->
-    Observations.find patientId: patientId if authorizedUser @userId
-
-Meteor.publish "observationFiles", (patientId) ->
-    ObservationFiles.find "metadata.patientId": patientId if authorizedUser @userId
-
-Meteor.publish "observationDetail", (observationId) ->
-    Observations.find _id: observationId if authorizedUser @userId
-
-Meteor.publish "observationDetailFiles",  (observationId) ->
-    ObservationFiles.find "metadata.observationId": observationId if authorizedUser @userId


OX-586 removed test-assertion

OX-586 removed test-assertion

--- app/assets/javascripts/main.coffee
+++ app/assets/javascripts/main.coffee
@@ -65,5 +65,3 @@
           platform : navigator.platform
       log: $.proxy(console.warn, console)
     )
-
-    $.assert(false, "MSG", {})


took out the cam2d stuff

took out the cam2d stuff

--- app/assets/javascripts/view.coffee
+++ app/assets/javascripts/view.coffee
@@ -6,7 +6,7 @@

 # global View variables
 cam = null
-cam2d = null
+#cam2d = null

 #constants
 CAM_DISTANCE = 140
@@ -64,7 +64,7 @@
     # calculate which pixel are visible on the trianglesplane
     # after moving around.
     cam = new Flycam CAM_DISTANCE
-    cam2d = new Flycam2d CAM_DISTANCE
+    #cam2d = new Flycam2d CAM_DISTANCE

     # FPS stats
     stats = new Stats()
@@ -83,7 +83,7 @@

     # refresh the scene once a bucket is loaded
     # FIXME: probably not the most elgant thing to do
-    $(window).on("bucketloaded", => cam.hasChanged = true; cam2d.hasChanged = true)
+    $(window).on("bucketloaded", => cam.hasChanged = true)

   animate : ->
     @renderFunction()
@@ -100,8 +100,8 @@
     # ATTENTION: this limits the FPS to 30 FPS (depending on the keypress update frequence)
     if cam.hasChanged is false
       return
-    if cam2d.hasChanged is false
-      return
+    #if cam2d.hasChanged is false
+    #  return

     @updateTrianglesplane()

@@ -112,7 +112,7 @@
     @stats.update()

     cam.hasChanged = false
-    cam2d.hasChanged = false
+    #cam2d.hasChanged = false
     @rendererxy.render @scenexy, @cameraxy
     @rendereryz.render @sceneyz, @camerayz
     @rendererxz.render @scenexz, @cameraxz
@@ -174,7 +174,7 @@
   draw : ->
     #FIXME: this is dirty
     cam.hasChanged = true
-    cam2d.hasChanged = true
+    #cam2d.hasChanged = true

   setMatrix : (matrix) ->
     cam.setMatrix(matrix)
@@ -232,7 +232,7 @@
         # why z? keep in mind the plane is rotated 90°
         g.scale.x = g.scale.z = x
         cam.hasChanged = true
-        cam2d.hasChanged = true
+        #cam2d.hasChanged = true

   zoomIn : ->
     if cam.getZoomStep() > 0


finished configuring layer types

finished configuring layer types

--- app/coffeescripts/menu-data.coffee
+++ app/coffeescripts/menu-data.coffee
@@ -71,26 +71,27 @@

 # Layers Menu
 $a.layers_node_type_list = [
-       { label: 'Freeway Nodes', event: 'toggleVisabilty', triggerShow: "map:nodes:show_freeway", triggerHide: "map:nodes:hide_freeway" }
-       { label: 'Highway Nodes',  event: ((e) -> alert('Not Configured'))  }
+       { label: 'Freeway', event: 'toggleVisabilty', triggerShow: "map:nodes:show_freeway", triggerHide: "map:nodes:hide_freeway" }
+       { label: 'Highway',   event: 'toggleVisabilty', triggerShow: "map:nodes:show_highway", triggerHide: "map:nodes:hide_higway"  }
        { label: 'Signalized Intersections', event: 'toggleVisabilty', triggerShow: "map:nodes:show_signalized_intersection", triggerHide: "map:nodes:hide_signalized_intersection"  }
-       { label: 'Stop Intersections',  event: ((e) -> alert('Not Configured')) }
+       { label: 'Simple', event: 'toggleVisabilty', triggerShow: "map:nodes:show_simple", triggerHide: "map:nodes:hide_simple" }
+       { label: 'Stop Intersections',   event: 'toggleVisabilty', triggerShow: "map:nodes:show_stop_intersection", triggerHide: "map:nodes:hide_stop_intersection"  }
        { label: 'Terminals', event: 'toggleVisabilty', triggerShow: "map:nodes:show_terminal", triggerHide: "map:nodes:hide_terminal"  }
-       { label: 'Other', event: 'toggleVisabilty', triggerShow: "map:nodes:show_simple", triggerHide: "map:nodes:hide_simple"  }
+       { label: 'Other', event: 'toggleVisabilty', triggerShow: "map:nodes:show_other", triggerHide: "map:nodes:hide_other"  }
      ]

 $a.layers_link_type_list = [
+      { label: 'Elec. toll coll. lanes', event: 'toggleVisabilty', triggerShow: "map:links:show_electric_toll", triggerHide: "map:links:hide_electric_toll" }
       { label: 'Freeway mainlines', event: 'toggleVisabilty', triggerShow: "map:links:show_freeway", triggerHide: "map:links:hide_freeway"  }
       { label: 'Highway mainlines', event: 'toggleVisabilty', triggerShow: "map:links:show_highway", triggerHide: "map:links:hide_highway"  }
+      { label: 'Heavy vehicle lanes', event: 'toggleVisabilty', triggerShow: "map:links:show_heavy_vehicle", triggerHide: "map:links:hide_heavy_vehicle" }
       { label: 'HOV lanes', event: 'toggleVisabilty', triggerShow: "map:links:show_hov", triggerHide: "map:links:hide_hov"  }
       { label: 'HOT lanes', event: 'toggleVisabilty', triggerShow: "map:links:show_hot", triggerHide: "map:links:hide_hot"  }
-      { label: 'Heavy vehicle lanes', event: ((e) -> alert('Not Configured'))  }
-      { label: 'Elec. toll coll. lanes',  event: ((e) -> alert('Not Configured'))   }
+      { label: 'Interconnects', event: 'toggleVisabilty', triggerShow: "map:links:show_freeway_connector", triggerHide: "map:links:hide_freeway_connector" }
+      { label: 'Intersection Approach', event: 'toggleVisabilty', triggerShow: "map:links:show_intersection_approach", triggerHide: "map:links:hide_intersection_approach" }
       { label: 'On-ramps', event: 'toggleVisabilty', triggerShow: "map:links:show_onramp", triggerHide: "map:links:hide_onramp"  }
       { label: 'Off-ramps', event: 'toggleVisabilty', triggerShow: "map:links:show_offramp", triggerHide: "map:links:hide_offramp"  }
-      { label: 'Interconnects', event: 'toggleVisabilty', triggerShow: "map:links:show_freeway_connector", triggerHide: "map:links:hide_freeway_connector" }
       { label: 'Streets', event: 'toggleVisabilty', triggerShow: "map:links:show_street", triggerHide: "map:links:hide_street"  }
-      { label: 'Dummy links', event: ((e) -> alert('Not Configured')) }
     ]

 $a.layers_menu = [


move require work from index

move require work from index

--- lib/add-listeners.coffee
+++ lib/add-listeners.coffee
@@ -1,4 +1,8 @@
-
+multiplexor  = require './multiplex'
+eventor      = require './eventor'
+jsonify      = require './jsonify'
+authenticator= require './authenticate-client'
+transformer  = require './transformer'

 module.exports = (options, socket, whichEvents) ->


exec: remove console.log

exec: remove console.log

--- lib/commands/exec.coffee
+++ lib/commands/exec.coffee
@@ -21,15 +21,16 @@
       connection.port ?= 22
       connection.private_key_location ?= '~/.ssh/id_rsa'
       connect connection, (err, ssh) ->
-        return util.print "\x1b[31m#{err.message}\x1b[39m\n" if err
+        write = (msg) -> process.stdout.write msg
+        return write "\x1b[31m#{err.message}\x1b[39m\n" if err
         exec ssh, params.subcommand, (err, stdout, stderr) ->
-          util.print if err
+          write if err
           then "\x1b[31m#{server.host} (exit code #{err.code})\x1b[39m\n"
           else "\x1b[32m#{server.host}\x1b[39m\n"
-          util.print "\n" if stdout.length or stderr.length
-          util.print "\x1b[36m#{stdout.trim()}\x1b[39m\n" if stdout.length
-          util.print "\x1b[35m#{stderr.trim()}\x1b[39m\n" if stderr.length
-          util.print "\n"
+          write "\n" if stdout.length or stderr.length
+          write "\x1b[36m#{stdout.trim()}\x1b[39m\n" if stdout.length
+          write "\x1b[35m#{stderr.trim()}\x1b[39m\n" if stderr.length
+          write "\n"
           ssh.end()
     .on 'both', (err) ->
       # Done


bring result to foreground on click

bring result to foreground on click

--- lib/editor/result.coffee
+++ lib/editor/result.coffee
@@ -3,7 +3,6 @@

 module.exports =
 class Result
-
   fadeIn: ->
     @view.classList.add 'ink-hide'
     @timeout 20, =>
@@ -19,6 +18,10 @@
     # @view.style.pointerEvents = 'auto'
     @view.addEventListener 'mousewheel', (e) ->
       e.stopPropagation()
+    # clicking on it will bring the current result to the top of the stack
+    @view.addEventListener 'click', =>
+      @view.parentNode.parentNode.appendChild @view.parentNode
+
     @disposables.add atom.commands.add @view,
       'inline-results:clear': (e) => @remove()
     fade and @fadeIn()


pref improvements (BROKEN!)

pref improvements (BROKEN!)

--- lib/editor/result.coffee
+++ lib/editor/result.coffee
@@ -1,5 +1,5 @@
 # TODO: better scrolling behaviour
-{throttle} = require 'underscore-plus'
+{throttle, debounce} = require 'underscore-plus'
 {$, $$} = require 'atom-space-pen-views'
 {CompositeDisposable, Emitter} = require 'atom'
 trees = require '../tree'
@@ -34,6 +34,8 @@
 metrics = throttle metrics, 60*60*1000

 resizer = ResizeDetector strategy: "scroll"
+
+debouncedUpdateWidth = (res, el) -> debounce(((res, el) -> res.updateWidth(el)), 200)

 module.exports =
 class Result
@@ -130,7 +132,7 @@
       when 'block' then mark.type = 'block'; mark.position = 'after'
     @decoration = @editor.decorateMarker @marker, mark
     if @type == 'inline'
-      setTimeout (=> resizer.listenTo @editor.editorElement, => @updateWidth()), 50
+      resizer.listenTo @editor.editorElement, ((el) => debouncedUpdateWidth(this, el))()

   initMarker: ->
     @marker = @editor.markBufferRange @lineRange(@start, @end)
@@ -138,11 +140,10 @@
     @decorateMarker()
     @disposables.add @marker.onDidChange (e) => @checkMarker e

-  updateWidth: ->
-    elRect = @editor.editorElement.getBoundingClientRect()
-    if not @view.parentElement? then return
-    w = elRect.width + elRect.left - 40 -
-        @view.parentElement.getBoundingClientRect().left
+  updateWidth: (el) ->
+    elRect = el.getBoundingClientRect()
+    if not @view.offsetParent? then return
+    w = elRect.width + elRect.left - 40 - @view.offsetParent.offsetLeft
     if w < 100 then w = 100
     @view.style.maxWidth = w + 'px'


Function-based node.js exports excluded from methods list

--- lib/entities/file.coffee
+++ lib/entities/file.coffee
@@ -26,7 +26,7 @@
       if node.entities?
         for entity in node.entities
           if entity instanceof Method
-            @methods.push entity
+            @methods.push(entity) if entity.name.length > 0
           if entity instanceof Variable
             @variables.push entity
           if entity instanceof Mixin


make compileContext asynchronous

make compileContext asynchronous

--- library/membrane/visual.coffee
+++ library/membrane/visual.coffee
@@ -71,7 +71,7 @@
     # implementation for greater understanding of what it does exactly.
     # The resulting value is a string with compiled JavaScript code.
     # Uses `cheerio` library (jQuery for server) to do the rendering.
-    compileContext: (context) ->
+    compileContext: (context, callback) ->
         assert _.isObject $ = cheerio.load "<!DOCTYPE html>"
         assert $.root().append html = $ "<html>" # set a root
         xs = (src) -> rel: "stylesheet", href: src.toString()
@@ -89,7 +89,7 @@
         ha(xr($("<script>"), r)) for r in context.scripts
         ha(xo($("<script>"), jstr o)) for o in javascript
         $('script[type*="javascript"]:empty').remove()
-        dom($.root().get(0).children).toString()
+        return callback dom($.root().get(0).children)

     # This is an internal routine that performs a very important task
     # of deploying the context onto the call (client) site. It also
@@ -240,9 +240,10 @@
             context.inline -> this.externals.push "eco"
             context.inline -> assert @broadcast = ->
                 this.root.emit.apply $root, arguments
-            context = @compressContext context if asm
-            compiled = @compileContext context if asm
-            return receive context, compiled or null
+            return receive context, null unless asm
+            assert context = @compressContext context
+            this.compileContext context, (compiled) ->
+                return receive context, compiled
         return prelude symbol, context, request

     # An internally used routine, part of the context assembly proc.


implement session var expansion

implement session var expansion

--- library/nucleus/restful.coffee
+++ library/nucleus/restful.coffee
@@ -150,7 +150,9 @@
         assert mw = @constructor.middleware().bind this
         prestreamer = @upstreamAsync "preprocess", =>
             mw([request, response, variables...]) (error) =>
-                this[method] request, response, variables...
+                assert expanded = _.clone variables or []
+                expanded.push request.session or undefined
+                this[method] request, response, expanded...
                 poststreamer = @upstreamAsync "postprocess"
                 poststreamer request, response, variables...
         prestreamer request, response, variables...


Disabled debugging.

Disabled debugging.

--- app/assets/javascripts/app/lib/ajax.js.coffee
+++ app/assets/javascripts/app/lib/ajax.js.coffee
@@ -40,7 +40,7 @@
     else
       $.ajax( data )

-    console.log('AJAX', params['url'] )
+#    console.log('AJAX', params['url'] )

   _show_spinner: =>
     @count++


make option component value = the option text

--- app/assets/javascripts/components/option.cjsx
+++ app/assets/javascripts/components/option.cjsx
@@ -4,4 +4,4 @@
   displayName: 'Option'

   render: ->
-    <option value={@props.option_index}>{@props.option_text}</option>+    <option value={@props.option_text}>{@props.option_text}</option>


fix #4 , increasing flash message timeout by 2 seconds

--- app/assets/javascripts/shared/flash.js.coffee
+++ app/assets/javascripts/shared/flash.js.coffee
@@ -1,4 +1,4 @@
 $ ->
   if $('#flash')
     $('#flash').slideDown(500)
-    window.setTimeout (-> $('#flash').slideUp 500), 5000+    window.setTimeout (-> $('#flash').slideUp 500), 7000


Fixed user select failing tests on merge request

--- app/assets/javascripts/users_select.js.coffee
+++ app/assets/javascripts/users_select.js.coffee
@@ -221,7 +221,7 @@
         multiple: $(select).hasClass('multiselect')
         minimumInputLength: 0
         query: (query) =>
-          @users query.term, false, (users) =>
+          @users query.term, @projectId?, (users) =>
             data = { results: users }

             if query.term.length == 0


Only set open click event if element is trigger

--- source/javascripts/jquery.windoze.js.coffee
+++ source/javascripts/jquery.windoze.js.coffee
@@ -180,7 +180,8 @@
         .on('open.windoze', $.proxy(@showAll, @))
         .on('close.windoze', $.proxy(@hideAll, @))
         .on('destroy.windoze', $.proxy(@teardown, @))
-      @$el.on('click.windoze', @delegate, $.proxy(@showAll, @))
+      if !@$el.is('.wdz-modal')
+        @$el.on('click.windoze', @delegate, $.proxy(@showAll, @))
       !@init_shown && @$el.trigger('close.windoze')
       @$el