consider non-barre positions too

consider non-barre positions too

--- lib/fretboard_logic.coffee
+++ lib/fretboard_logic.coffee
@@ -21,7 +21,7 @@
     cache[name] = fn.call(this)

 class Fingering
-  constructor: ({@positions, @chord}) ->
+  constructor: ({@positions, @chord, @barres}) ->
     @positions.sort (a, b) -> a.string - b.string

   @cached_getter 'fretstring', ->
@@ -55,6 +55,15 @@
       subsumption_count: m[1].match(/x/g).length
   barres

+find_barre_sets = (positions) ->
+  powerset = (xs) ->
+    return [[]] unless xs.length
+    [x, xs...] = xs
+    tail = powerset xs
+    tail.concat([x].concat(ys) for ys in tail)
+  barres = find_barres positions
+  return powerset barres
+
 finger_positions_on_chord = (chord) ->
   positions = []
   fretboard_positions_each (pos) ->
@@ -87,7 +96,9 @@
       for n in frets for right in following_finger_positions)...)

   generate_fingerings = ->
-    (new Fingering {positions, chord} for positions in collect_fingering_positions(frets_per_string))
+    _.flatten(new Fingering {positions, chord, barres} \
+      for barres in find_barre_sets(positions) \
+      for positions in collect_fingering_positions(frets_per_string))

   chord_note_count = chord.pitch_classes.length

@@ -109,31 +120,34 @@
     return fingering.fretstring.match(/x$/)

   finger_count = (fingering) ->
-    fingering.barres ||= find_barres(fingering.positions)
-    n = (pos for pos in fingering.positions when pos.fret).length
+    n = (pos for pos in fingering.positions when pos.fret > 0).length
     n -= barre.subsumption_count for barre in fingering.barres
     n

-  few_fingers = (fingering) ->
+  four_fingers_or_fewer = (fingering) ->
     return finger_count(fingering) <= 4

   cmp = (fn) -> (x...) -> !fn(x...)

+  # Construct the filter set
+
   filters = [
-    {name: 'has all chord notes', filter: has_all_notes},
-    {name: 'no muted medial strings', filter: cmp(muted_medial_strings)},
-    {name: 'no muted treble strings', filter: cmp(muted_treble_strings)},
-    {name: 'no more than four fingers', filter: few_fingers}
+    {name: 'four fingers or fewer', filter: four_fingers_or_fewer}
   ]

-  unless options.filter
-    filters = [{name: 'has all chord notes', filter: has_all_notes}]
+  if options.filter
+    filters.push name: 'has all chord notes', filter: has_all_notes

+  unless options.fingerpicking
+    filters.push name: 'no muted medial strings', filter: cmp(muted_medial_strings)
+    filters.push name: 'no muted treble strings', filter: cmp(muted_treble_strings)
+
+  # filter by all the filters in the list, except ignore those that wouldn't pass anything
   filter_fingerings = (fingerings) ->
     for {name, filter} in filters
       filtered = (fingering for fingering in fingerings when filter(fingering))
       unless filtered.length
-        console.error "#{chord_name}: no fingerings pass filter \"#{name}\"" if warn
+        console.warn "#{chord_name}: no fingerings pass filter \"#{name}\"" if warn
         filtered = fingerings
       fingerings = filtered
     return fingerings
@@ -145,17 +159,17 @@

   high_note_count = (fingering) -> -fingering.positions.length

-  is_first_position = (fingering) ->
+  is_root_position = (fingering) ->
     _(fingering.positions).sortBy((pos) -> pos.string)[0].degree_index == 0

   sorts = [
-    finger_count,
-    high_note_count,
-    cmp(is_first_position)
+    {name: 'low finger count', key: (fingering) -> -fingering.positions.length}
+    {name: 'high note count', key: high_note_count}
+    {name: 'root position', key: cmp(is_root_position)}
   ]

   sort_fingerings = (fingerings) ->
-    fingerings = _(fingerings).sortBy(sort) for sort in sorts
+    fingerings = _(fingerings).sortBy(key) for {key} in sorts
     return fingerings

@@ -168,8 +182,6 @@
   fingerings = filter_fingerings fingerings
   fingerings = sort_fingerings fingerings

-  # for fingering in fingerings
-  #   console.info finger_count(fingering)
   return fingerings

 best_fingering_for = (chord) ->


More clear description of additionalPathDirs opt.

--- lib/haskell-ghc-mod.coffee
+++ lib/haskell-ghc-mod.coffee
@@ -28,7 +28,8 @@
       type: 'array'
       default: []
       description: 'Add this directories to PATH when invoking ghc-mod.
-                    You might want to add path to ghc here.
+                    You might want to add path to a directory with
+                    ghc, cabal, etc binaries here.
                     Separate with comma.'
       items:
         type: 'string'


Use slim arrow in module

Use slim arrow in module

--- lib/haskell-ghc-mod.coffee
+++ lib/haskell-ghc-mod.coffee
@@ -63,8 +63,7 @@
     @subscriptions.dispose()
     @process?.destroy()

-  provideGhcMod_0_1_0: =>
-    @process=new GhcModiProcess unless @process?
+  provideGhcMod_0_1_0: ->
     if @process?
       type: @process.getType
       info: @process.getInfo


STL/fx enabling CSS3 transitions by default in Opera

--- stl/fx/src/fx/style.coffee
+++ stl/fx/src/fx/style.coffee
@@ -72,7 +72,6 @@
       element.no event_name, callback # unbinding itself immediately
       fx.__finished = true
       fx.finish()
-      console.log('fuck')

   element.on event_name, callback

@@ -103,11 +102,6 @@
     # setting the actual end styles
     setTimeout((->element.style(style)), 0)
   , 0
-
-
-# NOTE: OPERA's css-transitions are a bit jerky so we disable them by default
-Fx.Options.engine = if native_fx_prefix is null or Browser is 'Opera' then 'javascript' else 'css'
-

 #########################################################################


Config tweaks for nodesass

Config tweaks for nodesass

--- docpad.coffee
+++ docpad.coffee
@@ -102,6 +102,10 @@
 			startingPageNumber: 2
 		cleanurls:
 			trailingSlashes: true
+		nodesass:
+			outputStyle: 'compressed'
+			bourbon: true
+			neat: true
 }

 # Export the DocPad Configuration


Format selection for non-Markdown scopes

--- lib/table-formatter.coffee
+++ lib/table-formatter.coffee
@@ -38,14 +38,13 @@
     @subscriptions.dispose()

   format: (editor, force) ->
-    if not (editor.getGrammar().scopeName in @markdownGrammarScopes)
-      return
-
     selectionsRanges = editor.getSelectedBufferRanges()

     bufferRange = editor.getBuffer().getRange()
     selectionsRangesEmpty =
       selectionsRanges.every (i) -> i.isEmpty()
+    if not (editor.getGrammar().scopeName in @markdownGrammarScopes) and selectionsRangesEmpty
+      return
     if force or (selectionsRangesEmpty and @autoSelectEntireDocument)
       selectionsRanges = [bufferRange]
     else


New words in about.cson are translated to zh-cn

--- def/zh-cn/about.cson
+++ def/zh-cn/about.cson
@@ -1,9 +1,9 @@
 About:
   tabTitle: "关于"
   releaseNotes: "更新日志"
-  newUpdate: "New Update"
-  automaticDownloadUpdates: "Automatic download updates"
-  restartInstall: "Restart and install"
+  newUpdate: "新版本"
+  automaticDownloadUpdates: "自动下载更新"
+  restartInstall: "重启 Atom 并安装更新"
   license: "许可协议"
   termsOfUse: "使用条款"
   with: " 带着 "


Add tests for graph saving and loading

Add tests for graph saving and loading

--- spec/NoFlo.coffee
+++ spec/NoFlo.coffee
@@ -1,6 +1,7 @@
 if typeof process isnt 'undefined' and process.execPath and process.execPath.match /node|iojs/
   chai = require 'chai' unless chai
   noflo = require '../src/lib/NoFlo.coffee'
+  path = require('path')
   browser = false
 else
   noflo = require 'noflo'
@@ -9,3 +10,25 @@
 describe 'NoFlo interface', ->
   it 'should be able to tell whether it is running on browser', ->
     chai.expect(noflo.isBrowser()).to.equal browser
+  describe 'working with graph files', ->
+    targetPath = null
+    before ->
+      # These features only work on Node.js
+      return @skip() if noflo.isBrowser()
+      targetPath = path.resolve __dirname, 'tmp.json'
+    after (done) ->
+      return done() if noflo.isBrowser()
+      fs = require 'fs'
+      fs.unlink targetPath, done
+    it 'should be able to save a graph file', (done) ->
+      graph = new noflo.Graph
+      graph.addNode 'G', 'Graph'
+      noflo.saveFile graph, targetPath, done
+    it 'should be able to load a graph file', (done) ->
+      noflo.loadFile targetPath,
+        baseDir: process.cwd()
+        delay: true
+      , (err, network) ->
+        return done err if err
+        chai.expect(network.isRunning()).to.equal false
+        done()


fix issue with wrong method selected

fix issue with wrong method selected

--- app/assets/javascripts/angular/worklogs/worklog.js.coffee
+++ app/assets/javascripts/angular/worklogs/worklog.js.coffee
@@ -97,7 +97,7 @@
       @clients    = @clients.concat(shared)

       @clientId   = wl.clientId
-      selectClientById()
+      @selectClientById()
       @timeframes = _.map wl.timeframes, (tf)->
         f = new Timeframe(tf)
         f.started = new Date(tf.started)
@@ -113,6 +113,8 @@
     selectClientById: ->
       client     = _.select(@clients, (cl)=> cl.id == @clientId)[0]
       @client = client
+      @clientChanged()
+      @client

   Worklog
 ]


fix matrix conditional validation in js

fix matrix conditional validation in js

--- app/assets/javascripts/frontend/form-validation.js.coffee
+++ app/assets/javascripts/frontend/form-validation.js.coffee
@@ -286,6 +286,17 @@
             @addErrorClass(question)

   validateMatrix: (question) ->
+    # if it's a conditional question, but condition was not satisfied
+    conditional = true
+
+    question.find(".js-conditional-question").each ->
+      if !$(this).hasClass("show-question")
+        conditional = false
+
+    if !conditional
+      return
+    # end of conditional validation
+
     for subquestion in question.find("input")
       subq = $(subquestion)
       qParent = subq.parent()
@@ -302,8 +313,8 @@
         if t < 0
           @appendMessage(qParent, "At least 0")
           @addErrorClass(question)
-
-
+
+
   validateCurrentAwards: (question) ->
     $(".errors-container", question).empty()


Diagnostic POSTs

Diagnostic POSTs

--- tests/scripts/test_diagnostics.coffee
+++ tests/scripts/test_diagnostics.coffee
@@ -1,24 +1,52 @@

 Helper = require('hubot-test-helper')
 expect = require('chai').expect
-http = require('http')
+request = require('request')
+querystring = require('querystring')

-# helper loads a specific script if it's a file
 helper = new Helper('../../src/scripts/diagnostics.coffee')

+process.env.ORG_NAME = "test"
+process.env.SLASH_INFO_TOKEN = "abc123"
+process.env.SLASH_USERS_TOKEN = "abc123"
+process.env.SLASH_PROJECTS_TOKEN = "abc123"
+process.env.SLASH_CALENDAR_TOKEN = "abc123"
+process.env.SLASH_HOUND_TOKEN = "abc123"
+process.env.SLASH_PAYROLL_TOKEN = "abc123"
+process.env.SLASH_SYNC_TOKEN = "abc123"
+process.env.SLASH_PUNCH_TOKEN = "abc123"
+process.env.ADMINS = "admin"
+
+goodtoken = querystring.stringify({ token: 'abc123' })
+badtoken = querystring.stringify({ token: 'f' })
+infoendpoint = 'http://localhost:8080/ibizan/diagnostics/info'
+
 describe 'diagnostics', ->
-  room = null
-
   beforeEach ->
-    room = helper.createRoom()
+    @room = helper.createRoom()

   afterEach ->
-    room.destroy()
+    @room.destroy()
+
+  context 'POST /ibizan/diagnostics/info', ->
+    it 'responds with status 200 if correct token is provided', ->
+      request.post infoendpoint, goodtoken, (err, response, body) ->
+        if err
+          console.log err
+        expect(response.statusCode).to.equal 200
+        return
+
+    it 'responds with status 401 if incorrect token is provided', ->
+      request.post infoendpoint, badtoken, (err, response, body) ->
+        if err
+          console.log err
+        expect(response.statusCode).to.equal 401
+        return

   context 'user says: hubot uptime', ->
     beforeEach ->
-      room.user.say 'briancoia', 'hubot uptime'
+      @room.user.say 'briancoia', 'hubot uptime'

     it 'should reply with uptime', ->
-      expect(room.messages[0]).to.eql(['briancoia', 'hubot uptime'])
-      expect(room.messages[1][1]).to.include('has been up')
+      expect(@room.messages[0]).to.eql(['briancoia', 'hubot uptime'])
+      expect(@room.messages[1][1]).to.include('has been up')


Reduce error noise on Sentry from audio player (#4368)

Reduce error noise on Sentry from audio player

--- resources/assets/coffee/_classes/osu-audio.coffee
+++ resources/assets/coffee/_classes/osu-audio.coffee
@@ -40,7 +40,11 @@

     @urlSet url
     @publish 'initializing'
-    @player().play()
+    promise = @player().play()
+    # old api returns undefined
+    promise?.catch (error) ->
+      return if error.name == 'AbortError' || error.name == 'NotSupportedError' && !osu.present(@player.src)
+      throw error

   player: =>


[neo4j] changed new install app cypher where query

--- server/lib/server/graph/graph.coffee
+++ server/lib/server/graph/graph.coffee
@@ -105,7 +105,7 @@
       'START kd=node:koding(id={groupId})'
       'MATCH kd-[:member]->users<-[r:user]-koding'
       'WHERE koding.name="JApp"'
-      'and koding.`meta.createdAtEpoch` < {startDate}'
+      'and r.createdAtEpoch < {startDate}'
       'return *'
       'order by r.createdAtEpoch DESC'
       'limit 10'


Fix bug

Fix bug

--- src/6.misc.coffee
+++ src/6.misc.coffee
@@ -15,8 +15,8 @@
     sources.forEach((source) ->
         deepAssign = (target, source) ->
             Object.forEach(source, (key, value) ->
-                if Object.isObject(value)
-                    if Object.isObject(target[key])
+                if Object.isObject(value) and not Array.isArray(value)
+                    if Object.isObject(target[key]) and not Array.isArray(target[key])
                         deepAssign(target[key], value)
                     else
                         target[key] = Object.deepClone(value)
@@ -35,8 +35,8 @@
     objects.forEach((object) ->
         deepAbsorb = (subject, object) ->
             Object.forEach(object, (key, value) ->
-                if Object.isObject(value)
-                    if Object.isObject(subject[key])
+                if Object.isObject(value) and not Array.isArray(value)
+                    if Object.isObject(subject[key]) and not Array.isArray(subject[key])
                         deepAbsorb(subject[key], value)
                     else
                         subject[key] = Object.deepClone(value) if subject[key] == undefined
@@ -47,16 +47,16 @@
     )
     subject
 Object.deepClone = (x) ->
-    target = {}
-    deepExtend = (target, source) ->
+    target = if Array.isArray(x) then [] else {}
+    deepCopyFrom = (target, source) ->
         Object.forEach(source, (key, value) ->
             if Object.isObject(value)
-                target[key] = {}
-                deepExtend(target[key], value)
+                target[key] = if Array.isArray(value) then [] else {}
+                deepCopyFrom(target[key], value)
             else
                 target[key] = value
         )
-    deepExtend(target, x)
+    deepCopyFrom(target, x)
     target
 JSON.clone = (x) -> JSON.parse(JSON.stringify(x))
 Date::add = (x) -> # `x` must be a number


Workspace: Improved session user tracking.

--- client/landing/app/CommonViews/workspace/collaborativeworkspace.coffee
+++ client/landing/app/CommonViews/workspace/collaborativeworkspace.coffee
@@ -26,18 +26,24 @@

       keys = snapshot.val()?.keys

-      @workspaceRef.onDisconnect().remove()  if @amIHost()
-
       if keys # if we have keys this means we're about to join an old session
         log "it's an old session, impressed!"
         @sessionData  = keys
         @createPanel()
-        @workspaceRef.child("users").push KD.nick()
+        @userRef = @workspaceRef.child("users").child KD.nick()
+        @userRef.set "online"
+        @userRef.onDisconnect().set "offline"
       else
         log "your awesome new session, saving keys now"
         @createPanel()
         @workspaceRef.set "keys": @sessionData
-        @workspaceRef.child("users").push KD.nick()
+        @userRef = @workspaceRef.child("users").child KD.nick()
+        @userRef.set "online"
+        @userRef.onDisconnect().set "offline"
+
+      if @amIHost()
+        @workspaceRef.onDisconnect().remove()
+        @userRef.onDisconnect().remove()

       @loader.destroy()


Ported API to use response.send

Ported API to use response.send

--- library/gearing/api.coffee
+++ library/gearing/api.coffee
@@ -59,8 +59,8 @@
         response.writeHead(methodNotAllowed, message)
         descriptor = error: message, code: methodNotAllowed
         @emit("unsupported", request, response, next)
-        return response.end(descriptor) if handles("json")
-        response.end(message); this
+        return response.send descriptor if handles("json")
+        response.send message; this

     # Process the already macted HTTP request according to the REST
     # specification. That is, see if the request method conforms to
@@ -90,8 +90,8 @@
         checkIfSupported = (method) => @[method] isnt @unsupported
         supported = _.filter(knowns, checkIfSupported)
         descriptor = methods: supported, resource: pathname
-        return respons.end(descriptor) if handles("json")
-        response.end(supported.join(", ")); this
+        return respons.send descriptor if handles("json")
+        response.send supported.join ", "; this

 # An abstract base class with all of the HTTP methods, defined in
 # the HTTP specification and covered by the base implementation


fix: Remove log statement when running tests

This must've been left over from someone debugging

--- test/parser-mson-test.coffee
+++ test/parser-mson-test.coffee
@@ -23,8 +23,6 @@

       attributes = result.content[0].content[0].content[0].content[0].content[0].content[1].content[0]
       dataStructures = result.content[0].content[1].content
-
-      console.log(JSON.stringify(dataStructures[0].content[0].content[0].content.key.content, null, 2));

       done()


fix (Events) Provide all required params for CustomEvent

Required for `visibilitychange` event to work on
Android Platform WebView.

Fixes https://github.com/AppGyver/steroids/issues/1065

--- src/Events.coffee
+++ src/Events.coffee
@@ -5,7 +5,7 @@
       msg: "dispatched visibilitychanged"

     visibilityChangeCustomEvent = document.createEvent "CustomEvent"
-    visibilityChangeCustomEvent.initCustomEvent "visibilitychange", true, true
+    visibilityChangeCustomEvent.initCustomEvent "visibilitychange", true, true, {}

     document.dispatchEvent visibilityChangeCustomEvent


Remove unused flag.

Remove unused flag.

--- services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
+++ services/web/public/coffee/ide/review-panel/controllers/ReviewPanelController.coffee
@@ -15,7 +15,6 @@
 			entries: {}
 			resolvedComments: {}
 			hasEntries: false
-			showAddComment: false
 			subView: $scope.SubViews.CUR_FILE
 			openSubView: $scope.SubViews.CUR_FILE
 			overview:


fix yes and no check images

fix yes and no check images

--- vue/src/shared/helpers/poll.coffee
+++ vue/src/shared/helpers/poll.coffee
@@ -18,6 +18,8 @@
   block: 'block'
   consent: 'agree'
   objection: 'block'
+  yes: 'yes'
+  no: 'no'

 # A series of helpers for interacting with polls, such as template values for a
 # particular poll or getting the last stance from a given user


adding a line animations

adding a line animations

--- src/Player.coffee
+++ src/Player.coffee
@@ -1,24 +1,32 @@
 TWEEN = require 'tween.js'
-
+RADIUS = 3
 class Player
   constructor: (@two, name, color) ->
     @color = color || 0x000000
     @pos   = { x: Math.random() * 500, y: Math.random() * 500 }
-    @drawTo()
+    @snaps = 0
+    @draw()

-  drawTo: ->
-    c = @two.makeCircle(@pos.x, @pos.y, 3)
-    c.fill = @color
+  draw: ->
+    @two.remove @circle if @circle
+    @circle = @two.makeCircle(@pos.x, @pos.y, @snaps + RADIUS)
+    @circle.fill = @color

-  # draw a line from current player to other player
   snap: (player) ->
+    @snaps += 1
+    @draw()
+
+    # draw a line from current player to other player
     line = @two.makeLine(@pos.x, @pos.y, @pos.x, @pos.y)
-
-    dX = player.pos.x - @pos.x
-    dY = player.pos.y - @pos.y
-    new TWEEN.Tween(line.vertices[1])
-             .to( {x: "#{dX}", y: "#{dY}"}, 400)
-             .start()
+    dX   = player.pos.x - @pos.x
+    dY   = player.pos.y - @pos.y
+    drawLine = new TWEEN.Tween(line.vertices[1])
+                        .to( {x: "#{dX}", y: "#{dY}"}, 400)
+    hideLine = new TWEEN.Tween(line)
+                        .to({opacity: 0}, 500)
+                        .onComplete( => @two.remove(hideLine) )
+    drawLine.chain(hideLine)
+    drawLine.start()

 module.exports = Player


Workspace: Create default workspace for owner only

--- workers/social/lib/social/models/workspace.coffee
+++ workers/social/lib/social/models/workspace.coffee
@@ -190,11 +190,16 @@
         return callback err  if err
         return callback null, workspace  if workspace

-        data =
-          name         : 'My Workspace'
-          isDefault    : yes
-          machineLabel : machine.label
-          machineUId   : machine.uid
-          rootPath     : "/home/#{nickname}"
-
-        @create client, data, callback
+        machine.fetchOwner (err, account) =>
+
+          return callback err  if err
+
+          data =
+            name         : 'My Workspace'
+            isDefault    : yes
+            machineLabel : machine.label
+            machineUId   : machine.uid
+            rootPath     : "/home/#{nickname}"
+            originId     : account.getId()
+
+          @create client, data, callback


Fix terminal scrolling up on tab change

Fix terminal scrolling up on tab change

--- client/main/main.ng.coffee
+++ client/main/main.ng.coffee
@@ -397,11 +397,13 @@
     $rootScope.$on('$stateChangeStart', (event, toState, toParams, fromState, fromParams) ->
         if toState.name isnt "terminal"
             $("#terminal").appendTo(".terminalOuter")
+            $.terminal.active()?.scroll_to_bottom()
     )

     $rootScope.$on('$viewContentLoaded', (event, toState, toParams, fromState, fromParams) ->
         if $state.current.name is "terminal"
             $("#terminal").appendTo("#terminalTab")
+            $.terminal.active()?.scroll_to_bottom()
     )

     $scope.$watch((-> $mdMedia('gt-sm')), (big) ->
@@ -522,7 +524,6 @@

         term = terminal()
         term.error message
-        term.scroll_to_bottom()

     listen.startRunning = ->
         #console.log "startRunning"
@@ -540,8 +541,6 @@
             prompt: ''
         )

-        terminal().scroll_to_bottom()
-
     listen.startDebugging = ->
         $scope.debugging = yes

@@ -562,8 +561,6 @@
         $scope.astString = ast

         $scope.instructionsString = instructions
-
-        terminal().scroll_to_bottom()

     listen.executionFinish = ({ status }) ->
         # TODO: Show status somehow


Removed debug log.

Removed debug log.

--- django_cradmin/static/django_cradmin/src/lib/iosaddtohomescreen.coffee
+++ django_cradmin/static/django_cradmin/src/lib/iosaddtohomescreen.coffee
@@ -21,11 +21,11 @@
       else
         $scope.deviceModel = cradminDetectize.device.model

-      console.log 'Detected os:', $scope.os
-      console.log 'Detected browser:', $scope.browser
-      console.log 'Detected deviceModel:', $scope.deviceModel
-
-      console.log $window.navigator.standalone
+#      console.log 'Detected os:', $scope.os
+#      console.log 'Detected browser:', $scope.browser
+#      console.log 'Detected deviceModel:', $scope.deviceModel
+#
+#      console.log $window.navigator.standalone

       if $scope.os == 'ios' and $scope.browser == 'safari'
         $element.show()


Fix bug: the speaker page had an error for anonymous users

--- client/view/speaker.coffee
+++ client/view/speaker.coffee
@@ -44,7 +44,7 @@

 canEdit = ->
   cur = User.current()
-  @speaker.me() or cur.admin()
+  @speaker.me() or (cur and cur.admin())

 Template.speaker.photo = ->
   @speaker.photoUrl(120)


Disable backdrop close

Disable backdrop close

--- components/inquiry_questionnaire/index.coffee
+++ components/inquiry_questionnaire/index.coffee
@@ -13,6 +13,8 @@
   modal = modalize questionnaire,
     className: 'modalize inquiry-questionnaire-modal'
     dimensions: width: '500px', height: '580px'
+
+  modal.view.$el.off 'click', '.js-modalize-backdrop'

   modal.load (done) ->
     user.fetch


Updated routing tests to run a bit faster

--- tests/batman/app_test.coffee
+++ tests/batman/app_test.coffee
@@ -17,6 +17,7 @@
       @controller = TestApp.TestController.sharedInstance
     teardown: ->
       @app.stopRouting()
+      window.location.hash = ""

   test "should match simple routes", ->
     spyOn(@controller, "show")
@@ -50,7 +51,7 @@
     setTimeout(=>
       deepEqual @app.dispatch.lastCallArguments, ["/"]
       start()
-    , 15)
+    , ASYNC_TEST_DELAY)

   asyncTest "should start routing for aribtrary routes", 1, ->
     window.location.hash = "#!/products/1"
@@ -59,20 +60,21 @@
     setTimeout(=>
       deepEqual @app.dispatch.lastCallArguments, ["/products/1"]
       start()
-    , 15)
+    , ASYNC_TEST_DELAY)

-  asyncTest "should listen for hashchange events", 2, ->
+  asyncTest "should listen for hashchange events", 3, ->
     window.location.hash = "#!/products/1"
     spyOn(@app, "dispatch")
     @app.startRouting()
     setTimeout(->
       window.location.hash = "#!/products/2"
-    , 15)
+    , ASYNC_TEST_DELAY)
     setTimeout(=>
+      equal @app.dispatch.callCount, 2
       deepEqual @app.dispatch.calls[0].arguments, ["/products/1"]
       deepEqual @app.dispatch.calls[1].arguments, ["/products/2"]
       start()
-    , 115)
+    , ASYNC_TEST_DELAY*2 + 100)

   test "should redirect", ->
     spyOn(@app, "dispatch")


default authcallbacks

default authcallbacks

--- js/src/auth/CredentialService.coffee
+++ js/src/auth/CredentialService.coffee
@@ -37,7 +37,7 @@
       @directoryApi    = new DirectoryApi()
       @rsaKeyGenerator = new RsaKeyGenerator()

-    deriveCredential : ({ username, password, realm }, authCallback) ->
+    deriveCredential : ({ username, password, realm }, authCallback = -> ) ->
       { iterations, keySize, passwordCrypto } = {}

       Promise.resolve()
@@ -54,7 +54,7 @@
         hexDerived     = Forge.util.bytesToHex(derived)
         return hexDerived

-    initializeKeypair : ({ password }, authCallback) ->
+    initializeKeypair : ({ password }, authCallback = -> ) ->
       { publicKey, privateKey, keypair } = {}

       Promise.resolve()
@@ -84,7 +84,7 @@
         log.error(e)
         log.error('keypair generation failed!', e)

-    deriveKeypair : ({ password }, authCallback) ->
+    deriveKeypair : ({ password }, authCallback = -> ) ->
       Promise.resolve()
       .then =>
         authCallback(AuthenticationStage.DERIVE_KEYPAIR)


Added header to coffeeScript file

Added header to coffeeScript file

--- js/jquery.table-summarizer.js.coffee
+++ js/jquery.table-summarizer.js.coffee
@@ -1,8 +1,8 @@
 #
-# Name    : jquery.table-summarizer
-# Author  : Ben Thouret, http://benjamin.thouret.com
-# Version : 1.0
-# Repo    : <repo url>
+#  Title:		  jquery.table-summarizer (tableSummarizer)
+#  Homepage:	https://github.com/benichu/jquery.table-summarizer
+#  Copyright:	(c)2012: Benjamin Thouret <ben@2ret.com>
+#  License:	  MIT, https://github.com/benichu/jquery.table-summarizer/LICENSE-MIT
 #

 jQuery ->


akin picture after creating ticket

akin picture after creating ticket

--- app/assets/javascripts/backbone/apps/picture/new/new_views.js.coffee
+++ app/assets/javascripts/backbone/apps/picture/new/new_views.js.coffee
@@ -16,3 +16,11 @@
       "click #snapshot" : "take:snapshot"
       "click #video" :    "take:snapshot"
       "click #stop"  :    "stop:recording"
+
+    onShow:->
+      @playVideo()
+
+    playVideo: ->
+      # window.elll = @$el.find("#video")
+      # video = @$el.find("#video")
+      Recorder.play video, "both", ->


Fix indentation in RegistrationApi

Fix indentation in RegistrationApi

--- js/src/http/RegistrationApi.coffee
+++ js/src/http/RegistrationApi.coffee
@@ -28,7 +28,7 @@
           email       : email
           givenName   : givenName
         url : registrationUrl()
-        }))
+      }))
       .then (response) ->
         return response


Add support for special 'preview' helper in layouts

--- emails.coffee
+++ emails.coffee
@@ -111,13 +111,27 @@
     check templateName, String
     check data, Match.Optional Object

-    if not Template[templateName]
+    tmpl = Template[templateName]
+
+    if not tmpl
       compile _.findWhere(options.templates, name: templateName)

-    rendered = SSR.render templateName, data
-
-    if Template[templateName].__layout?
-      rendered = SSR.render Template[templateName].__layout, body: rendered
+    rendered = SSR.render tmpl, data
+
+    if tmpl.__layout?
+      layout = tmpl.__layout
+
+      if tmpl.__helpers.has 'preview'
+        preview = tmpl.__helpers.get('preview')
+      else if data.preview
+        preview = data.preview
+
+      layoutData = _.extend({}, data,
+        body: rendered
+        preview: preview
+      )
+
+      rendered = SSR.render layout, layoutData

     Utils.addDoctype rendered


update時に例外を無視しつつpushする

update時に例外を無視しつつpushする

--- app/assets/javascripts/components/adsense/google_adsense_ins.js.cjsx
+++ app/assets/javascripts/components/adsense/google_adsense_ins.js.cjsx
@@ -4,6 +4,10 @@

   componentDidMount: ->
     @pushAd()
+
+  componentDidUpdate: ->
+    try
+      @pushAd()

   pushAd: ->
     (adsbygoogle = window.adsbygoogle || []).push {}


ignore wallop css clean

ignore wallop css clean

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -314,6 +314,7 @@
                 new RegExp('^.Cart-r.*')
                 new RegExp('\.no-touch*(.)\S+')
                 new RegExp('\.Wallop.*(.)\S+')
+                new RegExp('^.Wallop.*')
                 new RegExp('^.Store.*')
                 new RegExp('\.Add*(.)\S+')
                 new RegExp('\.Button*(.)\S+')


fix coffeelint warning

fix coffeelint warning

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -60,7 +60,7 @@
     )
     React.DOM.script(
       dangerouslySetInnerHTML:
-        __html: '//<!--\nvar INITIAL_PROPS=' + JSON.stringify(props) + ';\n//-->'
+        __html: "//<!--\nvar INITIAL_PROPS=#{JSON.stringify(props)};\n//-->"
     )

 buildTitle = (entry) ->


fix typedoc task: include refs

fix typedoc task: include refs

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -27,17 +27,25 @@
 branch = args.branch || 'unknown'
 console.log "branch: #{branch}"

+# typedoc sources (Array), dest
+typedocSrc = ['jThree/src/**/*.ts']
+typedocDest = 'ci/docs'
+
+# tsd file sources (Array)
+tsdSrc = 'jThree/refs/**/*.d.ts'
+
+# test target (Array)
+testTarget = 'jThree/test/build/test.js'
+
+# path to tsconfig.json
+tsconfigPath = './tsconfig.json'
+
+# pathes for webpack building
 requireRoot = 'jThree/src'
 serverRoot = 'jThree/wwwroot'
 watchForReload = ['jThree/wwwroot/**/*.js', 'jThree/wwwroot/**/*.html', 'jThree/wwwroot/**/*.goml']

-typedocSrc = ['jThree/src/**/*.ts']
-typedocDest = 'ci/docs'
-
-testTarget = 'jThree/test/build/test.js'
-
-tsconfigPath = './tsconfig.json'
-
+# individual config for webpack building
 config =
   main:
     entry: 'jThree/src/jThree.ts'
@@ -148,7 +156,7 @@
 ###
 gulp.task 'doc', (cb) ->
   gulp
-    .src typedocSrc
+    .src [].concat typedocSrc, tsdSrc
     .pipe typedoc
       module: 'commonjs'
       target: 'es5'


Fix callback

Fix callback

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -62,6 +62,6 @@
 gulp.task 'merge', ->
   current = branch()
   git.checkout 'master'
-  git.merge current, (err) -> if (err) throw err
+  git.merge current, ((err) -> if (err) throw err)
   git.checkout current


updated gulp file

updated gulp file

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -66,10 +66,7 @@
   gulp.watch "./stage/*.jade", -> _markup()
   gulp.watch "./src/*.coffee", -> _scripts()

-
 ## tasks
 gulp.task 'bump', () -> _bump(gulp.env.type)
 gulp.task 'compile', () -> _markup(); _scripts()
-
-#
 gulp.task 'default', [ 'compile' ], -> _watch()


add inline scripts for vulcanize

add inline scripts for vulcanize

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -106,14 +106,14 @@
     .pipe $.fileInclude()
     .pipe gulp.dest 'dist/elements'

-gulp.task 'compress-pages', ->
-  runSequence 'compress-elements', 'replace-min'
+gulp.task 'compress-pages', (cb) ->
+  runSequence 'compress-elements', 'replace-min', cb

 gulp.task 'compress-elements', ->
   gulp
     .src 'app/elements/elements.html'
     .pipe gulp.dest 'dist/elements'
-    .pipe $.vulcanize()
+    .pipe $.vulcanize { inlineScripts: true }
     .pipe $.rename 'elements.vulcanized.html'
     .pipe gulp.dest 'dist/elements/'

@@ -142,15 +142,15 @@

 gulp.task 'build', (cb) ->
   runSequence(
-    'clean',
-    'copy',
-    ['compile-resources-meta', 'compile-scripts', 'compile-pages'],
-    'handle-styles',
+    'clean'
+    'copy'
+    ['compile-resources-meta', 'compile-scripts', 'compile-pages']
+    'handle-styles'
     'compress-pages'
     cb
   )

 gulp.task 'build-phonegap', (cb) ->
-  runSequence [ 'build', 'clean-phonegap' ], 'copy-phonegap'
+  runSequence 'build', 'clean-phonegap', 'copy-phonegap'

 gulp.task 'default', [ 'build' ]


Fix #43: Build bug with bytediff

Fix #43: Build bug with bytediff

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -352,8 +352,8 @@
 			.pipe( rename( basename: "maxmertkit" ) )
 			.pipe( gulp.dest "#{path.build.css}" )

+			.pipe( minifyCSS() )
 			.pipe( bytediff.start() )
-			.pipe( minifyCSS() )
 			.pipe( gzip( append: no ) )
 			.pipe( bytediff.stop() )
 			.pipe( rename( basename: "maxmertkit.min" ) )


Adds explicit nwjs version to gulpfile; closes #85

--- gulpfile.coffee
+++ gulpfile.coffee
@@ -19,6 +19,7 @@
     gulp.src './src/**'
       .pipe $.nodeWebkitBuilder
         platforms: [platform]
+        version: '0.12.2'
         winIco: if process.argv.indexOf('--noicon') > 0 then undefined else './assets-windows/icon.ico'
         macIcns: './assets-osx/icon.icns'
         macZip: true


Add tests for createOrUpdate method.

Add tests for createOrUpdate method.

--- src/spec/product-import.spec.coffee
+++ src/spec/product-import.spec.coffee
@@ -380,7 +380,7 @@

   describe '::_createOrUpdate', ->

-    it 'should create a new product', (done) ->
+    it 'should create a new product and update an existing product', (done) ->
       newProduct = _.deepClone(sampleNewPreparedProduct)
       newProduct.name = { en: "My new product" }
       newProduct.masterVariant = sampleMasterVariant
@@ -388,38 +388,52 @@

       existingProduct1 = _.deepClone(newProduct)
       existingProduct1.id = "existing_id1"
-      existingProduct1.masterVariant.sku = "9876"
-      existingProduct1.variants[0].sku = "9876_1"
-      existingProduct1.variants[1].sku = "9876_2"
+      existingProduct1.masterVariant.sku = "9876_1"
+      existingProduct1.variants[0].sku = "9876_1_1"
+      existingProduct1.variants[1].sku = "9876_1_2"

       existingProduct2 = _.deepClone(newProduct)
       existingProduct2.id = "existing_id2"
-      existingProduct2.masterVariant.sku = "9876_1"
-      existingProduct2.variants[0].sku = "9876_1_1"
-      existingProduct2.variants[1].sku = "9876_1_2"
+      existingProduct2.masterVariant.sku = "9876_2"
+      existingProduct2.variants[0].sku = "9876_2_1"
+      existingProduct2.variants[1].sku = "9876_2_2"
       existingProduct2.version = 1

       updateProduct = _.deepClone(existingProduct2)
       sampleVariant3 = _.deepClone(sampleVariant2)
-      sampleVariant3.sku = "9876_1_3"
+      sampleVariant3.sku = "9876_2_3"
       sampleVariant3.id = "9"
-      #updateProduct.variants = []
       updateProduct.variants[2] = sampleVariant3

-
-
       existingProducts = [existingProduct1,existingProduct2]
+
+      expectedUpdateActions = {
+        actions: [
+          {
+            action: "addVariant",
+            sku: "9876_2_3",
+            attributes: [
+              {
+                name: "attribute1",
+                value: "attribute1_value3"
+              },
+              {
+                images: []
+              }
+            ]
+          }
+        ],
+        version: 1
+      }

       spyOn(@import, "_prepareNewProduct").andCallFake (prepareProduct) => Promise.resolve(prepareProduct)
       spyOn(@import.client._rest, 'POST').andCallFake (endpoint, payload, callback) ->
         callback(null, {statusCode: 200}, {})
-      console.log(existingProducts[1].masterVariant)
-      console.log(updateProduct.masterVariant)
       @import._createOrUpdate([newProduct,updateProduct],existingProducts)
       .then =>
         expect(@import._prepareNewProduct).toHaveBeenCalled()
         expect(@import.client._rest.POST.calls[0].args[1]._settledValue).toEqual newProduct
-        console.log(@import.client._rest.POST.calls[1].args[1])
-        done()
-      .catch done
-
+        expect(@import.client._rest.POST.calls[1].args[1]).toEqual expectedUpdateActions
+        done()
+      .catch done
+


Remove the well from around alerts

Remove the well from around alerts

--- tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee
+++ tapestry-core/src/main/coffeescript/META-INF/modules/t5/core/alert.coffee
@@ -60,14 +60,12 @@
     setupUI = (container) ->

       container.update """
-

             <button class="btn btn-mini pull-right" data-action="dismiss-all">
               ×
               #{messages "core-dismiss-label"}
             </button>
-

          """


Update team

Update team

--- client/About/team.coffee
+++ client/About/team.coffee
@@ -28,17 +28,14 @@
         username  : 'cihangirsavas'
         title     : 'Software Engineer'
       ,
-        username  : 'geraint'
+        username  : 'kiwigeraint'
         title     : 'Director of Infrastructure'
       ,
-        username  : 'erdinc'
-        title     : 'Software Engineer'
-      ,
         username  : 'szkl'
-        title     : 'Software Engineer'
+        title     : 'DevOps'
       ,
         username  : 'leventyalcin'
-        title     : 'System Administrator'
+        title     : 'DevOps'
       ,
         username  : 'burakcan'
         title     : 'CSS Wizard'
@@ -129,4 +126,4 @@
       # ,
       #   username  : 'psanchezdl'
       #   title     : 'Growth Engineer'
-      # ]+      # ]


Fix noscript rendering of CoverImage.

Fix noscript rendering of CoverImage.

--- components/CoverImage.cjsx
+++ components/CoverImage.cjsx
@@ -126,7 +126,9 @@
             { @props.children }
             {
                 if @props.noscript and not @state.__live
-
+
+
+
             }


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -19,7 +19,7 @@
       } = meterData

       if not I[name] || not I["max#{name.capitalize()}"]
-        warn "The mixin"
+        warn "The mixin Me"
       else
         ratio = I[name] / I["max#{name.capitalize()}"]


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/metered.coffee
+++ src/metered.coffee
@@ -56,7 +56,7 @@

       if not I["max#{name.capitalize()}"]
         if I[name]
-        I["max#{name.capitalize()}"] = 100
+          I["max#{name.capitalize()}"] = 100

       ratio = I[name] / I["max#{name.capitalize()}"]


even better way to allow for table opts

even better way to allow for table opts

--- salvus/rethink.coffee
+++ salvus/rethink.coffee
@@ -325,8 +325,8 @@
                     factor    : 1.3
                     cb        : -> cb(error, result)

-    table: (name, readMode='outdated') =>
-        @db.table(name, {readMode: readMode})
+    table: (name, opts={readMode:'outdated'}) =>
+        @db.table(name, opts)

     # Compute the sha1 hash (in hex) of the input arguments, which are
     # converted to strings (via json) if they are not strings, then concatenated.


Extra cleanup

Extra cleanup

--- client/lib/resize.coffee
+++ client/lib/resize.coffee
@@ -1,7 +1,7 @@
 import {useLayoutEffect, useState} from 'react'
 import useResizeObserver from '@react-hook/resize-observer'

-export useElementWidth = (ref, debounce) ->
+export useElementWidth = (ref) ->
   [width, setWidth] = useState()
   useLayoutEffect ->
     setWidth ref.current.clientWidth


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/camera.coffee
+++ src/camera.coffee
@@ -124,7 +124,8 @@
   # The order of theses includes is important for
   # the way in wich they modify the camera view transform

-  for moduleName in Camera.defaultM
+  for moduleName in Camera.defaultModules
+    self.incl
   self.include(Camera.Zoom)
   self.include(Camera.Rotate)
   self.include(Camera.Shake)


made more use of $().on()

made more use of $().on()

--- client/editor.coffee
+++ client/editor.coffee
@@ -87,40 +87,47 @@
     return

   $tb = $ '.toolbar', $e
-  $('.toolbar-button', $tb) # todo
-    .on 'mousedown', (e) -> $(e.target).addClass 'armed'; e.preventDefault(); return
-    .on 'mouseup mouseout', (e) -> $(e.target).removeClass 'armed'; e.preventDefault(); return
+    .on 'mousedown',        '.toolbar-button', (e) -> $(e.target).addClass    'armed'; e.preventDefault(); return
+    .on 'mouseup mouseout', '.toolbar-button', (e) -> $(e.target).removeClass 'armed'; e.preventDefault(); return
+    .on 'click', '.b-over',       -> opts.over?()
+    .on 'click', '.b-into',       -> opts.into?()
+    .on 'click', '.b-back',       -> opts.back?()
+    .on 'click', '.b-skip',       -> opts.skip?()
+    .on 'click', '.b-cont-trace', -> opts.continueTrace?()
+    .on 'click', '.b-cont-exec',  -> opts.continueExec?()
+    .on 'click', '.b-restart',    -> opts.restartThreads?()
+    .on 'click', '.b-edit-name',  -> opts.edit? cm.getValue(), 0
+    .on 'click', '.b-interrupt',  -> opts.interrupt?()
+    .on 'click', '.b-cutback',    -> opts.cutback?()
+    .on 'click', '.b-line-numbers', -> cm.setOption 'lineNumbers', b = !cm.getOption 'lineNumbers'; $(@).toggleClass 'pressed', b; false
+    .on 'click', '.b-save', -> saveAndClose(); false
+    .on 'click', '.b-comment', ->
+      a = cm.listSelections()
+      cm.replaceSelections cm.getSelections().map (s) -> s.replace(/^/gm, '⍝').replace /\n⍝$/, '\n'
+      cm.setSelections a
+      false
+    .on 'click', '.b-uncomment', ->
+      a = cm.listSelections()
+      cm.replaceSelections cm.getSelections().map (s) -> s.replace /^⍝/gm, ''
+      cm.setSelections a
+      false
+    .on 'click', '.b-hid, .b-case', -> $(@).toggleClass 'pressed'; false
+    .on 'click', '.b-next', -> search(); false
+    .on 'click', '.b-prev', -> search true; false
+    .on 'keydown', '.search', -> if e.which == 13 then search(); false
+    .on 'click', '.b-refac-m', ->
+      if !/^\s*$/.test s = cm.getLine l = cm.getCursor().line
+        cm.replaceRange "∇ #{s}\n\n∇", {line: l, ch: 0}, {line: l, ch: s.length}, 'Dyalog'
+        cm.setCursor line: l + 1, ch: 0
+    .on 'click', '.b-refac-f', ->
+      if !/^\s*$/.test s = cm.getLine l = cm.getCursor().line
+        cm.replaceRange ":field public #{s}", {line: l, ch: 0}, {line: l, ch: s.length}, 'Dyalog'
+        cm.setCursor line: l + 1, ch: 0
+    .on 'click', '.b-refac-p', ->
+      if !/^\s*$/.test s = cm.getLine l = cm.getCursor().line
+        cm.replaceRange ":Property #{s}\n\n∇r←get\nr←0\n∇\n\n∇set args\n∇\n:EndProperty", {line: l, ch: 0}, {line: l, ch: s.length}, 'Dyalog'
+        cm.setCursor line: l + 1, ch: 0

-  $('.b-over',       $tb).click -> opts.over?()
-  $('.b-into',       $tb).click -> opts.into?()
-  $('.b-back',       $tb).click -> opts.back?()
-  $('.b-skip',       $tb).click -> opts.skip?()
-  $('.b-cont-trace', $tb).click -> opts.continueTrace?()
-  $('.b-cont-exec',  $tb).click -> opts.continueExec?()
-  $('.b-restart',    $tb).click -> opts.restartThreads?()
-  $('.b-edit-name',  $tb).click -> opts.edit? cm.getValue(), 0
-  $('.b-interrupt',  $tb).click -> opts.interrupt?()
-  $('.b-cutback',    $tb).click -> opts.cutback?()
-
-  $('.b-line-numbers', $tb).click -> cm.setOption 'lineNumbers', b = !cm.getOption 'lineNumbers'; $(@).toggleClass 'pressed', b; false
-  $('.b-save', $tb).click -> saveAndClose(); false
-
-  $('.b-comment', $tb).click ->
-    a = cm.listSelections()
-    cm.replaceSelections cm.getSelections().map (s) -> s.replace(/^/gm, '⍝').replace /\n⍝$/, '\n'
-    cm.setSelections a
-    false
-
-  $('.b-uncomment', $tb).click ->
-    a = cm.listSelections()
-    cm.replaceSelections cm.getSelections().map (s) -> s.replace /^⍝/gm, ''
-    cm.setSelections a
-    false
-
-  $('.b-hid, .b-case', $tb).click -> $(@).toggleClass 'pressed'; false
-  $('.b-next', $tb).click -> search(); false
-  $('.b-prev', $tb).click -> search true; false
-  $('.search', $tb).keydown (e) -> if e.which == 13 then search(); false
   search = (backwards) ->
     if q = $('.search:visible', $tb).val()
       v = cm.getValue()
@@ -136,21 +143,6 @@
         if wrapped then alert 'Search wrapping'
         cm.setSelections [anchor: cm.posFromIndex(j), head: cm.posFromIndex j + q.length]
     false
-
-  $('.b-refac-m', $tb).click ->
-    if !/^\s*$/.test s = cm.getLine l = cm.getCursor().line
-      cm.replaceRange "∇ #{s}\n\n∇", {line: l, ch: 0}, {line: l, ch: s.length}, 'Dyalog'
-      cm.setCursor line: l + 1, ch: 0
-
-  $('.b-refac-f', $tb).click ->
-    if !/^\s*$/.test s = cm.getLine l = cm.getCursor().line
-      cm.replaceRange ":field public #{s}", {line: l, ch: 0}, {line: l, ch: s.length}, 'Dyalog'
-      cm.setCursor line: l + 1, ch: 0
-
-  $('.b-refac-p', $tb).click ->
-    if !/^\s*$/.test s = cm.getLine l = cm.getCursor().line
-      cm.replaceRange ":Property #{s}\n\n∇r←get\nr←0\n∇\n\n∇set args\n∇\n:EndProperty", {line: l, ch: 0}, {line: l, ch: s.length}, 'Dyalog'
-      cm.setCursor line: l + 1, ch: 0

   setDebugger = (x) ->
     opts.debugger = x


add tarball note inside core documentation

--- hdp/core.coffee
+++ hdp/core.coffee
@@ -17,6 +17,13 @@
 *   `hdp.static_host` (boolean)
     Write the host name of the server instead of the Hadoop "_HOST"
     placeholder accross all the configuration files, default to false.
+
+The Hadoop distribution used is the Hortonwork distribution named HDP. The
+installation is leveraging the Yum repositories. [Individual tarballs][tar]
+are also available as an alternative with the benefit of including the source
+code.
+
+[tar]: http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.9.1/bk_installing_manually_book/content/rpm-chap13.html

 ###
 module.exports.push module.exports.configure = (ctx) ->
@@ -173,13 +180,13 @@
   do_core()

 module.exports.push name: 'HDP Core # Hadoop OPTS', timeout: -1, callback: (ctx, next) ->
-  {hadoop_conf_dir, hadoop_opts, hdfs_log_dir, hdfs_pid_dir} = ctx.config.hdp
+  {hadoop_conf_dir, hdfs_user, hadoop_group, hadoop_opts, hdfs_log_dir, hdfs_pid_dir} = ctx.config.hdp
   ctx.write
     source: "#{__dirname}/files/core_hadoop/hadoop-env.sh"
     destination: "#{hadoop_conf_dir}/hadoop-env.sh"
     local_source: true
-    uid: 'hdfs'
-    gid: 'hadoop'
+    uid: hdfs_user
+    gid: hadoop_group
     mode: 0o755
     write: [
       match: /^export HADOOP_OPTS.*$/mg


Add justification for mysterious replace in min/max parsing method

--- src/coffee/cilantro/ui/field/controls/date.coffee
+++ src/coffee/cilantro/ui/field/controls/date.coffee
@@ -23,6 +23,10 @@
         parseMinStat: (value) ->
             return @parseMaxStat(value)
         parseMaxStat: (value) ->
+            # The date string parser apparently has issues with dashes. If we
+            # leave the dashes in, a date of 2009-06-21 will be parsed as
+            # June 20th 2009 so we replaces the dashes with slashes to get the
+            # date to parse it as we expect it to, that is, June 21st 2009.
             return value.replace(/-/g, "/")

         # We need to override the default behavior here so that the value is


Separate out _parseDate method for clarity

Remove redundant return statements

--- src/coffee/cilantro/ui/field/controls/date.coffee
+++ src/coffee/cilantro/ui/field/controls/date.coffee
@@ -10,7 +10,6 @@

         initialize: ->
             super
-
             @events = _.extend({}, @_events, @events)

         onRender: ->
@@ -21,20 +20,24 @@

         # Convert the lower bound to a date for use in the getValue() method
         getLowerBoundValue: ->
-            return @ui.lowerBound.datepicker('getFormattedDate')
+            @ui.lowerBound.datepicker('getFormattedDate')

         # Convert the upper bound to a date for use in the getValue() method
         getUpperBoundValue: ->
-            return @ui.upperBound.datepicker('getFormattedDate')
+            @ui.upperBound.datepicker('getFormattedDate')
+
+        # The date string parser apparently has issues with dashes. If we
+        # leave the dashes in, a date of 2009-06-21 will be parsed as
+        # June 20th 2009 so we replaces the dashes with slashes to get the
+        # date to parse it as we expect it to, that is, June 21st 2009.
+        _parseDate: (value) ->
+            if value? then value.replace(/-/g, '/')

         parseMinStat: (value) ->
-            return @parseMaxStat(value)
+            @_parseDate(value)
+
         parseMaxStat: (value) ->
-            # The date string parser apparently has issues with dashes. If we
-            # leave the dashes in, a date of 2009-06-21 will be parsed as
-            # June 20th 2009 so we replaces the dashes with slashes to get the
-            # date to parse it as we expect it to, that is, June 21st 2009.
-            return value.replace(/-/g, "/")
+            @_parseDate(value)

         # Override the default behavior so the date is formatted correctly
         # for use in the placeholder.
@@ -45,7 +48,6 @@
             # months are 0 based, we need to add one there when formatting the
             # date string for placeholder use.
             dateStr = "#{date.getMonth() + 1}/#{date.getDate()}/#{date.getFullYear()}"
-
             @ui.lowerBound.attr('placeholder', dateStr)

         # We need to override the default behavior here so that the value is
@@ -63,7 +65,6 @@
             # months are 0 based, we need to add one there when formatting the
             # date string for placeholder use.
             dateStr = "#{date.getMonth() + 1}/#{date.getDate()}/#{date.getFullYear()}"
-
             @ui.upperBound.attr('placeholder', dateStr)

         # We need to override the default behavior here so that the value is


Remove unnecessary rejection

Remove unnecessary rejection

--- src/package.coffee
+++ src/package.coffee
@@ -219,10 +219,6 @@
   deactivate: ->
     @activationDeferred?.reject()
     @activationDeferred = null
-    @grammarsPromise?.reject()
-    @grammarsPromise = null
-    @scopedPropertiesPromise?.reject()
-    @scopedPropertiesPromise = null
     @unsubscribeFromActivationEvents()
     @deactivateResources()
     @deactivateConfig()


handle browserify bundle errors

handle browserify bundle errors

--- config/grunt/server.coffee
+++ config/grunt/server.coffee
@@ -19,15 +19,19 @@
   standalone: 'Quill'

+bundle = (watcher) ->
+  return watcher.bundle().on('error', console.error)
+
+
 serve = (connect, req, res, next) ->
   watchers = connect.watchers
   switch req.url
     when '/quill.js'
       res.setHeader('Content-Type', 'application/javascript')
-      watchers['src'].bundle().pipe(res)
+      bundle(watchers['src']).pipe(res)
     when '/test/quill.js'
       res.setHeader('Content-Type', 'application/javascript')
-      watchers['test'].bundle().pipe(res)
+      bundle(watchers['test']).pipe(res)
     when '/quill.snow.css', '/quill.base.css'
       theme = req.url.slice(7, 11)
       res.setHeader('Content-Type', 'text/css')
@@ -57,10 +61,8 @@
           watchers[type] = watchify(b)
           watchers[type].transform(coffeeify)
           watchers[type].transform(stylify)
-          watchers[type].on('update', ->
-            watchers[type].bundle() # Gotta call with no arguments
-          )
-          watchers[type].bundle()
+          watchers[type].on('update', _.bind(bundle, watchers[type], watchers[type]))
+          bundle(watchers[type])
           return watchers
         , {})
       middleware: (connect, options, middlewares) ->


Updated NG_OPTIONS_REGEXP to ng's new version

Look like their change is mostly about whitespace handling -- which is
the issue I'm hoping to correct with this change.

--- src/chosen.coffee
+++ src/chosen.coffee
@@ -3,7 +3,8 @@
 angular.module('localytics.directives').directive 'chosen', ['$timeout', ($timeout) ->

   # This is stolen from Angular...
-  NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/
+  NG_OPTIONS_REGEXP =  /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/
+

   # Whitelist of options that will be parsed from the element's attributes and passed into Chosen
   CHOSEN_OPTION_WHITELIST = [


Client cleanups.

Client cleanups.

--- src/client.coffee
+++ src/client.coffee
@@ -47,13 +47,13 @@

   _completed: (task) ->
     handle = @_getHandle task.id
-    handle.callback null, task.data if handle.callback?
+    handle.callback? null, task.data
     handle.emit "complete", task.data
     @_removeHandle handle

   _failed: (task) ->
     handle = @_getHandle task.id
-    handle.callback task.data if handle.callback?
+    handle.callback? task.data
     handle.emit "error", task.data unless handle.listeners("error").length is 0
     @_removeHandle handle


hotfix: HTML values can contain objects and arrays

--- client/src/app/io.coffee
+++ client/src/app/io.coffee
@@ -359,11 +359,13 @@
         read: (templateId, keypath) ->
           # console.log("read called with ", arguments)
           [circuitId, templateName] = decodeTemplateId(templateId)
-          return state[circuitId].templates[templateName].values[keypath]
+          [parent, key] = RW.getParentAndKey(state[circuitId].templates[templateName].values, keypath.split("."))
+          return parent[key]
         publish: (templateId, keypath, value) ->
           # console.log("publish called with ", arguments)
           [circuitId, templateName] = decodeTemplateId(templateId)
-          state[circuitId].templates[templateName].values[keypath] = value
+          [parent, key] = RW.getParentAndKey(state[circuitId].templates[templateName].values, keypath.split("."))
+          parent[key] = value

     return {
       provideData: ->


Removed redundant if guard in hg gpg garbage removal


CoffeeScript strings do not work that way

--- lib/view/merge-conflicts-view.coffee
+++ lib/view/merge-conflicts-view.coffee
@@ -158,8 +158,8 @@
     repo = GitBridge.getActiveRepo()
     unless repo?
       atom.notifications.addWarning "No git repository found",
-        detail: "Tip: if you have multiple projects open, open an editor in the one"
-          "containing conflicts."
+        detail: "Tip: if you have multiple projects open, open an editor in the one
+          containing conflicts."
       return

     MergeState.read repo, (err, state) =>


Chmod the root private key for the integration tests server

--- integration_test/cobalt.coffee
+++ integration_test/cobalt.coffee
@@ -16,6 +16,7 @@
 sshkey_prv_path =  "../swops-secret/cotest-rsa"
 sshkey_prv_path_root = "../swops-secret/id_dsa"
 fs.chmodSync sshkey_prv_path, 0o600
+fs.chmodSync sshkey_prv_path_root, 0o600

 ssh_args = [
   "-o LogLevel=ERROR",


cronでデータ更新は失敗した時のため例外処理を適用

cronでデータ更新は失敗した時のため例外処理を適用

--- src/ritsbus.coffee
+++ src/ritsbus.coffee
@@ -40,9 +40,14 @@
   new cron('1 4 * * *', () ->
     now = new Date
     console.log "自動更新:#{now}"
-    for day, index in allDay
-      for to in toList
-        brainBusSchedule(to, day, urls[to][index], robot)
+    try
+      for day, index in allDay
+        for to in toList
+          brainBusSchedule(to, day, urls[to][index], robot)
+    catch error
+      console.log error
+      envelope = room: 'Home'
+      robot.send envelope, error.toString()
   ).start()

   # 立命館から南草津行き


Fixing a small bug.

Fixing a small bug.

Hm. Does that boolean actually matter, then?

--- src/runtime.coffee
+++ src/runtime.coffee
@@ -214,7 +214,7 @@
     # initialize the system class
     my_sf = @curr_frame()
     @get_bs_class('Ljava/lang/System;').get_method('initializeSystemClass()V').setup_stack(this)
-    my_sf.runner = ->
+    my_sf.runner = =>
       my_sf.runner = null
       @system_initialized = true
       debug "### finished system class initialization ###"


split out functions for readability

split out functions for readability

--- src/runtime.coffee
+++ src/runtime.coffee
@@ -392,8 +392,7 @@
         # when java_throw is called from the main method lookup.
         return @run_until_finished (->), done_cb, no_threads
       else if e instanceof YieldIOException
-        retval = null
-        e.condition ((ret1, ret2) =>
+        success_fn = (ret1, ret2) =>
           @curr_frame().runner = =>
               @meta_stack().pop()
               unless ret1 is undefined
@@ -404,12 +403,12 @@
               # XXX: Assuming ret2 is never a boolean; these native methods
               #      can't have 2 return values (ret2 is here for long/doubles)
               @push ret2 unless ret2 is undefined
-          retval = @run_until_finished (->), done_cb, no_threads),
-          ((e_cb) =>
-            @curr_frame().runner = e_cb
-            retval = @run_until_finished (->), done_cb, no_threads
-          )
-        return retval
+          @run_until_finished (->), done_cb, no_threads
+        failure_fn = (e_cb) =>
+          @curr_frame().runner = e_cb
+          @run_until_finished (->), done_cb, no_threads
+        e.condition success_fn, failure_fn
+        return
       else
         if e.method_catch_handler? and @meta_stack().length() > 1
           tos = true


export

export

--- modules/dynamicNick.coffee
+++ modules/dynamicNick.coffee
@@ -31,3 +31,5 @@
     Core.modules.loaded.player.removeListener('paused', @handlePause)
     Core.modules.loaded.player.removeListener('suspended', @handlePause)
     Core.modules.loaded.player.removeListener('stopped', @handleStop)
+
+module.exports = DynamicNick


Quick Fix

Quick Fix

--- modules/player/util.coffee
+++ modules/player/util.coffee
@@ -182,7 +182,7 @@
       thumbnail: info.thumbnail
       radioStream: info.isRadioStream or false
       time: info.startAt if isFinite(info.duration) and info.duration > 0
-      videoPath: info.formats.find((f)-> f.width and f.width >= 480) or info.url
+      videoPath: (info.formats.find((f)-> f.width and f.width >= 480) or info).url
       duration
       filters
     }, playlist, not play)


changed exit to close event when finding mongoimport cmd

* stdout can live after exit event in particular ubuntu

--- src/service.coffee
+++ src/service.coffee
@@ -325,16 +325,28 @@
     scala: 'scala'
   map[lang]

+mongoImportCmd = ""
+findMongoImportCmd = (datetime, callback) ->
+  if (mongoImportCmd)
+    callback null, mongoImportCmd
+  else
+    which = spawn 'which', ["mongoimport"]
+    which.stdout.on 'data', (data) ->
+      mongoImportCmd = data.toString()
+    which.on 'exit', (code) ->
+      if (code is 0)
+        # remove trailing new line
+        mongoImportCmd = mongoImportCmd.match(/([\w\/]+)/)[0]
+        callback null, mongoImportCmd
+      else
+        logger.error "mongoimport doesn't exist."
+        callback(code)
+
 importIntoMongodb = (datetime, callback) ->
-  console.log "datetime #{datetime}"
-
-  mongoImportCmd = ""
-
-  which = spawn 'which', ["mongoimport"]
-  which.stdout.on 'data', (data) ->
-    mongoImportCmd = data.toString()
-  which.on 'exit', (code) ->
-    if (code is 0)
+  findMongoImportCmd datetime, (err, mongoCmd) ->
+    if err?
+      logger.error "error occured during mongoimport"
+    else
       args = [
         '--host', process.env['MONGODB_HOST']
         '--port', process.env['MONGODB_PORT']
@@ -349,13 +361,10 @@
           '--password', process.env["MONGODB_PASS"]
         ]

-      # remove trailing new line
-      mongoImportCmd = mongoImportCmd.match(/([\w\/]+)/)[0]
-
-      mongoimport = spawn mongoImportCmd, args
+      mongoimport = spawn mongoCmd, args
       mongoimport.stderr.on 'data', (data) ->
         logger.error "mongoimport error occured"
-      mongoimport.on 'exit', (code) ->
+      mongoimport.on 'close', (code) ->
         logger.info "mongoimport exited with code #{code}"
         doc =
           file: datetime
@@ -367,9 +376,6 @@
         callback(code) if code isnt 0

         deleteArchiveFile(datetime)
-    else
-      logger.error "mongoimport doesn't exist."
-      callback(code)

 deleteArchiveFile = (datetime) ->
   fs.unlink "#{archiveDir}/#{datetime}.json", (err) ->


use eamil to identify the openedby

use eamil to identify the openedby

--- src/sm-cmds.coffee
+++ src/sm-cmds.coffee
@@ -125,7 +125,7 @@
         title = match[1]
         ins = match[2] or Config.get "sm.servers.default"

-        SM.incident.createIncident(title, ins,resp.message.user.name)
+        SM.incident.createIncident(title, ins,resp.message.user.email_address)
           .then (r)->
             resp.reply "Incident #{r.body.Incident.IncidentID} was created!"
             msg = robot.sm_ext.formatRecord r.body.Incident


Set notificationCron for each 10 seconds

--- config/main.dev-new.coffee
+++ config/main.dev-new.coffee
@@ -108,6 +108,7 @@
     host        : 'localhost'
     protocol    : 'http:'
     defaultFromAddress: 'hello@koding.com'
+    notificationCron : '*/10 * * * * *'
   guests        :
     # define this to limit the number of guset accounts
     # to be cleaned up per collection cycle.


bring back the "/Join" route

bring back the "/Join" route

--- client/app/MainApp/kodingrouter.coffee
+++ client/app/MainApp/kodingrouter.coffee
@@ -170,10 +170,11 @@
       '/:name?/Login'     : ({params:{name}})->
         requireLogout -> mainController.doLogin name
       '/:name?/Logout'    : ({params:{name}})->
-        requireLogin -> mainController.doLogout name; @clear()
+        requireLogin => mainController.doLogout name; @clear()
       '/:name?/Register'  : ({params:{name}})->
         requireLogout -> mainController.doRegister name
-      # '/:name?/Join'      : ({params:{name}})-> mainController.doJoin name
+      '/:name?/Join'      : ({params:{name}})->
+        requireLogout -> mainController.doJoin name
       '/:name?/Recover'   : ({params:{name}})->
         requireLogout -> mainController.doRecover name


Client: Considerably less weather reflows.

--- client/app/js/views/battle_view.coffee
+++ client/app/js/views/battle_view.coffee
@@ -505,7 +505,6 @@
     $weather = switch newWeather
       when Weather.RAIN
         $weather = $("
").addClass("battle_overlay weather rain")
-        $overlays.append($weather)
         for i in [0...100]
           dropLeft = _.random(-300, overlayWidth)
           dropTop = _.random(-2 * overlayHeight - 100, overlayHeight)
@@ -513,10 +512,10 @@
           $drop = $('

')
           $drop.css(left: dropLeft, top: dropTop)
           $weather.append($drop)
+        $overlays.append($weather)
         $weather
       when Weather.SUN
         $weather = $("
").addClass("battle_overlay weather sun")
-        $overlays.append($weather)
         for i in [0...10]
           millisecs = Math.floor(Math.random() * 3000) + 'ms'
           $ray = $('

')
@@ -529,6 +528,7 @@
             'animation-delay': millisecs
           })
           $weather.append($ray)
+        $overlays.append($weather)
         $weather
       when Weather.SAND
         $weather = $("
").addClass("battle_overlay weather sand")


Fix conversation's message counter when a message is trashed

--- client/app/stores/message_store.coffee
+++ client/app/stores/message_store.coffee
@@ -301,6 +301,14 @@
                     _messages = _messages.remove message.id
                 else
                     onReceiveRawMessage message
+
+                # Update conversation length
+                {conversationID} = message
+                currentLength = _conversationLengths.get conversationID
+                newLength = currentLength - 1
+                _conversationLengths = _conversationLengths
+                                                 .update(conversationID,
+                                                         (value) -> value - 1)
             @emit 'change'

         handle ActionTypes.MESSAGE_TRASH_FAILURE, ({target, ref}) ->


1.更换模块压缩代码。 2.增加loading动画

1.更换模块压缩代码。
2.增加loading动画

--- lib/package/package-list-view.coffee
+++ lib/package/package-list-view.coffee
@@ -1,6 +1,6 @@
 {View} = require "atom"
 _ = require "underscore"
-AdmZip = require 'adm-zip'
+zip = require '../../utils/zip'
 path = require 'path'
 fs = require 'fs'
 request = require 'request'
@@ -52,11 +52,14 @@
     @div class: 'overlay from-top select-list', =>
       @ol outlet: 'list', class: 'list-group package-list'
       @button 'Cancel', click: 'destroy', class: "btn btn-lg"
+      @span class: "loading loading-spinner-small inline-block pull-right",outlet: 'loading'

   attach: ->
     request = request.defaults({jar: true})

     root = atom.project.path
+
+    @loading.hide();

     readdir(root)
     # filter butterfly packages
@@ -90,7 +93,7 @@
     # show up
     .then (map) =>
       @showPackageList map
-    .catch (err) ->
+    .catch (err) =>
       console.log err.message
       console.trace err.stack

@@ -114,15 +117,13 @@
     # .then (result) =>
   upload: (cell, module)->
     cell.changeState 'upload'
-
+    @loading.show();
     @login 'cube', 'cube', 'cube'
     .then (result) =>
       throw new Error('login fail') unless result.result is 'true'
       console.log "upload"
-      zip = new AdmZip()
-      # zip.addLocalFolder path.join(atom.project.path, 'encrypt', module.package.identifier)
-      zip.addLocalFolder module.path
-      @uploadAttach zip.toBuffer()
+      zip(module.path, module.path).then (zipPath) =>
+        @uploadAttach zipPath + '.zip'
     .then (result) =>
       console.log "validate"
       throw new Error('upload fail') unless result.result is 'success'
@@ -135,9 +136,11 @@
       console.log "new module"
       throw new Error('validate fail') unless result.result is 'success'
       @newModule _.extend result, {widget_id: result.widget_id}
-    .then (result) ->
+    .then (result) =>
+      @loading.hide();
       cell.changeState 'normal' if result.result is 'success'
-    .catch (err) ->
+    .catch (err) =>
+      @loading.hide();
       console.trace err.stack

   #模块上传流程
@@ -180,14 +183,15 @@
   validateAttach: (id) ->
     request_get "#{C_Server}/bsl-web/mam/attachment/readfile/#{id}"

-  uploadAttach: (buf) ->
+  uploadAttach: (zipPath) ->

     Q.Promise (resolve, reject, notify) ->
       r = request.post "#{C_Server}/bsl-web/mam/attachment/upload", (err, res, body)=>
+          fs.unlink zipPath
           if err then reject(err) else resolve JSON.parse(body)

       form = r.form()
-      form.append "file", buf,
+      form.append "file", fs.createReadStream(zipPath),
         filename: 'upload.zip'
         contentType: 'application/zip'


Fix getting date from x-app-date http header

Looks like at some point axios switched to lowercasing headers

--- tutor/src/api/adapter.coffee
+++ tutor/src/api/adapter.coffee
@@ -12,8 +12,8 @@
 IS_LOCAL = window.location.port is '8000' or window.__karma__

 setNow = (headers) ->
-  # X-App-Date with fallback to nginx date
-  date = headers['X-App-Date'] or headers['Date']
+  # axios will lower case headers https://github.com/axios/axios/issues/413
+  date = headers['x-app-date'] or headers['date']
   TimeActions.setFromString(date)

 updateHeadersWithToken = (token) ->


lod_and_effect: remove extraneous word in a comment

--- lod_and_effect/lod_and_effect.coffee
+++ lod_and_effect/lod_and_effect.coffee
@@ -176,7 +176,7 @@

   dotsAtMarkers(randomChr)

-  # select of chromosome for lower LOD detailed curve
+  # select chromosome for lower LOD detailed curve
   lastChr = randomChr
   topsvg.select("#rect#{randomChr}").attr("fill", pink)
   chrRect.on("click", (d) ->


Construct player acorn from data

Construct player acorn from data

--- coffee/src/player.coffee
+++ coffee/src/player.coffee
@@ -29,7 +29,8 @@
     @options = _.defaults @options, @defaults()

     @model = @options.model ? @options.acornModel
-    # TODO initialize from id or data
+    if !@model and @options.data
+      @model ?= acorn @options.data

     unless @model instanceof acorn.Model
       TypeError @model, 'acorn.Model'


Fat arrows, continued

Fat arrows, continued

--- lib/view/merge-conflicts-view.coffee
+++ lib/view/merge-conflicts-view.coffee
@@ -144,7 +144,7 @@
       e.save() if e.getPath() is filePath

     @state.context.add(repoPath)
-    .then ->
+    .then =>
       @pkg.didStageFile file: filePath
     .catch (err) ->
       handleErr(err)


named capture

named capture

Signed-off-by: Adam Stokes <0a364f4bf549cc82d725fa7fd7ed34404be64079@ubuntu.com>

--- scripts/debpkg.coffee
+++ scripts/debpkg.coffee
@@ -24,13 +24,13 @@
   return

 module.exports = (robot) ->
-  robot.hear /debpkg\s(\w+)/i, (msg) ->
-    console.log msg.match
-    pkg = msg.match[2]
+  robot.hear /debpkg\s(?<pkgname>\w+)/i, (msg) ->
+    console.log msg.match.pkgname
+    pkg = msg.match.pkgname
     queryVersion robot, msg, urlMap.debian, pkg
     return
-  robot.hear /ubupkg\s(\w+)/i, (msg) ->
-    pkg = msg.match[2]
+  robot.hear /ubupkg\s(?<pkgname>\w+)/i, (msg) ->
+    pkg = msg.match.pkgname
     queryVersion robot, msg, urlMap.ubuntu, pkg
     return
   return


debug

debug

--- scripts/trello.coffee
+++ scripts/trello.coffee
@@ -82,6 +82,9 @@
     name: subject
     idList: '510acfdfeca4af654e004e83'

+  msg.send 'I AM WORKING:'
+  msg.send 'API KEY: ' + process.env.TRELLO_API_KEY
+  msg.send 'TOKEN: ' + process.env.TRELLO_TOKEN
   t.get "/1/cards", args, (err, data) ->
     msg.send err if err
     msg.send "Added card: " + args.name + " - " + data.url


show terms in invitation

show terms in invitation

--- @client/auth.coffee
+++ @client/auth.coffee
@@ -759,7 +759,7 @@
     else
       questions = []

-    if auth.form in ['create account', 'craete account via invitation']
+    if auth.form in ['create account', 'create account via invitation']
       questions.push
           tag: 'considerit_terms.editable'
           question: @privacyAndTerms()


avoid a spurious "Pass" when running tests in keep_going mode

--- src/testing.coffee
+++ src/testing.coffee
@@ -32,7 +32,7 @@

   _runner = () ->
     if test_classes.length == 0
-      quiet || stdout "Pass\n"
+      quiet || keep_going || stdout "Pass\n"
       return callback(false)
     test = test_classes.shift()
     quiet || stdout "testing #{test}...\n"


corrected method of returning json for client rendering

--- src/timbits.coffee
+++ src/timbits.coffee
@@ -224,8 +224,7 @@
 				else
 					if context.callback?
 						# remote client side include
-						res.contentType 'application/javascript'
-						res.send "#{context.callback} ( #{JSON.stringify(str)} );"
+						res.json str
 					else
 						res.send str


home/utilities: remove integrations section from members' view

--- client/home/lib/utilities/index.coffee
+++ client/home/lib/utilities/index.coffee
@@ -17,6 +17,7 @@
     super options, data

     TeamFlux.actions.loadTeam()
+    canEdit = kd.singletons.groupsController.canEditGroup()

     @wrapper.addSubView headerize  'KD CLI'
     @wrapper.addSubView sectionize 'KD CLI', HomeUtilitiesKD
@@ -27,6 +28,6 @@
     @wrapper.addSubView headerize  'Koding Button'
     @wrapper.addSubView sectionize 'Koding Button', HomeUtilitiesTryOnKoding

-    @wrapper.addSubView headerize  'Integrations'
-
-    @wrapper.addSubView sectionize 'Customer Feedback', HomeUtilitiesCustomerFeedback
+    if canEdit
+        @wrapper.addSubView headerize  'Integrations'
+        @wrapper.addSubView sectionize 'Customer Feedback', HomeUtilitiesCustomerFeedback


AdminIntegrationsListView: Remove dummy code.

--- client/admin/lib/views/integrations/adminintegrationslistview.coffee
+++ client/admin/lib/views/integrations/adminintegrationslistview.coffee
@@ -47,9 +47,6 @@

       return @handleNoItem err  if err

-      if @integrationType is 'configured' # dummy code.
-        data = data.first
-
       for item in data
         item.integrationType = @integrationType
         listItem = @listController.addItem item


Working on sending back replies to users

--- src/twitter.coffee
+++ src/twitter.coffee
@@ -1,4 +1,4 @@
-{Robot, Adapter} = require 'hubot'
+{Robot, Adapter, TextMessage, EnterMessage, LeaveMessage, Response} = require 'hubot'

 HTTPS        = require 'https'
 EventEmitter = require('events').EventEmitter
@@ -6,6 +6,7 @@

 class Twitter extends Adapter
  send: (user, strings...) ->
+   console.log "Sending strings to user: " + user
    strings.forEach (str) =>
      text = str
      console.log text
@@ -14,8 +15,14 @@
        @bot.send(user,tweetText)

  reply: (user, strings...) ->
+   console.log "Replying"
    strings.forEach (text) =>
-       @bot.reply(user,text)
+       console.log text
+       @bot.send(user,text)
+
+ command: (command, strings...) ->
+    console.log command
+    @bot.send command, strings...

  run: ->
    self = @
@@ -26,14 +33,14 @@
     tokensecret : process.env.HUBOT_TWITTER_TOKEN_SECRET
    bot = new TwitterStreaming(options)

-   bot.tweet self.robot.name, (err, data) ->
+   bot.tweet self.robot.name, (data, err) ->
      reg = new RegExp('@'+self.robot.name,'i')
      console.log "received #{data.text} from #{data.user.screen_name}"

      message = data.text.replace reg, self.robot.name
      console.log "hubot command: #{message}"

-     self.receive new Robot.TextMessage data.user.screen_name, message
+     self.receive new TextMessage data.user.screen_name, message
      if err
        console.log "received error: #{err}"

@@ -103,8 +110,6 @@
        data = data.slice(index + 2)
        if json.length > 0
           try
-             console.log "json"+json
-             callback null, JSON.parse(json)
+             callback JSON.parse(json), null
           catch err
              console.log "error parse"+json
-             callback null, data || { }


Corrects expression equality expression length check

--- math/expression_equality_spec.coffee
+++ math/expression_equality_spec.coffee
@@ -54,6 +54,16 @@
             ])
           )).toEqual false

+    it "rejects expressions that are of different lengths", ->
+      expect(
+        @isEqual(
+          @comps.expression.build(expression: []),
+          @comps.expression.build(expression: [
+              @comps.number.build(value: 10)
+            ])
+          )).toEqual false
+
+
   describe "addition", ->
     it "accepts two addition symbols", ->
       expect(
@@ -78,6 +88,7 @@
           @comps.number.build(value: 1)
         )).toEqual false

+
   describe "exponentiation", ->
     it "accepts exponents with same base and power", ->
       a = @exp_builder('^': [11, 22])


adding elapsedTime

adding elapsedTime

--- src/engine.coffee
+++ src/engine.coffee
@@ -150,7 +150,7 @@
     step = ->
       if !I.paused || frameAdvance
         msPerFrame = (1000 / I.FPS)
-        update()
+        update((1000 / I.FPS))
         I.age += 1

       draw()


mixin Comments  with Likeable.

mixin Comments  with Likeable.

--- server/app/bongo/models/messages/comment.coffee
+++ server/app/bongo/models/messages/comment.coffee
@@ -3,25 +3,31 @@
   {ObjectId,ObjectRef,dash,daisy} = require 'bongo'
   {Relationship}  = require 'jraphical'

+  @::mixin Likeable::
+
   @share()

   @set
-    sharedMethods :
-      instance    : ['delete']
-    schema        :
-      isLowQuality: Boolean
-      body        :
-        type      : String
-        required  : yes
-      originType  :
-        type      : String
-        required  : yes
-      originId    :
-        type      : ObjectId
-        required  : yes
-      deletedAt   : Date
-      deletedBy   : ObjectRef
-      meta        : require 'bongo/bundles/meta'
+    sharedMethods  :
+      instance     : ['delete', 'like', 'fetchLikedByes', 'checkIfLikedBefore']
+    schema         :
+      isLowQuality : Boolean
+      body         :
+        type       : String
+        required   : yes
+      originType   :
+        type       : String
+        required   : yes
+      originId     :
+        type       : ObjectId
+        required   : yes
+      deletedAt    : Date
+      deletedBy    : ObjectRef
+      meta         : require 'bongo/bundles/meta'
+    relationships  :
+      likedBy      :
+        targetType : JAccount
+        as         : 'like'

   delete: bongo.secure (client, callback)->
     {delegate} = client.connection


activity: prevent profile link click event to reload window [fixes #77927968]

--- client/Social/Activity/views/comments/listitemview.coffee
+++ client/Social/Activity/views/comments/listitemview.coffee
@@ -29,7 +29,20 @@
     else @body.unsetClass 'edited'

-  click: (event) -> KD.utils.showMoreClickHandler event
+  click: (event) ->
+
+    if event.target.classList.contains 'profile-link'
+      @handleProfileLink event
+
+    KD.utils.showMoreClickHandler event
+
+
+  handleProfileLink: (event) ->
+
+    KD.utils.stopDOMEvent event
+
+    {target} = event
+    KD.getSingleton('router').handleRoute target.getAttribute 'href'

   showEditForm: ->


slack: message sending initial

slack: message sending initial

--- client/admin/lib/views/invitations/slackinviteview.coffee
+++ client/admin/lib/views/invitations/slackinviteview.coffee
@@ -1,5 +1,6 @@
 $             = require 'jquery'
 kd            = require 'kd'
+whoami        = require 'app/util/whoami'
 SlackUserItem = require './slackuseritem'

@@ -18,10 +19,12 @@

 module.exports = class SlackInviteView extends kd.CustomScrollView

-  SLACKBOT_ID = 'USLACKBOT'
-  OAUTH_URL   = "#{location.origin}/api/social/slack/oauth"
+  SLACKBOT_ID   = 'USLACKBOT'
+  OAUTH_URL     = "#{location.origin}/api/social/slack/oauth"
+  USERS_URL     = "#{location.origin}/api/social/slack/users"
   CHANNELS_URL  = "#{location.origin}/api/social/slack/channels"
   MESSAGING_URL = "#{location.origin}/api/social/slack/message"
+  ICON_URL      = "#{location.origin}/a/images/logos/notify_logo.png"

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

@@ -139,6 +142,33 @@
       cssClass : 'solid medium green invite-members fr'
       title    : 'Invite selected members'
       disabled : yes
-      callback : ->
-        selected = getSelectedMembers listController
-        console.log selected
+      callback : => @prepareMessages getSelectedMembers listController
+
+
+  prepareMessages: (recipients) ->
+
+
+
+    recipients.forEach (recipient) ->
+      $.ajax
+        url              : MESSAGING_URL
+        method           : 'POST'
+        headers          :
+          Accept         : 'application/json'
+          'Content-Type' : 'application/json'
+        data             : JSON.stringify
+          channel        : recipient.id
+          text           : 'Invite ulan!'
+          params         :
+            as_user      : no
+            username     : whoami().profile.firstName
+            icon_url     : ICON_URL
+            icon_emoji   : ':cihangir:'
+        success: ->
+          console.log 'success'
+        error: ->
+          console.log 'error'
+
+
+
+  sendMessage: (message) ->


client: home: persist try on koding state by allowing joining from any domain

--- client/home/lib/utilities/homeutilitiestryonkoding.coffee
+++ client/home/lib/utilities/homeutilitiestryonkoding.coffee
@@ -12,12 +12,11 @@

     super options, data

+
     @switch  = new KodingSwitch
       cssClass: 'small'
-      callback: (state) =>
-        if state
-        then @setClass 'on'
-        else @unsetClass 'on'
+      callback: @bound 'handleSwitch'
+

     @guide  = new CustomLinkView
       cssClass : 'HomeAppView--button'
@@ -28,6 +27,37 @@
       cssClass : 'TryOnKodingButton fr'
       title    : ''
       callback : kd.noop
+
+    team               = kd.singletons.groupsController.getCurrentGroup()
+    { allowedDomains } = team
+
+    # set initial state
+    if '*' in allowedDomains
+      withCallback = no
+      @switch.setOn withCallback
+      @setClass 'on'
+
+
+  handleSwitch: (state) ->
+
+    team               = kd.singletons.groupsController.getCurrentGroup()
+    { allowedDomains } = team
+
+    if state
+      newDomains = _.clone allowedDomains
+      newDomains.push '*'
+    else
+      _.remove newDomains, (domain) -> domain is '*'
+
+    team.modify { allowedDomains: newDomains }, (err) ->
+      if err
+        withCallback = no
+        @switch.setOn !state
+        return
+
+      if state
+      then @setClass 'on'
+      else @unsetClass 'on'

   click: (event) ->


revert pr #7920

revert pr #7920

--- client/stacks/lib/views/stacks/updatestacktemplate.coffee
+++ client/stacks/lib/views/stacks/updatestacktemplate.coffee
@@ -1,13 +1,10 @@
-kd = require 'kd'
 remote = require('app/remote').getInstance()
 EnvironmentFlux = require 'app/flux/environment'
 generateStackTemplateTitle = require 'app/util/generateStackTemplateTitle'

 module.exports = updateStackTemplate = (data, callback) ->
-
-  { reactor } = kd.singletons
-
+  console.trace('UPDATESTACKTEMPLATE')
   { template, templateDetails, credentials, description
     title, stackTemplate, machines, config, rawContent } = data

@@ -24,12 +21,7 @@
       templateDetails, config, description
     }
     EnvironmentFlux.actions.updateStackTemplate(stackTemplate, dataToUpdate)
-      .then ({ stackTemplate }) ->
-        stackTemplate.on 'update', (data) ->
-          if 'accessLevel' in data
-            template = stackTemplate
-            reactor.dispatch 'REMOVE_STACK_TEMPLATE_SUCCESS', { template }
-        callback null, stackTemplate
+      .then ({ stackTemplate }) -> callback null, stackTemplate
       .catch (err) -> callback err

   else


Modified in browser at pixie.strd6.com

Modified in browser at pixie.strd6.com

--- src/follow.coffee
+++ src/follow.coffee
@@ -1,5 +1,5 @@
 ###*
-The Follow module provides a simple method to set an object's velocity
+The Follow module provides a simple method to set an object's velocity

 # Health regeneration


Changes in group create

Changes in group create

--- components/buttons/KDButtonView.coffee
+++ components/buttons/KDButtonView.coffee
@@ -117,7 +117,7 @@
   hideLoader:->
     {icon, iconOnly} = @getOptions()
     @unsetClass "loading"
-    @loader.hide()
+    @loader?.hide()
     @showIcon() if icon and not iconOnly

   disable:-> @$().attr "disabled",yes


remove consolelog

remove consolelog

--- components/filter/artworks/view.coffee
+++ components/filter/artworks/view.coffee
@@ -91,8 +91,6 @@
   reset: =>
     @params.set({ page: 1, size: @pageSize }, { silent: true }).trigger('change change:page')

-    console.log 'hellloo', @params
-
     @counts.fetch
       data:
         price_range: @params.get('price_range')


chr2dpanelframe: fix rectangle positioning

--- src/chr2dpanelframe.coffee
+++ src/chr2dpanelframe.coffee
@@ -80,8 +80,12 @@
                      .append("rect")
                      .attr("x", (d) -> xscale[d.chrx](data.start[d.xi]) - chrGap/2)
                      .attr("width", (d) -> xscale[d.chrx](data.end[d.xi]) - xscale[d.chrx](data.start[d.xi]) + chrGap)
-                     .attr("y", (d) -> yscale[d.chry](data.start[d.yi]) - chrGap/2)
-                     .attr("height", (d) -> yscale[d.chry](data.end[d.yi]) - yscale[d.chry](data.start[d.yi]) + chrGap)
+                     .attr("y", (d) ->
+                         return yscale[d.chry](data.start[d.yi]) - chrGap/2 if oneAtTop
+                         yscale[d.chry](data.end[d.yi]) - chrGap/2)
+                     .attr("height", (d) ->
+                         return yscale[d.chry](data.end[d.yi]) - yscale[d.chry](data.start[d.yi]) + chrGap if oneAtTop
+                         yscale[d.chry](data.start[d.yi]) - yscale[d.chry](data.end[d.yi]) + chrGap)
                      .attr("fill", (d,i) ->
                          return rectcolor unless d.odd
                          altrectcolor)


Fixed url and object name.

Fixed url and object name.

--- app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee
+++ app/assets/javascripts/app/controllers/_dashboard/activity_stream.js.coffee
@@ -42,17 +42,17 @@
     for item in items
       if item.history_object is 'Ticket'
         ticket = App.Ticket.find( item.o_id )
-        item.link = '#ticket_zoom/' + ticket.id
+        item.link = '#ticket/zoom/' + ticket.id
         item.title = ticket.title
-        item.type  = item.history_object
+        item.type = 'Ticket'
         item.updated_by_id = ticket.updated_by_id
         item.updated_by = App.User.find( ticket.updated_by_id )
       else if item.history_object is 'Ticket::Article'
         article = App.TicketArticle.find( item.o_id )
         ticket  = App.Ticket.find( article.ticket_id )
-        item.link = '#ticket_zoom/' + ticket.id + '/' + article.od
+        item.link = '#ticket/zoom/' + ticket.id + '/' + article.id
         item.title = article.subject || ticket.title
-        item.type  = item.history_object
+        item.type = 'Article'
         item.updated_by_id = article.updated_by_id
         item.updated_by = App.User.find( article.updated_by_id )


Remove the right listener from hashchange

--- content_scripts/vimium_frontend.coffee
+++ content_scripts/vimium_frontend.coffee
@@ -236,7 +236,7 @@
     handlerStack.reset()
     isEnabledForUrl = false
     window.removeEventListener "focus", onFocus
-    window.removeEventListener "hashchange", onFocus
+    window.removeEventListener "hashchange", checkEnabledAfterURLChange

 setScrollPosition = ({ scrollX, scrollY }) ->
   DomUtils.documentReady ->


Rerun buffer first after reset

Rerun buffer first after reset

--- src/config/programs.coffee
+++ src/config/programs.coffee
@@ -7,7 +7,7 @@
   _KIND: 'program'
   _EXPORTS: ['reset']
   path: (world) -> undefined
-  reset: (world, args) -> world.call('load', args)
+  reset: (world, args) -> world.call('load', {name: 'buffer:'})
   load: (world, args) ->
     args = {name: DEFAULT} unless args?
     {name} = args


refolder files

refolder files

--- src/js/app.coffee
+++ src/js/app.coffee
@@ -1,44 +0,0 @@
-
-
-window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem
-
-successCallback = (fs) ->
-  reader = do fs.root.createReader
-  entries = []
-
-  readEntries = ->
-    reader.readEntries ((results)->
-      if not results.length
-        console.log  entries
-      else
-        entries = entries.concat(toArray(results))
-        do readEntries
-
-      ), onError
-
-  do readEntries
-
-onError = (event) ->
-  console.log event
-
-
-errorHandler: (e)->
-  msg = ''
-  switch e.code
-    when FileError.QUOTA_EXCEEDED_ERR
-      msg = 'QUOTA_EXCEEDED_ERR'
-    when FileError.NOT_FOUND_ERR
-      msg = 'NOT_FOUND_ERR'
-    when FileError.SECURITY_ERR
-      msg = 'SECURITY_ERR'
-    when FileError.INVALID_MODIFICATION_ERR
-      msg = 'INVALID_MODIFICATION_ERR'
-    when FileError.INVALID_STATE_ERR
-      msg = 'INVALID_STATE_ERR'
-    else
-      msg = 'Unknown Error'
-
-  alert msg
-
-
-window.requestFileSystem window.PERSISTENT, 20000, successCallback, onError


#5  settings tab refreshes correctly when folder is selected

Fixes #5 with some small refactoring of the vue object.

--- src/controller.main.coffee
+++ src/controller.main.coffee
@@ -56,7 +56,6 @@
   name: 'settings'
   template: '#settings-template'
   data: ->
-    #active: this.$parent.active
     active: dfc.getSelectedObject()
     t: this.$root.t
   methods:
@@ -69,10 +68,9 @@
         @active[type] = f
       c.log.debug type
   events:
-    'active': ->
+    'refresh': ->
       c.log.debug "settings. active"
-      this.active = this.$parent.active
-
+      this.active = this.$root.active
   })

 vueLogs = Vue.extend({
@@ -100,11 +98,8 @@
     activeIndex: dfc.selectedObjectIndex
     activeTab: 'files'
   events:
-    'active': ->
-      this.$broadcast 'active'
-      this.active = dfc.getSelectedObject
-      c.log.debug "active event in root"
     'refreshRoot': ->
+      c.log.debug "refreshRoot called"
       @folders = dfc.getObjects()
       @active = dfc.getSelectedObject
       @activeIndex = dfc.selectedObjectIndex
@@ -127,7 +122,7 @@
       dfc.selectObject index
       this.folders = dfc.getObjects()
       this.active = dfc.getSelectedObject()
-      this.$on 'refreshRoot'
+      @$broadcast 'refresh'
       dfc.write()
       c.log.debug "Activate: #{index}"
     startAutoCommit: ->


Small fix for auth controller

Small fix for auth controller

--- src/controller/auth.coffee
+++ src/controller/auth.coffee
@@ -16,9 +16,6 @@
   usernameField: 'username'
   passwordField: 'pass',
   user.auth
-
-# tmp
-mailer = require '../core/mail/mailer'

 ###
 # Response signin page


fixes displaying custom agg functions in tooltips (closes #510)

--- src/core/fetch/sort.coffee
+++ src/core/fetch/sort.coffee
@@ -30,8 +30,9 @@

     if [vars.data.keys[key], vars.attrs.keys[key]].indexOf("number") >= 0
       agg = vars.order.agg.value or vars.aggs.value[key] or "sum"
+      agg = d3[agg] if agg.constructor is String
       value = [value] if !(value instanceof Array)
-      value = d3[agg] value
+      value = agg value
     else
       value = value[0] if value instanceof Array
       value = if typeof value is "string" then value.toLowerCase() else value


rename

rename


Append (friendly) iframe to body if possible

--- src/loader.coffee
+++ src/loader.coffee
@@ -16,9 +16,13 @@

   (iframe.frameElement or iframe).style.cssText =
     "position: absolute; top: 0; left: 0; width: 1px; height: 1px; opacity: 0; border: none;"
-  where = document.getElementsByTagName('script')
-  where = where[where.length - 1]
-  where.parentNode.insertBefore(iframe, where)
+
+  if document.body
+    document.body.appendChild(iframe)
+  else
+    where = document.getElementsByTagName('script')
+    where = where[where.length - 1]
+    where.parentNode.insertBefore(iframe, where)

   # Section 2
   try


Lookup Netlify site by id instead of iterating over all the users sites

--- lib/deployers/netlify/index.coffee
+++ lib/deployers/netlify/index.coffee
@@ -2,6 +2,9 @@
 W       = require 'when'
 node    = require 'when/node'
 _       = require 'lodash'
+
+# This is used to resolve a name to a netlify preview domain for site lookups
+preview_domain = ".netlify.com"

 module.exports = (root, config) ->
   d = W.defer()
@@ -32,8 +35,11 @@
 ###

 lookup = ->
-  node.call(@client.sites.bind(@client))
-    .then (sites) => _.find(sites, name: @config.name)
+  id = if @config.name.indexOf(preview_domain) != -1
+    @config.name
+  else
+    @config.name + preview_domain
+  node.call(@client.site.bind(@client), id)

 ###*
  * Creates a new site on netlify with a given name.


Support small medium and large

Support small medium and large

--- js/inner.coffee
+++ js/inner.coffee
@@ -798,7 +798,8 @@
     @chosenPlan(plan)
     SammyApp.setLocation "/account/plans/organization"

-  load: () =>
+  load: (hash="small") =>
+    @planSize(hash)
     unless @loaded
       unless window.location.pathname == "/account/new-plans"
         SammyApp.setLocation "/account/plans"
@@ -1070,12 +1071,14 @@
     ko.applyBindings(VM)

-  loadAccountPage: (cx, subpage, organization) =>
+  loadAccountPage: (cx, subpage) =>
     subpage = subpage[0].replace(/\//, '') # first one
     subpage = subpage.replace(/\//g, '_')
-    subpage = subpage || "notifications"
+    subpage or= "notifications"
+
     if subpage.indexOf("plans") == 0 or subpage.indexOf("new-plans") == 0
-      @billing().load()
+      [subpage, hash] = subpage.split('#')
+      @billing().load(hash)
     $('#main').html(HAML['account']({}))
     $('#subpage').html(HAML['account_' + subpage.replace(/-/g, '_')]({}))
     ko.applyBindings(VM)


remove unnecessary interpolation

remove unnecessary interpolation

--- js/coffee/scroll-animate.coffee
+++ js/coffee/scroll-animate.coffee
@@ -40,7 +40,7 @@
             animation = $this.data('animation')

             $this.css 'visibility', 'visible'
-            $this.addClass("#{animation}").dequeue()
+            $this.addClass(animation).dequeue()

           options.loaded = true


Make node path even smarter

Make node path even smarter

--- lib/layervault/organization.coffee
+++ lib/layervault/organization.coffee
@@ -2,5 +2,9 @@
   constructor: (org, @api) ->
     @orgName = if typeof org is "object" then org.name else org

-  node: (path, cb) -> @api.get @apiPath(path), {}, cb
-  apiPath: (path) -> "/#{encodeURIComponent(@orgName)}/#{path}"+  node: (path, cb) ->
+    @api.get @apiPath(path), {}, cb
+
+  apiPath: (path) ->
+    path = path.path || path.name if typeof path is "object"
+    "/#{encodeURIComponent(@orgName)}/#{path}"


Use atom.views.updateDocument to update the suggestionList

--- lib/suggestion-list-element.coffee
+++ lib/suggestion-list-element.coffee
@@ -49,7 +49,8 @@

   itemsChanged: ->
     @selectedIndex = 0
-    @renderItems()
+    atom.views.pollAfterNextUpdate?()
+    atom.views.updateDocument => @renderItems()

   addActiveClassToEditor: ->
     editorElement = atom.views.getView(atom.workspace.getActiveTextEditor())


Delete unused file

Delete unused file


Dont parse time

Dont parse time

--- vendor/assets/javascripts/bootstrap_widgets.js.coffee
+++ vendor/assets/javascripts/bootstrap_widgets.js.coffee
@@ -26,7 +26,6 @@
 window.line_graph = (json_data, labels, title, opts, links=[]) ->
   options = $.extend({},opts,{
     element: 'line_graph-' + title,
-    parseTime: false,
     data:  json_data,
     xkey: 'label',
     ykeys: ['value'],


not all deploys are ok

not all deploys are ok

--- controllers/deploys.coffee
+++ controllers/deploys.coffee
@@ -9,7 +9,7 @@

 # create (if anyone finds the team by code, they're authorized)
 app.all '/teams/:code/deploys', [m.loadTeam], (req, res) ->
-  util.log "#{'DEPLOY'.green} #{req.team.name} (#{req.team.id})"
+  util.log "#{'DEPLOY'.magenta} #{req.team.name} (#{req.team.id})"
   req.session.destroy()
   res.end 'ok'


Add compatibility shim for Array.indexOf in IE8

--- keypress.coffee
+++ keypress.coffee
@@ -633,13 +633,19 @@
         return false unless item in a2
     return true

+_index_of_in_array = Array.prototype.indexOf || ((arr, el) ->
+    for i in [0..arr.length]
+        return i if arr[i] is el
+    return -1
+)
+
 _is_array_in_array_sorted = (a1, a2) ->
     # Return true only if all of the contents of
     # a1 are include in a2 and they appear in the
     # same order in both.
     prev = 0
     for item in a1
-        index = a2.indexOf item
+        index = _index_of_in_array.call(a2, item)
         if index >= prev
             prev = index
         else
@@ -695,7 +701,7 @@
     if "meta" in combo.keys or "cmd" in combo.keys
         non_modifier_keys = combo.keys.slice()
         for mod_key in _modifier_keys
-            if (i = non_modifier_keys.indexOf(mod_key)) > -1
+            if (i = _index_of_in_array.call(non_modifier_keys, mod_key)) > -1
                 non_modifier_keys.splice(i, 1)
         if non_modifier_keys.length > 1
             _log_error "META and CMD key combos cannot have more than 1 non-modifier keys", combo, non_modifier_keys


standardize the javascript

standardize the javascript

--- vendor/assets/javascripts/frontend_editor/views/toolbar_view.js.coffee
+++ vendor/assets/javascripts/frontend_editor/views/toolbar_view.js.coffee
@@ -5,9 +5,9 @@
   template: JST['frontend_editor/templates/toolbar_views']

   events:
-    'click .editing-mode': 'toggle_editing_mode'
-    'click .save': 'save_changes'
-    'click .cancel': 'cancel_changes'
+    'click .editing-mode': 'toggleEditingMode'
+    'click .save': 'saveChanges'
+    'click .cancel': 'cancelChanges'

   render: ->
     super
@@ -21,19 +21,19 @@
     @

 # commit all changes for all stored model
-  save_changes: (event) ->
+  saveChanges: (event) ->
     Editor.commitAll()
     FrontendEditor.currentModels.save()
     FrontendEditor.currentModels.reset()
     alert "Enregistrement Effectué"
-    @toggle_editing_mode()
+    @toggleEditingMode()

 # reload the page to cancel all change
-  cancel_changes: (event) ->
+  cancelChanges: (event) ->
     window.location.reload()

 # toggle the editing mode
-  toggle_editing_mode: ->
+  toggleEditingMode: ->
     if $('.save').is(':hidden')
       @$('.save').show()
       @$('.cancel').show()


fix websocket-based updates

fix websocket-based updates

On more recent versions of the websocket library `clients` cannot be
iterated over using a `for in` loop, the body will never run. Using
the `forEach` method fixes this issue.

Before this patch, the task and user lisk was not updated automatically (it
required a reload to refresh) because the websocket updates were not
broadcasted correctly to all connected clients.

--- main.coffee
+++ main.coffee
@@ -255,8 +255,8 @@

 wss = new WebSocketServer {server:server}
 wss.broadcast = (msg, exclude, scope=null) ->
-  for c in this.clients
-    unless c.authenticated then continue
+  this.clients.forEach (c) ->
+    unless c.authenticated then return
     if c isnt exclude and (scope is null or scope is c.authenticated.scope)
       try
         c.send msg
@@ -282,7 +282,7 @@
                 sock.send JSON.stringify {type: 'assign', subject: i.challenge, data: [{name: i.user}, true]}
             # notify all users about new authentication and notify new socket about other users
             wss.broadcast JSON.stringify {type: 'login', data: ans.name}
-            for s in wss.getClients()
+            wss.getClients().forEach (s) ->
               if s.authenticated and s.authenticated.name isnt ans.name
                 sock.send JSON.stringify {type: 'login', data: s.authenticated.name}
     else
@@ -304,7 +304,7 @@
             db.modifyChallenge c.id, c.title, c.category, c.points
           else
             db.addChallenge msg.data.ctf, c.title, c.category, c.points
-        for s in wss.clients
+        wss.clients.forEach (s) ->
           if s.authenticated and s.authenticated.scope is msg.data.ctf
             s.send JSON.stringify {type: 'ctfmodification'}
       else console.log msg


Improved: code style

Improved: code style

--- main.coffee
+++ main.coffee
@@ -369,8 +369,7 @@
             designList = "all the designs"
         @log "[INFO] Removing views for #{designList}...".yellow

-        designsToRemove = designsToRemove.map (single) ->
-            return "_design/#{single}"
+        designsToRemove = designsToRemove.map (single) -> "_design/#{single}"

         # Get all the design documents
         @clientCouch = new Client "http://localhost:5984/"